1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/rryqszq4-JsonRPC

В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
jsr_client.c 38 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
rryqszq4 Отправлено 07.02.2016 18:42 9eba8c7
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2013 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: rryqszq4 |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "ext/standard/basic_functions.h"
#include "ext/standard/php_rand.h"
#include "ext/standard/php_smart_str.h"
#include "SAPI.h"
#include "ext/json/php_json.h"
#include "ext/standard/file.h"
#include "php_jsonrpc.h"
#include "jsr_client.h"
#include "jsr_curl.h"
#include "jsr_epoll.h"
#include "jsr_utils.h"
#include "jsr_yajl.h"
int le_jsr_epoll_persist;
int le_jsr_curlm_persist;
/** {{{ ARG_INFO
* */
ZEND_BEGIN_ARG_INFO_EX(jsonrpc_client_construct_arginfo, 0, 0, 0)
ZEND_ARG_INFO(0, persist)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(jsonrpc_client_destruct_arginfo, 0, 0, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(jsonrpc_client_call_arginfo, 0, 0, 3)
ZEND_ARG_INFO(0, url)
ZEND_ARG_INFO(0, procedure)
ZEND_ARG_INFO(0, params)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(jsonrpc_client_execute_arginfo, 0, 0, 0)
ZEND_ARG_INFO(0, response_type)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(jsonrpc_client_connect_arginfo, 0, 0, 1)
ZEND_ARG_INFO(0, url)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(jsonrpc_client___call_arginfo, 0, 0, 2)
ZEND_ARG_INFO(0, method)
ZEND_ARG_INFO(0, params)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(jsonrpc_client_dorequest_arginfo, 0, 0, 1)
ZEND_ARG_INFO(0, payload)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(jsonrpc_client_authentication_arginfo, 0, 0, 2)
ZEND_ARG_INFO(0, username)
ZEND_ARG_INFO(0, password)
ZEND_END_ARG_INFO()
/* }}} */
static int _php_count_recursive(zval *array, long mode TSRMLS_DC) /* {{{ */
{
long cnt = 0;
zval **element;
if (Z_TYPE_P(array) == IS_ARRAY) {
if (Z_ARRVAL_P(array)->nApplyCount > 1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
return 0;
}
cnt = zend_hash_num_elements(Z_ARRVAL_P(array));
if (mode == COUNT_RECURSIVE) {
HashPosition pos;
for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos);
zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **) &element, &pos) == SUCCESS;
zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos)
) {
Z_ARRVAL_P(array)->nApplyCount++;
cnt += _php_count_recursive(*element, COUNT_RECURSIVE TSRMLS_CC);
Z_ARRVAL_P(array)->nApplyCount--;
}
}
}
return cnt;
}
static zval*
_jsr_client_prepare_request(zval *procedure, zval *params, zval *custom_id TSRMLS_DC)
{
zval *payload;
long number;
int nb_params;
MAKE_STD_ZVAL(payload);
array_init(payload);
add_assoc_string(payload, "jsonrpc", "2.0", 0);
add_assoc_string(payload, "method", Z_STRVAL_P(procedure), 0);
if (Z_TYPE_P(custom_id) == IS_NULL){
zval *id;
MAKE_STD_ZVAL(id);
if (!BG(mt_rand_is_seeded)) {
php_mt_srand(GENERATE_SEED() TSRMLS_CC);
}
number = (long) (php_mt_rand(TSRMLS_C) >> 1);
ZVAL_LONG(id, number);
add_assoc_long(payload, "id", Z_LVAL_P(id));
//add_assoc_long(payload, "id", 123456);
}else {
add_assoc_zval(payload, "id", custom_id);
}
nb_params = _php_count_recursive(params, 0 TSRMLS_CC);
if (nb_params > 0)
{
add_assoc_zval(payload, "params", params);
}
return payload;
}
static int
_socket_callback(CURL *easy, curl_socket_t fd, int action, void *u, void *s)
{
//php_printf(">>> %s: adding fd=%d action=%d\n", __func__, fd, action);
php_jsr_reuqest_object *request = (php_jsr_reuqest_object *) u;
jsr_epoll_t *jsr_epoll = request->context->epoll;
jsr_curl_sockinfo_t *jsr_sock = (jsr_curl_sockinfo_t *) s;
if (action == CURL_POLL_REMOVE)
{
if (jsr_sock){
jsr_epoll_del_fd(jsr_epoll, jsr_sock->sockfd);
free(jsr_sock);
jsr_sock = NULL;
}
}else {
if (!jsr_sock){
jsr_sock = calloc(sizeof(jsr_curl_sockinfo_t), 1);
jsr_sock->sockfd = fd;
jsr_sock->easy = easy;
jsr_epoll_add_fd(jsr_epoll, jsr_sock->sockfd);
curl_multi_assign(request->curlm->multi_handle, jsr_sock->sockfd, jsr_sock);
}
if (action == CURL_POLL_IN || action == CURL_POLL_INOUT)
{
jsr_epoll_set_in(jsr_epoll, jsr_sock->sockfd);
}
if (action == CURL_POLL_OUT || action == CURL_POLL_INOUT)
{
jsr_epoll_set_out(jsr_epoll, jsr_sock->sockfd);
}
}
return 0;
}
static int
_timer_callback(CURLM *multi, long timeout_ms, void *u)
{
//php_printf(">>> %s: timeout: %ld ms\n", __func__, timeout_ms);
//php_jsr_reuqest_object *request = (php_jsr_reuqest_object *) u;
//request->curlm->timeout = timeout_ms;
return 0;
}
static size_t
_read_callback(void *ptr, size_t size, size_t nmemb, void *ctx)
{
return 0;
}
static size_t
_write_callback(char *ptr, size_t size, size_t nmemb, void *ctx)
{
TSRMLS_FETCH();
jsr_curl_item_t * item = (jsr_curl_item_t *)ctx;
zval *response_tmp;
zval *error;
char *buffer;
CURLcode code;
long response_code;
size_t length = size * nmemb;
item->write_length = item->write_length + length;
code = curl_easy_getinfo(item->curl_handle, CURLINFO_RESPONSE_CODE, &response_code);
if (response_code == 200){
if (!item->write_data){
item->write_data = malloc(item->write_length + 1);
memset(item->write_data, 0, item->write_length+1);
strncpy(item->write_data, ptr, item->write_length);
}else {
item->write_data = realloc(item->write_data, item->write_length + 1);
strncat(item->write_data, ptr, length);
}
return length;
}
switch (response_code)
{
case 100:
response_tmp = _php_jsr_response_error(-32100, "Continue", &item->payload_id);
break;
case 101:
response_tmp = _php_jsr_response_error(-32101, "Switching Protocols", &item->payload_id);
break;
case 102:
response_tmp = _php_jsr_response_error(-32102, "Processing", &item->payload_id);
break;
case 201:
response_tmp = _php_jsr_response_error(-32201, "Created", &item->payload_id);
break;
case 202:
response_tmp = _php_jsr_response_error(-32202, "Accepted", &item->payload_id);
break;
case 203:
response_tmp = _php_jsr_response_error(-32203, "Non-Authoritative Information", &item->payload_id);
break;
case 204:
response_tmp = _php_jsr_response_error(-32204, "No Content", &item->payload_id);
break;
case 205:
response_tmp = _php_jsr_response_error(-32205, "Reset Content", &item->payload_id);
break;
case 206:
response_tmp = _php_jsr_response_error(-32206, "Partial Content", &item->payload_id);
break;
case 207:
response_tmp = _php_jsr_response_error(-32207, "Multi-Status", &item->payload_id);
break;
case 300:
response_tmp = _php_jsr_response_error(-32300, "Multiple Choices", &item->payload_id);
break;
case 301:
response_tmp = _php_jsr_response_error(-32301, "Moved Permanently", &item->payload_id);
break;
case 302:
response_tmp = _php_jsr_response_error(-32302, "Move temporarily", &item->payload_id);
break;
case 303:
response_tmp = _php_jsr_response_error(-32303, "See Other", &item->payload_id);
break;
case 304:
response_tmp = _php_jsr_response_error(-32304, "Not Modified", &item->payload_id);
break;
case 305:
response_tmp = _php_jsr_response_error(-32305, "Use Proxy", &item->payload_id);
break;
case 306:
response_tmp = _php_jsr_response_error(-32306, "Switch Proxy", &item->payload_id);
break;
case 307:
response_tmp = _php_jsr_response_error(-32307, "Temporary Redirect", &item->payload_id);
break;
case 400:
response_tmp = _php_jsr_response_error(-32400, "Bad Request", &item->payload_id);
break;
case 401:
response_tmp = _php_jsr_response_error(-32401, "Unauthorized", &item->payload_id);
break;
case 402:
response_tmp = _php_jsr_response_error(-32402, "Payment Required", &item->payload_id);
break;
case 403:
response_tmp = _php_jsr_response_error(-32403, "Forbidden", &item->payload_id);
break;
case 404:
response_tmp = _php_jsr_response_error(-32404, "Not Found", &item->payload_id);
break;
case 405:
response_tmp = _php_jsr_response_error(-32405, "Method Not Allowed", &item->payload_id);
break;
case 406:
response_tmp = _php_jsr_response_error(-32406, "Not Acceptable", &item->payload_id);
break;
case 407:
response_tmp = _php_jsr_response_error(-32407, "Proxy Authentication Required", &item->payload_id);
break;
case 408:
response_tmp = _php_jsr_response_error(-32408, "Request Timeout", &item->payload_id);
break;
case 409:
response_tmp = _php_jsr_response_error(-32409, "Conflict", &item->payload_id);
break;
case 410:
response_tmp = _php_jsr_response_error(-32410, "Gone", &item->payload_id);
break;
case 411:
response_tmp = _php_jsr_response_error(-32411, "Length Required", &item->payload_id);
break;
case 412:
response_tmp = _php_jsr_response_error(-32412, "Precondition Failed", &item->payload_id);
break;
case 413:
response_tmp = _php_jsr_response_error(-32413, "Request Entity Too Large", &item->payload_id);
break;
case 414:
response_tmp = _php_jsr_response_error(-32414, "Request URI Too Long", &item->payload_id);
break;
case 415:
response_tmp = _php_jsr_response_error(-32415, "Unsupported Media Type", &item->payload_id);
break;
case 416:
response_tmp = _php_jsr_response_error(-32416, "Requested Range Not Satisfiable", &item->payload_id);
break;
case 417:
response_tmp = _php_jsr_response_error(-32417, "Expectation Failed", &item->payload_id);
break;
case 418:
response_tmp = _php_jsr_response_error(-32418, "I'm a teapot", &item->payload_id);
break;
case 421:
response_tmp = _php_jsr_response_error(-32421, "Misdirected Request", &item->payload_id);
break;
case 422:
response_tmp = _php_jsr_response_error(-32422, "Unprocessable Entity", &item->payload_id);
break;
case 423:
response_tmp = _php_jsr_response_error(-32423, "Locked", &item->payload_id);
break;
case 424:
response_tmp = _php_jsr_response_error(-32424, "Failed Dependency", &item->payload_id);
break;
case 426:
response_tmp = _php_jsr_response_error(-32426, "Upgrade Required", &item->payload_id);
break;
case 428:
response_tmp = _php_jsr_response_error(-32428, "Precondition Required", &item->payload_id);
break;
case 429:
response_tmp = _php_jsr_response_error(-32429, "Too Many Requests", &item->payload_id);
break;
case 431:
response_tmp = _php_jsr_response_error(-32431, "Request Header Fields Too Large", &item->payload_id);
break;
case 500:
response_tmp = _php_jsr_response_error(-32500, "Internal Server Error", &item->payload_id);
break;
case 501:
response_tmp = _php_jsr_response_error(-32501, "Not Implemented", &item->payload_id);
break;
case 502:
response_tmp = _php_jsr_response_error(-32502, "Bad Gateway", &item->payload_id);
break;
case 503:
response_tmp = _php_jsr_response_error(-32503, "Service Unavailable", &item->payload_id);
break;
case 504:
response_tmp = _php_jsr_response_error(-32504, "Gateway Timeout", &item->payload_id);
break;
case 505:
response_tmp = _php_jsr_response_error(-32505, "HTTP Version Not Supported", &item->payload_id);
break;
case 506:
response_tmp = _php_jsr_response_error(-32506, "Variant Also Negotiates", &item->payload_id);
break;
case 507:
response_tmp = _php_jsr_response_error(-32507, "Insufficient Storage", &item->payload_id);
break;
case 509:
response_tmp = _php_jsr_response_error(-32509, "Bandwidth Limit Exceeded", &item->payload_id);
break;
case 510:
response_tmp = _php_jsr_response_error(-32510, "Not Extended", &item->payload_id);
break;
default:
response_tmp = _php_jsr_response_error(-32599, "HTTP Unknow", &item->payload_id);
break;
}
zval *func;
zval **exec_params;
MAKE_STD_ZVAL(func);
exec_params = emalloc(sizeof(zval *) * 1);
exec_params[0] = response_tmp;
ZVAL_STRINGL(func, "Jsonrpc_Yajl::generate", sizeof("Jsonrpc_Yajl::generate") - 1, 0);
if (call_user_function(EG(function_table), NULL, func, response_tmp, 1, exec_params TSRMLS_CC) == FAILURE)
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed calling Jsonrpc_Yajl::generate()");
return ;
}
efree(exec_params);
efree(func);
item->write_length = Z_STRLEN_P(response_tmp);
//smart_str buf = {0};
//php_json_encode(&buf, response_tmp, 0 TSRMLS_CC);
//item->write_length = buf.len;
item->write_data = malloc(item->write_length + 1);
memset(item->write_data, 0, item->write_length);
//strncpy(item->write_data, buf.c, item->write_length+1);
strncpy(item->write_data, Z_STRVAL_P(response_tmp), item->write_length+1);
//smart_str_free(&buf);
zval_ptr_dtor(&response_tmp);
return length;
}
static zval*
_php_jsr_response_error(long code, char *message, jsr_payload_id *payload_id)
{
zval *response_tmp;
zval *error;
MAKE_STD_ZVAL(response_tmp);
array_init(response_tmp);
MAKE_STD_ZVAL(error);
array_init(error);
add_assoc_string(response_tmp, "jsonrpc", "2.0", 1);
if (payload_id){
if (payload_id->type == IS_LONG){
add_assoc_long(response_tmp, "id", payload_id->long_id);
}else if (payload_id->type == IS_STRING){
add_assoc_string(response_tmp, "id", payload_id->char_id, 1);
}else {
add_assoc_null(response_tmp, "id");
}
}else {
add_assoc_null(response_tmp, "id");
}
add_assoc_long(error, "code", code);
add_assoc_string(error, "message", message, 1);
add_assoc_zval(response_tmp, "error", error);
return response_tmp;
}
static void
_php_jsr_request_object_free_storage(void *object TSRMLS_DC)
{
php_jsr_reuqest_object *jsr_request = (php_jsr_reuqest_object *) object;
if (!jsr_request->context->is_persistent){
jsr_epoll_destroy(&(jsr_request->context->epoll));
}
jsr_curl_item_t *item;
size_t size;
while ((size = jsr_list_size(jsr_request->curlm->list)) > 0){
item = jsr_list_pop(jsr_request->curlm->list);
if (!jsr_request->executed){
//curl_easy_getinfo(item->curl_handle, CURLINFO_PRIVATE, &list);
curl_multi_remove_handle(jsr_request->curlm->multi_handle, item->curl_handle);
curl_easy_cleanup(item->curl_handle);
curl_slist_free_all(item->slist);
}
jsr_curl_item_destroy(&item);
}
if (!jsr_request->is_persistent){
jsr_curlm_destroy(&jsr_request->curlm);
}
jsr_curl_global_destroy();
zend_object_std_dtor(&jsr_request->zo TSRMLS_CC);
efree(jsr_request);
}
static zend_object_value
_php_jsr_request_object_new(zend_class_entry *class_type TSRMLS_DC)
{
zend_object_value result;
php_jsr_reuqest_object *jsr_request;
#if PHP_VERSION_ID < 50399
zval *tmp;
#endif
jsr_request = (php_jsr_reuqest_object *)emalloc(sizeof(php_jsr_reuqest_object));
memset(&jsr_request->zo, 0, sizeof(zend_object));
jsr_request->context = NULL;
jsr_request->curlm = NULL;
jsr_request->executed = 0;
jsr_request->is_persistent = 0;
zend_object_std_init(&jsr_request->zo, class_type TSRMLS_CC);
#if PHP_VERSION_ID < 50399
zend_hash_copy(
jsr_request->zo.properties,
&class_type->default_properties,
(copy_ctor_func_t) zval_property_ctor,
(void *)&tmp,
sizeof(zval *)
);
#else
object_properties_init( &jsr_request->zo, class_type );
#endif
result.handle = zend_objects_store_put(
jsr_request,
(zend_objects_store_dtor_t)zend_objects_destroy_object,
(zend_objects_free_object_storage_t) _php_jsr_request_object_free_storage,
NULL TSRMLS_CC
);
result.handlers = &jsr_request_object_handlers;
return result;
}
static php_jsr_epoll_context *
_php_jsr_epoll_new(zend_bool is_persistent TSRMLS_DC)
{
php_jsr_epoll_context *context;
context = pemalloc(sizeof(php_jsr_epoll_context), 1);
context->epoll = jsr_epoll_init();
if (!context->epoll){
pefree(context, is_persistent);
return NULL;
}
context->is_persistent = is_persistent;
return context;
}
static php_jsr_epoll_context *
_php_jsr_epoll_get(zend_bool is_persistent TSRMLS_DC)
{
php_jsr_epoll_context *context;
char plist_key[48];
int plist_key_len;
zend_rsrc_list_entry le, *le_p;
if (is_persistent){
plist_key_len = snprintf(plist_key, 48, "jsonrpc_client_epoll_1");
plist_key_len += 1;
if (zend_hash_find(&EG(persistent_list), plist_key, plist_key_len, (void *)&le_p) == SUCCESS)
{
if (le_p->type == le_jsr_epoll_persist){
return (php_jsr_epoll_context *) le_p->ptr;
}
}
}
context = _php_jsr_epoll_new(is_persistent TSRMLS_CC);
if (!context){
return NULL;
}
if (is_persistent){
le.type = le_jsr_epoll_persist;
le.ptr = context;
if (zend_hash_update(&EG(persistent_list), plist_key, plist_key_len, &le, sizeof(zend_rsrc_list_entry), NULL) == FAILURE)
{
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Could not register persistent entry for epoll");
}
}
return context;
}
static void
_php_jsr_epoll_destroy(php_jsr_epoll_context *context)
{
jsr_epoll_destroy(&context->epoll);
pefree(context, context->is_persistent);
}
static php_jsr_curlm_conn *
_php_jsr_curlm_new(zend_bool is_persistent TSRMLS_DC)
{
php_jsr_curlm_conn *conn;
conn = pemalloc(sizeof(php_jsr_curlm_conn), 1);
conn->curlm = jsr_curlm_new();
//php_printf("new curlm : %p\n", conn->curlm->multi_handle);
if (!conn->curlm){
pefree(conn, is_persistent);
return NULL;
}
conn->is_persistent = is_persistent;
return conn;
}
static php_jsr_curlm_conn *
_php_jsr_curlm_get(zend_bool is_persistent TSRMLS_DC)
{
php_jsr_curlm_conn *conn;
char plist_key[48];
int plist_key_len;
zend_rsrc_list_entry le, *le_p;
if (is_persistent){
plist_key_len = snprintf(plist_key, 48, "jsonrpc_client_curlm_1");
plist_key_len += 1;
if (zend_hash_find(&EG(persistent_list), plist_key, plist_key_len, (void *)&le_p) == SUCCESS)
{
if (le_p->type == le_jsr_curlm_persist){
return (php_jsr_curlm_conn *) le_p->ptr;
}
}
}
conn = _php_jsr_curlm_new(is_persistent TSRMLS_CC);
if (!conn){
return NULL;
}
if (is_persistent){
le.type = le_jsr_curlm_persist;
le.ptr = conn;
if (zend_hash_update(&EG(persistent_list), plist_key, plist_key_len, &le, sizeof(zend_rsrc_list_entry), NULL) == FAILURE)
{
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Could not register persistent entry for curlm");
}
}
return conn;
}
static void
_php_jsr_curlm_destroy(php_jsr_curlm_conn *conn)
{
jsr_curlm_destroy(&conn->curlm);
pefree(conn, conn->is_persistent);
}
ZEND_RSRC_DTOR_FUNC(_php_jsr_epoll_dtor)
{
if (rsrc->ptr){
php_jsr_epoll_context *context = (php_jsr_epoll_context *)rsrc->ptr;
_php_jsr_epoll_destroy(context);
rsrc->ptr = NULL;
}
}
ZEND_RSRC_DTOR_FUNC(_php_jsr_curlm_dtor)
{
if (rsrc->ptr){
php_jsr_curlm_conn *conn = (php_jsr_curlm_conn *) rsrc->ptr;
_php_jsr_curlm_destroy(conn);
rsrc->ptr = NULL;
}
}
PHP_METHOD(jsonrpc_client, __construct)
{
zval *object;
zval *request_obj;
zend_bool persist = 0;
php_jsr_epoll_context *context;
php_jsr_curlm_conn *conn;
php_jsr_reuqest_object *request;
jsr_epoll_t *epoll;
jsr_curlm_t *curlm;
object = getThis();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b",
&persist) == FAILURE)
{
return ;
}
jsr_curl_global_new();
context = _php_jsr_epoll_get(persist TSRMLS_CC);
conn = _php_jsr_curlm_get(persist TSRMLS_CC);
MAKE_STD_ZVAL(request_obj);
object_init_ex(request_obj, php_jsonrpc_client_request_entry);
request = (php_jsr_reuqest_object *)zend_object_store_get_object(request_obj TSRMLS_CC);
request->context = context;
request->curlm = conn->curlm;
request->is_persistent = persist;
curl_multi_setopt(request->curlm->multi_handle, CURLMOPT_SOCKETFUNCTION, _socket_callback);
curl_multi_setopt(request->curlm->multi_handle, CURLMOPT_SOCKETDATA, request);
curl_multi_setopt(request->curlm->multi_handle, CURLMOPT_TIMERFUNCTION, _timer_callback);
curl_multi_setopt(request->curlm->multi_handle, CURLMOPT_TIMERDATA, request);
zend_update_property(php_jsonrpc_client_entry,
object, "request", sizeof("request")-1, request_obj TSRMLS_CC
);
zval_ptr_dtor(&request_obj);
zend_update_property_long(php_jsonrpc_client_entry,
object, "response_total", sizeof("response_total")-1, 0 TSRMLS_CC
);
}
PHP_METHOD(jsonrpc_client, __destruct)
{
php_jsr_reuqest_object *request;
zval *object;
zval *request_obj;
object = getThis();
}
PHP_METHOD(jsonrpc_client, call)
{
php_jsr_reuqest_object *request;
jsr_curl_item_t *jsr_curl_item;
jsr_epoll_t **epoll_p;
char *url;
long url_len;
char *procedure;
long procedure_len;
zval *params;
zval *id = NULL;
zval *payload;
zval **payload_id;
zval *item;
zval *object;
zval *request_obj;
zval *response_total;
zval *coroutine_start;
zval *username;
zval *password;
object = getThis();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssz|z", &url, &url_len, &procedure, &procedure_len, &params, &id) == FAILURE)
{
return ;
}
request_obj = zend_read_property(
php_jsonrpc_client_entry, object, "request", sizeof("request")-1, 0 TSRMLS_CC
);
response_total = zend_read_property(
php_jsonrpc_client_entry, object, "response_total", sizeof("response_total")-1, 0 TSRMLS_CC
);
username = zend_read_property(
php_jsonrpc_client_entry, object, "username", sizeof("username")-1, 0 TSRMLS_CC
);
password = zend_read_property(
php_jsonrpc_client_entry, object, "password", sizeof("password")-1, 0 TSRMLS_CC
);
request = (php_jsr_reuqest_object *)zend_object_store_get_object(request_obj TSRMLS_CC);
MAKE_STD_ZVAL(payload);
//payload = _jsr_client_prepare_request(procedure, params, id TSRMLS_CC);
array_init(payload);
add_assoc_string(payload, "jsonrpc", "2.0", 1);
add_assoc_stringl(payload, "method", procedure, procedure_len, 1);
if (!id){
if (!BG(mt_rand_is_seeded)) {
php_mt_srand(GENERATE_SEED() TSRMLS_CC);
}
long number;
number = (long) (php_mt_rand(TSRMLS_C) >> 1);
MAKE_STD_ZVAL(id);
ZVAL_LONG(id, number);
add_assoc_long(payload, "id", Z_LVAL_P(id));
}else {
add_assoc_zval(payload, "id", id);
}
int nb_params;
nb_params = _php_count_recursive(params, 0 TSRMLS_CC);
if (nb_params > 0)
{
add_assoc_zval(payload, "params", params);
}
zval *func;
zval **exec_params;
MAKE_STD_ZVAL(func);
exec_params = emalloc(sizeof(zval *) * 1);
exec_params[0] = payload;
ZVAL_STRINGL(func, "Jsonrpc_Yajl::generate", sizeof("Jsonrpc_Yajl::generate") - 1, 0);
if (call_user_function(EG(function_table), NULL, func, payload, 1, exec_params TSRMLS_CC) == FAILURE)
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed calling Jsonrpc_Yajl::generate()");
return ;
}
efree(exec_params);
efree(func);
/*smart_str buf = {0};
php_json_encode(&buf, payload, 0 TSRMLS_CC);
ZVAL_STRINGL(payload, buf.c, buf.len, 1);
smart_str_free(&buf);*/
//jsr_dump_zval(payload);
convert_to_string_ex(&payload);
jsr_curl_item = jsr_curl_item_new(
url,
url_len,
Z_STRVAL_P(payload),
Z_STRLEN_P(payload),
Z_LVAL_P(response_total),
id
);
zval_ptr_dtor(&payload);
//jsr_curl_item->read_callback = _read_callback;
jsr_curl_item->write_callback = _write_callback;
if (strcmp(Z_STRVAL_P(username), "") != 0 && strcmp(Z_STRVAL_P(password), "") != 0)
{
jsr_curl_item->slist = curl_slist_append(jsr_curl_item->slist, Z_STRVAL_P(username));
jsr_curl_item->slist = curl_slist_append(jsr_curl_item->slist, Z_STRVAL_P(password));
}
jsr_curl_item_setopt(jsr_curl_item);
curl_multi_add_handle(request->curlm->multi_handle, jsr_curl_item->curl_handle);
jsr_curlm_list_push(request->curlm, jsr_curl_item);
//jsr_curlm_list_append(request->curlm, jsr_curl_item);
zend_update_property_long(php_jsonrpc_client_entry,
object, "response_total", sizeof("response_total")-1, Z_LVAL_P(response_total) + 1 TSRMLS_CC
);
}
PHP_METHOD(jsonrpc_client, execute)
{
zval *procedure;
zval *params;
zval *payload;
zval *response;
php_jsr_reuqest_object *request;
zval *object;
zval *func;
zval **func_params;
zval *request_obj;
zend_bool response_type=0;
object = getThis();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b",
&response_type) == FAILURE)
{
return ;
}
MAKE_STD_ZVAL(func);
request_obj = zend_read_property(
php_jsonrpc_client_entry, object, "request", sizeof("request")-1, 0 TSRMLS_CC
);
request = (php_jsr_reuqest_object *)zend_object_store_get_object(request_obj TSRMLS_CC);
request->executed = 1;
MAKE_STD_ZVAL(response);
array_init(response);
request->curlm->running_handles = 1;
request->context->epoll->loop_total = 0;
int action;
int start_mcode = CURLM_CALL_MULTI_PERFORM;
CURLMcode mcode;
while (request->curlm->running_handles > 0)
{
request->context->epoll->loop_total = jsr_epoll_loop(request->context->epoll , request->curlm->timeout);
//php_printf("loop_total: %d\n", request->context->epoll->loop_total);
if (request->context->epoll->loop_total == 0){
if (start_mcode == CURLM_CALL_MULTI_PERFORM){
start_mcode = curl_multi_socket_action(request->curlm->multi_handle, CURL_SOCKET_TIMEOUT, 0, &(request->curlm->running_handles));
//php_printf("start_mcode : %d\n", start_mcode);
}else if (start_mcode == CURLM_OK) {
start_mcode = curl_multi_socket_action(request->curlm->multi_handle, CURL_SOCKET_TIMEOUT, 0, &(request->curlm->running_handles));
//php_printf("running: %d\n",request->curlm->running_handles);
request->curlm->timeout = (request->curlm->timeout) * 2;
}else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "call curl_multi_socket_action error : %d", start_mcode);
break;
}
}else if (request->context->epoll->loop_total > 0){
int i;
for (i = 0; i < request->context->epoll->loop_total; i++){
//php_printf("action(.events) : %d\n" ,request->context->epoll->events[i].events);
if (request->context->epoll->events[i].events & EPOLLIN){
action = CURL_CSELECT_IN;
//php_printf("action(.events) : %d\n" ,action);
mcode = curl_multi_socket_action(request->curlm->multi_handle,
request->context->epoll->events[i].data.fd, action, &(request->curlm->running_handles));
//php_printf("action-mcode : %d\n", mcode);
}else if (request->context->epoll->events[i].events & EPOLLOUT){
action = CURL_CSELECT_OUT;
//php_printf("action(.events) : %d\n" ,action);
mcode = curl_multi_socket_action(request->curlm->multi_handle,
request->context->epoll->events[i].data.fd, action, &(request->curlm->running_handles));
//php_printf("action-mcode : %d\n", mcode);
}
}
}else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "epoll_wait error '%s'", strerror(errno));
break;
}
}
request->curlm->timeout = 1;
CURLMsg *msg;
int msgs_left;
CURL *easy;
CURLcode error_code;
jsr_curl_item_t *item;
size_t size;
zval *response_tmp;
while ((msg = curl_multi_info_read(request->curlm->multi_handle, &msgs_left)))
{
if (msg->msg == CURLMSG_DONE){
easy = msg->easy_handle;
error_code = msg->data.result;
//php_printf("error_code : %d\n", error_code);
curl_easy_getinfo(easy, CURLINFO_PRIVATE, &item);
if (error_code != CURLE_OK){
switch (error_code)
{
case CURLE_UNSUPPORTED_PROTOCOL:
response_tmp = _php_jsr_response_error(-32001, "Curl Unsupported Protocol", &item->payload_id);
break;
case CURLE_FAILED_INIT:
response_tmp = _php_jsr_response_error(-32002, "Curl Failed Init", &item->payload_id);
break;
case CURLE_URL_MALFORMAT:
response_tmp = _php_jsr_response_error(-32003, "Curl Url Malformat", &item->payload_id);
break;
case 4:
response_tmp = _php_jsr_response_error(-32004, "Curl Not Built In", &item->payload_id);
break;
case CURLE_COULDNT_RESOLVE_PROXY:
response_tmp = _php_jsr_response_error(-32005, "Curl Couldnt Resolve Proxy", &item->payload_id);
break;
case CURLE_COULDNT_RESOLVE_HOST:
response_tmp = _php_jsr_response_error(-32006, "Curl Couldnt Resolve Host", &item->payload_id);
break;
case CURLE_COULDNT_CONNECT:
response_tmp = _php_jsr_response_error(-32007, "Curl Couldnt Connect", &item->payload_id);
break;
case CURLE_OUT_OF_MEMORY:
response_tmp = _php_jsr_response_error(-32027, "Curl Out Of Memory", &item->payload_id);
break;
case CURLE_OPERATION_TIMEDOUT:
response_tmp = _php_jsr_response_error(-32028, "Curl Operaiton Timeout", &item->payload_id);
break;
case CURLE_RANGE_ERROR:
response_tmp = _php_jsr_response_error(-32033, "Curl Range Error", &item->payload_id);
break;
case CURLE_HTTP_POST_ERROR:
response_tmp = _php_jsr_response_error(-32034, "Curl Http Post Error", &item->payload_id);
break;
case CURLE_SEND_ERROR:
response_tmp = _php_jsr_response_error(-32055, "Curl Send Error", &item->payload_id);
break;
case CURLE_RECV_ERROR:
response_tmp = _php_jsr_response_error(-32056, "Curl Recv Error", &item->payload_id);
break;
default:
response_tmp = _php_jsr_response_error(-32099, "Curl Error Unknow", &item->payload_id);
break;
}
if (!response_type){
add_index_zval(response, item->response_id, response_tmp);
}else {
//zval *func;
zval **exec_params;
//MAKE_STD_ZVAL(func);
exec_params = emalloc(sizeof(zval *) * 1);
exec_params[0] = response_tmp;
ZVAL_STRINGL(func, "Jsonrpc_Yajl::generate", sizeof("Jsonrpc_Yajl::generate") - 1, 0);
if (call_user_function(EG(function_table), NULL, func, response_tmp, 1, exec_params TSRMLS_CC) == FAILURE)
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed calling Jsonrpc_Yajl::generate()");
return ;
}
efree(exec_params);
//efree(func);
add_index_stringl(response, item->response_id, Z_STRVAL_P(response_tmp), Z_STRLEN_P(response_tmp), 1);
zval_dtor(response_tmp);
//smart_str buf = {0};
//php_json_encode(&buf, response_tmp, 0 TSRMLS_CC);
//add_index_stringl(response, item->response_id, buf.c, buf.len, 1);
//zval_dtor(response_tmp);
}
//zval_ptr_dtor(&response_tmp);
}
if (item->write_data){
if (!response_type){
zval *tmp;
MAKE_STD_ZVAL(tmp);
ZVAL_STRINGL(tmp, item->write_data, item->write_length, 0);
func_params = emalloc(sizeof(zval *) * 1);
func_params[0] = tmp;
ZVAL_STRINGL(func, "Jsonrpc_Yajl::parse", sizeof("Jsonrpc_Yajl::parse") - 1, 0);
if (call_user_function(EG(function_table), NULL, func, tmp, 1, func_params TSRMLS_CC) == FAILURE)
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed calling Jsonrpc_Yajl::parse()");
return ;
}
add_index_zval(response, item->response_id, tmp);
efree(func_params);
/*zval *tmp;
MAKE_STD_ZVAL(tmp);
//array_init(tmp);
//php_printf("%s\n", item->write_data);
php_json_decode(tmp, item->write_data, item->write_length, 1, 512 TSRMLS_CC);
add_index_zval(response, item->response_id, tmp);
//zval_ptr_dtor(&tmp);*/
}else {
add_index_stringl(response, item->response_id, item->write_data, item->write_length, 1);
}
if (item->write_data){
free(item->write_data);
item->write_data = NULL;
}
}
curl_multi_remove_handle(request->curlm->multi_handle, easy);
curl_easy_cleanup(easy);
curl_slist_free_all(item->slist);
}
}
RETVAL_ZVAL(response, 1, 0);
zval_dtor(response);
efree(func);
}
PHP_METHOD(jsonrpc_client, connect)
{
char *url;
long url_len;
zval *object;
object = getThis();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &url, &url_len) == FAILURE)
{
return ;
}
zend_update_property_stringl(php_jsonrpc_client_entry,
object, "request_url", sizeof("request_url")-1, url, url_len TSRMLS_CC
);
}
PHP_METHOD(jsonrpc_client, __call)
{
char *method_s;
long method_len;
zval *method;
zval *params;
zval *request_url;
zval *func;
zval **exec_params;
zval retval;
zval *object;
object = getThis();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa", &method_s, &method_len, &params) == FAILURE)
{
return ;
}
//jsr_dump_zval(params);
INIT_ZVAL(retval);
request_url = zend_read_property(
php_jsonrpc_client_entry, object, "request_url", sizeof("request_url")-1, 0 TSRMLS_CC
);
//jsr_dump_zval(request_url);
MAKE_STD_ZVAL(method);
ZVAL_STRINGL(method, method_s, method_len, 0);
exec_params = emalloc(sizeof(zval *) * 3);
exec_params[0] = request_url;
exec_params[1] = method;
exec_params[2] = params;
MAKE_STD_ZVAL(func);
ZVAL_STRINGL(func, "call", sizeof("call") - 1, 0);
if (call_user_function(NULL, &object, func, &retval, 3, exec_params TSRMLS_CC) == FAILURE){
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed calling Jsonrpc_Client::call()");
return ;
}
//zval_ptr_dtor(&func);
//zval_ptr_dtor(&method);
efree(method);
efree(exec_params);
}
PHP_METHOD(jsonrpc_client, authentication)
{
char *username;
char *password;
long username_len;
long password_len;
zval *object;
object = getThis();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &username, &username_len, &password, &password_len) == FAILURE)
{
return ;
}
zend_update_property_stringl(php_jsonrpc_client_entry,
object, "username", sizeof("username")-1, username, username_len TSRMLS_CC
);
zend_update_property_stringl(php_jsonrpc_client_entry,
object, "password", sizeof("password")-1, password, password_len TSRMLS_CC
);
}
static const zend_function_entry jsonrpc_client_class_functions[] = {
PHP_ME(jsonrpc_client, __construct, jsonrpc_client_construct_arginfo, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
PHP_ME(jsonrpc_client, __destruct, jsonrpc_client_destruct_arginfo, ZEND_ACC_PUBLIC | ZEND_ACC_DTOR)
PHP_ME(jsonrpc_client, connect, jsonrpc_client_connect_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(jsonrpc_client, __call, jsonrpc_client___call_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(jsonrpc_client, call, jsonrpc_client_call_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(jsonrpc_client, execute, jsonrpc_client_execute_arginfo, ZEND_ACC_PUBLIC)
PHP_ME(jsonrpc_client, authentication, jsonrpc_client_authentication_arginfo, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
void
jsonrpc_client_init(int module_number TSRMLS_DC)
{
le_jsr_epoll_persist = zend_register_list_destructors_ex(NULL, _php_jsr_epoll_dtor, "jsonrpc persistent epoll", module_number);
le_jsr_curlm_persist = zend_register_list_destructors_ex(NULL, _php_jsr_curlm_dtor, "jsonrpc persisten curlm", module_number);
memcpy(&jsr_request_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
zend_class_entry jsonrpc_client_class_entry;
INIT_CLASS_ENTRY(jsonrpc_client_class_entry, "Jsonrpc_Client", jsonrpc_client_class_functions);
php_jsonrpc_client_entry = zend_register_internal_class(&jsonrpc_client_class_entry TSRMLS_CC);
//zend_declare_property_null(php_jsonrpc_client_entry, "response", sizeof("response")-1, ZEND_ACC_PUBLIC TSRMLS_CC);
zend_declare_property_null(php_jsonrpc_client_entry, "request", sizeof("request")-1, ZEND_ACC_PUBLIC TSRMLS_CC);
zend_declare_property_long(php_jsonrpc_client_entry, "response_total", sizeof("response_total")-1, 0, ZEND_ACC_PUBLIC TSRMLS_CC);
zend_declare_property_stringl(php_jsonrpc_client_entry, "request_url", sizeof("request_url")-1, "", 0, ZEND_ACC_PUBLIC TSRMLS_CC);
zend_declare_property_stringl(php_jsonrpc_client_entry, "username", sizeof("username")-1, "", 0, ZEND_ACC_PUBLIC TSRMLS_CC);
zend_declare_property_stringl(php_jsonrpc_client_entry, "password", sizeof("password")-1, "", 0, ZEND_ACC_PUBLIC TSRMLS_CC);
zend_class_entry jsonrpc_client_request_class_entry;
INIT_CLASS_ENTRY(jsonrpc_client_request_class_entry, "Jsonrpc_Client_Request", NULL);
jsonrpc_client_request_class_entry.create_object = _php_jsr_request_object_new;
php_jsonrpc_client_request_entry = zend_register_internal_class(&jsonrpc_client_request_class_entry TSRMLS_CC);
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/rryqszq4-JsonRPC.git
git@api.gitlife.ru:oschina-mirror/rryqszq4-JsonRPC.git
oschina-mirror
rryqszq4-JsonRPC
rryqszq4-JsonRPC
master