PHP_METHOD(swoole_async, exec) { char *command; zend_size_t command_len; zval *callback; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &command, &command_len, &callback) == FAILURE) { return; } php_swoole_check_reactor(); if (!swReactor_handle_isset(SwooleG.main_reactor, PHP_SWOOLE_FD_PROCESS_STREAM)) { SwooleG.main_reactor->setHandle(SwooleG.main_reactor, PHP_SWOOLE_FD_PROCESS_STREAM | SW_EVENT_READ, process_stream_onRead); SwooleG.main_reactor->setHandle(SwooleG.main_reactor, PHP_SWOOLE_FD_PROCESS_STREAM | SW_EVENT_ERROR, process_stream_onRead); } pid_t pid; int fd = swoole_shell_exec(command, &pid); if (fd < 0) { swoole_php_error(E_WARNING, "Unable to execute '%s'", command); RETURN_FALSE; } swString *buffer = swString_new(1024); if (buffer == NULL) { RETURN_FALSE; } process_stream *ps = emalloc(sizeof(process_stream)); ps->callback = sw_zval_dup(callback); #ifdef SW_COROUTINE ps->context = NULL; #endif sw_zval_add_ref(&ps->callback); ps->fd = fd; ps->pid = pid; ps->buffer = buffer; if (SwooleG.main_reactor->add(SwooleG.main_reactor, ps->fd, PHP_SWOOLE_FD_PROCESS_STREAM | SW_EVENT_READ) < 0) { sw_zval_free(ps->callback); efree(ps); RETURN_FALSE; } else { swConnection *_socket = swReactor_get(SwooleG.main_reactor, ps->fd); _socket->object = ps; RETURN_LONG(pid); } }
static PHP_METHOD(swoole_server_port, getSocket) { swListenPort *port = swoole_get_object(getThis()); php_socket *socket_object = swoole_convert_to_socket(port->sock); if (!socket_object) { RETURN_FALSE; } SW_ZEND_REGISTER_RESOURCE(return_value, (void *) socket_object, php_sockets_le_socket()); zval *zsocket = sw_zval_dup(return_value); sw_zval_add_ref(&zsocket); }
static PHP_METHOD(swoole_ringqueue, push) { swRingQueue *queue = swoole_get_object(getThis()); zval *zdata; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zdata) == FAILURE) { RETURN_FALSE; } zdata = sw_zval_dup(zdata); if (swRingQueue_push(queue, zdata) < 0) { efree(zdata); RETURN_FALSE; } else { Z_TRY_ADDREF_P(zdata); RETURN_TRUE; } }
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 PHP_METHOD(swoole_mysql, query) { zval *callback; swString sql; bzero(&sql, sizeof(sql)); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &sql.str, &sql.length, &callback) == FAILURE) { return; } if (sql.length <= 0) { swoole_php_fatal_error(E_WARNING, "Query is empty."); RETURN_FALSE; } mysql_client *client = swoole_get_object(getThis()); if (!client) { swoole_php_fatal_error(E_WARNING, "object is not instanceof swoole_mysql."); RETURN_FALSE; } if (!client->cli) { swoole_php_fatal_error(E_WARNING, "mysql connection#%d is closed.", client->fd); RETURN_FALSE; } if (client->state != SW_MYSQL_STATE_QUERY) { swoole_php_fatal_error(E_WARNING, "mysql client is waiting response, cannot send new sql query."); RETURN_FALSE; } sw_zval_add_ref(&callback); client->callback = sw_zval_dup(callback); swString_clear(mysql_request_buffer); if (mysql_request(&sql, mysql_request_buffer) < 0) { RETURN_FALSE; } //send query if (SwooleG.main_reactor->write(SwooleG.main_reactor, client->fd, mysql_request_buffer->str, mysql_request_buffer->length) < 0) { //connection is closed if (swConnection_error(errno) == SW_CLOSE) { zend_update_property_bool(swoole_mysql_class_entry_ptr, getThis(), ZEND_STRL("connected"), 0 TSRMLS_CC); zend_update_property_bool(swoole_mysql_class_entry_ptr, getThis(), ZEND_STRL("errno"), 2006 TSRMLS_CC); } RETURN_FALSE; } else { client->state = SW_MYSQL_STATE_READ_START; RETURN_TRUE; } }
static PHP_METHOD(swoole_coroutine_util, create) { zval *callback; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &callback) == FAILURE) { return; } sw_zval_add_ref(&callback); callback = sw_zval_dup(callback); char *func_name = NULL; zend_fcall_info_cache *func_cache = emalloc(sizeof(zend_fcall_info_cache)); if (!sw_zend_is_callable_ex(callback, NULL, 0, &func_name, NULL, func_cache, NULL TSRMLS_CC)) { swoole_php_fatal_error(E_ERROR, "Function '%s' is not callable", func_name); sw_zval_free(callback); efree(func_name); return; } efree(func_name); php_swoole_check_reactor(); if (swReactorCheckPoint == NULL) { coro_init(TSRMLS_C); } zval *retval = NULL; zval *args[1]; jmp_buf *prev_checkpoint = swReactorCheckPoint; swReactorCheckPoint = emalloc(sizeof(jmp_buf)); php_context *cxt = emalloc(sizeof(php_context)); coro_save(cxt); int ret = coro_create(func_cache, args, 0, &retval, NULL, NULL); efree(func_cache); efree(swReactorCheckPoint); if (ret < 0) { sw_zval_free(callback); RETURN_FALSE; } //save callback COROG.current_coro->function = callback; swReactorCheckPoint = prev_checkpoint; coro_resume_parent(cxt, retval, retval); efree(cxt); if (EG(exception)) { zend_exception_error(EG(exception), E_ERROR TSRMLS_CC); } if (retval != NULL) { sw_zval_ptr_dtor(&retval); } RETURN_TRUE; }