static PHP_METHOD(swoole_coroutine_util, sleep) { coro_check(TSRMLS_C); double seconds; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", & seconds) == FAILURE) { return; } int ms = (int) (seconds * 1000); if (SwooleG.serv && swIsMaster()) { swoole_php_fatal_error(E_WARNING, "cannot use timer in master process."); return; } if (ms > SW_TIMER_MAX_VALUE) { swoole_php_fatal_error(E_WARNING, "The given parameters is too big."); return; } if (ms <= 0) { swoole_php_fatal_error(E_WARNING, "Timer must be greater than 0"); return; } php_swoole_check_reactor(); php_swoole_check_timer(ms); swoole_coroutine_sleep(seconds); RETURN_TRUE; }
static void co_socket_read(int fd, zend_long length, INTERNAL_FUNCTION_PARAMETERS) { php_swoole_check_reactor(); if (!swReactor_handle_isset(SwooleG.main_reactor, PHP_SWOOLE_FD_SOCKET)) { SwooleG.main_reactor->setHandle(SwooleG.main_reactor, PHP_SWOOLE_FD_CO_UTIL | SW_EVENT_READ, co_socket_onReadable); SwooleG.main_reactor->setHandle(SwooleG.main_reactor, PHP_SWOOLE_FD_CO_UTIL | SW_EVENT_WRITE, co_socket_onWritable); } if (SwooleG.main_reactor->add(SwooleG.main_reactor, fd, PHP_SWOOLE_FD_CO_UTIL | SW_EVENT_READ) < 0) { SwooleG.error = errno; RETURN_FALSE; } swConnection *_socket = swReactor_get(SwooleG.main_reactor, fd); util_socket *sock = emalloc(sizeof(util_socket)); bzero(sock, sizeof(util_socket)); _socket->object = sock; sock->fd = fd; sock->buf = zend_string_alloc(length + 1, 0); sock->nbytes = length <= 0 ? SW_BUFFER_SIZE_STD : length; sock->context.state = SW_CORO_CONTEXT_RUNNING; coro_save(&sock->context); coro_yield(); }
static PHP_METHOD(swoole_process, signal) { zval *callback = NULL; long signo = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz", &signo, &callback) == FAILURE) { return; } if (!SWOOLE_G(cli)) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "cannot use swoole_process::signal here."); RETURN_FALSE; } if (SwooleGS->start) { if (signo == SIGTERM || signo == SIGALRM) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot use swoole_process::signal in swoole_server."); RETURN_FALSE; } } if (callback == NULL || ZVAL_IS_NULL(callback)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "no callback."); RETURN_FALSE; } char *func_name; if (!sw_zend_is_callable(callback, 0, &func_name TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "function '%s' is not callable", func_name); efree(func_name); RETURN_FALSE; } efree(func_name); sw_zval_add_ref(&callback); signal_callback[signo] = callback; #if PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 4 SwooleG.use_signalfd = 1; #else SwooleG.use_signalfd = 0; #endif php_swoole_check_reactor(); /** * for swSignalfd_setup */ SwooleG.main_reactor->check_signalfd = 1; swSignal_add(signo, php_swoole_onSignal); RETURN_TRUE; }
void php_swoole_check_aio() { if (unlikely(SwooleAIO.init == 0)) { php_swoole_check_reactor(); swAio_init(); } }
static void php_swoole_check_aio() { if (SwooleAIO.init == 0) { php_swoole_check_reactor(); swAio_init(); SwooleAIO.callback = php_swoole_aio_onComplete; } }
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 void php_swoole_check_aio() { if (php_swoole_aio_init == 0) { php_swoole_check_reactor(); swoole_aio_init(SwooleG.main_reactor, PHP_SWOOLE_AIO_MAXEVENTS); swoole_aio_set_callback(php_swoole_aio_onComplete); php_swoole_try_run_reactor(); php_swoole_aio_init = 1; } }
static PHP_METHOD(swoole_coroutine_util, readFile) { coro_check(TSRMLS_C); char *filename = NULL; size_t l_filename = 0; #ifdef FAST_ZPP ZEND_PARSE_PARAMETERS_START(1, 2) Z_PARAM_STRING(filename, l_filename) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); #else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &l_filename) == FAILURE) { return; } #endif swAio_event ev; bzero(&ev, sizeof(swAio_event)); php_context *context = emalloc(sizeof(php_context)); ev.type = SW_AIO_READ_FILE; ev.object = context; ev.handler = swAio_handler_read_file; ev.callback = aio_onReadFileCompleted; ev.req = estrndup(filename, l_filename); if (!SwooleAIO.init) { php_swoole_check_reactor(); swAio_init(); } swTrace("readFile(%s)", filename); int ret = swAio_dispatch(&ev); if (ret < 0) { efree(context); RETURN_FALSE; } context->state = SW_CORO_CONTEXT_RUNNING; coro_save(context); coro_yield(); }
long php_swoole_add_timer(int ms, zval *callback, zval *param, int is_tick TSRMLS_DC) { if (ms > 86400000) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "The given parameters is too big."); return SW_ERR; } char *func_name = NULL; if (!sw_zend_is_callable(callback, 0, &func_name TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "Function '%s' is not callable", func_name); efree(func_name); return SW_ERR; } efree(func_name); if (SwooleGS->start > 0 && swIsTaskWorker()) { swoole_php_error(E_WARNING, "cannot use swoole_server->after in task worker."); } swTimer_callback *cb = emalloc(sizeof(swTimer_callback)); cb->data = param; cb->callback = callback; if (is_tick) { cb->type = SW_TIMER_TICK; } else { cb->type = SW_TIMER_AFTER; } php_swoole_check_reactor(); php_swoole_check_timer(ms); sw_zval_add_ref(&cb->callback); if (cb->data) { sw_zval_add_ref(&cb->data); } return SwooleG.timer.add(&SwooleG.timer, ms, is_tick, cb); }
static PHP_METHOD(swoole_coroutine_util, sleep) { coro_check(TSRMLS_C); double seconds; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", & seconds) == FAILURE) { return; } int ms = (int) (seconds * 1000); if (SwooleG.serv && swIsMaster()) { swoole_php_fatal_error(E_WARNING, "cannot use timer in master process."); return; } if (ms > SW_TIMER_MAX_VALUE) { swoole_php_fatal_error(E_WARNING, "The given parameters is too big."); return; } if (ms <= 0) { swoole_php_fatal_error(E_WARNING, "Timer must be greater than 0"); return; } php_context *context = emalloc(sizeof(php_context)); context->onTimeout = NULL; context->state = SW_CORO_CONTEXT_RUNNING; php_swoole_check_reactor(); php_swoole_check_timer(ms); if (SwooleG.timer.add(&SwooleG.timer, ms, 0, context, php_coroutine_sleep_timeout) == NULL) { RETURN_FALSE; } coro_save(context); coro_yield(); }
static PHP_METHOD(swoole_mysql, connect) { zval *server_info; zval *callback; char buf[2048]; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "az", &server_info, &callback) == FAILURE) { RETURN_FALSE; } HashTable *_ht = Z_ARRVAL_P(server_info); zval *value; mysql_client *client = swoole_get_object(getThis()); mysql_connector *connector = &client->connector; if (php_swoole_array_get_value(_ht, "host", value)) { convert_to_string(value); connector->host = Z_STRVAL_P(value); connector->host_len = Z_STRLEN_P(value); } else { zend_throw_exception(swoole_mysql_exception_class_entry, "HOST parameter is required.", 11 TSRMLS_CC); RETURN_FALSE; } if (php_swoole_array_get_value(_ht, "port", value)) { convert_to_long(value); connector->port = Z_LVAL_P(value); } else { connector->port = SW_MYSQL_DEFAULT_PORT; } if (php_swoole_array_get_value(_ht, "user", value)) { convert_to_string(value); connector->user = Z_STRVAL_P(value); connector->user_len = Z_STRLEN_P(value); } else { zend_throw_exception(swoole_mysql_exception_class_entry, "USER parameter is required.", 11 TSRMLS_CC); RETURN_FALSE; } if (php_swoole_array_get_value(_ht, "password", value)) { convert_to_string(value); connector->password = Z_STRVAL_P(value); connector->password_len = Z_STRLEN_P(value); } else { zend_throw_exception(swoole_mysql_exception_class_entry, "PASSWORD parameter is required.", 11 TSRMLS_CC); RETURN_FALSE; } if (php_swoole_array_get_value(_ht, "database", value)) { convert_to_string(value); connector->database = Z_STRVAL_P(value); connector->database_len = Z_STRLEN_P(value); } else { zend_throw_exception(swoole_mysql_exception_class_entry, "DATABASE parameter is required.", 11 TSRMLS_CC); RETURN_FALSE; } if (php_swoole_array_get_value(_ht, "timeout", value)) { convert_to_double(value); connector->timeout = Z_DVAL_P(value); } else { connector->timeout = SW_MYSQL_CONNECT_TIMEOUT; } if (php_swoole_array_get_value(_ht, "charset", value)) { convert_to_string(value); connector->character_set = mysql_get_charset(Z_STRVAL_P(value)); if (connector->character_set < 0) { snprintf(buf, sizeof(buf), "unknown charset [%s].", Z_STRVAL_P(value)); zend_throw_exception(swoole_mysql_exception_class_entry, buf, 11 TSRMLS_CC); RETURN_FALSE; } } else { connector->character_set = SW_MYSQL_DEFAULT_CHARSET; } swClient *cli = emalloc(sizeof(swClient)); int type = SW_SOCK_TCP; if (strncasecmp(connector->host, ZEND_STRL("unix:/")) == 0) { connector->host = connector->host + 5; connector->host_len = connector->host_len - 5; type = SW_SOCK_UNIX_STREAM; } else if (strchr(connector->host, ':')) { type = SW_SOCK_TCP6; } php_swoole_check_reactor(); if (!isset_event_callback) { SwooleG.main_reactor->setHandle(SwooleG.main_reactor, PHP_SWOOLE_FD_MYSQL | SW_EVENT_READ, swoole_mysql_onRead); SwooleG.main_reactor->setHandle(SwooleG.main_reactor, PHP_SWOOLE_FD_MYSQL | SW_EVENT_WRITE, swoole_mysql_onWrite); SwooleG.main_reactor->setHandle(SwooleG.main_reactor, PHP_SWOOLE_FD_MYSQL | SW_EVENT_ERROR, swoole_mysql_onError); } if (swClient_create(cli, type, 0) < 0) { zend_throw_exception(swoole_mysql_exception_class_entry, "swClient_create failed.", 1 TSRMLS_CC); RETURN_FALSE; } int tcp_nodelay = 1; if (setsockopt(cli->socket->fd, IPPROTO_TCP, TCP_NODELAY, (const void *) &tcp_nodelay, sizeof(int)) == -1) { swoole_php_sys_error(E_WARNING, "setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) failed.", cli->socket->fd); } int ret = cli->connect(cli, connector->host, connector->port, connector->timeout, 1); if ((ret < 0 && errno == EINPROGRESS) || ret == 0) { if (SwooleG.main_reactor->add(SwooleG.main_reactor, cli->socket->fd, PHP_SWOOLE_FD_MYSQL | SW_EVENT_WRITE) < 0) { RETURN_FALSE; } } else { snprintf(buf, sizeof(buf), "connect to mysql server[%s:%d] failed.", connector->host, connector->port); zend_throw_exception(swoole_mysql_exception_class_entry, buf, 2 TSRMLS_CC); RETURN_FALSE; } zend_update_property(swoole_mysql_class_entry_ptr, getThis(), ZEND_STRL("onConnect"), callback TSRMLS_CC); zend_update_property(swoole_mysql_class_entry_ptr, getThis(), ZEND_STRL("serverInfo"), server_info TSRMLS_CC); zend_update_property_long(swoole_mysql_class_entry_ptr, getThis(), ZEND_STRL("sock"), cli->socket->fd TSRMLS_CC); client->buffer = swString_new(SW_BUFFER_SIZE_BIG); client->fd = cli->socket->fd; client->object = getThis(); client->cli = cli; sw_copy_to_stack(client->object, client->_object); sw_zval_add_ref(&client->object); swConnection *_socket = swReactor_get(SwooleG.main_reactor, cli->socket->fd); _socket->object = client; _socket->active = 0; RETURN_TRUE; }
static int http_client_coro_execute(zval *zobject, char *uri, zend_size_t uri_len TSRMLS_DC) { if (uri_len <= 0) { swoole_php_fatal_error(E_WARNING, "path is empty."); return SW_ERR; } http_client *http = swoole_get_object(zobject); //http is not null when keeping alive if (http) { //http not ready if (http->state != HTTP_CLIENT_STATE_READY) { //swWarn("fd=%d, state=%d, active=%d, keep_alive=%d", http->cli->socket->fd, http->state, http->cli->socket->active, http->keep_alive); swoole_php_fatal_error(E_WARNING, "Operation now in progress phase %d.", http->state); return SW_ERR; } else if (!http->cli->socket->active) { swoole_php_fatal_error(E_WARNING, "connection#%d is closed.", http->cli->socket->fd); return SW_ERR; } } else { php_swoole_check_reactor(); http = http_client_create(zobject TSRMLS_CC); } if (http == NULL) { return SW_ERR; } if (http->body == NULL) { http->body = swString_new(SW_HTTP_RESPONSE_INIT_SIZE); if (http->body == NULL) { swoole_php_fatal_error(E_ERROR, "[1] swString_new(%d) failed.", SW_HTTP_RESPONSE_INIT_SIZE); return SW_ERR; } } else { swString_clear(http->body); } if (http->uri) { efree(http->uri); } http->uri = estrdup(uri); http->uri_len = uri_len; //if connection exists if (http->cli) { http_client_coro_send_http_request(zobject TSRMLS_CC); return SW_OK; } swClient *cli = php_swoole_client_new(zobject, http->host, http->host_len, http->port); if (cli == NULL) { return SW_ERR; } http->cli = cli; zval *ztmp; HashTable *vht; zval *zset = sw_zend_read_property(swoole_http_client_coro_class_entry_ptr, zobject, ZEND_STRL("setting"), 1 TSRMLS_CC); if (zset && !ZVAL_IS_NULL(zset)) { vht = Z_ARRVAL_P(zset); /** * timeout */ if (php_swoole_array_get_value(vht, "timeout", ztmp)) { convert_to_double(ztmp); http->timeout = (double) Z_DVAL_P(ztmp); } /** * keep_alive */ if (php_swoole_array_get_value(vht, "keep_alive", ztmp)) { convert_to_boolean(ztmp); http->keep_alive = (int) Z_LVAL_P(ztmp); } //client settings php_swoole_client_check_setting(http->cli, zset TSRMLS_CC); } if (cli->socket->active == 1) { swoole_php_fatal_error(E_WARNING, "swoole_http_client is already connected."); return SW_ERR; } #if PHP_MAJOR_VERSION < 7 sw_zval_add_ref(&zobject); #endif cli->object = zobject; //sw_copy_to_stack(cli->object, hcc->_object); cli->open_eof_check = 0; cli->open_length_check = 0; cli->reactor_fdtype = PHP_SWOOLE_FD_STREAM_CLIENT; cli->onReceive = http_client_coro_onReceive; cli->onConnect = http_client_coro_onConnect; cli->onClose = http_client_coro_onClose; cli->onError = http_client_coro_onError; return cli->connect(cli, http->host, http->port, http->timeout, 0); }
static PHP_METHOD(swoole_coroutine_util, fgets) { coro_check(TSRMLS_C); zval *handle; php_stream *stream; #ifdef FAST_ZPP ZEND_PARSE_PARAMETERS_START(1, 2) Z_PARAM_RESOURCE(handle) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); #else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &handle) == FAILURE) { return; } #endif int async; int fd = swoole_convert_to_fd_ex(handle, &async); if (fd < 0) { RETURN_FALSE; } if (async == 1) { swoole_php_fatal_error(E_WARNING, "only support file resources."); RETURN_FALSE; } swAio_event ev; bzero(&ev, sizeof(swAio_event)); php_stream_from_res(stream, Z_RES_P(handle)); if (stream->readbuf == NULL) { stream->readbuflen = stream->chunk_size; stream->readbuf = emalloc(stream->chunk_size); } ev.nbytes = stream->readbuflen; ev.buf = stream->readbuf; if (!ev.buf) { RETURN_FALSE; } php_context *context = emalloc(sizeof(php_context)); ev.flags = 0; ev.type = SW_AIO_STREAM_GET_LINE; ev.object = context; ev.callback = aio_onStreamGetLineCompleted; ev.handler = swAio_handler_stream_get_line; ev.fd = fd; ev.offset = stream->readpos; ev.req = (void *) (long) stream->writepos; if (!SwooleAIO.init) { php_swoole_check_reactor(); swAio_init(); } swTrace("fd=%d, offset=%jd, length=%ld", fd, (intmax_t) ev.offset, ev.nbytes); int ret = swAio_dispatch(&ev); if (ret < 0) { efree(context); RETURN_FALSE; } context->coro_params = *handle; context->state = SW_CORO_CONTEXT_RUNNING; coro_save(context); coro_yield(); }
static PHP_METHOD(swoole_coroutine_util, fread) { coro_check(TSRMLS_C); zval *handle; zend_long length = 0; #ifdef FAST_ZPP ZEND_PARSE_PARAMETERS_START(1, 2) Z_PARAM_RESOURCE(handle) Z_PARAM_OPTIONAL Z_PARAM_LONG(length) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); #else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &handle, &length) == FAILURE) { return; } #endif int async; int fd = swoole_convert_to_fd_ex(handle, &async TSRMLS_CC); if (fd < 0) { RETURN_FALSE; } if (async) { co_socket_read(fd, length, INTERNAL_FUNCTION_PARAM_PASSTHRU); return; } struct stat file_stat; if (fstat(fd, &file_stat) < 0) { SwooleG.error = errno; RETURN_FALSE; } off_t _seek = lseek(fd, 0, SEEK_CUR); if (_seek < 0) { SwooleG.error = errno; RETURN_FALSE; } if (length <= 0 || file_stat.st_size - _seek < length) { length = file_stat.st_size - _seek; } swAio_event ev; bzero(&ev, sizeof(swAio_event)); ev.nbytes = length + 1; ev.buf = emalloc(ev.nbytes); if (!ev.buf) { RETURN_FALSE; } php_context *context = emalloc(sizeof(php_context)); ((char *) ev.buf)[length] = 0; ev.flags = 0; ev.type = SW_AIO_READ; ev.object = context; ev.handler = swAio_handler_read; ev.callback = aio_onReadCompleted; ev.fd = fd; ev.offset = _seek; if (!SwooleAIO.init) { php_swoole_check_reactor(); swAio_init(); } swTrace("fd=%d, offset=%jd, length=%ld", fd, (intmax_t) ev.offset, ev.nbytes); int ret = swAio_dispatch(&ev); if (ret < 0) { efree(context); RETURN_FALSE; } context->state = SW_CORO_CONTEXT_RUNNING; coro_save(context); coro_yield(); }
long php_swoole_add_timer(int ms, zval *callback, zval *param, int persistent TSRMLS_DC) { if (ms > SW_TIMER_MAX_VALUE) { swoole_php_fatal_error(E_WARNING, "The given parameters is too big."); return SW_ERR; } if (ms <= 0) { swoole_php_fatal_error(E_WARNING, "Timer must be greater than 0"); return SW_ERR; } 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)) { efree(func_cache); efree(func_name); swoole_php_fatal_error(E_ERROR, "Function '%s' is not callable", func_name); return SW_ERR; } efree(func_name); if (!swIsTaskWorker()) { php_swoole_check_reactor(); } php_swoole_check_timer(ms); swTimer_callback *cb = emalloc(sizeof(swTimer_callback)); cb->data = &cb->_data; cb->callback = &cb->_callback; memcpy(cb->callback, callback, sizeof(zval)); if (param) { memcpy(cb->data, param, sizeof(zval)); } else { cb->data = NULL; } if (SwooleG.enable_coroutine) { cb->func_cache = func_cache; } else { efree(func_cache); } swTimerCallback timer_func; if (persistent) { cb->type = SW_TIMER_TICK; timer_func = php_swoole_onInterval; } else { cb->type = SW_TIMER_AFTER; timer_func = php_swoole_onTimeout; } sw_zval_add_ref(&cb->callback); if (cb->data) { sw_zval_add_ref(&cb->data); } swTimer_node *tnode = SwooleG.timer.add(&SwooleG.timer, ms, persistent, cb, timer_func); if (tnode == NULL) { swoole_php_fatal_error(E_WARNING, "add timer failed."); return SW_ERR; } else { tnode->type = SW_TIMER_TYPE_PHP; return tnode->id; } }
static PHP_METHOD(swoole_mysql, __construct) { if (!mysql_request_buffer) { mysql_request_buffer = swString_new(SW_MYSQL_QUERY_INIT_SIZE); if (!mysql_request_buffer) { swoole_php_fatal_error(E_ERROR, "[1] swString_new(%d) failed.", SW_HTTP_RESPONSE_INIT_SIZE); RETURN_FALSE; } } char *unixsocket = NULL; zend_size_t unixsocket_len = 0; mysql_connector connector; connector.port = SW_MYSQL_DEFAULT_PORT; if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "ssss|ls", &connector.host, &connector.host_len, &connector.user, &connector.user_len, &connector.password, &connector.password_len, &connector.database, &connector.database_len, &connector.port, &unixsocket, &unixsocket_len) == FAILURE) { RETURN_FALSE; } swClient *cli = emalloc(sizeof(swClient)); int type = SW_SOCK_TCP; if (unixsocket) { type = SW_SOCK_UNIX_STREAM; connector.host = unixsocket; connector.host_len = unixsocket_len; } if (swClient_create(cli, type, 0) < 0) { zend_throw_exception(swoole_mysql_exception_class_entry, "swClient_create failed.", 1 TSRMLS_CC); RETURN_FALSE; } if (cli->connect(cli, connector.host, connector.port, SW_MYSQL_CONNECT_TIMEOUT, 0) < 0) { zend_throw_exception(swoole_mysql_exception_class_entry, "connect to mysql server[%s:%d] failed.", 2 TSRMLS_CC); RETURN_FALSE; } int tcp_nodelay = 1; if (setsockopt(cli->socket->fd, IPPROTO_TCP, TCP_NODELAY, (const void *) &tcp_nodelay, sizeof(int)) == -1) { swoole_php_sys_error(E_WARNING, "setsockopt(%d, IPPROTO_TCP, TCP_NODELAY) failed.", cli->socket->fd); } char buf[2048]; int n = cli->recv(cli, buf, sizeof(buf), 0); if (n < 0) { zend_throw_exception(swoole_mysql_exception_class_entry, "recvfrom mysql server failed.", 3 TSRMLS_CC); RETURN_FALSE; } if (mysql_handshake(&connector, buf, n) == SW_ERR) { zend_throw_exception(swoole_mysql_exception_class_entry, "handshake with mysql server failed.", 4 TSRMLS_CC); RETURN_FALSE; } if (cli->send(cli, connector.buf, connector.packet_length + 4, 0) < 0) { zend_throw_exception(swoole_mysql_exception_class_entry, "sendto mysql server failed.", 5 TSRMLS_CC); RETURN_FALSE; } if (cli->recv(cli, buf, sizeof(buf), 0) < 0) { zend_throw_exception(swoole_mysql_exception_class_entry, "recvfrom mysql server failed.", 6 TSRMLS_CC); RETURN_FALSE; } mysql_client *client = emalloc(sizeof(mysql_client)); bzero(client, sizeof(mysql_client)); client->buffer = swString_new(SW_BUFFER_SIZE_BIG); client->fd = cli->socket->fd; client->object = getThis(); client->cli = cli; sw_copy_to_stack(client->object, client->_object); zend_update_property_bool(swoole_mysql_class_entry_ptr, getThis(), ZEND_STRL("connected"), 1 TSRMLS_CC); swoole_set_object(getThis(), client); php_swoole_check_reactor(); swSetNonBlock(cli->socket->fd); if (!isset_event_callback) { SwooleG.main_reactor->setHandle(SwooleG.main_reactor, PHP_SWOOLE_FD_MYSQL | SW_EVENT_READ, swoole_mysql_onRead); SwooleG.main_reactor->setHandle(SwooleG.main_reactor, PHP_SWOOLE_FD_MYSQL | SW_EVENT_ERROR, swoole_mysql_onError); } swConnection *socket = swReactor_get(SwooleG.main_reactor, cli->socket->fd); socket->active = 1; socket->object = client; }
static PHP_METHOD(swoole_coroutine_util, writeFile) { coro_check(TSRMLS_C); char *filename = NULL; size_t l_filename = 0; char *data = NULL; size_t l_data = 0; zend_long flags = 0; #ifdef FAST_ZPP ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STRING(filename, l_filename) Z_PARAM_STRING(data, l_data) Z_PARAM_OPTIONAL Z_PARAM_LONG(flags) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); #else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &filename, &l_filename, &data, &l_data, &flags) == FAILURE) { return; } #endif swAio_event ev; bzero(&ev, sizeof(swAio_event)); ev.nbytes = l_data; ev.buf = data; php_context *context = emalloc(sizeof(php_context)); ev.type = SW_AIO_WRITE_FILE; ev.object = context; ev.handler = swAio_handler_write_file; ev.callback = aio_onWriteFileCompleted; ev.req = estrndup(filename, l_filename); ev.flags = O_CREAT | O_WRONLY; if (flags & PHP_FILE_APPEND) { ev.flags |= O_APPEND; } else { ev.flags |= O_TRUNC; } if (!SwooleAIO.init) { php_swoole_check_reactor(); swAio_init(); } swTrace("writeFile(%s, %ld)", filename, ev.nbytes); int ret = swAio_dispatch(&ev); if (ret < 0) { efree(context); RETURN_FALSE; } context->state = SW_CORO_CONTEXT_RUNNING; coro_save(context); coro_yield(); }
static PHP_METHOD(swoole_redis, connect) { char *host; zend_size_t host_len; long port; zval *callback; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "slz", &host, &host_len, &port, &callback) == FAILURE) { RETURN_FALSE; } if (host_len <= 0) { swoole_php_error(E_WARNING, "host is empty."); RETURN_FALSE; } if (port <= 1 || port > 65535) { swoole_php_error(E_WARNING, "port is invalid."); RETURN_FALSE; } swRedisClient *redis = emalloc(sizeof(swRedisClient)); bzero(redis, sizeof(swRedisClient)); #if PHP_MAJOR_VERSION < 7 redis->object = getThis(); #else redis->object = &redis->_object; memcpy(redis->object, getThis(), sizeof(zval)); #endif sw_zval_add_ref(&redis->object); swoole_set_object(getThis(), redis); redisAsyncContext *context = redisAsyncConnect(host, (int) port); if (context->err) { swoole_php_error(E_WARNING, "connect to redis-server[%s:%d] failed, Erorr: %s[%d]", host, (int) port, context->errstr, context->err); RETURN_FALSE; } php_swoole_check_reactor(); if (!isset_event_callback) { SwooleG.main_reactor->setHandle(SwooleG.main_reactor, PHP_SWOOLE_FD_REDIS | SW_EVENT_READ, swoole_redis_onRead); SwooleG.main_reactor->setHandle(SwooleG.main_reactor, PHP_SWOOLE_FD_REDIS | SW_EVENT_WRITE, swoole_redis_onWrite); isset_event_callback = 1; } redisAsyncSetConnectCallback(context, swoole_redis_onConnect); redisAsyncSetDisconnectCallback(context, swoole_redis_onClose); #if PHP_MAJOR_VERSION < 7 redis->connect_callback = callback; #else redis->connect_callback = &redis->_connect_callback; memcpy(redis->connect_callback, callback, sizeof(zval)); #endif sw_zval_add_ref(&redis->connect_callback); redis->context = context; context->ev.addRead = swoole_redis_event_AddRead; context->ev.delRead = swoole_redis_event_DelRead; context->ev.addWrite = swoole_redis_event_AddWrite; context->ev.delWrite = swoole_redis_event_DelWrite; context->ev.cleanup = swoole_redis_event_Cleanup; context->ev.data = redis; zend_update_property_string(swoole_redis_class_entry_ptr, getThis(), ZEND_STRL("host"), host TSRMLS_CC); zend_update_property_long(swoole_redis_class_entry_ptr, getThis(), ZEND_STRL("port"), port TSRMLS_CC); if (SwooleG.main_reactor->add(SwooleG.main_reactor, redis->context->c.fd, PHP_SWOOLE_FD_REDIS | SW_EVENT_WRITE) < 0) { swoole_php_fatal_error(E_WARNING, "swoole_event_add failed. Erorr: %s[%d].", redis->context->errstr, redis->context->err); RETURN_FALSE; } swConnection *conn = swReactor_get(SwooleG.main_reactor, redis->context->c.fd); conn->object = redis; }
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; }
static PHP_METHOD(swoole_redis, connect) { char *host; zend_size_t host_len; long port; zval *callback; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "slz", &host, &host_len, &port, &callback) == FAILURE) { RETURN_FALSE; } if (host_len <= 0) { swoole_php_error(E_WARNING, "redis server host is empty."); RETURN_FALSE; } swRedisClient *redis = swoole_get_object(getThis()); redisAsyncContext *context; if (strncasecmp(host, ZEND_STRL("unix:/")) == 0) { context = redisAsyncConnectUnix(host + 5); } else { if (port <= 1 || port > 65535) { swoole_php_error(E_WARNING, "redis server port is invalid."); RETURN_FALSE; } context = redisAsyncConnect(host, (int) port); } if (context->err) { swoole_php_error(E_WARNING, "failed to connect to the redis-server[%s:%d], Erorr: %s[%d]", host, (int) port, context->errstr, context->err); RETURN_FALSE; } php_swoole_check_reactor(); if (!swReactor_handle_isset(SwooleG.main_reactor, PHP_SWOOLE_FD_REDIS)) { SwooleG.main_reactor->setHandle(SwooleG.main_reactor, PHP_SWOOLE_FD_REDIS | SW_EVENT_READ, swoole_redis_onRead); SwooleG.main_reactor->setHandle(SwooleG.main_reactor, PHP_SWOOLE_FD_REDIS | SW_EVENT_WRITE, swoole_redis_onWrite); SwooleG.main_reactor->setHandle(SwooleG.main_reactor, PHP_SWOOLE_FD_REDIS | SW_EVENT_ERROR, swoole_redis_onError); } redisAsyncSetConnectCallback(context, swoole_redis_onConnect); redisAsyncSetDisconnectCallback(context, swoole_redis_onClose); zend_update_property_long(swoole_redis_class_entry_ptr, getThis(), ZEND_STRL("sock"), context->c.fd TSRMLS_CC); zend_update_property(swoole_redis_class_entry_ptr, getThis(), ZEND_STRL("onConnect"), callback TSRMLS_CC); redis->context = context; context->ev.addRead = swoole_redis_event_AddRead; context->ev.delRead = swoole_redis_event_DelRead; context->ev.addWrite = swoole_redis_event_AddWrite; context->ev.delWrite = swoole_redis_event_DelWrite; context->ev.cleanup = swoole_redis_event_Cleanup; context->ev.data = redis; zend_update_property_string(swoole_redis_class_entry_ptr, getThis(), ZEND_STRL("host"), host TSRMLS_CC); zend_update_property_long(swoole_redis_class_entry_ptr, getThis(), ZEND_STRL("port"), port TSRMLS_CC); if (SwooleG.main_reactor->add(SwooleG.main_reactor, redis->context->c.fd, PHP_SWOOLE_FD_REDIS | SW_EVENT_WRITE) < 0) { swoole_php_fatal_error(E_WARNING, "swoole_event_add failed. Erorr: %s[%d].", redis->context->errstr, redis->context->err); RETURN_FALSE; } if (redis->timeout > 0) { php_swoole_check_timer((int) (redis->timeout * 1000)); redis->timer = SwooleG.timer.add(&SwooleG.timer, (int) (redis->timeout * 1000), 0, redis, swoole_redis_onTimeout); } sw_zval_add_ref(&redis->object); swConnection *conn = swReactor_get(SwooleG.main_reactor, redis->context->c.fd); conn->object = redis; }
static PHP_METHOD(swoole_process, signal) { zval *callback = NULL; long signo = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz", &signo, &callback) == FAILURE) { return; } if (!SWOOLE_G(cli)) { swoole_php_fatal_error(E_ERROR, "cannot use swoole_process::signal here."); RETURN_FALSE; } if (SwooleGS->start && (swIsWorker() || swIsMaster() || swIsManager() || swIsTaskWorker())) { if (signo == SIGTERM || signo == SIGALRM) { swoole_php_fatal_error(E_WARNING, "cannot use swoole_process::signal in swoole_server."); RETURN_FALSE; } } if (callback == NULL || ZVAL_IS_NULL(callback)) { callback = signal_callback[signo]; if (callback) { sw_zval_ptr_dtor(&callback); swSignal_add(signo, NULL); RETURN_TRUE; } else { swoole_php_error(E_WARNING, "no callback."); RETURN_FALSE; } } char *func_name; if (!sw_zend_is_callable(callback, 0, &func_name TSRMLS_CC)) { swoole_php_error(E_WARNING, "function '%s' is not callable", func_name); efree(func_name); RETURN_FALSE; } efree(func_name); #if PHP_MAJOR_VERSION >= 7 zval *tmp = emalloc(sizeof(zval)); memcpy(tmp, callback, sizeof(zval)); callback = tmp; #endif sw_zval_add_ref(&callback); if (signal_callback[signo]) { sw_zval_ptr_dtor(&callback); } signal_callback[signo] = callback; #if PHP_MAJOR_VERSION >= 7 || (PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 4) SwooleG.use_signalfd = 1; #else SwooleG.use_signalfd = 0; #endif php_swoole_check_reactor(); /** * for swSignalfd_setup */ SwooleG.main_reactor->check_signalfd = 1; swSignal_add(signo, php_swoole_onSignal); RETURN_TRUE; }