640 lines
22 KiB
C
Executable File
640 lines
22 KiB
C
Executable File
/*
|
|
+----------------------------------------------------------------------+
|
|
| Swoole |
|
|
+----------------------------------------------------------------------+
|
|
| This source file is subject to version 2.0 of the Apache license, |
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
| available through the world-wide-web at the following url: |
|
|
| http://www.apache.org/licenses/LICENSE-2.0.html |
|
|
| If you did not receive a copy of the Apache2.0 license and are unable|
|
|
| to obtain it through the world-wide-web, please send a note to |
|
|
| license@swoole.com so we can mail you a copy immediately. |
|
|
+----------------------------------------------------------------------+
|
|
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
|
|
+----------------------------------------------------------------------+
|
|
*/
|
|
|
|
#include "php_swoole.h"
|
|
|
|
#ifdef SW_COROUTINE
|
|
#include "swoole_coroutine.h"
|
|
#endif
|
|
|
|
zend_class_entry swoole_server_port_ce;
|
|
zend_class_entry *swoole_server_port_class_entry_ptr;
|
|
|
|
static PHP_METHOD(swoole_server_port, __construct);
|
|
static PHP_METHOD(swoole_server_port, __destruct);
|
|
static PHP_METHOD(swoole_server_port, on);
|
|
static PHP_METHOD(swoole_server_port, set);
|
|
|
|
#ifdef SWOOLE_SOCKETS_SUPPORT
|
|
static PHP_METHOD(swoole_server_port, getSocket);
|
|
#endif
|
|
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_void, 0, 0, 0)
|
|
ZEND_END_ARG_INFO()
|
|
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_server_port_set, 0, 0, 1)
|
|
ZEND_ARG_ARRAY_INFO(0, settings, 0)
|
|
ZEND_END_ARG_INFO()
|
|
|
|
ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_server_port_on, 0, 0, 2)
|
|
ZEND_ARG_INFO(0, event_name)
|
|
ZEND_ARG_INFO(0, callback)
|
|
ZEND_END_ARG_INFO()
|
|
|
|
const zend_function_entry swoole_server_port_methods[] =
|
|
{
|
|
PHP_ME(swoole_server_port, __construct, arginfo_swoole_void, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR)
|
|
PHP_ME(swoole_server_port, __destruct, arginfo_swoole_void, ZEND_ACC_PUBLIC | ZEND_ACC_DTOR)
|
|
PHP_ME(swoole_server_port, set, arginfo_swoole_server_port_set, ZEND_ACC_PUBLIC)
|
|
PHP_ME(swoole_server_port, on, arginfo_swoole_server_port_on, ZEND_ACC_PUBLIC)
|
|
PHP_FALIAS(__sleep, swoole_unsupport_serialize, NULL)
|
|
PHP_FALIAS(__wakeup, swoole_unsupport_serialize, NULL)
|
|
#ifdef SWOOLE_SOCKETS_SUPPORT
|
|
PHP_ME(swoole_server_port, getSocket, arginfo_swoole_void, ZEND_ACC_PUBLIC)
|
|
#endif
|
|
PHP_FE_END
|
|
};
|
|
|
|
void swoole_server_port_init(int module_number TSRMLS_DC)
|
|
{
|
|
SWOOLE_INIT_CLASS_ENTRY(swoole_server_port_ce, "swoole_server_port", "Swoole\\Server\\Port", swoole_server_port_methods);
|
|
swoole_server_port_class_entry_ptr = zend_register_internal_class(&swoole_server_port_ce TSRMLS_CC);
|
|
SWOOLE_CLASS_ALIAS(swoole_server_port, "Swoole\\Server\\Port");
|
|
|
|
if (SWOOLE_G(use_shortname))
|
|
{
|
|
sw_zend_register_class_alias("Co\\Server\\Port", swoole_server_port_class_entry_ptr);
|
|
}
|
|
|
|
zend_declare_property_null(swoole_server_port_class_entry_ptr, ZEND_STRL("onConnect"), ZEND_ACC_PUBLIC TSRMLS_CC);
|
|
zend_declare_property_null(swoole_server_port_class_entry_ptr, ZEND_STRL("onReceive"), ZEND_ACC_PUBLIC TSRMLS_CC);
|
|
zend_declare_property_null(swoole_server_port_class_entry_ptr, ZEND_STRL("onClose"), ZEND_ACC_PUBLIC TSRMLS_CC);
|
|
zend_declare_property_null(swoole_server_port_class_entry_ptr, ZEND_STRL("onPacket"), ZEND_ACC_PUBLIC TSRMLS_CC);
|
|
zend_declare_property_null(swoole_server_port_class_entry_ptr, ZEND_STRL("onBufferFull"), ZEND_ACC_PUBLIC TSRMLS_CC);
|
|
zend_declare_property_null(swoole_server_port_class_entry_ptr, ZEND_STRL("onBufferEmpty"), ZEND_ACC_PUBLIC TSRMLS_CC);
|
|
zend_declare_property_null(swoole_server_port_class_entry_ptr, ZEND_STRL("onRequest"), ZEND_ACC_PUBLIC TSRMLS_CC);
|
|
zend_declare_property_null(swoole_server_port_class_entry_ptr, ZEND_STRL("onHandShake"), ZEND_ACC_PUBLIC TSRMLS_CC);
|
|
zend_declare_property_null(swoole_server_port_class_entry_ptr, ZEND_STRL("onMessage"), ZEND_ACC_PUBLIC TSRMLS_CC);
|
|
zend_declare_property_null(swoole_server_port_class_entry_ptr, ZEND_STRL("onOpen"), ZEND_ACC_PUBLIC TSRMLS_CC);
|
|
|
|
zend_declare_property_null(swoole_server_port_class_entry_ptr, ZEND_STRL("host"), ZEND_ACC_PUBLIC TSRMLS_CC);
|
|
zend_declare_property_long(swoole_server_port_class_entry_ptr, ZEND_STRL("port"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
|
|
zend_declare_property_long(swoole_server_port_class_entry_ptr, ZEND_STRL("type"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
|
|
zend_declare_property_long(swoole_server_port_class_entry_ptr, ZEND_STRL("sock"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
|
|
zend_declare_property_null(swoole_server_port_class_entry_ptr, ZEND_STRL("setting"), ZEND_ACC_PUBLIC TSRMLS_CC);
|
|
|
|
#ifdef HAVE_PCRE
|
|
zend_declare_property_null(swoole_server_port_class_entry_ptr, ZEND_STRL("connections"), ZEND_ACC_PUBLIC TSRMLS_CC);
|
|
#endif
|
|
}
|
|
|
|
static PHP_METHOD(swoole_server_port, __construct)
|
|
{
|
|
swoole_php_fatal_error(E_ERROR, "please use the swoole_server->listen method.");
|
|
return;
|
|
}
|
|
|
|
static PHP_METHOD(swoole_server_port, __destruct)
|
|
{
|
|
swoole_server_port_property *property = swoole_get_property(getThis(), 0);
|
|
|
|
#ifdef PHP_SWOOLE_ENABLE_FASTCALL
|
|
int j;
|
|
for (j = 0; j < PHP_SERVER_CALLBACK_NUM; j++)
|
|
{
|
|
if (property->caches[j])
|
|
{
|
|
efree(property->caches[j]);
|
|
property->caches[j] = NULL;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
efree(property);
|
|
swoole_set_property(getThis(), 0, NULL);
|
|
swoole_set_object(getThis(), NULL);
|
|
}
|
|
|
|
static PHP_METHOD(swoole_server_port, set)
|
|
{
|
|
zval *zset = NULL;
|
|
HashTable *vht;
|
|
zval *v;
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "z", &zset) == FAILURE)
|
|
{
|
|
return;
|
|
}
|
|
if (Z_TYPE_P(zset) != IS_ARRAY)
|
|
{
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
php_swoole_array_separate(zset);
|
|
vht = Z_ARRVAL_P(zset);
|
|
|
|
swListenPort *port = swoole_get_object(getThis());
|
|
swoole_server_port_property *property = swoole_get_property(getThis(), 0);
|
|
|
|
if (port == NULL || property == NULL)
|
|
{
|
|
swoole_php_fatal_error(E_ERROR, "please use the swoole_server->listen method.");
|
|
return;
|
|
}
|
|
|
|
property->setting = zset;
|
|
|
|
//backlog
|
|
if (php_swoole_array_get_value(vht, "backlog", v))
|
|
{
|
|
convert_to_long(v);
|
|
port->backlog = (int) Z_LVAL_P(v);
|
|
}
|
|
if (php_swoole_array_get_value(vht, "socket_buffer_size", v))
|
|
{
|
|
convert_to_long(v);
|
|
port->socket_buffer_size = (int) Z_LVAL_P(v);
|
|
if (port->socket_buffer_size <= 0)
|
|
{
|
|
port->socket_buffer_size = SW_MAX_INT;
|
|
}
|
|
}
|
|
/**
|
|
* !!! Don't set this option, for tests only.
|
|
*/
|
|
if (php_swoole_array_get_value(vht, "kernel_socket_recv_buffer_size", v))
|
|
{
|
|
convert_to_long(v);
|
|
port->kernel_socket_recv_buffer_size = (int) Z_LVAL_P(v);
|
|
if (port->kernel_socket_recv_buffer_size <= 0)
|
|
{
|
|
port->kernel_socket_recv_buffer_size = SW_MAX_INT;
|
|
}
|
|
}
|
|
/**
|
|
* !!! Don't set this option, for tests only.
|
|
*/
|
|
if (php_swoole_array_get_value(vht, "kernel_socket_send_buffer_size", v))
|
|
{
|
|
convert_to_long(v);
|
|
port->kernel_socket_send_buffer_size = (int) Z_LVAL_P(v);
|
|
if (port->kernel_socket_send_buffer_size <= 0)
|
|
{
|
|
port->kernel_socket_send_buffer_size = SW_MAX_INT;
|
|
}
|
|
}
|
|
if (php_swoole_array_get_value(vht, "buffer_high_watermark", v))
|
|
{
|
|
convert_to_long(v);
|
|
port->buffer_high_watermark = (int) Z_LVAL_P(v);
|
|
}
|
|
if (php_swoole_array_get_value(vht, "buffer_low_watermark", v))
|
|
{
|
|
convert_to_long(v);
|
|
port->buffer_low_watermark = (int) Z_LVAL_P(v);
|
|
}
|
|
//tcp_nodelay
|
|
if (php_swoole_array_get_value(vht, "open_tcp_nodelay", v))
|
|
{
|
|
convert_to_boolean(v);
|
|
port->open_tcp_nodelay = Z_BVAL_P(v);
|
|
}
|
|
//tcp_defer_accept
|
|
if (php_swoole_array_get_value(vht, "tcp_defer_accept", v))
|
|
{
|
|
convert_to_long(v);
|
|
port->tcp_defer_accept = (uint8_t) Z_LVAL_P(v);
|
|
}
|
|
//tcp_keepalive
|
|
if (php_swoole_array_get_value(vht, "open_tcp_keepalive", v))
|
|
{
|
|
convert_to_boolean(v);
|
|
port->open_tcp_keepalive = Z_BVAL_P(v);
|
|
}
|
|
//buffer: eof check
|
|
if (php_swoole_array_get_value(vht, "open_eof_check", v))
|
|
{
|
|
convert_to_boolean(v);
|
|
port->open_eof_check = Z_BVAL_P(v);
|
|
}
|
|
//buffer: split package with eof
|
|
if (php_swoole_array_get_value(vht, "open_eof_split", v))
|
|
{
|
|
convert_to_boolean(v);
|
|
port->protocol.split_by_eof = Z_BVAL_P(v);
|
|
if (port->protocol.split_by_eof)
|
|
{
|
|
port->open_eof_check = 1;
|
|
}
|
|
}
|
|
//package eof
|
|
if (php_swoole_array_get_value(vht, "package_eof", v))
|
|
{
|
|
convert_to_string(v);
|
|
port->protocol.package_eof_len = Z_STRLEN_P(v);
|
|
if (port->protocol.package_eof_len > SW_DATA_EOF_MAXLEN)
|
|
{
|
|
swoole_php_fatal_error(E_ERROR, "pacakge_eof max length is %d", SW_DATA_EOF_MAXLEN);
|
|
RETURN_FALSE;
|
|
}
|
|
bzero(port->protocol.package_eof, SW_DATA_EOF_MAXLEN);
|
|
memcpy(port->protocol.package_eof, Z_STRVAL_P(v), Z_STRLEN_P(v));
|
|
}
|
|
//http_protocol
|
|
if (php_swoole_array_get_value(vht, "open_http_protocol", v))
|
|
{
|
|
convert_to_boolean(v);
|
|
port->open_http_protocol = Z_BVAL_P(v);
|
|
}
|
|
//websocket protocol
|
|
if (php_swoole_array_get_value(vht, "open_websocket_protocol", v))
|
|
{
|
|
convert_to_boolean(v);
|
|
port->open_websocket_protocol = Z_BVAL_P(v);
|
|
}
|
|
if (php_swoole_array_get_value(vht, "websocket_subprotocol", v))
|
|
{
|
|
convert_to_string(v);
|
|
if (port->websocket_subprotocol)
|
|
{
|
|
sw_free(port->websocket_subprotocol);
|
|
}
|
|
port->websocket_subprotocol = sw_strdup(Z_STRVAL_P(v));
|
|
port->websocket_subprotocol_length = Z_STRLEN_P(v);
|
|
}
|
|
#ifdef SW_USE_HTTP2
|
|
//http2 protocol
|
|
if (php_swoole_array_get_value(vht, "open_http2_protocol", v))
|
|
{
|
|
convert_to_boolean(v);
|
|
port->open_http2_protocol = Z_BVAL_P(v);
|
|
}
|
|
#endif
|
|
//buffer: mqtt protocol
|
|
if (php_swoole_array_get_value(vht, "open_mqtt_protocol", v))
|
|
{
|
|
convert_to_boolean(v);
|
|
port->open_mqtt_protocol = Z_BVAL_P(v);
|
|
}
|
|
//redis protocol
|
|
if (php_swoole_array_get_value(vht, "open_redis_protocol", v))
|
|
{
|
|
convert_to_boolean(v);
|
|
port->open_redis_protocol = Z_BVAL_P(v);
|
|
}
|
|
//tcp_keepidle
|
|
if (php_swoole_array_get_value(vht, "tcp_keepidle", v))
|
|
{
|
|
convert_to_long(v);
|
|
port->tcp_keepidle = (uint16_t) Z_LVAL_P(v);
|
|
}
|
|
//tcp_keepinterval
|
|
if (php_swoole_array_get_value(vht, "tcp_keepinterval", v))
|
|
{
|
|
convert_to_long(v);
|
|
port->tcp_keepinterval = (uint16_t) Z_LVAL_P(v);
|
|
}
|
|
//tcp_keepcount
|
|
if (sw_zend_hash_find(vht, ZEND_STRS("tcp_keepcount"), (void **) &v) == SUCCESS)
|
|
{
|
|
convert_to_long(v);
|
|
port->tcp_keepcount = (uint16_t) Z_LVAL_P(v);
|
|
}
|
|
//tcp_fastopen
|
|
if (sw_zend_hash_find(vht, ZEND_STRS("tcp_fastopen"), (void **) &v) == SUCCESS)
|
|
{
|
|
convert_to_boolean(v);
|
|
port->tcp_fastopen = Z_BVAL_P(v);
|
|
}
|
|
//open length check
|
|
if (php_swoole_array_get_value(vht, "open_length_check", v))
|
|
{
|
|
convert_to_boolean(v);
|
|
port->open_length_check = Z_BVAL_P(v);
|
|
}
|
|
//package length size
|
|
if (php_swoole_array_get_value(vht, "package_length_type", v))
|
|
{
|
|
convert_to_string(v);
|
|
port->protocol.package_length_type = Z_STRVAL_P(v)[0];
|
|
port->protocol.package_length_size = swoole_type_size(port->protocol.package_length_type);
|
|
if (port->protocol.package_length_size == 0)
|
|
{
|
|
swoole_php_fatal_error(E_ERROR, "unknow package_length_type, see pack(). Link: http://php.net/pack");
|
|
RETURN_FALSE;
|
|
}
|
|
}
|
|
//length function
|
|
if (php_swoole_array_get_value(vht, "package_length_func", v))
|
|
{
|
|
while(1)
|
|
{
|
|
if (Z_TYPE_P(v) == IS_STRING)
|
|
{
|
|
swProtocol_length_function func = swoole_get_function(Z_STRVAL_P(v), Z_STRLEN_P(v));
|
|
if (func != NULL)
|
|
{
|
|
port->protocol.get_package_length = func;
|
|
break;
|
|
}
|
|
}
|
|
|
|
char *func_name = NULL;
|
|
if (!sw_zend_is_callable(v, 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);
|
|
port->protocol.get_package_length = php_swoole_length_func;
|
|
sw_zval_add_ref(&v);
|
|
port->protocol.private_data = sw_zval_dup(v);
|
|
break;
|
|
}
|
|
|
|
port->protocol.package_length_size = 0;
|
|
port->protocol.package_length_type = '\0';
|
|
port->protocol.package_length_offset = SW_BUFFER_SIZE;
|
|
}
|
|
//package length offset
|
|
if (php_swoole_array_get_value(vht, "package_length_offset", v))
|
|
{
|
|
convert_to_long(v);
|
|
port->protocol.package_length_offset = (int) Z_LVAL_P(v);
|
|
if (port->protocol.package_length_offset > SW_BUFFER_SIZE)
|
|
{
|
|
swoole_php_fatal_error(E_ERROR, "'package_length_offset' value is too large.");
|
|
}
|
|
}
|
|
//package body start
|
|
if (php_swoole_array_get_value(vht, "package_body_offset", v) || php_swoole_array_get_value(vht, "package_body_start", v))
|
|
{
|
|
convert_to_long(v);
|
|
port->protocol.package_body_offset = (int) Z_LVAL_P(v);
|
|
if (port->protocol.package_body_offset > SW_BUFFER_SIZE)
|
|
{
|
|
swoole_php_fatal_error(E_ERROR, "'package_body_offset' value is too large.");
|
|
}
|
|
}
|
|
/**
|
|
* package max length
|
|
*/
|
|
if (php_swoole_array_get_value(vht, "package_max_length", v))
|
|
{
|
|
convert_to_long(v);
|
|
port->protocol.package_max_length = (int) Z_LVAL_P(v);
|
|
}
|
|
|
|
#ifdef SW_USE_OPENSSL
|
|
if (port->ssl)
|
|
{
|
|
if (php_swoole_array_get_value(vht, "ssl_cert_file", v))
|
|
{
|
|
convert_to_string(v);
|
|
if (access(Z_STRVAL_P(v), R_OK) < 0)
|
|
{
|
|
swoole_php_fatal_error(E_ERROR, "ssl cert file[%s] not found.", Z_STRVAL_P(v));
|
|
return;
|
|
}
|
|
if (port->ssl_option.cert_file)
|
|
{
|
|
sw_free(port->ssl_option.cert_file);
|
|
}
|
|
port->ssl_option.cert_file = sw_strdup(Z_STRVAL_P(v));
|
|
port->open_ssl_encrypt = 1;
|
|
}
|
|
if (php_swoole_array_get_value(vht, "ssl_key_file", v))
|
|
{
|
|
convert_to_string(v);
|
|
if (access(Z_STRVAL_P(v), R_OK) < 0)
|
|
{
|
|
swoole_php_fatal_error(E_ERROR, "ssl key file[%s] not found.", Z_STRVAL_P(v));
|
|
return;
|
|
}
|
|
if (port->ssl_option.key_file)
|
|
{
|
|
sw_free(port->ssl_option.key_file);
|
|
}
|
|
port->ssl_option.key_file = sw_strdup(Z_STRVAL_P(v));
|
|
}
|
|
if (php_swoole_array_get_value(vht, "ssl_method", v))
|
|
{
|
|
convert_to_long(v);
|
|
port->ssl_option.method = (int) Z_LVAL_P(v);
|
|
}
|
|
//verify client cert
|
|
if (php_swoole_array_get_value(vht, "ssl_client_cert_file", v))
|
|
{
|
|
convert_to_string(v);
|
|
if (access(Z_STRVAL_P(v), R_OK) < 0)
|
|
{
|
|
swoole_php_fatal_error(E_ERROR, "ssl cert file[%s] not found.", port->ssl_option.cert_file);
|
|
return;
|
|
}
|
|
if (port->ssl_option.client_cert_file)
|
|
{
|
|
sw_free(port->ssl_option.client_cert_file);
|
|
}
|
|
port->ssl_option.client_cert_file = sw_strdup(Z_STRVAL_P(v));
|
|
}
|
|
if (php_swoole_array_get_value(vht, "ssl_verify_depth", v))
|
|
{
|
|
convert_to_long(v);
|
|
port->ssl_option.verify_depth = (int) Z_LVAL_P(v);
|
|
}
|
|
if (php_swoole_array_get_value(vht, "ssl_prefer_server_ciphers", v))
|
|
{
|
|
convert_to_boolean(v);
|
|
port->ssl_config.prefer_server_ciphers = Z_BVAL_P(v);
|
|
}
|
|
// if (sw_zend_hash_find(vht, ZEND_STRS("ssl_session_tickets"), (void **) &v) == SUCCESS)
|
|
// {
|
|
// convert_to_boolean(v);
|
|
// port->ssl_config.session_tickets = Z_BVAL_P(v);
|
|
// }
|
|
// if (sw_zend_hash_find(vht, ZEND_STRS("ssl_stapling"), (void **) &v) == SUCCESS)
|
|
// {
|
|
// convert_to_boolean(v);
|
|
// port->ssl_config.stapling = Z_BVAL_P(v);
|
|
// }
|
|
// if (sw_zend_hash_find(vht, ZEND_STRS("ssl_stapling_verify"), (void **) &v) == SUCCESS)
|
|
// {
|
|
// convert_to_boolean(v);
|
|
// port->ssl_config.stapling_verify = Z_BVAL_P(v);
|
|
// }
|
|
if (php_swoole_array_get_value(vht, "ssl_ciphers", v))
|
|
{
|
|
convert_to_string(v);
|
|
if (port->ssl_config.ciphers)
|
|
{
|
|
sw_free(port->ssl_config.ciphers);
|
|
}
|
|
port->ssl_config.ciphers = sw_strdup(Z_STRVAL_P(v));
|
|
}
|
|
if (php_swoole_array_get_value(vht, "ssl_ecdh_curve", v))
|
|
{
|
|
convert_to_string(v);
|
|
if (port->ssl_config.ecdh_curve)
|
|
{
|
|
sw_free(port->ssl_config.ecdh_curve);
|
|
}
|
|
port->ssl_config.ecdh_curve = sw_strdup(Z_STRVAL_P(v));
|
|
}
|
|
if (php_swoole_array_get_value(vht, "ssl_dhparam", v))
|
|
{
|
|
convert_to_string(v);
|
|
if (port->ssl_config.dhparam)
|
|
{
|
|
sw_free(port->ssl_config.dhparam);
|
|
}
|
|
port->ssl_config.dhparam = sw_strdup(Z_STRVAL_P(v));
|
|
}
|
|
// if (sw_zend_hash_find(vht, ZEND_STRS("ssl_session_cache"), (void **) &v) == SUCCESS)
|
|
// {
|
|
// convert_to_string(v);
|
|
// port->ssl_config.session_cache = strdup(Z_STRVAL_P(v));
|
|
// }
|
|
if (swPort_enable_ssl_encrypt(port) < 0)
|
|
{
|
|
swoole_php_fatal_error(E_ERROR, "swPort_enable_ssl_encrypt() failed.");
|
|
RETURN_FALSE;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
zval *zsetting = php_swoole_read_init_property(swoole_server_port_class_entry_ptr, getThis(), ZEND_STRL("setting") TSRMLS_CC);
|
|
sw_php_array_merge(Z_ARRVAL_P(zsetting), Z_ARRVAL_P(zset));
|
|
sw_zval_ptr_dtor(&zset);
|
|
}
|
|
|
|
static PHP_METHOD(swoole_server_port, on)
|
|
{
|
|
char *name = NULL;
|
|
zend_size_t len, i;
|
|
zval *cb;
|
|
|
|
swoole_server_port_property *property = swoole_get_property(getThis(), 0);
|
|
swServer *serv = property->serv;
|
|
if (serv->gs->start > 0)
|
|
{
|
|
swoole_php_fatal_error(E_WARNING, "can't register event callback function after server started.");
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS()TSRMLS_CC, "sz", &name, &len, &cb) == FAILURE)
|
|
{
|
|
return;
|
|
}
|
|
|
|
char *func_name = NULL;
|
|
zend_fcall_info_cache *func_cache = emalloc(sizeof(zend_fcall_info_cache));
|
|
if (!sw_zend_is_callable_ex(cb, NULL, 0, &func_name, NULL, func_cache, NULL TSRMLS_CC))
|
|
{
|
|
swoole_php_fatal_error(E_ERROR, "function '%s' is not callable", func_name);
|
|
efree(func_name);
|
|
return;
|
|
}
|
|
efree(func_name);
|
|
|
|
swListenPort *port = swoole_get_object(getThis());
|
|
if (!port->ptr)
|
|
{
|
|
port->ptr = property;
|
|
}
|
|
|
|
char *callback_name[PHP_SERVER_CALLBACK_NUM] = {
|
|
"Connect",
|
|
"Receive",
|
|
"Close",
|
|
"Packet",
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
"Request",
|
|
"HandShake",
|
|
"Open",
|
|
"Message",
|
|
"BufferFull",
|
|
"BufferEmpty",
|
|
};
|
|
|
|
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 && serv->onConnect == NULL)
|
|
{
|
|
serv->onConnect = php_swoole_onConnect;
|
|
}
|
|
else if (i == SW_SERVER_CB_onPacket && serv->onPacket == NULL)
|
|
{
|
|
serv->onPacket = php_swoole_onPacket;
|
|
}
|
|
else if (i == SW_SERVER_CB_onClose && serv->onClose == NULL)
|
|
{
|
|
serv->onClose = php_swoole_onClose;
|
|
}
|
|
else if (i == SW_SERVER_CB_onBufferFull && serv->onBufferFull == NULL)
|
|
{
|
|
serv->onBufferFull = php_swoole_onBufferFull;
|
|
}
|
|
else if (i == SW_SERVER_CB_onBufferEmpty && serv->onBufferEmpty == NULL)
|
|
{
|
|
serv->onBufferEmpty = php_swoole_onBufferEmpty;
|
|
}
|
|
property->caches[i] = func_cache;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (l_property_name == 0)
|
|
{
|
|
swoole_php_error(E_WARNING, "unknown event types[%s]", name);
|
|
efree(func_cache);
|
|
RETURN_FALSE;
|
|
}
|
|
RETURN_TRUE;
|
|
}
|
|
|
|
#ifdef SWOOLE_SOCKETS_SUPPORT
|
|
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);
|
|
}
|
|
#endif
|