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(); }
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_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; }
int swClient_create(swClient *cli, int type, int async) { int _domain; int _type; bzero(cli, sizeof(swClient)); switch (type) { case SW_SOCK_TCP: _domain = AF_INET; _type = SOCK_STREAM; break; case SW_SOCK_TCP6: _domain = AF_INET6; _type = SOCK_STREAM; break; case SW_SOCK_UNIX_STREAM: _domain = AF_UNIX; _type = SOCK_STREAM; break; case SW_SOCK_UDP: _domain = AF_INET; _type = SOCK_DGRAM; break; case SW_SOCK_UDP6: _domain = AF_INET6; _type = SOCK_DGRAM; break; case SW_SOCK_UNIX_DGRAM: _domain = AF_UNIX; _type = SOCK_DGRAM; break; default: return SW_ERR; } #ifdef SOCK_CLOEXEC int sockfd = socket(_domain, _type | SOCK_CLOEXEC, 0); #else int sockfd = socket(_domain, _type, 0); #endif if (sockfd < 0) { swWarn("socket() failed. Error: %s[%d]", strerror(errno), errno); return SW_ERR; } if (async) { cli->socket = swReactor_get(SwooleG.main_reactor, sockfd); } else { cli->socket = sw_malloc(sizeof(swConnection)); } cli->buffer_input_size = SW_CLIENT_BUFFER_SIZE; if (!cli->socket) { swWarn("malloc(%d) failed.", (int ) sizeof(swConnection)); close(sockfd); return SW_ERR; } bzero(cli->socket, sizeof(swConnection)); cli->socket->fd = sockfd; cli->socket->object = cli; if (async) { swSetNonBlock(cli->socket->fd); if (!swReactor_handle_isset(SwooleG.main_reactor, SW_FD_STREAM_CLIENT)) { SwooleG.main_reactor->setHandle(SwooleG.main_reactor, SW_FD_STREAM_CLIENT | SW_EVENT_READ, swClient_onStreamRead); SwooleG.main_reactor->setHandle(SwooleG.main_reactor, SW_FD_DGRAM_CLIENT | SW_EVENT_READ, swClient_onDgramRead); SwooleG.main_reactor->setHandle(SwooleG.main_reactor, SW_FD_STREAM_CLIENT | SW_EVENT_WRITE, swClient_onWrite); SwooleG.main_reactor->setHandle(SwooleG.main_reactor, SW_FD_STREAM_CLIENT | SW_EVENT_ERROR, swClient_onError); } } if (swSocket_is_stream(type)) { cli->recv = swClient_tcp_recv_no_buffer; if (async) { cli->connect = swClient_tcp_connect_async; cli->send = swClient_tcp_send_async; cli->sendfile = swClient_tcp_sendfile_async; cli->pipe = swClient_tcp_pipe; } else { cli->connect = swClient_tcp_connect_sync; cli->send = swClient_tcp_send_sync; cli->sendfile = swClient_tcp_sendfile_sync; } } else { cli->connect = swClient_udp_connect; cli->recv = swClient_udp_recv; cli->send = swClient_udp_send; } cli->_sock_domain = _domain; cli->_sock_type = _type; cli->close = swClient_close; cli->type = type; cli->async = async; cli->protocol.package_length_type = 'N'; cli->protocol.package_length_size = 4; cli->protocol.package_body_offset = 0; cli->protocol.package_max_length = SW_BUFFER_INPUT_SIZE; return SW_OK; }