static PHP_METHOD(swoole_redis, __call) { zval *params; char *command; zend_size_t command_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &command, &command_len, ¶ms) == FAILURE) { return; } if (Z_TYPE_P(params) != IS_ARRAY) { swoole_php_fatal_error(E_WARNING, "invalid params."); RETURN_FALSE; } swRedisClient *redis = swoole_get_object(getThis()); if (!redis) { swoole_php_fatal_error(E_WARNING, "the object is not an instance of swoole_redis."); RETURN_FALSE; } switch (redis->state) { case SWOOLE_REDIS_STATE_CONNECT: swoole_php_error(E_WARNING, "redis client is not connected."); RETURN_FALSE; break; case SWOOLE_REDIS_STATE_WAIT_RESULT: if (swoole_redis_is_message_command(command, command_len)) { swoole_php_error(E_WARNING, "redis client is waiting for response."); RETURN_FALSE; } break; case SWOOLE_REDIS_STATE_SUBSCRIBE: if (!swoole_redis_is_message_command(command, command_len)) { swoole_php_error(E_WARNING, "redis client is waiting for subscribed messages."); RETURN_FALSE; } break; case SWOOLE_REDIS_STATE_CLOSED: swoole_php_error(E_WARNING, "redis client connection is closed."); RETURN_FALSE; break; default: break; } int argc = zend_hash_num_elements(Z_ARRVAL_P(params)); size_t stack_argvlen[SW_REDIS_COMMAND_BUFFER_SIZE]; char *stack_argv[SW_REDIS_COMMAND_BUFFER_SIZE]; size_t *argvlen; char **argv; zend_bool free_mm = 0; if (argc > SW_REDIS_COMMAND_BUFFER_SIZE) { argvlen = emalloc(sizeof(size_t) * argc); argv = emalloc(sizeof(char*) * argc); free_mm = 1; } else { argvlen = stack_argvlen; argv = stack_argv; } #define FREE_MEM() do { \ for (i = 1; i < argc; i++) \ { \ efree((void* )argv[i]); \ } \ \ if (redis->state == SWOOLE_REDIS_STATE_SUBSCRIBE) \ { \ efree(argv[argc]); \ } \ \ if (free_mm) \ { \ efree(argvlen); \ efree(argv); \ } \ } while (0) assert(command_len < SW_REDIS_COMMAND_KEY_SIZE - 1); char command_name[SW_REDIS_COMMAND_KEY_SIZE]; memcpy(command_name, command, command_len); command_name[command_len] = '\0'; argv[0] = command_name; argvlen[0] = command_len; zval *value; int i = 1; /** * subscribe command */ if (redis->state == SWOOLE_REDIS_STATE_SUBSCRIBE || (redis->subscribe && swoole_redis_is_message_command(command, command_len))) { redis->state = SWOOLE_REDIS_STATE_SUBSCRIBE; SW_HASHTABLE_FOREACH_START(Z_ARRVAL_P(params), value) convert_to_string(value); argvlen[i] = (size_t) Z_STRLEN_P(value); argv[i] = estrndup(Z_STRVAL_P(value), Z_STRLEN_P(value)); if (i == argc) { break; } i++; SW_HASHTABLE_FOREACH_END(); if (redisAsyncCommandArgv(redis->context, swoole_redis_onResult, NULL, argc + 1, (const char **) argv, (const size_t *) argvlen) < 0) { swoole_php_error(E_WARNING, "redisAsyncCommandArgv() failed."); FREE_MEM(); RETURN_FALSE; } } /** * storage command */ else { redis->state = SWOOLE_REDIS_STATE_WAIT_RESULT; redis->reqnum++; #if PHP_MAJOR_VERSION < 7 zval *callback; zval **cb_tmp; if (zend_hash_index_find(Z_ARRVAL_P(params), zend_hash_num_elements(Z_ARRVAL_P(params)) - 1, (void **) &cb_tmp) == FAILURE) { swoole_php_error(E_WARNING, "index out of array bounds."); FREE_MEM(); RETURN_FALSE; } callback = *cb_tmp; #else zval *callback = zend_hash_index_find(Z_ARRVAL_P(params), zend_hash_num_elements(Z_ARRVAL_P(params)) - 1); if (callback == NULL) { swoole_php_error(E_WARNING, "index out of array bounds."); FREE_MEM(); RETURN_FALSE; } #endif sw_zval_add_ref(&callback); callback = sw_zval_dup(callback); SW_HASHTABLE_FOREACH_START(Z_ARRVAL_P(params), value) if (i == argc) { break; } convert_to_string(value); argvlen[i] = (size_t) Z_STRLEN_P(value); argv[i] = estrndup(Z_STRVAL_P(value), Z_STRLEN_P(value)); i++; SW_HASHTABLE_FOREACH_END(); if (redisAsyncCommandArgv(redis->context, swoole_redis_onResult, callback, argc, (const char **) argv, (const size_t *) argvlen) < 0) { swoole_php_error(E_WARNING, "redisAsyncCommandArgv() failed."); FREE_MEM(); RETURN_FALSE; } } FREE_MEM(); RETURN_TRUE; }
static int http2_client_build_header(zval *zobject, http2_client_request *req, char *buffer, int buffer_len TSRMLS_DC) { char *date_str = NULL; int ret; zval *zheader = sw_zend_read_property(swoole_http2_client_class_entry_ptr, zobject, ZEND_STRL("requestHeaders"), 1 TSRMLS_CC); int index = 0; int find_host = 0; nghttp2_nv nv[1024]; http2_client_property *hcc = swoole_get_property(zobject, HTTP2_CLIENT_PROPERTY_INDEX); if (req->type == HTTP_GET) { http2_add_header(&nv[index++], ZEND_STRL(":method"), ZEND_STRL("GET")); } else { http2_add_header(&nv[index++], ZEND_STRL(":method"), ZEND_STRL("POST")); } http2_add_header(&nv[index++], ZEND_STRL(":path"), req->uri, req->uri_len); if (hcc->ssl) { http2_add_header(&nv[index++], ZEND_STRL(":scheme"), ZEND_STRL("https")); } else { http2_add_header(&nv[index++], ZEND_STRL(":scheme"), ZEND_STRL("http")); } //Host index++; if (zheader && !ZVAL_IS_NULL(zheader)) { HashTable *ht = Z_ARRVAL_P(zheader); zval *value = NULL; char *key = NULL; uint32_t keylen = 0; int type; SW_HASHTABLE_FOREACH_START2(ht, key, keylen, type, value) { if (!key) { break; } if (*key == ':') { continue; } if (strncasecmp("Host", key, keylen) == 0) { http2_add_header(&nv[3], ZEND_STRL(":authority"), Z_STRVAL_P(value), Z_STRLEN_P(value)); find_host = 1; } else { http2_add_header(&nv[index++], key, keylen, Z_STRVAL_P(value), Z_STRLEN_P(value)); } } SW_HASHTABLE_FOREACH_END(); (void)type; }
static PHP_METHOD(swoole_redis, __call) { zval *params; char *command; zend_size_t command_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &command, &command_len, ¶ms) == FAILURE) { return; } swRedisClient *redis = swoole_get_object(getThis()); switch (redis->state) { case SWOOLE_REDIS_STATE_CONNECT: swoole_php_error(E_WARNING, "redis client is not connected."); RETURN_FALSE; break; case SWOOLE_REDIS_STATE_WAIT: swoole_php_error(E_WARNING, "redis client is waiting for response."); RETURN_FALSE; break; case SWOOLE_REDIS_STATE_CLOSED: swoole_php_error(E_WARNING, "redis client connection is closed."); RETURN_FALSE; break; default: break; } #if PHP_MAJOR_VERSION < 7 zval *callback; zval **cb_tmp; if (zend_hash_index_find(Z_ARRVAL_P(params), zend_hash_num_elements(Z_ARRVAL_P(params)) - 1, (void **) &cb_tmp) == FAILURE) { swoole_php_error(E_WARNING, "index out of array."); RETURN_FALSE; } callback = *cb_tmp; redis->result_callback = callback; #else zval *callback = zend_hash_index_find(Z_ARRVAL_P(params), zend_hash_num_elements(Z_ARRVAL_P(params)) - 1); if (callback == NULL) { swoole_php_error(E_WARNING, "index out of array."); RETURN_FALSE; } redis->result_callback = &redis->_result_callback; memcpy(redis->result_callback, callback, sizeof(zval)); #endif sw_zval_add_ref(&redis->result_callback); redis->state = SWOOLE_REDIS_STATE_WAIT; int argc = zend_hash_num_elements(Z_ARRVAL_P(params)); size_t stack_argvlen[SW_REDIS_COMMAND_BUFFER_SIZE]; char *stack_argv[SW_REDIS_COMMAND_BUFFER_SIZE]; size_t *argvlen; char **argv; zend_bool free_mm = 0; if (argc > SW_REDIS_COMMAND_BUFFER_SIZE) { argvlen = emalloc(sizeof(size_t) * argc); argv = emalloc(sizeof(char*) * argc); free_mm = 1; } else { argvlen = stack_argvlen; argv = stack_argv; } assert(command_len < SW_REDIS_COMMAND_KEY_SIZE - 1); char command_name[SW_REDIS_COMMAND_KEY_SIZE]; memcpy(command_name, command, command_len); command_name[command_len] = '\0'; argv[0] = command_name; argvlen[0] = command_len; zval *value; int i = 1; SW_HASHTABLE_FOREACH_START(Z_ARRVAL_P(params), value) convert_to_string(value); argvlen[i] = (size_t) Z_STRLEN_P(value); argv[i] = estrndup(Z_STRVAL_P(value), Z_STRLEN_P(value)); if (i == argc - 1) { break; } i++; SW_HASHTABLE_FOREACH_END(); if (redisAsyncCommandArgv(redis->context, swoole_redis_onResult, NULL, argc, (const char **) argv, (const size_t *) argvlen) < 0) { swoole_php_error(E_WARNING, "redisAsyncCommandArgv() failed."); RETURN_FALSE; } for (i = 1; i < argc; i++) { efree((void* )argv[i]); } if (free_mm) { efree(argvlen); efree(argv); } redis->state = SWOOLE_REDIS_STATE_WAIT; RETURN_TRUE; }
static PHP_METHOD(swoole_module, __call) { zval *params; char *name; zend_size_t name_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &name, &name_len, ¶ms) == FAILURE) { return; } swModule *module = swoole_get_object(getThis()); if (module == NULL) { swoole_php_fatal_error(E_ERROR, "Please use swoole_load_module()."); return; } swModule_function func = swHashMap_find(module->functions, name, name_len); if (func == NULL) { swoole_php_fatal_error(E_ERROR, "Module[%s] does not have [%s] function.", module->name, name); return; } swArgs_clear(); zval *value; SW_HASHTABLE_FOREACH_START(Z_ARRVAL_P(params), value) switch(SW_Z_TYPE_P(value)) { case IS_STRING: swParam_string(Z_STRVAL_P(value), Z_STRLEN_P(value)); break; case IS_LONG: swParam_long(Z_LVAL_P(value)); break; case IS_DOUBLE: swParam_double(Z_DVAL_P(value)); break; #if PHP_MAJOR_VERSION < 7 case IS_BOOL: swParam_bool(Z_BVAL_P(value)); break; #else case IS_TRUE: swParam_bool(1); break; case IS_FALSE: swParam_bool(0); break; #endif default: swWarn("unknown type."); RETURN_FALSE; } SW_HASHTABLE_FOREACH_END(); swString *args = swString_dup2(SwooleG.call_php_func_args); if (args == NULL) { return; } swVal *retval = func(module, args, Z_ARRVAL_P(params)->nNumOfElements); if (swVal_to_zval(retval, return_value) < 0) { RETURN_NULL(); } swString_free(args); }
static int http2_build_header(http_context *ctx, uchar *buffer, int body_length TSRMLS_DC) { assert(ctx->send_header == 0); char buf[SW_HTTP_HEADER_MAX_SIZE]; char *date_str = NULL; char intbuf[2][16]; int ret; /** * http header */ zval *zheader = ctx->response.zheader; int index = 0; nghttp2_nv nv[128]; /** * http status code */ if (ctx->response.status == 0) { ctx->response.status = 200; } ret = swoole_itoa(intbuf[0], ctx->response.status); http2_add_header(&nv[index++], ZEND_STRL(":status"), intbuf[0], ret); if (zheader) { int flag = 0x0; char *key_server = "server"; char *key_content_length = "content-length"; char *key_content_type = "content-type"; char *key_date = "date"; HashTable *ht = Z_ARRVAL_P(zheader); zval *value = NULL; char *key = NULL; uint32_t keylen = 0; int type; SW_HASHTABLE_FOREACH_START2(ht, key, keylen, type, value) { if (!key) { break; } if (strcmp(key, key_server) == 0) { flag |= HTTP_RESPONSE_SERVER; } else if (strcmp(key, key_content_length) == 0) { flag |= HTTP_RESPONSE_CONTENT_LENGTH; } else if (strcmp(key, key_date) == 0) { flag |= HTTP_RESPONSE_DATE; } else if (strcmp(key, key_content_type) == 0) { flag |= HTTP_RESPONSE_CONTENT_TYPE; } http2_add_header(&nv[index++], key, keylen - 1, Z_STRVAL_P(value), Z_STRLEN_P(value)); } SW_HASHTABLE_FOREACH_END(); if (!(flag & HTTP_RESPONSE_SERVER)) { http2_add_header(&nv[index++], ZEND_STRL("server"), ZEND_STRL(SW_HTTP_SERVER_SOFTWARE)); } if (ctx->request.method == PHP_HTTP_OPTIONS) { http2_add_header(&nv[index++], ZEND_STRL("allow"), ZEND_STRL("GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS")); } else { if (!(flag & HTTP_RESPONSE_CONTENT_LENGTH) && body_length >= 0) { #ifdef SW_HAVE_ZLIB if (ctx->gzip_enable) { body_length = swoole_zlib_buffer->length; } #endif ret = swoole_itoa(intbuf[1], body_length); http2_add_header(&nv[index++], ZEND_STRL("content-length"), intbuf[1], ret); } } if (!(flag & HTTP_RESPONSE_DATE)) { date_str = sw_php_format_date(ZEND_STRL(SW_HTTP_DATE_FORMAT), SwooleGS->now, 0 TSRMLS_CC); http2_add_header(&nv[index++], ZEND_STRL("date"), date_str, strlen(date_str)); } if (!(flag & HTTP_RESPONSE_CONTENT_TYPE)) { http2_add_header(&nv[index++], ZEND_STRL("content-type"), ZEND_STRL("text/html")); } } else {
static int http2_client_build_header(zval *zobject, zval *req, char *buffer, int buffer_len TSRMLS_DC) { char *date_str = NULL; int ret; int index = 0; int find_host = 0; zval *cookies = sw_zend_read_property(swoole_http2_request_coro_class_entry_ptr, req, ZEND_STRL("cookies"), 1 TSRMLS_CC); zval *method = sw_zend_read_property(swoole_http2_request_coro_class_entry_ptr, req, ZEND_STRL("method"), 1 TSRMLS_CC); zval *path = sw_zend_read_property(swoole_http2_request_coro_class_entry_ptr, req, ZEND_STRL("path"), 1 TSRMLS_CC); zval *headers = sw_zend_read_property(swoole_http2_request_coro_class_entry_ptr, req, ZEND_STRL("headers"), 1 TSRMLS_CC); nghttp2_nv nv[1024]; http2_client_property *hcc = swoole_get_property(zobject, HTTP2_CLIENT_CORO_PROPERTY); if (ZVAL_IS_NULL(method) || Z_TYPE_P(method) != IS_STRING || Z_STRLEN_P(method) == 0) { http2_add_header(&nv[index++], ZEND_STRL(":method"), ZEND_STRL("GET")); } else { http2_add_header(&nv[index++], ZEND_STRL(":method"), Z_STRVAL_P(method), Z_STRLEN_P(method)); } if (ZVAL_IS_NULL(path) || Z_TYPE_P(path) != IS_STRING || Z_STRLEN_P(path) == 0) { http2_add_header(&nv[index++], ZEND_STRL(":path"), "/", 1); } else { http2_add_header(&nv[index++], ZEND_STRL(":path"), Z_STRVAL_P(path), Z_STRLEN_P(path)); } if (hcc->ssl) { http2_add_header(&nv[index++], ZEND_STRL(":scheme"), ZEND_STRL("https")); } else { http2_add_header(&nv[index++], ZEND_STRL(":scheme"), ZEND_STRL("http")); } //Host index++; if (headers && !ZVAL_IS_NULL(headers)) { HashTable *ht = Z_ARRVAL_P(headers); zval *value = NULL; char *key = NULL; uint32_t keylen = 0; int type; SW_HASHTABLE_FOREACH_START2(ht, key, keylen, type, value) { if (!key) { break; } if (*key == ':') { continue; } if (strncasecmp("Host", key, keylen) == 0) { http2_add_header(&nv[HTTP2_CLIENT_HOST_HEADER_INDEX], ZEND_STRL(":authority"), Z_STRVAL_P(value), Z_STRLEN_P(value)); find_host = 1; } else { http2_add_header(&nv[index++], key, keylen, Z_STRVAL_P(value), Z_STRLEN_P(value)); } } SW_HASHTABLE_FOREACH_END(); (void)type; }