static PHP_METHOD(swoole_mysql, on) { char *name; zend_size_t len; zval *cb; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &name, &len, &cb) == FAILURE) { return; } mysql_client *client = swoole_get_object(getThis()); if (!client) { swoole_php_fatal_error(E_WARNING, "object is not instanceof swoole_mysql."); RETURN_FALSE; } if (strncasecmp("close", name, len) == 0) { zend_update_property(swoole_mysql_class_entry_ptr, getThis(), ZEND_STRL("onClose"), cb TSRMLS_CC); client->onClose = sw_zend_read_property(swoole_mysql_class_entry_ptr, getThis(), ZEND_STRL("onClose"), 0 TSRMLS_CC); sw_copy_to_stack(client->onClose, client->_onClose); } else { swoole_php_error(E_WARNING, "Unknown event type[%s]", name); RETURN_FALSE; } RETURN_TRUE; }
static PHP_METHOD(swoole_redis, __construct) { swRedisClient *redis = emalloc(sizeof(swRedisClient)); bzero(redis, sizeof(swRedisClient)); redis->object = getThis(); sw_copy_to_stack(redis->object, redis->_object); swoole_set_object(getThis(), redis); }
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_MYSQL)) { 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 = callback; sw_copy_to_stack(ps->callback, ps->_callback); 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_ptr_dtor(&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, on) { char *name; zend_size_t len; zval *cb; if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "sz", &name, &len, &cb) == FAILURE) { return; } swRedisClient *redis = swoole_get_object(getThis()); if (redis->context != NULL) { swoole_php_fatal_error(E_WARNING, "Must be called before connect."); RETURN_FALSE; } if (strncasecmp("close", name, len) == 0) { zend_update_property(swoole_redis_class_entry_ptr, getThis(), ZEND_STRL("onClose"), cb TSRMLS_CC); redis->close_callback = sw_zend_read_property(swoole_redis_class_entry_ptr, getThis(), ZEND_STRL("onClose"), 0 TSRMLS_CC); sw_copy_to_stack(redis->close_callback, redis->_close_callback); } else if (strncasecmp("message", name, len) == 0) { zend_update_property(swoole_redis_class_entry_ptr, getThis(), ZEND_STRL("onMessage"), cb TSRMLS_CC); redis->message_callback = sw_zend_read_property(swoole_redis_class_entry_ptr, getThis(), ZEND_STRL("onMessage"), 0 TSRMLS_CC); sw_copy_to_stack(redis->message_callback, redis->_message_callback); redis->subscribe = 1; } else { swoole_php_error(E_WARNING, "Unknown event type[%s]", name); RETURN_FALSE; } RETURN_TRUE; }
static PHP_METHOD(swoole_server_port, on) { char *name = NULL; zend_size_t len, i; zval *cb; if (SwooleGS->start > 0) { swoole_php_fatal_error(E_WARNING, "Server is running. Unable to set event callback now."); RETURN_FALSE; } if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "sz", &name, &len, &cb) == FAILURE) { return; } #ifdef PHP_SWOOLE_CHECK_CALLBACK char *func_name = NULL; if (!sw_zend_is_callable(cb, 0, &func_name TSRMLS_CC)) { swoole_php_fatal_error(E_ERROR, "Function '%s' is not callable", func_name); efree(func_name); return; } efree(func_name); #endif swoole_server_port_property *property = swoole_get_property(getThis(), 0); swListenPort *port = swoole_get_object(getThis()); if (!port->ptr) { port->ptr = property; } char *callback_name[PHP_SERVER_CALLBACK_NUM] = { "Connect", "Receive", "Close", "Packet", "Start", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "Request", "HandShake", "Open", "Message", }; char property_name[128]; int l_property_name = 0; memcpy(property_name, "on", 2); for (i = 0; i < PHP_SERVER_CALLBACK_NUM; i++) { if (callback_name[i] == NULL) { continue; } if (strncasecmp(callback_name[i], name, len) == 0) { memcpy(property_name + 2, callback_name[i], len); l_property_name = len + 2; property_name[l_property_name] = '\0'; zend_update_property(swoole_server_port_class_entry_ptr, getThis(), property_name, l_property_name, cb TSRMLS_CC); property->callbacks[i] = sw_zend_read_property(swoole_server_port_class_entry_ptr, getThis(), property_name, l_property_name, 0 TSRMLS_CC); sw_copy_to_stack(property->callbacks[i], property->_callbacks[i]); if (i == SW_SERVER_CB_onConnect && SwooleG.serv->onConnect == NULL) { SwooleG.serv->onConnect = php_swoole_onConnect; } else if (i == SW_SERVER_CB_onClose && SwooleG.serv->onClose == NULL) { SwooleG.serv->onClose = php_swoole_onClose; } break; } } if (l_property_name == 0) { swoole_php_error(E_WARNING, "Unknown event types[%s]", name); RETURN_FALSE; } RETURN_TRUE; }
static PHP_METHOD(swoole_redis, __construct) { zval *zset = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &zset) == FAILURE) { return; } swRedisClient *redis = emalloc(sizeof(swRedisClient)); bzero(redis, sizeof(swRedisClient)); redis->object = getThis(); redis->timeout = SW_REDIS_CONNECT_TIMEOUT; redis->database = -1; if (zset && !ZVAL_IS_NULL(zset)) { php_swoole_array_separate(zset); zend_update_property(swoole_redis_class_entry_ptr, getThis(), ZEND_STRL("setting"), zset TSRMLS_CC); sw_zval_ptr_dtor(&zset); HashTable *vht; zval *ztmp; vht = Z_ARRVAL_P(zset); /** * timeout */ if (php_swoole_array_get_value(vht, "timeout", ztmp)) { convert_to_double(ztmp); redis->timeout = (double) Z_DVAL_P(ztmp); } /** * password */ if (php_swoole_array_get_value(vht, "password", ztmp)) { convert_to_string(ztmp); if (Z_STRLEN_P(ztmp) >= 1 << 8) { swoole_php_fatal_error(E_WARNING, "redis password is too long."); } else if (Z_STRLEN_P(ztmp) > 0) { redis->password = estrdup(Z_STRVAL_P(ztmp)); redis->password_len = Z_STRLEN_P(ztmp); } } /** * database */ if (php_swoole_array_get_value(vht, "database", ztmp)) { convert_to_long(ztmp); if (Z_LVAL_P(ztmp) > 1 << 8) { swoole_php_fatal_error(E_WARNING, "redis database number is too big."); } else { redis->database = (int8_t) Z_LVAL_P(ztmp); } } } sw_copy_to_stack(redis->object, redis->_object); swoole_set_object(getThis(), redis); }
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 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_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; } client->callback = callback; sw_copy_to_stack(client->callback, client->_callback); sw_zval_add_ref(&client->callback); sw_zval_add_ref(&client->object); swString_clear(mysql_request_buffer); if (mysql_request(&sql, mysql_request_buffer) < 0) { RETURN_FALSE; } //add to eventloop if (SwooleG.main_reactor->add(SwooleG.main_reactor, client->fd, PHP_SWOOLE_FD_MYSQL | SW_EVENT_READ) < 0) { swoole_php_fatal_error(E_WARNING, "swoole_event_add failed."); 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_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 = swoole_get_object(getThis()); 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); SwooleG.main_reactor->setHandle(SwooleG.main_reactor, PHP_SWOOLE_FD_REDIS | SW_EVENT_ERROR, swoole_redis_onError); isset_event_callback = 1; } redisAsyncSetConnectCallback(context, swoole_redis_onConnect); redisAsyncSetDisconnectCallback(context, swoole_redis_onClose); zend_update_property(swoole_redis_class_entry_ptr, getThis(), ZEND_STRL("onConnect"), callback TSRMLS_CC); redis->connect_callback = sw_zend_read_property(swoole_redis_class_entry_ptr, getThis(), ZEND_STRL("onConnect"), 0 TSRMLS_CC); sw_copy_to_stack(redis->connect_callback, 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; } sw_zval_add_ref(&redis->object); swConnection *conn = swReactor_get(SwooleG.main_reactor, redis->context->c.fd); conn->object = redis; }