From 34d1db233540a1eeb13863a82d11cfb16801a2c5 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Wed, 6 Jan 2021 10:51:45 +0800 Subject: [PATCH 001/936] update library --- ext-src/php_swoole_library.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index 077f27df9fd..aebfcfb800a 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: aaf668ce8d685f40bb28a5aadbc595be586fd7dd */ +/* $Id: f1ce9bcc9b378dc1d233b63cf4acaf854d0ec744 */ static const char* swoole_library_source_constants = "\n" @@ -3683,7 +3683,7 @@ static const char* swoole_library_source_core_curl_handler = " case CURLOPT_FILE:\n" " case CURLOPT_INFILE:\n" " if (!is_resource($value)) {\n" - " trigger_error(E_USER_WARNING, 'swoole_curl_setopt(): supplied argument is not a valid File-Handle resource');\n" + " trigger_error('swoole_curl_setopt(): supplied argument is not a valid File-Handle resource', E_USER_WARNING);\n" " return false;\n" " }\n" " break;\n" @@ -3769,7 +3769,7 @@ static const char* swoole_library_source_core_curl_handler = " * Ignore options\n" " */\n" " case CURLOPT_VERBOSE:\n" - " // trigger_error(E_USER_WARNING, 'swoole_curl_setopt(): CURLOPT_VERBOSE is not supported');\n" + " // trigger_error('swoole_curl_setopt(): CURLOPT_VERBOSE is not supported', E_USER_WARNING);\n" " case CURLOPT_SSLVERSION:\n" " case CURLOPT_NOSIGNAL:\n" " case CURLOPT_FRESH_CONNECT:\n" From 049eeff8352f598c76c3cd40e987c3c784f425be Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 6 Jan 2021 10:03:31 +0100 Subject: [PATCH 002/936] Fix minimal PHP version (#3979) --- package.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.xml b/package.xml index 80293dd28b1..7dabe9c0a81 100644 --- a/package.xml +++ b/package.xml @@ -2026,7 +2026,7 @@ - 7.1.0 + 7.2.0 1.4.0 From 927a801626cbd16332b5c62a673d5fa283187dcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Wed, 6 Jan 2021 17:04:24 +0800 Subject: [PATCH 003/936] Fix pecl install missing enable-swoole-json and enable-swoole-curl options (#3980) --- package.xml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/package.xml b/package.xml index 7dabe9c0a81..fb2b8053933 100644 --- a/package.xml +++ b/package.xml @@ -42,8 +42,8 @@ shenzhe163@gmail.com yes - 2021-01-04 - + 2021-01-06 + 4.6.0 4.0 @@ -1537,6 +1537,7 @@ + @@ -2039,5 +2040,7 @@ + + From b516d69f17dbc5b143d55df8db4dc914a2d8fa43 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Thu, 7 Jan 2021 18:38:16 +0800 Subject: [PATCH 004/936] Fix openssl thread safety issue --- src/server/master.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/master.cc b/src/server/master.cc index 7bcd34a5d30..aced4e7c16e 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -341,7 +341,7 @@ int Server::start_check() { /** * OpenSSL thread-safe */ - if (is_base_mode()) { + if (is_process_mode() && !single_thread) { swSSL_init_thread_safety(); } #endif From b2a861359af65ba73583be9bf2335e1ecac3f012 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Thu, 7 Jan 2021 18:40:18 +0800 Subject: [PATCH 005/936] Update README (#3981) - Add compiler configurations - Remove travis badge and Add GitHub Actions badge --- README-CN.md | 6 +++++- README.md | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/README-CN.md b/README-CN.md index ac65cec4a60..bd22b61b780 100644 --- a/README-CN.md +++ b/README-CN.md @@ -3,8 +3,10 @@ # Swoole [![Latest Version](https://img.shields.io/github/release/swoole/swoole-src.svg)](https://github.com/swoole/swoole-src/releases) -[![Build Status](https://api.travis-ci.org/swoole/swoole-src.svg)](https://travis-ci.org/swoole/swoole-src) [![License](https://img.shields.io/badge/license-apache2-blue.svg)](LICENSE) +[![lib-swoole](https://github.com/swoole/swoole-src/workflows/lib-swoole/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Alib-swoole) +[![ext-swoole](https://github.com/swoole/swoole-src/workflows/ext-swoole/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Aext-swoole) +[![run-swoole-test](https://github.com/swoole/swoole-src/workflows/run-swoole-test/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Arun-swoole-test) [![Coverity Scan Build Status](https://scan.coverity.com/projects/11654/badge.svg)](https://scan.coverity.com/projects/swoole-swoole-src) [![codecov](https://codecov.io/gh/swoole/swoole-src/branch/master/graph/badge.svg)](https://codecov.io/gh/swoole/swoole-src) @@ -475,6 +477,8 @@ make && sudo make install + `--enable-sockets` + `--enable-http2` + `--enable-mysqlnd` (需要 mysqlnd, 只是为了支持`mysql->escape`方法) ++ `--enable-swoole-json` ++ `--enable-swoole-curl` ### 升级 diff --git a/README.md b/README.md index 4410f8c0f98..b85f7aa6791 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,10 @@ English | [中文](./README-CN.md) # Swoole [![Latest Version](https://img.shields.io/github/release/swoole/swoole-src.svg)](https://github.com/swoole/swoole-src/releases) -[![Build Status](https://api.travis-ci.org/swoole/swoole-src.svg)](https://travis-ci.org/swoole/swoole-src) [![License](https://img.shields.io/badge/license-apache2-blue.svg)](LICENSE) +[![lib-swoole](https://github.com/swoole/swoole-src/workflows/lib-swoole/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Alib-swoole) +[![ext-swoole](https://github.com/swoole/swoole-src/workflows/ext-swoole/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Aext-swoole) +[![run-swoole-test](https://github.com/swoole/swoole-src/workflows/run-swoole-test/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Arun-swoole-test) [![Coverity Scan Build Status](https://scan.coverity.com/projects/11654/badge.svg)](https://scan.coverity.com/projects/swoole-swoole-src) [![codecov](https://codecov.io/gh/swoole/swoole-src/branch/master/graph/badge.svg)](https://codecov.io/gh/swoole/swoole-src) @@ -476,6 +478,8 @@ After compiling and installing to the system successfully, you have to add a new + `--enable-sockets` + `--enable-http2` + `--enable-mysqlnd` (need mysqlnd, it just for supporting `$mysql->escape` method) ++ `--enable-swoole-json` ++ `--enable-swoole-curl` ### Upgrade From 7f54ce267494562fe176ecc5ac729ac898f26915 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Fri, 8 Jan 2021 14:42:15 +0800 Subject: [PATCH 006/936] Fix can not find bootstrap (#3985) --- tests/swoole_http_client_coro/websocket/bug_01.phpt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/swoole_http_client_coro/websocket/bug_01.phpt b/tests/swoole_http_client_coro/websocket/bug_01.phpt index eca56c80013..4eebef0b56c 100644 --- a/tests/swoole_http_client_coro/websocket/bug_01.phpt +++ b/tests/swoole_http_client_coro/websocket/bug_01.phpt @@ -4,7 +4,7 @@ swoole_http_client_coro/websocket: handshake + frame --FILE-- Date: Fri, 8 Jan 2021 14:44:43 +0800 Subject: [PATCH 007/936] add --enable-thread-context option (#3970) * Support Apple m1 system * fix bug * fix bug [2] * fix --- config.m4 | 8 + examples/coroutine/coro_empty.php | 2 - ext-src/php_swoole.cc | 11 +- ext-src/php_swoole.h | 4 + ext-src/swoole_coroutine.cc | 25 ++- ext-src/swoole_event.cc | 2 +- ext-src/swoole_process.cc | 2 +- include/swoole.h | 11 +- include/swoole_async.h | 35 +++- include/swoole_error.h | 10 + include/swoole_reactor.h | 1 + src/core/base.cc | 7 +- src/core/error.cc | 13 +- src/coroutine/system.cc | 2 +- src/coroutine/thread_context.cc | 30 +-- src/os/async_thread.cc | 214 ++++++++++------------ tests/swoole_coroutine/bailout/error.phpt | 4 + 17 files changed, 201 insertions(+), 180 deletions(-) diff --git a/config.m4 b/config.m4 index 47469cfc6dd..8e34e43af7a 100644 --- a/config.m4 +++ b/config.m4 @@ -58,6 +58,9 @@ PHP_ARG_ENABLE(swoole-json, whether to enable Swoole JSON build flags, PHP_ARG_ENABLE(swoole-curl, whether to enable Swoole CURL build flags, [ --enable-swoole-curl Enable cURL support], no, no) +PHP_ARG_ENABLE(thread-context, whether to enable thread context, +[ --enable-thread-context Use thread context], no, no) + AC_DEFUN([SWOOLE_HAVE_PHP_EXT], [ extname=$1 haveext=$[PHP_]translit($1,a-z_-,A-Z__) @@ -671,6 +674,11 @@ if test "$PHP_SWOOLE" != "no"; then else SW_USE_ASM_CONTEXT="no" fi + + if test "$PHP_THREAD_CONTEXT" != "no"; then + AC_DEFINE(SW_USE_THREAD_CONTEXT, 1, [do we enable thread context]) + SW_USE_ASM_CONTEXT="no" + fi if test "$SW_USE_ASM_CONTEXT" = "yes"; then swoole_source_file="$swoole_source_file \ diff --git a/examples/coroutine/coro_empty.php b/examples/coroutine/coro_empty.php index 2a869b09f22..5b57ae8cbf7 100644 --- a/examples/coroutine/coro_empty.php +++ b/examples/coroutine/coro_empty.php @@ -1,8 +1,6 @@ 1]); -var_dump(SWOOLE_CORO_SCHEDULE); co::create(function () { echo "no coro exit\n"; }); diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index 8f42ecb37e4..9e01d113038 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -813,16 +813,19 @@ PHP_MINFO_FUNCTION(swoole) { php_info_print_table_row(2, "Version", SWOOLE_VERSION); snprintf(buf, sizeof(buf), "%s %s", __DATE__, __TIME__); php_info_print_table_row(2, "Built", buf); - php_info_print_table_row(2, "coroutine", "enabled"); +#if defined(SW_USE_THREAD_CONTEXT) + php_info_print_table_row(2, "coroutine", "enabled with thread context"); +#elif defined(SW_USE_ASM_CONTEXT) + php_info_print_table_row(2, "coroutine", "enabled with boost asm context"); +#else + php_info_print_table_row(2, "coroutine", "enabled with ucontext"); +#endif #ifdef SW_DEBUG php_info_print_table_row(2, "debug", "enabled"); #endif #ifdef SW_LOG_TRACE_OPEN php_info_print_table_row(2, "trace_log", "enabled"); #endif -#ifdef SW_NO_USE_ASM_CONTEXT - php_info_print_table_row(2, "ucontext", "enabled"); -#endif #ifdef HAVE_EPOLL php_info_print_table_row(2, "epoll", "enabled"); #endif diff --git a/ext-src/php_swoole.h b/ext-src/php_swoole.h index 94bf5bade55..b3d8b2a8e24 100644 --- a/ext-src/php_swoole.h +++ b/ext-src/php_swoole.h @@ -100,6 +100,10 @@ extern zend_module_entry swoole_module_entry; #error "require PHP version 7.2 or later" #endif +#if defined(ZTS) && defined(SW_USE_THREAD_CONTEXT) +#error "thread context cannot be used with ZTS" +#endif + //-------------------------------------------------------- #define SW_MAX_FIND_COUNT 100 //for swoole_server::connection_list #define SW_PHP_CLIENT_BUFFER_SIZE 65535 diff --git a/ext-src/swoole_coroutine.cc b/ext-src/swoole_coroutine.cc index 53aa072062d..56fcad22989 100644 --- a/ext-src/swoole_coroutine.cc +++ b/ext-src/swoole_coroutine.cc @@ -340,10 +340,10 @@ void PHPCoroutine::activate() { /* update the last coroutine's info */ save_task(get_context()); } - bool _ori_value = config.enable_deadlock_check; - config.enable_deadlock_check = false; - swoole_event_free(); - config.enable_deadlock_check = _ori_value; + if (sw_reactor()) { + sw_reactor()->running = false; + sw_reactor()->bailout = true; + } } if (sw_likely(orig_error_function)) { orig_error_function(type, error_filename, error_lineno, ZEND_ERROR_CB_LAST_ARG_RELAY); @@ -381,7 +381,7 @@ void PHPCoroutine::deadlock_check() { if (Coroutine::count() == 0) { return; } - if (php_swoole_is_fatal_error()) { + if (php_swoole_is_fatal_error() || (sw_reactor() && sw_reactor()->bailout)) { return; } if (SWOOLE_G(enable_library)) { @@ -769,7 +769,10 @@ void PHPCoroutine::main_func(void *arg) { } zend_catch { Coroutine::bailout([]() { - swoole_event_free(); + if (sw_reactor()) { + sw_reactor()->running = false; + sw_reactor()->bailout = true; + } sw_zend_bailout(); }); } @@ -938,8 +941,14 @@ PHP_METHOD(swoole_coroutine, stats) { add_assoc_long_ex(return_value, ZEND_STRL("event_num"), SwooleTG.reactor ? SwooleTG.reactor->event_num : 0); add_assoc_long_ex( return_value, ZEND_STRL("signal_listener_num"), SwooleTG.signal_listener_num + SwooleTG.co_signal_listener_num); - add_assoc_long_ex(return_value, ZEND_STRL("aio_task_num"), SwooleTG.aio_task_num); - add_assoc_long_ex(return_value, ZEND_STRL("aio_worker_num"), swoole::async::thread_count()); + + if (SwooleTG.async_threads) { + add_assoc_long_ex(return_value, ZEND_STRL("aio_task_num"), SwooleTG.async_threads->task_num); + add_assoc_long_ex(return_value, ZEND_STRL("aio_worker_num"), SwooleTG.async_threads->thread_count()); + } else { + add_assoc_long_ex(return_value, ZEND_STRL("aio_task_num"), 0); + add_assoc_long_ex(return_value, ZEND_STRL("aio_worker_num"), 0); + } add_assoc_long_ex(return_value, ZEND_STRL("c_stack_size"), Coroutine::get_stack_size()); add_assoc_long_ex(return_value, ZEND_STRL("coroutine_num"), Coroutine::count()); add_assoc_long_ex(return_value, ZEND_STRL("coroutine_peak_num"), Coroutine::get_peak_num()); diff --git a/ext-src/swoole_event.cc b/ext-src/swoole_event.cc index 83b9aa9aecd..8bf86fb3f62 100644 --- a/ext-src/swoole_event.cc +++ b/ext-src/swoole_event.cc @@ -281,7 +281,7 @@ void php_swoole_event_wait() { swSignalfd_setup(sw_reactor()); } #endif - if (!sw_reactor()->if_exit()) { + if (!sw_reactor()->if_exit() && !sw_reactor()->bailout) { // Don't disable object slot reuse while running shutdown functions: // https://github.com/php/php-src/commit/bd6eabd6591ae5a7c9ad75dfbe7cc575fa907eac #if defined(EG_FLAGS_IN_SHUTDOWN) && !defined(EG_FLAGS_OBJECT_STORE_NO_REUSE) diff --git a/ext-src/swoole_process.cc b/ext-src/swoole_process.cc index 7e3f3692a92..4235e86272c 100644 --- a/ext-src/swoole_process.cc +++ b/ext-src/swoole_process.cc @@ -347,7 +347,7 @@ static PHP_METHOD(swoole_process, __construct) { RETURN_FALSE; } - if (SwooleTG.aio_init) { + if (SwooleTG.async_threads) { php_swoole_fatal_error(E_ERROR, "unable to create %s with async-io threads", SW_Z_OBJCE_NAME_VAL_P(ZEND_THIS)); RETURN_FALSE; } diff --git a/include/swoole.h b/include/swoole.h index 3f9079dcaa5..60691ab85aa 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -179,6 +179,10 @@ namespace network { struct Socket; struct Address; } // namespace network +class AsyncThreads; +namespace async { +class ThreadPool; +} struct Protocol; struct EventData; struct DataHead; @@ -588,12 +592,7 @@ struct ThreadGlobal { String *buffer_stack; Reactor *reactor; Timer *timer; - uint8_t aio_init; - uint8_t aio_schedule; - uint32_t aio_task_num; - Pipe *aio_pipe; - network::Socket *aio_read_socket; - network::Socket *aio_write_socket; + AsyncThreads *async_threads; uint32_t signal_listener_num; uint32_t co_signal_listener_num; int error; diff --git a/include/swoole_async.h b/include/swoole_async.h index 5c351aaa42a..d2aeafbc229 100644 --- a/include/swoole_async.h +++ b/include/swoole_async.h @@ -20,18 +20,20 @@ #include #include +#include +#include #ifndef O_DIRECT #define O_DIRECT 040000 #endif -enum flag { +namespace swoole { + +enum AsyncFlags { SW_AIO_WRITE_FSYNC = 1u << 1, SW_AIO_EOF = 1u << 2, }; -namespace swoole { - struct AsyncEvent { int fd; size_t task_id; @@ -60,18 +62,31 @@ struct AsyncEvent { void (*callback)(AsyncEvent *event); }; +class AsyncThreads { + public: + bool schedule = false; + uint32_t task_num = 0; + Pipe *pipe = nullptr; + async::ThreadPool *pool = nullptr; + network::Socket *read_socket = nullptr; + network::Socket *write_socket = nullptr; + + AsyncThreads(); + ~AsyncThreads(); + + size_t thread_count(); + void notify_one(); + + static int callback(Reactor *reactor, Event *event); + private: + std::mutex init_lock; +}; + namespace async { typedef void (*Handler)(AsyncEvent *event); AsyncEvent *dispatch(const AsyncEvent *request); -int cancel(int task_id); -int callback(Reactor *reactor, swEvent *_event); -size_t thread_count(); - -#ifdef SW_DEBUG -void notify_one(); -#endif void handler_gethostbyname(AsyncEvent *event); void handler_getaddrinfo(AsyncEvent *event); diff --git a/include/swoole_error.h b/include/swoole_error.h index f5fe0bc2757..f4ea2f1ed98 100644 --- a/include/swoole_error.h +++ b/include/swoole_error.h @@ -167,3 +167,13 @@ enum swErrorCode { SW_ERROR_END }; + +namespace swoole { +class Exception { + public: + int code; + const char *msg; + + Exception(int code); +}; +} diff --git a/include/swoole_reactor.h b/include/swoole_reactor.h index faedd6c5880..f2b04f0603d 100644 --- a/include/swoole_reactor.h +++ b/include/swoole_reactor.h @@ -118,6 +118,7 @@ class Reactor { bool once = false; bool wait_exit = false; bool destroyed = false; + bool bailout = false; /** * callback signal */ diff --git a/src/core/base.cc b/src/core/base.cc index 5130e7cbd81..659eb4406c0 100644 --- a/src/core/base.cc +++ b/src/core/base.cc @@ -258,11 +258,8 @@ pid_t swoole_fork(int flags) { if (swoole_coroutine_is_in()) { swFatalError(SW_ERROR_OPERATION_NOT_SUPPORT, "must be forked outside the coroutine"); } - if (SwooleTG.aio_init) { - printf("aio_init=%d, aio_task_num=%d, reactor=%p\n", - SwooleTG.aio_init, - SwooleTG.aio_task_num, - SwooleTG.reactor); + if (SwooleTG.async_threads) { + swTrace("aio_task_num=%d, reactor=%p", SwooleTG.async_threads->task_num, SwooleTG.reactor); swFatalError(SW_ERROR_OPERATION_NOT_SUPPORT, "can not create server after using async file operation"); } } diff --git a/src/core/error.cc b/src/core/error.cc index b44ea03858f..449e02b3228 100644 --- a/src/core/error.cc +++ b/src/core/error.cc @@ -19,16 +19,9 @@ #include "swoole.h" namespace swoole { - -class Exception { - public: - int code; - const char *msg; - - Exception(int code) : code(code) { - msg = swoole_strerror(code); - } -}; +Exception::Exception(int code) : code(code) { + msg = swoole_strerror(code); +} } // namespace swoole const char *swoole_strerror(int code) { diff --git a/src/coroutine/system.cc b/src/coroutine/system.cc index 1683e17f5dc..6eaa7f799b0 100644 --- a/src/coroutine/system.cc +++ b/src/coroutine/system.cc @@ -593,7 +593,7 @@ void System::init_reactor(Reactor *reactor) { reactor->set_handler(SW_FD_CORO_EVENT | SW_EVENT_WRITE, event_waiter_write_callback); reactor->set_handler(SW_FD_CORO_EVENT | SW_EVENT_ERROR, event_waiter_error_callback); - reactor->set_handler(SW_FD_AIO | SW_EVENT_READ, async::callback); + reactor->set_handler(SW_FD_AIO | SW_EVENT_READ, AsyncThreads::callback); } static void async_task_completed(AsyncEvent *event) { diff --git a/src/coroutine/thread_context.cc b/src/coroutine/thread_context.cc index 42aa42ba23f..d7731570399 100644 --- a/src/coroutine/thread_context.cc +++ b/src/coroutine/thread_context.cc @@ -15,6 +15,7 @@ */ #include "swoole_api.h" +#include "swoole_async.h" #include "swoole_coroutine_context.h" #ifdef SW_USE_THREAD_CONTEXT @@ -22,25 +23,30 @@ namespace swoole { namespace coroutine { -static std::mutex global_lock; +static std::mutex g_lock; static Reactor *g_reactor = nullptr; static Timer *g_timer = nullptr; +static String *g_buffer = nullptr; +static AsyncThreads *g_async_threads = nullptr; static std::mutex *current_lock = nullptr; -static void empty_timer(Timer *timer, TimerNode *tnode) { - // do nothing -} - Context::Context(size_t stack_size, const coroutine_func_t &fn, void *private_data) : fn_(fn), private_data_(private_data) { if (sw_unlikely(current_lock == nullptr)) { - current_lock = &global_lock; - g_reactor = SwooleTG.reactor; + current_lock = &g_lock; if (SwooleTG.timer == nullptr) { - swoole_timer_add(1, 0, empty_timer, nullptr); + swoole_timer_add(1, false, [](Timer *timer, TimerNode *tnode) { + // do nothing + }, nullptr); + } + if (SwooleTG.async_threads == nullptr) { + SwooleTG.async_threads = new AsyncThreads(); } + g_reactor = SwooleTG.reactor; + g_buffer = SwooleTG.buffer_stack; g_timer = SwooleTG.timer; - global_lock.lock(); + g_async_threads = SwooleTG.async_threads; + g_lock.lock(); } end_ = false; lock_.lock(); @@ -71,11 +77,13 @@ void Context::context_func(void *arg) { Context *_this = (Context *) arg; SwooleTG.reactor = g_reactor; SwooleTG.timer = g_timer; + SwooleTG.buffer_stack = g_buffer; + SwooleTG.async_threads = g_async_threads; _this->lock_.lock(); _this->fn_(_this->private_data_); - _this->lock_.unlock(); - _this->swap_lock_->unlock(); _this->end_ = true; + current_lock = _this->swap_lock_; + _this->swap_lock_->unlock(); } } // namespace coroutine } // namespace swoole diff --git a/src/os/async_thread.cc b/src/os/async_thread.cc index db1035b7b3c..f254aed96a3 100644 --- a/src/os/async_thread.cc +++ b/src/os/async_thread.cc @@ -35,18 +35,6 @@ namespace swoole { namespace async { //------------------------------------------------------------------------------- -static std::mutex init_lock; -static std::atomic refcount(0); -static void aio_thread_release(AsyncEvent *event); -static thread_local std::string tmp_thread_id; - -static const char *get_thread_id(std::thread::id id) { - std::stringstream ss; - ss << id; - tmp_thread_id = ss.str(); - return tmp_thread_id.c_str(); -} - class EventQueue { public: inline void push(AsyncEvent *event) { @@ -88,8 +76,6 @@ class ThreadPool { worker_num = _worker_num == 0 ? SW_CPU_NUM * SW_AIO_THREAD_NUM_MULTIPLE : SW_MAX(core_worker_num, _worker_num); max_wait_time = _max_wait_time == 0 ? SW_AIO_TASK_MAX_WAIT_TIME : _max_wait_time; max_idle_time = _max_idle_time == 0 ? SW_AIO_THREAD_MAX_IDLE_TIME : _max_idle_time; - - creator_pid = getpid(); } ~ThreadPool() { @@ -155,13 +141,13 @@ class ThreadPool { } AsyncEvent *dispatch(const AsyncEvent *request) { - if (SwooleTG.aio_schedule) { + if (SwooleTG.async_threads->schedule) { schedule(); } auto _event_copy = new AsyncEvent(*request); _event_copy->task_id = current_task_id++; _event_copy->timestamp = microtime(); - _event_copy->pipe_socket = SwooleTG.aio_write_socket; + _event_copy->pipe_socket = SwooleTG.async_threads->write_socket; event_mutex.lock(); _queue.push(_event_copy); _cv.notify_one(); @@ -179,18 +165,23 @@ class ThreadPool { return _queue.count(); } - pid_t get_creator_pid() { - return creator_pid; + static std::string get_thread_id(std::thread::id id) { + std::stringstream ss; + ss << id; + return ss.str(); } void release_thread(std::thread::id tid) { auto i = threads.find(tid); if (i == threads.end()) { - swWarn("AIO thread#%s is missing", get_thread_id(tid)); + swWarn("AIO thread#%s is missing", get_thread_id(tid).c_str()); return; } else { std::thread *_thread = i->second; - swTraceLog(SW_TRACE_AIO, "release idle thread#%s, we have %zu now", get_thread_id(tid), threads.size() - 1); + swTraceLog(SW_TRACE_AIO, + "release idle thread#%s, we have %zu now", + get_thread_id(tid).c_str(), + threads.size() - 1); if (_thread->joinable()) { _thread->join(); } @@ -199,11 +190,17 @@ class ThreadPool { } } -#ifdef SW_DEBUG + static void release_callback(AsyncEvent *event) { + std::thread::id *tid = reinterpret_cast(event->object); + SwooleTG.async_threads->pool->release_thread(*tid); + delete tid; + // balance + SwooleTG.async_threads->task_num++; + } + void notify_one() { _cv.notify_one(); } -#endif private: void create_thread(const bool is_core_worker = false); @@ -218,15 +215,12 @@ class ThreadPool { std::atomic n_waiting; std::atomic n_closing; size_t current_task_id = 0; - pid_t creator_pid; std::unordered_map threads; EventQueue _queue; std::mutex event_mutex; std::condition_variable _cv; }; -static ThreadPool *pool = nullptr; - void ThreadPool::create_thread(const bool is_core_worker) { try { std::thread *_thread = new std::thread([this, is_core_worker]() { @@ -299,7 +293,7 @@ void ThreadPool::create_thread(const bool is_core_worker) { } else { while (true) { if (_cv.wait_for(lock, std::chrono::microseconds((size_t)(max_idle_time * 1000 * 1000))) == - std::cv_status::timeout) { + std::cv_status::timeout) { if (running && n_closing != 0) { // wait for the next round continue; @@ -307,7 +301,7 @@ void ThreadPool::create_thread(const bool is_core_worker) { /* notifies the main thread to release this thread */ event = new AsyncEvent; event->object = new std::thread::id(std::this_thread::get_id()); - event->callback = aio_thread_release; + event->callback = release_callback; event->pipe_socket = SwooleG.aio_default_socket; event->canceled = false; @@ -330,101 +324,23 @@ void ThreadPool::create_thread(const bool is_core_worker) { } } -static void aio_thread_release(AsyncEvent *event) { - std::thread::id *tid = reinterpret_cast(event->object); - pool->release_thread(*tid); - delete tid; - // balance - SwooleTG.aio_task_num++; -} - -static void destroy(void *private_data) { - if (!SwooleTG.aio_init) { - return; - } - SwooleTG.aio_init = 0; - swoole_event_del(SwooleTG.aio_read_socket); - - if (pool->get_creator_pid() == getpid()) { - if ((--refcount) == 0) { - delete pool; - pool = nullptr; - - SwooleTG.aio_pipe->close(); - SwooleTG.aio_read_socket = nullptr; - SwooleTG.aio_write_socket = nullptr; - delete SwooleTG.aio_pipe; - SwooleTG.aio_pipe = nullptr; - } - } -} - -static int init() { - if (SwooleTG.aio_init) { - swWarn("aio_thread_pool has already been initialized"); - return SW_ERR; - } - if (!SwooleTG.reactor) { - swWarn("no event loop, cannot initialized"); - return SW_ERR; - } - - SwooleTG.aio_pipe = new Pipe(false); - - if (!SwooleTG.aio_pipe->ready()) { - delete SwooleTG.aio_pipe; - SwooleTG.aio_pipe = nullptr; - swoole_throw_error(SW_ERROR_SYSTEM_CALL_FAIL); - } - - SwooleTG.aio_read_socket = SwooleTG.aio_pipe->get_socket(false); - SwooleTG.aio_write_socket = SwooleTG.aio_pipe->get_socket(true); - SwooleTG.aio_read_socket->fd_type = SW_FD_AIO; - SwooleTG.aio_write_socket->fd_type = SW_FD_AIO; - - swoole_event_add(SwooleTG.aio_read_socket, SW_EVENT_READ); - - sw_reactor()->add_destroy_callback(destroy); - sw_reactor()->set_exit_condition(Reactor::EXIT_CONDITION_AIO_TASK, - [](Reactor *reactor, int &event_num) -> bool { - if (SwooleTG.aio_init && SwooleTG.aio_task_num == 0) { - event_num--; - } - return true; - }); - - init_lock.lock(); - if ((refcount++) == 0) { - pool = new ThreadPool( - SwooleG.aio_core_worker_num, SwooleG.aio_worker_num, SwooleG.aio_max_wait_time, SwooleG.aio_max_idle_time); - pool->start(); - SwooleTG.aio_schedule = 1; - SwooleG.aio_default_socket = SwooleTG.aio_write_socket; - } - SwooleTG.aio_init = 1; - init_lock.unlock(); - - return SW_OK; -} - -size_t thread_count() { - return pool ? pool->worker_count() : 0; -} - AsyncEvent *dispatch(const AsyncEvent *request) { - if (sw_unlikely(!SwooleTG.aio_init)) { - init(); + if (sw_unlikely(!SwooleTG.async_threads)) { + SwooleTG.async_threads = new AsyncThreads(); } - AsyncEvent *event = pool->dispatch(request); + AsyncEvent *event = SwooleTG.async_threads->pool->dispatch(request); if (sw_likely(event)) { - SwooleTG.aio_task_num++; + SwooleTG.async_threads->task_num++; } return event; } -int callback(Reactor *reactor, Event *event) { - if (SwooleTG.aio_schedule) { - pool->schedule(); +//------------------------------------------------------------------------------- +} // namespace async + +int AsyncThreads::callback(Reactor *reactor, Event *event) { + if (SwooleTG.async_threads->schedule) { + SwooleTG.async_threads->pool->schedule(); } AsyncEvent *events[SW_AIO_EVENT_NUM]; @@ -438,21 +354,77 @@ int callback(Reactor *reactor, Event *event) { if (!event->canceled) { event->callback(event); } - SwooleTG.aio_task_num--; + SwooleTG.async_threads->task_num--; delete event; } return SW_OK; } -#ifdef SW_DEBUG -void notify_one() { +size_t AsyncThreads::thread_count() { + return pool ? pool->worker_count() : 0; +} + +void AsyncThreads::notify_one() { if (pool) { pool->notify_one(); } } -#endif -//------------------------------------------------------------------------------- -} // namespace async +AsyncThreads::AsyncThreads() { + if (!SwooleTG.reactor) { + swWarn("no event loop, cannot initialized"); + throw swoole::Exception(SW_ERROR_WRONG_OPERATION); + } + + pipe = new Pipe(false); + if (!pipe->ready()) { + delete pipe; + pipe = nullptr; + swoole_throw_error(SW_ERROR_SYSTEM_CALL_FAIL); + } + + read_socket = pipe->get_socket(false); + write_socket = pipe->get_socket(true); + read_socket->fd_type = SW_FD_AIO; + write_socket->fd_type = SW_FD_AIO; + + swoole_event_add(read_socket, SW_EVENT_READ); + + sw_reactor()->add_destroy_callback([](void *data) { + if (!SwooleTG.async_threads) { + return; + } + swoole_event_del(SwooleTG.async_threads->read_socket); + delete SwooleTG.async_threads; + SwooleTG.async_threads = nullptr; + }); + + sw_reactor()->set_exit_condition(Reactor::EXIT_CONDITION_AIO_TASK, [](Reactor *reactor, int &event_num) -> bool { + if (SwooleTG.async_threads && SwooleTG.async_threads->task_num == 0) { + event_num--; + } + return true; + }); + + init_lock.lock(); + pool = new async::ThreadPool( + SwooleG.aio_core_worker_num, SwooleG.aio_worker_num, SwooleG.aio_max_wait_time, SwooleG.aio_max_idle_time); + pool->start(); + schedule = true; + init_lock.unlock(); + + SwooleG.aio_default_socket = write_socket; + SwooleTG.async_threads = this; +} + +AsyncThreads::~AsyncThreads() { + delete pool; + pool = nullptr; + pipe->close(); + read_socket = nullptr; + write_socket = nullptr; + delete pipe; + pipe = nullptr; +} }; // namespace swoole diff --git a/tests/swoole_coroutine/bailout/error.phpt b/tests/swoole_coroutine/bailout/error.phpt index 1c3cf8d560a..d775de3d2fc 100644 --- a/tests/swoole_coroutine/bailout/error.phpt +++ b/tests/swoole_coroutine/bailout/error.phpt @@ -5,12 +5,16 @@ swoole_coroutine/bailout: error --FILE-- --EXPECTF-- Fatal error: Uncaught Error in %s:%d From 1f3000ba17ec67880d5dcd760428b94135859a10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Fri, 8 Jan 2021 17:48:24 +0800 Subject: [PATCH 008/936] Add tests (#3989) * Add tests for ssl server * update error message * fix tests --- core-tests/src/lock/lock.cpp | 2 + core-tests/src/server/server.cpp | 65 ++++++++++++++++++++++++++++++++ include/swoole_client.h | 10 +++++ include/swoole_server.h | 8 ++++ include/swoole_ssl.h | 1 + src/memory/buffer.cc | 1 + src/protocol/ssl.cc | 37 ++++++++++++------ 7 files changed, 113 insertions(+), 11 deletions(-) diff --git a/core-tests/src/lock/lock.cpp b/core-tests/src/lock/lock.cpp index 741dd58ab97..24e9b426797 100644 --- a/core-tests/src/lock/lock.cpp +++ b/core-tests/src/lock/lock.cpp @@ -26,7 +26,9 @@ using swLock = swoole::Lock; using swoole::RWLock; +#ifdef HAVE_SPINLOCK using swoole::SpinLock; +#endif using swoole::Mutex; static void test_func(swLock &lock) { diff --git a/core-tests/src/server/server.cpp b/core-tests/src/server/server.cpp index 3a8c7c76968..c39fc00eec6 100644 --- a/core-tests/src/server/server.cpp +++ b/core-tests/src/server/server.cpp @@ -141,6 +141,71 @@ TEST(server, process) { delete lock; } +#ifdef SW_USE_OPENSSL +TEST(server, ssl) { + Server serv(Server::MODE_PROCESS); + serv.worker_num = 1; + + SwooleG.running = 1; + + sw_logger()->set_level(SW_LOG_WARNING); + + Mutex *lock = new Mutex(Mutex::PROCESS_SHARED); + lock->lock(); + + ListenPort *port = serv.add_port((enum swSocket_type )(SW_SOCK_TCP | SW_SOCK_SSL), TEST_HOST, 0); + if (!port) { + swWarn("listen failed, [error=%d]", swoole_get_last_error()); + exit(2); + } + + port->ssl_set_cert_file(test::get_root_path() + "/tests/include/ssl_certs/server.crt"); + port->ssl_set_key_file(test::get_root_path() + "/tests/include/ssl_certs/server.key"); + port->ssl_init(); + + ASSERT_EQ(serv.create(), SW_OK); + + serv.onStart = [&lock](Server *serv) { + thread t1([=]() { + swSignal_none(); + + lock->lock(); + + ListenPort *port = serv->get_primary_port(); + + EXPECT_EQ(port->ssl, 1); + EXPECT_EQ(swSSL_is_thread_safety(), true); + + swoole::network::SyncClient c(SW_SOCK_TCP); + c.connect(TEST_HOST, port->port); + c.enable_ssl_encrypt(); + c.send(packet, strlen(packet)); + char buf[1024]; + c.recv(buf, sizeof(buf)); + c.close(); + + kill(serv->gs->master_pid, SIGTERM); + }); + t1.detach(); + }; + + serv.onWorkerStart = [&lock](Server *serv, int worker_id) { lock->unlock(); }; + + serv.onReceive = [](Server *serv, RecvData *req) -> int { + EXPECT_EQ(string(req->data, req->info.len), string(packet)); + + string resp = string("Server: ") + string(packet); + serv->send(req->info.fd, resp.c_str(), resp.length()); + + return SW_OK; + }; + + ASSERT_EQ(serv.start(), 0); + + delete lock; +} +#endif + TEST(server, task_worker) { swServer serv; serv.worker_num = 1; diff --git a/include/swoole_client.h b/include/swoole_client.h index 12b69fe1a3f..cee92947889 100644 --- a/include/swoole_client.h +++ b/include/swoole_client.h @@ -192,6 +192,16 @@ class SyncClient { return true; } +#ifdef SW_USE_OPENSSL + bool enable_ssl_encrypt() { + if (client.enable_ssl_encrypt() < 0 || client.ssl_handshake() < 0) { + return false; + } else { + return true; + } + } +#endif + ssize_t send(const std::string &data) { return client.send(&client, data.c_str(), data.length(), 0); } diff --git a/include/swoole_server.h b/include/swoole_server.h index 35723d623ba..9d3529fbd17 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -394,6 +394,14 @@ struct ListenPort { bool ssl_create(Connection *conn, network::Socket *sock); bool ssl_add_sni_cert(const std::string &name, SSLContext *context); bool ssl_init(); + + void ssl_set_key_file(const std::string &file) { + ssl_context->key_file = file; + } + + void ssl_set_cert_file(const std::string &file) { + ssl_context->cert_file = file; + } #endif void clear_protocol(); inline network::Socket *get_socket() { diff --git a/include/swoole_ssl.h b/include/swoole_ssl.h index 4118fed5bbd..4690edf396a 100644 --- a/include/swoole_ssl.h +++ b/include/swoole_ssl.h @@ -160,6 +160,7 @@ struct SSLContext { void swSSL_init(void); void swSSL_init_thread_safety(); +bool swSSL_is_thread_safety(); void swSSL_server_http_advise(swoole::SSLContext &); const char *swSSL_get_error(); int swSSL_get_ex_connection_index(); diff --git a/src/memory/buffer.cc b/src/memory/buffer.cc index ed4cc7630ff..f5bc784778d 100644 --- a/src/memory/buffer.cc +++ b/src/memory/buffer.cc @@ -16,6 +16,7 @@ #include "swoole.h" #include "swoole_buffer.h" + namespace swoole { Buffer::Buffer(uint32_t _chunk_size) { diff --git a/src/protocol/ssl.cc b/src/protocol/ssl.cc index b45144fcac9..18207fb2b58 100644 --- a/src/protocol/ssl.cc +++ b/src/protocol/ssl.cc @@ -29,7 +29,8 @@ using swoole::SSLContext; #error "require openssl version 1.0 or later" #endif -static int openssl_init = 0; +static bool openssl_init = false; +static bool openssl_thread_safety_init = false; static int ssl_connection_index = 0; static int ssl_port_index = 0; static pthread_mutex_t *lock_array; @@ -81,7 +82,7 @@ void swSSL_init(void) { return; } - openssl_init = 1; + openssl_init = true; } int swSSL_get_ex_connection_index() { @@ -97,18 +98,20 @@ void swSSL_destroy() { return; } - CRYPTO_set_locking_callback(nullptr); - int i; - for (i = 0; i < CRYPTO_num_locks(); i++) { + SW_LOOP_N(CRYPTO_num_locks()) { pthread_mutex_destroy(&(lock_array[i])); } - openssl_init = 0; + + OPENSSL_free(lock_array); + #if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_1_0_0 (void) CRYPTO_THREADID_set_callback(nullptr); #else CRYPTO_set_id_callback(nullptr); #endif CRYPTO_set_locking_callback(nullptr); + openssl_init = false; + openssl_thread_safety_init = false; } static void MAYBE_UNUSED swSSL_lock_callback(int mode, int type, const char *file, int line) { @@ -145,9 +148,13 @@ void swSSL_init_thread_safety() { if (!openssl_init) { return; } - int i; + + if (openssl_thread_safety_init) { + return; + } + lock_array = (pthread_mutex_t *) OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); - for (i = 0; i < CRYPTO_num_locks(); i++) { + SW_LOOP_N(CRYPTO_num_locks()) { pthread_mutex_init(&(lock_array[i]), nullptr); } @@ -158,6 +165,11 @@ void swSSL_init_thread_safety() { #endif CRYPTO_set_locking_callback(swSSL_lock_callback); + openssl_thread_safety_init = true; +} + +bool swSSL_is_thread_safety() { + return openssl_thread_safety_init; } static void swSSL_info_callback(const SSL *ssl, int where, int ret) { @@ -411,7 +423,8 @@ bool SSLContext::create() { */ if (SSL_CTX_use_certificate_file(context, cert_file.c_str(), SSL_FILETYPE_PEM) <= 0) { int error = ERR_get_error(); - swWarn("SSL_CTX_use_certificate_file() failed, Error: %s[%d]", ERR_reason_error_string(error), error); + swWarn("SSL_CTX_use_certificate_file(%s) failed, Error: %s[%d]", cert_file.c_str(), + ERR_reason_error_string(error), error); return true; } /* @@ -420,7 +433,8 @@ bool SSLContext::create() { */ if (SSL_CTX_use_certificate_chain_file(context, cert_file.c_str()) <= 0) { int error = ERR_get_error(); - swWarn("SSL_CTX_use_certificate_chain_file() failed, Error: %s[%d]", ERR_reason_error_string(error), error); + swWarn("SSL_CTX_use_certificate_chain_file(%s) failed, Error: %s[%d]", cert_file.c_str(), + ERR_reason_error_string(error), error); return false; } /* @@ -428,7 +442,8 @@ bool SSLContext::create() { */ if (SSL_CTX_use_PrivateKey_file(context, key_file.c_str(), SSL_FILETYPE_PEM) <= 0) { int error = ERR_get_error(); - swWarn("SSL_CTX_use_PrivateKey_file() failed, Error: %s[%d]", ERR_reason_error_string(error), error); + swWarn("SSL_CTX_use_PrivateKey_file(%s) failed, Error: %s[%d]", key_file.c_str(), + ERR_reason_error_string(error), error); return false; } /* From 36a1dc2045b43c8dfdd159520badb7f4b10af056 Mon Sep 17 00:00:00 2001 From: codinghuang <2812240764@qq.com> Date: Sun, 10 Jan 2021 12:43:54 +0800 Subject: [PATCH 009/936] Fix issue 3988 (#3990) * Fix issue 3988 * Add test * Don't create socket in enableSSL * Fix test * Enable ssl in PHP_METHOD(swoole_client_coro, enableSSL) * Enable ssl before php_swoole_socket_set_ssl --- ext-src/swoole_client_coro.cc | 5 ++++ tests/swoole_client_coro/enableSSL.phpt | 35 +++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 tests/swoole_client_coro/enableSSL.phpt diff --git a/ext-src/swoole_client_coro.cc b/ext-src/swoole_client_coro.cc index 25e10164fa0..5c3e5b7f71c 100644 --- a/ext-src/swoole_client_coro.cc +++ b/ext-src/swoole_client_coro.cc @@ -867,9 +867,11 @@ static PHP_METHOD(swoole_client_coro, close) { #ifdef SW_USE_OPENSSL static PHP_METHOD(swoole_client_coro, enableSSL) { Socket *cli = client_get_ptr(ZEND_THIS); + if (!cli) { RETURN_FALSE; } + if (cli->get_type() != SW_SOCK_TCP && cli->get_type() != SW_SOCK_TCP6) { php_swoole_fatal_error(E_WARNING, "cannot use enableSSL"); RETURN_FALSE; @@ -878,6 +880,9 @@ static PHP_METHOD(swoole_client_coro, enableSSL) { php_swoole_fatal_error(E_WARNING, "SSL has been enabled"); RETURN_FALSE; } + + cli->enable_ssl_encrypt(); + zval *zset = sw_zend_read_property_ex(swoole_client_coro_ce, ZEND_THIS, SW_ZSTR_KNOWN(SW_ZEND_STR_SETTING), 0); if (php_swoole_array_length_safe(zset) > 0) { php_swoole_socket_set_ssl(cli, zset); diff --git a/tests/swoole_client_coro/enableSSL.phpt b/tests/swoole_client_coro/enableSSL.phpt new file mode 100644 index 00000000000..4e022ccdd63 --- /dev/null +++ b/tests/swoole_client_coro/enableSSL.phpt @@ -0,0 +1,35 @@ +--TEST-- +swoole_client_coro: enableSSL +--SKIPIF-- + +--FILE-- +connect('www.baidu.com', 443); + $client->enableSSL(); + + $http = "GET / HTTP/1.0\r\nAccept: */*User-Agent: Lowell-Agent\r\nHost: www.baidu.com\r\nConnection: Close\r\n\r\n"; + if (!$client->send($http)) { + echo "ERROR\n"; + } + + $content = ''; + while (true) { + $read = $client->recv(); + if (empty($read)) { + break; + } + $content .= $read; + } + $client->close(); + Assert::assert(strpos($content, 'map.baidu.com') !== false); +}); +?> +--EXPECT-- From 85f7153b04fc428fd70e0071db9c1fcf6391fa89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Mon, 11 Jan 2021 10:52:15 +0800 Subject: [PATCH 010/936] Strict session ID (#3993) * Strict session ID * optimize code --- ext-src/swoole_http_response.cc | 6 +++-- ext-src/swoole_server.cc | 43 +++++++++++++----------------- ext-src/swoole_websocket_server.cc | 8 +++--- include/swoole_server.h | 1 - 4 files changed, 26 insertions(+), 32 deletions(-) diff --git a/ext-src/swoole_http_response.cc b/ext-src/swoole_http_response.cc index 9f35bee733f..a32b8a723e4 100644 --- a/ext-src/swoole_http_response.cc +++ b/ext-src/swoole_http_response.cc @@ -39,6 +39,8 @@ extern "C" { #endif using swoole::coroutine::Socket; +using swoole::Server; +using swoole::Connection; using swoole::substr_len; using http_response = swoole::http::Response; using http_context = swoole::http::Context; @@ -843,8 +845,8 @@ void swoole_http_response_end(http_context *ctx, zval *zdata, zval *return_value _skip_copy: #endif if (ctx->upgrade && !ctx->co_socket) { - swServer *serv = (swServer *) ctx->private_data; - swConnection *conn = serv->get_connection_by_session_id(ctx->fd); + Server *serv = (Server *) ctx->private_data; + Connection *conn = serv->get_connection_verify(ctx->fd); if (conn && conn->websocket_status == WEBSOCKET_STATUS_HANDSHAKE) { if (ctx->response.status == 101) { conn->websocket_status = WEBSOCKET_STATUS_ACTIVE; diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index c9d7798c518..ac4f06227f8 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -3645,8 +3645,8 @@ static PHP_METHOD(swoole_server, bind) { RETURN_FALSE; } - Connection *conn = serv->get_connection_by_session_id(fd); - if (conn == nullptr || conn->active == 0) { + Connection *conn = serv->get_connection_verify(fd); + if (conn == nullptr) { RETURN_FALSE; } @@ -3751,10 +3751,10 @@ static PHP_METHOD(swoole_server, getClientList) { RETURN_FALSE; } - zend_long start_fd = 0; + zend_long start_session_id = 0; zend_long find_count = 10; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &start_fd, &find_count) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &start_session_id, &find_count) == FAILURE) { RETURN_FALSE; } @@ -3766,12 +3766,13 @@ static PHP_METHOD(swoole_server, getClientList) { // copy it out to avoid being overwritten by other processes int serv_max_fd = serv->get_maxfd(); + int start_fd; - if (start_fd == 0) { + if (start_session_id == 0) { start_fd = serv->get_minfd(); } else { - Connection *conn = serv->get_connection_by_session_id(start_fd); - if (!conn) { + Connection *conn = serv->get_connection_verify(start_session_id); + if (!serv->is_valid_connection(conn)) { RETURN_FALSE; } start_fd = conn->fd; @@ -3786,10 +3787,10 @@ static PHP_METHOD(swoole_server, getClientList) { Connection *conn; for (; fd <= serv_max_fd; fd++) { - swTrace("maxfd=%d, fd=%d, find_count=%ld, start_fd=%ld", serv_max_fd, fd, find_count, start_fd); + swTrace("maxfd=%d, fd=%d, find_count=%ld, start_fd=%ld", serv_max_fd, fd, find_count, start_session_id); conn = serv->get_connection(fd); - if (conn->active && !conn->closed) { + if (serv->is_valid_connection(conn)) { #ifdef SW_USE_OPENSSL if (conn->ssl && !conn->ssl_ready) { continue; @@ -3842,18 +3843,14 @@ static PHP_METHOD(swoole_server, exists) { RETURN_FALSE; } - zend_long fd; + zend_long session_id; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_LONG(fd) + Z_PARAM_LONG(session_id) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - Connection *conn = serv->get_connection_by_session_id(fd); - if (!conn) { - RETURN_FALSE; - } - // connection is closed - if (conn->active == 0 || conn->closed) { + Connection *conn = serv->get_connection_verify(session_id); + if (!conn || conn->closed) { RETURN_FALSE; } else { RETURN_TRUE; @@ -3867,19 +3864,15 @@ static PHP_METHOD(swoole_server, protect) { RETURN_FALSE; } - zend_long fd; + zend_long session_id; zend_bool value = 1; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|b", &fd, &value) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|b", &session_id, &value) == FAILURE) { RETURN_FALSE; } - Connection *conn = serv->get_connection_by_session_id(fd); - if (!conn) { - RETURN_FALSE; - } - // connection is closed - if (conn->active == 0 || conn->closed) { + Connection *conn = serv->get_connection_verify(session_id); + if (!conn || conn->closed) { RETURN_FALSE; } else { conn->protect = value; diff --git a/ext-src/swoole_websocket_server.cc b/ext-src/swoole_websocket_server.cc index 0b1915e81a3..c0e6fbff411 100644 --- a/ext-src/swoole_websocket_server.cc +++ b/ext-src/swoole_websocket_server.cc @@ -907,15 +907,15 @@ static PHP_METHOD(swoole_websocket_server, isEstablished) { RETURN_FALSE; } - zend_long fd; + zend_long session_id; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &fd) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &session_id) == FAILURE) { RETURN_FALSE; } - Connection *conn = serv->get_connection_by_session_id(fd); + Connection *conn = serv->get_connection_verify(session_id); // not isEstablished - if (!conn || conn->active == 0 || conn->closed || conn->websocket_status < WEBSOCKET_STATUS_ACTIVE) { + if (!conn || conn->closed || conn->websocket_status < WEBSOCKET_STATUS_ACTIVE) { RETURN_FALSE; } else { RETURN_TRUE; diff --git a/include/swoole_server.h b/include/swoole_server.h index 9d3529fbd17..2239942dc46 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -1136,7 +1136,6 @@ class Server { Connection *conn = get_connection_verify_no_ssl(session_id); #ifdef SW_USE_OPENSSL if (conn && conn->ssl && !conn->ssl_ready) { - swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SSL_NOT_READY, "SSL not ready"); return nullptr; } #endif From 3d4c2d717bad3a4254ced83bf065bf4d414ba095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Mon, 11 Jan 2021 17:06:08 +0800 Subject: [PATCH 011/936] Optimize ipc writev (#3994) * optimize ipc writev * added assertion * added assertion [2] * optimize code * update tests --- src/memory/buffer.cc | 4 ++ src/server/process.cc | 13 +++-- tests/swoole_server/slow_worker.phpt | 80 ++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 tests/swoole_server/slow_worker.phpt diff --git a/src/memory/buffer.cc b/src/memory/buffer.cc index f5bc784778d..40520ced0d5 100644 --- a/src/memory/buffer.cc +++ b/src/memory/buffer.cc @@ -62,6 +62,8 @@ void Buffer::append(const void *data, uint32_t size) { char *_pos = (char *) data; uint32_t _n; + assert(size > 0); + // buffer enQueue while (_length > 0) { _n = _length >= chunk_size ? chunk_size : _length; @@ -84,6 +86,8 @@ void Buffer::append(const struct iovec *iov, size_t iovcnt, off_t offset) { size_t _length = 0; SW_LOOP_N(iovcnt) { + assert(iov[i].iov_len > 0); + assert(iov[i].iov_base != nullptr); _length += iov[i].iov_len; } diff --git a/src/server/process.cc b/src/server/process.cc index f367d58a58f..03c28eb8443 100644 --- a/src/server/process.cc +++ b/src/server/process.cc @@ -215,12 +215,19 @@ static bool process_send_packet(Server *serv, SendData *resp, SendFunc _send, vo resp->info.flags = 0; resp->info.len = send_n; + size_t iovcnt; iov[0].iov_base = &resp->info; iov[0].iov_len = sizeof(resp->info); - iov[1].iov_base = (void *) resp->data; - iov[1].iov_len = send_n; - int retval = _send(serv, &resp->info, iov, 2, private_data); + if (resp->data) { + iov[1].iov_base = (void *) resp->data; + iov[1].iov_len = send_n; + iovcnt = 2; + } else { + iovcnt = 1; + } + + int retval = _send(serv, &resp->info, iov, iovcnt, private_data); #ifdef __linux__ if (retval < 0 && errno == ENOBUFS) { max_length = SW_IPC_BUFFER_SIZE; diff --git a/tests/swoole_server/slow_worker.phpt b/tests/swoole_server/slow_worker.phpt new file mode 100644 index 00000000000..1aafc4af0db --- /dev/null +++ b/tests/swoole_server/slow_worker.phpt @@ -0,0 +1,80 @@ +--TEST-- +swoole_server: slow worker +--SKIPIF-- + +--FILE-- +add(strlen($data)); +} + +$pm = new SwooleTest\ProcessManager; +$pm->parentFunc = function ($pid) use ($pm, $counter_server, $counter_client, $data_chunks) { + $cli = new Client(SWOOLE_SOCK_TCP); + $r = $cli->connect(TCP_SERVER_HOST, $pm->getFreePort(), 5); + Assert::assert($r); + Assert::eq($cli->recv(), 'CONNECT OK'.PHP_EOL); + + foreach ($data_chunks as $chunk) { + $cli->send($chunk); + } + + $cli2 = new Client(SWOOLE_SOCK_TCP); + $r = $cli2->connect(TCP_SERVER_HOST, $pm->getFreePort(), 5); + Assert::assert($r); + Assert::eq($cli2->recv(), 'CONNECT OK'.PHP_EOL); + + echo $cli->recv(); + Assert::eq($counter_server->get(), $counter_client->get()); + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm, $counter_server, $counter_client) { + $serv = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_PROCESS); + $serv->set(array( + "worker_num" => 1, + 'log_file' => '/dev/null', + 'open_length_check' => true, + 'package_max_length' => 16 * 1024 * 1024, + 'package_length_type' => 'N', + 'package_length_offset' => 0, + 'package_body_offset' => 4, + )); + + $serv->on("WorkerStart", function (Server $serv) use ($pm) { + $pm->wakeup(); + usleep(100000); + }); + + $serv->on(Swoole\Constant::EVENT_CONNECT, function (Server $serv, $fd, $rid) { + $serv->send($fd, 'CONNECT OK'.PHP_EOL); + }); + + $serv->on('receive', function (Server $serv, $fd, $rid, $data) use ($counter_server, $counter_client) { + $counter_server->add(strlen($data)); + if ($counter_server->get() == $counter_client->get()) { + $serv->send($fd, "DONE\n"); + } + }); + + $serv->start(); +}; + +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +DONE From 48498a4d2dcdbbcdb2f53bd154c7b8c426718525 Mon Sep 17 00:00:00 2001 From: codinghuang <2812240764@qq.com> Date: Mon, 11 Jan 2021 18:36:31 +0800 Subject: [PATCH 012/936] Update version for Swoole 4.6.1 (#3996) --- CMakeLists.txt | 2 +- ext-src/php_swoole_library.h | 31 +++++++++++++------ include/swoole_version.h | 6 ++-- package.xml | 60 ++++++++---------------------------- 4 files changed, 38 insertions(+), 61 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b5103180b3..b3c8b5648f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ PROJECT(libswoole) ENABLE_LANGUAGE(ASM) -SET(SWOOLE_VERSION 4.6.0) +SET(SWOOLE_VERSION 4.6.1) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g") diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index aebfcfb800a..dda61e633e2 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: f1ce9bcc9b378dc1d233b63cf4acaf854d0ec744 */ +/* $Id: 59f277126e24cdce28e80f0f45070b9df857add2 */ static const char* swoole_library_source_constants = "\n" @@ -3988,9 +3988,20 @@ static const char* swoole_library_source_core_curl_handler = " * Http Proxy\n" " */\n" " if ($this->proxy) {\n" - " $proxy = explode(':', $this->proxy);\n" - " $proxyPort = $proxy[1] ?? $this->proxyPort;\n" - " $proxy = $proxy[0];\n" + " $parse = parse_url($this->proxy);\n" + " $proxy = $parse['host'] ?? $parse['path'];\n" + " $proxyPort = $parse['port'] ?? $this->proxyPort;\n" + " $proxyUsername = $parse['user'] ?? $this->proxyUsername;\n" + " $proxyPassword = $parse['pass'] ?? $this->proxyPassword;\n" + " $proxyType = $parse['scheme'] ?? $this->proxyType;\n" + " if (is_string($proxyType)) {\n" + " if ($proxyType === 'socks5') {\n" + " $proxyType = CURLPROXY_SOCKS5;\n" + " } else {\n" + " $proxyType = CURLPROXY_HTTP;\n" + " }\n" + " }\n" + "\n" " if (!filter_var($proxy, FILTER_VALIDATE_IP)) {\n" " $ip = Swoole\\Coroutine::gethostbyname($proxy, AF_INET, $this->clientOptions['connect_timeout'] ?? -1);\n" " if (!$ip) {\n" @@ -3999,25 +4010,25 @@ static const char* swoole_library_source_core_curl_handler = " }\n" " $this->proxy = $proxy = $ip;\n" " }\n" - " switch ($this->proxyType) {\n" + " switch ($proxyType) {\n" " case CURLPROXY_HTTP:\n" " $proxyOptions = [\n" " 'http_proxy_host' => $proxy,\n" " 'http_proxy_port' => $proxyPort,\n" - " 'http_proxy_username' => $this->proxyUsername,\n" - " 'http_proxy_password' => $this->proxyPassword,\n" + " 'http_proxy_username' => $proxyUsername,\n" + " 'http_proxy_password' => $proxyPassword,\n" " ];\n" " break;\n" " case CURLPROXY_SOCKS5:\n" " $proxyOptions = [\n" " 'socks5_host' => $proxy,\n" " 'socks5_port' => $proxyPort,\n" - " 'socks5_username' => $this->proxyUsername,\n" - " 'socks5_password' => $this->proxyPassword,\n" + " 'socks5_username' => $proxyUsername,\n" + " 'socks5_password' => $proxyPassword,\n" " ];\n" " break;\n" " default:\n" - " throw new CurlException(\"Unexpected proxy type [{$this->proxyType}]\");\n" + " throw new CurlException(\"Unexpected proxy type [{$proxyType}]\");\n" " }\n" " }\n" " /*\n" diff --git a/include/swoole_version.h b/include/swoole_version.h index 306154d577f..a5222f47050 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -20,10 +20,10 @@ #define SWOOLE_MAJOR_VERSION 4 #define SWOOLE_MINOR_VERSION 6 -#define SWOOLE_RELEASE_VERSION 0 +#define SWOOLE_RELEASE_VERSION 1 #define SWOOLE_EXTRA_VERSION "" -#define SWOOLE_VERSION "4.6.0" -#define SWOOLE_VERSION_ID 40600 +#define SWOOLE_VERSION "4.6.1" +#define SWOOLE_VERSION_ID 40601 #define SWOOLE_API_VERSION_ID 0x202012a #define SWOOLE_BUG_REPORT \ diff --git a/package.xml b/package.xml index fb2b8053933..85c4ece65fa 100644 --- a/package.xml +++ b/package.xml @@ -42,10 +42,10 @@ shenzhe163@gmail.com yes - 2021-01-06 - + 2021-01-11 + - 4.6.0 + 4.6.1 4.0 @@ -54,58 +54,22 @@ Apache2.0 - Backward compatibility Break - --- - * Removed the maximum limit of session id, never repeat (#3879) (@matyhtf) - * Disabled unsafe function when use Coroutine, including pcntl_fork/pcntl_wait/pcntl_waitpid/pcntl_sigtimedwait (#3880) (@matyhtf) - * Enabled coroutine hook by default (#3903) (@matyhtf) - - Remove - --- - - No longer support PHP-7.1 (swoole/swoole-src@4a963df) (swoole/swoole-src@9de8d9e) (@matyhtf) - - Deprecated - --- - - Marked the Event::rshutdown() as deprecated, please use Coroutine::run instead (#3881) (@matyhtf) - - New APIs - --- - + Supported setPriority/getPriority (#3876) (@matyhtf) - + Supported native-curl hook (#3863) (@matyhtf) (@huanghantao) - + Supported object style callback parameters for Server, off by default (#3888) (@matyhtf) - + Supported ext-sockets hook (#3898) (@matyhtf) - + Supported duplicate header (#3905) (@matyhtf) - + Supported SSL sni (#3908) (@matyhtf) - + Supported hook stdio (#3924) (@matyhtf) - + Supported capture_peer_cert option for stream_socket (#3930) (@matyhtf) - + Added Http\Request::create/parse/isCompleted (#3938) (@matyhtf) - + Added Http\Response::isWritable (swoole/swoole-src@db56827) (@matyhtf) - Enhancement --- - + All time accuracy of Server changed from int to double (#3882) (@matyhtf) - + Added poll EINTR check for swoole_client_select (#3909) (@shiguangqi) - + Added coroutine deadlock detect (#3911) (@matyhtf) - + Supported closing the connection in another process with server base mode (#3916) (@matyhtf) - + Optimized send to worker from master, reduced memory copy (#3910) (@huanghantao) (@matyhtf) + + Added --enable-thread-context option (#3970) (@matyhtf) + + Strict session_id, check the connection activity (#3993) (@matyhtf) + * Optimized CURLOPT_PROXY, support user, pass and scheme (swoole/library#87) (sy-records) Fixed --- - * Pop Coroutine::Channel data when channel is closed (swoole/swoole-src@960431d) (@matyhtf) - * Fixed memory error when use JIT (#3907) (@twose) - * Fixed port->set() dtls compile error (#3947) (@Yurunsoft) - * Fixed connection_list error (#3948) (@sy-records) - * Fixed ssl verify (#3954) (@matyhtf) - * Clear all columns when incr and decr (#3956) (@matyhtf) (@sy-records) - * Fixed failed to compile with LibreSSL 2.7.5 (#3962) (@matyhtf) - * Fixed undefined constant CURLOPT_HEADEROPT and CURLOPT_PROXYHEADER + * Fixed minimal PHP version (#3979) (@remicollet) + * Fixed pecl install missing enable-swoole-json and enable-swoole-curl options (#3980) (@sy-records) + * Fixed openssl thread safety issue (swoole/swoole-src@b516d69) (@matyhtf) + * Fixed enableSSL coredump (#3990) (@huanghantao) Kernel --- - * Ignored SIGPIPE signal by default (swoole/swoole-src@9647678) (@matyhtf) - * Supported running php and c coroutines at same time (swoole/swoole-src@c94bfd8) (@matyhtf) - * Added TEST(coroutine_base, get_elapsed) (#3961) (@luolaifa000) - * Added TEST(coroutine_base, get_init_msec) (#3964) (@luffluo) + * Optimized ipc writev, avoid coredump how event data is null (#3994) (@matyhtf) @@ -856,6 +820,7 @@ + @@ -1715,6 +1680,7 @@ + From 75395e052908e35503cb7dbe1534966d26bf12b6 Mon Sep 17 00:00:00 2001 From: yumancang Date: Wed, 13 Jan 2021 12:57:41 +0800 Subject: [PATCH 013/936] Add swoole_http_server request->getMethod() (#3987) * Add swoole_http_server ->getMethod() * Add swoole_http_server ->getMethod() * Add swoole_http_server ->getMethod() Co-authored-by: yumancang --- ext-src/swoole_http_request.cc | 76 ++++---------------- tests/swoole_http_server/create_request.phpt | 18 +++++ thirdparty/swoole_http_parser.h | 2 +- 3 files changed, 33 insertions(+), 63 deletions(-) diff --git a/ext-src/swoole_http_request.cc b/ext-src/swoole_http_request.cc index c91e487c24e..07746068215 100644 --- a/ext-src/swoole_http_request.cc +++ b/ext-src/swoole_http_request.cc @@ -102,67 +102,8 @@ static inline char *http_trim_double_quote(char *ptr, int *len) { return tmp; } -static sw_inline const char *http_get_method_name(int method) { - switch (method) { - case PHP_HTTP_GET: - return "GET"; - case PHP_HTTP_POST: - return "POST"; - case PHP_HTTP_HEAD: - return "HEAD"; - case PHP_HTTP_PUT: - return "PUT"; - case PHP_HTTP_DELETE: - return "DELETE"; - case PHP_HTTP_PATCH: - return "PATCH"; - case PHP_HTTP_CONNECT: - return "CONNECT"; - case PHP_HTTP_OPTIONS: - return "OPTIONS"; - case PHP_HTTP_TRACE: - return "TRACE"; - case PHP_HTTP_COPY: - return "COPY"; - case PHP_HTTP_LOCK: - return "LOCK"; - case PHP_HTTP_MKCOL: - return "MKCOL"; - case PHP_HTTP_MOVE: - return "MOVE"; - case PHP_HTTP_PROPFIND: - return "PROPFIND"; - case PHP_HTTP_PROPPATCH: - return "PROPPATCH"; - case PHP_HTTP_UNLOCK: - return "UNLOCK"; - /* subversion */ - case PHP_HTTP_REPORT: - return "REPORT"; - case PHP_HTTP_MKACTIVITY: - return "MKACTIVITY"; - case PHP_HTTP_CHECKOUT: - return "CHECKOUT"; - case PHP_HTTP_MERGE: - return "MERGE"; - /* upnp */ - case PHP_HTTP_MSEARCH: - return "MSEARCH"; - case PHP_HTTP_NOTIFY: - return "NOTIFY"; - case PHP_HTTP_SUBSCRIBE: - return "SUBSCRIBE"; - case PHP_HTTP_UNSUBSCRIBE: - return "UNSUBSCRIBE"; - /* proxy */ - case PHP_HTTP_PURGE: - return "PURGE"; - /* unknown */ - case PHP_HTTP_NOT_IMPLEMENTED: - return "UNKNOWN"; - default: - return nullptr; - } +static sw_inline const char *http_get_method_name(enum swoole_http_method method) { + return swoole_http_method_str(method); } // clang-format off @@ -257,6 +198,7 @@ static PHP_METHOD(swoole_http_request, getData); static PHP_METHOD(swoole_http_request, create); static PHP_METHOD(swoole_http_request, parse); static PHP_METHOD(swoole_http_request, isCompleted); +static PHP_METHOD(swoole_http_request, getMethod); static PHP_METHOD(swoole_http_request, rawContent); static PHP_METHOD(swoole_http_request, __destruct); SW_EXTERN_C_END @@ -281,6 +223,7 @@ const zend_function_entry swoole_http_request_methods[] = PHP_ME(swoole_http_request, create, arginfo_swoole_http_create, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(swoole_http_request, parse, arginfo_swoole_http_parse, ZEND_ACC_PUBLIC) PHP_ME(swoole_http_request, isCompleted, arginfo_swoole_http_void, ZEND_ACC_PUBLIC) + PHP_ME(swoole_http_request, getMethod, arginfo_swoole_http_void, ZEND_ACC_PUBLIC) PHP_ME(swoole_http_request, __destruct, arginfo_swoole_http_void, ZEND_ACC_PUBLIC) PHP_FE_END }; @@ -531,7 +474,7 @@ static int http_request_on_headers_complete(swoole_http_parser *parser) { ctx->keepalive = swoole_http_should_keep_alive(parser); - add_assoc_string(zserver, "request_method", (char *) http_get_method_name(parser->method)); + add_assoc_string(zserver, "request_method", http_get_method_name(parser->method)); add_assoc_stringl_ex(zserver, ZEND_STRL("request_uri"), ctx->request.path, ctx->request.path_len); // path_info should be decoded zend_string *zstr_path = zend_string_init(ctx->request.path, ctx->request.path_len, 0); @@ -1040,6 +983,15 @@ static PHP_METHOD(swoole_http_request, parse) { RETURN_LONG(swoole_http_requset_parse(ctx, str, l_str)); } +static PHP_METHOD(swoole_http_request, getMethod) { + http_context *ctx = php_swoole_http_request_get_and_check_context(ZEND_THIS); + if (UNEXPECTED(!ctx)) { + RETURN_FALSE; + } + const char *method = http_get_method_name((ctx->parser).method); + RETURN_STRING(method); +} + static PHP_METHOD(swoole_http_request, isCompleted) { http_context *ctx = php_swoole_http_request_get_and_check_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { diff --git a/tests/swoole_http_server/create_request.phpt b/tests/swoole_http_server/create_request.phpt index 0799b12dedf..9b3e4c17bf0 100644 --- a/tests/swoole_http_server/create_request.phpt +++ b/tests/swoole_http_server/create_request.phpt @@ -38,6 +38,8 @@ Assert::eq($req->parse("\r\n"), 2); Assert::true($req->isCompleted()); Assert::false($req->parse('error data')); +Assert::eq("GET", $req->getMethod()); + Assert::greaterThan(count($req->header), 4); Assert::eq(count($req->cookie), 3); @@ -47,5 +49,21 @@ $req2 = Request::create(['parse_cookie' => false]); Assert::eq($req2->parse($data . "\r\n"), strlen($data) + 2); Assert::null($req2->cookie); +$data = "POST /index.html?hello=world&test=2123 HTTP/1.1\r\n"; +$data .= "Host: 127.0.0.1\r\n"; +$data .= "Connection: keep-alive\r\n"; +$data .= "Pragma: no-cache\r\n"; +$data .= "Cache-Control: no-cache\r\n"; +$data .= "Upgrade-Insecure-Requests: \r\n"; +$data .= "User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36\r\n"; +$data .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\n"; +$data .= "Accept-Encoding: gzip, deflate, br\r\n"; +$data .= "Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7,ja;q=0.6\r\n"; +$data .= "Cookie: env=pretest; phpsessid=fcccs2af8673a2f343a61a96551c8523d79ea; username=hantianfeng\r\n"; + +$req3 = Request::create(); +$req3->parse($data); +Assert::eq("POST", $req3->getMethod()); + ?> --EXPECT-- diff --git a/thirdparty/swoole_http_parser.h b/thirdparty/swoole_http_parser.h index 6107cf68d8d..f87bca5a823 100644 --- a/thirdparty/swoole_http_parser.h +++ b/thirdparty/swoole_http_parser.h @@ -187,7 +187,7 @@ struct swoole_http_parser { unsigned short http_major; unsigned short http_minor; unsigned short status_code; /* responses only */ - unsigned char method; /* requests only */ + enum swoole_http_method method; /* requests only */ /* 1 = Upgrade header was present and the parser has exited because of that. * 0 = No upgrade header present. From 6475e296697073d59903b7beda4c8109b2a433e4 Mon Sep 17 00:00:00 2001 From: codinghuang Date: Thu, 14 Jan 2021 22:41:58 +0800 Subject: [PATCH 014/936] Fix coroutine::defer coredump in php8 (#3997) * Fix coroutine::defer coredump in php8 when not return value * Add PHP_VERSION_ID for build --- ext-src/swoole_coroutine.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ext-src/swoole_coroutine.cc b/ext-src/swoole_coroutine.cc index 56fcad22989..f2aae6a7bed 100644 --- a/ext-src/swoole_coroutine.cc +++ b/ext-src/swoole_coroutine.cc @@ -737,8 +737,16 @@ void PHPCoroutine::main_func(void *arg) { while (!tasks->empty()) { zend::Function *defer_fci = tasks->top(); tasks->pop(); +#if PHP_VERSION_ID < 80000 defer_fci->fci.param_count = 1; defer_fci->fci.params = retval; +#else + if (Z_TYPE_P(retval) != IS_UNDEF) { + defer_fci->fci.param_count = 1; + defer_fci->fci.params = retval; + } +#endif + if (UNEXPECTED(sw_zend_call_function_anyway(&defer_fci->fci, &defer_fci->fci_cache) != SUCCESS)) { php_swoole_fatal_error(E_WARNING, "defer callback handler error"); } From 00915ac99396d12a1c939839b7214bdc00f31e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Sun, 17 Jan 2021 08:40:16 +0800 Subject: [PATCH 015/936] Fix #4001 (#4002) * Coroutine socket supports async write * fix * add core tests, fix trace log * fix tests, add test for co-socket::async_write * fix tests * fix 4 * revert * hook stdio, fix tests * refactor stdio hook * optimize tests --- core-tests/include/test_core.h | 2 + core-tests/src/coroutine/hook.cpp | 71 +++++++++++++++++++- core-tests/src/reactor/base.cpp | 21 ++++++ ext-src/php_swoole_coroutine.h | 1 + ext-src/swoole_runtime.cc | 11 ++- include/swoole_api.h | 1 + include/swoole_coroutine_c_api.h | 12 ++++ include/swoole_coroutine_socket.h | 2 - include/swoole_file_hook.h | 10 +++ include/swoole_socket.h | 24 ++++--- src/coroutine/hook.cc | 90 +++++++++++++++++++++++++ src/network/client.cc | 8 +-- src/reactor/base.cc | 2 +- src/reactor/epoll.cc | 4 +- src/server/worker.cc | 6 +- src/wrapper/event.cc | 11 +++ thirdparty/php/streams/plain_wrapper.c | 92 +++++++++----------------- 17 files changed, 280 insertions(+), 88 deletions(-) diff --git a/core-tests/include/test_core.h b/core-tests/include/test_core.h index 3e907a7c573..370d7ea7304 100644 --- a/core-tests/include/test_core.h +++ b/core-tests/include/test_core.h @@ -22,6 +22,8 @@ #define TEST_JPG_FILE "/examples/test.jpg" #define TEST_JPG_MD5SUM "64a42b4c0f3c65a14c23b60d3880a917" +#define ASSERT_MEMEQ(x,y,n) ASSERT_EQ(memcmp((x), (y), n), 0) + namespace swoole { namespace test { const std::string &get_root_path(); std::string get_jpg_file(); diff --git a/core-tests/src/coroutine/hook.cpp b/core-tests/src/coroutine/hook.cpp index 1f39e1b8e73..83d49119bb7 100644 --- a/core-tests/src/coroutine/hook.cpp +++ b/core-tests/src/coroutine/hook.cpp @@ -22,6 +22,7 @@ #include "swoole_util.h" using swoole::Coroutine; +using swoole::String; using swoole::coroutine::System; using swoole::test::coroutine; @@ -214,7 +215,7 @@ TEST(coroutine_hook, flock) { } TEST(coroutine_hook, read_dir) { - coroutine::run([](void *arg) { + auto fn = []() { auto fp = swoole_coroutine_opendir("/tmp"); ASSERT_NE(fp, nullptr); struct dirent *entry; @@ -228,11 +229,16 @@ TEST(coroutine_hook, read_dir) { ASSERT_STREQ(entry->d_name, ".."); swoole_coroutine_closedir(fp); + }; + + coroutine::run([&](void *arg) { + fn(); }); + fn(); } TEST(coroutine_hook, readlink) { - coroutine::run([](void *arg) { + auto fn = []() { char buf1[1024] = {}; char buf2[1024] = {}; @@ -241,6 +247,67 @@ TEST(coroutine_hook, readlink) { getcwd(buf2, sizeof(buf2)); ASSERT_STREQ(buf1, buf2); + }; + + coroutine::run([&](void *arg) { + fn(); }); + fn(); } +TEST(coroutine_hook, stdio_1) { + auto fn = []() { + FILE *fp1 = swoole_coroutine_fopen(test_file, "w+"); + const char *str = "hello world"; + int n = swoole_coroutine_fputs(str, fp1); + ASSERT_TRUE(n); + swoole_coroutine_fclose(fp1); + + FILE *fp2 = swoole_coroutine_fopen(test_file, "r+"); + char buf[1024]; + char *str2 = swoole_coroutine_fgets(buf, sizeof(buf), fp2); + + ASSERT_STREQ(str2, str); + swoole_coroutine_fclose(fp2); + + unlink(test_file); + }; + + coroutine::run([&](void *arg) { + fn(); + }); + fn(); +} + +TEST(coroutine_hook, stdio_2) { + auto fn = []() { + size_t size = 1024; + + FILE *fp1 = swoole_coroutine_fopen(test_file, "w+"); + String str(size); + str.append_random_bytes(size); + size_t n = swoole_coroutine_fwrite(str.str, 1, size, fp1); + ASSERT_EQ(n, size); + swoole_coroutine_fclose(fp1); + + FILE *fp2 = swoole_coroutine_fopen(test_file, "r+"); + char buf[size]; + size_t len = swoole_coroutine_fread(buf, 1, size, fp2); + ASSERT_EQ(len, size); + + len = swoole_coroutine_fread(buf, 1, size, fp2); + ASSERT_EQ(len, 0); + + ASSERT_TRUE(swoole_coroutine_feof(fp2)); + + ASSERT_MEMEQ(buf, str.str, size); + swoole_coroutine_fclose(fp2); + + unlink(test_file); + }; + + coroutine::run([&](void *arg) { + fn(); + }); + fn(); +} diff --git a/core-tests/src/reactor/base.cpp b/core-tests/src/reactor/base.cpp index a27dc161813..5147703adfb 100644 --- a/core-tests/src/reactor/base.cpp +++ b/core-tests/src/reactor/base.cpp @@ -173,3 +173,24 @@ TEST(reactor, select) { reactor.wait_exit = true; reactor_test_func(&reactor); } + +TEST(reactor, add_or_update) { + int ret; + UnixSocket p(true, SOCK_DGRAM); + ASSERT_TRUE(p.ready()); + + ret = swoole_event_init(SW_EVENTLOOP_WAIT_EXIT); + ASSERT_EQ(ret, SW_OK); + ASSERT_NE(SwooleTG.reactor, nullptr); + + ret = swoole_event_add_or_update(p.get_socket(false), SW_EVENT_READ); + ASSERT_EQ(ret, SW_OK); + ASSERT_TRUE(p.get_socket(false)->events & SW_EVENT_READ); + + ret = swoole_event_add_or_update(p.get_socket(false), SW_EVENT_WRITE); + ASSERT_EQ(ret, SW_OK); + ASSERT_TRUE(p.get_socket(false)->events & SW_EVENT_READ); + ASSERT_TRUE(p.get_socket(false)->events & SW_EVENT_WRITE); + + swoole_event_free(); +} diff --git a/ext-src/php_swoole_coroutine.h b/ext-src/php_swoole_coroutine.h index b75065dec7f..de6fc1b6b28 100644 --- a/ext-src/php_swoole_coroutine.h +++ b/ext-src/php_swoole_coroutine.h @@ -117,6 +117,7 @@ class PHPCoroutine { HOOK_NATIVE_CURL = 1u << 12, HOOK_BLOCKING_FUNCTION = 1u << 13, HOOK_SOCKETS = 1u << 14, + HOOK_STDIO = 1u << 15, #ifdef SW_USE_CURL HOOK_ALL = 0x7fffffff ^ HOOK_CURL, #else diff --git a/ext-src/swoole_runtime.cc b/ext-src/swoole_runtime.cc index a899c48c499..d4958b4e5a3 100644 --- a/ext-src/swoole_runtime.cc +++ b/ext-src/swoole_runtime.cc @@ -176,6 +176,7 @@ void php_swoole_runtime_minit(int module_number) { SW_REGISTER_LONG_CONSTANT("SWOOLE_HOOK_STREAM_FUNCTION", PHPCoroutine::HOOK_STREAM_FUNCTION); SW_REGISTER_LONG_CONSTANT("SWOOLE_HOOK_STREAM_SELECT", PHPCoroutine::HOOK_STREAM_FUNCTION); // backward compatibility SW_REGISTER_LONG_CONSTANT("SWOOLE_HOOK_FILE", PHPCoroutine::HOOK_FILE); + SW_REGISTER_LONG_CONSTANT("SWOOLE_HOOK_STDIO", PHPCoroutine::HOOK_STDIO); SW_REGISTER_LONG_CONSTANT("SWOOLE_HOOK_SLEEP", PHPCoroutine::HOOK_SLEEP); SW_REGISTER_LONG_CONSTANT("SWOOLE_HOOK_PROC", PHPCoroutine::HOOK_PROC); SW_REGISTER_LONG_CONSTANT("SWOOLE_HOOK_CURL", PHPCoroutine::HOOK_CURL); @@ -1259,11 +1260,19 @@ bool PHPCoroutine::enable_hook(uint32_t flags) { if (flags & PHPCoroutine::HOOK_FILE) { if (!(runtime_hook_flags & PHPCoroutine::HOOK_FILE)) { memcpy((void *) &php_plain_files_wrapper, &sw_php_plain_files_wrapper, sizeof(php_plain_files_wrapper)); - memcpy((void *) &php_stream_stdio_ops, &sw_php_stream_stdio_ops, sizeof(php_stream_stdio_ops)); } } else { if (runtime_hook_flags & PHPCoroutine::HOOK_FILE) { memcpy((void *) &php_plain_files_wrapper, &ori_php_plain_files_wrapper, sizeof(php_plain_files_wrapper)); + } + } + // stdio + if (flags & PHPCoroutine::HOOK_STDIO) { + if (!(runtime_hook_flags & PHPCoroutine::HOOK_STDIO)) { + memcpy((void *) &php_stream_stdio_ops, &sw_php_stream_stdio_ops, sizeof(php_stream_stdio_ops)); + } + } else { + if (runtime_hook_flags & PHPCoroutine::HOOK_STDIO) { memcpy((void *) &php_stream_stdio_ops, &ori_php_stream_stdio_ops, sizeof(php_stream_stdio_ops)); } } diff --git a/include/swoole_api.h b/include/swoole_api.h index a71b87c355f..60bad3d0cef 100644 --- a/include/swoole_api.h +++ b/include/swoole_api.h @@ -40,6 +40,7 @@ SW_API int swoole_timer_select(); SW_API int swoole_event_init(int flags); SW_API int swoole_event_add(swoole::network::Socket *socket, int events); SW_API int swoole_event_set(swoole::network::Socket *socket, int events); +SW_API int swoole_event_add_or_update(swoole::network::Socket *socket, int event); SW_API int swoole_event_del(swoole::network::Socket *socket); SW_API void swoole_event_defer(swoole::Callback cb, void *private_data); SW_API ssize_t swoole_event_write(swoole::network::Socket *socket, const void *data, size_t len); diff --git a/include/swoole_coroutine_c_api.h b/include/swoole_coroutine_c_api.h index c05e8eb61e5..f96fcf02f05 100644 --- a/include/swoole_coroutine_c_api.h +++ b/include/swoole_coroutine_c_api.h @@ -55,6 +55,18 @@ int swoole_coroutine_rename(const char *oldpath, const char *newpath); int swoole_coroutine_flock(int fd, int operation); int swoole_coroutine_flock_ex(const char *filename, int fd, int operation); int swoole_coroutine_statvfs(const char *path, struct statvfs *buf); +/** + * stdio + */ +FILE *swoole_coroutine_fopen(const char *pathname, const char *mode); +FILE *swoole_coroutine_fdopen(int fd, const char *mode); +FILE *swoole_coroutine_freopen(const char *pathname, const char *mode, FILE *stream); +size_t swoole_coroutine_fread(void *ptr, size_t size, size_t nmemb, FILE *stream); +size_t swoole_coroutine_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); +char *swoole_coroutine_fgets(char *s, int size, FILE *stream); +int swoole_coroutine_fputs(const char *s, FILE *stream); +int swoole_coroutine_feof(FILE *stream); +int swoole_coroutine_fclose(FILE *stream); /** * dir */ diff --git a/include/swoole_coroutine_socket.h b/include/swoole_coroutine_socket.h index 925489b6df6..c5d49126857 100644 --- a/include/swoole_coroutine_socket.h +++ b/include/swoole_coroutine_socket.h @@ -192,8 +192,6 @@ class Socket { return socket->info.get_port(); } - - inline bool has_bound(const enum swEvent_type event = SW_EVENT_RDWR) { return get_bound_co(event) != nullptr; } diff --git a/include/swoole_file_hook.h b/include/swoole_file_hook.h index 5c097e6637c..07a971f72ef 100644 --- a/include/swoole_file_hook.h +++ b/include/swoole_file_hook.h @@ -31,6 +31,16 @@ #define rmdir(pathname) swoole_coroutine_rmdir(pathname) #define rename(oldpath, newpath) swoole_coroutine_rename(oldpath, newpath) +#define fopen(pathname, mode) swoole_coroutine_fopen(pathname, mode) +#define fdopen(fd, mode) swoole_coroutine_fdopen(fd, mode) +#define freopen(pathname, mode, stream) swoole_coroutine_freopen(pathname, mode, stream) +#define fread(ptr, size, nmemb, stream) swoole_coroutine_fread(ptr, size, nmemb, stream) +#define fwrite(ptr, size, nmemb, stream) swoole_coroutine_fwrite(ptr, size, nmemb, stream) +#define fgets(s, size, stream) swoole_coroutine_fgets(s, size, stream) +#define fputs(s, stream) swoole_coroutine_fputs(s, stream) +#define feof(stream) swoole_coroutine_feof(stream) +#define fclose(stream) swoole_coroutine_fclose(stream) + #define opendir(name) swoole_coroutine_opendir(name) #define readdir(dir) swoole_coroutine_readdir(dir) #define closedir(dir) swoole_coroutine_closedir(dir) diff --git a/include/swoole_socket.h b/include/swoole_socket.h index d9c78ca5c10..a2042a8a055 100644 --- a/include/swoole_socket.h +++ b/include/swoole_socket.h @@ -122,6 +122,14 @@ struct IOVector { return iov_iterator; } + size_t length() { + size_t len = 0; + SW_LOOP_N(count) { + len += iov[i].iov_len; + } + return len; + } + inline int get_remain_count() { return remain_count; } @@ -173,9 +181,7 @@ struct Socket { uchar recv_wait : 1; uchar event_hup : 1; - /** - * memory buffer size; - */ + // memory buffer size [user space] uint32_t buffer_size; uint32_t chunk_size; @@ -203,14 +209,14 @@ struct Socket { size_t total_recv_bytes; size_t total_send_bytes; - /** - * for reactor - */ + // for reactor int handle_send(); int handle_sendfile(); - /** - * socket option - */ + // user space memory buffer + void set_memory_buffer_size(uint32_t _buffer_size) { + buffer_size = _buffer_size; + } + // socket option [kernel buffer] bool set_buffer_size(uint32_t _buffer_size); bool set_recv_buffer_size(uint32_t _buffer_size); bool set_send_buffer_size(uint32_t _buffer_size); diff --git a/src/coroutine/hook.cc b/src/coroutine/hook.cc index 590b1e5ce32..dde942ec886 100644 --- a/src/coroutine/hook.cc +++ b/src/coroutine/hook.cc @@ -330,6 +330,96 @@ int swoole_coroutine_access(const char *pathname, int mode) { return retval; } +FILE *swoole_coroutine_fopen(const char *pathname, const char *mode) { + if (sw_unlikely(is_no_coro())) { + return fopen(pathname, mode); + } + + FILE *retval = nullptr; + swoole::coroutine::async([&]() { retval = fopen(pathname, mode); }); + return retval; +} + +FILE *swoole_coroutine_fdopen(int fd, const char *mode) { + if (sw_unlikely(is_no_coro())) { + return fdopen(fd, mode); + } + + FILE *retval = nullptr; + swoole::coroutine::async([&]() { retval = fdopen(fd, mode); }); + return retval; +} + +FILE *swoole_coroutine_freopen(const char *pathname, const char *mode, FILE *stream) { + if (sw_unlikely(is_no_coro())) { + return freopen(pathname, mode, stream); + } + + FILE *retval = nullptr; + swoole::coroutine::async([&]() { retval = freopen(pathname, mode, stream); }); + return retval; +} + +size_t swoole_coroutine_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) { + if (sw_unlikely(is_no_coro())) { + return fread(ptr, size, nmemb, stream); + } + + size_t retval = 0; + swoole::coroutine::async([&]() { retval = fread(ptr, size, nmemb, stream); }); + return retval; +} + +size_t swoole_coroutine_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) { + if (sw_unlikely(is_no_coro())) { + return fwrite(ptr, size, nmemb, stream); + } + + size_t retval = 0; + swoole::coroutine::async([&]() { retval = fwrite(ptr, size, nmemb, stream); }); + return retval; +} + +char *swoole_coroutine_fgets(char *s, int size, FILE *stream) { + if (sw_unlikely(is_no_coro())) { + return fgets(s, size, stream); + } + + char *retval = nullptr; + swoole::coroutine::async([&]() { retval = fgets(s, size, stream); }); + return retval; +} + +int swoole_coroutine_fputs(const char *s, FILE *stream) { + if (sw_unlikely(is_no_coro())) { + return fputs(s, stream); + } + + int retval = -1; + swoole::coroutine::async([&]() { retval = fputs(s, stream); }); + return retval; +} + +int swoole_coroutine_feof(FILE *stream) { + if (sw_unlikely(is_no_coro())) { + return feof(stream); + } + + int retval = -1; + swoole::coroutine::async([&]() { retval = feof(stream); }); + return retval; +} + +int swoole_coroutine_fclose(FILE *stream) { + if (sw_unlikely(is_no_coro())) { + return fclose(stream); + } + + int retval = -1; + swoole::coroutine::async([&]() { retval = fclose(stream); }); + return retval; +} + int swoole_coroutine_flock(int fd, int operation) { if (sw_unlikely(is_no_coro())) { return flock(fd, operation); diff --git a/src/network/client.cc b/src/network/client.cc index f98f442e47a..d2bc97e3bfa 100644 --- a/src/network/client.cc +++ b/src/network/client.cc @@ -718,12 +718,8 @@ static int Client_tcp_sendfile_async(Client *cli, const char *filename, off_t of swoole_set_last_error(errno); return SW_ERR; } - if (!(cli->socket->events & SW_EVENT_WRITE)) { - if (cli->socket->events & SW_EVENT_READ) { - return swoole_event_set(cli->socket, SW_EVENT_READ | SW_EVENT_WRITE); - } else { - return swoole_event_add(cli->socket, SW_EVENT_WRITE); - } + if (swoole_event_add_or_update(cli->socket, SW_EVENT_WRITE) == SW_ERR) { + return SW_ERR; } return SW_OK; } diff --git a/src/reactor/base.cc b/src/reactor/base.cc index ea44d8b6792..935bff51c00 100644 --- a/src/reactor/base.cc +++ b/src/reactor/base.cc @@ -231,7 +231,7 @@ static int write_func( int fd = socket->fd; if (socket->buffer_size == 0) { - socket->buffer_size = Socket::default_buffer_size; + socket->set_memory_buffer_size(Socket::default_buffer_size); } if (socket->nonblock == 0) { diff --git a/src/reactor/epoll.cc b/src/reactor/epoll.cc index 8a5b77bdf88..cbd7f9a0add 100644 --- a/src/reactor/epoll.cc +++ b/src/reactor/epoll.cc @@ -122,7 +122,7 @@ int ReactorEpoll::add(Socket *socket, int events) { reactor_->_add(socket, events); swTraceLog( - SW_TRACE_EVENT, "add events[fd=%d#%d, type=%d, events=%d]", socket->fd, reactor_->id, socket->fd_type, events_); + SW_TRACE_EVENT, "add events[fd=%d#%d, type=%d, events=%d]", socket->fd, reactor_->id, socket->fd_type, events); return SW_OK; } @@ -165,7 +165,7 @@ int ReactorEpoll::set(Socket *socket, int events) { return SW_ERR; } - swTraceLog(SW_TRACE_EVENT, "set event[reactor_id=%d, fd=%d, events=%d]", reactor_->id, socket->fd, events_); + swTraceLog(SW_TRACE_EVENT, "set event[reactor_id=%d, fd=%d, events=%d]", reactor_->id, socket->fd, events); reactor_->_set(socket, events); return SW_OK; diff --git a/src/server/worker.cc b/src/server/worker.cc index 774b02d2eb8..5c13b9d7b72 100644 --- a/src/server/worker.cc +++ b/src/server/worker.cc @@ -597,8 +597,8 @@ int Server::start_event_worker(Worker *worker) { */ ssize_t Server::send_to_reactor_thread(const EventData *ev_data, size_t sendn, SessionId session_id) { Socket *pipe_sock = get_reactor_thread_pipe(session_id, ev_data->info.reactor_id); - if (SwooleTG.reactor) { - return SwooleTG.reactor->write(SwooleTG.reactor, pipe_sock, ev_data, sendn); + if (swoole_event_is_available()) { + return swoole_event_write(pipe_sock, ev_data, sendn); } else { return pipe_sock->send_blocking(ev_data, sendn); } @@ -606,7 +606,7 @@ ssize_t Server::send_to_reactor_thread(const EventData *ev_data, size_t sendn, S ssize_t Server::send_to_reactor_thread(const DataHead *head, const iovec *iov, size_t iovcnt, SessionId session_id) { Socket *pipe_sock = get_reactor_thread_pipe(session_id, head->reactor_id); - if (SwooleTG.reactor) { + if (swoole_event_is_available()) { return swoole_event_writev(pipe_sock, iov, iovcnt); } else { return pipe_sock->writev_blocking(iov, iovcnt); diff --git a/src/wrapper/event.cc b/src/wrapper/event.cc index 31b8e699295..c7c12988543 100644 --- a/src/wrapper/event.cc +++ b/src/wrapper/event.cc @@ -66,6 +66,17 @@ int swoole_event_add(Socket *socket, int events) { return SwooleTG.reactor->add(socket, events); } +int swoole_event_add_or_update(swoole::network::Socket *_socket, int event) { + if (event == SW_EVENT_READ) { + return SwooleTG.reactor->add_read_event(_socket); + } else if (event == SW_EVENT_WRITE) { + return SwooleTG.reactor->add_write_event(_socket); + } else { + assert(0); + return SW_ERR; + } +} + int swoole_event_set(Socket *socket, int events) { return SwooleTG.reactor->set(socket, events); } diff --git a/thirdparty/php/streams/plain_wrapper.c b/thirdparty/php/streams/plain_wrapper.c index e9d38192d59..eba33611043 100644 --- a/thirdparty/php/streams/plain_wrapper.c +++ b/thirdparty/php/streams/plain_wrapper.c @@ -59,13 +59,8 @@ extern int php_get_gid_by_name(const char *name, gid_t *gid); # define PLAIN_WRAP_BUF_SIZE(st) (st) #endif -#if PHP_VERSION_ID < 70400 -static size_t sw_php_stdiop_write(php_stream *stream, const char *buf, size_t count); -static size_t sw_php_stdiop_read(php_stream *stream, char *buf, size_t count); -#else -static ssize_t sw_php_stdiop_write(php_stream *stream, const char *buf, size_t count); -static ssize_t sw_php_stdiop_read(php_stream *stream, char *buf, size_t count); -#endif +static php_stream_size_t sw_php_stdiop_write(php_stream *stream, const char *buf, size_t count); +static php_stream_size_t sw_php_stdiop_read(php_stream *stream, char *buf, size_t count); static int sw_php_stdiop_close(php_stream *stream, int close_handle); static int sw_php_stdiop_stat(php_stream *stream, php_stream_statbuf *ssb); static int sw_php_stdiop_flush(php_stream *stream); @@ -227,81 +222,54 @@ static php_stream *_sw_php_stream_fopen_from_fd_int(int fd, const char *mode, co return php_stream_alloc_rel(&sw_php_stream_stdio_ops, self, persistent_id, mode); } -#if PHP_VERSION_ID < 70400 -static size_t sw_php_stdiop_write(php_stream *stream, const char *buf, size_t count) -#else -static ssize_t sw_php_stdiop_write(php_stream *stream, const char *buf, size_t count) -#endif -{ +static php_stream_size_t sw_php_stdiop_write(php_stream *stream, const char *buf, size_t count) { php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract; assert(data != NULL); if (data->fd >= 0) { - if (file_can_poll(&data->sb)) { - if (!swoole_coroutine_socket_exists(data->fd) && swoole_coroutine_socket_create(data->fd) < 0) { - stream->eof = 1; - return -1; - } - return swoole_coroutine_write(data->fd, buf, count); - } else { - int bytes_written = write(data->fd, buf, count); + ssize_t bytes_written = write(data->fd, buf, count); #if PHP_VERSION_ID < 70400 - if (bytes_written < 0) - { - return 0; - } - return (size_t) bytes_written; + if (bytes_written < 0) { + return 0; + } + return (size_t) bytes_written; #else - return bytes_written; + return bytes_written; #endif - } - } else { return fwrite(buf, 1, count, data->file); } } -#if PHP_VERSION_ID < 70400 -static size_t sw_php_stdiop_read(php_stream *stream, char *buf, size_t count) -#else -static ssize_t sw_php_stdiop_read(php_stream *stream, char *buf, size_t count) -#endif -{ +static php_stream_size_t sw_php_stdiop_read(php_stream *stream, char *buf, size_t count) { php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract; - size_t ret; assert(data != NULL); - if (data->fd >= 0) - { - if (file_can_poll(&data->sb)) { - if (!swoole_coroutine_socket_exists(data->fd) && swoole_coroutine_socket_create(data->fd) < 0) { - stream->eof = 1; - return -1; - } - return swoole_coroutine_read(data->fd, buf, PLAIN_WRAP_BUF_SIZE(count)); - } - // file - else { - ret = read(data->fd, buf, PLAIN_WRAP_BUF_SIZE(count)); - - if (ret == (size_t) -1 && errno == EINTR) { - /* Read was interrupted, retry once, - If read still fails, giveup with feof==0 - so script can retry if desired */ - ret = read(data->fd, buf, PLAIN_WRAP_BUF_SIZE(count)); - } - stream->eof = - (ret == 0 || (ret == (size_t) -1 && errno != EWOULDBLOCK && errno != EINTR && errno != EBADF)); - } + if (data->fd >= 0) { + ssize_t ret = read(data->fd, buf, PLAIN_WRAP_BUF_SIZE(count)); + if (ret == -1 && errno == EINTR) { + /* Read was interrupted, retry once, + If read still fails, giveup with feof==0 + so script can retry if desired */ + ret = read(data->fd, buf, PLAIN_WRAP_BUF_SIZE(count)); + } + stream->eof = (ret == 0 || (ret == -1 && errno != EWOULDBLOCK && errno != EINTR && errno != EBADF)); +#if PHP_VERSION_ID < 70400 + if (ret < 0) { + return 0; + } + return (size_t) ret; +#else + return ret; +#endif } - else - { - ret = fread(buf, 1, count, data->file); + else { + size_t ret = fread(buf, 1, count, data->file); stream->eof = feof(data->file); + return ret; } - return ret; } static int sw_php_stdiop_close(php_stream *stream, int close_handle) From 9e2568f840c92efcfefd55817e0332e5f7f6d991 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Sun, 17 Jan 2021 08:58:31 +0800 Subject: [PATCH 016/936] code format --- thirdparty/php/streams/plain_wrapper.c | 1613 +++++++++++------------- 1 file changed, 766 insertions(+), 847 deletions(-) diff --git a/thirdparty/php/streams/plain_wrapper.c b/thirdparty/php/streams/plain_wrapper.c index eba33611043..4be72ac6ed8 100644 --- a/thirdparty/php/streams/plain_wrapper.c +++ b/thirdparty/php/streams/plain_wrapper.c @@ -40,10 +40,10 @@ #include "thirdparty/php/streams/php_streams_int.h" #ifdef PHP_WIN32 -# include "win32/winutil.h" -# include "win32/time.h" -# include "win32/ioutil.h" -# include "win32/readdir.h" +#include "win32/winutil.h" +#include "win32/time.h" +#include "win32/ioutil.h" +#include "win32/readdir.h" #endif #include "swoole_file_hook.h" @@ -54,9 +54,9 @@ extern int php_get_gid_by_name(const char *name, gid_t *gid); #endif #if defined(PHP_WIN32) -# define PLAIN_WRAP_BUF_SIZE(st) (((st) > UINT_MAX) ? UINT_MAX : (unsigned int)(st)) +#define PLAIN_WRAP_BUF_SIZE(st) (((st) > UINT_MAX) ? UINT_MAX : (unsigned int) (st)) #else -# define PLAIN_WRAP_BUF_SIZE(st) (st) +#define PLAIN_WRAP_BUF_SIZE(st) (st) #endif static php_stream_size_t sw_php_stdiop_write(php_stream *stream, const char *buf, size_t count); @@ -76,12 +76,10 @@ static inline zend_bool file_can_poll(zend_stat_t *_stat) { return S_ISCHR(_stat->st_mode) || S_ISSOCK(_stat->st_mode) || S_ISFIFO(_stat->st_mode); } -static int sw_php_stream_parse_fopen_modes(const char *mode, int *open_flags) -{ +static int sw_php_stream_parse_fopen_modes(const char *mode, int *open_flags) { int flags; - switch (mode[0]) - { + switch (mode[0]) { case 'r': flags = 0; break; @@ -102,40 +100,30 @@ static int sw_php_stream_parse_fopen_modes(const char *mode, int *open_flags) return FAILURE; } - if (strchr(mode, '+')) - { + if (strchr(mode, '+')) { flags |= O_RDWR; - } - else if (flags) - { + } else if (flags) { flags |= O_WRONLY; - } - else - { + } else { flags |= O_RDONLY; } #if defined(O_CLOEXEC) - if (strchr(mode, 'e')) - { + if (strchr(mode, 'e')) { flags |= O_CLOEXEC; } #endif #if defined(O_NONBLOCK) - if (strchr(mode, 'n')) - { + if (strchr(mode, 'n')) { flags |= O_NONBLOCK; } #endif #if defined(_O_TEXT) && defined(O_BINARY) - if (strchr(mode, 't')) - { + if (strchr(mode, 't')) { flags |= _O_TEXT; - } - else - { + } else { flags |= O_BINARY; } #endif @@ -144,22 +132,25 @@ static int sw_php_stream_parse_fopen_modes(const char *mode, int *open_flags) return SUCCESS; } -#define stream_fopen_from_fd_rel(fd, mode, persistent_id) _sw_php_stream_fopen_from_fd((fd), (mode), (persistent_id) STREAMS_REL_CC) -#define sw_php_stream_fopen_from_fd_int(fd, mode, persistent_id) _sw_php_stream_fopen_from_fd_int((fd), (mode), (persistent_id) STREAMS_CC) -#define sw_php_stream_fopen_from_fd_int_rel(fd, mode, persistent_id) _sw_php_stream_fopen_from_fd_int((fd), (mode), (persistent_id) STREAMS_REL_CC) +#define stream_fopen_from_fd_rel(fd, mode, persistent_id) \ + _sw_php_stream_fopen_from_fd((fd), (mode), (persistent_id) STREAMS_REL_CC) +#define sw_php_stream_fopen_from_fd_int(fd, mode, persistent_id) \ + _sw_php_stream_fopen_from_fd_int((fd), (mode), (persistent_id) STREAMS_CC) +#define sw_php_stream_fopen_from_fd_int_rel(fd, mode, persistent_id) \ + _sw_php_stream_fopen_from_fd_int((fd), (mode), (persistent_id) STREAMS_REL_CC) /* {{{ ------- STDIO stream implementation -------*/ typedef struct { FILE *file; - int fd; /* underlying file descriptor */ - unsigned is_process_pipe:1; /* use pclose instead of fclose */ - unsigned is_pipe:1; /* stream is an actual pipe, currently Windows only*/ - unsigned cached_fstat:1; /* sb is valid */ - unsigned is_pipe_blocking:1; /* allow blocking read() on pipes, currently Windows only */ - unsigned no_forced_fstat:1; /* Use fstat cache even if forced */ - unsigned is_seekable:1; /* don't try and seek, if not set */ - unsigned _reserved:26; + int fd; /* underlying file descriptor */ + unsigned is_process_pipe : 1; /* use pclose instead of fclose */ + unsigned is_pipe : 1; /* stream is an actual pipe, currently Windows only*/ + unsigned cached_fstat : 1; /* sb is valid */ + unsigned is_pipe_blocking : 1; /* allow blocking read() on pipes, currently Windows only */ + unsigned no_forced_fstat : 1; /* Use fstat cache even if forced */ + unsigned is_seekable : 1; /* don't try and seek, if not set */ + unsigned _reserved : 26; int lock_flag; /* stores the lock state */ zend_string *temp_name; /* if non-null, this is the path to a temporary file that @@ -180,7 +171,7 @@ typedef struct { zend_stat_t sb; } php_stdio_stream_data; -#define PHP_STDIOP_GET_FD(anfd, data) anfd = (data)->file ? fileno((data)->file) : (data)->fd +#define PHP_STDIOP_GET_FD(anfd, data) anfd = (data)->file ? fileno((data)->file) : (data)->fd static php_stream_ops sw_php_stream_stdio_ops = { sw_php_stdiop_write, @@ -194,23 +185,21 @@ static php_stream_ops sw_php_stream_stdio_ops = { sw_php_stdiop_set_option, }; -static int do_fstat(php_stdio_stream_data *d, int force) -{ - if (!d->cached_fstat || force) { - int fd; - int r; +static int do_fstat(php_stdio_stream_data *d, int force) { + if (!d->cached_fstat || force) { + int fd; + int r; - PHP_STDIOP_GET_FD(fd, d); - r = fstat(fd, &d->sb); - d->cached_fstat = r == 0; + PHP_STDIOP_GET_FD(fd, d); + r = fstat(fd, &d->sb); + d->cached_fstat = r == 0; - return r; - } - return 0; + return r; + } + return 0; } -static php_stream *_sw_php_stream_fopen_from_fd_int(int fd, const char *mode, const char *persistent_id STREAMS_DC) -{ +static php_stream *_sw_php_stream_fopen_from_fd_int(int fd, const char *mode, const char *persistent_id STREAMS_DC) { php_stdio_stream_data *self = (php_stdio_stream_data *) pemalloc_rel_orig(sizeof(*self), persistent_id); memset(self, 0, sizeof(*self)); self->file = NULL; @@ -223,17 +212,17 @@ static php_stream *_sw_php_stream_fopen_from_fd_int(int fd, const char *mode, co } static php_stream_size_t sw_php_stdiop_write(php_stream *stream, const char *buf, size_t count) { - php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract; + php_stdio_stream_data *data = (php_stdio_stream_data *) stream->abstract; assert(data != NULL); if (data->fd >= 0) { - ssize_t bytes_written = write(data->fd, buf, count); + ssize_t bytes_written = write(data->fd, buf, count); #if PHP_VERSION_ID < 70400 - if (bytes_written < 0) { - return 0; - } - return (size_t) bytes_written; + if (bytes_written < 0) { + return 0; + } + return (size_t) bytes_written; #else return bytes_written; #endif @@ -243,93 +232,76 @@ static php_stream_size_t sw_php_stdiop_write(php_stream *stream, const char *buf } static php_stream_size_t sw_php_stdiop_read(php_stream *stream, char *buf, size_t count) { - php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract; + php_stdio_stream_data *data = (php_stdio_stream_data *) stream->abstract; assert(data != NULL); if (data->fd >= 0) { - ssize_t ret = read(data->fd, buf, PLAIN_WRAP_BUF_SIZE(count)); - if (ret == -1 && errno == EINTR) { - /* Read was interrupted, retry once, - If read still fails, giveup with feof==0 - so script can retry if desired */ - ret = read(data->fd, buf, PLAIN_WRAP_BUF_SIZE(count)); - } - stream->eof = (ret == 0 || (ret == -1 && errno != EWOULDBLOCK && errno != EINTR && errno != EBADF)); + ssize_t ret = read(data->fd, buf, PLAIN_WRAP_BUF_SIZE(count)); + if (ret == -1 && errno == EINTR) { + /* Read was interrupted, retry once, + If read still fails, giveup with feof==0 + so script can retry if desired */ + ret = read(data->fd, buf, PLAIN_WRAP_BUF_SIZE(count)); + } + stream->eof = (ret == 0 || (ret == -1 && errno != EWOULDBLOCK && errno != EINTR && errno != EBADF)); #if PHP_VERSION_ID < 70400 - if (ret < 0) { - return 0; - } - return (size_t) ret; + if (ret < 0) { + return 0; + } + return (size_t) ret; #else - return ret; + return ret; #endif - } - else { + } else { size_t ret = fread(buf, 1, count, data->file); stream->eof = feof(data->file); - return ret; + return ret; } } -static int sw_php_stdiop_close(php_stream *stream, int close_handle) -{ +static int sw_php_stdiop_close(php_stream *stream, int close_handle) { int ret; - php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract; + php_stdio_stream_data *data = (php_stdio_stream_data *) stream->abstract; assert(data != NULL); - if (data->last_mapped_addr) - { + if (data->last_mapped_addr) { munmap(data->last_mapped_addr, data->last_mapped_len); data->last_mapped_addr = NULL; } - if (close_handle) - { - if (data->file) - { - if (data->is_process_pipe) - { + if (close_handle) { + if (data->file) { + if (data->is_process_pipe) { errno = 0; ret = pclose(data->file); #if HAVE_SYS_WAIT_H - if (WIFEXITED(ret)) - { + if (WIFEXITED(ret)) { ret = WEXITSTATUS(ret); } #endif - } - else - { + } else { ret = fclose(data->file); data->file = NULL; } - } - else if (data->fd != -1) - { - if ((data->lock_flag & LOCK_EX) || (data->lock_flag & LOCK_SH)) - { + } else if (data->fd != -1) { + if ((data->lock_flag & LOCK_EX) || (data->lock_flag & LOCK_SH)) { swoole_coroutine_flock_ex(stream->orig_path, data->fd, LOCK_UN); } ret = close(data->fd); data->fd = -1; - } - else - { + } else { return 0; /* everything should be closed already -> success */ } - if (data->temp_name) - { + if (data->temp_name) { unlink(ZSTR_VAL(data->temp_name)); /* temporary streams are never persistent */ zend_string_release(data->temp_name); data->temp_name = NULL; } - } - else - { + } else { ret = 0; data->file = NULL; data->fd = -1; @@ -340,9 +312,8 @@ static int sw_php_stdiop_close(php_stream *stream, int close_handle) return ret; } -static int sw_php_stdiop_flush(php_stream *stream) -{ - php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract; +static int sw_php_stdiop_flush(php_stream *stream) { + php_stdio_stream_data *data = (php_stdio_stream_data *) stream->abstract; assert(data != NULL); @@ -351,87 +322,73 @@ static int sw_php_stdiop_flush(php_stream *stream) * data is send to the kernel using write(2). fsync'ing is * something completely different. */ - if (data->file) - { + if (data->file) { return fflush(data->file); } return 0; } -static int sw_php_stdiop_seek(php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffset) -{ - php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract; +static int sw_php_stdiop_seek(php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffset) { + php_stdio_stream_data *data = (php_stdio_stream_data *) stream->abstract; int ret; assert(data != NULL); - if (data->is_pipe) - { + if (data->is_pipe) { php_error_docref(NULL, E_WARNING, "cannot seek on a pipe"); return -1; } - if (data->fd >= 0) - { + if (data->fd >= 0) { zend_off_t result; result = lseek(data->fd, offset, whence); - if (result == (zend_off_t) -1) - return -1; + if (result == (zend_off_t) -1) return -1; *newoffset = result; return 0; - } - else - { + } else { ret = zend_fseek(data->file, offset, whence); *newoffset = zend_ftell(data->file); return ret; } } -static int sw_php_stdiop_cast(php_stream *stream, int castas, void **ret) -{ +static int sw_php_stdiop_cast(php_stream *stream, int castas, void **ret) { php_socket_t fd; - php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract; + php_stdio_stream_data *data = (php_stdio_stream_data *) stream->abstract; assert(data != NULL); /* as soon as someone touches the stdio layer, buffering may ensue, * so we need to stop using the fd directly in that case */ - switch (castas) - { + switch (castas) { case PHP_STREAM_AS_STDIO: - if (ret) - { - if (data->file == NULL) - { + if (ret) { + if (data->file == NULL) { /* we were opened as a plain file descriptor, so we * need fdopen now */ char fixed_mode[5]; php_stream_mode_sanitize_fdopen_fopencookie(stream, fixed_mode); data->file = fdopen(data->fd, fixed_mode); - if (data->file == NULL) - { + if (data->file == NULL) { return FAILURE; } } - *(FILE**) ret = data->file; + *(FILE **) ret = data->file; data->fd = SOCK_ERR; } return SUCCESS; case PHP_STREAM_AS_FD_FOR_SELECT: PHP_STDIOP_GET_FD(fd, data); - if (SOCK_ERR == fd) - { + if (SOCK_ERR == fd) { return FAILURE; } - if (ret) - { + if (ret) { *(php_socket_t *) ret = fd; } return SUCCESS; @@ -439,16 +396,13 @@ static int sw_php_stdiop_cast(php_stream *stream, int castas, void **ret) case PHP_STREAM_AS_FD: PHP_STDIOP_GET_FD(fd, data); - if (SOCK_ERR == fd) - { + if (SOCK_ERR == fd) { return FAILURE; } - if (data->file) - { + if (data->file) { fflush(data->file); } - if (ret) - { + if (ret) { *(php_socket_t *) ret = fd; } return SUCCESS; @@ -457,375 +411,370 @@ static int sw_php_stdiop_cast(php_stream *stream, int castas, void **ret) } } -static int sw_php_stdiop_stat(php_stream *stream, php_stream_statbuf *ssb) -{ - int ret; - php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract; +static int sw_php_stdiop_stat(php_stream *stream, php_stream_statbuf *ssb) { + int ret; + php_stdio_stream_data *data = (php_stdio_stream_data *) stream->abstract; - assert(data != NULL); - if((ret = do_fstat(data, 1)) == 0) { - memcpy(&ssb->sb, &data->sb, sizeof(ssb->sb)); - } + assert(data != NULL); + if ((ret = do_fstat(data, 1)) == 0) { + memcpy(&ssb->sb, &data->sb, sizeof(ssb->sb)); + } - return ret; + return ret; } -static int sw_php_stdiop_set_option(php_stream *stream, int option, int value, void *ptrparam) -{ - php_stdio_stream_data *data = (php_stdio_stream_data*) stream->abstract; - size_t size; - int fd; +static int sw_php_stdiop_set_option(php_stream *stream, int option, int value, void *ptrparam) { + php_stdio_stream_data *data = (php_stdio_stream_data *) stream->abstract; + size_t size; + int fd; #ifdef O_NONBLOCK - /* FIXME: make this work for win32 */ - int flags; - int oldval; + /* FIXME: make this work for win32 */ + int flags; + int oldval; #endif - PHP_STDIOP_GET_FD(fd, data); + PHP_STDIOP_GET_FD(fd, data); - switch(option) { - case PHP_STREAM_OPTION_BLOCKING: - if (fd == -1) - return -1; + switch (option) { + case PHP_STREAM_OPTION_BLOCKING: + if (fd == -1) return -1; #ifdef O_NONBLOCK - flags = fcntl(fd, F_GETFL, 0); - oldval = (flags & O_NONBLOCK) ? 0 : 1; - if (value) - flags &= ~O_NONBLOCK; - else - flags |= O_NONBLOCK; - - if (-1 == fcntl(fd, F_SETFL, flags)) - return -1; - return oldval; + flags = fcntl(fd, F_GETFL, 0); + oldval = (flags & O_NONBLOCK) ? 0 : 1; + if (value) + flags &= ~O_NONBLOCK; + else + flags |= O_NONBLOCK; + + if (-1 == fcntl(fd, F_SETFL, flags)) return -1; + return oldval; #else - return -1; /* not yet implemented */ + return -1; /* not yet implemented */ #endif - case PHP_STREAM_OPTION_WRITE_BUFFER: + case PHP_STREAM_OPTION_WRITE_BUFFER: - if (data->file == NULL) { - return -1; - } + if (data->file == NULL) { + return -1; + } - if (ptrparam) - size = *(size_t *)ptrparam; - else - size = BUFSIZ; + if (ptrparam) + size = *(size_t *) ptrparam; + else + size = BUFSIZ; - switch(value) { - case PHP_STREAM_BUFFER_NONE: - return setvbuf(data->file, NULL, _IONBF, 0); + switch (value) { + case PHP_STREAM_BUFFER_NONE: + return setvbuf(data->file, NULL, _IONBF, 0); - case PHP_STREAM_BUFFER_LINE: - return setvbuf(data->file, NULL, _IOLBF, size); + case PHP_STREAM_BUFFER_LINE: + return setvbuf(data->file, NULL, _IOLBF, size); - case PHP_STREAM_BUFFER_FULL: - return setvbuf(data->file, NULL, _IOFBF, size); + case PHP_STREAM_BUFFER_FULL: + return setvbuf(data->file, NULL, _IOFBF, size); - default: - return -1; - } - break; + default: + return -1; + } + break; - case PHP_STREAM_OPTION_LOCKING: - if (fd == -1) { - return -1; - } + case PHP_STREAM_OPTION_LOCKING: + if (fd == -1) { + return -1; + } - if ((zend_uintptr_t) ptrparam == PHP_STREAM_LOCK_SUPPORTED) { - return 0; - } + if ((zend_uintptr_t) ptrparam == PHP_STREAM_LOCK_SUPPORTED) { + return 0; + } - if (!swoole_coroutine_flock_ex(stream->orig_path, fd, value)) { - data->lock_flag = value; - return 0; - } else { - return -1; - } - break; + if (!swoole_coroutine_flock_ex(stream->orig_path, fd, value)) { + data->lock_flag = value; + return 0; + } else { + return -1; + } + break; - case PHP_STREAM_OPTION_MMAP_API: + case PHP_STREAM_OPTION_MMAP_API: #if HAVE_MMAP - { - php_stream_mmap_range *range = (php_stream_mmap_range*)ptrparam; - int prot, flags; - - switch (value) { - case PHP_STREAM_MMAP_SUPPORTED: - return fd == -1 ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK; - - case PHP_STREAM_MMAP_MAP_RANGE: - if(do_fstat(data, 1) != 0) { - return PHP_STREAM_OPTION_RETURN_ERR; - } - if (range->length == 0 && range->offset > 0 && range->offset < (size_t)data->sb.st_size) { - range->length = data->sb.st_size - range->offset; - } - if (range->length == 0 || range->length > (size_t)data->sb.st_size) { - range->length = data->sb.st_size; - } - if (range->offset >= (size_t)data->sb.st_size) { - range->offset = data->sb.st_size; - range->length = 0; - } - switch (range->mode) { - case PHP_STREAM_MAP_MODE_READONLY: - prot = PROT_READ; - flags = MAP_PRIVATE; - break; - case PHP_STREAM_MAP_MODE_READWRITE: - prot = PROT_READ | PROT_WRITE; - flags = MAP_PRIVATE; - break; - case PHP_STREAM_MAP_MODE_SHARED_READONLY: - prot = PROT_READ; - flags = MAP_SHARED; - break; - case PHP_STREAM_MAP_MODE_SHARED_READWRITE: - prot = PROT_READ | PROT_WRITE; - flags = MAP_SHARED; - break; - default: - return PHP_STREAM_OPTION_RETURN_ERR; - } - range->mapped = (char*)mmap(NULL, range->length, prot, flags, fd, range->offset); - if (range->mapped == (char*)MAP_FAILED) { - range->mapped = NULL; - return PHP_STREAM_OPTION_RETURN_ERR; - } - /* remember the mapping */ - data->last_mapped_addr = range->mapped; - data->last_mapped_len = range->length; - return PHP_STREAM_OPTION_RETURN_OK; - - case PHP_STREAM_MMAP_UNMAP: - if (data->last_mapped_addr) { - munmap(data->last_mapped_addr, data->last_mapped_len); - data->last_mapped_addr = NULL; - - return PHP_STREAM_OPTION_RETURN_OK; - } - return PHP_STREAM_OPTION_RETURN_ERR; - } - } + { + php_stream_mmap_range *range = (php_stream_mmap_range *) ptrparam; + int prot, flags; + + switch (value) { + case PHP_STREAM_MMAP_SUPPORTED: + return fd == -1 ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK; + + case PHP_STREAM_MMAP_MAP_RANGE: + if (do_fstat(data, 1) != 0) { + return PHP_STREAM_OPTION_RETURN_ERR; + } + if (range->length == 0 && range->offset > 0 && range->offset < (size_t) data->sb.st_size) { + range->length = data->sb.st_size - range->offset; + } + if (range->length == 0 || range->length > (size_t) data->sb.st_size) { + range->length = data->sb.st_size; + } + if (range->offset >= (size_t) data->sb.st_size) { + range->offset = data->sb.st_size; + range->length = 0; + } + switch (range->mode) { + case PHP_STREAM_MAP_MODE_READONLY: + prot = PROT_READ; + flags = MAP_PRIVATE; + break; + case PHP_STREAM_MAP_MODE_READWRITE: + prot = PROT_READ | PROT_WRITE; + flags = MAP_PRIVATE; + break; + case PHP_STREAM_MAP_MODE_SHARED_READONLY: + prot = PROT_READ; + flags = MAP_SHARED; + break; + case PHP_STREAM_MAP_MODE_SHARED_READWRITE: + prot = PROT_READ | PROT_WRITE; + flags = MAP_SHARED; + break; + default: + return PHP_STREAM_OPTION_RETURN_ERR; + } + range->mapped = (char *) mmap(NULL, range->length, prot, flags, fd, range->offset); + if (range->mapped == (char *) MAP_FAILED) { + range->mapped = NULL; + return PHP_STREAM_OPTION_RETURN_ERR; + } + /* remember the mapping */ + data->last_mapped_addr = range->mapped; + data->last_mapped_len = range->length; + return PHP_STREAM_OPTION_RETURN_OK; + + case PHP_STREAM_MMAP_UNMAP: + if (data->last_mapped_addr) { + munmap(data->last_mapped_addr, data->last_mapped_len); + data->last_mapped_addr = NULL; + + return PHP_STREAM_OPTION_RETURN_OK; + } + return PHP_STREAM_OPTION_RETURN_ERR; + } + } #elif defined(PHP_WIN32) - { - php_stream_mmap_range *range = (php_stream_mmap_range*)ptrparam; - HANDLE hfile = (HANDLE)_get_osfhandle(fd); - DWORD prot, acc, loffs = 0, delta = 0; - - switch (value) { - case PHP_STREAM_MMAP_SUPPORTED: - return hfile == INVALID_HANDLE_VALUE ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK; - - case PHP_STREAM_MMAP_MAP_RANGE: - switch (range->mode) { - case PHP_STREAM_MAP_MODE_READONLY: - prot = PAGE_READONLY; - acc = FILE_MAP_READ; - break; - case PHP_STREAM_MAP_MODE_READWRITE: - prot = PAGE_READWRITE; - acc = FILE_MAP_READ | FILE_MAP_WRITE; - break; - case PHP_STREAM_MAP_MODE_SHARED_READONLY: - prot = PAGE_READONLY; - acc = FILE_MAP_READ; - /* TODO: we should assign a name for the mapping */ - break; - case PHP_STREAM_MAP_MODE_SHARED_READWRITE: - prot = PAGE_READWRITE; - acc = FILE_MAP_READ | FILE_MAP_WRITE; - /* TODO: we should assign a name for the mapping */ - break; - default: - return PHP_STREAM_OPTION_RETURN_ERR; - } - - /* create a mapping capable of viewing the whole file (this costs no real resources) */ - data->file_mapping = CreateFileMapping(hfile, NULL, prot, 0, 0, NULL); - - if (data->file_mapping == NULL) { - return PHP_STREAM_OPTION_RETURN_ERR; - } - - size = GetFileSize(hfile, NULL); - if (range->length == 0 && range->offset > 0 && range->offset < size) { - range->length = size - range->offset; - } - if (range->length == 0 || range->length > size) { - range->length = size; - } - if (range->offset >= size) { - range->offset = size; - range->length = 0; - } - - /* figure out how big a chunk to map to be able to view the part that we need */ - if (range->offset != 0) { - SYSTEM_INFO info; - DWORD gran; - - GetSystemInfo(&info); - gran = info.dwAllocationGranularity; - loffs = ((DWORD)range->offset / gran) * gran; - delta = (DWORD)range->offset - loffs; - } - - data->last_mapped_addr = MapViewOfFile(data->file_mapping, acc, 0, loffs, range->length + delta); - - if (data->last_mapped_addr) { - /* give them back the address of the start offset they requested */ - range->mapped = data->last_mapped_addr + delta; - return PHP_STREAM_OPTION_RETURN_OK; - } - - CloseHandle(data->file_mapping); - data->file_mapping = NULL; - - return PHP_STREAM_OPTION_RETURN_ERR; - - case PHP_STREAM_MMAP_UNMAP: - if (data->last_mapped_addr) { - UnmapViewOfFile(data->last_mapped_addr); - data->last_mapped_addr = NULL; - CloseHandle(data->file_mapping); - data->file_mapping = NULL; - return PHP_STREAM_OPTION_RETURN_OK; - } - return PHP_STREAM_OPTION_RETURN_ERR; - - default: - return PHP_STREAM_OPTION_RETURN_ERR; - } - } + { + php_stream_mmap_range *range = (php_stream_mmap_range *) ptrparam; + HANDLE hfile = (HANDLE) _get_osfhandle(fd); + DWORD prot, acc, loffs = 0, delta = 0; + + switch (value) { + case PHP_STREAM_MMAP_SUPPORTED: + return hfile == INVALID_HANDLE_VALUE ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK; + + case PHP_STREAM_MMAP_MAP_RANGE: + switch (range->mode) { + case PHP_STREAM_MAP_MODE_READONLY: + prot = PAGE_READONLY; + acc = FILE_MAP_READ; + break; + case PHP_STREAM_MAP_MODE_READWRITE: + prot = PAGE_READWRITE; + acc = FILE_MAP_READ | FILE_MAP_WRITE; + break; + case PHP_STREAM_MAP_MODE_SHARED_READONLY: + prot = PAGE_READONLY; + acc = FILE_MAP_READ; + /* TODO: we should assign a name for the mapping */ + break; + case PHP_STREAM_MAP_MODE_SHARED_READWRITE: + prot = PAGE_READWRITE; + acc = FILE_MAP_READ | FILE_MAP_WRITE; + /* TODO: we should assign a name for the mapping */ + break; + default: + return PHP_STREAM_OPTION_RETURN_ERR; + } + + /* create a mapping capable of viewing the whole file (this costs no real resources) */ + data->file_mapping = CreateFileMapping(hfile, NULL, prot, 0, 0, NULL); + + if (data->file_mapping == NULL) { + return PHP_STREAM_OPTION_RETURN_ERR; + } + + size = GetFileSize(hfile, NULL); + if (range->length == 0 && range->offset > 0 && range->offset < size) { + range->length = size - range->offset; + } + if (range->length == 0 || range->length > size) { + range->length = size; + } + if (range->offset >= size) { + range->offset = size; + range->length = 0; + } + + /* figure out how big a chunk to map to be able to view the part that we need */ + if (range->offset != 0) { + SYSTEM_INFO info; + DWORD gran; + + GetSystemInfo(&info); + gran = info.dwAllocationGranularity; + loffs = ((DWORD) range->offset / gran) * gran; + delta = (DWORD) range->offset - loffs; + } + + data->last_mapped_addr = MapViewOfFile(data->file_mapping, acc, 0, loffs, range->length + delta); + + if (data->last_mapped_addr) { + /* give them back the address of the start offset they requested */ + range->mapped = data->last_mapped_addr + delta; + return PHP_STREAM_OPTION_RETURN_OK; + } + + CloseHandle(data->file_mapping); + data->file_mapping = NULL; + + return PHP_STREAM_OPTION_RETURN_ERR; + + case PHP_STREAM_MMAP_UNMAP: + if (data->last_mapped_addr) { + UnmapViewOfFile(data->last_mapped_addr); + data->last_mapped_addr = NULL; + CloseHandle(data->file_mapping); + data->file_mapping = NULL; + return PHP_STREAM_OPTION_RETURN_OK; + } + return PHP_STREAM_OPTION_RETURN_ERR; + + default: + return PHP_STREAM_OPTION_RETURN_ERR; + } + } #endif - return PHP_STREAM_OPTION_RETURN_NOTIMPL; - - case PHP_STREAM_OPTION_TRUNCATE_API: - switch (value) { - case PHP_STREAM_TRUNCATE_SUPPORTED: - return fd == -1 ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK; - - case PHP_STREAM_TRUNCATE_SET_SIZE: { - ptrdiff_t new_size = *(ptrdiff_t*)ptrparam; - if (new_size < 0) { - return PHP_STREAM_OPTION_RETURN_ERR; - } - return ftruncate(fd, new_size) == 0 ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR; - } - } + return PHP_STREAM_OPTION_RETURN_NOTIMPL; + + case PHP_STREAM_OPTION_TRUNCATE_API: + switch (value) { + case PHP_STREAM_TRUNCATE_SUPPORTED: + return fd == -1 ? PHP_STREAM_OPTION_RETURN_ERR : PHP_STREAM_OPTION_RETURN_OK; + + case PHP_STREAM_TRUNCATE_SET_SIZE: { + ptrdiff_t new_size = *(ptrdiff_t *) ptrparam; + if (new_size < 0) { + return PHP_STREAM_OPTION_RETURN_ERR; + } + return ftruncate(fd, new_size) == 0 ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR; + } + } #ifdef PHP_WIN32 - case PHP_STREAM_OPTION_PIPE_BLOCKING: - data->is_pipe_blocking = value; - return PHP_STREAM_OPTION_RETURN_OK; + case PHP_STREAM_OPTION_PIPE_BLOCKING: + data->is_pipe_blocking = value; + return PHP_STREAM_OPTION_RETURN_OK; #endif - case PHP_STREAM_OPTION_META_DATA_API: - if (fd == -1) - return -1; + case PHP_STREAM_OPTION_META_DATA_API: + if (fd == -1) return -1; #ifdef O_NONBLOCK - flags = fcntl(fd, F_GETFL, 0); + flags = fcntl(fd, F_GETFL, 0); - add_assoc_bool((zval*)ptrparam, "timed_out", 0); - add_assoc_bool((zval*)ptrparam, "blocked", (flags & O_NONBLOCK)? 0 : 1); - add_assoc_bool((zval*)ptrparam, "eof", stream->eof); + add_assoc_bool((zval *) ptrparam, "timed_out", 0); + add_assoc_bool((zval *) ptrparam, "blocked", (flags & O_NONBLOCK) ? 0 : 1); + add_assoc_bool((zval *) ptrparam, "eof", stream->eof); - return PHP_STREAM_OPTION_RETURN_OK; + return PHP_STREAM_OPTION_RETURN_OK; #endif - return -1; - default: - return PHP_STREAM_OPTION_RETURN_NOTIMPL; - } + return -1; + default: + return PHP_STREAM_OPTION_RETURN_NOTIMPL; + } } /* }}} */ /* {{{ plain files opendir/readdir implementation */ -#if PHP_VERSION_ID < 70400 -static size_t php_plain_files_dirstream_read(php_stream *stream, char *buf, size_t count) -#else -static ssize_t php_plain_files_dirstream_read(php_stream *stream, char *buf, size_t count) -#endif -{ - DIR *dir = (DIR*) stream->abstract; +static php_stream_size_t php_plain_files_dirstream_read(php_stream *stream, char *buf, size_t count) { + DIR *dir = (DIR *) stream->abstract; struct dirent *result; - php_stream_dirent *ent = (php_stream_dirent*) buf; - - /* avoid problems if someone mis-uses the stream */ - if (count != sizeof(php_stream_dirent)) { - return 0; - } - - if ((result = readdir(dir))) { - PHP_STRLCPY(ent->d_name, result->d_name, sizeof(ent->d_name), strlen(result->d_name)); - return sizeof(php_stream_dirent); - } - return 0; + php_stream_dirent *ent = (php_stream_dirent *) buf; + + /* avoid problems if someone mis-uses the stream */ + if (count != sizeof(php_stream_dirent)) { + return 0; + } + + if ((result = readdir(dir))) { + PHP_STRLCPY(ent->d_name, result->d_name, sizeof(ent->d_name), strlen(result->d_name)); + return sizeof(php_stream_dirent); + } + return 0; } -static int php_plain_files_dirstream_close(php_stream *stream, int close_handle) -{ - return closedir((DIR *)stream->abstract); +static int php_plain_files_dirstream_close(php_stream *stream, int close_handle) { + return closedir((DIR *) stream->abstract); } -static int php_plain_files_dirstream_rewind(php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffs) -{ - rewinddir((DIR *)stream->abstract); - return 0; +static int php_plain_files_dirstream_rewind(php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffs) { + rewinddir((DIR *) stream->abstract); + return 0; } -static php_stream_ops php_plain_files_dirstream_ops = { - NULL, php_plain_files_dirstream_read, - php_plain_files_dirstream_close, NULL, - "dir", - php_plain_files_dirstream_rewind, - NULL, /* cast */ - NULL, /* stat */ - NULL /* set_option */ +static php_stream_ops php_plain_files_dirstream_ops = { + NULL, + php_plain_files_dirstream_read, + php_plain_files_dirstream_close, + NULL, + "dir", + php_plain_files_dirstream_rewind, + NULL, /* cast */ + NULL, /* stat */ + NULL /* set_option */ }; -static php_stream *php_plain_files_dir_opener(php_stream_wrapper *wrapper, const char *path, const char *mode, - int options, zend_string **opened_path, php_stream_context *context STREAMS_DC) -{ - DIR *dir = NULL; - php_stream *stream = NULL; +static php_stream *php_plain_files_dir_opener(php_stream_wrapper *wrapper, + const char *path, + const char *mode, + int options, + zend_string **opened_path, + php_stream_context *context STREAMS_DC) { + DIR *dir = NULL; + php_stream *stream = NULL; #ifdef HAVE_GLOB - if (options & STREAM_USE_GLOB_DIR_OPEN) { - return php_glob_stream_wrapper.wops->dir_opener((php_stream_wrapper*)&php_glob_stream_wrapper, path, mode, options, opened_path, context STREAMS_REL_CC); - } + if (options & STREAM_USE_GLOB_DIR_OPEN) { + return php_glob_stream_wrapper.wops->dir_opener( + (php_stream_wrapper *) &php_glob_stream_wrapper, path, mode, options, opened_path, context STREAMS_REL_CC); + } #endif - if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(path)) { - return NULL; - } + if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(path)) { + return NULL; + } - dir = opendir(path); + dir = opendir(path); #ifdef PHP_WIN32 - if (!dir) { - php_win32_docref2_from_error(GetLastError(), path, path); - } - - if (dir && dir->finished) { - closedir(dir); - dir = NULL; - } + if (!dir) { + php_win32_docref2_from_error(GetLastError(), path, path); + } + + if (dir && dir->finished) { + closedir(dir); + dir = NULL; + } #endif - if (dir) { - stream = php_stream_alloc(&php_plain_files_dirstream_ops, dir, 0, mode); - if (stream == NULL) - closedir(dir); - } + if (dir) { + stream = php_stream_alloc(&php_plain_files_dirstream_ops, dir, 0, mode); + if (stream == NULL) closedir(dir); + } - return stream; + return stream; } /* }}} */ -static php_stream *stream_fopen_rel(const char *filename, const char *mode, zend_string **opened_path, int options STREAMS_DC) -{ +static php_stream *stream_fopen_rel(const char *filename, + const char *mode, + zend_string **opened_path, + int options STREAMS_DC) { char _realpath[MAXPATHLEN]; int open_flags; int fd; @@ -833,36 +782,27 @@ static php_stream *stream_fopen_rel(const char *filename, const char *mode, zend int persistent = options & STREAM_OPEN_PERSISTENT; char *persistent_id = NULL; - if (FAILURE == sw_php_stream_parse_fopen_modes(mode, &open_flags)) - { - if (options & REPORT_ERRORS) - { + if (FAILURE == sw_php_stream_parse_fopen_modes(mode, &open_flags)) { + if (options & REPORT_ERRORS) { php_error_docref(NULL, E_WARNING, "`%s' is not a valid mode for fopen", mode); } return NULL; } - if (options & STREAM_ASSUME_REALPATH) - { + if (options & STREAM_ASSUME_REALPATH) { strlcpy(_realpath, filename, sizeof(_realpath)); - } - else - { - if (expand_filepath(filename, _realpath) == NULL) - { + } else { + if (expand_filepath(filename, _realpath) == NULL) { return NULL; } } - if (persistent) - { + if (persistent) { spprintf(&persistent_id, 0, "streams_stdio_%d_%s", open_flags, _realpath); - switch (php_stream_from_persistent_id(persistent_id, &ret)) - { + switch (php_stream_from_persistent_id(persistent_id, &ret)) { case PHP_STREAM_PERSISTENT_SUCCESS: - if (opened_path) - { - //TODO: avoid reallocation??? + if (opened_path) { + // TODO: avoid reallocation??? *opened_path = zend_string_init(_realpath, strlen(_realpath), 0); } /* fall through */ @@ -873,73 +813,73 @@ static php_stream *stream_fopen_rel(const char *filename, const char *mode, zend } } #ifdef PHP_WIN32 - fd = php_win32_ioutil_open(_realpath, open_flags, 0666); + fd = php_win32_ioutil_open(_realpath, open_flags, 0666); #else - fd = open(_realpath, open_flags, 0666); + fd = open(_realpath, open_flags, 0666); #endif - if (fd != -1) - { + if (fd != -1) { ret = stream_fopen_from_fd_rel(fd, mode, persistent_id); - if (ret) - { - if (opened_path) - { + if (ret) { + if (opened_path) { *opened_path = zend_string_init(_realpath, strlen(_realpath), 0); } - if (persistent_id) - { + if (persistent_id) { efree(persistent_id); } - /* WIN32 always set ISREG flag */ + /* WIN32 always set ISREG flag */ #ifndef PHP_WIN32 - /* sanity checks for include/require. - * We check these after opening the stream, so that we save - * on fstat() syscalls */ - if (options & STREAM_OPEN_FOR_INCLUDE) { - php_stdio_stream_data *self = (php_stdio_stream_data*)ret->abstract; - int r; - - r = do_fstat(self, 0); - if ((r == 0 && !S_ISREG(self->sb.st_mode))) { - if (opened_path) { - zend_string_release(*opened_path); - *opened_path = NULL; - } - php_stream_close(ret); - return NULL; - } - } - - if (options & STREAM_USE_BLOCKING_PIPE) { - php_stdio_stream_data *self = (php_stdio_stream_data*)ret->abstract; - self->is_pipe_blocking = 1; - } + /* sanity checks for include/require. + * We check these after opening the stream, so that we save + * on fstat() syscalls */ + if (options & STREAM_OPEN_FOR_INCLUDE) { + php_stdio_stream_data *self = (php_stdio_stream_data *) ret->abstract; + int r; + + r = do_fstat(self, 0); + if ((r == 0 && !S_ISREG(self->sb.st_mode))) { + if (opened_path) { + zend_string_release(*opened_path); + *opened_path = NULL; + } + php_stream_close(ret); + return NULL; + } + } + + if (options & STREAM_USE_BLOCKING_PIPE) { + php_stdio_stream_data *self = (php_stdio_stream_data *) ret->abstract; + self->is_pipe_blocking = 1; + } #endif - return ret; - } - close(fd); - } - if (persistent_id) { - efree(persistent_id); - } - return NULL; + return ret; + } + close(fd); + } + if (persistent_id) { + efree(persistent_id); + } + return NULL; } -static php_stream* stream_opener(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, - zend_string **opened_path, php_stream_context *context STREAMS_DC) { +static php_stream *stream_opener(php_stream_wrapper *wrapper, + const char *path, + const char *mode, + int options, + zend_string **opened_path, + php_stream_context *context STREAMS_DC) { if (((options & STREAM_DISABLE_OPEN_BASEDIR) == 0) && php_check_open_basedir(path)) { return NULL; } php_stream *stream; /** phar_open_archive_fp, cannot use async-io */ - if (EG(current_execute_data) &&EG(current_execute_data)->func && - ZEND_USER_CODE(EG(current_execute_data)->func->type)) { + if (EG(current_execute_data) && EG(current_execute_data)->func && + ZEND_USER_CODE(EG(current_execute_data)->func->type)) { const zend_op *opline = EG(current_execute_data)->opline; - if (opline && opline->opcode == ZEND_INCLUDE_OR_EVAL - && (opline->extended_value & (ZEND_INCLUDE | ZEND_INCLUDE_ONCE | ZEND_REQUIRE | ZEND_REQUIRE_ONCE))) { + if (opline && opline->opcode == ZEND_INCLUDE_OR_EVAL && + (opline->extended_value & (ZEND_INCLUDE | ZEND_INCLUDE_ONCE | ZEND_REQUIRE | ZEND_REQUIRE_ONCE))) { size_t path_len = strlen(path); size_t phar_len = sizeof(".phar") - 1; if (path_len > phar_len && memcmp(path + path_len - phar_len, ".phar", phar_len) == 0) { @@ -949,7 +889,7 @@ static php_stream* stream_opener(php_stream_wrapper *wrapper, const char *path, } /** include file, cannot use async-io */ if (options & STREAM_OPEN_FOR_INCLUDE) { - _open_for_include: + _open_for_include: stream = php_stream_fopen_rel(path, mode, opened_path, options); stream->ops = php_swoole_get_ori_php_stream_stdio_ops(); return stream; @@ -958,362 +898,357 @@ static php_stream* stream_opener(php_stream_wrapper *wrapper, const char *path, return stream_fopen_rel(path, mode, opened_path, options STREAMS_REL_CC); } -static int php_plain_files_url_stater(php_stream_wrapper *wrapper, const char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context) -{ - if (strncasecmp(url, "file://", sizeof("file://") - 1) == 0) { - url += sizeof("file://") - 1; - } +static int php_plain_files_url_stater( + php_stream_wrapper *wrapper, const char *url, int flags, php_stream_statbuf *ssb, php_stream_context *context) { + if (strncasecmp(url, "file://", sizeof("file://") - 1) == 0) { + url += sizeof("file://") - 1; + } - if (php_check_open_basedir_ex(url, (flags & PHP_STREAM_URL_STAT_QUIET) ? 0 : 1)) { - return -1; - } + if (php_check_open_basedir_ex(url, (flags & PHP_STREAM_URL_STAT_QUIET) ? 0 : 1)) { + return -1; + } #ifdef PHP_WIN32 - if (flags & PHP_STREAM_URL_STAT_LINK) { - return lstat(url, &ssb->sb); - } + if (flags & PHP_STREAM_URL_STAT_LINK) { + return lstat(url, &ssb->sb); + } #else -# ifdef HAVE_SYMLINK - if (flags & PHP_STREAM_URL_STAT_LINK) { - return lstat(url, &ssb->sb); - } else -# endif +#ifdef HAVE_SYMLINK + if (flags & PHP_STREAM_URL_STAT_LINK) { + return lstat(url, &ssb->sb); + } else #endif - return stat(url, &ssb->sb); +#endif + return stat(url, &ssb->sb); } -static int php_plain_files_unlink(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context) -{ - int ret; +static int php_plain_files_unlink(php_stream_wrapper *wrapper, + const char *url, + int options, + php_stream_context *context) { + int ret; - if (strncasecmp(url, "file://", sizeof("file://") - 1) == 0) { - url += sizeof("file://") - 1; - } + if (strncasecmp(url, "file://", sizeof("file://") - 1) == 0) { + url += sizeof("file://") - 1; + } - if (php_check_open_basedir(url)) { - return 0; - } + if (php_check_open_basedir(url)) { + return 0; + } - ret = unlink(url); - if (ret == -1) { - if (options & REPORT_ERRORS) { - php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno)); - } - return 0; - } + ret = unlink(url); + if (ret == -1) { + if (options & REPORT_ERRORS) { + php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno)); + } + return 0; + } - /* Clear stat cache (and realpath cache) */ - php_clear_stat_cache(1, NULL, 0); + /* Clear stat cache (and realpath cache) */ + php_clear_stat_cache(1, NULL, 0); - return 1; + return 1; } -static int php_plain_files_rename(php_stream_wrapper *wrapper, const char *url_from, const char *url_to, int options, php_stream_context *context) -{ - int ret; +static int php_plain_files_rename( + php_stream_wrapper *wrapper, const char *url_from, const char *url_to, int options, php_stream_context *context) { + int ret; - if (!url_from || !url_to) { - return 0; - } + if (!url_from || !url_to) { + return 0; + } #ifdef PHP_WIN32 - if (!php_win32_check_trailing_space(url_from, (int)strlen(url_from))) { - php_win32_docref2_from_error(ERROR_INVALID_NAME, url_from, url_to); - return 0; - } - if (!php_win32_check_trailing_space(url_to, (int)strlen(url_to))) { - php_win32_docref2_from_error(ERROR_INVALID_NAME, url_from, url_to); - return 0; - } + if (!php_win32_check_trailing_space(url_from, (int) strlen(url_from))) { + php_win32_docref2_from_error(ERROR_INVALID_NAME, url_from, url_to); + return 0; + } + if (!php_win32_check_trailing_space(url_to, (int) strlen(url_to))) { + php_win32_docref2_from_error(ERROR_INVALID_NAME, url_from, url_to); + return 0; + } #endif - if (strncasecmp(url_from, "file://", sizeof("file://") - 1) == 0) { - url_from += sizeof("file://") - 1; - } + if (strncasecmp(url_from, "file://", sizeof("file://") - 1) == 0) { + url_from += sizeof("file://") - 1; + } - if (strncasecmp(url_to, "file://", sizeof("file://") - 1) == 0) { - url_to += sizeof("file://") - 1; - } + if (strncasecmp(url_to, "file://", sizeof("file://") - 1) == 0) { + url_to += sizeof("file://") - 1; + } - if (php_check_open_basedir(url_from) || php_check_open_basedir(url_to)) { - return 0; - } + if (php_check_open_basedir(url_from) || php_check_open_basedir(url_to)) { + return 0; + } - ret = rename(url_from, url_to); + ret = rename(url_from, url_to); - if (ret == -1) { + if (ret == -1) { #ifndef PHP_WIN32 -# ifdef EXDEV - if (errno == EXDEV) { - zend_stat_t sb; - if (php_copy_file(url_from, url_to) == SUCCESS) { - if (stat(url_from, &sb) == 0) { -# if !defined(TSRM_WIN32) && !defined(NETWARE) - if (chmod(url_to, sb.st_mode)) { - if (errno == EPERM) { - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); - unlink(url_from); - return 1; - } - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); - return 0; - } - if (chown(url_to, sb.st_uid, sb.st_gid)) { - if (errno == EPERM) { - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); - unlink(url_from); - return 1; - } - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); - return 0; - } -# endif - unlink(url_from); - return 1; - } - } - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); - return 0; - } -# endif +#ifdef EXDEV + if (errno == EXDEV) { + zend_stat_t sb; + if (php_copy_file(url_from, url_to) == SUCCESS) { + if (stat(url_from, &sb) == 0) { +#if !defined(TSRM_WIN32) && !defined(NETWARE) + if (chmod(url_to, sb.st_mode)) { + if (errno == EPERM) { + php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + unlink(url_from); + return 1; + } + php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + return 0; + } + if (chown(url_to, sb.st_uid, sb.st_gid)) { + if (errno == EPERM) { + php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + unlink(url_from); + return 1; + } + php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + return 0; + } +#endif + unlink(url_from); + return 1; + } + } + php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + return 0; + } +#endif #endif #ifdef PHP_WIN32 - php_win32_docref2_from_error(GetLastError(), url_from, url_to); + php_win32_docref2_from_error(GetLastError(), url_from, url_to); #else - php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); + php_error_docref2(NULL, url_from, url_to, E_WARNING, "%s", strerror(errno)); #endif - return 0; - } + return 0; + } - /* Clear stat cache (and realpath cache) */ - php_clear_stat_cache(1, NULL, 0); + /* Clear stat cache (and realpath cache) */ + php_clear_stat_cache(1, NULL, 0); - return 1; + return 1; } -static int php_plain_files_mkdir(php_stream_wrapper *wrapper, const char *dir, int mode, int options, php_stream_context *context) -{ - int ret, recursive = options & PHP_STREAM_MKDIR_RECURSIVE; - char *p; - - if (strncasecmp(dir, "file://", sizeof("file://") - 1) == 0) { - dir += sizeof("file://") - 1; - } - - if (!recursive) { - ret = mkdir(dir, mode); - } else { - /* we look for directory separator from the end of string, thus hopefuly reducing our work load */ - char *e; - zend_stat_t sb; - int dir_len = (int)strlen(dir); - int offset = 0; - char buf[MAXPATHLEN]; - - if (!expand_filepath_with_mode(dir, buf, NULL, 0, CWD_EXPAND )) { - php_error_docref(NULL, E_WARNING, "Invalid path"); - return 0; - } - - e = buf + strlen(buf); - - if ((p = (char*)memchr(buf, DEFAULT_SLASH, dir_len))) { - offset = p - buf + 1; - } - - if (p && dir_len == 1) { - /* buf == "DEFAULT_SLASH" */ - } - else { - /* find a top level directory we need to create */ - while ( (p = strrchr(buf + offset, DEFAULT_SLASH)) || (offset != 1 && (p = strrchr(buf, DEFAULT_SLASH))) ) { - int n = 0; - - *p = '\0'; - while (p > buf && *(p-1) == DEFAULT_SLASH) { - ++n; - --p; - *p = '\0'; - } - if (stat(buf, &sb) == 0) { - while (1) { - *p = DEFAULT_SLASH; - if (!n) break; - --n; - ++p; - } - break; - } - } - } - - if (p == buf) { - ret = mkdir(dir, mode); - } else if (!(ret = mkdir(buf, mode))) { - if (!p) { - p = buf; - } - /* create any needed directories if the creation of the 1st directory worked */ - while (++p != e) { - if (*p == '\0') { - *p = DEFAULT_SLASH; - if ((*(p+1) != '\0') && - (ret = mkdir(buf, (mode_t)mode)) < 0) { - if (options & REPORT_ERRORS) { - php_error_docref(NULL, E_WARNING, "%s", strerror(errno)); - } - break; - } - } - } - } - } - if (ret < 0) { - /* Failure */ - return 0; - } else { - /* Success */ - return 1; - } +static int php_plain_files_mkdir( + php_stream_wrapper *wrapper, const char *dir, int mode, int options, php_stream_context *context) { + int ret, recursive = options & PHP_STREAM_MKDIR_RECURSIVE; + char *p; + + if (strncasecmp(dir, "file://", sizeof("file://") - 1) == 0) { + dir += sizeof("file://") - 1; + } + + if (!recursive) { + ret = mkdir(dir, mode); + } else { + /* we look for directory separator from the end of string, thus hopefuly reducing our work load */ + char *e; + zend_stat_t sb; + int dir_len = (int) strlen(dir); + int offset = 0; + char buf[MAXPATHLEN]; + + if (!expand_filepath_with_mode(dir, buf, NULL, 0, CWD_EXPAND)) { + php_error_docref(NULL, E_WARNING, "Invalid path"); + return 0; + } + + e = buf + strlen(buf); + + if ((p = (char *) memchr(buf, DEFAULT_SLASH, dir_len))) { + offset = p - buf + 1; + } + + if (p && dir_len == 1) { + /* buf == "DEFAULT_SLASH" */ + } else { + /* find a top level directory we need to create */ + while ((p = strrchr(buf + offset, DEFAULT_SLASH)) || (offset != 1 && (p = strrchr(buf, DEFAULT_SLASH)))) { + int n = 0; + + *p = '\0'; + while (p > buf && *(p - 1) == DEFAULT_SLASH) { + ++n; + --p; + *p = '\0'; + } + if (stat(buf, &sb) == 0) { + while (1) { + *p = DEFAULT_SLASH; + if (!n) break; + --n; + ++p; + } + break; + } + } + } + + if (p == buf) { + ret = mkdir(dir, mode); + } else if (!(ret = mkdir(buf, mode))) { + if (!p) { + p = buf; + } + /* create any needed directories if the creation of the 1st directory worked */ + while (++p != e) { + if (*p == '\0') { + *p = DEFAULT_SLASH; + if ((*(p + 1) != '\0') && (ret = mkdir(buf, (mode_t) mode)) < 0) { + if (options & REPORT_ERRORS) { + php_error_docref(NULL, E_WARNING, "%s", strerror(errno)); + } + break; + } + } + } + } + } + if (ret < 0) { + /* Failure */ + return 0; + } else { + /* Success */ + return 1; + } } -static int php_plain_files_rmdir(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context) -{ - if (strncasecmp(url, "file://", sizeof("file://") - 1) == 0) { - url += sizeof("file://") - 1; - } +static int php_plain_files_rmdir(php_stream_wrapper *wrapper, + const char *url, + int options, + php_stream_context *context) { + if (strncasecmp(url, "file://", sizeof("file://") - 1) == 0) { + url += sizeof("file://") - 1; + } - if (php_check_open_basedir(url)) { - return 0; - } + if (php_check_open_basedir(url)) { + return 0; + } #ifdef PHP_WIN32 - if (!php_win32_check_trailing_space(url, (int)strlen(url))) { - php_error_docref1(NULL, url, E_WARNING, "%s", strerror(ENOENT)); - return 0; - } + if (!php_win32_check_trailing_space(url, (int) strlen(url))) { + php_error_docref1(NULL, url, E_WARNING, "%s", strerror(ENOENT)); + return 0; + } #endif - if (rmdir(url) < 0) { - php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno)); - return 0; - } + if (rmdir(url) < 0) { + php_error_docref1(NULL, url, E_WARNING, "%s", strerror(errno)); + return 0; + } - /* Clear stat cache (and realpath cache) */ - php_clear_stat_cache(1, NULL, 0); + /* Clear stat cache (and realpath cache) */ + php_clear_stat_cache(1, NULL, 0); - return 1; + return 1; } -static int php_plain_files_metadata(php_stream_wrapper *wrapper, const char *url, int option, void *value, php_stream_context *context) -{ - struct utimbuf *newtime; +static int php_plain_files_metadata( + php_stream_wrapper *wrapper, const char *url, int option, void *value, php_stream_context *context) { + struct utimbuf *newtime; #if !defined(WINDOWS) && !defined(NETWARE) - uid_t uid; - gid_t gid; + uid_t uid; + gid_t gid; #endif - mode_t mode; - int ret = 0; + mode_t mode; + int ret = 0; #ifdef PHP_WIN32 - int url_len = (int)strlen(url); + int url_len = (int) strlen(url); #endif #ifdef PHP_WIN32 - if (!php_win32_check_trailing_space(url, url_len)) { - php_error_docref1(NULL, url, E_WARNING, "%s", strerror(ENOENT)); - return 0; - } + if (!php_win32_check_trailing_space(url, url_len)) { + php_error_docref1(NULL, url, E_WARNING, "%s", strerror(ENOENT)); + return 0; + } #endif - if (strncasecmp(url, "file://", sizeof("file://") - 1) == 0) { - url += sizeof("file://") - 1; - } - - if (php_check_open_basedir(url)) { - return 0; - } - - switch(option) { - case PHP_STREAM_META_TOUCH: - newtime = (struct utimbuf *)value; - if (access(url, F_OK) != 0) { - int file = open(url, O_CREAT|O_WRONLY|O_TRUNC, 0666); - if (file == -1) { - php_error_docref1(NULL, url, E_WARNING, "Unable to create file %s because %s", url, strerror(errno)); - return 0; - } - close(file); - } - - ret = utime(url, newtime); - break; + if (strncasecmp(url, "file://", sizeof("file://") - 1) == 0) { + url += sizeof("file://") - 1; + } + + if (php_check_open_basedir(url)) { + return 0; + } + + switch (option) { + case PHP_STREAM_META_TOUCH: + newtime = (struct utimbuf *) value; + if (access(url, F_OK) != 0) { + int file = open(url, O_CREAT | O_WRONLY | O_TRUNC, 0666); + if (file == -1) { + php_error_docref1(NULL, url, E_WARNING, "Unable to create file %s because %s", url, strerror(errno)); + return 0; + } + close(file); + } + + ret = utime(url, newtime); + break; #if !defined(WINDOWS) && !defined(NETWARE) - case PHP_STREAM_META_OWNER_NAME: - case PHP_STREAM_META_OWNER: - if(option == PHP_STREAM_META_OWNER_NAME) { - if(php_get_uid_by_name((char *)value, &uid) != SUCCESS) { - php_error_docref1(NULL, url, E_WARNING, "Unable to find uid for %s", (char *)value); - return 0; - } - } else { - uid = (uid_t)*(long *)value; - } - ret = chown(url, uid, -1); - break; - case PHP_STREAM_META_GROUP: - case PHP_STREAM_META_GROUP_NAME: - if(option == PHP_STREAM_META_GROUP_NAME) { - if(php_get_gid_by_name((char *)value, &gid) != SUCCESS) { - php_error_docref1(NULL, url, E_WARNING, "Unable to find gid for %s", (char *)value); - return 0; - } - } else { - gid = (gid_t)*(long *)value; - } - ret = chown(url, -1, gid); - break; + case PHP_STREAM_META_OWNER_NAME: + case PHP_STREAM_META_OWNER: + if (option == PHP_STREAM_META_OWNER_NAME) { + if (php_get_uid_by_name((char *) value, &uid) != SUCCESS) { + php_error_docref1(NULL, url, E_WARNING, "Unable to find uid for %s", (char *) value); + return 0; + } + } else { + uid = (uid_t) * (long *) value; + } + ret = chown(url, uid, -1); + break; + case PHP_STREAM_META_GROUP: + case PHP_STREAM_META_GROUP_NAME: + if (option == PHP_STREAM_META_GROUP_NAME) { + if (php_get_gid_by_name((char *) value, &gid) != SUCCESS) { + php_error_docref1(NULL, url, E_WARNING, "Unable to find gid for %s", (char *) value); + return 0; + } + } else { + gid = (gid_t) * (long *) value; + } + ret = chown(url, -1, gid); + break; #endif - case PHP_STREAM_META_ACCESS: - mode = (mode_t)*(zend_long *)value; - ret = chmod(url, mode); - break; - default: - php_error_docref1(NULL, url, E_WARNING, "Unknown option %d for stream_metadata", option); - return 0; - } - if (ret == -1) { - php_error_docref1(NULL, url, E_WARNING, "Operation failed: %s", strerror(errno)); - return 0; - } - php_clear_stat_cache(0, NULL, 0); - return 1; + case PHP_STREAM_META_ACCESS: + mode = (mode_t) * (zend_long *) value; + ret = chmod(url, mode); + break; + default: + php_error_docref1(NULL, url, E_WARNING, "Unknown option %d for stream_metadata", option); + return 0; + } + if (ret == -1) { + php_error_docref1(NULL, url, E_WARNING, "Operation failed: %s", strerror(errno)); + return 0; + } + php_clear_stat_cache(0, NULL, 0); + return 1; } -static php_stream *_sw_php_stream_fopen_from_fd(int fd, const char *mode, const char *persistent_id STREAMS_DC) -{ +static php_stream *_sw_php_stream_fopen_from_fd(int fd, const char *mode, const char *persistent_id STREAMS_DC) { php_stream *stream = sw_php_stream_fopen_from_fd_int_rel(fd, mode, persistent_id); - if (stream) - { - php_stdio_stream_data *self = (php_stdio_stream_data*) stream->abstract; + if (stream) { + php_stdio_stream_data *self = (php_stdio_stream_data *) stream->abstract; /* detect if this is a pipe */ - if (self->fd >= 0) - { + if (self->fd >= 0) { self->is_pipe = (do_fstat(self, 0) == 0 && S_ISFIFO(self->sb.st_mode)) ? 1 : 0; } - if (self->is_pipe) - { + if (self->is_pipe) { stream->flags |= PHP_STREAM_FLAG_NO_SEEK; - } - else - { + } else { stream->position = zend_lseek(self->fd, 0, SEEK_CUR); #ifdef ESPIPE - if (stream->position == (zend_off_t) -1 && errno == ESPIPE) - { + if (stream->position == (zend_off_t) -1 && errno == ESPIPE) { stream->position = 0; stream->flags |= PHP_STREAM_FLAG_NO_SEEK; self->is_pipe = 1; @@ -1325,19 +1260,15 @@ static php_stream *_sw_php_stream_fopen_from_fd(int fd, const char *mode, const return stream; } -static void php_stream_mode_sanitize_fdopen_fopencookie(php_stream *stream, char *result) -{ +static void php_stream_mode_sanitize_fdopen_fopencookie(php_stream *stream, char *result) { /* replace modes not supported by fdopen and fopencookie, but supported * by PHP's fread(), so that their calls won't fail */ const char *cur_mode = stream->mode; int has_plus = 0, has_bin = 0, i, res_curs = 0; - if (cur_mode[0] == 'r' || cur_mode[0] == 'w' || cur_mode[0] == 'a') - { + if (cur_mode[0] == 'r' || cur_mode[0] == 'w' || cur_mode[0] == 'a') { result[res_curs++] = cur_mode[0]; - } - else - { + } else { /* assume cur_mode[0] is 'c' or 'x'; substitute by 'w', which should not * truncate anything in fdopen/fopencookie */ result[res_curs++] = 'w'; @@ -1347,49 +1278,37 @@ static void php_stream_mode_sanitize_fdopen_fopencookie(php_stream *stream, char } /* assume current mode has at most length 4 (e.g. wbn+) */ - for (i = 1; i < 4 && cur_mode[i] != '\0'; i++) - { - if (cur_mode[i] == 'b') - { + for (i = 1; i < 4 && cur_mode[i] != '\0'; i++) { + if (cur_mode[i] == 'b') { has_bin = 1; - } - else if (cur_mode[i] == '+') - { + } else if (cur_mode[i] == '+') { has_plus = 1; } /* ignore 'n', 't' or other stuff */ } - if (has_bin) - { + if (has_bin) { result[res_curs++] = 'b'; } - if (has_plus) - { + if (has_plus) { result[res_curs++] = '+'; } result[res_curs] = '\0'; } -static php_stream_wrapper_ops wrapper_ops = { - stream_opener, - NULL, - NULL, - php_plain_files_url_stater, - php_plain_files_dir_opener, - "plainfile/coroutine", - php_plain_files_unlink, - php_plain_files_rename, - php_plain_files_mkdir, - php_plain_files_rmdir, - php_plain_files_metadata -}; - -PHPAPI php_stream_wrapper sw_php_plain_files_wrapper = { - &wrapper_ops, - NULL, - 0 -}; +static php_stream_wrapper_ops wrapper_ops = {stream_opener, + NULL, + NULL, + php_plain_files_url_stater, + php_plain_files_dir_opener, + "plainfile/coroutine", + php_plain_files_unlink, + php_plain_files_rename, + php_plain_files_mkdir, + php_plain_files_rmdir, + php_plain_files_metadata}; + +PHPAPI php_stream_wrapper sw_php_plain_files_wrapper = {&wrapper_ops, NULL, 0}; /* * Local variables: From 7097eae352605ec7b308fd608dc35524d22fd3e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Sun, 17 Jan 2021 09:41:47 +0800 Subject: [PATCH 017/936] Improve Response::create() & Refactor HttpContext (#3998) * Improve Response::create() * support array * optimize code * optimize code [2] * optimize code * fix * fix 2 * fix 3 * optimize code * fix * rename * fix 3 --- ext-src/php_swoole.cc | 4 - ext-src/php_swoole.h | 6 + ext-src/php_swoole_http.h | 51 ++-- ext-src/php_swoole_http_server.h | 2 - ext-src/swoole_http2_server.cc | 38 +-- ext-src/swoole_http_request.cc | 75 +++--- ext-src/swoole_http_response.cc | 233 +++++++++++------- ext-src/swoole_http_server.cc | 73 +++--- ext-src/swoole_http_server_coro.cc | 32 ++- ext-src/swoole_websocket_server.cc | 36 ++- include/swoole_http.h | 2 + .../create_response.phpt | 58 +++++ .../create_response_2.phpt | 58 +++++ 13 files changed, 436 insertions(+), 232 deletions(-) create mode 100644 tests/swoole_http_server_coro/create_response.phpt create mode 100644 tests/swoole_http_server_coro/create_response_2.phpt diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index 9e01d113038..42681f4c30c 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -217,10 +217,6 @@ const zend_function_entry swoole_functions[] = }; // clang-format on -#if PHP_MEMORY_DEBUG -php_vmstat_t php_vmstat; -#endif - zend_class_entry *swoole_exception_ce; zend_object_handlers swoole_exception_handlers; diff --git a/ext-src/php_swoole.h b/ext-src/php_swoole.h index b3d8b2a8e24..4eb04cd1566 100644 --- a/ext-src/php_swoole.h +++ b/ext-src/php_swoole.h @@ -499,6 +499,12 @@ static sw_inline zend_bool ZVAL_IS_ARRAY(zval *v) } #endif +#ifndef ZVAL_IS_OBJECT +static sw_inline zend_bool ZVAL_IS_OBJECT(zval *v) { + return Z_TYPE_P(v) == IS_OBJECT; +} +#endif + static sw_inline zval *sw_malloc_zval() { return (zval *) emalloc(sizeof(zval)); diff --git a/ext-src/php_swoole_http.h b/ext-src/php_swoole_http.h index fa4df346673..86d8a5796a3 100644 --- a/ext-src/php_swoole_http.h +++ b/ext-src/php_swoole_http.h @@ -54,7 +54,7 @@ enum http_compress_method { }; namespace swoole { - +class Server; #ifdef SW_USE_HTTP2 class Coroutine; namespace http2 { @@ -119,15 +119,15 @@ struct Response { struct Context { SessionId fd; uchar completed : 1; - uchar end : 1; - uchar send_header : 1; + uchar end_ : 1; + uchar send_header_ : 1; #ifdef SW_HAVE_COMPRESSION uchar enable_compression : 1; uchar accept_compression : 1; #endif uchar send_chunked : 1; uchar recv_chunked : 1; - uchar send_trailer : 1; + uchar send_trailer_ : 1; uchar keepalive : 1; uchar websocket : 1; #ifdef SW_HAVE_ZLIB @@ -165,12 +165,36 @@ struct Context { size_t current_form_data_name_len; zval *current_multipart_header; - const char *upload_tmp_dir; + std::string upload_tmp_dir; void *private_data; bool (*send)(Context *ctx, const char *data, size_t length); bool (*sendfile)(Context *ctx, const char *file, uint32_t l_file, off_t offset, size_t length); bool (*close)(Context *ctx); + + void init(Server *server); + void init(coroutine::Socket *socket); + void bind(Server *server); + void bind(coroutine::Socket *socket); + void copy(Context *ctx); + bool parse_form_data(const char *boundary_str, int boundary_len); + size_t parse(const char *data, size_t length); + bool set_header(const char *, size_t, zval *, bool); + bool set_header(const char *, size_t, const char *, size_t, bool); + void end(zval *zdata, zval *return_value); + void send_trailer(zval *return_value); + String *get_write_buffer(); + +#ifdef SW_HAVE_COMPRESSION + void set_compression_method(const char *accept_encoding, size_t length); + const char *get_content_encoding(); +#endif + +#ifdef SW_USE_HTTP2 + void http2_end(zval *zdata, zval *return_value); +#endif + + void free(); }; } // namespace http @@ -191,7 +215,7 @@ class Stream { ~Stream(); bool send_header(size_t body_length, bool end_stream); - bool send_body(swString *body, bool end_stream, size_t max_frame_size, off_t offset = 0, size_t length = 0); + bool send_body(String *body, bool end_stream, size_t max_frame_size, off_t offset = 0, size_t length = 0); bool send_trailer(); void reset(uint32_t error_code); @@ -240,8 +264,6 @@ extern swoole::String *swoole_zlib_buffer; swoole::http::Context *swoole_http_context_new(swoole::SessionId fd); swoole::http::Context *php_swoole_http_request_get_and_check_context(zval *zobject); swoole::http::Context *php_swoole_http_response_get_and_check_context(zval *zobject); -void swoole_http_context_free(swoole::http::Context *ctx); -void swoole_http_context_copy(swoole::http::Context *src, swoole::http::Context *dst); static sw_inline zval *swoole_http_init_and_read_property( zend_class_entry *ce, zval *zobject, zval **zproperty_store_pp, const char *name, size_t name_len) { @@ -254,25 +276,16 @@ static sw_inline zval *swoole_http_init_and_read_property( } return *zproperty_store_pp; } -int swoole_http_parse_form_data(swoole::http::Context *ctx, const char *boundary_str, int boundary_len); + void swoole_http_parse_cookie(zval *array, const char *at, size_t length); swoole::http::Context *php_swoole_http_request_get_context(zval *zobject); void php_swoole_http_request_set_context(zval *zobject, swoole::http::Context *context); swoole::http::Context *php_swoole_http_response_get_context(zval *zobject); void php_swoole_http_response_set_context(zval *zobject, swoole::http::Context *context); -size_t swoole_http_requset_parse(swoole::http::Context *ctx, const char *data, size_t length); - -bool swoole_http_response_set_header(swoole::http::Context *, const char *, size_t, zval *, bool); -bool swoole_http_response_set_header(swoole::http::Context *, const char *, size_t, const char *, size_t, bool); - -void swoole_http_response_end(swoole::http::Context *ctx, zval *zdata, zval *return_value); -void swoole_http_response_send_trailer(swoole::http::Context *ctx, zval *return_value); #ifdef SW_HAVE_COMPRESSION int swoole_http_response_compress(const char *data, size_t length, int method, int level); -void swoole_http_get_compression_method(swoole::http::Context *ctx, const char *accept_encoding, size_t length); -const char *swoole_http_get_content_encoding(swoole::http::Context *ctx); #endif #ifdef SW_HAVE_ZLIB @@ -296,8 +309,6 @@ static sw_inline nghttp2_mem *php_nghttp2_mem() { return &mem; } -void swoole_http2_response_end(swoole::http::Context *ctx, zval *zdata, zval *return_value); - namespace swoole { namespace http2 { //-----------------------------------namespace begin-------------------------------------------- diff --git a/ext-src/php_swoole_http_server.h b/ext-src/php_swoole_http_server.h index 9edb471280f..0e9b8620711 100644 --- a/ext-src/php_swoole_http_server.h +++ b/ext-src/php_swoole_http_server.h @@ -35,8 +35,6 @@ void swoole_websocket_onOpen(swoole::http::Context *ctx); void swoole_websocket_onRequest(swoole::http::Context *ctx); bool swoole_websocket_handshake(swoole::http::Context *ctx); -void swoole_http_server_init_context(swoole::Server *serv, swoole::http::Context *ctx); - #ifdef SW_USE_HTTP2 int swoole_http2_server_onFrame(swoole::Server *serv, swoole::Connection *conn, swoole::RecvData *req); diff --git a/ext-src/swoole_http2_server.cc b/ext-src/swoole_http2_server.cc index 41c21ea3d7d..c7736b0b5e7 100644 --- a/ext-src/swoole_http2_server.cc +++ b/ext-src/swoole_http2_server.cc @@ -40,7 +40,7 @@ static bool swoole_http2_server_respond(http_context *ctx, String *body); Http2Stream::Stream(Http2Session *client, uint32_t _id) { ctx = swoole_http_context_new(client->fd); - swoole_http_context_copy(client->default_ctx, ctx); + ctx->copy(client->default_ctx); ctx->http2 = true; ctx->stream = this; ctx->keepalive = true; @@ -51,8 +51,8 @@ Http2Stream::Stream(Http2Session *client, uint32_t _id) { Http2Stream::~Stream() { ctx->stream = nullptr; - ctx->end = true; - swoole_http_context_free(ctx); + ctx->end_ = true; + ctx->free(); } void Http2Stream::reset(uint32_t error_code) { @@ -87,7 +87,7 @@ Http2Session::~Session() { nghttp2_hd_deflate_del(deflater); } if (default_ctx) { - efree(default_ctx); + delete default_ctx; } http2_sessions.erase(fd); } @@ -172,7 +172,7 @@ static bool swoole_http2_is_static_file(Server *serv, http_context *ctx) { auto date_str_last_modified = handler.get_date_last_modified(); zval *zheader = ctx->request.zserver; - swoole_http_response_set_header(ctx, ZEND_STRL("Last-Modified"), date_str.c_str(), date_str.length(), 0); + ctx->set_header(ZEND_STRL("Last-Modified"), date_str.c_str(), date_str.length(), 0); zval *zdate_if_modified_since = zend_hash_str_find(Z_ARR_P(zheader), ZEND_STRL("if-modified-since")); if (zdate_if_modified_since) { @@ -244,7 +244,7 @@ static ssize_t http2_build_header(http_context *ctx, uchar *buffer, size_t body_ char intbuf[2][16]; int ret; - assert(ctx->send_header == 0); + assert(ctx->send_header_ == 0); // status code if (ctx->response.status == 0) { @@ -314,7 +314,7 @@ static ssize_t http2_build_header(http_context *ctx, uchar *buffer, size_t body_ // content encoding #ifdef SW_HAVE_COMPRESSION if (ctx->accept_compression) { - const char *content_encoding = swoole_http_get_content_encoding(ctx); + const char *content_encoding = ctx->get_content_encoding(); headers.add(ZEND_STRL("content-encoding"), (char *) content_encoding, strlen(content_encoding)); } #endif @@ -353,7 +353,7 @@ static ssize_t http2_build_header(http_context *ctx, uchar *buffer, size_t body_ return -1; } - ctx->send_header = 1; + ctx->send_header_ = 1; return rv; } @@ -416,7 +416,7 @@ bool Http2Stream::send_header(size_t body_length, bool end_stream) { swoole_http_buffer->append(header_buffer, bytes); if (!ctx->send(ctx, swoole_http_buffer->str, swoole_http_buffer->length)) { - ctx->send_header = 0; + ctx->send_header_ = 0; return false; } @@ -503,7 +503,7 @@ static bool swoole_http2_server_respond(http_context *ctx, String *body) { } // The headers has already been sent, retries are no longer allowed (even if send body failed) - ctx->end = 1; + ctx->end_ = 1; bool error = false; @@ -602,7 +602,7 @@ static bool http2_context_sendfile(http_context *ctx, const char *file, uint32_t } const char *mimetype = swoole::mime_type::get(file).c_str(); - swoole_http_response_set_header(ctx, ZEND_STRL("content-type"), mimetype, strlen(mimetype), 0); + ctx->set_header(ZEND_STRL("content-type"), mimetype, strlen(mimetype), 0); bool end_stream = (ztrailer == nullptr); if (!stream->send_header(length, end_stream)) { @@ -610,7 +610,7 @@ static bool http2_context_sendfile(http_context *ctx, const char *file, uint32_t } /* headers has already been sent, retries are no longer allowed (even if send body failed) */ - ctx->end = 1; + ctx->end_ = 1; bool error = false; @@ -725,7 +725,7 @@ static int http2_parse_header(Http2Session *client, http_context *ctx, int flags swWarn("invalid multipart/form-data body fd:%ld", ctx->fd); return SW_ERR; } - swoole_http_parse_form_data(ctx, (char *) nv.value + nv.valuelen - boundary_len, boundary_len); + ctx->parse_form_data((char *) nv.value + nv.valuelen - boundary_len, boundary_len); ctx->parser.data = ctx; } } else if (SW_STRCASEEQ((char *) nv.name, nv.namelen, "cookie")) { @@ -738,7 +738,7 @@ static int http2_parse_header(Http2Session *client, http_context *ctx, int flags } #ifdef SW_HAVE_COMPRESSION else if (ctx->enable_compression && SW_STRCASEEQ((char *) nv.name, nv.namelen, "accept-encoding")) { - swoole_http_get_compression_method(ctx, (char *) nv.value, nv.valuelen); + ctx->set_compression_method((char *) nv.value, nv.valuelen); } #endif add_assoc_stringl_ex(zheader, (char *) nv.name, nv.namelen, (char *) nv.value, nv.valuelen); @@ -996,8 +996,8 @@ int swoole_http2_server_onFrame(Server *serv, Connection *conn, RecvData *req) { client->handle = swoole_http2_onRequest; if (!client->default_ctx) { - client->default_ctx = (http_context *) ecalloc(1, sizeof(http_context)); - swoole_http_server_init_context(serv, client->default_ctx); + client->default_ctx = new http_context(); + client->default_ctx->init(serv); client->default_ctx->fd = session_id; client->default_ctx->http2 = true; client->default_ctx->stream = (Http2Stream *) -1; @@ -1022,8 +1022,8 @@ void swoole_http2_server_session_free(Connection *conn) { delete client; } -void swoole_http2_response_end(http_context *ctx, zval *zdata, zval *return_value) { - swString http_body = {}; +void http_context::http2_end(zval *zdata, zval *return_value) { + String http_body = {}; if (zdata) { http_body.length = php_swoole_get_send_data(zdata, &http_body.str); } else { @@ -1031,7 +1031,7 @@ void swoole_http2_response_end(http_context *ctx, zval *zdata, zval *return_valu http_body.str = nullptr; } - RETURN_BOOL(swoole_http2_server_respond(ctx, &http_body)); + RETURN_BOOL(swoole_http2_server_respond(this, &http_body)); } #endif diff --git a/ext-src/swoole_http_request.cc b/ext-src/swoole_http_request.cc index 07746068215..bc381f2959f 100644 --- a/ext-src/swoole_http_request.cc +++ b/ext-src/swoole_http_request.cc @@ -52,6 +52,9 @@ enum http_upload_errno { using http_request = swoole::http::Request; using http_context = swoole::http::Context; +using swoole::Server; +using swoole::Connection; +using swoole::ListenPort; using swoole::microtime; static int http_request_on_path(swoole_http_parser *parser, const char *at, size_t length); @@ -133,8 +136,8 @@ static const multipart_parser_settings mt_parser_settings = }; // clang-format on -size_t swoole_http_requset_parse(http_context *ctx, const char *data, size_t length) { - return swoole_http_parser_execute(&ctx->parser, &http_parser_settings, data, length); +size_t http_context::parse(const char *data, size_t length) { + return swoole_http_parser_execute(&parser, &http_parser_settings, data, length); } zend_class_entry *swoole_http_request_ce; @@ -179,7 +182,7 @@ static void php_swoole_http_request_free_object(zend_object *object) { } if (ctx) { ctx->request.zobject = nullptr; - swoole_http_context_free(ctx); + ctx->free(); } zend_object_std_dtor(&request->std); @@ -272,17 +275,15 @@ static int http_request_on_header_field(swoole_http_parser *parser, const char * return 0; } -int swoole_http_parse_form_data(http_context *ctx, const char *boundary_str, int boundary_len) { - multipart_parser *mt_parser = multipart_parser_init(boundary_str, boundary_len, &mt_parser_settings); +bool http_context::parse_form_data(const char *boundary_str, int boundary_len) { + mt_parser = multipart_parser_init(boundary_str, boundary_len, &mt_parser_settings); if (!mt_parser) { php_swoole_fatal_error(E_WARNING, "multipart_parser_init() failed"); - return SW_ERR; + return false; } - ctx->mt_parser = mt_parser; - mt_parser->data = ctx; - - return SW_OK; + mt_parser->data = this; + return true; } void swoole_http_parse_cookie(zval *zarray, const char *at, size_t length) { @@ -388,14 +389,14 @@ static int http_request_on_header_value(swoole_http_parser *parser, const char * if (ctx->co_socket) { goto _add_header; } - swServer *serv = (swServer *) ctx->private_data; - swConnection *conn = serv->get_connection_by_session_id(ctx->fd); + Server *serv = (Server *) ctx->private_data; + Connection *conn = serv->get_connection_by_session_id(ctx->fd); if (!conn) { swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_CLOSED, "session[%ld] is closed", ctx->fd); efree(header_name); return -1; } - swListenPort *port = serv->get_port_by_server_fd(conn->server_fd); + ListenPort *port = serv->get_port_by_server_fd(conn->server_fd); if (port->open_websocket_protocol) { conn->websocket_status = WEBSOCKET_STATUS_CONNECTION; } @@ -434,12 +435,12 @@ static int http_request_on_header_value(swoole_http_parser *parser, const char * boundary_len -= 2; } swTraceLog(SW_TRACE_HTTP, "form_data, boundary_str=%s", boundary_str); - swoole_http_parse_form_data(ctx, boundary_str, boundary_len); + ctx->parse_form_data(boundary_str, boundary_len); } } #ifdef SW_HAVE_COMPRESSION else if (ctx->enable_compression && SW_STREQ(header_name, header_len, "accept-encoding")) { - swoole_http_get_compression_method(ctx, at, length); + ctx->set_compression_method(at, length); } #endif else if (SW_STREQ(header_name, header_len, "transfer-encoding") && SW_STRCASECT(at, length, "chunked")) { @@ -645,7 +646,7 @@ static int multipart_body_on_header_complete(multipart_parser *p) { } char file_path[SW_HTTP_UPLOAD_TMPDIR_SIZE]; - sw_snprintf(file_path, SW_HTTP_UPLOAD_TMPDIR_SIZE, "%s/swoole.upfile.XXXXXX", ctx->upload_tmp_dir); + sw_snprintf(file_path, SW_HTTP_UPLOAD_TMPDIR_SIZE, "%s/swoole.upfile.XXXXXX", ctx->upload_tmp_dir.c_str()); int tmpfile = swoole_tmpfile(file_path); if (tmpfile < 0) { return 0; @@ -817,32 +818,32 @@ static int http_request_message_complete(swoole_http_parser *parser) { } #ifdef SW_HAVE_COMPRESSION -void swoole_http_get_compression_method(http_context *ctx, const char *accept_encoding, size_t length) { +void http_context::set_compression_method(const char *accept_encoding, size_t length) { #ifdef SW_HAVE_BROTLI if (swoole_strnpos(accept_encoding, length, ZEND_STRL("br")) >= 0) { - ctx->accept_compression = 1; - ctx->compression_method = HTTP_COMPRESS_BR; + accept_compression = 1; + compression_method = HTTP_COMPRESS_BR; } else #endif if (swoole_strnpos(accept_encoding, length, ZEND_STRL("gzip")) >= 0) { - ctx->accept_compression = 1; - ctx->compression_method = HTTP_COMPRESS_GZIP; + accept_compression = 1; + compression_method = HTTP_COMPRESS_GZIP; } else if (swoole_strnpos(accept_encoding, length, ZEND_STRL("deflate")) >= 0) { - ctx->accept_compression = 1; - ctx->compression_method = HTTP_COMPRESS_DEFLATE; + accept_compression = 1; + compression_method = HTTP_COMPRESS_DEFLATE; } else { - ctx->accept_compression = 0; + accept_compression = 0; } } -const char *swoole_http_get_content_encoding(http_context *ctx) { - if (ctx->compression_method == HTTP_COMPRESS_GZIP) { +const char *http_context::get_content_encoding() { + if (compression_method == HTTP_COMPRESS_GZIP) { return "gzip"; - } else if (ctx->compression_method == HTTP_COMPRESS_DEFLATE) { + } else if (compression_method == HTTP_COMPRESS_DEFLATE) { return "deflate"; } #ifdef SW_HAVE_BROTLI - else if (ctx->compression_method == HTTP_COMPRESS_BR) { + else if (compression_method == HTTP_COMPRESS_BR) { return "br"; } #endif @@ -902,7 +903,7 @@ static PHP_METHOD(swoole_http_request, create) { Z_PARAM_ARRAY(zoptions) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - http_context *ctx = (http_context *) ecalloc(1, sizeof(http_context)); + http_context *ctx = new http_context(); object_init_ex(return_value, swoole_http_request_ce); zval *zrequest_object = &ctx->request._zobject; ctx->request.zobject = zrequest_object; @@ -932,14 +933,22 @@ static PHP_METHOD(swoole_http_request, create) { } else if (SW_STRCASEEQ(key, keylen, "parse_files")) { ctx->parse_files = zval_is_true(zvalue); } - #ifdef SW_HAVE_COMPRESSION +#ifdef SW_HAVE_COMPRESSION else if (SW_STRCASEEQ(key, keylen, "enable_compression")) { ctx->enable_compression = zval_is_true(zvalue); } else if (SW_STRCASEEQ(key, keylen, "compression_level")) { ctx->compression_level = zval_get_long(zvalue); } - #endif - (void)keytype; +#endif +#ifdef SW_HAVE_ZLIB + else if (SW_STRCASEEQ(key, keylen, "websocket_compression")) { + ctx->websocket_compression = zval_is_true(zvalue); + } +#endif + else if (SW_STRCASEEQ(key, keylen, "upload_tmp_dir")) { + ctx->upload_tmp_dir = zend::String(zvalue).to_std_string(); + } + (void) keytype; } SW_HASHTABLE_FOREACH_END(); } @@ -980,7 +989,7 @@ static PHP_METHOD(swoole_http_request, parse) { ZVAL_STR(&ctx->request.zdata, new_str); } - RETURN_LONG(swoole_http_requset_parse(ctx, str, l_str)); + RETURN_LONG(ctx->parse(str, l_str)); } static PHP_METHOD(swoole_http_request, getMethod) { diff --git a/ext-src/swoole_http_response.cc b/ext-src/swoole_http_response.cc index a32b8a723e4..c391568d0f3 100644 --- a/ext-src/swoole_http_response.cc +++ b/ext-src/swoole_http_response.cc @@ -41,6 +41,7 @@ extern "C" { using swoole::coroutine::Socket; using swoole::Server; using swoole::Connection; +using swoole::String; using swoole::substr_len; using http_response = swoole::http::Response; using http_context = swoole::http::Context; @@ -86,9 +87,9 @@ static inline bool http_has_crlf(const char *value, size_t length) { return false; } -static inline swString *http_get_write_buffer(http_context *ctx) { - if (ctx->co_socket) { - swString *buffer = ((Socket *) ctx->private_data)->get_write_buffer(); +String *http_context::get_write_buffer() { + if (co_socket) { + String *buffer = ((Socket *) private_data)->get_write_buffer(); if (buffer != nullptr) { return buffer; } @@ -119,7 +120,7 @@ static void php_swoole_http_response_free_object(zend_object *object) { zval ztmp; /* bool, not required to release it */ if (ctx) { - if (!ctx->end && !ctx->detached && sw_reactor()) { + if (!ctx->end_ && !ctx->detached && sw_reactor()) { if (ctx->response.status == 0) { ctx->response.status = SW_HTTP_INTERNAL_SERVER_ERROR; } @@ -127,24 +128,24 @@ static void php_swoole_http_response_free_object(zend_object *object) { #ifdef SW_USE_HTTP2 if (ctx->http2) { if (ctx->stream) { - swoole_http2_response_end(ctx, nullptr, &ztmp); + ctx->http2_end(nullptr, &ztmp); } } else #endif { if (ctx->co_socket) { - swoole_http_response_end(ctx, nullptr, &ztmp); + ctx->end(nullptr, &ztmp); } else { - swServer *serv = (swServer *) ctx->private_data; - swConnection *conn = serv->get_connection_by_session_id(ctx->fd); + Server *serv = (Server *) ctx->private_data; + Connection *conn = serv->get_connection_by_session_id(ctx->fd); if (conn && !conn->closed && !conn->peer_closed) { - swoole_http_response_end(ctx, nullptr, &ztmp); + ctx->end(nullptr, &ztmp); } } } } ctx->response.zobject = nullptr; - swoole_http_context_free(ctx); + ctx->free(); } zend_object_std_dtor(&response->std); @@ -326,15 +327,15 @@ static PHP_METHOD(swoole_http_response, write) { ctx->accept_compression = 0; #endif - swString *http_buffer = http_get_write_buffer(ctx); + String *http_buffer = ctx->get_write_buffer(); - if (!ctx->send_header) { + if (!ctx->send_header_) { ctx->send_chunked = 1; http_buffer->clear(); http_build_header(ctx, http_buffer, 0); if (!ctx->send(ctx, http_buffer->str, http_buffer->length)) { ctx->send_chunked = 0; - ctx->send_header = 0; + ctx->send_header_ = 0; RETURN_FALSE; } } @@ -394,7 +395,7 @@ static void http_build_header(http_context *ctx, swString *response, size_t body int n; char *date_str; - assert(ctx->send_header == 0); + assert(ctx->send_header_ == 0); /** * http status line @@ -479,7 +480,7 @@ static void http_build_header(http_context *ctx, swString *response, size_t body // websocket protocol (subsequent header info is unnecessary) if (ctx->upgrade == 1) { response->append(ZEND_STRL("\r\n")); - ctx->send_header = 1; + ctx->send_header_ = 1; return; } @@ -519,14 +520,14 @@ static void http_build_header(http_context *ctx, swString *response, size_t body #ifdef SW_HAVE_COMPRESSION // http compress if (ctx->accept_compression) { - const char *content_encoding = swoole_http_get_content_encoding(ctx); + const char *content_encoding = ctx->get_content_encoding(); response->append(ZEND_STRL("Content-Encoding: ")); response->append((char *) content_encoding, strlen(content_encoding)); response->append(ZEND_STRL("\r\n")); } #endif response->append(ZEND_STRL("\r\n")); - ctx->send_header = 1; + ctx->send_header_ = 1; } static ssize_t http_build_trailer(http_context *ctx, swString *response) { @@ -707,7 +708,7 @@ static PHP_METHOD(swoole_http_response, initHeader) { static PHP_METHOD(swoole_http_response, isWritable) { http_context *ctx = php_swoole_http_response_get_context(ZEND_THIS); - if (!ctx || (ctx->end || ctx->detached)) { + if (!ctx || (ctx->end_ || ctx->detached)) { RETURN_FALSE; } RETURN_TRUE; @@ -728,29 +729,29 @@ static PHP_METHOD(swoole_http_response, end) { #ifdef SW_USE_HTTP2 if (ctx->http2) { - swoole_http2_response_end(ctx, zdata, return_value); + ctx->http2_end(zdata, return_value); } else #endif { - swoole_http_response_end(ctx, zdata, return_value); + ctx->end(zdata, return_value); } } -void swoole_http_response_send_trailer(http_context *ctx, zval *return_value) { - swString *http_buffer = http_get_write_buffer(ctx); +void http_context::send_trailer(zval *return_value) { + String *http_buffer = get_write_buffer(); http_buffer->clear(); - if (http_build_trailer(ctx, http_buffer) == 0) { + if (http_build_trailer(this, http_buffer) == 0) { return; } - if (!ctx->send(ctx, http_buffer->str, http_buffer->length)) { - ctx->end = 1; - ctx->close(ctx); + if (!send(this, http_buffer->str, http_buffer->length)) { + end_ = 1; + close(this); RETURN_FALSE; } } -void swoole_http_response_end(http_context *ctx, zval *zdata, zval *return_value) { +void http_context::end(zval *zdata, zval *return_value) { struct { char *str; size_t length; @@ -762,42 +763,42 @@ void swoole_http_response_end(http_context *ctx, zval *zdata, zval *return_value http_body.str = nullptr; } - if (ctx->send_chunked) { - if (ctx->send_trailer) { - if (!ctx->send(ctx, ZEND_STRL("0\r\n"))) { + if (send_chunked) { + if (send_trailer_) { + if (!send(this, ZEND_STRL("0\r\n"))) { RETURN_FALSE; } - swoole_http_response_send_trailer(ctx, return_value); - ctx->send_trailer = 0; + send_trailer(return_value); + send_trailer_ = 0; } else { - if (!ctx->send(ctx, ZEND_STRL("0\r\n\r\n"))) { + if (!send(this, ZEND_STRL("0\r\n\r\n"))) { RETURN_FALSE; } } - ctx->send_chunked = 0; + send_chunked = 0; } // no http chunk else { - swString *http_buffer = http_get_write_buffer(ctx); + String *http_buffer = get_write_buffer(); http_buffer->clear(); #ifdef SW_HAVE_COMPRESSION - if (ctx->accept_compression) { + if (accept_compression) { if (http_body.length == 0 || swoole_http_response_compress( - http_body.str, http_body.length, ctx->compression_method, ctx->compression_level) != SW_OK) { - ctx->accept_compression = 0; + http_body.str, http_body.length, compression_method, compression_level) != SW_OK) { + accept_compression = 0; } } #endif - http_build_header(ctx, http_buffer, http_body.length); + http_build_header(this, http_buffer, http_body.length); char *send_body_str; size_t send_body_len; if (http_body.length > 0) { #ifdef SW_HAVE_COMPRESSION - if (ctx->accept_compression) { + if (accept_compression) { send_body_str = swoole_zlib_buffer->str; send_body_len = swoole_zlib_buffer->length; } else @@ -814,19 +815,19 @@ void swoole_http_response_end(http_context *ctx, zval *zdata, zval *return_value #endif { if (http_buffer->append(send_body_str, send_body_len) < 0) { - ctx->send_header = 0; + send_header_ = 0; RETURN_FALSE; } } #ifdef SW_HTTP_SEND_TWICE else { - if (!ctx->send(ctx, http_buffer->str, http_buffer->length)) { - ctx->send_header = 0; + if (!send(this, http_buffer->str, http_buffer->length)) { + send_header_ = 0; RETURN_FALSE; } - if (!ctx->send(ctx, send_body_str, send_body_len)) { - ctx->end = 1; - ctx->close(ctx); + if (!send(this, send_body_str, send_body_len)) { + end_ = 1; + close(this); RETURN_FALSE; } goto _skip_copy; @@ -834,9 +835,9 @@ void swoole_http_response_end(http_context *ctx, zval *zdata, zval *return_value #endif } - if (!ctx->send(ctx, http_buffer->str, http_buffer->length)) { - ctx->end = 1; - ctx->close(ctx); + if (!send(this, http_buffer->str, http_buffer->length)) { + end_ = 1; + close(this); RETURN_FALSE; } } @@ -844,34 +845,34 @@ void swoole_http_response_end(http_context *ctx, zval *zdata, zval *return_value #ifdef SW_HTTP_SEND_TWICE _skip_copy: #endif - if (ctx->upgrade && !ctx->co_socket) { - Server *serv = (Server *) ctx->private_data; - Connection *conn = serv->get_connection_verify(ctx->fd); + if (upgrade && !co_socket) { + Server *serv = (Server *) private_data; + Connection *conn = serv->get_connection_verify(fd); if (conn && conn->websocket_status == WEBSOCKET_STATUS_HANDSHAKE) { - if (ctx->response.status == 101) { + if (response.status == 101) { conn->websocket_status = WEBSOCKET_STATUS_ACTIVE; } else { /* connection should be closed when handshake failed */ conn->websocket_status = WEBSOCKET_STATUS_NONE; - ctx->keepalive = 0; + keepalive = 0; } } } - if (!ctx->keepalive) { - ctx->close(ctx); + if (!keepalive) { + close(this); } - ctx->end = 1; + end_ = 1; RETURN_TRUE; } -bool swoole_http_response_set_header(http_context *ctx, const char *k, size_t klen, const char *v, size_t vlen, bool format) { +bool http_context::set_header(const char *k, size_t klen, const char *v, size_t vlen, bool format) { zval ztmp; ZVAL_STRINGL(&ztmp, v, vlen); Z_ADDREF(ztmp); - return swoole_http_response_set_header(ctx, k, klen, &ztmp, format); + return set_header(k, klen, &ztmp, format); } -bool swoole_http_response_set_header(http_context *ctx, const char *k, size_t klen, zval *zvalue, bool format) { +bool http_context::set_header(const char *k, size_t klen, zval *zvalue, bool format) { if (UNEXPECTED(klen > SW_HTTP_HEADER_KEY_SIZE - 1)) { php_swoole_error(E_WARNING, "header key is too long"); Z_TRY_DELREF_P(zvalue); @@ -884,11 +885,11 @@ bool swoole_http_response_set_header(http_context *ctx, const char *k, size_t kl } zval *zheader = swoole_http_init_and_read_property( - swoole_http_response_ce, ctx->response.zobject, &ctx->response.zheader, ZEND_STRL("header")); + swoole_http_response_ce, response.zobject, &response.zheader, ZEND_STRL("header")); if (format) { swoole_strlcpy(sw_tg_buffer()->str, k, SW_HTTP_HEADER_KEY_SIZE); #ifdef SW_USE_HTTP2 - if (ctx->http2) { + if (http2) { swoole_strtolower(sw_tg_buffer()->str, klen); } else #endif @@ -946,11 +947,11 @@ static PHP_METHOD(swoole_http_response, sendfile) { #ifdef SW_USE_HTTP2 if (!ctx->http2) #endif - if (!ctx->send_header) { + if (!ctx->send_header_) { #ifdef SW_HAVE_COMPRESSION ctx->accept_compression = 0; #endif - swString *http_buffer = http_get_write_buffer(ctx); + String *http_buffer = ctx->get_write_buffer(); http_buffer->clear(); @@ -963,7 +964,7 @@ static PHP_METHOD(swoole_http_response, sendfile) { http_build_header(ctx, http_buffer, length); if (!ctx->send(ctx, http_buffer->str, http_buffer->length)) { - ctx->send_header = 0; + ctx->send_header_ = 0; RETURN_FALSE; } } @@ -975,7 +976,7 @@ static PHP_METHOD(swoole_http_response, sendfile) { } } - ctx->end = 1; + ctx->end_ = 1; if (!ctx->keepalive) { ctx->close(ctx); @@ -1132,7 +1133,7 @@ static PHP_METHOD(swoole_http_response, header) { RETURN_FALSE; } Z_TRY_ADDREF_P(zvalue); - RETURN_BOOL(swoole_http_response_set_header(ctx, k, klen, zvalue, format)); + RETURN_BOOL(ctx->set_header(k, klen, zvalue, format)); } #ifdef SW_USE_HTTP2 @@ -1163,7 +1164,7 @@ static PHP_METHOD(swoole_http_response, trailer) { } else { add_assoc_stringl_ex(ztrailer, key_buf, klen, v, vlen); } - ctx->send_trailer = 1; + ctx->send_trailer_ = 1; RETURN_TRUE; } @@ -1239,7 +1240,7 @@ static PHP_METHOD(swoole_http_response, push) { flags = zval_get_long(zflags); } - swString *http_buffer = http_get_write_buffer(ctx); + String *http_buffer = ctx->get_write_buffer(); http_buffer->clear(); if (php_swoole_websocket_frame_is_object(zdata)) { if (php_swoole_websocket_frame_object_pack(http_buffer, zdata, 0, ctx->websocket_compression) < 0) { @@ -1314,40 +1315,84 @@ static PHP_METHOD(swoole_http_response, detach) { } static PHP_METHOD(swoole_http_response, create) { - zval *zserver = nullptr; - zend_long fd; - swServer *serv; + zval *zobject = nullptr; + zval *zrequest = nullptr; + zend_long fd = -1; + Server *serv = nullptr; + Socket *sock = nullptr; + http_context *ctx = nullptr; - if (ZEND_NUM_ARGS() == 1) { - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_LONG(fd) - ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_ZVAL(zobject) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(fd) + ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - serv = sw_server(); + if (ZVAL_IS_OBJECT(zobject)) { + _type_detect: + if (instanceof_function(Z_OBJCE_P(zobject), swoole_server_ce)) { + serv = php_swoole_server_get_and_check_server(zobject); + if (serv->get_connection_verify(fd) == nullptr) { + php_swoole_fatal_error(E_WARNING, "parameter $2 must be valid connection session id"); + RETURN_FALSE; + } + } else if (instanceof_function(Z_OBJCE_P(zobject), swoole_socket_coro_ce)) { + sock = php_swoole_get_socket(zobject); + fd = sock->get_fd(); + } else { + _bad_type: + php_swoole_fatal_error(E_WARNING, "parameter $1 must be instanceof Server or Coroutine\\Socket"); + RETURN_FALSE; + } + } else if (ZVAL_IS_ARRAY(zobject)) { + zrequest = zend_hash_index_find(Z_ARR_P(zobject), 1); + if (!ZVAL_IS_OBJECT(zrequest) || !instanceof_function(Z_OBJCE_P(zrequest), swoole_http_request_ce)) { + php_swoole_fatal_error(E_WARNING, "parameter $1.second must be instanceof Http\\Request"); + RETURN_FALSE; + } + zobject = zend_hash_index_find(Z_ARR_P(zobject), 0); + if (!ZVAL_IS_OBJECT(zobject)) { + goto _bad_type; + } else { + ctx = php_swoole_http_request_get_context(zrequest); + goto _type_detect; + } } else { - ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_OBJECT_OF_CLASS(zserver, swoole_server_ce) - Z_PARAM_LONG(fd) - ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - - serv = php_swoole_server_get_and_check_server(zserver); + fd = zval_get_long(zobject); + serv = sw_server(); } - if (serv == nullptr || !serv->is_started()) { + if (serv && !serv->is_started()) { php_swoole_fatal_error(E_WARNING, "server is not running"); RETURN_FALSE; } - http_context *ctx = (http_context *) ecalloc(1, sizeof(http_context)); if (!ctx) { - RETURN_FALSE; + ctx = new http_context(); + ctx->fd = fd; + ctx->keepalive = 1; + + if (serv) { + ctx->init(serv); + } else if (sock) { + ctx->init(sock); + ctx->parser.data = ctx; + swoole_http_parser_init(&ctx->parser, PHP_HTTP_REQUEST); + } else { + assert(0); + RETURN_FALSE; + } + } else { + if (serv) { + ctx->bind(serv); + } else if (sock) { + ctx->bind(sock); + } else { + assert(0); + RETURN_FALSE; + } } - ctx->fd = fd; - ctx->keepalive = 1; - - swoole_http_server_init_context(sw_server(), ctx); - if (sw_unlikely(swoole_http_buffer == nullptr)) { php_swoole_http_server_init_global_variant(); } @@ -1356,8 +1401,10 @@ static PHP_METHOD(swoole_http_response, create) { php_swoole_http_response_set_context(return_value, ctx); ctx->response.zobject = return_value; sw_copy_to_stack(ctx->response.zobject, ctx->response._zobject); - zend_update_property_long(swoole_http_response_ce, SW_Z8_OBJ_P(return_value), ZEND_STRL("fd"), fd); + if (ctx->co_socket) { + zend_update_property(swoole_http_response_ce, SW_Z8_OBJ_P(ctx->response.zobject), ZEND_STRL("socket"), zobject); + } } static PHP_METHOD(swoole_http_response, redirect) { @@ -1389,7 +1436,7 @@ static PHP_METHOD(swoole_http_response, redirect) { if (!Z_BVAL_P(return_value)) { return; } - swoole_http_response_end(ctx, nullptr, return_value); + ctx->end(nullptr, return_value); } static PHP_METHOD(swoole_http_response, __destruct) {} diff --git a/ext-src/swoole_http_server.cc b/ext-src/swoole_http_server.cc index a44269dbf05..b68e8d82561 100644 --- a/ext-src/swoole_http_server.cc +++ b/ext-src/swoole_http_server.cc @@ -64,7 +64,7 @@ int php_swoole_http_onReceive(Server *serv, RecvData *req) { #endif http_context *ctx = swoole_http_context_new(session_id); - swoole_http_server_init_context(serv, ctx); + ctx->init(serv); zval *zdata = &ctx->request.zdata; php_swoole_get_recv_data(serv, zdata, req); @@ -84,7 +84,7 @@ int php_swoole_http_onReceive(Server *serv, RecvData *req) { parser->data = ctx; swoole_http_parser_init(parser, PHP_HTTP_REQUEST); - size_t parsed_n = swoole_http_requset_parse(ctx, Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)); + size_t parsed_n = ctx->parse(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)); if (ctx->parser.state == s_dead) { #ifdef SW_HTTP_BAD_REQUEST_PACKET ctx->send(ctx, SW_STRL(SW_HTTP_BAD_REQUEST_PACKET)); @@ -164,7 +164,7 @@ void php_swoole_http_server_minit(int module_number) { } http_context *swoole_http_context_new(SessionId fd) { - http_context *ctx = (http_context *) ecalloc(1, sizeof(http_context)); + http_context *ctx = new http_context(); zval *zrequest_object = &ctx->request._zobject; ctx->request.zobject = zrequest_object; @@ -179,10 +179,6 @@ http_context *swoole_http_context_new(SessionId fd) { zend_update_property_long(swoole_http_request_ce, SW_Z8_OBJ_P(zrequest_object), ZEND_STRL("fd"), fd); zend_update_property_long(swoole_http_response_ce, SW_Z8_OBJ_P(zresponse_object), ZEND_STRL("fd"), fd); -#if PHP_MEMORY_DEBUG - php_vmstat.new_http_request++; -#endif - swoole_http_init_and_read_property( swoole_http_request_ce, zrequest_object, &ctx->request.zserver, ZEND_STRL("server")); swoole_http_init_and_read_property( @@ -192,49 +188,54 @@ http_context *swoole_http_context_new(SessionId fd) { return ctx; } -void swoole_http_server_init_context(Server *serv, http_context *ctx) { - ctx->parse_cookie = serv->http_parse_cookie; - ctx->parse_body = serv->http_parse_post; - ctx->parse_files = serv->http_parse_files; +void http_context::init(Server *serv) { + parse_cookie = serv->http_parse_cookie; + parse_body = serv->http_parse_post; + parse_files = serv->http_parse_files; #ifdef SW_HAVE_COMPRESSION - ctx->enable_compression = serv->http_compression; - ctx->compression_level = serv->http_compression_level; + enable_compression = serv->http_compression; + compression_level = serv->http_compression_level; #endif - ctx->private_data = serv; - ctx->upload_tmp_dir = serv->upload_tmp_dir.c_str(); - ctx->send = http_context_send_data; - ctx->sendfile = http_context_sendfile; - ctx->close = http_context_disconnect; + upload_tmp_dir = serv->upload_tmp_dir; + bind(serv); +} + +void http_context::bind(Server *serv) { + private_data = serv; + send = http_context_send_data; + sendfile = http_context_sendfile; + close = http_context_disconnect; } -void swoole_http_context_copy(http_context *src, http_context *dst) { - dst->parse_cookie = src->parse_cookie; - dst->parse_body = src->parse_body; - dst->parse_files = src->parse_files; +void http_context::copy(http_context *ctx) { + parse_cookie = ctx->parse_cookie; + parse_body = ctx->parse_body; + parse_files = ctx->parse_files; #ifdef SW_HAVE_COMPRESSION - dst->enable_compression = src->enable_compression; - dst->compression_level = src->compression_level; + enable_compression = ctx->enable_compression; + compression_level = ctx->compression_level; #endif - dst->private_data = src->private_data; - dst->upload_tmp_dir = src->upload_tmp_dir; - dst->send = src->send; - dst->sendfile = src->sendfile; - dst->close = src->close; + co_socket = ctx->co_socket; + private_data = ctx->private_data; + upload_tmp_dir = ctx->upload_tmp_dir; + send = ctx->send; + sendfile = ctx->sendfile; + close = ctx->close; } -void swoole_http_context_free(http_context *ctx) { +void http_context::free() { /* http context can only be free'd after request and response were free'd */ - if (ctx->request.zobject || ctx->response.zobject) { + if (request.zobject || response.zobject) { return; } #ifdef SW_USE_HTTP2 - if (ctx->stream) { + if (stream) { return; } #endif - http_request *req = &ctx->request; - http_response *res = &ctx->response; + http_request *req = &request; + http_response *res = &response; if (req->path) { efree(req->path); } @@ -252,7 +253,7 @@ void swoole_http_context_free(http_context *ctx) { if (res->reason) { efree(res->reason); } - efree(ctx); + delete this; } void php_swoole_http_server_init_global_variant() { @@ -275,7 +276,7 @@ http_context *php_swoole_http_request_get_and_check_context(zval *zobject) { http_context *php_swoole_http_response_get_and_check_context(zval *zobject) { http_context *ctx = php_swoole_http_response_get_context(zobject); - if (!ctx || (ctx->end || ctx->detached)) { + if (!ctx || (ctx->end_ || ctx->detached)) { php_swoole_fatal_error(E_WARNING, "http response is unavailable (maybe it has been ended or detached)"); return nullptr; } diff --git a/ext-src/swoole_http_server_coro.cc b/ext-src/swoole_http_server_coro.cc index b77ac72d340..08df5313697 100644 --- a/ext-src/swoole_http_server_coro.cc +++ b/ext-src/swoole_http_server_coro.cc @@ -125,13 +125,10 @@ class http_server { #ifdef SW_HAVE_ZLIB ctx->websocket_compression = websocket_compression; #endif - ctx->private_data = conn; - ctx->co_socket = 1; - ctx->send = http_context_send_data; - ctx->sendfile = http_context_sendfile; - ctx->close = http_context_disconnect; ctx->upload_tmp_dir = upload_tmp_dir; + ctx->bind(conn); + swoole_http_parser *parser = &ctx->parser; parser->data = ctx; swoole_http_parser_init(parser, PHP_HTTP_REQUEST); @@ -273,6 +270,29 @@ static void php_swoole_http_server_coro_free_object(zend_object *object) { zend_object_std_dtor(&hsc->std); } +void http_context::init(Socket *sock) { + parse_cookie = 1; + parse_body = 1; + parse_files = 1; +#ifdef SW_HAVE_COMPRESSION + enable_compression = 1; + compression_level = SW_Z_BEST_SPEED; +#endif +#ifdef SW_HAVE_ZLIB + websocket_compression = 0; +#endif + upload_tmp_dir = "/tmp"; + bind(sock); +} + +void http_context::bind(Socket *sock) { + private_data = sock; + co_socket = 1; + send = http_context_send_data; + sendfile = http_context_sendfile; + close = http_context_disconnect; +} + void php_swoole_http_server_coro_minit(int module_number) { SW_INIT_CLASS_ENTRY(swoole_http_server_coro, "Swoole\\Coroutine\\Http\\Server", @@ -562,7 +582,7 @@ static PHP_METHOD(swoole_http_server_coro, onAccept) { } } - size_t parsed_n = swoole_http_requset_parse(ctx, buffer->str + buffer->offset, buffer->length - buffer->offset); + size_t parsed_n = ctx->parse(buffer->str + buffer->offset, buffer->length - buffer->offset); buffer->offset += parsed_n; swTraceLog(SW_TRACE_CO_HTTP_SERVER, diff --git a/ext-src/swoole_websocket_server.cc b/ext-src/swoole_websocket_server.cc index c0e6fbff411..aa8ece72f6e 100644 --- a/ext-src/swoole_websocket_server.cc +++ b/ext-src/swoole_websocket_server.cc @@ -30,13 +30,13 @@ SW_EXTERN_C_END #include "swoole_base64.h" #include "thirdparty/swoole_http_parser.h" -using swoole::Server; using swoole::Connection; using swoole::ListenPort; -using swoole::String; using swoole::RecvData; -using swoole::coroutine::Socket; +using swoole::Server; using swoole::SessionId; +using swoole::String; +using swoole::coroutine::Socket; using http_request = swoole::http::Request; using http_response = swoole::http::Response; @@ -312,7 +312,7 @@ void swoole_websocket_onRequest(http_context *ctx) { "

HTTP 400 Bad Request


Powered by Swoole"; ctx->send(ctx, (char *) bad_request, strlen(bad_request)); - ctx->end = 1; + ctx->end_ = 1; ctx->close(ctx); } @@ -333,7 +333,7 @@ bool swoole_websocket_handshake(http_context *ctx) { if (!(pData = zend_hash_str_find(ht, ZEND_STRL("sec-websocket-key")))) { _bad_request: ctx->response.status = SW_HTTP_BAD_REQUEST; - swoole_http_response_end(ctx, nullptr, &retval); + ctx->end(nullptr, &retval); return false; } @@ -352,10 +352,10 @@ bool swoole_websocket_handshake(http_context *ctx) { // base64 encode int sec_len = swoole::base64_encode((unsigned char *) sha1_str, sizeof(sha1_str), sec_buf); - swoole_http_response_set_header(ctx, ZEND_STRL("Upgrade"), ZEND_STRL("websocket"), false); - swoole_http_response_set_header(ctx, ZEND_STRL("Connection"), ZEND_STRL("Upgrade"), false); - swoole_http_response_set_header(ctx, ZEND_STRL("Sec-WebSocket-Accept"), sec_buf, sec_len, false); - swoole_http_response_set_header(ctx, ZEND_STRL("Sec-WebSocket-Version"), ZEND_STRL(SW_WEBSOCKET_VERSION), false); + ctx->set_header(ZEND_STRL("Upgrade"), ZEND_STRL("websocket"), false); + ctx->set_header(ZEND_STRL("Connection"), ZEND_STRL("Upgrade"), false); + ctx->set_header(ZEND_STRL("Sec-WebSocket-Accept"), sec_buf, sec_len, false); + ctx->set_header(ZEND_STRL("Sec-WebSocket-Version"), ZEND_STRL(SW_WEBSOCKET_VERSION), false); #ifdef SW_HAVE_ZLIB bool enable_websocket_compression = true; @@ -387,8 +387,7 @@ bool swoole_websocket_handshake(http_context *ctx) { std::string value(Z_STRVAL_P(pData), Z_STRLEN_P(pData)); if (value.substr(0, value.find_first_of(';')) == "permessage-deflate") { websocket_compression = true; - swoole_http_response_set_header( - ctx, ZEND_STRL("Sec-Websocket-Extensions"), ZEND_STRL(SW_WEBSOCKET_EXTENSION_DEFLATE), false); + ctx->set_header(ZEND_STRL("Sec-Websocket-Extensions"), ZEND_STRL(SW_WEBSOCKET_EXTENSION_DEFLATE), false); } } #endif @@ -397,11 +396,10 @@ bool swoole_websocket_handshake(http_context *ctx) { conn->websocket_status = WEBSOCKET_STATUS_ACTIVE; ListenPort *port = serv->get_port_by_server_fd(conn->server_fd); if (port && !port->websocket_subprotocol.empty()) { - swoole_http_response_set_header(ctx, - ZEND_STRL("Sec-WebSocket-Protocol"), - port->websocket_subprotocol.c_str(), - port->websocket_subprotocol.length(), - false); + ctx->set_header(ZEND_STRL("Sec-WebSocket-Protocol"), + port->websocket_subprotocol.c_str(), + port->websocket_subprotocol.length(), + false); } #ifdef SW_HAVE_ZLIB ctx->websocket_compression = conn->websocket_compression = websocket_compression; @@ -421,7 +419,7 @@ bool swoole_websocket_handshake(http_context *ctx) { ctx->response.status = SW_HTTP_SWITCHING_PROTOCOLS; ctx->upgrade = 1; - swoole_http_response_end(ctx, nullptr, &retval); + ctx->end(nullptr, &retval); return Z_TYPE(retval) == IS_TRUE; } @@ -553,7 +551,7 @@ int swoole_websocket_onMessage(Server *serv, RecvData *req) { SessionId fd = req->info.fd; uchar flags = 0; zend_long opcode = 0; - auto port = serv->get_port_by_session_id(fd); + auto port = serv->get_port_by_session_id(fd); if (!port) { return SW_ERR; } @@ -574,7 +572,7 @@ int swoole_websocket_onMessage(Server *serv, RecvData *req) { if (opcode == WEBSOCKET_OPCODE_PING) { String send_frame = {}; char buf[SW_WEBSOCKET_HEADER_LEN + SW_WEBSOCKET_CLOSE_CODE_LEN + SW_WEBSOCKET_CLOSE_REASON_MAX_LEN]; - send_frame.str = buf; + send_frame.str = buf; send_frame.size = sizeof(buf); swWebSocket_encode(&send_frame, req->data, req->info.len, WEBSOCKET_OPCODE_PONG, SW_WEBSOCKET_FLAG_FIN); serv->send(fd, send_frame.str, send_frame.length); diff --git a/include/swoole_http.h b/include/swoole_http.h index f84ee666731..6d4209fae00 100644 --- a/include/swoole_http.h +++ b/include/swoole_http.h @@ -20,6 +20,8 @@ enum swHttp_version { SW_HTTP_VERSION_10 = 1, SW_HTTP_VERSION_11, + SW_HTTP_VERSION_2, + SW_HTTP_VERSION_3, }; enum swHttp_method { diff --git a/tests/swoole_http_server_coro/create_response.phpt b/tests/swoole_http_server_coro/create_response.phpt new file mode 100644 index 00000000000..cf966f2db2f --- /dev/null +++ b/tests/swoole_http_server_coro/create_response.phpt @@ -0,0 +1,58 @@ +--TEST-- +swoole_http_server: create response +--SKIPIF-- + +--FILE-- +handle(function (Connection $conn) use ($server) { + $req = Request::create(); + while(true) { + $data = $conn->recv(); + if (strlen($data) != $req->parse($data) or $req->isCompleted()) { + break; + } + } + Assert::eq($req->get['value'], 1); + Assert::eq($req->get['hello'], 'world'); + $resp = Response::create($conn->exportSocket()); + $resp->header('X-Server', 'swoole'); + $resp->end(GREETER); + + $server->shutdown(); + }); + $server->start(); + }); + + go(function () use ($port, $server) { + $httpClient = new Co\Http\Client(HTTP_SERVER_HOST, $port, false); + $httpClient->setMethod("POST"); + $httpClient->setData("HELLO"); + $ok = $httpClient->execute("/rawcookie?hello=world&value=1"); + Assert::assert($ok); + Assert::same($httpClient->statusCode, 200); + Assert::same($httpClient->errCode, 0); + Assert::eq($httpClient->getHeaders()['x-server'], 'swoole'); + Assert::same($httpClient->getBody(), GREETER); + $server->shutdown(); + }); +}); +?> +--EXPECT-- diff --git a/tests/swoole_http_server_coro/create_response_2.phpt b/tests/swoole_http_server_coro/create_response_2.phpt new file mode 100644 index 00000000000..5bef1055420 --- /dev/null +++ b/tests/swoole_http_server_coro/create_response_2.phpt @@ -0,0 +1,58 @@ +--TEST-- +swoole_http_server: create response [2] +--SKIPIF-- + +--FILE-- +handle(function (Connection $conn) use ($server) { + $req = Request::create(); + while(true) { + $data = $conn->recv(); + if (strlen($data) != $req->parse($data) or $req->isCompleted()) { + break; + } + } + Assert::eq($req->get['value'], 1); + Assert::eq($req->get['hello'], 'world'); + $resp = Response::create([$conn->exportSocket(), $req]); + $resp->header('X-Server', 'swoole'); + $resp->end(GREETER); + + $server->shutdown(); + }); + $server->start(); + }); + + go(function () use ($port, $server) { + $httpClient = new Co\Http\Client(HTTP_SERVER_HOST, $port, false); + $httpClient->setMethod("POST"); + $httpClient->setData("HELLO"); + $ok = $httpClient->execute("/rawcookie?hello=world&value=1"); + Assert::assert($ok); + Assert::same($httpClient->statusCode, 200); + Assert::same($httpClient->errCode, 0); + Assert::eq($httpClient->getHeaders()['x-server'], 'swoole'); + Assert::same($httpClient->getBody(), GREETER); + $server->shutdown(); + }); +}); +?> +--EXPECT-- From 004d08a75089c063b4200010b03dd5246a1ab9d0 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Mon, 18 Jan 2021 18:07:04 +0800 Subject: [PATCH 018/936] Fix Co-Socket->errCode is not set correctly when using thread context --- include/swoole_coroutine_socket.h | 8 ++++++++ src/coroutine/socket.cc | 30 +++++++++++++++--------------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/include/swoole_coroutine_socket.h b/include/swoole_coroutine_socket.h index c5d49126857..ee00122eef5 100644 --- a/include/swoole_coroutine_socket.h +++ b/include/swoole_coroutine_socket.h @@ -430,6 +430,14 @@ class Socket { inline bool init_sock(); bool init_reactor_socket(int fd); + void check_return_value(ssize_t retval) { + if (retval >= 0) { + set_err(0); + } else if (errCode == 0) { + set_err(errno); + } + } + inline void init_options() { if (type == SW_SOCK_TCP || type == SW_SOCK_TCP6) { set_option(IPPROTO_TCP, TCP_NODELAY, 1); diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index 0269e752fd8..fb3abffd886 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -758,7 +758,7 @@ bool Socket::check_liveness() { ssize_t Socket::peek(void *__buf, size_t __n) { ssize_t retval = socket->peek(__buf, __n, 0); - set_err(retval < 0 ? errno : 0); + check_return_value(retval); return retval; } @@ -783,7 +783,7 @@ ssize_t Socket::recv(void *__buf, size_t __n) { do { retval = socket->recv(__buf, __n, 0); } while (retval < 0 && socket->catch_error(errno) == SW_WAIT && timer.start() && wait_event(SW_EVENT_READ)); - set_err(retval < 0 ? errno : 0); + check_return_value(retval); return retval; } @@ -797,7 +797,7 @@ ssize_t Socket::send(const void *__buf, size_t __n) { retval = socket->send(__buf, __n, 0); } while (retval < 0 && socket->catch_error(errno) == SW_WAIT && timer.start() && wait_event(SW_EVENT_WRITE, &__buf, __n)); - set_err(retval < 0 ? errno : 0); + check_return_value(retval); return retval; } @@ -810,7 +810,7 @@ ssize_t Socket::read(void *__buf, size_t __n) { do { retval = socket->read(__buf, __n); } while (retval < 0 && socket->catch_error(errno) == SW_WAIT && timer.start() && wait_event(SW_EVENT_READ)); - set_err(retval < 0 ? errno : 0); + check_return_value(retval); return retval; } @@ -860,7 +860,7 @@ ssize_t Socket::write(const void *__buf, size_t __n) { retval = socket->write((void *) __buf, __n); } while (retval < 0 && socket->catch_error(errno) == SW_WAIT && timer.start() && wait_event(SW_EVENT_WRITE, &__buf, __n)); - set_err(retval < 0 ? errno : 0); + check_return_value(retval); return retval; } @@ -873,7 +873,7 @@ ssize_t Socket::readv(network::IOVector *io_vector) { do { retval = socket->readv(io_vector); } while (retval < 0 && socket->catch_error(errno) == SW_WAIT && timer.start() && wait_event(SW_EVENT_READ)); - set_err(retval < 0 ? errno : 0); + check_return_value(retval); return retval; } @@ -919,7 +919,7 @@ ssize_t Socket::readv_all(network::IOVector *io_vector) { recv_barrier = &barrier; if (timer.start() && wait_event(SW_EVENT_READ)) { - set_err(retval < 0 ? errno : 0); + check_return_value(retval); } recv_barrier = nullptr; @@ -935,7 +935,7 @@ ssize_t Socket::writev(network::IOVector *io_vector) { do { retval = socket->writev(io_vector); } while (retval < 0 && socket->catch_error(errno) == SW_WAIT && timer.start() && wait_event(SW_EVENT_WRITE)); - set_err(retval < 0 ? errno : 0); + check_return_value(retval); return retval; } @@ -981,7 +981,7 @@ ssize_t Socket::writev_all(network::IOVector *io_vector) { send_barrier = &barrier; if (timer.start() && wait_event(SW_EVENT_WRITE)) { - set_err(retval < 0 ? errno : 0); + check_return_value(retval); } send_barrier = nullptr; @@ -1016,7 +1016,7 @@ ssize_t Socket::recv_all(void *__buf, size_t __n) { recv_barrier = &barrier; if (timer.start() && wait_event(SW_EVENT_READ)) { - set_err(retval < 0 ? errno : 0); + check_return_value(retval); } recv_barrier = nullptr; @@ -1051,7 +1051,7 @@ ssize_t Socket::send_all(const void *__buf, size_t __n) { send_barrier = &barrier; if (timer.start() && wait_event(SW_EVENT_WRITE)) { - set_err(retval < 0 ? errno : 0); + check_return_value(retval); } send_barrier = nullptr; @@ -1067,7 +1067,7 @@ ssize_t Socket::recvmsg(struct msghdr *msg, int flags) { do { retval = ::recvmsg(sock_fd, msg, flags); } while (retval < 0 && socket->catch_error(errno) == SW_WAIT && timer.start() && wait_event(SW_EVENT_READ)); - set_err(retval < 0 ? errno : 0); + check_return_value(retval); return retval; } @@ -1083,7 +1083,7 @@ ssize_t Socket::sendmsg(const struct msghdr *msg, int flags) { do { retval = ::sendmsg(sock_fd, msg, flags); } while (retval < 0 && socket->catch_error(errno) == SW_WAIT && timer.start() && wait_event(SW_EVENT_WRITE)); - set_err(retval < 0 ? errno : 0); + check_return_value(retval); return retval; } @@ -1391,7 +1391,7 @@ ssize_t Socket::sendto(const std::string &host, int port, const void *__buf, siz swTraceLog(SW_TRACE_SOCKET, "sendto %ld/%ld bytes, errno=%d", retval, __n, errno); } while (retval < 0 && (errno == EINTR || (socket->catch_error(errno) == SW_WAIT && timer.start() && wait_event(SW_EVENT_WRITE, &__buf, __n)))); - set_err(retval < 0 ? errno : 0); + check_return_value(retval); } return retval; @@ -1416,7 +1416,7 @@ ssize_t Socket::recvfrom(void *__buf, size_t __n, struct sockaddr *_addr, sockle swTraceLog(SW_TRACE_SOCKET, "recvfrom %ld/%ld bytes, errno=%d", retval, __n, errno); } while (retval < 0 && ((errno == EINTR) || (socket->catch_error(errno) == SW_WAIT && timer.start() && wait_event(SW_EVENT_READ)))); - set_err(retval < 0 ? errno : 0); + check_return_value(retval); return retval; } From f142924bfec76ca5a536c492fd8551238149a251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Tue, 19 Jan 2021 16:18:09 +0800 Subject: [PATCH 019/936] Optimize code (#4005) * add slow master tests * optimize code * optimize code [2] * fix * add core-test --- core-tests/src/coroutine/base.cpp | 7 +++ ext-src/php_swoole_coroutine.h | 10 ++-- ext-src/swoole_coroutine.cc | 49 ++++++++-------- include/swoole_api.h | 1 + include/swoole_coroutine.h | 4 ++ include/swoole_coroutine_context.h | 4 +- src/coroutine/base.cc | 24 ++++++++ src/coroutine/thread_context.cc | 42 ++++++++------ src/server/reactor_thread.cc | 2 +- src/wrapper/timer.cc | 18 +++--- tests/init | 4 +- tests/swoole_server/slow_master.phpt | 85 ++++++++++++++++++++++++++++ 12 files changed, 193 insertions(+), 57 deletions(-) create mode 100644 tests/swoole_server/slow_master.phpt diff --git a/core-tests/src/coroutine/base.cpp b/core-tests/src/coroutine/base.cpp index f867fc8a1f3..750f87f0775 100644 --- a/core-tests/src/coroutine/base.cpp +++ b/core-tests/src/coroutine/base.cpp @@ -171,3 +171,10 @@ TEST(coroutine_base, get_elapsed) { &elapsed_time); ASSERT_GE(elapsed_time, 2); } + +TEST(coroutine_base, run) { + long cid = coroutine::run([](void *ptr){ + + }); + ASSERT_GE(cid, 1); +} diff --git a/ext-src/php_swoole_coroutine.h b/ext-src/php_swoole_coroutine.h index de6fc1b6b28..8bb1513ec29 100644 --- a/ext-src/php_swoole_coroutine.h +++ b/ext-src/php_swoole_coroutine.h @@ -127,7 +127,6 @@ class PHPCoroutine { static const uint8_t MAX_EXEC_MSEC = 10; static void init(); - static void deactivate(void *ptr); static void shutdown(); static long create(zend_fcall_info_cache *fci_cache, uint32_t argc, zval *argv); static void defer(zend::Function *fci); @@ -144,7 +143,7 @@ class PHPCoroutine { static void resume_m(FutureTask *task, zval *retval); static inline long get_cid() { - return sw_likely(active) ? Coroutine::get_current_cid() : -1; + return sw_likely(activated) ? Coroutine::get_current_cid() : -1; } static inline long get_pcid(long cid = 0) { @@ -153,7 +152,7 @@ class PHPCoroutine { } static inline long get_elapsed(long cid = 0) { - return sw_likely(active) ? Coroutine::get_elapsed(cid) : -1; + return sw_likely(activated) ? Coroutine::get_elapsed(cid) : -1; } static inline PHPContext *get_context() { @@ -215,11 +214,11 @@ class PHPCoroutine { } static inline bool is_activated() { - return active; + return activated; } protected: - static bool active; + static bool activated; static PHPContext main_task; static Config config; @@ -227,6 +226,7 @@ class PHPCoroutine { static std::thread interrupt_thread; static void activate(); + static void deactivate(void *ptr); static inline void vm_stack_init(void); static inline void vm_stack_destroy(void); diff --git a/ext-src/swoole_coroutine.cc b/ext-src/swoole_coroutine.cc index f2aae6a7bed..6255d30a4b2 100644 --- a/ext-src/swoole_coroutine.cc +++ b/ext-src/swoole_coroutine.cc @@ -42,7 +42,7 @@ using swoole::coroutine::System; enum sw_exit_flags { SW_EXIT_IN_COROUTINE = 1 << 1, SW_EXIT_IN_SERVER = 1 << 2 }; -bool PHPCoroutine::active = false; +bool PHPCoroutine::activated = false; zend_array *PHPCoroutine::options = nullptr; PHPCoroutine::Config PHPCoroutine::config { @@ -290,27 +290,8 @@ void PHPCoroutine::init() { Coroutine::set_on_close(on_close); } -void PHPCoroutine::deactivate(void *ptr) { - interrupt_thread_stop(); - /** - * reset runtime hook - */ - disable_hook(); - - zend_interrupt_function = orig_interrupt_function; - zend_error_cb = orig_error_function; - - if (config.enable_deadlock_check) { - deadlock_check(); - } - - enable_unsafe_function(); - - active = false; -} - void PHPCoroutine::activate() { - if (sw_unlikely(active)) { + if (sw_unlikely(activated)) { return; } @@ -336,7 +317,7 @@ void PHPCoroutine::activate() { orig_error_function = zend_error_cb; zend_error_cb = [](int type, const char *error_filename, const uint32_t error_lineno, ZEND_ERROR_CB_LAST_ARG_D) { if (sw_unlikely(type & E_FATAL_ERRORS)) { - if (active) { + if (activated) { /* update the last coroutine's info */ save_task(get_context()); } @@ -365,7 +346,27 @@ void PHPCoroutine::activate() { * deactivate when reactor free. */ SwooleTG.reactor->add_destroy_callback(deactivate, nullptr); - active = true; + Coroutine::activate(); + activated = true; +} + +void PHPCoroutine::deactivate(void *ptr) { + interrupt_thread_stop(); + /** + * reset runtime hook + */ + disable_hook(); + + zend_interrupt_function = orig_interrupt_function; + zend_error_cb = orig_error_function; + + if (config.enable_deadlock_check) { + deadlock_check(); + } + + enable_unsafe_function(); + Coroutine::deactivate(); + activated = false; } void PHPCoroutine::shutdown() { @@ -803,7 +804,7 @@ long PHPCoroutine::create(zend_fcall_info_cache *fci_cache, uint32_t argc, zval return Coroutine::ERR_INVALID; } - if (sw_unlikely(!active)) { + if (sw_unlikely(!activated)) { activate(); } diff --git a/include/swoole_api.h b/include/swoole_api.h index 60bad3d0cef..151c9c23590 100644 --- a/include/swoole_api.h +++ b/include/swoole_api.h @@ -36,6 +36,7 @@ SW_API swoole::TimerNode *swoole_timer_get(long timer_id); SW_API bool swoole_timer_clear(long timer_id); SW_API void swoole_timer_free(); SW_API int swoole_timer_select(); +SW_API bool swoole_timer_is_available(); SW_API int swoole_event_init(int flags); SW_API int swoole_event_add(swoole::network::Socket *socket, int events); diff --git a/include/swoole_coroutine.h b/include/swoole_coroutine.h index 062cbe5641e..19d50eb65a7 100644 --- a/include/swoole_coroutine.h +++ b/include/swoole_coroutine.h @@ -105,6 +105,9 @@ class Coroutine { return (new Coroutine(fn, args))->run(); } + static void activate(); + static void deactivate(); + static inline Coroutine *get_current() { return current; } @@ -170,6 +173,7 @@ class Coroutine { static SwapCallback on_resume; /* before resume */ static SwapCallback on_close; /* before close */ static BailoutCallback on_bailout; /* when bailout */ + static bool activated; enum State state = STATE_INIT; long cid; diff --git a/include/swoole_coroutine_context.h b/include/swoole_coroutine_context.h index c956dd03888..9f2bc31882b 100644 --- a/include/swoole_coroutine_context.h +++ b/include/swoole_coroutine_context.h @@ -58,8 +58,6 @@ class Context { inline bool is_end() { return end_; } - static void context_func(void *arg); - protected: coroutine_func_t fn_; #ifdef SW_USE_THREAD_CONTEXT @@ -77,6 +75,8 @@ class Context { #endif void *private_data_; bool end_; + + static void context_func(void *arg); }; } // namespace coroutine diff --git a/src/coroutine/base.cc b/src/coroutine/base.cc index 1d46952917e..bf9fa50b75e 100644 --- a/src/coroutine/base.cc +++ b/src/coroutine/base.cc @@ -23,6 +23,7 @@ Coroutine *Coroutine::current = nullptr; long Coroutine::last_cid = 0; std::unordered_map Coroutine::coroutines; uint64_t Coroutine::peak_num = 0; +bool Coroutine::activated = false; size_t Coroutine::stack_size = SW_DEFAULT_C_STACK_SIZE; Coroutine::SwapCallback Coroutine::on_yield = nullptr; @@ -30,6 +31,27 @@ Coroutine::SwapCallback Coroutine::on_resume = nullptr; Coroutine::SwapCallback Coroutine::on_close = nullptr; Coroutine::BailoutCallback Coroutine::on_bailout = nullptr; +#ifdef SW_USE_THREAD_CONTEXT +namespace coroutine { +void thread_context_init(); +void thread_context_clean(); +} +#endif + +void Coroutine::activate() { +#ifdef SW_USE_THREAD_CONTEXT + coroutine::thread_context_init(); +#endif + activated = true; +} + +void Coroutine::deactivate() { +#ifdef SW_USE_THREAD_CONTEXT + coroutine::thread_context_clean(); +#endif + activated = false; +} + void Coroutine::yield() { SW_ASSERT(current == this || on_bailout != nullptr); state = STATE_WAITING; @@ -154,8 +176,10 @@ bool run(const coroutine_func_t &fn, void *arg) { if (swoole_event_init(SW_EVENTLOOP_WAIT_EXIT) < 0) { return false; } + Coroutine::activate(); long cid = Coroutine::create(fn, arg); swoole_event_wait(); + Coroutine::deactivate(); return cid > 0; } } // namespace coroutine diff --git a/src/coroutine/thread_context.cc b/src/coroutine/thread_context.cc index d7731570399..5af1d46ea47 100644 --- a/src/coroutine/thread_context.cc +++ b/src/coroutine/thread_context.cc @@ -30,24 +30,34 @@ static String *g_buffer = nullptr; static AsyncThreads *g_async_threads = nullptr; static std::mutex *current_lock = nullptr; +void thread_context_init() { + if (!swoole_timer_is_available()) { + swoole_timer_add(1, false, [](Timer *timer, TimerNode *tnode) { + // do nothing + }, nullptr); + } + if (SwooleTG.async_threads == nullptr) { + SwooleTG.async_threads = new AsyncThreads(); + } + g_reactor = SwooleTG.reactor; + g_buffer = SwooleTG.buffer_stack; + g_timer = SwooleTG.timer; + g_async_threads = SwooleTG.async_threads; + current_lock = &g_lock; + g_lock.lock(); +} + +void thread_context_clean() { + g_reactor = nullptr; + g_buffer = nullptr; + g_timer = nullptr; + g_async_threads = nullptr; + current_lock = nullptr; + g_lock.unlock(); +} + Context::Context(size_t stack_size, const coroutine_func_t &fn, void *private_data) : fn_(fn), private_data_(private_data) { - if (sw_unlikely(current_lock == nullptr)) { - current_lock = &g_lock; - if (SwooleTG.timer == nullptr) { - swoole_timer_add(1, false, [](Timer *timer, TimerNode *tnode) { - // do nothing - }, nullptr); - } - if (SwooleTG.async_threads == nullptr) { - SwooleTG.async_threads = new AsyncThreads(); - } - g_reactor = SwooleTG.reactor; - g_buffer = SwooleTG.buffer_stack; - g_timer = SwooleTG.timer; - g_async_threads = SwooleTG.async_threads; - g_lock.lock(); - } end_ = false; lock_.lock(); swap_lock_ = nullptr; diff --git a/src/server/reactor_thread.cc b/src/server/reactor_thread.cc index 03310d7f13f..3a334b4aa62 100644 --- a/src/server/reactor_thread.cc +++ b/src/server/reactor_thread.cc @@ -822,7 +822,7 @@ static int ReactorThread_init(Server *serv, Reactor *reactor, uint16_t reactor_i reactor->close = Server::close_connection; reactor->set_exit_condition(Reactor::EXIT_CONDITION_DEFAULT, [thread](Reactor *reactor, int &event_num) -> bool { - return reactor->event_num == thread->pipe_num; + return event_num == (int) thread->pipe_num; }); reactor->default_error_handler = ReactorThread_onClose; diff --git a/src/wrapper/timer.cc b/src/wrapper/timer.cc index eba0c951310..4ee4cfb3887 100644 --- a/src/wrapper/timer.cc +++ b/src/wrapper/timer.cc @@ -25,8 +25,12 @@ Timer *sw_timer() { } #endif +bool swoole_timer_is_available() { + return SwooleTG.timer != nullptr; +} + TimerNode *swoole_timer_add(long ms, bool persistent, const TimerCallback &callback, void *private_data) { - if (sw_unlikely(SwooleTG.timer == nullptr)) { + if (sw_unlikely(!swoole_timer_is_available())) { SwooleTG.timer = new Timer(); if (sw_unlikely(!SwooleTG.timer->init())) { delete SwooleTG.timer; @@ -72,8 +76,8 @@ long swoole_timer_tick(long ms, const TimerCallback &callback, void *private_dat } bool swoole_timer_exists(long timer_id) { - if (!SwooleTG.timer) { - swWarn("no timer"); + if (!swoole_timer_is_available()) { + swWarn("timer[%ld] is not exists", timer_id); return false; } TimerNode *tnode = SwooleTG.timer->get(timer_id); @@ -85,15 +89,15 @@ bool swoole_timer_clear(long timer_id) { } TimerNode *swoole_timer_get(long timer_id) { - if (!SwooleTG.timer) { - swWarn("no timer"); + if (!swoole_timer_is_available()) { + swWarn("timer[%ld] is not exists", timer_id); return nullptr; } return SwooleTG.timer->get(timer_id); } void swoole_timer_free() { - if (!SwooleTG.timer) { + if (!swoole_timer_is_available()) { return; } delete SwooleTG.timer; @@ -102,7 +106,7 @@ void swoole_timer_free() { } int swoole_timer_select() { - if (!SwooleTG.timer) { + if (!swoole_timer_is_available()) { return SW_ERR; } return SwooleTG.timer->select(); diff --git a/tests/init b/tests/init index 15fb1006c19..75370e63f4a 100755 --- a/tests/init +++ b/tests/init @@ -37,7 +37,7 @@ function read_sql_file(string $file) require __DIR__ . '/include/config.php'; -go(function () { +Swoole\Coroutine\run(function () { echo "[DB-init] initialization MySQL database...\n"; $mysql = new Swoole\Coroutine\MySQL(); $connected = $mysql->connect([ @@ -59,4 +59,4 @@ go(function () { } } echo "[DB-init] Done!\n"; -}); \ No newline at end of file +}); diff --git a/tests/swoole_server/slow_master.phpt b/tests/swoole_server/slow_master.phpt new file mode 100644 index 00000000000..d9768c5d6c3 --- /dev/null +++ b/tests/swoole_server/slow_master.phpt @@ -0,0 +1,85 @@ +--TEST-- +swoole_server: slow master +--SKIPIF-- + +--FILE-- +add(strlen($data)); +} + +$pm = new SwooleTest\ProcessManager; + +$pm->parentFunc = function ($pid) use ($pm, $counter_server, $counter_client, $data_chunks) { + $cli = new Client(SWOOLE_SOCK_TCP); + $r = $cli->connect(TCP_SERVER_HOST, $pm->getFreePort(), 5); + Assert::assert($r); + $cli->send('hello world'); + + $n = $counter_client->get(); + $data = ''; + while (strlen($data) < $n) { + $_recv = $cli->recv(); + if (empty($_recv)) { + break; + } + $data .= $_recv; + } + Assert::eq($data, implode('', $data_chunks)); + $cli->close(); + $pm->kill(); + Assert::greaterThanEq($counter_server->get(), 5); + echo "DONE\n"; +}; + +$pm->childFunc = function () use ($pm, $counter_server, $counter_client, $data_chunks) { + $serv = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_PROCESS); + $serv->set(array( + 'worker_num' => 1, + 'log_file' => '/dev/null', + 'single_thread' => true, + )); + + $serv->on(Constant::EVENT_START, function () use ($pm) { + $pm->wakeup(); + Timer::after(50, function (){ + usleep(300000); + }); + }); + + $serv->on('receive', function (Server $serv, $fd, $rid, $data) use ($counter_server, $counter_client, $data_chunks) { + $serv->timer = Timer::tick(50, function () use ($counter_server) { + $counter_server->add(1); + }); + foreach ($data_chunks as $chunk) { + $serv->send($fd, $chunk); + } + }); + + $serv->on(Constant::EVENT_CLOSE, function ($serv) use ($pm) { + Timer::clear($serv->timer); + }); + + $serv->start(); +}; + +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +DONE From b8cce7c2c39e8ca22cdb3b632c4157e218a5765f Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 19 Jan 2021 17:55:03 +0800 Subject: [PATCH 020/936] fix code style, fix #4006 --- ext-src/swoole_redis_coro.cc | 110 +++++++++--------- .../compatibility_mode/hExists.phpt | 23 ++++ 2 files changed, 77 insertions(+), 56 deletions(-) create mode 100644 tests/swoole_redis_coro/compatibility_mode/hExists.phpt diff --git a/ext-src/swoole_redis_coro.cc b/ext-src/swoole_redis_coro.cc index 1dda946b464..8e396270b84 100644 --- a/ext-src/swoole_redis_coro.cc +++ b/ext-src/swoole_redis_coro.cc @@ -847,9 +847,30 @@ ZEND_END_ARG_INFO() #define IS_EX_PX_ARG(a) (IS_EX_ARG(a) || IS_PX_ARG(a)) #define IS_NX_XX_ARG(a) (IS_NX_ARG(a) || IS_XX_ARG(a)) +struct RedisClient { + redisContext *context; + struct { + bool auth; + long db_num; + bool subscribe; + } session; + double connect_timeout; + double timeout; + bool serialize; + bool defer; + uint8_t reconnect_interval; + uint8_t reconnected_count; + bool auth; + bool compatibility_mode; + long database; + zval *zobject; + zval _zobject; + zend_object std; +}; + #define SW_REDIS_COMMAND_CHECK \ Coroutine::get_current_safe(); \ - swRedisClient *redis = php_swoole_get_redis_client(ZEND_THIS); + RedisClient *redis = php_swoole_get_redis_client(ZEND_THIS); #define SW_REDIS_COMMAND_ARGV_FILL(str, str_len) \ argvlen[i] = str_len; \ @@ -893,43 +914,16 @@ ZEND_END_ARG_INFO() efree(argv); \ } -typedef struct { - redisContext *context; - struct { - bool auth; - long db_num; - bool subscribe; - } session; - double connect_timeout; - double timeout; - bool serialize; - bool defer; - uint8_t reconnect_interval; - uint8_t reconnected_count; - bool auth; - bool compatibility_mode; - long database; - zval *zobject; - zval _zobject; - zend_object std; -} swRedisClient; - -typedef struct { - zval _value; - zval *value; - swRedisClient *redis; -} swRedis_result; - enum { SW_REDIS_MODE_MULTI, SW_REDIS_MODE_PIPELINE }; -static void swoole_redis_coro_parse_result(swRedisClient *redis, zval *return_value, redisReply *reply); +static void swoole_redis_coro_parse_result(RedisClient *redis, zval *return_value, redisReply *reply); -static sw_inline swRedisClient *php_swoole_redis_coro_fetch_object(zend_object *obj) { - return (swRedisClient *) ((char *) obj - swoole_redis_coro_handlers.offset); +static sw_inline RedisClient *php_swoole_redis_coro_fetch_object(zend_object *obj) { + return (RedisClient *) ((char *) obj - swoole_redis_coro_handlers.offset); } -static sw_inline swRedisClient *php_swoole_get_redis_client(zval *zobject) { - swRedisClient *redis = (swRedisClient *) php_swoole_redis_coro_fetch_object(Z_OBJ_P(zobject)); +static sw_inline RedisClient *php_swoole_get_redis_client(zval *zobject) { + RedisClient *redis = (RedisClient *) php_swoole_redis_coro_fetch_object(Z_OBJ_P(zobject)); if (UNEXPECTED(!redis)) { php_swoole_fatal_error(E_ERROR, "you must call Redis constructor first"); } @@ -943,7 +937,7 @@ static sw_inline Socket *swoole_redis_coro_get_socket(redisContext *context) { return nullptr; } -static sw_inline bool swoole_redis_coro_close(swRedisClient *redis) { +static sw_inline bool swoole_redis_coro_close(RedisClient *redis) { if (redis->context) { int sockfd = redis->context->fd; Socket *socket = swoole_redis_coro_get_socket(redis->context); @@ -963,7 +957,7 @@ static sw_inline bool swoole_redis_coro_close(swRedisClient *redis) { } static void php_swoole_redis_coro_free_object(zend_object *object) { - swRedisClient *redis = php_swoole_redis_coro_fetch_object(object); + RedisClient *redis = php_swoole_redis_coro_fetch_object(object); if (redis && redis->context) { swoole_redis_coro_close(redis); @@ -973,7 +967,7 @@ static void php_swoole_redis_coro_free_object(zend_object *object) { } static zend_object *php_swoole_redis_coro_create_object(zend_class_entry *ce) { - swRedisClient *redis = (swRedisClient *) zend_object_alloc(sizeof(swRedisClient), ce); + RedisClient *redis = (RedisClient *) zend_object_alloc(sizeof(RedisClient), ce); zend_object_std_init(&redis->std, ce); object_properties_init(&redis->std, ce); redis->std.handlers = &swoole_redis_coro_handlers; @@ -1027,12 +1021,12 @@ static sw_inline void swoole_redis_handle_assoc_array_result(zval *return_value, RETVAL_ZVAL(&zret, 1, 1); } -static bool redis_auth(swRedisClient *redis, char *pw, size_t pw_len); -static bool redis_select_db(swRedisClient *redis, long db_number); +static bool redis_auth(RedisClient *redis, char *pw, size_t pw_len); +static bool redis_select_db(RedisClient *redis, long db_number); static void redis_request( - swRedisClient *redis, int argc, char **argv, size_t *argvlen, zval *return_value, bool retry = false); + RedisClient *redis, int argc, char **argv, size_t *argvlen, zval *return_value, bool retry = false); -static bool swoole_redis_coro_connect(swRedisClient *redis) { +static bool swoole_redis_coro_connect(RedisClient *redis) { zval *zobject = redis->zobject; redisContext *context; Socket *socket; @@ -1134,7 +1128,7 @@ static bool swoole_redis_coro_connect(swRedisClient *redis) { return true; } -static sw_inline bool swoole_redis_coro_keep_liveness(swRedisClient *redis) { +static sw_inline bool swoole_redis_coro_keep_liveness(RedisClient *redis) { Socket *socket = nullptr; if (!redis->context || !(socket = swoole_redis_coro_get_socket(redis->context)) || !socket->check_liveness()) { if (socket) { @@ -1161,7 +1155,7 @@ static sw_inline bool swoole_redis_coro_keep_liveness(swRedisClient *redis) { return true; } -static bool redis_auth(swRedisClient *redis, char *pw, size_t pw_len) { +static bool redis_auth(RedisClient *redis, char *pw, size_t pw_len) { int i = 0; size_t argvlen[2]; char *argv[2]; @@ -1178,7 +1172,7 @@ static bool redis_auth(swRedisClient *redis, char *pw, size_t pw_len) { return ret; } -static bool redis_select_db(swRedisClient *redis, long db_number) { +static bool redis_select_db(RedisClient *redis, long db_number) { int i = 0; size_t argvlen[2]; char *argv[2]; @@ -1198,7 +1192,7 @@ static bool redis_select_db(swRedisClient *redis, long db_number) { } static void redis_request( - swRedisClient *redis, int argc, char **argv, size_t *argvlen, zval *return_value, bool retry) { + RedisClient *redis, int argc, char **argv, size_t *argvlen, zval *return_value, bool retry) { redisReply *reply = nullptr; if (!swoole_redis_coro_keep_liveness(redis)) { ZVAL_FALSE(return_value); @@ -1261,8 +1255,7 @@ static void redis_request( } } } - int i; - for (i = 0; i < argc; i++) { + SW_LOOP_N(argc) { efree(argv[i]); } } @@ -1907,7 +1900,7 @@ void php_swoole_redis_coro_minit(int module_number) { SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_redis_coro, sw_zend_class_unset_property_deny); SW_SET_CLASS_CREATE_WITH_ITS_OWN_HANDLERS(swoole_redis_coro); SW_SET_CLASS_CUSTOM_OBJECT( - swoole_redis_coro, php_swoole_redis_coro_create_object, php_swoole_redis_coro_free_object, swRedisClient, std); + swoole_redis_coro, php_swoole_redis_coro_create_object, php_swoole_redis_coro_free_object, RedisClient, std); zend_declare_property_string(swoole_redis_coro_ce, ZEND_STRL("host"), "", ZEND_ACC_PUBLIC); zend_declare_property_long(swoole_redis_coro_ce, ZEND_STRL("port"), 0, ZEND_ACC_PUBLIC); @@ -1938,7 +1931,7 @@ void php_swoole_redis_coro_minit(int module_number) { SW_REGISTER_LONG_CONSTANT("SWOOLE_REDIS_ERR_ALLOC", SW_REDIS_ERR_ALLOC); } -static void swoole_redis_coro_set_options(swRedisClient *redis, zval *zoptions, bool backward_compatibility = false) { +static void swoole_redis_coro_set_options(RedisClient *redis, zval *zoptions, bool backward_compatibility = false) { zval *zsettings = sw_zend_read_and_convert_property_array(swoole_redis_coro_ce, redis->zobject, ZEND_STRL("setting"), 0); HashTable *vht = Z_ARRVAL_P(zoptions); @@ -1979,7 +1972,7 @@ static void swoole_redis_coro_set_options(swRedisClient *redis, zval *zoptions, } static PHP_METHOD(swoole_redis_coro, __construct) { - swRedisClient *redis = php_swoole_get_redis_client(ZEND_THIS); + RedisClient *redis = php_swoole_get_redis_client(ZEND_THIS); zval *zsettings = sw_zend_read_and_convert_property_array(swoole_redis_coro_ce, ZEND_THIS, ZEND_STRL("setting"), 0); zval *zset = nullptr; @@ -2044,7 +2037,7 @@ static PHP_METHOD(swoole_redis_coro, connect) { } static PHP_METHOD(swoole_redis_coro, getAuth) { - swRedisClient *redis = php_swoole_get_redis_client(ZEND_THIS); + RedisClient *redis = php_swoole_get_redis_client(ZEND_THIS); if (redis->session.auth) { zval *ztmp = sw_zend_read_and_convert_property_array(swoole_redis_coro_ce, ZEND_THIS, ZEND_STRL("setting"), 0); if (php_swoole_array_get_value(Z_ARRVAL_P(ztmp), "password", ztmp)) { @@ -2056,7 +2049,7 @@ static PHP_METHOD(swoole_redis_coro, getAuth) { } static PHP_METHOD(swoole_redis_coro, getDBNum) { - swRedisClient *redis = php_swoole_get_redis_client(ZEND_THIS); + RedisClient *redis = php_swoole_get_redis_client(ZEND_THIS); if (!redis->context) { RETURN_FALSE; } @@ -2069,7 +2062,7 @@ static PHP_METHOD(swoole_redis_coro, getOptions) { } static PHP_METHOD(swoole_redis_coro, setOptions) { - swRedisClient *redis = php_swoole_get_redis_client(ZEND_THIS); + RedisClient *redis = php_swoole_get_redis_client(ZEND_THIS); zval *zoptions; ZEND_PARSE_PARAMETERS_START(1, 1) @@ -2082,13 +2075,13 @@ static PHP_METHOD(swoole_redis_coro, setOptions) { } static PHP_METHOD(swoole_redis_coro, getDefer) { - swRedisClient *redis = php_swoole_get_redis_client(ZEND_THIS); + RedisClient *redis = php_swoole_get_redis_client(ZEND_THIS); RETURN_BOOL(redis->defer); } static PHP_METHOD(swoole_redis_coro, setDefer) { - swRedisClient *redis = php_swoole_get_redis_client(ZEND_THIS); + RedisClient *redis = php_swoole_get_redis_client(ZEND_THIS); zend_bool defer = 1; if (redis->session.subscribe) { @@ -2165,7 +2158,7 @@ static PHP_METHOD(swoole_redis_coro, recv) { } static PHP_METHOD(swoole_redis_coro, close) { - swRedisClient *redis = php_swoole_get_redis_client(ZEND_THIS); + RedisClient *redis = php_swoole_get_redis_client(ZEND_THIS); RETURN_BOOL(swoole_redis_coro_close(redis)); } @@ -3890,6 +3883,11 @@ static PHP_METHOD(swoole_redis_coro, hMGet) { static PHP_METHOD(swoole_redis_coro, hExists) { sw_redis_command_key_str(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("HEXISTS")); + + RedisClient *redis = php_swoole_get_redis_client(ZEND_THIS); + if (redis->compatibility_mode && ZVAL_IS_LONG(return_value)) { + RETURN_BOOL(zval_get_long(return_value) ); + } } static PHP_METHOD(swoole_redis_coro, publish) { @@ -4406,7 +4404,7 @@ static PHP_METHOD(swoole_redis_coro, script) { } } -static void swoole_redis_coro_parse_result(swRedisClient *redis, zval *return_value, redisReply *reply) { +static void swoole_redis_coro_parse_result(RedisClient *redis, zval *return_value, redisReply *reply) { int j; zval _val, *val = &_val; diff --git a/tests/swoole_redis_coro/compatibility_mode/hExists.phpt b/tests/swoole_redis_coro/compatibility_mode/hExists.phpt new file mode 100644 index 00000000000..1f9b334324d --- /dev/null +++ b/tests/swoole_redis_coro/compatibility_mode/hExists.phpt @@ -0,0 +1,23 @@ +--TEST-- +swoole_redis_coro: hExists +--SKIPIF-- + +--FILE-- +setOptions(['compatibility_mode' => true]); + $redis->connect(REDIS_SERVER_HOST, REDIS_SERVER_PORT); + + $redis->delete(KEY); + $redis->hSet(KEY, 'field', 'val1'); + + Assert::true($redis->hExists(KEY, 'field') === true); + Assert::true($redis->hExists(KEY, 'field_not_found') === false); +}); +?> +--EXPECT-- From 009b4242a3f6fc516faa9c1df93c0c1ff78af519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Tue, 19 Jan 2021 18:40:43 +0800 Subject: [PATCH 021/936] Update version, Optimize code, Fix #3968, Fix #3917 (#4007) * Optimize code, Fix #3917 * update version * update package.xml, fix tests --- CMakeLists.txt | 2 +- config.m4 | 8 +------- ext-src/swoole_redis_coro.cc | 2 +- include/swoole_version.h | 8 ++++---- package.xml | 10 +++++++--- tests/swoole_http_server_coro/create_response.phpt | 2 +- tests/swoole_http_server_coro/create_response_2.phpt | 2 +- .../swoole_redis_coro/compatibility_mode/hExists.phpt | 2 +- thirdparty/boost/asm/jump_combined_sysv_macho_gas.S | 4 ++++ thirdparty/boost/asm/make_combined_sysv_macho_gas.S | 4 ++++ 10 files changed, 25 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b3c8b5648f4..f43a7126272 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ PROJECT(libswoole) ENABLE_LANGUAGE(ASM) -SET(SWOOLE_VERSION 4.6.1) +SET(SWOOLE_VERSION 4.6.2) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g") diff --git a/config.m4 b/config.m4 index 8e34e43af7a..2d6f09192d0 100644 --- a/config.m4 +++ b/config.m4 @@ -622,13 +622,7 @@ if test "$PHP_SWOOLE" != "no"; then ) if test "$SW_OS" = "MAC"; then - if test "$SW_CPU" = "arm"; then - SW_CONTEXT_ASM_FILE="arm_aapcs_macho_gas.S" - elif test "$SW_CPU" = "arm64"; then - SW_CONTEXT_ASM_FILE="arm64_aapcs_macho_gas.S" - else - SW_CONTEXT_ASM_FILE="combined_sysv_macho_gas.S" - fi + SW_CONTEXT_ASM_FILE="combined_sysv_macho_gas.S" elif test "$SW_CPU" = "x86_64"; then if test "$SW_OS" = "LINUX"; then SW_CONTEXT_ASM_FILE="x86_64_sysv_elf_gas.S" diff --git a/ext-src/swoole_redis_coro.cc b/ext-src/swoole_redis_coro.cc index 8e396270b84..a1955397d84 100644 --- a/ext-src/swoole_redis_coro.cc +++ b/ext-src/swoole_redis_coro.cc @@ -3886,7 +3886,7 @@ static PHP_METHOD(swoole_redis_coro, hExists) { RedisClient *redis = php_swoole_get_redis_client(ZEND_THIS); if (redis->compatibility_mode && ZVAL_IS_LONG(return_value)) { - RETURN_BOOL(zval_get_long(return_value) ); + RETURN_BOOL(zval_get_long(return_value)); } } diff --git a/include/swoole_version.h b/include/swoole_version.h index a5222f47050..ed05bf4374b 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -20,10 +20,10 @@ #define SWOOLE_MAJOR_VERSION 4 #define SWOOLE_MINOR_VERSION 6 -#define SWOOLE_RELEASE_VERSION 1 -#define SWOOLE_EXTRA_VERSION "" -#define SWOOLE_VERSION "4.6.1" -#define SWOOLE_VERSION_ID 40601 +#define SWOOLE_RELEASE_VERSION 2 +#define SWOOLE_EXTRA_VERSION "alpha" +#define SWOOLE_VERSION "4.6.2" +#define SWOOLE_VERSION_ID 40602 #define SWOOLE_API_VERSION_ID 0x202012a #define SWOOLE_BUG_REPORT \ diff --git a/package.xml b/package.xml index 85c4ece65fa..542378afd7b 100644 --- a/package.xml +++ b/package.xml @@ -42,10 +42,10 @@ shenzhe163@gmail.com yes - 2021-01-11 - + 2021-01-19 + - 4.6.1 + 4.6.2 4.0 @@ -1245,6 +1245,8 @@ + + @@ -1423,6 +1425,7 @@ + @@ -1680,6 +1683,7 @@ + diff --git a/tests/swoole_http_server_coro/create_response.phpt b/tests/swoole_http_server_coro/create_response.phpt index cf966f2db2f..e724549c526 100644 --- a/tests/swoole_http_server_coro/create_response.phpt +++ b/tests/swoole_http_server_coro/create_response.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_http_server: create response +swoole_http_server_coro: create response --SKIPIF-- --FILE-- diff --git a/thirdparty/boost/asm/jump_combined_sysv_macho_gas.S b/thirdparty/boost/asm/jump_combined_sysv_macho_gas.S index 1d27afad100..34a32f785f2 100644 --- a/thirdparty/boost/asm/jump_combined_sysv_macho_gas.S +++ b/thirdparty/boost/asm/jump_combined_sysv_macho_gas.S @@ -15,6 +15,10 @@ #include "jump_ppc32_sysv_macho_gas.S" #elif defined(__ppc64__) #include "jump_ppc64_sysv_macho_gas.S" +#elif defined(__arm__) + #include "jump_arm_aapcs_macho_gas.S" +#elif defined(__arm64__) + #include "jump_arm64_aapcs_macho_gas.S" #else #error "No arch's" #endif diff --git a/thirdparty/boost/asm/make_combined_sysv_macho_gas.S b/thirdparty/boost/asm/make_combined_sysv_macho_gas.S index 727e9045fc1..b22fa7ebe92 100644 --- a/thirdparty/boost/asm/make_combined_sysv_macho_gas.S +++ b/thirdparty/boost/asm/make_combined_sysv_macho_gas.S @@ -15,6 +15,10 @@ #include "make_ppc32_sysv_macho_gas.S" #elif defined(__ppc64__) #include "make_ppc64_sysv_macho_gas.S" +#elif defined(__arm__) + #include "make_arm_aapcs_macho_gas.S" +#elif defined(__arm64__) + #include "make_arm64_aapcs_macho_gas.S" #else #error "No arch's" #endif From b9de2a05c12414061025be999e2794f3b8035be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Wed, 20 Jan 2021 15:02:00 +0800 Subject: [PATCH 022/936] Update README (#4008) --- README-CN.md | 4 ++-- README.md | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/README-CN.md b/README-CN.md index bd22b61b780..5d261ea1500 100644 --- a/README-CN.md +++ b/README-CN.md @@ -445,7 +445,7 @@ echo 'use ' . (microtime(true) - $s) . ' s'; ### 编译需求 + Linux, OS X 系统 或 CygWin, WSL -+ PHP 7.0.0 或以上版本 (版本越高性能越好) ++ PHP 7.2.0 或以上版本 (版本越高性能越好) + GCC 4.8 及以上 ### 1. 使用PHP官方的PECL工具安装 (初学者) @@ -485,7 +485,7 @@ make && sudo make install > ⚠️ 如果你要从源码升级, 别忘记在源码目录执行 `make clean` 1. `pecl upgrade swoole` -2. `git pull && cd swoole-src && make clean && make && sudo make install` +2. `cd swoole-src && git pull && make clean && make && sudo make install` 3. 如果你改变了PHP版本, 请重新执行 `phpize clean && phpize`后重新编译 ## 💎 框架 & 组件 diff --git a/README.md b/README.md index b85f7aa6791..0c03e668b44 100644 --- a/README.md +++ b/README.md @@ -439,7 +439,7 @@ echo 'use ' . (microtime(true) - $s) . ' s'; ### Compiling requirements + Linux, OS X or Cygwin, WSL -+ PHP 7.0.0 or later (The higher the version, the better the performance.) ++ PHP 7.2.0 or later (The higher the version, the better the performance.) + GCC 4.8 or later ### 1. Install via PECL (beginners) @@ -454,8 +454,7 @@ Please download the source packages from [Releases](https://github.com/swoole/sw ```shell git clone https://github.com/swoole/swoole-src.git && \ -cd swoole-src && \ -git checkout v4.x.x +cd swoole-src ``` Compile and install at the source folder: @@ -486,7 +485,7 @@ After compiling and installing to the system successfully, you have to add a new > ⚠️ If you upgrade from source, don't forget to `make clean` before you upgrade your swoole 1. `pecl upgrade swoole` -2. `git pull && cd swoole-src && make clean && make && sudo make install` +2. `cd swoole-src && git pull && make clean && make && sudo make install` 3. if you change your PHP version, please re-run `phpize clean && phpize` then try to compile ### Major change since version 4.3.0 From e31b36e77b8e6f2f2c16771d8cf814d7a6176791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Thu, 21 Jan 2021 12:46:23 +0800 Subject: [PATCH 023/936] Added Socket:recvLine() (#4014) * Added Socket:recvLine() * add core tests --- core-tests/src/coroutine/socket.cpp | 51 +++++++++++++++++++++++++ ext-src/swoole_socket_coro.cc | 36 ++++++++++++++--- include/swoole_coroutine_socket.h | 1 + src/coroutine/socket.cc | 26 +++++++++++++ tests/swoole_socket_coro/recv_line.phpt | 42 ++++++++++++++++++++ 5 files changed, 151 insertions(+), 5 deletions(-) create mode 100644 tests/swoole_socket_coro/recv_line.phpt diff --git a/core-tests/src/coroutine/socket.cpp b/core-tests/src/coroutine/socket.cpp index 104704d5a3e..7f9423d695c 100644 --- a/core-tests/src/coroutine/socket.cpp +++ b/core-tests/src/coroutine/socket.cpp @@ -662,3 +662,54 @@ TEST(coroutine_socket, event_hup) { ASSERT_EQ(n, 0); }}); } + +TEST(coroutine_socket, recv_line) { + coroutine::run({[](void *arg) { + Socket sock(SW_SOCK_TCP); + bool retval = sock.bind("127.0.0.1", 9909); + ASSERT_EQ(retval, true); + ASSERT_EQ(sock.listen(128), true); + + Socket *conn = sock.accept(); + conn->send("hello world\n"); + conn->send("\r"); + char buf[256]; + memset(buf, 'A', 128); + memset(buf + 128, 'B', 125); + conn->send(buf, 253); + delete conn; + }, + + [](void *arg) { + Socket sock(SW_SOCK_TCP); + bool retval = sock.connect("127.0.0.1", 9909, -1); + ASSERT_EQ(retval, true); + ASSERT_EQ(sock.errCode, 0); + + size_t n; + auto buf = sock.get_read_buffer(); + + n = sock.recv_line(buf->str, 128); + ASSERT_EQ(n, 12); + ASSERT_MEMEQ(buf->str, "hello world\n", 12); + + n = sock.recv_line(buf->str, 128); + ASSERT_EQ(n, 1); + ASSERT_MEMEQ(buf->str, "\r", 1); + + char buf_2[256]; + memset(buf_2, 'A', 128); + memset(buf_2 + 128, 'B', 125); + + n = sock.recv_line(buf->str, 128); + ASSERT_EQ(n, 128); + ASSERT_MEMEQ(buf->str, buf_2, 128); + + n = sock.recv_line(buf->str, 128); + ASSERT_EQ(n, 125); + ASSERT_MEMEQ(buf->str, buf_2 + 128, 125); + + n = sock.recv_line(buf->str, 128); + ASSERT_EQ(n, 0); + }}); +} diff --git a/ext-src/swoole_socket_coro.cc b/ext-src/swoole_socket_coro.cc index 824f4f1bc67..294258fe783 100644 --- a/ext-src/swoole_socket_coro.cc +++ b/ext-src/swoole_socket_coro.cc @@ -58,6 +58,7 @@ static PHP_METHOD(swoole_socket_coro, sendFile); static PHP_METHOD(swoole_socket_coro, recvAll); static PHP_METHOD(swoole_socket_coro, sendAll); static PHP_METHOD(swoole_socket_coro, recvPacket); +static PHP_METHOD(swoole_socket_coro, recvLine); static PHP_METHOD(swoole_socket_coro, recvfrom); static PHP_METHOD(swoole_socket_coro, sendto); static PHP_METHOD(swoole_socket_coro, getOption); @@ -194,6 +195,8 @@ static const zend_function_entry swoole_socket_coro_methods[] = PHP_ME(swoole_socket_coro, checkLiveness, arginfo_swoole_socket_coro_checkLiveness, ZEND_ACC_PUBLIC) PHP_ME(swoole_socket_coro, peek, arginfo_swoole_socket_coro_peek, ZEND_ACC_PUBLIC) PHP_ME(swoole_socket_coro, recv, arginfo_swoole_socket_coro_recv, ZEND_ACC_PUBLIC) + PHP_ME(swoole_socket_coro, recvAll, arginfo_swoole_socket_coro_recv, ZEND_ACC_PUBLIC) + PHP_ME(swoole_socket_coro, recvLine, arginfo_swoole_socket_coro_recv, ZEND_ACC_PUBLIC) PHP_ME(swoole_socket_coro, recvPacket, arginfo_swoole_socket_coro_recvPacket, ZEND_ACC_PUBLIC) PHP_ME(swoole_socket_coro, send, arginfo_swoole_socket_coro_send, ZEND_ACC_PUBLIC) PHP_ME(swoole_socket_coro, readVector, arginfo_swoole_socket_coro_readVector, ZEND_ACC_PUBLIC) @@ -201,7 +204,6 @@ static const zend_function_entry swoole_socket_coro_methods[] = PHP_ME(swoole_socket_coro, writeVector, arginfo_swoole_socket_coro_writeVector, ZEND_ACC_PUBLIC) PHP_ME(swoole_socket_coro, writeVectorAll,arginfo_swoole_socket_coro_writeVectorAll,ZEND_ACC_PUBLIC) PHP_ME(swoole_socket_coro, sendFile, arginfo_swoole_socket_coro_sendFile, ZEND_ACC_PUBLIC) - PHP_ME(swoole_socket_coro, recvAll, arginfo_swoole_socket_coro_recv, ZEND_ACC_PUBLIC) PHP_ME(swoole_socket_coro, sendAll, arginfo_swoole_socket_coro_send, ZEND_ACC_PUBLIC) PHP_ME(swoole_socket_coro, recvfrom, arginfo_swoole_socket_coro_recvfrom, ZEND_ACC_PUBLIC) PHP_ME(swoole_socket_coro, sendto, arginfo_swoole_socket_coro_sendto, ZEND_ACC_PUBLIC) @@ -1246,7 +1248,13 @@ static PHP_METHOD(swoole_socket_coro, peek) { } } -static inline void swoole_socket_coro_recv(INTERNAL_FUNCTION_PARAMETERS, const bool all) { +enum RecvType { + SOCKET_RECV, + SOCKET_RECV_ALL, + SOCKET_RECV_LINE, +}; + +static inline void swoole_socket_coro_recv(INTERNAL_FUNCTION_PARAMETERS, RecvType type) { zend_long length = SW_BUFFER_SIZE_BIG; double timeout = 0; @@ -1264,7 +1272,21 @@ static inline void swoole_socket_coro_recv(INTERNAL_FUNCTION_PARAMETERS, const b zend_string *buf = zend_string_alloc(length, 0); Socket::TimeoutSetter ts(sock->socket, timeout, Socket::TIMEOUT_READ); - ssize_t bytes = all ? sock->socket->recv_all(ZSTR_VAL(buf), length) : sock->socket->recv(ZSTR_VAL(buf), length); + ssize_t bytes = -1; + switch (type) { + case SOCKET_RECV: + bytes = sock->socket->recv(ZSTR_VAL(buf), length); + break; + case SOCKET_RECV_ALL: + bytes = sock->socket->recv_all(ZSTR_VAL(buf), length); + break; + case SOCKET_RECV_LINE: + bytes = sock->socket->recv_line(ZSTR_VAL(buf), length); + break; + default: + assert(0); + break; + } swoole_socket_coro_sync_properties(ZEND_THIS, sock); if (UNEXPECTED(bytes < 0)) { zend_string_free(buf); @@ -1278,11 +1300,15 @@ static inline void swoole_socket_coro_recv(INTERNAL_FUNCTION_PARAMETERS, const b } static PHP_METHOD(swoole_socket_coro, recv) { - swoole_socket_coro_recv(INTERNAL_FUNCTION_PARAM_PASSTHRU, false); + swoole_socket_coro_recv(INTERNAL_FUNCTION_PARAM_PASSTHRU, SOCKET_RECV); } static PHP_METHOD(swoole_socket_coro, recvAll) { - swoole_socket_coro_recv(INTERNAL_FUNCTION_PARAM_PASSTHRU, true); + swoole_socket_coro_recv(INTERNAL_FUNCTION_PARAM_PASSTHRU, SOCKET_RECV_ALL); +} + +static PHP_METHOD(swoole_socket_coro, recvLine) { + swoole_socket_coro_recv(INTERNAL_FUNCTION_PARAM_PASSTHRU, SOCKET_RECV_LINE); } static PHP_METHOD(swoole_socket_coro, recvPacket) { diff --git a/include/swoole_coroutine_socket.h b/include/swoole_coroutine_socket.h index ee00122eef5..6af6d937cbe 100644 --- a/include/swoole_coroutine_socket.h +++ b/include/swoole_coroutine_socket.h @@ -93,6 +93,7 @@ class Socket { ssize_t recv_all(void *__buf, size_t __n); ssize_t send_all(const void *__buf, size_t __n); ssize_t recv_packet(double timeout = 0); + ssize_t recv_line(void *__buf, size_t maxlen); ssize_t recv_with_buffer(void *__buf, size_t __n); inline char *pop_packet() { diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index fb3abffd886..04533962017 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -814,6 +814,32 @@ ssize_t Socket::read(void *__buf, size_t __n) { return retval; } +ssize_t Socket::recv_line(void *__buf, size_t maxlen) { + size_t n = 0; + ssize_t m = 0; + char *t = (char *) __buf; + + *t = '\0'; + while (*t != '\n' && *t != '\r' && n < maxlen) { + if (m > 0) { + t++; + n++; + } + if (n < maxlen) { + m = recv_with_buffer((void *) t, 1); + if (m < 0) { + return -1; + } else if (m == 0) { + return n > 0 ? n : 0; + } + } + } + if (n < maxlen) { + n++; + } + return n; +} + ssize_t Socket::recv_with_buffer(void *__buf, size_t __n) { if (sw_unlikely(!is_available(SW_EVENT_READ))) { return -1; diff --git a/tests/swoole_socket_coro/recv_line.phpt b/tests/swoole_socket_coro/recv_line.phpt new file mode 100644 index 00000000000..c9795e8ed2f --- /dev/null +++ b/tests/swoole_socket_coro/recv_line.phpt @@ -0,0 +1,42 @@ +--TEST-- +swoole_socket_coro: recv line +--SKIPIF-- + +--FILE-- +handle(function (Connection $conn) use ($server) { + $conn->send("hello world\n"); + $conn->send("\r"); + $conn->send(str_repeat('A', 128) . str_repeat('B', 125)); + $server->shutdown(); + }); + + $server->start(); + }); + + $cli = new Co\Socket(AF_INET, SOCK_STREAM, 0); + if ($cli->connect('127.0.0.1', $port) == false) { + echo "ERROR\n"; + return; + } + Assert::eq($cli->recvLine(128), "hello world\n"); + Assert::eq($cli->recvLine(128), "\r"); + Assert::eq($cli->recvLine(128), str_repeat('A', 128)); + Assert::eq($cli->recvLine(128), str_repeat('B', 125)); + Assert::eq($cli->recvLine(128), ""); +}); + +?> +--EXPECT-- From a3e36ea2c075625280c0c14119daf6632b338966 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Thu, 21 Jan 2021 12:53:06 +0800 Subject: [PATCH 024/936] Fix apt not found (#4013) --- travis/docker-compile.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/travis/docker-compile.sh b/travis/docker-compile.sh index f14f07e756e..d770337f23f 100755 --- a/travis/docker-compile.sh +++ b/travis/docker-compile.sh @@ -9,8 +9,8 @@ fi #-----------compile------------ #-------print error only------- -apt update -y -apt install -y libcurl4-openssl-dev +apt-get update -y +apt-get install -y libcurl4-openssl-dev cd "${__DIR__}" && cd ../ && \ ./clear.sh > /dev/null && \ phpize --clean > /dev/null && \ @@ -20,7 +20,6 @@ phpize > /dev/null && \ --enable-http2 \ --enable-sockets \ --enable-mysqlnd \ ---enable-gconv \ --enable-swoole-json \ --enable-swoole-curl \ > /dev/null && \ From b1a0dcccabc738d3db87facf5b37633f5e8080af Mon Sep 17 00:00:00 2001 From: matyhtf Date: Thu, 21 Jan 2021 13:55:16 +0800 Subject: [PATCH 025/936] fix #4011 --- ext-src/php_swoole_library.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index dda61e633e2..658c21a5540 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: 59f277126e24cdce28e80f0f45070b9df857add2 */ +/* $Id: d11b08d63da2235271f6423764b5b0a5ab803b5e */ static const char* swoole_library_source_constants = "\n" @@ -7037,7 +7037,7 @@ static const char* swoole_library_source_ext_sockets = "function swoole_socket_read(Socket $socket, int $length, int $type = PHP_BINARY_READ)\n" "{\n" " if ($type != PHP_BINARY_READ) {\n" - " throw new RuntimeException('PHP_NORMAL_READ type is not supported');\n" + " return $socket->recvLine($length);\n" " }\n" " return $socket->recv($length);\n" "}\n" From d0a9d10c0882b3d415a60a3112adac3fd6720f8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Thu, 21 Jan 2021 18:27:42 +0800 Subject: [PATCH 026/936] optimize code (#4015) * optimize code * add http proxy tests * fix tests * fix tests[2] --- core-tests/include/test_core.h | 2 + core-tests/src/network/client.cpp | 81 +++++++++++++++++++++++++++++++ ext-src/swoole_server_port.cc | 2 + include/swoole_client.h | 22 ++++++--- include/swoole_ssl.h | 4 ++ src/network/client.cc | 64 ++++++++++++------------ 6 files changed, 137 insertions(+), 38 deletions(-) diff --git a/core-tests/include/test_core.h b/core-tests/include/test_core.h index 370d7ea7304..76af3571573 100644 --- a/core-tests/include/test_core.h +++ b/core-tests/include/test_core.h @@ -21,6 +21,8 @@ #define TEST_TMP_DIR "/tmp/swoole_core_test_dir" #define TEST_JPG_FILE "/examples/test.jpg" #define TEST_JPG_MD5SUM "64a42b4c0f3c65a14c23b60d3880a917" +#define TEST_HTTP_PROXY_PORT 8888 +#define TEST_HTTP_PROXY_HOST "127.0.0.1" #define ASSERT_MEMEQ(x,y,n) ASSERT_EQ(memcmp((x), (y), n), 0) diff --git a/core-tests/src/network/client.cpp b/core-tests/src/network/client.cpp index 7e35175fbf9..686e9f8c2b2 100644 --- a/core-tests/src/network/client.cpp +++ b/core-tests/src/network/client.cpp @@ -205,3 +205,84 @@ TEST(client, shutdown_all) { retval = cli.recv(&cli, buf, sizeof(buf), 0); ASSERT_EQ(retval, 0); } + +#ifdef SW_USE_OPENSSL +TEST(client, ssl_1) { + int ret; + + bool connected = false; + bool closed = false; + swoole::String buf(65536); + + swoole_event_init(SW_EVENTLOOP_WAIT_EXIT); + + Client client(SW_SOCK_TCP, true); + client.enable_ssl_encrypt(); + client.onConnect = [&connected](Client *cli) { + connected = true; + cli->send(cli, SW_STRL("GET / HTTP/1.1\r\n" + "Host: www.baidu.com\r\n" + "Connection: close\r\n" + "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36" + "\r\n\r\n"), 0); + }; + + client.onError = [](Client *cli) { + }; + client.onClose = [&closed](Client *cli) { + closed = true; + }; + client.onReceive = [&buf](Client *cli, const char *data, size_t length) { + buf.append(data, length); + }; + ret = client.connect(&client, "www.baidu.com", 443, -1, 0); + ASSERT_EQ(ret, 0); + + swoole_event_wait(); + + ASSERT_TRUE(connected); + ASSERT_TRUE(closed); + ASSERT_TRUE(buf.contains("Baidu")); +} + +TEST(client, http_proxy) { + int ret; + + bool connected = false; + bool closed = false; + swoole::String buf(65536); + + swoole_event_init(SW_EVENTLOOP_WAIT_EXIT); + + Client client(SW_SOCK_TCP, true); + client.enable_ssl_encrypt(); + client.set_http_proxy(TEST_HTTP_PROXY_HOST, TEST_HTTP_PROXY_PORT); + + client.onConnect = [&connected](Client *cli) { + connected = true; + cli->send(cli, SW_STRL("GET / HTTP/1.1\r\n" + "Host: www.baidu.com\r\n" + "Connection: close\r\n" + "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36" + "\r\n\r\n"), 0); + }; + + client.onError = [](Client *cli) { + }; + client.onClose = [&closed](Client *cli) { + closed = true; + }; + client.onReceive = [&buf](Client *cli, const char *data, size_t length) { + buf.append(data, length); + }; + ret = client.connect(&client, "www.baidu.com", 443, -1, 0); + ASSERT_EQ(ret, 0); + + swoole_event_wait(); + + ASSERT_TRUE(connected); + ASSERT_TRUE(closed); + ASSERT_TRUE(buf.contains("Baidu")); +} +#endif + diff --git a/ext-src/swoole_server_port.cc b/ext-src/swoole_server_port.cc index 8d7a8d2ebbd..ddf8d936154 100644 --- a/ext-src/swoole_server_port.cc +++ b/ext-src/swoole_server_port.cc @@ -580,10 +580,12 @@ static PHP_METHOD(swoole_server_port, set) { SSLContext *context = new SSLContext(); *context = *port->ssl_context; if (!php_swoole_server_set_ssl_option(Z_ARRVAL_P(current), context)) { + delete context; RETURN_FALSE; } if (!port->ssl_add_sni_cert(std::string(key->val, key->len), context)) { php_swoole_fatal_error(E_ERROR, "ssl_add_sni_cert() failed"); + delete context; RETURN_FALSE; } } ZEND_HASH_FOREACH_END(); diff --git a/include/swoole_client.h b/include/swoole_client.h index cee92947889..13ed459cbdf 100644 --- a/include/swoole_client.h +++ b/include/swoole_client.h @@ -104,12 +104,12 @@ class Client { std::shared_ptr ssl_context = nullptr; #endif - void (*onConnect)(Client *cli) = nullptr; - void (*onError)(Client *cli) = nullptr; - void (*onReceive)(Client *cli, const char *data, uint32_t length) = nullptr; - void (*onClose)(Client *cli) = nullptr; - void (*onBufferFull)(Client *cli) = nullptr; - void (*onBufferEmpty)(Client *cli) = nullptr; + std::function onConnect = nullptr; + std::function onError = nullptr; + std::function onReceive = nullptr; + std::function onClose = nullptr; + std::function onBufferFull = nullptr; + std::function onBufferEmpty = nullptr; int (*connect)(Client *cli, const char *host, int port, double _timeout, int sock_flag) = nullptr; ssize_t (*send)(Client *cli, const char *data, size_t length, int flags) = nullptr; @@ -120,6 +120,12 @@ class Client { Client(enum swSocket_type type, bool async); ~Client(); + void set_http_proxy(const std::string &host, int port) { + http_proxy = new swoole::HttpProxy; + http_proxy->proxy_host = host; + http_proxy->proxy_port = port; + } + int sleep(); int wakeup(); int shutdown(int __how); @@ -235,7 +241,7 @@ class AsyncClient : public SyncClient { std::function _onConnect = nullptr; std::function _onError = nullptr; std::function _onClose = nullptr; - std::function _onReceive = nullptr; + std::function _onReceive = nullptr; public: AsyncClient(enum swSocket_type _type) : SyncClient(_type, true) {} @@ -254,7 +260,7 @@ class AsyncClient : public SyncClient { AsyncClient *ac = (AsyncClient *) cli->object; ac->_onClose(ac); }; - client.onReceive = [](Client *cli, const char *data, uint32_t length) { + client.onReceive = [](Client *cli, const char *data, size_t length) { AsyncClient *ac = (AsyncClient *) cli->object; ac->_onReceive(ac, data, length); }; diff --git a/include/swoole_ssl.h b/include/swoole_ssl.h index 4690edf396a..d212a0fa461 100644 --- a/include/swoole_ssl.h +++ b/include/swoole_ssl.h @@ -126,6 +126,10 @@ struct SSLContext { return context; } + bool ready() { + return context != nullptr; + } + void set_protocols(uint32_t _protocols) { protocols = _protocols; } diff --git a/src/network/client.cc b/src/network/client.cc index d2bc97e3bfa..b6cb6f82b5f 100644 --- a/src/network/client.cc +++ b/src/network/client.cc @@ -271,22 +271,26 @@ int Client::enable_ssl_encrypt() { } int Client::ssl_handshake() { - if (socket->ssl) { + if (socket->ssl_state == SW_SSL_STATE_READY) { return SW_ERR; } - ssl_context->http_v2 = http2; - if (!ssl_context->create()) { - return SW_ERR; - } - socket->ssl_send_ = 1; - if (socket->ssl_create(ssl_context.get(), SW_SSL_CLIENT) < 0) { - return SW_ERR; + if (!ssl_context->ready()) { + ssl_context->http_v2 = http2; + if (!ssl_context->create()) { + return SW_ERR; + } } + if (!socket->ssl) { + socket->ssl_send_ = 1; + if (socket->ssl_create(ssl_context.get(), SW_SSL_CLIENT) < 0) { + return SW_ERR; + } #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME - if (!ssl_context->tls_host_name.empty()) { - SSL_set_tlsext_host_name(socket->ssl, ssl_context->tls_host_name.c_str()); - } + if (!ssl_context->tls_host_name.empty()) { + SSL_set_tlsext_host_name(socket->ssl, ssl_context->tls_host_name.c_str()); + } #endif + } if (socket->ssl_connect() < 0) { return SW_ERR; } @@ -454,7 +458,7 @@ int Client::close() { timer = nullptr; } // onClose callback - if (active && onClose) { + if (active) { active = 0; onClose(this); } @@ -584,8 +588,8 @@ static int Client_tcp_connect_async(Client *cli, const char *host, int port, dou cli->buffer = new String(cli->input_buffer_size); } - if (!(cli->onConnect && cli->onError && cli->onClose)) { - swWarn("onConnect/onError/onClose callback have not set"); + if (!(cli->onConnect && cli->onError && cli->onClose && cli->onReceive)) { + swWarn("onConnect/onError/onReceive/onClose callback have not set"); return SW_ERR; } @@ -772,6 +776,11 @@ static int Client_udp_connect(Client *cli, const char *host, int port, double ti return SW_ERR; } + if (cli->async && !cli->onReceive) { + swWarn("onReceive callback have not set"); + return SW_ERR; + } + cli->active = 1; cli->timeout = timeout; int bufsize = Socket::default_buffer_size; @@ -950,11 +959,12 @@ static int Client_onStreamRead(Reactor *reactor, Event *event) { if (cli->ssl_handshake() < 0) { goto _connect_fail; } else { - cli->socket->ssl_state = SW_SSL_STATE_WAIT_STREAM; - return swoole_event_set(event->socket, SW_EVENT_WRITE); - } - if (cli->onConnect) { - execute_onConnect(cli); + if (cli->socket->ssl_state == SW_SSL_STATE_READY) { + execute_onConnect(cli); + } + else if (cli->socket->ssl_state == SW_SSL_STATE_WAIT_STREAM && cli->socket->ssl_want_write) { + swoole_event_set(event->socket, SW_EVENT_WRITE); + } } return SW_OK; } @@ -986,9 +996,7 @@ static int Client_onStreamRead(Reactor *reactor, Event *event) { } else #endif { - if (cli->onConnect) { - execute_onConnect(cli); - } + execute_onConnect(cli); } return SW_OK; } @@ -1001,9 +1009,9 @@ static int Client_onStreamRead(Reactor *reactor, Event *event) { if (cli->socket->ssl_state != SW_SSL_STATE_READY) { return SW_OK; } - // ssl handshake sucess - else if (cli->onConnect) { + else { execute_onConnect(cli); + return SW_OK; } } #endif @@ -1205,18 +1213,14 @@ static int Client_onWrite(Reactor *reactor, Event *event) { } _connect_success: #endif - if (cli->onConnect) { - execute_onConnect(cli); - } + execute_onConnect(cli); } else { #ifdef SW_USE_OPENSSL _connect_fail: #endif cli->active = 0; cli->close(); - if (cli->onError) { - cli->onError(cli); - } + cli->onError(cli); } return SW_OK; From 1ee4182a37ef86cb7d3f319d751d359cf02c6909 Mon Sep 17 00:00:00 2001 From: zhiyanglee Date: Fri, 22 Jan 2021 09:54:57 +0800 Subject: [PATCH 027/936] Check stream context is null (#4016) --- ext-src/swoole_runtime.cc | 9 ++++++--- .../stream_context_pass_null.phpt | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 tests/swoole_runtime/stream_context_pass_null.phpt diff --git a/ext-src/swoole_runtime.cc b/ext-src/swoole_runtime.cc index d4958b4e5a3..d7822fae42b 100644 --- a/ext-src/swoole_runtime.cc +++ b/ext-src/swoole_runtime.cc @@ -761,9 +761,12 @@ static int socket_enable_crypto(php_stream *stream, Socket *sock, php_stream_xpo return sock->ssl_shutdown() ? 0 : -1; } - zval *val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", "capture_peer_cert"); - if (val && zend_is_true(val)) { - return php_openssl_capture_peer_certs(stream, sock) ? 0 : -1; + php_stream_context *context = PHP_STREAM_CONTEXT(stream); + if (context) { + zval *val = php_stream_context_get_option(context, "ssl", "capture_peer_cert"); + if (val && zend_is_true(val)) { + return php_openssl_capture_peer_certs(stream, sock) ? 0 : -1; + } } return 0; diff --git a/tests/swoole_runtime/stream_context_pass_null.phpt b/tests/swoole_runtime/stream_context_pass_null.phpt new file mode 100644 index 00000000000..b585ae02d98 --- /dev/null +++ b/tests/swoole_runtime/stream_context_pass_null.phpt @@ -0,0 +1,19 @@ +--TEST-- +swoole_runtime: stream context pass null +--SKIPIF-- + +--FILE-- + +--EXPECT-- +bool(true) \ No newline at end of file From a5c4f93249775d9b1d0b3b3fee36ef0849972ace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Fri, 22 Jan 2021 14:12:18 +0800 Subject: [PATCH 028/936] add Socket::readWithBuffer() (#4017) --- ext-src/swoole_socket_coro.cc | 14 +++++- .../swoole_socket_coro/recv_with_buffer.phpt | 47 +++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 tests/swoole_socket_coro/recv_with_buffer.phpt diff --git a/ext-src/swoole_socket_coro.cc b/ext-src/swoole_socket_coro.cc index 294258fe783..2b52d41e9f4 100644 --- a/ext-src/swoole_socket_coro.cc +++ b/ext-src/swoole_socket_coro.cc @@ -59,6 +59,7 @@ static PHP_METHOD(swoole_socket_coro, recvAll); static PHP_METHOD(swoole_socket_coro, sendAll); static PHP_METHOD(swoole_socket_coro, recvPacket); static PHP_METHOD(swoole_socket_coro, recvLine); +static PHP_METHOD(swoole_socket_coro, recvWithBuffer); static PHP_METHOD(swoole_socket_coro, recvfrom); static PHP_METHOD(swoole_socket_coro, sendto); static PHP_METHOD(swoole_socket_coro, getOption); @@ -197,6 +198,7 @@ static const zend_function_entry swoole_socket_coro_methods[] = PHP_ME(swoole_socket_coro, recv, arginfo_swoole_socket_coro_recv, ZEND_ACC_PUBLIC) PHP_ME(swoole_socket_coro, recvAll, arginfo_swoole_socket_coro_recv, ZEND_ACC_PUBLIC) PHP_ME(swoole_socket_coro, recvLine, arginfo_swoole_socket_coro_recv, ZEND_ACC_PUBLIC) + PHP_ME(swoole_socket_coro, recvWithBuffer, arginfo_swoole_socket_coro_recv, ZEND_ACC_PUBLIC) PHP_ME(swoole_socket_coro, recvPacket, arginfo_swoole_socket_coro_recvPacket, ZEND_ACC_PUBLIC) PHP_ME(swoole_socket_coro, send, arginfo_swoole_socket_coro_send, ZEND_ACC_PUBLIC) PHP_ME(swoole_socket_coro, readVector, arginfo_swoole_socket_coro_readVector, ZEND_ACC_PUBLIC) @@ -1248,13 +1250,14 @@ static PHP_METHOD(swoole_socket_coro, peek) { } } -enum RecvType { +enum RecvMode { SOCKET_RECV, SOCKET_RECV_ALL, SOCKET_RECV_LINE, + SOCKET_RECV_WITH_BUFFER, }; -static inline void swoole_socket_coro_recv(INTERNAL_FUNCTION_PARAMETERS, RecvType type) { +static inline void swoole_socket_coro_recv(INTERNAL_FUNCTION_PARAMETERS, RecvMode type) { zend_long length = SW_BUFFER_SIZE_BIG; double timeout = 0; @@ -1283,6 +1286,9 @@ static inline void swoole_socket_coro_recv(INTERNAL_FUNCTION_PARAMETERS, RecvTyp case SOCKET_RECV_LINE: bytes = sock->socket->recv_line(ZSTR_VAL(buf), length); break; + case SOCKET_RECV_WITH_BUFFER: + bytes = sock->socket->recv_with_buffer(ZSTR_VAL(buf), length); + break; default: assert(0); break; @@ -1311,6 +1317,10 @@ static PHP_METHOD(swoole_socket_coro, recvLine) { swoole_socket_coro_recv(INTERNAL_FUNCTION_PARAM_PASSTHRU, SOCKET_RECV_LINE); } +static PHP_METHOD(swoole_socket_coro, recvWithBuffer) { + swoole_socket_coro_recv(INTERNAL_FUNCTION_PARAM_PASSTHRU, SOCKET_RECV_WITH_BUFFER); +} + static PHP_METHOD(swoole_socket_coro, recvPacket) { double timeout = 0; diff --git a/tests/swoole_socket_coro/recv_with_buffer.phpt b/tests/swoole_socket_coro/recv_with_buffer.phpt new file mode 100644 index 00000000000..539b8f2426d --- /dev/null +++ b/tests/swoole_socket_coro/recv_with_buffer.phpt @@ -0,0 +1,47 @@ +--TEST-- +swoole_socket_coro: recv with buffer +--SKIPIF-- + +--FILE-- +handle(function (Connection $conn) use ($server) { + $conn->send(DATA); + $server->shutdown(); + }); + + $server->start(); + }); + + $cli = new Co\Socket(AF_INET, SOCK_STREAM, 0); + if ($cli->connect('127.0.0.1', $port) == false) { + echo "ERROR\n"; + return; + } + + $data = ''; + while (1) { + $char = $cli->recvWithBuffer(1); + if (strlen($char) == 1) { + $data .= $char; + } else { + break; + } + } + Assert::eq($data, DATA); +}); +?> +--EXPECT-- From 505c8c8bef894dd565d8803a2dbca1b54643558f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Fri, 22 Jan 2021 16:06:57 +0800 Subject: [PATCH 029/936] refactor wait_process() (#4019) * refactor wait_process() * format code, fix tests * fix tests --- ext-src/swoole_process.cc | 16 +- ext-src/swoole_server.cc | 18 +- include/swoole_process_pool.h | 48 ++- include/swoole_server.h | 6 +- src/os/process_pool.cc | 41 ++- src/os/wait.cc | 48 +-- src/server/manager.cc | 53 ++-- src/server/master.cc | 2 +- thirdparty/php/standard/proc_open.cc | 437 +++++++++++---------------- 9 files changed, 305 insertions(+), 364 deletions(-) diff --git a/ext-src/swoole_process.cc b/ext-src/swoole_process.cc index 4235e86272c..4d7d08693a7 100644 --- a/ext-src/swoole_process.cc +++ b/ext-src/swoole_process.cc @@ -417,24 +417,18 @@ static PHP_METHOD(swoole_process, __construct) { static PHP_METHOD(swoole_process, __destruct) {} static PHP_METHOD(swoole_process, wait) { - int status; zend_bool blocking = 1; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &blocking) == FAILURE) { RETURN_FALSE; } - int options = 0; - if (!blocking) { - options |= WNOHANG; - } - - pid_t pid = swoole_waitpid(-1, &status, options); - if (pid > 0) { + auto exit_status = swoole::wait_process(-1, blocking ? 0 : WNOHANG); + if (exit_status.get_pid() > 0) { array_init(return_value); - add_assoc_long(return_value, "pid", pid); - add_assoc_long(return_value, "code", WEXITSTATUS(status)); - add_assoc_long(return_value, "signal", WTERMSIG(status)); + add_assoc_long(return_value, "pid", exit_status.get_pid()); + add_assoc_long(return_value, "code", exit_status.get_code()); + add_assoc_long(return_value, "signal", exit_status.get_signal()); } else { RETURN_FALSE; } diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index ac4f06227f8..f734d3898f1 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -102,7 +102,7 @@ static void php_swoole_onWorkerExit(Server *serv, int worker_id); static void php_swoole_onUserWorkerStart(Server *serv, Worker *worker); static int php_swoole_onTask(Server *, EventData *task); static int php_swoole_onFinish(Server *, EventData *task); -static void php_swoole_onWorkerError(Server *serv, int worker_id, pid_t worker_pid, int status); +static void php_swoole_onWorkerError(Server *serv, int worker_id, const ExitStatus &exit_status); static void php_swoole_onManagerStart(Server *serv); static void php_swoole_onManagerStop(Server *serv); @@ -1764,7 +1764,7 @@ static void php_swoole_onUserWorkerStart(Server *serv, Worker *worker) { php_swoole_process_start(worker, object); } -static void php_swoole_onWorkerError(Server *serv, int worker_id, pid_t worker_pid, int status) { +static void php_swoole_onWorkerError(Server *serv, int worker_id, const ExitStatus &exit_status) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onWorkerError]; @@ -1777,16 +1777,16 @@ static void php_swoole_onWorkerError(Server *serv, int worker_id, pid_t worker_p zval *object = &args[1]; object_init_ex(object, swoole_server_status_info_ce); zend_update_property_long(swoole_server_status_info_ce, SW_Z8_OBJ_P(object), ZEND_STRL("worker_id"), worker_id); - zend_update_property_long(swoole_server_status_info_ce, SW_Z8_OBJ_P(object), ZEND_STRL("worker_pid"), worker_pid); - zend_update_property_long(swoole_server_status_info_ce, SW_Z8_OBJ_P(object), ZEND_STRL("status"), status); - zend_update_property_long(swoole_server_status_info_ce, SW_Z8_OBJ_P(object), ZEND_STRL("exit_code"), WEXITSTATUS(status)); - zend_update_property_long(swoole_server_status_info_ce, SW_Z8_OBJ_P(object), ZEND_STRL("signal"), WTERMSIG(status)); + zend_update_property_long(swoole_server_status_info_ce, SW_Z8_OBJ_P(object), ZEND_STRL("worker_pid"), exit_status.get_pid()); + zend_update_property_long(swoole_server_status_info_ce, SW_Z8_OBJ_P(object), ZEND_STRL("status"), exit_status.get_status()); + zend_update_property_long(swoole_server_status_info_ce, SW_Z8_OBJ_P(object), ZEND_STRL("exit_code"), exit_status.get_code()); + zend_update_property_long(swoole_server_status_info_ce, SW_Z8_OBJ_P(object), ZEND_STRL("signal"), exit_status.get_signal()); argc = 2; } else { ZVAL_LONG(&args[1], worker_id); - ZVAL_LONG(&args[2], worker_pid); - ZVAL_LONG(&args[3], WEXITSTATUS(status)); - ZVAL_LONG(&args[4], WTERMSIG(status)); + ZVAL_LONG(&args[2], exit_status.get_pid()); + ZVAL_LONG(&args[3], exit_status.get_code()); + ZVAL_LONG(&args[4], exit_status.get_signal()); argc = 5; } diff --git a/include/swoole_process_pool.h b/include/swoole_process_pool.h index f1bdd7d9a28..89eb4aa9cb1 100644 --- a/include/swoole_process_pool.h +++ b/include/swoole_process_pool.h @@ -20,6 +20,7 @@ #include "swoole.h" #include +#include #include "swoole_lock.h" #include "swoole_pipe.h" @@ -40,6 +41,48 @@ enum swIPC_type { namespace swoole { +class ExitStatus { + private: + pid_t pid_; + int status_; + public: + ExitStatus(pid_t _pid, int _status) : pid_(_pid), status_(_status) { + + } + + pid_t get_pid() const { + return pid_; + } + + int get_status() const { + return status_; + } + + int get_code() const { + return WEXITSTATUS(status_); + } + + int get_signal() const { + return WTERMSIG(status_); + } + + bool is_normal_exit() { + return WIFEXITED(status_); + } +}; + +static ExitStatus wait_process() { + int status = 0; + pid_t pid = ::wait(&status); + return ExitStatus(pid, status); +} + +static ExitStatus wait_process(pid_t _pid, int options) { + int status = 0; + pid_t pid = ::waitpid(_pid, &status, options); + return ExitStatus(pid, status); +} + struct ProcessPool; struct Worker; @@ -181,7 +224,7 @@ struct ProcessPool { void (*onWorkerStop)(ProcessPool *pool, int worker_id); int (*main_loop)(ProcessPool *pool, Worker *worker); - int (*onWorkerNotFound)(ProcessPool *pool, pid_t pid, int status); + int (*onWorkerNotFound)(ProcessPool *pool, const ExitStatus &exit_status); sw_atomic_t round_id; @@ -235,9 +278,6 @@ struct ProcessPool { }; }; // namespace swoole -typedef swoole::ProcessPool swProcessPool; -typedef swoole::Worker swWorker; - static sw_inline int swoole_waitpid(pid_t __pid, int *__stat_loc, int __options) { int ret; do { diff --git a/include/swoole_server.h b/include/swoole_server.h index 2239942dc46..72629f28be1 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -834,7 +834,7 @@ class Server { */ std::function onManagerStart; std::function onManagerStop; - std::function onWorkerError; + std::function onWorkerError; std::function onBeforeReload; std::function onAfterReload; /** @@ -1240,11 +1240,11 @@ class Server { void kill_event_workers(); void kill_task_workers(); - static int wait_other_worker(ProcessPool *pool, pid_t pid, int status); + static int wait_other_worker(ProcessPool *pool, const ExitStatus &exit_status); void drain_worker_pipe(); - void check_worker_exit_status(int worker_id, pid_t pid, int status); + void check_worker_exit_status(int worker_id, const ExitStatus &exit_status); /** * [Worker] diff --git a/src/os/process_pool.cc b/src/os/process_pool.cc index 52b24b64a9f..4faf19f895f 100644 --- a/src/os/process_pool.cc +++ b/src/os/process_pool.cc @@ -22,6 +22,7 @@ #include "swoole_msg_queue.h" #include "swoole_pipe.h" #include "swoole_server.h" +#include "swoole_util.h" #include "swoole_process_pool.h" #include "swoole_client.h" @@ -595,24 +596,23 @@ int ProcessPool_add_worker(ProcessPool *pool, Worker *worker) { } int ProcessPool::wait() { - int pid, new_pid; - pid_t reload_worker_pid = 0; + pid_t new_pid, reload_worker_pid = 0; int ret; - int status; - reload_workers = (Worker *) sw_calloc(worker_num, sizeof(Worker)); - if (reload_workers == nullptr) { - swError("malloc[reload_workers] failed"); - return SW_ERR; - } + reload_workers = new Worker[worker_num](); + ON_SCOPE_EXIT { + delete[] reload_workers; + reload_workers = nullptr; + }; while (running) { - pid = ::wait(&status); + ExitStatus exit_status = wait_process(); + if (SwooleG.signal_alarm && SwooleTG.timer) { SwooleG.signal_alarm = false; SwooleTG.timer->select(); } - if (pid < 0) { + if (exit_status.get_pid() < 0) { if (!running) { break; } @@ -635,33 +635,32 @@ int ProcessPool::wait() { } if (running) { - auto iter = map_->find(pid); + auto iter = map_->find(exit_status.get_pid()); if (iter == map_->end()) { if (onWorkerNotFound) { - onWorkerNotFound(this, pid, status); + onWorkerNotFound(this, exit_status); } else { - swWarn("[Manager]unknow worker[pid=%d]", pid); + swWarn("[Manager]unknow worker[pid=%d]", exit_status.get_pid()); } continue; } Worker *exit_worker = iter->second; - if (!WIFEXITED(status)) { + if (!exit_status.is_normal_exit()) { swWarn("worker#%d abnormal exit, status=%d, signal=%d" "%s", exit_worker->id, - WEXITSTATUS(status), - WTERMSIG(status), - WTERMSIG(status) == SIGSEGV ? "\n" SWOOLE_BUG_REPORT : ""); + exit_status.get_code(), + exit_status.get_signal(), + exit_status.get_signal() == SIGSEGV ? "\n" SWOOLE_BUG_REPORT : ""); } new_pid = spawn(exit_worker); if (new_pid < 0) { swSysWarn("Fork worker process failed"); - sw_free(reload_workers); return SW_ERR; } - map_->erase(pid); - if (pid == reload_worker_pid) { + map_->erase(exit_status.get_pid()); + if (exit_status.get_pid() == reload_worker_pid) { reload_worker_i++; } } @@ -686,8 +685,6 @@ int ProcessPool::wait() { } } } - sw_free(reload_workers); - reload_workers = nullptr; return SW_OK; } diff --git a/src/os/wait.cc b/src/os/wait.cc index 45867d8cfc4..d5db51d5e07 100644 --- a/src/os/wait.cc +++ b/src/os/wait.cc @@ -15,7 +15,7 @@ */ #include "swoole.h" #include "swoole_api.h" - +#include "swoole_process_pool.h" #include "swoole_coroutine.h" #include "swoole_coroutine_system.h" #include "swoole_signal.h" @@ -39,29 +39,29 @@ static std::unordered_map child_processes; bool signal_ready = false; static void signal_handler(int signo) { - if (signo == SIGCHLD) { - int __stat_loc; - - while (true) { - pid_t __pid = waitpid(-1, &__stat_loc, WNOHANG); - if (__pid <= 0) { - break; - } - - WaitTask *task = nullptr; - if (waitpid_map.find(__pid) != waitpid_map.end()) { - task = waitpid_map[__pid]; - } else if (!wait_list.empty()) { - task = wait_list.front(); - } else { - child_processes[__pid] = __stat_loc; - } - - if (task) { - task->status = __stat_loc; - task->pid = __pid; - task->co->resume(); - } + if (signo != SIGCHLD) { + return; + } + + while (true) { + auto exit_status = swoole::wait_process(-1, WNOHANG); + if (exit_status.get_pid() <= 0) { + break; + } + + WaitTask *task = nullptr; + if (waitpid_map.find(exit_status.get_pid()) != waitpid_map.end()) { + task = waitpid_map[exit_status.get_pid()]; + } else if (!wait_list.empty()) { + task = wait_list.front(); + } else { + child_processes[exit_status.get_pid()] = exit_status.get_status(); + } + + if (task) { + task->status = exit_status.get_status(); + task->pid = exit_status.get_pid(); + task->co->resume(); } } } diff --git a/src/server/manager.cc b/src/server/manager.cc index ccf3681b9b9..04e846474df 100644 --- a/src/server/manager.cc +++ b/src/server/manager.cc @@ -15,6 +15,8 @@ */ #include "swoole_server.h" +#include "swoole_util.h" + #include #include @@ -198,17 +200,17 @@ int Server::start_manager_process() { return SW_OK; } -void Server::check_worker_exit_status(int worker_id, pid_t pid, int status) { - if (status != 0) { +void Server::check_worker_exit_status(int worker_id, const ExitStatus &exit_status) { + if (exit_status.get_status() != 0) { swWarn("worker#%d[pid=%d] abnormal exit, status=%d, signal=%d" "%s", worker_id, - pid, - WEXITSTATUS(status), - WTERMSIG(status), - WTERMSIG(status) == SIGSEGV ? "\n" SWOOLE_BUG_REPORT : ""); + exit_status.get_pid(), + exit_status.get_code(), + exit_status.get_signal(), + exit_status.get_signal() == SIGSEGV ? "\n" SWOOLE_BUG_REPORT : ""); if (onWorkerError != nullptr) { - onWorkerError(this, worker_id, pid, status); + onWorkerError(this, worker_id, exit_status); } } } @@ -220,11 +222,11 @@ int Manager::start(Server *_server) { SwooleG.use_signalfd = 0; SwooleTG.reactor = nullptr; - reload_workers = (Worker *) sw_calloc(_server->worker_num + _server->task_worker_num, sizeof(Worker)); - if (reload_workers == nullptr) { - swError("malloc[reload_workers] failed"); - return SW_ERR; - } + reload_workers = new Worker[_server->worker_num + _server->task_worker_num]; + ON_SCOPE_EXIT { + delete[] reload_workers; + reload_workers = nullptr; + }; // for reload swSignal_set(SIGHUP, nullptr); @@ -255,8 +257,7 @@ int Manager::start(Server *_server) { } while (_server->running) { - int status; - pid_t pid = wait(&status); + ExitStatus exit_status = wait_process(); if (read_message) { WorkerStopMessage msg; @@ -282,7 +283,7 @@ int Manager::start(Server *_server) { swoole_timer_select(); } - if (pid < 0) { + if (exit_status.get_pid() < 0) { if (!reloading) { _error: if (errno > 0 && errno != EINTR) { @@ -355,12 +356,12 @@ int Manager::start(Server *_server) { // event workers SW_LOOP_N(_server->worker_num) { // find worker - if (pid != _server->workers[i].pid) { + if (exit_status.get_pid() != _server->workers[i].pid) { continue; } // check the process return code and signal - _server->check_worker_exit_status(i, pid, status); + _server->check_worker_exit_status(i, exit_status); while (1) { Worker *worker = _server->get_worker(i); @@ -377,17 +378,17 @@ int Manager::start(Server *_server) { // task worker if (_server->gs->task_workers.map_) { - auto iter = _server->gs->task_workers.map_->find(pid); + auto iter = _server->gs->task_workers.map_->find(exit_status.get_pid()); if (iter != _server->gs->task_workers.map_->end()) { - _server->check_worker_exit_status(iter->second->id, pid, status); + _server->check_worker_exit_status(iter->second->id, exit_status); _server->spawn_task_worker(iter->second); } } // user process if (_server->user_worker_map != nullptr) { - Server::wait_other_worker(&_server->gs->event_workers, pid, status); + Server::wait_other_worker(&_server->gs->event_workers, exit_status); } - if (pid == reload_worker_pid && reloading) { + if (exit_status.get_pid() == reload_worker_pid && reloading) { reload_worker_i++; } } @@ -414,8 +415,6 @@ int Manager::start(Server *_server) { } } - sw_free(reload_workers); - if (SwooleTG.timer) { swoole_timer_free(); } @@ -510,14 +509,14 @@ void Manager::signal_handler(int sig) { /** * @return: success returns pid, failure returns SW_ERR. */ -int Server::wait_other_worker(ProcessPool *pool, pid_t pid, int status) { +int Server::wait_other_worker(ProcessPool *pool, const ExitStatus &exit_status) { Server *serv = (Server *) pool->ptr; Worker *exit_worker = nullptr; int worker_type; do { if (serv->gs->task_workers.map_) { - auto iter = serv->gs->task_workers.map_->find(pid); + auto iter = serv->gs->task_workers.map_->find(exit_status.get_pid()); if (iter != serv->gs->task_workers.map_->end()) { worker_type = SW_PROCESS_TASKWORKER; exit_worker = iter->second; @@ -525,7 +524,7 @@ int Server::wait_other_worker(ProcessPool *pool, pid_t pid, int status) { } } if (serv->user_worker_map) { - auto iter = serv->user_worker_map->find(pid); + auto iter = serv->user_worker_map->find(exit_status.get_pid()); if (iter != serv->user_worker_map->end()) { worker_type = SW_PROCESS_USERWORKER; exit_worker = iter->second; @@ -535,7 +534,7 @@ int Server::wait_other_worker(ProcessPool *pool, pid_t pid, int status) { return SW_ERR; } while (0); - serv->check_worker_exit_status(exit_worker->id, pid, status); + serv->check_worker_exit_status(exit_worker->id, exit_status); pid_t new_process_pid = -1; diff --git a/src/server/master.cc b/src/server/master.cc index aced4e7c16e..6590d807d51 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -554,7 +554,7 @@ int Server::start() { gs->start_time = ::time(nullptr); /** - * store to swProcessPool object + * store to ProcessPool object */ gs->event_workers.ptr = this; gs->event_workers.workers = workers; diff --git a/thirdparty/php/standard/proc_open.cc b/thirdparty/php/standard/proc_open.cc index c664f33aec7..8903e977ed5 100644 --- a/thirdparty/php/standard/proc_open.cc +++ b/thirdparty/php/standard/proc_open.cc @@ -20,16 +20,15 @@ #include "swoole_coroutine_c_api.h" using namespace std; -using swoole::coroutine::Socket; using swoole::Coroutine; using swoole::PHPCoroutine; +using swoole::coroutine::Socket; static int le_proc_open; static const char *le_proc_name = "process/coroutine"; /* {{{ _php_array_to_envp */ -static proc_co_env_t _php_array_to_envp(zval *environment) -{ +static proc_co_env_t _php_array_to_envp(zval *environment) { zval *element; proc_co_env_t env; zend_string *key, *str; @@ -40,15 +39,13 @@ static proc_co_env_t _php_array_to_envp(zval *environment) memset(&env, 0, sizeof(env)); - if (!environment) - { + if (!environment) { return env; } cnt = zend_hash_num_elements(Z_ARRVAL_P(environment)); - if (cnt < 1) - { + if (cnt < 1) { env.envarray = (char **) ecalloc(1, sizeof(char *)); env.envp = (char *) ecalloc(4, 1); return env; @@ -58,25 +55,20 @@ static proc_co_env_t _php_array_to_envp(zval *environment) zend_hash_init(env_hash, cnt, NULL, NULL, 0); /* first, we have to get the size of all the elements in the hash */ - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(environment), key, element) - { + ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(environment), key, element) { str = zval_get_string(element); - if (ZSTR_LEN(str) == 0) - { + if (ZSTR_LEN(str) == 0) { zend_string_release(str); continue; } sizeenv += ZSTR_LEN(str) + 1; - if (key && ZSTR_LEN(key)) - { + if (key && ZSTR_LEN(key)) { sizeenv += ZSTR_LEN(key) + 1; zend_hash_add_ptr(env_hash, key, str); - } - else - { + } else { zend_hash_next_index_insert_ptr(env_hash, str); } } @@ -86,13 +78,11 @@ static proc_co_env_t _php_array_to_envp(zval *environment) p = env.envp = (char *) ecalloc(sizeenv + 4, 1); void *_v1, *_v2; - ZEND_HASH_FOREACH_STR_KEY_PTR(env_hash, _v1, _v2) - { - key = (zend_string*) _v1; - str = (zend_string*) _v2; + ZEND_HASH_FOREACH_STR_KEY_PTR(env_hash, _v1, _v2) { + key = (zend_string *) _v1; + str = (zend_string *) _v2; - if (key) - { + if (key) { l = ZSTR_LEN(key) + ZSTR_LEN(str) + 2; memcpy(p, ZSTR_VAL(key), ZSTR_LEN(key)); strcat(p, "="); @@ -101,9 +91,7 @@ static proc_co_env_t _php_array_to_envp(zval *environment) *ep = p; ++ep; p += l; - } - else - { + } else { memcpy(p, ZSTR_VAL(str), ZSTR_LEN(str)); *ep = p; ++ep; @@ -113,7 +101,7 @@ static proc_co_env_t _php_array_to_envp(zval *environment) } ZEND_HASH_FOREACH_END(); - assert((uint32_t )(p - env.envp) <= sizeenv); + assert((uint32_t)(p - env.envp) <= sizeenv); zend_hash_destroy(env_hash); FREE_HASHTABLE(env_hash); @@ -123,30 +111,24 @@ static proc_co_env_t _php_array_to_envp(zval *environment) /* }}} */ /* {{{ _php_free_envp */ -static void _php_free_envp(proc_co_env_t env) -{ - if (env.envarray) - { +static void _php_free_envp(proc_co_env_t env) { + if (env.envarray) { efree(env.envarray); } - if (env.envp) - { + if (env.envp) { efree(env.envp); } } /* }}} */ -static void proc_co_rsrc_dtor(zend_resource *rsrc) -{ - proc_co_t *proc = (proc_co_t*) rsrc->ptr; +static void proc_co_rsrc_dtor(zend_resource *rsrc) { + proc_co_t *proc = (proc_co_t *) rsrc->ptr; int i; int wstatus = 0; /* Close all handles to avoid a deadlock */ - for (i = 0; i < proc->npipes; i++) - { - if (proc->pipes[i] != 0) - { + for (i = 0; i < proc->npipes; i++) { + if (proc->pipes[i] != 0) { GC_DELREF(proc->pipes[i]); zend_list_close(proc->pipes[i]); proc->pipes[i] = 0; @@ -158,8 +140,7 @@ static void proc_co_rsrc_dtor(zend_resource *rsrc) swoole_coroutine_waitpid(proc->child, &wstatus, 0); } } - if (proc->wstatus) - { + if (proc->wstatus) { *proc->wstatus = wstatus; } @@ -169,27 +150,24 @@ static void proc_co_rsrc_dtor(zend_resource *rsrc) efree(proc); } -void swoole_proc_open_init(int module_number) -{ - le_proc_open = zend_register_list_destructors_ex(proc_co_rsrc_dtor, NULL, le_proc_name, module_number); +void swoole_proc_open_init(int module_number) { + le_proc_open = zend_register_list_destructors_ex(proc_co_rsrc_dtor, NULL, le_proc_name, module_number); } /* {{{ proto bool proc_terminate(resource process [, int signal]) kill a process opened by proc_open */ -PHP_FUNCTION(swoole_proc_terminate) -{ - zval *zproc; - proc_co_t *proc; - zend_long sig_no = SIGTERM; - - ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_RESOURCE(zproc) - Z_PARAM_OPTIONAL - Z_PARAM_LONG(sig_no) - ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - - if ((proc = (proc_co_t *) zend_fetch_resource(Z_RES_P(zproc), le_proc_name, le_proc_open)) == NULL) - { +PHP_FUNCTION(swoole_proc_terminate) { + zval *zproc; + proc_co_t *proc; + zend_long sig_no = SIGTERM; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_RESOURCE(zproc) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(sig_no) + ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + + if ((proc = (proc_co_t *) zend_fetch_resource(Z_RES_P(zproc), le_proc_name, le_proc_open)) == NULL) { RETURN_FALSE; } @@ -197,307 +175,259 @@ PHP_FUNCTION(swoole_proc_terminate) } /* }}} */ +PHP_FUNCTION(swoole_proc_close) { + zval *zproc; + proc_co_t *proc; + int wstatus; -PHP_FUNCTION(swoole_proc_close) -{ - zval *zproc; - proc_co_t *proc; - int wstatus; + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_RESOURCE(zproc) + ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(zproc) - ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - - if ((proc = (proc_co_t *) zend_fetch_resource(Z_RES_P(zproc), le_proc_name, le_proc_open)) == NULL) - { + if ((proc = (proc_co_t *) zend_fetch_resource(Z_RES_P(zproc), le_proc_name, le_proc_open)) == NULL) { RETURN_FALSE; } proc->wstatus = &wstatus; zend_list_close(Z_RES_P(zproc)); - RETURN_LONG(wstatus); + RETURN_LONG(wstatus); } -PHP_FUNCTION(swoole_proc_get_status) -{ - zval *zproc; - proc_co_t *proc; - int wstatus; - pid_t wait_pid; - int running = 1, signaled = 0, stopped = 0; - int exitcode = -1, termsig = 0, stopsig = 0; - - ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_RESOURCE(zproc) - ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - - if ((proc = (proc_co_t *) zend_fetch_resource(Z_RES_P(zproc), le_proc_name, le_proc_open)) == NULL) - { +PHP_FUNCTION(swoole_proc_get_status) { + zval *zproc; + proc_co_t *proc; + int wstatus; + pid_t wait_pid; + int running = 1, signaled = 0, stopped = 0; + int exitcode = -1, termsig = 0, stopsig = 0; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_RESOURCE(zproc) + ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + + if ((proc = (proc_co_t *) zend_fetch_resource(Z_RES_P(zproc), le_proc_name, le_proc_open)) == NULL) { RETURN_FALSE; } - array_init(return_value); + array_init(return_value); - add_assoc_string(return_value, "command", proc->command); - add_assoc_long(return_value, "pid", (zend_long) proc->child); + add_assoc_string(return_value, "command", proc->command); + add_assoc_long(return_value, "pid", (zend_long) proc->child); - errno = 0; + errno = 0; wait_pid = swoole_coroutine_waitpid(proc->child, &wstatus, WNOHANG | WUNTRACED); - if (wait_pid == proc->child) - { - if (WIFEXITED(wstatus)) - { + if (wait_pid == proc->child) { + if (WIFEXITED(wstatus)) { running = 0; exitcode = WEXITSTATUS(wstatus); } - if (WIFSIGNALED(wstatus)) - { + if (WIFSIGNALED(wstatus)) { running = 0; signaled = 1; termsig = WTERMSIG(wstatus); } - if (WIFSTOPPED(wstatus)) - { + if (WIFSTOPPED(wstatus)) { stopped = 1; stopsig = WSTOPSIG(wstatus); } - } - else if (wait_pid == -1) - { + } else if (wait_pid == -1) { running = 0; } proc->running = running; - add_assoc_bool(return_value, "running", running); - add_assoc_bool(return_value, "signaled", signaled); - add_assoc_bool(return_value, "stopped", stopped); - add_assoc_long(return_value, "exitcode", exitcode); - add_assoc_long(return_value, "termsig", termsig); - add_assoc_long(return_value, "stopsig", stopsig); + add_assoc_bool(return_value, "running", running); + add_assoc_bool(return_value, "signaled", signaled); + add_assoc_bool(return_value, "stopped", stopped); + add_assoc_long(return_value, "exitcode", exitcode); + add_assoc_long(return_value, "termsig", termsig); + add_assoc_long(return_value, "stopsig", stopsig); } /* }}} */ -#define DESC_PIPE 1 -#define DESC_FILE 2 -#define DESC_PARENT_MODE_WRITE 8 +#define DESC_PIPE 1 +#define DESC_FILE 2 +#define DESC_PARENT_MODE_WRITE 8 struct php_proc_open_descriptor_item { - int index; /* desired fd number in child process */ - int parentend, childend; /* fds for pipes in parent/child */ - int mode; /* mode for proc_open code */ - int mode_flags; /* mode flags for opening fds */ + int index; /* desired fd number in child process */ + int parentend, childend; /* fds for pipes in parent/child */ + int mode; /* mode for proc_open code */ + int mode_flags; /* mode flags for opening fds */ }; /* }}} */ -/* {{{ proto resource proc_open(string command, array descriptorspec, array &pipes [, string cwd [, array env [, array other_options]]]) - Run a process with more control over it's file descriptors */ -PHP_FUNCTION(swoole_proc_open) -{ - char *command, *cwd=NULL; - size_t command_len, cwd_len = 0; - zval *descriptorspec; - zval *pipes; - zval *environment = NULL; - zval *other_options = NULL; - proc_co_env_t env; - int ndesc = 0; - int i; - zval *descitem = NULL; - zend_string *str_index; - zend_ulong nindex; - struct php_proc_open_descriptor_item *descriptors = NULL; - int ndescriptors_array; - - pid_t child; - proc_co_t *proc; - - ZEND_PARSE_PARAMETERS_START(3, 6) - Z_PARAM_STRING(command, command_len) - Z_PARAM_ARRAY(descriptorspec) +/* {{{ proto resource proc_open(string command, array descriptorspec, array &pipes [, string cwd [, array env [, array + other_options]]]) Run a process with more control over it's file descriptors */ +PHP_FUNCTION(swoole_proc_open) { + char *command, *cwd = NULL; + size_t command_len, cwd_len = 0; + zval *descriptorspec; + zval *pipes; + zval *environment = NULL; + zval *other_options = NULL; + proc_co_env_t env; + int ndesc = 0; + int i; + zval *descitem = NULL; + zend_string *str_index; + zend_ulong nindex; + struct php_proc_open_descriptor_item *descriptors = NULL; + int ndescriptors_array; + + pid_t child; + proc_co_t *proc; + + ZEND_PARSE_PARAMETERS_START(3, 6) + Z_PARAM_STRING(command, command_len) + Z_PARAM_ARRAY(descriptorspec) #if PHP_VERSION_ID >= 70400 - Z_PARAM_ZVAL(pipes) + Z_PARAM_ZVAL(pipes) #else - Z_PARAM_ZVAL_DEREF(pipes) + Z_PARAM_ZVAL_DEREF(pipes) #endif - Z_PARAM_OPTIONAL - Z_PARAM_STRING_EX(cwd, cwd_len, 1, 0) - Z_PARAM_ARRAY_EX(environment, 1, 0) - Z_PARAM_ARRAY_EX(other_options, 1, 0) - ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - - php_swoole_check_reactor(); - if (php_swoole_signal_isset_handler(SIGCHLD)) - { + Z_PARAM_OPTIONAL + Z_PARAM_STRING_EX(cwd, cwd_len, 1, 0) + Z_PARAM_ARRAY_EX(environment, 1, 0) + Z_PARAM_ARRAY_EX(other_options, 1, 0) + ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + + php_swoole_check_reactor(); + if (php_swoole_signal_isset_handler(SIGCHLD)) { php_swoole_error(E_WARNING, "The signal [SIGCHLD] is registered, cannot execute swoole_proc_open"); RETURN_FALSE; } Coroutine::get_current_safe(); - command = estrdup(command); + command = estrdup(command); - command_len = strlen(command); + command_len = strlen(command); - if (environment) - { + if (environment) { env = _php_array_to_envp(environment); - } - else - { + } else { memset(&env, 0, sizeof(env)); } ndescriptors_array = zend_hash_num_elements(Z_ARRVAL_P(descriptorspec)); - descriptors = (struct php_proc_open_descriptor_item *) safe_emalloc(sizeof(struct php_proc_open_descriptor_item), - ndescriptors_array, 0); + descriptors = (struct php_proc_open_descriptor_item *) safe_emalloc( + sizeof(struct php_proc_open_descriptor_item), ndescriptors_array, 0); memset(descriptors, 0, sizeof(struct php_proc_open_descriptor_item) * ndescriptors_array); /* walk the descriptor spec and set up files/pipes */ - ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(descriptorspec), nindex, str_index, descitem) - { + ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(descriptorspec), nindex, str_index, descitem) { zval *ztype; - if (str_index) - { + if (str_index) { php_swoole_fatal_error(E_WARNING, "descriptor spec must be an integer indexed array"); goto exit_fail; } descriptors[ndesc].index = (int) nindex; - if (Z_TYPE_P(descitem) == IS_RESOURCE) - { + if (Z_TYPE_P(descitem) == IS_RESOURCE) { /* should be a stream - try and dup the descriptor */ php_stream *stream; php_socket_t fd; php_stream_from_zval(stream, descitem); - if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_FD, (void ** )&fd, REPORT_ERRORS)) - { + if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_FD, (void **) &fd, REPORT_ERRORS)) { goto exit_fail; } descriptors[ndesc].childend = dup(fd); - if (descriptors[ndesc].childend < 0) - { + if (descriptors[ndesc].childend < 0) { php_swoole_fatal_error(E_WARNING, - "unable to dup File-Handle for descriptor " ZEND_ULONG_FMT " - %s", nindex, - strerror(errno)); + "unable to dup File-Handle for descriptor " ZEND_ULONG_FMT " - %s", + nindex, + strerror(errno)); goto exit_fail; } descriptors[ndesc].mode = DESC_FILE; - } - else if (Z_TYPE_P(descitem) != IS_ARRAY) - { + } else if (Z_TYPE_P(descitem) != IS_ARRAY) { php_swoole_fatal_error(E_WARNING, "Descriptor item must be either an array or a File-Handle"); goto exit_fail; - } - else - { - - if ((ztype = zend_hash_index_find(Z_ARRVAL_P(descitem), 0)) != NULL) - { + } else { + if ((ztype = zend_hash_index_find(Z_ARRVAL_P(descitem), 0)) != NULL) { convert_to_string_ex(ztype); - } - else - { + } else { php_swoole_fatal_error(E_WARNING, "Missing handle qualifier in array"); goto exit_fail; } - if (strcmp(Z_STRVAL_P(ztype), "pipe") == 0) - { + if (strcmp(Z_STRVAL_P(ztype), "pipe") == 0) { int newpipe[2]; zval *zmode; - if ((zmode = zend_hash_index_find(Z_ARRVAL_P(descitem), 1)) != NULL) - { + if ((zmode = zend_hash_index_find(Z_ARRVAL_P(descitem), 1)) != NULL) { convert_to_string_ex(zmode); - } - else - { + } else { php_swoole_fatal_error(E_WARNING, "Missing mode parameter for 'pipe'"); goto exit_fail; } descriptors[ndesc].mode = DESC_PIPE; - if (0 != socketpair(AF_UNIX, SOCK_STREAM, 0, newpipe)) - { + if (0 != socketpair(AF_UNIX, SOCK_STREAM, 0, newpipe)) { php_swoole_fatal_error(E_WARNING, "unable to create pipe %s", strerror(errno)); goto exit_fail; } - if (strncmp(Z_STRVAL_P(zmode), "w", 1) != 0) - { + if (strncmp(Z_STRVAL_P(zmode), "w", 1) != 0) { descriptors[ndesc].parentend = newpipe[1]; descriptors[ndesc].childend = newpipe[0]; descriptors[ndesc].mode |= DESC_PARENT_MODE_WRITE; - } - else - { + } else { descriptors[ndesc].parentend = newpipe[0]; descriptors[ndesc].childend = newpipe[1]; } - descriptors[ndesc].mode_flags = - descriptors[ndesc].mode & DESC_PARENT_MODE_WRITE ? O_WRONLY : O_RDONLY; + descriptors[ndesc].mode_flags = descriptors[ndesc].mode & DESC_PARENT_MODE_WRITE ? O_WRONLY : O_RDONLY; - } - else if (strcmp(Z_STRVAL_P(ztype), "file") == 0) - { + } else if (strcmp(Z_STRVAL_P(ztype), "file") == 0) { zval *zfile, *zmode; php_socket_t fd; php_stream *stream; descriptors[ndesc].mode = DESC_FILE; - if ((zfile = zend_hash_index_find(Z_ARRVAL_P(descitem), 1)) != NULL) - { + if ((zfile = zend_hash_index_find(Z_ARRVAL_P(descitem), 1)) != NULL) { convert_to_string_ex(zfile); - } - else - { + } else { php_swoole_fatal_error(E_WARNING, "Missing file name parameter for 'file'"); goto exit_fail; } - if ((zmode = zend_hash_index_find(Z_ARRVAL_P(descitem), 2)) != NULL) - { + if ((zmode = zend_hash_index_find(Z_ARRVAL_P(descitem), 2)) != NULL) { convert_to_string_ex(zmode); - } - else - { + } else { php_swoole_fatal_error(E_WARNING, "Missing mode parameter for 'file'"); goto exit_fail; } /* try a wrapper */ - stream = php_stream_open_wrapper(Z_STRVAL_P(zfile), Z_STRVAL_P(zmode), REPORT_ERRORS|STREAM_WILL_CAST, NULL); + stream = php_stream_open_wrapper( + Z_STRVAL_P(zfile), Z_STRVAL_P(zmode), REPORT_ERRORS | STREAM_WILL_CAST, NULL); /* force into an fd */ - if (stream == NULL || FAILURE == php_stream_cast(stream, PHP_STREAM_CAST_RELEASE|PHP_STREAM_AS_FD, (void ** )&fd, REPORT_ERRORS)) - { + if (stream == NULL || + FAILURE == php_stream_cast( + stream, PHP_STREAM_CAST_RELEASE | PHP_STREAM_AS_FD, (void **) &fd, REPORT_ERRORS)) { goto exit_fail; } descriptors[ndesc].childend = fd; - } - else if (strcmp(Z_STRVAL_P(ztype), "pty") == 0) - { - + } else if (strcmp(Z_STRVAL_P(ztype), "pty") == 0) { php_swoole_fatal_error(E_WARNING, "pty pseudo terminal not supported on this system"); goto exit_fail; - } - else - { + } else { php_swoole_fatal_error(E_WARNING, "%s is not a valid descriptor spec/mode", Z_STRVAL_P(ztype)); goto exit_fail; } @@ -509,57 +439,44 @@ PHP_FUNCTION(swoole_proc_open) /* the unix way */ child = swoole_fork(SW_FORK_EXEC); - if (child == 0) - { + if (child == 0) { /* this is the child process */ /* close those descriptors that we just opened for the parent stuff, * dup new descriptors into required descriptors and close the original * cruft */ - for (i = 0; i < ndesc; i++) - { - switch (descriptors[i].mode & ~DESC_PARENT_MODE_WRITE) - { + for (i = 0; i < ndesc; i++) { + switch (descriptors[i].mode & ~DESC_PARENT_MODE_WRITE) { case DESC_PIPE: close(descriptors[i].parentend); break; } - if (dup2(descriptors[i].childend, descriptors[i].index) < 0) - { + if (dup2(descriptors[i].childend, descriptors[i].index) < 0) { perror("dup2"); } - if (descriptors[i].childend != descriptors[i].index) - { + if (descriptors[i].childend != descriptors[i].index) { close(descriptors[i].childend); } } - if (cwd) - { + if (cwd) { php_ignore_value(chdir(cwd)); } - if (env.envarray) - { + if (env.envarray) { execle("/bin/sh", "sh", "-c", command, NULL, env.envarray); - } - else - { + } else { execl("/bin/sh", "sh", "-c", command, NULL); } _exit(127); - } - else if (child < 0) - { + } else if (child < 0) { /* failed to fork() */ /* clean up all the descriptors */ - for (i = 0; i < ndesc; i++) - { + for (i = 0; i < ndesc; i++) { close(descriptors[i].childend); - if (descriptors[i].parentend) - { + if (descriptors[i].parentend) { close(descriptors[i].parentend); } } @@ -567,12 +484,11 @@ PHP_FUNCTION(swoole_proc_open) php_swoole_fatal_error(E_WARNING, "fork failed - %s", strerror(errno)); goto exit_fail; - } /* we forked/spawned and this is the parent */ - proc = (proc_co_t*) emalloc(sizeof(proc_co_t)); + proc = (proc_co_t *) emalloc(sizeof(proc_co_t)); proc->wstatus = nullptr; proc->command = command; proc->pipes = (zend_resource **) emalloc(sizeof(zend_resource *) * ndesc); @@ -583,8 +499,7 @@ PHP_FUNCTION(swoole_proc_open) #if PHP_VERSION_ID >= 70400 pipes = zend_try_array_init(pipes); - if (!pipes) - { + if (!pipes) { goto exit_fail; } #else @@ -592,22 +507,19 @@ PHP_FUNCTION(swoole_proc_open) array_init(pipes); #endif - /* clean up all the child ends and then open streams on the parent - * ends, where appropriate */ - for (i = 0; i < ndesc; i++) - { + /* clean up all the child ends and then open streams on the parent + * ends, where appropriate */ + for (i = 0; i < ndesc; i++) { php_stream *stream = NULL; close(descriptors[i].childend); - switch (descriptors[i].mode & ~DESC_PARENT_MODE_WRITE) - { + switch (descriptors[i].mode & ~DESC_PARENT_MODE_WRITE) { case DESC_PIPE: stream = php_swoole_create_stream_from_socket(descriptors[i].parentend, AF_UNIX, SOCK_STREAM, 0 STREAMS_CC); /* mark the descriptor close-on-exec, so that it won't be inherited by potential other children */ fcntl(descriptors[i].parentend, F_SETFD, FD_CLOEXEC); - if (stream) - { + if (stream) { zval retfp; /* nasty hack; don't copy it */ @@ -625,16 +537,15 @@ PHP_FUNCTION(swoole_proc_open) } } - efree(descriptors); - ZVAL_RES(return_value, zend_register_resource(proc, le_proc_open)); - return; + efree(descriptors); + ZVAL_RES(return_value, zend_register_resource(proc, le_proc_open)); + return; - exit_fail: +exit_fail: efree(descriptors); _php_free_envp(env); efree(command); - RETURN_FALSE; - + RETURN_FALSE; } /* }}} */ From b74d5d4c1e78ec9c89ad728f5b2cd9dd89ef90b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Fri, 22 Jan 2021 16:44:06 +0800 Subject: [PATCH 030/936] Optimize make.sh (#4009) * Optimize make.sh * Add CPU_COUNT and whoami * remove sync-module --- make.sh | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/make.sh b/make.sh index 1b998bbeed0..1069b396628 100755 --- a/make.sh +++ b/make.sh @@ -1,14 +1,23 @@ #!/bin/sh -e __DIR__=$(cd "$(dirname "$0")";pwd) -__EXT_DIR__=$(php-config --extension-dir) +COMPILE_PARAMS="--enable-openssl --enable-sockets --enable-mysqlnd --enable-http2 --enable-swoole-json --enable-swoole-curl" + +if [ "$(uname | grep -i darwin)"x != ""x ]; then + CPU_COUNT="$(sysctl -n machdep.cpu.core_count)" +else + CPU_COUNT="$(/usr/bin/nproc)" +fi +if [ -z ${CPU_COUNT} ]; then + CPU_COUNT=4 +fi cd "${__DIR__}" if [ "$1" = "cmake" ] ;then phpize - ./configure --enable-openssl --enable-swoole-json --enable-swoole-curl --enable-sockets --enable-mysqlnd --enable-http2 + ./configure ${COMPILE_PARAMS} cmake . - make -j 8 + make -j ${CPU_COUNT} exit 0 fi @@ -20,18 +29,12 @@ fi if [ "$1" = "install-module" ] ;then make ext-swoole + __EXT_DIR__=$(php-config --extension-dir) cp lib/swoole.so "${__EXT_DIR__}" echo "cp lib/swoole.so ${__EXT_DIR__}" exit 0 fi -if [ "$1" = "sync-module" ] ;then - # thirtparty - git submodule init - git submodule update - exit 0 -fi - if [ "$1" = "library" ] ;then set -e cd ${__DIR__} @@ -45,7 +48,7 @@ if [ "$1" = "library" ] ;then if [ "$2" = "dev" ] ;then /usr/bin/env php tools/build-library.php dev else - /usr/bin/env php tools/build-library.php + /usr/bin/env php tools/build-library.php fi echo "remake..." @@ -57,20 +60,24 @@ fi if [ "$1" = "help" ] ;then echo "./make.sh cmake" echo "./make.sh install-module" - echo "./make.sh sync-module" echo "./make.sh clean" echo "./make.sh debug" + echo "./make.sh library [dev]" echo "./make.sh" - echo "./make.sh library" exit 0 fi phpize if [ "$1" = "debug" ] ;then - ./configure --enable-openssl --enable-swoole-json --enable-swoole-curl --enable-sockets --enable-mysqlnd --enable-http2 --enable-debug-log + ./configure ${COMPILE_PARAMS} --enable-debug-log else - ./configure --enable-openssl --enable-swoole-json --enable-swoole-curl --enable-sockets --enable-mysqlnd --enable-http2 + ./configure ${COMPILE_PARAMS} fi make clean -make -j 8 -make install +make -j ${CPU_COUNT} + +if [ "$(whoami)" == "root" ];then + make install +else + sudo make install +fi From 1f747531ec022cf75c9ad6988634fc5ce268c919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Fri, 22 Jan 2021 16:44:30 +0800 Subject: [PATCH 031/936] Add coverity scan action and Update gitee mirror action (#4020) --- .github/workflows/coverity.yml | 58 +++++++++++++++++++++ .github/workflows/{gitee.yml => mirror.yml} | 7 ++- 2 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/coverity.yml rename .github/workflows/{gitee.yml => mirror.yml} (85%) diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml new file mode 100644 index 00000000000..b36b8bb7d85 --- /dev/null +++ b/.github/workflows/coverity.yml @@ -0,0 +1,58 @@ +name: coverity-scan + +on: + push: + branches: + - coverity_scan + +env: + COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} + COVERITY_SCAN_EMAIL: team@swoole.com + COVERITY_PROJECT: ${{ github.repository }} + COV_TOOLS_DIR: ${{ github.workspace }}/cov-analysis-linux64 + COV_BUILD_DIR: ${{ github.workspace }} + COV_RESULTS_DIR: cov-int + COV_RESULTS_FILE: analysis-results.tgz + +jobs: + coverity-scan: + if: github.repository_owner == 'swoole' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: "7.4" + + - name: Download and install Coverity Build Tool + run: | + wget -q https://scan.coverity.com/download/linux64 \ + --post-data "token=${COVERITY_SCAN_TOKEN}&project=${COVERITY_PROJECT}" \ + -O cov-analysis-linux64.tar.gz + mkdir ${COV_TOOLS_DIR} + tar xzf cov-analysis-linux64.tar.gz --strip 1 -C ${COV_TOOLS_DIR} + ls -la ${COV_TOOLS_DIR}/bin + + - name: Run build steps + run: | + sudo phpize && ./configure + + - name: Run Coverity Scan Analysis Tool + run: | + export PATH=${COV_TOOLS_DIR}/bin:$PATH + cd ${COV_BUILD_DIR} + cov-build --dir ${COV_RESULTS_DIR} make -j 4 + + - name: Upload Coverity Scan Analysis results + run: | + cd ${COV_BUILD_DIR} + tar czf ${COV_RESULTS_FILE} ${COV_RESULTS_DIR} + curl \ + --form project=${COVERITY_PROJECT} \ + --form token=${COVERITY_SCAN_TOKEN} \ + --form email=${COVERITY_SCAN_EMAIL} \ + --form file=@${COV_RESULTS_FILE} \ + --form version=${GITHUB_SHA} \ + --form description="GitHub Actions" \ + https://scan.coverity.com/builds?project=${COVERITY_PROJECT} diff --git a/.github/workflows/gitee.yml b/.github/workflows/mirror.yml similarity index 85% rename from .github/workflows/gitee.yml rename to .github/workflows/mirror.yml index d500e2b4a28..dc42ad90314 100644 --- a/.github/workflows/gitee.yml +++ b/.github/workflows/mirror.yml @@ -1,13 +1,13 @@ -name: Mirror to Gitee Repo +name: mirror on: [ push, delete, create ] jobs: - git-mirror: + gitee: + if: github.repository_owner == 'swoole' runs-on: ubuntu-latest steps: - name: Configure Private Key - if: github.repository_owner == 'swoole' env: SSH_PRIVATE_KEY: ${{ secrets.GITEE_PRIVATE_KEY }} run: | @@ -17,7 +17,6 @@ jobs: echo "StrictHostKeyChecking no" >> ~/.ssh/config - name: Push Mirror - if: github.repository_owner == 'swoole' env: SOURCE_REPO: 'https://github.com/swoole/swoole-src.git' DESTINATION_REPO: 'git@gitee.com:swoole/swoole.git' From 00090982a3b9790c29d0e8c47063cf5d0d9de1f3 Mon Sep 17 00:00:00 2001 From: codinghuang Date: Mon, 25 Jan 2021 17:06:59 +0800 Subject: [PATCH 032/936] Update version for Swoole 4.6.2 (#4025) --- include/swoole_version.h | 2 +- package.xml | 31 +++++++++++++------ .../stream_context_pass_null.phpt | 2 +- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/include/swoole_version.h b/include/swoole_version.h index ed05bf4374b..05ecaa52484 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -21,7 +21,7 @@ #define SWOOLE_MAJOR_VERSION 4 #define SWOOLE_MINOR_VERSION 6 #define SWOOLE_RELEASE_VERSION 2 -#define SWOOLE_EXTRA_VERSION "alpha" +#define SWOOLE_EXTRA_VERSION "" #define SWOOLE_VERSION "4.6.2" #define SWOOLE_VERSION_ID 40602 #define SWOOLE_API_VERSION_ID 0x202012a diff --git a/package.xml b/package.xml index 542378afd7b..a2c05be6dae 100644 --- a/package.xml +++ b/package.xml @@ -42,8 +42,8 @@ shenzhe163@gmail.com yes - 2021-01-19 - + 2021-01-25 + 4.6.2 4.0 @@ -54,22 +54,30 @@ Apache2.0 + New APIs + --- + + Added Http::Request::getMethod() (#3987) (@luolaifa000) + + Added Coroutine::Socket:recvLine() (#4014) (@matyhtf) + Enhancement --- - + Added --enable-thread-context option (#3970) (@matyhtf) - + Strict session_id, check the connection activity (#3993) (@matyhtf) - * Optimized CURLOPT_PROXY, support user, pass and scheme (swoole/library#87) (sy-records) + + Improved Response::create() (#3998) (@matyhtf) + + Supported Coroutine\Redis::hExists return bool with compatibility_mode (swoole/swoole-src@b8cce7c) (@matyhtf) + + Supported PHP_NORMAL_READ for Coroutine::Socket::read (swoole/swoole-src@b1a0dcc) (@matyhtf) Fixed --- - * Fixed minimal PHP version (#3979) (@remicollet) - * Fixed pecl install missing enable-swoole-json and enable-swoole-curl options (#3980) (@sy-records) - * Fixed openssl thread safety issue (swoole/swoole-src@b516d69) (@matyhtf) - * Fixed enableSSL coredump (#3990) (@huanghantao) + * Fixed Coroutine::defer coredump in PHP8 (#3997) (@huanghantao) + * Fixed Coroutine::Socket::errCode is not set correctly when using thread context (swoole/swoole-src@004d08a) (@matyhtf) + * Fixed build Swoole error on latest macos (#4007) (@matyhtf) + * Fixed php stream context is nullptr when use md5_file with url (#4016) (@ZhiyangLeeCN) Kernel --- - * Optimized ipc writev, avoid coredump how event data is null (#3994) (@matyhtf) + * Used AIO thread hook stdio instead of coroutine socket (#4002) (@matyhtf) + * Refactor HttpContext (#3998) (@matyhtf) + * Fixed Github action (#4013) (#4020) (@sy-records) + * Refactor Process::wait() (#4019) (@matyhtf) @@ -1533,6 +1541,7 @@ + @@ -1779,7 +1788,9 @@ + + diff --git a/tests/swoole_runtime/stream_context_pass_null.phpt b/tests/swoole_runtime/stream_context_pass_null.phpt index b585ae02d98..be9280f1211 100644 --- a/tests/swoole_runtime/stream_context_pass_null.phpt +++ b/tests/swoole_runtime/stream_context_pass_null.phpt @@ -16,4 +16,4 @@ swoole_event_wait(); ?> --EXPECT-- -bool(true) \ No newline at end of file +bool(true) From 91ef1ec30c46538c123bc730d5285aebe63fda9b Mon Sep 17 00:00:00 2001 From: codinghuang Date: Mon, 25 Jan 2021 18:53:12 +0800 Subject: [PATCH 033/936] Fix rshutdown deprecated warning (#4026) When throw Exception, do not show the info --- ext-src/swoole_event.cc | 5 ++++- tests/swoole_event/deprecated_event_wait.phpt | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 tests/swoole_event/deprecated_event_wait.phpt diff --git a/ext-src/swoole_event.cc b/ext-src/swoole_event.cc index 8bf86fb3f62..03186ee67d5 100644 --- a/ext-src/swoole_event.cc +++ b/ext-src/swoole_event.cc @@ -735,7 +735,10 @@ static PHP_FUNCTION(swoole_event_rshutdown) { if (!sw_reactor()) { return; } - php_swoole_fatal_error(E_DEPRECATED, "Event::wait() in shutdown function is deprecated"); + // when throw Exception, do not show the info + if (!sw_reactor()->bailout) { + php_swoole_fatal_error(E_DEPRECATED, "Event::wait() in shutdown function is deprecated"); + } php_swoole_event_wait(); } zend_end_try(); diff --git a/tests/swoole_event/deprecated_event_wait.phpt b/tests/swoole_event/deprecated_event_wait.phpt new file mode 100644 index 00000000000..ab49ff4a27e --- /dev/null +++ b/tests/swoole_event/deprecated_event_wait.phpt @@ -0,0 +1,22 @@ +--TEST-- +swoole_event: deprecated_event_wait +--SKIPIF-- + +--FILE-- + +--EXPECT-- From 78a86c882fbc48b0c0a19f728dbdd66657309825 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Mon, 25 Jan 2021 18:53:28 +0800 Subject: [PATCH 034/936] Update ISSUE (#4027) * Update ISSUE * Fix typo --- .github/ISSUE-CN.md | 24 ++++++++++++------------ .github/ISSUE.md | 21 +++++++++++---------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/.github/ISSUE-CN.md b/.github/ISSUE-CN.md index 0c511db2799..90aef4945fb 100644 --- a/.github/ISSUE-CN.md +++ b/.github/ISSUE-CN.md @@ -5,11 +5,11 @@ # 需知 -当你觉得发现了一个Swoole内核的bug时, 请提出报告. +当你觉得发现了一个Swoole内核的BUG时, 请提出报告. Swoole的内核开发者们或许还不知道问题的存在, 除非你主动提出报告, 否则BUG也许将很难被发现并修复, 你可以在[Github的issue区](https://github.com/swoole/swoole-src/issues)提出错误报告(即点击右上角绿色的`New issue`按钮), 这里的错误报告将会被最优先解决. -请不要在邮件列表或私人信件中发送错误报告, Github的issue区同样可以提出对于Swoole的任何要求与建议. +请不要在邮件列表或私人信件中发送错误报告, GitHub的issue区同样可以提出对于Swoole的任何要求与建议. 在你提交错误报告之前, 请先阅读以下的**如何提交错误报告**. @@ -42,6 +42,16 @@ Please answer these questions before submitting your issue. Thanks! 其中, 最为关键的是提供**可稳定重现的简单脚本代码**, 否则你必须提供尽可能多的其它信息来帮助开发者判断错误原因 +## 内存分析 (强烈推荐) + +更多时候, Valgrind比gdb更能发现内存问题, 通过以下指令运行你的程序, 直到触发BUG + +```shell +USE_ZEND_ALLOC=0 valgrind --log-file=/tmp/valgrind.log php xxx.php +``` + +* 当程序发生错误时, 可以通过键入 `ctrl+c` 退出, 然后上传 `/tmp/valgrind.log` 文件以便于开发组定位BUG. + ## 关于段错误(核心转储) 此外, 在一种特殊情况下你可以使用调试工具来帮助开发者定位问题 @@ -77,13 +87,3 @@ gdb php /tmp/core.4596 ``` 将以上信息都贴在issue中 - -#### 内存分析 (强烈推荐) - -更多时候, Valgrind比gdb更能发现内存问题, 通过以下指令运行你的程序, 直到触发BUG - -```shell -USE_ZEND_ALLOC=0 valgrind --log-file=/tmp/valgrind.log php xxx.php -``` - -* 当程序发生错误时, 可以通过键入 `ctrl+c` 退出, 然后上传 `/tmp/valgrind.log` 文件以便于开发组定位BUG. diff --git a/.github/ISSUE.md b/.github/ISSUE.md index ce81bea2b39..8ea842da8e0 100644 --- a/.github/ISSUE.md +++ b/.github/ISSUE.md @@ -27,6 +27,16 @@ Please answer these questions before submitting your issue. Thanks! ``` The most important thing is to provide a simple script for reproducing the error, otherwise, you must provide as much information as possible. +## Memory detection (recommended) + +In addition to using `gdb` analysis, you can use the `valgrind` tool to check if the program is working properly. + +```shell +USE_ZEND_ALLOC=0 valgrind --log-file=/tmp/valgrind.log php xxx.php +``` + +* After the program is executed to the wrong location, `ctrl+c` is interrupted, and upload the `/tmp/valgrind.log` file. + ## CoreDump Besides, In a special case, you can use debugging tools to help developers locate problems @@ -60,16 +70,7 @@ Use the f command in gdb to view the code segment corresponding to the ID. ``` If there is no function call stack information, it may be that the compiler has removed the debug information. Please manually modify the `Makefile` file in the swoole source directory and modify CFLAGS to -```shell -CFLAGS = -Wall -pthread -g -O0 -``` - -#### Memory detection (recommended) - -In addition to using `gdb` analysis, you can use the `valgrind` tool to check if the program is working properly. ```shell -USE_ZEND_ALLOC=0 valgrind --log-file=/tmp/valgrind.log php xxx.php +CFLAGS = -Wall -pthread -g -O0 ``` - -* After the program is executed to the wrong location, `ctrl+c` is interrupted, and upload the `/tmp/valgrind.log` file. From 29be16fcd39b3d265a565f072cc67770c12ca3b8 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 26 Jan 2021 11:55:21 +0800 Subject: [PATCH 035/936] Optimize action flow name --- .github/workflows/{test.yml => test-linux.yml} | 4 ++-- README-CN.md | 2 +- README.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename .github/workflows/{test.yml => test-linux.yml} (95%) diff --git a/.github/workflows/test.yml b/.github/workflows/test-linux.yml similarity index 95% rename from .github/workflows/test.yml rename to .github/workflows/test-linux.yml index b439b6da0b5..2c4785c25e7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test-linux.yml @@ -1,9 +1,9 @@ -name: run-swoole-test +name: test-linux on: [push, pull_request] jobs: - run-swoole-test: + test-linux: runs-on: ubuntu-latest strategy: fail-fast: false diff --git a/README-CN.md b/README-CN.md index 5d261ea1500..43bbf6f53a4 100644 --- a/README-CN.md +++ b/README-CN.md @@ -6,7 +6,7 @@ [![License](https://img.shields.io/badge/license-apache2-blue.svg)](LICENSE) [![lib-swoole](https://github.com/swoole/swoole-src/workflows/lib-swoole/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Alib-swoole) [![ext-swoole](https://github.com/swoole/swoole-src/workflows/ext-swoole/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Aext-swoole) -[![run-swoole-test](https://github.com/swoole/swoole-src/workflows/run-swoole-test/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Arun-swoole-test) +[![test-linux](https://github.com/swoole/swoole-src/workflows/test-linux/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Atest-linux) [![Coverity Scan Build Status](https://scan.coverity.com/projects/11654/badge.svg)](https://scan.coverity.com/projects/swoole-swoole-src) [![codecov](https://codecov.io/gh/swoole/swoole-src/branch/master/graph/badge.svg)](https://codecov.io/gh/swoole/swoole-src) diff --git a/README.md b/README.md index 0c03e668b44..990c1fbbb03 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ English | [中文](./README-CN.md) [![License](https://img.shields.io/badge/license-apache2-blue.svg)](LICENSE) [![lib-swoole](https://github.com/swoole/swoole-src/workflows/lib-swoole/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Alib-swoole) [![ext-swoole](https://github.com/swoole/swoole-src/workflows/ext-swoole/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Aext-swoole) -[![run-swoole-test](https://github.com/swoole/swoole-src/workflows/run-swoole-test/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Arun-swoole-test) +[![test-linux](https://github.com/swoole/swoole-src/workflows/test-linux/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Atest-linux) [![Coverity Scan Build Status](https://scan.coverity.com/projects/11654/badge.svg)](https://scan.coverity.com/projects/swoole-swoole-src) [![codecov](https://codecov.io/gh/swoole/swoole-src/branch/master/graph/badge.svg)](https://codecov.io/gh/swoole/swoole-src) From 63ff79d3cd6b105e303f5e4a0572d714a33d62bc Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 26 Jan 2021 15:55:58 +0800 Subject: [PATCH 036/936] fix #4010 --- config.m4 | 1 + include/swoole_coroutine_context.h | 1 + 2 files changed, 2 insertions(+) diff --git a/config.m4 b/config.m4 index 2d6f09192d0..8193d9d691c 100644 --- a/config.m4 +++ b/config.m4 @@ -149,6 +149,7 @@ AC_DEFUN([AC_SWOOLE_HAVE_UCONTEXT], [ AC_MSG_CHECKING([for ucontext]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #define _XOPEN_SOURCE #include #include #include diff --git a/include/swoole_coroutine_context.h b/include/swoole_coroutine_context.h index 9f2bc31882b..e92c969f94b 100644 --- a/include/swoole_coroutine_context.h +++ b/include/swoole_coroutine_context.h @@ -24,6 +24,7 @@ #include #elif !defined(SW_USE_ASM_CONTEXT) #define USE_UCONTEXT 1 +#define _XOPEN_SOURCE #include #else #define USE_ASM_CONTEXT 1 From 709813fcc3f70ea9f2368746d7e80d9a0cae7c3d Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 26 Jan 2021 16:44:55 +0800 Subject: [PATCH 037/936] fix #4028 --- ext-src/php_swoole.h | 6 ++++++ ext-src/swoole_runtime.cc | 6 ------ thirdparty/php/streams/plain_wrapper.c | 16 +++++----------- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/ext-src/php_swoole.h b/ext-src/php_swoole.h index 4eb04cd1566..313269d7832 100644 --- a/ext-src/php_swoole.h +++ b/ext-src/php_swoole.h @@ -425,6 +425,12 @@ extern ZEND_DECLARE_MODULE_GLOBALS(swoole); #endif /*}}}*/ +#if PHP_VERSION_ID < 70400 +typedef size_t php_stream_size_t; +#else +typedef ssize_t php_stream_size_t; +#endif + /* PHP 7 wrapper functions / macros */ //----------------------------------Zval API------------------------------------ diff --git a/ext-src/swoole_runtime.cc b/ext-src/swoole_runtime.cc index d7822fae42b..9f72fa4bcb8 100644 --- a/ext-src/swoole_runtime.cc +++ b/ext-src/swoole_runtime.cc @@ -37,12 +37,6 @@ #define HAVE_SEC_LEVEL 1 #endif -#if PHP_VERSION_ID < 70400 -typedef size_t php_stream_size_t; -#else -typedef ssize_t php_stream_size_t; -#endif - using swoole::Coroutine; using swoole::PHPCoroutine; using swoole::coroutine::Socket; diff --git a/thirdparty/php/streams/plain_wrapper.c b/thirdparty/php/streams/plain_wrapper.c index 4be72ac6ed8..de6257368b2 100644 --- a/thirdparty/php/streams/plain_wrapper.c +++ b/thirdparty/php/streams/plain_wrapper.c @@ -18,14 +18,12 @@ /* $Id$ */ -#include "php.h" -#include "php_globals.h" -#include "php_network.h" +#include "php_swoole.h" #include "php_open_temporary_file.h" #include "ext/standard/file.h" #include "ext/standard/flock_compat.h" #include "ext/standard/php_filestat.h" -#include + #include #if HAVE_SYS_WAIT_H #include @@ -36,15 +34,8 @@ #ifdef HAVE_SYS_MMAN_H #include #endif -#include "SAPI.h" #include "thirdparty/php/streams/php_streams_int.h" -#ifdef PHP_WIN32 -#include "win32/winutil.h" -#include "win32/time.h" -#include "win32/ioutil.h" -#include "win32/readdir.h" -#endif #include "swoole_file_hook.h" @@ -891,6 +882,9 @@ static php_stream *stream_opener(php_stream_wrapper *wrapper, if (options & STREAM_OPEN_FOR_INCLUDE) { _open_for_include: stream = php_stream_fopen_rel(path, mode, opened_path, options); + if (stream == NULL) { + return NULL; + } stream->ops = php_swoole_get_ori_php_stream_stdio_ops(); return stream; } From b63dbe194596143ed66bc21b55c657e7dd2b4a15 Mon Sep 17 00:00:00 2001 From: twosee Date: Wed, 27 Jan 2021 20:09:49 +0800 Subject: [PATCH 038/936] Magic way to avoid JIT being disabled (#4029) --- ext-src/php_swoole.cc | 1 + ext-src/php_swoole.h | 1 + ext-src/swoole_coroutine.cc | 2 ++ 3 files changed, 4 insertions(+) diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index 42681f4c30c..d981277339c 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -1000,6 +1000,7 @@ PHP_RINIT_FUNCTION(swoole) { SIGG(check) = 0; #endif + php_swoole_coroutine_rinit(); php_swoole_runtime_rinit(); SWOOLE_G(req_status) = PHP_SWOOLE_RINIT_END; diff --git a/ext-src/php_swoole.h b/ext-src/php_swoole.h index 313269d7832..a3f10f2f37a 100644 --- a/ext-src/php_swoole.h +++ b/ext-src/php_swoole.h @@ -252,6 +252,7 @@ void php_swoole_redis_server_minit(int module_number); * RINIT * ============================================================== */ +void php_swoole_coroutine_rinit(); void php_swoole_runtime_rinit(); /** diff --git a/ext-src/swoole_coroutine.cc b/ext-src/swoole_coroutine.cc index 6255d30a4b2..684ec32c276 100644 --- a/ext-src/swoole_coroutine.cc +++ b/ext-src/swoole_coroutine.cc @@ -877,7 +877,9 @@ void php_swoole_coroutine_minit(int module_number) { SW_REGISTER_LONG_CONSTANT("SWOOLE_EXIT_IN_COROUTINE", SW_EXIT_IN_COROUTINE); SW_REGISTER_LONG_CONSTANT("SWOOLE_EXIT_IN_SERVER", SW_EXIT_IN_SERVER); +} +void php_swoole_coroutine_rinit() { if (SWOOLE_G(cli)) { ori_exit_handler = zend_get_user_opcode_handler(ZEND_EXIT); zend_set_user_opcode_handler(ZEND_EXIT, coro_exit_handler); From 8f075dcd3790443850c96035f53439a388e16d90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Thu, 28 Jan 2021 00:10:15 +0800 Subject: [PATCH 039/936] optimize ssl_connect/ssl_shutdown (#4030) * optimize ssl_connect/ssl_shutdown * optimize ssl_shutdown * ssl core-tests * fix core-tests * fix core-tests [2] * fix core-tests [3] * skip in github action --- .github/workflows/lib.yml | 13 ++++- core-tests/src/network/client.cpp | 5 ++ include/swoole_process_pool.h | 4 +- include/swoole_socket.h | 3 ++ src/coroutine/socket.cc | 3 +- src/network/socket.cc | 57 ++++++++++++-------- tests/swoole_socket_coro/ssl.phpt | 51 ++++++++++++++++++ tests/swoole_socket_coro/ssl_bad_server.phpt | 24 +++++++++ travis/docker-compose.yml | 2 +- 9 files changed, 132 insertions(+), 30 deletions(-) create mode 100644 tests/swoole_socket_coro/ssl.phpt create mode 100644 tests/swoole_socket_coro/ssl_bad_server.phpt diff --git a/.github/workflows/lib.yml b/.github/workflows/lib.yml index f16a96a01cb..fcf2009fdda 100644 --- a/.github/workflows/lib.yml +++ b/.github/workflows/lib.yml @@ -7,9 +7,18 @@ env: jobs: build: - runs-on: ubuntu-latest + services: + tinyproxy: + image: "vimagick/tinyproxy" + ports: + - 8888:8888 + socks5: + image: "xkuma/socks5" + ports: + - 1080:1080 + steps: - uses: actions/checkout@v1 @@ -25,7 +34,7 @@ jobs: sudo rm -rf /usr/src/googletest/googletest/build - name: configure - run: phpize && ./configure --enable-sockets --enable-mysqlnd --enable-http2 + run: phpize && ./configure --enable-sockets --enable-mysqlnd --enable-http2 --enable-openssl - name: make run: cmake . -DCODE_COVERAGE=ON && diff --git a/core-tests/src/network/client.cpp b/core-tests/src/network/client.cpp index 686e9f8c2b2..2447ea45e28 100644 --- a/core-tests/src/network/client.cpp +++ b/core-tests/src/network/client.cpp @@ -246,6 +246,11 @@ TEST(client, ssl_1) { } TEST(client, http_proxy) { + // skip in github action + if (swoole::test::is_github_ci()) { + return; + } + int ret; bool connected = false; diff --git a/include/swoole_process_pool.h b/include/swoole_process_pool.h index 89eb4aa9cb1..6ea3a6fa136 100644 --- a/include/swoole_process_pool.h +++ b/include/swoole_process_pool.h @@ -71,13 +71,13 @@ class ExitStatus { } }; -static ExitStatus wait_process() { +static inline ExitStatus wait_process() { int status = 0; pid_t pid = ::wait(&status); return ExitStatus(pid, status); } -static ExitStatus wait_process(pid_t _pid, int options) { +static inline ExitStatus wait_process(pid_t _pid, int options) { int status = 0; pid_t pid = ::waitpid(_pid, &status, options); return ExitStatus(pid, status); diff --git a/include/swoole_socket.h b/include/swoole_socket.h index a2042a8a055..4dbc9f96d62 100644 --- a/include/swoole_socket.h +++ b/include/swoole_socket.h @@ -168,6 +168,7 @@ struct Socket { uchar ssl_renegotiation : 1; uchar ssl_handshake_buffer_set : 1; uchar ssl_quiet_shutdown : 1; + uchar ssl_closed_ : 1; #ifdef SW_SUPPORT_DTLS uchar dtls : 1; #endif @@ -368,7 +369,9 @@ struct Socket { bool ssl_verify(bool allow_self_signed); bool ssl_check_host(const char *tls_host_name); void ssl_catch_error(); + bool ssl_shutdown(); void ssl_close(); + const char *ssl_get_error_reason(int *reason); #endif inline ssize_t recvfrom(char *__buf, size_t __len, int flags, Address *sa) { diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index 04533962017..0ecfaf7d864 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -1623,8 +1623,7 @@ bool Socket::shutdown(int __how) { } else { #ifdef SW_USE_OPENSSL if (socket->ssl) { - SSL_set_quiet_shutdown(socket->ssl, 0); - SSL_shutdown(socket->ssl); + socket->ssl_shutdown(); } #endif if (::shutdown(sock_fd, __how) == 0 || errno == ENOTCONN) { diff --git a/src/network/socket.cc b/src/network/socket.cc index 86c93093863..7d8e0cf9ce8 100644 --- a/src/network/socket.cc +++ b/src/network/socket.cc @@ -1046,6 +1046,12 @@ int Socket::ssl_get_peer_certificate(char *buffer, size_t length) { return _ssl_read_x509_file(cert, buffer, length); } +const char *Socket::ssl_get_error_reason(int *reason) { + int error = ERR_get_error(); + *reason = ERR_GET_REASON(error); + return ERR_reason_error_string(error); +} + enum swReturn_code Socket::ssl_accept() { ssl_clear_error(); @@ -1081,9 +1087,8 @@ enum swReturn_code Socket::ssl_accept() { ssl_want_write = 1; return SW_WAIT; } else if (err == SSL_ERROR_SSL) { - int error = ERR_get_error(); - int reason = ERR_GET_REASON(error); - const char *error_string = ERR_reason_error_string(error); + int reason; + const char *error_string = ssl_get_error_reason(&reason); swWarn( "bad SSL client[%s:%d], reason=%d, error_string=%s", info.get_ip(), info.get_port(), reason, error_string); return SW_ERROR; @@ -1139,7 +1144,8 @@ int Socket::ssl_connect() { long err_code = ERR_get_error(); char *msg = ERR_error_string(err_code, sw_tg_buffer()->str); - swWarn("SSL_connect(fd=%d) failed. Error: %s[%ld|%d]", fd, msg, err, ERR_GET_REASON(err_code)); + swNotice("Socket::ssl_connect(fd=%d) to server[%s:%d] failed. Error: %s[%ld|%d]", fd, info.get_ip(), info.get_port(), msg, + err, ERR_GET_REASON(err_code)); return SW_ERR; } @@ -1166,20 +1172,13 @@ int Socket::ssl_sendfile(const File &fp, off_t *_offset, size_t _size) { } } -void Socket::ssl_close() { - int n, sslerr, err; - +bool Socket::ssl_shutdown() { + if (ssl_closed_) { + return false; + } if (SSL_in_init(ssl)) { - /* - * OpenSSL 1.0.2f complains if SSL_shutdown() is called during - * an SSL handshake, while previous versions always return 0. - * Avoid calling SSL_shutdown() if handshake wasn't completed. - */ - SSL_free(ssl); - ssl = nullptr; - return; + return false; } - /** * If the peer close first, local should be set to quiet mode and do not send any data, * otherwise the peer will send RST segment. @@ -1189,15 +1188,13 @@ void Socket::ssl_close() { } int mode = SSL_get_shutdown(ssl); - SSL_set_shutdown(ssl, mode | SSL_RECEIVED_SHUTDOWN | SSL_SENT_SHUTDOWN); - n = SSL_shutdown(ssl); - + int n = SSL_shutdown(ssl); + ssl_closed_ = 1; swTrace("SSL_shutdown: %d", n); - sslerr = 0; - + int sslerr = 0; /* before 0.9.8m SSL_shutdown() returned 0 instead of -1 on errors */ if (n != 1 && ERR_peek_error()) { sslerr = SSL_get_error(ssl, n); @@ -1205,10 +1202,24 @@ void Socket::ssl_close() { } if (!(n == 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN)) { - err = (sslerr == SSL_ERROR_SYSCALL) ? errno : 0; - swWarn("SSL_shutdown() failed. Error: %d:%d", sslerr, err); + int reason; + const char *error_string = ssl_get_error_reason(&reason); + swWarn("SSL_shutdown() failed, reason=%d, error_string=%s", reason, error_string); + return false; } + return true; +} + +void Socket::ssl_close() { + /* + * OpenSSL 1.0.2f complains if SSL_shutdown() is called during + * an SSL handshake, while previous versions always return 0. + * Avoid calling SSL_shutdown() if handshake wasn't completed. + */ + if (!ssl_closed_) { + ssl_shutdown(); + } SSL_free(ssl); ssl = nullptr; } diff --git a/tests/swoole_socket_coro/ssl.phpt b/tests/swoole_socket_coro/ssl.phpt new file mode 100644 index 00000000000..41e3f8dd756 --- /dev/null +++ b/tests/swoole_socket_coro/ssl.phpt @@ -0,0 +1,51 @@ +--TEST-- +swoole_socket_coro: ssl client +--SKIPIF-- + +--FILE-- +setProtocol(['open_ssl' => true,]); + + if (!$cli->connect('www.baidu.com', 443)) { + echo "ERROR\n"; + } + + $http = "GET / HTTP/1.1\r\nAccept: */*User-Agent: Lowell-Agent\r\nHost: www.baidu.com\r\nConnection: Keep-Alive\r\n" + . "Keep-Alive: on\r\n\r\n"; + if (!$cli->send($http)) { + echo "ERROR\n"; + } + + $content = ''; + $length = 0; + while (true) { + $read = $cli->recv(); + if (empty($read)) { + var_dump($read); + break; + } + $content .= $read; + if ($length == 0) { + if (preg_match('#Content-Length: (\d+)#i', $content, $match)) { + $length = intval($match[1]); + } + } + $header_length = strpos($content, "\r\n\r\n"); + if (strlen($content) == $length + $header_length + 4) { + break; + } + } + $cli->close(); + Assert::assert(strpos($content, 'map.baidu.com') !== false); +}); +?> +--EXPECT-- diff --git a/tests/swoole_socket_coro/ssl_bad_server.phpt b/tests/swoole_socket_coro/ssl_bad_server.phpt new file mode 100644 index 00000000000..f690f34fa15 --- /dev/null +++ b/tests/swoole_socket_coro/ssl_bad_server.phpt @@ -0,0 +1,24 @@ +--TEST-- +swoole_socket_coro: ssl connect with bad server +--SKIPIF-- + +--FILE-- + SWOOLE_LOG_WARNING]); + +run(function () { + $cli = new Swoole\Coroutine\Socket(AF_INET, SOCK_STREAM, 0); + $cli->setProtocol(['open_ssl' => true,]); + + Assert::false ($cli->connect('www.baidu.com', 80)); + Assert::eq($cli->errCode, SWOOLE_ERROR_SSL_HANDSHAKE_FAILED); +}); +?> +--EXPECT-- diff --git a/travis/docker-compose.yml b/travis/docker-compose.yml index 73cda611f23..00fcffbb029 100755 --- a/travis/docker-compose.yml +++ b/travis/docker-compose.yml @@ -40,7 +40,7 @@ services: httpbin: container_name: "httpbin" image: "kennethreitz/httpbin" - goproxy: + tinyproxy: container_name: "tinyproxy" image: "vimagick/tinyproxy" socks5: From a131fa874aa4577d22c3d0c3acf24e8976d8e713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Thu, 28 Jan 2021 18:07:38 +0800 Subject: [PATCH 040/936] Optimize http (#4032) * improve httpclient * fix bugs * improve library, fix type * fix tests --- ext-src/php_swoole_library.h | 52 ++++++++++++------ ext-src/swoole_http_client_coro.cc | 11 +++- ext-src/swoole_http_server.cc | 4 +- src/network/client.cc | 2 +- src/server/process.cc | 2 +- .../sendfile_no_keepalive.phpt | 55 +++++++++++++++++++ .../sendfile_with_dispatch_mode_7.phpt | 54 ++++++++++++++++++ .../swoole_http_server/sendfile_with_ssl.phpt | 47 ++++++++++++++++ .../curl_native/yield_in_callback.phpt | 2 +- 9 files changed, 204 insertions(+), 25 deletions(-) create mode 100644 tests/swoole_http_server/sendfile_no_keepalive.phpt create mode 100644 tests/swoole_http_server/sendfile_with_dispatch_mode_7.phpt create mode 100644 tests/swoole_http_server/sendfile_with_ssl.phpt diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index 658c21a5540..ea7a16a4963 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: d11b08d63da2235271f6423764b5b0a5ab803b5e */ +/* $Id: 92fd0de7d122fd973205d73931bda42c3bc80bb7 */ static const char* swoole_library_source_constants = "\n" @@ -6844,6 +6844,27 @@ static const char* swoole_library_source_core_coroutine_functions = "\n" "use Swoole\\Coroutine;\n" "\n" + "function run(callable $fn, ...$args)\n" + "{\n" + " $s = new Scheduler();\n" + " $options = Coroutine::getOptions();\n" + " if (!isset($options['hook_flags'])) {\n" + " $s->set(['hook_flags' => SWOOLE_HOOK_ALL]);\n" + " }\n" + " $s->add($fn, ...$args);\n" + " return $s->start();\n" + "}\n" + "\n" + "function go(callable $fn, ...$args)\n" + "{\n" + " Coroutine::create($fn, ...$args);\n" + "}\n" + "\n" + "function defer(callable $fn)\n" + "{\n" + " Coroutine::defer($fn);\n" + "}\n" + "\n" "function batch(array $tasks, float $timeout = -1): array\n" "{\n" " $wg = new WaitGroup(count($tasks));\n" @@ -7392,27 +7413,24 @@ static const char* swoole_library_source_alias_ns = "\n" "declare(strict_types=1);\n" "\n" - "namespace Swoole\\Coroutine {\n" - " use Swoole\\Coroutine;\n" + "namespace Co;\n" "\n" + "use Swoole\\Coroutine;\n" + "\n" + "if (SWOOLE_USE_SHORTNAME) {\n" " function run(callable $fn, ...$args)\n" " {\n" - " $s = new Scheduler();\n" - " $options = Coroutine::getOptions();\n" - " if (!isset($options['hook_flags'])) {\n" - " $s->set(['hook_flags' => SWOOLE_HOOK_ALL]);\n" - " }\n" - " $s->add($fn, ...$args);\n" - " return $s->start();\n" + " return \\Swoole\\Coroutine\\run($fn, ...$args);\n" " }\n" - "}\n" "\n" - "namespace Co {\n" - " if (SWOOLE_USE_SHORTNAME) {\n" - " function run(callable $fn, ...$args)\n" - " {\n" - " return \\Swoole\\Coroutine\\run($fn, ...$args);\n" - " }\n" + " function go(callable $fn, ...$args)\n" + " {\n" + " return Coroutine::create($fn, ...$args);\n" + " }\n" + "\n" + " function defer(callable $fn)\n" + " {\n" + " Coroutine::defer($fn);\n" " }\n" "}\n"; diff --git a/ext-src/swoole_http_client_coro.cc b/ext-src/swoole_http_client_coro.cc index 9afac29383d..9e6225e5701 100644 --- a/ext-src/swoole_http_client_coro.cc +++ b/ext-src/swoole_http_client_coro.cc @@ -1034,13 +1034,18 @@ bool HttpClient::send() { header_flag |= HTTP_HEADER_CONTENT_LENGTH; // ignore custom Content-Length value continue; - } else if (SW_STRCASEEQ(key, keylen, "Connection")) { + } + zend::String str_value(zvalue); + add_headers(buffer, key, keylen, str_value.val(), str_value.len()); + + if (SW_STRCASEEQ(key, keylen, "Connection")) { header_flag |= HTTP_HEADER_CONNECTION; + if (SW_STRCASEEQ(str_value.val(), str_value.len(), "close")) { + keep_alive = 0; + } } else if (SW_STRCASEEQ(key, keylen, "Accept-Encoding")) { header_flag |= HTTP_HEADER_ACCEPT_ENCODING; } - zend::String str_value(zvalue); - add_headers(buffer, key, keylen, str_value.val(), str_value.len()); } SW_HASHTABLE_FOREACH_END(); } diff --git a/ext-src/swoole_http_server.cc b/ext-src/swoole_http_server.cc index b68e8d82561..ec1023ccc10 100644 --- a/ext-src/swoole_http_server.cc +++ b/ext-src/swoole_http_server.cc @@ -298,10 +298,10 @@ bool http_context_send_data(http_context *ctx, const char *data, size_t length) static bool http_context_sendfile(http_context *ctx, const char *file, uint32_t l_file, off_t offset, size_t length) { Server *serv = (Server *) ctx->private_data; - return serv->sendfile(ctx->fd, file, l_file, offset, length) == SW_OK; + return serv->sendfile(ctx->fd, file, l_file, offset, length); } static bool http_context_disconnect(http_context *ctx) { Server *serv = (Server *) ctx->private_data; - return serv->close(ctx->fd, 0) == SW_OK; + return serv->close(ctx->fd, 0); } diff --git a/src/network/client.cc b/src/network/client.cc index b6cb6f82b5f..ddf783f5a1f 100644 --- a/src/network/client.cc +++ b/src/network/client.cc @@ -665,7 +665,7 @@ static int Client_tcp_connect_async(Client *cli, const char *host, int port, dou } static ssize_t Client_tcp_send_async(Client *cli, const char *data, size_t length, int flags) { - int n = length; + ssize_t n = length; if (swoole_event_write(cli->socket, data, length) < 0) { if (swoole_get_last_error() == SW_ERROR_OUTPUT_BUFFER_OVERFLOW) { n = -1; diff --git a/src/server/process.cc b/src/server/process.cc index 03c28eb8443..1e4c667d2fd 100644 --- a/src/server/process.cc +++ b/src/server/process.cc @@ -341,7 +341,7 @@ bool ProcessFactory::finish(SendData *resp) { if (swoole_event_write(server_->last_stream_socket, &resp->info, sizeof(resp->info)) < 0) { return false; } - if (swoole_event_write(server_->last_stream_socket, resp->data, _len) < 0) { + if (_len > 0 && swoole_event_write(server_->last_stream_socket, resp->data, _len) < 0) { return false; } return true; diff --git a/tests/swoole_http_server/sendfile_no_keepalive.phpt b/tests/swoole_http_server/sendfile_no_keepalive.phpt new file mode 100644 index 00000000000..3886d0a4437 --- /dev/null +++ b/tests/swoole_http_server/sendfile_no_keepalive.phpt @@ -0,0 +1,55 @@ +--TEST-- +swoole_http_server: sendfile with dispatch_mode=7 +--SKIPIF-- + +--FILE-- +parentFunc = function ($pid) use ($pm) { + run(function () use ($pm) { + $n = MAX_CONCURRENCY_LOW; + while ($n--) { + go(function () use ($pm) { + $cli = new Client('127.0.0.1', $pm->getFreePort()); + $cli->setHeaders(['KeepAlive' => 'off', 'Connection' => 'close']); + for ($i = MAX_REQUESTS_LOW; $i--;) { + $cli->get('/'); + Assert::contains($cli->getBody(), 'swoole_http_server: sendfile with dispatch_mode=7'); + } + }); + } + }); + echo "DONE\n"; + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm) { + $http = new Server('0.0.0.0', $pm->getFreePort(), SWOOLE_PROCESS, SWOOLE_SOCK_TCP); + $http->set([ + 'log_file' => '/dev/null', + 'dispatch_mode' => 7, + ]); + $http->on('workerStart', function () use ($pm) { + $pm->wakeup(); + }); + $http->on('request', function (swoole_http_request $request, swoole_http_response $response) { + $response->sendfile(__FILE__); + }); + + $http->on('message', function(){}); + $http->start(); +}; +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +DONE diff --git a/tests/swoole_http_server/sendfile_with_dispatch_mode_7.phpt b/tests/swoole_http_server/sendfile_with_dispatch_mode_7.phpt new file mode 100644 index 00000000000..a7ac241ef54 --- /dev/null +++ b/tests/swoole_http_server/sendfile_with_dispatch_mode_7.phpt @@ -0,0 +1,54 @@ +--TEST-- +swoole_http_server: sendfile with dispatch_mode=7 +--SKIPIF-- + +--FILE-- +parentFunc = function ($pid) use ($pm) { + run(function () use ($pm) { + $n = MAX_CONCURRENCY_LOW; + while ($n--) { + go(function () use ($pm) { + $cli = new Client('127.0.0.1', $pm->getFreePort()); + for ($i = MAX_REQUESTS_LOW; $i--;) { + $cli->get('/'); + Assert::contains($cli->getBody(), 'swoole_http_server: sendfile with dispatch_mode=7'); + } + }); + } + }); + echo "DONE\n"; + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm) { + $http = new Server('0.0.0.0', $pm->getFreePort(), SWOOLE_PROCESS, SWOOLE_SOCK_TCP); + $http->set([ + 'log_file' => '/dev/null', + 'dispatch_mode' => 7, + ]); + $http->on('workerStart', function () use ($pm) { + $pm->wakeup(); + }); + $http->on('request', function (swoole_http_request $request, swoole_http_response $response) { + $response->sendfile(__FILE__); + }); + + $http->on('message', function(){}); + $http->start(); +}; +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +DONE diff --git a/tests/swoole_http_server/sendfile_with_ssl.phpt b/tests/swoole_http_server/sendfile_with_ssl.phpt new file mode 100644 index 00000000000..0ce6ade1c08 --- /dev/null +++ b/tests/swoole_http_server/sendfile_with_ssl.phpt @@ -0,0 +1,47 @@ +--TEST-- +swoole_http_server: sendfile with ssl +--SKIPIF-- + +--FILE-- +parentFunc = function ($pid) use ($pm) { + for ($i = MAX_REQUESTS; $i--;) { + $send_file = get_safe_random(mt_rand(0, 65535 * 10)); + file_put_contents('/tmp/sendfile.txt', $send_file); + + $ctxArr = [ + 'verify_peer' => false, + ]; + $ctx = stream_context_create(['ssl' => $ctxArr]); + $recv_file = file_get_contents("https://127.0.0.1:{$pm->getFreePort()}", false, $ctx); + Assert::same($send_file, $recv_file); + } + echo "DONE\n"; + $pm->kill(); +}; +$pm->childFunc = function () use ($pm) { + $http = new swoole_http_server('127.0.0.1', $pm->getFreePort(), SERVER_MODE_RANDOM, SWOOLE_SOCK_TCP | SWOOLE_SSL); + $http->set([ + 'worker_num' => 1, + 'log_file' => '/dev/null', + 'ssl_cert_file' => SSL_FILE_DIR . '/server.crt', + 'ssl_key_file' => SSL_FILE_DIR . '/server.key', + ]); + $http->on('workerStart', function () use ($pm) { + $pm->wakeup(); + }); + $http->on('request', function (swoole_http_request $request, swoole_http_response $response) { + $response->header('Content-Type', 'application/octet-stream'); + $response->header('Content-Disposition', 'attachment; filename=recvfile.txt'); + $response->sendfile('/tmp/sendfile.txt'); + }); + $http->start(); +}; +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +DONE diff --git a/tests/swoole_runtime/curl_native/yield_in_callback.phpt b/tests/swoole_runtime/curl_native/yield_in_callback.phpt index d0e85ba33f8..fe5295e3780 100644 --- a/tests/swoole_runtime/curl_native/yield_in_callback.phpt +++ b/tests/swoole_runtime/curl_native/yield_in_callback.phpt @@ -48,7 +48,7 @@ Fatal error: Uncaught Swoole\Error: API must be called in the coroutine in %s:%d Stack trace: #0 %s(%d): Swoole\Coroutine::sleep(0.1) #1 [internal function]: {closure}(Resource id #%d, 'HTTP/1.1 200 OK...') -#2 @swoole-src/library/alias_ns.php(%d): Swoole\Coroutine\Scheduler->start() +#2 @swoole-src/library/core/Coroutine/functions.php(%d): Swoole\Coroutine\Scheduler->start() #3 %s(%d): Swoole\Coroutine\run(Object(Closure)) #4 {main} thrown in %s on line %d From 2300af59aedcded7837848975130cf6f9764f19f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Fri, 29 Jan 2021 19:38:13 +0800 Subject: [PATCH 041/936] Add compression_min_length option (#4033) * add gip_min_length * rename, add tests * fix tests * optimize --- ext-src/php_swoole_http.h | 1 + ext-src/php_swoole_library.h | 1 + ext-src/swoole_http_response.cc | 18 +++---- ext-src/swoole_http_server.cc | 1 + ext-src/swoole_http_server_coro.cc | 6 +++ ext-src/swoole_server.cc | 3 ++ include/swoole_config.h | 1 + include/swoole_server.h | 1 + src/server/master.cc | 1 + tests/swoole_http_server/bug_2947.phpt | 2 +- .../compression_min_length.phpt | 45 +++++++++++++++++ .../compression_min_length.phpt | 49 +++++++++++++++++++ 12 files changed, 119 insertions(+), 10 deletions(-) create mode 100644 tests/swoole_http_server/compression_min_length.phpt create mode 100644 tests/swoole_http_server_coro/compression_min_length.phpt diff --git a/ext-src/php_swoole_http.h b/ext-src/php_swoole_http.h index 86d8a5796a3..f8fe7a36d7e 100644 --- a/ext-src/php_swoole_http.h +++ b/ext-src/php_swoole_http.h @@ -148,6 +148,7 @@ struct Context { #ifdef SW_HAVE_COMPRESSION int8_t compression_level; int8_t compression_method; + uint32_t compression_min_length; #endif Request request; diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index ea7a16a4963..4b70bcd114b 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -6718,6 +6718,7 @@ static const char* swoole_library_source_core_server_helper = " 'http_parse_files' => true,\n" " 'http_compression' => true,\n" " 'http_compression_level' => true,\n" + " 'compression_min_length' => true,\n" " 'http_gzip_level' => true,\n" " 'websocket_compression' => true,\n" " 'upload_tmp_dir' => true,\n" diff --git a/ext-src/swoole_http_response.cc b/ext-src/swoole_http_response.cc index c391568d0f3..57fcf49c9a6 100644 --- a/ext-src/swoole_http_response.cc +++ b/ext-src/swoole_http_response.cc @@ -38,11 +38,11 @@ extern "C" { #include #endif -using swoole::coroutine::Socket; -using swoole::Server; using swoole::Connection; +using swoole::Server; using swoole::String; using swoole::substr_len; +using swoole::coroutine::Socket; using http_response = swoole::http::Response; using http_context = swoole::http::Context; @@ -784,9 +784,9 @@ void http_context::end(zval *zdata, zval *return_value) { http_buffer->clear(); #ifdef SW_HAVE_COMPRESSION if (accept_compression) { - if (http_body.length == 0 || - swoole_http_response_compress( - http_body.str, http_body.length, compression_method, compression_level) != SW_OK) { + if (http_body.length == 0 || http_body.length < compression_min_length || + swoole_http_response_compress(http_body.str, http_body.length, compression_method, compression_level) != + SW_OK) { accept_compression = 0; } } @@ -1329,7 +1329,7 @@ static PHP_METHOD(swoole_http_response, create) { ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); if (ZVAL_IS_OBJECT(zobject)) { - _type_detect: + _type_detect: if (instanceof_function(Z_OBJCE_P(zobject), swoole_server_ce)) { serv = php_swoole_server_get_and_check_server(zobject); if (serv->get_connection_verify(fd) == nullptr) { @@ -1340,18 +1340,18 @@ static PHP_METHOD(swoole_http_response, create) { sock = php_swoole_get_socket(zobject); fd = sock->get_fd(); } else { - _bad_type: + _bad_type: php_swoole_fatal_error(E_WARNING, "parameter $1 must be instanceof Server or Coroutine\\Socket"); RETURN_FALSE; } - } else if (ZVAL_IS_ARRAY(zobject)) { + } else if (ZVAL_IS_ARRAY(zobject)) { zrequest = zend_hash_index_find(Z_ARR_P(zobject), 1); if (!ZVAL_IS_OBJECT(zrequest) || !instanceof_function(Z_OBJCE_P(zrequest), swoole_http_request_ce)) { php_swoole_fatal_error(E_WARNING, "parameter $1.second must be instanceof Http\\Request"); RETURN_FALSE; } zobject = zend_hash_index_find(Z_ARR_P(zobject), 0); - if (!ZVAL_IS_OBJECT(zobject)) { + if (!ZVAL_IS_OBJECT(zobject)) { goto _bad_type; } else { ctx = php_swoole_http_request_get_context(zrequest); diff --git a/ext-src/swoole_http_server.cc b/ext-src/swoole_http_server.cc index ec1023ccc10..3bf976b6450 100644 --- a/ext-src/swoole_http_server.cc +++ b/ext-src/swoole_http_server.cc @@ -195,6 +195,7 @@ void http_context::init(Server *serv) { #ifdef SW_HAVE_COMPRESSION enable_compression = serv->http_compression; compression_level = serv->http_compression_level; + compression_min_length = serv->compression_min_length; #endif upload_tmp_dir = serv->upload_tmp_dir; bind(serv); diff --git a/ext-src/swoole_http_server_coro.cc b/ext-src/swoole_http_server_coro.cc index 08df5313697..7e53bc3b93f 100644 --- a/ext-src/swoole_http_server_coro.cc +++ b/ext-src/swoole_http_server_coro.cc @@ -67,6 +67,7 @@ class http_server { char *upload_tmp_dir; #ifdef SW_HAVE_COMPRESSION uint8_t http_compression_level; + uint32_t compression_min_length; #endif http_server(enum swSocket_type type) { @@ -81,6 +82,7 @@ class http_server { #ifdef SW_HAVE_COMPRESSION http_compression = true; http_compression_level = SW_Z_BEST_SPEED; + compression_min_length = SW_COMPRESSION_MIN_LENGTH_DEFAULT; #endif #ifdef SW_HAVE_ZLIB websocket_compression = false; @@ -121,6 +123,7 @@ class http_server { #ifdef SW_HAVE_COMPRESSION ctx->enable_compression = http_compression; ctx->compression_level = http_compression_level; + ctx->compression_min_length = compression_min_length; #endif #ifdef SW_HAVE_ZLIB ctx->websocket_compression = websocket_compression; @@ -472,6 +475,9 @@ static PHP_METHOD(swoole_http_server_coro, start) { } hs->http_compression_level = level; } + if (php_swoole_array_get_value(vht, "compression_min_length", ztmp)) { + hs->compression_min_length = zval_get_long(ztmp); + } #endif #ifdef SW_HAVE_ZLIB if (php_swoole_array_get_value(vht, "websocket_compression", ztmp)) { diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index f734d3898f1..db271c58037 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -2527,6 +2527,9 @@ static PHP_METHOD(swoole_server, set) { } serv->http_compression_level = level; } + if (php_swoole_array_get_value(vht, "compression_min_length", ztmp)) { + serv->compression_min_length = zval_get_long(ztmp); + } #endif #ifdef SW_HAVE_ZLIB diff --git a/include/swoole_config.h b/include/swoole_config.h index 7b6bd0a7e7d..7ee5d23af01 100644 --- a/include/swoole_config.h +++ b/include/swoole_config.h @@ -194,6 +194,7 @@ #define SW_DNS_DEFAULT_SERVER "8.8.8.8" #define SW_Z_BEST_SPEED 1 +#define SW_COMPRESSION_MIN_LENGTH_DEFAULT 20 #ifndef IOV_MAX #define IOV_MAX 16 diff --git a/include/swoole_server.h b/include/swoole_server.h index 72629f28be1..bf895329ce7 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -797,6 +797,7 @@ class Server { */ #ifdef SW_HAVE_COMPRESSION uint8_t http_compression_level = 0; + uint32_t compression_min_length; #endif /** * master process pid diff --git a/src/server/master.cc b/src/server/master.cc index 6590d807d51..b7df715c12d 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -645,6 +645,7 @@ Server::Server(enum Mode _mode) { #ifdef SW_HAVE_COMPRESSION http_compression = 1; http_compression_level = SW_Z_BEST_SPEED; + compression_min_length = SW_COMPRESSION_MIN_LENGTH_DEFAULT; #endif #ifdef __linux__ diff --git a/tests/swoole_http_server/bug_2947.phpt b/tests/swoole_http_server/bug_2947.phpt index b10af32e9e1..302849846de 100644 --- a/tests/swoole_http_server/bug_2947.phpt +++ b/tests/swoole_http_server/bug_2947.phpt @@ -37,7 +37,7 @@ $pm->childFunc = function () use ($pm) { $http->on('request', function (Swoole\Http\Request $request, Swoole\Http\Response $response) use ($pm) { Assert::same($request->server['request_method'], 'POST'); Assert::same($request->rawContent(), $pm->getRandomData()); - $response->end('OK'); + $response->end(str_repeat('OK', 16)); }); $http->start(); }; diff --git a/tests/swoole_http_server/compression_min_length.phpt b/tests/swoole_http_server/compression_min_length.phpt new file mode 100644 index 00000000000..1273c4f12b3 --- /dev/null +++ b/tests/swoole_http_server/compression_min_length.phpt @@ -0,0 +1,45 @@ +--TEST-- +swoole_http_server: compression_min_length +--SKIPIF-- + +--FILE-- +parentFunc = function () use ($pm) +{ + run(function () use ($pm) { + $cli = new Client('127.0.0.1', $pm->getFreePort()); + $cli->setHeaders(['Accept-Encoding' => 'gzip', ]); + $cli->get('/?bytes=128'); + Assert::eq($cli->getHeaders()['content-encoding'], 'gzip'); + + $cli = new Client('127.0.0.1', $pm->getFreePort()); + $cli->setHeaders(['Accept-Encoding' => 'gzip', ]); + $cli->get('/?bytes=127'); + Assert::assert(!isset($cli->getHeaders()['content-encoding'])); + }); + echo "DONE\n"; + $pm->kill(); +}; +$pm->childFunc = function () use ($pm) +{ + $http = new Swoole\Http\Server('127.0.0.1', $pm->getFreePort(), SWOOLE_BASE, SWOOLE_SOCK_TCP); + $http->set(['compression_min_length' => 128,]); + $http->on("WorkerStart", function ($serv, $wid) { + global $pm; + $pm->wakeup(); + }); + $http->on("request", function ($request, swoole_http_response $response) { + $response->end(str_repeat('A', $request->get['bytes'])); + }); + $http->start(); +}; +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +DONE diff --git a/tests/swoole_http_server_coro/compression_min_length.phpt b/tests/swoole_http_server_coro/compression_min_length.phpt new file mode 100644 index 00000000000..b3acd07c8a6 --- /dev/null +++ b/tests/swoole_http_server_coro/compression_min_length.phpt @@ -0,0 +1,49 @@ +--TEST-- +swoole_http_server_coro: compression_min_length +--SKIPIF-- + +--FILE-- +set(['compression_min_length' => 128,]); + $server->handle('/test', function ($request, $response) { + $response->end(str_repeat('A', $request->get['bytes'])); + }); + $server->handle('/shutdown', function ($request, $response) use ($server) { + $response->end("shutdown"); + $server->shutdown(); + }); + $server->start(); + }); + + go(function () { + $cli = new Client('127.0.0.1', TEST_PORT); + $cli->setHeaders(['Accept-Encoding' => 'gzip', ]); + $cli->get('/test?bytes=128'); + Assert::eq($cli->getHeaders()['content-encoding'], 'gzip'); + + $cli = new Client('127.0.0.1', TEST_PORT); + $cli->setHeaders(['Accept-Encoding' => 'gzip', ]); + $cli->get('/test?bytes=127'); + Assert::assert(!isset($cli->getHeaders()['content-encoding'])); + + file_get_contents('http://127.0.0.1:' . TEST_PORT . '/shutdown'); + }); +}); +echo "DONE\n"; +?> +--EXPECT-- +DONE From 5fc4359ee7662aa829cc920b6c3562699ce14eaa Mon Sep 17 00:00:00 2001 From: matyhtf Date: Mon, 1 Feb 2021 21:55:22 +0800 Subject: [PATCH 042/936] Optimize server manager code --- src/server/manager.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/server/manager.cc b/src/server/manager.cc index 04e846474df..3c6b06cdeae 100644 --- a/src/server/manager.cc +++ b/src/server/manager.cc @@ -44,7 +44,7 @@ struct Manager { std::vector kill_workers; - int start(Server *_server); + void start(Server *_server); void add_timeout_killer(Worker *workers, int n); static void signal_handler(int sig); @@ -186,7 +186,8 @@ int Server::start_manager_process() { SwooleG.process_type = SW_PROCESS_MANAGER; SwooleG.pid = getpid(); Manager manager{}; - exit(manager.start(this)); + manager.start(this); + exit(0); break; } // master process @@ -215,7 +216,7 @@ void Server::check_worker_exit_status(int worker_id, const ExitStatus &exit_stat } } -int Manager::start(Server *_server) { +void Manager::start(Server *_server) { server_ = _server; server_->manager = this; @@ -226,6 +227,7 @@ int Manager::start(Server *_server) { ON_SCOPE_EXIT { delete[] reload_workers; reload_workers = nullptr; + server_->manager = nullptr; }; // for reload @@ -449,13 +451,11 @@ int Manager::start(Server *_server) { if (_server->onManagerStop) { _server->onManagerStop(_server); } - - return SW_OK; } void Manager::signal_handler(int sig) { Server *_server = sw_server(); - if (!_server) { + if (!_server || !_server->manager) { return; } Manager *manager = _server->manager; From e8713c20f6de472ca2b0883efccef28a0a09e422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Tue, 2 Feb 2021 11:37:54 +0800 Subject: [PATCH 043/936] Update SUPPORTED.md (#4037) --- SUPPORTED.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/SUPPORTED.md b/SUPPORTED.md index dab1473a8d9..4903612a5f3 100644 --- a/SUPPORTED.md +++ b/SUPPORTED.md @@ -1,15 +1,16 @@ Supported Versions --- + | Branch | Initialization | Active Support Until | Security Support Until | | ---------------------------------------------------------- | -------------- | -------------------- | ---------------------- | | [v4.4.x](https://github.com/swoole/swoole-src/tree/v4.4.x) | 2019-4-15 | 2020-4-30 | 2020-7-31 | -| [v4.5.x](https://github.com/swoole/swoole-src/tree/master) | 2019-12-20 | 2020-12-31 | 2021-3-31 | +| [v4.5.x](https://github.com/swoole/swoole-src/tree/v4.5.x) | 2019-12-20 | 2020-12-31 | 2021-3-31 | +| [v4.6.x](https://github.com/swoole/swoole-src/tree/master) | 2021-01-06 | 2022-01-31 | 2023-01-31 | | Active support | A release that is being actively supported. Reported bugs and security issues are fixed and regular point releases are made. | | ------------------- | ------------------------------------------------------------ | | Security fixes only | A release that is supported for critical security issues only. Releases are only made on an as-needed basis. | - Unsupported Branches --- > These releases that are no longer supported. Users of this release should upgrade as soon as possible, as they may be exposed to unpatched security vulnerabilities. From a630b5b2a681523834828d8bb3eaa84eff91bcf8 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 2 Feb 2021 20:17:22 +0800 Subject: [PATCH 044/936] fix Response::create() bugs --- ext-src/swoole_http_response.cc | 5 +- tests/swoole_server/http_protocol.phpt | 66 ++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 tests/swoole_server/http_protocol.phpt diff --git a/ext-src/swoole_http_response.cc b/ext-src/swoole_http_response.cc index 57fcf49c9a6..99a28022037 100644 --- a/ext-src/swoole_http_response.cc +++ b/ext-src/swoole_http_response.cc @@ -1369,7 +1369,6 @@ static PHP_METHOD(swoole_http_response, create) { if (!ctx) { ctx = new http_context(); - ctx->fd = fd; ctx->keepalive = 1; if (serv) { @@ -1399,12 +1398,16 @@ static PHP_METHOD(swoole_http_response, create) { object_init_ex(return_value, swoole_http_response_ce); php_swoole_http_response_set_context(return_value, ctx); + ctx->fd = fd; ctx->response.zobject = return_value; sw_copy_to_stack(ctx->response.zobject, ctx->response._zobject); zend_update_property_long(swoole_http_response_ce, SW_Z8_OBJ_P(return_value), ZEND_STRL("fd"), fd); if (ctx->co_socket) { zend_update_property(swoole_http_response_ce, SW_Z8_OBJ_P(ctx->response.zobject), ZEND_STRL("socket"), zobject); } + if (zrequest) { + zend_update_property_long(swoole_http_request_ce, SW_Z8_OBJ_P(ctx->request.zobject), ZEND_STRL("fd"), fd); + } } static PHP_METHOD(swoole_http_response, redirect) { diff --git a/tests/swoole_server/http_protocol.phpt b/tests/swoole_server/http_protocol.phpt new file mode 100644 index 00000000000..3a61f897ef8 --- /dev/null +++ b/tests/swoole_server/http_protocol.phpt @@ -0,0 +1,66 @@ +--TEST-- +swoole_server: http request & response +--SKIPIF-- + +--FILE-- +parentFunc = function ($pid) use ($pm) { + run(function () use ($pm) { + $httpClient = new Client(HTTP_SERVER_HOST, $pm->getFreePort(), false); + $httpClient->setMethod("POST"); + $httpClient->setData("HELLO"); + $ok = $httpClient->execute("/rawcookie?hello=world&value=1"); + Assert::assert($ok); + Assert::same($httpClient->statusCode, 200); + Assert::same($httpClient->errCode, 0); + Assert::eq($httpClient->getHeaders()['x-server'], 'swoole'); + Assert::same($httpClient->getBody(), GREETER); + echo "DONE\n"; + }); + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm) { + $serv = new Server('127.0.0.1', $pm->getFreePort(), SERVER_MODE_RANDOM); + $serv->set([ + 'worker_num' => 1, + 'log_file' => '/dev/null', + ]); + $serv->on("Start", function ($serv) use ($pm) { + $pm->wakeup(); + }); + $serv->on('receive', function (Server $serv, $fd, $reactor_id, $data) { + $req = Request::create(); + Assert::eq($req->parse($data), strlen($data)); + + $resp = Response::create([$serv, $req], $fd); + $resp->header('X-Server', 'swoole'); + $resp->end(GREETER); + Assert::eq($resp->fd, $fd); + Assert::eq($req->fd, $fd); + }); + $serv->on(Constant::EVENT_CLOSE, function (Server $serv, $fd, $reactor_id) { + }); + $serv->start(); +}; + +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +DONE From bcf418fe04e5bcd1252888af4c9a1d2e1c782c99 Mon Sep 17 00:00:00 2001 From: Yurun Date: Wed, 3 Feb 2021 15:52:13 +0800 Subject: [PATCH 045/936] Fix make.sh (#4038) --- make.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/make.sh b/make.sh index 1069b396628..38c4e00abb3 100755 --- a/make.sh +++ b/make.sh @@ -76,8 +76,8 @@ fi make clean make -j ${CPU_COUNT} -if [ "$(whoami)" == "root" ];then - make install +if [ "$(whoami)" = "root" ]; then + make install else - sudo make install + sudo make install fi From 2a741fe66fa542d070fb7364b12fd393e2e829ba Mon Sep 17 00:00:00 2001 From: Bruce Dou Date: Thu, 4 Feb 2021 08:39:39 +0000 Subject: [PATCH 046/936] Fix #3176 #4036 (#4040) --- ext-src/swoole_server.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index db271c58037..031df5f08c8 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -861,7 +861,7 @@ static sw_inline int php_swoole_check_task_param(Server *serv, zend_long dst_wor php_swoole_fatal_error(E_WARNING, "task method can't be executed without task worker"); return SW_ERR; } - if (UNEXPECTED(dst_worker_id >= serv->task_worker_num)) { + if (UNEXPECTED(dst_worker_id > 0 && dst_worker_id >= serv->task_worker_num)) { php_swoole_fatal_error(E_WARNING, "worker_id must be less than task_worker_num[%u]", serv->task_worker_num); return SW_ERR; } From e678bba847959a01438be3997b8738f40eeac7fd Mon Sep 17 00:00:00 2001 From: Yurun Date: Thu, 4 Feb 2021 21:00:40 +0800 Subject: [PATCH 047/936] Fix timer (#4042) * Fix timer * Optimize * Add test * Optimize warning info --- src/wrapper/timer.cc | 18 ++++++++-- .../curl_native/timer_coredump.phpt | 34 +++++++++++++++++++ thirdparty/php/curl/curl_multi.h | 2 +- 3 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 tests/swoole_runtime/curl_native/timer_coredump.phpt diff --git a/src/wrapper/timer.cc b/src/wrapper/timer.cc index 4ee4cfb3887..9226b1d5fda 100644 --- a/src/wrapper/timer.cc +++ b/src/wrapper/timer.cc @@ -42,10 +42,18 @@ TimerNode *swoole_timer_add(long ms, bool persistent, const TimerCallback &callb } bool swoole_timer_del(TimerNode *tnode) { + if (!swoole_timer_is_available()) { + swWarn("timer is not available"); + return false; + } return SwooleTG.timer->remove(tnode); } void swoole_timer_delay(TimerNode *tnode, long delay_ms) { + if (!swoole_timer_is_available()) { + swWarn("timer is not available"); + return; + } return SwooleTG.timer->delay(tnode, delay_ms); } @@ -77,7 +85,7 @@ long swoole_timer_tick(long ms, const TimerCallback &callback, void *private_dat bool swoole_timer_exists(long timer_id) { if (!swoole_timer_is_available()) { - swWarn("timer[%ld] is not exists", timer_id); + swWarn("timer is not available"); return false; } TimerNode *tnode = SwooleTG.timer->get(timer_id); @@ -85,12 +93,16 @@ bool swoole_timer_exists(long timer_id) { } bool swoole_timer_clear(long timer_id) { + if (!swoole_timer_is_available()) { + swWarn("timer is not available"); + return false; + } return SwooleTG.timer->remove(SwooleTG.timer->get(timer_id)); } TimerNode *swoole_timer_get(long timer_id) { if (!swoole_timer_is_available()) { - swWarn("timer[%ld] is not exists", timer_id); + swWarn("timer is not available"); return nullptr; } return SwooleTG.timer->get(timer_id); @@ -98,6 +110,7 @@ TimerNode *swoole_timer_get(long timer_id) { void swoole_timer_free() { if (!swoole_timer_is_available()) { + swWarn("timer is not available"); return; } delete SwooleTG.timer; @@ -107,6 +120,7 @@ void swoole_timer_free() { int swoole_timer_select() { if (!swoole_timer_is_available()) { + swWarn("timer is not available"); return SW_ERR; } return SwooleTG.timer->select(); diff --git a/tests/swoole_runtime/curl_native/timer_coredump.phpt b/tests/swoole_runtime/curl_native/timer_coredump.phpt new file mode 100644 index 00000000000..0661008833a --- /dev/null +++ b/tests/swoole_runtime/curl_native/timer_coredump.phpt @@ -0,0 +1,34 @@ +--TEST-- +swoole_runtime/curl_native: timer coredump +--SKIPIF-- + +--FILE-- + +--EXPECT-- +Done diff --git a/thirdparty/php/curl/curl_multi.h b/thirdparty/php/curl/curl_multi.h index 60347a51e5f..afc15737b18 100644 --- a/thirdparty/php/curl/curl_multi.h +++ b/thirdparty/php/curl/curl_multi.h @@ -95,7 +95,7 @@ class cURLMulti { } void del_timer() { - if (timer && swoole_event_is_available()) { + if (timer) { swoole_timer_del(timer); } } From 6d9b69e8a1a2326d416872b53301220a27e78275 Mon Sep 17 00:00:00 2001 From: Asher Oto <49938263+asheroto@users.noreply.github.com> Date: Sat, 6 Feb 2021 04:38:23 -0600 Subject: [PATCH 048/936] Update README (#4046) Fixed GitHub repo path for ext-async --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 990c1fbbb03..478ecd1820c 100644 --- a/README.md +++ b/README.md @@ -493,8 +493,8 @@ After compiling and installing to the system successfully, you have to add a new Async clients and API are moved to a separate PHP extension `swoole_async` since version 4.3.0, install `swoole_async`: ```shell -git clone https://github.com/swoole/async-ext.git -cd async-src +git clone https://github.com/swoole/ext-async.git +cd ext-async phpize ./configure make -j 4 From 289e673352fe3831b33c70c35f5bb30649c9d676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Sun, 7 Feb 2021 19:06:59 +0800 Subject: [PATCH 049/936] fix native-curl crash on PHP8 (#4045) * fix native-curl crash on PHP8 * optimize code * optimize code[2] * fix tests * optimize code[3] * fix tests --- ext-src/swoole_runtime.cc | 67 ++++++++-------- src/core/base.cc | 4 +- src/core/timer.cc | 9 ++- thirdparty/php/curl/curl_arginfo.h | 71 +++++------------ thirdparty/php/curl/curl_interface.h | 37 +++++++++ thirdparty/php/curl/curl_multi.h | 7 +- thirdparty/php/curl/interface.cc | 111 +++++++++++---------------- 7 files changed, 149 insertions(+), 157 deletions(-) create mode 100644 thirdparty/php/curl/curl_interface.h diff --git a/ext-src/swoole_runtime.cc b/ext-src/swoole_runtime.cc index 9f72fa4bcb8..849acf4cfdb 100644 --- a/ext-src/swoole_runtime.cc +++ b/ext-src/swoole_runtime.cc @@ -18,7 +18,9 @@ #include "swoole_util.h" #include "thirdparty/php/standard/proc_open.h" -#include "thirdparty/php/curl/curl_arginfo.h" +#ifdef SW_USE_CURL +#include "thirdparty/php/curl/curl_interface.h" +#endif #include #include @@ -54,12 +56,6 @@ static PHP_FUNCTION(swoole_time_sleep_until); static PHP_FUNCTION(swoole_stream_select); static PHP_FUNCTION(swoole_stream_socket_pair); static PHP_FUNCTION(swoole_user_func_handler); - -#ifdef SW_USE_CURL -void swoole_native_curl_init(int module_number); -void swoole_native_curl_shutdown(); -#endif - SW_EXTERN_C_END static int socket_set_option(php_stream *stream, int option, int value, void *ptrparam); @@ -144,10 +140,18 @@ static php_stream_ops ori_php_stream_stdio_ops; static void hook_func(const char *name, size_t l_name, zif_handler handler = nullptr, zend_internal_arg_info *arg_info = nullptr); static void unhook_func(const char *name, size_t l_name); -static bool hook_internal_functions(const zend_function_entry *fes); + +static zend_internal_arg_info *get_arginfo(const char *name, size_t l_name) { + zend_function *zf = (zend_function *) zend_hash_str_find_ptr(EG(function_table), name, l_name); + if (zf == nullptr) { + return nullptr; + } + return zf->internal_function.arg_info; +} #define SW_HOOK_FUNC(f) hook_func(ZEND_STRL(#f), PHP_FN(swoole_##f)) #define SW_UNHOOK_FUNC(f) unhook_func(ZEND_STRL(#f)) +#define SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(f) hook_func(ZEND_STRL(#f), PHP_FN(swoole_native_##f), get_arginfo(ZEND_STRL("swoole_native_" #f))) static zend_array *tmp_function_table = nullptr; @@ -179,7 +183,7 @@ void php_swoole_runtime_minit(int module_number) { SW_REGISTER_LONG_CONSTANT("SWOOLE_HOOK_SOCKETS", PHPCoroutine::HOOK_SOCKETS); SW_REGISTER_LONG_CONSTANT("SWOOLE_HOOK_ALL", PHPCoroutine::HOOK_ALL); #ifdef SW_USE_CURL - swoole_native_curl_init(module_number); + swoole_native_curl_minit(module_number); #endif swoole_proc_open_init(module_number); } @@ -221,7 +225,7 @@ void php_swoole_runtime_rshutdown() { void php_swoole_runtime_mshutdown() { #ifdef SW_USE_CURL - swoole_native_curl_shutdown(); + swoole_native_curl_mshutdown(); #endif } @@ -1384,23 +1388,19 @@ bool PHPCoroutine::enable_hook(uint32_t flags) { flags ^= PHPCoroutine::HOOK_CURL; } if (!(runtime_hook_flags & PHPCoroutine::HOOK_NATIVE_CURL)) { -#if PHP_VERSION_ID >= 80000 - hook_internal_functions(swoole_native_curl_functions); -#else - hook_func(ZEND_STRL("curl_close"), PHP_FN(swoole_native_curl_close)); - hook_func(ZEND_STRL("curl_copy_handle"), PHP_FN(swoole_native_curl_copy_handle)); - hook_func(ZEND_STRL("curl_errno"), PHP_FN(swoole_native_curl_errno)); - hook_func(ZEND_STRL("curl_error"), PHP_FN(swoole_native_curl_error)); - hook_func(ZEND_STRL("curl_exec"), PHP_FN(swoole_native_curl_exec)); - hook_func(ZEND_STRL("curl_getinfo"), PHP_FN(swoole_native_curl_getinfo)); - hook_func(ZEND_STRL("curl_init"), PHP_FN(swoole_native_curl_init)); - hook_func(ZEND_STRL("curl_setopt"), PHP_FN(swoole_native_curl_setopt)); - hook_func(ZEND_STRL("curl_setopt_array"), PHP_FN(swoole_native_curl_setopt_array)); - hook_func(ZEND_STRL("curl_reset"), PHP_FN(swoole_native_curl_reset)); - hook_func(ZEND_STRL("curl_pause"), PHP_FN(swoole_native_curl_pause)); - hook_func(ZEND_STRL("curl_escape"), PHP_FN(swoole_native_curl_escape)); - hook_func(ZEND_STRL("curl_unescape"), PHP_FN(swoole_native_curl_unescape)); - #endif + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_close); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_copy_handle); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_errno); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_error); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_exec); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_getinfo); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_init); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_setopt); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_setopt_array); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_reset); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_pause); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_escape); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_unescape); } } else { if (runtime_hook_flags & PHPCoroutine::HOOK_NATIVE_CURL) { @@ -1804,11 +1804,6 @@ static PHP_FUNCTION(swoole_stream_select) { RETURN_LONG(retval); } -bool hook_internal_functions(const zend_function_entry *fes) { - zend_unregister_functions(fes, -1, CG(function_table)); - return zend_register_functions(NULL, fes, NULL, MODULE_PERSISTENT) == SUCCESS; -} - static void hook_func(const char *name, size_t l_name, zif_handler handler, zend_internal_arg_info *arg_info) { real_func *rf = (real_func *) zend_hash_str_find_ptr(tmp_function_table, name, l_name); bool use_php_func = false; @@ -1821,6 +1816,9 @@ static void hook_func(const char *name, size_t l_name, zif_handler handler, zend } if (rf) { rf->function->internal_function.handler = handler; + if (arg_info) { + rf->function->internal_function.arg_info = arg_info; + } return; } @@ -1833,7 +1831,11 @@ static void hook_func(const char *name, size_t l_name, zif_handler handler, zend sw_memset_zero(rf, sizeof(*rf)); rf->function = zf; rf->ori_handler = zf->internal_function.handler; + rf->ori_arg_info = zf->internal_function.arg_info; zf->internal_function.handler = handler; + if (arg_info) { + zf->internal_function.arg_info = arg_info; + } if (use_php_func) { char func[128]; @@ -1861,6 +1863,7 @@ static void unhook_func(const char *name, size_t l_name) { return; } rf->function->internal_function.handler = rf->ori_handler; + rf->function->internal_function.arg_info = rf->ori_arg_info; } php_stream *php_swoole_create_stream_from_socket(php_socket_t _fd, int domain, int type, int protocol STREAMS_DC) { diff --git a/src/core/base.cc b/src/core/base.cc index 659eb4406c0..f60d277f46c 100644 --- a/src/core/base.cc +++ b/src/core/base.cc @@ -276,7 +276,7 @@ pid_t swoole_fork(int flags) { /** * [!!!] All timers and event loops must be cleaned up after fork */ - if (SwooleTG.timer) { + if (swoole_timer_is_available()) { swoole_timer_free(); } if (SwooleG.memory_pool) { @@ -288,7 +288,7 @@ pid_t swoole_fork(int flags) { // reopen log file sw_logger()->reopen(); // reset eventLoop - if (SwooleTG.reactor) { + if (swoole_event_is_available()) { swoole_event_free(); swTraceLog(SW_TRACE_REACTOR, "reactor has been destroyed"); } diff --git a/src/core/timer.cc b/src/core/timer.cc index f8e2b261c0b..187ccf3688f 100644 --- a/src/core/timer.cc +++ b/src/core/timer.cc @@ -47,8 +47,7 @@ int swoole_clock_gettime(int which_clock, struct timespec *t) { namespace swoole { -Timer::Timer() - : heap(1024, Heap::MIN_HEAP) { +Timer::Timer() : heap(1024, Heap::MIN_HEAP) { _current_id = -1; next_msec_ = -1; _next_id = 1; @@ -80,7 +79,11 @@ bool Timer::init_reactor(Reactor *reactor) { reactor->set_exit_condition(Reactor::EXIT_CONDITION_TIMER, [this](Reactor *reactor, int &event_num) -> bool { return count() == 0; }); - reactor->add_destroy_callback([](void *) { swoole_timer_free(); }); + reactor->add_destroy_callback([](void *) { + if (swoole_timer_is_available()) { + swoole_timer_free(); + } + }); return true; } diff --git a/thirdparty/php/curl/curl_arginfo.h b/thirdparty/php/curl/curl_arginfo.h index 59a7502c2d2..261776dbdbe 100644 --- a/thirdparty/php/curl/curl_arginfo.h +++ b/thirdparty/php/curl/curl_arginfo.h @@ -1,38 +1,9 @@ /* This is a generated file, edit the .stub.php file instead. * Stub hash: f1d616c644ad366405816cde0384f6f391773ebf */ -#ifdef SW_USE_CURL - -#include "zend_API.h" - -#include -#include - -SW_EXTERN_C_BEGIN -PHP_FUNCTION(swoole_native_curl_close); -PHP_FUNCTION(swoole_native_curl_copy_handle); -PHP_FUNCTION(swoole_native_curl_errno); -PHP_FUNCTION(swoole_native_curl_error); -PHP_FUNCTION(swoole_native_curl_exec); -PHP_FUNCTION(swoole_native_curl_getinfo); -PHP_FUNCTION(swoole_native_curl_init); -PHP_FUNCTION(swoole_native_curl_setopt); -PHP_FUNCTION(swoole_native_curl_setopt_array); - -#if LIBCURL_VERSION_NUM >= 0x070c01 /* 7.12.1 */ -PHP_FUNCTION(swoole_native_curl_reset); -#endif - -#if LIBCURL_VERSION_NUM >= 0x070f04 /* 7.15.4 */ -PHP_FUNCTION(swoole_native_curl_escape); -PHP_FUNCTION(swoole_native_curl_unescape); -#endif - -#if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */ -PHP_FUNCTION(swoole_native_curl_pause); -#endif -SW_EXTERN_C_END +#include "curl_interface.h" +#ifdef SW_USE_CURL #if PHP_VERSION_ID >= 80000 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_swoole_native_curl_close, 0, 1, IS_VOID, 0) @@ -102,25 +73,25 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_swoole_native_curl_setopt, 0, 3, ZEND_END_ARG_INFO() static const zend_function_entry swoole_native_curl_functions[] = { - ZEND_FENTRY(curl_close, PHP_FN(swoole_native_curl_close), arginfo_swoole_native_curl_close, 0) - ZEND_FENTRY(curl_copy_handle, PHP_FN(swoole_native_curl_copy_handle), arginfo_swoole_native_curl_copy_handle, 0) - ZEND_FENTRY(curl_errno, PHP_FN(swoole_native_curl_errno), arginfo_swoole_native_curl_errno, 0) - ZEND_FENTRY(curl_error, PHP_FN(swoole_native_curl_error), arginfo_swoole_native_curl_error, 0) - ZEND_FENTRY(curl_exec, PHP_FN(swoole_native_curl_exec), arginfo_swoole_native_curl_exec, 0) - ZEND_FENTRY(curl_getinfo, PHP_FN(swoole_native_curl_getinfo), arginfo_swoole_native_curl_getinfo, 0) - ZEND_FENTRY(curl_init, PHP_FN(swoole_native_curl_init), arginfo_swoole_native_curl_init, 0) - ZEND_FENTRY(curl_setopt, PHP_FN(swoole_native_curl_setopt), arginfo_swoole_native_curl_setopt, 0) - ZEND_FENTRY(curl_setopt_array, PHP_FN(swoole_native_curl_setopt_array), arginfo_swoole_native_curl_setopt_array, 0) - #if LIBCURL_VERSION_NUM >= 0x070c01 /* 7.12.1 */ - ZEND_FENTRY(curl_reset, PHP_FN(swoole_native_curl_reset), arginfo_swoole_native_curl_reset, 0) - #endif - #if LIBCURL_VERSION_NUM >= 0x070f04 /* 7.15.4 */ - ZEND_FENTRY(curl_escape, PHP_FN(swoole_native_curl_escape), arginfo_swoole_native_curl_escape, 0) - ZEND_FENTRY(curl_unescape, PHP_FN(swoole_native_curl_unescape), arginfo_swoole_native_curl_unescape, 0) - #endif - #if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */ - ZEND_FENTRY(curl_pause, PHP_FN(swoole_native_curl_pause), arginfo_swoole_native_curl_pause, 0) - #endif + PHP_FE(swoole_native_curl_close, arginfo_swoole_native_curl_close) + PHP_FE(swoole_native_curl_copy_handle, arginfo_swoole_native_curl_copy_handle) + PHP_FE(swoole_native_curl_errno, arginfo_swoole_native_curl_errno) + PHP_FE(swoole_native_curl_error, arginfo_swoole_native_curl_error) + PHP_FE(swoole_native_curl_exec, arginfo_swoole_native_curl_exec) + PHP_FE(swoole_native_curl_getinfo, arginfo_swoole_native_curl_getinfo) + PHP_FE(swoole_native_curl_init, arginfo_swoole_native_curl_init) + PHP_FE(swoole_native_curl_setopt, arginfo_swoole_native_curl_setopt) + PHP_FE(swoole_native_curl_setopt_array, arginfo_swoole_native_curl_setopt_array) +#if LIBCURL_VERSION_NUM >= 0x070c01 /* 7.12.1 */ + PHP_FE(swoole_native_curl_reset, arginfo_swoole_native_curl_reset) +#endif +#if LIBCURL_VERSION_NUM >= 0x070f04 /* 7.15.4 */ + PHP_FE(swoole_native_curl_escape, arginfo_swoole_native_curl_escape) + PHP_FE(swoole_native_curl_unescape, arginfo_swoole_native_curl_unescape) +#endif +#if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */ + PHP_FE(swoole_native_curl_pause, arginfo_swoole_native_curl_pause) +#endif PHP_FE_END }; #endif diff --git a/thirdparty/php/curl/curl_interface.h b/thirdparty/php/curl/curl_interface.h new file mode 100644 index 00000000000..c9448db77df --- /dev/null +++ b/thirdparty/php/curl/curl_interface.h @@ -0,0 +1,37 @@ +#pragma once + +#include "php_swoole_cxx.h" + +#ifdef SW_USE_CURL +SW_EXTERN_C_BEGIN + +#include +#include + +void swoole_native_curl_minit(int module_number); +void swoole_native_curl_mshutdown(); + +PHP_FUNCTION(swoole_native_curl_close); +PHP_FUNCTION(swoole_native_curl_copy_handle); +PHP_FUNCTION(swoole_native_curl_errno); +PHP_FUNCTION(swoole_native_curl_error); +PHP_FUNCTION(swoole_native_curl_exec); +PHP_FUNCTION(swoole_native_curl_getinfo); +PHP_FUNCTION(swoole_native_curl_init); +PHP_FUNCTION(swoole_native_curl_setopt); +PHP_FUNCTION(swoole_native_curl_setopt_array); + +#if LIBCURL_VERSION_NUM >= 0x070c01 /* 7.12.1 */ +PHP_FUNCTION(swoole_native_curl_reset); +#endif + +#if LIBCURL_VERSION_NUM >= 0x070f04 /* 7.15.4 */ +PHP_FUNCTION(swoole_native_curl_escape); +PHP_FUNCTION(swoole_native_curl_unescape); +#endif + +#if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */ +PHP_FUNCTION(swoole_native_curl_pause); +#endif +SW_EXTERN_C_END +#endif diff --git a/thirdparty/php/curl/curl_multi.h b/thirdparty/php/curl/curl_multi.h index afc15737b18..b313b0c88cd 100644 --- a/thirdparty/php/curl/curl_multi.h +++ b/thirdparty/php/curl/curl_multi.h @@ -13,11 +13,10 @@ | Author: Tianfeng Han | +----------------------------------------------------------------------+ */ +#pragma once #ifdef SW_USE_CURL -#pragma once - #include "php_swoole_cxx.h" #include "swoole_util.h" @@ -85,7 +84,7 @@ class cURLMulti { } void add_timer(long timeout_ms) { - if (timer) { + if (timer && swoole_timer_is_available()) { swoole_timer_del(timer); } @@ -95,7 +94,7 @@ class cURLMulti { } void del_timer() { - if (timer) { + if (timer && swoole_timer_is_available()) { swoole_timer_del(timer); } } diff --git a/thirdparty/php/curl/interface.cc b/thirdparty/php/curl/interface.cc index d8eb3bd9784..0d8ce786880 100644 --- a/thirdparty/php/curl/interface.cc +++ b/thirdparty/php/curl/interface.cc @@ -24,6 +24,8 @@ using namespace swoole; SW_EXTERN_C_BEGIN +#include "curl_interface.h" +#include "curl_arginfo.h" #include #include @@ -113,9 +115,9 @@ static int php_curl_option_str(php_curl *ch, zend_long option, const char *str, long error = CURLE_OK; if (strlen(str) != len) { - #if PHP_VERSION_ID >= 80000 +#if PHP_VERSION_ID >= 80000 zend_value_error("%s(): cURL option must not contain any null bytes", get_active_function_name()); - #else +#else php_error_docref(NULL, E_WARNING, "Curl option contains invalid characters (\\0)"); #endif return FAILURE; @@ -269,6 +271,7 @@ static cURLMulti *g_curl_multi = nullptr; static inline cURLMulti *sw_curl_multi() { return g_curl_multi; } +SW_EXTERN_C_END int cURLMulti::cb_readable(Reactor *reactor, Event *event) { sw_curl_multi()->socket_action(event->fd, CURL_CSELECT_IN); @@ -343,7 +346,7 @@ int cURLMulti::handle_timeout(CURLM *multi, long timeout_ms, void *userp) { return 0; } -void swoole_native_curl_init(int module_number) +void swoole_native_curl_minit(int module_number) { #if PHP_VERSION_ID >= 80000 SW_INIT_CLASS_ENTRY(swoole_coroutine_curl_handle, @@ -362,6 +365,10 @@ void swoole_native_curl_init(int module_number) swoole_coroutine_curl_handle_handlers.get_constructor = curl_get_constructor; swoole_coroutine_curl_handle_handlers.clone_obj = curl_clone_obj; swoole_coroutine_curl_handle_handlers.cast_object = curl_cast_object; + + zend_unregister_functions(swoole_native_curl_functions, -1, CG(function_table)); + zend_register_functions(NULL, swoole_native_curl_functions, NULL, MODULE_PERSISTENT); + #else le_curl = zend_register_list_destructors_ex(_php_curl_close, NULL, le_curl_name, module_number); #endif @@ -482,7 +489,7 @@ int curl_cast_object(zend_object *obj, zval *result, int type) } #endif -void swoole_native_curl_shutdown() { +void swoole_native_curl_mshutdown() { delete g_curl_multi; g_curl_multi = nullptr; } @@ -607,11 +614,11 @@ static int fn_fnmatch(void *ctx, const char *pattern, const char *string) fci.retval = &retval; fci.param_count = 3; fci.params = argv; - #if PHP_VERSION_ID >= 80000 - fci.named_params = NULL; - #else +#if PHP_VERSION_ID >= 80000 + fci.named_params = NULL; +#else fci.no_separation = 0; - #endif +#endif ch->in_callback = 1; error = zend_call_function(&fci, &t->fci_cache); @@ -653,13 +660,13 @@ static size_t fn_progress(void *clientp, double dltotal, double dlnow, double ul int error; zend_fcall_info fci; - #if PHP_VERSION_ID >= 80000 +#if PHP_VERSION_ID >= 80000 GC_ADDREF(&ch->std); ZVAL_OBJ(&argv[0], &ch->std); - #else +#else GC_ADDREF(ch->res); ZVAL_RES(&argv[0], ch->res); - #endif +#endif ZVAL_LONG(&argv[1], (zend_long)dltotal); ZVAL_LONG(&argv[2], (zend_long)dlnow); ZVAL_LONG(&argv[3], (zend_long)ultotal); @@ -671,11 +678,11 @@ static size_t fn_progress(void *clientp, double dltotal, double dlnow, double ul fci.retval = &retval; fci.param_count = 5; fci.params = argv; - #if PHP_VERSION_ID >= 80000 - fci.named_params = NULL; - #else - fci.no_separation = 0; - #endif +#if PHP_VERSION_ID >= 80000 + fci.named_params = NULL; +#else + fci.no_separation = 0; +#endif ch->in_callback = 1; error = zend_call_function(&fci, &t->fci_cache); @@ -798,7 +805,7 @@ static size_t fn_write_header(char *data, size_t size, size_t nmemb, void *ctx) #else ZVAL_RES(&argv[0], ch->res); Z_ADDREF(argv[0]); - #endif +#endif ZVAL_STRINGL(&argv[1], data, length); @@ -813,7 +820,6 @@ static size_t fn_write_header(char *data, size_t size, size_t nmemb, void *ctx) #else fci.no_separation = 0; #endif - ch->in_callback = 1; error = zend_call_function(&fci, &t->fci_cache); ch->in_callback = 0; @@ -1068,9 +1074,9 @@ PHP_FUNCTION(swoole_native_curl_init) } #if PHP_VERSION_ID >= 80000 - ch = init_curl_handle_into_zval(return_value); + ch = init_curl_handle_into_zval(return_value); #else - ch = alloc_curl_handle(); + ch = alloc_curl_handle(); #endif ch->cp = cp; @@ -1224,11 +1230,7 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields { CURLcode error = CURLE_OK; zval *current; - #if PHP_VERSION_ID >= 80000 - HashTable *postfields = Z_ARRVAL_P(zpostfields); - #else - HashTable *postfields; - #endif + HashTable *postfields = HASH_OF(zpostfields); zend_string *string_key; zend_ulong num_key; #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ @@ -1241,13 +1243,10 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields CURLFORMcode form_error; #endif - #if PHP_VERSION_ID < 80000 - postfields = HASH_OF(zpostfields); if (!postfields) { php_error_docref(NULL, E_WARNING, "Couldn't get HashTable in CURLOPT_POSTFIELDS"); return FAILURE; } - #endif #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ if (zend_hash_num_elements(postfields) > 0) { @@ -1882,11 +1881,11 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{ ch->handlers->write->method = PHP_CURL_FILE; ZVAL_COPY(&ch->handlers->write->stream, zvalue); } else { - #if PHP_VERSION_ID >= 80000 +#if PHP_VERSION_ID >= 80000 zend_value_error("%s(): The provided file handle must be writable", get_active_function_name()); - #else +#else php_error_docref(NULL, E_WARNING, "the provided file handle is not writable"); - #endif +#endif return FAILURE; } break; @@ -1904,11 +1903,11 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{ ch->handlers->write_header->method = PHP_CURL_FILE; ZVAL_COPY(&ch->handlers->write_header->stream, zvalue); } else { - #if PHP_VERSION_ID >= 80000 +#if PHP_VERSION_ID >= 80000 zend_value_error("%s(): The provided file handle must be writable", get_active_function_name()); - #else +#else php_error_docref(NULL, E_WARNING, "the provided file handle is not writable"); - #endif +#endif return FAILURE; } break; @@ -1937,11 +1936,11 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{ zval_ptr_dtor(&ch->handlers->std_err); ZVAL_COPY(&ch->handlers->std_err, zvalue); } else { - #if PHP_VERSION_ID >= 80000 +#if PHP_VERSION_ID >= 80000 zend_value_error("%s(): The provided file handle must be writable", get_active_function_name()); - #else +#else php_error_docref(NULL, E_WARNING, "the provided file handle is not writable"); - #endif +#endif return FAILURE; } /* break omitted intentionally */ @@ -1977,12 +1976,8 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{ zend_string *val; struct curl_slist *slist = NULL; - #if PHP_VERSION_ID >= 80000 - if (Z_TYPE_P(zvalue) != IS_ARRAY) { - #else ph = HASH_OF(zvalue); if (!ph) { - #endif const char *name = NULL; switch (option) { case CURLOPT_HTTPHEADER: @@ -2024,11 +2019,11 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{ break; #endif } - #if PHP_VERSION_ID >= 80000 +#if PHP_VERSION_ID >= 80000 zend_type_error("%s(): The %s option must have an array value", get_active_function_name(), name); - #else +#else php_error_docref(NULL, E_WARNING, "You must pass either an object or an array with the %s argument", name); - #endif +#endif return FAILURE; } @@ -2081,11 +2076,11 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{ break; case CURLOPT_POSTFIELDS: - #if PHP_VERSION_ID >= 80000 +#if PHP_VERSION_ID >= 80000 if (Z_TYPE_P(zvalue) == IS_ARRAY) { - #else +#else if (Z_TYPE_P(zvalue) == IS_ARRAY || Z_TYPE_P(zvalue) == IS_OBJECT) { - #endif +#endif return build_mime_structure_from_hash(ch, zvalue); } else { #if LIBCURL_VERSION_NUM >= 0x071101 @@ -2211,21 +2206,7 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{ case CURLOPT_SHARE: { - #if PHP_VERSION_ID >= 80000 - if (Z_TYPE_P(zvalue) == IS_OBJECT && Z_OBJCE_P(zvalue) == curl_share_ce) { - php_curlsh *sh = Z_CURL_SHARE_P(zvalue); - curl_easy_setopt(ch->cp, CURLOPT_SHARE, sh->share); - - if (ch->share) { - OBJ_RELEASE(&ch->share->std); - } - GC_ADDREF(&sh->std); - ch->share = sh; - } - #else php_error_docref(NULL, E_WARNING, "CURLOPT_SHARE option is not supported"); - return FAILURE; - #endif } break; @@ -2328,11 +2309,11 @@ PHP_FUNCTION(swoole_native_curl_setopt_array) RETURN_FALSE; } ZVAL_DEREF(entry); - #if PHP_VERSION_ID >= 80000 +#if PHP_VERSION_ID >= 80000 if (_php_curl_setopt(ch, (zend_long) option, entry, 1) == FAILURE) { - #else +#else if (_php_curl_setopt(ch, (zend_long) option, entry) == FAILURE) { - #endif +#endif RETURN_FALSE; } } ZEND_HASH_FOREACH_END(); @@ -3133,6 +3114,4 @@ PHP_FUNCTION(swoole_native_curl_pause) } /* }}} */ #endif - -SW_EXTERN_C_END #endif From a1cef6e97f8aa6291f5a5ff423d711e0d535fd3e Mon Sep 17 00:00:00 2001 From: Bruce Dou Date: Sun, 7 Feb 2021 12:23:48 +0000 Subject: [PATCH 050/936] Allow setting content-length HTTP header in application layer (#4041) * Allow setting content-length http header. * fix tests * fix tests [2] Co-authored-by: matyhtf --- ext-src/swoole_http_response.cc | 10 +++-- .../swoole_http_server/duplicate_header.phpt | 7 +-- .../set_content_length.phpt | 44 +++++++++++++++++++ 3 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 tests/swoole_http_server/set_content_length.phpt diff --git a/ext-src/swoole_http_response.cc b/ext-src/swoole_http_response.cc index 99a28022037..65975c548e6 100644 --- a/ext-src/swoole_http_response.cc +++ b/ext-src/swoole_http_response.cc @@ -379,8 +379,8 @@ static bool parse_header_flags(http_context *ctx, const char *key, size_t keylen header_flags |= HTTP_HEADER_CONNECTION; } else if (SW_STRCASEEQ(key, keylen, "Date")) { header_flags |= HTTP_HEADER_DATE; - } else if (SW_STRCASEEQ(key, keylen, "Content-Length") && ctx->parser.method != PHP_HTTP_HEAD) { - return false; + } else if (SW_STRCASEEQ(key, keylen, "Content-Length")) { + header_flags |= HTTP_HEADER_CONTENT_LENGTH; } else if (SW_STRCASEEQ(key, keylen, "Content-Type")) { header_flags |= HTTP_HEADER_CONTENT_TYPE; } else if (SW_STRCASEEQ(key, keylen, "Transfer-Encoding")) { @@ -514,8 +514,10 @@ static void http_build_header(http_context *ctx, swString *response, size_t body body_length = swoole_zlib_buffer->length; } #endif - n = sw_snprintf(buf, l_buf, "Content-Length: %zu\r\n", body_length); - response->append(buf, n); + if (!(header_flags & HTTP_HEADER_CONTENT_LENGTH)) { + n = sw_snprintf(buf, l_buf, "Content-Length: %zu\r\n", body_length); + response->append(buf, n); + } } #ifdef SW_HAVE_COMPRESSION // http compress diff --git a/tests/swoole_http_server/duplicate_header.phpt b/tests/swoole_http_server/duplicate_header.phpt index f17bafd723f..2cb5b495644 100644 --- a/tests/swoole_http_server/duplicate_header.phpt +++ b/tests/swoole_http_server/duplicate_header.phpt @@ -29,7 +29,8 @@ $pm->childFunc = function () use ($pm) { $pm->wakeup(); }); $http->on('request', function (swoole_http_request $request, swoole_http_response $response) { - $response->header("content-length", "10000 "); + $msg = "hello world"; + $response->header("content-length", strlen($msg) . " "); $response->header("Test-Value", [ "a\r\n", "b1234 ", @@ -39,7 +40,7 @@ $pm->childFunc = function () use ($pm) { 5678, 3.1415926, ]); - $response->end("hello world"); + $response->end($msg); }); $http->start(); }; @@ -49,6 +50,7 @@ $pm->run(); ?> --EXPECTF-- HTTP/1.1 200 OK +Content-Length: 11 Test-Value: a Test-Value: b1234 Test-Value: d5678 @@ -59,6 +61,5 @@ Server: swoole-http-server Connection: keep-alive Content-Type: text/html Date: %s -Content-Length: 11 hello world diff --git a/tests/swoole_http_server/set_content_length.phpt b/tests/swoole_http_server/set_content_length.phpt new file mode 100644 index 00000000000..e1d73162ce3 --- /dev/null +++ b/tests/swoole_http_server/set_content_length.phpt @@ -0,0 +1,44 @@ +--TEST-- +swoole_http_server: allow setting content length header +--SKIPIF-- + +--FILE-- +parentFunc = function () use ($pm, $data) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, "http://127.0.0.1:" . $pm->getFreePort() . '/'); + curl_setopt($ch, CURLOPT_HEADER, 1); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + $response = curl_exec($ch); + $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE); + $header = substr($response, 0, $header_size); + Assert::assert(strrpos($header, 'Content-Length: 50') > 0); + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm, $data) { + $http = new Swoole\Http\Server('127.0.0.1', $pm->getFreePort(), SWOOLE_BASE, SWOOLE_SOCK_TCP); + + $http->on("WorkerStart", function ($serv, $wid) { + global $pm; + $pm->wakeup(); + }); + + $http->on('request', function ($req, Swoole\Http\Response $resp) use ($data) { + $resp->header('Content-Type', 'application/json'); + $resp->header('Content-Length', 50); + $resp->end($data); + }); + + $http->start(); +}; + +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- From c2eceb4f01524fd8dbc87ab17ab92b77bc00f39f Mon Sep 17 00:00:00 2001 From: codinghuang Date: Mon, 8 Feb 2021 19:28:10 +0800 Subject: [PATCH 051/936] Update version for Swoole 4.6.3 (#4047) --- CMakeLists.txt | 2 +- ext-src/php_swoole_library.h | 4 +++- include/swoole_version.h | 6 +++--- package.xml | 42 ++++++++++++++++++++++-------------- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f43a7126272..407458b094d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ PROJECT(libswoole) ENABLE_LANGUAGE(ASM) -SET(SWOOLE_VERSION 4.6.2) +SET(SWOOLE_VERSION 4.6.3) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g") diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index 4b70bcd114b..dacc2a1cfde 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: 92fd0de7d122fd973205d73931bda42c3bc80bb7 */ +/* $Id: 0f2d353333c7bd6f81592f64d7699de50f86a871 */ static const char* swoole_library_source_constants = "\n" @@ -306,6 +306,8 @@ static const char* swoole_library_source_core_constant = "\n" " public const OPTION_HTTP_GZIP_LEVEL = 'http_gzip_level';\n" "\n" + " public const OPTION_COMPRESSION_MIN_LENGTH = 'compression_min_length';\n" + "\n" " public const OPTION_UPLOAD_TMP_DIR = 'upload_tmp_dir';\n" "\n" " public const OPTION_HOST = 'host';\n" diff --git a/include/swoole_version.h b/include/swoole_version.h index 05ecaa52484..a4d649e45cf 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -20,10 +20,10 @@ #define SWOOLE_MAJOR_VERSION 4 #define SWOOLE_MINOR_VERSION 6 -#define SWOOLE_RELEASE_VERSION 2 +#define SWOOLE_RELEASE_VERSION 3 #define SWOOLE_EXTRA_VERSION "" -#define SWOOLE_VERSION "4.6.2" -#define SWOOLE_VERSION_ID 40602 +#define SWOOLE_VERSION "4.6.3" +#define SWOOLE_VERSION_ID 40603 #define SWOOLE_API_VERSION_ID 0x202012a #define SWOOLE_BUG_REPORT \ diff --git a/package.xml b/package.xml index a2c05be6dae..ce89d8b2e26 100644 --- a/package.xml +++ b/package.xml @@ -42,10 +42,10 @@ shenzhe163@gmail.com yes - 2021-01-25 - + 2021-02-08 + - 4.6.2 + 4.6.3 4.0 @@ -56,28 +56,26 @@ New APIs --- - + Added Http::Request::getMethod() (#3987) (@luolaifa000) - + Added Coroutine::Socket:recvLine() (#4014) (@matyhtf) + + Added Swoole\Coroutine\go function (swoole/library@92fd0de) (@matyhtf) Enhancement --- - + Improved Response::create() (#3998) (@matyhtf) - + Supported Coroutine\Redis::hExists return bool with compatibility_mode (swoole/swoole-src@b8cce7c) (@matyhtf) - + Supported PHP_NORMAL_READ for Coroutine::Socket::read (swoole/swoole-src@b1a0dcc) (@matyhtf) + + Added option compression_min_length for HTTP Server (#4033) (@matyhtf) + + Allowed setting content-length HTTP header in application layer (#4041) (@doubaokun) Fixed --- - * Fixed Coroutine::defer coredump in PHP8 (#3997) (@huanghantao) - * Fixed Coroutine::Socket::errCode is not set correctly when using thread context (swoole/swoole-src@004d08a) (@matyhtf) - * Fixed build Swoole error on latest macos (#4007) (@matyhtf) - * Fixed php stream context is nullptr when use md5_file with url (#4016) (@ZhiyangLeeCN) + * Fixed coredump when program reach file open limitation (swoole/swoole-src@709813f) (@matyhtf) + * Fixed JIT being disabled (#4029) (@twose) + * Fixed Response::create() bug (swoole/swoole-src@a630b5b) (@matyhtf) + * Fixed task process id false positives (#4040) (@doubaokun) + * Fixed coredump with native curl hook (#4042) (@Yurunsoft) + * Fixed README (#4046) (@asheroto) + * Fixed native-curl crash on PHP8 (#4045) (@matyhtf) Kernel --- - * Used AIO thread hook stdio instead of coroutine socket (#4002) (@matyhtf) - * Refactor HttpContext (#3998) (@matyhtf) - * Fixed Github action (#4013) (#4020) (@sy-records) - * Refactor Process::wait() (#4019) (@matyhtf) + * Optimized ssl_connect/ssl_shutdown (#4030) (@matyhtf) @@ -1036,6 +1034,7 @@ + @@ -1192,6 +1191,7 @@ + @@ -1226,6 +1226,10 @@ + + + + @@ -1253,6 +1257,7 @@ + @@ -1488,6 +1493,7 @@ + @@ -1627,6 +1633,7 @@ + @@ -1804,6 +1811,8 @@ + + @@ -1957,6 +1966,7 @@ + From b41cdea7233b4bac02a50423a433fd0d6cb80bdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Tue, 9 Feb 2021 00:49:53 +0800 Subject: [PATCH 052/936] Fix mem error (#4050) * fix * fix 2 * fix 3 * fix tests * fix tests[2] --- ext-src/php_swoole.cc | 3 +++ ext-src/swoole_runtime.cc | 3 ++- tests/swoole_client_sync/sendto.phpt | 12 ++++++------ tests/swoole_coroutine/check.phpt | 13 ++++++++++--- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index d981277339c..b4ce8b95ca0 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -398,6 +398,9 @@ SW_API bool php_swoole_is_enable_coroutine() { static void fatal_error(int code, const char *format, ...) { va_list args; zend_object *exception; + if (sw_reactor()) { + sw_reactor()->bailout = true; + } va_start(args, format); exception = zend_throw_exception(swoole_error_ce, swoole::std_string::vformat(format, args).c_str(), code); va_end(args); diff --git a/ext-src/swoole_runtime.cc b/ext-src/swoole_runtime.cc index 849acf4cfdb..38305f5c45d 100644 --- a/ext-src/swoole_runtime.cc +++ b/ext-src/swoole_runtime.cc @@ -1069,6 +1069,7 @@ static php_stream *socket_create(const char *proto, zval *ztmp; if (php_swoole_array_get_value_ex(options, name, ztmp)) { add_assoc_zval_ex(&zalias, alias, strlen(alias), ztmp); + zval_add_ref(ztmp); } }; @@ -1087,7 +1088,7 @@ static php_stream *socket_create(const char *proto, if (!sock->ssl_check_context()) { goto _failed; } - zend_array_destroy(Z_ARRVAL(zalias)); + zval_dtor(&zalias); } #endif } diff --git a/tests/swoole_client_sync/sendto.phpt b/tests/swoole_client_sync/sendto.phpt index 6159be9bbf2..21f237d0cb7 100644 --- a/tests/swoole_client_sync/sendto.phpt +++ b/tests/swoole_client_sync/sendto.phpt @@ -15,11 +15,11 @@ $pm = new SwooleTest\ProcessManager; $pm->parentFunc = function () use ($pm) { $cli = new Client(SWOOLE_SOCK_UDP); - $cli->sendto('127.0.0.1', $pm->getFreePort(), "hello"); - $cli->sendto('localhost', $pm->getFreePort(), "hello"); + $cli->sendto('127.0.0.1', $pm->getFreePort(), "packet-1"); + $cli->sendto('localhost', $pm->getFreePort(), "packet-2"); Assert::false($cli->sendto('error_domain', $pm->getFreePort(), "hello")); Assert::assert($cli->errCode, SWOOLE_ERROR_DNSLOOKUP_RESOLVE_FAILED); - $cli->sendto('localhost', $pm->getFreePort(), "hello"); + $cli->sendto('localhost', $pm->getFreePort(), "packet-3"); echo "DONE\n"; }; $pm->childFunc = function () use ($pm) { @@ -29,11 +29,11 @@ $pm->childFunc = function () use ($pm) { $pm->wakeup(); $peer = null; $ret = $socket->recvfrom($peer); - Assert::eq($ret, 'hello', 'packet-1'); + Assert::eq($ret, 'packet-1'); $ret = $socket->recvfrom($peer); - Assert::eq($ret, 'hello', 'packet-2'); + Assert::eq($ret, 'packet-2'); $ret = $socket->recvfrom($peer); - Assert::eq($ret, 'hello', 'packet-3'); + Assert::eq($ret, 'packet-3'); }); }; $pm->childFirst(); diff --git a/tests/swoole_coroutine/check.phpt b/tests/swoole_coroutine/check.phpt index 4cb532f2d5a..0c4e0b3432c 100644 --- a/tests/swoole_coroutine/check.phpt +++ b/tests/swoole_coroutine/check.phpt @@ -5,6 +5,9 @@ swoole_coroutine: check if is in the coroutine --FILE-- $f) { $GLOBALS['f'] = $f; + if (RUN_IN_CHILD == false) { + $f(); + continue; + } $process = new Swoole\Process(function () { function a() { From 62fd4594e8f7d13f43016cf61dd5160780c43bec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Tue, 9 Feb 2021 17:45:06 +0800 Subject: [PATCH 053/936] Exit the process directly when a fatal error occurs (#4053) * Exit the process directly when a fatal error occurs * use zend_try * fix tests * fix tests [2] --- ext-src/php_swoole.cc | 14 +++++++------- ext-src/php_swoole.h | 1 + ext-src/swoole_coroutine.cc | 7 +++++++ tests/swoole_mysql_coro/another_coroutine.phpt | 1 - 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index b4ce8b95ca0..7fa57adcf71 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -397,15 +397,15 @@ SW_API bool php_swoole_is_enable_coroutine() { static void fatal_error(int code, const char *format, ...) { va_list args; - zend_object *exception; - if (sw_reactor()) { - sw_reactor()->bailout = true; - } va_start(args, format); - exception = zend_throw_exception(swoole_error_ce, swoole::std_string::vformat(format, args).c_str(), code); + zend_object *exception = zend_throw_exception(swoole_error_ce, swoole::std_string::vformat(format, args).c_str(), code); va_end(args); - zend_exception_error(exception, E_ERROR); - exit(255); + + zend_try { + zend_exception_error(exception, E_ERROR); + } zend_catch { + exit(255); + } zend_end_try(); } /* {{{ PHP_MINIT_FUNCTION diff --git a/ext-src/php_swoole.h b/ext-src/php_swoole.h index a3f10f2f37a..6e13fb22de2 100644 --- a/ext-src/php_swoole.h +++ b/ext-src/php_swoole.h @@ -174,6 +174,7 @@ extern zend_class_entry *swoole_websocket_frame_ce; extern zend_class_entry *swoole_server_port_ce; extern zend_class_entry *swoole_exception_ce; extern zend_object_handlers swoole_exception_handlers; +extern zend_class_entry *swoole_error_ce;; PHP_MINIT_FUNCTION(swoole); PHP_MSHUTDOWN_FUNCTION(swoole); diff --git a/ext-src/swoole_coroutine.cc b/ext-src/swoole_coroutine.cc index 684ec32c276..ee2a68b81cb 100644 --- a/ext-src/swoole_coroutine.cc +++ b/ext-src/swoole_coroutine.cc @@ -325,6 +325,13 @@ void PHPCoroutine::activate() { sw_reactor()->running = false; sw_reactor()->bailout = true; } +#ifdef SW_EXIT_WHEN_OCCURS_FATAL_ERROR + zend_try { + orig_error_function(type, error_filename, error_lineno, ZEND_ERROR_CB_LAST_ARG_RELAY); + } zend_catch { + exit(255); + } zend_end_try(); +#endif } if (sw_likely(orig_error_function)) { orig_error_function(type, error_filename, error_lineno, ZEND_ERROR_CB_LAST_ARG_RELAY); diff --git a/tests/swoole_mysql_coro/another_coroutine.phpt b/tests/swoole_mysql_coro/another_coroutine.phpt index 6907b05f137..e2c6632fbb0 100644 --- a/tests/swoole_mysql_coro/another_coroutine.phpt +++ b/tests/swoole_mysql_coro/another_coroutine.phpt @@ -63,4 +63,3 @@ Stack trace: #3 %s(%d): {closure}() #4 {main} thrown in %s on line %d -DONE From e24a52e2a3e4121f8db1c3968a21ef27d2b3e4d8 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 9 Feb 2021 21:39:49 +0800 Subject: [PATCH 054/936] Update version --- CMakeLists.txt | 2 +- include/swoole_version.h | 8 ++-- tools/next-version.php | 72 +++++++++++++++++++++++++++++++++++ tools/templates/version.tpl.h | 38 ++++++++++++++++++ 4 files changed, 115 insertions(+), 5 deletions(-) create mode 100755 tools/next-version.php create mode 100644 tools/templates/version.tpl.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 407458b094d..00874627236 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ PROJECT(libswoole) ENABLE_LANGUAGE(ASM) -SET(SWOOLE_VERSION 4.6.3) +set(SWOOLE_VERSION 4.6.4-dev) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g") diff --git a/include/swoole_version.h b/include/swoole_version.h index a4d649e45cf..a167fbfe255 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -20,10 +20,10 @@ #define SWOOLE_MAJOR_VERSION 4 #define SWOOLE_MINOR_VERSION 6 -#define SWOOLE_RELEASE_VERSION 3 -#define SWOOLE_EXTRA_VERSION "" -#define SWOOLE_VERSION "4.6.3" -#define SWOOLE_VERSION_ID 40603 +#define SWOOLE_RELEASE_VERSION 4 +#define SWOOLE_EXTRA_VERSION "dev" +#define SWOOLE_VERSION "4.6.4-dev" +#define SWOOLE_VERSION_ID 40604 #define SWOOLE_API_VERSION_ID 0x202012a #define SWOOLE_BUG_REPORT \ diff --git a/tools/next-version.php b/tools/next-version.php new file mode 100755 index 00000000000..7db439bfccb --- /dev/null +++ b/tools/next-version.php @@ -0,0 +1,72 @@ +#!/usr/bin/env php +major, $this->minor, $this->release]); + if ($this->extra) { + $versoin .= '-' . $this->extra; + } + return $versoin; + } + + function getVersionId() { + return intval(sprintf('%d%02d%02d', $this->major, $this->minor, $this->release)); + } +} + +$type = empty($argv[1]) ? 'release' : trim($argv[1]); +$kernel_version_file = dirname(__DIR__) . '/include/swoole_version.h'; +$cmake_file = dirname(__DIR__) . '/CMakeLists.txt'; + +$versionInfo = file_get_contents($kernel_version_file); + +preg_match(Version::REGX_MAJOR, $versionInfo, $match_major) or die('no match MAJOR_VERSION'); +preg_match(Version::REGX_MINOR, $versionInfo, $match_minor) or die('no match MAJOR_MINOR');; +preg_match(Version::REGX_RELEASE, $versionInfo, + $match_release) or die('no match RELEASE_VERSION');; +preg_match(Version::REGX_EXTRA, $versionInfo, $match_extra) or die('no match EXTRA_VERSION'); + +$current = new Version; +$current->major = intval($match_major[1]); +$current->minor = intval($match_minor[1]); +$current->release = intval($match_release[1]); +$current->extra = trim($match_extra[1]); + +$next = clone $current; + +if ($type == 'release') { + if ($current->extra == '') { + $next->release++; + $next->extra = 'dev'; + } else { + $next->extra = ''; + } +} elseif ($type == 'minor') { + $next->minor++; + $next->release = 0; + $next->extra = 'dev'; +} elseif ($type == 'major') { + $next->major++; + $next->minor = 0; + $next->release = 0; + $next->extra = 'dev'; +} + +ob_start(); +include __DIR__.'/templates/version.tpl.h'; +file_put_contents($kernel_version_file, ob_get_clean()); + +file_put_contents($cmake_file, preg_replace('#set\(SWOOLE_VERSION\s+[0-9\.\-a-z]+\)#i', 'set(SWOOLE_VERSION '.$next->getVersion().')', file_get_contents($cmake_file))); diff --git a/tools/templates/version.tpl.h b/tools/templates/version.tpl.h new file mode 100644 index 00000000000..3487d27b23e --- /dev/null +++ b/tools/templates/version.tpl.h @@ -0,0 +1,38 @@ +/* + +----------------------------------------------------------------------+ + | 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 | + | Twosee | + +----------------------------------------------------------------------+ +*/ + +#ifndef SWOOLE_VERSION_H_ +#define SWOOLE_VERSION_H_ + +#define SWOOLE_MAJOR_VERSION major."\n" ?> +#define SWOOLE_MINOR_VERSION minor."\n" ?> +#define SWOOLE_RELEASE_VERSION release."\n" ?> +#define SWOOLE_EXTRA_VERSION "extra ?>" +#define SWOOLE_VERSION "getVersion() ?>" +#define SWOOLE_VERSION_ID getVersionId()."\n" ?> +#define SWOOLE_API_VERSION_ID 0x202012a + +#define SWOOLE_BUG_REPORT \ + "A bug occurred in Swoole-v" SWOOLE_VERSION ", please report it.\n" \ + "The Swoole developers probably don't know about it,\n" \ + "and unless you report it, chances are it won't be fixed.\n" \ + "You can read How to report a bug doc before submitting any bug reports:\n" \ + ">> https://github.com/swoole/swoole-src/blob/master/.github/ISSUE.md \n" \ + "Please do not send bug reports in the mailing list or personal letters.\n" \ + "The issue page is also suitable to submit feature requests.\n" + +#endif From b4f2985b7c29567ab4d698fa4e8e6c3d5752e9ca Mon Sep 17 00:00:00 2001 From: matyhtf Date: Wed, 10 Feb 2021 10:44:48 +0800 Subject: [PATCH 055/936] format & optimize code --- ext-src/php_swoole.h | 688 +++++++++++++++++++--------------------- ext-src/swoole_event.cc | 15 +- tools/next-version.php | 11 +- 3 files changed, 331 insertions(+), 383 deletions(-) diff --git a/ext-src/php_swoole.h b/ext-src/php_swoole.h index 6e13fb22de2..a817aad5612 100644 --- a/ext-src/php_swoole.h +++ b/ext-src/php_swoole.h @@ -65,25 +65,35 @@ extern PHPAPI int php_array_merge(zend_array *dest, zend_array *src); extern zend_module_entry swoole_module_entry; #ifdef PHP_WIN32 -# define PHP_SWOOLE_API __declspec(dllexport) +#define PHP_SWOOLE_API __declspec(dllexport) #elif defined(__GNUC__) && __GNUC__ >= 4 -# define PHP_SWOOLE_API __attribute__ ((visibility("default"))) +#define PHP_SWOOLE_API __attribute__((visibility("default"))) #else -# define PHP_SWOOLE_API +#define PHP_SWOOLE_API #endif -#define SW_CHECK_RETURN(s) if(s<0){RETURN_FALSE;}else{RETURN_TRUE;} -#define SW_LOCK_CHECK_RETURN(s) if(s==0){RETURN_TRUE;}else{zend_update_property_long(NULL,SW_Z8_OBJ_P(ZEND_THIS),SW_STRL("errCode"),s);RETURN_FALSE;} +#define SW_CHECK_RETURN(s) \ + if (s < 0) { \ + RETURN_FALSE; \ + } else { \ + RETURN_TRUE; \ + } +#define SW_LOCK_CHECK_RETURN(s) \ + if (s == 0) { \ + RETURN_TRUE; \ + } else { \ + zend_update_property_long(NULL, SW_Z8_OBJ_P(ZEND_THIS), SW_STRL("errCode"), s); \ + RETURN_FALSE; \ + } -#define php_swoole_fatal_error(level, fmt_str, ...) \ - php_error_docref(NULL, level, (const char *) (fmt_str), ##__VA_ARGS__) +#define php_swoole_fatal_error(level, fmt_str, ...) \ + php_error_docref(NULL, level, (const char *) (fmt_str), ##__VA_ARGS__) -#define php_swoole_error(level, fmt_str, ...) \ - if (SWOOLE_G(display_errors) || level == E_ERROR) \ - php_swoole_fatal_error(level, fmt_str, ##__VA_ARGS__) +#define php_swoole_error(level, fmt_str, ...) \ + if (SWOOLE_G(display_errors) || level == E_ERROR) php_swoole_fatal_error(level, fmt_str, ##__VA_ARGS__) -#define php_swoole_sys_error(level, fmt_str, ...) \ - php_swoole_error(level, fmt_str ", Error: %s[%d]", ##__VA_ARGS__, strerror(errno), errno) +#define php_swoole_sys_error(level, fmt_str, ...) \ + php_swoole_error(level, fmt_str ", Error: %s[%d]", ##__VA_ARGS__, strerror(errno), errno) #ifdef SW_USE_OPENSSL #ifndef HAVE_OPENSSL @@ -105,11 +115,10 @@ extern zend_module_entry swoole_module_entry; #endif //-------------------------------------------------------- -#define SW_MAX_FIND_COUNT 100 //for swoole_server::connection_list -#define SW_PHP_CLIENT_BUFFER_SIZE 65535 +#define SW_MAX_FIND_COUNT 100 // for swoole_server::connection_list +#define SW_PHP_CLIENT_BUFFER_SIZE 65535 //-------------------------------------------------------- -enum php_swoole_client_callback_type -{ +enum php_swoole_client_callback_type { SW_CLIENT_CB_onConnect = 1, SW_CLIENT_CB_onReceive, SW_CLIENT_CB_onClose, @@ -121,12 +130,11 @@ enum php_swoole_client_callback_type #endif }; //--------------------------------------------------------- -#define SW_FLAG_KEEP (1u << 12) -#define SW_FLAG_ASYNC (1u << 10) -#define SW_FLAG_SYNC (1u << 11) +#define SW_FLAG_KEEP (1u << 12) +#define SW_FLAG_ASYNC (1u << 10) +#define SW_FLAG_SYNC (1u << 11) //--------------------------------------------------------- -enum php_swoole_fd_type -{ +enum php_swoole_fd_type { PHP_SWOOLE_FD_STREAM_CLIENT = SW_FD_STREAM_CLIENT, PHP_SWOOLE_FD_DGRAM_CLIENT, PHP_SWOOLE_FD_MYSQL, @@ -144,8 +152,7 @@ enum php_swoole_fd_type PHP_SWOOLE_FD_CO_CURL, }; //--------------------------------------------------------- -typedef enum -{ +typedef enum { PHP_SWOOLE_RINIT_BEGIN, PHP_SWOOLE_RINIT_END, PHP_SWOOLE_CALL_USER_SHUTDOWNFUNC_BEGIN, @@ -154,9 +161,8 @@ typedef enum } php_swoole_req_status; //--------------------------------------------------------- -static sw_inline enum swSocket_type php_swoole_socktype(long type) -{ - return (enum swSocket_type) (type & (~SW_FLAG_SYNC) & (~SW_FLAG_ASYNC) & (~SW_FLAG_KEEP) & (~SW_SOCK_SSL)); +static sw_inline enum swSocket_type php_swoole_socktype(long type) { + return (enum swSocket_type)(type & (~SW_FLAG_SYNC) & (~SW_FLAG_ASYNC) & (~SW_FLAG_KEEP) & (~SW_SOCK_SSL)); } extern zend_class_entry *swoole_event_ce; @@ -174,7 +180,7 @@ extern zend_class_entry *swoole_websocket_frame_ce; extern zend_class_entry *swoole_server_port_ce; extern zend_class_entry *swoole_exception_ce; extern zend_object_handlers swoole_exception_handlers; -extern zend_class_entry *swoole_error_ce;; +extern zend_class_entry *swoole_error_ce; PHP_MINIT_FUNCTION(swoole); PHP_MSHUTDOWN_FUNCTION(swoole); @@ -193,7 +199,7 @@ PHP_FUNCTION(swoole_coroutine_exec); PHP_FUNCTION(swoole_coroutine_gethostbyname); PHP_FUNCTION(swoole_coroutine_defer); PHP_FUNCTION(swoole_coroutine_socketpair); -PHP_FUNCTION(swoole_test_kernel_coroutine); // for tests +PHP_FUNCTION(swoole_test_kernel_coroutine); // for tests //--------------------------------------------------------- // event //--------------------------------------------------------- @@ -206,10 +212,10 @@ PHP_FUNCTION(swoole_async_dns_lookup_coro); //--------------------------------------------------------- // error //--------------------------------------------------------- -#define SW_STRERROR_SYSTEM 0 -#define SW_STRERROR_GAI 1 -#define SW_STRERROR_DNS 2 -#define SW_STRERROR_SWOOLE 9 +#define SW_STRERROR_SYSTEM 0 +#define SW_STRERROR_GAI 1 +#define SW_STRERROR_DNS 2 +#define SW_STRERROR_SWOOLE 9 /** * MINIT @@ -284,15 +290,13 @@ void php_swoole_event_exit(); * MSHUTDOWN * ============================================================== */ -void php_swoole_runtime_mshutdown() ; +void php_swoole_runtime_mshutdown(); -static sw_inline zend_bool php_swoole_websocket_frame_is_object(zval *zdata) -{ +static sw_inline zend_bool php_swoole_websocket_frame_is_object(zval *zdata) { return Z_TYPE_P(zdata) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zdata), swoole_websocket_frame_ce); } -static sw_inline size_t php_swoole_get_send_data(zval *zdata, char **str) -{ +static sw_inline size_t php_swoole_get_send_data(zval *zdata, char **str) { convert_to_string(zdata); *str = Z_STRVAL_P(zdata); return Z_STRLEN_P(zdata); @@ -307,6 +311,7 @@ php_socket *php_swoole_convert_to_socket(int sock); zend_bool php_swoole_signal_isset_handler(int signo); +// clang-format off ZEND_BEGIN_MODULE_GLOBALS(swoole) zend_bool display_errors; zend_bool cli; @@ -317,6 +322,7 @@ ZEND_BEGIN_MODULE_GLOBALS(swoole) long socket_buffer_size; php_swoole_req_status req_status; ZEND_END_MODULE_GLOBALS(swoole) +// clang-format on extern ZEND_DECLARE_MODULE_GLOBALS(swoole); @@ -335,44 +341,45 @@ extern ZEND_DECLARE_MODULE_GLOBALS(swoole); // Then https://github.com/php/php-src/commit/2dcfd8d16f5fa69582015cbd882aff833075a34c // See https://github.com/php/php-src/commit/52db03b3e52bfc886896925d050af79bc4dc1ba3 #if PHP_MINOR_VERSION == 2 -#define SW_ZEND_WRONG_PARAMETERS_COUNT_ERROR zend_wrong_parameters_count_error(_flags & ZEND_PARSE_PARAMS_THROW, _num_args, _min_num_args, _max_num_args) +#define SW_ZEND_WRONG_PARAMETERS_COUNT_ERROR \ + zend_wrong_parameters_count_error(_flags &ZEND_PARSE_PARAMS_THROW, _num_args, _min_num_args, _max_num_args) #else #define SW_ZEND_WRONG_PARAMETERS_COUNT_ERROR zend_wrong_parameters_count_error(_num_args, _min_num_args, _max_num_args) #endif #undef ZEND_PARSE_PARAMETERS_START_EX -#define ZEND_PARSE_PARAMETERS_START_EX(flags, min_num_args, max_num_args) do { \ - const int _flags = (flags); \ - int _min_num_args = (min_num_args); \ - int _max_num_args = (max_num_args); \ - int _num_args = EX_NUM_ARGS(); \ - int _i; \ - zval *_real_arg, *_arg = NULL; \ - zend_expected_type _expected_type = Z_EXPECTED_LONG; \ - char *_error = NULL; \ - zend_bool _dummy; \ - zend_bool _optional = 0; \ - int error_code = ZPP_ERROR_OK; \ - ((void)_i); \ - ((void)_real_arg); \ - ((void)_arg); \ - ((void)_expected_type); \ - ((void)_error); \ - ((void)_dummy); \ - ((void)_optional); \ - \ - do { \ - if (UNEXPECTED(_num_args < _min_num_args) || \ - (UNEXPECTED(_num_args > _max_num_args) && \ - EXPECTED(_max_num_args >= 0))) { \ - if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \ - SW_ZEND_WRONG_PARAMETERS_COUNT_ERROR; \ - } \ - error_code = ZPP_ERROR_FAILURE; \ - break; \ - } \ - _i = 0; \ +#define ZEND_PARSE_PARAMETERS_START_EX(flags, min_num_args, max_num_args) \ + do { \ + const int _flags = (flags); \ + int _min_num_args = (min_num_args); \ + int _max_num_args = (max_num_args); \ + int _num_args = EX_NUM_ARGS(); \ + int _i; \ + zval *_real_arg, *_arg = NULL; \ + zend_expected_type _expected_type = Z_EXPECTED_LONG; \ + char *_error = NULL; \ + zend_bool _dummy; \ + zend_bool _optional = 0; \ + int error_code = ZPP_ERROR_OK; \ + ((void) _i); \ + ((void) _real_arg); \ + ((void) _arg); \ + ((void) _expected_type); \ + ((void) _error); \ + ((void) _dummy); \ + ((void) _optional); \ + \ + do { \ + if (UNEXPECTED(_num_args < _min_num_args) || \ + (UNEXPECTED(_num_args > _max_num_args) && EXPECTED(_max_num_args >= 0))) { \ + if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \ + SW_ZEND_WRONG_PARAMETERS_COUNT_ERROR; \ + } \ + error_code = ZPP_ERROR_FAILURE; \ + break; \ + } \ + _i = 0; \ _real_arg = ZEND_CALL_ARG(execute_data, 0); #endif @@ -384,7 +391,7 @@ extern ZEND_DECLARE_MODULE_GLOBALS(swoole); #endif #ifndef ZEND_CLOSURE_OBJECT -#define ZEND_CLOSURE_OBJECT(func) (zend_object*)func->op_array.prototype +#define ZEND_CLOSURE_OBJECT(func) (zend_object *) func->op_array.prototype #endif /* PHP 7.4 compatibility macro {{{*/ @@ -396,10 +403,14 @@ extern ZEND_DECLARE_MODULE_GLOBALS(swoole); #define ZVAL_EMPTY_ARRAY(zval) (array_init((zval))) #endif #ifndef RETVAL_EMPTY_ARRAY -#define RETVAL_EMPTY_ARRAY() ZVAL_EMPTY_ARRAY(return_value) +#define RETVAL_EMPTY_ARRAY() ZVAL_EMPTY_ARRAY(return_value) #endif #ifndef RETURN_EMPTY_ARRAY -#define RETURN_EMPTY_ARRAY() do { RETVAL_EMPTY_ARRAY(); return; } while (0) +#define RETURN_EMPTY_ARRAY() \ + do { \ + RETVAL_EMPTY_ARRAY(); \ + return; \ + } while (0) #endif #ifndef ZEND_THIS @@ -417,13 +428,13 @@ extern ZEND_DECLARE_MODULE_GLOBALS(swoole); /* PHP 8 compatibility macro {{{*/ #if PHP_VERSION_ID < 80000 -#define sw_zend7_object zval -#define SW_Z7_OBJ_P(object) Z_OBJ_P(object) -#define SW_Z8_OBJ_P(zobj) zobj +#define sw_zend7_object zval +#define SW_Z7_OBJ_P(object) Z_OBJ_P(object) +#define SW_Z8_OBJ_P(zobj) zobj #else -#define sw_zend7_object zend_object -#define SW_Z7_OBJ_P(object) object -#define SW_Z8_OBJ_P(zobj) Z_OBJ_P(zobj) +#define sw_zend7_object zend_object +#define SW_Z7_OBJ_P(object) object +#define SW_Z8_OBJ_P(zobj) Z_OBJ_P(zobj) #endif /*}}}*/ @@ -439,17 +450,17 @@ typedef ssize_t php_stream_size_t; // Deprecated: do not use it anymore // do not use sw_copy_to_stack(return_value, foo); -#define sw_copy_to_stack(ptr, val) do { \ - (val) = *(zval *) (ptr); \ - (ptr) = &(val); \ -} while (0) +#define sw_copy_to_stack(ptr, val) \ + do { \ + (val) = *(zval *) (ptr); \ + (ptr) = &(val); \ + } while (0) #if PHP_VERSION_ID < 80000 -#define SW_ZVAL_SOCKET(return_value, result) \ - ZVAL_RES(return_value,zend_register_resource((void *) (result), php_sockets_le_socket())) +#define SW_ZVAL_SOCKET(return_value, result) \ + ZVAL_RES(return_value, zend_register_resource((void *) (result), php_sockets_le_socket())) #else -#define SW_ZVAL_SOCKET(return_value, result) \ - ZVAL_OBJ(return_value, &result->std) +#define SW_ZVAL_SOCKET(return_value, result) ZVAL_OBJ(return_value, &result->std) #endif #if PHP_VERSION_ID < 80000 @@ -459,50 +470,43 @@ typedef ssize_t php_stream_size_t; #endif #ifndef ZVAL_IS_BOOL -static sw_inline zend_bool ZVAL_IS_BOOL(zval *v) -{ +static sw_inline zend_bool ZVAL_IS_BOOL(zval *v) { return Z_TYPE_P(v) == IS_TRUE || Z_TYPE_P(v) == IS_FALSE; } #endif #ifndef ZVAL_IS_TRUE -static sw_inline zend_bool ZVAL_IS_TRUE(zval *v) -{ +static sw_inline zend_bool ZVAL_IS_TRUE(zval *v) { return Z_TYPE_P(v) == IS_TRUE; } #endif #ifndef ZVAL_IS_FALSE -static sw_inline zend_bool ZVAL_IS_FALSE(zval *v) -{ +static sw_inline zend_bool ZVAL_IS_FALSE(zval *v) { return Z_TYPE_P(v) == IS_FALSE; } #endif #ifndef ZVAL_IS_LONG -static sw_inline zend_bool ZVAL_IS_LONG(zval *v) -{ +static sw_inline zend_bool ZVAL_IS_LONG(zval *v) { return Z_TYPE_P(v) == IS_LONG; } #endif #ifndef ZVAL_IS_STRING -static sw_inline zend_bool ZVAL_IS_STRING(zval *v) -{ +static sw_inline zend_bool ZVAL_IS_STRING(zval *v) { return Z_TYPE_P(v) == IS_STRING; } #endif #ifndef Z_BVAL_P -static sw_inline zend_bool Z_BVAL_P(zval *v) -{ +static sw_inline zend_bool Z_BVAL_P(zval *v) { return Z_TYPE_P(v) == IS_TRUE; } #endif #ifndef ZVAL_IS_ARRAY -static sw_inline zend_bool ZVAL_IS_ARRAY(zval *v) -{ +static sw_inline zend_bool ZVAL_IS_ARRAY(zval *v) { return Z_TYPE_P(v) == IS_ARRAY; } #endif @@ -513,45 +517,42 @@ static sw_inline zend_bool ZVAL_IS_OBJECT(zval *v) { } #endif -static sw_inline zval *sw_malloc_zval() -{ +static sw_inline zval *sw_malloc_zval() { return (zval *) emalloc(sizeof(zval)); } -static sw_inline zend_string *sw_get_zend_string(void *addr) -{ +static sw_inline zend_string *sw_get_zend_string(void *addr) { return (zend_string *) ((char *) addr - offsetof(zend_string, val)); } -static sw_inline void sw_set_zend_string(zval *zdata, char *addr, size_t length) -{ +static sw_inline void sw_set_zend_string(zval *zdata, char *addr, size_t length) { zend_string *zstr = sw_get_zend_string(addr); addr[length] = 0; zstr->len = length; ZVAL_STR(zdata, zstr); } -static sw_inline zval *sw_zval_dup(zval *val) -{ +static sw_inline zval *sw_zval_dup(zval *val) { zval *dup = sw_malloc_zval(); memcpy(dup, val, sizeof(zval)); return dup; } -static sw_inline void sw_zval_free(zval *val) -{ +static sw_inline void sw_zval_free(zval *val) { zval_ptr_dtor(val); efree(val); } //----------------------------------Constant API------------------------------------ -#define SW_REGISTER_NULL_CONSTANT(name) REGISTER_NULL_CONSTANT(name, CONST_CS | CONST_PERSISTENT) -#define SW_REGISTER_BOOL_CONSTANT(name, value) REGISTER_BOOL_CONSTANT(name, value, CONST_CS | CONST_PERSISTENT) -#define SW_REGISTER_LONG_CONSTANT(name, value) REGISTER_LONG_CONSTANT(name, value, CONST_CS | CONST_PERSISTENT) -#define SW_REGISTER_DOUBLE_CONSTANT(name, value) REGISTER_DOUBLE_CONSTANT(name, value, CONST_CS | CONST_PERSISTENT) -#define SW_REGISTER_STRING_CONSTANT(name, value) REGISTER_STRING_CONSTANT(name, (char *) value, CONST_CS | CONST_PERSISTENT) -#define SW_REGISTER_STRINGL_CONSTANT(name, value) REGISTER_STRINGL_CONSTANT(name, (char *) value, CONST_CS | CONST_PERSISTENT) +#define SW_REGISTER_NULL_CONSTANT(name) REGISTER_NULL_CONSTANT(name, CONST_CS | CONST_PERSISTENT) +#define SW_REGISTER_BOOL_CONSTANT(name, value) REGISTER_BOOL_CONSTANT(name, value, CONST_CS | CONST_PERSISTENT) +#define SW_REGISTER_LONG_CONSTANT(name, value) REGISTER_LONG_CONSTANT(name, value, CONST_CS | CONST_PERSISTENT) +#define SW_REGISTER_DOUBLE_CONSTANT(name, value) REGISTER_DOUBLE_CONSTANT(name, value, CONST_CS | CONST_PERSISTENT) +#define SW_REGISTER_STRING_CONSTANT(name, value) \ + REGISTER_STRING_CONSTANT(name, (char *) value, CONST_CS | CONST_PERSISTENT) +#define SW_REGISTER_STRINGL_CONSTANT(name, value) \ + REGISTER_STRINGL_CONSTANT(name, (char *) value, CONST_CS | CONST_PERSISTENT) //----------------------------------Number API----------------------------------- @@ -559,26 +560,22 @@ static sw_inline void sw_zval_free(zval *val) //----------------------------------String API----------------------------------- -#define SW_PHP_OB_START(zoutput) \ - zval zoutput; \ - do { \ +#define SW_PHP_OB_START(zoutput) \ + zval zoutput; \ + do { \ php_output_start_user(NULL, 0, PHP_OUTPUT_HANDLER_STDFLAGS); -#define SW_PHP_OB_END() \ - php_output_get_contents(&zoutput); \ - php_output_discard(); \ - } while (0) +#define SW_PHP_OB_END() \ + php_output_get_contents(&zoutput); \ + php_output_discard(); \ + } \ + while (0) -static sw_inline zend_string* sw_zend_string_recycle(zend_string *s, size_t alloc_len, size_t real_len) -{ +static sw_inline zend_string *sw_zend_string_recycle(zend_string *s, size_t alloc_len, size_t real_len) { SW_ASSERT(!ZSTR_IS_INTERNED(s)); - if (UNEXPECTED(alloc_len != real_len)) - { - if (alloc_len > SwooleG.pagesize && alloc_len > real_len * 2) - { + if (UNEXPECTED(alloc_len != real_len)) { + if (alloc_len > SwooleG.pagesize && alloc_len > real_len * 2) { s = zend_string_realloc(s, real_len, 0); - } - else - { + } else { ZSTR_LEN(s) = real_len; } } @@ -588,18 +585,14 @@ static sw_inline zend_string* sw_zend_string_recycle(zend_string *s, size_t allo //----------------------------------Array API------------------------------------ -#define php_swoole_array_length(zarray) zend_hash_num_elements(Z_ARRVAL_P(zarray)) -#define php_swoole_array_get_value(ht, str, v) ((v = zend_hash_str_find(ht, str, sizeof(str)-1)) && !ZVAL_IS_NULL(v)) +#define php_swoole_array_length(zarray) zend_hash_num_elements(Z_ARRVAL_P(zarray)) +#define php_swoole_array_get_value(ht, str, v) ((v = zend_hash_str_find(ht, str, sizeof(str) - 1)) && !ZVAL_IS_NULL(v)) #define php_swoole_array_get_value_ex(ht, str, v) ((v = zend_hash_str_find(ht, str, strlen(str))) && !ZVAL_IS_NULL(v)) -static sw_inline int php_swoole_array_length_safe(zval *zarray) -{ - if (zarray && ZVAL_IS_ARRAY(zarray)) - { +static sw_inline int php_swoole_array_length_safe(zval *zarray) { + if (zarray && ZVAL_IS_ARRAY(zarray)) { return php_swoole_array_length(zarray); - } - else - { + } else { return 0; } } @@ -607,29 +600,36 @@ static sw_inline int php_swoole_array_length_safe(zval *zarray) void php_swoole_sha1(const char *str, int _len, uchar *digest); void php_swoole_sha256(const char *str, int _len, uchar *digest); -#define SW_HASHTABLE_FOREACH_START(ht, _val) ZEND_HASH_FOREACH_VAL(ht, _val); { -#define SW_HASHTABLE_FOREACH_START2(ht, k, klen, ktype, _val) zend_string *_foreach_key;\ - ZEND_HASH_FOREACH_STR_KEY_VAL(ht, _foreach_key, _val); \ - if (!_foreach_key) {k = NULL; klen = 0; ktype = 0;} \ - else {k = ZSTR_VAL(_foreach_key), klen=ZSTR_LEN(_foreach_key); ktype = 1;} { -#define SW_HASHTABLE_FOREACH_END() } ZEND_HASH_FOREACH_END(); - -static sw_inline void add_assoc_ulong_safe_ex(zval *arg, const char *key, size_t key_len, zend_ulong value) -{ - if (sw_likely(value <= ZEND_LONG_MAX)) +#define SW_HASHTABLE_FOREACH_START(ht, _val) \ + ZEND_HASH_FOREACH_VAL(ht, _val); \ { - add_assoc_long_ex(arg, key, key_len, value); - } - else +#define SW_HASHTABLE_FOREACH_START2(ht, k, klen, ktype, _val) \ + zend_string *_foreach_key; \ + ZEND_HASH_FOREACH_STR_KEY_VAL(ht, _foreach_key, _val); \ + if (!_foreach_key) { \ + k = NULL; \ + klen = 0; \ + ktype = 0; \ + } else { \ + k = ZSTR_VAL(_foreach_key), klen = ZSTR_LEN(_foreach_key); \ + ktype = 1; \ + } \ { +#define SW_HASHTABLE_FOREACH_END() \ + } \ + ZEND_HASH_FOREACH_END(); + +static sw_inline void add_assoc_ulong_safe_ex(zval *arg, const char *key, size_t key_len, zend_ulong value) { + if (sw_likely(value <= ZEND_LONG_MAX)) { + add_assoc_long_ex(arg, key, key_len, value); + } else { char buf[MAX_LENGTH_OF_LONG + 1]; size_t len = sw_snprintf(buf, sizeof(buf), ZEND_ULONG_FMT, value); add_assoc_stringl_ex(arg, key, key_len, buf, len); } } -static sw_inline void add_assoc_ulong_safe(zval *arg, const char *key, zend_ulong value) -{ +static sw_inline void add_assoc_ulong_safe(zval *arg, const char *key, zend_ulong value) { add_assoc_ulong_safe_ex(arg, key, strlen(key), value); } @@ -639,113 +639,114 @@ static sw_inline void add_assoc_ulong_safe(zval *arg, const char *key, zend_ulon /* PHP 7 class declaration macros */ -#define SW_INIT_CLASS_ENTRY_BASE(module, namespace_name, snake_name, short_name, methods, parent_ce) do { \ - zend_class_entry _##module##_ce = {}; \ - INIT_CLASS_ENTRY(_##module##_ce, namespace_name, methods); \ - module##_ce = zend_register_internal_class_ex(&_##module##_ce, parent_ce); \ - if (snake_name) SW_CLASS_ALIAS(snake_name, module); \ - if (short_name) SW_CLASS_ALIAS_SHORT_NAME(short_name, module); \ -} while (0) +#define SW_INIT_CLASS_ENTRY_BASE(module, namespace_name, snake_name, short_name, methods, parent_ce) \ + do { \ + zend_class_entry _##module##_ce = {}; \ + INIT_CLASS_ENTRY(_##module##_ce, namespace_name, methods); \ + module##_ce = zend_register_internal_class_ex(&_##module##_ce, parent_ce); \ + if (snake_name) SW_CLASS_ALIAS(snake_name, module); \ + if (short_name) SW_CLASS_ALIAS_SHORT_NAME(short_name, module); \ + } while (0) -#define SW_INIT_CLASS_ENTRY(module, namespace_name, snake_name, short_name, methods) \ - SW_INIT_CLASS_ENTRY_BASE(module, namespace_name, snake_name, short_name, methods, NULL); \ +#define SW_INIT_CLASS_ENTRY(module, namespace_name, snake_name, short_name, methods) \ + SW_INIT_CLASS_ENTRY_BASE(module, namespace_name, snake_name, short_name, methods, NULL); \ memcpy(&module##_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)) -#define SW_INIT_CLASS_ENTRY_EX(module, namespace_name, snake_name, short_name, methods, parent_module) \ - SW_INIT_CLASS_ENTRY_BASE(module, namespace_name, snake_name, short_name, methods, parent_module##_ce); \ +#define SW_INIT_CLASS_ENTRY_EX(module, namespace_name, snake_name, short_name, methods, parent_module) \ + SW_INIT_CLASS_ENTRY_BASE(module, namespace_name, snake_name, short_name, methods, parent_module##_ce); \ memcpy(&module##_handlers, &parent_module##_handlers, sizeof(zend_object_handlers)) -#define SW_INIT_CLASS_ENTRY_EX2(module, namespace_name, snake_name, short_name, methods, parent_module_ce, parent_module_handlers) \ - SW_INIT_CLASS_ENTRY_BASE(module, namespace_name, snake_name, short_name, methods, parent_module_ce); \ +#define SW_INIT_CLASS_ENTRY_EX2( \ + module, namespace_name, snake_name, short_name, methods, parent_module_ce, parent_module_handlers) \ + SW_INIT_CLASS_ENTRY_BASE(module, namespace_name, snake_name, short_name, methods, parent_module_ce); \ memcpy(&module##_handlers, parent_module_handlers, sizeof(zend_object_handlers)) // Data Object: no methods, no parent -#define SW_INIT_CLASS_ENTRY_DATA_OBJECT(module, namespace_name) \ - SW_INIT_CLASS_ENTRY_BASE(module, namespace_name, NULL, NULL, NULL, NULL); \ +#define SW_INIT_CLASS_ENTRY_DATA_OBJECT(module, namespace_name) \ + SW_INIT_CLASS_ENTRY_BASE(module, namespace_name, NULL, NULL, NULL, NULL); \ memcpy(&module##_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)) -#define SW_CLASS_ALIAS(name, module) do { \ - if (name) { \ - sw_zend_register_class_alias(ZEND_STRL(name), module##_ce); \ - } \ -} while (0) +#define SW_CLASS_ALIAS(name, module) \ + do { \ + if (name) { \ + sw_zend_register_class_alias(ZEND_STRL(name), module##_ce); \ + } \ + } while (0) -#define SW_CLASS_ALIAS_SHORT_NAME(short_name, module) do { \ - if (SWOOLE_G(use_shortname)) { \ - SW_CLASS_ALIAS(short_name, module); \ - } \ -} while (0) +#define SW_CLASS_ALIAS_SHORT_NAME(short_name, module) \ + do { \ + if (SWOOLE_G(use_shortname)) { \ + SW_CLASS_ALIAS(short_name, module); \ + } \ + } while (0) -#define SW_SET_CLASS_SERIALIZABLE(module, _serialize, _unserialize) \ - module##_ce->serialize = _serialize; \ +#define SW_SET_CLASS_SERIALIZABLE(module, _serialize, _unserialize) \ + module##_ce->serialize = _serialize; \ module##_ce->unserialize = _unserialize #define sw_zend_class_clone_deny NULL -#define SW_SET_CLASS_CLONEABLE(module, _clone_obj) \ - module##_handlers.clone_obj = _clone_obj +#define SW_SET_CLASS_CLONEABLE(module, _clone_obj) module##_handlers.clone_obj = _clone_obj -#define SW_SET_CLASS_UNSET_PROPERTY_HANDLER(module, _unset_property) \ - module##_handlers.unset_property = _unset_property +#define SW_SET_CLASS_UNSET_PROPERTY_HANDLER(module, _unset_property) module##_handlers.unset_property = _unset_property -#define SW_SET_CLASS_CREATE(module, _create_object) \ - module##_ce->create_object = _create_object +#define SW_SET_CLASS_CREATE(module, _create_object) module##_ce->create_object = _create_object -#define SW_SET_CLASS_DTOR(module, _dtor_obj) \ - module##_handlers.dtor_obj = _dtor_obj +#define SW_SET_CLASS_DTOR(module, _dtor_obj) module##_handlers.dtor_obj = _dtor_obj -#define SW_SET_CLASS_FREE(module, _free_obj) \ - module##_handlers.free_obj = _free_obj +#define SW_SET_CLASS_FREE(module, _free_obj) module##_handlers.free_obj = _free_obj -#define SW_SET_CLASS_CREATE_AND_FREE(module, _create_object, _free_obj) \ - SW_SET_CLASS_CREATE(module, _create_object); \ +#define SW_SET_CLASS_CREATE_AND_FREE(module, _create_object, _free_obj) \ + SW_SET_CLASS_CREATE(module, _create_object); \ SW_SET_CLASS_FREE(module, _free_obj) -#define SW_SET_CLASS_CUSTOM_OBJECT(module, _create_object, _free_obj, _struct, _std) \ - SW_SET_CLASS_CREATE_AND_FREE(module, _create_object, _free_obj); \ +#define SW_SET_CLASS_CUSTOM_OBJECT(module, _create_object, _free_obj, _struct, _std) \ + SW_SET_CLASS_CREATE_AND_FREE(module, _create_object, _free_obj); \ module##_handlers.offset = XtOffsetOf(_struct, _std) -#define SW_PREVENT_USER_DESTRUCT() do { \ - if (sw_unlikely(!(GC_FLAGS(Z_OBJ_P(ZEND_THIS)) & IS_OBJ_DESTRUCTOR_CALLED))) { \ - RETURN_NULL(); \ - } \ -} while (0) +#define SW_PREVENT_USER_DESTRUCT() \ + do { \ + if (sw_unlikely(!(GC_FLAGS(Z_OBJ_P(ZEND_THIS)) & IS_OBJ_DESTRUCTOR_CALLED))) { \ + RETURN_NULL(); \ + } \ + } while (0) -#define SW_FUNCTION_ALIAS(origin_function_table, origin, alias_function_table, alias) \ +#define SW_FUNCTION_ALIAS(origin_function_table, origin, alias_function_table, alias) \ sw_zend_register_function_alias(origin_function_table, ZEND_STRL(origin), alias_function_table, ZEND_STRL(alias)) -static sw_inline int sw_zend_register_function_alias -( - zend_array *origin_function_table, const char *origin, size_t origin_length, - zend_array *alias_function_table, const char *alias, size_t alias_length -) -{ +static sw_inline int sw_zend_register_function_alias(zend_array *origin_function_table, + const char *origin, + size_t origin_length, + zend_array *alias_function_table, + const char *alias, + size_t alias_length) { zend_string *lowercase_origin = zend_string_alloc(origin_length, 0); zend_str_tolower_copy(ZSTR_VAL(lowercase_origin), origin, origin_length); zend_function *origin_function = (zend_function *) zend_hash_find_ptr(origin_function_table, lowercase_origin); zend_string_release(lowercase_origin); - if (UNEXPECTED(!origin_function)) - { + if (UNEXPECTED(!origin_function)) { return FAILURE; } SW_ASSERT(origin_function->common.type == ZEND_INTERNAL_FUNCTION); char *_alias = (char *) emalloc(alias_length + 1); ((char *) memcpy(_alias, alias, alias_length))[alias_length] = '\0'; - zend_function_entry zfe[] = {{_alias, origin_function->internal_function.handler, ((zend_internal_arg_info *) origin_function->common.arg_info) - 1, origin_function->common.num_args, 0 }, PHP_FE_END}; - int ret = zend_register_functions(origin_function->common.scope, zfe, alias_function_table, origin_function->common.type); + zend_function_entry zfe[] = {{_alias, + origin_function->internal_function.handler, + ((zend_internal_arg_info *) origin_function->common.arg_info) - 1, + origin_function->common.num_args, + 0}, + PHP_FE_END}; + int ret = + zend_register_functions(origin_function->common.scope, zfe, alias_function_table, origin_function->common.type); efree(_alias); return ret; } -static sw_inline int sw_zend_register_class_alias(const char *name, size_t name_len, zend_class_entry *ce) -{ +static sw_inline int sw_zend_register_class_alias(const char *name, size_t name_len, zend_class_entry *ce) { zend_string *_name; - if (name[0] == '\\') - { + if (name[0] == '\\') { _name = zend_string_init(name, name_len, 1); zend_str_tolower_copy(ZSTR_VAL(_name), name + 1, name_len - 1); - } - else - { + } else { _name = zend_string_init(name, name_len, 1); zend_str_tolower_copy(ZSTR_VAL(_name), name, name_len); } @@ -762,8 +763,7 @@ static sw_inline int sw_zend_register_class_alias(const char *name, size_t name_ #if PHP_VERSION_ID < 70300 /* Allocates object type and zeros it, but not the properties. * Properties MUST be initialized using object_properties_init(). */ -static zend_always_inline void *zend_object_alloc(size_t obj_size, zend_class_entry *ce) -{ +static zend_always_inline void *zend_object_alloc(size_t obj_size, zend_class_entry *ce) { void *obj = emalloc(obj_size + zend_object_properties_size(ce)); /* Subtraction of sizeof(zval) is necessary, because zend_object_properties_size() may be * -sizeof(zval), if the object has no properties. */ @@ -772,17 +772,15 @@ static zend_always_inline void *zend_object_alloc(size_t obj_size, zend_class_en } #endif -static sw_inline zend_object *sw_zend_create_object(zend_class_entry *ce, zend_object_handlers *handlers) -{ - zend_object* object = (zend_object *) zend_object_alloc(sizeof(zend_object), ce); +static sw_inline zend_object *sw_zend_create_object(zend_class_entry *ce, zend_object_handlers *handlers) { + zend_object *object = (zend_object *) zend_object_alloc(sizeof(zend_object), ce); zend_object_std_init(object, ce); object_properties_init(object, ce); object->handlers = handlers; return object; } -static sw_inline zend_object* sw_zend_create_object_deny(zend_class_entry *ce) -{ +static sw_inline zend_object *sw_zend_create_object_deny(zend_class_entry *ce) { zend_object *object; object = zend_objects_new(ce); /* Initialize default properties */ @@ -799,32 +797,27 @@ static sw_inline zend_object* sw_zend_create_object_deny(zend_class_entry *ce) } #if PHP_VERSION_ID < 80000 -static sw_inline void sw_zend_class_unset_property_deny(zval *zobject, zval *zmember, void **cache_slot) -{ +static sw_inline void sw_zend_class_unset_property_deny(zval *zobject, zval *zmember, void **cache_slot) { zend_class_entry *ce = Z_OBJCE_P(zobject); - while (ce->parent) - { + while (ce->parent) { ce = ce->parent; } SW_ASSERT(ce->type == ZEND_INTERNAL_CLASS); - if (EXPECTED(zend_hash_find(&ce->properties_info, Z_STR_P(zmember)))) - { - zend_throw_error(NULL, "Property %s of class %s cannot be unset", Z_STRVAL_P(zmember), SW_Z_OBJCE_NAME_VAL_P(zobject)); + if (EXPECTED(zend_hash_find(&ce->properties_info, Z_STR_P(zmember)))) { + zend_throw_error( + NULL, "Property %s of class %s cannot be unset", Z_STRVAL_P(zmember), SW_Z_OBJCE_NAME_VAL_P(zobject)); return; } std_object_handlers.unset_property(zobject, zmember, cache_slot); } #else -static sw_inline void sw_zend_class_unset_property_deny(zend_object *object, zend_string *member, void **cache_slot) -{ +static sw_inline void sw_zend_class_unset_property_deny(zend_object *object, zend_string *member, void **cache_slot) { zend_class_entry *ce = object->ce; - while (ce->parent) - { + while (ce->parent) { ce = ce->parent; } SW_ASSERT(ce->type == ZEND_INTERNAL_CLASS); - if (EXPECTED(zend_hash_find(&ce->properties_info, member))) - { + if (EXPECTED(zend_hash_find(&ce->properties_info, member))) { zend_throw_error(NULL, "Property %s of class %s cannot be unset", ZSTR_VAL(member), ZSTR_VAL(object->ce->name)); return; } @@ -832,52 +825,45 @@ static sw_inline void sw_zend_class_unset_property_deny(zend_object *object, zen } #endif -static sw_inline zval* sw_zend_read_property(zend_class_entry *ce, zval *obj, const char *s, int len, int silent) -{ +static sw_inline zval *sw_zend_read_property(zend_class_entry *ce, zval *obj, const char *s, int len, int silent) { zval rv, *property = zend_read_property(ce, SW_Z8_OBJ_P(obj), s, len, silent, &rv); - if (UNEXPECTED(property == &EG(uninitialized_zval))) - { + if (UNEXPECTED(property == &EG(uninitialized_zval))) { zend_update_property_null(ce, SW_Z8_OBJ_P(obj), s, len); return zend_read_property(ce, SW_Z8_OBJ_P(obj), s, len, silent, &rv); } return property; } -static sw_inline void sw_zend_update_property_null_ex(zend_class_entry *scope, zval *object, zend_string *s) -{ +static sw_inline void sw_zend_update_property_null_ex(zend_class_entry *scope, zval *object, zend_string *s) { zval tmp; ZVAL_NULL(&tmp); zend_update_property_ex(scope, SW_Z8_OBJ_P(object), s, &tmp); } -static sw_inline zval* sw_zend_read_property_ex(zend_class_entry *ce, zval *obj, zend_string *s, int silent) -{ +static sw_inline zval *sw_zend_read_property_ex(zend_class_entry *ce, zval *obj, zend_string *s, int silent) { zval rv, *property = zend_read_property_ex(ce, SW_Z8_OBJ_P(obj), s, silent, &rv); - if (UNEXPECTED(property == &EG(uninitialized_zval))) - { + if (UNEXPECTED(property == &EG(uninitialized_zval))) { sw_zend_update_property_null_ex(ce, obj, s); return zend_read_property_ex(ce, SW_Z8_OBJ_P(obj), s, silent, &rv); } return property; } -static sw_inline zval* sw_zend_read_property_not_null(zend_class_entry *ce, zval *obj, const char *s, int len, int silent) -{ +static sw_inline zval *sw_zend_read_property_not_null( + zend_class_entry *ce, zval *obj, const char *s, int len, int silent) { zval rv, *property = zend_read_property(ce, SW_Z8_OBJ_P(obj), s, len, silent, &rv); zend_uchar type = Z_TYPE_P(property); return (type == IS_NULL || UNEXPECTED(type == IS_UNDEF)) ? NULL : property; } -static sw_inline zval* sw_zend_read_property_not_null_ex(zend_class_entry *ce, zval *obj, zend_string *s, int silent) -{ +static sw_inline zval *sw_zend_read_property_not_null_ex(zend_class_entry *ce, zval *obj, zend_string *s, int silent) { zval rv, *property = zend_read_property_ex(ce, SW_Z8_OBJ_P(obj), s, silent, &rv); zend_uchar type = Z_TYPE_P(property); return (type == IS_NULL || UNEXPECTED(type == IS_UNDEF)) ? NULL : property; } -static sw_inline zval *sw_zend_update_and_read_property_array(zend_class_entry *ce, zval *obj, const char *s, int len) -{ +static sw_inline zval *sw_zend_update_and_read_property_array(zend_class_entry *ce, zval *obj, const char *s, int len) { zval ztmp; array_init(&ztmp); zend_update_property(ce, SW_Z8_OBJ_P(obj), s, len, &ztmp); @@ -885,18 +871,14 @@ static sw_inline zval *sw_zend_update_and_read_property_array(zend_class_entry * return zend_read_property(ce, SW_Z8_OBJ_P(obj), s, len, 1, &ztmp); } -static sw_inline zval* sw_zend_read_and_convert_property_array(zend_class_entry *ce, zval *obj, const char *s, int len, int silent) -{ +static sw_inline zval *sw_zend_read_and_convert_property_array( + zend_class_entry *ce, zval *obj, const char *s, int len, int silent) { zval rv, *property = zend_read_property(ce, SW_Z8_OBJ_P(obj), s, len, silent, &rv); - if (Z_TYPE_P(property) != IS_ARRAY) - { + if (Z_TYPE_P(property) != IS_ARRAY) { // NOTICE: if user unset the property, zend_read_property will return uninitialized_zval instead of NULL pointer - if (UNEXPECTED(property == &EG(uninitialized_zval))) - { + if (UNEXPECTED(property == &EG(uninitialized_zval))) { property = sw_zend_update_and_read_property_array(ce, obj, s, len); - } - else - { + } else { zval_ptr_dtor(property); array_init(property); } @@ -905,38 +887,38 @@ static sw_inline zval* sw_zend_read_and_convert_property_array(zend_class_entry return property; } -#define SW_RETURN_PROPERTY(name) do { \ - RETURN_ZVAL(sw_zend_read_property(Z_OBJCE_P(ZEND_THIS), ZEND_THIS, ZEND_STRL(name), 0), 1, 0); \ -} while (0) +#define SW_RETURN_PROPERTY(name) \ + do { \ + RETURN_ZVAL(sw_zend_read_property(Z_OBJCE_P(ZEND_THIS), ZEND_THIS, ZEND_STRL(name), 0), 1, 0); \ + } while (0) -#define RETURN_SW_STRING(buf) do { \ - RETURN_STRINGL(buf->str, buf->length); \ -} while (0) +#define RETURN_SW_STRING(buf) \ + do { \ + RETURN_STRINGL(buf->str, buf->length); \ + } while (0) //----------------------------------Function API------------------------------------ /** * Notice (sw_zend_call_method_with_%u_params): If you don't want to check the return value, please set retval to NULL */ -#define sw_zend_call_method_with_0_params(zobj, obj_ce, fn_ptr_ptr, fn_name, retval) \ - zend_call_method_with_0_params(SW_Z8_OBJ_P(zobj), obj_ce, fn_ptr_ptr, fn_name, retval) +#define sw_zend_call_method_with_0_params(zobj, obj_ce, fn_ptr_ptr, fn_name, retval) \ + zend_call_method_with_0_params(SW_Z8_OBJ_P(zobj), obj_ce, fn_ptr_ptr, fn_name, retval) -#define sw_zend_call_method_with_1_params(zobj, obj_ce, fn_ptr_ptr, fn_name, retval, v1) \ - zend_call_method_with_1_params(SW_Z8_OBJ_P(zobj), obj_ce, fn_ptr_ptr, fn_name, retval, v1) +#define sw_zend_call_method_with_1_params(zobj, obj_ce, fn_ptr_ptr, fn_name, retval, v1) \ + zend_call_method_with_1_params(SW_Z8_OBJ_P(zobj), obj_ce, fn_ptr_ptr, fn_name, retval, v1) -#define sw_zend_call_method_with_2_params(zobj, obj_ce, fn_ptr_ptr, fn_name, retval, v1, v2) \ - zend_call_method_with_2_params(SW_Z8_OBJ_P(zobj), obj_ce, fn_ptr_ptr, fn_name, retval, v1, v2) +#define sw_zend_call_method_with_2_params(zobj, obj_ce, fn_ptr_ptr, fn_name, retval, v1, v2) \ + zend_call_method_with_2_params(SW_Z8_OBJ_P(zobj), obj_ce, fn_ptr_ptr, fn_name, retval, v1, v2) -static sw_inline int sw_zend_function_max_num_args(zend_function *function) -{ +static sw_inline int sw_zend_function_max_num_args(zend_function *function) { // https://github.com/php/php-src/commit/2646f7bcb98dcdd322ea21701c8bb101104ea619 // zend_function.common.num_args don't include the variadic argument anymore. return (function->common.fn_flags & ZEND_ACC_VARIADIC) ? UINT32_MAX : function->common.num_args; } // TODO: remove it after remove async modules -static sw_inline zend_bool sw_zend_is_callable(zval *callable, int check_flags, char **callable_name) -{ +static sw_inline zend_bool sw_zend_is_callable(zval *callable, int check_flags, char **callable_name) { zend_string *name; zend_bool ret = zend_is_callable(callable, check_flags, &name); *callable_name = estrndup(ZSTR_VAL(name), ZSTR_LEN(name)); @@ -944,8 +926,14 @@ static sw_inline zend_bool sw_zend_is_callable(zval *callable, int check_flags, return ret; } -static sw_inline zend_bool sw_zend_is_callable_at_frame(zval *zcallable, zval *zobject, zend_execute_data *frame, uint check_flags, char **callable_name, size_t *callable_name_len, zend_fcall_info_cache *fci_cache, char **error) -{ +static sw_inline zend_bool sw_zend_is_callable_at_frame(zval *zcallable, + zval *zobject, + zend_execute_data *frame, + uint check_flags, + char **callable_name, + size_t *callable_name_len, + zend_fcall_info_cache *fci_cache, + char **error) { zend_string *name; zend_bool ret; #if PHP_VERSION_ID < 80000 @@ -954,43 +942,43 @@ static sw_inline zend_bool sw_zend_is_callable_at_frame(zval *zcallable, zval *z ret = zend_is_callable_at_frame(zcallable, zobject ? Z_OBJ_P(zobject) : NULL, frame, check_flags, fci_cache, error); name = zend_get_callable_name_ex(zcallable, zobject ? Z_OBJ_P(zobject) : NULL); #endif - if (callable_name) - { + if (callable_name) { *callable_name = estrndup(ZSTR_VAL(name), ZSTR_LEN(name)); } - if (callable_name_len) - { + if (callable_name_len) { *callable_name_len = ZSTR_LEN(name); } zend_string_release(name); return ret; } -static sw_inline zend_bool sw_zend_is_callable_ex(zval *zcallable, zval *zobject, uint check_flags, char **callable_name, size_t *callable_name_len, zend_fcall_info_cache *fci_cache, char **error) -{ - return sw_zend_is_callable_at_frame(zcallable, zobject, NULL, check_flags, callable_name, callable_name_len, fci_cache, error); +static sw_inline zend_bool sw_zend_is_callable_ex(zval *zcallable, + zval *zobject, + uint check_flags, + char **callable_name, + size_t *callable_name_len, + zend_fcall_info_cache *fci_cache, + char **error) { + return sw_zend_is_callable_at_frame( + zcallable, zobject, NULL, check_flags, callable_name, callable_name_len, fci_cache, error); } /* this API can work well when retval is NULL */ -static sw_inline int sw_zend_call_function_ex(zval *function_name, zend_fcall_info_cache *fci_cache, uint32_t param_count, zval *params, zval *retval) -{ +static sw_inline int sw_zend_call_function_ex( + zval *function_name, zend_fcall_info_cache *fci_cache, uint32_t param_count, zval *params, zval *retval) { zend_fcall_info fci; zval _retval; int ret; fci.size = sizeof(fci); fci.object = NULL; - if (!fci_cache || !fci_cache->function_handler) - { - if (!function_name) - { + if (!fci_cache || !fci_cache->function_handler) { + if (!function_name) { php_swoole_fatal_error(E_WARNING, "Bad function"); return FAILURE; } ZVAL_COPY_VALUE(&fci.function_name, function_name); - } - else - { + } else { ZVAL_UNDEF(&fci.function_name); } fci.retval = retval ? retval : &_retval; @@ -1004,134 +992,107 @@ static sw_inline int sw_zend_call_function_ex(zval *function_name, zend_fcall_in ret = zend_call_function(&fci, fci_cache); - if (!retval) - { + if (!retval) { zval_ptr_dtor(&_retval); } return ret; } /* we must check for exception immediately if we don't have chances to go back to ZendVM (e.g event loop) */ -static sw_inline int sw_zend_call_function_ex2(zval *function_name, zend_fcall_info_cache *fci_cache, uint32_t param_count, zval *params, zval *retval) -{ +static sw_inline int sw_zend_call_function_ex2( + zval *function_name, zend_fcall_info_cache *fci_cache, uint32_t param_count, zval *params, zval *retval) { int ret = sw_zend_call_function_ex(function_name, fci_cache, param_count, params, retval); - if (UNEXPECTED(EG(exception))) - { + if (UNEXPECTED(EG(exception))) { zend_exception_error(EG(exception), E_ERROR); } return ret; } -static sw_inline int sw_zend_call_function_anyway(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) -{ +static sw_inline int sw_zend_call_function_anyway(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache) { zval retval; - zend_object* exception = EG(exception); - if (exception) - { + zend_object *exception = EG(exception); + if (exception) { EG(exception) = NULL; } - if (!fci->retval) - { + if (!fci->retval) { fci->retval = &retval; } int ret = zend_call_function(fci, fci_cache); - if (fci->retval == &retval) - { + if (fci->retval == &retval) { zval_ptr_dtor(&retval); } - if (exception) - { + if (exception) { EG(exception) = exception; } return ret; } -static sw_inline void sw_zend_fci_params_persist(zend_fcall_info *fci) -{ - if (fci->param_count > 0) - { +static sw_inline void sw_zend_fci_params_persist(zend_fcall_info *fci) { + if (fci->param_count > 0) { uint32_t i; zval *params = (zval *) ecalloc(fci->param_count, sizeof(zval)); - for (i = 0; i < fci->param_count; i++) - { + for (i = 0; i < fci->param_count; i++) { ZVAL_COPY(¶ms[i], &fci->params[i]); } fci->params = params; } } -static sw_inline void sw_zend_fci_params_discard(zend_fcall_info *fci) -{ - if (fci->param_count > 0) - { +static sw_inline void sw_zend_fci_params_discard(zend_fcall_info *fci) { + if (fci->param_count > 0) { uint32_t i; - for (i = 0; i < fci->param_count; i++) - { + for (i = 0; i < fci->param_count; i++) { zval_ptr_dtor(&fci->params[i]); } efree(fci->params); } } -static sw_inline void sw_zend_fci_cache_persist(zend_fcall_info_cache *fci_cache) -{ - if (fci_cache->object) - { +static sw_inline void sw_zend_fci_cache_persist(zend_fcall_info_cache *fci_cache) { + if (fci_cache->object) { GC_ADDREF(fci_cache->object); } - if (fci_cache->function_handler->op_array.fn_flags & ZEND_ACC_CLOSURE) - { + if (fci_cache->function_handler->op_array.fn_flags & ZEND_ACC_CLOSURE) { GC_ADDREF(ZEND_CLOSURE_OBJECT(fci_cache->function_handler)); } } -static sw_inline void sw_zend_fci_cache_discard(zend_fcall_info_cache *fci_cache) -{ - if (fci_cache->object) - { +static sw_inline void sw_zend_fci_cache_discard(zend_fcall_info_cache *fci_cache) { + if (fci_cache->object) { OBJ_RELEASE(fci_cache->object); } - if (fci_cache->function_handler->op_array.fn_flags & ZEND_ACC_CLOSURE) - { + if (fci_cache->function_handler->op_array.fn_flags & ZEND_ACC_CLOSURE) { OBJ_RELEASE(ZEND_CLOSURE_OBJECT(fci_cache->function_handler)); } } /* use void* to match some C callback function pointers */ -static sw_inline void sw_zend_fci_cache_free(void* fci_cache) -{ +static sw_inline void sw_zend_fci_cache_free(void *fci_cache) { sw_zend_fci_cache_discard((zend_fcall_info_cache *) fci_cache); efree((zend_fcall_info_cache *) fci_cache); } //----------------------------------Misc API------------------------------------ -static sw_inline int php_swoole_check_reactor() -{ - if (SWOOLE_G(req_status) == PHP_SWOOLE_RSHUTDOWN_BEGIN) - { +static sw_inline int php_swoole_check_reactor() { + if (SWOOLE_G(req_status) == PHP_SWOOLE_RSHUTDOWN_BEGIN) { return -1; } - if (sw_unlikely(!sw_reactor())) - { + if (sw_unlikely(!sw_reactor())) { return php_swoole_reactor_init() == SW_OK ? 1 : -1; - } - else - { + } else { return 0; } } -static sw_inline char* php_swoole_format_date(char *format, size_t format_len, time_t ts, int localtime) -{ +static sw_inline char *php_swoole_format_date(char *format, size_t format_len, time_t ts, int localtime) { zend_string *time = php_format_date(format, format_len, ts, localtime); char *return_str = estrndup(ZSTR_VAL(time), ZSTR_LEN(time)); zend_string_release(time); return return_str; } -static sw_inline char* php_swoole_url_encode(const char *value, size_t value_len, int* exten) -{ +static sw_inline char *php_swoole_url_encode(const char *value, size_t value_len, int *exten) { zend_string *str = php_url_encode(value, value_len); *exten = ZSTR_LEN(str); char *return_str = estrndup(ZSTR_VAL(str), ZSTR_LEN(str)); @@ -1139,26 +1100,21 @@ static sw_inline char* php_swoole_url_encode(const char *value, size_t value_len return return_str; } -static sw_inline char* php_swoole_http_build_query(zval *zdata, size_t *length, smart_str *formstr) -{ +static sw_inline char *php_swoole_http_build_query(zval *zdata, size_t *length, smart_str *formstr) { #if PHP_VERSION_ID < 80000 - if (php_url_encode_hash_ex(HASH_OF(zdata), formstr, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, (int) PHP_QUERY_RFC1738) == FAILURE) - { + if (php_url_encode_hash_ex( + HASH_OF(zdata), formstr, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, (int) PHP_QUERY_RFC1738) == FAILURE) { #else if (HASH_OF(zdata)) { php_url_encode_hash_ex(HASH_OF(zdata), formstr, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, (int) PHP_QUERY_RFC1738); - } - else - { + } else { #endif - if (formstr->s) - { + if (formstr->s) { smart_str_free(formstr); } return NULL; } - if (!formstr->s) - { + if (!formstr->s) { return NULL; } smart_str_0(formstr); diff --git a/ext-src/swoole_event.cc b/ext-src/swoole_event.cc index 03186ee67d5..10770d712e0 100644 --- a/ext-src/swoole_event.cc +++ b/ext-src/swoole_event.cc @@ -260,22 +260,9 @@ int php_swoole_reactor_init() { } void php_swoole_event_wait() { - if (PG(last_error_message)) { - switch (PG(last_error_type)) { - case E_ERROR: - case E_CORE_ERROR: - case E_USER_ERROR: - case E_COMPILE_ERROR: - return; - default: - break; - } - } - - if (!sw_reactor()) { + if (php_swoole_is_fatal_error() || !sw_reactor()) { return; } - #ifdef HAVE_SIGNALFD if (sw_reactor()->check_signalfd) { swSignalfd_setup(sw_reactor()); diff --git a/tools/next-version.php b/tools/next-version.php index 7db439bfccb..2dbd6a8a672 100755 --- a/tools/next-version.php +++ b/tools/next-version.php @@ -22,7 +22,8 @@ function getVersion() return $versoin; } - function getVersionId() { + function getVersionId() + { return intval(sprintf('%d%02d%02d', $this->major, $this->minor, $this->release)); } } @@ -63,10 +64,14 @@ function getVersionId() { $next->minor = 0; $next->release = 0; $next->extra = 'dev'; +} else { + exit("wrong version type"); } ob_start(); -include __DIR__.'/templates/version.tpl.h'; +include __DIR__ . '/templates/version.tpl.h'; file_put_contents($kernel_version_file, ob_get_clean()); -file_put_contents($cmake_file, preg_replace('#set\(SWOOLE_VERSION\s+[0-9\.\-a-z]+\)#i', 'set(SWOOLE_VERSION '.$next->getVersion().')', file_get_contents($cmake_file))); +file_put_contents($cmake_file, + preg_replace('#set\(SWOOLE_VERSION\s+[0-9\.\-a-z]+\)#i', 'set(SWOOLE_VERSION ' . $next->getVersion() . ')', + file_get_contents($cmake_file))); From 804ef9d0921d764f0506ba4baf433fee4fd19311 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Fri, 19 Feb 2021 03:09:48 +0000 Subject: [PATCH 056/936] ARM 64 build update proposal. (#4057) --- include/swoole_atomic.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/swoole_atomic.h b/include/swoole_atomic.h index 8349d22bf36..fa64de55eb2 100644 --- a/include/swoole_atomic.h +++ b/include/swoole_atomic.h @@ -20,12 +20,12 @@ typedef volatile int32_t sw_atomic_int32_t; typedef volatile uint32_t sw_atomic_uint32_t; -#ifdef __x86_64__ +#if defined(__x86_64__) || defined(__aarch64__) typedef volatile int64_t sw_atomic_int64_t; typedef volatile uint64_t sw_atomic_uint64_t; #endif -#ifdef __x86_64__ +#if defined(__x86_64__) || defined(__aarch64__) typedef sw_atomic_int64_t sw_atomic_long_t; typedef sw_atomic_uint64_t sw_atomic_ulong_t; #else @@ -46,6 +46,8 @@ typedef sw_atomic_uint32_t sw_atomic_t; #define sw_atomic_cpu_pause() __asm__ __volatile__("NOP"); #elif defined(__x86_64__) #define sw_atomic_cpu_pause() __asm__ __volatile__("pause") +#elif defined(__aarch64__) +#define sw_atomic_cpu_pause() __asm__ __volatile__("yield") #else #define sw_atomic_cpu_pause() #endif From 6672e5444d8c416a75552324438c20c466f3c641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Fri, 19 Feb 2021 16:22:55 +0800 Subject: [PATCH 057/936] optimize code (#4062) * optimize code * fix tests * fix tests[2] * fix tests[3] * fix tests[4] --- .github/workflows/lib.yml | 12 ++---------- core-tests/samples/s1.cc | 8 ++++---- core-tests/src/server/http.cpp | 6 +++--- ext-src/swoole_server.cc | 13 ++++++------- ext-src/swoole_server_port.cc | 2 +- include/swoole_server.h | 13 ++++++++++++- src/server/manager.cc | 5 ----- src/server/master.cc | 3 +-- src/server/task_worker.cc | 4 ---- 9 files changed, 29 insertions(+), 37 deletions(-) diff --git a/.github/workflows/lib.yml b/.github/workflows/lib.yml index fcf2009fdda..068be733617 100644 --- a/.github/workflows/lib.yml +++ b/.github/workflows/lib.yml @@ -23,22 +23,14 @@ jobs: - uses: actions/checkout@v1 - name: install dependencies - run: sudo apt update -y && sudo apt install -y googletest libgtest-dev redis-server libboost-stacktrace-dev && - cd /usr/src/googletest/googletest && - sudo mkdir build && - cd build && - sudo cmake .. && - sudo make -j$(sysctl -n hw.ncpu) && - sudo make install && - cd - && - sudo rm -rf /usr/src/googletest/googletest/build + run: sudo apt update -y && sudo apt install -y googletest libgtest-dev redis-server libboost-stacktrace-dev libbrotli-dev - name: configure run: phpize && ./configure --enable-sockets --enable-mysqlnd --enable-http2 --enable-openssl - name: make run: cmake . -DCODE_COVERAGE=ON && - make VERBOSE=1 -j$(sysctl -n hw.ncpu) && + make VERBOSE=1 -j && sudo make install - name: make test diff --git a/core-tests/samples/s1.cc b/core-tests/samples/s1.cc index 828da82eda5..a9fa1dc7dbe 100644 --- a/core-tests/samples/s1.cc +++ b/core-tests/samples/s1.cc @@ -1,10 +1,10 @@ #include "swoole.h" #include "swoole_api.h" -#include "client.h" +#include "swoole_client.h" #include "swoole_server.h" -#include "coroutine.h" -#include "coroutine_socket.h" -#include "coroutine_system.h" +#include "swoole_coroutine.h" +#include "swoole_coroutine_socket.h" +#include "swoole_coroutine_system.h" #include diff --git a/core-tests/src/server/http.cpp b/core-tests/src/server/http.cpp index 84c003e0509..fbb10b2d15d 100644 --- a/core-tests/src/server/http.cpp +++ b/core-tests/src/server/http.cpp @@ -242,7 +242,7 @@ static void websocket_test(int server_port, const char *data, size_t length) { TEST(http_server, websocket_small) { test_run_server([](swServer *serv) { swSignal_none(); - websocket_test(serv->get_primary_port()->port, SW_STRL("hello world, swoole is best!")); + websocket_test(serv->get_primary_port()->get_port(), SW_STRL("hello world, swoole is best!")); kill(getpid(), SIGTERM); }); } @@ -253,7 +253,7 @@ TEST(http_server, websocket_medium) { swString str(8192); str.repeat("A", 1, 8192); - websocket_test(serv->get_primary_port()->port, str.value(), str.get_length()); + websocket_test(serv->get_primary_port()->get_port(), str.value(), str.get_length()); kill(getpid(), SIGTERM); }); @@ -265,7 +265,7 @@ TEST(http_server, websocket_big) { swString str(128 * 1024); str.repeat("A", 1, str.capacity() - 1); - websocket_test(serv->get_primary_port()->port, str.value(), str.get_length()); + websocket_test(serv->get_primary_port()->get_port(), str.value(), str.get_length()); kill(getpid(), SIGTERM); }); diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 031df5f08c8..13b5043a251 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -996,10 +996,10 @@ static zval *php_swoole_server_add_port(ServerObject *server_object, ListenPort /* linked */ port->ptr = property; - zend_update_property_string(swoole_server_port_ce, SW_Z8_OBJ_P(zport), ZEND_STRL("host"), port->host.c_str()); - zend_update_property_long(swoole_server_port_ce, SW_Z8_OBJ_P(zport), ZEND_STRL("port"), port->port); - zend_update_property_long(swoole_server_port_ce, SW_Z8_OBJ_P(zport), ZEND_STRL("type"), port->type); - zend_update_property_long(swoole_server_port_ce, SW_Z8_OBJ_P(zport), ZEND_STRL("sock"), port->socket->fd); + zend_update_property_string(swoole_server_port_ce, SW_Z8_OBJ_P(zport), ZEND_STRL("host"), port->get_host()); + zend_update_property_long(swoole_server_port_ce, SW_Z8_OBJ_P(zport), ZEND_STRL("port"), port->get_port()); + zend_update_property_long(swoole_server_port_ce, SW_Z8_OBJ_P(zport), ZEND_STRL("type"), port->get_type()); + zend_update_property_long(swoole_server_port_ce, SW_Z8_OBJ_P(zport), ZEND_STRL("sock"), port->get_fd()); do { zval *zserv = (zval *) serv->private_data_2; @@ -3674,7 +3674,7 @@ static PHP_METHOD(swoole_server, getSocket) { } ListenPort *lp = serv->get_port(port); - php_socket *socket_object = php_swoole_convert_to_socket(lp->socket->fd); + php_socket *socket_object = php_swoole_convert_to_socket(lp->get_fd()); if (!socket_object) { RETURN_FALSE; @@ -4023,8 +4023,7 @@ static PHP_METHOD(swoole_connection_iterator, valid) { continue; } #endif - if (iterator->port && - (iterator->port->socket_fd < 0 || conn->server_fd != iterator->port->socket_fd)) { + if (iterator->port && (iterator->port->get_fd() < 0 || conn->server_fd != iterator->port->get_fd())) { continue; } iterator->session_id = conn->session_id; diff --git a/ext-src/swoole_server_port.cc b/ext-src/swoole_server_port.cc index ddf8d936154..6b1bc99d450 100644 --- a/ext-src/swoole_server_port.cc +++ b/ext-src/swoole_server_port.cc @@ -723,7 +723,7 @@ static PHP_METHOD(swoole_server_port, getCallback) { #ifdef SWOOLE_SOCKETS_SUPPORT static PHP_METHOD(swoole_server_port, getSocket) { ListenPort *port = php_swoole_server_port_get_and_check_ptr(ZEND_THIS); - php_socket *socket_object = php_swoole_convert_to_socket(port->socket->fd); + php_socket *socket_object = php_swoole_convert_to_socket(port->get_fd()); if (!socket_object) { RETURN_FALSE; } diff --git a/include/swoole_server.h b/include/swoole_server.h index bf895329ce7..aa867591d9c 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -277,7 +277,6 @@ struct ListenPort { uint8_t ssl = 0; std::string host; int port = 0; - int socket_fd = 0; network::Socket *socket = nullptr; pthread_t thread_id = 0; @@ -407,6 +406,18 @@ struct ListenPort { inline network::Socket *get_socket() { return socket; } + int get_port() { + return port; + } + const char *get_host() { + return host.c_str(); + } + enum swSocket_type get_type() { + return type; + } + int get_fd() { + return socket ? socket->fd : -1; + } }; struct ServerGS { diff --git a/src/server/manager.cc b/src/server/manager.cc index 3c6b06cdeae..86246ec4f22 100644 --- a/src/server/manager.cc +++ b/src/server/manager.cc @@ -148,7 +148,6 @@ int Server::start_manager_process() { swError("master process is not running"); return SW_ERR; } - close_port(true); pid_t pid; @@ -637,10 +636,6 @@ pid_t Server::spawn_user_worker(Worker *worker) { SwooleG.process_id = worker->id; SwooleWG.worker = worker; worker->pid = getpid(); - // close tcp listen socket - if (is_base_mode()) { - close_port(true); - } onUserWorkerStart(this, worker); exit(0); } diff --git a/src/server/master.cc b/src/server/master.cc index b7df715c12d..663fa4d1a90 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -717,7 +717,7 @@ int Server::create() { // Max Connections uint32_t minimum_connection = (worker_num + task_worker_num) * 2 + 32; if (ports.size() > 0) { - minimum_connection += ports.back()->socket_fd; + minimum_connection += ports.back()->get_fd(); } if (max_connection < minimum_connection) { max_connection = SwooleG.max_sockets; @@ -1536,7 +1536,6 @@ ListenPort *Server::add_port(enum swSocket_type type, const char *host, int port ls->socket->info.assign(ls->type, ls->host, ls->port); check_port_type(ls); ptr.release(); - ls->socket_fd = ls->socket->fd; ports.push_back(ls); return ls; } diff --git a/src/server/task_worker.cc b/src/server/task_worker.cc index 08ac1d748b0..1ef7a9d27f3 100644 --- a/src/server/task_worker.cc +++ b/src/server/task_worker.cc @@ -134,10 +134,6 @@ static void TaskWorker_onStart(ProcessPool *pool, int worker_id) { Server *serv = (Server *) pool->ptr; SwooleG.process_id = worker_id; - if (serv->is_base_mode()) { - serv->close_port(true); - } - /** * Make the task worker support asynchronous */ From 0e855e7a090e8e30fec5842d2a8da878d353c098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Sat, 20 Feb 2021 20:18:54 +0800 Subject: [PATCH 058/936] optimize callback name, allow to set open_http_protocol with Server (#4063) * optimize callback name, allow to set open_http_protocol with Server * optimize code, add test * fix tests * optimize code * optimize code [2] * fix * fix 2 * fix 3 * fix 4, optimize code * fix tests * fix tests [2] --- ext-src/php_swoole.h | 2 + ext-src/php_swoole_server.h | 86 ++++- ext-src/swoole_http_server.cc | 16 +- ext-src/swoole_redis_server.cc | 58 +--- ext-src/swoole_server.cc | 422 ++++++++++++------------ ext-src/swoole_server_port.cc | 26 +- include/swoole.h | 5 +- tests/swoole_server/check_callback.phpt | 83 +++++ tests/swoole_server/http_protocol.phpt | 1 + 9 files changed, 405 insertions(+), 294 deletions(-) create mode 100644 tests/swoole_server/check_callback.phpt diff --git a/ext-src/php_swoole.h b/ext-src/php_swoole.h index a817aad5612..51f44f565ef 100644 --- a/ext-src/php_swoole.h +++ b/ext-src/php_swoole.h @@ -171,6 +171,8 @@ extern zend_class_entry *swoole_socket_coro_ce; extern zend_class_entry *swoole_client_ce; extern zend_class_entry *swoole_server_ce; extern zend_object_handlers swoole_server_handlers; +extern zend_class_entry *swoole_redis_server_ce; +extern zend_object_handlers swoole_redis_server_handlers; extern zend_class_entry *swoole_connection_iterator_ce; extern zend_class_entry *swoole_process_ce; extern zend_class_entry *swoole_http_server_ce; diff --git a/ext-src/php_swoole_server.h b/ext-src/php_swoole_server.h index 32b49f72652..c54c3d769c8 100644 --- a/ext-src/php_swoole_server.h +++ b/ext-src/php_swoole_server.h @@ -21,6 +21,10 @@ #include "php_swoole_cxx.h" #include "swoole_server.h" +#include +#include +#include + //-------------------------------------------------------- enum php_swoole_server_callback_type { SW_SERVER_CB_onStart, // master @@ -54,30 +58,90 @@ enum php_swoole_server_port_callback_type { #define PHP_SWOOLE_SERVER_CALLBACK_NUM (SW_SERVER_CB_onPipeMessage + 1) #define PHP_SWOOLE_SERVER_PORT_CALLBACK_NUM (SW_SERVER_CB_onBufferEmpty + 1) -struct php_swoole_server_port_property { +namespace swoole { +struct TaskCo; + +struct ServerPortProperty { zval *callbacks[PHP_SWOOLE_SERVER_PORT_CALLBACK_NUM]; zend_fcall_info_cache *caches[PHP_SWOOLE_SERVER_PORT_CALLBACK_NUM]; zval _callbacks[PHP_SWOOLE_SERVER_PORT_CALLBACK_NUM]; - swServer *serv; - swListenPort *port; + Server *serv; + ListenPort *port; zval *zsetting; }; +struct ServerProperty { + std::vector ports; + std::vector user_processes; + ServerPortProperty *primary_port; + zend_fcall_info_cache *callbacks[PHP_SWOOLE_SERVER_CALLBACK_NUM]; + std::unordered_map task_callbacks; + std::unordered_map task_coroutine_map; + std::unordered_map *> send_coroutine_map; +}; + +struct ServerObject { + Server *serv; + ServerProperty *property; + zend_object std; + + zend_class_entry *get_ce() { + return Z_OBJCE_P(get_object()); + } + + zval *get_object() { + return (zval *) serv->private_data_2; + } + + bool isset_callback(ListenPort *port, int event_type) { + ServerPortProperty *port_property = (ServerPortProperty *) port->ptr; + return (port_property->callbacks[event_type] || property->primary_port->callbacks[event_type]); + } + + zend_bool is_websocket_server() { + return instanceof_function(get_ce(), swoole_websocket_server_ce); + } + + zend_bool is_http_server() { + return instanceof_function(get_ce(), swoole_http_server_ce); + } + + zend_bool is_redis_server() { + return instanceof_function(get_ce(), swoole_redis_server_ce); + } + + void register_callback(); + void on_before_start(); +}; + +struct TaskCo { + FutureTask context; + int *list; + uint32_t count; + zval *result; + TimerNode *timer; + ServerObject *server_object; +}; + +} // namespace swoole + void php_swoole_server_register_callbacks(swServer *serv); zend_fcall_info_cache *php_swoole_server_get_fci_cache(swServer *serv, int server_fd, int event_type); int php_swoole_create_dir(const char *path, size_t length); void php_swoole_server_before_start(swServer *serv, zval *zobject); +bool php_swoole_server_isset_callback(swServer *serv, swListenPort *port, int event_type); void php_swoole_http_server_init_global_variant(); void php_swoole_server_send_yield(swServer *serv, swoole::SessionId sesion_id, zval *zdata, zval *return_value); void php_swoole_get_recv_data(swServer *serv, zval *zdata, swRecvData *req); -void php_swoole_onConnect(swServer *, swDataHead *); -int php_swoole_onReceive(swServer *, swRecvData *); -int php_swoole_http_onReceive(swServer *, swRecvData *); -void php_swoole_http_onClose(swServer *, swDataHead *); -int php_swoole_onPacket(swServer *, swRecvData *); -void php_swoole_onClose(swServer *, swDataHead *); -void php_swoole_onBufferFull(swServer *, swDataHead *); -void php_swoole_onBufferEmpty(swServer *, swDataHead *); +void php_swoole_server_onConnect(swServer *, swDataHead *); +int php_swoole_server_onReceive(swServer *, swRecvData *); +int php_swoole_http_server_onReceive(swServer *, swRecvData *); +int php_swoole_redis_server_onReceive(swServer *serv, swRecvData *req); +void php_swoole_http_server_onClose(swServer *, swDataHead *); +int php_swoole_server_onPacket(swServer *, swRecvData *); +void php_swoole_server_onClose(swServer *, swDataHead *); +void php_swoole_server_onBufferFull(swServer *, swDataHead *); +void php_swoole_server_onBufferEmpty(swServer *, swDataHead *); swServer *php_swoole_server_get_and_check_server(zval *zobject); void php_swoole_server_port_deref(zend_object *object); diff --git a/ext-src/swoole_http_server.cc b/ext-src/swoole_http_server.cc index 3bf976b6450..8e3d9e48e85 100644 --- a/ext-src/swoole_http_server.cc +++ b/ext-src/swoole_http_server.cc @@ -38,7 +38,7 @@ static bool http_context_send_data(http_context *ctx, const char *data, size_t l static bool http_context_sendfile(http_context *ctx, const char *file, uint32_t l_file, off_t offset, size_t length); static bool http_context_disconnect(http_context *ctx); -int php_swoole_http_onReceive(Server *serv, RecvData *req) { +int php_swoole_http_server_onReceive(Server *serv, RecvData *req) { SessionId session_id = req->info.fd; int server_fd = req->info.server_fd; @@ -50,8 +50,14 @@ int php_swoole_http_onReceive(Server *serv, RecvData *req) { ListenPort *port = serv->get_port_by_server_fd(server_fd); // other server port - if (!port->open_http_protocol) { - return php_swoole_onReceive(serv, req); + if (!port->open_http_protocol || !php_swoole_server_isset_callback(serv, port, SW_SERVER_CB_onRequest)) { + SW_LOOP { + if (port->open_websocket_protocol && php_swoole_server_isset_callback(serv, port, SW_SERVER_CB_onMessage)) { + break; + } else { + return php_swoole_server_onReceive(serv, req); + } + } } // websocket client if (conn->websocket_status == WEBSOCKET_STATUS_ACTIVE) { @@ -142,12 +148,12 @@ int php_swoole_http_onReceive(Server *serv, RecvData *req) { return SW_OK; } -void php_swoole_http_onClose(Server *serv, DataHead *ev) { +void php_swoole_http_server_onClose(Server *serv, DataHead *ev) { Connection *conn = serv->get_connection_by_session_id(ev->fd); if (!conn) { return; } - php_swoole_onClose(serv, ev); + php_swoole_server_onClose(serv, ev); #ifdef SW_USE_HTTP2 if (conn->http2_stream) { swoole_http2_server_session_free(conn); diff --git a/ext-src/swoole_redis_server.cc b/ext-src/swoole_redis_server.cc index 6de5c23669f..a71ab622835 100644 --- a/ext-src/swoole_redis_server.cc +++ b/ext-src/swoole_redis_server.cc @@ -24,9 +24,13 @@ BEGIN_EXTERN_C() #include "ext/standard/php_string.h" END_EXTERN_C() +using swoole::Server; +using swoole::RecvData; +using swoole::ListenPort; +using swoole::Connection; -static zend_class_entry *swoole_redis_server_ce; -static zend_object_handlers swoole_redis_server_handlers; +zend_class_entry *swoole_redis_server_ce; +zend_object_handlers swoole_redis_server_handlers; static std::unordered_map redis_handlers; @@ -38,9 +42,6 @@ static PHP_METHOD(swoole_redis_server, format); SW_EXTERN_C_END // clang-format off -ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_server_start, 0, 0, 0) -ZEND_END_ARG_INFO() - ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_server_setHandler, 0, 0, 2) ZEND_ARG_INFO(0, command) ZEND_ARG_CALLABLE_INFO(0, callback, 0) @@ -57,7 +58,6 @@ ZEND_END_ARG_INFO() const zend_function_entry swoole_redis_server_methods[] = { - PHP_ME(swoole_redis_server, start, arginfo_swoole_redis_server_start, ZEND_ACC_PUBLIC) PHP_ME(swoole_redis_server, setHandler, arginfo_swoole_redis_server_setHandler, ZEND_ACC_PUBLIC) PHP_ME(swoole_redis_server, getHandler, arginfo_swoole_redis_server_getHandler, ZEND_ACC_PUBLIC) PHP_ME(swoole_redis_server, format, arginfo_swoole_redis_server_format, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) @@ -92,18 +92,18 @@ void php_swoole_redis_server_rshutdown() { redis_handlers.clear(); } -static int redis_onReceive(swServer *serv, swRecvData *req) { +int php_swoole_redis_server_onReceive(Server *serv, RecvData *req) { int fd = req->info.fd; - swConnection *conn = serv->get_connection_by_session_id(fd); + Connection *conn = serv->get_connection_by_session_id(fd); if (!conn) { swWarn("connection[%d] is closed", fd); return SW_ERR; } - swListenPort *port = serv->get_port_by_fd(conn->fd); + ListenPort *port = serv->get_port_by_fd(conn->fd); // other server port if (!port->open_redis_protocol) { - return php_swoole_onReceive(serv, req); + return php_swoole_server_onReceive(serv, req); } zval zdata; @@ -206,44 +206,6 @@ static int redis_onReceive(swServer *serv, swRecvData *req) { return SW_OK; } -static PHP_METHOD(swoole_redis_server, start) { - swServer *serv = php_swoole_server_get_and_check_server(ZEND_THIS); - zval *zserv = ZEND_THIS; - - if (serv->is_started()) { - php_swoole_error(E_WARNING, "server is running, unable to execute %s->start", SW_Z_OBJCE_NAME_VAL_P(zserv)); - RETURN_FALSE; - } - - php_swoole_server_register_callbacks(serv); - - serv->onReceive = redis_onReceive; - - zval *zsetting = sw_zend_read_and_convert_property_array(swoole_server_ce, zserv, ZEND_STRL("setting"), 0); - - add_assoc_bool(zsetting, "open_http_protocol", 0); - add_assoc_bool(zsetting, "open_mqtt_protocol", 0); - add_assoc_bool(zsetting, "open_eof_check", 0); - add_assoc_bool(zsetting, "open_length_check", 0); - add_assoc_bool(zsetting, "open_redis_protocol", 0); - - auto primary_port = serv->get_primary_port(); - - primary_port->open_http_protocol = 0; - primary_port->open_mqtt_protocol = 0; - primary_port->open_eof_check = 0; - primary_port->open_length_check = 0; - primary_port->open_redis_protocol = 1; - - php_swoole_server_before_start(serv, zserv); - - if (serv->start() < 0) { - php_swoole_fatal_error(E_ERROR, "server failed to start. Error: %s", sw_error); - } - - RETURN_TRUE; -} - static PHP_METHOD(swoole_redis_server, setHandler) { char *command; size_t command_len; diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 13b5043a251..73fefd4222d 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -25,30 +25,8 @@ #include #endif -#include -#include -#include - using namespace swoole; -struct TaskCo; - -struct ServerProperty { - std::vector ports; - std::vector user_processes; - php_swoole_server_port_property *primary_port; - zend_fcall_info_cache *callbacks[PHP_SWOOLE_SERVER_CALLBACK_NUM]; - std::unordered_map task_callbacks; - std::unordered_map task_coroutine_map; - std::unordered_map *> send_coroutine_map; -}; - -struct ServerObject { - Server *serv; - ServerProperty *property; - zend_object std; -}; - struct ConnectionIterator { int current_fd; SessionId session_id; @@ -57,15 +35,6 @@ struct ConnectionIterator { int index; }; -struct TaskCo { - FutureTask context; - int *list; - uint32_t count; - zval *result; - TimerNode *timer; - ServerObject *server_object; -}; - struct ServerEvent { enum php_swoole_server_callback_type type; std::string name; @@ -94,19 +63,19 @@ static int php_swoole_task_finish(Server *serv, zval *zdata, EventData *current_ static void php_swoole_onPipeMessage(Server *serv, EventData *req); static void php_swoole_onStart(Server *); static void php_swoole_onShutdown(Server *); -static void php_swoole_onWorkerStart(Server *, int worker_id); -static void php_swoole_onBeforeReload(Server *serv); -static void php_swoole_onAfterReload(Server *serv); -static void php_swoole_onWorkerStop(Server *, int worker_id); -static void php_swoole_onWorkerExit(Server *serv, int worker_id); +static void php_swoole_server_onWorkerStart(Server *, int worker_id); +static void php_swoole_server_onBeforeReload(Server *serv); +static void php_swoole_server_onAfterReload(Server *serv); +static void php_swoole_server_onWorkerStop(Server *, int worker_id); +static void php_swoole_server_onWorkerExit(Server *serv, int worker_id); static void php_swoole_onUserWorkerStart(Server *serv, Worker *worker); -static int php_swoole_onTask(Server *, EventData *task); -static int php_swoole_onFinish(Server *, EventData *task); -static void php_swoole_onWorkerError(Server *serv, int worker_id, const ExitStatus &exit_status); -static void php_swoole_onManagerStart(Server *serv); -static void php_swoole_onManagerStop(Server *serv); +static int php_swoole_server_onTask(Server *, EventData *task); +static int php_swoole_server_onFinish(Server *, EventData *task); +static void php_swoole_server_onWorkerError(Server *serv, int worker_id, const ExitStatus &exit_status); +static void php_swoole_server_onManagerStart(Server *serv); +static void php_swoole_server_onManagerStop(Server *serv); +static void php_swoole_server_onSendTimeout(Timer *timer, TimerNode *tnode); -static void php_swoole_onSendTimeout(Timer *timer, TimerNode *tnode); static enum swReturn_code php_swoole_server_send_resume(Server *serv, FutureTask *context, SessionId fd); static void php_swoole_task_onTimeout(Timer *timer, TimerNode *tnode); static int php_swoole_server_dispatch_func(Server *serv, Connection *conn, SendData *data); @@ -123,17 +92,6 @@ static void php_swoole_server_worker_add_buffer_len(Server *serv, DataHead *info static void php_swoole_server_worker_move_buffer(Server *serv, PipeBuffer *buffer); static size_t php_swoole_server_worker_get_packet(Server *serv, EventData *req, char **data_ptr); -static inline zend_bool php_swoole_server_isset_callback(ServerObject *server_object, - ListenPort *port, - int event_type) { - php_swoole_server_port_property *property = (php_swoole_server_port_property *) port->ptr; - if (property->callbacks[event_type] || server_object->property->primary_port->callbacks[event_type]) { - return true; - } else { - return false; - } -} - void php_swoole_server_rshutdown() { if (!sw_server()) { return; @@ -201,6 +159,11 @@ Server *php_swoole_server_get_and_check_server(zval *zobject) { return serv; } +bool php_swoole_server_isset_callback(Server *serv, ListenPort *port, int event_type) { + ServerObject *server_object = server_fetch_object(Z_OBJ_P((zval *) serv->private_data_2)); + return server_object->isset_callback(port, event_type); +} + static sw_inline void server_set_ptr(zval *zobject, Server *serv) { server_fetch_object(Z_OBJ_P(zobject))->serv = serv; } @@ -776,14 +739,14 @@ void php_swoole_server_minit(int module_number) { zend_fcall_info_cache *php_swoole_server_get_fci_cache(Server *serv, int server_fd, int event_type) { ListenPort *port = serv->get_port_by_server_fd(server_fd); - php_swoole_server_port_property *property; + ServerPortProperty *property; zend_fcall_info_cache *fci_cache; ServerObject *server_object = server_fetch_object(Z_OBJ_P((zval *) serv->private_data_2)); if (sw_unlikely(!port)) { return nullptr; } - if ((property = (php_swoole_server_port_property *) port->ptr) && (fci_cache = property->caches[event_type])) { + if ((property = (ServerPortProperty *) port->ptr) && (fci_cache = property->caches[event_type])) { return fci_cache; } else { return server_object->property->primary_port->caches[event_type]; @@ -974,7 +937,7 @@ static void php_swoole_task_onTimeout(Timer *timer, TimerNode *tnode) { extern ListenPort *php_swoole_server_port_get_and_check_ptr(zval *zobject); extern void php_swoole_server_port_set_ptr(zval *zobject, ListenPort *port); -extern php_swoole_server_port_property *php_swoole_server_port_get_property(zval *zobject); +extern ServerPortProperty *php_swoole_server_port_get_property(zval *zobject); static zval *php_swoole_server_add_port(ServerObject *server_object, ListenPort *port) { /* port */ @@ -989,7 +952,7 @@ static zval *php_swoole_server_add_port(ServerObject *server_object, ListenPort php_swoole_server_port_set_ptr(zport, port); /* port property */ - php_swoole_server_port_property *property = php_swoole_server_port_get_property(zport); + ServerPortProperty *property = php_swoole_server_port_get_property(zport); property->serv = serv; property->port = port; @@ -1023,7 +986,7 @@ static zval *php_swoole_server_add_port(ServerObject *server_object, ListenPort return zport; } -void php_swoole_server_before_start(Server *serv, zval *zobject) { +void ServerObject::on_before_start() { /** * create swoole server */ @@ -1032,8 +995,10 @@ void php_swoole_server_before_start(Server *serv, zval *zobject) { return; } -#ifdef SW_LOG_TRACE_OPEN + zval *zobject = get_object(); auto primary_port = serv->get_primary_port(); + +#ifdef SW_LOG_TRACE_OPEN swTraceLog(SW_TRACE_SERVER, "Create Server: host=%s, port=%d, mode=%d, type=%d", primary_port->host.c_str(), @@ -1048,7 +1013,7 @@ void php_swoole_server_before_start(Server *serv, zval *zobject) { if (serv->send_yield) { if (serv->onClose == nullptr && serv->is_support_unsafe_events()) { - serv->onClose = php_swoole_onClose; + serv->onClose = php_swoole_server_onClose; } } @@ -1070,9 +1035,9 @@ void php_swoole_server_before_start(Server *serv, zval *zobject) { /** * Master Process ID */ - zend_update_property_long(swoole_server_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("master_pid"), getpid()); + zend_update_property_long(get_ce(), SW_Z8_OBJ_P(zobject), ZEND_STRL("master_pid"), getpid()); - zval *zsetting = sw_zend_read_and_convert_property_array(swoole_server_ce, zobject, ZEND_STRL("setting"), 0); + zval *zsetting = sw_zend_read_and_convert_property_array(get_ce(), zobject, ZEND_STRL("setting"), 0); if (!zend_hash_str_exists(Z_ARRVAL_P(zsetting), ZEND_STRL("worker_num"))) { add_assoc_long(zsetting, "worker_num", serv->worker_num); @@ -1087,16 +1052,64 @@ void php_swoole_server_before_start(Server *serv, zval *zobject) { add_assoc_long(zsetting, "max_connection", serv->get_max_connection()); } - uint32_t i; - zval *zport; - zval *zport_setting; - ListenPort *port; bool find_http_port = false; - ServerObject *server_object = server_fetch_object(Z_OBJ_P(zobject)); + if (is_redis_server()) { + add_assoc_bool(zsetting, "open_redis_protocol", 1); + add_assoc_bool(zsetting, "open_http_protocol", 0); + add_assoc_bool(zsetting, "open_mqtt_protocol", 0); + add_assoc_bool(zsetting, "open_eof_check", 0); + add_assoc_bool(zsetting, "open_length_check", 0); + primary_port->clear_protocol(); + primary_port->open_redis_protocol = 1; + serv->onReceive = php_swoole_redis_server_onReceive; + } else if (is_http_server()) { + if (is_websocket_server()) { + if (!isset_callback(primary_port, SW_SERVER_CB_onMessage)) { + php_swoole_fatal_error(E_ERROR, "require onMessage callback"); + return; + } + } else if (!isset_callback(primary_port, SW_SERVER_CB_onRequest)) { + php_swoole_fatal_error(E_ERROR, "require onRequest callback"); + return; + } + + add_assoc_bool(zsetting, "open_http_protocol", 1); + add_assoc_bool(zsetting, "open_mqtt_protocol", 0); + add_assoc_bool(zsetting, "open_eof_check", 0); + add_assoc_bool(zsetting, "open_length_check", 0); + + enum protocol_flags { SW_HTTP2_PROTOCOL = 1u << 1, SW_WEBSOCKET_PROTOCOL = 1u << 2 }; + uint8_t protocol_flag = 0; + if (primary_port->open_http2_protocol) { + add_assoc_bool(zsetting, "open_http2_protocol", 1); + protocol_flag |= SW_HTTP2_PROTOCOL; + } + if (primary_port->open_websocket_protocol || is_websocket_server()) { + add_assoc_bool(zsetting, "open_websocket_protocol", 1); + protocol_flag |= SW_WEBSOCKET_PROTOCOL; + } + primary_port->clear_protocol(); + primary_port->open_http_protocol = 1; + primary_port->open_http2_protocol = !!(protocol_flag & SW_HTTP2_PROTOCOL); + primary_port->open_websocket_protocol = !!(protocol_flag & SW_WEBSOCKET_PROTOCOL); + find_http_port = true; + serv->onReceive = php_swoole_http_server_onReceive; + } else { + if (serv->if_require_packet_callback(primary_port, isset_callback(primary_port, SW_SERVER_CB_onPacket))) { + php_swoole_fatal_error(E_ERROR, "require onPacket callback"); + return; + } + if (serv->if_require_receive_callback(primary_port, isset_callback(primary_port, SW_SERVER_CB_onReceive))) { + php_swoole_fatal_error(E_ERROR, "require onReceive callback"); + return; + } + serv->onReceive = php_swoole_server_onReceive; + } - for (i = 1; i < server_object->property->ports.size(); i++) { - zport = server_object->property->ports.at(i); - zport_setting = sw_zend_read_property_ex(swoole_server_port_ce, zport, SW_ZSTR_KNOWN(SW_ZEND_STR_SETTING), 0); + for (size_t i = 1; i < property->ports.size(); i++) { + zval *zport = property->ports.at(i); + zval *zport_setting = + sw_zend_read_property_ex(swoole_server_port_ce, zport, SW_ZSTR_KNOWN(SW_ZEND_STR_SETTING), 0); // use swoole_server->setting if (zport_setting == nullptr || ZVAL_IS_NULL(zport_setting)) { Z_TRY_ADDREF_P(zport); @@ -1104,12 +1117,11 @@ void php_swoole_server_before_start(Server *serv, zval *zobject) { } } - for (i = 0; i < server_object->property->ports.size(); i++) { - zport = server_object->property->ports.at(i); - port = php_swoole_server_port_get_and_check_ptr(zport); + for (size_t i = 0; i < property->ports.size(); i++) { + zval *zport = property->ports.at(i); + ListenPort *port = php_swoole_server_port_get_and_check_ptr(zport); - if (serv->if_require_packet_callback( - port, php_swoole_server_isset_callback(server_object, port, SW_SERVER_CB_onPacket))) { + if (serv->if_require_packet_callback(port, isset_callback(port, SW_SERVER_CB_onPacket))) { php_swoole_fatal_error(E_ERROR, "require onPacket callback"); return; } @@ -1135,17 +1147,24 @@ void php_swoole_server_before_start(Server *serv, zval *zobject) { if (port->open_http_protocol) { find_http_port = true; if (port->open_websocket_protocol) { - if (!php_swoole_server_isset_callback(server_object, port, SW_SERVER_CB_onMessage)) { + if (!isset_callback(port, SW_SERVER_CB_onMessage) && !isset_callback(port, SW_SERVER_CB_onReceive)) { php_swoole_fatal_error(E_ERROR, "require onMessage callback"); return; } - } else if (port->open_http_protocol && - !php_swoole_server_isset_callback(server_object, port, SW_SERVER_CB_onRequest)) { + } else if (port->open_http_protocol && !isset_callback(port, SW_SERVER_CB_onRequest) && + !isset_callback(port, SW_SERVER_CB_onReceive)) { php_swoole_fatal_error(E_ERROR, "require onRequest callback"); return; } + if (!is_http_server() && isset_callback(port, SW_SERVER_CB_onRequest)) { + php_swoole_error( + E_WARNING, + "use %s class and open http related protocols may lead to some errors (inconsistent class type)", + SW_Z_OBJCE_NAME_VAL_P(zobject)); + } } else if (!port->open_redis_protocol) { - if (port->is_stream() && !php_swoole_server_isset_callback(server_object, port, SW_SERVER_CB_onReceive)) { + // redis server does not require to set receive callback + if (port->is_stream() && !isset_callback(port, SW_SERVER_CB_onReceive)) { php_swoole_fatal_error(E_ERROR, "require onReceive callback"); return; } @@ -1153,67 +1172,60 @@ void php_swoole_server_before_start(Server *serv, zval *zobject) { } if (find_http_port) { - serv->onReceive = php_swoole_http_onReceive; + serv->onReceive = php_swoole_http_server_onReceive; if (serv->is_support_unsafe_events()) { - serv->onClose = php_swoole_http_onClose; - } - if (!instanceof_function(Z_OBJCE_P(zobject), swoole_http_server_ce)) { - php_swoole_error( - E_WARNING, - "use %s class and open http related protocols may lead to some errors (inconsistent class type)", - SW_Z_OBJCE_NAME_VAL_P(zobject)); + serv->onClose = php_swoole_http_server_onClose; } php_swoole_http_server_init_global_variant(); } } -void php_swoole_server_register_callbacks(Server *serv) { - ServerObject *server_object = server_fetch_object(Z_OBJ_P((zval *) serv->private_data_2)); +void ServerObject::register_callback() { /* * optional callback */ - if (server_object->property->callbacks[SW_SERVER_CB_onStart] != nullptr) { + if (property->callbacks[SW_SERVER_CB_onStart] != nullptr) { serv->onStart = php_swoole_onStart; } serv->onShutdown = php_swoole_onShutdown; /** * require callback, set the master/manager/worker PID */ - serv->onWorkerStart = php_swoole_onWorkerStart; + serv->onWorkerStart = php_swoole_server_onWorkerStart; - if (server_object->property->callbacks[SW_SERVER_CB_onBeforeReload] != nullptr) { - serv->onBeforeReload = php_swoole_onBeforeReload; + if (property->callbacks[SW_SERVER_CB_onBeforeReload] != nullptr) { + serv->onBeforeReload = php_swoole_server_onBeforeReload; } - if (server_object->property->callbacks[SW_SERVER_CB_onAfterReload] != nullptr) { - serv->onAfterReload = php_swoole_onAfterReload; + if (property->callbacks[SW_SERVER_CB_onAfterReload] != nullptr) { + serv->onAfterReload = php_swoole_server_onAfterReload; } - if (server_object->property->callbacks[SW_SERVER_CB_onWorkerStop] != nullptr) { - serv->onWorkerStop = php_swoole_onWorkerStop; + if (property->callbacks[SW_SERVER_CB_onWorkerStop] != nullptr) { + serv->onWorkerStop = php_swoole_server_onWorkerStop; } - serv->onWorkerExit = php_swoole_onWorkerExit; + serv->onWorkerExit = php_swoole_server_onWorkerExit; /** * Task Worker */ - if (server_object->property->callbacks[SW_SERVER_CB_onTask] != nullptr) { - serv->onTask = php_swoole_onTask; - serv->onFinish = php_swoole_onFinish; + if (property->callbacks[SW_SERVER_CB_onTask] != nullptr) { + serv->onTask = php_swoole_server_onTask; + serv->onFinish = php_swoole_server_onFinish; } - if (server_object->property->callbacks[SW_SERVER_CB_onWorkerError] != nullptr) { - serv->onWorkerError = php_swoole_onWorkerError; + if (property->callbacks[SW_SERVER_CB_onWorkerError] != nullptr) { + serv->onWorkerError = php_swoole_server_onWorkerError; } - if (server_object->property->callbacks[SW_SERVER_CB_onManagerStart] != nullptr) { - serv->onManagerStart = php_swoole_onManagerStart; + if (property->callbacks[SW_SERVER_CB_onManagerStart] != nullptr) { + serv->onManagerStart = php_swoole_server_onManagerStart; } - if (server_object->property->callbacks[SW_SERVER_CB_onManagerStop] != nullptr) { - serv->onManagerStop = php_swoole_onManagerStop; + if (property->callbacks[SW_SERVER_CB_onManagerStop] != nullptr) { + serv->onManagerStop = php_swoole_server_onManagerStop; } - if (server_object->property->callbacks[SW_SERVER_CB_onPipeMessage] != nullptr) { + if (property->callbacks[SW_SERVER_CB_onPipeMessage] != nullptr) { serv->onPipeMessage = php_swoole_onPipeMessage; } if (serv->send_yield && serv->is_support_unsafe_events()) { - serv->onBufferEmpty = php_swoole_onBufferEmpty; + serv->onBufferEmpty = php_swoole_server_onBufferEmpty; } } @@ -1271,10 +1283,12 @@ static void php_swoole_onPipeMessage(Server *serv, EventData *req) { if (serv->event_object) { zval *object = &args[1]; object_init_ex(object, swoole_server_pipe_message_ce); - zend_update_property_long(swoole_server_pipe_message_ce, SW_Z8_OBJ_P(object), ZEND_STRL("worker_id"), + zend_update_property_long(swoole_server_pipe_message_ce, + SW_Z8_OBJ_P(object), + ZEND_STRL("worker_id"), (zend_long) req->info.reactor_id); - zend_update_property_double(swoole_server_pipe_message_ce, SW_Z8_OBJ_P(object), ZEND_STRL("dispatch_time"), - req->info.time); + zend_update_property_double( + swoole_server_pipe_message_ce, SW_Z8_OBJ_P(object), ZEND_STRL("dispatch_time"), req->info.time); zend_update_property(swoole_server_pipe_message_ce, SW_Z8_OBJ_P(object), ZEND_STRL("data"), zdata); argc = 2; } else { @@ -1294,7 +1308,7 @@ static void php_swoole_onPipeMessage(Server *serv, EventData *req) { sw_zval_free(zdata); } -int php_swoole_onReceive(Server *serv, RecvData *req) { +int php_swoole_server_onReceive(Server *serv, RecvData *req) { zend_fcall_info_cache *fci_cache = php_swoole_server_get_fci_cache(serv, req->info.server_fd, SW_SERVER_CB_onReceive); @@ -1309,12 +1323,12 @@ int php_swoole_onReceive(Server *serv, RecvData *req) { zval *object = &args[1]; zval data; object_init_ex(object, swoole_server_event_ce); - zend_update_property_long(swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("fd"), - (zend_long) req->info.fd); - zend_update_property_long(swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("reactor_id"), - (zend_long) req->info.reactor_id); - zend_update_property_double(swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("dispatch_time"), - req->info.time); + zend_update_property_long( + swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("fd"), (zend_long) req->info.fd); + zend_update_property_long( + swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("reactor_id"), (zend_long) req->info.reactor_id); + zend_update_property_double( + swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("dispatch_time"), req->info.time); php_swoole_get_recv_data(serv, &data, req); zend_update_property(swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("data"), &data); zval_ptr_dtor(&data); @@ -1340,46 +1354,52 @@ int php_swoole_onReceive(Server *serv, RecvData *req) { return SW_OK; } -int php_swoole_onPacket(Server *serv, RecvData *req) { +int php_swoole_server_onPacket(Server *serv, RecvData *req) { zval *zserv = (zval *) serv->private_data_2; zval args[3]; int argc; args[0] = *zserv; - DgramPacket *packet = (DgramPacket*) req->data; + DgramPacket *packet = (DgramPacket *) req->data; if (serv->event_object) { zval zobject; object_init_ex(&zobject, swoole_server_packet_ce); - zend_update_property_long(swoole_server_packet_ce, SW_Z8_OBJ_P(&zobject), ZEND_STRL("server_socket"), - req->info.server_fd); - zend_update_property_double(swoole_server_packet_ce, SW_Z8_OBJ_P(&zobject), ZEND_STRL("dispatch_time"), - req->info.time); + zend_update_property_long( + swoole_server_packet_ce, SW_Z8_OBJ_P(&zobject), ZEND_STRL("server_socket"), req->info.server_fd); + zend_update_property_double( + swoole_server_packet_ce, SW_Z8_OBJ_P(&zobject), ZEND_STRL("dispatch_time"), req->info.time); Connection *server_sock = serv->get_connection(req->info.server_fd); if (server_sock) { - zend_update_property_long(swoole_server_packet_ce, SW_Z8_OBJ_P(&zobject), ZEND_STRL("server_port"), - server_sock->info.get_port()); + zend_update_property_long( + swoole_server_packet_ce, SW_Z8_OBJ_P(&zobject), ZEND_STRL("server_port"), server_sock->info.get_port()); } char address[INET6_ADDRSTRLEN]; if (packet->socket_type == SW_SOCK_UDP) { inet_ntop(AF_INET, &packet->socket_addr.addr.inet_v4.sin_addr, address, sizeof(address)); zend_update_property_string(swoole_server_packet_ce, SW_Z8_OBJ_P(&zobject), ZEND_STRL("address"), address); - zend_update_property_long(swoole_server_packet_ce, SW_Z8_OBJ_P(&zobject), ZEND_STRL("port"), + zend_update_property_long(swoole_server_packet_ce, + SW_Z8_OBJ_P(&zobject), + ZEND_STRL("port"), ntohs(packet->socket_addr.addr.inet_v4.sin_port)); } else if (packet->socket_type == SW_SOCK_UDP6) { inet_ntop(AF_INET6, &packet->socket_addr.addr.inet_v6.sin6_addr, address, sizeof(address)); zend_update_property_string(swoole_server_packet_ce, SW_Z8_OBJ_P(&zobject), ZEND_STRL("address"), address); - zend_update_property_long(swoole_server_packet_ce, SW_Z8_OBJ_P(&zobject), ZEND_STRL("port"), + zend_update_property_long(swoole_server_packet_ce, + SW_Z8_OBJ_P(&zobject), + ZEND_STRL("port"), ntohs(packet->socket_addr.addr.inet_v6.sin6_port)); } else if (packet->socket_type == SW_SOCK_UNIX_DGRAM) { - zend_update_property_string(swoole_server_packet_ce, SW_Z8_OBJ_P(&zobject), ZEND_STRL("address"), + zend_update_property_string(swoole_server_packet_ce, + SW_Z8_OBJ_P(&zobject), + ZEND_STRL("address"), packet->socket_addr.addr.un.sun_path); } - zend_update_property_stringl(swoole_server_packet_ce, SW_Z8_OBJ_P(&zobject), ZEND_STRL("data"), packet->data, - packet->length); + zend_update_property_stringl( + swoole_server_packet_ce, SW_Z8_OBJ_P(&zobject), ZEND_STRL("data"), packet->data, packet->length); args[1] = zobject; argc = 2; } else { @@ -1410,8 +1430,8 @@ int php_swoole_onPacket(Server *serv, RecvData *req) { argc = 3; } - zend_fcall_info_cache *fci_cache = php_swoole_server_get_fci_cache(serv, req->info.server_fd, - SW_SERVER_CB_onPacket); + zend_fcall_info_cache *fci_cache = + php_swoole_server_get_fci_cache(serv, req->info.server_fd, SW_SERVER_CB_onPacket); if (UNEXPECTED(!zend::function::call(fci_cache, argc, args, nullptr, serv->enable_coroutine))) { php_swoole_error(E_WARNING, "%s->onPipeMessage handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } @@ -1438,7 +1458,7 @@ static sw_inline void php_swoole_create_task_object(zval *ztask, Server *serv, E swoole_server_task_ce, SW_Z8_OBJ_P(ztask), ZEND_STRL("flags"), (zend_long) swTask_type(req)); } -static int php_swoole_onTask(Server *serv, EventData *req) { +static int php_swoole_server_onTask(Server *serv, EventData *req) { sw_atomic_fetch_sub(&serv->gs->tasking_num, 1); zval *zserv = (zval *) serv->private_data_2; @@ -1486,7 +1506,7 @@ static int php_swoole_onTask(Server *serv, EventData *req) { return SW_OK; } -static int php_swoole_onFinish(Server *serv, EventData *req) { +static int php_swoole_server_onFinish(Server *serv, EventData *req) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); @@ -1573,12 +1593,14 @@ static int php_swoole_onFinish(Server *serv, EventData *req) { if (serv->event_object) { zval *object = &args[1]; object_init_ex(object, swoole_server_task_result_ce); - zend_update_property_long(swoole_server_task_result_ce, SW_Z8_OBJ_P(object), ZEND_STRL("task_id"), - (zend_long) req->info.fd); - zend_update_property_long(swoole_server_task_result_ce, SW_Z8_OBJ_P(object), ZEND_STRL("task_worker_id"), + zend_update_property_long( + swoole_server_task_result_ce, SW_Z8_OBJ_P(object), ZEND_STRL("task_id"), (zend_long) req->info.fd); + zend_update_property_long(swoole_server_task_result_ce, + SW_Z8_OBJ_P(object), + ZEND_STRL("task_worker_id"), (zend_long) req->info.reactor_id); - zend_update_property_double(swoole_server_task_result_ce, SW_Z8_OBJ_P(object), ZEND_STRL("dispatch_time"), - req->info.time); + zend_update_property_double( + swoole_server_task_result_ce, SW_Z8_OBJ_P(object), ZEND_STRL("dispatch_time"), req->info.time); zend_update_property(swoole_server_task_result_ce, SW_Z8_OBJ_P(object), ZEND_STRL("data"), zdata); argc = 2; } else { @@ -1616,7 +1638,7 @@ static void php_swoole_onStart(Server *serv) { serv->unlock(); } -static void php_swoole_onManagerStart(Server *serv) { +static void php_swoole_server_onManagerStart(Server *serv) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onManagerStart]; @@ -1629,7 +1651,7 @@ static void php_swoole_onManagerStart(Server *serv) { } } -static void php_swoole_onManagerStop(Server *serv) { +static void php_swoole_server_onManagerStop(Server *serv) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onManagerStop]; @@ -1653,7 +1675,7 @@ static void php_swoole_onShutdown(Server *serv) { serv->unlock(); } -static void php_swoole_onWorkerStart(Server *serv, int worker_id) { +static void php_swoole_server_onWorkerStart(Server *serv, int worker_id) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onWorkerStart]; @@ -1683,7 +1705,7 @@ static void php_swoole_onWorkerStart(Server *serv, int worker_id) { } } -static void php_swoole_onBeforeReload(Server *serv) { +static void php_swoole_server_onBeforeReload(Server *serv) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onBeforeReload]; @@ -1697,7 +1719,7 @@ static void php_swoole_onBeforeReload(Server *serv) { } } -static void php_swoole_onAfterReload(Server *serv) { +static void php_swoole_server_onAfterReload(Server *serv) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onAfterReload]; @@ -1711,7 +1733,7 @@ static void php_swoole_onAfterReload(Server *serv) { } } -static void php_swoole_onWorkerStop(Server *serv, int worker_id) { +static void php_swoole_server_onWorkerStop(Server *serv, int worker_id) { if (SwooleWG.shutdown) { return; } @@ -1733,7 +1755,7 @@ static void php_swoole_onWorkerStop(Server *serv, int worker_id) { } } -static void php_swoole_onWorkerExit(Server *serv, int worker_id) { +static void php_swoole_server_onWorkerExit(Server *serv, int worker_id) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onWorkerExit]; @@ -1764,7 +1786,7 @@ static void php_swoole_onUserWorkerStart(Server *serv, Worker *worker) { php_swoole_process_start(worker, object); } -static void php_swoole_onWorkerError(Server *serv, int worker_id, const ExitStatus &exit_status) { +static void php_swoole_server_onWorkerError(Server *serv, int worker_id, const ExitStatus &exit_status) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onWorkerError]; @@ -1777,10 +1799,14 @@ static void php_swoole_onWorkerError(Server *serv, int worker_id, const ExitStat zval *object = &args[1]; object_init_ex(object, swoole_server_status_info_ce); zend_update_property_long(swoole_server_status_info_ce, SW_Z8_OBJ_P(object), ZEND_STRL("worker_id"), worker_id); - zend_update_property_long(swoole_server_status_info_ce, SW_Z8_OBJ_P(object), ZEND_STRL("worker_pid"), exit_status.get_pid()); - zend_update_property_long(swoole_server_status_info_ce, SW_Z8_OBJ_P(object), ZEND_STRL("status"), exit_status.get_status()); - zend_update_property_long(swoole_server_status_info_ce, SW_Z8_OBJ_P(object), ZEND_STRL("exit_code"), exit_status.get_code()); - zend_update_property_long(swoole_server_status_info_ce, SW_Z8_OBJ_P(object), ZEND_STRL("signal"), exit_status.get_signal()); + zend_update_property_long( + swoole_server_status_info_ce, SW_Z8_OBJ_P(object), ZEND_STRL("worker_pid"), exit_status.get_pid()); + zend_update_property_long( + swoole_server_status_info_ce, SW_Z8_OBJ_P(object), ZEND_STRL("status"), exit_status.get_status()); + zend_update_property_long( + swoole_server_status_info_ce, SW_Z8_OBJ_P(object), ZEND_STRL("exit_code"), exit_status.get_code()); + zend_update_property_long( + swoole_server_status_info_ce, SW_Z8_OBJ_P(object), ZEND_STRL("signal"), exit_status.get_signal()); argc = 2; } else { ZVAL_LONG(&args[1], worker_id); @@ -1799,7 +1825,7 @@ static void php_swoole_onWorkerError(Server *serv, int worker_id, const ExitStat } } -void php_swoole_onConnect(Server *serv, DataHead *info) { +void php_swoole_server_onConnect(Server *serv, DataHead *info) { zend_fcall_info_cache *fci_cache = php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onConnect); if (fci_cache) { zval *zserv = (zval *) serv->private_data_2; @@ -1810,12 +1836,12 @@ void php_swoole_onConnect(Server *serv, DataHead *info) { if (serv->event_object) { zval *object = &args[1]; object_init_ex(object, swoole_server_event_ce); - zend_update_property_long(swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("fd"), - (zend_long) info->fd); - zend_update_property_long(swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("reactor_id"), - (zend_long) info->reactor_id); - zend_update_property_double(swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("dispatch_time"), - info->time); + zend_update_property_long( + swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("fd"), (zend_long) info->fd); + zend_update_property_long( + swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("reactor_id"), (zend_long) info->reactor_id); + zend_update_property_double( + swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("dispatch_time"), info->time); argc = 2; } else { ZVAL_LONG(&args[1], info->fd); @@ -1833,7 +1859,7 @@ void php_swoole_onConnect(Server *serv, DataHead *info) { } } -void php_swoole_onClose(Server *serv, DataHead *info) { +void php_swoole_server_onClose(Server *serv, DataHead *info) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); @@ -1864,12 +1890,12 @@ void php_swoole_onClose(Server *serv, DataHead *info) { if (serv->event_object) { zval *object = &args[1]; object_init_ex(object, swoole_server_event_ce); - zend_update_property_long(swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("fd"), - (zend_long) info->fd); - zend_update_property_long(swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("reactor_id"), - (zend_long) info->reactor_id); - zend_update_property_double(swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("dispatch_time"), - info->time); + zend_update_property_long( + swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("fd"), (zend_long) info->fd); + zend_update_property_long( + swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("reactor_id"), (zend_long) info->reactor_id); + zend_update_property_double( + swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("dispatch_time"), info->time); argc = 2; } else { ZVAL_LONG(&args[1], info->fd); @@ -1887,7 +1913,7 @@ void php_swoole_onClose(Server *serv, DataHead *info) { } } -void php_swoole_onBufferFull(Server *serv, DataHead *info) { +void php_swoole_server_onBufferFull(Server *serv, DataHead *info) { zval *zserv = (zval *) serv->private_data_2; zend_fcall_info_cache *fci_cache = php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onBufferFull); @@ -1904,7 +1930,7 @@ void php_swoole_onBufferFull(Server *serv, DataHead *info) { } } -static void php_swoole_onSendTimeout(Timer *timer, TimerNode *tnode) { +static void php_swoole_server_onSendTimeout(Timer *timer, TimerNode *tnode) { FutureTask *context = (FutureTask *) tnode->data; zval *zdata = &context->coro_params; zval result; @@ -1985,7 +2011,8 @@ void php_swoole_server_send_yield(Server *serv, SessionId session_id, zval *zdat coros_list->push_back(context); context->private_data = (void *) session_id; if (serv->send_timeout > 0) { - context->timer = swoole_timer_add((long) (serv->send_timeout * 1000), false, php_swoole_onSendTimeout, context); + context->timer = + swoole_timer_add((long) (serv->send_timeout * 1000), false, php_swoole_server_onSendTimeout, context); } else { context->timer = nullptr; } @@ -2034,7 +2061,7 @@ static int php_swoole_server_dispatch_func(Server *serv, Connection *conn, SendD return worker_id; } -void php_swoole_onBufferEmpty(Server *serv, DataHead *info) { +void php_swoole_server_onBufferEmpty(Server *serv, DataHead *info) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); zend_fcall_info_cache *fci_cache; @@ -2218,7 +2245,7 @@ static PHP_METHOD(swoole_server, __construct) { php_swoole_server_add_port(server_object, ls); } - server_object->property->primary_port = (php_swoole_server_port_property *) serv->get_primary_port()->ptr; + server_object->property->primary_port = (ServerPortProperty *) serv->get_primary_port()->ptr; } while (0); /* iterator */ @@ -2378,7 +2405,7 @@ static PHP_METHOD(swoole_server, set) { #endif // task use object if (php_swoole_array_get_value(vht, "task_use_object", ztmp) || - php_swoole_array_get_value(vht, "task_object", ztmp)) { + php_swoole_array_get_value(vht, "task_object", ztmp)) { serv->task_object = zval_is_true(ztmp); } if (php_swoole_array_get_value(vht, "event_object", ztmp)) { @@ -2784,14 +2811,6 @@ static PHP_METHOD(swoole_server, addProcess) { RETURN_LONG(id); } -static inline zend_bool is_websocket_server(zval *zobject) { - return instanceof_function(Z_OBJCE_P(zobject), swoole_websocket_server_ce); -} - -static inline zend_bool is_http_server(zval *zobject) { - return instanceof_function(Z_OBJCE_P(zobject), swoole_http_server_ce); -} - static PHP_METHOD(swoole_server, start) { zval *zserv = ZEND_THIS; Server *serv = php_swoole_server_get_and_check_server(zserv); @@ -2813,35 +2832,9 @@ static PHP_METHOD(swoole_server, start) { RETURN_FALSE; } - php_swoole_server_register_callbacks(serv); - - serv->onReceive = php_swoole_onReceive; - - if (is_websocket_server(zserv) || is_http_server(zserv)) { - zval *zsetting = sw_zend_read_and_convert_property_array(swoole_server_ce, ZEND_THIS, ZEND_STRL("setting"), 0); - add_assoc_bool(zsetting, "open_http_protocol", 1); - add_assoc_bool(zsetting, "open_mqtt_protocol", 0); - add_assoc_bool(zsetting, "open_eof_check", 0); - add_assoc_bool(zsetting, "open_length_check", 0); - - enum protocol_flags { SW_HTTP2_PROTOCOL = 1u << 1, SW_WEBSOCKET_PROTOCOL = 1u << 2 }; - uint8_t protocol_flag = 0; - auto primary_port = serv->get_primary_port(); - if (primary_port->open_http2_protocol) { - add_assoc_bool(zsetting, "open_http2_protocol", 1); - protocol_flag |= SW_HTTP2_PROTOCOL; - } - if (primary_port->open_websocket_protocol || is_websocket_server(zserv)) { - add_assoc_bool(zsetting, "open_websocket_protocol", 1); - protocol_flag |= SW_WEBSOCKET_PROTOCOL; - } - primary_port->clear_protocol(); - primary_port->open_http_protocol = 1; - primary_port->open_http2_protocol = !!(protocol_flag & SW_HTTP2_PROTOCOL); - primary_port->open_websocket_protocol = !!(protocol_flag & SW_WEBSOCKET_PROTOCOL); - } - - php_swoole_server_before_start(serv, zserv); + ServerObject *server_object = server_fetch_object(Z_OBJ_P((zval *) serv->private_data_2)); + server_object->register_callback(); + server_object->on_before_start(); if (serv->start() < 0) { php_swoole_fatal_error(E_ERROR, "failed to start server. Error: %s", sw_error); @@ -3006,7 +2999,7 @@ static PHP_METHOD(swoole_server, close) { php_swoole_fatal_error(E_WARNING, "server is not running"); RETURN_FALSE; } - + zend_long fd; zend_bool reset = false; @@ -3310,7 +3303,8 @@ static PHP_METHOD(swoole_server, taskWaitMulti) { // clear history task network::Socket *task_notify_socket = pipe->get_socket(false); task_notify_socket->set_nonblock(); - while (task_notify_socket->read(¬ify, sizeof(notify)) > 0) {} + while (task_notify_socket->read(¬ify, sizeof(notify)) > 0) { + } task_notify_socket->set_block(); SW_HASHTABLE_FOREACH_START(Z_ARRVAL_P(ztasks), ztask) @@ -3734,10 +3728,10 @@ static PHP_METHOD(swoole_server, getClientInfo) { add_assoc_long(return_value, "socket_fd", conn->fd); add_assoc_long(return_value, "socket_type", conn->socket_type); add_assoc_long(return_value, "remote_port", conn->info.get_port()); - add_assoc_string(return_value, "remote_ip", (char * ) conn->info.get_ip()); + add_assoc_string(return_value, "remote_ip", (char *) conn->info.get_ip()); add_assoc_long(return_value, "reactor_id", conn->reactor_id); add_assoc_long(return_value, "connect_time", conn->connect_time); - add_assoc_long(return_value, "last_time", (int ) conn->last_recv_time); + add_assoc_long(return_value, "last_time", (int) conn->last_recv_time); add_assoc_double(return_value, "last_recv_time", conn->last_recv_time); add_assoc_double(return_value, "last_send_time", conn->last_send_time); add_assoc_double(return_value, "last_dispatch_time", conn->last_dispatch_time); diff --git a/ext-src/swoole_server_port.cc b/ext-src/swoole_server_port.cc index 6b1bc99d450..05f351be74c 100644 --- a/ext-src/swoole_server_port.cc +++ b/ext-src/swoole_server_port.cc @@ -44,7 +44,7 @@ static zend_object_handlers swoole_server_port_handlers; struct server_port_t { ListenPort *port; - php_swoole_server_port_property property; + ServerPortProperty property; zend_object std; }; @@ -68,12 +68,12 @@ void php_swoole_server_port_set_ptr(zval *zobject, ListenPort *port) { php_swoole_server_port_fetch_object(Z_OBJ_P(zobject))->port = port; } -php_swoole_server_port_property *php_swoole_server_port_get_property(zval *zobject) { +ServerPortProperty *php_swoole_server_port_get_property(zval *zobject) { return &php_swoole_server_port_fetch_object(Z_OBJ_P(zobject))->property; } -static php_swoole_server_port_property *php_swoole_server_port_get_and_check_property(zval *zobject) { - php_swoole_server_port_property *property = php_swoole_server_port_get_property(zobject); +static ServerPortProperty *php_swoole_server_port_get_and_check_property(zval *zobject) { + ServerPortProperty *property = php_swoole_server_port_get_property(zobject); if (UNEXPECTED(!property->serv)) { php_swoole_fatal_error(E_ERROR, "Invaild instance of %s", SW_Z_OBJCE_NAME_VAL_P(zobject)); } @@ -83,7 +83,7 @@ static php_swoole_server_port_property *php_swoole_server_port_get_and_check_pro // Dereference from server object void php_swoole_server_port_deref(zend_object *object) { server_port_t *server_port = php_swoole_server_port_fetch_object(object); - php_swoole_server_port_property *property = &server_port->property; + ServerPortProperty *property = &server_port->property; if (property->serv) { for (int j = 0; j < PHP_SWOOLE_SERVER_PORT_CALLBACK_NUM; j++) { if (property->caches[j]) { @@ -268,7 +268,7 @@ static PHP_METHOD(swoole_server_port, set) { vht = Z_ARRVAL_P(zset); ListenPort *port = php_swoole_server_port_get_and_check_ptr(ZEND_THIS); - php_swoole_server_port_property *property = php_swoole_server_port_get_and_check_property(ZEND_THIS); + ServerPortProperty *property = php_swoole_server_port_get_and_check_property(ZEND_THIS); if (port == nullptr || property == nullptr) { php_swoole_fatal_error(E_ERROR, "please use the swoole_server->listen method"); @@ -621,7 +621,7 @@ static PHP_METHOD(swoole_server_port, on) { size_t len, i; zval *cb; - php_swoole_server_port_property *property = php_swoole_server_port_get_and_check_property(ZEND_THIS); + ServerPortProperty *property = php_swoole_server_port_get_and_check_property(ZEND_THIS); Server *serv = property->serv; if (serv->is_started()) { php_swoole_fatal_error(E_WARNING, "can't register event callback function after server started"); @@ -675,17 +675,15 @@ static PHP_METHOD(swoole_server_port, on) { property->caches[i] = fci_cache; if (i == SW_SERVER_CB_onConnect && !serv->onConnect) { - serv->onConnect = php_swoole_onConnect; + serv->onConnect = php_swoole_server_onConnect; } else if (i == SW_SERVER_CB_onPacket && !serv->onPacket) { - serv->onPacket = php_swoole_onPacket; + serv->onPacket = php_swoole_server_onPacket; } else if (i == SW_SERVER_CB_onClose && !serv->onClose) { - serv->onClose = php_swoole_onClose; + serv->onClose = php_swoole_server_onClose; } else if (i == SW_SERVER_CB_onBufferFull && !serv->onBufferFull) { - serv->onBufferFull = php_swoole_onBufferFull; + serv->onBufferFull = php_swoole_server_onBufferFull; } else if (i == SW_SERVER_CB_onBufferEmpty && !serv->onBufferEmpty) { - serv->onBufferEmpty = php_swoole_onBufferEmpty; - } else if (i == SW_SERVER_CB_onMessage || i == SW_SERVER_CB_onRequest) { - serv->onReceive = php_swoole_http_onReceive; + serv->onBufferEmpty = php_swoole_server_onBufferEmpty; } break; } diff --git a/include/swoole.h b/include/swoole.h index 60691ab85aa..9f0b7696a83 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -126,6 +126,7 @@ typedef unsigned long ulong_t; #define SW_MAX(A, B) ((A) > (B) ? (A) : (B)) #define SW_MIN(A, B) ((A) < (B) ? (A) : (B)) #define SW_LOOP_N(n) for (decltype(n) i = 0; i < n; i++) +#define SW_LOOP for (;;) #ifndef MAX #define MAX(A, B) SW_MAX(A, B) @@ -655,7 +656,7 @@ std::string dirname(const std::string &file); int hook_add(void **hooks, int type, const Callback &func, int push_back); void hook_call(void **hooks, int type, void *arg); double microtime(void); -} +} // namespace swoole extern swoole::Global SwooleG; // Local Global Variable extern __thread swoole::ThreadGlobal SwooleTG; // Thread Global Variable @@ -708,7 +709,7 @@ static sw_inline void sw_spinlock(sw_atomic_t *lock) { } static sw_inline swoole::String *sw_tg_buffer() { - return SwooleTG.buffer_stack; + return SwooleTG.buffer_stack; } static sw_inline swoole::MemoryPool *sw_mem_pool() { diff --git a/tests/swoole_server/check_callback.phpt b/tests/swoole_server/check_callback.phpt new file mode 100644 index 00000000000..a8cd701760e --- /dev/null +++ b/tests/swoole_server/check_callback.phpt @@ -0,0 +1,83 @@ +--TEST-- +swoole_server: check callback +--SKIPIF-- + +--FILE-- +start(); + }, true, SOCK_STREAM, false); + $proc->start(); + $result = Process::wait(); + Assert::contains($proc->read(), 'require on'.ucfirst($callback).' callback'); + Assert::eq($result['code'], 255); +} + +test_create_server(Swoole\Server::class, Constant::EVENT_RECEIVE); +test_create_server(Swoole\Http\Server::class, Constant::EVENT_REQUEST); +test_create_server(Swoole\WebSocket\Server::class, Constant::EVENT_MESSAGE); + +$proc = new Process(function () { + $server = new Swoole\Server('127.0.0.1', 0, SWOOLE_BASE, SWOOLE_SOCK_UDP); + $server->start(); +}, true, SOCK_STREAM, false); +$proc->start(); +$result = Process::wait(); +Assert::contains($proc->read(), 'require onPacket callback'); +Assert::eq($result['code'], 255); + +$proc = new Process(function () { + $server = new Swoole\Server('127.0.0.1', 0, SWOOLE_BASE, SWOOLE_SOCK_UDP); + $server->on(Constant::EVENT_PACKET, function () {}); + $server->addlistener('127.0.0.1', 0, SWOOLE_SOCK_TCP); + $server->start(); +}, true, SOCK_STREAM, false); +$proc->start(); +$result = Process::wait(); +Assert::contains($proc->read(), 'require onReceive callback'); +Assert::eq($result['code'], 255); + +$proc = new Process(function () { + $server = new Swoole\Server('127.0.0.1', 0, SWOOLE_BASE, SWOOLE_SOCK_TCP); + $server->on(Constant::EVENT_RECEIVE, function () {}); + $server->addlistener('127.0.0.1', 0, SWOOLE_SOCK_UDP); + $server->start(); +}, true, SOCK_STREAM, false); +$proc->start(); +$result = Process::wait(); +Assert::contains($proc->read(), 'require onPacket callback'); +Assert::eq($result['code'], 255); + +$proc = new Process(function () { + $server = new Swoole\Http\Server('127.0.0.1', 0, SWOOLE_BASE, SWOOLE_SOCK_TCP); + $server->on(Constant::EVENT_REQUEST, function () {}); + $server->addlistener('127.0.0.1', 0, SWOOLE_SOCK_UDP); + $server->start(); +}, true, SOCK_STREAM, false); +$proc->start(); +$result = Process::wait(); +Assert::contains($proc->read(), 'require onPacket callback'); +Assert::eq($result['code'], 255); + +$proc = new Process(function () { + $server = new Swoole\Http\Server('127.0.0.1', 0, SWOOLE_BASE, SWOOLE_SOCK_TCP); + $server->on(Constant::EVENT_REQUEST, function () {}); + $port = $server->addlistener('127.0.0.1', 0, SWOOLE_SOCK_TCP); + $port->set(['open_http_protocol' => false]); + $server->start(); +}, true, SOCK_STREAM, false); +$proc->start(); +$result = Process::wait(); +Assert::contains($proc->read(), 'require onReceive callback'); +Assert::eq($result['code'], 255); + +?> +--EXPECT-- diff --git a/tests/swoole_server/http_protocol.phpt b/tests/swoole_server/http_protocol.phpt index 3a61f897ef8..30d3155f35d 100644 --- a/tests/swoole_server/http_protocol.phpt +++ b/tests/swoole_server/http_protocol.phpt @@ -40,6 +40,7 @@ $pm->childFunc = function () use ($pm) { $serv->set([ 'worker_num' => 1, 'log_file' => '/dev/null', + 'open_http_protocol' => true, ]); $serv->on("Start", function ($serv) use ($pm) { $pm->wakeup(); From 6558d187a31d533792b0cbd30fada31d62193b73 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Sat, 20 Feb 2021 20:19:52 +0800 Subject: [PATCH 059/936] optimize code --- ext-src/swoole_server.cc | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 73fefd4222d..b4143bb41b0 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -1309,8 +1309,7 @@ static void php_swoole_onPipeMessage(Server *serv, EventData *req) { } int php_swoole_server_onReceive(Server *serv, RecvData *req) { - zend_fcall_info_cache *fci_cache = - php_swoole_server_get_fci_cache(serv, req->info.server_fd, SW_SERVER_CB_onReceive); + auto fci_cache = php_swoole_server_get_fci_cache(serv, req->info.server_fd, SW_SERVER_CB_onReceive); if (fci_cache) { zval *zserv = (zval *) serv->private_data_2; @@ -1430,8 +1429,7 @@ int php_swoole_server_onPacket(Server *serv, RecvData *req) { argc = 3; } - zend_fcall_info_cache *fci_cache = - php_swoole_server_get_fci_cache(serv, req->info.server_fd, SW_SERVER_CB_onPacket); + auto fci_cache = php_swoole_server_get_fci_cache(serv, req->info.server_fd, SW_SERVER_CB_onPacket); if (UNEXPECTED(!zend::function::call(fci_cache, argc, args, nullptr, serv->enable_coroutine))) { php_swoole_error(E_WARNING, "%s->onPipeMessage handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } @@ -1628,7 +1626,7 @@ static void php_swoole_onStart(Server *serv) { serv->lock(); zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onStart]; + auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onStart]; zend_update_property_long(swoole_server_ce, SW_Z8_OBJ_P(zserv), ZEND_STRL("master_pid"), serv->gs->master_pid); zend_update_property_long(swoole_server_ce, SW_Z8_OBJ_P(zserv), ZEND_STRL("manager_pid"), serv->gs->manager_pid); @@ -1641,7 +1639,7 @@ static void php_swoole_onStart(Server *serv) { static void php_swoole_server_onManagerStart(Server *serv) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onManagerStart]; + auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onManagerStart]; zend_update_property_long(swoole_server_ce, SW_Z8_OBJ_P(zserv), ZEND_STRL("master_pid"), serv->gs->master_pid); zend_update_property_long(swoole_server_ce, SW_Z8_OBJ_P(zserv), ZEND_STRL("manager_pid"), serv->gs->manager_pid); @@ -1654,7 +1652,7 @@ static void php_swoole_server_onManagerStart(Server *serv) { static void php_swoole_server_onManagerStop(Server *serv) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onManagerStop]; + auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onManagerStop]; if (UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, false))) { php_swoole_error(E_WARNING, "%s->onManagerStop handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); @@ -1665,7 +1663,7 @@ static void php_swoole_onShutdown(Server *serv) { serv->lock(); zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onShutdown]; + auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onShutdown]; if (fci_cache != nullptr) { if (UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, false))) { @@ -1678,7 +1676,7 @@ static void php_swoole_onShutdown(Server *serv) { static void php_swoole_server_onWorkerStart(Server *serv, int worker_id) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onWorkerStart]; + auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onWorkerStart]; zend_update_property_long(swoole_server_ce, SW_Z8_OBJ_P(zserv), ZEND_STRL("master_pid"), serv->gs->master_pid); zend_update_property_long(swoole_server_ce, SW_Z8_OBJ_P(zserv), ZEND_STRL("manager_pid"), serv->gs->manager_pid); @@ -1708,7 +1706,7 @@ static void php_swoole_server_onWorkerStart(Server *serv, int worker_id) { static void php_swoole_server_onBeforeReload(Server *serv) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onBeforeReload]; + auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onBeforeReload]; if (fci_cache) { zval args[1]; @@ -1722,7 +1720,7 @@ static void php_swoole_server_onBeforeReload(Server *serv) { static void php_swoole_server_onAfterReload(Server *serv) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onAfterReload]; + auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onAfterReload]; if (fci_cache) { zval args[1]; @@ -1741,7 +1739,7 @@ static void php_swoole_server_onWorkerStop(Server *serv, int worker_id) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onWorkerStop]; + auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onWorkerStop]; zval args[2]; args[0] = *zserv; ZVAL_LONG(&args[1], worker_id); @@ -1758,7 +1756,7 @@ static void php_swoole_server_onWorkerStop(Server *serv, int worker_id) { static void php_swoole_server_onWorkerExit(Server *serv, int worker_id) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onWorkerExit]; + auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onWorkerExit]; zval args[2]; args[0] = *zserv; @@ -1789,7 +1787,7 @@ static void php_swoole_onUserWorkerStart(Server *serv, Worker *worker) { static void php_swoole_server_onWorkerError(Server *serv, int worker_id, const ExitStatus &exit_status) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onWorkerError]; + auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onWorkerError]; zval args[5]; int argc; @@ -1826,7 +1824,7 @@ static void php_swoole_server_onWorkerError(Server *serv, int worker_id, const E } void php_swoole_server_onConnect(Server *serv, DataHead *info) { - zend_fcall_info_cache *fci_cache = php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onConnect); + auto fci_cache = php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onConnect); if (fci_cache) { zval *zserv = (zval *) serv->private_data_2; zval args[3]; @@ -1880,7 +1878,7 @@ void php_swoole_server_onClose(Server *serv, DataHead *info) { } } - zend_fcall_info_cache *fci_cache = php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onClose); + auto fci_cache = php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onClose); if (fci_cache) { zval *zserv = (zval *) serv->private_data_2; zval args[3]; @@ -1915,8 +1913,7 @@ void php_swoole_server_onClose(Server *serv, DataHead *info) { void php_swoole_server_onBufferFull(Server *serv, DataHead *info) { zval *zserv = (zval *) serv->private_data_2; - zend_fcall_info_cache *fci_cache = - php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onBufferFull); + auto fci_cache = php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onBufferFull); if (fci_cache) { zval args[2]; @@ -2023,7 +2020,7 @@ void php_swoole_server_send_yield(Server *serv, SessionId session_id, zval *zdat static int php_swoole_server_dispatch_func(Server *serv, Connection *conn, SendData *data) { serv->lock(); - zend_fcall_info_cache *fci_cache = (zend_fcall_info_cache *) serv->private_data_3; + auto fci_cache = (zend_fcall_info_cache *) serv->private_data_3; zval args[4]; zval *zserv = &args[0], *zfd = &args[1], *ztype = &args[2], *zdata = nullptr; zval retval; From edc0552c1c25c370df121c6c1363cc04f61c9131 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Mon, 22 Feb 2021 15:33:35 +0800 Subject: [PATCH 060/936] fixed #4060 --- ext-src/php_swoole_library.h | 94 +++++++++++++++++++++++++++--- ext-src/swoole_http_client_coro.cc | 51 ++++++++++------ include/swoole_coroutine_c_api.h | 1 + include/swoole_proxy.h | 5 +- src/coroutine/socket.cc | 43 ++++++++------ tools/build-library.php | 1 + 6 files changed, 148 insertions(+), 47 deletions(-) diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index dacc2a1cfde..8b4e4efc131 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: 0f2d353333c7bd6f81592f64d7699de50f86a871 */ +/* $Id: 2d8eaab25259a67bdb984f605d463d0bfb147c3c */ static const char* swoole_library_source_constants = "\n" @@ -1844,17 +1844,17 @@ static const char* swoole_library_source_core_coroutine_barrier = "\n" " public function __destruct()\n" " {\n" - " if ($this->timer != -1) {\n" + " if ($this->timer !== -1) {\n" " Timer::clear($this->timer);\n" - " if (isset(static::$cancel_list[$this->cid])) {\n" - " unset(static::$cancel_list[$this->cid]);\n" + " if (isset(self::$cancel_list[$this->cid])) {\n" + " unset(self::$cancel_list[$this->cid]);\n" " return;\n" " }\n" " }\n" - " if ($this->cid != -1 && $this->cid != Coroutine::getCid()) {\n" + " if ($this->cid !== -1 && $this->cid !== Coroutine::getCid()) {\n" " Coroutine::resume($this->cid);\n" " } else {\n" - " static::$cancel_list[$this->cid] = true;\n" + " self::$cancel_list[$this->cid] = true;\n" " }\n" " }\n" "\n" @@ -1868,12 +1868,12 @@ static const char* swoole_library_source_core_coroutine_barrier = " */\n" " public static function wait(Barrier &$barrier, float $timeout = -1)\n" " {\n" - " if ($barrier->cid != -1) {\n" + " if ($barrier->cid !== -1) {\n" " throw new Exception('The barrier is waiting, cannot wait again.');\n" " }\n" " $cid = Coroutine::getCid();\n" " $barrier->cid = $cid;\n" - " if ($timeout > 0 && ($timeout_ms = intval($timeout * 1000)) > 0) {\n" + " if ($timeout > 0 && ($timeout_ms = (int) ($timeout * 1000)) > 0) {\n" " $barrier->timer = Timer::after($timeout_ms, function () use ($cid) {\n" " self::$cancel_list[$cid] = true;\n" " Coroutine::resume($cid);\n" @@ -1882,10 +1882,85 @@ static const char* swoole_library_source_core_coroutine_barrier = " $barrier = null;\n" " if (!isset(self::$cancel_list[$cid])) {\n" " Coroutine::yield();\n" + " } else {\n" + " unset(self::$cancel_list[$cid]);\n" " }\n" " }\n" "}\n"; +static const char* swoole_library_source_core_coroutine_http_functions = + "\n" + "/**\n" + " * This file is part of Swoole.\n" + " *\n" + " * @link https://www.swoole.com\n" + " * @contact team@swoole.com\n" + " * @license https://github.com/swoole/library/blob/master/LICENSE\n" + " */\n" + "\n" + "declare(strict_types=1);\n" + "\n" + "namespace Swoole\\Coroutine\\Http;\n" + "\n" + "use Swoole\\Coroutine\\Http\\Client\\Exception;\n" + "\n" + "/**\n" + " * @param $url\n" + " * @param $data\n" + " * @param mixed $method\n" + " * @throws Exception\n" + " * @return mixed\n" + " */\n" + "function request($url, $method, $data = null, array $options = null, array $headers = null, array $cookies = null)\n" + "{\n" + " $info = parse_url($url);\n" + " if ($info['scheme'] == 'http') {\n" + " $client = new Client($info['host'], swoole_array_default_value($info, 'port', 80), false);\n" + " } elseif ($info['scheme'] == 'https') {\n" + " $client = new Client($info['host'], swoole_array_default_value($info, 'port', 443), true);\n" + " } else {\n" + " throw new Exception('unknown scheme \"' . $info['scheme'] . '\"');\n" + " }\n" + " $client->setMethod($method);\n" + " if ($data) {\n" + " $client->setData($data);\n" + " }\n" + " if (is_array($options)) {\n" + " $client->set($options);\n" + " }\n" + " if (is_array($headers)) {\n" + " $client->setHeaders($options);\n" + " }\n" + " if (is_array($cookies)) {\n" + " $client->setCookies($options);\n" + " }\n" + " if ($client->get($info['path'] . '?' . $info['query'])) {\n" + " return $client;\n" + " }\n" + " return false;\n" + "}\n" + "\n" + "/**\n" + " * @param $url\n" + " * @param $data\n" + " * @throws Exception\n" + " * @return Client|false|mixed\n" + " */\n" + "function post($url, $data, array $options = null, array $headers = null, array $cookies = null)\n" + "{\n" + " return request($url, 'POST', $data, $options, $headers, $cookies);\n" + "}\n" + "\n" + "/**\n" + " * @param $url\n" + " * @throws Exception\n" + " * @return Client|false|mixed\n" + " */\n" + "function get($url, array $options = null, array $headers = null, array $cookies = null)\n" + "{\n" + " return request($url, 'GET', null, $options, $headers, $cookies);\n" + "}\n"; + static const char* swoole_library_source_core_connection_pool = "\n" "/**\n" @@ -3636,7 +3711,7 @@ static const char* swoole_library_source_core_curl_handler = " private function setPort(int $port): void\n" " {\n" " $this->info['primary_port'] = $port;\n" - " if ($this->urlInfo['port'] !== $port) {\n" + " if (!isset($this->urlInfo['port']) || $this->urlInfo['port'] !== $port) {\n" " $this->urlInfo['port'] = $port;\n" " if ($this->client) {\n" " /* target changed */\n" @@ -7451,6 +7526,7 @@ void php_swoole_load_library() zend::eval(swoole_library_source_core_coroutine_server, "@swoole-src/library/core/Coroutine/Server.php"); zend::eval(swoole_library_source_core_coroutine_server_connection, "@swoole-src/library/core/Coroutine/Server/Connection.php"); zend::eval(swoole_library_source_core_coroutine_barrier, "@swoole-src/library/core/Coroutine/Barrier.php"); + zend::eval(swoole_library_source_core_coroutine_http_functions, "@swoole-src/library/core/Coroutine/Http/functions.php"); zend::eval(swoole_library_source_core_connection_pool, "@swoole-src/library/core/ConnectionPool.php"); zend::eval(swoole_library_source_core_database_object_proxy, "@swoole-src/library/core/Database/ObjectProxy.php"); zend::eval(swoole_library_source_core_database_mysqli_config, "@swoole-src/library/core/Database/MysqliConfig.php"); diff --git a/ext-src/swoole_http_client_coro.cc b/ext-src/swoole_http_client_coro.cc index 9e6225e5701..b37836f71d1 100644 --- a/ext-src/swoole_http_client_coro.cc +++ b/ext-src/swoole_http_client_coro.cc @@ -46,10 +46,10 @@ SW_EXTERN_C_END #include #endif -using swoole::network::Address; -using swoole::coroutine::Socket; using swoole::File; using swoole::String; +using swoole::coroutine::Socket; +using swoole::network::Address; enum http_client_error_status_code { HTTP_CLIENT_ESTATUS_CONNECT_FAILED = -1, @@ -82,7 +82,8 @@ static const swoole_http_parser_settings http_parser_settings = }; // clang-format on -namespace swoole { namespace coroutine { +namespace swoole { +namespace coroutine { class HttpClient { public: /* request info */ @@ -118,8 +119,8 @@ class HttpClient { #ifdef SW_HAVE_ZLIB bool websocket_compression = false; // allow to compress websocket messages #endif - File *download_file = nullptr; // save http response to file - zend::String download_file_name; // unlink the file on error + File *download_file = nullptr; // save http response to file + zend::String download_file_name; // unlink the file on error zend_long download_offset = 0; bool has_upload_files = false; @@ -246,7 +247,8 @@ class HttpClient { bool wait = false; }; -}} +} // namespace coroutine +} // namespace swoole static zend_class_entry *swoole_http_client_coro_ce; static zend_object_handlers swoole_http_client_coro_handlers; @@ -573,7 +575,8 @@ static int http_parser_on_body(swoole_http_parser *parser, const char *at, size_ } http->download_file = fp.release(); } - if (swoole_coroutine_write(http->download_file->get_fd(), SW_STRINGL(http->body)) != (ssize_t) http->body->length) { + if (swoole_coroutine_write(http->download_file->get_fd(), SW_STRINGL(http->body)) != + (ssize_t) http->body->length) { return -1; } http->body->clear(); @@ -970,6 +973,7 @@ bool HttpClient::send() { } // ============ path & proxy ============ + bool require_proxy_authentication = false; #ifdef SW_USE_OPENSSL if (socket->http_proxy && !socket->ssl_is_enable()) #else @@ -987,6 +991,9 @@ bool HttpClient::send() { char *proxy_uri = (char *) emalloc(proxy_uri_len); proxy_uri_len = sw_snprintf(proxy_uri, proxy_uri_len, "%s%s:%u%s", pre, _host, port, path.c_str()); buffer->append(proxy_uri, proxy_uri_len); + if (!socket->http_proxy->password.empty()) { + require_proxy_authentication = true; + } efree(proxy_uri); } else { buffer->append(path.c_str(), path.length()); @@ -1049,7 +1056,12 @@ bool HttpClient::send() { } SW_HASHTABLE_FOREACH_END(); } - + // http proxy authentication + if (require_proxy_authentication) { + std::string value("Basic "); + value += socket->http_proxy->get_auth_str(); + add_headers(buffer, ZEND_STRL("Proxy-Authorization"), value.c_str(), value.length()); + } if (!basic_auth.empty()) { add_headers(buffer, ZEND_STRL("Authorization"), basic_auth.c_str(), basic_auth.size()); } @@ -1063,15 +1075,15 @@ bool HttpClient::send() { #ifdef SW_HAVE_COMPRESSION if (!(header_flag & HTTP_HEADER_ACCEPT_ENCODING)) { add_headers(buffer, - ZEND_STRL("Accept-Encoding"), + ZEND_STRL("Accept-Encoding"), #if defined(SW_HAVE_ZLIB) && defined(SW_HAVE_BROTLI) - ZEND_STRL("gzip, deflate, br") + ZEND_STRL("gzip, deflate, br") #else #ifdef SW_HAVE_ZLIB - ZEND_STRL("gzip, deflate") + ZEND_STRL("gzip, deflate") #else #ifdef SW_HAVE_BROTLI - ZEND_STRL("br") + ZEND_STRL("br") #endif #endif #endif @@ -1486,7 +1498,8 @@ bool HttpClient::recv_http_response(double timeout) { if (!header_completed) { buffer->length += retval; - if (swoole_strnpos(buffer->str + header_crlf_offset, buffer->length - header_crlf_offset, ZEND_STRL("\r\n\r\n")) < 0) { + if (swoole_strnpos( + buffer->str + header_crlf_offset, buffer->length - header_crlf_offset, ZEND_STRL("\r\n\r\n")) < 0) { if (buffer->length == buffer->size) { swoole_error_log(SW_LOG_TRACE, SW_ERROR_HTTP_INVALID_PROTOCOL, "Http header too large"); socket->set_err(SW_ERROR_HTTP_INVALID_PROTOCOL); @@ -1674,8 +1687,8 @@ HttpClient::~HttpClient() { } } -static sw_inline HttpClientObject *php_swoole_http_client_coro_fetch_object(zend_object *obj) { - return (HttpClientObject *) ((char *) obj - swoole_http_client_coro_handlers.offset); +static sw_inline HttpClientObject *php_swoole_http_client_coro_fetch_object(zend_object *obj) { + return (HttpClientObject *) ((char *) obj - swoole_http_client_coro_handlers.offset); } static sw_inline HttpClient *php_swoole_get_phc(zval *zobject) { @@ -1687,7 +1700,7 @@ static sw_inline HttpClient *php_swoole_get_phc(zval *zobject) { } static void php_swoole_http_client_coro_free_object(zend_object *object) { - HttpClientObject *hcc = php_swoole_http_client_coro_fetch_object(object); + HttpClientObject *hcc = php_swoole_http_client_coro_fetch_object(object); if (hcc->phc) { delete hcc->phc; hcc->phc = nullptr; @@ -1696,7 +1709,7 @@ static void php_swoole_http_client_coro_free_object(zend_object *object) { } static zend_object *php_swoole_http_client_coro_create_object(zend_class_entry *ce) { - HttpClientObject *hcc = (HttpClientObject *) zend_object_alloc(sizeof(HttpClientObject ), ce); + HttpClientObject *hcc = (HttpClientObject *) zend_object_alloc(sizeof(HttpClientObject), ce); zend_object_std_init(&hcc->std, ce); object_properties_init(&hcc->std, ce); hcc->std.handlers = &swoole_http_client_coro_handlers; @@ -1715,7 +1728,7 @@ void php_swoole_http_client_coro_minit(int module_number) { SW_SET_CLASS_CUSTOM_OBJECT(swoole_http_client_coro, php_swoole_http_client_coro_create_object, php_swoole_http_client_coro_free_object, - HttpClientObject , + HttpClientObject, std); // client status @@ -1763,7 +1776,7 @@ void php_swoole_http_client_coro_minit(int module_number) { } static PHP_METHOD(swoole_http_client_coro, __construct) { - HttpClientObject *hcc = php_swoole_http_client_coro_fetch_object(Z_OBJ_P(ZEND_THIS)); + HttpClientObject *hcc = php_swoole_http_client_coro_fetch_object(Z_OBJ_P(ZEND_THIS)); char *host; size_t host_len; zend_long port = 80; diff --git a/include/swoole_coroutine_c_api.h b/include/swoole_coroutine_c_api.h index f96fcf02f05..c5d689fc2be 100644 --- a/include/swoole_coroutine_c_api.h +++ b/include/swoole_coroutine_c_api.h @@ -27,6 +27,7 @@ extern "C" { #include #include #include +#include #include #include #include diff --git a/include/swoole_proxy.h b/include/swoole_proxy.h index fb0a34bd1c7..a94279762a0 100644 --- a/include/swoole_proxy.h +++ b/include/swoole_proxy.h @@ -37,6 +37,8 @@ struct HttpProxy { std::string target_host; int target_port; char buf[512]; + + std::string get_auth_str(); }; struct Socks5Proxy { @@ -60,7 +62,7 @@ struct Socks5Proxy { buf[2] = method; } }; -} +} // namespace swoole enum swSocks5_state { SW_SOCKS5_STATE_WAIT = 0, @@ -73,4 +75,3 @@ enum swSocks5_state { enum swSocks5_method { SW_SOCKS5_METHOD_AUTH = 0x02, }; - diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index 0ecfaf7d864..cda5e6be043 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -31,7 +31,7 @@ namespace swoole { namespace coroutine { -enum Socket::TimeoutType Socket::timeout_type_list[4] = { TIMEOUT_DNS, TIMEOUT_CONNECT, TIMEOUT_READ, TIMEOUT_WRITE }; +enum Socket::TimeoutType Socket::timeout_type_list[4] = {TIMEOUT_DNS, TIMEOUT_CONNECT, TIMEOUT_READ, TIMEOUT_WRITE}; void Socket::timer_callback(Timer *timer, TimerNode *tnode) { Socket *socket = (Socket *) tnode->data; @@ -218,7 +218,8 @@ bool Socket::socks5_handshake() { return false; } if (method != ctx->method) { - swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SOCKS5_UNSUPPORT_METHOD, "SOCKS authentication method is not supported"); + swoole_error_log( + SW_LOG_NOTICE, SW_ERROR_SOCKS5_UNSUPPORT_METHOD, "SOCKS authentication method is not supported"); return false; } // authentication @@ -312,8 +313,10 @@ bool Socket::socks5_handshake() { ctx->state = SW_SOCKS5_STATE_READY; return true; } else { - swoole_error_log( - SW_LOG_NOTICE, SW_ERROR_SOCKS5_SERVER_ERROR, "Socks5 server error, reason: %s", Socks5Proxy::strerror(result)); + swoole_error_log(SW_LOG_NOTICE, + SW_ERROR_SOCKS5_SERVER_ERROR, + "Socks5 server error, reason: %s", + Socks5Proxy::strerror(result)); return false; } } @@ -342,16 +345,7 @@ bool Socket::http_proxy_handshake() { }; if (!http_proxy->password.empty()) { - char auth_buf[256]; - char encode_buf[512]; - n = sw_snprintf(auth_buf, - sizeof(auth_buf), - "%.*s:%.*s", - (int) http_proxy->username.length(), - http_proxy->username.c_str(), - (int) http_proxy->password.length(), - http_proxy->password.c_str()); - base64_encode((unsigned char *) auth_buf, n, encode_buf); + auto auth_str = http_proxy->get_auth_str(); n = sw_snprintf(send_buffer->str, send_buffer->size, HTTP_PROXY_FMT "Proxy-Authorization: Basic %s\r\n\r\n", @@ -361,7 +355,7 @@ bool Socket::http_proxy_handshake() { host_len, host, http_proxy->target_port, - encode_buf); + auth_str.c_str()); } else { n = sw_snprintf(send_buffer->str, send_buffer->size, @@ -442,8 +436,8 @@ bool Socket::http_proxy_handshake() { if (!ret) { set_err(SW_ERROR_HTTP_PROXY_BAD_RESPONSE, - std::string("wrong http_proxy response received, \n[Request]: ") + send_buffer->to_std_string() + "\n[Response]: " - + std::string(buf, len)); + std::string("wrong http_proxy response received, \n[Request]: ") + send_buffer->to_std_string() + + "\n[Response]: " + std::string(buf, len)); } return ret; @@ -1762,4 +1756,19 @@ Socket::~Socket() { } } // namespace coroutine + +std::string HttpProxy::get_auth_str() { + char auth_buf[256]; + char encode_buf[512]; + size_t n = sw_snprintf(auth_buf, + sizeof(auth_buf), + "%.*s:%.*s", + (int) username.length(), + username.c_str(), + (int) password.length(), + password.c_str()); + base64_encode((unsigned char *) auth_buf, n, encode_buf); + return std::string(encode_buf); +} + } // namespace swoole diff --git a/tools/build-library.php b/tools/build-library.php index 0105c85f564..ee33397c3e4 100755 --- a/tools/build-library.php +++ b/tools/build-library.php @@ -39,6 +39,7 @@ 'core/Coroutine/Server.php', 'core/Coroutine/Server/Connection.php', 'core/Coroutine/Barrier.php', + 'core/Coroutine/Http/functions.php', # # 'core/ConnectionPool.php', 'core/Database/ObjectProxy.php', From 3e7770f307a3c83a661c0ff10bc92f751585fd24 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 2 Mar 2021 18:06:36 +0800 Subject: [PATCH 061/936] fix #4072 --- src/memory/global_memory.cc | 2 +- tests/swoole_table/create_10k_object.phpt | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 tests/swoole_table/create_10k_object.phpt diff --git a/src/memory/global_memory.cc b/src/memory/global_memory.cc index a8444bbeafb..b15dd4591ec 100644 --- a/src/memory/global_memory.cc +++ b/src/memory/global_memory.cc @@ -104,7 +104,7 @@ void *GlobalMemory::alloc(uint32_t size) { } } - block = (MemoryBlock *) impl->pages.back() + impl->alloc_offset; + block = (MemoryBlock *) (impl->pages.back() + impl->alloc_offset); impl->alloc_offset += alloc_size; block->size = size; diff --git a/tests/swoole_table/create_10k_object.phpt b/tests/swoole_table/create_10k_object.phpt new file mode 100644 index 00000000000..95486ac2159 --- /dev/null +++ b/tests/swoole_table/create_10k_object.phpt @@ -0,0 +1,14 @@ +--TEST-- +swoole_table: create 10,000 objects +--SKIPIF-- + +--FILE-- + +--EXPECT-- +DONE From 630536d34f994f0b44ffaa0d76a82fc44c45e185 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Wed, 3 Mar 2021 12:22:00 +0800 Subject: [PATCH 062/936] Fix crash when http2 client connects concurrently --- ext-src/swoole_http2_client_coro.cc | 4 +- .../connect_twice.phpt | 40 +++++++++++++++++++ tests/swoole_http2_client_coro/error.phpt | 4 +- 3 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 tests/swoole_http2_client_coro/connect_twice.phpt diff --git a/ext-src/swoole_http2_client_coro.cc b/ext-src/swoole_http2_client_coro.cc index e605bf3c7ca..55e505342f7 100644 --- a/ext-src/swoole_http2_client_coro.cc +++ b/ext-src/swoole_http2_client_coro.cc @@ -119,10 +119,10 @@ class Client { } inline bool is_available() { - if (sw_unlikely(!client)) { + if (sw_unlikely(!client || !client->is_connect())) { swoole_set_last_error(SW_ERROR_CLIENT_NO_CONNECTION); zend_update_property_long( - swoole_http2_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), ECONNRESET); + swoole_http2_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), SW_ERROR_CLIENT_NO_CONNECTION); zend_update_property_string(swoole_http2_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errMsg"), diff --git a/tests/swoole_http2_client_coro/connect_twice.phpt b/tests/swoole_http2_client_coro/connect_twice.phpt new file mode 100644 index 00000000000..798ca5f724b --- /dev/null +++ b/tests/swoole_http2_client_coro/connect_twice.phpt @@ -0,0 +1,40 @@ +--TEST-- +swoole_http2_client_coro: connect twice +--SKIPIF-- + +--FILE-- +connect(); + $req = new \Swoole\Http2\Request(); + $req->method = 'GET'; + $req->path = '/io?io=' . str_repeat('xxx', 1000); + $client->send($req); + $chan->push(true); + $resp = $client->recv(); + Assert::eq($resp->statusCode, 200); + Assert::contains($resp->data, '知乎'); + $chan->pop(); + }); + go(function () use ($client, $chan) { + Assert::eq($client->connect(), false); + $req = new \Swoole\Http2\Request(); + $req->method = 'GET'; + $req->path = '/io?io=xxx'; + $client->send($req); + $chan->push(true); + Assert::eq($client->recv(), false); + $chan->pop(); + }); +}); + +?> +--EXPECT-- diff --git a/tests/swoole_http2_client_coro/error.phpt b/tests/swoole_http2_client_coro/error.phpt index 366e1b977be..1e2aab2bb0d 100644 --- a/tests/swoole_http2_client_coro/error.phpt +++ b/tests/swoole_http2_client_coro/error.phpt @@ -11,9 +11,9 @@ go(function () { Assert::false($cli->connect()); Assert::same($cli->errCode, SOCKET_ETIMEDOUT); Assert::false($cli->send(new Swoole\Http2\Request)); - Assert::same($cli->errCode, SOCKET_ECONNRESET); + Assert::same($cli->errCode, SWOOLE_ERROR_CLIENT_NO_CONNECTION); Assert::false($cli->recv(1)); - Assert::same($cli->errCode, SOCKET_ECONNRESET); + Assert::same($cli->errCode, SWOOLE_ERROR_CLIENT_NO_CONNECTION); }); Swoole\Event::wait(); ?> From cf8796655629e9eea85d2252edfab011d0ac7f09 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Wed, 3 Mar 2021 13:10:52 +0800 Subject: [PATCH 063/936] fix warning, optimize tests --- core-tests/src/memory/global_memory.cpp | 11 ++++++++--- ext-src/swoole_redis_server.cc | 1 - include/swoole_memory.h | 1 + src/memory/global_memory.cc | 4 ++++ 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/core-tests/src/memory/global_memory.cpp b/core-tests/src/memory/global_memory.cpp index ac4be30559c..1f50a644f6b 100644 --- a/core-tests/src/memory/global_memory.cpp +++ b/core-tests/src/memory/global_memory.cpp @@ -27,18 +27,23 @@ TEST(global_memory, alloc) { pool->free(ptr1); strcpy(ptr1, "hello, world, #1"); - char *ptr2 = (char *) pool->alloc(12); + char *ptr2 = (char *) pool->alloc(17); strcpy(ptr2, "hello, world, #2"); - char *ptr3 = (char *) pool->alloc(198); + pool->free(ptr2); + + char *ptr3 = (char *) pool->alloc(113); strcpy(ptr3, "hello, world, #3"); ASSERT_TRUE(ptr1); ASSERT_TRUE(ptr2); ASSERT_TRUE(ptr3); - delete pool; + ASSERT_GT(pool->capacity(), 2 * 1024 * 1024 - 512); ASSERT_STREQ(ptr1, "hello, world, #1"); ASSERT_STREQ(ptr2, "hello, world, #2"); ASSERT_STREQ(ptr3, "hello, world, #3"); + + pool->destroy(); + delete pool; } diff --git a/ext-src/swoole_redis_server.cc b/ext-src/swoole_redis_server.cc index a71ab622835..6d515d4aa5f 100644 --- a/ext-src/swoole_redis_server.cc +++ b/ext-src/swoole_redis_server.cc @@ -35,7 +35,6 @@ zend_object_handlers swoole_redis_server_handlers; static std::unordered_map redis_handlers; SW_EXTERN_C_BEGIN -static PHP_METHOD(swoole_redis_server, start); static PHP_METHOD(swoole_redis_server, setHandler); static PHP_METHOD(swoole_redis_server, getHandler); static PHP_METHOD(swoole_redis_server, format); diff --git a/include/swoole_memory.h b/include/swoole_memory.h index eb40222abc2..7241ed75c84 100644 --- a/include/swoole_memory.h +++ b/include/swoole_memory.h @@ -76,6 +76,7 @@ class GlobalMemory : public MemoryPool { void *alloc(uint32_t size); void free(void *ptr); void destroy(); + size_t capacity(); }; } // namespace swoole diff --git a/src/memory/global_memory.cc b/src/memory/global_memory.cc index b15dd4591ec..8f552143849 100644 --- a/src/memory/global_memory.cc +++ b/src/memory/global_memory.cc @@ -121,6 +121,10 @@ void GlobalMemory::destroy() { } } +size_t GlobalMemory::capacity() { + return impl->pagesize - impl->alloc_offset; +} + GlobalMemory::~GlobalMemory() { delete impl; } From 663156de4956a23240c77e248d44ed48956dc889 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Wed, 3 Mar 2021 16:22:33 +0800 Subject: [PATCH 064/936] fix #4075 --- src/os/signal.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/os/signal.cc b/src/os/signal.cc index 23c743c3773..919a589318b 100644 --- a/src/os/signal.cc +++ b/src/os/signal.cc @@ -40,8 +40,6 @@ static int signal_fd = 0; static swoole::network::Socket *signal_socket = nullptr; #elif HAVE_KQUEUE static swSignalHandler swKqueueSignal_set(int signo, swSignalHandler handler); -#else -static swSignalHandler swSignal_set(int signo, swSignalHandler func, int restart, int mask); #endif static void swSignal_async_handler(int signo); From 49d3f2a4d939c6fa0d3be06acd9947b71b681feb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Wed, 3 Mar 2021 16:59:34 +0800 Subject: [PATCH 065/936] optimize code (#4076) --- ext-src/swoole_client_coro.cc | 2 +- ext-src/swoole_http2_client_coro.cc | 2 +- ext-src/swoole_http_client_coro.cc | 68 ++++++++++------------------ ext-src/swoole_mysql_coro.cc | 16 +++---- include/swoole_coroutine_socket.h | 12 ++--- src/coroutine/socket.cc | 12 +++-- tests/swoole_client_sync/sendto.phpt | 6 +-- 7 files changed, 52 insertions(+), 66 deletions(-) diff --git a/ext-src/swoole_client_coro.cc b/ext-src/swoole_client_coro.cc index 5c3e5b7f71c..fb57f4769f2 100644 --- a/ext-src/swoole_client_coro.cc +++ b/ext-src/swoole_client_coro.cc @@ -789,7 +789,7 @@ static PHP_METHOD(swoole_client_coro, peek) { static PHP_METHOD(swoole_client_coro, isConnected) { Socket *cli = php_swoole_get_sock(ZEND_THIS); - if (cli && cli->is_connect()) { + if (cli && cli->is_connected()) { RETURN_TRUE; } else { RETURN_FALSE; diff --git a/ext-src/swoole_http2_client_coro.cc b/ext-src/swoole_http2_client_coro.cc index 55e505342f7..28619eaa624 100644 --- a/ext-src/swoole_http2_client_coro.cc +++ b/ext-src/swoole_http2_client_coro.cc @@ -119,7 +119,7 @@ class Client { } inline bool is_available() { - if (sw_unlikely(!client || !client->is_connect())) { + if (sw_unlikely(!client || !client->is_connected())) { swoole_set_last_error(SW_ERROR_CLIENT_NO_CONNECTION); zend_update_property_long( swoole_http2_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), SW_ERROR_CLIENT_NO_CONNECTION); diff --git a/ext-src/swoole_http_client_coro.cc b/ext-src/swoole_http_client_coro.cc index b37836f71d1..5f101edee12 100644 --- a/ext-src/swoole_http_client_coro.cc +++ b/ext-src/swoole_http_client_coro.cc @@ -141,6 +141,7 @@ class HttpClient { #endif bool bind(std::string address, int port = 0); bool connect(); + void set_error(int error, const char *msg, int status); bool keep_liveness(); bool send(); void reset(); @@ -174,7 +175,7 @@ class HttpClient { #endif void apply_setting(zval *zset, const bool check_all = true); void set_basic_auth(const std::string &username, const std::string &password); - bool exec(std::string path); + bool exec(std::string _path); bool recv(double timeout = 0); void recv(zval *zframe, double timeout = 0); bool recv_http_response(double timeout = 0); @@ -808,14 +809,7 @@ bool HttpClient::connect() { if (!body) { body = new String(SW_HTTP_RESPONSE_INIT_SIZE); if (!body) { - zend_update_property_long( - swoole_http_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), ENOMEM); - zend_update_property_string( - swoole_http_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errMsg"), swoole_strerror(ENOMEM)); - zend_update_property_long(swoole_http_client_coro_ce, - SW_Z8_OBJ_P(zobject), - ZEND_STRL("statusCode"), - HTTP_CLIENT_ESTATUS_CONNECT_FAILED); + set_error(ENOMEM, swoole_strerror(ENOMEM), HTTP_CLIENT_ESTATUS_CONNECT_FAILED); return false; } } @@ -824,13 +818,7 @@ bool HttpClient::connect() { socket = new Socket(socket_type); if (UNEXPECTED(socket->get_fd() < 0)) { php_swoole_sys_error(E_WARNING, "new Socket() failed"); - zend_update_property_long(swoole_http_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), errno); - zend_update_property_string( - swoole_http_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errMsg"), swoole_strerror(errno)); - zend_update_property_long(swoole_http_client_coro_ce, - SW_Z8_OBJ_P(zobject), - ZEND_STRL("statusCode"), - HTTP_CLIENT_ESTATUS_CONNECT_FAILED); + set_error(errno, swoole_strerror(errno), HTTP_CLIENT_ESTATUS_CONNECT_FAILED); delete socket; socket = nullptr; return false; @@ -849,14 +837,7 @@ bool HttpClient::connect() { // connect socket->set_timeout(connect_timeout, Socket::TIMEOUT_CONNECT); if (!socket->connect(host, port)) { - zend_update_property_long( - swoole_http_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), socket->errCode); - zend_update_property_string( - swoole_http_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errMsg"), socket->errMsg); - zend_update_property_long(swoole_http_client_coro_ce, - SW_Z8_OBJ_P(zobject), - ZEND_STRL("statusCode"), - HTTP_CLIENT_ESTATUS_CONNECT_FAILED); + set_error(socket->errCode, socket->errMsg, HTTP_CLIENT_ESTATUS_CONNECT_FAILED); close(); return false; } @@ -866,19 +847,20 @@ bool HttpClient::connect() { return true; } +void HttpClient::set_error(int error, const char *msg, int status) { + auto ce = swoole_http_client_coro_ce; + auto obj = SW_Z8_OBJ_P(zobject); + zend_update_property_long(ce, obj, ZEND_STRL("errCode"), error); + zend_update_property_string(ce, obj, ZEND_STRL("errMsg"), msg); + zend_update_property_long(ce, obj, ZEND_STRL("statusCode"), status); +} + bool HttpClient::keep_liveness() { if (!socket || !socket->check_liveness()) { if (socket) { /* in progress */ socket->check_bound_co(SW_EVENT_RDWR); - zend_update_property_long( - swoole_http_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), socket->errCode); - zend_update_property_string( - swoole_http_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errMsg"), socket->errMsg); - zend_update_property_long(swoole_http_client_coro_ce, - SW_Z8_OBJ_P(zobject), - ZEND_STRL("statusCode"), - HTTP_CLIENT_ESTATUS_SERVER_RESET); + set_error(socket->errCode, socket->errMsg, HTTP_CLIENT_ESTATUS_SERVER_RESET); close(false); } for (; reconnected_count < reconnect_interval; reconnected_count++) { @@ -1350,12 +1332,7 @@ bool HttpClient::send() { if (socket->send_all(buffer->str, buffer->length) != (ssize_t) buffer->length) { _send_fail: - zend_update_property_long( - swoole_http_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), socket->errCode); - zend_update_property_string( - swoole_http_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errMsg"), socket->errMsg); - zend_update_property_long( - swoole_http_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("statusCode"), HTTP_CLIENT_ESTATUS_SEND_FAILED); + set_error(socket->errCode, socket->errMsg, HTTP_CLIENT_ESTATUS_SEND_FAILED); close(); return false; } @@ -1363,8 +1340,8 @@ bool HttpClient::send() { return true; } -bool HttpClient::exec(std::string path) { - this->path = path; +bool HttpClient::exec(std::string _path) { + path = _path; // bzero when make a new reqeust reconnected_count = 0; if (defer) { @@ -1378,7 +1355,7 @@ bool HttpClient::recv(double timeout) { if (!wait) { return false; } - if (!socket || !socket->is_connect()) { + if (!socket || !socket->is_connected()) { swoole_set_last_error(SW_ERROR_CLIENT_NO_CONNECTION); zend_update_property_long( swoole_http_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), swoole_get_last_error()); @@ -1426,7 +1403,7 @@ bool HttpClient::recv(double timeout) { void HttpClient::recv(zval *zframe, double timeout) { SW_ASSERT(websocket); ZVAL_FALSE(zframe); - if (!socket || !socket->is_connect()) { + if (!socket || !socket->is_connected()) { swoole_set_last_error(SW_ERROR_CLIENT_NO_CONNECTION); zend_update_property_long( swoole_http_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), swoole_get_last_error()); @@ -1580,7 +1557,7 @@ bool HttpClient::push(zval *zdata, zend_long opcode, uint8_t flags) { HTTP_CLIENT_ESTATUS_CONNECT_FAILED); return false; } - if (!socket || !socket->is_connect()) { + if (!socket || !socket->is_connected()) { swoole_set_last_error(SW_ERROR_CLIENT_NO_CONNECTION); zend_update_property_long( swoole_http_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), swoole_get_last_error()); @@ -1779,7 +1756,7 @@ static PHP_METHOD(swoole_http_client_coro, __construct) { HttpClientObject *hcc = php_swoole_http_client_coro_fetch_object(Z_OBJ_P(ZEND_THIS)); char *host; size_t host_len; - zend_long port = 80; + zend_long port = 0; zend_bool ssl = 0; ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 1, 3) @@ -1807,6 +1784,9 @@ static PHP_METHOD(swoole_http_client_coro, __construct) { RETURN_FALSE; } #endif + if (port == 0) { + port = ssl ? 443 : 80; + } hcc->phc = new HttpClient(ZEND_THIS, std::string(host, host_len), port, ssl); } diff --git a/ext-src/swoole_mysql_coro.cc b/ext-src/swoole_mysql_coro.cc index 2ef85bb3d76..ae4a6477fcb 100644 --- a/ext-src/swoole_mysql_coro.cc +++ b/ext-src/swoole_mysql_coro.cc @@ -191,8 +191,8 @@ class mysql_client { return connect(host, port, ssl); } - inline bool is_connect() { - return socket && socket->is_connect(); + inline bool is_connected() { + return socket && socket->is_connected(); } inline int get_fd() { @@ -200,7 +200,7 @@ class mysql_client { } inline bool check_connection() { - if (sw_unlikely(!is_connect())) { + if (sw_unlikely(!is_connected())) { non_sql_error(MYSQLND_CR_CONNECTION_ERROR, "%s or %s", strerror(ECONNRESET), strerror(ENOTCONN)); return false; } @@ -220,7 +220,7 @@ class mysql_client { } inline bool is_writable() { - return is_connect() && !socket->has_bound(SW_EVENT_WRITE); + return is_connected() && !socket->has_bound(SW_EVENT_WRITE); } bool is_available_for_new_request() { @@ -1011,7 +1011,7 @@ void mysql_client::handle_strict_type(zval *ztext, mysql::field_packet *field) { } void mysql_client::fetch(zval *return_value) { - if (sw_unlikely(!is_connect())) { + if (sw_unlikely(!is_connected())) { RETURN_FALSE; } if (sw_unlikely(state != SW_MYSQL_STATE_QUERY_FETCH)) { @@ -1881,7 +1881,7 @@ static PHP_METHOD(swoole_mysql_coro, fetch) { mc->fetch(return_value); mc->del_timeout_controller(); if (sw_unlikely(Z_TYPE_P(return_value) == IS_FALSE)) { - swoole_mysql_coro_sync_error_properties(ZEND_THIS, mc->get_error_code(), mc->get_error_msg(), mc->is_connect()); + swoole_mysql_coro_sync_error_properties(ZEND_THIS, mc->get_error_code(), mc->get_error_msg(), mc->is_connected()); } } @@ -1898,7 +1898,7 @@ static PHP_METHOD(swoole_mysql_coro, fetchAll) { mc->fetch_all(return_value); mc->del_timeout_controller(); if (sw_unlikely(Z_TYPE_P(return_value) == IS_FALSE)) { - swoole_mysql_coro_sync_error_properties(ZEND_THIS, mc->get_error_code(), mc->get_error_msg(), mc->is_connect()); + swoole_mysql_coro_sync_error_properties(ZEND_THIS, mc->get_error_code(), mc->get_error_msg(), mc->is_connected()); } } @@ -1938,7 +1938,7 @@ static PHP_METHOD(swoole_mysql_coro, prepare) { mc->add_timeout_controller(timeout, Socket::TIMEOUT_RDWR); if (UNEXPECTED(!mc->send_prepare_request(statement, statement_length))) { _failed: - swoole_mysql_coro_sync_error_properties(ZEND_THIS, mc->get_error_code(), mc->get_error_msg(), mc->is_connect()); + swoole_mysql_coro_sync_error_properties(ZEND_THIS, mc->get_error_code(), mc->get_error_msg(), mc->is_connected()); RETVAL_FALSE; } else if (UNEXPECTED(mc->get_defer())) { RETVAL_TRUE; diff --git a/include/swoole_coroutine_socket.h b/include/swoole_coroutine_socket.h index 6af6d937cbe..5329c6fa7de 100644 --- a/include/swoole_coroutine_socket.h +++ b/include/swoole_coroutine_socket.h @@ -69,7 +69,7 @@ class Socket { bool cancel(const enum swEvent_type event); bool close(); - inline bool is_connect() { + inline bool is_connected() { return connected && !closed; } @@ -289,9 +289,11 @@ class Socket { return connect_timeout; } else if (type == TIMEOUT_READ) { return read_timeout; - } else // if (type == TIMEOUT_WRITE) - { + } else if (type == TIMEOUT_WRITE) { return write_timeout; + } else { + assert(0); + return -1; } } @@ -480,10 +482,8 @@ class Socket { if (timeout > 0) { *timer_pp = swoole_timer_add((long) (timeout * 1000), false, callback, socket_); return *timer_pp != nullptr; - } else // if (timeout < 0) - { - *timer_pp = (TimerNode *) -1; } + *timer_pp = (TimerNode *) -1; } return true; } diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index cda5e6be043..50c6a7ba0aa 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -124,6 +124,9 @@ bool Socket::add_event(const enum swEvent_type event) { bool Socket::wait_event(const enum swEvent_type event, const void **__buf, size_t __n) { enum swEvent_type added_event = event; Coroutine *co = Coroutine::get_current_safe(); + if (!co) { + return false; + } // clear the last errCode set_err(0); @@ -156,8 +159,7 @@ bool Socket::wait_event(const enum swEvent_type event, const void **__buf, size_ read_co = co; read_co->yield(); read_co = nullptr; - } else // if (event == SW_EVENT_WRITE) - { + } else if (event == SW_EVENT_WRITE) { if (sw_unlikely(!zero_copy && __n > 0 && *__buf != get_write_buffer()->str)) { write_buffer->clear(); if (write_buffer->append((const char *) *__buf, __n) != SW_OK) { @@ -169,6 +171,9 @@ bool Socket::wait_event(const enum swEvent_type event, const void **__buf, size_ write_co = co; write_co->yield(); write_co = nullptr; + } else { + assert(0); + return false; } _failed: #ifdef SW_USE_OPENSSL @@ -709,6 +714,7 @@ bool Socket::connect(std::string _host, int _port, int flags) { if (connect(_target_addr, socket->info.len) == false) { return false; } + // socks5 proxy if (socks5_proxy && socks5_handshake() == false) { if (errCode == 0) { @@ -1612,7 +1618,7 @@ ssize_t Socket::recv_packet(double timeout) { bool Socket::shutdown(int __how) { set_err(0); - if (!is_connect() || (__how == SHUT_RD && shutdown_read) || (__how == SHUT_WR && shutdown_write)) { + if (!is_connected() || (__how == SHUT_RD && shutdown_read) || (__how == SHUT_WR && shutdown_write)) { errno = ENOTCONN; } else { #ifdef SW_USE_OPENSSL diff --git a/tests/swoole_client_sync/sendto.phpt b/tests/swoole_client_sync/sendto.phpt index 21f237d0cb7..e301c72601c 100644 --- a/tests/swoole_client_sync/sendto.phpt +++ b/tests/swoole_client_sync/sendto.phpt @@ -15,11 +15,11 @@ $pm = new SwooleTest\ProcessManager; $pm->parentFunc = function () use ($pm) { $cli = new Client(SWOOLE_SOCK_UDP); - $cli->sendto('127.0.0.1', $pm->getFreePort(), "packet-1"); - $cli->sendto('localhost', $pm->getFreePort(), "packet-2"); + Assert::true($cli->sendto('127.0.0.1', $pm->getFreePort(), "packet-1")); + Assert::true($cli->sendto('localhost', $pm->getFreePort(), "packet-2")); Assert::false($cli->sendto('error_domain', $pm->getFreePort(), "hello")); Assert::assert($cli->errCode, SWOOLE_ERROR_DNSLOOKUP_RESOLVE_FAILED); - $cli->sendto('localhost', $pm->getFreePort(), "packet-3"); + Assert::true($cli->sendto('localhost', $pm->getFreePort(), "packet-3")); echo "DONE\n"; }; $pm->childFunc = function () use ($pm) { From 842733be4475618f74a046a1ccfdb25b3d73a059 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Wed, 3 Mar 2021 21:11:33 +0800 Subject: [PATCH 066/936] add dtls core-tests, fix enable_ssl_encrypt with DTLS --- core-tests/src/server/server.cpp | 62 ++++++++++++++++++++++++++++++++ include/swoole_client.h | 2 +- src/network/client.cc | 23 +++++++++--- 3 files changed, 81 insertions(+), 6 deletions(-) diff --git a/core-tests/src/server/server.cpp b/core-tests/src/server/server.cpp index c39fc00eec6..4b90421afcb 100644 --- a/core-tests/src/server/server.cpp +++ b/core-tests/src/server/server.cpp @@ -204,6 +204,68 @@ TEST(server, ssl) { delete lock; } + +TEST(server, dtls) { + Server serv(Server::MODE_BASE); + serv.worker_num = 1; + + SwooleG.running = 1; + + sw_logger()->set_level(SW_LOG_WARNING); + + Mutex *lock = new Mutex(Mutex::PROCESS_SHARED); + lock->lock(); + + ListenPort *port = serv.add_port((enum swSocket_type )(SW_SOCK_UDP | SW_SOCK_SSL), TEST_HOST, 0); + if (!port) { + swWarn("listen failed, [error=%d]", swoole_get_last_error()); + exit(2); + } + + port->ssl_set_cert_file(test::get_root_path() + "/tests/include/ssl_certs/server.crt"); + port->ssl_set_key_file(test::get_root_path() + "/tests/include/ssl_certs/server.key"); + port->ssl_init(); + + ASSERT_EQ(serv.create(), SW_OK); + + serv.onStart = [&lock](Server *serv) { + thread t1([=]() { + swSignal_none(); + + lock->lock(); + + ListenPort *port = serv->get_primary_port(); + + EXPECT_EQ(port->ssl, 1); + + swoole::network::SyncClient c(SW_SOCK_UDP); + c.connect(TEST_HOST, port->port); + c.enable_ssl_encrypt(); + c.send(packet, strlen(packet)); + char buf[1024]; + c.recv(buf, sizeof(buf)); + c.close(); + + kill(serv->gs->master_pid, SIGTERM); + }); + t1.detach(); + }; + + serv.onWorkerStart = [&lock](Server *serv, int worker_id) { lock->unlock(); }; + + serv.onReceive = [](Server *serv, RecvData *req) -> int { + EXPECT_EQ(string(req->data, req->info.len), string(packet)); + + string resp = string("Server: ") + string(packet); + serv->send(req->info.fd, resp.c_str(), resp.length()); + + return SW_OK; + }; + + ASSERT_EQ(serv.start(), 0); + + delete lock; +} #endif TEST(server, task_worker) { diff --git a/include/swoole_client.h b/include/swoole_client.h index 13ed459cbdf..66e7abd9710 100644 --- a/include/swoole_client.h +++ b/include/swoole_client.h @@ -191,7 +191,7 @@ class SyncClient { if (connected || !created) { return false; } - if (client.connect(&client, host, port, timeout, 0) < 0) { + if (client.connect(&client, host, port, timeout, client.socket->is_dgram()) < 0) { return false; } connected = true; diff --git a/src/network/client.cc b/src/network/client.cc index ddf783f5a1f..c9d22f0db68 100644 --- a/src/network/client.cc +++ b/src/network/client.cc @@ -267,6 +267,20 @@ int Client::enable_ssl_encrypt() { } ssl_context.reset(new swoole::SSLContext()); open_ssl = true; +#ifdef SW_SUPPORT_DTLS + if (socket->is_dgram()) { + ssl_context->protocols = SW_SSL_DTLS; + socket->dtls = 1; + socket->chunk_size = SW_SSL_BUFFER_SIZE; + send = Client_tcp_send_sync; + recv = Client_tcp_recv_no_buffer; + } +#else + { + swWarn("DTLS support require openssl-1.1 or later"); + return SW_ERR; + } +#endif return SW_OK; } @@ -961,8 +975,7 @@ static int Client_onStreamRead(Reactor *reactor, Event *event) { } else { if (cli->socket->ssl_state == SW_SSL_STATE_READY) { execute_onConnect(cli); - } - else if (cli->socket->ssl_state == SW_SSL_STATE_WAIT_STREAM && cli->socket->ssl_want_write) { + } else if (cli->socket->ssl_state == SW_SSL_STATE_WAIT_STREAM && cli->socket->ssl_want_write) { swoole_event_set(event->socket, SW_EVENT_WRITE); } } @@ -984,7 +997,8 @@ static int Client_onStreamRead(Reactor *reactor, Event *event) { #ifdef SW_USE_OPENSSL if (cli->open_ssl) { if (cli->ssl_handshake() < 0) { - _connect_fail: cli->active = 0; + _connect_fail: + cli->active = 0; cli->close(); if (cli->onError) { cli->onError(cli); @@ -1008,8 +1022,7 @@ static int Client_onStreamRead(Reactor *reactor, Event *event) { } if (cli->socket->ssl_state != SW_SSL_STATE_READY) { return SW_OK; - } - else { + } else { execute_onConnect(cli); return SW_OK; } From 08ea20c7fc688c20a7ad45f494419697c528cd9a Mon Sep 17 00:00:00 2001 From: matyhtf Date: Thu, 4 Mar 2021 16:33:35 +0800 Subject: [PATCH 067/936] fix #4070 --- ext-src/swoole_table.cc | 1 - tests/swoole_table/key_value.phpt | 14 ++++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/ext-src/swoole_table.cc b/ext-src/swoole_table.cc index 35108f20719..e9dead805b4 100644 --- a/ext-src/swoole_table.cc +++ b/ext-src/swoole_table.cc @@ -59,7 +59,6 @@ static inline void php_swoole_table_get_field_value( } else if (col->type == TableColumn::TYPE_FLOAT) { double dval = 0; row->get_value(col, &dval); - add_assoc_double_ex(return_value, col->name.c_str(), col->name.length(), dval); ZVAL_DOUBLE(return_value, dval); } else if (col->type == TableColumn::TYPE_INT) { long lval = 0; diff --git a/tests/swoole_table/key_value.phpt b/tests/swoole_table/key_value.phpt index 7f576414f30..8c82b1e6e7c 100644 --- a/tests/swoole_table/key_value.phpt +++ b/tests/swoole_table/key_value.phpt @@ -6,6 +6,9 @@ swoole_table: key-value operate column('id', swoole_table::TYPE_INT); @@ -16,7 +19,7 @@ if (!$table->create()) { echo __LINE__." error"; } -if (!$table->set('test_key', array('id' => 1, 'name' => 'rango', 'num' => 3.1415926))) +if (!$table->set('test_key', array('id' => 1, 'name' => NAME, 'num' =>PI))) { echo __LINE__." error"; } @@ -33,6 +36,13 @@ if (!($ret and $ret == 1)) echo __LINE__." error"; } +Assert::eq($table->get('test_key', 'name'), NAME); +Assert::eq($table->get('test_key', 'num'), PI); + +// field not exists +Assert::false($table->get('test_key', 'id_no_exists')); +Assert::false($table->get('test_key_no_exists', 'id_no_exists')); + $ret = $table->exist('test_key'); if (!($ret)) { @@ -82,7 +92,7 @@ if ($table->exist('test_key')) { echo __LINE__." error"; } -echo "SUCCESS"; +echo "SUCCESS\n"; ?> --EXPECT-- SUCCESS From b1f35698c5a0cc2080c0691982c315f7396c3d0a Mon Sep 17 00:00:00 2001 From: matyhtf Date: Thu, 4 Mar 2021 16:22:25 +0800 Subject: [PATCH 068/936] Reduce repetitive code --- include/swoole_client.h | 3 +++ src/network/client.cc | 22 ++++++++++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/include/swoole_client.h b/include/swoole_client.h index 66e7abd9710..8d7b2337fb3 100644 --- a/include/swoole_client.h +++ b/include/swoole_client.h @@ -134,6 +134,9 @@ class Client { int socks5_handshake(const char *recv_data, size_t length); #ifdef SW_USE_OPENSSL int enable_ssl_encrypt(); +#ifdef SW_SUPPORT_DTLS + void enable_dtls(); +#endif int ssl_handshake(); int ssl_verify(int allow_self_signed); #endif diff --git a/src/network/client.cc b/src/network/client.cc index c9d22f0db68..c3838c5bd83 100644 --- a/src/network/client.cc +++ b/src/network/client.cc @@ -261,6 +261,16 @@ int Client::socks5_handshake(const char *recv_data, size_t length) { } #ifdef SW_USE_OPENSSL +#ifdef SW_SUPPORT_DTLS +void Client::enable_dtls() { + ssl_context->protocols = SW_SSL_DTLS; + socket->dtls = 1; + socket->chunk_size = SW_SSL_BUFFER_SIZE; + send = Client_tcp_send_sync; + recv = Client_tcp_recv_no_buffer; +} +#endif + int Client::enable_ssl_encrypt() { if (ssl_context) { return SW_ERR; @@ -269,11 +279,7 @@ int Client::enable_ssl_encrypt() { open_ssl = true; #ifdef SW_SUPPORT_DTLS if (socket->is_dgram()) { - ssl_context->protocols = SW_SSL_DTLS; - socket->dtls = 1; - socket->chunk_size = SW_SSL_BUFFER_SIZE; - send = Client_tcp_send_sync; - recv = Client_tcp_recv_no_buffer; + enable_dtls(); } #else { @@ -820,11 +826,7 @@ static int Client_udp_connect(Client *cli, const char *host, int port, double ti #ifdef SW_SUPPORT_DTLS { udp_connect = 1; - cli->ssl_context->protocols = SW_SSL_DTLS; - cli->socket->dtls = 1; - cli->socket->chunk_size = SW_SSL_BUFFER_SIZE; - cli->send = Client_tcp_send_sync; - cli->recv = Client_tcp_recv_no_buffer; + cli->enable_dtls(); } #else { From d78ca8ccf8725af69599d899f5dbe51cfc1824ca Mon Sep 17 00:00:00 2001 From: matyhtf Date: Fri, 5 Mar 2021 13:54:01 +0800 Subject: [PATCH 069/936] fix mem leaks --- ext-src/swoole_table.cc | 4 ++++ include/swoole_table.h | 3 +++ src/memory/table.cc | 7 +++++++ 3 files changed, 14 insertions(+) diff --git a/ext-src/swoole_table.cc b/ext-src/swoole_table.cc index e9dead805b4..c30885c8fbc 100644 --- a/ext-src/swoole_table.cc +++ b/ext-src/swoole_table.cc @@ -109,6 +109,10 @@ static void inline php_swoole_table_set_ptr(zval *zobject, Table *ptr) { } static inline void php_swoole_table_free_object(zend_object *object) { + Table *table = php_swoole_table_fetch_object(object)->ptr; + if (table) { + table->free(); + } zend_object_std_dtor(object); } diff --git a/include/swoole_table.h b/include/swoole_table.h index 8998e8eefd4..40c44fd1605 100644 --- a/include/swoole_table.h +++ b/include/swoole_table.h @@ -162,6 +162,9 @@ class Table { TableRow *get(const char *key, uint16_t keylen, TableRow **rowlock); bool del(const char *key, uint16_t keylen); void forward(); + // only release local memory of the current process + void free(); + // release shared memory void destroy(); bool is_created() { diff --git a/src/memory/table.cc b/src/memory/table.cc index 1af16bc827a..c9c8aa534b7 100644 --- a/src/memory/table.cc +++ b/src/memory/table.cc @@ -57,6 +57,13 @@ Table *Table::make(uint32_t rows_size, float conflict_proportion) { return table; } +void Table::free() { + delete mutex; + delete iterator; + delete column_map; + delete column_list; +} + bool Table::add_column(const std::string &_name, enum TableColumn::Type _type, size_t _size) { if (_type < TableColumn::TYPE_INT || _type > TableColumn::TYPE_STRING) { swWarn("unknown column type"); From 91704aced9f1fa3530128ee33b298e683cade9b7 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Fri, 5 Mar 2021 16:35:09 +0800 Subject: [PATCH 070/936] Allow ssl client to only set certificate --- src/protocol/ssl.cc | 2 + tests/swoole_runtime/ssl/local_cert.phpt | 59 +++++++++++++++++++++++ tests/swoole_runtime/ssl/without_key.phpt | 59 +++++++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 tests/swoole_runtime/ssl/local_cert.phpt create mode 100644 tests/swoole_runtime/ssl/without_key.phpt diff --git a/src/protocol/ssl.cc b/src/protocol/ssl.cc index 18207fb2b58..d4a0e980716 100644 --- a/src/protocol/ssl.cc +++ b/src/protocol/ssl.cc @@ -437,6 +437,8 @@ bool SSLContext::create() { ERR_reason_error_string(error), error); return false; } + } + if (!key_file.empty()) { /* * set the private key from KeyFile (may be the same as CertFile) */ diff --git a/tests/swoole_runtime/ssl/local_cert.phpt b/tests/swoole_runtime/ssl/local_cert.phpt new file mode 100644 index 00000000000..0c9152a00c7 --- /dev/null +++ b/tests/swoole_runtime/ssl/local_cert.phpt @@ -0,0 +1,59 @@ +--TEST-- +swoole_runtime/ssl: client with local_cert/local_pk +--SKIPIF-- + +--FILE-- +\n"; + } else { + $ready->push(true); + $conn = stream_socket_accept($socket); + fwrite($conn, 'The local time is ' . date('n/j/Y g:i a')); + fclose($conn); + fclose($socket); + echo "OK\n"; + } +}); + +go(function () use ($ready) { + $ready->pop(); + + $context = stream_context_create(); + stream_context_set_option($context, 'ssl', 'local_cert', SSL_FILE_DIR . '/client.crt'); + stream_context_set_option($context, 'ssl', 'local_pk', SSL_FILE_DIR . '/client.key'); + + $fp = stream_socket_client("ssl://127.0.0.1:8000", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context); + if (!$fp) { + echo "$errstr ($errno)
\n"; + } else { + $data = fread($fp, 8192); + fclose($fp); + Assert::assert(strpos($data, 'local time') !== false); + echo "OK\n"; + } +}); + +swoole_event_wait(); +?> +--EXPECT-- +OK +OK diff --git a/tests/swoole_runtime/ssl/without_key.phpt b/tests/swoole_runtime/ssl/without_key.phpt new file mode 100644 index 00000000000..a4a4efad647 --- /dev/null +++ b/tests/swoole_runtime/ssl/without_key.phpt @@ -0,0 +1,59 @@ +--TEST-- +swoole_runtime/ssl: client without local_pk +--SKIPIF-- + +--FILE-- +\n"; + } else { + $ready->push(true); + $conn = stream_socket_accept($socket); + fwrite($conn, 'The local time is ' . date('n/j/Y g:i a')); + fclose($conn); + fclose($socket); + echo "OK\n"; + } +}); + +go(function () use ($ready) { + $ready->pop(); + + $context = stream_context_create(); + stream_context_set_option($context, 'ssl', 'local_cert', SSL_FILE_DIR . '/client.crt'); + + $fp = stream_socket_client("ssl://127.0.0.1:8000", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context); + if (!$fp) { + echo "$errstr ($errno)
\n"; + } else { + $data = fread($fp, 8192); + fclose($fp); + Assert::assert(strpos($data, 'local time') !== false); + echo "OK\n"; + } +}); + +swoole_event_wait(); +?> +--EXPECTF-- +Warning: stream_socket_client(): ssl require key file in %s on line %d +OK +OK From 02126e81987bf51832f48a3443d3f3bb570a3ea1 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Thu, 11 Mar 2021 00:12:13 +0000 Subject: [PATCH 071/936] tcp_defer_accept option support for FreeBSD. (#4049) SO_ACCEPTFILER acts similarly as Linux's TCP_DEFER_ACCEPT. --- src/server/port.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/server/port.cc b/src/server/port.cc index be8ec46446a..626e5136dc3 100644 --- a/src/server/port.cc +++ b/src/server/port.cc @@ -166,6 +166,17 @@ int ListenPort::listen() { } #endif +#ifdef SO_ACCEPTFILTER + if (tcp_defer_accept) { + struct accept_filter_arg a; + memset(&a, 0, sizeof(a)); + strcpy(a.af_name, "httpready"); + if (socket->set_option(SOL_SOCKET, SO_ACCEPTFILTER, &a, sizeof(a)) != 0) { + swSysWarn("setsockopt(SO_ACCEPTFILTER) failed"); + } + } +#endif + #ifdef TCP_FASTOPEN if (tcp_fastopen) { if (socket->set_option(IPPROTO_TCP, TCP_FASTOPEN, tcp_fastopen) != 0) { From 295e2703cbc66949622a7cbed43a18b3687b6ac3 Mon Sep 17 00:00:00 2001 From: codinghuang Date: Thu, 11 Mar 2021 20:59:44 +0800 Subject: [PATCH 072/936] Update version for Swoole 4.6.4 (#4083) --- CMakeLists.txt | 2 +- ext-src/php_swoole_library.h | 22 +++++++++--------- include/swoole_version.h | 4 ++-- package.xml | 43 +++++++++++++++++++----------------- 4 files changed, 37 insertions(+), 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 00874627236..e6076086e91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ PROJECT(libswoole) ENABLE_LANGUAGE(ASM) -set(SWOOLE_VERSION 4.6.4-dev) +set(SWOOLE_VERSION 4.6.4) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g") diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index 8b4e4efc131..5770f295562 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: 2d8eaab25259a67bdb984f605d463d0bfb147c3c */ +/* $Id: c0b3306481ecd77cc88ab51ba15403bcc33319a9 */ static const char* swoole_library_source_constants = "\n" @@ -1905,13 +1905,11 @@ static const char* swoole_library_source_core_coroutine_http_functions = "use Swoole\\Coroutine\\Http\\Client\\Exception;\n" "\n" "/**\n" - " * @param $url\n" - " * @param $data\n" - " * @param mixed $method\n" + " * @param mixed $data\n" " * @throws Exception\n" " * @return mixed\n" " */\n" - "function request($url, $method, $data = null, array $options = null, array $headers = null, array $cookies = null)\n" + "function request(string $url, string $method, $data = null, array $options = null, array $headers = null, array $cookies = null)\n" "{\n" " $info = parse_url($url);\n" " if ($info['scheme'] == 'http') {\n" @@ -1934,29 +1932,31 @@ static const char* swoole_library_source_core_coroutine_http_functions = " if (is_array($cookies)) {\n" " $client->setCookies($options);\n" " }\n" - " if ($client->get($info['path'] . '?' . $info['query'])) {\n" + " $request_url = swoole_array_default_value($info, 'path', '/');\n" + " if (!empty($info['query'])) {\n" + " $request_url .= '?' . $info['query'];\n" + " }\n" + " if ($client->execute($request_url)) {\n" " return $client;\n" " }\n" " return false;\n" "}\n" "\n" "/**\n" - " * @param $url\n" - " * @param $data\n" + " * @param mixed $data\n" " * @throws Exception\n" " * @return Client|false|mixed\n" " */\n" - "function post($url, $data, array $options = null, array $headers = null, array $cookies = null)\n" + "function post(string $url, $data, array $options = null, array $headers = null, array $cookies = null)\n" "{\n" " return request($url, 'POST', $data, $options, $headers, $cookies);\n" "}\n" "\n" "/**\n" - " * @param $url\n" " * @throws Exception\n" " * @return Client|false|mixed\n" " */\n" - "function get($url, array $options = null, array $headers = null, array $cookies = null)\n" + "function get(string $url, array $options = null, array $headers = null, array $cookies = null)\n" "{\n" " return request($url, 'GET', null, $options, $headers, $cookies);\n" "}\n"; diff --git a/include/swoole_version.h b/include/swoole_version.h index a167fbfe255..9969b6808d6 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -21,8 +21,8 @@ #define SWOOLE_MAJOR_VERSION 4 #define SWOOLE_MINOR_VERSION 6 #define SWOOLE_RELEASE_VERSION 4 -#define SWOOLE_EXTRA_VERSION "dev" -#define SWOOLE_VERSION "4.6.4-dev" +#define SWOOLE_EXTRA_VERSION "" +#define SWOOLE_VERSION "4.6.4" #define SWOOLE_VERSION_ID 40604 #define SWOOLE_API_VERSION_ID 0x202012a diff --git a/package.xml b/package.xml index ce89d8b2e26..fad66469610 100644 --- a/package.xml +++ b/package.xml @@ -42,10 +42,10 @@ shenzhe163@gmail.com yes - 2021-02-08 - + 2021-03-11 + - 4.6.3 + 4.6.4 4.0 @@ -54,28 +54,24 @@ Apache2.0 - New APIs - --- - + Added Swoole\Coroutine\go function (swoole/library@92fd0de) (@matyhtf) - Enhancement --- - + Added option compression_min_length for HTTP Server (#4033) (@matyhtf) - + Allowed setting content-length HTTP header in application layer (#4041) (@doubaokun) + + Supported ARM 64 build (#4057) (@devnexen) + + Supported set open_http_protocol in Swoole TCP Server (#4063) (@matyhtf) + + Supported ssl client only set certificate (swoole/swoole-src@91704ac) (@matyhtf) + + Supported ssl client only set certificate (swoole/swoole-src@91704ac) (@matyhtf) + * Supported tcp_defer_accept option for FreeBSD (#4049) (@devnexen) Fixed --- - * Fixed coredump when program reach file open limitation (swoole/swoole-src@709813f) (@matyhtf) - * Fixed JIT being disabled (#4029) (@twose) - * Fixed Response::create() bug (swoole/swoole-src@a630b5b) (@matyhtf) - * Fixed task process id false positives (#4040) (@doubaokun) - * Fixed coredump with native curl hook (#4042) (@Yurunsoft) - * Fixed README (#4046) (@asheroto) - * Fixed native-curl crash on PHP8 (#4045) (@matyhtf) - - Kernel - --- - * Optimized ssl_connect/ssl_shutdown (#4030) (@matyhtf) + * Fixed Proxy-Authorization missing when use Coroutine\Http\Client (swoole/swoole-src@edc0552) (@matyhtf) + * Fixed memory allocation issues with Swoole\Table (swoole/swoole-src@3e7770f) (@matyhtf) + * Fixed crash when Coroutine\Http2\Client connects concurrently (swoole/swoole-src@630536d) (@matyhtf) + * Fixed enable_ssl_encrypt with DTLS (swoole/swoole-src@842733b) (@matyhtf) + * Fixed Coroutine\Barrier mem leak (swoole/library#94) (@Appla) (@FMiS) + * Fixed the offset error caused by CURLOPT_PORT and CURLOPT_URL order (swoole/library#96) (@sy-records) + * Fixed Table::get($key, $field) when field type is float (swoole/swoole-src@08ea20c) (@matyhtf) + * Fixed Swoole\Table mem leaks (swoole/swoole-src@d78ca8c) (@matyhtf) @@ -1077,6 +1073,7 @@ + @@ -1543,6 +1540,8 @@ + + @@ -1590,6 +1589,7 @@ + @@ -1825,6 +1825,7 @@ + @@ -1995,12 +1996,14 @@ + + From cf36f69c8e302e8b37db7739a53c30d90c6be580 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Fri, 12 Mar 2021 23:27:31 +0000 Subject: [PATCH 073/936] NetBSD build fix proposal. (#4080) strengthen gethostbyname2_r detection which symbol is indeed present in the libc but not exposed. there is little different for the kqueue API, the private kqueue data is an integral instead. --- config.m4 | 14 +++++++++++++- include/swoole.h | 5 +++++ src/os/msg_queue.cc | 4 ++++ src/os/sendfile.cc | 2 +- src/os/signal.cc | 9 +++++++-- src/reactor/kqueue.cc | 35 +++++++++++++++++++++++++++-------- 6 files changed, 57 insertions(+), 12 deletions(-) diff --git a/config.m4 b/config.m4 index 8193d9d691c..0be38581e67 100644 --- a/config.m4 +++ b/config.m4 @@ -266,6 +266,19 @@ AC_DEFUN([AC_SWOOLE_CHECK_SOCKETS], [ if test "$ac_cv_gai_ai_idn" = yes; then AC_DEFINE(HAVE_AI_IDN,1,[Whether you have AI_IDN]) fi + + AC_CACHE_CHECK([if gethostbyname2_r is supported],[ac_cv_gethostbyname2_r], + [ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include +#include + ]], [[struct hostent s, *res; char ptr[256]; int err; gethostbyname2_r("example.com", AF_INET, &s, ptr, sizeof(ptr), &res, &err);]])], + [ac_cv_gethostbyname2_r=yes], [ac_cv_gethostbyname2_r=no]) + ]) + + if test "$ac_cv_gethostbyname2_r" = yes; then + AC_DEFINE(HAVE_GETHOSTBYNAME2_R,1,[Whether you have gethostbyname2_r]) + fi ]) AC_MSG_CHECKING([if compiling with clang]) @@ -300,7 +313,6 @@ if test "$PHP_SWOOLE" != "no"; then AC_CHECK_LIB(c, inotify_init, AC_DEFINE(HAVE_INOTIFY, 1, [have inotify])) AC_CHECK_LIB(c, malloc_trim, AC_DEFINE(HAVE_MALLOC_TRIM, 1, [have malloc_trim])) AC_CHECK_LIB(c, inotify_init1, AC_DEFINE(HAVE_INOTIFY_INIT1, 1, [have inotify_init1])) - AC_CHECK_LIB(c, gethostbyname2_r, AC_DEFINE(HAVE_GETHOSTBYNAME2_R, 1, [have gethostbyname2_r])) AC_CHECK_LIB(c, ptrace, AC_DEFINE(HAVE_PTRACE, 1, [have ptrace])) AC_CHECK_LIB(c, getrandom, AC_DEFINE(HAVE_GETRANDOM, 1, [have getrandom])) AC_CHECK_LIB(pthread, pthread_rwlock_init, AC_DEFINE(HAVE_RWLOCK, 1, [have pthread_rwlock_init])) diff --git a/include/swoole.h b/include/swoole.h index 9f0b7696a83..62669261fba 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -35,10 +35,15 @@ #define _GNU_SOURCE #endif +#ifndef _PTHREAD_PSHARED +#define _PTHREAD_PSHARED +#endif + /*--- C standard library ---*/ #include #include #include +#include #include #include #include diff --git a/src/os/msg_queue.cc b/src/os/msg_queue.cc index 6fd4074c085..08c00eab24f 100644 --- a/src/os/msg_queue.cc +++ b/src/os/msg_queue.cc @@ -96,7 +96,11 @@ bool MsgQueue::stat(size_t *queue_num, size_t *queue_bytes) { struct msqid_ds __stat; if (msgctl(msg_id_, IPC_STAT, &__stat) == 0) { *queue_num = __stat.msg_qnum; +#ifndef __NetBSD__ *queue_bytes = __stat.msg_cbytes; +#else + *queue_bytes = __stat._msg_cbytes; +#endif return true; } else { return false; diff --git a/src/os/sendfile.cc b/src/os/sendfile.cc index f3fb7a99b8f..90a28a8f612 100644 --- a/src/os/sendfile.cc +++ b/src/os/sendfile.cc @@ -15,7 +15,7 @@ */ #include "swoole.h" -#ifdef HAVE_KQUEUE +#if defined(HAVE_KQUEUE) && defined(HAVE_SENDFILE) #include #include diff --git a/src/os/signal.cc b/src/os/signal.cc index 919a589318b..58b4d153b83 100644 --- a/src/os/signal.cc +++ b/src/os/signal.cc @@ -311,7 +311,7 @@ static swSignalHandler swKqueueSignal_set(int signo, swSignalHandler handler) { if (handler == nullptr) { signal(signo, SIG_DFL); sw_memset_zero(&signals[signo], sizeof(swSignal)); - EV_SET(&ev, signo, EVFILT_SIGNAL, EV_DELETE, 0, 0, nullptr); + EV_SET(&ev, signo, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL); } // add/update signal else { @@ -320,8 +320,13 @@ static swSignalHandler swKqueueSignal_set(int signo, swSignalHandler handler) { signals[signo].handler = handler; signals[signo].signo = signo; signals[signo].activated = true; +#ifndef __NetBSD__ + auto sigptr = &signals[signo]; +#else + auto sigptr = reinterpret_cast(&signals[signo]); +#endif // save swSignal* as udata - EV_SET(&ev, signo, EVFILT_SIGNAL, EV_ADD, 0, 0, &signals[signo]); + EV_SET(&ev, signo, EVFILT_SIGNAL, EV_ADD, 0, 0, sigptr); } int n = kevent(reactor->native_handle, &ev, 1, nullptr, 0, nullptr); if (n < 0 && sw_unlikely(handler)) { diff --git a/src/reactor/kqueue.cc b/src/reactor/kqueue.cc index 5b0e01adc52..2b47b77db66 100644 --- a/src/reactor/kqueue.cc +++ b/src/reactor/kqueue.cc @@ -99,11 +99,17 @@ int ReactorKqueue::add(Socket *socket, int events) { int fd = socket->fd; int fflags = 0; +#ifndef __NetBSD__ + auto sobj = socket; +#else + auto sobj = reinterpret_cast(socket); +#endif + if (Reactor::isset_read_event(events)) { #ifdef NOTE_EOF fflags = NOTE_EOF; #endif - EV_SET(&e, fd, EVFILT_READ, EV_ADD, fflags, 0, socket); + EV_SET(&e, fd, EVFILT_READ, EV_ADD, fflags, 0, sobj); ret = ::kevent(epfd_, &e, 1, nullptr, 0, nullptr); if (ret < 0) { swSysWarn( @@ -113,7 +119,7 @@ int ReactorKqueue::add(Socket *socket, int events) { } if (Reactor::isset_write_event(events)) { - EV_SET(&e, fd, EVFILT_WRITE, EV_ADD, 0, 0, socket); + EV_SET(&e, fd, EVFILT_WRITE, EV_ADD, 0, 0, sobj); ret = ::kevent(epfd_, &e, 1, nullptr, 0, nullptr); if (ret < 0) { swSysWarn( @@ -135,18 +141,24 @@ int ReactorKqueue::set(Socket *socket, int events) { int fd = socket->fd; int fflags = 0; +#ifndef __NetBSD__ + auto sobj = socket; +#else + auto sobj = reinterpret_cast(socket); +#endif + if (Reactor::isset_read_event(events)) { #ifdef NOTE_EOF fflags = NOTE_EOF; #endif - EV_SET(&e, fd, EVFILT_READ, EV_ADD, fflags, 0, socket); + EV_SET(&e, fd, EVFILT_READ, EV_ADD, fflags, 0, sobj); ret = ::kevent(epfd_, &e, 1, nullptr, 0, nullptr); if (ret < 0) { swSysWarn("kqueue->set(%d, SW_EVENT_READ) failed", fd); return SW_ERR; } } else { - EV_SET(&e, fd, EVFILT_READ, EV_DELETE, 0, 0, socket); + EV_SET(&e, fd, EVFILT_READ, EV_DELETE, 0, 0, sobj); ret = ::kevent(epfd_, &e, 1, nullptr, 0, nullptr); if (ret < 0) { swSysWarn("kqueue->del(%d, SW_EVENT_READ) failed", fd); @@ -155,14 +167,14 @@ int ReactorKqueue::set(Socket *socket, int events) { } if (Reactor::isset_write_event(events)) { - EV_SET(&e, fd, EVFILT_WRITE, EV_ADD, 0, 0, socket); + EV_SET(&e, fd, EVFILT_WRITE, EV_ADD, 0, 0, sobj); ret = ::kevent(epfd_, &e, 1, nullptr, 0, nullptr); if (ret < 0) { swSysWarn("kqueue->set(%d, SW_EVENT_WRITE) failed", fd); return SW_ERR; } } else { - EV_SET(&e, fd, EVFILT_WRITE, EV_DELETE, 0, 0, socket); + EV_SET(&e, fd, EVFILT_WRITE, EV_DELETE, 0, 0, sobj); ret = ::kevent(epfd_, &e, 1, nullptr, 0, nullptr); if (ret < 0) { swSysWarn("kqueue->del(%d, SW_EVENT_WRITE) failed", fd); @@ -181,6 +193,13 @@ int ReactorKqueue::del(Socket *socket) { int ret; int fd = socket->fd; +#ifndef __NetBSD__ + auto sobj = socket; +#else + auto sobj = reinterpret_cast(socket); +#endif + + if (socket->removed) { swoole_error_log( SW_LOG_WARNING, SW_ERROR_EVENT_SOCKET_REMOVED, "failed to delete event[%d], has been removed", socket->fd); @@ -188,7 +207,7 @@ int ReactorKqueue::del(Socket *socket) { } if (socket->events & SW_EVENT_READ) { - EV_SET(&e, fd, EVFILT_READ, EV_DELETE, 0, 0, socket); + EV_SET(&e, fd, EVFILT_READ, EV_DELETE, 0, 0, sobj); ret = ::kevent(epfd_, &e, 1, nullptr, 0, nullptr); if (ret < 0) { swSysWarn("kqueue->del(%d, SW_EVENT_READ) failed", fd); @@ -199,7 +218,7 @@ int ReactorKqueue::del(Socket *socket) { } if (socket->events & SW_EVENT_WRITE) { - EV_SET(&e, fd, EVFILT_WRITE, EV_DELETE, 0, 0, socket); + EV_SET(&e, fd, EVFILT_WRITE, EV_DELETE, 0, 0, sobj); ret = ::kevent(epfd_, &e, 1, nullptr, 0, nullptr); if (ret < 0) { after_removal_failure(socket); From 8a9a3947211cd4e1ba3d5ffb66b2e6df9fccd5b8 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Fri, 12 Mar 2021 23:28:07 +0000 Subject: [PATCH 074/936] enable asm context on BSD. (#4082) only NetBSD does not support note.GNU-stack segment. --- config.m4 | 12 +++++++----- thirdparty/boost/asm/combined.S | 4 ++-- thirdparty/boost/asm/jump_arm64_aapcs_elf_gas.S | 2 ++ thirdparty/boost/asm/jump_arm_aapcs_elf_gas.S | 2 ++ thirdparty/boost/asm/jump_ppc32_sysv_elf_gas.S | 2 ++ thirdparty/boost/asm/jump_ppc64_sysv_elf_gas.S | 2 ++ thirdparty/boost/asm/jump_x86_64_sysv_elf_gas.S | 2 ++ thirdparty/boost/asm/make_arm64_aapcs_elf_gas.S | 2 ++ thirdparty/boost/asm/make_arm_aapcs_elf_gas.S | 2 ++ thirdparty/boost/asm/make_ppc32_sysv_elf_gas.S | 2 ++ thirdparty/boost/asm/make_ppc64_sysv_elf_gas.S | 2 ++ thirdparty/boost/asm/make_x86_64_sysv_elf_gas.S | 2 ++ 12 files changed, 29 insertions(+), 7 deletions(-) diff --git a/config.m4 b/config.m4 index 0be38581e67..8724227329d 100644 --- a/config.m4 +++ b/config.m4 @@ -439,6 +439,7 @@ if test "$PHP_SWOOLE" != "no"; then [cygwin*], [SW_OS="CYGWIN"], [mingw*], [SW_OS="MINGW"], [linux*], [SW_OS="LINUX"], + [*bsd*], [SW_OS="BSD"], [] ) @@ -623,6 +624,7 @@ if test "$PHP_SWOOLE" != "no"; then AS_CASE([$host_cpu], [x86_64*], [SW_CPU="x86_64"], + [amd64*], [SW_CPU="x86_64"], [x86*], [SW_CPU="x86"], [i?86*], [SW_CPU="x86"], [arm*], [SW_CPU="arm"], @@ -637,25 +639,25 @@ if test "$PHP_SWOOLE" != "no"; then if test "$SW_OS" = "MAC"; then SW_CONTEXT_ASM_FILE="combined_sysv_macho_gas.S" elif test "$SW_CPU" = "x86_64"; then - if test "$SW_OS" = "LINUX"; then + if test "$SW_OS" = "LINUX" || test "$SW_OS" = "BSD"; then SW_CONTEXT_ASM_FILE="x86_64_sysv_elf_gas.S" else SW_USE_ASM_CONTEXT="no" fi elif test "$SW_CPU" = "x86"; then - if test "$SW_OS" = "LINUX"; then + if test "$SW_OS" = "LINUX" || test "$SW_OS" = "BSD"; then SW_CONTEXT_ASM_FILE="i386_sysv_elf_gas.S" else SW_USE_ASM_CONTEXT="no" fi elif test "$SW_CPU" = "arm"; then - if test "$SW_OS" = "LINUX"; then + if test "$SW_OS" = "LINUX" || test "$SW_OS" = "BSD"; then SW_CONTEXT_ASM_FILE="arm_aapcs_elf_gas.S" else SW_USE_ASM_CONTEXT="no" fi elif test "$SW_CPU" = "arm64"; then - if test "$SW_OS" = "LINUX"; then + if test "$SW_OS" = "LINUX" || test "$SW_OS" = "BSD"; then SW_CONTEXT_ASM_FILE="arm64_aapcs_elf_gas.S" else SW_USE_ASM_CONTEXT="no" @@ -667,7 +669,7 @@ if test "$PHP_SWOOLE" != "no"; then SW_USE_ASM_CONTEXT="no" fi elif test "$SW_CPU" = "ppc64"; then - if test "$SW_OS" = "LINUX"; then + if test "$SW_OS" = "LINUX" || test "$SW_OS" = "BSD"; then SW_CONTEXT_ASM_FILE="ppc64_sysv_elf_gas.S" else SW_USE_ASM_CONTEXT="no" diff --git a/thirdparty/boost/asm/combined.S b/thirdparty/boost/asm/combined.S index cbe77512e37..35fd2098b8e 100644 --- a/thirdparty/boost/asm/combined.S +++ b/thirdparty/boost/asm/combined.S @@ -1,4 +1,4 @@ -#ifdef __linux__ +#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) #if defined(__i386__) #include "make_i386_sysv_elf_gas.S" #include "jump_i386_sysv_elf_gas.S" @@ -25,4 +25,4 @@ #include "jump_combined_sysv_macho_gas.S" #else #error "not supports" -#endif \ No newline at end of file +#endif diff --git a/thirdparty/boost/asm/jump_arm64_aapcs_elf_gas.S b/thirdparty/boost/asm/jump_arm64_aapcs_elf_gas.S index 09bd7b52259..52821a9b9eb 100644 --- a/thirdparty/boost/asm/jump_arm64_aapcs_elf_gas.S +++ b/thirdparty/boost/asm/jump_arm64_aapcs_elf_gas.S @@ -127,5 +127,7 @@ jump_fcontext: ret x4 .size jump_fcontext,.-jump_fcontext +#ifndef __NetBSD__ # Mark that we don't need executable stack. .section .note.GNU-stack,"",%progbits +#endif diff --git a/thirdparty/boost/asm/jump_arm_aapcs_elf_gas.S b/thirdparty/boost/asm/jump_arm_aapcs_elf_gas.S index 3019aeb49dc..7ad3c695ea7 100644 --- a/thirdparty/boost/asm/jump_arm_aapcs_elf_gas.S +++ b/thirdparty/boost/asm/jump_arm_aapcs_elf_gas.S @@ -89,5 +89,7 @@ jump_fcontext: pop {v1-v8,lr,pc} .size jump_fcontext,.-jump_fcontext +#ifndef __NetBSD__ @ Mark that we don't need executable stack. .section .note.GNU-stack,"",%progbits +#endif diff --git a/thirdparty/boost/asm/jump_ppc32_sysv_elf_gas.S b/thirdparty/boost/asm/jump_ppc32_sysv_elf_gas.S index d5380d50f23..f3c799237c6 100644 --- a/thirdparty/boost/asm/jump_ppc32_sysv_elf_gas.S +++ b/thirdparty/boost/asm/jump_ppc32_sysv_elf_gas.S @@ -204,5 +204,7 @@ jump_fcontext: bctr .size jump_fcontext, .-jump_fcontext +#ifndef __NetBSD__ /* Mark that we don't need executable stack. */ .section .note.GNU-stack,"",%progbits +#endif diff --git a/thirdparty/boost/asm/jump_ppc64_sysv_elf_gas.S b/thirdparty/boost/asm/jump_ppc64_sysv_elf_gas.S index 46bc3cc2c81..bd7bc9f6779 100644 --- a/thirdparty/boost/asm/jump_ppc64_sysv_elf_gas.S +++ b/thirdparty/boost/asm/jump_ppc64_sysv_elf_gas.S @@ -263,5 +263,7 @@ jump_fcontext: #endif +#ifndef __NetBSD__ /* Mark that we don't need executable stack. */ .section .note.GNU-stack,"",%progbits +#endif diff --git a/thirdparty/boost/asm/jump_x86_64_sysv_elf_gas.S b/thirdparty/boost/asm/jump_x86_64_sysv_elf_gas.S index ac555319e93..893b094be00 100644 --- a/thirdparty/boost/asm/jump_x86_64_sysv_elf_gas.S +++ b/thirdparty/boost/asm/jump_x86_64_sysv_elf_gas.S @@ -94,5 +94,7 @@ jump_fcontext: jmp *%r8 .size jump_fcontext,.-jump_fcontext +#ifndef __NetBSD__ /* Mark that we don't need executable stack. */ .section .note.GNU-stack,"",%progbits +#endif diff --git a/thirdparty/boost/asm/make_arm64_aapcs_elf_gas.S b/thirdparty/boost/asm/make_arm64_aapcs_elf_gas.S index b208ab7f39d..5fa092eef5d 100644 --- a/thirdparty/boost/asm/make_arm64_aapcs_elf_gas.S +++ b/thirdparty/boost/asm/make_arm64_aapcs_elf_gas.S @@ -81,5 +81,7 @@ finish: bl _exit .size make_fcontext,.-make_fcontext +#ifndef __NetBSD__ # Mark that we don't need executable stack. .section .note.GNU-stack,"",%progbits +#endif diff --git a/thirdparty/boost/asm/make_arm_aapcs_elf_gas.S b/thirdparty/boost/asm/make_arm_aapcs_elf_gas.S index 9877655161b..1606dbb0fd8 100644 --- a/thirdparty/boost/asm/make_arm_aapcs_elf_gas.S +++ b/thirdparty/boost/asm/make_arm_aapcs_elf_gas.S @@ -67,5 +67,7 @@ finish: bl _exit@PLT .size make_fcontext,.-make_fcontext +#ifndef __NetBSD__ @ Mark that we don't need executable stack. .section .note.GNU-stack,"",%progbits +#endif diff --git a/thirdparty/boost/asm/make_ppc32_sysv_elf_gas.S b/thirdparty/boost/asm/make_ppc32_sysv_elf_gas.S index 30ce473c9eb..043bc4ac4e1 100644 --- a/thirdparty/boost/asm/make_ppc32_sysv_elf_gas.S +++ b/thirdparty/boost/asm/make_ppc32_sysv_elf_gas.S @@ -119,5 +119,7 @@ finish: bl _exit@plt .size make_fcontext, .-make_fcontext +#ifndef __NetBSD__ /* Mark that we don't need executable stack. */ .section .note.GNU-stack,"",%progbits +#endif diff --git a/thirdparty/boost/asm/make_ppc64_sysv_elf_gas.S b/thirdparty/boost/asm/make_ppc64_sysv_elf_gas.S index b777fe69b9e..35c49442406 100644 --- a/thirdparty/boost/asm/make_ppc64_sysv_elf_gas.S +++ b/thirdparty/boost/asm/make_ppc64_sysv_elf_gas.S @@ -185,5 +185,7 @@ finish: # endif #endif +#ifndef __NetBSD__ /* Mark that we don't need executable stack. */ .section .note.GNU-stack,"",%progbits +#endif diff --git a/thirdparty/boost/asm/make_x86_64_sysv_elf_gas.S b/thirdparty/boost/asm/make_x86_64_sysv_elf_gas.S index b6878795846..335117a22ee 100644 --- a/thirdparty/boost/asm/make_x86_64_sysv_elf_gas.S +++ b/thirdparty/boost/asm/make_x86_64_sysv_elf_gas.S @@ -71,5 +71,7 @@ finish: hlt .size make_fcontext,.-make_fcontext +#ifndef __NetBSD__ /* Mark that we don't need executable stack. */ .section .note.GNU-stack,"",%progbits +#endif From 72c56c3a9c44624262d8b7b3e3b5a934f7720341 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Fri, 12 Mar 2021 23:31:31 +0000 Subject: [PATCH 075/936] using arc4random api as alternative backend for swoole_random_bytes, (#4096) lessening file descriptor usage in the process too. --- config.m4 | 1 + src/core/base.cc | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/config.m4 b/config.m4 index 8724227329d..bf752887393 100644 --- a/config.m4 +++ b/config.m4 @@ -315,6 +315,7 @@ if test "$PHP_SWOOLE" != "no"; then AC_CHECK_LIB(c, inotify_init1, AC_DEFINE(HAVE_INOTIFY_INIT1, 1, [have inotify_init1])) AC_CHECK_LIB(c, ptrace, AC_DEFINE(HAVE_PTRACE, 1, [have ptrace])) AC_CHECK_LIB(c, getrandom, AC_DEFINE(HAVE_GETRANDOM, 1, [have getrandom])) + AC_CHECK_LIB(c, arc4random, AC_DEFINE(HAVE_ARC4RANDOM, 1, [have arc4random])) AC_CHECK_LIB(pthread, pthread_rwlock_init, AC_DEFINE(HAVE_RWLOCK, 1, [have pthread_rwlock_init])) AC_CHECK_LIB(pthread, pthread_spin_lock, AC_DEFINE(HAVE_SPINLOCK, 1, [have pthread_spin_lock])) AC_CHECK_LIB(pthread, pthread_mutex_timedlock, AC_DEFINE(HAVE_MUTEX_TIMEDLOCK, 1, [have pthread_mutex_timedlock])) diff --git a/src/core/base.cc b/src/core/base.cc index f60d277f46c..def5efdfc2c 100644 --- a/src/core/base.cc +++ b/src/core/base.cc @@ -56,6 +56,10 @@ using swoole::String; #include #else static ssize_t getrandom(void *buffer, size_t size, unsigned int __flags) { +#ifdef HAVE_ARC4RANDOM + arc4random_buf(buffer, size); + return size; +#else int fd = open("/dev/urandom", O_RDONLY); if (fd < 0) { return -1; @@ -73,6 +77,7 @@ static ssize_t getrandom(void *buffer, size_t size, unsigned int __flags) { close(fd); return read_bytes; +#endif } #endif From d313a45c6f5a82f58ff2a4a33b377000c2c8eeb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Sat, 13 Mar 2021 21:34:08 +0800 Subject: [PATCH 076/936] Support native curl multi (#4093) * Hook curl_multi_init * Hook curl_multi_add_handle * Hook curl_multi_exec * Hook curl_multi_remove_handle and curl_multi_close * support curl_multi * fix * fix 2 * fix 3, add tests * fix * Create multiple curl-multi instances * optimize code * fix * Fix wrong arg info * Restore arg_info If arg_info is not restored, it will result in double free. Co-authored-by: codinghuang --- config.m4 | 1 + examples/curl/multi.php | 62 ++ ext-src/swoole_runtime.cc | 15 + tests/swoole_runtime/curl_native/multi.phpt | 60 ++ thirdparty/php/curl/curl_arginfo.h | 49 ++ thirdparty/php/curl/curl_interface.h | 9 + thirdparty/php/curl/curl_multi.h | 83 ++- thirdparty/php/curl/curl_private.h | 20 +- thirdparty/php/curl/interface.cc | 113 ++-- thirdparty/php/curl/multi.cc | 664 ++++++++++++++++++++ thirdparty/php/curl/php_curl.h | 3 +- 11 files changed, 1010 insertions(+), 69 deletions(-) create mode 100644 examples/curl/multi.php create mode 100644 tests/swoole_runtime/curl_native/multi.phpt create mode 100644 thirdparty/php/curl/multi.cc diff --git a/config.m4 b/config.m4 index bf752887393..aec9dd60d1d 100644 --- a/config.m4 +++ b/config.m4 @@ -594,6 +594,7 @@ if test "$PHP_SWOOLE" != "no"; then swoole_source_file="$swoole_source_file \ thirdparty/php/curl/interface.cc \ + thirdparty/php/curl/multi.cc \ thirdparty/php/sockets/multicast.cc \ thirdparty/php/sockets/sendrecvmsg.cc \ thirdparty/php/sockets/conversions.cc \ diff --git a/examples/curl/multi.php b/examples/curl/multi.php new file mode 100644 index 00000000000..b53dda2f2f0 --- /dev/null +++ b/examples/curl/multi.php @@ -0,0 +1,62 @@ +fci_cache); } rf->function->internal_function.handler = rf->ori_handler; + rf->function->internal_function.arg_info = rf->ori_arg_info; efree(rf); } ZEND_HASH_FOREACH_END(); @@ -1402,6 +1403,14 @@ bool PHPCoroutine::enable_hook(uint32_t flags) { SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_pause); SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_escape); SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_unescape); + + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_init); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_add_handle); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_exec); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_select); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_getcontent); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_remove_handle); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_close); } } else { if (runtime_hook_flags & PHPCoroutine::HOOK_NATIVE_CURL) { @@ -1418,6 +1427,12 @@ bool PHPCoroutine::enable_hook(uint32_t flags) { SW_UNHOOK_FUNC(curl_pause); SW_UNHOOK_FUNC(curl_escape); SW_UNHOOK_FUNC(curl_unescape); + + SW_UNHOOK_FUNC(curl_multi_init); + SW_UNHOOK_FUNC(curl_multi_add_handle); + SW_UNHOOK_FUNC(curl_multi_exec); + SW_UNHOOK_FUNC(curl_multi_remove_handle); + SW_UNHOOK_FUNC(curl_multi_close); } } #endif diff --git a/tests/swoole_runtime/curl_native/multi.phpt b/tests/swoole_runtime/curl_native/multi.phpt new file mode 100644 index 00000000000..84cd138808d --- /dev/null +++ b/tests/swoole_runtime/curl_native/multi.phpt @@ -0,0 +1,60 @@ +--TEST-- +swoole_runtime/curl_native: multi +--SKIPIF-- + +--FILE-- + +--EXPECT-- +Done diff --git a/thirdparty/php/curl/curl_arginfo.h b/thirdparty/php/curl/curl_arginfo.h index 261776dbdbe..1a9135676db 100644 --- a/thirdparty/php/curl/curl_arginfo.h +++ b/thirdparty/php/curl/curl_arginfo.h @@ -52,6 +52,43 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_swoole_native_curl_init, 0, ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, url, IS_STRING, 1, "null") ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_swoole_native_curl_multi_add_handle, 0, 2, IS_LONG, 0) + ZEND_ARG_OBJ_INFO(0, multi_handle, Swoole\\Coroutine\\Curl\\MultiHandle, 0) + ZEND_ARG_OBJ_INFO(0, handle, Swoole\\Coroutine\\Curl\\Handle, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_swoole_native_curl_multi_close, 0, 1, IS_VOID, 0) + ZEND_ARG_OBJ_INFO(0, multi_handle, Swoole\\Coroutine\\Curl\\MultiHandle, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_swoole_native_curl_multi_errno, 0, 1, IS_LONG, 0) + ZEND_ARG_OBJ_INFO(0, multi_handle, Swoole\\Coroutine\\Curl\\MultiHandle, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_swoole_native_curl_multi_exec, 0, 2, IS_LONG, 0) + ZEND_ARG_OBJ_INFO(0, multi_handle, Swoole\\Coroutine\\Curl\\MultiHandle, 0) + ZEND_ARG_INFO(1, still_running) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_swoole_native_curl_multi_getcontent, 0, 1, IS_STRING, 1) + ZEND_ARG_OBJ_INFO(0, handle, Swoole\\Coroutine\\Curl\\Handle, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_swoole_native_curl_multi_info_read, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE) + ZEND_ARG_OBJ_INFO(0, multi_handle, Swoole\\Coroutine\\Curl\\MultiHandle, 0) + ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, queued_messages, "null") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_swoole_native_curl_multi_init, 0, 0, Swoole\\Coroutine\\Curl\\MultiHandle, 0) +ZEND_END_ARG_INFO() + +#define arginfo_swoole_native_curl_multi_remove_handle arginfo_swoole_native_curl_multi_add_handle + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_swoole_native_curl_multi_select, 0, 1, IS_LONG, 0) + ZEND_ARG_OBJ_INFO(0, multi_handle, Swoole\\Coroutine\\Curl\\MultiHandle, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, timeout, IS_DOUBLE, 0, "1.0") +ZEND_END_ARG_INFO() + #if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_swoole_native_curl_pause, 0, 2, IS_LONG, 0) ZEND_ARG_OBJ_INFO(0, handle, Swoole\\Coroutine\\Curl\\Handle, 0) @@ -92,6 +129,18 @@ static const zend_function_entry swoole_native_curl_functions[] = { #if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */ PHP_FE(swoole_native_curl_pause, arginfo_swoole_native_curl_pause) #endif + + PHP_FE(swoole_native_curl_multi_add_handle, arginfo_swoole_native_curl_multi_add_handle) + PHP_FE(swoole_native_curl_multi_close, arginfo_swoole_native_curl_multi_close) + PHP_FE(swoole_native_curl_multi_errno, arginfo_swoole_native_curl_multi_errno) + PHP_FE(swoole_native_curl_multi_exec, arginfo_swoole_native_curl_multi_exec) + PHP_FE(swoole_native_curl_multi_select, arginfo_swoole_native_curl_multi_select) + PHP_FE(swoole_native_curl_multi_getcontent, arginfo_swoole_native_curl_multi_getcontent) + PHP_FE(swoole_native_curl_multi_info_read, arginfo_swoole_native_curl_multi_info_read) + PHP_FE(swoole_native_curl_multi_init, arginfo_swoole_native_curl_multi_init) + PHP_FE(swoole_native_curl_multi_remove_handle, arginfo_swoole_native_curl_multi_remove_handle) + + PHP_FE_END }; #endif diff --git a/thirdparty/php/curl/curl_interface.h b/thirdparty/php/curl/curl_interface.h index c9448db77df..8f36226ff17 100644 --- a/thirdparty/php/curl/curl_interface.h +++ b/thirdparty/php/curl/curl_interface.h @@ -33,5 +33,14 @@ PHP_FUNCTION(swoole_native_curl_unescape); #if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */ PHP_FUNCTION(swoole_native_curl_pause); #endif +PHP_FUNCTION(swoole_native_curl_multi_add_handle); +PHP_FUNCTION(swoole_native_curl_multi_close); +PHP_FUNCTION(swoole_native_curl_multi_errno); +PHP_FUNCTION(swoole_native_curl_multi_exec); +PHP_FUNCTION(swoole_native_curl_multi_select); +PHP_FUNCTION(swoole_native_curl_multi_remove_handle); +PHP_FUNCTION(swoole_native_curl_multi_getcontent); +PHP_FUNCTION(swoole_native_curl_multi_info_read); +PHP_FUNCTION(swoole_native_curl_multi_init); SW_EXTERN_C_END #endif diff --git a/thirdparty/php/curl/curl_multi.h b/thirdparty/php/curl/curl_multi.h index b313b0c88cd..4098a7f163b 100644 --- a/thirdparty/php/curl/curl_multi.h +++ b/thirdparty/php/curl/curl_multi.h @@ -13,9 +13,8 @@ | Author: Tianfeng Han | +----------------------------------------------------------------------+ */ -#pragma once -#ifdef SW_USE_CURL +#pragma once #include "php_swoole_cxx.h" #include "swoole_util.h" @@ -23,6 +22,7 @@ SW_EXTERN_C_BEGIN #include +#include #include "curl_private.h" @@ -32,9 +32,16 @@ namespace swoole { using network::Socket; +struct MultiSelector { + bool defer_callback = false; + int event_count = 0; + FutureTask context; +}; + class cURLMulti { CURLM *handle; TimerNode *timer = nullptr; + MultiSelector *selector = nullptr; void read_info(); @@ -47,8 +54,9 @@ class cURLMulti { Socket *socket = new Socket(); socket->fd = sockfd; socket->removed = 1; + socket->object = this; socket->fd_type = (enum swFd_type) PHP_SWOOLE_FD_CO_CURL; - curl_multi_assign(handle, sockfd, (void*) socket); + curl_multi_assign(handle, sockfd, (void *) socket); return socket; } @@ -57,7 +65,7 @@ class cURLMulti { } void set_event(void *socket_ptr, curl_socket_t sockfd, int action) { - Socket *socket = socket_ptr ? (Socket*) socket_ptr : create_socket(sockfd); + Socket *socket = socket_ptr ? (Socket *) socket_ptr : create_socket(sockfd); int events = 0; if (action != CURL_POLL_IN) { events |= SW_EVENT_WRITE; @@ -73,7 +81,7 @@ class cURLMulti { } void del_event(void *socket_ptr, curl_socket_t sockfd) { - Socket *socket = (Socket*) socket_ptr; + Socket *socket = (Socket *) socket_ptr; socket->silent_remove = 1; if (socket->events && swoole_event_is_available()) { swoole_event_del(socket); @@ -88,9 +96,8 @@ class cURLMulti { swoole_timer_del(timer); } - timer = swoole_timer_add(timeout_ms, false, [this](Timer *timer, TimerNode *tnode) { - socket_action(CURL_SOCKET_TIMEOUT, 0); - }); + timer = swoole_timer_add( + timeout_ms, false, [this](Timer *timer, TimerNode *tnode) { socket_action(CURL_SOCKET_TIMEOUT, 0); }); } void del_timer() { @@ -99,11 +106,17 @@ class cURLMulti { } } - public: + public: cURLMulti() { handle = curl_multi_init(); curl_multi_setopt(handle, CURLMOPT_SOCKETFUNCTION, handle_socket); curl_multi_setopt(handle, CURLMOPT_TIMERFUNCTION, handle_timeout); + curl_multi_setopt(handle, CURLMOPT_SOCKETDATA, this); + curl_multi_setopt(handle, CURLMOPT_TIMERDATA, this); + } + + CURLM *get_multi_handle() { + return handle; } CURLcode exec(php_curl *ch) { @@ -116,7 +129,7 @@ class cURLMulti { zval _return_value; zval *return_value = &_return_value; - FutureTask *context = (FutureTask*) emalloc(sizeof(FutureTask)); + FutureTask *context = (FutureTask *) emalloc(sizeof(FutureTask)); ON_SCOPE_EXIT { efree(context); }; @@ -127,10 +140,54 @@ class cURLMulti { return (CURLcode) Z_LVAL_P(return_value); } + CURLMcode select(php_curlm *mh) { + Coroutine::get_current_safe(); + + zval _return_value; + zval *return_value = &_return_value; + + MultiSelector task{}; + selector = &task; + + auto set_context_fn = [mh](FutureTask *ctx) { + for (zend_llist_element *element = mh->easyh.head; element; element = element->next) { + zval *z_ch = (zval *) element->data; + php_curl *ch; + if ((ch = _php_curl_get_handle(z_ch, false)) == NULL) { + continue; + } + ch->context = ctx; + } + }; + + set_context_fn(&task.context); + PHPCoroutine::yield_m(return_value, &task.context); + set_context_fn(nullptr); + selector = nullptr; + + return (CURLMcode) Z_LVAL_P(return_value); + } + void socket_action(int fd, int event_bitmask) { int running_handles; curl_multi_socket_action(handle, fd, event_bitmask, &running_handles); - read_info(); + + // for curl_multi_select + if (selector) { + selector->event_count++; + if (!selector->defer_callback) { + selector->defer_callback = true; + swoole_event_defer( + [this](void *data) { + zval result; + ZVAL_LONG(&result, selector->event_count); + PHPCoroutine::resume_m(&selector->context, &result); + }, + nullptr); + } + } else { + read_info(); + } } static int cb_readable(Reactor *reactor, Event *event); @@ -139,6 +196,4 @@ class cURLMulti { static int handle_socket(CURL *easy, curl_socket_t s, int action, void *userp, void *socketp); static int handle_timeout(CURLM *multi, long timeout_ms, void *userp); }; -} - -#endif +} // namespace swoole diff --git a/thirdparty/php/curl/curl_private.h b/thirdparty/php/curl/curl_private.h index c38520ee812..9df278e481a 100644 --- a/thirdparty/php/curl/curl_private.h +++ b/thirdparty/php/curl/curl_private.h @@ -129,9 +129,13 @@ typedef struct { php_curlm_server_push *server_push; } php_curlm_handlers; +namespace swoole { +class cURLMulti; +} + typedef struct { int still_running; - CURLM *multi; + swoole::cURLMulti *multi; zend_llist easyh; php_curlm_handlers *handlers; struct { @@ -167,8 +171,22 @@ static inline php_curlsh *curl_share_from_obj(zend_object *obj) { } #define Z_CURL_SHARE_P(zv) curl_share_from_obj(Z_OBJ_P(zv)) +void curl_multi_register_class(const zend_function_entry *method_entries); int curl_cast_object(zend_object *obj, zval *result, int type); +#else +#define Z_CURL_P(zv) _php_curl_get_handle(zv) +#endif /* PHP8 end */ + +php_curl *_php_curl_get_handle(zval *zid, bool exclusive = true); + +SW_EXTERN_C_BEGIN +#if PHP_VERSION_ID < 80000 +void _php_curl_close_ex(php_curl *ch); +void _php_curl_close(zend_resource *rsrc); +void _php_curl_multi_close(zend_resource *rsrc); +php_curl *alloc_curl_handle(); #endif +SW_EXTERN_C_END #endif /* _PHP_CURL_PRIVATE_H */ #endif diff --git a/thirdparty/php/curl/interface.cc b/thirdparty/php/curl/interface.cc index 0d8ce786880..b83651db475 100644 --- a/thirdparty/php/curl/interface.cc +++ b/thirdparty/php/curl/interface.cc @@ -87,14 +87,16 @@ static zend_object_handlers swoole_native_curl_exception_handlers; #if PHP_VERSION_ID < 80000 static int le_curl; -#endif +static int le_curl_multi_handle; -static php_curl *get_curl_handle(zval *zid, bool exclusive = true); +int _php_curl_get_le_curl() { + return le_curl; +} + +int _php_curl_get_le_curl_multi() { + return le_curl_multi_handle; +} -#if PHP_VERSION_ID < 80000 -static void _php_curl_close_ex(php_curl *ch); -static void _php_curl_close(zend_resource *rsrc); -static php_curl *alloc_curl_handle(); #endif #define CAAL(s, v) add_assoc_long_ex(return_value, s, sizeof(s) - 1, (zend_long) v); @@ -110,6 +112,23 @@ static php_curl *alloc_curl_handle(); # define php_curl_ret(__ret) RETVAL_FALSE; return; #endif +php_curl *_php_curl_get_handle(zval *zid, bool exclusive) { + php_curl *ch; +#if PHP_VERSION_ID >= 80000 + ch = Z_CURL_P(zid); +#else + if ((ch = (php_curl*) zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { + swFatalError(SW_ERROR_INVALID_PARAMS, "The cURL client is executing, this handle cannot be operated"); + return nullptr; + } +#endif + if (exclusive && ch->context) { + swFatalError(SW_ERROR_CO_HAS_BEEN_BOUND, "The cURL client is executing, this handle cannot be operated"); + return nullptr; + } + return ch; +} + static int php_curl_option_str(php_curl *ch, zend_long option, const char *str, const size_t len, zend_bool make_copy) { long error = CURLE_OK; @@ -266,38 +285,43 @@ php_curl *init_curl_handle_into_zval(zval *curl); static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields); +SW_EXTERN_C_END + static cURLMulti *g_curl_multi = nullptr; -static inline cURLMulti *sw_curl_multi() { +cURLMulti *sw_curl_multi() { return g_curl_multi; } -SW_EXTERN_C_END int cURLMulti::cb_readable(Reactor *reactor, Event *event) { - sw_curl_multi()->socket_action(event->fd, CURL_CSELECT_IN); + cURLMulti *multi = (cURLMulti *) event->socket->object; + multi->socket_action(event->fd, CURL_CSELECT_IN); return 0; } int cURLMulti::cb_writable(Reactor *reactor, Event *event) { - sw_curl_multi()->socket_action(event->fd, CURL_CSELECT_OUT); + cURLMulti *multi = (cURLMulti *) event->socket->object; + multi->socket_action(event->fd, CURL_CSELECT_OUT); return 0; } int cURLMulti::cb_error(Reactor *reactor, Event *event) { - sw_curl_multi()->socket_action(event->fd, CURL_CSELECT_ERR); + cURLMulti *multi = (cURLMulti *) event->socket->object; + multi->socket_action(event->fd, CURL_CSELECT_ERR); return 0; } int cURLMulti::handle_socket(CURL *easy, curl_socket_t s, int action, void *userp, void *socketp) { + cURLMulti *multi = (cURLMulti *) userp; switch (action) { case CURL_POLL_IN: case CURL_POLL_OUT: case CURL_POLL_INOUT: - sw_curl_multi()->set_event(socketp, s, action); + multi->set_event(socketp, s, action); break; case CURL_POLL_REMOVE: if (socketp) { - sw_curl_multi()->del_event(socketp, s); + multi->del_event(socketp, s); } break; default: @@ -334,14 +358,15 @@ void cURLMulti::read_info() { } } -int cURLMulti::handle_timeout(CURLM *multi, long timeout_ms, void *userp) { +int cURLMulti::handle_timeout(CURLM *mh, long timeout_ms, void *userp) { + cURLMulti *multi = (cURLMulti *) userp; if (timeout_ms < 0) { - sw_curl_multi()->del_timer(); + multi->del_timer(); } else { if (timeout_ms == 0) { timeout_ms = 1; /* 0 means directly call socket_action, but we'll do it in a bit */ } - sw_curl_multi()->add_timer(timeout_ms); + multi->add_timer(timeout_ms); } return 0; } @@ -366,11 +391,14 @@ void swoole_native_curl_minit(int module_number) swoole_coroutine_curl_handle_handlers.clone_obj = curl_clone_obj; swoole_coroutine_curl_handle_handlers.cast_object = curl_cast_object; + curl_multi_register_class(nullptr); + zend_unregister_functions(swoole_native_curl_functions, -1, CG(function_table)); zend_register_functions(NULL, swoole_native_curl_functions, NULL, MODULE_PERSISTENT); #else le_curl = zend_register_list_destructors_ex(_php_curl_close, NULL, le_curl_name, module_number); + le_curl_multi_handle = zend_register_list_destructors_ex(_php_curl_multi_close, NULL, le_curl_multi_handle_name, module_number); #endif @@ -927,7 +955,7 @@ php_curl *init_curl_handle_into_zval(zval *curl) #if PHP_VERSION_ID >= 80000 void init_curl_handle(php_curl *ch) #else -static php_curl *alloc_curl_handle() +php_curl *alloc_curl_handle() #endif { #if PHP_VERSION_ID < 80000 @@ -963,23 +991,6 @@ static php_curl *alloc_curl_handle() } /* }}} */ -static php_curl *get_curl_handle(zval *zid, bool exclusive) { - php_curl *ch; -#if PHP_VERSION_ID >= 80000 - ch = Z_CURL_P(zid); -#else - if ((ch = (php_curl*) zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { - swFatalError(SW_ERROR_INVALID_PARAMS, "The cURL client is executing, this handle cannot be operated"); - return nullptr; - } -#endif - if (exclusive && ch->context) { - swFatalError(SW_ERROR_CO_HAS_BEEN_BOUND, "The cURL client is executing, this handle cannot be operated"); - return nullptr; - } - return ch; -} - #if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */ /* {{{ create_certinfo */ @@ -1058,7 +1069,7 @@ PHP_FUNCTION(swoole_native_curl_init) CURL *cp; zend_string *url = NULL; - ZEND_PARSE_PARAMETERS_START(0,1) + ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL #if PHP_VERSION_ID >= 80000 Z_PARAM_STR_OR_NULL(url) @@ -1423,7 +1434,7 @@ PHP_FUNCTION(swoole_native_curl_copy_handle) #endif ZEND_PARSE_PARAMETERS_END(); - if ((ch = get_curl_handle(zid)) == NULL) { + if ((ch = _php_curl_get_handle(zid)) == NULL) { RETURN_FALSE; } @@ -2264,7 +2275,7 @@ PHP_FUNCTION(swoole_native_curl_setopt) Z_PARAM_ZVAL(zvalue) ZEND_PARSE_PARAMETERS_END(); - if ((ch = get_curl_handle(zid)) == NULL) { + if ((ch = _php_curl_get_handle(zid)) == NULL) { RETURN_FALSE; } @@ -2298,7 +2309,7 @@ PHP_FUNCTION(swoole_native_curl_setopt_array) Z_PARAM_ARRAY(arr) ZEND_PARSE_PARAMETERS_END(); - if ((ch = get_curl_handle(zid)) == NULL) { + if ((ch = _php_curl_get_handle(zid)) == NULL) { RETURN_FALSE; } @@ -2353,7 +2364,7 @@ PHP_FUNCTION(swoole_native_curl_exec) #endif ZEND_PARSE_PARAMETERS_END(); - if ((ch = get_curl_handle(zid)) == NULL) { + if ((ch = _php_curl_get_handle(zid)) == NULL) { RETURN_FALSE; } @@ -2425,7 +2436,7 @@ PHP_FUNCTION(swoole_native_curl_getinfo) #endif ZEND_PARSE_PARAMETERS_END(); - if ((ch = get_curl_handle(zid, false)) == NULL) { + if ((ch = _php_curl_get_handle(zid, false)) == NULL) { RETURN_FALSE; } @@ -2698,7 +2709,7 @@ PHP_FUNCTION(swoole_native_curl_error) #endif ZEND_PARSE_PARAMETERS_END(); - if ((ch = get_curl_handle(zid, false)) == NULL) { + if ((ch = _php_curl_get_handle(zid, false)) == NULL) { RETURN_FALSE; } @@ -2726,7 +2737,7 @@ PHP_FUNCTION(swoole_native_curl_errno) #endif ZEND_PARSE_PARAMETERS_END(); - if ((ch = get_curl_handle(zid, false)) == NULL) { + if ((ch = _php_curl_get_handle(zid, false)) == NULL) { RETURN_FALSE; } @@ -2749,7 +2760,7 @@ PHP_FUNCTION(swoole_native_curl_close) #endif ZEND_PARSE_PARAMETERS_END(); - if ((ch = get_curl_handle(zid)) == NULL) { + if ((ch = _php_curl_get_handle(zid)) == NULL) { RETURN_FALSE; } @@ -2846,11 +2857,10 @@ static void curl_free_obj(zend_object *object) } #endif +#if PHP_VERSION_ID < 80000 /* {{{ _php_curl_close_ex() List destructor for curl handles */ -#if PHP_VERSION_ID < 80000 -static void _php_curl_close_ex(php_curl *ch) -{ +void _php_curl_close_ex(php_curl *ch) { #if PHP_CURL_DEBUG fprintf(stderr, "DTOR CALLED, ch = %x\n", ch); #endif @@ -2921,14 +2931,11 @@ static void _php_curl_close_ex(php_curl *ch) #endif efree(ch); } -#endif /* }}} */ /* {{{ _php_curl_close() List destructor for curl handles */ -#if PHP_VERSION_ID < 80000 -static void _php_curl_close(zend_resource *rsrc) -{ +void _php_curl_close(zend_resource *rsrc) { php_curl *ch = (php_curl *) rsrc->ptr; _php_curl_close_ex(ch); } @@ -2998,7 +3005,7 @@ PHP_FUNCTION(swoole_native_curl_reset) #endif ZEND_PARSE_PARAMETERS_END(); - if ((ch = get_curl_handle(zid)) == NULL) { + if ((ch = _php_curl_get_handle(zid)) == NULL) { RETURN_FALSE; } @@ -3031,7 +3038,7 @@ PHP_FUNCTION(swoole_native_curl_escape) Z_PARAM_STR(str) ZEND_PARSE_PARAMETERS_END(); - if ((ch = get_curl_handle(zid)) == NULL) { + if ((ch = _php_curl_get_handle(zid)) == NULL) { RETURN_FALSE; } @@ -3106,7 +3113,7 @@ PHP_FUNCTION(swoole_native_curl_pause) Z_PARAM_LONG(bitmask) ZEND_PARSE_PARAMETERS_END(); - if ((ch = get_curl_handle(zid)) == NULL) { + if ((ch = _php_curl_get_handle(zid)) == NULL) { RETURN_FALSE; } diff --git a/thirdparty/php/curl/multi.cc b/thirdparty/php/curl/multi.cc new file mode 100644 index 00000000000..82907417d3c --- /dev/null +++ b/thirdparty/php/curl/multi.cc @@ -0,0 +1,664 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Sterling Hughes | + +----------------------------------------------------------------------+ +*/ + +#include "php_swoole_cxx.h" + +#ifdef SW_USE_CURL +#include "curl_multi.h" + +using namespace swoole; + +SW_EXTERN_C_BEGIN +#include "curl_interface.h" +#include "curl_arginfo.h" + +#include +#include + +#include +#include + +#define SAVE_CURLM_ERROR(__handle, __err) (__handle)->err.no = (int) __err; + +#if PHP_VERSION_ID >= 80000 +/* CurlMultiHandle class */ + +zend_class_entry *swoole_coroutine_curl_multi_handle_ce; + +static inline php_curlm *curl_multi_from_obj(zend_object *obj) { + return (php_curlm *) ((char *) (obj) -XtOffsetOf(php_curlm, std)); +} +#define Z_CURL_MULTI_P(zv) curl_multi_from_obj(Z_OBJ_P(zv)) +#else +extern int _php_curl_get_le_curl(); +extern int _php_curl_get_le_curl_multi(); +static inline php_curlm *Z_CURL_MULTI_P(zval *zv) { + return (php_curlm *) zend_fetch_resource(Z_RES_P(zv), le_curl_multi_handle_name, _php_curl_get_le_curl_multi()); +} +#endif + +static void _php_curl_multi_free(php_curlm *mh); + +SW_EXTERN_C_END + +/* {{{ Returns a new cURL multi handle */ +PHP_FUNCTION(swoole_native_curl_multi_init) { + php_curlm *mh; + +#ifdef ZEND_PARSE_PARAMETERS_NONE + ZEND_PARSE_PARAMETERS_NONE(); +#endif + +#if PHP_VERSION_ID >= 80000 + object_init_ex(return_value, swoole_coroutine_curl_multi_handle_ce); + mh = Z_CURL_MULTI_P(return_value); + mh->multi = new cURLMulti(); + mh->handlers = (php_curlm_handlers *) ecalloc(1, sizeof(php_curlm_handlers)); + zend_llist_init(&mh->easyh, sizeof(zval), _php_curl_multi_cleanup_list, 0); +#else + mh = (php_curlm *) ecalloc(1, sizeof(php_curlm)); + mh->multi = new cURLMulti(); + mh->handlers = (php_curlm_handlers *) ecalloc(1, sizeof(php_curlm_handlers)); + zend_llist_init(&mh->easyh, sizeof(zval), _php_curl_multi_cleanup_list, 0); + RETURN_RES(zend_register_resource(mh, _php_curl_get_le_curl_multi())); +#endif +} +/* }}} */ + +/* {{{ Add a normal cURL handle to a cURL multi handle */ +PHP_FUNCTION(swoole_native_curl_multi_add_handle) { + zval *z_mh; + zval *z_ch; + php_curlm *mh; + php_curl *ch; + CURLMcode error = CURLM_OK; + + ZEND_PARSE_PARAMETERS_START(2, 2) +#if PHP_VERSION_ID >= 80000 + Z_PARAM_OBJECT_OF_CLASS(z_mh, swoole_coroutine_curl_multi_handle_ce) + Z_PARAM_OBJECT_OF_CLASS(z_ch, swoole_coroutine_curl_handle_ce) +#else + Z_PARAM_RESOURCE(z_mh) + Z_PARAM_RESOURCE(z_ch) +#endif + ZEND_PARSE_PARAMETERS_END(); + + mh = Z_CURL_MULTI_P(z_mh); + ch = Z_CURL_P(z_ch); + + _php_curl_verify_handlers(ch, 1); + + _php_curl_cleanup_handle(ch); + + Z_ADDREF_P(z_ch); + zend_llist_add_element(&mh->easyh, z_ch); + + error = curl_multi_add_handle(mh->multi->get_multi_handle(), ch->cp); + SAVE_CURLM_ERROR(mh, error); + + RETURN_LONG((zend_long) error); +} +/* }}} */ + +void _php_curl_multi_cleanup_list(void *data) /* {{{ */ +{ + zval *z_ch = (zval *) data; + + zval_ptr_dtor(z_ch); +} +/* }}} */ + +/* Used internally as comparison routine passed to zend_list_del_element */ +static int curl_compare_objects(zval *z1, zval *z2) /* {{{ */ +{ + return (Z_TYPE_P(z1) == Z_TYPE_P(z2) && Z_TYPE_P(z1) == IS_OBJECT && Z_OBJ_P(z1) == Z_OBJ_P(z2)); +} +/* }}} */ + +/* Used to find the php_curl resource for a given curl easy handle */ +static zval *_php_curl_multi_find_easy_handle(php_curlm *mh, CURL *easy) /* {{{ */ +{ + php_curl *tmp_ch; + zend_llist_position pos; + zval *pz_ch_temp; + + for (pz_ch_temp = (zval *) zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch_temp; + pz_ch_temp = (zval *) zend_llist_get_next_ex(&mh->easyh, &pos)) { + tmp_ch = Z_CURL_P(pz_ch_temp); + + if (tmp_ch->cp == easy) { + return pz_ch_temp; + } + } + + return NULL; +} +/* }}} */ + +/* {{{ Remove a multi handle from a set of cURL handles */ +PHP_FUNCTION(swoole_native_curl_multi_remove_handle) { + zval *z_mh; + zval *z_ch; + php_curlm *mh; + php_curl *ch; + CURLMcode error = CURLM_OK; + + ZEND_PARSE_PARAMETERS_START(2, 2) +#if PHP_VERSION_ID >= 80000 + Z_PARAM_OBJECT_OF_CLASS(z_mh, swoole_coroutine_curl_multi_handle_ce) + Z_PARAM_OBJECT_OF_CLASS(z_ch, swoole_coroutine_curl_handle_ce) +#else + Z_PARAM_RESOURCE(z_mh) + Z_PARAM_RESOURCE(z_ch) +#endif + ZEND_PARSE_PARAMETERS_END(); + + mh = Z_CURL_MULTI_P(z_mh); + ch = Z_CURL_P(z_ch); + + error = curl_multi_remove_handle(mh->multi->get_multi_handle(), ch->cp); + SAVE_CURLM_ERROR(mh, error); + + RETVAL_LONG((zend_long) error); + zend_llist_del_element(&mh->easyh, z_ch, (int (*)(void *, void *)) curl_compare_objects); +} +/* }}} */ + +/* {{{ Get all the sockets associated with the cURL extension, which can then be "selected" */ +PHP_FUNCTION(swoole_native_curl_multi_select) { + zval *z_mh; + php_curlm *mh; + double timeout = 1.0; + + ZEND_PARSE_PARAMETERS_START(1, 2) +#if PHP_VERSION_ID >= 80000 + Z_PARAM_OBJECT_OF_CLASS(z_mh, swoole_coroutine_curl_multi_handle_ce) +#else + Z_PARAM_RESOURCE(z_mh) +#endif + Z_PARAM_OPTIONAL + Z_PARAM_DOUBLE(timeout) + ZEND_PARSE_PARAMETERS_END(); + + mh = Z_CURL_MULTI_P(z_mh); + RETURN_LONG(mh->multi->select(mh)); +} +/* }}} */ + +/* {{{ Run the sub-connections of the current cURL handle */ +PHP_FUNCTION(swoole_native_curl_multi_exec) { + zval *z_mh; + zval *z_still_running; + php_curlm *mh; + int still_running = 0; + CURLMcode error = CURLM_OK; + + ZEND_PARSE_PARAMETERS_START(2, 2) +#if PHP_VERSION_ID >= 80000 + Z_PARAM_OBJECT_OF_CLASS(z_mh, swoole_coroutine_curl_multi_handle_ce) +#else + Z_PARAM_RESOURCE(z_mh) +#endif +#if PHP_VERSION_ID >= 70400 + Z_PARAM_ZVAL(z_still_running) +#else + Z_PARAM_ZVAL_DEREF(z_still_running) +#endif + ZEND_PARSE_PARAMETERS_END(); + + mh = Z_CURL_MULTI_P(z_mh); + + { + zend_llist_position pos; + php_curl *ch; + zval *pz_ch; + + for (pz_ch = (zval *) zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch; + pz_ch = (zval *) zend_llist_get_next_ex(&mh->easyh, &pos)) { + ch = Z_CURL_P(pz_ch); + + _php_curl_verify_handlers(ch, 1); + } + } + + error = curl_multi_perform(mh->multi->get_multi_handle(), &still_running); +#if PHP_VERSION_ID >= 70400 + ZEND_TRY_ASSIGN_REF_LONG(z_still_running, still_running); +#else + zval_ptr_dtor(z_still_running); + ZVAL_LONG(z_still_running, still_running); +#endif + + SAVE_CURLM_ERROR(mh, error); + RETURN_LONG((zend_long) error); +} +/* }}} */ + +/* {{{ Return the content of a cURL handle if CURLOPT_RETURNTRANSFER is set */ +PHP_FUNCTION(swoole_native_curl_multi_getcontent) { + zval *z_ch; + php_curl *ch; + + ZEND_PARSE_PARAMETERS_START(1, 1) +#if PHP_VERSION_ID >= 80000 + Z_PARAM_OBJECT_OF_CLASS(z_ch, swoole_coroutine_curl_handle_ce) +#else + Z_PARAM_RESOURCE(z_ch) +#endif + ZEND_PARSE_PARAMETERS_END(); + + ch = Z_CURL_P(z_ch); + + if (ch->handlers->write->method == PHP_CURL_RETURN) { + if (!ch->handlers->write->buf.s) { + RETURN_EMPTY_STRING(); + } + smart_str_0(&ch->handlers->write->buf); + RETURN_STR_COPY(ch->handlers->write->buf.s); + } + + RETURN_NULL(); +} +/* }}} */ + +/* {{{ Get information about the current transfers */ +PHP_FUNCTION(swoole_native_curl_multi_info_read) { + zval *z_mh; + php_curlm *mh; + CURLMsg *tmp_msg; + int queued_msgs; + zval *zmsgs_in_queue = NULL; + php_curl *ch; + + ZEND_PARSE_PARAMETERS_START(1, 2) +#if PHP_VERSION_ID >= 80000 + Z_PARAM_OBJECT_OF_CLASS(z_mh, swoole_coroutine_curl_multi_handle_ce) +#else + Z_PARAM_RESOURCE(z_mh) +#endif + Z_PARAM_OPTIONAL + Z_PARAM_ZVAL(zmsgs_in_queue) + ZEND_PARSE_PARAMETERS_END(); + + mh = Z_CURL_MULTI_P(z_mh); + + tmp_msg = curl_multi_info_read(mh->multi->get_multi_handle(), &queued_msgs); + if (tmp_msg == NULL) { + RETURN_FALSE; + } + + if (zmsgs_in_queue) { +#if PHP_VERSION_ID >= 70400 + ZEND_TRY_ASSIGN_REF_LONG(zmsgs_in_queue, queued_msgs); +#else + zval_ptr_dtor(zmsgs_in_queue); + ZVAL_LONG(zmsgs_in_queue, queued_msgs); +#endif + } + + array_init(return_value); + add_assoc_long(return_value, "msg", tmp_msg->msg); + add_assoc_long(return_value, "result", tmp_msg->data.result); + + /* find the original easy curl handle */ + { + zval *pz_ch = _php_curl_multi_find_easy_handle(mh, tmp_msg->easy_handle); + if (pz_ch != NULL) { + /* we must save result to be able to read error message */ + ch = Z_CURL_P(pz_ch); + SAVE_CURL_ERROR(ch, tmp_msg->data.result); + + Z_ADDREF_P(pz_ch); + add_assoc_zval(return_value, "handle", pz_ch); + } + } +} +/* }}} */ + +/* {{{ Close a set of cURL handles */ +PHP_FUNCTION(swoole_native_curl_multi_close) { + php_curlm *mh; + zval *z_mh; + + zend_llist_position pos; + zval *pz_ch; + + ZEND_PARSE_PARAMETERS_START(1, 1) +#if PHP_VERSION_ID >= 80000 + Z_PARAM_OBJECT_OF_CLASS(z_mh, swoole_coroutine_curl_multi_handle_ce) +#else + Z_PARAM_RESOURCE(z_mh) +#endif + ZEND_PARSE_PARAMETERS_END(); + + mh = Z_CURL_MULTI_P(z_mh); + + for (pz_ch = (zval *) zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch; + pz_ch = (zval *) zend_llist_get_next_ex(&mh->easyh, &pos)) { + php_curl *ch = Z_CURL_P(pz_ch); + _php_curl_verify_handlers(ch, 1); + curl_multi_remove_handle(mh->multi->get_multi_handle(), ch->cp); + } + zend_llist_clean(&mh->easyh); +} +/* }}} */ + +/* {{{ Return an integer containing the last multi curl error number */ +PHP_FUNCTION(swoole_native_curl_multi_errno) { + zval *z_mh; + php_curlm *mh; + + ZEND_PARSE_PARAMETERS_START(1, 1) +#if PHP_VERSION_ID >= 80000 + Z_PARAM_OBJECT_OF_CLASS(z_mh, swoole_coroutine_curl_multi_handle_ce) +#else + Z_PARAM_RESOURCE(z_mh) +#endif + ZEND_PARSE_PARAMETERS_END(); + + mh = Z_CURL_MULTI_P(z_mh); + + RETURN_LONG(mh->err.no); +} +/* }}} */ + +/* {{{ return string describing error code */ +PHP_FUNCTION(swoole_native_curl_multi_strerror) { + zend_long code; + const char *str; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_LONG(code) + ZEND_PARSE_PARAMETERS_END(); + + str = curl_multi_strerror((CURLMcode) code); + if (str) { + RETURN_STRING(str); + } else { + RETURN_NULL(); + } +} +/* }}} */ + +#if LIBCURL_VERSION_NUM >= 0x072C00 /* Available since 7.44.0 */ + +static int _php_server_push_callback( + CURL *parent_ch, CURL *easy, size_t num_headers, struct curl_pushheaders *push_headers, void *userp) /* {{{ */ +{ + php_curl *ch; + php_curl *parent; + php_curlm *mh = (php_curlm *) userp; + size_t rval = CURL_PUSH_DENY; + php_curlm_server_push *t = mh->handlers->server_push; + zval *pz_parent_ch = NULL; + zval pz_ch; + zval headers; + zval retval; + char *header; + int error; + zend_fcall_info fci = empty_fcall_info; + + pz_parent_ch = _php_curl_multi_find_easy_handle(mh, parent_ch); + if (pz_parent_ch == NULL) { + return rval; + } + + parent = Z_CURL_P(pz_parent_ch); + + ch = init_curl_handle_into_zval(&pz_ch); + ch->cp = easy; + _php_setup_easy_copy_handlers(ch, parent); + + size_t i; + array_init(&headers); + for (i = 0; i < num_headers; i++) { + header = curl_pushheader_bynum(push_headers, i); + add_next_index_string(&headers, header); + } + + zend_fcall_info_init(&t->func_name, 0, &fci, &t->fci_cache, NULL, NULL); + + zend_fcall_info_argn(&fci, 3, pz_parent_ch, &pz_ch, &headers); + + fci.retval = &retval; + + error = zend_call_function(&fci, &t->fci_cache); + zend_fcall_info_args_clear(&fci, 1); + zval_ptr_dtor_nogc(&headers); + + if (error == FAILURE) { + php_error_docref(NULL, E_WARNING, "Cannot call the CURLMOPT_PUSHFUNCTION"); + } else if (!Z_ISUNDEF(retval)) { + if (CURL_PUSH_DENY != zval_get_long(&retval)) { + rval = CURL_PUSH_OK; + zend_llist_add_element(&mh->easyh, &pz_ch); + } else { + /* libcurl will free this easy handle, avoid double free */ + ch->cp = NULL; + } + } + + return rval; +} +/* }}} */ + +#endif + +static int _php_curl_multi_setopt(php_curlm *mh, zend_long option, zval *zvalue, zval *return_value) /* {{{ */ +{ + CURLMcode error = CURLM_OK; + + switch (option) { + case CURLMOPT_PIPELINING: + case CURLMOPT_MAXCONNECTS: +#if LIBCURL_VERSION_NUM >= 0x071e00 /* 7.30.0 */ + case CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE: + case CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE: + case CURLMOPT_MAX_HOST_CONNECTIONS: + case CURLMOPT_MAX_PIPELINE_LENGTH: + case CURLMOPT_MAX_TOTAL_CONNECTIONS: +#endif + { + zend_long lval = zval_get_long(zvalue); + + if (option == CURLMOPT_PIPELINING && (lval & 1)) { +#if LIBCURL_VERSION_NUM >= 0x073e00 /* 7.62.0 */ + php_error_docref(NULL, E_WARNING, "CURLPIPE_HTTP1 is no longer supported"); +#else + php_error_docref(NULL, E_DEPRECATED, "CURLPIPE_HTTP1 is deprecated"); +#endif + } + error = curl_multi_setopt(mh->multi->get_multi_handle(), (CURLMoption) option, lval); + break; + } +#if LIBCURL_VERSION_NUM > 0x072D00 /* Available since 7.45.0 */ + case CURLMOPT_PUSHFUNCTION: + if (mh->handlers->server_push == NULL) { + mh->handlers->server_push = (php_curlm_server_push *) ecalloc(1, sizeof(php_curlm_server_push)); + } else if (!Z_ISUNDEF(mh->handlers->server_push->func_name)) { + zval_ptr_dtor(&mh->handlers->server_push->func_name); + mh->handlers->server_push->fci_cache = empty_fcall_info_cache; + } + + ZVAL_COPY(&mh->handlers->server_push->func_name, zvalue); + mh->handlers->server_push->method = PHP_CURL_USER; + error = curl_multi_setopt(mh->multi->get_multi_handle(), (CURLMoption) option, _php_server_push_callback); + if (error != CURLM_OK) { + return 0; + } + error = curl_multi_setopt(mh->multi->get_multi_handle(), CURLMOPT_PUSHDATA, mh); + break; +#endif + default: +#if PHP_VERSION_ID < 80000 + php_error_docref(NULL, E_WARNING, "Invalid curl multi configuration option"); +#else + zend_argument_value_error(2, "is not a valid cURL multi option"); +#endif + error = CURLM_UNKNOWN_OPTION; + break; + } + + SAVE_CURLM_ERROR(mh, error); + + return error != CURLM_OK; +} +/* }}} */ + +/* {{{ Set an option for the curl multi handle */ +PHP_FUNCTION(swoole_native_curl_multi_setopt) { + zval *z_mh, *zvalue; + zend_long options; + php_curlm *mh; + + ZEND_PARSE_PARAMETERS_START(3, 3) +#if PHP_VERSION_ID >= 80000 + Z_PARAM_OBJECT_OF_CLASS(z_mh, swoole_coroutine_curl_multi_handle_ce) +#else + Z_PARAM_RESOURCE(z_mh) +#endif + Z_PARAM_LONG(options) + Z_PARAM_ZVAL(zvalue) + ZEND_PARSE_PARAMETERS_END(); + + mh = Z_CURL_MULTI_P(z_mh); + + if (!_php_curl_multi_setopt(mh, options, zvalue, return_value)) { + RETURN_TRUE; + } else { + RETURN_FALSE; + } +} +/* }}} */ + +#if PHP_VERSION_ID >= 80000 +/* CurlMultiHandle class */ + +static zend_object_handlers swoole_coroutine_curl_multi_handle_handlers; + +static zend_object *curl_multi_create_object(zend_class_entry *class_type) { + php_curlm *intern = (php_curlm *) zend_object_alloc(sizeof(php_curlm), class_type); + + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &swoole_coroutine_curl_multi_handle_handlers; + + return &intern->std; +} + +static zend_function *curl_multi_get_constructor(zend_object *object) { + zend_throw_error(NULL, "Cannot directly construct CurlMultiHandle, use curl_multi_init() instead"); + return NULL; +} + +void curl_multi_free_obj(zend_object *object) { + php_curlm *mh = (php_curlm *) curl_multi_from_obj(object); + + zend_llist_position pos; + php_curl *ch; + zval *pz_ch; + + if (!mh->multi) { + /* Can happen if constructor throws. */ + zend_object_std_dtor(&mh->std); + return; + } + + _php_curl_multi_free(mh); + zend_object_std_dtor(&mh->std); +} + +static HashTable *curl_multi_get_gc(zend_object *object, zval **table, int *n) { + php_curlm *curl_multi = curl_multi_from_obj(object); + + zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create(); + + if (curl_multi->handlers) { + if (curl_multi->handlers->server_push) { + zend_get_gc_buffer_add_zval(gc_buffer, &curl_multi->handlers->server_push->func_name); + } + } + + zend_llist_position pos; + for (zval *pz_ch = (zval *) zend_llist_get_first_ex(&curl_multi->easyh, &pos); pz_ch; + pz_ch = (zval *) zend_llist_get_next_ex(&curl_multi->easyh, &pos)) { + zend_get_gc_buffer_add_zval(gc_buffer, pz_ch); + } + + zend_get_gc_buffer_use(gc_buffer, table, n); + + return zend_std_get_properties(object); +} + +void curl_multi_register_class(const zend_function_entry *method_entries) { + SW_INIT_CLASS_ENTRY(swoole_coroutine_curl_multi_handle, + "Swoole\\Coroutine\\Curl\\MultiHandle", + nullptr, + "Co\\Curl\\MultiHandle", + nullptr); + SW_SET_CLASS_SERIALIZABLE( + swoole_coroutine_curl_multi_handle, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_CUSTOM_OBJECT( + swoole_coroutine_curl_multi_handle, curl_multi_create_object, curl_multi_free_obj, php_curlm, std); + swoole_coroutine_curl_multi_handle_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NO_DYNAMIC_PROPERTIES; + swoole_coroutine_curl_multi_handle_handlers.get_gc = curl_multi_get_gc; + swoole_coroutine_curl_multi_handle_handlers.get_constructor = curl_multi_get_constructor; + swoole_coroutine_curl_multi_handle_handlers.clone_obj = NULL; + swoole_coroutine_curl_multi_handle_handlers.cast_object = curl_cast_object; +} +#else +void _php_curl_multi_close(zend_resource *rsrc) /* {{{ */ +{ + php_curlm *mh = (php_curlm *) rsrc->ptr; + if (mh) { + _php_curl_multi_free(mh); + rsrc->ptr = NULL; + efree(mh); + } +} +/* }}} */ +#endif + +void _php_curl_multi_free(php_curlm *mh) { + zend_llist_position pos; + php_curl *ch; + zval *pz_ch; + + for (pz_ch = (zval *) zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch; + pz_ch = (zval *) zend_llist_get_next_ex(&mh->easyh, &pos)) { + /* ptr is NULL means it already be freed */ + if (Z_RES_P(pz_ch)->ptr) { + if ((ch = _php_curl_get_handle(pz_ch, false))) { + _php_curl_verify_handlers(ch, 0); + } + } + } + + curl_multi_cleanup(mh->multi->get_multi_handle()); + zend_llist_clean(&mh->easyh); + if (mh->handlers->server_push) { + zval_ptr_dtor(&mh->handlers->server_push->func_name); + efree(mh->handlers->server_push); + } + if (mh->handlers) { + efree(mh->handlers); + } + if (mh->multi) { + delete mh->multi; + } +} + +#endif diff --git a/thirdparty/php/curl/php_curl.h b/thirdparty/php/curl/php_curl.h index f2c351c96fe..809d2bab7d6 100644 --- a/thirdparty/php/curl/php_curl.h +++ b/thirdparty/php/curl/php_curl.h @@ -54,14 +54,15 @@ #if PHP_VERSION_ID < 80000 #define le_curl_name "Swoole-Coroutine-cURL Handle" -#endif #define le_curl_multi_handle_name "Swoole-Coroutine-cURL Multi Handle" #define le_curl_share_handle_name "Swoole-Coroutine-cURL Share Handle" +#endif #if PHP_VERSION_ID >= 80000 PHP_CURL_API extern zend_class_entry *curl_ce; PHP_CURL_API extern zend_class_entry *curl_share_ce; PHP_CURL_API extern zend_class_entry *curl_multi_ce; +PHP_CURL_API extern zend_class_entry *swoole_coroutine_curl_handle_ce; #endif PHP_CURL_API extern zend_class_entry *curl_CURLFile_class; From 4eda7bd35d0ea7219e4a624c25f62f587cb9f49f Mon Sep 17 00:00:00 2001 From: matyhtf Date: Sat, 13 Mar 2021 21:44:45 +0800 Subject: [PATCH 077/936] [clang-format] thirdparty/php/curl/interface.cc --- thirdparty/php/curl/interface.cc | 2574 +++++++++++++++--------------- 1 file changed, 1276 insertions(+), 1298 deletions(-) diff --git a/thirdparty/php/curl/interface.cc b/thirdparty/php/curl/interface.cc index b83651db475..963b4fcc3f2 100644 --- a/thirdparty/php/curl/interface.cc +++ b/thirdparty/php/curl/interface.cc @@ -40,37 +40,34 @@ SW_EXTERN_C_BEGIN /* {{{ cruft for thread safe SSL crypto locks */ #if defined(ZTS) && defined(HAVE_CURL_SSL) -# ifdef PHP_WIN32 -# define PHP_CURL_NEED_OPENSSL_TSL -# include -# else /* !PHP_WIN32 */ -# if defined(HAVE_CURL_OPENSSL) -# if defined(HAVE_OPENSSL_CRYPTO_H) -# define PHP_CURL_NEED_OPENSSL_TSL -# include -# else -# warning \ - "libcurl was compiled with OpenSSL support, but configure could not find " \ +#ifdef PHP_WIN32 +#define PHP_CURL_NEED_OPENSSL_TSL +#include +#else /* !PHP_WIN32 */ +#if defined(HAVE_CURL_OPENSSL) +#if defined(HAVE_OPENSSL_CRYPTO_H) +#define PHP_CURL_NEED_OPENSSL_TSL +#include +#else +#warning "libcurl was compiled with OpenSSL support, but configure could not find " \ "openssl/crypto.h; thus no SSL crypto locking callbacks will be set, which may " \ "cause random crashes on SSL requests" -# endif -# elif defined(HAVE_CURL_GNUTLS) -# if defined(HAVE_GCRYPT_H) -# define PHP_CURL_NEED_GNUTLS_TSL -# include -# else -# warning \ - "libcurl was compiled with GnuTLS support, but configure could not find " \ +#endif +#elif defined(HAVE_CURL_GNUTLS) +#if defined(HAVE_GCRYPT_H) +#define PHP_CURL_NEED_GNUTLS_TSL +#include +#else +#warning "libcurl was compiled with GnuTLS support, but configure could not find " \ "gcrypt.h; thus no SSL crypto locking callbacks will be set, which may " \ "cause random crashes on SSL requests" -# endif -# else -# warning \ - "libcurl was compiled with SSL support, but configure could not determine which" \ +#endif +#else +#warning "libcurl was compiled with SSL support, but configure could not determine which" \ "library was used; thus no SSL crypto locking callbacks will be set, which may " \ "cause random crashes on SSL requests" -# endif /* HAVE_CURL_OPENSSL || HAVE_CURL_GNUTLS */ -# endif /* PHP_WIN32 */ +#endif /* HAVE_CURL_OPENSSL || HAVE_CURL_GNUTLS */ +#endif /* PHP_WIN32 */ #endif /* ZTS && HAVE_CURL_SSL */ /* }}} */ @@ -102,14 +99,17 @@ int _php_curl_get_le_curl_multi() { #define CAAL(s, v) add_assoc_long_ex(return_value, s, sizeof(s) - 1, (zend_long) v); #define CAAD(s, v) add_assoc_double_ex(return_value, s, sizeof(s) - 1, (double) v); #define CAAS(s, v) add_assoc_string_ex(return_value, s, sizeof(s) - 1, (char *) (v ? v : "")); -#define CAASTR(s, v) add_assoc_str_ex(return_value, s, sizeof(s) - 1, \ - v ? zend_string_copy(v) : ZSTR_EMPTY_ALLOC()); -#define CAAZ(s, v) add_assoc_zval_ex(return_value, s, sizeof(s) -1 , (zval *) v); +#define CAASTR(s, v) add_assoc_str_ex(return_value, s, sizeof(s) - 1, v ? zend_string_copy(v) : ZSTR_EMPTY_ALLOC()); +#define CAAZ(s, v) add_assoc_zval_ex(return_value, s, sizeof(s) - 1, (zval *) v); #if defined(PHP_WIN32) || defined(__GNUC__) -# define php_curl_ret(__ret) RETVAL_FALSE; return __ret; +#define php_curl_ret(__ret) \ + RETVAL_FALSE; \ + return __ret; #else -# define php_curl_ret(__ret) RETVAL_FALSE; return; +#define php_curl_ret(__ret) \ + RETVAL_FALSE; \ + return; #endif php_curl *_php_curl_get_handle(zval *zid, bool exclusive) { @@ -117,7 +117,7 @@ php_curl *_php_curl_get_handle(zval *zid, bool exclusive) { #if PHP_VERSION_ID >= 80000 ch = Z_CURL_P(zid); #else - if ((ch = (php_curl*) zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { + if ((ch = (php_curl *) zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { swFatalError(SW_ERROR_INVALID_PARAMS, "The cURL client is executing, this handle cannot be operated"); return nullptr; } @@ -129,8 +129,7 @@ php_curl *_php_curl_get_handle(zval *zid, bool exclusive) { return ch; } -static int php_curl_option_str(php_curl *ch, zend_long option, const char *str, const size_t len, zend_bool make_copy) -{ +static int php_curl_option_str(php_curl *ch, zend_long option, const char *str, const size_t len, zend_bool make_copy) { long error = CURLE_OK; if (strlen(str) != len) { @@ -138,7 +137,7 @@ static int php_curl_option_str(php_curl *ch, zend_long option, const char *str, zend_value_error("%s(): cURL option must not contain any null bytes", get_active_function_name()); #else php_error_docref(NULL, E_WARNING, "Curl option contains invalid characters (\\0)"); - #endif +#endif return FAILURE; } @@ -149,11 +148,11 @@ static int php_curl_option_str(php_curl *ch, zend_long option, const char *str, /* Strings passed to libcurl as 'char *' arguments, are copied by the library since 7.17.0 */ copystr = estrndup(str, len); - error = curl_easy_setopt(ch->cp, (CURLoption)option, copystr); + error = curl_easy_setopt(ch->cp, (CURLoption) option, copystr); zend_llist_add_element(&ch->to_free->str, ©str); #if LIBCURL_VERSION_NUM >= 0x071100 } else { - error = curl_easy_setopt(ch->cp, (CURLoption)option, str); + error = curl_easy_setopt(ch->cp, (CURLoption) option, str); } #endif @@ -186,7 +185,8 @@ static int php_curl_option_url(php_curl *ch, const char *url, const size_t len) } #if LIBCURL_VERSION_NUM > 0x073800 && defined(PHP_WIN32) - if (len > sizeof("file://") - 1 && '/' != url[sizeof("file://") - 1] && !strncmp("file://", url, sizeof("file://") - 1) && len < MAXPATHLEN - 2) { + if (len > sizeof("file://") - 1 && '/' != url[sizeof("file://") - 1] && + !strncmp("file://", url, sizeof("file://") - 1) && len < MAXPATHLEN - 2) { char _tmp[MAXPATHLEN] = {0}; memmove(_tmp, "file:///", sizeof("file:///") - 1); @@ -207,7 +207,8 @@ void _php_curl_verify_handlers(php_curl *ch, int reporterror) /* {{{ */ ZEND_ASSERT(ch && ch->handlers); if (!Z_ISUNDEF(ch->handlers->std_err)) { - stream = (php_stream *)zend_fetch_resource2_ex(&ch->handlers->std_err, NULL, php_file_le_stream(), php_file_le_pstream()); + stream = (php_stream *) zend_fetch_resource2_ex( + &ch->handlers->std_err, NULL, php_file_le_stream(), php_file_le_pstream()); if (stream == NULL) { if (reporterror) { php_error_docref(NULL, E_WARNING, "CURLOPT_STDERR resource has gone away, resetting to stderr"); @@ -219,7 +220,8 @@ void _php_curl_verify_handlers(php_curl *ch, int reporterror) /* {{{ */ } } if (ch->handlers->read && !Z_ISUNDEF(ch->handlers->read->stream)) { - stream = (php_stream *)zend_fetch_resource2_ex(&ch->handlers->read->stream, NULL, php_file_le_stream(), php_file_le_pstream()); + stream = (php_stream *) zend_fetch_resource2_ex( + &ch->handlers->read->stream, NULL, php_file_le_stream(), php_file_le_pstream()); if (stream == NULL) { if (reporterror) { php_error_docref(NULL, E_WARNING, "CURLOPT_INFILE resource has gone away, resetting to default"); @@ -233,7 +235,8 @@ void _php_curl_verify_handlers(php_curl *ch, int reporterror) /* {{{ */ } } if (ch->handlers->write_header && !Z_ISUNDEF(ch->handlers->write_header->stream)) { - stream = (php_stream *)zend_fetch_resource2_ex(&ch->handlers->write_header->stream, NULL, php_file_le_stream(), php_file_le_pstream()); + stream = (php_stream *) zend_fetch_resource2_ex( + &ch->handlers->write_header->stream, NULL, php_file_le_stream(), php_file_le_pstream()); if (stream == NULL) { if (reporterror) { php_error_docref(NULL, E_WARNING, "CURLOPT_WRITEHEADER resource has gone away, resetting to default"); @@ -247,7 +250,8 @@ void _php_curl_verify_handlers(php_curl *ch, int reporterror) /* {{{ */ } } if (ch->handlers->write && !Z_ISUNDEF(ch->handlers->write->stream)) { - stream = (php_stream *)zend_fetch_resource2_ex(&ch->handlers->write->stream, NULL, php_file_le_stream(), php_file_le_pstream()); + stream = (php_stream *) zend_fetch_resource2_ex( + &ch->handlers->write->stream, NULL, php_file_le_stream(), php_file_le_pstream()); if (stream == NULL) { if (reporterror) { php_error_docref(NULL, E_WARNING, "CURLOPT_FILE resource has gone away, resetting to default"); @@ -267,9 +271,7 @@ void _php_curl_verify_handlers(php_curl *ch, int reporterror) /* {{{ */ /* CurlHandle class */ #if PHP_VERSION_ID >= 80000 -static const zend_function_entry swoole_coroutine_curl_handle_methods[] = { - ZEND_FE_END -}; +static const zend_function_entry swoole_coroutine_curl_handle_methods[] = {ZEND_FE_END}; zend_class_entry *swoole_coroutine_curl_handle_ce; zend_class_entry *curl_share_ce; @@ -371,38 +373,29 @@ int cURLMulti::handle_timeout(CURLM *mh, long timeout_ms, void *userp) { return 0; } -void swoole_native_curl_minit(int module_number) -{ +void swoole_native_curl_minit(int module_number) { #if PHP_VERSION_ID >= 80000 - SW_INIT_CLASS_ENTRY(swoole_coroutine_curl_handle, - "Swoole\\Coroutine\\Curl\\Handle", - nullptr, - "Co\\Curl\\Handle", - nullptr); + SW_INIT_CLASS_ENTRY( + swoole_coroutine_curl_handle, "Swoole\\Coroutine\\Curl\\Handle", nullptr, "Co\\Curl\\Handle", nullptr); SW_SET_CLASS_SERIALIZABLE(swoole_coroutine_curl_handle, zend_class_serialize_deny, zend_class_unserialize_deny); - SW_SET_CLASS_CUSTOM_OBJECT(swoole_coroutine_curl_handle, - curl_create_object, - curl_free_obj, - php_curl, - std); + SW_SET_CLASS_CUSTOM_OBJECT(swoole_coroutine_curl_handle, curl_create_object, curl_free_obj, php_curl, std); swoole_coroutine_curl_handle_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NO_DYNAMIC_PROPERTIES; swoole_coroutine_curl_handle_handlers.get_gc = curl_get_gc; swoole_coroutine_curl_handle_handlers.get_constructor = curl_get_constructor; - swoole_coroutine_curl_handle_handlers.clone_obj = curl_clone_obj; - swoole_coroutine_curl_handle_handlers.cast_object = curl_cast_object; + swoole_coroutine_curl_handle_handlers.clone_obj = curl_clone_obj; + swoole_coroutine_curl_handle_handlers.cast_object = curl_cast_object; - curl_multi_register_class(nullptr); + curl_multi_register_class(nullptr); zend_unregister_functions(swoole_native_curl_functions, -1, CG(function_table)); zend_register_functions(NULL, swoole_native_curl_functions, NULL, MODULE_PERSISTENT); #else le_curl = zend_register_list_destructors_ex(_php_curl_close, NULL, le_curl_name, module_number); - le_curl_multi_handle = zend_register_list_destructors_ex(_php_curl_multi_close, NULL, le_curl_multi_handle_name, module_number); + le_curl_multi_handle = + zend_register_list_destructors_ex(_php_curl_multi_close, NULL, le_curl_multi_handle_name, module_number); #endif - - SW_INIT_CLASS_ENTRY_EX(swoole_native_curl_exception, "Swoole\\Coroutine\\Curl\\Exception", nullptr, @@ -417,103 +410,101 @@ void swoole_native_curl_minit(int module_number) #if PHP_VERSION_ID >= 80000 static zend_object *curl_create_object(zend_class_entry *class_type) { - php_curl *intern = (php_curl *) zend_object_alloc(sizeof(php_curl), class_type); + php_curl *intern = (php_curl *) zend_object_alloc(sizeof(php_curl), class_type); - zend_object_std_init(&intern->std, class_type); - object_properties_init(&intern->std, class_type); - intern->std.handlers = &swoole_coroutine_curl_handle_handlers; + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &swoole_coroutine_curl_handle_handlers; - return &intern->std; + return &intern->std; } static zend_function *curl_get_constructor(zend_object *object) { - zend_throw_error(NULL, "Cannot directly construct CurlHandle, use curl_init() instead"); - return NULL; + zend_throw_error(NULL, "Cannot directly construct CurlHandle, use curl_init() instead"); + return NULL; } static zend_object *curl_clone_obj(zend_object *object) { - php_curl *ch; - CURL *cp; - zval *postfields; - zend_object *clone_object; - php_curl *clone_ch; - - clone_object = curl_create_object(curl_ce); - clone_ch = curl_from_obj(clone_object); - init_curl_handle(clone_ch); - - ch = curl_from_obj(object); - cp = curl_easy_duphandle(ch->cp); - if (!cp) { - zend_throw_exception(NULL, "Failed to clone CurlHandle", 0); - return &clone_ch->std; - } - - clone_ch->cp = cp; - _php_setup_easy_copy_handlers(clone_ch, ch); - - postfields = &clone_ch->postfields; - if (Z_TYPE_P(postfields) != IS_UNDEF) { - if (build_mime_structure_from_hash(clone_ch, postfields) != SUCCESS) { - zend_throw_exception(NULL, "Failed to clone CurlHandle", 0); - return &clone_ch->std; - } - } - - return &clone_ch->std; + php_curl *ch; + CURL *cp; + zval *postfields; + zend_object *clone_object; + php_curl *clone_ch; + + clone_object = curl_create_object(curl_ce); + clone_ch = curl_from_obj(clone_object); + init_curl_handle(clone_ch); + + ch = curl_from_obj(object); + cp = curl_easy_duphandle(ch->cp); + if (!cp) { + zend_throw_exception(NULL, "Failed to clone CurlHandle", 0); + return &clone_ch->std; + } + + clone_ch->cp = cp; + _php_setup_easy_copy_handlers(clone_ch, ch); + + postfields = &clone_ch->postfields; + if (Z_TYPE_P(postfields) != IS_UNDEF) { + if (build_mime_structure_from_hash(clone_ch, postfields) != SUCCESS) { + zend_throw_exception(NULL, "Failed to clone CurlHandle", 0); + return &clone_ch->std; + } + } + + return &clone_ch->std; } -static HashTable *curl_get_gc(zend_object *object, zval **table, int *n) -{ - php_curl *curl = curl_from_obj(object); +static HashTable *curl_get_gc(zend_object *object, zval **table, int *n) { + php_curl *curl = curl_from_obj(object); - zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create(); + zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create(); - zend_get_gc_buffer_add_zval(gc_buffer, &curl->postfields); - if (curl->handlers) { - if (curl->handlers->read) { - zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->read->func_name); - zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->read->stream); - } + zend_get_gc_buffer_add_zval(gc_buffer, &curl->postfields); + if (curl->handlers) { + if (curl->handlers->read) { + zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->read->func_name); + zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->read->stream); + } - if (curl->handlers->write) { - zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->write->func_name); - zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->write->stream); - } + if (curl->handlers->write) { + zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->write->func_name); + zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->write->stream); + } - if (curl->handlers->write_header) { - zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->write_header->func_name); - zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->write_header->stream); - } + if (curl->handlers->write_header) { + zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->write_header->func_name); + zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->write_header->stream); + } - if (curl->handlers->progress) { - zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->progress->func_name); - } + if (curl->handlers->progress) { + zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->progress->func_name); + } #if LIBCURL_VERSION_NUM >= 0x071500 - if (curl->handlers->fnmatch) { - zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->fnmatch->func_name); - } + if (curl->handlers->fnmatch) { + zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->fnmatch->func_name); + } #endif - zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->std_err); - } + zend_get_gc_buffer_add_zval(gc_buffer, &curl->handlers->std_err); + } - zend_get_gc_buffer_use(gc_buffer, table, n); + zend_get_gc_buffer_use(gc_buffer, table, n); - return zend_std_get_properties(object); + return zend_std_get_properties(object); } -int curl_cast_object(zend_object *obj, zval *result, int type) -{ - if (type == IS_LONG) { - /* For better backward compatibility, make (int) $curl_handle return the object ID, - * similar to how it previously returned the resource ID. */ - ZVAL_LONG(result, obj->handle); - return SUCCESS; - } - - return zend_std_cast_object_tostring(obj, result, type); +int curl_cast_object(zend_object *obj, zval *result, int type) { + if (type == IS_LONG) { + /* For better backward compatibility, make (int) $curl_handle return the object ID, + * similar to how it previously returned the resource ID. */ + ZVAL_LONG(result, obj->handle); + return SUCCESS; + } + + return zend_std_cast_object_tostring(obj, result, type); } #endif @@ -525,8 +516,7 @@ void swoole_native_curl_mshutdown() { /* {{{ curl_write_nothing * Used as a work around. See _php_curl_close_ex */ -static size_t fn_write_nothing(char *data, size_t size, size_t nmemb, void *ctx) -{ +static size_t fn_write_nothing(char *data, size_t size, size_t nmemb, void *ctx) { return size * nmemb; } /* }}} */ @@ -534,16 +524,14 @@ static size_t fn_write_nothing(char *data, size_t size, size_t nmemb, void *ctx) /* {{{ curl_write_nothing * Used as a work around. See _php_curl_close_ex */ -static size_t curl_write_nothing(char *data, size_t size, size_t nmemb, void *ctx) -{ - return size * nmemb; +static size_t curl_write_nothing(char *data, size_t size, size_t nmemb, void *ctx) { + return size * nmemb; } /* }}} */ /* {{{ curl_write */ -static size_t fn_write(char *data, size_t size, size_t nmemb, void *ctx) -{ +static size_t fn_write(char *data, size_t size, size_t nmemb, void *ctx) { php_curl *ch = (php_curl *) ctx; php_curl_write *t = ch->handlers->write; size_t length = size * nmemb; @@ -554,57 +542,57 @@ static size_t fn_write(char *data, size_t size, size_t nmemb, void *ctx) #endif switch (t->method) { - case PHP_CURL_STDOUT: - PHPWRITE(data, length); - break; - case PHP_CURL_FILE: - return fwrite(data, size, nmemb, t->fp); - case PHP_CURL_RETURN: - if (length > 0) { - smart_str_appendl(&t->buf, data, (int) length); - } - break; - case PHP_CURL_USER: { - zval argv[2]; - zval retval; - int error; - zend_fcall_info fci; + case PHP_CURL_STDOUT: + PHPWRITE(data, length); + break; + case PHP_CURL_FILE: + return fwrite(data, size, nmemb, t->fp); + case PHP_CURL_RETURN: + if (length > 0) { + smart_str_appendl(&t->buf, data, (int) length); + } + break; + case PHP_CURL_USER: { + zval argv[2]; + zval retval; + int error; + zend_fcall_info fci; #if PHP_VERSION_ID >= 80000 - GC_ADDREF(&ch->std); - ZVAL_OBJ(&argv[0], &ch->std); + GC_ADDREF(&ch->std); + ZVAL_OBJ(&argv[0], &ch->std); #else - GC_ADDREF(ch->res); - ZVAL_RES(&argv[0], ch->res); + GC_ADDREF(ch->res); + ZVAL_RES(&argv[0], ch->res); #endif - ZVAL_STRINGL(&argv[1], data, length); + ZVAL_STRINGL(&argv[1], data, length); - fci.size = sizeof(fci); - fci.object = NULL; - ZVAL_COPY_VALUE(&fci.function_name, &t->func_name); - fci.retval = &retval; - fci.param_count = 2; - fci.params = argv; + fci.size = sizeof(fci); + fci.object = NULL; + ZVAL_COPY_VALUE(&fci.function_name, &t->func_name); + fci.retval = &retval; + fci.param_count = 2; + fci.params = argv; #if PHP_VERSION_ID >= 80000 - fci.named_params = NULL; + fci.named_params = NULL; #else - fci.no_separation = 0; -#endif - ch->in_callback = 1; - error = zend_call_function(&fci, &t->fci_cache); - ch->in_callback = 0; - if (error == FAILURE) { - php_error_docref(NULL, E_WARNING, "Could not call the CURLOPT_WRITEFUNCTION"); - length = -1; - } else if (!Z_ISUNDEF(retval)) { - _php_curl_verify_handlers(ch, 1); - length = zval_get_long(&retval); - } - - zval_ptr_dtor(&argv[0]); - zval_ptr_dtor(&argv[1]); - break; + fci.no_separation = 0; +#endif + ch->in_callback = 1; + error = zend_call_function(&fci, &t->fci_cache); + ch->in_callback = 0; + if (error == FAILURE) { + php_error_docref(NULL, E_WARNING, "Could not call the CURLOPT_WRITEFUNCTION"); + length = -1; + } else if (!Z_ISUNDEF(retval)) { + _php_curl_verify_handlers(ch, 1); + length = zval_get_long(&retval); } + + zval_ptr_dtor(&argv[0]); + zval_ptr_dtor(&argv[1]); + break; + } } return length; @@ -614,54 +602,53 @@ static size_t fn_write(char *data, size_t size, size_t nmemb, void *ctx) #if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */ /* {{{ curl_fnmatch */ -static int fn_fnmatch(void *ctx, const char *pattern, const char *string) -{ +static int fn_fnmatch(void *ctx, const char *pattern, const char *string) { php_curl *ch = (php_curl *) ctx; php_curl_fnmatch *t = ch->handlers->fnmatch; int rval = CURL_FNMATCHFUNC_FAIL; switch (t->method) { - case PHP_CURL_USER: { - zval argv[3]; - zval retval; - int error; - zend_fcall_info fci; + case PHP_CURL_USER: { + zval argv[3]; + zval retval; + int error; + zend_fcall_info fci; #if PHP_VERSION_ID >= 80000 - GC_ADDREF(&ch->std); - ZVAL_OBJ(&argv[0], &ch->std); + GC_ADDREF(&ch->std); + ZVAL_OBJ(&argv[0], &ch->std); #else - GC_ADDREF(ch->res); - ZVAL_RES(&argv[0], ch->res); -#endif - ZVAL_STRING(&argv[1], pattern); - ZVAL_STRING(&argv[2], string); - - fci.size = sizeof(fci); - ZVAL_COPY_VALUE(&fci.function_name, &t->func_name); - fci.object = NULL; - fci.retval = &retval; - fci.param_count = 3; - fci.params = argv; + GC_ADDREF(ch->res); + ZVAL_RES(&argv[0], ch->res); +#endif + ZVAL_STRING(&argv[1], pattern); + ZVAL_STRING(&argv[2], string); + + fci.size = sizeof(fci); + ZVAL_COPY_VALUE(&fci.function_name, &t->func_name); + fci.object = NULL; + fci.retval = &retval; + fci.param_count = 3; + fci.params = argv; #if PHP_VERSION_ID >= 80000 - fci.named_params = NULL; + fci.named_params = NULL; #else - fci.no_separation = 0; + fci.no_separation = 0; #endif - ch->in_callback = 1; - error = zend_call_function(&fci, &t->fci_cache); - ch->in_callback = 0; - if (error == FAILURE) { - php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_FNMATCH_FUNCTION"); - } else if (!Z_ISUNDEF(retval)) { - _php_curl_verify_handlers(ch, 1); - rval = zval_get_long(&retval); - } - zval_ptr_dtor(&argv[0]); - zval_ptr_dtor(&argv[1]); - zval_ptr_dtor(&argv[2]); - break; + ch->in_callback = 1; + error = zend_call_function(&fci, &t->fci_cache); + ch->in_callback = 0; + if (error == FAILURE) { + php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_FNMATCH_FUNCTION"); + } else if (!Z_ISUNDEF(retval)) { + _php_curl_verify_handlers(ch, 1); + rval = zval_get_long(&retval); } + zval_ptr_dtor(&argv[0]); + zval_ptr_dtor(&argv[1]); + zval_ptr_dtor(&argv[2]); + break; + } } return rval; } @@ -670,61 +657,66 @@ static int fn_fnmatch(void *ctx, const char *pattern, const char *string) /* {{{ curl_progress */ -static size_t fn_progress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) -{ - php_curl *ch = (php_curl *)clientp; +static size_t fn_progress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow) { + php_curl *ch = (php_curl *) clientp; php_curl_progress *t = ch->handlers->progress; - size_t rval = 0; + size_t rval = 0; #if PHP_CURL_DEBUG fprintf(stderr, "curl_progress() called\n"); - fprintf(stderr, "clientp = %x, dltotal = %f, dlnow = %f, ultotal = %f, ulnow = %f\n", clientp, dltotal, dlnow, ultotal, ulnow); + fprintf(stderr, + "clientp = %x, dltotal = %f, dlnow = %f, ultotal = %f, ulnow = %f\n", + clientp, + dltotal, + dlnow, + ultotal, + ulnow); #endif switch (t->method) { - case PHP_CURL_USER: { - zval argv[5]; - zval retval; - int error; - zend_fcall_info fci; + case PHP_CURL_USER: { + zval argv[5]; + zval retval; + int error; + zend_fcall_info fci; #if PHP_VERSION_ID >= 80000 - GC_ADDREF(&ch->std); - ZVAL_OBJ(&argv[0], &ch->std); + GC_ADDREF(&ch->std); + ZVAL_OBJ(&argv[0], &ch->std); #else - GC_ADDREF(ch->res); - ZVAL_RES(&argv[0], ch->res); -#endif - ZVAL_LONG(&argv[1], (zend_long)dltotal); - ZVAL_LONG(&argv[2], (zend_long)dlnow); - ZVAL_LONG(&argv[3], (zend_long)ultotal); - ZVAL_LONG(&argv[4], (zend_long)ulnow); - - fci.size = sizeof(fci); - ZVAL_COPY_VALUE(&fci.function_name, &t->func_name); - fci.object = NULL; - fci.retval = &retval; - fci.param_count = 5; - fci.params = argv; + GC_ADDREF(ch->res); + ZVAL_RES(&argv[0], ch->res); +#endif + ZVAL_LONG(&argv[1], (zend_long) dltotal); + ZVAL_LONG(&argv[2], (zend_long) dlnow); + ZVAL_LONG(&argv[3], (zend_long) ultotal); + ZVAL_LONG(&argv[4], (zend_long) ulnow); + + fci.size = sizeof(fci); + ZVAL_COPY_VALUE(&fci.function_name, &t->func_name); + fci.object = NULL; + fci.retval = &retval; + fci.param_count = 5; + fci.params = argv; #if PHP_VERSION_ID >= 80000 - fci.named_params = NULL; + fci.named_params = NULL; #else - fci.no_separation = 0; -#endif - - ch->in_callback = 1; - error = zend_call_function(&fci, &t->fci_cache); - ch->in_callback = 0; - if (error == FAILURE) { - php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_PROGRESSFUNCTION"); - } else if (!Z_ISUNDEF(retval)) { - _php_curl_verify_handlers(ch, 1); - if (0 != zval_get_long(&retval)) { - rval = 1; - } + fci.no_separation = 0; +#endif + + ch->in_callback = 1; + error = zend_call_function(&fci, &t->fci_cache); + ch->in_callback = 0; + if (error == FAILURE) { + php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_PROGRESSFUNCTION"); + } else if (!Z_ISUNDEF(retval)) { + _php_curl_verify_handlers(ch, 1); + if (0 != zval_get_long(&retval)) { + rval = 1; } - zval_ptr_dtor(&argv[0]); } + zval_ptr_dtor(&argv[0]); + } } return rval; } @@ -733,69 +725,69 @@ static size_t fn_progress(void *clientp, double dltotal, double dlnow, double ul /* {{{ curl_read */ static size_t fn_read(char *data, size_t size, size_t nmemb, void *ctx) { - php_curl *ch = (php_curl *)ctx; + php_curl *ch = (php_curl *) ctx; php_curl_read *t = ch->handlers->read; int length = 0; switch (t->method) { - case PHP_CURL_DIRECT: - if (t->fp) { - length = fread(data, size, nmemb, t->fp); - } - break; - case PHP_CURL_USER: { - zval argv[3]; - zval retval; - int error; - zend_fcall_info fci; + case PHP_CURL_DIRECT: + if (t->fp) { + length = fread(data, size, nmemb, t->fp); + } + break; + case PHP_CURL_USER: { + zval argv[3]; + zval retval; + int error; + zend_fcall_info fci; #if PHP_VERSION_ID >= 80000 - GC_ADDREF(&ch->std); - ZVAL_OBJ(&argv[0], &ch->std); + GC_ADDREF(&ch->std); + ZVAL_OBJ(&argv[0], &ch->std); #else - GC_ADDREF(ch->res); - ZVAL_RES(&argv[0], ch->res); + GC_ADDREF(ch->res); + ZVAL_RES(&argv[0], ch->res); #endif - if (t->res) { - GC_ADDREF(t->res); - ZVAL_RES(&argv[1], t->res); - } else { - ZVAL_NULL(&argv[1]); - } - ZVAL_LONG(&argv[2], (int )size * nmemb); - - fci.size = sizeof(fci); - ZVAL_COPY_VALUE(&fci.function_name, &t->func_name); - fci.object = NULL; - fci.retval = &retval; - fci.param_count = 3; - fci.params = argv; + if (t->res) { + GC_ADDREF(t->res); + ZVAL_RES(&argv[1], t->res); + } else { + ZVAL_NULL(&argv[1]); + } + ZVAL_LONG(&argv[2], (int) size * nmemb); + + fci.size = sizeof(fci); + ZVAL_COPY_VALUE(&fci.function_name, &t->func_name); + fci.object = NULL; + fci.retval = &retval; + fci.param_count = 3; + fci.params = argv; #if PHP_VERSION_ID >= 80000 - fci.named_params = NULL; + fci.named_params = NULL; #else - fci.no_separation = 0; -#endif - ch->in_callback = 1; - error = zend_call_function(&fci, &t->fci_cache); - ch->in_callback = 0; - if (error == FAILURE) { - php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_READFUNCTION"); - length = CURL_READFUNC_ABORT; - } else if (!Z_ISUNDEF(retval)) { - _php_curl_verify_handlers(ch, 1); - if (Z_TYPE(retval) == IS_STRING) { - length = MIN((int ) (size * nmemb), Z_STRLEN(retval)); - memcpy(data, Z_STRVAL(retval), length); - } - zval_ptr_dtor(&retval); + fci.no_separation = 0; +#endif + ch->in_callback = 1; + error = zend_call_function(&fci, &t->fci_cache); + ch->in_callback = 0; + if (error == FAILURE) { + php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_READFUNCTION"); + length = CURL_READFUNC_ABORT; + } else if (!Z_ISUNDEF(retval)) { + _php_curl_verify_handlers(ch, 1); + if (Z_TYPE(retval) == IS_STRING) { + length = MIN((int) (size * nmemb), Z_STRLEN(retval)); + memcpy(data, Z_STRVAL(retval), length); } - - zval_ptr_dtor(&argv[0]); - zval_ptr_dtor(&argv[1]); - break; + zval_ptr_dtor(&retval); } - default: - break; + + zval_ptr_dtor(&argv[0]); + zval_ptr_dtor(&argv[1]); + break; + } + default: + break; } return length; @@ -804,70 +796,69 @@ static size_t fn_read(char *data, size_t size, size_t nmemb, void *ctx) { /* {{{ curl_write_header */ -static size_t fn_write_header(char *data, size_t size, size_t nmemb, void *ctx) -{ +static size_t fn_write_header(char *data, size_t size, size_t nmemb, void *ctx) { php_curl *ch = (php_curl *) ctx; php_curl_write *t = ch->handlers->write_header; size_t length = size * nmemb; switch (t->method) { - case PHP_CURL_STDOUT: - // Handle special case write when we're returning the entire transfer - if (ch->handlers->write->method == PHP_CURL_RETURN && length > 0) { - smart_str_appendl(&ch->handlers->write->buf, data, (int) length); - } else { - PHPWRITE(data, length); - } - break; - case PHP_CURL_FILE: - return fwrite(data, size, nmemb, t->fp); - case PHP_CURL_USER: { - zval argv[2]; - zval retval; - int error; - zend_fcall_info fci; + case PHP_CURL_STDOUT: + // Handle special case write when we're returning the entire transfer + if (ch->handlers->write->method == PHP_CURL_RETURN && length > 0) { + smart_str_appendl(&ch->handlers->write->buf, data, (int) length); + } else { + PHPWRITE(data, length); + } + break; + case PHP_CURL_FILE: + return fwrite(data, size, nmemb, t->fp); + case PHP_CURL_USER: { + zval argv[2]; + zval retval; + int error; + zend_fcall_info fci; #if PHP_VERSION_ID >= 80000 - GC_ADDREF(&ch->std); - ZVAL_OBJ(&argv[0], &ch->std); + GC_ADDREF(&ch->std); + ZVAL_OBJ(&argv[0], &ch->std); #else - ZVAL_RES(&argv[0], ch->res); - Z_ADDREF(argv[0]); + ZVAL_RES(&argv[0], ch->res); + Z_ADDREF(argv[0]); #endif - ZVAL_STRINGL(&argv[1], data, length); + ZVAL_STRINGL(&argv[1], data, length); - fci.size = sizeof(fci); - ZVAL_COPY_VALUE(&fci.function_name, &t->func_name); - fci.object = NULL; - fci.retval = &retval; - fci.param_count = 2; - fci.params = argv; + fci.size = sizeof(fci); + ZVAL_COPY_VALUE(&fci.function_name, &t->func_name); + fci.object = NULL; + fci.retval = &retval; + fci.param_count = 2; + fci.params = argv; #if PHP_VERSION_ID >= 80000 - fci.named_params = NULL; + fci.named_params = NULL; #else - fci.no_separation = 0; -#endif - ch->in_callback = 1; - error = zend_call_function(&fci, &t->fci_cache); - ch->in_callback = 0; - if (error == FAILURE) { - php_error_docref(NULL, E_WARNING, "Could not call the CURLOPT_HEADERFUNCTION"); - length = -1; - } else if (!Z_ISUNDEF(retval)) { - _php_curl_verify_handlers(ch, 1); - length = zval_get_long(&retval); - } - zval_ptr_dtor(&argv[0]); - zval_ptr_dtor(&argv[1]); - break; - } + fci.no_separation = 0; +#endif + ch->in_callback = 1; + error = zend_call_function(&fci, &t->fci_cache); + ch->in_callback = 0; + if (error == FAILURE) { + php_error_docref(NULL, E_WARNING, "Could not call the CURLOPT_HEADERFUNCTION"); + length = -1; + } else if (!Z_ISUNDEF(retval)) { + _php_curl_verify_handlers(ch, 1); + length = zval_get_long(&retval); + } + zval_ptr_dtor(&argv[0]); + zval_ptr_dtor(&argv[1]); + break; + } - case PHP_CURL_IGNORE: - return length; + case PHP_CURL_IGNORE: + return length; - default: - return -1; + default: + return -1; } return length; @@ -876,7 +867,7 @@ static size_t fn_write_header(char *data, size_t size, size_t nmemb, void *ctx) static int curl_debug(CURL *cp, curl_infotype type, char *buf, size_t buf_len, void *ctx) /* {{{ */ { - php_curl *ch = (php_curl *)ctx; + php_curl *ch = (php_curl *) ctx; if (type == CURLINFO_HEADER_OUT) { if (ch->header.str) { @@ -893,20 +884,18 @@ static int curl_debug(CURL *cp, curl_infotype type, char *buf, size_t buf_len, v /* {{{ curl_free_string */ -static void curl_free_string(void **string) -{ - efree((char *)*string); +static void curl_free_string(void **string) { + efree((char *) *string); } /* }}} */ /* {{{ curl_free_post */ -static void curl_free_post(void **post) -{ +static void curl_free_post(void **post) { #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ - curl_mime_free((curl_mime *)*post); + curl_mime_free((curl_mime *) *post); #else - curl_formfree((struct HttpPost *)*post); + curl_formfree((struct HttpPost *) *post); #endif } /* }}} */ @@ -918,8 +907,7 @@ struct mime_data_cb_arg { /* {{{ curl_free_cb_arg */ -static void curl_free_cb_arg(void **cb_arg_p) -{ +static void curl_free_cb_arg(void **cb_arg_p) { struct mime_data_cb_arg *cb_arg = (struct mime_data_cb_arg *) *cb_arg_p; ZEND_ASSERT(cb_arg->stream == NULL); @@ -930,23 +918,21 @@ static void curl_free_cb_arg(void **cb_arg_p) /* {{{ curl_free_slist */ -static void curl_free_slist(zval *el) -{ - curl_slist_free_all(((struct curl_slist *)Z_PTR_P(el))); +static void curl_free_slist(zval *el) { + curl_slist_free_all(((struct curl_slist *) Z_PTR_P(el))); } /* }}} */ #if PHP_VERSION_ID >= 80000 -php_curl *init_curl_handle_into_zval(zval *curl) -{ - php_curl *ch; +php_curl *init_curl_handle_into_zval(zval *curl) { + php_curl *ch; - object_init_ex(curl, swoole_coroutine_curl_handle_ce); - ch = Z_CURL_P(curl); + object_init_ex(curl, swoole_coroutine_curl_handle_ce); + ch = Z_CURL_P(curl); - init_curl_handle(ch); + init_curl_handle(ch); - return ch; + return ch; } #endif @@ -959,25 +945,25 @@ php_curl *alloc_curl_handle() #endif { #if PHP_VERSION_ID < 80000 - php_curl *ch = (php_curl *)ecalloc(1, sizeof(php_curl)); -#endif - ch->to_free = (struct _php_curl_free *)ecalloc(1, sizeof(struct _php_curl_free)); - ch->handlers = (php_curl_handlers *)ecalloc(1, sizeof(php_curl_handlers)); - ch->handlers->write = (php_curl_write *)ecalloc(1, sizeof(php_curl_write)); - ch->handlers->write_header = (php_curl_write *)ecalloc(1, sizeof(php_curl_write)); - ch->handlers->read = (php_curl_read *)ecalloc(1, sizeof(php_curl_read)); - ch->handlers->progress = NULL; + php_curl *ch = (php_curl *) ecalloc(1, sizeof(php_curl)); +#endif + ch->to_free = (struct _php_curl_free *) ecalloc(1, sizeof(struct _php_curl_free)); + ch->handlers = (php_curl_handlers *) ecalloc(1, sizeof(php_curl_handlers)); + ch->handlers->write = (php_curl_write *) ecalloc(1, sizeof(php_curl_write)); + ch->handlers->write_header = (php_curl_write *) ecalloc(1, sizeof(php_curl_write)); + ch->handlers->read = (php_curl_read *) ecalloc(1, sizeof(php_curl_read)); + ch->handlers->progress = NULL; #if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */ - ch->handlers->fnmatch = NULL; + ch->handlers->fnmatch = NULL; #endif - ch->clone = (uint32_t *)emalloc(sizeof(uint32_t)); - *ch->clone = 1; + ch->clone = (uint32_t *) emalloc(sizeof(uint32_t)); + *ch->clone = 1; memset(&ch->err, 0, sizeof(struct _php_curl_error)); - zend_llist_init(&ch->to_free->str, sizeof(char *), (llist_dtor_func_t)curl_free_string, 0); - zend_llist_init(&ch->to_free->post, sizeof(struct HttpPost *), (llist_dtor_func_t)curl_free_post, 0); - zend_llist_init(&ch->to_free->stream, sizeof(struct mime_data_cb_arg *), (llist_dtor_func_t)curl_free_cb_arg, 0); + zend_llist_init(&ch->to_free->str, sizeof(char *), (llist_dtor_func_t) curl_free_string, 0); + zend_llist_init(&ch->to_free->post, sizeof(struct HttpPost *), (llist_dtor_func_t) curl_free_post, 0); + zend_llist_init(&ch->to_free->stream, sizeof(struct mime_data_cb_arg *), (llist_dtor_func_t) curl_free_cb_arg, 0); ch->to_free->slist = (HashTable *) emalloc(sizeof(HashTable)); zend_hash_init(ch->to_free->slist, 4, NULL, curl_free_slist, 0); @@ -994,14 +980,13 @@ php_curl *alloc_curl_handle() #if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */ /* {{{ create_certinfo */ -static void create_certinfo(struct curl_certinfo *ci, zval *listcode) -{ +static void create_certinfo(struct curl_certinfo *ci, zval *listcode) { int i; if (ci) { zval certhash; - for (i=0; inum_of_certs; i++) { + for (i = 0; i < ci->num_of_certs; i++) { struct curl_slist *slist; array_init(&certhash); @@ -1010,12 +995,12 @@ static void create_certinfo(struct curl_certinfo *ci, zval *listcode) char s[64]; char *tmp; strncpy(s, slist->data, sizeof(s)); - s[sizeof(s)-1] = '\0'; - tmp = (char *)memchr(s, ':', sizeof(s)); - if(tmp) { + s[sizeof(s) - 1] = '\0'; + tmp = (char *) memchr(s, ':', sizeof(s)); + if (tmp) { *tmp = '\0'; len = strlen(s); - add_assoc_string(&certhash, s, &slist->data[len+1]); + add_assoc_string(&certhash, s, &slist->data[len + 1]); } else { php_error_docref(NULL, E_WARNING, "Could not extract hash key from certificate info"); } @@ -1029,19 +1014,18 @@ static void create_certinfo(struct curl_certinfo *ci, zval *listcode) /* {{{ _php_curl_set_default_options() Set default options for a handle */ -static void _php_curl_set_default_options(php_curl *ch) -{ +static void _php_curl_set_default_options(php_curl *ch) { const char *cainfo; - curl_easy_setopt(ch->cp, CURLOPT_NOPROGRESS, 1); - curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0); - curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER, ch->err.str); - curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, fn_write); - curl_easy_setopt(ch->cp, CURLOPT_FILE, (void *) ch); - curl_easy_setopt(ch->cp, CURLOPT_READFUNCTION, fn_read); - curl_easy_setopt(ch->cp, CURLOPT_INFILE, (void *) ch); - curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, fn_write_header); - curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch); + curl_easy_setopt(ch->cp, CURLOPT_NOPROGRESS, 1); + curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0); + curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER, ch->err.str); + curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, fn_write); + curl_easy_setopt(ch->cp, CURLOPT_FILE, (void *) ch); + curl_easy_setopt(ch->cp, CURLOPT_READFUNCTION, fn_read); + curl_easy_setopt(ch->cp, CURLOPT_INFILE, (void *) ch); + curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, fn_write_header); + curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch); curl_easy_setopt(ch->cp, CURLOPT_PRIVATE, ch); #if !defined(ZTS) @@ -1063,18 +1047,17 @@ static void _php_curl_set_default_options(php_curl *ch) /* {{{ proto resource curl_init([string url]) Initialize a cURL session */ -PHP_FUNCTION(swoole_native_curl_init) -{ +PHP_FUNCTION(swoole_native_curl_init) { php_curl *ch; - CURL *cp; + CURL *cp; zend_string *url = NULL; ZEND_PARSE_PARAMETERS_START(0, 1) - Z_PARAM_OPTIONAL + Z_PARAM_OPTIONAL #if PHP_VERSION_ID >= 80000 - Z_PARAM_STR_OR_NULL(url) + Z_PARAM_STR_OR_NULL(url) #else - Z_PARAM_STR(url) + Z_PARAM_STR(url) #endif ZEND_PARSE_PARAMETERS_END(); @@ -1093,7 +1076,7 @@ PHP_FUNCTION(swoole_native_curl_init) ch->cp = cp; ch->handlers->write->method = PHP_CURL_STDOUT; - ch->handlers->read->method = PHP_CURL_DIRECT; + ch->handlers->read->method = PHP_CURL_DIRECT; ch->handlers->write_header->method = PHP_CURL_IGNORE; _php_curl_set_default_options(ch); @@ -1101,23 +1084,22 @@ PHP_FUNCTION(swoole_native_curl_init) if (url) { if (php_curl_option_url(ch, ZSTR_VAL(url), ZSTR_LEN(url)) == FAILURE) { #if PHP_VERSION_ID >= 80000 - zval_ptr_dtor(return_value); + zval_ptr_dtor(return_value); #else - _php_curl_close_ex(ch); + _php_curl_close_ex(ch); #endif RETURN_FALSE; } } #if PHP_VERSION_ID < 80000 - ZVAL_RES(return_value, zend_register_resource(ch, le_curl)); - ch->res = Z_RES_P(return_value); + ZVAL_RES(return_value, zend_register_resource(ch, le_curl)); + ch->res = Z_RES_P(return_value); #endif } /* }}} */ -void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source) -{ +void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source) { if (!Z_ISUNDEF(source->handlers->write->stream)) { Z_ADDREF(source->handlers->write->stream); } @@ -1126,8 +1108,8 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source) if (!Z_ISUNDEF(source->handlers->read->stream)) { Z_ADDREF(source->handlers->read->stream); } - ch->handlers->read->stream = source->handlers->read->stream; - ch->handlers->read->method = source->handlers->read->method; + ch->handlers->read->stream = source->handlers->read->stream; + ch->handlers->read->method = source->handlers->read->method; ch->handlers->write_header->method = source->handlers->write_header->method; if (!Z_ISUNDEF(source->handlers->write_header->stream)) { Z_ADDREF(source->handlers->write_header->stream); @@ -1156,13 +1138,13 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source) ZVAL_COPY(&ch->handlers->write_header->func_name, &source->handlers->write_header->func_name); } - curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER, ch->err.str); - curl_easy_setopt(ch->cp, CURLOPT_FILE, (void *) ch); - curl_easy_setopt(ch->cp, CURLOPT_INFILE, (void *) ch); - curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch); + curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER, ch->err.str); + curl_easy_setopt(ch->cp, CURLOPT_FILE, (void *) ch); + curl_easy_setopt(ch->cp, CURLOPT_INFILE, (void *) ch); + curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch); if (source->handlers->progress) { - ch->handlers->progress = (php_curl_progress *)ecalloc(1, sizeof(php_curl_progress)); + ch->handlers->progress = (php_curl_progress *) ecalloc(1, sizeof(php_curl_progress)); if (!Z_ISUNDEF(source->handlers->progress->func_name)) { ZVAL_COPY(&ch->handlers->progress->func_name, &source->handlers->progress->func_name); } @@ -1172,7 +1154,7 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source) #if LIBCURL_VERSION_NUM >= 0x071500 if (source->handlers->fnmatch) { - ch->handlers->fnmatch = (php_curl_fnmatch *)ecalloc(1, sizeof(php_curl_fnmatch)); + ch->handlers->fnmatch = (php_curl_fnmatch *) ecalloc(1, sizeof(php_curl_fnmatch)); if (!Z_ISUNDEF(source->handlers->fnmatch->func_name)) { ZVAL_COPY(&ch->handlers->fnmatch->func_name, &source->handlers->fnmatch->func_name); } @@ -1191,7 +1173,7 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source) (*source->clone)++; } -#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ +#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ static size_t read_cb(char *buffer, size_t size, size_t nitems, void *arg) /* {{{ */ { struct mime_data_cb_arg *cb_arg = (struct mime_data_cb_arg *) arg; @@ -1250,7 +1232,7 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields CURLcode form_error; #else struct HttpPost *first = NULL; - struct HttpPost *last = NULL; + struct HttpPost *last = NULL; CURLFORMcode form_error; #endif @@ -1282,8 +1264,7 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields } ZVAL_DEREF(current); - if (Z_TYPE_P(current) == IS_OBJECT && - instanceof_function(Z_OBJCE_P(current), curl_CURLFile_class)) { + if (Z_TYPE_P(current) == IS_OBJECT && instanceof_function(Z_OBJCE_P(current), curl_CURLFile_class)) { /* new-style file upload */ zval *prop, rv; char *type = NULL, *filename = NULL; @@ -1295,7 +1276,7 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields curl_seek_callback seekfunc = seek_cb; #endif - prop = zend_read_property(curl_CURLFile_class, SW_Z8_OBJ_P(current), "name", sizeof("name")-1, 0, &rv); + prop = zend_read_property(curl_CURLFile_class, SW_Z8_OBJ_P(current), "name", sizeof("name") - 1, 0, &rv); if (Z_TYPE_P(prop) != IS_STRING) { php_error_docref(NULL, E_WARNING, "Invalid filename for key %s", ZSTR_VAL(string_key)); } else { @@ -1305,11 +1286,13 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields return 1; } - prop = zend_read_property(curl_CURLFile_class, SW_Z8_OBJ_P(current), "mime", sizeof("mime")-1, 0, &rv); + prop = + zend_read_property(curl_CURLFile_class, SW_Z8_OBJ_P(current), "mime", sizeof("mime") - 1, 0, &rv); if (Z_TYPE_P(prop) == IS_STRING && Z_STRLEN_P(prop) > 0) { type = Z_STRVAL_P(prop); } - prop = zend_read_property(curl_CURLFile_class, SW_Z8_OBJ_P(current), "postname", sizeof("postname")-1, 0, &rv); + prop = zend_read_property( + curl_CURLFile_class, SW_Z8_OBJ_P(current), "postname", sizeof("postname") - 1, 0, &rv); if (Z_TYPE_P(prop) == IS_STRING && Z_STRLEN_P(prop) > 0) { filename = Z_STRVAL_P(prop); } @@ -1335,24 +1318,30 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields zend_string_release(string_key); return FAILURE; } - if ((form_error = curl_mime_name(part, ZSTR_VAL(string_key))) != CURLE_OK - || (form_error = curl_mime_data_cb(part, filesize, read_cb, seekfunc, free_cb, cb_arg)) != CURLE_OK - || (form_error = curl_mime_filename(part, filename ? filename : ZSTR_VAL(postval))) != CURLE_OK - || (form_error = curl_mime_type(part, type ? type : "application/octet-stream")) != CURLE_OK) { + if ((form_error = curl_mime_name(part, ZSTR_VAL(string_key))) != CURLE_OK || + (form_error = curl_mime_data_cb(part, filesize, read_cb, seekfunc, free_cb, cb_arg)) != CURLE_OK || + (form_error = curl_mime_filename(part, filename ? filename : ZSTR_VAL(postval))) != CURLE_OK || + (form_error = curl_mime_type(part, type ? type : "application/octet-stream")) != CURLE_OK) { error = form_error; } zend_llist_add_element(&ch->to_free->stream, &cb_arg); #else - form_error = curl_formadd(&first, &last, - CURLFORM_COPYNAME, ZSTR_VAL(string_key), - CURLFORM_NAMELENGTH, ZSTR_LEN(string_key), - CURLFORM_FILENAME, filename ? filename : ZSTR_VAL(postval), - CURLFORM_CONTENTTYPE, type ? type : "application/octet-stream", - CURLFORM_FILE, ZSTR_VAL(postval), - CURLFORM_END); + form_error = curl_formadd(&first, + &last, + CURLFORM_COPYNAME, + ZSTR_VAL(string_key), + CURLFORM_NAMELENGTH, + ZSTR_LEN(string_key), + CURLFORM_FILENAME, + filename ? filename : ZSTR_VAL(postval), + CURLFORM_CONTENTTYPE, + type ? type : "application/octet-stream", + CURLFORM_FILE, + ZSTR_VAL(postval), + CURLFORM_END); if (form_error != CURL_FORMADD_OK) { /* Not nice to convert between enums but we only have place for one error type */ - error = (CURLcode)form_error; + error = (CURLcode) form_error; } #endif } @@ -1370,29 +1359,35 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields zend_string_release(string_key); return FAILURE; } - if ((form_error = curl_mime_name(part, ZSTR_VAL(string_key))) != CURLE_OK - || (form_error = curl_mime_data(part, ZSTR_VAL(postval), ZSTR_LEN(postval))) != CURLE_OK) { + if ((form_error = curl_mime_name(part, ZSTR_VAL(string_key))) != CURLE_OK || + (form_error = curl_mime_data(part, ZSTR_VAL(postval), ZSTR_LEN(postval))) != CURLE_OK) { error = form_error; } #else /* The arguments after _NAMELENGTH and _CONTENTSLENGTH - * must be explicitly cast to long in curl_formadd - * use since curl needs a long not an int. */ - form_error = curl_formadd(&first, &last, - CURLFORM_COPYNAME, ZSTR_VAL(string_key), - CURLFORM_NAMELENGTH, ZSTR_LEN(string_key), - CURLFORM_COPYCONTENTS, ZSTR_VAL(postval), - CURLFORM_CONTENTSLENGTH, ZSTR_LEN(postval), - CURLFORM_END); + * must be explicitly cast to long in curl_formadd + * use since curl needs a long not an int. */ + form_error = curl_formadd(&first, + &last, + CURLFORM_COPYNAME, + ZSTR_VAL(string_key), + CURLFORM_NAMELENGTH, + ZSTR_LEN(string_key), + CURLFORM_COPYCONTENTS, + ZSTR_VAL(postval), + CURLFORM_CONTENTSLENGTH, + ZSTR_LEN(postval), + CURLFORM_END); if (form_error != CURL_FORMADD_OK) { /* Not nice to convert between enums but we only have place for one error type */ - error = (CURLcode)form_error; + error = (CURLcode) form_error; } #endif zend_string_release(postval); zend_string_release(string_key); - } ZEND_HASH_FOREACH_END(); + } + ZEND_HASH_FOREACH_END(); SAVE_CURL_ERROR(ch, error); if (error != CURLE_OK) { @@ -1417,20 +1412,19 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields /* {{{ proto resource curl_copy_handle(resource ch) Copy a cURL handle along with all of it's preferences */ -PHP_FUNCTION(swoole_native_curl_copy_handle) -{ - CURL *cp; - zval *zid; - php_curl *ch, *dupch; +PHP_FUNCTION(swoole_native_curl_copy_handle) { + CURL *cp; + zval *zid; + php_curl *ch, *dupch; #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ - zval *postfields; + zval *postfields; #endif - ZEND_PARSE_PARAMETERS_START(1,1) + ZEND_PARSE_PARAMETERS_START(1, 1) #if PHP_VERSION_ID >= 80000 - Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) + Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) #else - Z_PARAM_RESOURCE(zid) + Z_PARAM_RESOURCE(zid) #endif ZEND_PARSE_PARAMETERS_END(); @@ -1457,11 +1451,11 @@ PHP_FUNCTION(swoole_native_curl_copy_handle) postfields = &ch->postfields; if (Z_TYPE_P(postfields) != IS_UNDEF) { if (build_mime_structure_from_hash(dupch, postfields) != SUCCESS) { - #if PHP_VERSION_ID >= 80000 +#if PHP_VERSION_ID >= 80000 zval_ptr_dtor(return_value); - #else +#else _php_curl_close_ex(dupch); - #endif +#endif php_error_docref(NULL, E_WARNING, "Cannot rebuild mime structure"); RETURN_FALSE; } @@ -1484,767 +1478,770 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{ zend_long lval; switch (option) { - /* Long options */ - case CURLOPT_SSL_VERIFYHOST: - lval = zval_get_long(zvalue); - if (lval == 1) { + /* Long options */ + case CURLOPT_SSL_VERIFYHOST: + lval = zval_get_long(zvalue); + if (lval == 1) { #if LIBCURL_VERSION_NUM <= 0x071c00 /* 7.28.0 */ - php_error_docref(NULL, E_NOTICE, "CURLOPT_SSL_VERIFYHOST with value 1 is deprecated and will be removed as of libcurl 7.28.1. It is recommended to use value 2 instead"); + php_error_docref(NULL, + E_NOTICE, + "CURLOPT_SSL_VERIFYHOST with value 1 is deprecated and will be removed as of libcurl " + "7.28.1. It is recommended to use value 2 instead"); #else - php_error_docref(NULL, E_NOTICE, "CURLOPT_SSL_VERIFYHOST no longer accepts the value 1, value 2 will be used instead"); - error = curl_easy_setopt(ch->cp, (CURLoption) option, 2); - break; + php_error_docref( + NULL, E_NOTICE, "CURLOPT_SSL_VERIFYHOST no longer accepts the value 1, value 2 will be used instead"); + error = curl_easy_setopt(ch->cp, (CURLoption) option, 2); + break; #endif - } - /* no break */ - case CURLOPT_AUTOREFERER: - case CURLOPT_BUFFERSIZE: - case CURLOPT_CONNECTTIMEOUT: - case CURLOPT_COOKIESESSION: - case CURLOPT_CRLF: - case CURLOPT_DNS_CACHE_TIMEOUT: - case CURLOPT_DNS_USE_GLOBAL_CACHE: - case CURLOPT_FAILONERROR: - case CURLOPT_FILETIME: - case CURLOPT_FORBID_REUSE: - case CURLOPT_FRESH_CONNECT: - case CURLOPT_FTP_USE_EPRT: - case CURLOPT_FTP_USE_EPSV: - case CURLOPT_HEADER: - case CURLOPT_HTTPGET: - case CURLOPT_HTTPPROXYTUNNEL: - case CURLOPT_HTTP_VERSION: - case CURLOPT_INFILESIZE: - case CURLOPT_LOW_SPEED_LIMIT: - case CURLOPT_LOW_SPEED_TIME: - case CURLOPT_MAXCONNECTS: - case CURLOPT_MAXREDIRS: - case CURLOPT_NETRC: - case CURLOPT_NOBODY: - case CURLOPT_NOPROGRESS: - case CURLOPT_NOSIGNAL: - case CURLOPT_PORT: - case CURLOPT_POST: - case CURLOPT_PROXYPORT: - case CURLOPT_PROXYTYPE: - case CURLOPT_PUT: - case CURLOPT_RESUME_FROM: - case CURLOPT_SSLVERSION: - case CURLOPT_SSL_VERIFYPEER: - case CURLOPT_TIMECONDITION: - case CURLOPT_TIMEOUT: - case CURLOPT_TIMEVALUE: - case CURLOPT_TRANSFERTEXT: - case CURLOPT_UNRESTRICTED_AUTH: - case CURLOPT_UPLOAD: - case CURLOPT_VERBOSE: - case CURLOPT_HTTPAUTH: - case CURLOPT_FTP_CREATE_MISSING_DIRS: - case CURLOPT_PROXYAUTH: - case CURLOPT_FTP_RESPONSE_TIMEOUT: - case CURLOPT_IPRESOLVE: - case CURLOPT_MAXFILESIZE: - case CURLOPT_TCP_NODELAY: - case CURLOPT_FTPSSLAUTH: - case CURLOPT_IGNORE_CONTENT_LENGTH: - case CURLOPT_FTP_SKIP_PASV_IP: - case CURLOPT_FTP_FILEMETHOD: - case CURLOPT_CONNECT_ONLY: - case CURLOPT_LOCALPORT: - case CURLOPT_LOCALPORTRANGE: + } + /* no break */ + case CURLOPT_AUTOREFERER: + case CURLOPT_BUFFERSIZE: + case CURLOPT_CONNECTTIMEOUT: + case CURLOPT_COOKIESESSION: + case CURLOPT_CRLF: + case CURLOPT_DNS_CACHE_TIMEOUT: + case CURLOPT_DNS_USE_GLOBAL_CACHE: + case CURLOPT_FAILONERROR: + case CURLOPT_FILETIME: + case CURLOPT_FORBID_REUSE: + case CURLOPT_FRESH_CONNECT: + case CURLOPT_FTP_USE_EPRT: + case CURLOPT_FTP_USE_EPSV: + case CURLOPT_HEADER: + case CURLOPT_HTTPGET: + case CURLOPT_HTTPPROXYTUNNEL: + case CURLOPT_HTTP_VERSION: + case CURLOPT_INFILESIZE: + case CURLOPT_LOW_SPEED_LIMIT: + case CURLOPT_LOW_SPEED_TIME: + case CURLOPT_MAXCONNECTS: + case CURLOPT_MAXREDIRS: + case CURLOPT_NETRC: + case CURLOPT_NOBODY: + case CURLOPT_NOPROGRESS: + case CURLOPT_NOSIGNAL: + case CURLOPT_PORT: + case CURLOPT_POST: + case CURLOPT_PROXYPORT: + case CURLOPT_PROXYTYPE: + case CURLOPT_PUT: + case CURLOPT_RESUME_FROM: + case CURLOPT_SSLVERSION: + case CURLOPT_SSL_VERIFYPEER: + case CURLOPT_TIMECONDITION: + case CURLOPT_TIMEOUT: + case CURLOPT_TIMEVALUE: + case CURLOPT_TRANSFERTEXT: + case CURLOPT_UNRESTRICTED_AUTH: + case CURLOPT_UPLOAD: + case CURLOPT_VERBOSE: + case CURLOPT_HTTPAUTH: + case CURLOPT_FTP_CREATE_MISSING_DIRS: + case CURLOPT_PROXYAUTH: + case CURLOPT_FTP_RESPONSE_TIMEOUT: + case CURLOPT_IPRESOLVE: + case CURLOPT_MAXFILESIZE: + case CURLOPT_TCP_NODELAY: + case CURLOPT_FTPSSLAUTH: + case CURLOPT_IGNORE_CONTENT_LENGTH: + case CURLOPT_FTP_SKIP_PASV_IP: + case CURLOPT_FTP_FILEMETHOD: + case CURLOPT_CONNECT_ONLY: + case CURLOPT_LOCALPORT: + case CURLOPT_LOCALPORTRANGE: #if LIBCURL_VERSION_NUM >= 0x071000 /* Available since 7.16.0 */ - case CURLOPT_SSL_SESSIONID_CACHE: + case CURLOPT_SSL_SESSIONID_CACHE: #endif #if LIBCURL_VERSION_NUM >= 0x071001 /* Available since 7.16.1 */ - case CURLOPT_FTP_SSL_CCC: - case CURLOPT_SSH_AUTH_TYPES: + case CURLOPT_FTP_SSL_CCC: + case CURLOPT_SSH_AUTH_TYPES: #endif #if LIBCURL_VERSION_NUM >= 0x071002 /* Available since 7.16.2 */ - case CURLOPT_CONNECTTIMEOUT_MS: - case CURLOPT_HTTP_CONTENT_DECODING: - case CURLOPT_HTTP_TRANSFER_DECODING: - case CURLOPT_TIMEOUT_MS: + case CURLOPT_CONNECTTIMEOUT_MS: + case CURLOPT_HTTP_CONTENT_DECODING: + case CURLOPT_HTTP_TRANSFER_DECODING: + case CURLOPT_TIMEOUT_MS: #endif #if LIBCURL_VERSION_NUM >= 0x071004 /* Available since 7.16.4 */ - case CURLOPT_NEW_DIRECTORY_PERMS: - case CURLOPT_NEW_FILE_PERMS: + case CURLOPT_NEW_DIRECTORY_PERMS: + case CURLOPT_NEW_FILE_PERMS: #endif #if LIBCURL_VERSION_NUM >= 0x071100 /* Available since 7.17.0 */ - case CURLOPT_USE_SSL: - case CURLOPT_APPEND: - case CURLOPT_DIRLISTONLY: + case CURLOPT_USE_SSL: + case CURLOPT_APPEND: + case CURLOPT_DIRLISTONLY: #else - case CURLOPT_FTP_SSL: - case CURLOPT_FTPAPPEND: - case CURLOPT_FTPLISTONLY: + case CURLOPT_FTP_SSL: + case CURLOPT_FTPAPPEND: + case CURLOPT_FTPLISTONLY: #endif #if LIBCURL_VERSION_NUM >= 0x071200 /* Available since 7.18.0 */ - case CURLOPT_PROXY_TRANSFER_MODE: + case CURLOPT_PROXY_TRANSFER_MODE: #endif #if LIBCURL_VERSION_NUM >= 0x071300 /* Available since 7.19.0 */ - case CURLOPT_ADDRESS_SCOPE: + case CURLOPT_ADDRESS_SCOPE: #endif -#if LIBCURL_VERSION_NUM > 0x071301 /* Available since 7.19.1 */ - case CURLOPT_CERTINFO: +#if LIBCURL_VERSION_NUM > 0x071301 /* Available since 7.19.1 */ + case CURLOPT_CERTINFO: #endif #if LIBCURL_VERSION_NUM >= 0x071304 /* Available since 7.19.4 */ - case CURLOPT_PROTOCOLS: - case CURLOPT_REDIR_PROTOCOLS: - case CURLOPT_SOCKS5_GSSAPI_NEC: - case CURLOPT_TFTP_BLKSIZE: + case CURLOPT_PROTOCOLS: + case CURLOPT_REDIR_PROTOCOLS: + case CURLOPT_SOCKS5_GSSAPI_NEC: + case CURLOPT_TFTP_BLKSIZE: #endif #if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */ - case CURLOPT_FTP_USE_PRET: - case CURLOPT_RTSP_CLIENT_CSEQ: - case CURLOPT_RTSP_REQUEST: - case CURLOPT_RTSP_SERVER_CSEQ: + case CURLOPT_FTP_USE_PRET: + case CURLOPT_RTSP_CLIENT_CSEQ: + case CURLOPT_RTSP_REQUEST: + case CURLOPT_RTSP_SERVER_CSEQ: #endif #if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */ - case CURLOPT_WILDCARDMATCH: + case CURLOPT_WILDCARDMATCH: #endif #if LIBCURL_VERSION_NUM >= 0x071504 /* Available since 7.21.4 */ - case CURLOPT_TLSAUTH_TYPE: + case CURLOPT_TLSAUTH_TYPE: #endif #if LIBCURL_VERSION_NUM >= 0x071600 /* Available since 7.22.0 */ - case CURLOPT_GSSAPI_DELEGATION: + case CURLOPT_GSSAPI_DELEGATION: #endif #if LIBCURL_VERSION_NUM >= 0x071800 /* Available since 7.24.0 */ - case CURLOPT_ACCEPTTIMEOUT_MS: + case CURLOPT_ACCEPTTIMEOUT_MS: #endif #if LIBCURL_VERSION_NUM >= 0x071900 /* Available since 7.25.0 */ - case CURLOPT_SSL_OPTIONS: - case CURLOPT_TCP_KEEPALIVE: - case CURLOPT_TCP_KEEPIDLE: - case CURLOPT_TCP_KEEPINTVL: + case CURLOPT_SSL_OPTIONS: + case CURLOPT_TCP_KEEPALIVE: + case CURLOPT_TCP_KEEPIDLE: + case CURLOPT_TCP_KEEPINTVL: #endif #if LIBCURL_VERSION_NUM >= 0x071f00 /* Available since 7.31.0 */ - case CURLOPT_SASL_IR: + case CURLOPT_SASL_IR: #endif #if LIBCURL_VERSION_NUM >= 0x072400 /* Available since 7.36.0 */ - case CURLOPT_EXPECT_100_TIMEOUT_MS: - case CURLOPT_SSL_ENABLE_ALPN: - case CURLOPT_SSL_ENABLE_NPN: + case CURLOPT_EXPECT_100_TIMEOUT_MS: + case CURLOPT_SSL_ENABLE_ALPN: + case CURLOPT_SSL_ENABLE_NPN: #endif #if LIBCURL_VERSION_NUM >= 0x072500 /* Available since 7.37.0 */ - case CURLOPT_HEADEROPT: + case CURLOPT_HEADEROPT: #endif #if LIBCURL_VERSION_NUM >= 0x072900 /* Available since 7.41.0 */ - case CURLOPT_SSL_VERIFYSTATUS: + case CURLOPT_SSL_VERIFYSTATUS: #endif #if LIBCURL_VERSION_NUM >= 0x072a00 /* Available since 7.42.0 */ - case CURLOPT_PATH_AS_IS: - case CURLOPT_SSL_FALSESTART: + case CURLOPT_PATH_AS_IS: + case CURLOPT_SSL_FALSESTART: #endif #if LIBCURL_VERSION_NUM >= 0x072b00 /* Available since 7.43.0 */ - case CURLOPT_PIPEWAIT: + case CURLOPT_PIPEWAIT: #endif #if LIBCURL_VERSION_NUM >= 0x072e00 /* Available since 7.46.0 */ - case CURLOPT_STREAM_WEIGHT: + case CURLOPT_STREAM_WEIGHT: #endif #if LIBCURL_VERSION_NUM >= 0x073000 /* Available since 7.48.0 */ - case CURLOPT_TFTP_NO_OPTIONS: + case CURLOPT_TFTP_NO_OPTIONS: #endif #if LIBCURL_VERSION_NUM >= 0x073100 /* Available since 7.49.0 */ - case CURLOPT_TCP_FASTOPEN: + case CURLOPT_TCP_FASTOPEN: #endif #if LIBCURL_VERSION_NUM >= 0x073300 /* Available since 7.51.0 */ - case CURLOPT_KEEP_SENDING_ON_ERROR: + case CURLOPT_KEEP_SENDING_ON_ERROR: #endif #if LIBCURL_VERSION_NUM >= 0x073400 /* Available since 7.52.0 */ - case CURLOPT_PROXY_SSL_OPTIONS: - case CURLOPT_PROXY_SSL_VERIFYHOST: - case CURLOPT_PROXY_SSL_VERIFYPEER: - case CURLOPT_PROXY_SSLVERSION: + case CURLOPT_PROXY_SSL_OPTIONS: + case CURLOPT_PROXY_SSL_VERIFYHOST: + case CURLOPT_PROXY_SSL_VERIFYPEER: + case CURLOPT_PROXY_SSLVERSION: #endif #if LIBCURL_VERSION_NUM >= 0x073600 /* Available since 7.54.0 */ - case CURLOPT_SUPPRESS_CONNECT_HEADERS: + case CURLOPT_SUPPRESS_CONNECT_HEADERS: #endif #if LIBCURL_VERSION_NUM >= 0x073700 /* Available since 7.55.0 */ - case CURLOPT_SOCKS5_AUTH: + case CURLOPT_SOCKS5_AUTH: #endif #if LIBCURL_VERSION_NUM >= 0x073800 /* Available since 7.56.0 */ - case CURLOPT_SSH_COMPRESSION: + case CURLOPT_SSH_COMPRESSION: #endif #if LIBCURL_VERSION_NUM >= 0x073b00 /* Available since 7.59.0 */ - case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS: + case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS: #endif #if LIBCURL_VERSION_NUM >= 0x073c00 /* Available since 7.60.0 */ - case CURLOPT_DNS_SHUFFLE_ADDRESSES: - case CURLOPT_HAPROXYPROTOCOL: + case CURLOPT_DNS_SHUFFLE_ADDRESSES: + case CURLOPT_HAPROXYPROTOCOL: #endif #if LIBCURL_VERSION_NUM >= 0x073d00 /* Available since 7.61.0 */ - case CURLOPT_DISALLOW_USERNAME_IN_URL: + case CURLOPT_DISALLOW_USERNAME_IN_URL: #endif #if LIBCURL_VERSION_NUM >= 0x074000 /* Available since 7.64.0 */ - case CURLOPT_HTTP09_ALLOWED: + case CURLOPT_HTTP09_ALLOWED: #endif - lval = zval_get_long(zvalue); + lval = zval_get_long(zvalue); #if LIBCURL_VERSION_NUM >= 0x071304 - if ((option == CURLOPT_PROTOCOLS || option == CURLOPT_REDIR_PROTOCOLS) && - (PG(open_basedir) && *PG(open_basedir)) && (lval & CURLPROTO_FILE)) { - php_error_docref(NULL, E_WARNING, "CURLPROTO_FILE cannot be activated when an open_basedir is set"); - return 1; - } + if ((option == CURLOPT_PROTOCOLS || option == CURLOPT_REDIR_PROTOCOLS) && + (PG(open_basedir) && *PG(open_basedir)) && (lval & CURLPROTO_FILE)) { + php_error_docref(NULL, E_WARNING, "CURLPROTO_FILE cannot be activated when an open_basedir is set"); + return 1; + } #endif -# if defined(ZTS) - if (option == CURLOPT_DNS_USE_GLOBAL_CACHE && lval) { - php_error_docref(NULL, E_WARNING, "CURLOPT_DNS_USE_GLOBAL_CACHE cannot be activated when thread safety is enabled"); - return 1; - } -# endif - error = curl_easy_setopt(ch->cp, (CURLoption) option, lval); - break; - case CURLOPT_SAFE_UPLOAD: - if (!zend_is_true(zvalue)) { - php_error_docref(NULL, E_WARNING, "Disabling safe uploads is no longer supported"); - return FAILURE; - } - break; +#if defined(ZTS) + if (option == CURLOPT_DNS_USE_GLOBAL_CACHE && lval) { + php_error_docref( + NULL, E_WARNING, "CURLOPT_DNS_USE_GLOBAL_CACHE cannot be activated when thread safety is enabled"); + return 1; + } +#endif + error = curl_easy_setopt(ch->cp, (CURLoption) option, lval); + break; + case CURLOPT_SAFE_UPLOAD: + if (!zend_is_true(zvalue)) { + php_error_docref(NULL, E_WARNING, "Disabling safe uploads is no longer supported"); + return FAILURE; + } + break; - /* String options */ - case CURLOPT_CAINFO: - case CURLOPT_CAPATH: - case CURLOPT_COOKIE: - case CURLOPT_EGDSOCKET: - case CURLOPT_INTERFACE: - case CURLOPT_PROXY: - case CURLOPT_PROXYUSERPWD: - case CURLOPT_REFERER: - case CURLOPT_SSLCERTTYPE: - case CURLOPT_SSLENGINE: - case CURLOPT_SSLENGINE_DEFAULT: - case CURLOPT_SSLKEY: - case CURLOPT_SSLKEYPASSWD: - case CURLOPT_SSLKEYTYPE: - case CURLOPT_SSL_CIPHER_LIST: - case CURLOPT_USERAGENT: - case CURLOPT_USERPWD: - case CURLOPT_COOKIELIST: - case CURLOPT_FTP_ALTERNATIVE_TO_USER: + /* String options */ + case CURLOPT_CAINFO: + case CURLOPT_CAPATH: + case CURLOPT_COOKIE: + case CURLOPT_EGDSOCKET: + case CURLOPT_INTERFACE: + case CURLOPT_PROXY: + case CURLOPT_PROXYUSERPWD: + case CURLOPT_REFERER: + case CURLOPT_SSLCERTTYPE: + case CURLOPT_SSLENGINE: + case CURLOPT_SSLENGINE_DEFAULT: + case CURLOPT_SSLKEY: + case CURLOPT_SSLKEYPASSWD: + case CURLOPT_SSLKEYTYPE: + case CURLOPT_SSL_CIPHER_LIST: + case CURLOPT_USERAGENT: + case CURLOPT_USERPWD: + case CURLOPT_COOKIELIST: + case CURLOPT_FTP_ALTERNATIVE_TO_USER: #if LIBCURL_VERSION_NUM >= 0x071101 /* Available since 7.17.1 */ - case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5: + case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5: #endif #if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */ - case CURLOPT_PASSWORD: - case CURLOPT_PROXYPASSWORD: - case CURLOPT_PROXYUSERNAME: - case CURLOPT_USERNAME: + case CURLOPT_PASSWORD: + case CURLOPT_PROXYPASSWORD: + case CURLOPT_PROXYUSERNAME: + case CURLOPT_USERNAME: #endif #if LIBCURL_VERSION_NUM >= 0x071304 /* Available since 7.19.4 */ - case CURLOPT_NOPROXY: - case CURLOPT_SOCKS5_GSSAPI_SERVICE: + case CURLOPT_NOPROXY: + case CURLOPT_SOCKS5_GSSAPI_SERVICE: #endif #if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */ - case CURLOPT_MAIL_FROM: - case CURLOPT_RTSP_STREAM_URI: - case CURLOPT_RTSP_TRANSPORT: + case CURLOPT_MAIL_FROM: + case CURLOPT_RTSP_STREAM_URI: + case CURLOPT_RTSP_TRANSPORT: #endif #if LIBCURL_VERSION_NUM >= 0x071504 /* Available since 7.21.4 */ - case CURLOPT_TLSAUTH_PASSWORD: - case CURLOPT_TLSAUTH_USERNAME: + case CURLOPT_TLSAUTH_PASSWORD: + case CURLOPT_TLSAUTH_USERNAME: #endif #if LIBCURL_VERSION_NUM >= 0x071506 /* Available since 7.21.6 */ - case CURLOPT_ACCEPT_ENCODING: - case CURLOPT_TRANSFER_ENCODING: + case CURLOPT_ACCEPT_ENCODING: + case CURLOPT_TRANSFER_ENCODING: #else - case CURLOPT_ENCODING: + case CURLOPT_ENCODING: #endif #if LIBCURL_VERSION_NUM >= 0x071800 /* Available since 7.24.0 */ - case CURLOPT_DNS_SERVERS: + case CURLOPT_DNS_SERVERS: #endif #if LIBCURL_VERSION_NUM >= 0x071900 /* Available since 7.25.0 */ - case CURLOPT_MAIL_AUTH: + case CURLOPT_MAIL_AUTH: #endif #if LIBCURL_VERSION_NUM >= 0x072200 /* Available since 7.34.0 */ - case CURLOPT_LOGIN_OPTIONS: + case CURLOPT_LOGIN_OPTIONS: #endif #if LIBCURL_VERSION_NUM >= 0x072700 /* Available since 7.39.0 */ - case CURLOPT_PINNEDPUBLICKEY: + case CURLOPT_PINNEDPUBLICKEY: #endif #if LIBCURL_VERSION_NUM >= 0x072b00 /* Available since 7.43.0 */ - case CURLOPT_PROXY_SERVICE_NAME: - case CURLOPT_SERVICE_NAME: + case CURLOPT_PROXY_SERVICE_NAME: + case CURLOPT_SERVICE_NAME: #endif #if LIBCURL_VERSION_NUM >= 0x072d00 /* Available since 7.45.0 */ - case CURLOPT_DEFAULT_PROTOCOL: + case CURLOPT_DEFAULT_PROTOCOL: #endif #if LIBCURL_VERSION_NUM >= 0x073400 /* Available since 7.52.0 */ - case CURLOPT_PRE_PROXY: - case CURLOPT_PROXY_CAINFO: - case CURLOPT_PROXY_CAPATH: - case CURLOPT_PROXY_CRLFILE: - case CURLOPT_PROXY_KEYPASSWD: - case CURLOPT_PROXY_PINNEDPUBLICKEY: - case CURLOPT_PROXY_SSL_CIPHER_LIST: - case CURLOPT_PROXY_SSLCERT: - case CURLOPT_PROXY_SSLCERTTYPE: - case CURLOPT_PROXY_SSLKEY: - case CURLOPT_PROXY_SSLKEYTYPE: - case CURLOPT_PROXY_TLSAUTH_PASSWORD: - case CURLOPT_PROXY_TLSAUTH_TYPE: - case CURLOPT_PROXY_TLSAUTH_USERNAME: + case CURLOPT_PRE_PROXY: + case CURLOPT_PROXY_CAINFO: + case CURLOPT_PROXY_CAPATH: + case CURLOPT_PROXY_CRLFILE: + case CURLOPT_PROXY_KEYPASSWD: + case CURLOPT_PROXY_PINNEDPUBLICKEY: + case CURLOPT_PROXY_SSL_CIPHER_LIST: + case CURLOPT_PROXY_SSLCERT: + case CURLOPT_PROXY_SSLCERTTYPE: + case CURLOPT_PROXY_SSLKEY: + case CURLOPT_PROXY_SSLKEYTYPE: + case CURLOPT_PROXY_TLSAUTH_PASSWORD: + case CURLOPT_PROXY_TLSAUTH_TYPE: + case CURLOPT_PROXY_TLSAUTH_USERNAME: #endif #if LIBCURL_VERSION_NUM >= 0x073500 /* Available since 7.53.0 */ - case CURLOPT_ABSTRACT_UNIX_SOCKET: + case CURLOPT_ABSTRACT_UNIX_SOCKET: #endif #if LIBCURL_VERSION_NUM >= 0x073700 /* Available since 7.55.0 */ - case CURLOPT_REQUEST_TARGET: + case CURLOPT_REQUEST_TARGET: #endif #if LIBCURL_VERSION_NUM >= 0x073d00 /* Available since 7.61.0 */ - case CURLOPT_PROXY_TLS13_CIPHERS: - case CURLOPT_TLS13_CIPHERS: + case CURLOPT_PROXY_TLS13_CIPHERS: + case CURLOPT_TLS13_CIPHERS: #endif - { - zend_string *str = zval_get_string(zvalue); - int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 0); - zend_string_release(str); - return ret; - } + { + zend_string *str = zval_get_string(zvalue); + int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 0); + zend_string_release(str); + return ret; + } - /* Curl nullable string options */ - case CURLOPT_CUSTOMREQUEST: - case CURLOPT_FTPPORT: - case CURLOPT_RANGE: - case CURLOPT_FTP_ACCOUNT: + /* Curl nullable string options */ + case CURLOPT_CUSTOMREQUEST: + case CURLOPT_FTPPORT: + case CURLOPT_RANGE: + case CURLOPT_FTP_ACCOUNT: #if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */ - case CURLOPT_RTSP_SESSION_ID: + case CURLOPT_RTSP_SESSION_ID: #endif #if LIBCURL_VERSION_NUM >= 0x072100 /* Available since 7.33.0 */ - case CURLOPT_DNS_INTERFACE: - case CURLOPT_DNS_LOCAL_IP4: - case CURLOPT_DNS_LOCAL_IP6: - case CURLOPT_XOAUTH2_BEARER: + case CURLOPT_DNS_INTERFACE: + case CURLOPT_DNS_LOCAL_IP4: + case CURLOPT_DNS_LOCAL_IP6: + case CURLOPT_XOAUTH2_BEARER: #endif #if LIBCURL_VERSION_NUM >= 0x072800 /* Available since 7.40.0 */ - case CURLOPT_UNIX_SOCKET_PATH: + case CURLOPT_UNIX_SOCKET_PATH: #endif #if LIBCURL_VERSION_NUM >= 0x071004 /* Available since 7.16.4 */ - case CURLOPT_KRBLEVEL: + case CURLOPT_KRBLEVEL: #else - case CURLOPT_KRB4LEVEL: + case CURLOPT_KRB4LEVEL: #endif - { - if (Z_ISNULL_P(zvalue)) { - error = curl_easy_setopt(ch->cp, (CURLoption) option, NULL); - } else { - zend_string *str = zval_get_string(zvalue); - int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 0); - zend_string_release(str); - return ret; - } - break; - } - - /* Curl private option */ - case CURLOPT_PRIVATE: - { + { + if (Z_ISNULL_P(zvalue)) { + error = curl_easy_setopt(ch->cp, (CURLoption) option, NULL); + } else { zend_string *str = zval_get_string(zvalue); - int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 1); + int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 0); zend_string_release(str); return ret; } + break; + } - /* Curl url option */ - case CURLOPT_URL: - { - zend_string *str = zval_get_string(zvalue); - int ret = php_curl_option_url(ch, ZSTR_VAL(str), ZSTR_LEN(str)); - zend_string_release(str); - return ret; - } + /* Curl private option */ + case CURLOPT_PRIVATE: { + zend_string *str = zval_get_string(zvalue); + int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 1); + zend_string_release(str); + return ret; + } - /* Curl file handle options */ - case CURLOPT_FILE: - case CURLOPT_INFILE: - case CURLOPT_STDERR: - case CURLOPT_WRITEHEADER: { - FILE *fp = NULL; - php_stream *what = NULL; + /* Curl url option */ + case CURLOPT_URL: { + zend_string *str = zval_get_string(zvalue); + int ret = php_curl_option_url(ch, ZSTR_VAL(str), ZSTR_LEN(str)); + zend_string_release(str); + return ret; + } - if (Z_TYPE_P(zvalue) != IS_NULL) { - what = (php_stream *)zend_fetch_resource2_ex(zvalue, "File-Handle", php_file_le_stream(), php_file_le_pstream()); - if (!what) { - return FAILURE; - } + /* Curl file handle options */ + case CURLOPT_FILE: + case CURLOPT_INFILE: + case CURLOPT_STDERR: + case CURLOPT_WRITEHEADER: { + FILE *fp = NULL; + php_stream *what = NULL; - if (FAILURE == php_stream_cast(what, PHP_STREAM_AS_STDIO, (void **) &fp, REPORT_ERRORS)) { - return FAILURE; - } + if (Z_TYPE_P(zvalue) != IS_NULL) { + what = (php_stream *) zend_fetch_resource2_ex( + zvalue, "File-Handle", php_file_le_stream(), php_file_le_pstream()); + if (!what) { + return FAILURE; + } - if (!fp) { - return FAILURE; - } + if (FAILURE == php_stream_cast(what, PHP_STREAM_AS_STDIO, (void **) &fp, REPORT_ERRORS)) { + return FAILURE; } - error = CURLE_OK; - switch (option) { - case CURLOPT_FILE: - if (!what) { - if (!Z_ISUNDEF(ch->handlers->write->stream)) { - zval_ptr_dtor(&ch->handlers->write->stream); - ZVAL_UNDEF(&ch->handlers->write->stream); - } - ch->handlers->write->fp = NULL; - ch->handlers->write->method = PHP_CURL_STDOUT; - } else if (what->mode[0] != 'r' || what->mode[1] == '+') { - zval_ptr_dtor(&ch->handlers->write->stream); - ch->handlers->write->fp = fp; - ch->handlers->write->method = PHP_CURL_FILE; - ZVAL_COPY(&ch->handlers->write->stream, zvalue); - } else { + if (!fp) { + return FAILURE; + } + } + + error = CURLE_OK; + switch (option) { + case CURLOPT_FILE: + if (!what) { + if (!Z_ISUNDEF(ch->handlers->write->stream)) { + zval_ptr_dtor(&ch->handlers->write->stream); + ZVAL_UNDEF(&ch->handlers->write->stream); + } + ch->handlers->write->fp = NULL; + ch->handlers->write->method = PHP_CURL_STDOUT; + } else if (what->mode[0] != 'r' || what->mode[1] == '+') { + zval_ptr_dtor(&ch->handlers->write->stream); + ch->handlers->write->fp = fp; + ch->handlers->write->method = PHP_CURL_FILE; + ZVAL_COPY(&ch->handlers->write->stream, zvalue); + } else { #if PHP_VERSION_ID >= 80000 - zend_value_error("%s(): The provided file handle must be writable", get_active_function_name()); + zend_value_error("%s(): The provided file handle must be writable", get_active_function_name()); #else - php_error_docref(NULL, E_WARNING, "the provided file handle is not writable"); + php_error_docref(NULL, E_WARNING, "the provided file handle is not writable"); #endif - return FAILURE; - } - break; - case CURLOPT_WRITEHEADER: - if (!what) { - if (!Z_ISUNDEF(ch->handlers->write_header->stream)) { - zval_ptr_dtor(&ch->handlers->write_header->stream); - ZVAL_UNDEF(&ch->handlers->write_header->stream); - } - ch->handlers->write_header->fp = NULL; - ch->handlers->write_header->method = PHP_CURL_IGNORE; - } else if (what->mode[0] != 'r' || what->mode[1] == '+') { - zval_ptr_dtor(&ch->handlers->write_header->stream); - ch->handlers->write_header->fp = fp; - ch->handlers->write_header->method = PHP_CURL_FILE; - ZVAL_COPY(&ch->handlers->write_header->stream, zvalue); - } else { + return FAILURE; + } + break; + case CURLOPT_WRITEHEADER: + if (!what) { + if (!Z_ISUNDEF(ch->handlers->write_header->stream)) { + zval_ptr_dtor(&ch->handlers->write_header->stream); + ZVAL_UNDEF(&ch->handlers->write_header->stream); + } + ch->handlers->write_header->fp = NULL; + ch->handlers->write_header->method = PHP_CURL_IGNORE; + } else if (what->mode[0] != 'r' || what->mode[1] == '+') { + zval_ptr_dtor(&ch->handlers->write_header->stream); + ch->handlers->write_header->fp = fp; + ch->handlers->write_header->method = PHP_CURL_FILE; + ZVAL_COPY(&ch->handlers->write_header->stream, zvalue); + } else { #if PHP_VERSION_ID >= 80000 - zend_value_error("%s(): The provided file handle must be writable", get_active_function_name()); + zend_value_error("%s(): The provided file handle must be writable", get_active_function_name()); #else - php_error_docref(NULL, E_WARNING, "the provided file handle is not writable"); + php_error_docref(NULL, E_WARNING, "the provided file handle is not writable"); #endif - return FAILURE; - } - break; - case CURLOPT_INFILE: - if (!what) { - if (!Z_ISUNDEF(ch->handlers->read->stream)) { - zval_ptr_dtor(&ch->handlers->read->stream); - ZVAL_UNDEF(&ch->handlers->read->stream); - } - ch->handlers->read->fp = NULL; - ch->handlers->read->res = NULL; - } else { - zval_ptr_dtor(&ch->handlers->read->stream); - ch->handlers->read->fp = fp; - ch->handlers->read->res = Z_RES_P(zvalue); - ZVAL_COPY(&ch->handlers->read->stream, zvalue); - } - break; - case CURLOPT_STDERR: - if (!what) { - if (!Z_ISUNDEF(ch->handlers->std_err)) { - zval_ptr_dtor(&ch->handlers->std_err); - ZVAL_UNDEF(&ch->handlers->std_err); - } - } else if (what->mode[0] != 'r' || what->mode[1] == '+') { - zval_ptr_dtor(&ch->handlers->std_err); - ZVAL_COPY(&ch->handlers->std_err, zvalue); - } else { + return FAILURE; + } + break; + case CURLOPT_INFILE: + if (!what) { + if (!Z_ISUNDEF(ch->handlers->read->stream)) { + zval_ptr_dtor(&ch->handlers->read->stream); + ZVAL_UNDEF(&ch->handlers->read->stream); + } + ch->handlers->read->fp = NULL; + ch->handlers->read->res = NULL; + } else { + zval_ptr_dtor(&ch->handlers->read->stream); + ch->handlers->read->fp = fp; + ch->handlers->read->res = Z_RES_P(zvalue); + ZVAL_COPY(&ch->handlers->read->stream, zvalue); + } + break; + case CURLOPT_STDERR: + if (!what) { + if (!Z_ISUNDEF(ch->handlers->std_err)) { + zval_ptr_dtor(&ch->handlers->std_err); + ZVAL_UNDEF(&ch->handlers->std_err); + } + } else if (what->mode[0] != 'r' || what->mode[1] == '+') { + zval_ptr_dtor(&ch->handlers->std_err); + ZVAL_COPY(&ch->handlers->std_err, zvalue); + } else { #if PHP_VERSION_ID >= 80000 - zend_value_error("%s(): The provided file handle must be writable", get_active_function_name()); + zend_value_error("%s(): The provided file handle must be writable", get_active_function_name()); #else - php_error_docref(NULL, E_WARNING, "the provided file handle is not writable"); + php_error_docref(NULL, E_WARNING, "the provided file handle is not writable"); #endif - return FAILURE; - } - /* break omitted intentionally */ - default: - error = curl_easy_setopt(ch->cp, (CURLoption) option, fp); - break; + return FAILURE; } + /* break omitted intentionally */ + default: + error = curl_easy_setopt(ch->cp, (CURLoption) option, fp); break; } + break; + } - /* Curl linked list options */ - case CURLOPT_HTTP200ALIASES: - case CURLOPT_HTTPHEADER: - case CURLOPT_POSTQUOTE: - case CURLOPT_PREQUOTE: - case CURLOPT_QUOTE: - case CURLOPT_TELNETOPTIONS: + /* Curl linked list options */ + case CURLOPT_HTTP200ALIASES: + case CURLOPT_HTTPHEADER: + case CURLOPT_POSTQUOTE: + case CURLOPT_PREQUOTE: + case CURLOPT_QUOTE: + case CURLOPT_TELNETOPTIONS: #if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */ - case CURLOPT_MAIL_RCPT: + case CURLOPT_MAIL_RCPT: #endif #if LIBCURL_VERSION_NUM >= 0x071503 /* Available since 7.21.3 */ - case CURLOPT_RESOLVE: + case CURLOPT_RESOLVE: #endif #if LIBCURL_VERSION_NUM >= 0x072500 /* Available since 7.37.0 */ - case CURLOPT_PROXYHEADER: + case CURLOPT_PROXYHEADER: #endif #if LIBCURL_VERSION_NUM >= 0x073100 /* Available since 7.49.0 */ - case CURLOPT_CONNECT_TO: -#endif - { - zval *current; - HashTable *ph = NULL; - zend_string *val; - struct curl_slist *slist = NULL; - - ph = HASH_OF(zvalue); - if (!ph) { - const char *name = NULL; - switch (option) { - case CURLOPT_HTTPHEADER: - name = "CURLOPT_HTTPHEADER"; - break; - case CURLOPT_QUOTE: - name = "CURLOPT_QUOTE"; - break; - case CURLOPT_HTTP200ALIASES: - name = "CURLOPT_HTTP200ALIASES"; - break; - case CURLOPT_POSTQUOTE: - name = "CURLOPT_POSTQUOTE"; - break; - case CURLOPT_PREQUOTE: - name = "CURLOPT_PREQUOTE"; - break; - case CURLOPT_TELNETOPTIONS: - name = "CURLOPT_TELNETOPTIONS"; - break; + case CURLOPT_CONNECT_TO: +#endif + { + zval *current; + HashTable *ph = NULL; + zend_string *val; + struct curl_slist *slist = NULL; + + ph = HASH_OF(zvalue); + if (!ph) { + const char *name = NULL; + switch (option) { + case CURLOPT_HTTPHEADER: + name = "CURLOPT_HTTPHEADER"; + break; + case CURLOPT_QUOTE: + name = "CURLOPT_QUOTE"; + break; + case CURLOPT_HTTP200ALIASES: + name = "CURLOPT_HTTP200ALIASES"; + break; + case CURLOPT_POSTQUOTE: + name = "CURLOPT_POSTQUOTE"; + break; + case CURLOPT_PREQUOTE: + name = "CURLOPT_PREQUOTE"; + break; + case CURLOPT_TELNETOPTIONS: + name = "CURLOPT_TELNETOPTIONS"; + break; #if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */ - case CURLOPT_MAIL_RCPT: - name = "CURLOPT_MAIL_RCPT"; - break; + case CURLOPT_MAIL_RCPT: + name = "CURLOPT_MAIL_RCPT"; + break; #endif #if LIBCURL_VERSION_NUM >= 0x071503 /* Available since 7.21.3 */ - case CURLOPT_RESOLVE: - name = "CURLOPT_RESOLVE"; - break; + case CURLOPT_RESOLVE: + name = "CURLOPT_RESOLVE"; + break; #endif #if LIBCURL_VERSION_NUM >= 0x072500 /* Available since 7.37.0 */ - case CURLOPT_PROXYHEADER: - name = "CURLOPT_PROXYHEADER"; - break; + case CURLOPT_PROXYHEADER: + name = "CURLOPT_PROXYHEADER"; + break; #endif #if LIBCURL_VERSION_NUM >= 0x073100 /* Available since 7.49.0 */ - case CURLOPT_CONNECT_TO: - name = "CURLOPT_CONNECT_TO"; - break; + case CURLOPT_CONNECT_TO: + name = "CURLOPT_CONNECT_TO"; + break; #endif - } + } #if PHP_VERSION_ID >= 80000 - zend_type_error("%s(): The %s option must have an array value", get_active_function_name(), name); + zend_type_error("%s(): The %s option must have an array value", get_active_function_name(), name); #else - php_error_docref(NULL, E_WARNING, "You must pass either an object or an array with the %s argument", name); + php_error_docref(NULL, E_WARNING, "You must pass either an object or an array with the %s argument", name); #endif - return FAILURE; - } + return FAILURE; + } - ZEND_HASH_FOREACH_VAL(ph, current) { - ZVAL_DEREF(current); - val = zval_get_string(current); - slist = curl_slist_append(slist, ZSTR_VAL(val)); - zend_string_release(val); - if (!slist) { - php_error_docref(NULL, E_WARNING, "Could not build curl_slist"); - return 1; - } - } ZEND_HASH_FOREACH_END(); + ZEND_HASH_FOREACH_VAL(ph, current) { + ZVAL_DEREF(current); + val = zval_get_string(current); + slist = curl_slist_append(slist, ZSTR_VAL(val)); + zend_string_release(val); + if (!slist) { + php_error_docref(NULL, E_WARNING, "Could not build curl_slist"); + return 1; + } + } + ZEND_HASH_FOREACH_END(); - if (slist) { - if ((*ch->clone) == 1) { - zend_hash_index_update_ptr(ch->to_free->slist, option, slist); - } else { - zend_hash_next_index_insert_ptr(ch->to_free->slist, slist); - } + if (slist) { + if ((*ch->clone) == 1) { + zend_hash_index_update_ptr(ch->to_free->slist, option, slist); + } else { + zend_hash_next_index_insert_ptr(ch->to_free->slist, slist); } + } - error = curl_easy_setopt(ch->cp, (CURLoption) option, slist); + error = curl_easy_setopt(ch->cp, (CURLoption) option, slist); - break; - } + break; + } - case CURLOPT_BINARYTRANSFER: - /* Do nothing, just backward compatibility */ - break; + case CURLOPT_BINARYTRANSFER: + /* Do nothing, just backward compatibility */ + break; - case CURLOPT_FOLLOWLOCATION: - lval = zend_is_true(zvalue); + case CURLOPT_FOLLOWLOCATION: + lval = zend_is_true(zvalue); #if LIBCURL_VERSION_NUM < 0x071304 - if (lval && PG(open_basedir) && *PG(open_basedir)) { - php_error_docref(NULL, E_WARNING, "CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set"); - return FAILURE; - } + if (lval && PG(open_basedir) && *PG(open_basedir)) { + php_error_docref(NULL, E_WARNING, "CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set"); + return FAILURE; + } #endif - error = curl_easy_setopt(ch->cp, (CURLoption) option, lval); - break; + error = curl_easy_setopt(ch->cp, (CURLoption) option, lval); + break; - case CURLOPT_HEADERFUNCTION: - if (!Z_ISUNDEF(ch->handlers->write_header->func_name)) { - zval_ptr_dtor(&ch->handlers->write_header->func_name); - ch->handlers->write_header->fci_cache = empty_fcall_info_cache; - } - ZVAL_COPY(&ch->handlers->write_header->func_name, zvalue); - ch->handlers->write_header->method = PHP_CURL_USER; - break; + case CURLOPT_HEADERFUNCTION: + if (!Z_ISUNDEF(ch->handlers->write_header->func_name)) { + zval_ptr_dtor(&ch->handlers->write_header->func_name); + ch->handlers->write_header->fci_cache = empty_fcall_info_cache; + } + ZVAL_COPY(&ch->handlers->write_header->func_name, zvalue); + ch->handlers->write_header->method = PHP_CURL_USER; + break; - case CURLOPT_POSTFIELDS: + case CURLOPT_POSTFIELDS: #if PHP_VERSION_ID >= 80000 - if (Z_TYPE_P(zvalue) == IS_ARRAY) { + if (Z_TYPE_P(zvalue) == IS_ARRAY) { #else - if (Z_TYPE_P(zvalue) == IS_ARRAY || Z_TYPE_P(zvalue) == IS_OBJECT) { + if (Z_TYPE_P(zvalue) == IS_ARRAY || Z_TYPE_P(zvalue) == IS_OBJECT) { #endif - return build_mime_structure_from_hash(ch, zvalue); - } else { + return build_mime_structure_from_hash(ch, zvalue); + } else { #if LIBCURL_VERSION_NUM >= 0x071101 - zend_string *str = zval_get_string(zvalue); - /* with curl 7.17.0 and later, we can use COPYPOSTFIELDS, but we have to provide size before */ - error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, ZSTR_LEN(str)); - error = curl_easy_setopt(ch->cp, CURLOPT_COPYPOSTFIELDS, ZSTR_VAL(str)); - zend_string_release(str); + zend_string *str = zval_get_string(zvalue); + /* with curl 7.17.0 and later, we can use COPYPOSTFIELDS, but we have to provide size before */ + error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, ZSTR_LEN(str)); + error = curl_easy_setopt(ch->cp, CURLOPT_COPYPOSTFIELDS, ZSTR_VAL(str)); + zend_string_release(str); #else - char *post = NULL; - zend_string *str = zval_get_string(zvalue); + char *post = NULL; + zend_string *str = zval_get_string(zvalue); - post = estrndup(ZSTR_VAL(str), ZSTR_LEN(str)); - zend_llist_add_element(&ch->to_free->str, &post); + post = estrndup(ZSTR_VAL(str), ZSTR_LEN(str)); + zend_llist_add_element(&ch->to_free->str, &post); - curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDS, post); - error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, ZSTR_LEN(str)); - zend_string_release(str); + curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDS, post); + error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, ZSTR_LEN(str)); + zend_string_release(str); #endif - } - break; + } + break; - case CURLOPT_PROGRESSFUNCTION: - curl_easy_setopt(ch->cp, CURLOPT_PROGRESSFUNCTION, fn_progress); - curl_easy_setopt(ch->cp, CURLOPT_PROGRESSDATA, ch); - if (ch->handlers->progress == NULL) { - ch->handlers->progress = (php_curl_progress *)ecalloc(1, sizeof(php_curl_progress)); - } else if (!Z_ISUNDEF(ch->handlers->progress->func_name)) { - zval_ptr_dtor(&ch->handlers->progress->func_name); - ch->handlers->progress->fci_cache = empty_fcall_info_cache; - } - ZVAL_COPY(&ch->handlers->progress->func_name, zvalue); - ch->handlers->progress->method = PHP_CURL_USER; - break; + case CURLOPT_PROGRESSFUNCTION: + curl_easy_setopt(ch->cp, CURLOPT_PROGRESSFUNCTION, fn_progress); + curl_easy_setopt(ch->cp, CURLOPT_PROGRESSDATA, ch); + if (ch->handlers->progress == NULL) { + ch->handlers->progress = (php_curl_progress *) ecalloc(1, sizeof(php_curl_progress)); + } else if (!Z_ISUNDEF(ch->handlers->progress->func_name)) { + zval_ptr_dtor(&ch->handlers->progress->func_name); + ch->handlers->progress->fci_cache = empty_fcall_info_cache; + } + ZVAL_COPY(&ch->handlers->progress->func_name, zvalue); + ch->handlers->progress->method = PHP_CURL_USER; + break; - case CURLOPT_READFUNCTION: - if (!Z_ISUNDEF(ch->handlers->read->func_name)) { - zval_ptr_dtor(&ch->handlers->read->func_name); - ch->handlers->read->fci_cache = empty_fcall_info_cache; - } - ZVAL_COPY(&ch->handlers->read->func_name, zvalue); - ch->handlers->read->method = PHP_CURL_USER; - break; + case CURLOPT_READFUNCTION: + if (!Z_ISUNDEF(ch->handlers->read->func_name)) { + zval_ptr_dtor(&ch->handlers->read->func_name); + ch->handlers->read->fci_cache = empty_fcall_info_cache; + } + ZVAL_COPY(&ch->handlers->read->func_name, zvalue); + ch->handlers->read->method = PHP_CURL_USER; + break; - case CURLOPT_RETURNTRANSFER: - if (zend_is_true(zvalue)) { - ch->handlers->write->method = PHP_CURL_RETURN; - } else { - ch->handlers->write->method = PHP_CURL_STDOUT; - } - break; + case CURLOPT_RETURNTRANSFER: + if (zend_is_true(zvalue)) { + ch->handlers->write->method = PHP_CURL_RETURN; + } else { + ch->handlers->write->method = PHP_CURL_STDOUT; + } + break; - case CURLOPT_WRITEFUNCTION: - if (!Z_ISUNDEF(ch->handlers->write->func_name)) { - zval_ptr_dtor(&ch->handlers->write->func_name); - ch->handlers->write->fci_cache = empty_fcall_info_cache; - } - ZVAL_COPY(&ch->handlers->write->func_name, zvalue); - ch->handlers->write->method = PHP_CURL_USER; - break; + case CURLOPT_WRITEFUNCTION: + if (!Z_ISUNDEF(ch->handlers->write->func_name)) { + zval_ptr_dtor(&ch->handlers->write->func_name); + ch->handlers->write->fci_cache = empty_fcall_info_cache; + } + ZVAL_COPY(&ch->handlers->write->func_name, zvalue); + ch->handlers->write->method = PHP_CURL_USER; + break; - /* Curl off_t options */ - case CURLOPT_MAX_RECV_SPEED_LARGE: - case CURLOPT_MAX_SEND_SPEED_LARGE: + /* Curl off_t options */ + case CURLOPT_MAX_RECV_SPEED_LARGE: + case CURLOPT_MAX_SEND_SPEED_LARGE: #if LIBCURL_VERSION_NUM >= 0x073b00 /* Available since 7.59.0 */ - case CURLOPT_TIMEVALUE_LARGE: + case CURLOPT_TIMEVALUE_LARGE: #endif - lval = zval_get_long(zvalue); - error = curl_easy_setopt(ch->cp, (CURLoption) option, (curl_off_t)lval); - break; + lval = zval_get_long(zvalue); + error = curl_easy_setopt(ch->cp, (CURLoption) option, (curl_off_t) lval); + break; #if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */ - case CURLOPT_POSTREDIR: - lval = zval_get_long(zvalue); - error = curl_easy_setopt(ch->cp, CURLOPT_POSTREDIR, lval & CURL_REDIR_POST_ALL); - break; + case CURLOPT_POSTREDIR: + lval = zval_get_long(zvalue); + error = curl_easy_setopt(ch->cp, CURLOPT_POSTREDIR, lval & CURL_REDIR_POST_ALL); + break; #endif - /* the following options deal with files, therefore the open_basedir check - * is required. - */ - case CURLOPT_COOKIEFILE: - case CURLOPT_COOKIEJAR: - case CURLOPT_RANDOM_FILE: - case CURLOPT_SSLCERT: - case CURLOPT_NETRC_FILE: + /* the following options deal with files, therefore the open_basedir check + * is required. + */ + case CURLOPT_COOKIEFILE: + case CURLOPT_COOKIEJAR: + case CURLOPT_RANDOM_FILE: + case CURLOPT_SSLCERT: + case CURLOPT_NETRC_FILE: #if LIBCURL_VERSION_NUM >= 0x071001 /* Available since 7.16.1 */ - case CURLOPT_SSH_PRIVATE_KEYFILE: - case CURLOPT_SSH_PUBLIC_KEYFILE: + case CURLOPT_SSH_PRIVATE_KEYFILE: + case CURLOPT_SSH_PUBLIC_KEYFILE: #endif #if LIBCURL_VERSION_NUM >= 0x071300 /* Available since 7.19.0 */ - case CURLOPT_CRLFILE: - case CURLOPT_ISSUERCERT: + case CURLOPT_CRLFILE: + case CURLOPT_ISSUERCERT: #endif #if LIBCURL_VERSION_NUM >= 0x071306 /* Available since 7.19.6 */ - case CURLOPT_SSH_KNOWNHOSTS: + case CURLOPT_SSH_KNOWNHOSTS: #endif - { - zend_string *str = zval_get_string(zvalue); - int ret; + { + zend_string *str = zval_get_string(zvalue); + int ret; - if (ZSTR_LEN(str) && php_check_open_basedir(ZSTR_VAL(str))) { - zend_string_release(str); - return FAILURE; - } - - ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 0); + if (ZSTR_LEN(str) && php_check_open_basedir(ZSTR_VAL(str))) { zend_string_release(str); - return ret; + return FAILURE; } - case CURLINFO_HEADER_OUT: - if (zend_is_true(zvalue)) { - curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, curl_debug); - curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, (void *)ch); - curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 1); - } else { - curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, NULL); - curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, NULL); - curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0); - } - break; + ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 0); + zend_string_release(str); + return ret; + } - case CURLOPT_SHARE: - { - php_error_docref(NULL, E_WARNING, "CURLOPT_SHARE option is not supported"); - } - break; + case CURLINFO_HEADER_OUT: + if (zend_is_true(zvalue)) { + curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, curl_debug); + curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, (void *) ch); + curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 1); + } else { + curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, NULL); + curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, NULL); + curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0); + } + break; + + case CURLOPT_SHARE: { + php_error_docref(NULL, E_WARNING, "CURLOPT_SHARE option is not supported"); + } break; #if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */ - case CURLOPT_FNMATCH_FUNCTION: - curl_easy_setopt(ch->cp, CURLOPT_FNMATCH_FUNCTION, fn_fnmatch); - curl_easy_setopt(ch->cp, CURLOPT_FNMATCH_DATA, ch); - if (ch->handlers->fnmatch == NULL) { - ch->handlers->fnmatch = (php_curl_fnmatch*)ecalloc(1, sizeof(php_curl_fnmatch)); - } else if (!Z_ISUNDEF(ch->handlers->fnmatch->func_name)) { - zval_ptr_dtor(&ch->handlers->fnmatch->func_name); - ch->handlers->fnmatch->fci_cache = empty_fcall_info_cache; - } - ZVAL_COPY(&ch->handlers->fnmatch->func_name, zvalue); - ch->handlers->fnmatch->method = PHP_CURL_USER; - break; + case CURLOPT_FNMATCH_FUNCTION: + curl_easy_setopt(ch->cp, CURLOPT_FNMATCH_FUNCTION, fn_fnmatch); + curl_easy_setopt(ch->cp, CURLOPT_FNMATCH_DATA, ch); + if (ch->handlers->fnmatch == NULL) { + ch->handlers->fnmatch = (php_curl_fnmatch *) ecalloc(1, sizeof(php_curl_fnmatch)); + } else if (!Z_ISUNDEF(ch->handlers->fnmatch->func_name)) { + zval_ptr_dtor(&ch->handlers->fnmatch->func_name); + ch->handlers->fnmatch->fci_cache = empty_fcall_info_cache; + } + ZVAL_COPY(&ch->handlers->fnmatch->func_name, zvalue); + ch->handlers->fnmatch->method = PHP_CURL_USER; + break; #endif #if PHP_VERSION_ID >= 80000 - default: - if (is_array_config) { - zend_argument_value_error(2, "must contain only valid cURL options"); - } else { - zend_argument_value_error(2, "is not a valid cURL option"); - } - error = CURLE_UNKNOWN_OPTION; - break; + default: + if (is_array_config) { + zend_argument_value_error(2, "must contain only valid cURL options"); + } else { + zend_argument_value_error(2, "is not a valid cURL option"); + } + error = CURLE_UNKNOWN_OPTION; + break; #endif } @@ -2259,20 +2256,19 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{ /* {{{ proto bool curl_setopt(resource ch, int option, mixed value) Set an option for a cURL transfer */ -PHP_FUNCTION(swoole_native_curl_setopt) -{ - zval *zid, *zvalue; - zend_long options; - php_curl *ch; +PHP_FUNCTION(swoole_native_curl_setopt) { + zval *zid, *zvalue; + zend_long options; + php_curl *ch; ZEND_PARSE_PARAMETERS_START(3, 3) #if PHP_VERSION_ID >= 80000 - Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) + Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) #else - Z_PARAM_RESOURCE(zid) + Z_PARAM_RESOURCE(zid) #endif - Z_PARAM_LONG(options) - Z_PARAM_ZVAL(zvalue) + Z_PARAM_LONG(options) + Z_PARAM_ZVAL(zvalue) ZEND_PARSE_PARAMETERS_END(); if ((ch = _php_curl_get_handle(zid)) == NULL) { @@ -2293,20 +2289,19 @@ PHP_FUNCTION(swoole_native_curl_setopt) /* {{{ proto bool curl_setopt_array(resource ch, array options) Set an array of option for a cURL transfer */ -PHP_FUNCTION(swoole_native_curl_setopt_array) -{ - zval *zid, *arr, *entry; - php_curl *ch; - zend_ulong option; - zend_string *string_key; +PHP_FUNCTION(swoole_native_curl_setopt_array) { + zval *zid, *arr, *entry; + php_curl *ch; + zend_ulong option; + zend_string *string_key; ZEND_PARSE_PARAMETERS_START(2, 2) #if PHP_VERSION_ID >= 80000 - Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) + Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) #else - Z_PARAM_RESOURCE(zid) + Z_PARAM_RESOURCE(zid) #endif - Z_PARAM_ARRAY(arr) + Z_PARAM_ARRAY(arr) ZEND_PARSE_PARAMETERS_END(); if ((ch = _php_curl_get_handle(zid)) == NULL) { @@ -2315,19 +2310,19 @@ PHP_FUNCTION(swoole_native_curl_setopt_array) ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(arr), option, string_key, entry) { if (string_key) { - php_error_docref(NULL, E_WARNING, - "Array keys must be CURLOPT constants or equivalent integer values"); + php_error_docref(NULL, E_WARNING, "Array keys must be CURLOPT constants or equivalent integer values"); RETURN_FALSE; } ZVAL_DEREF(entry); #if PHP_VERSION_ID >= 80000 - if (_php_curl_setopt(ch, (zend_long) option, entry, 1) == FAILURE) { + if (_php_curl_setopt(ch, (zend_long) option, entry, 1) == FAILURE) { #else if (_php_curl_setopt(ch, (zend_long) option, entry) == FAILURE) { #endif RETURN_FALSE; } - } ZEND_HASH_FOREACH_END(); + } + ZEND_HASH_FOREACH_END(); RETURN_TRUE; } @@ -2335,8 +2330,7 @@ PHP_FUNCTION(swoole_native_curl_setopt_array) /* {{{ _php_curl_cleanup_handle(ch) Cleanup an execution phase */ -void _php_curl_cleanup_handle(php_curl *ch) -{ +void _php_curl_cleanup_handle(php_curl *ch) { smart_str_free(&ch->handlers->write->buf); if (ch->header.str) { zend_string_release(ch->header.str); @@ -2350,17 +2344,16 @@ void _php_curl_cleanup_handle(php_curl *ch) /* {{{ proto bool curl_exec(resource ch) Perform a cURL session */ -PHP_FUNCTION(swoole_native_curl_exec) -{ - CURLcode error; - zval *zid; - php_curl *ch; +PHP_FUNCTION(swoole_native_curl_exec) { + CURLcode error; + zval *zid; + php_curl *ch; ZEND_PARSE_PARAMETERS_START(1, 1) #if PHP_VERSION_ID >= 80000 - Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) + Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) #else - Z_PARAM_RESOURCE(zid) + Z_PARAM_RESOURCE(zid) #endif ZEND_PARSE_PARAMETERS_END(); @@ -2381,8 +2374,9 @@ PHP_FUNCTION(swoole_native_curl_exec) } if (!Z_ISUNDEF(ch->handlers->std_err)) { - php_stream *stream; - stream = (php_stream*)zend_fetch_resource2_ex(&ch->handlers->std_err, NULL, php_file_le_stream(), php_file_le_pstream()); + php_stream *stream; + stream = (php_stream *) zend_fetch_resource2_ex( + &ch->handlers->std_err, NULL, php_file_le_stream(), php_file_le_pstream()); if (stream) { php_stream_flush(stream); } @@ -2411,28 +2405,27 @@ PHP_FUNCTION(swoole_native_curl_exec) /* {{{ proto mixed curl_getinfo(resource ch [, int option]) Get information regarding a specific transfer */ -PHP_FUNCTION(swoole_native_curl_getinfo) -{ - zval *zid; - php_curl *ch; +PHP_FUNCTION(swoole_native_curl_getinfo) { + zval *zid; + php_curl *ch; #if PHP_VERSION_ID >= 80000 - zend_long option; - zend_bool option_is_null = 1; + zend_long option; + zend_bool option_is_null = 1; #else - zend_long option = 0; + zend_long option = 0; #endif ZEND_PARSE_PARAMETERS_START(1, 2) #if PHP_VERSION_ID >= 80000 - Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) + Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) #else - Z_PARAM_RESOURCE(zid) + Z_PARAM_RESOURCE(zid) #endif - Z_PARAM_OPTIONAL + Z_PARAM_OPTIONAL #if PHP_VERSION_ID >= 80000 - Z_PARAM_LONG_OR_NULL(option, option_is_null) + Z_PARAM_LONG_OR_NULL(option, option_is_null) #else - Z_PARAM_LONG(option) + Z_PARAM_LONG(option) #endif ZEND_PARSE_PARAMETERS_END(); @@ -2600,112 +2593,106 @@ PHP_FUNCTION(swoole_native_curl_getinfo) } } else { switch (option) { - case CURLINFO_HEADER_OUT: - if (ch->header.str) { - RETURN_STR_COPY(ch->header.str); + case CURLINFO_HEADER_OUT: + if (ch->header.str) { + RETURN_STR_COPY(ch->header.str); + } else { + RETURN_FALSE; + } + break; +#if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */ + case CURLINFO_CERTINFO: { + struct curl_certinfo *ci = NULL; + + array_init(return_value); + + if (curl_easy_getinfo(ch->cp, CURLINFO_CERTINFO, &ci) == CURLE_OK) { + create_certinfo(ci, return_value); + } else { + RETURN_FALSE; + } + break; + } +#endif + default: { + int type = CURLINFO_TYPEMASK & option; + switch (type) { + case CURLINFO_STRING: { + char *s_code = NULL; + + if (curl_easy_getinfo(ch->cp, (CURLINFO) option, &s_code) == CURLE_OK && s_code) { + RETURN_STRING(s_code); } else { RETURN_FALSE; } break; -#if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */ - case CURLINFO_CERTINFO: { - struct curl_certinfo *ci = NULL; + } + case CURLINFO_LONG: { + zend_long code = 0; - array_init(return_value); + if (curl_easy_getinfo(ch->cp, (CURLINFO) option, &code) == CURLE_OK) { + RETURN_LONG(code); + } else { + RETURN_FALSE; + } + break; + } + case CURLINFO_DOUBLE: { + double code = 0.0; - if (curl_easy_getinfo(ch->cp, CURLINFO_CERTINFO, &ci) == CURLE_OK) { - create_certinfo(ci, return_value); + if (curl_easy_getinfo(ch->cp, (CURLINFO) option, &code) == CURLE_OK) { + RETURN_DOUBLE(code); } else { RETURN_FALSE; } break; } -#endif - default: { - int type = CURLINFO_TYPEMASK & option; - switch (type) { - case CURLINFO_STRING: - { - char *s_code = NULL; - - if (curl_easy_getinfo(ch->cp, (CURLINFO) option, &s_code) == CURLE_OK && s_code) { - RETURN_STRING(s_code); - } else { - RETURN_FALSE; - } - break; - } - case CURLINFO_LONG: - { - zend_long code = 0; - - if (curl_easy_getinfo(ch->cp, (CURLINFO) option, &code) == CURLE_OK) { - RETURN_LONG(code); - } else { - RETURN_FALSE; - } - break; - } - case CURLINFO_DOUBLE: - { - double code = 0.0; - - if (curl_easy_getinfo(ch->cp, (CURLINFO) option, &code) == CURLE_OK) { - RETURN_DOUBLE(code); - } else { - RETURN_FALSE; - } - break; - } - case CURLINFO_SLIST: - { - struct curl_slist *slist; - if (curl_easy_getinfo(ch->cp, (CURLINFO) option, &slist) == CURLE_OK) { - struct curl_slist *current = slist; - array_init(return_value); - while (current) { - add_next_index_string(return_value, current->data); - current = current->next; - } - curl_slist_free_all(slist); - } else { - RETURN_FALSE; - } - break; + case CURLINFO_SLIST: { + struct curl_slist *slist; + if (curl_easy_getinfo(ch->cp, (CURLINFO) option, &slist) == CURLE_OK) { + struct curl_slist *current = slist; + array_init(return_value); + while (current) { + add_next_index_string(return_value, current->data); + current = current->next; } + curl_slist_free_all(slist); + } else { + RETURN_FALSE; + } + break; + } #if LIBCURL_VERSION_NUM >= 0x073700 /* Available since 7.55.0 */ - case CURLINFO_OFF_T: - { - curl_off_t c_off; - if (curl_easy_getinfo(ch->cp, (CURLINFO) option, &c_off) == CURLE_OK) { - RETURN_LONG((long) c_off); - } else { - RETURN_FALSE; - } - break; - } -#endif - default: - RETURN_FALSE; + case CURLINFO_OFF_T: { + curl_off_t c_off; + if (curl_easy_getinfo(ch->cp, (CURLINFO) option, &c_off) == CURLE_OK) { + RETURN_LONG((long) c_off); + } else { + RETURN_FALSE; } + break; + } +#endif + default: + RETURN_FALSE; } } + } } } /* }}} */ /* {{{ proto string curl_error(resource ch) Return a string contain the last error for the current session */ -PHP_FUNCTION(swoole_native_curl_error) -{ - zval *zid; - php_curl *ch; +PHP_FUNCTION(swoole_native_curl_error) { + zval *zid; + php_curl *ch; ZEND_PARSE_PARAMETERS_START(1, 1) #if PHP_VERSION_ID >= 80000 - Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) + Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) #else - Z_PARAM_RESOURCE(zid) + Z_PARAM_RESOURCE(zid) #endif ZEND_PARSE_PARAMETERS_END(); @@ -2724,16 +2711,15 @@ PHP_FUNCTION(swoole_native_curl_error) /* {{{ proto int curl_errno(resource ch) Return an integer containing the last error number */ -PHP_FUNCTION(swoole_native_curl_errno) -{ - zval *zid; - php_curl *ch; +PHP_FUNCTION(swoole_native_curl_errno) { + zval *zid; + php_curl *ch; - ZEND_PARSE_PARAMETERS_START(1,1) + ZEND_PARSE_PARAMETERS_START(1, 1) #if PHP_VERSION_ID >= 80000 - Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) + Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) #else - Z_PARAM_RESOURCE(zid) + Z_PARAM_RESOURCE(zid) #endif ZEND_PARSE_PARAMETERS_END(); @@ -2747,16 +2733,15 @@ PHP_FUNCTION(swoole_native_curl_errno) /* {{{ proto void curl_close(resource ch) Close a cURL session */ -PHP_FUNCTION(swoole_native_curl_close) -{ - zval *zid; - php_curl *ch; +PHP_FUNCTION(swoole_native_curl_close) { + zval *zid; + php_curl *ch; ZEND_PARSE_PARAMETERS_START(1, 1) #if PHP_VERSION_ID >= 80000 - Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) + Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) #else - Z_PARAM_RESOURCE(zid) + Z_PARAM_RESOURCE(zid) #endif ZEND_PARSE_PARAMETERS_END(); @@ -2776,84 +2761,83 @@ PHP_FUNCTION(swoole_native_curl_close) /* }}} */ #if PHP_VERSION_ID >= 80000 -static void curl_free_obj(zend_object *object) -{ - php_curl *ch = curl_from_obj(object); +static void curl_free_obj(zend_object *object) { + php_curl *ch = curl_from_obj(object); #if PHP_CURL_DEBUG - fprintf(stderr, "DTOR CALLED, ch = %x\n", ch); -#endif - - if (!ch->cp) { - /* Can happen if constructor throws. */ - zend_object_std_dtor(&ch->std); - return; - } - - _php_curl_verify_handlers(ch, 0); - - /* - * Libcurl is doing connection caching. When easy handle is cleaned up, - * if the handle was previously used by the curl_multi_api, the connection - * remains open un the curl multi handle is cleaned up. Some protocols are - * sending content like the FTP one, and libcurl try to use the - * WRITEFUNCTION or the HEADERFUNCTION. Since structures used in those - * callback are freed, we need to use an other callback to which avoid - * segfaults. - * - * Libcurl commit d021f2e8a00 fix this issue and should be part of 7.28.2 - */ - curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_nothing); - curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write_nothing); - - curl_easy_cleanup(ch->cp); - - /* cURL destructors should be invoked only by last curl handle */ - if (--(*ch->clone) == 0) { - zend_llist_clean(&ch->to_free->str); - zend_llist_clean(&ch->to_free->post); - zend_llist_clean(&ch->to_free->stream); - zend_hash_destroy(ch->to_free->slist); - efree(ch->to_free->slist); - efree(ch->to_free); - efree(ch->clone); - } - - smart_str_free(&ch->handlers->write->buf); - zval_ptr_dtor(&ch->handlers->write->func_name); - zval_ptr_dtor(&ch->handlers->read->func_name); - zval_ptr_dtor(&ch->handlers->write_header->func_name); - zval_ptr_dtor(&ch->handlers->std_err); - if (ch->header.str) { - zend_string_release_ex(ch->header.str, 0); - } - - zval_ptr_dtor(&ch->handlers->write_header->stream); - zval_ptr_dtor(&ch->handlers->write->stream); - zval_ptr_dtor(&ch->handlers->read->stream); - - efree(ch->handlers->write); - efree(ch->handlers->write_header); - efree(ch->handlers->read); - - if (ch->handlers->progress) { - zval_ptr_dtor(&ch->handlers->progress->func_name); - efree(ch->handlers->progress); - } - - if (ch->handlers->fnmatch) { - zval_ptr_dtor(&ch->handlers->fnmatch->func_name); - efree(ch->handlers->fnmatch); - } - - efree(ch->handlers); - zval_ptr_dtor(&ch->postfields); - - if (ch->share) { - OBJ_RELEASE(&ch->share->std); - } - - zend_object_std_dtor(&ch->std); + fprintf(stderr, "DTOR CALLED, ch = %x\n", ch); +#endif + + if (!ch->cp) { + /* Can happen if constructor throws. */ + zend_object_std_dtor(&ch->std); + return; + } + + _php_curl_verify_handlers(ch, 0); + + /* + * Libcurl is doing connection caching. When easy handle is cleaned up, + * if the handle was previously used by the curl_multi_api, the connection + * remains open un the curl multi handle is cleaned up. Some protocols are + * sending content like the FTP one, and libcurl try to use the + * WRITEFUNCTION or the HEADERFUNCTION. Since structures used in those + * callback are freed, we need to use an other callback to which avoid + * segfaults. + * + * Libcurl commit d021f2e8a00 fix this issue and should be part of 7.28.2 + */ + curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_nothing); + curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write_nothing); + + curl_easy_cleanup(ch->cp); + + /* cURL destructors should be invoked only by last curl handle */ + if (--(*ch->clone) == 0) { + zend_llist_clean(&ch->to_free->str); + zend_llist_clean(&ch->to_free->post); + zend_llist_clean(&ch->to_free->stream); + zend_hash_destroy(ch->to_free->slist); + efree(ch->to_free->slist); + efree(ch->to_free); + efree(ch->clone); + } + + smart_str_free(&ch->handlers->write->buf); + zval_ptr_dtor(&ch->handlers->write->func_name); + zval_ptr_dtor(&ch->handlers->read->func_name); + zval_ptr_dtor(&ch->handlers->write_header->func_name); + zval_ptr_dtor(&ch->handlers->std_err); + if (ch->header.str) { + zend_string_release_ex(ch->header.str, 0); + } + + zval_ptr_dtor(&ch->handlers->write_header->stream); + zval_ptr_dtor(&ch->handlers->write->stream); + zval_ptr_dtor(&ch->handlers->read->stream); + + efree(ch->handlers->write); + efree(ch->handlers->write_header); + efree(ch->handlers->read); + + if (ch->handlers->progress) { + zval_ptr_dtor(&ch->handlers->progress->func_name); + efree(ch->handlers->progress); + } + + if (ch->handlers->fnmatch) { + zval_ptr_dtor(&ch->handlers->fnmatch->func_name); + efree(ch->handlers->fnmatch); + } + + efree(ch->handlers); + zval_ptr_dtor(&ch->postfields); + + if (ch->share) { + OBJ_RELEASE(&ch->share->std); + } + + zend_object_std_dtor(&ch->std); } #endif @@ -2944,8 +2928,7 @@ void _php_curl_close(zend_resource *rsrc) { /* {{{ _php_curl_reset_handlers() Reset all handlers of a given php_curl */ -static void _php_curl_reset_handlers(php_curl *ch) -{ +static void _php_curl_reset_handlers(php_curl *ch) { if (!Z_ISUNDEF(ch->handlers->write->stream)) { zval_ptr_dtor(&ch->handlers->write->stream); ZVAL_UNDEF(&ch->handlers->write->stream); @@ -2966,7 +2949,7 @@ static void _php_curl_reset_handlers(php_curl *ch) } ch->handlers->read->fp = NULL; ch->handlers->read->res = NULL; - ch->handlers->read->method = PHP_CURL_DIRECT; + ch->handlers->read->method = PHP_CURL_DIRECT; if (!Z_ISUNDEF(ch->handlers->std_err)) { zval_ptr_dtor(&ch->handlers->std_err); @@ -2986,22 +2969,20 @@ static void _php_curl_reset_handlers(php_curl *ch) ch->handlers->fnmatch = NULL; } #endif - } /* }}} */ /* {{{ proto void curl_reset(resource ch) Reset all options of a libcurl session handle */ -PHP_FUNCTION(swoole_native_curl_reset) -{ - zval *zid; - php_curl *ch; +PHP_FUNCTION(swoole_native_curl_reset) { + zval *zid; + php_curl *ch; ZEND_PARSE_PARAMETERS_START(1, 1) #if PHP_VERSION_ID >= 80000 - Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) + Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) #else - Z_PARAM_RESOURCE(zid) + Z_PARAM_RESOURCE(zid) #endif ZEND_PARSE_PARAMETERS_END(); @@ -3022,20 +3003,19 @@ PHP_FUNCTION(swoole_native_curl_reset) /* {{{ proto void curl_escape(resource ch, string str) URL encodes the given string */ -PHP_FUNCTION(swoole_native_curl_escape) -{ +PHP_FUNCTION(swoole_native_curl_escape) { zend_string *str; - char *res; - zval *zid; - php_curl *ch; - - ZEND_PARSE_PARAMETERS_START(2,2) - #if PHP_VERSION_ID >= 80000 - Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) - #else - Z_PARAM_RESOURCE(zid) - #endif - Z_PARAM_STR(str) + char *res; + zval *zid; + php_curl *ch; + + ZEND_PARSE_PARAMETERS_START(2, 2) +#if PHP_VERSION_ID >= 80000 + Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) +#else + Z_PARAM_RESOURCE(zid) +#endif + Z_PARAM_STR(str) ZEND_PARSE_PARAMETERS_END(); if ((ch = _php_curl_get_handle(zid)) == NULL) { @@ -3057,27 +3037,26 @@ PHP_FUNCTION(swoole_native_curl_escape) /* {{{ proto void curl_unescape(resource ch, string str) URL decodes the given string */ -PHP_FUNCTION(swoole_native_curl_unescape) -{ - char *out = NULL; - int out_len; - zval *zid; +PHP_FUNCTION(swoole_native_curl_unescape) { + char *out = NULL; + int out_len; + zval *zid; zend_string *str; - php_curl *ch; - - ZEND_PARSE_PARAMETERS_START(2,2) - #if PHP_VERSION_ID >= 80000 - Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) - #else - Z_PARAM_RESOURCE(zid) - #endif - Z_PARAM_STR(str) + php_curl *ch; + + ZEND_PARSE_PARAMETERS_START(2, 2) +#if PHP_VERSION_ID >= 80000 + Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) +#else + Z_PARAM_RESOURCE(zid) +#endif + Z_PARAM_STR(str) ZEND_PARSE_PARAMETERS_END(); #if PHP_VERSION_ID >= 80000 ch = Z_CURL_P(zid); #else - if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { + if ((ch = (php_curl *) zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { RETURN_FALSE; } #endif @@ -3098,19 +3077,18 @@ PHP_FUNCTION(swoole_native_curl_unescape) #if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */ /* {{{ proto void curl_pause(resource ch, int bitmask) pause and unpause a connection */ -PHP_FUNCTION(swoole_native_curl_pause) -{ - zend_long bitmask; - zval *zid; - php_curl *ch; +PHP_FUNCTION(swoole_native_curl_pause) { + zend_long bitmask; + zval *zid; + php_curl *ch; - ZEND_PARSE_PARAMETERS_START(2,2) + ZEND_PARSE_PARAMETERS_START(2, 2) #if PHP_VERSION_ID >= 80000 - Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) + Z_PARAM_OBJECT_OF_CLASS(zid, swoole_coroutine_curl_handle_ce) #else - Z_PARAM_RESOURCE(zid) + Z_PARAM_RESOURCE(zid) #endif - Z_PARAM_LONG(bitmask) + Z_PARAM_LONG(bitmask) ZEND_PARSE_PARAMETERS_END(); if ((ch = _php_curl_get_handle(zid)) == NULL) { From 02c1ab23206db814823aa66835bae10a3724c7a2 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Mon, 15 Mar 2021 12:33:14 +0800 Subject: [PATCH 078/936] update error message, add defense code --- thirdparty/php/curl/curl_multi.h | 5 +++++ thirdparty/php/curl/interface.cc | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/thirdparty/php/curl/curl_multi.h b/thirdparty/php/curl/curl_multi.h index 4098a7f163b..4fd051655af 100644 --- a/thirdparty/php/curl/curl_multi.h +++ b/thirdparty/php/curl/curl_multi.h @@ -143,6 +143,11 @@ class cURLMulti { CURLMcode select(php_curlm *mh) { Coroutine::get_current_safe(); + if (selector) { + swFatalError(SW_ERROR_CO_HAS_BEEN_BOUND, "cURL is already waiting, cannot be operated"); + return CURLM_RECURSIVE_API_CALL; + } + zval _return_value; zval *return_value = &_return_value; diff --git a/thirdparty/php/curl/interface.cc b/thirdparty/php/curl/interface.cc index 963b4fcc3f2..3b6b29f6019 100644 --- a/thirdparty/php/curl/interface.cc +++ b/thirdparty/php/curl/interface.cc @@ -118,12 +118,12 @@ php_curl *_php_curl_get_handle(zval *zid, bool exclusive) { ch = Z_CURL_P(zid); #else if ((ch = (php_curl *) zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { - swFatalError(SW_ERROR_INVALID_PARAMS, "The cURL client is executing, this handle cannot be operated"); + swFatalError(SW_ERROR_INVALID_PARAMS, "cURL is executing, cannot be operated"); return nullptr; } #endif if (exclusive && ch->context) { - swFatalError(SW_ERROR_CO_HAS_BEEN_BOUND, "The cURL client is executing, this handle cannot be operated"); + swFatalError(SW_ERROR_CO_HAS_BEEN_BOUND, "cURL is executing, cannot be operated"); return nullptr; } return ch; From 2a76648898d00c7607ca361888e88b9e88b96f0f Mon Sep 17 00:00:00 2001 From: matyhtf Date: Mon, 15 Mar 2021 14:25:23 +0800 Subject: [PATCH 079/936] Update version --- CMakeLists.txt | 2 +- include/swoole_version.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e6076086e91..e386a500733 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ PROJECT(libswoole) ENABLE_LANGUAGE(ASM) -set(SWOOLE_VERSION 4.6.4) +set(SWOOLE_VERSION 4.6.5-dev) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g") diff --git a/include/swoole_version.h b/include/swoole_version.h index 9969b6808d6..2ad816f0166 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -20,10 +20,10 @@ #define SWOOLE_MAJOR_VERSION 4 #define SWOOLE_MINOR_VERSION 6 -#define SWOOLE_RELEASE_VERSION 4 -#define SWOOLE_EXTRA_VERSION "" -#define SWOOLE_VERSION "4.6.4" -#define SWOOLE_VERSION_ID 40604 +#define SWOOLE_RELEASE_VERSION 5 +#define SWOOLE_EXTRA_VERSION "dev" +#define SWOOLE_VERSION "4.6.5-dev" +#define SWOOLE_VERSION_ID 40605 #define SWOOLE_API_VERSION_ID 0x202012a #define SWOOLE_BUG_REPORT \ From cd7f51cb55aaa5ce33046c080679d9e664639627 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Mon, 15 Mar 2021 14:47:50 +0800 Subject: [PATCH 080/936] support curl_multi_info_read --- ext-src/swoole_runtime.cc | 4 ++++ tests/swoole_runtime/curl_native/multi.phpt | 8 ++++++++ thirdparty/php/curl/interface.cc | 2 +- thirdparty/php/curl/multi.cc | 7 ++++++- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/ext-src/swoole_runtime.cc b/ext-src/swoole_runtime.cc index 2fd2bc335af..15d27bab036 100644 --- a/ext-src/swoole_runtime.cc +++ b/ext-src/swoole_runtime.cc @@ -1409,6 +1409,7 @@ bool PHPCoroutine::enable_hook(uint32_t flags) { SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_exec); SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_select); SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_getcontent); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_info_read); SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_remove_handle); SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_close); } @@ -1431,6 +1432,9 @@ bool PHPCoroutine::enable_hook(uint32_t flags) { SW_UNHOOK_FUNC(curl_multi_init); SW_UNHOOK_FUNC(curl_multi_add_handle); SW_UNHOOK_FUNC(curl_multi_exec); + SW_UNHOOK_FUNC(curl_multi_select); + SW_UNHOOK_FUNC(curl_multi_getcontent); + SW_UNHOOK_FUNC(curl_multi_info_read); SW_UNHOOK_FUNC(curl_multi_remove_handle); SW_UNHOOK_FUNC(curl_multi_close); } diff --git a/tests/swoole_runtime/curl_native/multi.phpt b/tests/swoole_runtime/curl_native/multi.phpt index 84cd138808d..8568dc4bc9e 100644 --- a/tests/swoole_runtime/curl_native/multi.phpt +++ b/tests/swoole_runtime/curl_native/multi.phpt @@ -46,6 +46,14 @@ run(function () { } } + $info1 = curl_multi_info_read($mh); + $info2 = curl_multi_info_read($mh); + $info3 = curl_multi_info_read($mh); + + Assert::eq($info1['msg'], CURLMSG_DONE); + Assert::eq($info2['msg'], CURLMSG_DONE); + Assert::eq($info3, false); + Assert::contains(curl_multi_getcontent($ch1), 'baidu.com'); Assert::contains(curl_multi_getcontent($ch2), '中央人民政府门户网站'); diff --git a/thirdparty/php/curl/interface.cc b/thirdparty/php/curl/interface.cc index 3b6b29f6019..5f16fd37b3a 100644 --- a/thirdparty/php/curl/interface.cc +++ b/thirdparty/php/curl/interface.cc @@ -118,7 +118,7 @@ php_curl *_php_curl_get_handle(zval *zid, bool exclusive) { ch = Z_CURL_P(zid); #else if ((ch = (php_curl *) zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { - swFatalError(SW_ERROR_INVALID_PARAMS, "cURL is executing, cannot be operated"); + swFatalError(SW_ERROR_INVALID_PARAMS, "supplied resource is not a valid " le_curl_name "Handle resource "); return nullptr; } #endif diff --git a/thirdparty/php/curl/multi.cc b/thirdparty/php/curl/multi.cc index 82907417d3c..7f736278494 100644 --- a/thirdparty/php/curl/multi.cc +++ b/thirdparty/php/curl/multi.cc @@ -46,7 +46,12 @@ static inline php_curlm *curl_multi_from_obj(zend_object *obj) { extern int _php_curl_get_le_curl(); extern int _php_curl_get_le_curl_multi(); static inline php_curlm *Z_CURL_MULTI_P(zval *zv) { - return (php_curlm *) zend_fetch_resource(Z_RES_P(zv), le_curl_multi_handle_name, _php_curl_get_le_curl_multi()); + php_curlm *cm; + if ((cm = (php_curlm *) zend_fetch_resource(Z_RES_P(zv), le_curl_multi_handle_name, _php_curl_get_le_curl_multi())) == NULL) { + swFatalError(SW_ERROR_INVALID_PARAMS, "supplied resource is not a valid " le_curl_multi_handle_name "Handle resource "); + return nullptr; + } + return cm; } #endif From 1267b2efc45f16af98523f575a0daf936f8ccc5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Mon, 15 Mar 2021 18:09:30 +0800 Subject: [PATCH 081/936] Fix curl multi (#4099) * fix curl_multi * fix tests * optimize code --- .../curl_native/close_before_resume.phpt | 2 +- .../curl_native/exec_twice.phpt | 2 +- .../swoole_runtime/curl_native/multi_02.phpt | 70 +++++++++++++++++++ thirdparty/php/curl/curl_multi.h | 54 ++++++++------ thirdparty/php/curl/multi.cc | 14 ++-- 5 files changed, 110 insertions(+), 32 deletions(-) create mode 100644 tests/swoole_runtime/curl_native/multi_02.phpt diff --git a/tests/swoole_runtime/curl_native/close_before_resume.phpt b/tests/swoole_runtime/curl_native/close_before_resume.phpt index 734b88e7cb5..84dd23fcdf6 100644 --- a/tests/swoole_runtime/curl_native/close_before_resume.phpt +++ b/tests/swoole_runtime/curl_native/close_before_resume.phpt @@ -71,7 +71,7 @@ $pm->childFirst(); $pm->run(); ?> --EXPECTF-- -Fatal error: Uncaught Swoole\Error: The cURL client is executing, this handle cannot be operated in %s:%d +Fatal error: Uncaught Swoole\Error: cURL is executing, cannot be operated in %s:%d Stack trace: #0 %s(%d): curl_close(%s) #1 {main} diff --git a/tests/swoole_runtime/curl_native/exec_twice.phpt b/tests/swoole_runtime/curl_native/exec_twice.phpt index 7105fbd36da..7b2043e993e 100644 --- a/tests/swoole_runtime/curl_native/exec_twice.phpt +++ b/tests/swoole_runtime/curl_native/exec_twice.phpt @@ -67,7 +67,7 @@ $pm->childFirst(); $pm->run(); ?> --EXPECTF-- -Fatal error: Uncaught Swoole\Error: The cURL client is executing, this handle cannot be operated in %s:%d +Fatal error: Uncaught Swoole\Error: cURL is executing, cannot be operated in %s:%d Stack trace: #0 %s(%d): curl_exec(%s) #1 {main} diff --git a/tests/swoole_runtime/curl_native/multi_02.phpt b/tests/swoole_runtime/curl_native/multi_02.phpt new file mode 100644 index 00000000000..c6844d0e26d --- /dev/null +++ b/tests/swoole_runtime/curl_native/multi_02.phpt @@ -0,0 +1,70 @@ +--TEST-- +swoole_runtime/curl_native: multi +--SKIPIF-- + +--FILE-- + +--EXPECT-- +Done diff --git a/thirdparty/php/curl/curl_multi.h b/thirdparty/php/curl/curl_multi.h index 4fd051655af..8ec99ddfc31 100644 --- a/thirdparty/php/curl/curl_multi.h +++ b/thirdparty/php/curl/curl_multi.h @@ -34,14 +34,14 @@ using network::Socket; struct MultiSelector { bool defer_callback = false; - int event_count = 0; - FutureTask context; + std::set active_handles; + FutureTask *context; }; class cURLMulti { CURLM *handle; TimerNode *timer = nullptr; - MultiSelector *selector = nullptr; + std::unique_ptr selector; void read_info(); @@ -119,6 +119,10 @@ class cURLMulti { return handle; } + void set_selector(MultiSelector *_selector) { + selector.reset(_selector); + } + CURLcode exec(php_curl *ch) { Coroutine::get_current_safe(); @@ -140,21 +144,24 @@ class cURLMulti { return (CURLcode) Z_LVAL_P(return_value); } - CURLMcode select(php_curlm *mh) { + long select(php_curlm *mh) { Coroutine::get_current_safe(); - if (selector) { + if (selector->context) { swFatalError(SW_ERROR_CO_HAS_BEEN_BOUND, "cURL is already waiting, cannot be operated"); - return CURLM_RECURSIVE_API_CALL; + return -1; + } + + if (selector->active_handles.size() > 0) { + return selector->active_handles.size(); } zval _return_value; zval *return_value = &_return_value; - MultiSelector task{}; - selector = &task; + FutureTask context{}; - auto set_context_fn = [mh](FutureTask *ctx) { + auto set_context_fn = [this, mh](FutureTask *ctx) { for (zend_llist_element *element = mh->easyh.head; element; element = element->next) { zval *z_ch = (zval *) element->data; php_curl *ch; @@ -163,14 +170,14 @@ class cURLMulti { } ch->context = ctx; } + selector->context = ctx; }; - set_context_fn(&task.context); - PHPCoroutine::yield_m(return_value, &task.context); + set_context_fn(&context); + PHPCoroutine::yield_m(return_value, &context); set_context_fn(nullptr); - selector = nullptr; - return (CURLMcode) Z_LVAL_P(return_value); + return Z_LVAL_P(return_value); } void socket_action(int fd, int event_bitmask) { @@ -179,17 +186,18 @@ class cURLMulti { // for curl_multi_select if (selector) { - selector->event_count++; - if (!selector->defer_callback) { - selector->defer_callback = true; - swoole_event_defer( - [this](void *data) { - zval result; - ZVAL_LONG(&result, selector->event_count); - PHPCoroutine::resume_m(&selector->context, &result); - }, - nullptr); + selector->active_handles.insert(fd); + if (!selector->context || selector->defer_callback) { + return; } + selector->defer_callback = true; + swoole_event_defer( + [this](void *data) { + zval result; + ZVAL_LONG(&result, selector->active_handles.size()); + PHPCoroutine::resume_m(selector->context, &result); + }, + nullptr); } else { read_info(); } diff --git a/thirdparty/php/curl/multi.cc b/thirdparty/php/curl/multi.cc index 7f736278494..7d94646329a 100644 --- a/thirdparty/php/curl/multi.cc +++ b/thirdparty/php/curl/multi.cc @@ -47,8 +47,10 @@ extern int _php_curl_get_le_curl(); extern int _php_curl_get_le_curl_multi(); static inline php_curlm *Z_CURL_MULTI_P(zval *zv) { php_curlm *cm; - if ((cm = (php_curlm *) zend_fetch_resource(Z_RES_P(zv), le_curl_multi_handle_name, _php_curl_get_le_curl_multi())) == NULL) { - swFatalError(SW_ERROR_INVALID_PARAMS, "supplied resource is not a valid " le_curl_multi_handle_name "Handle resource "); + if ((cm = (php_curlm *) zend_fetch_resource( + Z_RES_P(zv), le_curl_multi_handle_name, _php_curl_get_le_curl_multi())) == NULL) { + swFatalError(SW_ERROR_INVALID_PARAMS, + "supplied resource is not a valid " le_curl_multi_handle_name "Handle resource "); return nullptr; } return cm; @@ -70,16 +72,14 @@ PHP_FUNCTION(swoole_native_curl_multi_init) { #if PHP_VERSION_ID >= 80000 object_init_ex(return_value, swoole_coroutine_curl_multi_handle_ce); mh = Z_CURL_MULTI_P(return_value); - mh->multi = new cURLMulti(); - mh->handlers = (php_curlm_handlers *) ecalloc(1, sizeof(php_curlm_handlers)); - zend_llist_init(&mh->easyh, sizeof(zval), _php_curl_multi_cleanup_list, 0); #else mh = (php_curlm *) ecalloc(1, sizeof(php_curlm)); + RETVAL_RES(zend_register_resource(mh, _php_curl_get_le_curl_multi())); +#endif mh->multi = new cURLMulti(); + mh->multi->set_selector(new MultiSelector()); mh->handlers = (php_curlm_handlers *) ecalloc(1, sizeof(php_curlm_handlers)); zend_llist_init(&mh->easyh, sizeof(zval), _php_curl_multi_cleanup_list, 0); - RETURN_RES(zend_register_resource(mh, _php_curl_get_le_curl_multi())); -#endif } /* }}} */ From 62c01b0806d33093356b8cef01da9032c3eb7330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Tue, 16 Mar 2021 16:30:34 +0800 Subject: [PATCH 082/936] Optimize native curl (#4101) * reset active_handles when select returns * defense --- thirdparty/php/curl/curl_multi.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/thirdparty/php/curl/curl_multi.h b/thirdparty/php/curl/curl_multi.h index 8ec99ddfc31..0994005b353 100644 --- a/thirdparty/php/curl/curl_multi.h +++ b/thirdparty/php/curl/curl_multi.h @@ -103,6 +103,7 @@ class cURLMulti { void del_timer() { if (timer && swoole_timer_is_available()) { swoole_timer_del(timer); + timer = nullptr; } } @@ -153,7 +154,9 @@ class cURLMulti { } if (selector->active_handles.size() > 0) { - return selector->active_handles.size(); + auto count = selector->active_handles.size(); + selector->active_handles.clear(); + return count; } zval _return_value; @@ -195,6 +198,7 @@ class cURLMulti { [this](void *data) { zval result; ZVAL_LONG(&result, selector->active_handles.size()); + selector->active_handles.clear(); PHPCoroutine::resume_m(selector->context, &result); }, nullptr); From b9e8eb74620783aefe6c90f35170990df437d510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=93=AD=E6=98=95?= <715557344@qq.com> Date: Wed, 17 Mar 2021 17:15:34 +0800 Subject: [PATCH 083/936] Added build job for alpine (#4104) --- .github/workflows/alpine.Dockerfile | 9 +++++---- .github/workflows/ext.yml | 23 +++++++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/.github/workflows/alpine.Dockerfile b/.github/workflows/alpine.Dockerfile index 95274f1c6aa..790cb5be8db 100644 --- a/.github/workflows/alpine.Dockerfile +++ b/.github/workflows/alpine.Dockerfile @@ -1,4 +1,7 @@ -FROM hyperf/hyperf:7.4-alpine-v3.11-dev +ARG PHP_VERSION +ARG ALPINE_VERSION + +FROM hyperf/hyperf:${PHP_VERSION}-alpine-v${ALPINE_VERSION}-dev LABEL maintainer="Swoole Team " version="1.0" license="MIT" @@ -7,10 +10,8 @@ COPY . /opt/www WORKDIR /opt/www RUN set -ex \ - && ln -sf /usr/bin/phpize7 /usr/local/bin/phpize \ - && ln -sf /usr/bin/php-config7 /usr/local/bin/php-config \ && phpize \ - && ./configure --enable-mysqlnd --enable-openssl --enable-http2 \ + && ./configure --enable-openssl --enable-http2 --enable-swoole-curl --enable-swoole-json \ && make -s -j$(nproc) && make install \ && echo "extension=swoole.so" > /etc/php7/conf.d/50_swoole.ini \ # check diff --git a/.github/workflows/ext.yml b/.github/workflows/ext.yml index 128e7ddaff8..626154e288c 100644 --- a/.github/workflows/ext.yml +++ b/.github/workflows/ext.yml @@ -29,7 +29,7 @@ jobs: run: ./configure --enable-sockets --enable-mysqlnd --enable-http2 --enable-openssl --enable-debug-log && make clean && make -j$(sysctl -n hw.ncpu) - name: build7 - run: ./configure --enable-sockets --enable-mysqlnd --enable-http2 --enable-swoole-curl --enable-swoole-json + run: ./configure --enable-sockets --enable-mysqlnd --enable-http2 --enable-swoole-curl --enable-swoole-json --enable-openssl --enable-debug-log && make clean && make -j$(sysctl -n hw.ncpu) @@ -56,7 +56,7 @@ jobs: run: ./configure --enable-sockets --enable-mysqlnd --enable-http2 --enable-openssl && make clean && make -j$(sysctl -n hw.ncpu) - name: build6 - run: ./configure --enable-sockets --enable-mysqlnd --enable-http2 --enable-swoole-curl --enable-swoole-json + run: ./configure --enable-sockets --enable-mysqlnd --enable-http2 --enable-swoole-curl --enable-swoole-json --enable-openssl --enable-debug-log && make clean && make -j$(sysctl -n hw.ncpu) @@ -64,7 +64,7 @@ jobs: runs-on: macos-latest steps: - name: install dependencies - run: brew install openssl && brew link openssl && brew install curl && brew link curl + run: brew install openssl && brew link openssl && brew install curl && brew link curl - uses: actions/checkout@v1 - name: phpize run: phpize @@ -80,17 +80,28 @@ jobs: run: ./configure --enable-sockets --enable-mysqlnd --enable-http2 && make clean && make -j$(sysctl -n hw.ncpu) - name: build5 - run: ./configure --enable-sockets --enable-mysqlnd --enable-http2 --enable-openssl + run: ./configure --enable-sockets --enable-mysqlnd --enable-http2 --enable-openssl --with-openssl-dir=/usr/local/opt/openssl@1.1 && make clean && make -j$(sysctl -n hw.ncpu) - name: build6 - run: ./configure --enable-sockets --enable-mysqlnd --enable-http2 --enable-swoole-curl --enable-swoole-json + run: ./configure --enable-sockets --enable-mysqlnd --enable-http2 --enable-swoole-curl --enable-swoole-json --enable-openssl --with-openssl-dir=/usr/local/opt/openssl@1.1 --enable-debug-log && make clean && make -j$(sysctl -n hw.ncpu) build-alpine-latest: runs-on: ubuntu-latest + strategy: + matrix: + php-version: [ '7.3', '7.4' ] + alpine-version: [ '3.9', '3.10', '3.11', '3.12' ] + exclude: + - php-version: '7.3' + alpine-version: '3.12' + max-parallel: 8 + fail-fast: false steps: - uses: actions/checkout@v1 - name: build - run: cp .github/workflows/alpine.Dockerfile alpine.Dockerfile && docker build -t swoole . -f alpine.Dockerfile + run: | + cp .github/workflows/alpine.Dockerfile alpine.Dockerfile + docker build -t swoole . -f alpine.Dockerfile --build-arg PHP_VERSION=${{ matrix.php-version }} --build-arg ALPINE_VERSION=${{ matrix.alpine-version }} From 490ef86886e48b9eddecea526eadcd63606f465f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Wed, 17 Mar 2021 18:27:57 +0800 Subject: [PATCH 084/936] optimize curl_multi (#4105) * optimize * fix * fix 2 --- tests/swoole_runtime/curl_native/multi.phpt | 2 +- .../swoole_runtime/curl_native/multi_02.phpt | 2 +- thirdparty/php/curl/curl_multi.h | 71 +++-------------- thirdparty/php/curl/curl_private.h | 2 + thirdparty/php/curl/interface.cc | 65 +++++++++++++++- thirdparty/php/curl/multi.cc | 76 ++++++++++++++++++- 6 files changed, 152 insertions(+), 66 deletions(-) diff --git a/tests/swoole_runtime/curl_native/multi.phpt b/tests/swoole_runtime/curl_native/multi.phpt index 8568dc4bc9e..d35ffa164f5 100644 --- a/tests/swoole_runtime/curl_native/multi.phpt +++ b/tests/swoole_runtime/curl_native/multi.phpt @@ -61,8 +61,8 @@ run(function () { curl_multi_remove_handle($mh, $ch2); curl_multi_close($mh); + echo "Done\n"; }); -echo "Done\n"; ?> --EXPECT-- Done diff --git a/tests/swoole_runtime/curl_native/multi_02.phpt b/tests/swoole_runtime/curl_native/multi_02.phpt index c6844d0e26d..0d7e93e828a 100644 --- a/tests/swoole_runtime/curl_native/multi_02.phpt +++ b/tests/swoole_runtime/curl_native/multi_02.phpt @@ -63,8 +63,8 @@ run(function () { curl_multi_remove_handle($mh, $ch2); curl_multi_close($mh); + echo "Done\n"; }); -echo "Done\n"; ?> --EXPECT-- Done diff --git a/thirdparty/php/curl/curl_multi.h b/thirdparty/php/curl/curl_multi.h index 0994005b353..41a3e5c9c0e 100644 --- a/thirdparty/php/curl/curl_multi.h +++ b/thirdparty/php/curl/curl_multi.h @@ -35,6 +35,7 @@ using network::Socket; struct MultiSelector { bool defer_callback = false; std::set active_handles; + int running_handles; FutureTask *context; }; @@ -120,6 +121,10 @@ class cURLMulti { return handle; } + int get_running_handles() { + return selector ? selector->running_handles : -1; + } + void set_selector(MultiSelector *_selector) { selector.reset(_selector); } @@ -145,67 +150,15 @@ class cURLMulti { return (CURLcode) Z_LVAL_P(return_value); } - long select(php_curlm *mh) { - Coroutine::get_current_safe(); - - if (selector->context) { - swFatalError(SW_ERROR_CO_HAS_BEEN_BOUND, "cURL is already waiting, cannot be operated"); - return -1; - } - - if (selector->active_handles.size() > 0) { - auto count = selector->active_handles.size(); - selector->active_handles.clear(); - return count; - } - - zval _return_value; - zval *return_value = &_return_value; - - FutureTask context{}; - - auto set_context_fn = [this, mh](FutureTask *ctx) { - for (zend_llist_element *element = mh->easyh.head; element; element = element->next) { - zval *z_ch = (zval *) element->data; - php_curl *ch; - if ((ch = _php_curl_get_handle(z_ch, false)) == NULL) { - continue; - } - ch->context = ctx; - } - selector->context = ctx; - }; - - set_context_fn(&context); - PHPCoroutine::yield_m(return_value, &context); - set_context_fn(nullptr); - - return Z_LVAL_P(return_value); + CURLMcode perform() { + int running_handles = 0; + auto retval = curl_multi_perform(get_multi_handle(), &running_handles); + selector ? selector->running_handles = running_handles : 0; + return retval; } - void socket_action(int fd, int event_bitmask) { - int running_handles; - curl_multi_socket_action(handle, fd, event_bitmask, &running_handles); - - // for curl_multi_select - if (selector) { - selector->active_handles.insert(fd); - if (!selector->context || selector->defer_callback) { - return; - } - selector->defer_callback = true; - swoole_event_defer( - [this](void *data) { - zval result; - ZVAL_LONG(&result, selector->active_handles.size()); - selector->active_handles.clear(); - PHPCoroutine::resume_m(selector->context, &result); - }, - nullptr); - } else { - read_info(); - } - } + long select(php_curlm *mh); + void socket_action(int fd, int event_bitmask); static int cb_readable(Reactor *reactor, Event *event); static int cb_writable(Reactor *reactor, Event *event); diff --git a/thirdparty/php/curl/curl_private.h b/thirdparty/php/curl/curl_private.h index 9df278e481a..fc6bf155efb 100644 --- a/thirdparty/php/curl/curl_private.h +++ b/thirdparty/php/curl/curl_private.h @@ -185,6 +185,8 @@ void _php_curl_close_ex(php_curl *ch); void _php_curl_close(zend_resource *rsrc); void _php_curl_multi_close(zend_resource *rsrc); php_curl *alloc_curl_handle(); +int _php_curl_get_le_curl(); +int _php_curl_get_le_curl_multi(); #endif SW_EXTERN_C_END diff --git a/thirdparty/php/curl/interface.cc b/thirdparty/php/curl/interface.cc index 5f16fd37b3a..f2924c8d625 100644 --- a/thirdparty/php/curl/interface.cc +++ b/thirdparty/php/curl/interface.cc @@ -282,7 +282,6 @@ static void curl_free_obj(zend_object *object); static HashTable *curl_get_gc(zend_object *object, zval **table, int *n); static zend_function *curl_get_constructor(zend_object *object); static zend_object *curl_clone_obj(zend_object *object); -php_curl *init_curl_handle_into_zval(zval *curl); #endif static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields); @@ -373,6 +372,70 @@ int cURLMulti::handle_timeout(CURLM *mh, long timeout_ms, void *userp) { return 0; } +long cURLMulti::select(php_curlm *mh) { + Coroutine::get_current_safe(); + + if (selector->context) { + swFatalError(SW_ERROR_CO_HAS_BEEN_BOUND, "cURL is already waiting, cannot be operated"); + return -1; + } + + if (selector->active_handles.size() > 0) { + auto count = selector->active_handles.size(); + selector->active_handles.clear(); + return count; + } + + zval _return_value; + zval *return_value = &_return_value; + + FutureTask context{}; + + auto set_context_fn = [this, mh](FutureTask *ctx) { + for (zend_llist_element *element = mh->easyh.head; element; element = element->next) { + zval *z_ch = (zval *) element->data; + php_curl *ch; + if ((ch = _php_curl_get_handle(z_ch, false)) == NULL) { + continue; + } + ch->context = ctx; + } + selector->context = ctx; + }; + + set_context_fn(&context); + PHPCoroutine::yield_m(return_value, &context); + set_context_fn(nullptr); + + return Z_LVAL_P(return_value); +} + +void cURLMulti::socket_action(int fd, int event_bitmask) { + int running_handles = 0; + curl_multi_socket_action(handle, fd, event_bitmask, &running_handles); + + // for curl_multi_select + if (selector) { + selector->active_handles.insert(fd); + selector->running_handles = running_handles; + if (!selector->context || selector->defer_callback) { + return; + } + selector->defer_callback = true; + swoole_event_defer( + [this](void *data) { + zval result; + ZVAL_LONG(&result, selector->active_handles.size()); + selector->active_handles.clear(); + selector->defer_callback = false; + PHPCoroutine::resume_m(selector->context, &result); + }, + nullptr); + } else { + read_info(); + } +} + void swoole_native_curl_minit(int module_number) { #if PHP_VERSION_ID >= 80000 SW_INIT_CLASS_ENTRY( diff --git a/thirdparty/php/curl/multi.cc b/thirdparty/php/curl/multi.cc index 7d94646329a..eeeb3449b71 100644 --- a/thirdparty/php/curl/multi.cc +++ b/thirdparty/php/curl/multi.cc @@ -43,8 +43,6 @@ static inline php_curlm *curl_multi_from_obj(zend_object *obj) { } #define Z_CURL_MULTI_P(zv) curl_multi_from_obj(Z_OBJ_P(zv)) #else -extern int _php_curl_get_le_curl(); -extern int _php_curl_get_le_curl_multi(); static inline php_curlm *Z_CURL_MULTI_P(zval *zv) { php_curlm *cm; if ((cm = (php_curlm *) zend_fetch_resource( @@ -239,7 +237,8 @@ PHP_FUNCTION(swoole_native_curl_multi_exec) { } } - error = curl_multi_perform(mh->multi->get_multi_handle(), &still_running); + error = mh->multi->perform(); + still_running = mh->multi->get_running_handles(); #if PHP_VERSION_ID >= 70400 ZEND_TRY_ASSIGN_REF_LONG(z_still_running, still_running); #else @@ -400,6 +399,75 @@ PHP_FUNCTION(swoole_native_curl_multi_strerror) { #if LIBCURL_VERSION_NUM >= 0x072C00 /* Available since 7.44.0 */ +#if PHP_VERSION_ID < 80000 +static int _php_server_push_callback( + CURL *parent_ch, CURL *easy, size_t num_headers, struct curl_pushheaders *push_headers, void *userp) /* {{{ */ +{ + php_curl *ch; + php_curl *parent; + php_curlm *mh = (php_curlm *) userp; + size_t rval = CURL_PUSH_DENY; + php_curlm_server_push *t = mh->handlers->server_push; + zval *pz_parent_ch = NULL; + zval pz_ch; + zval headers; + zval retval; + zend_resource *res; + char *header; + int error; + zend_fcall_info fci = empty_fcall_info; + + pz_parent_ch = _php_curl_multi_find_easy_handle(mh, parent_ch); + if (pz_parent_ch == NULL) { + return rval; + } + + parent = (php_curl *) zend_fetch_resource(Z_RES_P(pz_parent_ch), le_curl_name, _php_curl_get_le_curl()); + + ch = alloc_curl_handle(); + ch->cp = easy; + _php_setup_easy_copy_handlers(ch, parent); + + Z_ADDREF_P(pz_parent_ch); + + res = zend_register_resource(ch, _php_curl_get_le_curl()); + ch->res = res; + ZVAL_RES(&pz_ch, res); + + size_t i; + array_init(&headers); + for (i = 0; i < num_headers; i++) { + header = curl_pushheader_bynum(push_headers, i); + add_next_index_string(&headers, header); + } + + zend_fcall_info_init(&t->func_name, 0, &fci, &t->fci_cache, NULL, NULL); + + zend_fcall_info_argn(&fci, 3, pz_parent_ch, &pz_ch, &headers); + + fci.retval = &retval; + + error = zend_call_function(&fci, &t->fci_cache); + zend_fcall_info_args_clear(&fci, 1); + zval_ptr_dtor_nogc(&headers); + + if (error == FAILURE) { + php_error_docref(NULL, E_WARNING, "Cannot call the CURLMOPT_PUSHFUNCTION"); + } else if (!Z_ISUNDEF(retval)) { + if (CURL_PUSH_DENY != zval_get_long(&retval)) { + rval = CURL_PUSH_OK; + GC_ADDREF(Z_RES(pz_ch)); + zend_llist_add_element(&mh->easyh, &pz_ch); + } else { + /* libcurl will free this easy handle, avoid double free */ + ch->cp = NULL; + } + } + + return rval; +} +/* }}} */ +#else static int _php_server_push_callback( CURL *parent_ch, CURL *easy, size_t num_headers, struct curl_pushheaders *push_headers, void *userp) /* {{{ */ { @@ -459,7 +527,7 @@ static int _php_server_push_callback( return rval; } /* }}} */ - +#endif #endif static int _php_curl_multi_setopt(php_curlm *mh, zend_long option, zval *zvalue, zval *return_value) /* {{{ */ From 823e1a51870231468c794407430f626c4a5c6a38 Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Mon, 22 Mar 2021 05:03:07 +0100 Subject: [PATCH 085/936] Add AS_HELP_STRING to *nix build configure options (#4110) The Autoconf's default AS_HELP_STRING macro can properly format help strings [1] so watching out if columns are aligned manually is not needed anymore. [1] https://www.gnu.org/software/autoconf/manual/autoconf.html#Pretty-Help-Strings --- config.m4 | 120 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 45 deletions(-) diff --git a/config.m4 b/config.m4 index aec9dd60d1d..2d2a113aa3d 100644 --- a/config.m4 +++ b/config.m4 @@ -16,50 +16,80 @@ dnl | Author: Tianfeng Han | dnl | Author: Twosee | dnl +----------------------------------------------------------------------+ -PHP_ARG_ENABLE(debug-log, enable debug log, -[ --enable-debug-log Enable swoole debug log], no, no) - -PHP_ARG_ENABLE(trace-log, enable trace log, -[ --enable-trace-log Enable swoole trace log], no, no) - -PHP_ARG_ENABLE(sockets, enable sockets support, -[ --enable-sockets Do you have sockets extension?], no, no) - -PHP_ARG_ENABLE(openssl, enable openssl support, -[ --enable-openssl Use openssl], no, no) - -PHP_ARG_ENABLE(http2, enable http2.0 support, -[ --enable-http2 Use http2.0], no, no) - -PHP_ARG_ENABLE(swoole, swoole support, -[ --enable-swoole Enable swoole support], [enable_swoole="yes"]) - -PHP_ARG_ENABLE(mysqlnd, enable mysqlnd support, -[ --enable-mysqlnd Enable mysqlnd], no, no) - -PHP_ARG_WITH(openssl_dir, dir of openssl, -[ --with-openssl-dir[=DIR] Include OpenSSL support (requires OpenSSL >= 1.0.2)], no, no) - -PHP_ARG_WITH(jemalloc_dir, dir of jemalloc, -[ --with-jemalloc-dir[=DIR] Include jemalloc support], no, no) - -PHP_ARG_ENABLE(asan, enable asan, -[ --enable-asan Enable asan], no, no) - -PHP_ARG_ENABLE(swoole-coverage, whether to enable swoole coverage support, -[ --enable-swoole-coverage Enable swoole coverage support], no, no) - -PHP_ARG_ENABLE(swoole-dev, whether to enable Swoole developer build flags, -[ --enable-swoole-dev Enable developer flags], no, no) - -PHP_ARG_ENABLE(swoole-json, whether to enable Swoole JSON build flags, -[ --enable-swoole-json Enable JSON support], no, no) - -PHP_ARG_ENABLE(swoole-curl, whether to enable Swoole CURL build flags, -[ --enable-swoole-curl Enable cURL support], no, no) - -PHP_ARG_ENABLE(thread-context, whether to enable thread context, -[ --enable-thread-context Use thread context], no, no) +PHP_ARG_ENABLE([debug-log], + [enable debug log], + [AS_HELP_STRING([--enable-debug-log], + [Enable swoole debug log])], [no], [no]) + +PHP_ARG_ENABLE([trace-log], + [enable trace log], + [AS_HELP_STRING([--enable-trace-log], + [Enable swoole trace log])], [no], [no]) + +PHP_ARG_ENABLE([sockets], + [enable sockets support], + [AS_HELP_STRING([--enable-sockets], + [Do you have sockets extension?])], [no], [no]) + +PHP_ARG_ENABLE([openssl], + [enable openssl support], + [AS_HELP_STRING([--enable-openssl], + [Use openssl])], [no], [no]) + +PHP_ARG_ENABLE([http2], + [enable http2.0 support], + [AS_HELP_STRING([--enable-http2], + [Use http2.0])], [no], [no]) + +PHP_ARG_ENABLE([swoole], + [swoole support], + [AS_HELP_STRING([--enable-swoole], + [Enable swoole support])], [enable_swoole="yes"]) + +PHP_ARG_ENABLE([mysqlnd], + [enable mysqlnd support], + [AS_HELP_STRING([--enable-mysqlnd], + [Enable mysqlnd])], [no], [no]) + +PHP_ARG_WITH([openssl_dir], + [dir of openssl], + [AS_HELP_STRING([[--with-openssl-dir[=DIR]]], + [Include OpenSSL support (requires OpenSSL >= 1.0.2)])], [no], [no]) + +PHP_ARG_WITH([jemalloc_dir], + [dir of jemalloc], + [AS_HELP_STRING([[--with-jemalloc-dir[=DIR]]], + [Include jemalloc support])], [no], [no]) + +PHP_ARG_ENABLE([asan], + [enable asan], + [AS_HELP_STRING([--enable-asan], + [Enable asan])], [no], [no]) + +PHP_ARG_ENABLE([swoole-coverage], + [whether to enable swoole coverage support], + [AS_HELP_STRING([--enable-swoole-coverage], + [Enable swoole coverage support])], [no], [no]) + +PHP_ARG_ENABLE([swoole-dev], + [whether to enable Swoole developer build flags], + [AS_HELP_STRING([--enable-swoole-dev], + [Enable developer flags])], [no], [no]) + +PHP_ARG_ENABLE([swoole-json], + [whether to enable Swoole JSON build flags], + [AS_HELP_STRING([--enable-swoole-json], + [Enable JSON support])], [no], [no]) + +PHP_ARG_ENABLE([swoole-curl], + [whether to enable Swoole CURL build flags], + [AS_HELP_STRING([--enable-swoole-curl], + [Enable cURL support])], [no], [no]) + +PHP_ARG_ENABLE([thread-context], + [whether to enable thread context], + [AS_HELP_STRING([--enable-thread-context], + [Use thread context])], [no], [no]) AC_DEFUN([SWOOLE_HAVE_PHP_EXT], [ extname=$1 @@ -685,7 +715,7 @@ if test "$PHP_SWOOLE" != "no"; then else SW_USE_ASM_CONTEXT="no" fi - + if test "$PHP_THREAD_CONTEXT" != "no"; then AC_DEFINE(SW_USE_THREAD_CONTEXT, 1, [do we enable thread context]) SW_USE_ASM_CONTEXT="no" From 1e5a17c288a5cf0315ae74daf0d96bafd2d886ba Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Mon, 22 Mar 2021 04:04:04 +0000 Subject: [PATCH 086/936] Fix OpenBSD build. (#4108) Also in case fiber context stack creation via mmap is enabled, adding MAP_STACK flag for this platform. --- config.m4 | 1 + src/coroutine/context.cc | 17 +++++++++++------ src/lock/mutex.cc | 4 ++++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/config.m4 b/config.m4 index 2d2a113aa3d..3580e7ea4c4 100644 --- a/config.m4 +++ b/config.m4 @@ -350,6 +350,7 @@ if test "$PHP_SWOOLE" != "no"; then AC_CHECK_LIB(pthread, pthread_spin_lock, AC_DEFINE(HAVE_SPINLOCK, 1, [have pthread_spin_lock])) AC_CHECK_LIB(pthread, pthread_mutex_timedlock, AC_DEFINE(HAVE_MUTEX_TIMEDLOCK, 1, [have pthread_mutex_timedlock])) AC_CHECK_LIB(pthread, pthread_barrier_init, AC_DEFINE(HAVE_PTHREAD_BARRIER, 1, [have pthread_barrier_init])) + AC_CHECK_LIB(pthread, pthread_mutexattr_setpshared, AC_DEFINE(HAVE_PTHREAD_MUTEXATTR_SETPSHARED, 1, [have pthread_mutexattr_setpshared])) AC_CHECK_LIB(pthread, pthread_mutexattr_setrobust, AC_DEFINE(HAVE_PTHREAD_MUTEXATTR_SETROBUST, 1, [have pthread_mutexattr_setrobust])) AC_CHECK_LIB(pthread, pthread_mutex_consistent, AC_DEFINE(HAVE_PTHREAD_MUTEX_CONSISTENT, 1, [have pthread_mutex_consistent])) AC_CHECK_LIB(pcre, pcre_compile, AC_DEFINE(HAVE_PCRE, 1, [have pcre])) diff --git a/src/coroutine/context.cc b/src/coroutine/context.cc index 75ff4089dec..dd9d083c490 100644 --- a/src/coroutine/context.cc +++ b/src/coroutine/context.cc @@ -15,8 +15,11 @@ */ #include "swoole_coroutine_context.h" -#if __linux__ +#ifdef SW_CONTEXT_PROTECT_STACK_PAGE #include +#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) +#define MAP_ANONYMOUS MAP_ANON +#endif #endif #ifndef SW_USE_THREAD_CONTEXT @@ -24,10 +27,6 @@ #define MAGIC_STRING "swoole_coroutine#5652a7fb2b38be" #define START_OFFSET (64 * 1024) -#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) -#define MAP_ANONYMOUS MAP_ANON -#endif - namespace swoole { namespace coroutine { @@ -36,7 +35,13 @@ Context::Context(size_t stack_size, const coroutine_func_t &fn, void *private_da end_ = false; #ifdef SW_CONTEXT_PROTECT_STACK_PAGE - stack_ = (char *) ::mmap(0, stack_size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + int mapflags = MAP_PRIVATE | MAP_ANONYMOUS; +#ifdef __OpenBSD__ + // no-op for Linux and NetBSD, not to enable on FreeBSD as the semantic differs. + // However necessary on OpenBSD. + mapflags |= MAP_STACK; +#endif + stack_ = (char *) ::mmap(0, stack_size_, PROT_READ | PROT_WRITE, mapflags, -1, 0); #else stack_ = (char *) sw_malloc(stack_size_); #endif diff --git a/src/lock/mutex.cc b/src/lock/mutex.cc index d186595d4a0..8db6168f54c 100644 --- a/src/lock/mutex.cc +++ b/src/lock/mutex.cc @@ -40,7 +40,11 @@ Mutex::Mutex(int flags) : Lock() { pthread_mutexattr_init(&impl->attr_); if (flags & PROCESS_SHARED) { +#ifdef HAVE_PTHREAD_MUTEXATTR_SETROBUST pthread_mutexattr_setpshared(&impl->attr_, PTHREAD_PROCESS_SHARED); +#else + swWarn("PTHREAD_MUTEX_PSHARED is not supported"); +#endif } if (flags & ROBUST) { From ada8d27eb5c20cb1c81db751f2598208d79b0be5 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Mon, 22 Mar 2021 04:04:30 +0000 Subject: [PATCH 087/936] Fix illumos/solaris build, member aliases only (#4109) exposed in kernel level so available for userland here. --- include/swoole_socket.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/swoole_socket.h b/include/swoole_socket.h index 4dbc9f96d62..6aa7c1630ec 100644 --- a/include/swoole_socket.h +++ b/include/swoole_socket.h @@ -39,6 +39,12 @@ #define SOCK_NONBLOCK O_NONBLOCK #endif +#ifdef __sun +#define s6_addr8 _S6_un._S6_u8 +#define s6_addr16 _S6_un._S6_u16 +#define s6_addr32 _S6_un._S6_u32 +#endif + // OS Feature #if defined(HAVE_KQUEUE) || !defined(HAVE_SENDFILE) int swoole_sendfile(int out_fd, int in_fd, off_t *offset, size_t size); From 816cad42fd45688586e20e42b0e92abcd87793d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Tue, 23 Mar 2021 13:51:19 +0800 Subject: [PATCH 088/936] Refactor native curl (#4113) * refactor native curl * fix * fix 2 * fix 3 * fix 4 * refactor * fix 4 * fix 5 * fix tests --- config.m4 | 1 + ext-src/php_swoole_curl.h | 173 +++++++++++ ext-src/swoole_curl.cc | 282 ++++++++++++++++++ include/swoole_log.h | 3 +- .../multi.phpt => include/api/curl_multi.php} | 36 +-- tests/include/config.php | 1 + .../curl_native/concurrent.phpt | 77 +++++ .../curl_native/exec_twice.phpt | 9 +- .../swoole_runtime/curl_native/multi_02.phpt | 70 ----- tests/swoole_runtime/curl_native/multi_1.phpt | 23 ++ tests/swoole_runtime/curl_native/multi_2.phpt | 23 ++ tests/swoole_runtime/curl_native/multi_3.phpt | 31 ++ tests/swoole_runtime/curl_native/multi_4.phpt | 31 ++ .../curl_native/multi_close.phpt | 31 ++ .../curl_native/multi_dtor.phpt | 29 ++ .../curl_native/select_twice.phpt | 32 ++ .../curl_native/yield_in_callback.phpt | 19 +- thirdparty/php/curl/curl_multi.h | 169 ----------- thirdparty/php/curl/curl_private.h | 11 +- thirdparty/php/curl/interface.cc | 167 +---------- thirdparty/php/curl/multi.cc | 41 +-- 21 files changed, 797 insertions(+), 462 deletions(-) create mode 100644 ext-src/php_swoole_curl.h create mode 100644 ext-src/swoole_curl.cc rename tests/{swoole_runtime/curl_native/multi.phpt => include/api/curl_multi.php} (78%) create mode 100644 tests/swoole_runtime/curl_native/concurrent.phpt delete mode 100644 tests/swoole_runtime/curl_native/multi_02.phpt create mode 100644 tests/swoole_runtime/curl_native/multi_1.phpt create mode 100644 tests/swoole_runtime/curl_native/multi_2.phpt create mode 100644 tests/swoole_runtime/curl_native/multi_3.phpt create mode 100644 tests/swoole_runtime/curl_native/multi_4.phpt create mode 100644 tests/swoole_runtime/curl_native/multi_close.phpt create mode 100644 tests/swoole_runtime/curl_native/multi_dtor.phpt create mode 100644 tests/swoole_runtime/curl_native/select_twice.phpt delete mode 100644 thirdparty/php/curl/curl_multi.h diff --git a/config.m4 b/config.m4 index 3580e7ea4c4..55ec8b7d61d 100644 --- a/config.m4 +++ b/config.m4 @@ -531,6 +531,7 @@ if test "$PHP_SWOOLE" != "no"; then ext-src/swoole_coroutine.cc \ ext-src/swoole_coroutine_scheduler.cc \ ext-src/swoole_coroutine_system.cc \ + ext-src/swoole_curl.cc \ ext-src/swoole_event.cc \ ext-src/swoole_http2_client_coro.cc \ ext-src/swoole_http2_server.cc \ diff --git a/ext-src/php_swoole_curl.h b/ext-src/php_swoole_curl.h new file mode 100644 index 00000000000..eebc6033767 --- /dev/null +++ b/ext-src/php_swoole_curl.h @@ -0,0 +1,173 @@ +/* + +----------------------------------------------------------------------+ + | 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 | + +----------------------------------------------------------------------+ + */ + +#pragma once + +#include "php_swoole_cxx.h" + +#ifdef SW_USE_CURL +#include "swoole_util.h" + +SW_EXTERN_C_BEGIN +#include +#include +#include "thirdparty/php/curl/curl_private.h" +SW_EXTERN_C_END + +namespace swoole { + +using network::Socket; + +namespace curl { + +class Multi; + +struct Handle { + CURL *cp; + Socket *socket; + Multi *multi; + int bitmask; + int action; + bool removed; +}; + +struct Selector { + bool defer_callback = false; + std::set active_handles; +}; + +class Multi { + CURLM *multi_handle_; + TimerNode *timer = nullptr; + bool timedout = false; + long timeout_ms_ = 0; + Coroutine *co = nullptr; + int running_handles_ = 0; + int last_sockfd; + std::unique_ptr selector; + + CURLcode read_info(); + + Socket *create_socket(CURL *cp, curl_socket_t sockfd); + + Handle *get_handle(CURL *cp) { + Handle *handle = nullptr; + curl_easy_getinfo(cp, CURLINFO_PRIVATE, &handle); + return handle; + } + + void set_event(CURL *easy, void *socket_ptr, curl_socket_t sockfd, int action); + void del_event(CURL *easy, void *socket_ptr, curl_socket_t sockfd); + + void add_timer(long timeout_ms) { + if (timer && swoole_timer_is_available()) { + swoole_timer_del(timer); + } + timeout_ms_ = timeout_ms; + timer = swoole_timer_add( + timeout_ms, false, [this](Timer *timer, TimerNode *tnode) { + this->timer = nullptr; + callback(nullptr, 0); + }); + } + + void del_timer() { + if (timer && swoole_timer_is_available()) { + swoole_timer_del(timer); + timeout_ms_ = -1; + timer = nullptr; + } + } + + void set_timer() { + long _timeout_ms = 0; + curl_multi_timeout(multi_handle_, &_timeout_ms); + handle_timeout(multi_handle_, _timeout_ms, this); + } + + public: + Multi() { + multi_handle_ = curl_multi_init(); + co = nullptr; + curl_multi_setopt(multi_handle_, CURLMOPT_SOCKETFUNCTION, handle_socket); + curl_multi_setopt(multi_handle_, CURLMOPT_TIMERFUNCTION, handle_timeout); + curl_multi_setopt(multi_handle_, CURLMOPT_SOCKETDATA, this); + curl_multi_setopt(multi_handle_, CURLMOPT_TIMERDATA, this); + } + + CURLM *get_multi_handle() { + return multi_handle_; + } + + int get_running_handles() { + return running_handles_; + } + + void set_selector(Selector *_selector) { + selector.reset(_selector); + } + + CURLMcode add_handle(CURL *cp) { + auto retval = curl_multi_add_handle(multi_handle_, cp); + if (retval == CURLM_OK) { + auto handle = new Handle{}; + handle->cp = cp; + handle->multi = this; + curl_easy_setopt(cp, CURLOPT_PRIVATE, handle); + } + return retval; + } + + CURLMcode remove_handle(CURL *cp) { + auto retval = curl_multi_remove_handle(multi_handle_, cp); + if (retval == CURLM_OK) { + auto handle = get_handle(cp); + delete handle; + curl_easy_setopt(cp, CURLOPT_PRIVATE, nullptr); + } + return retval; + } + + CURLMcode perform() { + auto retval = curl_multi_perform(multi_handle_, &running_handles_); + return retval; + } + + int get_event(int action) { + return action == CURL_POLL_IN ? SW_EVENT_READ : SW_EVENT_WRITE; + } + + Coroutine *check_bound_co() { + if (co) { + swFatalError(SW_ERROR_CO_HAS_BEEN_BOUND, "cURL is executing, cannot be operated"); + return nullptr; + } + return Coroutine::get_current_safe(); + } + + CURLcode exec(php_curl *ch); + long select(php_curlm *mh); + void callback(Handle *handle, int event_bitmask); + + static int cb_readable(Reactor *reactor, Event *event); + static int cb_writable(Reactor *reactor, Event *event); + static int cb_error(Reactor *reactor, Event *event); + static int handle_socket(CURL *easy, curl_socket_t s, int action, void *userp, void *socketp); + static int handle_timeout(CURLM *multi, long timeout_ms, void *userp); +}; +}; +} // namespace swoole +#endif diff --git a/ext-src/swoole_curl.cc b/ext-src/swoole_curl.cc new file mode 100644 index 00000000000..5bce8a914f3 --- /dev/null +++ b/ext-src/swoole_curl.cc @@ -0,0 +1,282 @@ +/* + +----------------------------------------------------------------------+ + | 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 | + +----------------------------------------------------------------------+ + */ + +#include "php_swoole_curl.h" + +#ifdef SW_USE_CURL + +namespace swoole { +namespace curl { + +int Multi::cb_readable(Reactor *reactor, Event *event) { + Handle *handle = (Handle *) event->socket->object; + handle->multi->callback(handle, CURL_CSELECT_IN); + return 0; +} + +int Multi::cb_writable(Reactor *reactor, Event *event) { + Handle *handle = (Handle *) event->socket->object; + handle->multi->callback(handle, CURL_CSELECT_OUT); + return 0; +} + +int Multi::cb_error(Reactor *reactor, Event *event) { + Handle *handle = (Handle *) event->socket->object; + handle->multi->callback(handle, CURL_CSELECT_ERR); + return 0; +} + +int Multi::handle_socket(CURL *easy, curl_socket_t s, int action, void *userp, void *socketp) { + Multi *multi = (Multi *) userp; + switch (action) { + case CURL_POLL_IN: + case CURL_POLL_OUT: + case CURL_POLL_INOUT: + multi->set_event(easy, socketp, s, action); + break; + case CURL_POLL_REMOVE: + if (socketp) { + multi->del_event(easy, socketp, s); + } + break; + default: + abort(); + } + return 0; +} + +Socket *Multi::create_socket(CURL *cp, curl_socket_t sockfd) { + if (!swoole_event_isset_handler(PHP_SWOOLE_FD_CO_CURL)) { + swoole_event_set_handler(PHP_SWOOLE_FD_CO_CURL | SW_EVENT_READ, cb_readable); + swoole_event_set_handler(PHP_SWOOLE_FD_CO_CURL | SW_EVENT_WRITE, cb_writable); + swoole_event_set_handler(PHP_SWOOLE_FD_CO_CURL | SW_EVENT_ERROR, cb_error); + } + Socket *socket = new Socket(); + socket->fd = sockfd; + socket->removed = 1; + socket->fd_type = (enum swFd_type) PHP_SWOOLE_FD_CO_CURL; + curl_multi_assign(multi_handle_, sockfd, (void *) socket); + + Handle *handle = get_handle(cp); + handle->socket = socket; + handle->cp = cp; + socket->object = handle; + + return socket; +} + +void Multi::del_event(CURL *cp, void *socket_ptr, curl_socket_t sockfd) { + Socket *socket = (Socket *) socket_ptr; + socket->silent_remove = 1; + if (socket->events && swoole_event_is_available()) { + swoole_event_del(socket); + } + socket->fd = -1; + socket->free(); + curl_multi_assign(multi_handle_, sockfd, NULL); + + Handle *handle = get_handle(cp); + handle->socket = nullptr; + + swTraceLog(SW_TRACE_CO_CURL, SW_ECHO_RED " handle=%p, curl=%p, fd=%d", "[DEL]", handle, cp, sockfd); +} + +void Multi::set_event(CURL *cp, void *socket_ptr, curl_socket_t sockfd, int action) { + Socket *socket = socket_ptr ? (Socket *) socket_ptr : create_socket(cp, sockfd); + int events = 0; + if (action != CURL_POLL_IN) { + events |= SW_EVENT_WRITE; + } + if (action != CURL_POLL_OUT) { + events |= SW_EVENT_READ; + } + assert(socket->fd > 0); + socket->fd = sockfd; + if (socket->events) { + swoole_event_set(socket, events); + } else { + swoole_event_add(socket, events); + } + Handle *handle = get_handle(cp); + handle->action = action; + handle->removed = false; + + swTraceLog(SW_TRACE_CO_CURL, SW_ECHO_GREEN " handle=%p, curl=%p, fd=%d, events=%d", "[ADD]", handle, cp, sockfd, events); +} + +CURLcode Multi::exec(php_curl *ch) { + co = check_bound_co(); + ON_SCOPE_EXIT { + co = nullptr; + }; + + if (add_handle(ch->cp) != CURLM_OK) { + return CURLE_FAILED_INIT; + } + + Handle *handle = get_handle(ch->cp); + + SW_LOOP { + co->yield(); + int sockfd = last_sockfd; + int bitmask = 0; + if (sockfd >= 0) { + bitmask = handle->bitmask; + swoole_event_del(handle->socket); + handle->removed = true; + } + del_timer(); + curl_multi_socket_action(multi_handle_, sockfd, bitmask, &running_handles_); + if (running_handles_ == 0) { + break; + } + set_timer(); + if (sockfd >= 0 && handle->socket && handle->removed) { + swoole_event_add(handle->socket, get_event(handle->action)); + handle->removed = false; + } + } + + CURLcode retval = read_info(); + remove_handle(ch->cp); + return retval; +} + +CURLcode Multi::read_info() { + CURLMsg *message; + int pending; + + while ((message = curl_multi_info_read(multi_handle_, &pending))) { + switch (message->msg) { + case CURLMSG_DONE: + /* Do not use message data after calling curl_multi_remove_handle() and + curl_easy_cleanup(). As per curl_multi_info_read() docs: + "WARNING: The data the returned pointer points to will not survive + calling curl_multi_cleanup, curl_multi_remove_handle or + curl_easy_cleanup." */ + return message->data.result; + default: + swWarn("CURLMSG default"); + break; + } + } + return CURLE_OK; +} + +int Multi::handle_timeout(CURLM *mh, long timeout_ms, void *userp) { + Multi *multi = (Multi *) userp; + if (timeout_ms < 0) { + multi->del_timer(); + } else { + if (timeout_ms == 0) { + timeout_ms = 1; /* 0 means directly call socket_action, but we'll do it in a bit */ + } + multi->add_timer(timeout_ms); + } + return 0; +} + +long Multi::select(php_curlm *mh) { + co = check_bound_co(); + ON_SCOPE_EXIT { + co = nullptr; + }; + + for (zend_llist_element *element = mh->easyh.head; element; element = element->next) { + zval *z_ch = (zval *) element->data; + php_curl *ch; + if ((ch = _php_curl_get_handle(z_ch, false)) == NULL) { + continue; + } + Handle *handle = get_handle(ch->cp); + if (handle && handle->socket && handle->removed) { + swoole_event_add(handle->socket, get_event(handle->action)); + handle->removed = false; + swTraceLog(SW_TRACE_CO_CURL, "resume, handle=%p, curl=%p, fd=%d", handle, ch->cp, handle->socket->get_fd()); + } + } + set_timer(); + + co->yield(); + auto count = selector->active_handles.size(); + + for (zend_llist_element *element = mh->easyh.head; element; element = element->next) { + zval *z_ch = (zval *) element->data; + php_curl *ch; + if ((ch = _php_curl_get_handle(z_ch, false)) == NULL) { + continue; + } + Handle *handle = get_handle(ch->cp); + if (handle && handle->socket) { + swTraceLog(SW_TRACE_CO_CURL, "suspend, handle=%p, curl=%p, fd=%d", handle, ch->cp, handle->socket->get_fd()); + swoole_event_del(handle->socket); + handle->removed = true; + } + } + del_timer(); + + for (auto iter = selector->active_handles.begin(); iter != selector->active_handles.end(); iter++) { + Handle *handle = *iter; + int bitmask = 0; + int sockfd = -1; + if (handle) { + bitmask = handle->bitmask; + sockfd = handle->socket->fd; + } + curl_multi_socket_action(multi_handle_, sockfd, bitmask, &running_handles_); + swTraceLog(SW_TRACE_CO_CURL, "socket_action, running_handles=%d", running_handles_); + } + selector->active_handles.clear(); + + return count; +} + +void Multi::callback(Handle *handle, int event_bitmask) { + if (handle) { + last_sockfd = handle->socket->fd; + handle->bitmask = event_bitmask; + } else { + last_sockfd = -1; + } + // for curl_multi_select + if (selector.get()) { + if (!co) { + if (handle) { + swoole_event_del(handle->socket); + handle->removed = true; + } else { + del_timer(); + } + return; + } + selector->active_handles.insert(handle); + if (selector->defer_callback) { + return; + } + selector->defer_callback = true; + swoole_event_defer( + [this](void *data) { + selector->defer_callback = false; + co->resume(); + }, + nullptr); + } else { + co->resume(); + } +} +} // namespace curl +} // namespace swoole +#endif diff --git a/include/swoole_log.h b/include/swoole_log.h index d1bb4580d9b..67a8607915a 100644 --- a/include/swoole_log.h +++ b/include/swoole_log.h @@ -161,7 +161,7 @@ swoole::Logger *sw_logger(); #define swFatalError(code, str, ...) \ do { \ SwooleG.fatal_error(code, str, ##__VA_ARGS__); \ - abort(); \ + exit(255); \ } while (0) #define swoole_error_log(level, __errno, str, ...) \ @@ -242,6 +242,7 @@ enum swTrace_type { SW_TRACE_CONTEXT = 1u << 26, SW_TRACE_CO_HTTP_SERVER = 1u << 27, SW_TRACE_TABLE = 1u << 28, + SW_TRACE_CO_CURL = 1u << 29, SW_TRACE_ALL = 0xffffffff }; diff --git a/tests/swoole_runtime/curl_native/multi.phpt b/tests/include/api/curl_multi.php similarity index 78% rename from tests/swoole_runtime/curl_native/multi.phpt rename to tests/include/api/curl_multi.php index d35ffa164f5..9e034e0a613 100644 --- a/tests/swoole_runtime/curl_native/multi.phpt +++ b/tests/include/api/curl_multi.php @@ -1,19 +1,5 @@ ---TEST-- -swoole_runtime/curl_native: multi ---SKIPIF-- ---FILE-- - ---EXPECT-- -Done +} \ No newline at end of file diff --git a/tests/include/config.php b/tests/include/config.php index d2e5e14e78f..b0d97b0b3fb 100644 --- a/tests/include/config.php +++ b/tests/include/config.php @@ -22,6 +22,7 @@ /** ============== Files ============== */ define('SOURCE_ROOT_PATH', __DIR__ . '/../../'); define('TESTS_ROOT_PATH', __DIR__ . '/../'); +define('TESTS_API_PATH', TESTS_ROOT_PATH.'/include/api'); define('TRAVIS_DIR_PATH', __DIR__ . '/../../travis/'); define('TEST_IMAGE', __DIR__ . '/../../examples/test.jpg'); define('TEST_LINK_IMAGE', __DIR__ . '/../../examples/test_link.jpg'); diff --git a/tests/swoole_runtime/curl_native/concurrent.phpt b/tests/swoole_runtime/curl_native/concurrent.phpt new file mode 100644 index 00000000000..9658a51f6b3 --- /dev/null +++ b/tests/swoole_runtime/curl_native/concurrent.phpt @@ -0,0 +1,77 @@ +--TEST-- +swoole_runtime/curl_native: Concurrent request +--SKIPIF-- + +--FILE-- +parentFunc = function () use ($pm) { + Runtime::enableCoroutine(SWOOLE_HOOK_NATIVE_CURL); + $s = microtime(true); + run(function () use ($pm) { + $fn = function () use ($pm) { + $ch = curl_init(); + $code = uniqid('swoole_'); + $url = "http://127.0.0.1:".$pm->getFreePort()."/?code=".urlencode($code); + + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HEADER, 0); + curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($ch, $strHeader) { + return strlen($strHeader); + }); + $output = curl_exec($ch); + Assert::eq($output, "Hello World\n".$code); + if ($output === false) { + echo "CURL Error:" . curl_error($ch); + } + curl_close($ch); + echo "DONE\n"; + }; + + $n = N; + while($n--) { + go($fn); + } + }); + Assert::lessThan(microtime(true) - $s, 0.5); + $pm->kill(); +}; +$pm->childFunc = function () use ($pm) { + $http = new Swoole\Http\Server("127.0.0.1", $pm->getFreePort()); + $http->set(['worker_num' => N, 'log_file' => '/dev/null']); + + $http->on("start", function ($server) use ($pm) { + $pm->wakeup(); + }); + + $http->on("request", function (Request $request, Response $response) { + usleep(rand(1000, 30000)); + $response->end("Hello World\n".$request->get['code']); + }); + $http->start(); +}; +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +DONE +DONE +DONE +DONE +DONE +DONE +DONE +DONE diff --git a/tests/swoole_runtime/curl_native/exec_twice.phpt b/tests/swoole_runtime/curl_native/exec_twice.phpt index 7b2043e993e..e9c42c527a4 100644 --- a/tests/swoole_runtime/curl_native/exec_twice.phpt +++ b/tests/swoole_runtime/curl_native/exec_twice.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_runtime/curl_native: close before resume +swoole_runtime/curl_native: exec twice --SKIPIF-- parentFunc = function () use ($pm) { go(function() use ($ch) { Co::sleep(0.1); - var_dump(curl_exec($ch)); + echo "co 2 exec\n"; + var_dump(curl_exec($ch), curl_errno($ch)); }); + echo "co 1 exec\n"; $output = curl_exec($ch); Assert::eq($output, "Hello World\n".$code); if ($output === false) { @@ -67,6 +69,9 @@ $pm->childFirst(); $pm->run(); ?> --EXPECTF-- +co 1 exec +co 2 exec + Fatal error: Uncaught Swoole\Error: cURL is executing, cannot be operated in %s:%d Stack trace: #0 %s(%d): curl_exec(%s) diff --git a/tests/swoole_runtime/curl_native/multi_02.phpt b/tests/swoole_runtime/curl_native/multi_02.phpt deleted file mode 100644 index 0d7e93e828a..00000000000 --- a/tests/swoole_runtime/curl_native/multi_02.phpt +++ /dev/null @@ -1,70 +0,0 @@ ---TEST-- -swoole_runtime/curl_native: multi ---SKIPIF-- - ---FILE-- - ---EXPECT-- -Done diff --git a/tests/swoole_runtime/curl_native/multi_1.phpt b/tests/swoole_runtime/curl_native/multi_1.phpt new file mode 100644 index 00000000000..fca70d7ddf4 --- /dev/null +++ b/tests/swoole_runtime/curl_native/multi_1.phpt @@ -0,0 +1,23 @@ +--TEST-- +swoole_runtime/curl_native: multi 1 +--SKIPIF-- + +--FILE-- + +--EXPECT-- +Done diff --git a/tests/swoole_runtime/curl_native/multi_2.phpt b/tests/swoole_runtime/curl_native/multi_2.phpt new file mode 100644 index 00000000000..d6ed164a33c --- /dev/null +++ b/tests/swoole_runtime/curl_native/multi_2.phpt @@ -0,0 +1,23 @@ +--TEST-- +swoole_runtime/curl_native: multi 2 +--SKIPIF-- + +--FILE-- + 0.2]); + echo "Done\n"; +}); +?> +--EXPECT-- +Done diff --git a/tests/swoole_runtime/curl_native/multi_3.phpt b/tests/swoole_runtime/curl_native/multi_3.phpt new file mode 100644 index 00000000000..78fe2058d67 --- /dev/null +++ b/tests/swoole_runtime/curl_native/multi_3.phpt @@ -0,0 +1,31 @@ +--TEST-- +swoole_runtime/curl_native: multi 3 +--SKIPIF-- + +--FILE-- + +--EXPECT-- +Done +Done +Done +Done diff --git a/tests/swoole_runtime/curl_native/multi_4.phpt b/tests/swoole_runtime/curl_native/multi_4.phpt new file mode 100644 index 00000000000..ab49a88a469 --- /dev/null +++ b/tests/swoole_runtime/curl_native/multi_4.phpt @@ -0,0 +1,31 @@ +--TEST-- +swoole_runtime/curl_native: multi 4 +--SKIPIF-- + +--FILE-- + 0.2]); + echo "Done\n"; + }); + } +}); +?> +--EXPECT-- +Done +Done +Done +Done diff --git a/tests/swoole_runtime/curl_native/multi_close.phpt b/tests/swoole_runtime/curl_native/multi_close.phpt new file mode 100644 index 00000000000..d9cbeab1656 --- /dev/null +++ b/tests/swoole_runtime/curl_native/multi_close.phpt @@ -0,0 +1,31 @@ +--TEST-- +swoole_runtime/curl_native: clean handle +--SKIPIF-- + +--FILE-- + +--EXPECT-- +Done diff --git a/tests/swoole_runtime/curl_native/multi_dtor.phpt b/tests/swoole_runtime/curl_native/multi_dtor.phpt new file mode 100644 index 00000000000..d4fcd843baa --- /dev/null +++ b/tests/swoole_runtime/curl_native/multi_dtor.phpt @@ -0,0 +1,29 @@ +--TEST-- +swoole_runtime/curl_native: multi dtor +--SKIPIF-- + +--FILE-- + +--EXPECT-- +Done diff --git a/tests/swoole_runtime/curl_native/select_twice.phpt b/tests/swoole_runtime/curl_native/select_twice.phpt new file mode 100644 index 00000000000..3e196a900bb --- /dev/null +++ b/tests/swoole_runtime/curl_native/select_twice.phpt @@ -0,0 +1,32 @@ +--TEST-- +swoole_runtime/curl_native: select twice +--SKIPIF-- + +--FILE-- + true]); + echo "Done\n"; + }); + } +}); +?> +--EXPECTF-- +Fatal error: Uncaught Swoole\Error: cURL is executing, cannot be operated in %s:%d +Stack trace: +#0 %s(%d): curl_multi_select(%s) +#1 {main} + thrown in %s on line %d diff --git a/tests/swoole_runtime/curl_native/yield_in_callback.phpt b/tests/swoole_runtime/curl_native/yield_in_callback.phpt index fe5295e3780..c99465d2579 100644 --- a/tests/swoole_runtime/curl_native/yield_in_callback.phpt +++ b/tests/swoole_runtime/curl_native/yield_in_callback.phpt @@ -27,28 +27,25 @@ run(function () use ($pm) { curl_setopt($ch, CURLOPT_HEADERFUNCTION, function ($ch, $strHeader) use (&$header_count) { Assert::eq(curl_getinfo($ch, CURLINFO_HTTP_CODE), 200); Assert::eq(md5_file(__FILE__), md5(file_get_contents(__FILE__))); + Co::sleep(0.05); $header_count++; - Co::sleep(0.1); return strlen($strHeader); }); + echo "exec\n"; $output = curl_exec($ch); - Assert::eq($output, "Hello World\n".$code); + Assert::contains($output, "baidu.com"); if ($output === false) { echo "CURL Error:" . curl_error($ch); } + echo "exec end\n"; Assert::greaterThan($header_count, 1); curl_close($ch); echo "Close\n"; }); ?> ---EXPECTF-- -Fatal error: Uncaught Swoole\Error: API must be called in the coroutine in %s:%d -Stack trace: -#0 %s(%d): Swoole\Coroutine::sleep(0.1) -#1 [internal function]: {closure}(Resource id #%d, 'HTTP/1.1 200 OK...') -#2 @swoole-src/library/core/Coroutine/functions.php(%d): Swoole\Coroutine\Scheduler->start() -#3 %s(%d): Swoole\Coroutine\run(Object(Closure)) -#4 {main} - thrown in %s on line %d +--EXPECT-- +exec +exec end +Close diff --git a/thirdparty/php/curl/curl_multi.h b/thirdparty/php/curl/curl_multi.h deleted file mode 100644 index 41a3e5c9c0e..00000000000 --- a/thirdparty/php/curl/curl_multi.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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 | - +----------------------------------------------------------------------+ - */ - -#pragma once - -#include "php_swoole_cxx.h" -#include "swoole_util.h" - -SW_EXTERN_C_BEGIN - -#include -#include - -#include "curl_private.h" - -SW_EXTERN_C_END - -namespace swoole { - -using network::Socket; - -struct MultiSelector { - bool defer_callback = false; - std::set active_handles; - int running_handles; - FutureTask *context; -}; - -class cURLMulti { - CURLM *handle; - TimerNode *timer = nullptr; - std::unique_ptr selector; - - void read_info(); - - Socket *create_socket(curl_socket_t sockfd) { - if (!swoole_event_isset_handler(PHP_SWOOLE_FD_CO_CURL)) { - swoole_event_set_handler(PHP_SWOOLE_FD_CO_CURL | SW_EVENT_READ, cb_readable); - swoole_event_set_handler(PHP_SWOOLE_FD_CO_CURL | SW_EVENT_WRITE, cb_writable); - swoole_event_set_handler(PHP_SWOOLE_FD_CO_CURL | SW_EVENT_ERROR, cb_error); - } - Socket *socket = new Socket(); - socket->fd = sockfd; - socket->removed = 1; - socket->object = this; - socket->fd_type = (enum swFd_type) PHP_SWOOLE_FD_CO_CURL; - curl_multi_assign(handle, sockfd, (void *) socket); - return socket; - } - - bool add(CURL *cp) { - return curl_multi_add_handle(handle, cp) == CURLM_OK; - } - - void set_event(void *socket_ptr, curl_socket_t sockfd, int action) { - Socket *socket = socket_ptr ? (Socket *) socket_ptr : create_socket(sockfd); - int events = 0; - if (action != CURL_POLL_IN) { - events |= SW_EVENT_WRITE; - } - if (action != CURL_POLL_OUT) { - events |= SW_EVENT_READ; - } - if (socket->events) { - swoole_event_set(socket, events); - } else { - swoole_event_add(socket, events); - } - } - - void del_event(void *socket_ptr, curl_socket_t sockfd) { - Socket *socket = (Socket *) socket_ptr; - socket->silent_remove = 1; - if (socket->events && swoole_event_is_available()) { - swoole_event_del(socket); - } - socket->fd = -1; - socket->free(); - curl_multi_assign(handle, sockfd, NULL); - } - - void add_timer(long timeout_ms) { - if (timer && swoole_timer_is_available()) { - swoole_timer_del(timer); - } - - timer = swoole_timer_add( - timeout_ms, false, [this](Timer *timer, TimerNode *tnode) { socket_action(CURL_SOCKET_TIMEOUT, 0); }); - } - - void del_timer() { - if (timer && swoole_timer_is_available()) { - swoole_timer_del(timer); - timer = nullptr; - } - } - - public: - cURLMulti() { - handle = curl_multi_init(); - curl_multi_setopt(handle, CURLMOPT_SOCKETFUNCTION, handle_socket); - curl_multi_setopt(handle, CURLMOPT_TIMERFUNCTION, handle_timeout); - curl_multi_setopt(handle, CURLMOPT_SOCKETDATA, this); - curl_multi_setopt(handle, CURLMOPT_TIMERDATA, this); - } - - CURLM *get_multi_handle() { - return handle; - } - - int get_running_handles() { - return selector ? selector->running_handles : -1; - } - - void set_selector(MultiSelector *_selector) { - selector.reset(_selector); - } - - CURLcode exec(php_curl *ch) { - Coroutine::get_current_safe(); - - if (!add(ch->cp)) { - return CURLE_FAILED_INIT; - } - - zval _return_value; - zval *return_value = &_return_value; - - FutureTask *context = (FutureTask *) emalloc(sizeof(FutureTask)); - ON_SCOPE_EXIT { - efree(context); - }; - ch->context = context; - PHPCoroutine::yield_m(return_value, context); - ch->context = nullptr; - - return (CURLcode) Z_LVAL_P(return_value); - } - - CURLMcode perform() { - int running_handles = 0; - auto retval = curl_multi_perform(get_multi_handle(), &running_handles); - selector ? selector->running_handles = running_handles : 0; - return retval; - } - - long select(php_curlm *mh); - void socket_action(int fd, int event_bitmask); - - static int cb_readable(Reactor *reactor, Event *event); - static int cb_writable(Reactor *reactor, Event *event); - static int cb_error(Reactor *reactor, Event *event); - static int handle_socket(CURL *easy, curl_socket_t s, int action, void *userp, void *socketp); - static int handle_timeout(CURLM *multi, long timeout_ms, void *userp); -}; -} // namespace swoole diff --git a/thirdparty/php/curl/curl_private.h b/thirdparty/php/curl/curl_private.h index fc6bf155efb..8286d07ab7d 100644 --- a/thirdparty/php/curl/curl_private.h +++ b/thirdparty/php/curl/curl_private.h @@ -117,7 +117,6 @@ typedef struct { #if PHP_VERSION_ID >= 80000 struct _php_curlsh *share; #endif - swoole::FutureTask *context; #if PHP_VERSION_ID >= 80000 zend_object std; #endif @@ -129,13 +128,15 @@ typedef struct { php_curlm_server_push *server_push; } php_curlm_handlers; -namespace swoole { -class cURLMulti; -} +namespace swoole { namespace curl { +class Multi; +}} + +using swoole::curl::Multi; typedef struct { int still_running; - swoole::cURLMulti *multi; + Multi *multi; zend_llist easyh; php_curlm_handlers *handlers; struct { diff --git a/thirdparty/php/curl/interface.cc b/thirdparty/php/curl/interface.cc index f2924c8d625..c28a363c23f 100644 --- a/thirdparty/php/curl/interface.cc +++ b/thirdparty/php/curl/interface.cc @@ -19,7 +19,7 @@ #include "php_swoole_cxx.h" #ifdef SW_USE_CURL -#include "curl_multi.h" +#include "php_swoole_curl.h" using namespace swoole; @@ -122,9 +122,12 @@ php_curl *_php_curl_get_handle(zval *zid, bool exclusive) { return nullptr; } #endif - if (exclusive && ch->context) { - swFatalError(SW_ERROR_CO_HAS_BEEN_BOUND, "cURL is executing, cannot be operated"); - return nullptr; + if (exclusive) { + swoole::curl::Handle *handle = nullptr; + curl_easy_getinfo(ch->cp, CURLINFO_PRIVATE, &handle); + if (handle && handle->multi->check_bound_co() == nullptr) { + return nullptr; + } } return ch; } @@ -288,154 +291,6 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields SW_EXTERN_C_END -static cURLMulti *g_curl_multi = nullptr; - -cURLMulti *sw_curl_multi() { - return g_curl_multi; -} - -int cURLMulti::cb_readable(Reactor *reactor, Event *event) { - cURLMulti *multi = (cURLMulti *) event->socket->object; - multi->socket_action(event->fd, CURL_CSELECT_IN); - return 0; -} - -int cURLMulti::cb_writable(Reactor *reactor, Event *event) { - cURLMulti *multi = (cURLMulti *) event->socket->object; - multi->socket_action(event->fd, CURL_CSELECT_OUT); - return 0; -} - -int cURLMulti::cb_error(Reactor *reactor, Event *event) { - cURLMulti *multi = (cURLMulti *) event->socket->object; - multi->socket_action(event->fd, CURL_CSELECT_ERR); - return 0; -} - -int cURLMulti::handle_socket(CURL *easy, curl_socket_t s, int action, void *userp, void *socketp) { - cURLMulti *multi = (cURLMulti *) userp; - switch (action) { - case CURL_POLL_IN: - case CURL_POLL_OUT: - case CURL_POLL_INOUT: - multi->set_event(socketp, s, action); - break; - case CURL_POLL_REMOVE: - if (socketp) { - multi->del_event(socketp, s); - } - break; - default: - abort(); - } - return 0; -} - -void cURLMulti::read_info() { - CURLMsg *message; - int pending; - CURL *easy_handle; - - while ((message = curl_multi_info_read(handle, &pending))) { - switch (message->msg) { - case CURLMSG_DONE: - /* Do not use message data after calling curl_multi_remove_handle() and - curl_easy_cleanup(). As per curl_multi_info_read() docs: - "WARNING: The data the returned pointer points to will not survive - calling curl_multi_cleanup, curl_multi_remove_handle or - curl_easy_cleanup." */ - easy_handle = message->easy_handle; - curl_multi_remove_handle(handle, easy_handle); - php_curl *ch; - curl_easy_getinfo(easy_handle, CURLINFO_PRIVATE, &ch); - zval result; - ZVAL_LONG(&result, message->data.result); - PHPCoroutine::resume_m(ch->context, &result); - break; - default: - swWarn("CURLMSG default"); - break; - } - } -} - -int cURLMulti::handle_timeout(CURLM *mh, long timeout_ms, void *userp) { - cURLMulti *multi = (cURLMulti *) userp; - if (timeout_ms < 0) { - multi->del_timer(); - } else { - if (timeout_ms == 0) { - timeout_ms = 1; /* 0 means directly call socket_action, but we'll do it in a bit */ - } - multi->add_timer(timeout_ms); - } - return 0; -} - -long cURLMulti::select(php_curlm *mh) { - Coroutine::get_current_safe(); - - if (selector->context) { - swFatalError(SW_ERROR_CO_HAS_BEEN_BOUND, "cURL is already waiting, cannot be operated"); - return -1; - } - - if (selector->active_handles.size() > 0) { - auto count = selector->active_handles.size(); - selector->active_handles.clear(); - return count; - } - - zval _return_value; - zval *return_value = &_return_value; - - FutureTask context{}; - - auto set_context_fn = [this, mh](FutureTask *ctx) { - for (zend_llist_element *element = mh->easyh.head; element; element = element->next) { - zval *z_ch = (zval *) element->data; - php_curl *ch; - if ((ch = _php_curl_get_handle(z_ch, false)) == NULL) { - continue; - } - ch->context = ctx; - } - selector->context = ctx; - }; - - set_context_fn(&context); - PHPCoroutine::yield_m(return_value, &context); - set_context_fn(nullptr); - - return Z_LVAL_P(return_value); -} - -void cURLMulti::socket_action(int fd, int event_bitmask) { - int running_handles = 0; - curl_multi_socket_action(handle, fd, event_bitmask, &running_handles); - - // for curl_multi_select - if (selector) { - selector->active_handles.insert(fd); - selector->running_handles = running_handles; - if (!selector->context || selector->defer_callback) { - return; - } - selector->defer_callback = true; - swoole_event_defer( - [this](void *data) { - zval result; - ZVAL_LONG(&result, selector->active_handles.size()); - selector->active_handles.clear(); - selector->defer_callback = false; - PHPCoroutine::resume_m(selector->context, &result); - }, - nullptr); - } else { - read_info(); - } -} - void swoole_native_curl_minit(int module_number) { #if PHP_VERSION_ID >= 80000 SW_INIT_CLASS_ENTRY( @@ -465,8 +320,6 @@ void swoole_native_curl_minit(int module_number) { "Co\\Coroutine\\Curl\\Exception", nullptr, swoole_exception); - - g_curl_multi = new cURLMulti(); } /* CurlHandle class */ @@ -572,8 +425,6 @@ int curl_cast_object(zend_object *obj, zval *result, int type) { #endif void swoole_native_curl_mshutdown() { - delete g_curl_multi; - g_curl_multi = nullptr; } /* {{{ curl_write_nothing @@ -1089,7 +940,6 @@ static void _php_curl_set_default_options(php_curl *ch) { curl_easy_setopt(ch->cp, CURLOPT_INFILE, (void *) ch); curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, fn_write_header); curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch); - curl_easy_setopt(ch->cp, CURLOPT_PRIVATE, ch); #if !defined(ZTS) curl_easy_setopt(ch->cp, CURLOPT_DNS_USE_GLOBAL_CACHE, 1); @@ -2428,7 +2278,8 @@ PHP_FUNCTION(swoole_native_curl_exec) { _php_curl_cleanup_handle(ch); - error = sw_curl_multi()->exec(ch); + Multi multi{}; + error = multi.exec(ch); SAVE_CURL_ERROR(ch, error); if (error != CURLE_OK) { diff --git a/thirdparty/php/curl/multi.cc b/thirdparty/php/curl/multi.cc index eeeb3449b71..8a120a6dab2 100644 --- a/thirdparty/php/curl/multi.cc +++ b/thirdparty/php/curl/multi.cc @@ -17,9 +17,10 @@ #include "php_swoole_cxx.h" #ifdef SW_USE_CURL -#include "curl_multi.h" +#include "php_swoole_curl.h" -using namespace swoole; +using swoole::curl::Multi; +using swoole::curl::Selector; SW_EXTERN_C_BEGIN #include "curl_interface.h" @@ -74,8 +75,8 @@ PHP_FUNCTION(swoole_native_curl_multi_init) { mh = (php_curlm *) ecalloc(1, sizeof(php_curlm)); RETVAL_RES(zend_register_resource(mh, _php_curl_get_le_curl_multi())); #endif - mh->multi = new cURLMulti(); - mh->multi->set_selector(new MultiSelector()); + mh->multi = new Multi(); + mh->multi->set_selector(new Selector()); mh->handlers = (php_curlm_handlers *) ecalloc(1, sizeof(php_curlm_handlers)); zend_llist_init(&mh->easyh, sizeof(zval), _php_curl_multi_cleanup_list, 0); } @@ -109,7 +110,7 @@ PHP_FUNCTION(swoole_native_curl_multi_add_handle) { Z_ADDREF_P(z_ch); zend_llist_add_element(&mh->easyh, z_ch); - error = curl_multi_add_handle(mh->multi->get_multi_handle(), ch->cp); + error = mh->multi->add_handle(ch->cp); SAVE_CURLM_ERROR(mh, error); RETURN_LONG((zend_long) error); @@ -172,7 +173,7 @@ PHP_FUNCTION(swoole_native_curl_multi_remove_handle) { mh = Z_CURL_MULTI_P(z_mh); ch = Z_CURL_P(z_ch); - error = curl_multi_remove_handle(mh->multi->get_multi_handle(), ch->cp); + error = mh->multi->remove_handle(ch->cp); SAVE_CURLM_ERROR(mh, error); RETVAL_LONG((zend_long) error); @@ -354,7 +355,7 @@ PHP_FUNCTION(swoole_native_curl_multi_close) { pz_ch = (zval *) zend_llist_get_next_ex(&mh->easyh, &pos)) { php_curl *ch = Z_CURL_P(pz_ch); _php_curl_verify_handlers(ch, 1); - curl_multi_remove_handle(mh->multi->get_multi_handle(), ch->cp); + mh->multi->remove_handle(ch->cp); } zend_llist_clean(&mh->easyh); } @@ -639,17 +640,11 @@ static zend_function *curl_multi_get_constructor(zend_object *object) { void curl_multi_free_obj(zend_object *object) { php_curlm *mh = (php_curlm *) curl_multi_from_obj(object); - - zend_llist_position pos; - php_curl *ch; - zval *pz_ch; - if (!mh->multi) { /* Can happen if constructor throws. */ zend_object_std_dtor(&mh->std); return; } - _php_curl_multi_free(mh); zend_object_std_dtor(&mh->std); } @@ -705,21 +700,15 @@ void _php_curl_multi_close(zend_resource *rsrc) /* {{{ */ /* }}} */ #endif -void _php_curl_multi_free(php_curlm *mh) { - zend_llist_position pos; - php_curl *ch; - zval *pz_ch; - - for (pz_ch = (zval *) zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch; - pz_ch = (zval *) zend_llist_get_next_ex(&mh->easyh, &pos)) { - /* ptr is NULL means it already be freed */ - if (Z_RES_P(pz_ch)->ptr) { - if ((ch = _php_curl_get_handle(pz_ch, false))) { - _php_curl_verify_handlers(ch, 0); - } +static void _php_curl_multi_free(php_curlm *mh) { + for (zend_llist_element *element = mh->easyh.head; element; element = element->next) { + zval *z_ch = (zval *) element->data; + php_curl *ch; + if ((ch = _php_curl_get_handle(z_ch, false))) { + _php_curl_verify_handlers(ch, 0); + mh->multi->remove_handle(ch->cp); } } - curl_multi_cleanup(mh->multi->get_multi_handle()); zend_llist_clean(&mh->easyh); if (mh->handlers->server_push) { From fe180dff2bc4b7afc01c1c319f6777c699ed34fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Tue, 23 Mar 2021 15:56:44 +0800 Subject: [PATCH 089/936] fix heartbeat detection of SSL connection does not take effect when handshake is not completed (#4114) --- src/server/reactor_thread.cc | 12 +++++- tests/swoole_server/ssl/heartbeat_1.phpt | 48 +++++++++++++++++++++++ tests/swoole_server/ssl/heartbeat_2.phpt | 49 ++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 tests/swoole_server/ssl/heartbeat_1.phpt create mode 100644 tests/swoole_server/ssl/heartbeat_2.phpt diff --git a/src/server/reactor_thread.cc b/src/server/reactor_thread.cc index 3a334b4aa62..9f92d4b9e49 100644 --- a/src/server/reactor_thread.cc +++ b/src/server/reactor_thread.cc @@ -411,7 +411,7 @@ static int ReactorThread_onPipeRead(Reactor *reactor, Event *ev) { ReactorThread_shutdown(reactor); } else if (resp->info.type == SW_SERVER_EVENT_CLOSE_FORCE) { SessionId session_id = resp->info.fd; - Connection *conn = serv->get_connection_verify(session_id); + Connection *conn = serv->get_connection_verify_no_ssl(session_id); if (!conn) { swoole_error_log(SW_LOG_NOTICE, @@ -425,6 +425,16 @@ static int ReactorThread_onPipeRead(Reactor *reactor, Event *ev) { return Server::close_connection(reactor, conn->socket); } +#ifdef SW_USE_OPENSSL + /** + * SSL connections that have not completed the handshake, + * do not need to notify the workers, just close + */ + if (conn->ssl && !conn->ssl_ready) { + return Server::close_connection(reactor, conn->socket); + } +#endif + conn->close_force = 1; Event _ev = {}; _ev.fd = conn->fd; diff --git a/tests/swoole_server/ssl/heartbeat_1.phpt b/tests/swoole_server/ssl/heartbeat_1.phpt new file mode 100644 index 00000000000..b4479e81973 --- /dev/null +++ b/tests/swoole_server/ssl/heartbeat_1.phpt @@ -0,0 +1,48 @@ +--TEST-- +swoole_server: heartbeat with bad client +--SKIPIF-- + +--FILE-- +parentFunc = function ($pid) use ($pm) { + $client = new Client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC); + if (!$client->connect('127.0.0.1', $pm->getFreePort(), 5, 0)) { + echo "Over flow. errno=" . $client->errCode; + die("\n"); + } + $s1 = time(); + Assert::same($client->recv(), ''); + $s2 = time(); + Assert::assert($s2 - $s1 > 1); + swoole_process::kill($pid); +}; + +$pm->childFunc = function () use ($pm) { + $serv = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL); + $serv->set(array( + 'heartbeat_check_interval' => 1, + 'log_file' => '/dev/null', + 'heartbeat_idle_time' => 1, + 'ssl_cert_file' => __DIR__ . '/../../include/api/ssl-ca/server-cert.pem', + 'ssl_key_file' => __DIR__ . '/../../include/api/ssl-ca/server-key.pem', + )); + $serv->on("workerStart", function ($serv) use ($pm) { + $pm->wakeup(); + }); + $serv->on('receive', function (Server $serv, $fd, $rid, $data) { + }); + $serv->start(); +}; + +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- diff --git a/tests/swoole_server/ssl/heartbeat_2.phpt b/tests/swoole_server/ssl/heartbeat_2.phpt new file mode 100644 index 00000000000..3503f201834 --- /dev/null +++ b/tests/swoole_server/ssl/heartbeat_2.phpt @@ -0,0 +1,49 @@ +--TEST-- +swoole_server: heartbeat normal +--SKIPIF-- + +--FILE-- +parentFunc = function ($pid) use ($pm) { + $client = new Client(SWOOLE_SOCK_TCP | SWOOLE_SSL, SWOOLE_SOCK_SYNC); + if (!$client->connect('127.0.0.1', $pm->getFreePort(), 5, 0)) { + echo "Over flow. errno=" . $client->errCode; + die("\n"); + } + $s1 = microtime(true); + Assert::same($client->recv(), ''); + $s2 = microtime(true); + Assert::assert($s2 - $s1 > 1); + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm) { + $serv = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL); + $serv->set(array( + 'heartbeat_check_interval' => 1, + 'log_file' => '/dev/null', + 'heartbeat_idle_time' => 1, + 'ssl_cert_file' => __DIR__ . '/../../include/api/ssl-ca/server-cert.pem', + 'ssl_key_file' => __DIR__ . '/../../include/api/ssl-ca/server-key.pem', + )); + $serv->on("workerStart", function ($serv) use ($pm) { + $pm->wakeup(); + }); + $serv->on('receive', function (Server $serv, $fd, $rid, $data) { + }); + $serv->start(); +}; + +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- From 980c8030b4420ad7281d8d1e201facdf64c01e2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Wed, 24 Mar 2021 11:45:35 +0800 Subject: [PATCH 090/936] add guzzle tests, defense (#4115) --- .gitignore | 1 + ext-src/php_swoole_curl.h | 3 +- ext-src/swoole_curl.cc | 27 +- tests/include/config.php | 1 + tests/include/lib/composer.json | 18 + tests/include/lib/composer.lock | 437 +++++++++++++++++++ tests/include/lib/vendor/autoload.php | 11 - tests/swoole_runtime/curl_native/guzzle.phpt | 67 +++ travis/docker-route.sh | 4 +- travis/run-tests.sh | 3 + 10 files changed, 545 insertions(+), 27 deletions(-) create mode 100644 tests/include/lib/composer.json create mode 100644 tests/include/lib/composer.lock delete mode 100755 tests/include/lib/vendor/autoload.php create mode 100644 tests/swoole_runtime/curl_native/guzzle.phpt diff --git a/.gitignore b/.gitignore index ead1c55768a..323ed6fe3f0 100644 --- a/.gitignore +++ b/.gitignore @@ -105,3 +105,4 @@ core-tests/samples/CMakeFiles/ *.gcda *.info /html +/tests/include/lib/vendor/ diff --git a/ext-src/php_swoole_curl.h b/ext-src/php_swoole_curl.h index eebc6033767..59ca6af80a5 100644 --- a/ext-src/php_swoole_curl.h +++ b/ext-src/php_swoole_curl.h @@ -39,7 +39,8 @@ struct Handle { CURL *cp; Socket *socket; Multi *multi; - int bitmask; + int event_bitmask; + int event_fd; int action; bool removed; }; diff --git a/ext-src/swoole_curl.cc b/ext-src/swoole_curl.cc index 5bce8a914f3..69787bc5b8e 100644 --- a/ext-src/swoole_curl.cc +++ b/ext-src/swoole_curl.cc @@ -21,22 +21,24 @@ namespace swoole { namespace curl { -int Multi::cb_readable(Reactor *reactor, Event *event) { +static int execute_callback(Event *event, int bitmask) { Handle *handle = (Handle *) event->socket->object; - handle->multi->callback(handle, CURL_CSELECT_IN); + handle->event_bitmask = bitmask; + handle->event_fd = event->fd; + handle->multi->callback(handle, bitmask); return 0; } +int Multi::cb_readable(Reactor *reactor, Event *event) { + return execute_callback(event, CURL_CSELECT_IN); +} + int Multi::cb_writable(Reactor *reactor, Event *event) { - Handle *handle = (Handle *) event->socket->object; - handle->multi->callback(handle, CURL_CSELECT_OUT); - return 0; + return execute_callback(event, CURL_CSELECT_OUT); } int Multi::cb_error(Reactor *reactor, Event *event) { - Handle *handle = (Handle *) event->socket->object; - handle->multi->callback(handle, CURL_CSELECT_ERR); - return 0; + return execute_callback(event, CURL_CSELECT_ERR); } int Multi::handle_socket(CURL *easy, curl_socket_t s, int action, void *userp, void *socketp) { @@ -134,7 +136,7 @@ CURLcode Multi::exec(php_curl *ch) { int sockfd = last_sockfd; int bitmask = 0; if (sockfd >= 0) { - bitmask = handle->bitmask; + bitmask = handle->event_bitmask; swoole_event_del(handle->socket); handle->removed = true; } @@ -233,8 +235,8 @@ long Multi::select(php_curlm *mh) { int bitmask = 0; int sockfd = -1; if (handle) { - bitmask = handle->bitmask; - sockfd = handle->socket->fd; + bitmask = handle->event_bitmask; + sockfd = handle->event_fd; } curl_multi_socket_action(multi_handle_, sockfd, bitmask, &running_handles_); swTraceLog(SW_TRACE_CO_CURL, "socket_action, running_handles=%d", running_handles_); @@ -246,8 +248,7 @@ long Multi::select(php_curlm *mh) { void Multi::callback(Handle *handle, int event_bitmask) { if (handle) { - last_sockfd = handle->socket->fd; - handle->bitmask = event_bitmask; + last_sockfd = handle->event_fd; } else { last_sockfd = -1; } diff --git a/tests/include/config.php b/tests/include/config.php index b0d97b0b3fb..6e7058ee829 100644 --- a/tests/include/config.php +++ b/tests/include/config.php @@ -23,6 +23,7 @@ define('SOURCE_ROOT_PATH', __DIR__ . '/../../'); define('TESTS_ROOT_PATH', __DIR__ . '/../'); define('TESTS_API_PATH', TESTS_ROOT_PATH.'/include/api'); +define('TESTS_LIB_PATH', TESTS_ROOT_PATH.'/include/lib'); define('TRAVIS_DIR_PATH', __DIR__ . '/../../travis/'); define('TEST_IMAGE', __DIR__ . '/../../examples/test.jpg'); define('TEST_LINK_IMAGE', __DIR__ . '/../../examples/test_link.jpg'); diff --git a/tests/include/lib/composer.json b/tests/include/lib/composer.json new file mode 100644 index 00000000000..47c8add6c31 --- /dev/null +++ b/tests/include/lib/composer.json @@ -0,0 +1,18 @@ +{ + "name": "swoole_tests/lib", + "description": "for swoole tests", + "authors": [ + { + "name": "tianfeng.han", + "email": "rango@swoole.com" + } + ], + "autoload": { + "psr-4": { + "SwooleTest\\": "src" + } + }, + "require": { + "guzzlehttp/guzzle": "^7.3" + } +} diff --git a/tests/include/lib/composer.lock b/tests/include/lib/composer.lock new file mode 100644 index 00000000000..8e0e42d7ff8 --- /dev/null +++ b/tests/include/lib/composer.lock @@ -0,0 +1,437 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "0a9d23d195d548959fddf890a013c0cb", + "packages": [ + { + "name": "guzzlehttp/guzzle", + "version": "7.3.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "7008573787b430c1c1f650e3722d9bba59967628" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7008573787b430c1c1f650e3722d9bba59967628", + "reference": "7008573787b430c1c1f650e3722d9bba59967628", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.4", + "guzzlehttp/psr7": "^1.7 || ^2.0", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "ext-curl": "*", + "php-http/client-integration-tests": "^3.0", + "phpunit/phpunit": "^8.5.5 || ^9.3.5", + "psr/log": "^1.1" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.3-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.3.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://github.com/alexeyshockov", + "type": "github" + }, + { + "url": "https://github.com/gmponos", + "type": "github" + } + ], + "time": "2021-03-23T11:33:13+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/8e7d04f1f6450fef59366c399cfad4b9383aa30d", + "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "symfony/phpunit-bridge": "^4.4 || ^5.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/1.4.1" + }, + "time": "2021-03-07T09:25:29+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.8.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "35ea11d335fd638b5882ff1725228b3d35496ab1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/35ea11d335fd638b5882ff1725228b3d35496ab1", + "reference": "35ea11d335fd638b5882ff1725228b3d35496ab1", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0", + "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "ext-zlib": "*", + "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/1.8.1" + }, + "time": "2021-03-21T16:25:00+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/master" + }, + "time": "2020-06-29T06:28:15+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.0.0" +} diff --git a/tests/include/lib/vendor/autoload.php b/tests/include/lib/vendor/autoload.php deleted file mode 100755 index e5526feda7b..00000000000 --- a/tests/include/lib/vendor/autoload.php +++ /dev/null @@ -1,11 +0,0 @@ - +--FILE-- + $client->getAsync('http://www.baidu.com/'), + 'qq' => $client->getAsync('https://www.qq.com/'), + 'gov' => $client->getAsync('http://www.gov.cn/') + ]; + $responses = Promise\Utils::unwrap($promises); + Assert::contains($responses['baidu']->getBody(), '百度'); + Assert::contains(iconv('gbk', 'utf-8', $responses['qq']->getBody()), '腾讯'); + Assert::contains($responses['gov']->getBody(), '中华人民共和国'); + $result['task_1'] = 'OK'; + }); + + go(function () use ($barrier, &$result) { + $client = new Client(['base_uri' => 'http://httpbin.org/']); + $n = N; + $data = $promises = []; + while ($n--) { + $key = 'req_' . $n; + $data[$key] = uniqid('swoole_test'); + $promises[$key] = $client->getAsync('/base64/' . base64_encode($data[$key])); + } + $responses = Promise\Utils::unwrap($promises); + + $n = N; + while ($n--) { + $key = 'req_' . $n; + Assert::eq($responses[$key]->getBody(), $data[$key]); + } + $result['task_2'] = 'OK'; + }); + + Barrier::wait($barrier); + Assert::eq($result['task_1'], 'OK'); + Assert::eq($result['task_2'], 'OK'); + echo 'Done' . PHP_EOL; +}); +?> +--EXPECT-- +Done diff --git a/travis/docker-route.sh b/travis/docker-route.sh index f89165123d9..80b890b8893 100755 --- a/travis/docker-route.sh +++ b/travis/docker-route.sh @@ -1,9 +1,9 @@ #!/bin/sh -e -__CURRENT__=`pwd` +__CURRENT__=$(pwd) __DIR__=$(cd "$(dirname "$0")";pwd) # enter the dir -cd ${__DIR__} +cd "${__DIR__}" # show system info date && echo "" diff --git a/travis/run-tests.sh b/travis/run-tests.sh index 96bc9f2034e..6ae34be8ba8 100755 --- a/travis/run-tests.sh +++ b/travis/run-tests.sh @@ -10,6 +10,9 @@ cd ${__DIR__} && cd ../tests/ # initialization echo "" && echo "⭐️ Initialization for tests..." && echo "" ./init +cd ./include/lib +composer update +cd - echo "" # debug From a762d243d34d61a5b7e2751409d811b5a14b63cd Mon Sep 17 00:00:00 2001 From: matyhtf Date: Wed, 24 Mar 2021 20:21:59 +0800 Subject: [PATCH 091/936] fix typo --- src/lock/mutex.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lock/mutex.cc b/src/lock/mutex.cc index 8db6168f54c..32c4448013a 100644 --- a/src/lock/mutex.cc +++ b/src/lock/mutex.cc @@ -40,7 +40,7 @@ Mutex::Mutex(int flags) : Lock() { pthread_mutexattr_init(&impl->attr_); if (flags & PROCESS_SHARED) { -#ifdef HAVE_PTHREAD_MUTEXATTR_SETROBUST +#ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED pthread_mutexattr_setpshared(&impl->attr_, PTHREAD_PROCESS_SHARED); #else swWarn("PTHREAD_MUTEX_PSHARED is not supported"); From 7d325e8d21c19afed068cfec6a33aa7c3bcf6620 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Sun, 28 Mar 2021 09:44:57 +0800 Subject: [PATCH 092/936] optimize code --- src/server/worker.cc | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/server/worker.cc b/src/server/worker.cc index 5c13b9d7b72..5c358500beb 100644 --- a/src/server/worker.cc +++ b/src/server/worker.cc @@ -63,32 +63,28 @@ void Server::worker_signal_handler(int signo) { } switch (signo) { case SIGTERM: - /** - * Event worker - */ - if (SwooleTG.reactor) { + // Event worker + if (swoole_event_is_available()) { sw_server()->stop_async_worker(SwooleWG.worker); } - /** - * Task worker - */ + // Task worker else { SwooleWG.shutdown = true; } break; - /** - * for test - */ + // for test case SIGVTALRM: swWarn("SIGVTALRM coming"); break; case SIGUSR1: case SIGUSR2: - sw_logger()->reopen(); + if (sw_logger()) { + sw_logger()->reopen(); + } break; default: #ifdef SIGRTMIN - if (signo == SIGRTMIN) { + if (signo == SIGRTMIN && sw_logger()) { sw_logger()->reopen(); } #endif @@ -630,32 +626,36 @@ static int Worker_onPipeReceive(Reactor *reactor, Event *event) { void *buffer; struct iovec buffers[2]; int recv_chunk_count = 0; + DataHead *info = &pipe_buffer->info; _read_from_pipe: - recv_n = recv(event->fd, &pipe_buffer->info, sizeof(pipe_buffer->info), MSG_PEEK); + recv_n = recv(event->fd, info, sizeof(pipe_buffer->info), MSG_PEEK); if (recv_n < 0) { - if (errno == EAGAIN) { + if (event->socket->catch_error(errno) == SW_WAIT) { return SW_OK; } return SW_ERR; } if (pipe_buffer->info.flags & SW_EVENT_DATA_CHUNK) { - buffer = serv->get_buffer(serv, &pipe_buffer->info); - size_t remain_len = pipe_buffer->info.len - serv->get_buffer_len(serv, &pipe_buffer->info); + buffer = serv->get_buffer(serv, info); + size_t remain_len = pipe_buffer->info.len - serv->get_buffer_len(serv, info); - buffers[0].iov_base = &pipe_buffer->info; + buffers[0].iov_base = info; buffers[0].iov_len = sizeof(pipe_buffer->info); buffers[1].iov_base = buffer; buffers[1].iov_len = SW_MIN(serv->ipc_max_size - sizeof(pipe_buffer->info), remain_len); recv_n = readv(event->fd, buffers, 2); - assert(recv_n != 0); - if (recv_n < 0 && errno == EAGAIN) { + if (recv_n == 0) { + swWarn("abnormal pipeline data, pipe_fd=%d, reactor_id=%d", event->fd, info->reactor_id); + return SW_ERR; + } + if (recv_n < 0 && event->socket->catch_error(errno) == SW_WAIT) { return SW_OK; } if (recv_n > 0) { - serv->add_buffer_len(serv, &pipe_buffer->info, recv_n - sizeof(pipe_buffer->info)); + serv->add_buffer_len(serv, info, recv_n - sizeof(pipe_buffer->info)); } recv_chunk_count++; From ab994a022f45049827c2bc26b18b23bf5a3cee0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Sun, 28 Mar 2021 18:36:13 +0800 Subject: [PATCH 093/936] Optimize code 20210328 (#4123) * optimize code * optimize --- include/swoole.h | 1 + include/swoole_server.h | 42 +++++-------------------- src/server/base.cc | 2 +- src/server/master.cc | 60 ++++++++++++++++++++---------------- src/server/reactor_thread.cc | 2 +- 5 files changed, 45 insertions(+), 62 deletions(-) diff --git a/include/swoole.h b/include/swoole.h index 62669261fba..143d656f280 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -571,6 +571,7 @@ struct Event { typedef long SessionId; typedef long TaskId; +typedef uint8_t ReactorId; struct DataHead { SessionId fd; diff --git a/include/swoole_server.h b/include/swoole_server.h index aa867591d9c..4d67da02094 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -90,31 +90,21 @@ struct Session { struct Connection { /** - * file descript + * It must be in the header. When set to 0, it means that connection does not exist. + * One-write and multiple-read operation is thread-safe + * system fd must be 0. en: signalfd, listen socket */ + uint8_t active; + enum swSocket_type socket_type; int fd; - /** - * session id - */ SessionId session_id; - /** - * socket type, SW_SOCK_TCP or SW_SOCK_UDP - */ - enum swSocket_type socket_type; //-------------------------------------------------------------- - /** - * is active - * system fd must be 0. en: signalfd, listen socket - */ - uint8_t active; #ifdef SW_USE_OPENSSL uint8_t ssl; uint8_t ssl_ready; #endif - //-------------------------------------------------------------- uint8_t overflow; uint8_t high_watermark; - //-------------------------------------------------------------- uint8_t http_upgrade; #ifdef SW_USE_HTTP2 uint8_t http2_stream; @@ -122,35 +112,19 @@ struct Connection { #ifdef SW_HAVE_ZLIB uint8_t websocket_compression; #endif - //-------------------------------------------------------------- - /** - * server is actively close the connection - */ + // If it is equal to 1, it means server actively closed the connection uint8_t close_actively; uint8_t closed; uint8_t close_queued; uint8_t closing; uint8_t close_reset; uint8_t peer_closed; - /** - * protected connection, do not close connection when receiving/sending timeout - */ + // protected connection, do not close connection when receiving/sending timeout uint8_t protect; - //-------------------------------------------------------------- uint8_t close_notify; uint8_t close_force; - //-------------------------------------------------------------- - /** - * ReactorThread id - */ - uint16_t reactor_id; - /** - * close error code - */ + ReactorId reactor_id; uint16_t close_errno; - /** - * from which socket fd - */ int server_fd; sw_atomic_t recv_queued_bytes; uint32_t send_queued_bytes; diff --git a/src/server/base.cc b/src/server/base.cc index 34f39ab347e..aeeb01e9e12 100644 --- a/src/server/base.cc +++ b/src/server/base.cc @@ -113,7 +113,7 @@ bool BaseFactory::end(SessionId session_id, int flags) { } Connection *conn = server_->get_connection_verify_no_ssl(session_id); - if (conn == nullptr || conn->active == 0) { + if (conn == nullptr) { swoole_set_last_error(SW_ERROR_SESSION_NOT_EXIST); return false; } diff --git a/src/server/master.cc b/src/server/master.cc index 663fa4d1a90..600fa5dd2d6 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -166,7 +166,7 @@ int Server::accept_connection(Reactor *reactor, Event *event) { ev.type = SW_SERVER_EVENT_INCOMING; ev.fd = conn->session_id; ev.reactor_id = conn->reactor_id; - if (serv->send_to_reactor_thread((EventData*) &ev, sizeof(ev), conn->session_id) < 0) { + if (serv->send_to_reactor_thread((EventData *) &ev, sizeof(ev), conn->session_id) < 0) { reactor->close(reactor, sock); return SW_OK; } @@ -908,7 +908,7 @@ bool Server::feedback(Connection *conn, enum ServerEventType event) { _send.info.reactor_id = conn->reactor_id; if (is_process_mode()) { - return send_to_reactor_thread((EventData*) &_send.info, sizeof(_send.info), conn->session_id) > 0; + return send_to_reactor_thread((EventData *) &_send.info, sizeof(_send.info), conn->session_id) > 0; } else { return send_to_connection(&_send) == SW_OK; } @@ -936,7 +936,7 @@ bool Server::send(SessionId session_id, const void *data, uint32_t length) { SendData _send{}; _send.info.fd = session_id; _send.info.type = SW_SERVER_EVENT_RECV_DATA; - _send.data = (char*) data; + _send.data = (char *) data; _send.info.len = length; return factory->finish(&_send); } @@ -973,11 +973,11 @@ int Server::schedule_worker(int fd, SendData *data) { // IPv6 else { #ifdef HAVE_KQUEUE - key = *(((uint32_t*) &conn->info.addr.inet_v6.sin6_addr) + 3); + key = *(((uint32_t *) &conn->info.addr.inet_v6.sin6_addr) + 3); #elif defined(_WIN32) - key = conn->info.addr.inet_v6.sin6_addr.u.Word[3]; + key = conn->info.addr.inet_v6.sin6_addr.u.Word[3]; #else - key = conn->info.addr.inet_v6.sin6_addr.s6_addr32[3]; + key = conn->info.addr.inet_v6.sin6_addr.s6_addr32[3]; #endif } } else if (dispatch_mode == SW_DISPATCH_UIDMOD) { @@ -1001,7 +1001,8 @@ int Server::schedule_worker(int fd, SendData *data) { } if (sw_unlikely(!found)) { scheduler_warning = true; - } swTraceLog(SW_TRACE_SERVER, "schedule=%d, round=%d", key, worker_round_id); + } + swTraceLog(SW_TRACE_SERVER, "schedule=%d, round=%d", key, worker_round_id); return key; } return key % worker_num; @@ -1335,7 +1336,7 @@ void Server::call_hook(HookType type, void *arg) { * [Worker] */ bool Server::close(SessionId session_id, bool reset) { - return factory->end(session_id, reset ? CLOSE_ACTIVELY | CLOSE_RESET: CLOSE_ACTIVELY); + return factory->end(session_id, reset ? CLOSE_ACTIVELY | CLOSE_RESET : CLOSE_ACTIVELY); } void Server::init_signal_handler() { @@ -1638,7 +1639,31 @@ Connection *Server::add_connection(ListenPort *ls, Socket *_socket, int server_f unlock(); Connection *connection = &(connection_list[fd]); + ReactorId reactor_id = is_base_mode() ? SwooleG.process_id : fd % reactor_num; *connection = {}; + + sw_spinlock(&gs->spinlock); + SessionId session_id = gs->session_round; + // get session id + SW_LOOP_N(max_connection) { + Session *session = get_session(++session_id); + // available slot + if (session->fd == 0) { + session->fd = fd; + session->id = session_id; + session->reactor_id = reactor_id; + goto _find_available_slot; + } + } + sw_spinlock_release(&gs->spinlock); + swoole_error_log(SW_LOG_WARNING, SW_ERROR_SERVER_TOO_MANY_SOCKET, "no available session slot, fd=%d", fd); + return nullptr; + +_find_available_slot: + sw_spinlock_release(&gs->spinlock); + gs->session_round = session_id; + connection->session_id = session_id; + _socket->object = connection; _socket->removed = 1; _socket->buffer_size = ls->socket_buffer_size; @@ -1667,7 +1692,7 @@ Connection *Server::add_connection(ListenPort *ls, Socket *_socket, int server_f } connection->fd = fd; - connection->reactor_id = is_base_mode() ? SwooleG.process_id : fd % reactor_num; + connection->reactor_id = reactor_id; connection->server_fd = (sw_atomic_t) server_fd; connection->last_recv_time = connection->connect_time = microtime(); connection->active = 1; @@ -1682,23 +1707,6 @@ Connection *Server::add_connection(ListenPort *ls, Socket *_socket, int server_f _socket->direct_send = 1; } - sw_spinlock(&gs->spinlock); - SessionId session_id = gs->session_round; - // get session id - SW_LOOP_N(max_connection) { - Session *session = get_session(++session_id); - // available slot - if (session->fd == 0) { - session->fd = fd; - session->id = session_id; - session->reactor_id = connection->reactor_id; - break; - } - } - gs->session_round = session_id; - sw_spinlock_release(&gs->spinlock); - connection->session_id = session_id; - return connection; } diff --git a/src/server/reactor_thread.cc b/src/server/reactor_thread.cc index 9f92d4b9e49..7190ed98aed 100644 --- a/src/server/reactor_thread.cc +++ b/src/server/reactor_thread.cc @@ -480,7 +480,7 @@ static int ReactorThread_onPipeWrite(Reactor *reactor, Event *ev) { BufferChunk *chunk = buffer->front(); EventData *send_data = (EventData *) chunk->value.ptr; - // server active close, discard data. + // server actively closed connection, should discard the data if (Server::is_stream_event(send_data->info.type)) { // send_data->info.fd is session_id Connection *conn = serv->get_connection_verify(send_data->info.fd); From 1562c2ccce4c7815da67955b3a7b3a49293ad203 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Fri, 2 Apr 2021 04:07:47 +0100 Subject: [PATCH 094/936] make context darwin arm64: removes workaround and uses the label (#4127) directly. LLVM support those since quite some years now. --- thirdparty/boost/asm/make_arm64_aapcs_macho_gas.S | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/thirdparty/boost/asm/make_arm64_aapcs_macho_gas.S b/thirdparty/boost/asm/make_arm64_aapcs_macho_gas.S index 6b55a08adfc..cd8b9742358 100644 --- a/thirdparty/boost/asm/make_arm64_aapcs_macho_gas.S +++ b/thirdparty/boost/asm/make_arm64_aapcs_macho_gas.S @@ -64,9 +64,7 @@ _make_fcontext: ; compute abs address of label finish ; 0x0c = 3 instructions * size (4) before label 'finish' - ; TODO: Numeric offset since llvm still does not support labels in ADR. Fix: - ; http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20140407/212336.html - adr x1, 0x0c + adr x1, finish ; save address of finish as return-address for context-function ; will be entered after context-function returns (LR register) From 2197e5770b8737975e45a8255e455bc43a879370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Fri, 2 Apr 2021 21:19:09 +0800 Subject: [PATCH 095/936] Add curl-multi tests (#4121) * Add guzzle cancel tests * defense * Add send_async test * fix tests, optimize code * Add requestAsync test * Add test * update proc_open * optimize * fix tests * fix * fix 2 * fix tests * fix tests[2] * add constant * fix tests[3] * fix tests[4] * fix tests[5] * migrate * migrate [2] * fix tests, add curl info * fix * remove zend::include, that is useless code * add curl info * fix tests * revert test * Use native curl by default * fix tests * fix tests * fix tests * fix tests * fix tests * fix tests Co-authored-by: sy-records <52o@qq52o.cn> --- ext-src/php_swoole.cc | 1 + ext-src/php_swoole_curl.h | 26 +- ext-src/php_swoole_cxx.cc | 36 --- ext-src/php_swoole_cxx.h | 1 - ext-src/swoole_curl.cc | 48 ++- ext-src/swoole_runtime.cc | 4 + tests/include/functions.php | 11 +- tests/include/lib/src/CurlManager.php | 12 +- tests/include/lib/src/responder/get.php | 2 +- tests/swoole_client_coro/sendto.phpt | 3 +- tests/swoole_client_sync/sendto.phpt | 5 +- .../curl => swoole_curl}/basic/1.phpt | 4 +- .../curl => swoole_curl}/basic/10.phpt | 4 +- .../curl => swoole_curl}/basic/11.phpt | 4 +- .../curl => swoole_curl}/basic/12.phpt | 5 +- .../curl => swoole_curl}/basic/13.phpt | 4 +- .../curl => swoole_curl}/basic/14.phpt | 5 +- .../curl => swoole_curl}/basic/15.phpt | 4 +- .../curl => swoole_curl}/basic/19.phpt | 4 +- .../curl => swoole_curl}/basic/2.phpt | 4 +- .../curl => swoole_curl}/basic/20.phpt | 4 +- .../curl => swoole_curl}/basic/21.phpt | 4 +- .../curl => swoole_curl}/basic/22.phpt | 4 +- .../curl => swoole_curl}/basic/23.phpt | 4 +- .../curl => swoole_curl}/basic/24.phpt | 5 +- .../curl => swoole_curl}/basic/25.phpt | 4 +- .../curl => swoole_curl}/basic/3.phpt | 4 +- .../curl => swoole_curl}/basic/4.phpt | 4 +- .../curl => swoole_curl}/basic/5.phpt | 4 +- .../curl => swoole_curl}/basic/7.phpt | 6 +- .../curl => swoole_curl}/basic/8.phpt | 4 +- .../curl => swoole_curl}/basic/9.phpt | 5 +- .../close_before_resume.phpt | 4 +- .../concurrent.phpt | 4 +- .../curl_native => swoole_curl}/error.phpt | 4 +- .../exec_twice.phpt | 4 +- .../curl_native => swoole_curl}/guzzle.phpt | 4 +- tests/swoole_curl/guzzle/cancel.phpt | 36 +++ .../guzzle/cannot_cancel_finished.phpt | 31 ++ tests/swoole_curl/guzzle/cookie.phpt | 38 +++ tests/swoole_curl/guzzle/request_async.phpt | 39 +++ .../swoole_curl/guzzle/request_on_stats.phpt | 43 +++ tests/swoole_curl/guzzle/send_async.phpt | 41 +++ .../curl_native => swoole_curl}/https.phpt | 4 +- tests/swoole_curl/multi/bug48203_multi.phpt | 95 ++++++ tests/swoole_curl/multi/bug67643.phpt | 38 +++ tests/swoole_curl/multi/bug71523.phpt | 34 +++ tests/swoole_curl/multi/bug76675.phpt | 67 +++++ tests/swoole_curl/multi/bug77535.phpt | 94 ++++++ tests/swoole_curl/multi/bug77946.phpt | 51 ++++ tests/swoole_curl/multi/curl_basic_018.phpt | 66 +++++ .../multi/curl_copy_handle_variation4.phpt | 48 +++ tests/swoole_curl/multi/curl_int_cast.phpt | 31 ++ .../multi/curl_multi_close_basic.phpt | 24 ++ .../multi/curl_multi_close_basic001.phpt | 24 ++ .../multi/curl_multi_close_reference.phpt | 27 ++ .../multi/curl_multi_errno_strerror_001.phpt | 40 +++ .../multi/curl_multi_getcontent_basic3.phpt | 62 ++++ .../multi/curl_multi_info_read.phpt | 43 +++ .../multi/curl_multi_init_basic.phpt | 30 ++ .../multi/curl_multi_segfault.phpt | 61 ++++ .../multi/curl_multi_select_basic1.phpt | 24 ++ .../multi/curl_multi_setopt_basic001.phpt | 32 ++ .../curl_native => swoole_curl}/multi_1.phpt | 4 +- .../curl_native => swoole_curl}/multi_2.phpt | 4 +- .../curl_native => swoole_curl}/multi_3.phpt | 4 +- .../curl_native => swoole_curl}/multi_4.phpt | 4 +- .../multi_close.phpt | 4 +- .../multi_dtor.phpt | 4 +- .../non_exclusive.phpt | 4 +- .../select_twice.phpt | 4 +- .../curl => swoole_curl}/setopt/1.phpt | 4 +- .../curl => swoole_curl}/setopt/3.phpt | 5 +- .../curl => swoole_curl}/setopt/4.phpt | 4 +- .../curl => swoole_curl}/setopt/5_skip.phpt | 4 +- .../setopt/filetime_1.phpt | 4 +- .../setopt/filetime_2.phpt | 4 +- .../setopt/header_out.phpt | 4 +- .../curl => swoole_curl}/setopt/infile.phpt | 4 +- .../curl => swoole_curl}/setopt/nobody.phpt | 4 +- .../curl_native => swoole_curl}/sleep.phpt | 4 +- .../curl => swoole_curl}/ssl/version.phpt | 4 +- .../curl => swoole_curl}/template | 2 +- .../timer_coredump.phpt | 4 +- .../curl => swoole_curl}/upload/1.phpt | 18 +- .../upload/curl_testdata1.txt | 0 .../upload/curl_testdata2.txt | 0 .../yield_in_callback.phpt | 4 +- thirdparty/php/curl/curl_arginfo.h | 10 +- thirdparty/php/curl/curl_interface.h | 1 + thirdparty/php/curl/curl_private.h | 6 +- thirdparty/php/curl/interface.cc | 120 +++----- thirdparty/php/curl/multi.cc | 42 ++- thirdparty/php/curl/php_curl.h | 6 +- thirdparty/php/standard/proc_open.cc | 278 +++++++++++++++--- thirdparty/php/standard/proc_open.h | 3 + travis/docker-compile.sh | 2 + travis/simple-compile-on-github.sh | 1 + 98 files changed, 1625 insertions(+), 331 deletions(-) rename tests/{swoole_library/curl => swoole_curl}/basic/1.phpt (88%) rename tests/{swoole_library/curl => swoole_curl}/basic/10.phpt (88%) rename tests/{swoole_library/curl => swoole_curl}/basic/11.phpt (89%) rename tests/{swoole_library/curl => swoole_curl}/basic/12.phpt (88%) rename tests/{swoole_library/curl => swoole_curl}/basic/13.phpt (89%) rename tests/{swoole_library/curl => swoole_curl}/basic/14.phpt (77%) rename tests/{swoole_library/curl => swoole_curl}/basic/15.phpt (81%) rename tests/{swoole_library/curl => swoole_curl}/basic/19.phpt (83%) rename tests/{swoole_library/curl => swoole_curl}/basic/2.phpt (88%) rename tests/{swoole_library/curl => swoole_curl}/basic/20.phpt (82%) rename tests/{swoole_library/curl => swoole_curl}/basic/21.phpt (82%) rename tests/{swoole_library/curl => swoole_curl}/basic/22.phpt (93%) rename tests/{swoole_library/curl => swoole_curl}/basic/23.phpt (87%) rename tests/{swoole_library/curl => swoole_curl}/basic/24.phpt (89%) rename tests/{swoole_library/curl => swoole_curl}/basic/25.phpt (92%) rename tests/{swoole_library/curl => swoole_curl}/basic/3.phpt (90%) rename tests/{swoole_library/curl => swoole_curl}/basic/4.phpt (90%) rename tests/{swoole_library/curl => swoole_curl}/basic/5.phpt (90%) rename tests/{swoole_library/curl => swoole_curl}/basic/7.phpt (79%) rename tests/{swoole_library/curl => swoole_curl}/basic/8.phpt (87%) rename tests/{swoole_library/curl => swoole_curl}/basic/9.phpt (82%) rename tests/{swoole_runtime/curl_native => swoole_curl}/close_before_resume.phpt (95%) rename tests/{swoole_runtime/curl_native => swoole_curl}/concurrent.phpt (95%) rename tests/{swoole_runtime/curl_native => swoole_curl}/error.phpt (89%) rename tests/{swoole_runtime/curl_native => swoole_curl}/exec_twice.phpt (95%) rename tests/{swoole_runtime/curl_native => swoole_curl}/guzzle.phpt (95%) create mode 100644 tests/swoole_curl/guzzle/cancel.phpt create mode 100644 tests/swoole_curl/guzzle/cannot_cancel_finished.phpt create mode 100644 tests/swoole_curl/guzzle/cookie.phpt create mode 100644 tests/swoole_curl/guzzle/request_async.phpt create mode 100644 tests/swoole_curl/guzzle/request_on_stats.phpt create mode 100644 tests/swoole_curl/guzzle/send_async.phpt rename tests/{swoole_runtime/curl_native => swoole_curl}/https.phpt (93%) create mode 100644 tests/swoole_curl/multi/bug48203_multi.phpt create mode 100644 tests/swoole_curl/multi/bug67643.phpt create mode 100644 tests/swoole_curl/multi/bug71523.phpt create mode 100644 tests/swoole_curl/multi/bug76675.phpt create mode 100644 tests/swoole_curl/multi/bug77535.phpt create mode 100644 tests/swoole_curl/multi/bug77946.phpt create mode 100644 tests/swoole_curl/multi/curl_basic_018.phpt create mode 100644 tests/swoole_curl/multi/curl_copy_handle_variation4.phpt create mode 100644 tests/swoole_curl/multi/curl_int_cast.phpt create mode 100644 tests/swoole_curl/multi/curl_multi_close_basic.phpt create mode 100644 tests/swoole_curl/multi/curl_multi_close_basic001.phpt create mode 100644 tests/swoole_curl/multi/curl_multi_close_reference.phpt create mode 100644 tests/swoole_curl/multi/curl_multi_errno_strerror_001.phpt create mode 100644 tests/swoole_curl/multi/curl_multi_getcontent_basic3.phpt create mode 100644 tests/swoole_curl/multi/curl_multi_info_read.phpt create mode 100644 tests/swoole_curl/multi/curl_multi_init_basic.phpt create mode 100644 tests/swoole_curl/multi/curl_multi_segfault.phpt create mode 100644 tests/swoole_curl/multi/curl_multi_select_basic1.phpt create mode 100644 tests/swoole_curl/multi/curl_multi_setopt_basic001.phpt rename tests/{swoole_runtime/curl_native => swoole_curl}/multi_1.phpt (77%) rename tests/{swoole_runtime/curl_native => swoole_curl}/multi_2.phpt (77%) rename tests/{swoole_runtime/curl_native => swoole_curl}/multi_3.phpt (81%) rename tests/{swoole_runtime/curl_native => swoole_curl}/multi_4.phpt (82%) rename tests/{swoole_runtime/curl_native => swoole_curl}/multi_close.phpt (85%) rename tests/{swoole_runtime/curl_native => swoole_curl}/multi_dtor.phpt (84%) rename tests/{swoole_runtime/curl_native => swoole_curl}/non_exclusive.phpt (94%) rename tests/{swoole_runtime/curl_native => swoole_curl}/select_twice.phpt (86%) rename tests/{swoole_library/curl => swoole_curl}/setopt/1.phpt (90%) rename tests/{swoole_library/curl => swoole_curl}/setopt/3.phpt (88%) rename tests/{swoole_library/curl => swoole_curl}/setopt/4.phpt (90%) rename tests/{swoole_library/curl => swoole_curl}/setopt/5_skip.phpt (93%) rename tests/{swoole_library/curl => swoole_curl}/setopt/filetime_1.phpt (85%) rename tests/{swoole_library/curl => swoole_curl}/setopt/filetime_2.phpt (84%) rename tests/{swoole_library/curl => swoole_curl}/setopt/header_out.phpt (89%) rename tests/{swoole_library/curl => swoole_curl}/setopt/infile.phpt (89%) rename tests/{swoole_library/curl => swoole_curl}/setopt/nobody.phpt (86%) rename tests/{swoole_runtime/curl_native => swoole_curl}/sleep.phpt (94%) rename tests/{swoole_library/curl => swoole_curl}/ssl/version.phpt (85%) rename tests/{swoole_library/curl => swoole_curl}/template (57%) rename tests/{swoole_runtime/curl_native => swoole_curl}/timer_coredump.phpt (85%) rename tests/{swoole_library/curl => swoole_curl}/upload/1.phpt (83%) rename tests/{swoole_library/curl => swoole_curl}/upload/curl_testdata1.txt (100%) rename tests/{swoole_library/curl => swoole_curl}/upload/curl_testdata2.txt (100%) rename tests/{swoole_runtime/curl_native => swoole_curl}/yield_in_callback.phpt (92%) diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index 7fa57adcf71..7b23b4da6c3 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -689,6 +689,7 @@ PHP_MINIT_FUNCTION(swoole) { SW_REGISTER_LONG_CONSTANT("SWOOLE_TRACE_CONTEXT", SW_TRACE_CONTEXT); SW_REGISTER_LONG_CONSTANT("SWOOLE_TRACE_CO_HTTP_SERVER", SW_TRACE_CO_HTTP_SERVER); SW_REGISTER_LONG_CONSTANT("SWOOLE_TRACE_TABLE", SW_TRACE_TABLE); + SW_REGISTER_LONG_CONSTANT("SWOOLE_TRACE_CO_CURL", SW_TRACE_CO_CURL); SW_REGISTER_LONG_CONSTANT("SWOOLE_TRACE_ALL", SW_TRACE_ALL); /** diff --git a/ext-src/php_swoole_curl.h b/ext-src/php_swoole_curl.h index 59ca6af80a5..34746008366 100644 --- a/ext-src/php_swoole_curl.h +++ b/ext-src/php_swoole_curl.h @@ -42,7 +42,6 @@ struct Handle { int event_bitmask; int event_fd; int action; - bool removed; }; struct Selector { @@ -121,30 +120,11 @@ class Multi { selector.reset(_selector); } - CURLMcode add_handle(CURL *cp) { - auto retval = curl_multi_add_handle(multi_handle_, cp); - if (retval == CURLM_OK) { - auto handle = new Handle{}; - handle->cp = cp; - handle->multi = this; - curl_easy_setopt(cp, CURLOPT_PRIVATE, handle); - } - return retval; - } - - CURLMcode remove_handle(CURL *cp) { - auto retval = curl_multi_remove_handle(multi_handle_, cp); - if (retval == CURLM_OK) { - auto handle = get_handle(cp); - delete handle; - curl_easy_setopt(cp, CURLOPT_PRIVATE, nullptr); - } - return retval; - } + CURLMcode add_handle(CURL *cp); + CURLMcode remove_handle(CURL *cp); CURLMcode perform() { - auto retval = curl_multi_perform(multi_handle_, &running_handles_); - return retval; + return curl_multi_perform(multi_handle_, &running_handles_); } int get_event(int action) { diff --git a/ext-src/php_swoole_cxx.cc b/ext-src/php_swoole_cxx.cc index b45a9d73f18..6873ee98862 100644 --- a/ext-src/php_swoole_cxx.cc +++ b/ext-src/php_swoole_cxx.cc @@ -30,42 +30,6 @@ static zend_op_array *swoole_compile_string(zend_source_string_t *source_string, } namespace zend { -bool include(const std::string &file) { - zend_file_handle file_handle; - int ret = php_stream_open_for_zend_ex(file.c_str(), &file_handle, USE_PATH | STREAM_OPEN_FOR_INCLUDE); - if (ret != SUCCESS) { - return false; - } - - zend_string *opened_path; - if (!file_handle.opened_path) { - file_handle.opened_path = zend_string_init(file.c_str(), file.length(), 0); - } - opened_path = zend_string_copy(file_handle.opened_path); - zval dummy; - - zval retval; - zend_op_array *new_op_array; - ZVAL_NULL(&dummy); - if (zend_hash_add(&EG(included_files), opened_path, &dummy)) { - new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE); - zend_destroy_file_handle(&file_handle); - } else { - new_op_array = nullptr; - zend_file_handle_dtor(&file_handle); - } - zend_string_release(opened_path); - if (!new_op_array) { - return false; - } - - zend_execute(new_op_array, &retval); - - destroy_op_array(new_op_array); - efree(new_op_array); - return Z_TYPE(retval) == IS_TRUE; -} - bool eval(const std::string &code, std::string const &filename) { if (!old_compile_string) { old_compile_string = zend_compile_string; diff --git a/ext-src/php_swoole_cxx.h b/ext-src/php_swoole_cxx.h index 9e905291757..2224b971a81 100644 --- a/ext-src/php_swoole_cxx.h +++ b/ext-src/php_swoole_cxx.h @@ -417,7 +417,6 @@ struct Function { } }; -bool include(const std::string &file); bool eval(const std::string &code, const std::string &filename = ""); void known_strings_init(void); void known_strings_dtor(void); diff --git a/ext-src/swoole_curl.cc b/ext-src/swoole_curl.cc index 69787bc5b8e..5c2398dbe3f 100644 --- a/ext-src/swoole_curl.cc +++ b/ext-src/swoole_curl.cc @@ -15,6 +15,7 @@ */ #include "php_swoole_curl.h" +#include "swoole_socket.h" #ifdef SW_USE_CURL @@ -114,11 +115,35 @@ void Multi::set_event(CURL *cp, void *socket_ptr, curl_socket_t sockfd, int acti } Handle *handle = get_handle(cp); handle->action = action; - handle->removed = false; swTraceLog(SW_TRACE_CO_CURL, SW_ECHO_GREEN " handle=%p, curl=%p, fd=%d, events=%d", "[ADD]", handle, cp, sockfd, events); } +CURLMcode Multi::add_handle(CURL *cp) { + auto retval = curl_multi_add_handle(multi_handle_, cp); + if (retval == CURLM_OK) { + auto handle = get_handle(cp); + if (handle == nullptr) { + handle = new Handle{}; + handle->cp = cp; + curl_easy_setopt(cp, CURLOPT_PRIVATE, handle); + } + handle->multi = this; + } + return retval; +} + +CURLMcode Multi::remove_handle(CURL *cp) { + auto retval = curl_multi_remove_handle(multi_handle_, cp); + if (retval == CURLM_OK) { + auto handle = get_handle(cp); + if (handle) { + handle->multi = nullptr; + } + } + return retval; +} + CURLcode Multi::exec(php_curl *ch) { co = check_bound_co(); ON_SCOPE_EXIT { @@ -137,8 +162,9 @@ CURLcode Multi::exec(php_curl *ch) { int bitmask = 0; if (sockfd >= 0) { bitmask = handle->event_bitmask; - swoole_event_del(handle->socket); - handle->removed = true; + if (handle->socket && !handle->socket->removed) { + swoole_event_del(handle->socket); + } } del_timer(); curl_multi_socket_action(multi_handle_, sockfd, bitmask, &running_handles_); @@ -146,9 +172,8 @@ CURLcode Multi::exec(php_curl *ch) { break; } set_timer(); - if (sockfd >= 0 && handle->socket && handle->removed) { + if (sockfd >= 0 && handle->socket && handle->socket->removed) { swoole_event_add(handle->socket, get_event(handle->action)); - handle->removed = false; } } @@ -180,6 +205,9 @@ CURLcode Multi::read_info() { int Multi::handle_timeout(CURLM *mh, long timeout_ms, void *userp) { Multi *multi = (Multi *) userp; + if (!swoole_event_is_available()) { + return 0; + } if (timeout_ms < 0) { multi->del_timer(); } else { @@ -193,6 +221,9 @@ int Multi::handle_timeout(CURLM *mh, long timeout_ms, void *userp) { long Multi::select(php_curlm *mh) { co = check_bound_co(); + if (zend_llist_count(&mh->easyh) == 0) { + return 0; + } ON_SCOPE_EXIT { co = nullptr; }; @@ -204,9 +235,8 @@ long Multi::select(php_curlm *mh) { continue; } Handle *handle = get_handle(ch->cp); - if (handle && handle->socket && handle->removed) { + if (handle && handle->socket && handle->socket->removed) { swoole_event_add(handle->socket, get_event(handle->action)); - handle->removed = false; swTraceLog(SW_TRACE_CO_CURL, "resume, handle=%p, curl=%p, fd=%d", handle, ch->cp, handle->socket->get_fd()); } } @@ -222,10 +252,9 @@ long Multi::select(php_curlm *mh) { continue; } Handle *handle = get_handle(ch->cp); - if (handle && handle->socket) { + if (handle && handle->socket && !handle->socket->removed) { swTraceLog(SW_TRACE_CO_CURL, "suspend, handle=%p, curl=%p, fd=%d", handle, ch->cp, handle->socket->get_fd()); swoole_event_del(handle->socket); - handle->removed = true; } } del_timer(); @@ -257,7 +286,6 @@ void Multi::callback(Handle *handle, int event_bitmask) { if (!co) { if (handle) { swoole_event_del(handle->socket); - handle->removed = true; } else { del_timer(); } diff --git a/ext-src/swoole_runtime.cc b/ext-src/swoole_runtime.cc index 15d27bab036..68a9e16acd9 100644 --- a/ext-src/swoole_runtime.cc +++ b/ext-src/swoole_runtime.cc @@ -1407,7 +1407,9 @@ bool PHPCoroutine::enable_hook(uint32_t flags) { SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_init); SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_add_handle); SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_exec); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_errno); SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_select); + SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_setopt); SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_getcontent); SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_info_read); SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_multi_remove_handle); @@ -1432,7 +1434,9 @@ bool PHPCoroutine::enable_hook(uint32_t flags) { SW_UNHOOK_FUNC(curl_multi_init); SW_UNHOOK_FUNC(curl_multi_add_handle); SW_UNHOOK_FUNC(curl_multi_exec); + SW_UNHOOK_FUNC(curl_multi_errno); SW_UNHOOK_FUNC(curl_multi_select); + SW_UNHOOK_FUNC(curl_multi_setopt); SW_UNHOOK_FUNC(curl_multi_getcontent); SW_UNHOOK_FUNC(curl_multi_info_read); SW_UNHOOK_FUNC(curl_multi_remove_handle); diff --git a/tests/include/functions.php b/tests/include/functions.php index e8b615fc711..6d9d66597e7 100644 --- a/tests/include/functions.php +++ b/tests/include/functions.php @@ -761,4 +761,13 @@ function dump_to_file($file, $data) fwrite($fp, $l . "\n"); } fclose($fp); -} \ No newline at end of file +} + +function curl_type_assert($ch, $resource_type, $class_type) +{ + if (PHP_VERSION_ID >= 80000) { + Assert::isInstanceOf($ch, $class_type); + } else { + Assert::eq(get_resource_type($ch), $resource_type); + } +} diff --git a/tests/include/lib/src/CurlManager.php b/tests/include/lib/src/CurlManager.php index d029825a6ff..9b593554363 100644 --- a/tests/include/lib/src/CurlManager.php +++ b/tests/include/lib/src/CurlManager.php @@ -9,6 +9,15 @@ class CurlManager { protected $port; + protected $nativeCurl = false; + + function __construct() { + $this->nativeCurl = defined('SWOOLE_HOOK_NATIVE_CURL'); + } + + function disableNativeCurl() { + $this->nativeCurl = false; + } function getUrlBase() { @@ -43,7 +52,8 @@ function run(callable $fn, $createCliServer = true) global $argc, $argv; if (!($argc > 1 and $argv[1] == 'ori')) { - Swoole\Runtime::enableCoroutine(SWOOLE_HOOK_CURL); + $flags = $this->nativeCurl ? SWOOLE_HOOK_NATIVE_CURL : SWOOLE_HOOK_CURL; + Swoole\Runtime::enableCoroutine($flags); } run(function () use ($fn, $proc) { diff --git a/tests/include/lib/src/responder/get.php b/tests/include/lib/src/responder/get.php index 5a78508c774..5df7b009c3f 100644 --- a/tests/include/lib/src/responder/get.php +++ b/tests/include/lib/src/responder/get.php @@ -33,7 +33,7 @@ break; case 'file': if (isset($_FILES['file'])) { - echo $_FILES['file']['name'] . '|' . $_FILES['file']['type']; + echo $_FILES['file']['name'] . '|' . $_FILES['file']['type'] . '|' . $_FILES['file']['size']; } break; case 'method': diff --git a/tests/swoole_client_coro/sendto.phpt b/tests/swoole_client_coro/sendto.phpt index 3b2fa2b8565..024d2c25399 100644 --- a/tests/swoole_client_coro/sendto.phpt +++ b/tests/swoole_client_coro/sendto.phpt @@ -1,7 +1,8 @@ --TEST-- swoole_client_coro: sendto --SKIPIF-- - + --FILE-- + --FILE-- --SKIPIF-- - + --FILE-- --SKIPIF-- - + ?> --FILE-- run(function ($host) { diff --git a/tests/swoole_library/curl/basic/11.phpt b/tests/swoole_curl/basic/11.phpt similarity index 89% rename from tests/swoole_library/curl/basic/11.phpt rename to tests/swoole_curl/basic/11.phpt index dc32e7b6d4c..8c3ca660b52 100644 --- a/tests/swoole_library/curl/basic/11.phpt +++ b/tests/swoole_curl/basic/11.phpt @@ -3,7 +3,7 @@ swoole_library/curl/basic: Test curl_opt() function with COOKIE --CREDITS-- TestFest 2009 - AFUP - Xavier Gorse --SKIPIF-- - + --FILE-- * Alias to functions: */ -require __DIR__ . '/../../../include/bootstrap.php'; +require __DIR__ . '/../../include/bootstrap.php'; $cm = new \SwooleTest\CurlManager(); $cm->run(function ($host) { diff --git a/tests/swoole_library/curl/basic/12.phpt b/tests/swoole_curl/basic/12.phpt similarity index 88% rename from tests/swoole_library/curl/basic/12.phpt rename to tests/swoole_curl/basic/12.phpt index c1df4bf2dad..a6df67c6660 100644 --- a/tests/swoole_library/curl/basic/12.phpt +++ b/tests/swoole_curl/basic/12.phpt @@ -3,7 +3,7 @@ swoole_library/curl/basic: Test curl_opt() function with CURLOPT_HTTP_VERSION/CU --CREDITS-- TestFest 2009 - AFUP - Xavier Gorse --SKIPIF-- - + --FILE-- * Source code: ext/curl/interface.c * Alias to functions: */ -require __DIR__ . '/../../../include/bootstrap.php'; +require __DIR__ . '/../../include/bootstrap.php'; $cm = new \SwooleTest\CurlManager(); +$cm->disableNativeCurl(); $cm->run(function ($host) { // start testing diff --git a/tests/swoole_library/curl/basic/13.phpt b/tests/swoole_curl/basic/13.phpt similarity index 89% rename from tests/swoole_library/curl/basic/13.phpt rename to tests/swoole_curl/basic/13.phpt index 5d59aad8589..27e38c74597 100644 --- a/tests/swoole_library/curl/basic/13.phpt +++ b/tests/swoole_curl/basic/13.phpt @@ -3,7 +3,7 @@ swoole_library/curl/basic: Test curl_opt() function with CURLOPT_HTTP_VERSION/CU --CREDITS-- TestFest 2009 - AFUP - Xavier Gorse --SKIPIF-- - + --FILE-- * Source code: ext/curl/interface.c * Alias to functions: */ -require __DIR__ . '/../../../include/bootstrap.php'; +require __DIR__ . '/../../include/bootstrap.php'; $cm = new \SwooleTest\CurlManager(); $cm->run(function ($host) { diff --git a/tests/swoole_library/curl/basic/14.phpt b/tests/swoole_curl/basic/14.phpt similarity index 77% rename from tests/swoole_library/curl/basic/14.phpt rename to tests/swoole_curl/basic/14.phpt index cc79ede92ee..7b523cd8562 100644 --- a/tests/swoole_library/curl/basic/14.phpt +++ b/tests/swoole_curl/basic/14.phpt @@ -3,14 +3,15 @@ swoole_library/curl/basic: Test curl_init() function with basic functionality --CREDITS-- Jean-Marc Fontaine --SKIPIF-- - + --FILE-- disableNativeCurl(); $cm->run(function ($host) { $ch = curl_init(); Assert::isInstanceOf($ch, Swoole\Curl\Handler::class); diff --git a/tests/swoole_library/curl/basic/15.phpt b/tests/swoole_curl/basic/15.phpt similarity index 81% rename from tests/swoole_library/curl/basic/15.phpt rename to tests/swoole_curl/basic/15.phpt index b95f67fa636..e42bfaefec4 100644 --- a/tests/swoole_library/curl/basic/15.phpt +++ b/tests/swoole_curl/basic/15.phpt @@ -3,12 +3,12 @@ swoole_library/curl/basic: Test curl_init() function with $url parameter defined --CREDITS-- Jean-Marc Fontaine --SKIPIF-- - + --FILE-- run(function ($host) { diff --git a/tests/swoole_library/curl/basic/19.phpt b/tests/swoole_curl/basic/19.phpt similarity index 83% rename from tests/swoole_library/curl/basic/19.phpt rename to tests/swoole_curl/basic/19.phpt index 050b6a1cf10..169363663ac 100644 --- a/tests/swoole_library/curl/basic/19.phpt +++ b/tests/swoole_curl/basic/19.phpt @@ -3,10 +3,10 @@ swoole_library/curl/basic: Test curl_getinfo() function with CURLINFO_EFFECTIVE_ --CREDITS-- Jean-Marc Fontaine --SKIPIF-- - + --FILE-- run(function ($host) { diff --git a/tests/swoole_library/curl/basic/2.phpt b/tests/swoole_curl/basic/2.phpt similarity index 88% rename from tests/swoole_library/curl/basic/2.phpt rename to tests/swoole_curl/basic/2.phpt index ccbab922964..987c40e54f9 100644 --- a/tests/swoole_library/curl/basic/2.phpt +++ b/tests/swoole_curl/basic/2.phpt @@ -4,10 +4,10 @@ swoole_library/curl/basic: Test curl_opt() function with CURLOPT_RETURNTRANSFER Sebastian Deutsch TestFest 2009 - AFUP - Jean-Marc Fontaine --SKIPIF-- - + --FILE-- run(function ($host) { diff --git a/tests/swoole_library/curl/basic/20.phpt b/tests/swoole_curl/basic/20.phpt similarity index 82% rename from tests/swoole_library/curl/basic/20.phpt rename to tests/swoole_curl/basic/20.phpt index 34baf375700..642a06cdba4 100644 --- a/tests/swoole_library/curl/basic/20.phpt +++ b/tests/swoole_curl/basic/20.phpt @@ -3,10 +3,10 @@ swoole_library/curl/basic: Test curl_getinfo() function with CURLINFO_HTTP_CODE --CREDITS-- Jean-Marc Fontaine --SKIPIF-- - + --FILE-- run(function ($host) { diff --git a/tests/swoole_library/curl/basic/21.phpt b/tests/swoole_curl/basic/21.phpt similarity index 82% rename from tests/swoole_library/curl/basic/21.phpt rename to tests/swoole_curl/basic/21.phpt index bdacdf83fa3..7c42ef3a1a7 100644 --- a/tests/swoole_library/curl/basic/21.phpt +++ b/tests/swoole_curl/basic/21.phpt @@ -3,10 +3,10 @@ swoole_library/curl/basic: Test curl_getinfo() function with CURLINFO_CONTENT_TY --CREDITS-- Jean-Marc Fontaine --SKIPIF-- - + --FILE-- run(function ($host) { diff --git a/tests/swoole_library/curl/basic/22.phpt b/tests/swoole_curl/basic/22.phpt similarity index 93% rename from tests/swoole_library/curl/basic/22.phpt rename to tests/swoole_curl/basic/22.phpt index 93f61146194..5e9a8a18e33 100644 --- a/tests/swoole_library/curl/basic/22.phpt +++ b/tests/swoole_curl/basic/22.phpt @@ -3,10 +3,10 @@ swoole_library/curl/basic: Test curl_setopt() function with CURLOPT_FOLLOWLOCATI --CREDITS-- Jean-Marc Fontaine --SKIPIF-- - + --FILE-- run(function ($host) { diff --git a/tests/swoole_library/curl/basic/23.phpt b/tests/swoole_curl/basic/23.phpt similarity index 87% rename from tests/swoole_library/curl/basic/23.phpt rename to tests/swoole_curl/basic/23.phpt index e68d281d384..5ab78002993 100644 --- a/tests/swoole_library/curl/basic/23.phpt +++ b/tests/swoole_curl/basic/23.phpt @@ -3,10 +3,10 @@ swoole_library/curl/basic: Test curl_setopt() function with CURLOPT_HEADER param --CREDITS-- Jean-Marc Fontaine --SKIPIF-- - + --FILE-- run(function ($host) { diff --git a/tests/swoole_library/curl/basic/24.phpt b/tests/swoole_curl/basic/24.phpt similarity index 89% rename from tests/swoole_library/curl/basic/24.phpt rename to tests/swoole_curl/basic/24.phpt index 2575d89c567..49e7f57a7cb 100644 --- a/tests/swoole_library/curl/basic/24.phpt +++ b/tests/swoole_curl/basic/24.phpt @@ -4,7 +4,7 @@ swoole_library/curl/basic: Test curl_opt() function with setting auto referer Sebastian Deutsch TestFest 2009 - AFUP - Jean-Marc Fontaine --SKIPIF-- - + --FILE-- * Alias to functions: */ -require __DIR__ . '/../../../include/bootstrap.php'; +require __DIR__ . '/../../include/bootstrap.php'; $cm = new \SwooleTest\CurlManager(); +$cm->disableNativeCurl(); $cm->run(function ($host) { // start testing diff --git a/tests/swoole_library/curl/basic/25.phpt b/tests/swoole_curl/basic/25.phpt similarity index 92% rename from tests/swoole_library/curl/basic/25.phpt rename to tests/swoole_curl/basic/25.phpt index d1cc087841d..a4176f17944 100644 --- a/tests/swoole_library/curl/basic/25.phpt +++ b/tests/swoole_curl/basic/25.phpt @@ -4,7 +4,7 @@ swoole_library/curl/basic: Test curl_multi_getcontent() function Sebastian Deutsch TestFest 2009 - AFUP - Jean-Marc Fontaine --SKIPIF-- - + --FILE-- * Source code: ext/curl/interface.c * Alias to functions: */ -require __DIR__ . '/../../../include/bootstrap.php'; +require __DIR__ . '/../../include/bootstrap.php'; $cm = new \SwooleTest\CurlManager(); $cm->run(function ($host) { // start testing diff --git a/tests/swoole_library/curl/basic/3.phpt b/tests/swoole_curl/basic/3.phpt similarity index 90% rename from tests/swoole_library/curl/basic/3.phpt rename to tests/swoole_curl/basic/3.phpt index 465a38a6a93..c4196924ed8 100644 --- a/tests/swoole_library/curl/basic/3.phpt +++ b/tests/swoole_curl/basic/3.phpt @@ -4,10 +4,10 @@ swoole_library/curl/basic: Test curl_opt() function with POST parameters Sebastian Deutsch TestFest 2009 - AFUP - Jean-Marc Fontaine --SKIPIF-- - + --FILE-- run(function ($host) { diff --git a/tests/swoole_library/curl/basic/4.phpt b/tests/swoole_curl/basic/4.phpt similarity index 90% rename from tests/swoole_library/curl/basic/4.phpt rename to tests/swoole_curl/basic/4.phpt index 9ec9458402a..0ee70d9a6f6 100644 --- a/tests/swoole_library/curl/basic/4.phpt +++ b/tests/swoole_curl/basic/4.phpt @@ -4,7 +4,7 @@ swoole_library/curl/basic: Test curl_opt() function with setting referer Sebastian Deutsch TestFest 2009 - AFUP - Jean-Marc Fontaine --SKIPIF-- - + --FILE-- * Alias to functions: */ -require __DIR__ . '/../../../include/bootstrap.php'; +require __DIR__ . '/../../include/bootstrap.php'; $cm = new \SwooleTest\CurlManager(); $cm->run(function ($host) { diff --git a/tests/swoole_library/curl/basic/5.phpt b/tests/swoole_curl/basic/5.phpt similarity index 90% rename from tests/swoole_library/curl/basic/5.phpt rename to tests/swoole_curl/basic/5.phpt index 49bb88e00b5..b6147becb3e 100644 --- a/tests/swoole_library/curl/basic/5.phpt +++ b/tests/swoole_curl/basic/5.phpt @@ -4,7 +4,7 @@ swoole_library/curl/basic: Test curl_opt() function with user agent Sebastian Deutsch TestFest 2009 - AFUP - Jean-Marc Fontaine --SKIPIF-- - + --FILE-- * Alias to functions: */ -require __DIR__ . '/../../../include/bootstrap.php'; +require __DIR__ . '/../../include/bootstrap.php'; $cm = new \SwooleTest\CurlManager(); $cm->run(function ($host) { diff --git a/tests/swoole_library/curl/basic/7.phpt b/tests/swoole_curl/basic/7.phpt similarity index 79% rename from tests/swoole_library/curl/basic/7.phpt rename to tests/swoole_curl/basic/7.phpt index 43a66b3d8fe..c8549480185 100644 --- a/tests/swoole_library/curl/basic/7.phpt +++ b/tests/swoole_curl/basic/7.phpt @@ -3,7 +3,7 @@ swoole_library/curl/basic: Test curl_error() & curl_errno() function without url --CREDITS-- TestFest 2009 - AFUP - Perrick Penet --SKIPIF-- - + --FILE-- //In January 2008 , level 7.18.0 of the curl lib, many of the messages changed. //The final crlf was removed. This test is coded to work with or without the crlf. -require __DIR__ . '/../../../include/bootstrap.php'; +require __DIR__ . '/../../include/bootstrap.php'; $cm = new \SwooleTest\CurlManager(); $cm->run(function ($host) { @@ -27,5 +27,5 @@ $cm->run(function ($host) { ?> --EXPECTF-- -%string(%d) "No URL set or URL using bad/illegal format" +%string(%d) "No URL set%s" int(3) diff --git a/tests/swoole_library/curl/basic/8.phpt b/tests/swoole_curl/basic/8.phpt similarity index 87% rename from tests/swoole_library/curl/basic/8.phpt rename to tests/swoole_curl/basic/8.phpt index e0ea4c0842c..f296edf2637 100644 --- a/tests/swoole_library/curl/basic/8.phpt +++ b/tests/swoole_curl/basic/8.phpt @@ -4,7 +4,7 @@ swoole_library/curl/basic: Test curl_error() & curl_errno() function with proble TestFest 2009 - AFUP - Perrick Penet --SKIPIF-- --FILE-- run(function ($host) { $url = "http://www." . uniqid() . "." . uniqid(); diff --git a/tests/swoole_library/curl/basic/9.phpt b/tests/swoole_curl/basic/9.phpt similarity index 82% rename from tests/swoole_library/curl/basic/9.phpt rename to tests/swoole_curl/basic/9.phpt index fbf3d93afb6..73f687427e9 100644 --- a/tests/swoole_library/curl/basic/9.phpt +++ b/tests/swoole_curl/basic/9.phpt @@ -3,13 +3,14 @@ swoole_library/curl/basic: Test curl_error() & curl_errno() function with proble --CREDITS-- TestFest 2009 - AFUP - Perrick Penet --SKIPIF-- - + --FILE-- disableNativeCurl(); $cm->run(function ($host) { $url = uniqid()."://www.".uniqid().".".uniqid(); $ch = curl_init(); diff --git a/tests/swoole_runtime/curl_native/close_before_resume.phpt b/tests/swoole_curl/close_before_resume.phpt similarity index 95% rename from tests/swoole_runtime/curl_native/close_before_resume.phpt rename to tests/swoole_curl/close_before_resume.phpt index 84dd23fcdf6..9ee7328d576 100644 --- a/tests/swoole_runtime/curl_native/close_before_resume.phpt +++ b/tests/swoole_curl/close_before_resume.phpt @@ -2,11 +2,11 @@ swoole_runtime/curl_native: close before resume --SKIPIF-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- +--FILE-- +cancel(); + $responses[] = $response; + } + foreach ($responses as $r) { + Assert::true(Promise\Is::rejected($r)); + } + echo 'Done' . PHP_EOL; +}); +?> +--EXPECT-- +Done diff --git a/tests/swoole_curl/guzzle/cannot_cancel_finished.phpt b/tests/swoole_curl/guzzle/cannot_cancel_finished.phpt new file mode 100644 index 00000000000..4ab6cf2cdb2 --- /dev/null +++ b/tests/swoole_curl/guzzle/cannot_cancel_finished.phpt @@ -0,0 +1,31 @@ +--TEST-- +swoole_runtime/curl_native/guzzle: cannot_cancel_finished +--SKIPIF-- + +--FILE-- +wait(); + $response->cancel(); + Assert::true(Promise\Is::fulfilled($response)); + echo 'Done' . PHP_EOL; +}); +?> +--EXPECT-- +Done diff --git a/tests/swoole_curl/guzzle/cookie.phpt b/tests/swoole_curl/guzzle/cookie.phpt new file mode 100644 index 00000000000..dc8a7d2b84e --- /dev/null +++ b/tests/swoole_curl/guzzle/cookie.phpt @@ -0,0 +1,38 @@ +--TEST-- +swoole_runtime/curl_native/guzzle: cookie +--SKIPIF-- + +--FILE-- + 'foo', + 'other_cookie' => 'barbaz1234' + ], + 'httpbin.org' + ); + $r = $client->request('GET', 'http://httpbin.org/cookies', [ + 'cookies' => $jar + ]); + Assert::eq($r->getStatusCode(), 200); + Assert::eq(json_decode($r->getBody()->getContents(), true)['cookies']['some_cookie'], 'foo'); + echo 'Done' . PHP_EOL; +}); +?> +--EXPECT-- +Done diff --git a/tests/swoole_curl/guzzle/request_async.phpt b/tests/swoole_curl/guzzle/request_async.phpt new file mode 100644 index 00000000000..d745e380002 --- /dev/null +++ b/tests/swoole_curl/guzzle/request_async.phpt @@ -0,0 +1,39 @@ +--TEST-- +swoole_runtime/curl_native/guzzle: request async +--SKIPIF-- + +--FILE-- +requestAsync('GET', 'http://httpbin.org/get'); + $promise->then( + function (ResponseInterface $res) { + echo $res->getStatusCode() .PHP_EOL; + }, + function (RequestException $e) { + echo $e->getMessage() . PHP_EOL; + echo $e->getRequest()->getMethod() . PHP_EOL; + } + ); + $promise->wait(); + echo 'Done' . PHP_EOL; +}); +?> +--EXPECT-- +200 +Done diff --git a/tests/swoole_curl/guzzle/request_on_stats.phpt b/tests/swoole_curl/guzzle/request_on_stats.phpt new file mode 100644 index 00000000000..bd2560a907b --- /dev/null +++ b/tests/swoole_curl/guzzle/request_on_stats.phpt @@ -0,0 +1,43 @@ +--TEST-- +swoole_runtime/curl_native/guzzle: request on_stats +--SKIPIF-- + +--FILE-- +request('GET', $host, [ + 'on_stats' => function (TransferStats $stats) use ($host) { + Assert::eq($stats->getEffectiveUri(), $host); + + // You must check if a response was received before using the + // response object. + if ($stats->hasResponse()) { + Assert::eq($stats->getResponse()->getStatusCode(), 200); + } else { + // Error data is handler specific. You will need to know what + // type of error data your handler uses before using this + // value. + var_dump($stats->getHandlerErrorData()); + } + } + ]); + echo 'Done' . PHP_EOL; +}); +?> +--EXPECT-- +Done diff --git a/tests/swoole_curl/guzzle/send_async.phpt b/tests/swoole_curl/guzzle/send_async.phpt new file mode 100644 index 00000000000..6fd27269fab --- /dev/null +++ b/tests/swoole_curl/guzzle/send_async.phpt @@ -0,0 +1,41 @@ +--TEST-- +swoole_runtime/curl_native/guzzle: send async +--SKIPIF-- + +--FILE-- +request('GET', 'https://api.github.com/repos/swoole/swoole-src'); + + echo $response->getStatusCode(), PHP_EOL; // 200 + echo $response->getHeaderLine('content-type'), PHP_EOL; // 'application/json; charset=utf8' + + // Send an asynchronous request. + $request = new Request('GET', 'http://httpbin.org'); + $promise = $client->sendAsync($request)->then(function ($response) { + echo 'I completed! ' . $response->getStatusCode() . PHP_EOL; + }); + + $promise->wait(); + echo 'Done' . PHP_EOL; +}); +?> +--EXPECT-- +200 +application/json; charset=utf-8 +I completed! 200 +Done diff --git a/tests/swoole_runtime/curl_native/https.phpt b/tests/swoole_curl/https.phpt similarity index 93% rename from tests/swoole_runtime/curl_native/https.phpt rename to tests/swoole_curl/https.phpt index 221dd802c2b..0c9fd60bc6e 100644 --- a/tests/swoole_runtime/curl_native/https.phpt +++ b/tests/swoole_curl/https.phpt @@ -2,11 +2,11 @@ swoole_runtime/curl_native: https --SKIPIF-- --FILE-- +--FILE-- + 1, + $curl_option => $fp, + CURLOPT_URL => $target_url, + ); + + // we also need to set CURLOPT_VERBOSE to test CURLOPT_STDERR properly + if (CURLOPT_STDERR == $curl_option) { + $options[CURLOPT_VERBOSE] = 1; + } + + if (CURLOPT_INFILE == $curl_option) { + $options[CURLOPT_UPLOAD] = 1; + } + + curl_setopt_array($ch1, $options); + curl_setopt_array($ch2, $options); + + fclose($fp); // <-- premature close of $fp caused a crash! + + $mh = curl_multi_init(); + + curl_multi_add_handle($mh, $ch1); + curl_multi_add_handle($mh, $ch2); + + $active = 0; + do { + curl_multi_exec($mh, $active); + } while ($active > 0); + + curl_multi_remove_handle($mh, $ch1); + curl_multi_remove_handle($mh, $ch2); + curl_multi_close($mh); + + // Force curl to output results + fflush(STDERR); + fflush(STDOUT); + + echo "Ok for $description\n"; +} + +$cm = new CurlManager(); +$cm->run(function ($host) { + $url = "{$host}/"; + + $options_to_check = array( + "CURLOPT_STDERR", "CURLOPT_WRITEHEADER", "CURLOPT_FILE", "CURLOPT_INFILE" + ); + + foreach($options_to_check as $option) { + checkForClosedFilePointer($url, constant($option), $option); + } +}); +?> +--CLEAN-- + +--EXPECTF-- +Warning: curl_multi_add_handle(): CURLOPT_STDERR resource has gone away, resetting to stderr in %s on line %d +%A +Warning: curl_multi_add_handle(): CURLOPT_STDERR resource has gone away, resetting to stderr in %s on line %d +%A +Ok for CURLOPT_STDERR + +Warning: curl_multi_add_handle(): CURLOPT_WRITEHEADER resource has gone away, resetting to default in %s on line %d + +Warning: curl_multi_add_handle(): CURLOPT_WRITEHEADER resource has gone away, resetting to default in %s on line %d +Ok for CURLOPT_WRITEHEADER + +Warning: curl_multi_add_handle(): CURLOPT_FILE resource has gone away, resetting to default in %s on line %d + +Warning: curl_multi_add_handle(): CURLOPT_FILE resource has gone away, resetting to default in %s on line %d +%AOk for CURLOPT_FILE + +Warning: curl_multi_add_handle(): CURLOPT_INFILE resource has gone away, resetting to default in %s on line %d + +Warning: curl_multi_add_handle(): CURLOPT_INFILE resource has gone away, resetting to default in %s on line %d +Ok for CURLOPT_INFILE diff --git a/tests/swoole_curl/multi/bug67643.phpt b/tests/swoole_curl/multi/bug67643.phpt new file mode 100644 index 00000000000..0f1881cedea --- /dev/null +++ b/tests/swoole_curl/multi/bug67643.phpt @@ -0,0 +1,38 @@ +--TEST-- +Bug #67643 (curl_multi_getcontent returns '' when RETURNTRANSFER isn't set) +--SKIPIF-- + +--FILE-- + 0); + + $results = curl_multi_getcontent($ch); + + curl_multi_remove_handle($mh, $ch); + curl_multi_close($mh); + + Assert::contains($results, 'Bug #67643'); + echo 'Done'.PHP_EOL; +}); +?> +--EXPECT-- +Done diff --git a/tests/swoole_curl/multi/bug71523.phpt b/tests/swoole_curl/multi/bug71523.phpt new file mode 100644 index 00000000000..33ea469578a --- /dev/null +++ b/tests/swoole_curl/multi/bug71523.phpt @@ -0,0 +1,34 @@ +--TEST-- +Bug #71523 (Copied handle with new option CURLOPT_HTTPHEADER crashes while curl_multi_exec) +--SKIPIF-- + +--FILE-- + +okey +--EXPECT-- +okey diff --git a/tests/swoole_curl/multi/bug76675.phpt b/tests/swoole_curl/multi/bug76675.phpt new file mode 100644 index 00000000000..c3951733d3f --- /dev/null +++ b/tests/swoole_curl/multi/bug76675.phpt @@ -0,0 +1,67 @@ +--TEST-- +Bug #76675 (Segfault with H2 server push write/writeheader handlers) +--SKIPIF-- + +--FILE-- + +--EXPECTREGEX-- +(Received \d+)+ diff --git a/tests/swoole_curl/multi/bug77535.phpt b/tests/swoole_curl/multi/bug77535.phpt new file mode 100644 index 00000000000..d23b22e9cea --- /dev/null +++ b/tests/swoole_curl/multi/bug77535.phpt @@ -0,0 +1,94 @@ +--TEST-- +Bug #77535 (Invalid callback, h2 server push) +--SKIPIF-- + +--FILE-- +mh = curl_multi_init()) { + throw new \RuntimeException('Unable to create a new cURL multi handle'); + } + + $this->addServerPushCallback(); + echo __METHOD__.'[2]'.PHP_EOL; + + $this->curl = curl_init(); + curl_setopt($this->curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); + curl_setopt($this->curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); + curl_setopt($this->curl, CURLOPT_HEADER, false); + curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, false); + curl_setopt($this->curl, CURLOPT_FAILONERROR, false); + curl_setopt($this->curl, CURLOPT_URL, 'https://http2.golang.org/serverpush'); + curl_setopt($this->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); + curl_setopt($this->curl, CURLOPT_HEADERFUNCTION, function ($ch, $data) { + return \strlen($data); + }); + curl_setopt($this->curl, CURLOPT_WRITEFUNCTION, function ($ch, $data) { + return \strlen($data); + }); + curl_multi_add_handle($this->mh, $this->curl); + echo __METHOD__.'[3]'.PHP_EOL; + + $stillRunning = null; + while (true) { + do { + $mrc = curl_multi_exec($this->mh, $stillRunning); + } while (CURLM_CALL_MULTI_PERFORM === $mrc); + + $info = curl_multi_info_read($this->mh); + while (false !== $info && $info['msg'] == CURLMSG_DONE) { + if (CURLMSG_DONE !== $info['msg']) { + continue; + } + echo "Start handle request.\n"; + return; + } + } + } + + private function addServerPushCallback(): void + { + echo __METHOD__.PHP_EOL; + $callback = static function () { + return CURL_PUSH_OK; + }; + + curl_multi_setopt($this->mh, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); + curl_multi_setopt($this->mh, CURLMOPT_PUSHFUNCTION, $callback); + } +} + +use Swoole\Runtime; + +use function Swoole\Coroutine\run; +Runtime::enableCoroutine(SWOOLE_HOOK_NATIVE_CURL); + +run(function () { + $buzz = new MyHttpClient(); + $buzz->sendRequest(); + $buzz = null; +}); +?> +--EXPECT-- +MyHttpClient::sendRequest[1] +MyHttpClient::addServerPushCallback +MyHttpClient::sendRequest[2] +MyHttpClient::sendRequest[3] +Start handle request. + + diff --git a/tests/swoole_curl/multi/bug77946.phpt b/tests/swoole_curl/multi/bug77946.phpt new file mode 100644 index 00000000000..45ad5660bc8 --- /dev/null +++ b/tests/swoole_curl/multi/bug77946.phpt @@ -0,0 +1,51 @@ +--TEST-- +Bug #77946 (Errored cURL resources returned by curl_multi_info_read() must be compatible with curl_errno() and curl_error()) +--SKIPIF-- + +--FILE-- + $url) { + $conn[$i] = curl_init($url); + curl_multi_add_handle($mh, $conn[$i]); + } + + do { + $status = curl_multi_exec($mh, $active); + $info = curl_multi_info_read($mh); + if (false !== $info) { + var_dump($info['result']); + var_dump(curl_errno($info['handle'])); + var_dump(curl_error($info['handle'])); + } + } while ($status === CURLM_CALL_MULTI_PERFORM || $active); + + foreach ($urls as $i => $url) { + curl_close($conn[$i]); + } + + curl_multi_close($mh); +}); +?> +--EXPECTF-- +int(1) +int(1) +string(%d) "Protocol %Sunknown%S not supported or disabled in libcurl" diff --git a/tests/swoole_curl/multi/curl_basic_018.phpt b/tests/swoole_curl/multi/curl_basic_018.phpt new file mode 100644 index 00000000000..93b70979ad3 --- /dev/null +++ b/tests/swoole_curl/multi/curl_basic_018.phpt @@ -0,0 +1,66 @@ +--TEST-- +Test curl_setopt() with curl_multi function with basic functionality +--CREDITS-- +TestFest 2009 - AFUP - Thomas Rabaix +--SKIPIF-- +--FILE-- +run(function ($host) { + // start testing + echo "*** Testing curl_exec() : basic functionality ***\n"; + + $url = "{$host}/get.inc?test=get"; + $chs = array( + 0 => curl_init(), + 1 => curl_init(), + 2 => curl_init(), + ); + + ob_start(); // start output buffering + + $options = array( + CURLOPT_RETURNTRANSFER => 1, + CURLOPT_URL => $url, + ); + + curl_setopt_array($chs[0], $options); //set the options + curl_setopt_array($chs[1], $options); //set the options + curl_setopt_array($chs[2], $options); //set the options + + $mh = curl_multi_init(); + + // add handlers + curl_multi_add_handle($mh, $chs[0]); + curl_multi_add_handle($mh, $chs[1]); + curl_multi_add_handle($mh, $chs[2]); + + $running=null; + //execute the handles + do { + curl_multi_exec($mh, $running); + } while ($running > 0); + + $curl_content = ''; + $curl_content .= curl_multi_getcontent($chs[0]); + $curl_content .= curl_multi_getcontent($chs[1]); + $curl_content .= curl_multi_getcontent($chs[2]); + + //close the handles + curl_multi_remove_handle($mh, $chs[0]); + curl_multi_remove_handle($mh, $chs[1]); + curl_multi_remove_handle($mh, $chs[2]); + curl_multi_close($mh); + + var_dump( $curl_content ); +}); +?> +--EXPECT-- +*** Testing curl_exec() : basic functionality *** +string(75) "Hello World! +Hello World!Hello World! +Hello World!Hello World! +Hello World!" diff --git a/tests/swoole_curl/multi/curl_copy_handle_variation4.phpt b/tests/swoole_curl/multi/curl_copy_handle_variation4.phpt new file mode 100644 index 00000000000..83e6cfd12ac --- /dev/null +++ b/tests/swoole_curl/multi/curl_copy_handle_variation4.phpt @@ -0,0 +1,48 @@ +--TEST-- +curl_copy_handle() allows to post CURLFile multiple times with curl_multi_exec() +--SKIPIF-- +--FILE-- +run(function ($host) { + $ch1 = curl_init(); + curl_setopt($ch1, CURLOPT_SAFE_UPLOAD, 1); + curl_setopt($ch1, CURLOPT_URL, "{$host}/get.php?test=file"); + // curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1); + + $filename = __DIR__ . '/АБВ.txt'; + file_put_contents($filename, "Test."); + $file = curl_file_create($filename); + $params = array('file' => $file); + var_dump(curl_setopt($ch1, CURLOPT_POSTFIELDS, $params)); + + $ch2 = curl_copy_handle($ch1); + $ch3 = curl_copy_handle($ch1); + + $mh = curl_multi_init(); + curl_multi_add_handle($mh, $ch1); + curl_multi_add_handle($mh, $ch2); + do { + $status = curl_multi_exec($mh, $active); + if ($active) { + curl_multi_select($mh); + } + } while ($active && $status == CURLM_OK); + + curl_multi_remove_handle($mh, $ch1); + curl_multi_remove_handle($mh, $ch2); + curl_multi_remove_handle($mh, $ch3); + curl_multi_close($mh); +}); +?> +===DONE=== +--EXPECT-- +bool(true) +АБВ.txt|application/octet-stream|5АБВ.txt|application/octet-stream|5===DONE=== +--CLEAN-- + diff --git a/tests/swoole_curl/multi/curl_int_cast.phpt b/tests/swoole_curl/multi/curl_int_cast.phpt new file mode 100644 index 00000000000..82e5d737766 --- /dev/null +++ b/tests/swoole_curl/multi/curl_int_cast.phpt @@ -0,0 +1,31 @@ +--TEST-- +Casting CurlHandle to int returns object ID +--FILE-- + +--EXPECTF-- +int(%d) +int(%d) +int(%d) +int(%d) diff --git a/tests/swoole_curl/multi/curl_multi_close_basic.phpt b/tests/swoole_curl/multi/curl_multi_close_basic.phpt new file mode 100644 index 00000000000..4f40907e657 --- /dev/null +++ b/tests/swoole_curl/multi/curl_multi_close_basic.phpt @@ -0,0 +1,24 @@ +--TEST-- +curl_multi_close +--CREDITS-- +Stefan Koopmanschap +#testfest Utrecht 2009 +--SKIPIF-- + +--FILE-- + +--EXPECT-- \ No newline at end of file diff --git a/tests/swoole_curl/multi/curl_multi_close_basic001.phpt b/tests/swoole_curl/multi/curl_multi_close_basic001.phpt new file mode 100644 index 00000000000..3620511483d --- /dev/null +++ b/tests/swoole_curl/multi/curl_multi_close_basic001.phpt @@ -0,0 +1,24 @@ +--TEST-- +curl_multi_close return false when supplied resource not valid cURL multi handle +--SKIPIF-- + +--FILE-- + +--EXPECT-- diff --git a/tests/swoole_curl/multi/curl_multi_close_reference.phpt b/tests/swoole_curl/multi/curl_multi_close_reference.phpt new file mode 100644 index 00000000000..4a11cad514d --- /dev/null +++ b/tests/swoole_curl/multi/curl_multi_close_reference.phpt @@ -0,0 +1,27 @@ +--TEST-- +curl_multi_close closed by cleanup functions +--SKIPIF-- + +--FILE-- + +--EXPECT-- +okey diff --git a/tests/swoole_curl/multi/curl_multi_errno_strerror_001.phpt b/tests/swoole_curl/multi/curl_multi_errno_strerror_001.phpt new file mode 100644 index 00000000000..dd9c3c63180 --- /dev/null +++ b/tests/swoole_curl/multi/curl_multi_errno_strerror_001.phpt @@ -0,0 +1,40 @@ +--TEST-- +curl_multi_errno and curl_multi_strerror basic test +--SKIPIF-- + +--FILE-- +getMessage() . "\n"; + } + + $errno = curl_multi_errno($mh); + echo $errno . PHP_EOL; + echo curl_multi_strerror($errno) . PHP_EOL; +}); +?> +--EXPECTF-- +0 +No error + +Warning: curl_multi_setopt(): Invalid curl multi configuration option in %s on line %d +6 +Unknown option diff --git a/tests/swoole_curl/multi/curl_multi_getcontent_basic3.phpt b/tests/swoole_curl/multi/curl_multi_getcontent_basic3.phpt new file mode 100644 index 00000000000..c49d7036f5e --- /dev/null +++ b/tests/swoole_curl/multi/curl_multi_getcontent_basic3.phpt @@ -0,0 +1,62 @@ +--TEST-- +Curl_multi_getcontent() basic test with different sources (local file/http) +--CREDITS-- +Rein Velt (rein@velt.org) +#TestFest Utrecht 20090509 +--SKIPIF-- +--FILE-- +run(function ($host) { + //CURL_MULTI_GETCONTENT TEST + + //CREATE RESOURCES + $ch1 = curl_init(); + $ch2 = curl_init(); + + //SET URL AND OTHER OPTIONS + curl_setopt($ch1, CURLOPT_URL, "{$host}/get.inc?test=getpost&get_param=Hello%20World"); + curl_setopt($ch2, CURLOPT_URL, "file://" . __DIR__ . DIRECTORY_SEPARATOR . "curl_testdata2.txt"); + curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true); + + //CREATE MULTIPLE CURL HANDLE + $mh = curl_multi_init(); + + //ADD THE 2 HANDLES + curl_multi_add_handle($mh, $ch1); + curl_multi_add_handle($mh, $ch2); + + //EXECUTE + $running = 0; + do { + curl_multi_exec($mh, $running); + } while ($running > 0); + + $results1 = curl_multi_getcontent($ch1); + $results2 = curl_multi_getcontent($ch2); + + //CLOSE + curl_multi_remove_handle($mh, $ch1); + curl_multi_remove_handle($mh, $ch2); + curl_multi_close($mh); + + echo $results1; + echo $results2; +}); +echo "CURL2\n"; +?> +--EXPECT-- +array(2) { + ["test"]=> + string(7) "getpost" + ["get_param"]=> + string(11) "Hello World" +} +array(0) { +} +CURL2 diff --git a/tests/swoole_curl/multi/curl_multi_info_read.phpt b/tests/swoole_curl/multi/curl_multi_info_read.phpt new file mode 100644 index 00000000000..ec5acb61cf6 --- /dev/null +++ b/tests/swoole_curl/multi/curl_multi_info_read.phpt @@ -0,0 +1,43 @@ +--TEST-- +array curl_multi_info_read ( resource $mh [, int &$msgs_in_queue = NULL ] ); +--CREDITS-- +marcosptf - - @phpsp - sao paulo - br +--SKIPIF-- + +--FILE-- + $url) { + $conn[$i] = curl_init($url); + curl_setopt($conn[$i], CURLOPT_RETURNTRANSFER, 1); + curl_multi_add_handle($mh, $conn[$i]); + } + + do { + $status = curl_multi_exec($mh, $active); + } while ($status === CURLM_CALL_MULTI_PERFORM || $active); + + while ($info = curl_multi_info_read($mh)) { + Assert::count($info, 3); + } + + foreach ($urls as $i => $url) { + curl_close($conn[$i]); + } +}); +?> +--EXPECT-- diff --git a/tests/swoole_curl/multi/curl_multi_init_basic.phpt b/tests/swoole_curl/multi/curl_multi_init_basic.phpt new file mode 100644 index 00000000000..1fd91174cd5 --- /dev/null +++ b/tests/swoole_curl/multi/curl_multi_init_basic.phpt @@ -0,0 +1,30 @@ +--TEST-- +Test curl_multi_init() +--CREDITS-- +Mark van der Velden +#testfest Utrecht 2009 +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +*** Testing curl_multi_init(void); *** diff --git a/tests/swoole_curl/multi/curl_multi_segfault.phpt b/tests/swoole_curl/multi/curl_multi_segfault.phpt new file mode 100644 index 00000000000..f72bde2594b --- /dev/null +++ b/tests/swoole_curl/multi/curl_multi_segfault.phpt @@ -0,0 +1,61 @@ +--TEST-- +Segfault due to libcurl connection caching +--SKIPIF-- + +--FILE-- + +--EXPECT-- +bool(true) diff --git a/tests/swoole_curl/multi/curl_multi_select_basic1.phpt b/tests/swoole_curl/multi/curl_multi_select_basic1.phpt new file mode 100644 index 00000000000..87a966c551d --- /dev/null +++ b/tests/swoole_curl/multi/curl_multi_select_basic1.phpt @@ -0,0 +1,24 @@ +--TEST-- +Test curl_multi_select() +--CREDITS-- +Ivo Jansch +#testfest Utrecht 2009 +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +%r(0|-1)%r diff --git a/tests/swoole_curl/multi/curl_multi_setopt_basic001.phpt b/tests/swoole_curl/multi/curl_multi_setopt_basic001.phpt new file mode 100644 index 00000000000..92ed301ab2e --- /dev/null +++ b/tests/swoole_curl/multi/curl_multi_setopt_basic001.phpt @@ -0,0 +1,32 @@ +--TEST-- +curl_multi_setopt basic test +--SKIPIF-- + +--FILE-- +getMessage() . "\n"; + } + curl_multi_close($mh); +}); +?> +--EXPECTF-- +bool(true) + +Warning: curl_multi_setopt(): Invalid curl multi configuration option in %s on line %d diff --git a/tests/swoole_runtime/curl_native/multi_1.phpt b/tests/swoole_curl/multi_1.phpt similarity index 77% rename from tests/swoole_runtime/curl_native/multi_1.phpt rename to tests/swoole_curl/multi_1.phpt index fca70d7ddf4..adc974cef46 100644 --- a/tests/swoole_runtime/curl_native/multi_1.phpt +++ b/tests/swoole_curl/multi_1.phpt @@ -2,11 +2,11 @@ swoole_runtime/curl_native: multi 1 --SKIPIF-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- + --FILE-- run(function ($host) { diff --git a/tests/swoole_library/curl/setopt/3.phpt b/tests/swoole_curl/setopt/3.phpt similarity index 88% rename from tests/swoole_library/curl/setopt/3.phpt rename to tests/swoole_curl/setopt/3.phpt index f1e1f35dc2c..b51b9a20321 100644 --- a/tests/swoole_library/curl/setopt/3.phpt +++ b/tests/swoole_curl/setopt/3.phpt @@ -4,13 +4,14 @@ swoole_library/curl/setopt: curl_setopt() call with CURLOPT_HTTPHEADER Paul Sohier #phptestfest utrecht --SKIPIF-- - + --FILE-- disableNativeCurl(); $cm->run(function ($host) { // start testing echo "*** curl_setopt() call with CURLOPT_HTTPHEADER\n"; diff --git a/tests/swoole_library/curl/setopt/4.phpt b/tests/swoole_curl/setopt/4.phpt similarity index 90% rename from tests/swoole_library/curl/setopt/4.phpt rename to tests/swoole_curl/setopt/4.phpt index 099d8c2cce2..cca1f8dbc30 100644 --- a/tests/swoole_library/curl/setopt/4.phpt +++ b/tests/swoole_curl/setopt/4.phpt @@ -4,11 +4,11 @@ swoole_library/curl/setopt: curl_setopt() call with CURLOPT_RETURNTRANSFER Paul Sohier #phptestfest utrecht --SKIPIF-- - + --FILE-- run(function ($host) { diff --git a/tests/swoole_library/curl/setopt/5_skip.phpt b/tests/swoole_curl/setopt/5_skip.phpt similarity index 93% rename from tests/swoole_library/curl/setopt/5_skip.phpt rename to tests/swoole_curl/setopt/5_skip.phpt index e15c5eaeb3e..44ad42479ed 100644 --- a/tests/swoole_library/curl/setopt/5_skip.phpt +++ b/tests/swoole_curl/setopt/5_skip.phpt @@ -5,12 +5,12 @@ WHITE new media architects - Jeroen Vermeulen #testfest Utrecht 2009 --SKIPIF-- --FILE-- + --FILE-- run(function ($host) { diff --git a/tests/swoole_library/curl/setopt/filetime_2.phpt b/tests/swoole_curl/setopt/filetime_2.phpt similarity index 84% rename from tests/swoole_library/curl/setopt/filetime_2.phpt rename to tests/swoole_curl/setopt/filetime_2.phpt index a786c823d1d..946d3b99394 100644 --- a/tests/swoole_library/curl/setopt/filetime_2.phpt +++ b/tests/swoole_curl/setopt/filetime_2.phpt @@ -1,10 +1,10 @@ --TEST-- swoole_library/curl/setopt: CURLOPT_FILETIME [return -1] --SKIPIF-- - + --FILE-- run(function ($host) { diff --git a/tests/swoole_library/curl/setopt/header_out.phpt b/tests/swoole_curl/setopt/header_out.phpt similarity index 89% rename from tests/swoole_library/curl/setopt/header_out.phpt rename to tests/swoole_curl/setopt/header_out.phpt index 565fbc422cb..2ee9c217f46 100644 --- a/tests/swoole_library/curl/setopt/header_out.phpt +++ b/tests/swoole_curl/setopt/header_out.phpt @@ -1,7 +1,7 @@ --TEST-- swoole_library/curl/setopt: CURLINFO_HEADER_OUT --SKIPIF-- - + --FILE-- run(function ($host) { diff --git a/tests/swoole_library/curl/setopt/infile.phpt b/tests/swoole_curl/setopt/infile.phpt similarity index 89% rename from tests/swoole_library/curl/setopt/infile.phpt rename to tests/swoole_curl/setopt/infile.phpt index 0916189f36c..7c26fa8e0f3 100644 --- a/tests/swoole_library/curl/setopt/infile.phpt +++ b/tests/swoole_curl/setopt/infile.phpt @@ -1,10 +1,10 @@ --TEST-- swoole_library/curl/setopt: CURLOPT_INFILE --SKIPIF-- - + --FILE-- run(function ($host) { diff --git a/tests/swoole_library/curl/setopt/nobody.phpt b/tests/swoole_curl/setopt/nobody.phpt similarity index 86% rename from tests/swoole_library/curl/setopt/nobody.phpt rename to tests/swoole_curl/setopt/nobody.phpt index 46a7e6c632e..515a853b4ed 100644 --- a/tests/swoole_library/curl/setopt/nobody.phpt +++ b/tests/swoole_curl/setopt/nobody.phpt @@ -1,7 +1,7 @@ --TEST-- swoole_library/curl/setopt: CURLOPT_NOBODY --SKIPIF-- - + --FILE-- run(function ($host) { diff --git a/tests/swoole_runtime/curl_native/sleep.phpt b/tests/swoole_curl/sleep.phpt similarity index 94% rename from tests/swoole_runtime/curl_native/sleep.phpt rename to tests/swoole_curl/sleep.phpt index 908e30ae427..86e3ec0b0f1 100644 --- a/tests/swoole_runtime/curl_native/sleep.phpt +++ b/tests/swoole_curl/sleep.phpt @@ -2,11 +2,11 @@ swoole_runtime/curl_native: sleep --SKIPIF-- --FILE-- + --FILE-- run(function ($host) { diff --git a/tests/swoole_library/curl/template b/tests/swoole_curl/template similarity index 57% rename from tests/swoole_library/curl/template rename to tests/swoole_curl/template index 8c7bef89e96..f5cc982b0fd 100644 --- a/tests/swoole_library/curl/template +++ b/tests/swoole_curl/template @@ -1,4 +1,4 @@ -require __DIR__ . '/../../../include/bootstrap.php'; +require __DIR__ . '/../../include/bootstrap.php'; $cm = new \SwooleTest\CurlManager(); $cm->run(function ($host) { diff --git a/tests/swoole_runtime/curl_native/timer_coredump.phpt b/tests/swoole_curl/timer_coredump.phpt similarity index 85% rename from tests/swoole_runtime/curl_native/timer_coredump.phpt rename to tests/swoole_curl/timer_coredump.phpt index 0661008833a..4167bf6ddb2 100644 --- a/tests/swoole_runtime/curl_native/timer_coredump.phpt +++ b/tests/swoole_curl/timer_coredump.phpt @@ -2,11 +2,11 @@ swoole_runtime/curl_native: timer coredump --SKIPIF-- --FILE-- + --FILE-- run(function ($host) { @@ -65,17 +65,17 @@ function testcurl($ch, $name, $mime = '', $postname = '') } ?> --EXPECTF-- -string(%d) "curl_testdata1.txt|application/octet-stream" -string(%d) "curl_testdata1.txt|text/plain" -string(%d) "foo.txt|application/octet-stream" -string(%d) "foo.txt|text/plain" +string(%d) "curl_testdata1.txt|application/octet-stream|6" +string(%d) "curl_testdata1.txt|text/plain|6" +string(%d) "foo.txt|application/octet-stream|6" +string(%d) "foo.txt|text/plain|6" string(%d) "text/plain" string(%d) "%s/curl_testdata1.txt" -string(%d) "curl_testdata1.txt|text/plain" +string(%d) "curl_testdata1.txt|text/plain|6" string(%d) "foo.txt" -string(%d) "foo.txt|application/octet-stream" +string(%d) "foo.txt|application/octet-stream|6" -Warning: swoole_curl_setopt(): Disabling safe uploads is no longer supported in %s on line %d +Warning: %s(): Disabling safe uploads is no longer supported in %s on line %d string(0) "" string(0) "" string(%d) "array(1) { diff --git a/tests/swoole_library/curl/upload/curl_testdata1.txt b/tests/swoole_curl/upload/curl_testdata1.txt similarity index 100% rename from tests/swoole_library/curl/upload/curl_testdata1.txt rename to tests/swoole_curl/upload/curl_testdata1.txt diff --git a/tests/swoole_library/curl/upload/curl_testdata2.txt b/tests/swoole_curl/upload/curl_testdata2.txt similarity index 100% rename from tests/swoole_library/curl/upload/curl_testdata2.txt rename to tests/swoole_curl/upload/curl_testdata2.txt diff --git a/tests/swoole_runtime/curl_native/yield_in_callback.phpt b/tests/swoole_curl/yield_in_callback.phpt similarity index 92% rename from tests/swoole_runtime/curl_native/yield_in_callback.phpt rename to tests/swoole_curl/yield_in_callback.phpt index c99465d2579..a5f6781a5b1 100644 --- a/tests/swoole_runtime/curl_native/yield_in_callback.phpt +++ b/tests/swoole_curl/yield_in_callback.phpt @@ -2,11 +2,11 @@ swoole_runtime/curl_native: suspend in callback --SKIPIF-- --FILE-- = 0x070f04 /* 7.15.4 */ +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_swoole_native_curl_multi_setopt, 0, 3, _IS_BOOL, 0) + ZEND_ARG_OBJ_INFO(0, multi_handle, Swoole\\Coroutine\\Curl\\MultiHandle, 0) + ZEND_ARG_TYPE_INFO(0, option, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0) +ZEND_END_ARG_INFO() +#endif + #if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_swoole_native_curl_pause, 0, 2, IS_LONG, 0) ZEND_ARG_OBJ_INFO(0, handle, Swoole\\Coroutine\\Curl\\Handle, 0) @@ -135,12 +143,12 @@ static const zend_function_entry swoole_native_curl_functions[] = { PHP_FE(swoole_native_curl_multi_errno, arginfo_swoole_native_curl_multi_errno) PHP_FE(swoole_native_curl_multi_exec, arginfo_swoole_native_curl_multi_exec) PHP_FE(swoole_native_curl_multi_select, arginfo_swoole_native_curl_multi_select) + PHP_FE(swoole_native_curl_multi_setopt, arginfo_swoole_native_curl_multi_setopt) PHP_FE(swoole_native_curl_multi_getcontent, arginfo_swoole_native_curl_multi_getcontent) PHP_FE(swoole_native_curl_multi_info_read, arginfo_swoole_native_curl_multi_info_read) PHP_FE(swoole_native_curl_multi_init, arginfo_swoole_native_curl_multi_init) PHP_FE(swoole_native_curl_multi_remove_handle, arginfo_swoole_native_curl_multi_remove_handle) - PHP_FE_END }; #endif diff --git a/thirdparty/php/curl/curl_interface.h b/thirdparty/php/curl/curl_interface.h index 8f36226ff17..c7220ee3d63 100644 --- a/thirdparty/php/curl/curl_interface.h +++ b/thirdparty/php/curl/curl_interface.h @@ -39,6 +39,7 @@ PHP_FUNCTION(swoole_native_curl_multi_errno); PHP_FUNCTION(swoole_native_curl_multi_exec); PHP_FUNCTION(swoole_native_curl_multi_select); PHP_FUNCTION(swoole_native_curl_multi_remove_handle); +PHP_FUNCTION(swoole_native_curl_multi_setopt); PHP_FUNCTION(swoole_native_curl_multi_getcontent); PHP_FUNCTION(swoole_native_curl_multi_info_read); PHP_FUNCTION(swoole_native_curl_multi_init); diff --git a/thirdparty/php/curl/curl_private.h b/thirdparty/php/curl/curl_private.h index 8286d07ab7d..e7c8abafc3c 100644 --- a/thirdparty/php/curl/curl_private.h +++ b/thirdparty/php/curl/curl_private.h @@ -44,10 +44,6 @@ #define SAVE_CURL_ERROR(__handle, __err) \ do { (__handle)->err.no = (int) __err; } while (0) -PHP_MINIT_FUNCTION(curl); -PHP_MSHUTDOWN_FUNCTION(curl); -PHP_MINFO_FUNCTION(curl); - typedef struct { zval func_name; zend_fcall_info_cache fci_cache; @@ -178,7 +174,7 @@ int curl_cast_object(zend_object *obj, zval *result, int type); #define Z_CURL_P(zv) _php_curl_get_handle(zv) #endif /* PHP8 end */ -php_curl *_php_curl_get_handle(zval *zid, bool exclusive = true); +php_curl *_php_curl_get_handle(zval *zid, bool exclusive = true, bool required = true); SW_EXTERN_C_BEGIN #if PHP_VERSION_ID < 80000 diff --git a/thirdparty/php/curl/interface.cc b/thirdparty/php/curl/interface.cc index c28a363c23f..8fe185be030 100644 --- a/thirdparty/php/curl/interface.cc +++ b/thirdparty/php/curl/interface.cc @@ -112,20 +112,22 @@ int _php_curl_get_le_curl_multi() { return; #endif -php_curl *_php_curl_get_handle(zval *zid, bool exclusive) { +php_curl *_php_curl_get_handle(zval *zid, bool exclusive, bool required) { php_curl *ch; #if PHP_VERSION_ID >= 80000 ch = Z_CURL_P(zid); #else if ((ch = (php_curl *) zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { - swFatalError(SW_ERROR_INVALID_PARAMS, "supplied resource is not a valid " le_curl_name "Handle resource "); + if (required) { + swFatalError(SW_ERROR_INVALID_PARAMS, "supplied resource is not a valid " le_curl_name " resource"); + } return nullptr; } #endif if (exclusive) { swoole::curl::Handle *handle = nullptr; curl_easy_getinfo(ch->cp, CURLINFO_PRIVATE, &handle); - if (handle && handle->multi->check_bound_co() == nullptr) { + if (handle && handle->multi && handle->multi->check_bound_co() == nullptr) { return nullptr; } } @@ -2674,22 +2676,7 @@ PHP_FUNCTION(swoole_native_curl_close) { } /* }}} */ -#if PHP_VERSION_ID >= 80000 -static void curl_free_obj(zend_object *object) { - php_curl *ch = curl_from_obj(object); - -#if PHP_CURL_DEBUG - fprintf(stderr, "DTOR CALLED, ch = %x\n", ch); -#endif - - if (!ch->cp) { - /* Can happen if constructor throws. */ - zend_object_std_dtor(&ch->std); - return; - } - - _php_curl_verify_handlers(ch, 0); - +void _php_curl_free(php_curl *ch) { /* * Libcurl is doing connection caching. When easy handle is cleaned up, * if the handle was previously used by the curl_multi_api, the connection @@ -2704,7 +2691,9 @@ static void curl_free_obj(zend_object *object) { curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_nothing); curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write_nothing); - curl_easy_cleanup(ch->cp); + if (ch->cp != NULL) { + curl_easy_cleanup(ch->cp); + } /* cURL destructors should be invoked only by last curl handle */ if (--(*ch->clone) == 0) { @@ -2715,6 +2704,11 @@ static void curl_free_obj(zend_object *object) { efree(ch->to_free->slist); efree(ch->to_free); efree(ch->clone); + + swoole::curl::Handle *handle = nullptr; + curl_easy_getinfo(ch->cp, CURLINFO_PRIVATE, &handle); + delete handle; + curl_easy_setopt(ch->cp, CURLOPT_PRIVATE, nullptr); } smart_str_free(&ch->handlers->write->buf); @@ -2723,7 +2717,7 @@ static void curl_free_obj(zend_object *object) { zval_ptr_dtor(&ch->handlers->write_header->func_name); zval_ptr_dtor(&ch->handlers->std_err); if (ch->header.str) { - zend_string_release_ex(ch->header.str, 0); + zend_string_release(ch->header.str); } zval_ptr_dtor(&ch->handlers->write_header->stream); @@ -2747,9 +2741,29 @@ static void curl_free_obj(zend_object *object) { efree(ch->handlers); zval_ptr_dtor(&ch->postfields); +#if PHP_VERSION_ID >= 80000 if (ch->share) { OBJ_RELEASE(&ch->share->std); } +#endif +} + +#if PHP_VERSION_ID >= 80000 +static void curl_free_obj(zend_object *object) { + php_curl *ch = curl_from_obj(object); + +#if PHP_CURL_DEBUG + fprintf(stderr, "DTOR CALLED, ch = %x\n", ch); +#endif + + if (!ch->cp) { + /* Can happen if constructor throws. */ + zend_object_std_dtor(&ch->std); + return; + } + + _php_curl_verify_handlers(ch, 0); + _php_curl_free(ch); zend_object_std_dtor(&ch->std); } @@ -2764,69 +2778,7 @@ void _php_curl_close_ex(php_curl *ch) { #endif _php_curl_verify_handlers(ch, 0); - - /* - * Libcurl is doing connection caching. When easy handle is cleaned up, - * if the handle was previously used by the curl_multi_api, the connection - * remains open un the curl multi handle is cleaned up. Some protocols are - * sending content like the FTP one, and libcurl try to use the - * WRITEFUNCTION or the HEADERFUNCTION. Since structures used in those - * callback are freed, we need to use an other callback to which avoid - * segfaults. - * - * Libcurl commit d021f2e8a00 fix this issue and should be part of 7.28.2 - */ - if (ch->cp != NULL) { - curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, fn_write_nothing); - curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, fn_write_nothing); - - curl_easy_cleanup(ch->cp); - } - - /* cURL destructors should be invoked only by last curl handle */ - if (--(*ch->clone) == 0) { - zend_llist_clean(&ch->to_free->str); - zend_llist_clean(&ch->to_free->post); - zend_llist_clean(&ch->to_free->stream); - zend_hash_destroy(ch->to_free->slist); - efree(ch->to_free->slist); - efree(ch->to_free); - efree(ch->clone); - } - - smart_str_free(&ch->handlers->write->buf); - zval_ptr_dtor(&ch->handlers->write->func_name); - zval_ptr_dtor(&ch->handlers->read->func_name); - zval_ptr_dtor(&ch->handlers->write_header->func_name); - zval_ptr_dtor(&ch->handlers->std_err); - if (ch->header.str) { - zend_string_release(ch->header.str); - } - - zval_ptr_dtor(&ch->handlers->write_header->stream); - zval_ptr_dtor(&ch->handlers->write->stream); - zval_ptr_dtor(&ch->handlers->read->stream); - - efree(ch->handlers->write); - efree(ch->handlers->write_header); - efree(ch->handlers->read); - - if (ch->handlers->progress) { - zval_ptr_dtor(&ch->handlers->progress->func_name); - efree(ch->handlers->progress); - } - -#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */ - if (ch->handlers->fnmatch) { - zval_ptr_dtor(&ch->handlers->fnmatch->func_name); - efree(ch->handlers->fnmatch); - } -#endif - - efree(ch->handlers); -#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ - zval_ptr_dtor(&ch->postfields); -#endif + _php_curl_free(ch); efree(ch); } /* }}} */ diff --git a/thirdparty/php/curl/multi.cc b/thirdparty/php/curl/multi.cc index 8a120a6dab2..56c366dfbe1 100644 --- a/thirdparty/php/curl/multi.cc +++ b/thirdparty/php/curl/multi.cc @@ -49,7 +49,7 @@ static inline php_curlm *Z_CURL_MULTI_P(zval *zv) { if ((cm = (php_curlm *) zend_fetch_resource( Z_RES_P(zv), le_curl_multi_handle_name, _php_curl_get_le_curl_multi())) == NULL) { swFatalError(SW_ERROR_INVALID_PARAMS, - "supplied resource is not a valid " le_curl_multi_handle_name "Handle resource "); + "supplied resource is not a valid " le_curl_multi_handle_name " resource"); return nullptr; } return cm; @@ -140,10 +140,14 @@ static zval *_php_curl_multi_find_easy_handle(php_curlm *mh, CURL *easy) /* {{{ zval *pz_ch_temp; for (pz_ch_temp = (zval *) zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch_temp; - pz_ch_temp = (zval *) zend_llist_get_next_ex(&mh->easyh, &pos)) { - tmp_ch = Z_CURL_P(pz_ch_temp); - - if (tmp_ch->cp == easy) { + pz_ch_temp = (zval *) zend_llist_get_next_ex(&mh->easyh, &pos)) { +#if PHP_VERSION_ID < 80000 + if (!Z_RES_P(pz_ch_temp)->ptr) { + continue; + } +#endif + tmp_ch = _php_curl_get_handle(pz_ch_temp, false, false); + if (tmp_ch && tmp_ch->cp == easy) { return pz_ch_temp; } } @@ -232,8 +236,12 @@ PHP_FUNCTION(swoole_native_curl_multi_exec) { for (pz_ch = (zval *) zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch; pz_ch = (zval *) zend_llist_get_next_ex(&mh->easyh, &pos)) { +#if PHP_VERSION_ID < 80000 + if (!Z_RES_P(pz_ch)->ptr) { + continue; + } +#endif ch = Z_CURL_P(pz_ch); - _php_curl_verify_handlers(ch, 1); } } @@ -323,9 +331,10 @@ PHP_FUNCTION(swoole_native_curl_multi_info_read) { zval *pz_ch = _php_curl_multi_find_easy_handle(mh, tmp_msg->easy_handle); if (pz_ch != NULL) { /* we must save result to be able to read error message */ - ch = Z_CURL_P(pz_ch); - SAVE_CURL_ERROR(ch, tmp_msg->data.result); - + ch = _php_curl_get_handle(pz_ch, false, false); + if (ch) { + SAVE_CURL_ERROR(ch, tmp_msg->data.result); + } Z_ADDREF_P(pz_ch); add_assoc_zval(return_value, "handle", pz_ch); } @@ -353,7 +362,15 @@ PHP_FUNCTION(swoole_native_curl_multi_close) { for (pz_ch = (zval *) zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch; pz_ch = (zval *) zend_llist_get_next_ex(&mh->easyh, &pos)) { +#if PHP_VERSION_ID < 80000 + if (!Z_RES_P(pz_ch)->ptr) { + continue; + } +#endif php_curl *ch = Z_CURL_P(pz_ch); + if (!ch) { + continue; + } _php_curl_verify_handlers(ch, 1); mh->multi->remove_handle(ch->cp); } @@ -704,7 +721,12 @@ static void _php_curl_multi_free(php_curlm *mh) { for (zend_llist_element *element = mh->easyh.head; element; element = element->next) { zval *z_ch = (zval *) element->data; php_curl *ch; - if ((ch = _php_curl_get_handle(z_ch, false))) { +#if PHP_VERSION_ID < 80000 + if (!Z_RES_P(z_ch)->ptr) { + continue; + } +#endif + if ((ch = _php_curl_get_handle(z_ch, true, false))) { _php_curl_verify_handlers(ch, 0); mh->multi->remove_handle(ch->cp); } diff --git a/thirdparty/php/curl/php_curl.h b/thirdparty/php/curl/php_curl.h index 809d2bab7d6..05bab093965 100644 --- a/thirdparty/php/curl/php_curl.h +++ b/thirdparty/php/curl/php_curl.h @@ -53,9 +53,9 @@ #define PHP_CURL_IGNORE 7 #if PHP_VERSION_ID < 80000 -#define le_curl_name "Swoole-Coroutine-cURL Handle" -#define le_curl_multi_handle_name "Swoole-Coroutine-cURL Multi Handle" -#define le_curl_share_handle_name "Swoole-Coroutine-cURL Share Handle" +#define le_curl_name "Swoole-Coroutine-cURL-Handle" +#define le_curl_multi_handle_name "Swoole-Coroutine-cURL-Multi-Handle" +#define le_curl_share_handle_name "Swoole-Coroutine-cURL-Share-Handle" #endif #if PHP_VERSION_ID >= 80000 diff --git a/thirdparty/php/standard/proc_open.cc b/thirdparty/php/standard/proc_open.cc index 8903e977ed5..8a05a34181c 100644 --- a/thirdparty/php/standard/proc_open.cc +++ b/thirdparty/php/standard/proc_open.cc @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 7 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2018 The PHP Group | + | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -24,6 +24,13 @@ using swoole::Coroutine; using swoole::PHPCoroutine; using swoole::coroutine::Socket; +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif + static int le_proc_open; static const char *le_proc_name = "process/coroutine"; @@ -34,7 +41,7 @@ static proc_co_env_t _php_array_to_envp(zval *environment) { zend_string *key, *str; char **ep; char *p; - size_t cnt, l, sizeenv = 0; + size_t cnt, sizeenv = 0; HashTable *env_hash; memset(&env, 0, sizeof(env)); @@ -77,26 +84,22 @@ static proc_co_env_t _php_array_to_envp(zval *environment) { ep = env.envarray = (char **) ecalloc(cnt + 1, sizeof(char *)); p = env.envp = (char *) ecalloc(sizeenv + 4, 1); - void *_v1, *_v2; - ZEND_HASH_FOREACH_STR_KEY_PTR(env_hash, _v1, _v2) { - key = (zend_string *) _v1; - str = (zend_string *) _v2; + void *v1, *v2; + ZEND_HASH_FOREACH_STR_KEY_PTR(env_hash, v1, v2) { + key = (zend_string *) v1; + str = (zend_string *) v2; + *ep = p; + ++ep; if (key) { - l = ZSTR_LEN(key) + ZSTR_LEN(str) + 2; memcpy(p, ZSTR_VAL(key), ZSTR_LEN(key)); - strcat(p, "="); - strncat(p, ZSTR_VAL(str), ZSTR_LEN(str)); - - *ep = p; - ++ep; - p += l; - } else { - memcpy(p, ZSTR_VAL(str), ZSTR_LEN(str)); - *ep = p; - ++ep; - p += ZSTR_LEN(str) + 1; + p += ZSTR_LEN(key); + *p++ = '='; } + + memcpy(p, ZSTR_VAL(str), ZSTR_LEN(str)); + p += ZSTR_LEN(str); + *p++ = '\0'; zend_string_release(str); } ZEND_HASH_FOREACH_END(); @@ -111,12 +114,12 @@ static proc_co_env_t _php_array_to_envp(zval *environment) { /* }}} */ /* {{{ _php_free_envp */ -static void _php_free_envp(proc_co_env_t env) { +static void _php_free_envp(proc_co_env_t env, int is_persistent) { if (env.envarray) { - efree(env.envarray); + pefree(env.envarray, is_persistent); } if (env.envp) { - efree(env.envp); + pefree(env.envp, is_persistent); } } /* }}} */ @@ -144,7 +147,7 @@ static void proc_co_rsrc_dtor(zend_resource *rsrc) { *proc->wstatus = wstatus; } - _php_free_envp(proc->env); + _php_free_envp(proc->env, proc->is_persistent); efree(proc->pipes); efree(proc->command); efree(proc); @@ -249,6 +252,7 @@ PHP_FUNCTION(swoole_proc_get_status) { #define DESC_PIPE 1 #define DESC_FILE 2 +#define DESC_REDIRECT 3 #define DESC_PARENT_MODE_WRITE 8 struct php_proc_open_descriptor_item { @@ -259,11 +263,27 @@ struct php_proc_open_descriptor_item { }; /* }}} */ -/* {{{ proto resource proc_open(string command, array descriptorspec, array &pipes [, string cwd [, array env [, array - other_options]]]) Run a process with more control over it's file descriptors */ +static zend_string *get_valid_arg_string(zval *zv, int elem_num) { + zend_string *str = zval_get_string(zv); + if (!str) { + return NULL; + } + + if (strlen(ZSTR_VAL(str)) != ZSTR_LEN(str)) { + php_error_docref(NULL, E_WARNING, "Command array element %d contains a null byte", elem_num); + zend_string_release(str); + return NULL; + } + + return str; +} + +/* {{{ proto resource proc_open(string|array command, array descriptorspec, array &pipes [, string cwd [, array env [, + array other_options]]]) Run a process with more control over it's file descriptors */ PHP_FUNCTION(swoole_proc_open) { - char *command, *cwd = NULL; - size_t command_len, cwd_len = 0; + zval *command_zv; + char *command = NULL, *cwd = NULL; + size_t cwd_len = 0; zval *descriptorspec; zval *pipes; zval *environment = NULL; @@ -277,11 +297,14 @@ PHP_FUNCTION(swoole_proc_open) { struct php_proc_open_descriptor_item *descriptors = NULL; int ndescriptors_array; + char **argv = NULL; + pid_t child; proc_co_t *proc; + int is_persistent = 0; /* TODO: ensure that persistent procs will work */ ZEND_PARSE_PARAMETERS_START(3, 6) - Z_PARAM_STRING(command, command_len) + Z_PARAM_ZVAL(command_zv) Z_PARAM_ARRAY(descriptorspec) #if PHP_VERSION_ID >= 70400 Z_PARAM_ZVAL(pipes) @@ -294,6 +317,42 @@ PHP_FUNCTION(swoole_proc_open) { Z_PARAM_ARRAY_EX(other_options, 1, 0) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + memset(&env, 0, sizeof(env)); + + if (Z_TYPE_P(command_zv) == IS_ARRAY) { + zval *arg_zv; + uint32_t num_elems = zend_hash_num_elements(Z_ARRVAL_P(command_zv)); + if (num_elems == 0) { + php_error_docref(NULL, E_WARNING, "Command array must have at least one element"); + RETURN_FALSE; + } + + argv = (char **) safe_emalloc(sizeof(char *), num_elems + 1, 0); + i = 0; + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(command_zv), arg_zv) { + zend_string *arg_str = get_valid_arg_string(arg_zv, i + 1); + if (!arg_str) { + argv[i] = NULL; + goto exit_fail; + } + + if (i == 0) { + command = pestrdup(ZSTR_VAL(arg_str), is_persistent); + } + + argv[i++] = estrdup(ZSTR_VAL(arg_str)); + zend_string_release(arg_str); + } + ZEND_HASH_FOREACH_END(); + argv[i] = NULL; + + /* As the array is non-empty, we should have found a command. */ + ZEND_ASSERT(command); + } else { + convert_to_string(command_zv); + command = pestrdup(Z_STRVAL_P(command_zv), is_persistent); + } + php_swoole_check_reactor(); if (php_swoole_signal_isset_handler(SIGCHLD)) { php_swoole_error(E_WARNING, "The signal [SIGCHLD] is registered, cannot execute swoole_proc_open"); @@ -304,8 +363,6 @@ PHP_FUNCTION(swoole_proc_open) { command = estrdup(command); - command_len = strlen(command); - if (environment) { env = _php_array_to_envp(environment); } else { @@ -364,7 +421,7 @@ PHP_FUNCTION(swoole_proc_open) { } if (strcmp(Z_STRVAL_P(ztype), "pipe") == 0) { - int newpipe[2]; + php_file_descriptor_t newpipe[2]; zval *zmode; if ((zmode = zend_hash_index_find(Z_ARRVAL_P(descitem), 1)) != NULL) { @@ -399,14 +456,26 @@ PHP_FUNCTION(swoole_proc_open) { descriptors[ndesc].mode = DESC_FILE; if ((zfile = zend_hash_index_find(Z_ARRVAL_P(descitem), 1)) != NULL) { +#if PHP_VERSION_ID >= 70400 + if (!try_convert_to_string(zfile)) { + goto exit_fail; + } +#else convert_to_string_ex(zfile); +#endif } else { php_swoole_fatal_error(E_WARNING, "Missing file name parameter for 'file'"); goto exit_fail; } if ((zmode = zend_hash_index_find(Z_ARRVAL_P(descitem), 2)) != NULL) { +#if PHP_VERSION_ID >= 70400 + if (!try_convert_to_string(zmode)) { + goto exit_fail; + } +#else convert_to_string_ex(zmode); +#endif } else { php_swoole_fatal_error(E_WARNING, "Missing mode parameter for 'file'"); goto exit_fail; @@ -424,6 +493,94 @@ PHP_FUNCTION(swoole_proc_open) { } descriptors[ndesc].childend = fd; + } else if (strcmp(Z_STRVAL_P(ztype), "redirect") == 0) { + zval *ztarget = zend_hash_index_find_deref(Z_ARRVAL_P(descitem), 1); + struct php_proc_open_descriptor_item *target = NULL; + php_file_descriptor_t childend; + + if (!ztarget) { + php_error_docref(NULL, E_WARNING, "Missing redirection target"); + goto exit_fail; + } + if (Z_TYPE_P(ztarget) != IS_LONG) { + php_error_docref(NULL, E_WARNING, "Redirection target must be an integer"); + goto exit_fail; + } + + for (i = 0; i < ndesc; i++) { + if (descriptors[i].index == Z_LVAL_P(ztarget)) { + target = &descriptors[i]; + break; + } + } + if (target) { + childend = target->childend; + } else { + if (Z_LVAL_P(ztarget) < 0 || Z_LVAL_P(ztarget) > 2) { + php_error_docref( + NULL, E_WARNING, "Redirection target " ZEND_LONG_FMT " not found", Z_LVAL_P(ztarget)); + goto exit_fail; + } + + /* Support referring to a stdin/stdout/stderr pipe adopted from the parent, + * which happens whenever an explicit override is not provided. */ +#ifndef PHP_WIN32 + childend = Z_LVAL_P(ztarget); +#else + switch (Z_LVAL_P(ztarget)) { + case 0: + childend = GetStdHandle(STD_INPUT_HANDLE); + break; + case 1: + childend = GetStdHandle(STD_OUTPUT_HANDLE); + break; + case 2: + childend = GetStdHandle(STD_ERROR_HANDLE); + break; + EMPTY_SWITCH_DEFAULT_CASE() + } +#endif + } + +#ifdef PHP_WIN32 + descriptors[ndesc].childend = dup_handle(childend, TRUE, FALSE); + if (descriptors[ndesc].childend == NULL) { + php_error_docref(NULL, E_WARNING, "Failed to dup() for descriptor " ZEND_LONG_FMT, nindex); + goto exit_fail; + } +#else + descriptors[ndesc].childend = dup(childend); + if (descriptors[ndesc].childend < 0) { + php_error_docref(NULL, + E_WARNING, + "Failed to dup() for descriptor " ZEND_LONG_FMT " - %s", + nindex, + strerror(errno)); + goto exit_fail; + } +#endif + descriptors[ndesc].mode = DESC_REDIRECT; + } else if (strcmp(Z_STRVAL_P(ztype), "null") == 0) { +#ifndef PHP_WIN32 + descriptors[ndesc].childend = open("/dev/null", O_RDWR); + if (descriptors[ndesc].childend < 0) { + php_error_docref(NULL, E_WARNING, "Failed to open /dev/null - %s", strerror(errno)); + goto exit_fail; + } +#else + descriptors[ndesc].childend = CreateFileA("nul", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL); + if (descriptors[ndesc].childend == NULL) { + php_error_docref(NULL, E_WARNING, "Failed to open nul"); + goto exit_fail; + } +#endif + descriptors[ndesc].mode = DESC_FILE; } else if (strcmp(Z_STRVAL_P(ztype), "pty") == 0) { php_swoole_fatal_error(E_WARNING, "pty pseudo terminal not supported on this system"); goto exit_fail; @@ -463,10 +620,18 @@ PHP_FUNCTION(swoole_proc_open) { php_ignore_value(chdir(cwd)); } - if (env.envarray) { - execle("/bin/sh", "sh", "-c", command, NULL, env.envarray); + if (argv) { + /* execvpe() is non-portable, use environ instead. */ + if (env.envarray) { + environ = env.envarray; + } + execvp(command, argv); } else { - execl("/bin/sh", "sh", "-c", command, NULL); + if (env.envarray) { + execle("/bin/sh", "sh", "-c", command, NULL, env.envarray); + } else { + execl("/bin/sh", "sh", "-c", command, NULL); + } } _exit(127); @@ -488,15 +653,6 @@ PHP_FUNCTION(swoole_proc_open) { /* we forked/spawned and this is the parent */ - proc = (proc_co_t *) emalloc(sizeof(proc_co_t)); - proc->wstatus = nullptr; - proc->command = command; - proc->pipes = (zend_resource **) emalloc(sizeof(zend_resource *) * ndesc); - proc->npipes = ndesc; - proc->child = child; - proc->env = env; - proc->running = true; - #if PHP_VERSION_ID >= 70400 pipes = zend_try_array_init(pipes); if (!pipes) { @@ -507,6 +663,16 @@ PHP_FUNCTION(swoole_proc_open) { array_init(pipes); #endif + proc = (proc_co_t *) pemalloc(sizeof(proc_co_t), is_persistent); + proc->is_persistent = is_persistent; + proc->wstatus = nullptr; + proc->running = true; + proc->command = command; + proc->pipes = (zend_resource **) emalloc(sizeof(zend_resource *) * ndesc); + proc->npipes = ndesc; + proc->child = child; + proc->env = env; + /* clean up all the child ends and then open streams on the parent * ends, where appropriate */ for (i = 0; i < ndesc; i++) { @@ -537,15 +703,35 @@ PHP_FUNCTION(swoole_proc_open) { } } + if (argv) { + char **arg = argv; + while (*arg != NULL) { + efree(*arg); + arg++; + } + efree(argv); + } + efree(descriptors); ZVAL_RES(return_value, zend_register_resource(proc, le_proc_open)); return; exit_fail: - efree(descriptors); - _php_free_envp(env); - efree(command); - + if (descriptors) { + efree(descriptors); + } + _php_free_envp(env, is_persistent); + if (command) { + pefree(command, is_persistent); + } + if (argv) { + char **arg = argv; + while (*arg != NULL) { + efree(*arg); + arg++; + } + efree(argv); + } RETURN_FALSE; } /* }}} */ diff --git a/thirdparty/php/standard/proc_open.h b/thirdparty/php/standard/proc_open.h index 05e4ac30ffa..393c72591c5 100644 --- a/thirdparty/php/standard/proc_open.h +++ b/thirdparty/php/standard/proc_open.h @@ -8,6 +8,8 @@ PHP_FUNCTION(swoole_proc_get_status); PHP_FUNCTION(swoole_proc_terminate); } +typedef int php_file_descriptor_t; + void swoole_proc_open_init(int module_number); struct proc_co_env_t @@ -24,5 +26,6 @@ struct proc_co_t int *wstatus; zend_resource **pipes; char *command; + int is_persistent; proc_co_env_t env; }; diff --git a/travis/docker-compile.sh b/travis/docker-compile.sh index d770337f23f..7d529ffac25 100755 --- a/travis/docker-compile.sh +++ b/travis/docker-compile.sh @@ -27,4 +27,6 @@ make -j8 > /dev/null | tee /tmp/compile.log && \ (test "`cat /tmp/compile.log`"x = ""x || exit 255) && \ make install && echo "" && \ docker-php-ext-enable swoole && \ +php --ri curl && \ php --ri swoole + diff --git a/travis/simple-compile-on-github.sh b/travis/simple-compile-on-github.sh index d156948e639..bb96ad99533 100755 --- a/travis/simple-compile-on-github.sh +++ b/travis/simple-compile-on-github.sh @@ -15,4 +15,5 @@ phpize > /dev/null && \ make -j8 > /dev/null | tee /tmp/compile.log && \ (test "`cat /tmp/compile.log`"x = ""x || exit 255) && \ make install && \ +php --ri curl && \ php -d extension=swoole.so --ri swoole From 6042d15eef71300768a03cff9ba92bd0162bded9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Tue, 6 Apr 2021 22:33:25 +0800 Subject: [PATCH 096/936] Update curl tests (#4130) --- tests/swoole_curl/basic/1.phpt | 2 +- tests/swoole_curl/basic/10.phpt | 2 +- tests/swoole_curl/basic/11.phpt | 2 +- tests/swoole_curl/basic/12.phpt | 2 +- tests/swoole_curl/basic/13.phpt | 2 +- tests/swoole_curl/basic/14.phpt | 2 +- tests/swoole_curl/basic/15.phpt | 2 +- tests/swoole_curl/basic/19.phpt | 2 +- tests/swoole_curl/basic/2.phpt | 2 +- tests/swoole_curl/basic/20.phpt | 2 +- tests/swoole_curl/basic/21.phpt | 2 +- tests/swoole_curl/basic/22.phpt | 2 +- tests/swoole_curl/basic/23.phpt | 2 +- tests/swoole_curl/basic/24.phpt | 2 +- tests/swoole_curl/basic/25.phpt | 2 +- tests/swoole_curl/basic/3.phpt | 2 +- tests/swoole_curl/basic/4.phpt | 2 +- tests/swoole_curl/basic/5.phpt | 2 +- tests/swoole_curl/basic/7.phpt | 2 +- tests/swoole_curl/basic/8.phpt | 2 +- tests/swoole_curl/basic/9.phpt | 2 +- tests/swoole_curl/close_before_resume.phpt | 2 +- tests/swoole_curl/concurrent.phpt | 2 +- tests/swoole_curl/error.phpt | 2 +- tests/swoole_curl/exec_twice.phpt | 2 +- tests/swoole_curl/guzzle.phpt | 2 +- tests/swoole_curl/guzzle/cancel.phpt | 2 +- .../guzzle/cannot_cancel_finished.phpt | 2 +- tests/swoole_curl/guzzle/cookie.phpt | 2 +- tests/swoole_curl/guzzle/promise.phpt | 43 +++++++++++++++++++ tests/swoole_curl/guzzle/request_async.phpt | 2 +- .../swoole_curl/guzzle/request_on_stats.phpt | 2 +- tests/swoole_curl/guzzle/send_async.phpt | 2 +- tests/swoole_curl/https.phpt | 2 +- tests/swoole_curl/multi_1.phpt | 2 +- tests/swoole_curl/multi_2.phpt | 2 +- tests/swoole_curl/multi_3.phpt | 2 +- tests/swoole_curl/multi_4.phpt | 2 +- tests/swoole_curl/multi_close.phpt | 2 +- tests/swoole_curl/multi_dtor.phpt | 2 +- tests/swoole_curl/non_exclusive.phpt | 2 +- tests/swoole_curl/select_twice.phpt | 2 +- tests/swoole_curl/setopt/1.phpt | 2 +- tests/swoole_curl/setopt/3.phpt | 2 +- tests/swoole_curl/setopt/4.phpt | 2 +- tests/swoole_curl/setopt/5_skip.phpt | 2 +- tests/swoole_curl/setopt/filetime_1.phpt | 2 +- tests/swoole_curl/setopt/filetime_2.phpt | 2 +- tests/swoole_curl/setopt/header_out.phpt | 2 +- tests/swoole_curl/setopt/infile.phpt | 2 +- tests/swoole_curl/setopt/nobody.phpt | 2 +- tests/swoole_curl/sleep.phpt | 2 +- tests/swoole_curl/ssl/version.phpt | 2 +- tests/swoole_curl/timer_coredump.phpt | 2 +- tests/swoole_curl/yield_in_callback.phpt | 2 +- 55 files changed, 97 insertions(+), 54 deletions(-) create mode 100644 tests/swoole_curl/guzzle/promise.phpt diff --git a/tests/swoole_curl/basic/1.phpt b/tests/swoole_curl/basic/1.phpt index 0c159de8c27..878d22384b8 100644 --- a/tests/swoole_curl/basic/1.phpt +++ b/tests/swoole_curl/basic/1.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_exec() function with basic functionality +swoole_curl/basic: Test curl_exec() function with basic functionality --CREDITS-- Sebastian Deutsch diff --git a/tests/swoole_curl/basic/10.phpt b/tests/swoole_curl/basic/10.phpt index 7b27a547301..a99aa7248f7 100644 --- a/tests/swoole_curl/basic/10.phpt +++ b/tests/swoole_curl/basic/10.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_error() & curl_errno() function with problematic proxy +swoole_curl/basic: Test curl_error() & curl_errno() function with problematic proxy --CREDITS-- TestFest 2009 - AFUP - Perrick Penet --SKIPIF-- diff --git a/tests/swoole_curl/basic/11.phpt b/tests/swoole_curl/basic/11.phpt index 8c3ca660b52..7c64ff0cf73 100644 --- a/tests/swoole_curl/basic/11.phpt +++ b/tests/swoole_curl/basic/11.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_opt() function with COOKIE +swoole_curl/basic: Test curl_opt() function with COOKIE --CREDITS-- TestFest 2009 - AFUP - Xavier Gorse --SKIPIF-- diff --git a/tests/swoole_curl/basic/12.phpt b/tests/swoole_curl/basic/12.phpt index a6df67c6660..546dad2464f 100644 --- a/tests/swoole_curl/basic/12.phpt +++ b/tests/swoole_curl/basic/12.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_opt() function with CURLOPT_HTTP_VERSION/CURL_HTTP_VERSION_1_0 +swoole_curl/basic: Test curl_opt() function with CURLOPT_HTTP_VERSION/CURL_HTTP_VERSION_1_0 --CREDITS-- TestFest 2009 - AFUP - Xavier Gorse --SKIPIF-- diff --git a/tests/swoole_curl/basic/13.phpt b/tests/swoole_curl/basic/13.phpt index 27e38c74597..c1acdb1d393 100644 --- a/tests/swoole_curl/basic/13.phpt +++ b/tests/swoole_curl/basic/13.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_opt() function with CURLOPT_HTTP_VERSION/CURL_HTTP_VERSION_1_1 +swoole_curl/basic: Test curl_opt() function with CURLOPT_HTTP_VERSION/CURL_HTTP_VERSION_1_1 --CREDITS-- TestFest 2009 - AFUP - Xavier Gorse --SKIPIF-- diff --git a/tests/swoole_curl/basic/14.phpt b/tests/swoole_curl/basic/14.phpt index 7b523cd8562..8e950a2fbf8 100644 --- a/tests/swoole_curl/basic/14.phpt +++ b/tests/swoole_curl/basic/14.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_init() function with basic functionality +swoole_curl/basic: Test curl_init() function with basic functionality --CREDITS-- Jean-Marc Fontaine --SKIPIF-- diff --git a/tests/swoole_curl/basic/15.phpt b/tests/swoole_curl/basic/15.phpt index e42bfaefec4..173b54f6c37 100644 --- a/tests/swoole_curl/basic/15.phpt +++ b/tests/swoole_curl/basic/15.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_init() function with $url parameter defined +swoole_curl/basic: Test curl_init() function with $url parameter defined --CREDITS-- Jean-Marc Fontaine --SKIPIF-- diff --git a/tests/swoole_curl/basic/19.phpt b/tests/swoole_curl/basic/19.phpt index 169363663ac..7829ff2fd58 100644 --- a/tests/swoole_curl/basic/19.phpt +++ b/tests/swoole_curl/basic/19.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_getinfo() function with CURLINFO_EFFECTIVE_URL parameter +swoole_curl/basic: Test curl_getinfo() function with CURLINFO_EFFECTIVE_URL parameter --CREDITS-- Jean-Marc Fontaine --SKIPIF-- diff --git a/tests/swoole_curl/basic/2.phpt b/tests/swoole_curl/basic/2.phpt index 987c40e54f9..cc405dbcb92 100644 --- a/tests/swoole_curl/basic/2.phpt +++ b/tests/swoole_curl/basic/2.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_opt() function with CURLOPT_RETURNTRANSFER parameter set to 1 +swoole_curl/basic: Test curl_opt() function with CURLOPT_RETURNTRANSFER parameter set to 1 --CREDITS-- Sebastian Deutsch TestFest 2009 - AFUP - Jean-Marc Fontaine diff --git a/tests/swoole_curl/basic/20.phpt b/tests/swoole_curl/basic/20.phpt index 642a06cdba4..b74a347c675 100644 --- a/tests/swoole_curl/basic/20.phpt +++ b/tests/swoole_curl/basic/20.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_getinfo() function with CURLINFO_HTTP_CODE parameter +swoole_curl/basic: Test curl_getinfo() function with CURLINFO_HTTP_CODE parameter --CREDITS-- Jean-Marc Fontaine --SKIPIF-- diff --git a/tests/swoole_curl/basic/21.phpt b/tests/swoole_curl/basic/21.phpt index 7c42ef3a1a7..4bc35b1b8d8 100644 --- a/tests/swoole_curl/basic/21.phpt +++ b/tests/swoole_curl/basic/21.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_getinfo() function with CURLINFO_CONTENT_TYPE parameter +swoole_curl/basic: Test curl_getinfo() function with CURLINFO_CONTENT_TYPE parameter --CREDITS-- Jean-Marc Fontaine --SKIPIF-- diff --git a/tests/swoole_curl/basic/22.phpt b/tests/swoole_curl/basic/22.phpt index 5e9a8a18e33..2aa6ab5c3bf 100644 --- a/tests/swoole_curl/basic/22.phpt +++ b/tests/swoole_curl/basic/22.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_setopt() function with CURLOPT_FOLLOWLOCATION parameter +swoole_curl/basic: Test curl_setopt() function with CURLOPT_FOLLOWLOCATION parameter --CREDITS-- Jean-Marc Fontaine --SKIPIF-- diff --git a/tests/swoole_curl/basic/23.phpt b/tests/swoole_curl/basic/23.phpt index 5ab78002993..f8d1e1689c6 100644 --- a/tests/swoole_curl/basic/23.phpt +++ b/tests/swoole_curl/basic/23.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_setopt() function with CURLOPT_HEADER parameter set to 1 +swoole_curl/basic: Test curl_setopt() function with CURLOPT_HEADER parameter set to 1 --CREDITS-- Jean-Marc Fontaine --SKIPIF-- diff --git a/tests/swoole_curl/basic/24.phpt b/tests/swoole_curl/basic/24.phpt index 49e7f57a7cb..b6d351d46ed 100644 --- a/tests/swoole_curl/basic/24.phpt +++ b/tests/swoole_curl/basic/24.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_opt() function with setting auto referer +swoole_curl/basic: Test curl_opt() function with setting auto referer --CREDITS-- Sebastian Deutsch TestFest 2009 - AFUP - Jean-Marc Fontaine diff --git a/tests/swoole_curl/basic/25.phpt b/tests/swoole_curl/basic/25.phpt index a4176f17944..baffab1e8e7 100644 --- a/tests/swoole_curl/basic/25.phpt +++ b/tests/swoole_curl/basic/25.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_multi_getcontent() function +swoole_curl/basic: Test curl_multi_getcontent() function --CREDITS-- Sebastian Deutsch TestFest 2009 - AFUP - Jean-Marc Fontaine diff --git a/tests/swoole_curl/basic/3.phpt b/tests/swoole_curl/basic/3.phpt index c4196924ed8..134dbd876e7 100644 --- a/tests/swoole_curl/basic/3.phpt +++ b/tests/swoole_curl/basic/3.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_opt() function with POST parameters +swoole_curl/basic: Test curl_opt() function with POST parameters --CREDITS-- Sebastian Deutsch TestFest 2009 - AFUP - Jean-Marc Fontaine diff --git a/tests/swoole_curl/basic/4.phpt b/tests/swoole_curl/basic/4.phpt index 0ee70d9a6f6..9595dcc176d 100644 --- a/tests/swoole_curl/basic/4.phpt +++ b/tests/swoole_curl/basic/4.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_opt() function with setting referer +swoole_curl/basic: Test curl_opt() function with setting referer --CREDITS-- Sebastian Deutsch TestFest 2009 - AFUP - Jean-Marc Fontaine diff --git a/tests/swoole_curl/basic/5.phpt b/tests/swoole_curl/basic/5.phpt index b6147becb3e..2536771ccf3 100644 --- a/tests/swoole_curl/basic/5.phpt +++ b/tests/swoole_curl/basic/5.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_opt() function with user agent +swoole_curl/basic: Test curl_opt() function with user agent --CREDITS-- Sebastian Deutsch TestFest 2009 - AFUP - Jean-Marc Fontaine diff --git a/tests/swoole_curl/basic/7.phpt b/tests/swoole_curl/basic/7.phpt index c8549480185..53f14f45136 100644 --- a/tests/swoole_curl/basic/7.phpt +++ b/tests/swoole_curl/basic/7.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_error() & curl_errno() function without url +swoole_curl/basic: Test curl_error() & curl_errno() function without url --CREDITS-- TestFest 2009 - AFUP - Perrick Penet --SKIPIF-- diff --git a/tests/swoole_curl/basic/8.phpt b/tests/swoole_curl/basic/8.phpt index f296edf2637..243efbdc606 100644 --- a/tests/swoole_curl/basic/8.phpt +++ b/tests/swoole_curl/basic/8.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_error() & curl_errno() function with problematic host +swoole_curl/basic: Test curl_error() & curl_errno() function with problematic host --CREDITS-- TestFest 2009 - AFUP - Perrick Penet --SKIPIF-- diff --git a/tests/swoole_curl/basic/9.phpt b/tests/swoole_curl/basic/9.phpt index 73f687427e9..c52988e9221 100644 --- a/tests/swoole_curl/basic/9.phpt +++ b/tests/swoole_curl/basic/9.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/basic: Test curl_error() & curl_errno() function with problematic protocol +swoole_curl/basic: Test curl_error() & curl_errno() function with problematic protocol --CREDITS-- TestFest 2009 - AFUP - Perrick Penet --SKIPIF-- diff --git a/tests/swoole_curl/close_before_resume.phpt b/tests/swoole_curl/close_before_resume.phpt index 9ee7328d576..76629de272d 100644 --- a/tests/swoole_curl/close_before_resume.phpt +++ b/tests/swoole_curl/close_before_resume.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_runtime/curl_native: close before resume +swoole_curl: close before resume --SKIPIF-- +--FILE-- + 'http://httpbin.org']); + + // Initiate each request but do not block + $promises = [ + 'a' => $client->requestAsync('POST', '/post', ['json' => ['data' => 'hello test1!']]), + 'b' => $client->requestAsync('POST', '/post', ['json' => ['data' => 'hello test2!']]), + 'b' => $client->requestAsync('POST', '/post', ['json' => ['data' => 'hello test3!']]), + ]; + + // Wait on all of the requests to complete. + $results = Promise\unwrap($promises); + + // You can access each result using the key provided to the unwrap + // function. + echo json_decode($results['a']->getBody()->getContents())->data . PHP_EOL; + echo $results['b']->getHeaderLine('Content-Length') . PHP_EOL; + echo 'Done' . PHP_EOL; +}); +?> +--EXPECT-- +{"data":"hello test1!"} +422 +Done diff --git a/tests/swoole_curl/guzzle/request_async.phpt b/tests/swoole_curl/guzzle/request_async.phpt index d745e380002..8f6f4cfed4e 100644 --- a/tests/swoole_curl/guzzle/request_async.phpt +++ b/tests/swoole_curl/guzzle/request_async.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_runtime/curl_native/guzzle: request async +swoole_curl/guzzle: request async --SKIPIF-- --FILE-- diff --git a/tests/swoole_curl/setopt/filetime_2.phpt b/tests/swoole_curl/setopt/filetime_2.phpt index 946d3b99394..5879c4385af 100644 --- a/tests/swoole_curl/setopt/filetime_2.phpt +++ b/tests/swoole_curl/setopt/filetime_2.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/setopt: CURLOPT_FILETIME [return -1] +swoole_curl/setopt: CURLOPT_FILETIME [return -1] --SKIPIF-- --FILE-- diff --git a/tests/swoole_curl/setopt/header_out.phpt b/tests/swoole_curl/setopt/header_out.phpt index 2ee9c217f46..1ec1969c8ac 100644 --- a/tests/swoole_curl/setopt/header_out.phpt +++ b/tests/swoole_curl/setopt/header_out.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/setopt: CURLINFO_HEADER_OUT +swoole_curl/setopt: CURLINFO_HEADER_OUT --SKIPIF-- --FILE-- diff --git a/tests/swoole_curl/setopt/infile.phpt b/tests/swoole_curl/setopt/infile.phpt index 7c26fa8e0f3..5dd86c05d39 100644 --- a/tests/swoole_curl/setopt/infile.phpt +++ b/tests/swoole_curl/setopt/infile.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/setopt: CURLOPT_INFILE +swoole_curl/setopt: CURLOPT_INFILE --SKIPIF-- --FILE-- diff --git a/tests/swoole_curl/setopt/nobody.phpt b/tests/swoole_curl/setopt/nobody.phpt index 515a853b4ed..d8dd27d001b 100644 --- a/tests/swoole_curl/setopt/nobody.phpt +++ b/tests/swoole_curl/setopt/nobody.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_library/curl/setopt: CURLOPT_NOBODY +swoole_curl/setopt: CURLOPT_NOBODY --SKIPIF-- --FILE-- diff --git a/tests/swoole_curl/sleep.phpt b/tests/swoole_curl/sleep.phpt index 86e3ec0b0f1..50a2fc2ecff 100644 --- a/tests/swoole_curl/sleep.phpt +++ b/tests/swoole_curl/sleep.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_runtime/curl_native: sleep +swoole_curl: sleep --SKIPIF-- diff --git a/tests/swoole_curl/timer_coredump.phpt b/tests/swoole_curl/timer_coredump.phpt index 4167bf6ddb2..89639847cdf 100644 --- a/tests/swoole_curl/timer_coredump.phpt +++ b/tests/swoole_curl/timer_coredump.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_runtime/curl_native: timer coredump +swoole_curl: timer coredump --SKIPIF-- Date: Tue, 6 Apr 2021 22:34:05 +0800 Subject: [PATCH 097/936] Fix httpclient proxy with host and port (#4124) * Fix proxy with host and port * Change strstr to memchr --- ext-src/swoole_http_client_coro.cc | 6 ++- .../http_proxy_with_host_port.phpt | 50 +++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 tests/swoole_http_client_coro/http_proxy_with_host_port.phpt diff --git a/ext-src/swoole_http_client_coro.cc b/ext-src/swoole_http_client_coro.cc index 5f101edee12..557a0b262bd 100644 --- a/ext-src/swoole_http_client_coro.cc +++ b/ext-src/swoole_http_client_coro.cc @@ -971,7 +971,11 @@ bool HttpClient::send() { } size_t proxy_uri_len = path.length() + _host_len + strlen(pre) + 10; char *proxy_uri = (char *) emalloc(proxy_uri_len); - proxy_uri_len = sw_snprintf(proxy_uri, proxy_uri_len, "%s%s:%u%s", pre, _host, port, path.c_str()); + if (nullptr == memchr(_host, ':', _host_len)) { + proxy_uri_len = sw_snprintf(proxy_uri, proxy_uri_len, "%s%s:%u%s", pre, _host, port, path.c_str()); + } else { + proxy_uri_len = sw_snprintf(proxy_uri, proxy_uri_len, "%s%s%s", pre, _host, path.c_str()); + } buffer->append(proxy_uri, proxy_uri_len); if (!socket->http_proxy->password.empty()) { require_proxy_authentication = true; diff --git a/tests/swoole_http_client_coro/http_proxy_with_host_port.phpt b/tests/swoole_http_client_coro/http_proxy_with_host_port.phpt new file mode 100644 index 00000000000..fb5a4062b4f --- /dev/null +++ b/tests/swoole_http_client_coro/http_proxy_with_host_port.phpt @@ -0,0 +1,50 @@ +--TEST-- +swoole_http_client_coro: http client with http_proxy and host and port +--SKIPIF-- + +--FILE-- +parentFunc = function () use ($pm) { + Co\Run(function () use ($pm) { + $cli = new Swoole\Coroutine\Http\Client('127.0.0.1', $pm->getFreePort()); + $cli->set([ + 'timeout' => 30, + 'http_proxy_host' => HTTP_PROXY_HOST, + 'http_proxy_port' => HTTP_PROXY_PORT, + ]); + $cli->setHeaders([ + 'Host' => '127.0.0.1:'.$pm->getFreePort(), + ]); + $result = $cli->get('/'); + Assert::assert($result); + Assert::assert('Swoole' === $cli->body); + $cli->close(); + $pm->kill(); + echo "DONE\n"; + }); +}; + +$pm->childFunc = function () use ($pm) { + $server = new Swoole\Http\Server('0.0.0.0', $pm->getFreePort(), SWOOLE_BASE); + $server->set(['log_file' => '/dev/null']); + $server->on('workerStart', function () use ($pm) { + $pm->wakeup(); + }); + $server->on('request', function (Swoole\Http\Request $request, Swoole\Http\Response $response) use ($pm) { + $response->end('Swoole'); + }); + $server->start(); +}; + +$pm->childFirst(); +$pm->run(); + +?> +--EXPECT-- +DONE From a5311c355b275dcac37a9786da71acecb25a5519 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Wed, 7 Apr 2021 21:24:59 +0800 Subject: [PATCH 098/936] Fix promise test (#4134) Different versions of PHP get different Content-Length --- tests/swoole_curl/guzzle/promise.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/swoole_curl/guzzle/promise.phpt b/tests/swoole_curl/guzzle/promise.phpt index 848aa4fad31..5230f56e152 100644 --- a/tests/swoole_curl/guzzle/promise.phpt +++ b/tests/swoole_curl/guzzle/promise.phpt @@ -33,11 +33,11 @@ run(function () { // You can access each result using the key provided to the unwrap // function. echo json_decode($results['a']->getBody()->getContents())->data . PHP_EOL; - echo $results['b']->getHeaderLine('Content-Length') . PHP_EOL; + echo $results['b']->getHeaderLine('Content-Type') . PHP_EOL; echo 'Done' . PHP_EOL; }); ?> --EXPECT-- {"data":"hello test1!"} -422 +application/json Done From 8ca2d5d75164859fcce54639d574f5a0940b7546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Thu, 8 Apr 2021 10:28:39 +0800 Subject: [PATCH 099/936] fix (#4135) --- ext-src/php_swoole_mysql_proto.h | 6 +++--- ext-src/swoole_http_server.cc | 11 +++-------- ext-src/swoole_redis_server.cc | 2 +- src/network/dns.cc | 2 +- thirdparty/php/curl/interface.cc | 8 ++++---- 5 files changed, 12 insertions(+), 17 deletions(-) diff --git a/ext-src/php_swoole_mysql_proto.h b/ext-src/php_swoole_mysql_proto.h index 336c14a6564..dae89128c88 100644 --- a/ext-src/php_swoole_mysql_proto.h +++ b/ext-src/php_swoole_mysql_proto.h @@ -786,9 +786,9 @@ class row_data class row_data_text { public: - uint64_t length; - bool nul; - const char *body; + uint64_t length = 0; + bool nul = false; + const char *body = nullptr; row_data_text(const char **pp) { body = *pp + read_lcb(*pp, &length, &nul); diff --git a/ext-src/swoole_http_server.cc b/ext-src/swoole_http_server.cc index 8e3d9e48e85..6933caad3b0 100644 --- a/ext-src/swoole_http_server.cc +++ b/ext-src/swoole_http_server.cc @@ -50,14 +50,9 @@ int php_swoole_http_server_onReceive(Server *serv, RecvData *req) { ListenPort *port = serv->get_port_by_server_fd(server_fd); // other server port - if (!port->open_http_protocol || !php_swoole_server_isset_callback(serv, port, SW_SERVER_CB_onRequest)) { - SW_LOOP { - if (port->open_websocket_protocol && php_swoole_server_isset_callback(serv, port, SW_SERVER_CB_onMessage)) { - break; - } else { - return php_swoole_server_onReceive(serv, req); - } - } + if (!(port->open_http_protocol && php_swoole_server_isset_callback(serv, port, SW_SERVER_CB_onRequest)) && + !(port->open_websocket_protocol && php_swoole_server_isset_callback(serv, port, SW_SERVER_CB_onMessage))) { + return php_swoole_server_onReceive(serv, req); } // websocket client if (conn->websocket_status == WEBSOCKET_STATUS_ACTIVE) { diff --git a/ext-src/swoole_redis_server.cc b/ext-src/swoole_redis_server.cc index 6d515d4aa5f..eb144ef9481 100644 --- a/ext-src/swoole_redis_server.cc +++ b/ext-src/swoole_redis_server.cc @@ -112,7 +112,7 @@ int php_swoole_redis_server_onReceive(Server *serv, RecvData *req) { int ret; int length = 0; - zval zparams; + zval zparams{}; array_init(&zparams); int state = SW_REDIS_RECEIVE_TOTAL_LINE; diff --git a/src/network/dns.cc b/src/network/dns.cc index 856419f3515..1399af82ed0 100644 --- a/src/network/dns.cc +++ b/src/network/dns.cc @@ -363,7 +363,7 @@ int gethostbyname(int flags, const char *name, char *addr) { union { char v4[INET_ADDRSTRLEN]; char v6[INET6_ADDRSTRLEN]; - } addr_list[SW_DNS_HOST_BUFFER_SIZE]; + } addr_list[SW_DNS_HOST_BUFFER_SIZE] {}; int i = 0; for (i = 0; i < SW_DNS_HOST_BUFFER_SIZE; i++) { diff --git a/thirdparty/php/curl/interface.cc b/thirdparty/php/curl/interface.cc index 8fe185be030..b3cb4b34870 100644 --- a/thirdparty/php/curl/interface.cc +++ b/thirdparty/php/curl/interface.cc @@ -2691,10 +2691,6 @@ void _php_curl_free(php_curl *ch) { curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_nothing); curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write_nothing); - if (ch->cp != NULL) { - curl_easy_cleanup(ch->cp); - } - /* cURL destructors should be invoked only by last curl handle */ if (--(*ch->clone) == 0) { zend_llist_clean(&ch->to_free->str); @@ -2711,6 +2707,10 @@ void _php_curl_free(php_curl *ch) { curl_easy_setopt(ch->cp, CURLOPT_PRIVATE, nullptr); } + if (ch->cp != NULL) { + curl_easy_cleanup(ch->cp); + } + smart_str_free(&ch->handlers->write->buf); zval_ptr_dtor(&ch->handlers->write->func_name); zval_ptr_dtor(&ch->handlers->read->func_name); From ff1adbf7c2b060706303a45d981e8e90bc45b136 Mon Sep 17 00:00:00 2001 From: Yurun Date: Thu, 8 Apr 2021 10:59:44 +0800 Subject: [PATCH 100/936] Fix test (#4136) * Fix test * Fix test --- .../http_proxy_with_host_port.phpt | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/swoole_http_client_coro/http_proxy_with_host_port.phpt b/tests/swoole_http_client_coro/http_proxy_with_host_port.phpt index fb5a4062b4f..79a983a593e 100644 --- a/tests/swoole_http_client_coro/http_proxy_with_host_port.phpt +++ b/tests/swoole_http_client_coro/http_proxy_with_host_port.phpt @@ -3,7 +3,6 @@ swoole_http_client_coro: http client with http_proxy and host and port --SKIPIF-- --FILE-- parentFunc = function () use ($pm) { - Co\Run(function () use ($pm) { - $cli = new Swoole\Coroutine\Http\Client('127.0.0.1', $pm->getFreePort()); + Co\run(function () use ($pm) { + $cli = new Swoole\Coroutine\Http\Client('127.0.0.1', 1234); $cli->set([ 'timeout' => 30, - 'http_proxy_host' => HTTP_PROXY_HOST, - 'http_proxy_port' => HTTP_PROXY_PORT, + 'http_proxy_host' => '127.0.0.1', + 'http_proxy_port' => $pm->getFreePort(), ]); $cli->setHeaders([ - 'Host' => '127.0.0.1:'.$pm->getFreePort(), + 'Host' => '127.0.0.1:1234', ]); - $result = $cli->get('/'); - Assert::assert($result); - Assert::assert('Swoole' === $cli->body); - $cli->close(); + $cli->get('/'); $pm->kill(); - echo "DONE\n"; }); }; $pm->childFunc = function () use ($pm) { - $server = new Swoole\Http\Server('0.0.0.0', $pm->getFreePort(), SWOOLE_BASE); - $server->set(['log_file' => '/dev/null']); - $server->on('workerStart', function () use ($pm) { - $pm->wakeup(); - }); - $server->on('request', function (Swoole\Http\Request $request, Swoole\Http\Response $response) use ($pm) { - $response->end('Swoole'); + $server = new Swoole\Server('0.0.0.0', $pm->getFreePort(), SWOOLE_BASE); + $server->set([ + 'log_file' => '/dev/null', + 'open_eof_check' => true, + 'package_eof' => "\r\n\r\n", + ]); + $server->on('Receive', function ($server, $fd, $reactor_id, $data) { + echo $data; + $server->close($fd); }); $server->start(); }; @@ -47,4 +44,7 @@ $pm->run(); ?> --EXPECT-- -DONE +GET http://127.0.0.1:1234/ HTTP/1.1 +Host: 127.0.0.1:1234 +Connection: keep-alive +Accept-Encoding: gzip, deflate From 4c85b2b35a5e290a997391807fcab6d0a7a39016 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Thu, 8 Apr 2021 11:57:23 +0800 Subject: [PATCH 101/936] fix mem invalid read --- ext-src/swoole_server.cc | 40 +++++++++++++--------------------------- include/swoole_server.h | 16 +++++++++++++++- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index b4143bb41b0..ffeb15c8c69 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -3766,7 +3766,7 @@ static PHP_METHOD(swoole_server, getClientList) { start_fd = serv->get_minfd(); } else { Connection *conn = serv->get_connection_verify(start_session_id); - if (!serv->is_valid_connection(conn)) { + if (!conn) { RETURN_FALSE; } start_fd = conn->fd; @@ -3778,18 +3778,11 @@ static PHP_METHOD(swoole_server, getClientList) { array_init(return_value); int fd = start_fd + 1; - Connection *conn; for (; fd <= serv_max_fd; fd++) { swTrace("maxfd=%d, fd=%d, find_count=%ld, start_fd=%ld", serv_max_fd, fd, find_count, start_session_id); - conn = serv->get_connection(fd); - - if (serv->is_valid_connection(conn)) { -#ifdef SW_USE_OPENSSL - if (conn->ssl && !conn->ssl_ready) { - continue; - } -#endif + Connection *conn = serv->get_connection_for_iterator(fd); + if (conn) { add_next_index_long(return_value, conn->session_id); find_count--; } @@ -4001,27 +3994,20 @@ static PHP_METHOD(swoole_connection_iterator, rewind) { static PHP_METHOD(swoole_connection_iterator, valid) { ConnectionIterator *iterator = php_swoole_connection_iterator_get_and_check_ptr(ZEND_THIS); int fd = iterator->current_fd; - Connection *conn; - int max_fd = iterator->serv->get_maxfd(); for (; fd <= max_fd; fd++) { - conn = iterator->serv->get_connection(fd); - - if (conn->active && !conn->closed) { -#ifdef SW_USE_OPENSSL - if (conn->ssl && !conn->ssl_ready) { - continue; - } -#endif - if (iterator->port && (iterator->port->get_fd() < 0 || conn->server_fd != iterator->port->get_fd())) { - continue; - } - iterator->session_id = conn->session_id; - iterator->current_fd = fd; - iterator->index++; - RETURN_TRUE; + Connection *conn = iterator->serv->get_connection_for_iterator(fd); + if (!conn) { + continue; + } + if (iterator->port && (iterator->port->get_fd() < 0 || conn->server_fd != iterator->port->get_fd())) { + continue; } + iterator->session_id = conn->session_id; + iterator->current_fd = fd; + iterator->index++; + RETURN_TRUE; } RETURN_FALSE; diff --git a/include/swoole_server.h b/include/swoole_server.h index 4d67da02094..f0af35a1c05 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -139,7 +139,7 @@ struct Connection { */ void *object; /** - * socket info + * socket, only operated in the main process */ network::Socket *socket; /** @@ -1073,6 +1073,7 @@ class Server { return gs->shutdown; } + // can only be used in the main process inline bool is_valid_connection(Connection *conn) { return (conn && conn->socket && conn->active && conn->socket->fd_type == SW_FD_SESSION); } @@ -1135,6 +1136,19 @@ class Server { return &connection_list[fd]; } + inline Connection *get_connection_for_iterator(int fd) { + Connection *conn = get_connection(fd); + if (conn && conn->active && !conn->closed && conn->session_id > 0) { +#ifdef SW_USE_OPENSSL + if (conn->ssl && !conn->ssl_ready) { + return nullptr; + } +#endif + return conn; + } + return nullptr; + } + inline Connection *get_connection_by_session_id(SessionId session_id) { return get_connection(get_connection_fd(session_id)); } From 7330c1aae9b7309a15366eaf1fcc1fd71e204713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Thu, 8 Apr 2021 18:43:23 +0800 Subject: [PATCH 102/936] fix core tests (#4138) --- core-tests/src/coroutine/hook.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/core-tests/src/coroutine/hook.cpp b/core-tests/src/coroutine/hook.cpp index 83d49119bb7..cb55525a4a5 100644 --- a/core-tests/src/coroutine/hook.cpp +++ b/core-tests/src/coroutine/hook.cpp @@ -215,18 +215,23 @@ TEST(coroutine_hook, flock) { } TEST(coroutine_hook, read_dir) { - auto fn = []() { + auto fp = opendir("/tmp"); + std::string dir1(readdir(fp)->d_name); + std::string dir2(readdir(fp)->d_name); + closedir(fp); + + auto fn = [&]() { auto fp = swoole_coroutine_opendir("/tmp"); ASSERT_NE(fp, nullptr); struct dirent *entry; entry = swoole_coroutine_readdir(fp); ASSERT_NE(entry, nullptr); - ASSERT_STREQ(entry->d_name, "."); + ASSERT_STREQ(entry->d_name, dir1.c_str()); entry = swoole_coroutine_readdir(fp); ASSERT_NE(entry, nullptr); - ASSERT_STREQ(entry->d_name, ".."); + ASSERT_STREQ(entry->d_name, dir2.c_str()); swoole_coroutine_closedir(fp); }; From a218e3569afec2eebbb302a7896cafebc9dfb20f Mon Sep 17 00:00:00 2001 From: codinghuang Date: Fri, 9 Apr 2021 09:08:59 +0800 Subject: [PATCH 103/936] Update version for Swoole 4.6.5 (#4139) --- CMakeLists.txt | 2 +- ext-src/php_swoole_library.h | 11 +- include/swoole_version.h | 4 +- package.xml | 173 ++++++++++++------ tests/swoole_curl/multi/bug48203_multi.phpt | 2 +- tests/swoole_curl/multi/bug67643.phpt | 3 +- tests/swoole_curl/multi/bug71523.phpt | 3 +- tests/swoole_curl/multi/bug76675.phpt | 3 +- tests/swoole_curl/multi/bug77535.phpt | 5 +- tests/swoole_curl/multi/bug77946.phpt | 3 +- tests/swoole_curl/multi/curl_basic_018.phpt | 3 +- .../multi/curl_copy_handle_variation4.phpt | 3 +- tests/swoole_curl/multi/curl_int_cast.phpt | 4 +- .../multi/curl_multi_close_basic.phpt | 5 +- .../multi/curl_multi_close_basic001.phpt | 3 +- .../multi/curl_multi_close_reference.phpt | 3 +- .../multi/curl_multi_errno_strerror_001.phpt | 3 +- .../multi/curl_multi_getcontent_basic3.phpt | 3 +- .../multi/curl_multi_info_read.phpt | 3 +- .../multi/curl_multi_init_basic.phpt | 3 +- .../multi/curl_multi_segfault.phpt | 3 +- .../multi/curl_multi_select_basic1.phpt | 3 +- .../multi/curl_multi_setopt_basic001.phpt | 3 +- tests/swoole_curl/upload/1.phpt | 2 +- tests/swoole_server/ssl/heartbeat_1.phpt | 2 +- tests/swoole_server/ssl/heartbeat_2.phpt | 2 +- 26 files changed, 165 insertions(+), 92 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e386a500733..a10a17a01d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ PROJECT(libswoole) ENABLE_LANGUAGE(ASM) -set(SWOOLE_VERSION 4.6.5-dev) +set(SWOOLE_VERSION 4.6.5) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g") diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index 5770f295562..9c812d3f201 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: c0b3306481ecd77cc88ab51ba15403bcc33319a9 */ +/* $Id: c1d47051d7a949c0a76ca595f6d523faa2ecc3b9 */ static const char* swoole_library_source_constants = "\n" @@ -1613,6 +1613,11 @@ static const char* swoole_library_source_core_coroutine_wait_group = " }\n" " return true;\n" " }\n" + "\n" + " public function count(): int\n" + " {\n" + " return $this->count;\n" + " }\n" "}\n"; static const char* swoole_library_source_core_coroutine_server = @@ -1927,10 +1932,10 @@ static const char* swoole_library_source_core_coroutine_http_functions = " $client->set($options);\n" " }\n" " if (is_array($headers)) {\n" - " $client->setHeaders($options);\n" + " $client->setHeaders($headers);\n" " }\n" " if (is_array($cookies)) {\n" - " $client->setCookies($options);\n" + " $client->setCookies($cookies);\n" " }\n" " $request_url = swoole_array_default_value($info, 'path', '/');\n" " if (!empty($info['query'])) {\n" diff --git a/include/swoole_version.h b/include/swoole_version.h index 2ad816f0166..72c9b4054fe 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -21,8 +21,8 @@ #define SWOOLE_MAJOR_VERSION 4 #define SWOOLE_MINOR_VERSION 6 #define SWOOLE_RELEASE_VERSION 5 -#define SWOOLE_EXTRA_VERSION "dev" -#define SWOOLE_VERSION "4.6.5-dev" +#define SWOOLE_EXTRA_VERSION "" +#define SWOOLE_VERSION "4.6.5" #define SWOOLE_VERSION_ID 40605 #define SWOOLE_API_VERSION_ID 0x202012a diff --git a/package.xml b/package.xml index fad66469610..a0ebd406072 100644 --- a/package.xml +++ b/package.xml @@ -42,10 +42,10 @@ shenzhe163@gmail.com yes - 2021-03-11 - + 2021-04-07 + - 4.6.4 + 4.6.5 4.0 @@ -54,24 +54,32 @@ Apache2.0 + New APIs + --- + * Add count method to WaitGroup (swoole/library#100) (@sy-records) (@deminy) + Enhancement --- - + Supported ARM 64 build (#4057) (@devnexen) - + Supported set open_http_protocol in Swoole TCP Server (#4063) (@matyhtf) - + Supported ssl client only set certificate (swoole/swoole-src@91704ac) (@matyhtf) - + Supported ssl client only set certificate (swoole/swoole-src@91704ac) (@matyhtf) - * Supported tcp_defer_accept option for FreeBSD (#4049) (@devnexen) + * Supported native curl multi (#4093) (#4099) (#4101) (#4105) (#4113) (#4121) (swoole/swoole-src@cd7f51c) (@matyhtf) (@sy-records) (@huanghantao) Fixed --- - * Fixed Proxy-Authorization missing when use Coroutine\Http\Client (swoole/swoole-src@edc0552) (@matyhtf) - * Fixed memory allocation issues with Swoole\Table (swoole/swoole-src@3e7770f) (@matyhtf) - * Fixed crash when Coroutine\Http2\Client connects concurrently (swoole/swoole-src@630536d) (@matyhtf) - * Fixed enable_ssl_encrypt with DTLS (swoole/swoole-src@842733b) (@matyhtf) - * Fixed Coroutine\Barrier mem leak (swoole/library#94) (@Appla) (@FMiS) - * Fixed the offset error caused by CURLOPT_PORT and CURLOPT_URL order (swoole/library#96) (@sy-records) - * Fixed Table::get($key, $field) when field type is float (swoole/swoole-src@08ea20c) (@matyhtf) - * Fixed Swoole\Table mem leaks (swoole/swoole-src@d78ca8c) (@matyhtf) + * Fixed NetBSD build (#4080) (@devnexen) + * Fixed OpenBSD build. (#4108) (@devnexen) + * Fixed illumos/solaris build, member aliases only (#4109) (@devnexen) + * Fixed heartbeat detection of SSL connection does not take effect when handshake is not completed (#4114) (@matyhtf) + * Fixed httpclient proxy with host and port (#4124) (@Yurunsoft) + * Fixed Swoole\Coroutine\Http::request, correct array to the client setting (swoole/library#103) (@leocavalcante) (@deminy) + + Kernel + --- + * Supported asm context on BSD (#4082) (@devnexen) + * Used arc4random_buf to implement getrandom under FreeBSD (#4096) (@devnexen) + * Make context darwin arm64: removes workaround and uses the label (#4127) (@devnexen) + + Test + --- + * Added build job for alpine (#4104) (@limingxinleo) @@ -279,6 +287,7 @@ + @@ -502,6 +511,7 @@ + @@ -518,6 +528,7 @@ + @@ -668,6 +679,7 @@ + @@ -716,6 +728,8 @@ + + @@ -734,7 +748,6 @@ - @@ -1025,6 +1038,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1133,6 +1224,7 @@ + @@ -1281,41 +1373,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1484,14 +1541,6 @@ - - - - - - - - @@ -1709,6 +1758,8 @@ + + @@ -1968,9 +2019,9 @@ - + diff --git a/tests/swoole_curl/multi/bug48203_multi.phpt b/tests/swoole_curl/multi/bug48203_multi.phpt index 4c838ecda5f..b5ba15104a0 100644 --- a/tests/swoole_curl/multi/bug48203_multi.phpt +++ b/tests/swoole_curl/multi/bug48203_multi.phpt @@ -1,5 +1,5 @@ --TEST-- -Variation of bug #48203 with curl_multi_exec (Crash when file pointers passed to curl are closed before calling curl_multi_exec) +swoole_curl/multi: Variation of bug #48203 with curl_multi_exec (Crash when file pointers passed to curl are closed before calling curl_multi_exec) --SKIPIF-- diff --git a/tests/swoole_curl/multi/bug71523.phpt b/tests/swoole_curl/multi/bug71523.phpt index 33ea469578a..2d7809581cc 100644 --- a/tests/swoole_curl/multi/bug71523.phpt +++ b/tests/swoole_curl/multi/bug71523.phpt @@ -1,6 +1,7 @@ --TEST-- -Bug #71523 (Copied handle with new option CURLOPT_HTTPHEADER crashes while curl_multi_exec) +swoole_curl/multi: Bug #71523 (Copied handle with new option CURLOPT_HTTPHEADER crashes while curl_multi_exec) --SKIPIF-- + --SKIPIF-- + --FILE-- --FILE-- --FILE-- #testfest Utrecht 2009 --SKIPIF-- + @@ -21,4 +22,4 @@ run(function () { curl_type_assert($ch, 'Swoole-Coroutine-cURL-Multi-Handle', Swoole\Coroutine\Curl\MultiHandle::class); }); ?> ---EXPECT-- \ No newline at end of file +--EXPECT-- diff --git a/tests/swoole_curl/multi/curl_multi_close_basic001.phpt b/tests/swoole_curl/multi/curl_multi_close_basic001.phpt index 3620511483d..ea4dc86066a 100644 --- a/tests/swoole_curl/multi/curl_multi_close_basic001.phpt +++ b/tests/swoole_curl/multi/curl_multi_close_basic001.phpt @@ -1,6 +1,7 @@ --TEST-- -curl_multi_close return false when supplied resource not valid cURL multi handle +swoole_curl/multi: curl_multi_close return false when supplied resource not valid cURL multi handle --SKIPIF-- + diff --git a/tests/swoole_curl/multi/curl_multi_close_reference.phpt b/tests/swoole_curl/multi/curl_multi_close_reference.phpt index 4a11cad514d..8a835aa8d4b 100644 --- a/tests/swoole_curl/multi/curl_multi_close_reference.phpt +++ b/tests/swoole_curl/multi/curl_multi_close_reference.phpt @@ -1,6 +1,7 @@ --TEST-- -curl_multi_close closed by cleanup functions +swoole_curl/multi: curl_multi_close closed by cleanup functions --SKIPIF-- + diff --git a/tests/swoole_curl/multi/curl_multi_errno_strerror_001.phpt b/tests/swoole_curl/multi/curl_multi_errno_strerror_001.phpt index dd9c3c63180..44dbf627322 100644 --- a/tests/swoole_curl/multi/curl_multi_errno_strerror_001.phpt +++ b/tests/swoole_curl/multi/curl_multi_errno_strerror_001.phpt @@ -1,6 +1,7 @@ --TEST-- -curl_multi_errno and curl_multi_strerror basic test +swoole_curl/multi: curl_multi_errno and curl_multi_strerror basic test --SKIPIF-- + --FILE-- - @phpsp - sao paulo - br --SKIPIF-- + diff --git a/tests/swoole_curl/multi/curl_multi_init_basic.phpt b/tests/swoole_curl/multi/curl_multi_init_basic.phpt index 1fd91174cd5..4b23d3b81c6 100644 --- a/tests/swoole_curl/multi/curl_multi_init_basic.phpt +++ b/tests/swoole_curl/multi/curl_multi_init_basic.phpt @@ -1,9 +1,10 @@ --TEST-- -Test curl_multi_init() +swoole_curl/multi: Test curl_multi_init() --CREDITS-- Mark van der Velden #testfest Utrecht 2009 --SKIPIF-- + --FILE-- #testfest Utrecht 2009 --SKIPIF-- + --FILE-- diff --git a/tests/swoole_server/ssl/heartbeat_1.phpt b/tests/swoole_server/ssl/heartbeat_1.phpt index b4479e81973..fd584481f07 100644 --- a/tests/swoole_server/ssl/heartbeat_1.phpt +++ b/tests/swoole_server/ssl/heartbeat_1.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_server: heartbeat with bad client +swoole_server/ssl: heartbeat with bad client --SKIPIF-- Date: Fri, 9 Apr 2021 02:09:14 +0100 Subject: [PATCH 104/936] Allow array HTTP/2 headers, Bug fixed for #4133 (#4140) * Allow array HTTP/2 headers, Bug fixed for #4133 * Fix tests * Fix tests * Fix tests * optimize Co-authored-by: matyhtf --- examples/http2/server.php | 10 ++- ext-src/php_swoole_http.h | 17 +++++ ext-src/swoole_http2_server.cc | 74 ++++++++++++-------- ext-src/swoole_http_response.cc | 23 +----- tests/swoole_http2_server/http2_headers.phpt | 50 +++++++++++++ 5 files changed, 124 insertions(+), 50 deletions(-) create mode 100644 tests/swoole_http2_server/http2_headers.phpt diff --git a/examples/http2/server.php b/examples/http2/server.php index 44b29a48bbc..fb8c3913054 100644 --- a/examples/http2/server.php +++ b/examples/http2/server.php @@ -1,5 +1,5 @@ SWOOLE_TRACE_HTTP2, 'log_level' => 0, ]); @@ -14,6 +14,14 @@ ]); $http->on('request', function (swoole_http_request $request, swoole_http_response $response) { + $response->header('Test-Value', [ + "a\r\n", + 'd5678', + "e \n ", + null, + 5678, + 3.1415926, + ]); $response->end("

Hello Swoole.

"); }); diff --git a/ext-src/php_swoole_http.h b/ext-src/php_swoole_http.h index f8fe7a36d7e..0ff0946fda6 100644 --- a/ext-src/php_swoole_http.h +++ b/ext-src/php_swoole_http.h @@ -278,6 +278,23 @@ static sw_inline zval *swoole_http_init_and_read_property( return *zproperty_store_pp; } +static inline bool swoole_http_has_crlf(const char *value, size_t length) { + /* new line/NUL character safety check */ + for (size_t i = 0; i < length; i++) { + /* RFC 7230 ch. 3.2.4 deprecates folding support */ + if (value[i] == '\n' || value[i] == '\r') { + php_swoole_error(E_WARNING, "Header may not contain more than a single header, new line detected"); + return true; + } + if (value[i] == '\0') { + php_swoole_error(E_WARNING, "Header may not contain NUL bytes"); + return true; + } + } + + return false; +} + void swoole_http_parse_cookie(zval *array, const char *at, size_t length); swoole::http::Context *php_swoole_http_request_get_context(zval *zobject); diff --git a/ext-src/swoole_http2_server.cc b/ext-src/swoole_http2_server.cc index c7736b0b5e7..a4696f2e083 100644 --- a/ext-src/swoole_http2_server.cc +++ b/ext-src/swoole_http2_server.cc @@ -239,7 +239,7 @@ static ssize_t http2_build_header(http_context *ctx, uchar *buffer, size_t body_ sw_zend_read_property_ex(swoole_http_response_ce, ctx->response.zobject, SW_ZSTR_KNOWN(SW_ZEND_STR_HEADER), 0); zval *zcookie = sw_zend_read_property_ex(swoole_http_response_ce, ctx->response.zobject, SW_ZSTR_KNOWN(SW_ZEND_STR_COOKIE), 0); - http2::HeaderSet headers(8 + php_swoole_array_length_safe(zheader) + php_swoole_array_length_safe(zcookie)); + http2::HeaderSet headers(32 + php_swoole_array_length_safe(zheader) + php_swoole_array_length_safe(zcookie)); char *date_str = nullptr; char intbuf[2][16]; int ret; @@ -253,48 +253,64 @@ static ssize_t http2_build_header(http_context *ctx, uchar *buffer, size_t body_ ret = swoole_itoa(intbuf[0], ctx->response.status); headers.add(ZEND_STRL(":status"), intbuf[0], ret); + uint32_t header_flags = 0x0; + // headers if (ZVAL_IS_ARRAY(zheader)) { - uint32_t header_flag = 0x0; - zend_string *key; + const char *key; + uint32_t keylen; zval *zvalue; + int type; + + auto add_header = [](http2::HeaderSet &headers, const char *key, size_t l_key, zval *value, uint32_t &header_flags) { + if (ZVAL_IS_NULL(value)) { + return; + } + zend::String str_value(value); + str_value.rtrim(); + if (swoole_http_has_crlf(str_value.val(), str_value.len())) { + return; + } + if (SW_STREQ(key, l_key, "server")) { + header_flags |= HTTP_HEADER_SERVER; + } else if (SW_STREQ(key, l_key, "content-length")) { + return; // ignore + } else if (SW_STREQ(key, l_key, "date")) { + header_flags |= HTTP_HEADER_DATE; + } else if (SW_STREQ(key, l_key, "content-type")) { + header_flags |= HTTP_HEADER_CONTENT_TYPE; + } + headers.add(key, l_key, str_value.val(), str_value.len()); + }; - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zheader), key, zvalue) { + SW_HASHTABLE_FOREACH_START2(Z_ARRVAL_P(zheader), key, keylen, type, zvalue) { if (UNEXPECTED(!key || ZVAL_IS_NULL(zvalue))) { continue; } - zend::String str_value(zvalue); - char *c_key = ZSTR_VAL(key); - size_t c_keylen = ZSTR_LEN(key); - if (SW_STREQ(c_key, c_keylen, "server")) { - header_flag |= HTTP_HEADER_SERVER; - } else if (SW_STREQ(c_key, c_keylen, "content-length")) { - continue; // ignore - } else if (SW_STREQ(c_key, c_keylen, "date")) { - header_flag |= HTTP_HEADER_DATE; - } else if (SW_STREQ(c_key, c_keylen, "content-type")) { - header_flag |= HTTP_HEADER_CONTENT_TYPE; + if (ZVAL_IS_ARRAY(zvalue)) { + zval *zvalue_2; + SW_HASHTABLE_FOREACH_START(Z_ARRVAL_P(zvalue), zvalue_2) { + add_header(headers, key, keylen, zvalue_2, header_flags); + } + SW_HASHTABLE_FOREACH_END(); + } else { + add_header(headers, key, keylen, zvalue, header_flags); } - headers.add(c_key, c_keylen, str_value.val(), str_value.len()); } - ZEND_HASH_FOREACH_END(); + SW_HASHTABLE_FOREACH_END(); + (void) type; + } - if (!(header_flag & HTTP_HEADER_SERVER)) { - headers.add(ZEND_STRL("server"), ZEND_STRL(SW_HTTP_SERVER_SOFTWARE)); - } - if (!(header_flag & HTTP_HEADER_DATE)) { - date_str = php_swoole_format_date((char *) ZEND_STRL(SW_HTTP_DATE_FORMAT), time(nullptr), 0); - headers.add(ZEND_STRL("date"), date_str, strlen(date_str)); - } - if (!(header_flag & HTTP_HEADER_CONTENT_TYPE)) { - headers.add(ZEND_STRL("content-type"), ZEND_STRL("text/html")); - } - } else { + if (!(header_flags & HTTP_HEADER_SERVER)) { headers.add(ZEND_STRL("server"), ZEND_STRL(SW_HTTP_SERVER_SOFTWARE)); - headers.add(ZEND_STRL("content-type"), ZEND_STRL("text/html")); + } + if (!(header_flags & HTTP_HEADER_DATE)) { date_str = php_swoole_format_date((char *) ZEND_STRL(SW_HTTP_DATE_FORMAT), time(nullptr), 0); headers.add(ZEND_STRL("date"), date_str, strlen(date_str)); } + if (!(header_flags & HTTP_HEADER_CONTENT_TYPE)) { + headers.add(ZEND_STRL("content-type"), ZEND_STRL("text/html")); + } if (date_str) { efree(date_str); } diff --git a/ext-src/swoole_http_response.cc b/ext-src/swoole_http_response.cc index 65975c548e6..c0f3240cb65 100644 --- a/ext-src/swoole_http_response.cc +++ b/ext-src/swoole_http_response.cc @@ -70,23 +70,6 @@ static inline void http_header_key_format(char *key, int length) { } } -static inline bool http_has_crlf(const char *value, size_t length) { - /* new line/NUL character safety check */ - for (size_t i = 0; i < length; i++) { - /* RFC 7230 ch. 3.2.4 deprecates folding support */ - if (value[i] == '\n' || value[i] == '\r') { - php_swoole_error(E_WARNING, "Header may not contain more than a single header, new line detected"); - return true; - } - if (value[i] == '\0') { - php_swoole_error(E_WARNING, "Header may not contain NUL bytes"); - return true; - } - } - - return false; -} - String *http_context::get_write_buffer() { if (co_socket) { String *buffer = ((Socket *) private_data)->get_write_buffer(); @@ -426,7 +409,7 @@ static void http_build_header(http_context *ctx, swString *response, size_t body } zend::String str_value(value); str_value.rtrim(); - if (http_has_crlf(str_value.val(), str_value.len())) { + if (swoole_http_has_crlf(str_value.val(), str_value.len())) { return; } response->append(key, l_key); @@ -881,7 +864,7 @@ bool http_context::set_header(const char *k, size_t klen, zval *zvalue, bool for return false; } - if (http_has_crlf(k, klen)) { + if (swoole_http_has_crlf(k, klen)) { Z_TRY_DELREF_P(zvalue); return false; } @@ -1020,7 +1003,7 @@ static void php_swoole_http_response_cookie(INTERNAL_FUNCTION_PARAMETERS, const RETURN_FALSE; } - if (!url_encode && http_has_crlf(value, value_len)) { + if (!url_encode && swoole_http_has_crlf(value, value_len)) { RETURN_FALSE; } diff --git a/tests/swoole_http2_server/http2_headers.phpt b/tests/swoole_http2_server/http2_headers.phpt new file mode 100644 index 00000000000..0f95b638ef8 --- /dev/null +++ b/tests/swoole_http2_server/http2_headers.phpt @@ -0,0 +1,50 @@ +--TEST-- +swoole_http2_server: array headers +--SKIPIF-- + +--FILE-- +parentFunc = function ($pid) use ($pm) { + $output = `curl --http2-prior-knowledge --silent -I http://127.0.0.1:{$pm->getFreePort()}`; + echo $output; + $pm->kill(); +}; +$pm->childFunc = function () use ($pm) { + $http = new swoole_http_server('127.0.0.1', $pm->getFreePort(), SWOOLE_BASE); + $http->set([ + 'worker_num' => 1, + 'log_file' => '/dev/null', + 'open_http2_protocol' => true + ]); + $http->on('workerStart', function ($serv, $wid) use ($pm) { + $pm->wakeup(); + }); + $http->on('request', function (swoole_http_request $request, swoole_http_response $response) { + $response->header('test-value', [ + "a\r\n", + 'd5678', + "e \n ", + null, + 5678, + 3.1415926, + ]); + $response->end("

Hello Swoole.

"); + }); + $http->start(); +}; +$pm->childFirst(); +$pm->run(); +?> +--EXPECTF-- +HTTP/2 200 +test-value: a +test-value: d5678 +test-value: e +test-value: 5678 +test-value: 3.1415926 +server: swoole-http-server +date: %s +content-type: text/html +content-length: 22 From 653f2fe2c0757c90cb7f1665e4259e9152c7c4a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Fri, 9 Apr 2021 10:22:54 +0800 Subject: [PATCH 105/936] Add optional packages to package.xml (#4146) * Add optional packages to package.xml * Fix missing sockets --- package.xml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/package.xml b/package.xml index a0ebd406072..68625891092 100644 --- a/package.xml +++ b/package.xml @@ -2078,6 +2078,24 @@ 1.4.0 + + + curl + pecl.php.net + + + mysqlnd + pecl.php.net + + + json + pecl.php.net + + + sockets + pecl.php.net + + swoole From f32867a91897315d72c4b0be77866169ec2141d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Fri, 9 Apr 2021 16:49:25 +0800 Subject: [PATCH 106/936] fix curl multi bug (#4147) * defense * optimize --- ext-src/swoole_curl.cc | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ext-src/swoole_curl.cc b/ext-src/swoole_curl.cc index 5c2398dbe3f..cbc201652c5 100644 --- a/ext-src/swoole_curl.cc +++ b/ext-src/swoole_curl.cc @@ -175,6 +175,9 @@ CURLcode Multi::exec(php_curl *ch) { if (sockfd >= 0 && handle->socket && handle->socket->removed) { swoole_event_add(handle->socket, get_event(handle->action)); } + if (!timer && handle->socket->removed) { + break; + } } CURLcode retval = read_info(); @@ -228,6 +231,7 @@ long Multi::select(php_curlm *mh) { co = nullptr; }; + int event_count = 0; for (zend_llist_element *element = mh->easyh.head; element; element = element->next) { zval *z_ch = (zval *) element->data; php_curl *ch; @@ -236,12 +240,18 @@ long Multi::select(php_curlm *mh) { } Handle *handle = get_handle(ch->cp); if (handle && handle->socket && handle->socket->removed) { - swoole_event_add(handle->socket, get_event(handle->action)); + if (swoole_event_add(handle->socket, get_event(handle->action)) == SW_OK) { + event_count++; + } swTraceLog(SW_TRACE_CO_CURL, "resume, handle=%p, curl=%p, fd=%d", handle, ch->cp, handle->socket->get_fd()); } } set_timer(); + // no events and timers, should not be suspended + if (!timer && event_count == 0) { + return 0; + } co->yield(); auto count = selector->active_handles.size(); From 71eb1659c9333c84da408a5e3426344e8e6210ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Fri, 9 Apr 2021 18:56:37 +0800 Subject: [PATCH 107/936] Update next version for 4.6.6-dev (#4149) * Fix missing bootstrap * Update next version --- CMakeLists.txt | 2 +- include/swoole_version.h | 8 ++++---- package.xml | 8 +++++--- tests/swoole_curl/multi/bug71523.phpt | 1 + tests/swoole_curl/multi/bug77535.phpt | 1 + tests/swoole_curl/multi/bug77946.phpt | 2 +- tests/swoole_curl/multi/curl_int_cast.phpt | 1 + tests/swoole_curl/multi/curl_multi_close_reference.phpt | 1 + .../swoole_curl/multi/curl_multi_errno_strerror_001.phpt | 2 +- tests/swoole_curl/multi/curl_multi_segfault.phpt | 2 +- tests/swoole_curl/multi/curl_multi_select_basic1.phpt | 1 + 11 files changed, 18 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a10a17a01d0..68bfcc73a15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ PROJECT(libswoole) ENABLE_LANGUAGE(ASM) -set(SWOOLE_VERSION 4.6.5) +set(SWOOLE_VERSION 4.6.6-dev) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g") diff --git a/include/swoole_version.h b/include/swoole_version.h index 72c9b4054fe..c0ebcd076d7 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -20,10 +20,10 @@ #define SWOOLE_MAJOR_VERSION 4 #define SWOOLE_MINOR_VERSION 6 -#define SWOOLE_RELEASE_VERSION 5 -#define SWOOLE_EXTRA_VERSION "" -#define SWOOLE_VERSION "4.6.5" -#define SWOOLE_VERSION_ID 40605 +#define SWOOLE_RELEASE_VERSION 6 +#define SWOOLE_EXTRA_VERSION "dev" +#define SWOOLE_VERSION "4.6.6-dev" +#define SWOOLE_VERSION_ID 40606 #define SWOOLE_API_VERSION_ID 0x202012a #define SWOOLE_BUG_REPORT \ diff --git a/package.xml b/package.xml index 68625891092..81a9288a5dc 100644 --- a/package.xml +++ b/package.xml @@ -42,8 +42,8 @@ shenzhe163@gmail.com yes - 2021-04-07 - + 2021-04-09 + 4.6.5 4.0 @@ -60,7 +60,8 @@ Enhancement --- - * Supported native curl multi (#4093) (#4099) (#4101) (#4105) (#4113) (#4121) (swoole/swoole-src@cd7f51c) (@matyhtf) (@sy-records) (@huanghantao) + * Supported native curl multi (#4093) (#4099) (#4101) (#4105) (#4113) (#4121) (swoole/swoole-src@cd7f51c) (#4147) (@matyhtf) (@sy-records) (@huanghantao) + * Allow array HTTP/2 headers, Bug fixed for #4133 (#4140) Fixed --- @@ -1187,6 +1188,7 @@ + diff --git a/tests/swoole_curl/multi/bug71523.phpt b/tests/swoole_curl/multi/bug71523.phpt index 2d7809581cc..373b9f4d54a 100644 --- a/tests/swoole_curl/multi/bug71523.phpt +++ b/tests/swoole_curl/multi/bug71523.phpt @@ -9,6 +9,7 @@ if (!extension_loaded("curl")) { ?> --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- --FILE-- Date: Sat, 10 Apr 2021 07:49:18 +0800 Subject: [PATCH 108/936] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 478ecd1820c..a34e5286f29 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,15 @@ English | [中文](./README-CN.md) # Swoole -[![Latest Version](https://img.shields.io/github/release/swoole/swoole-src.svg)](https://github.com/swoole/swoole-src/releases) -[![License](https://img.shields.io/badge/license-apache2-blue.svg)](LICENSE) [![lib-swoole](https://github.com/swoole/swoole-src/workflows/lib-swoole/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Alib-swoole) [![ext-swoole](https://github.com/swoole/swoole-src/workflows/ext-swoole/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Aext-swoole) [![test-linux](https://github.com/swoole/swoole-src/workflows/test-linux/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Atest-linux) [![Coverity Scan Build Status](https://scan.coverity.com/projects/11654/badge.svg)](https://scan.coverity.com/projects/swoole-swoole-src) [![codecov](https://codecov.io/gh/swoole/swoole-src/branch/master/graph/badge.svg)](https://codecov.io/gh/swoole/swoole-src) -![](./mascot.png) +
+Swoole Logo +
**Swoole is an event-driven asynchronous & coroutine-based concurrency networking communication engine with high performance written in C++ for PHP.** From fd8039528857050720d4ff7a1139aafc878ec203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Sat, 10 Apr 2021 07:50:14 +0800 Subject: [PATCH 109/936] Update README.md --- README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a34e5286f29..386c9a7a1f2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ English | [中文](./README-CN.md) -# Swoole +

+Swoole Logo +

[![lib-swoole](https://github.com/swoole/swoole-src/workflows/lib-swoole/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Alib-swoole) [![ext-swoole](https://github.com/swoole/swoole-src/workflows/ext-swoole/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Aext-swoole) @@ -8,10 +10,6 @@ English | [中文](./README-CN.md) [![Coverity Scan Build Status](https://scan.coverity.com/projects/11654/badge.svg)](https://scan.coverity.com/projects/swoole-swoole-src) [![codecov](https://codecov.io/gh/swoole/swoole-src/branch/master/graph/badge.svg)](https://codecov.io/gh/swoole/swoole-src) -
-Swoole Logo -
- **Swoole is an event-driven asynchronous & coroutine-based concurrency networking communication engine with high performance written in C++ for PHP.** ## ✨Event-based From 505659ede103eea4a6e1568929f9dc187ab85dc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Sat, 10 Apr 2021 08:01:01 +0800 Subject: [PATCH 110/936] Update SUPPORTED.md --- SUPPORTED.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SUPPORTED.md b/SUPPORTED.md index 4903612a5f3..cd2d76ebef2 100644 --- a/SUPPORTED.md +++ b/SUPPORTED.md @@ -3,8 +3,8 @@ Supported Versions | Branch | Initialization | Active Support Until | Security Support Until | | ---------------------------------------------------------- | -------------- | -------------------- | ---------------------- | -| [v4.4.x](https://github.com/swoole/swoole-src/tree/v4.4.x) | 2019-4-15 | 2020-4-30 | 2020-7-31 | -| [v4.5.x](https://github.com/swoole/swoole-src/tree/v4.5.x) | 2019-12-20 | 2020-12-31 | 2021-3-31 | +| [v4.4.x](https://github.com/swoole/swoole-src/tree/v4.4.x) | 2019-4-15 | 2020-4-30 | 2022-7-31 | +| ~~[v4.5.x](https://github.com/swoole/swoole-src/tree/v4.5.x)~~ [EOL] | 2019-12-20 | 2020-12-31 | 2021-3-31 | | [v4.6.x](https://github.com/swoole/swoole-src/tree/master) | 2021-01-06 | 2022-01-31 | 2023-01-31 | | Active support | A release that is being actively supported. Reported bugs and security issues are fixed and regular point releases are made. | From 51a76b4f01837320b5514762fef57304ff802638 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Mon, 12 Apr 2021 04:53:33 +0100 Subject: [PATCH 111/936] master: delivers SIGTERM to the parent on FreeBSD (#4150) --- src/server/manager.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/server/manager.cc b/src/server/manager.cc index 86246ec4f22..58a4fecf452 100644 --- a/src/server/manager.cc +++ b/src/server/manager.cc @@ -21,8 +21,10 @@ #include #include -#ifdef __linux__ +#if defined(__linux__) #include +#elif defined(__FreeBSD__) +#include #endif namespace swoole { @@ -241,8 +243,11 @@ void Manager::start(Server *_server) { swSignal_set(SIGRTMIN, signal_handler); #endif // swSignal_set(SIGINT, signal_handler); -#ifdef __linux__ +#if defined(__linux__) prctl(PR_SET_PDEATHSIG, SIGTERM); +#elif defined(__FreeBSD__) + int sigid = SIGTERM; + procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &sigid); #endif if (_server->hooks[Server::HOOK_MANAGER_START]) { From 12aa64c23f59fce03126753725fe3406cf8540e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Mon, 12 Apr 2021 19:40:25 +0800 Subject: [PATCH 112/936] fix sync-client async connect bugs (#4152) * fix sync-client async connect bugs * fix core-tests * fix --- ext-src/swoole_client.cc | 36 +++++++++++++++++-------- ext-src/swoole_event.cc | 4 ++- include/swoole_client.h | 5 ++++ src/network/client.cc | 24 ++++++++--------- tests/swoole_event/sync_client_1.phpt | 35 ++++++++++++++++++++++++ tests/swoole_event/sync_client_2.phpt | 39 +++++++++++++++++++++++++++ 6 files changed, 119 insertions(+), 24 deletions(-) create mode 100644 tests/swoole_event/sync_client_1.phpt create mode 100644 tests/swoole_event/sync_client_2.phpt diff --git a/ext-src/swoole_client.cc b/ext-src/swoole_client.cc index 2648d26807e..f6e5bd2ab80 100644 --- a/ext-src/swoole_client.cc +++ b/ext-src/swoole_client.cc @@ -139,15 +139,26 @@ static int client_select_wait(zval *sock_array, fd_set *fds); static sw_inline Client *client_get_ptr(zval *zobject) { Client *cli = php_swoole_client_get_cli(zobject); - if (cli && cli->socket && cli->active == 1) { - return cli; - } else { - swoole_set_last_error(SW_ERROR_CLIENT_NO_CONNECTION); - zend_update_property_long( - swoole_client_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), swoole_get_last_error()); - php_swoole_error(E_WARNING, "client is not connected to server"); - return nullptr; + if (cli && cli->socket) { + if (cli->active) { + return cli; + } + if (cli->async_connect) { + cli->async_connect = false; + int error = -1; + cli->get_socket()->get_option(SOL_SOCKET, SO_ERROR, &error); + if (error == 0) { + cli->active = 1; + return cli; + } + php_swoole_client_free(zobject, cli); + } } + swoole_set_last_error(SW_ERROR_CLIENT_NO_CONNECTION); + zend_update_property_long( + swoole_client_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), swoole_get_last_error()); + php_swoole_error(E_WARNING, "client is not connected to server"); + return nullptr; } // clang-format off @@ -809,16 +820,19 @@ static PHP_METHOD(swoole_client, connect) { } } - // nonblock async if (cli->connect(cli, host, port, timeout, sock_flag) < 0) { + zend_update_property_long( + swoole_client_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errCode"), swoole_get_last_error()); + // async connect + if (cli->async_connect) { + RETURN_TRUE; + } php_swoole_error(E_WARNING, "connect to server[%s:%d] failed. Error: %s[%d]", host, (int) port, swoole_strerror(swoole_get_last_error()), swoole_get_last_error()); - zend_update_property_long( - swoole_client_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errCode"), swoole_get_last_error()); php_swoole_client_free(ZEND_THIS, cli); RETURN_FALSE; } diff --git a/ext-src/swoole_event.cc b/ext-src/swoole_event.cc index 10770d712e0..54d165e7240 100644 --- a/ext-src/swoole_event.cc +++ b/ext-src/swoole_event.cc @@ -497,7 +497,7 @@ static PHP_FUNCTION(swoole_event_add) { if (swoole_event_add(socket, events) < 0) { php_swoole_fatal_error(E_WARNING, "swoole_event_add failed"); - efree(socket); + socket->free(); event_object_free(peo); RETURN_FALSE; } @@ -579,12 +579,14 @@ static PHP_FUNCTION(swoole_event_set) { if (reactor_fd->fci_cache_read.function_handler) { sw_zend_fci_cache_discard(&reactor_fd->fci_cache_read); } + sw_zend_fci_cache_persist(&fci_cache_read); reactor_fd->fci_cache_read = fci_cache_read; } if (fci_write.size != 0) { if (reactor_fd->fci_cache_write.function_handler) { sw_zend_fci_cache_discard(&reactor_fd->fci_cache_write); } + sw_zend_fci_cache_persist(&fci_cache_write); reactor_fd->fci_cache_write = fci_cache_write; } diff --git a/include/swoole_client.h b/include/swoole_client.h index 8d7b2337fb3..50d67f53c37 100644 --- a/include/swoole_client.h +++ b/include/swoole_client.h @@ -49,6 +49,7 @@ class Client { bool remove_delay = false; bool closed = false; bool high_watermark = false; + bool async_connect = false; /** * one package: length check @@ -126,6 +127,10 @@ class Client { http_proxy->proxy_port = port; } + Socket *get_socket() { + return socket; + } + int sleep(); int wakeup(); int shutdown(int __how); diff --git a/src/network/client.cc b/src/network/client.cc index c3838c5bd83..31988e58276 100644 --- a/src/network/client.cc +++ b/src/network/client.cc @@ -546,13 +546,16 @@ static int Client_tcp_connect_sync(Client *cli, const char *host, int port, doub } #else ret = cli->socket->connect(cli->server_addr); - if (ret < 0 && errno == EINPROGRESS) { - errno = ETIMEDOUT; - } #endif if (ret < 0) { if (errno == EINTR) { continue; + } else if (errno == EINPROGRESS) { + if (nonblock) { + cli->async_connect = true; + } else { + errno = ETIMEDOUT; + } } swoole_set_last_error(errno); } @@ -575,12 +578,11 @@ static int Client_tcp_connect_sync(Client *cli, const char *host, int port, doub if (n > 0) { if (cli->socks5_handshake(buf, n) < 0) { return SW_ERR; + } + if (cli->socks5_proxy->state == SW_SOCKS5_STATE_READY) { + break; } else { - if (cli->socks5_proxy->state == SW_SOCKS5_STATE_READY) { - break; - } else { - continue; - } + continue; } } return SW_ERR; @@ -588,10 +590,8 @@ static int Client_tcp_connect_sync(Client *cli, const char *host, int port, doub } #ifdef SW_USE_OPENSSL - if (cli->open_ssl) { - if (cli->ssl_handshake() < 0) { - return SW_ERR; - } + if (cli->open_ssl && cli->ssl_handshake() < 0) { + return SW_ERR; } #endif } diff --git a/tests/swoole_event/sync_client_1.phpt b/tests/swoole_event/sync_client_1.phpt new file mode 100644 index 00000000000..bd06c58ef7d --- /dev/null +++ b/tests/swoole_event/sync_client_1.phpt @@ -0,0 +1,35 @@ +--TEST-- +swoole_event: sync client +--SKIPIF-- + +--FILE-- + false]); + +$fp = new Client(SWOOLE_SOCK_TCP); + +// sync connect +$fp->connect('www.qq.com', 80); + +Event::add($fp, function($fp) { + $resp = $fp->recv(8192); + Assert::contains($resp, 'Location: https://www.qq.com/'); + + Event::del($fp); + $fp->close(); + + echo "Done\n"; +}); + +Event::write($fp, "GET / HTTP/1.1\r\nHost: www.qq.com\r\n\r\n"); +Event::wait(); +?> +--EXPECT-- +Done diff --git a/tests/swoole_event/sync_client_2.phpt b/tests/swoole_event/sync_client_2.phpt new file mode 100644 index 00000000000..ce1da3a0121 --- /dev/null +++ b/tests/swoole_event/sync_client_2.phpt @@ -0,0 +1,39 @@ +--TEST-- +swoole_event: sync client +--SKIPIF-- + +--FILE-- + false]); + +$fp = new Client(SWOOLE_SOCK_TCP); +// async connect +$result = $fp->connect('www.qq.com', 80, 1, 1); + +Assert::true($result); +Assert::eq($fp->errCode, SOCKET_EINPROGRESS); + +Event::add($fp, null, function (Client $fp) { + $fp->send("GET / HTTP/1.1\r\nHost: www.qq.com\r\n\r\n"); + Event::set($fp, function ($fp) { + $resp = $fp->recv(8192); + Assert::contains($resp, 'Location: https://www.qq.com/'); + + Event::del($fp); + $fp->close(); + + echo "Done\n"; + }, null, SWOOLE_EVENT_READ); +}, SWOOLE_EVENT_WRITE); + +Event::wait(); +?> +--EXPECT-- +Done From 97d9437107c401c7773554b102305e40ff1bea3c Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 13 Apr 2021 11:19:16 +0800 Subject: [PATCH 113/936] add table force unlock tests --- tests/swoole_table/force_unlock.phpt | 44 ++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 tests/swoole_table/force_unlock.phpt diff --git a/tests/swoole_table/force_unlock.phpt b/tests/swoole_table/force_unlock.phpt new file mode 100644 index 00000000000..f8413e7ade9 --- /dev/null +++ b/tests/swoole_table/force_unlock.phpt @@ -0,0 +1,44 @@ +--TEST-- +swoole_table: force unlock +--SKIPIF-- + +--FILE-- +column('string', \Swoole\Table::TYPE_STRING, 4 * 1024 * 1024); +$table->column('int', \Swoole\Table::TYPE_INT, 8); +$table->create(); +$str_size = 4 * 1024 * 1024; +$str_value = random_bytes($str_size); +$data = [ + 'string' => $str_value, + 'int' => PHP_INT_MAX +]; +$table->set('test', $data); + +(new Process(function () use ($table) { + $str = str_repeat('A', 4 * 1024 * 1024); + // Fatal error: memory exhausted + $data = $table->get('test'); + var_dump(strlen($data['string'])); + var_dump(strlen($str)); + var_dump(memory_get_usage()); +}))->start(); + +Process::wait(); + +$data = $table->get('test'); +Assert::eq(strlen($data['string']), $str_size); +Assert::eq($data['string'], $str_value); +echo "Done\n"; +?> +--EXPECTF-- +Fatal error: Allowed memory size of %d bytes exhausted at %s (tried to allocate %d bytes) in %s on line %d +[%s] WARNING lock: lock process[%d] not exists, force unlock +Done From 1982bb095046090346b6fa3a7bc036a058c2360c Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 13 Apr 2021 15:43:53 +0800 Subject: [PATCH 114/936] warning free, fix tests --- include/swoole_coroutine_context.h | 2 ++ tests/swoole_table/force_unlock.phpt | 13 ++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/include/swoole_coroutine_context.h b/include/swoole_coroutine_context.h index e92c969f94b..88c5fc67472 100644 --- a/include/swoole_coroutine_context.h +++ b/include/swoole_coroutine_context.h @@ -24,7 +24,9 @@ #include #elif !defined(SW_USE_ASM_CONTEXT) #define USE_UCONTEXT 1 +#ifndef _XOPEN_SOURCE #define _XOPEN_SOURCE +#endif #include #else #define USE_ASM_CONTEXT 1 diff --git a/tests/swoole_table/force_unlock.phpt b/tests/swoole_table/force_unlock.phpt index f8413e7ade9..fc5163f02d2 100644 --- a/tests/swoole_table/force_unlock.phpt +++ b/tests/swoole_table/force_unlock.phpt @@ -22,16 +22,20 @@ $data = [ ]; $table->set('test', $data); -(new Process(function () use ($table) { - $str = str_repeat('A', 4 * 1024 * 1024); +$proc = new Process(function () use ($table) { + $str = str_repeat('A', 5 * 1024 * 1024); // Fatal error: memory exhausted $data = $table->get('test'); var_dump(strlen($data['string'])); var_dump(strlen($str)); var_dump(memory_get_usage()); -}))->start(); +}, true, SOCK_STREAM); -Process::wait(); +$proc->start(); + +$exit_status = Process::wait(); +Assert::eq($exit_status['code'], 255); +Assert::contains($proc->read(), 'Fatal error: Allowed memory'); $data = $table->get('test'); Assert::eq(strlen($data['string']), $str_size); @@ -39,6 +43,5 @@ Assert::eq($data['string'], $str_value); echo "Done\n"; ?> --EXPECTF-- -Fatal error: Allowed memory size of %d bytes exhausted at %s (tried to allocate %d bytes) in %s on line %d [%s] WARNING lock: lock process[%d] not exists, force unlock Done From 992d0ad0fe284de6b43d1d51122fcff6f6fa8e8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Wed, 14 Apr 2021 13:48:39 +0800 Subject: [PATCH 115/936] Support static compilation (#4153) * Support static compilation * Support static compilation[2] * fix --- .gitignore | 1 + config.m4 | 2 +- ext-src/php_swoole_cxx.h | 2 +- .../{php_swoole.h => php_swoole_private.h} | 56 ++-------------- ext-src/swoole_atomic.cc | 2 +- ext-src/swoole_lock.cc | 2 +- include/swoole.h | 4 +- php_swoole.h | 67 +++++++++++++++++++ thirdparty/php/standard/var_decoder.cc | 3 +- 9 files changed, 81 insertions(+), 58 deletions(-) rename ext-src/{php_swoole.h => php_swoole_private.h} (97%) create mode 100644 php_swoole.h diff --git a/.gitignore b/.gitignore index 323ed6fe3f0..3924cb00214 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ *.so *.loT *.pid +*.dep /Debug/* modules/* /.deps diff --git a/config.m4 b/config.m4 index 55ec8b7d61d..b5f18aa098e 100644 --- a/config.m4 +++ b/config.m4 @@ -730,7 +730,7 @@ if test "$PHP_SWOOLE" != "no"; then AC_DEFINE(SW_USE_ASM_CONTEXT, 1, [use boost asm context]) fi - PHP_NEW_EXTENSION(swoole, $swoole_source_file, $ext_shared,,$EXTRA_CFLAGS, cxx) + PHP_NEW_EXTENSION(swoole, $swoole_source_file, $ext_shared,, "$EXTRA_CFLAGS -DENABLE_PHP_SWOOLE", cxx) PHP_ADD_INCLUDE([$ext_srcdir]) PHP_ADD_INCLUDE([$ext_srcdir/include]) diff --git a/ext-src/php_swoole_cxx.h b/ext-src/php_swoole_cxx.h index 2224b971a81..c65650724fd 100644 --- a/ext-src/php_swoole_cxx.h +++ b/ext-src/php_swoole_cxx.h @@ -16,7 +16,7 @@ #pragma once -#include "php_swoole.h" +#include "php_swoole_private.h" #include "php_swoole_coroutine.h" #include "swoole_util.h" diff --git a/ext-src/php_swoole.h b/ext-src/php_swoole_private.h similarity index 97% rename from ext-src/php_swoole.h rename to ext-src/php_swoole_private.h index 51f44f565ef..d38bb46a3c5 100644 --- a/ext-src/php_swoole.h +++ b/ext-src/php_swoole_private.h @@ -14,30 +14,15 @@ +----------------------------------------------------------------------+ */ -#ifndef PHP_SWOOLE_H -#define PHP_SWOOLE_H +#ifndef PHP_SWOOLE_PRIVATE_H +#define PHP_SWOOLE_PRIVATE_H // C++ build format macros must defined earlier #ifdef __cplusplus #define __STDC_FORMAT_MACROS #endif -#include "php.h" -#include "php_ini.h" -#include "php_globals.h" -#include "php_main.h" - -#include "php_streams.h" -#include "php_network.h" - -#include "zend_variables.h" -#include "zend_interfaces.h" -#include "zend_closures.h" -#include "zend_exceptions.h" - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif +#include "php_swoole.h" #define SW_HAVE_COUNTABLE 1 @@ -62,8 +47,6 @@ BEGIN_EXTERN_C() extern PHPAPI int php_array_merge(zend_array *dest, zend_array *src); -extern zend_module_entry swoole_module_entry; - #ifdef PHP_WIN32 #define PHP_SWOOLE_API __declspec(dllexport) #elif defined(__GNUC__) && __GNUC__ >= 4 @@ -152,13 +135,13 @@ enum php_swoole_fd_type { PHP_SWOOLE_FD_CO_CURL, }; //--------------------------------------------------------- -typedef enum { +enum php_swoole_req_status { PHP_SWOOLE_RINIT_BEGIN, PHP_SWOOLE_RINIT_END, PHP_SWOOLE_CALL_USER_SHUTDOWNFUNC_BEGIN, PHP_SWOOLE_RSHUTDOWN_BEGIN, PHP_SWOOLE_RSHUTDOWN_END, -} php_swoole_req_status; +}; //--------------------------------------------------------- static sw_inline enum swSocket_type php_swoole_socktype(long type) { @@ -184,12 +167,6 @@ extern zend_class_entry *swoole_exception_ce; extern zend_object_handlers swoole_exception_handlers; extern zend_class_entry *swoole_error_ce; -PHP_MINIT_FUNCTION(swoole); -PHP_MSHUTDOWN_FUNCTION(swoole); -PHP_RINIT_FUNCTION(swoole); -PHP_RSHUTDOWN_FUNCTION(swoole); -PHP_MINFO_FUNCTION(swoole); - PHP_FUNCTION(swoole_clear_dns_cache); PHP_FUNCTION(swoole_last_error); PHP_FUNCTION(swoole_set_process_name); @@ -313,27 +290,6 @@ php_socket *php_swoole_convert_to_socket(int sock); zend_bool php_swoole_signal_isset_handler(int signo); -// clang-format off -ZEND_BEGIN_MODULE_GLOBALS(swoole) - zend_bool display_errors; - zend_bool cli; - zend_bool use_shortname; - zend_bool enable_coroutine; - zend_bool enable_preemptive_scheduler; - zend_bool enable_library; - long socket_buffer_size; - php_swoole_req_status req_status; -ZEND_END_MODULE_GLOBALS(swoole) -// clang-format on - -extern ZEND_DECLARE_MODULE_GLOBALS(swoole); - -#ifdef ZTS -#define SWOOLE_G(v) TSRMG(swoole_globals_id, zend_swoole_globals *, v) -#else -#define SWOOLE_G(v) (swoole_globals.v) -#endif - /* PHP 7 compatibility patches */ #define sw_zend_bailout() zend_bailout() @@ -1126,4 +1082,4 @@ static sw_inline char *php_swoole_http_build_query(zval *zdata, size_t *length, END_EXTERN_C() -#endif /* PHP_SWOOLE_H */ +#endif /* PHP_SWOOLE_PRIVATE_H */ diff --git a/ext-src/swoole_atomic.cc b/ext-src/swoole_atomic.cc index 248661f6d14..ad6be3ec385 100644 --- a/ext-src/swoole_atomic.cc +++ b/ext-src/swoole_atomic.cc @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ */ -#include "php_swoole.h" +#include "php_swoole_private.h" #include "swoole_memory.h" #ifdef HAVE_FUTEX diff --git a/ext-src/swoole_lock.cc b/ext-src/swoole_lock.cc index 0445250a935..3420dda1de0 100644 --- a/ext-src/swoole_lock.cc +++ b/ext-src/swoole_lock.cc @@ -14,7 +14,7 @@ +----------------------------------------------------------------------+ */ -#include "php_swoole.h" +#include "php_swoole_private.h" #include "swoole_memory.h" #include "swoole_lock.h" diff --git a/include/swoole.h b/include/swoole.h index 143d656f280..e91d0720f1a 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -17,9 +17,9 @@ #pragma once -#if defined(HAVE_CONFIG_H) && !defined(COMPILE_DL_SWOOLE) +#ifdef HAVE_CONFIG_H #include "config.h" -#elif defined(PHP_ATOM_INC) || defined(ZEND_SIGNALS) +#elif defined(ENABLE_PHP_SWOOLE) #include "php_config.h" #endif diff --git a/php_swoole.h b/php_swoole.h new file mode 100644 index 00000000000..fb3437c4fbf --- /dev/null +++ b/php_swoole.h @@ -0,0 +1,67 @@ +/* + +----------------------------------------------------------------------+ + | 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 | + +----------------------------------------------------------------------+ +*/ + +#ifndef PHP_SWOOLE_H +#define PHP_SWOOLE_H + +#include "php.h" +#include "php_ini.h" +#include "php_globals.h" +#include "php_main.h" + +#include "php_streams.h" +#include "php_network.h" + +#include "zend_variables.h" +#include "zend_interfaces.h" +#include "zend_closures.h" +#include "zend_exceptions.h" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +extern zend_module_entry swoole_module_entry; +#define phpext_swoole_ptr &swoole_module_entry + +PHP_MINIT_FUNCTION(swoole); +PHP_MSHUTDOWN_FUNCTION(swoole); +PHP_RINIT_FUNCTION(swoole); +PHP_RSHUTDOWN_FUNCTION(swoole); +PHP_MINFO_FUNCTION(swoole); + +// clang-format off +ZEND_BEGIN_MODULE_GLOBALS(swoole) + zend_bool display_errors; + zend_bool cli; + zend_bool use_shortname; + zend_bool enable_coroutine; + zend_bool enable_preemptive_scheduler; + zend_bool enable_library; + long socket_buffer_size; + int req_status; +ZEND_END_MODULE_GLOBALS(swoole) +// clang-format on + +extern ZEND_DECLARE_MODULE_GLOBALS(swoole); + +#ifdef ZTS +#define SWOOLE_G(v) TSRMG(swoole_globals_id, zend_swoole_globals *, v) +#else +#define SWOOLE_G(v) (swoole_globals.v) +#endif + +#endif /* PHP_SWOOLE_H */ diff --git a/thirdparty/php/standard/var_decoder.cc b/thirdparty/php/standard/var_decoder.cc index 7475eaceb96..efdb2230287 100644 --- a/thirdparty/php/standard/var_decoder.cc +++ b/thirdparty/php/standard/var_decoder.cc @@ -4,8 +4,7 @@ BEGIN_EXTERN_C() #include "ext/standard/php_var.h" #ifdef SW_USE_JSON #include "ext/json/php_json.h" - -PHP_JSON_API zend_class_entry *php_json_exception_ce; +extern PHP_JSON_API zend_class_entry *php_json_exception_ce; #endif END_EXTERN_C() From a79bd5030890a6cf6c1a36507d37dc5e89d45f80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Tue, 20 Apr 2021 08:25:12 +0800 Subject: [PATCH 116/936] Delete FUNDING.yml (#4155) --- .github/FUNDING.yml | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index b1f6ccf28e7..00000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,14 +0,0 @@ -# These are supported funding model platforms - -github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] -patreon: # Replace with a single Patreon username -open_collective: # Replace with a single Open Collective username -ko_fi: # Replace with a single Ko-fi username -tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel -community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry -liberapay: # Replace with a single Liberapay username -issuehunt: # Replace with a single IssueHunt username -otechie: # Replace with a single Otechie username -custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] - -custom: ['https://gitee.com/swoole/swoole?donate=true'] From 91bf243458f71dc5d001a20a5d4cd5ae87c6a5db Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 20 Apr 2021 11:53:59 +0800 Subject: [PATCH 117/936] fix curl multi mem leak --- ext-src/php_swoole_curl.h | 4 ++++ thirdparty/php/curl/interface.cc | 9 +++++++-- thirdparty/php/curl/multi.cc | 1 - 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ext-src/php_swoole_curl.h b/ext-src/php_swoole_curl.h index 34746008366..35cae943b0c 100644 --- a/ext-src/php_swoole_curl.h +++ b/ext-src/php_swoole_curl.h @@ -108,6 +108,10 @@ class Multi { curl_multi_setopt(multi_handle_, CURLMOPT_TIMERDATA, this); } + ~Multi() { + curl_multi_cleanup(multi_handle_); + } + CURLM *get_multi_handle() { return multi_handle_; } diff --git a/thirdparty/php/curl/interface.cc b/thirdparty/php/curl/interface.cc index b3cb4b34870..8a42277dfaa 100644 --- a/thirdparty/php/curl/interface.cc +++ b/thirdparty/php/curl/interface.cc @@ -2691,6 +2691,13 @@ void _php_curl_free(php_curl *ch) { curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_nothing); curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write_nothing); + swoole::curl::Handle *handle = nullptr; + curl_easy_getinfo(ch->cp, CURLINFO_PRIVATE, &handle); + + if (handle && handle->multi) { + handle->multi->remove_handle(ch); + } + /* cURL destructors should be invoked only by last curl handle */ if (--(*ch->clone) == 0) { zend_llist_clean(&ch->to_free->str); @@ -2701,8 +2708,6 @@ void _php_curl_free(php_curl *ch) { efree(ch->to_free); efree(ch->clone); - swoole::curl::Handle *handle = nullptr; - curl_easy_getinfo(ch->cp, CURLINFO_PRIVATE, &handle); delete handle; curl_easy_setopt(ch->cp, CURLOPT_PRIVATE, nullptr); } diff --git a/thirdparty/php/curl/multi.cc b/thirdparty/php/curl/multi.cc index 56c366dfbe1..eb182b5770c 100644 --- a/thirdparty/php/curl/multi.cc +++ b/thirdparty/php/curl/multi.cc @@ -731,7 +731,6 @@ static void _php_curl_multi_free(php_curlm *mh) { mh->multi->remove_handle(ch->cp); } } - curl_multi_cleanup(mh->multi->get_multi_handle()); zend_llist_clean(&mh->easyh); if (mh->handlers->server_push) { zval_ptr_dtor(&mh->handlers->server_push->func_name); From 6e446f67974863dba05fcc23a401431d8f6e2304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Tue, 20 Apr 2021 17:49:01 +0800 Subject: [PATCH 118/936] fix #4058 (#4158) * fix #4058 * optimize code * revert, fix tests --- ext-src/swoole_runtime.cc | 93 ++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 41 deletions(-) diff --git a/ext-src/swoole_runtime.cc b/ext-src/swoole_runtime.cc index 68a9e16acd9..3af1eff5d39 100644 --- a/ext-src/swoole_runtime.cc +++ b/ext-src/swoole_runtime.cc @@ -65,7 +65,7 @@ static int socket_flush(php_stream *stream); static int socket_close(php_stream *stream, int close_handle); static int socket_stat(php_stream *stream, php_stream_statbuf *ssb); static int socket_cast(php_stream *stream, int castas, void **ret); - +static bool socket_ssl_set_options(Socket *sock, php_stream_context *context); // clang-format off ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_void, 0, 0, 0) @@ -747,11 +747,15 @@ static bool php_openssl_capture_peer_certs(php_stream *stream, Socket *sslsock) } static int socket_enable_crypto(php_stream *stream, Socket *sock, php_stream_xport_crypto_param *cparam STREAMS_DC) { + php_stream_context *context = PHP_STREAM_CONTEXT(stream); if (cparam->inputs.activate && !sock->ssl_is_available()) { sock->enable_ssl_encrypt(); if (!sock->ssl_check_context()) { return -1; } + if (!socket_ssl_set_options(sock, context)) { + return -1; + } if (!sock->ssl_handshake()) { return -1; } @@ -760,11 +764,10 @@ static int socket_enable_crypto(php_stream *stream, Socket *sock, php_stream_xpo return sock->ssl_shutdown() ? 0 : -1; } - php_stream_context *context = PHP_STREAM_CONTEXT(stream); if (context) { zval *val = php_stream_context_get_option(context, "ssl", "capture_peer_cert"); - if (val && zend_is_true(val)) { - return php_openssl_capture_peer_certs(stream, sock) ? 0 : -1; + if (val && zend_is_true(val) && !php_openssl_capture_peer_certs(stream, sock)) { + return -1; } } @@ -993,6 +996,49 @@ static int socket_set_option(php_stream *stream, int option, int value, void *pt return PHP_STREAM_OPTION_RETURN_OK; } +static bool socket_ssl_set_options(Socket *sock, php_stream_context *context) { + if (context && ZVAL_IS_ARRAY(&context->options)) { +#ifdef SW_USE_OPENSSL + zval *ztmp; + + if (sock->ssl_is_enable() && php_swoole_array_get_value(Z_ARRVAL_P(&context->options), "ssl", ztmp) && + ZVAL_IS_ARRAY(ztmp)) { + + zval zalias; + array_init(&zalias); + zend_array *options = Z_ARRVAL_P(ztmp); + + auto add_alias = [&zalias, options](const char *name, const char *alias) { + zval *ztmp; + if (php_swoole_array_get_value_ex(options, name, ztmp)) { + add_assoc_zval_ex(&zalias, alias, strlen(alias), ztmp); + zval_add_ref(ztmp); + } + }; + + add_alias("peer_name", "ssl_host_name"); + add_alias("verify_peer", "ssl_verify_peer"); + add_alias("allow_self_signed", "ssl_allow_self_signed"); + add_alias("cafile", "ssl_cafile"); + add_alias("capath", "ssl_capath"); + add_alias("local_cert", "ssl_cert_file"); + add_alias("local_pk", "ssl_key_file"); + add_alias("passphrase", "ssl_passphrase"); + add_alias("verify_depth", "ssl_verify_depth"); + add_alias("disable_compression", "ssl_disable_compression"); + + php_swoole_socket_set_ssl(sock, &zalias); + if (!sock->ssl_check_context()) { + return false; + } + zval_dtor(&zalias); + } +#endif + } + + return true; +} + static php_stream *socket_create(const char *proto, size_t protolen, const char *resourcename, @@ -1055,43 +1101,8 @@ static php_stream *socket_create(const char *proto, goto _failed; } - if (context && ZVAL_IS_ARRAY(&context->options)) { -#ifdef SW_USE_OPENSSL - zval *ztmp; - - if (sock->ssl_is_enable() && php_swoole_array_get_value(Z_ARRVAL_P(&context->options), "ssl", ztmp) && - ZVAL_IS_ARRAY(ztmp)) { - - zval zalias; - array_init(&zalias); - zend_array *options = Z_ARRVAL_P(ztmp); - - auto add_alias = [&zalias, options](const char *name, const char *alias) { - zval *ztmp; - if (php_swoole_array_get_value_ex(options, name, ztmp)) { - add_assoc_zval_ex(&zalias, alias, strlen(alias), ztmp); - zval_add_ref(ztmp); - } - }; - - add_alias("peer_name", "ssl_host_name"); - add_alias("verify_peer", "ssl_verify_peer"); - add_alias("allow_self_signed", "ssl_allow_self_signed"); - add_alias("cafile", "ssl_cafile"); - add_alias("capath", "ssl_capath"); - add_alias("local_cert", "ssl_cert_file"); - add_alias("local_pk", "ssl_key_file"); - add_alias("passphrase", "ssl_passphrase"); - add_alias("verify_depth", "ssl_verify_depth"); - add_alias("disable_compression", "ssl_disable_compression"); - - php_swoole_socket_set_ssl(sock, &zalias); - if (!sock->ssl_check_context()) { - goto _failed; - } - zval_dtor(&zalias); - } -#endif + if (!socket_ssl_set_options(sock, context)) { + goto _failed; } return stream; From 30d8bf856ca3091a548715991ed891abbe0ab295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Wed, 21 Apr 2021 18:34:38 +0800 Subject: [PATCH 119/936] Fix get_option without checking return value (#4160) * Fix get_option without checking return value * Fix --- ext-src/swoole_client.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ext-src/swoole_client.cc b/ext-src/swoole_client.cc index f6e5bd2ab80..238ccc860cf 100644 --- a/ext-src/swoole_client.cc +++ b/ext-src/swoole_client.cc @@ -146,10 +146,11 @@ static sw_inline Client *client_get_ptr(zval *zobject) { if (cli->async_connect) { cli->async_connect = false; int error = -1; - cli->get_socket()->get_option(SOL_SOCKET, SO_ERROR, &error); - if (error == 0) { - cli->active = 1; - return cli; + if (cli->get_socket()->get_option(SOL_SOCKET, SO_ERROR, &error) == 0) { + if (error == 0) { + cli->active = 1; + return cli; + } } php_swoole_client_free(zobject, cli); } From fea67205cf3dd4e016c3ab1f058706217ba1b896 Mon Sep 17 00:00:00 2001 From: codinghuang Date: Thu, 22 Apr 2021 16:44:28 +0800 Subject: [PATCH 120/936] Update version for Swoole 4.6.6 (#4164) --- CMakeLists.txt | 2 +- include/swoole_version.h | 4 +-- package.xml | 63 ++++++++++++---------------------------- 3 files changed, 22 insertions(+), 47 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 68bfcc73a15..e73dd3f3d78 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ PROJECT(libswoole) ENABLE_LANGUAGE(ASM) -set(SWOOLE_VERSION 4.6.6-dev) +set(SWOOLE_VERSION 4.6.6) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g") diff --git a/include/swoole_version.h b/include/swoole_version.h index c0ebcd076d7..5802bee8406 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -21,8 +21,8 @@ #define SWOOLE_MAJOR_VERSION 4 #define SWOOLE_MINOR_VERSION 6 #define SWOOLE_RELEASE_VERSION 6 -#define SWOOLE_EXTRA_VERSION "dev" -#define SWOOLE_VERSION "4.6.6-dev" +#define SWOOLE_EXTRA_VERSION "" +#define SWOOLE_VERSION "4.6.6" #define SWOOLE_VERSION_ID 40606 #define SWOOLE_API_VERSION_ID 0x202012a diff --git a/package.xml b/package.xml index 81a9288a5dc..b27df2b3f3a 100644 --- a/package.xml +++ b/package.xml @@ -42,10 +42,16 @@ shenzhe163@gmail.com yes - 2021-04-09 - + + Lu Fei + lufei + lufei@php.net + yes + + 2021-04-22 + - 4.6.5 + 4.6.6 4.0 @@ -54,33 +60,16 @@ Apache2.0 - New APIs - --- - * Add count method to WaitGroup (swoole/library#100) (@sy-records) (@deminy) - Enhancement --- - * Supported native curl multi (#4093) (#4099) (#4101) (#4105) (#4113) (#4121) (swoole/swoole-src@cd7f51c) (#4147) (@matyhtf) (@sy-records) (@huanghantao) - * Allow array HTTP/2 headers, Bug fixed for #4133 (#4140) + * Sended SIGTERM to the parent process on FreeBSD (#4150) (@devnexen) + * Supported static compilation with PHP (#4153) (@matyhtf) + * Supported SNI for File Wrapper over HTTP proxy (#4158) (@matyhtf) Fixed --- - * Fixed NetBSD build (#4080) (@devnexen) - * Fixed OpenBSD build. (#4108) (@devnexen) - * Fixed illumos/solaris build, member aliases only (#4109) (@devnexen) - * Fixed heartbeat detection of SSL connection does not take effect when handshake is not completed (#4114) (@matyhtf) - * Fixed httpclient proxy with host and port (#4124) (@Yurunsoft) - * Fixed Swoole\Coroutine\Http::request, correct array to the client setting (swoole/library#103) (@leocavalcante) (@deminy) - - Kernel - --- - * Supported asm context on BSD (#4082) (@devnexen) - * Used arc4random_buf to implement getrandom under FreeBSD (#4096) (@devnexen) - * Make context darwin arm64: removes workaround and uses the label (#4127) (@devnexen) - - Test - --- - * Added build job for alpine (#4104) (@limingxinleo) + * Fixed sync-client async connect bugs (#4152) (@matyhtf) + * Fixed native curl multi mem leak (swoole/swoole-src@91bf243) (@matyhtf) @@ -508,7 +497,6 @@ - @@ -519,6 +507,7 @@ + @@ -608,6 +597,7 @@ + @@ -1131,6 +1121,8 @@ + + @@ -1880,6 +1872,7 @@ + @@ -2080,24 +2073,6 @@ 1.4.0 - - - curl - pecl.php.net - - - mysqlnd - pecl.php.net - - - json - pecl.php.net - - - sockets - pecl.php.net - - swoole From 01f112d9c4d271def819527e3fe83526cce7823d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Thu, 22 Apr 2021 16:45:30 +0800 Subject: [PATCH 121/936] refactor worker buffer (#4163) * refactor worker buffer * optimize --- ext-src/php_swoole.cc | 4 +- ext-src/php_swoole_cxx.cc | 4 -- ext-src/php_swoole_cxx.h | 16 ++++- ext-src/php_swoole_private.h | 11 ---- ext-src/swoole_client.cc | 2 +- ext-src/swoole_client_coro.cc | 5 +- ext-src/swoole_http_server_coro.cc | 2 +- ext-src/swoole_server.cc | 100 ++--------------------------- ext-src/swoole_socket_coro.cc | 5 +- ext-src/swoole_table.cc | 2 +- include/swoole.h | 8 ++- include/swoole_error.h | 2 + include/swoole_server.h | 43 ++++++++----- include/swoole_util.h | 17 +++++ src/server/master.cc | 77 ++-------------------- src/server/process.cc | 7 +- src/server/worker.cc | 48 +++++++++----- tests/swoole_server/length/03.phpt | 13 ++-- 18 files changed, 132 insertions(+), 234 deletions(-) diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index 7b23b4da6c3..bbb78578d70 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -947,7 +947,7 @@ static void *_sw_zend_string_calloc(size_t nmemb, size_t size) { } static void *_sw_zend_string_realloc(void *address, size_t size) { - zend_string *str = zend_string_realloc(sw_get_zend_string(address), size, 0); + zend_string *str = zend_string_realloc(zend::fetch_zend_string_by_val(address), size, 0); if (str == nullptr) { return nullptr; } @@ -955,7 +955,7 @@ static void *_sw_zend_string_realloc(void *address, size_t size) { } static void _sw_zend_string_free(void *address) { - zend_string_free((zend_string *) (sw_get_zend_string(address))); + zend_string_free(zend::fetch_zend_string_by_val(address)); } static swoole::Allocator php_allocator { diff --git a/ext-src/php_swoole_cxx.cc b/ext-src/php_swoole_cxx.cc index 6873ee98862..3a08191e8b7 100644 --- a/ext-src/php_swoole_cxx.cc +++ b/ext-src/php_swoole_cxx.cc @@ -60,10 +60,6 @@ void known_strings_dtor(void) { sw_zend_known_strings = nullptr; } -zend_string *fetch_zend_string_by_val(char *val) { - return (zend_string *) (val - XtOffsetOf(zend_string, val)); -} - namespace function { bool call(zend_fcall_info_cache *fci_cache, uint32_t argc, zval *argv, zval *retval, const bool enable_coroutine) { diff --git a/ext-src/php_swoole_cxx.h b/ext-src/php_swoole_cxx.h index c65650724fd..37a20b188a3 100644 --- a/ext-src/php_swoole_cxx.h +++ b/ext-src/php_swoole_cxx.h @@ -421,8 +421,20 @@ bool eval(const std::string &code, const std::string &filename = ""); void known_strings_init(void); void known_strings_dtor(void); void unserialize(zval *return_value, const char *buf, size_t buf_len, HashTable *options); +#ifdef SW_USE_JSON void json_decode(zval *return_value, const char *str, size_t str_len, zend_long options, zend_long zend_long); -zend_string *fetch_zend_string_by_val(char *val); +#endif + +static inline zend_string *fetch_zend_string_by_val(void *val) { + return (zend_string *) ((char *) val - XtOffsetOf(zend_string, val)); +} + +static inline void assign_zend_string_by_val(zval *zdata, char *addr, size_t length) { + zend_string *zstr = fetch_zend_string_by_val(addr); + addr[length] = 0; + zstr->len = length; + ZVAL_STR(zdata, zstr); +} #if PHP_VERSION_ID < 80000 #define ZEND_STR_CONST @@ -432,3 +444,5 @@ zend_string *fetch_zend_string_by_val(char *val); //-----------------------------------namespace end-------------------------------------------- } // namespace zend + + diff --git a/ext-src/php_swoole_private.h b/ext-src/php_swoole_private.h index d38bb46a3c5..e09f5607e7e 100644 --- a/ext-src/php_swoole_private.h +++ b/ext-src/php_swoole_private.h @@ -479,17 +479,6 @@ static sw_inline zval *sw_malloc_zval() { return (zval *) emalloc(sizeof(zval)); } -static sw_inline zend_string *sw_get_zend_string(void *addr) { - return (zend_string *) ((char *) addr - offsetof(zend_string, val)); -} - -static sw_inline void sw_set_zend_string(zval *zdata, char *addr, size_t length) { - zend_string *zstr = sw_get_zend_string(addr); - addr[length] = 0; - zstr->len = length; - ZVAL_STR(zdata, zstr); -} - static sw_inline zval *sw_zval_dup(zval *val) { zval *dup = sw_malloc_zval(); memcpy(dup, val, sizeof(zval)); diff --git a/ext-src/swoole_client.cc b/ext-src/swoole_client.cc index 238ccc860cf..515ce95f2ca 100644 --- a/ext-src/swoole_client.cc +++ b/ext-src/swoole_client.cc @@ -1058,7 +1058,7 @@ static PHP_METHOD(swoole_client, recv) { buffer->length = 0; } - sw_set_zend_string(return_value, buffer->str, eof); + zend::assign_zend_string_by_val(return_value, buffer->str, eof); buffer->str = nullptr; delete buffer; diff --git a/ext-src/swoole_client_coro.cc b/ext-src/swoole_client_coro.cc index fb57f4769f2..03f12a42c9a 100644 --- a/ext-src/swoole_client_coro.cc +++ b/ext-src/swoole_client_coro.cc @@ -15,6 +15,9 @@ */ #include "php_swoole_cxx.h" +#include "swoole_string.h" +#include "swoole_socket.h" +#include "swoole_protocol.h" #include "swoole_proxy.h" #include "swoole_mqtt.h" @@ -734,7 +737,7 @@ static PHP_METHOD(swoole_client_coro, recv) { retval = -1; cli->set_err(ENOMEM); } else { - result = sw_get_zend_string(strval); + result = zend::fetch_zend_string_by_val(strval); } } } else { diff --git a/ext-src/swoole_http_server_coro.cc b/ext-src/swoole_http_server_coro.cc index 7e53bc3b93f..d1a02bfe221 100644 --- a/ext-src/swoole_http_server_coro.cc +++ b/ext-src/swoole_http_server_coro.cc @@ -628,7 +628,7 @@ static PHP_METHOD(swoole_http_server_coro, onAccept) { #endif size_t total_length = buffer->offset; - sw_set_zend_string(&ctx->request.zdata, buffer->pop(SW_BUFFER_SIZE_BIG), total_length); + zend::assign_zend_string_by_val(&ctx->request.zdata, buffer->pop(SW_BUFFER_SIZE_BIG), total_length); zval *zserver = ctx->request.zserver; add_assoc_long(zserver, "server_port", hs->socket->get_bind_port()); diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index ffeb15c8c69..1a84ad31575 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -81,17 +81,6 @@ static void php_swoole_task_onTimeout(Timer *timer, TimerNode *tnode); static int php_swoole_server_dispatch_func(Server *serv, Connection *conn, SendData *data); static zval *php_swoole_server_add_port(ServerObject *server_object, ListenPort *port); -/** - * Worker Buffer - */ -static void **php_swoole_server_worker_create_buffers(Server *serv, uint buffer_num); -static void php_swoole_server_worker_free_buffers(Server *serv, uint buffer_num, void **buffers); -static void *php_swoole_server_worker_get_buffer(Server *serv, DataHead *info); -static size_t php_swoole_server_worker_get_buffer_len(Server *serv, DataHead *info); -static void php_swoole_server_worker_add_buffer_len(Server *serv, DataHead *info, size_t len); -static void php_swoole_server_worker_move_buffer(Server *serv, PipeBuffer *buffer); -static size_t php_swoole_server_worker_get_packet(Server *serv, EventData *req, char **data_ptr); - void php_swoole_server_rshutdown() { if (!sw_server()) { return; @@ -808,11 +797,11 @@ void php_swoole_get_recv_data(Server *serv, zval *zdata, RecvData *req) { ZVAL_EMPTY_STRING(zdata); } else { if (req->info.flags & SW_EVENT_DATA_OBJ_PTR) { - zend_string *worker_buffer = zend::fetch_zend_string_by_val((char *) data); - ZVAL_STR(zdata, worker_buffer); + zend::assign_zend_string_by_val(zdata, (char *) data, length); + serv->pop_worker_buffer(&req->info); } else if (req->info.flags & SW_EVENT_DATA_POP_PTR) { String *recv_buffer = serv->get_recv_buffer(serv->get_connection_by_session_id(req->info.fd)->socket); - sw_set_zend_string(zdata, recv_buffer->pop(serv->recv_buffer_size), length); + zend::assign_zend_string_by_val(zdata, recv_buffer->pop(serv->recv_buffer_size), length); } else { ZVAL_STRINGL(zdata, data, length); } @@ -1020,13 +1009,7 @@ void ServerObject::on_before_start() { /** * init method */ - serv->create_buffers = php_swoole_server_worker_create_buffers; - serv->free_buffers = php_swoole_server_worker_free_buffers; - serv->get_buffer = php_swoole_server_worker_get_buffer; - serv->get_buffer_len = php_swoole_server_worker_get_buffer_len; - serv->add_buffer_len = php_swoole_server_worker_add_buffer_len; - serv->move_buffer = php_swoole_server_worker_move_buffer; - serv->get_packet = php_swoole_server_worker_get_packet; + serv->worker_buffer_allocator = sw_zend_string_allocator(); if (serv->is_base_mode()) { serv->buffer_allocator = sw_zend_string_allocator(); @@ -2093,81 +2076,6 @@ void php_swoole_server_onBufferEmpty(Server *serv, DataHead *info) { } } -static void **php_swoole_server_worker_create_buffers(Server *serv, uint buffer_num) { - zend_string **buffers = (zend_string **) sw_calloc(buffer_num, sizeof(zend_string *)); - if (buffers == nullptr) { - swError("malloc for worker input_buffers failed"); - } - return (void **) buffers; -} - -static void php_swoole_server_worker_free_buffers(Server *serv, uint buffer_num, void **buffers) { - sw_free(buffers); -} - -static sw_inline zend_string *php_swoole_server_worker_get_input_buffer(Server *serv, int reactor_id) { - zend_string **buffers = (zend_string **) serv->worker_input_buffers; - if (serv->is_base_mode()) { - return buffers[0]; - } else { - return buffers[reactor_id]; - } -} - -static sw_inline void php_swoole_server_worker_set_buffer(Server *serv, DataHead *info, zend_string *addr) { - zend_string **buffers = (zend_string **) serv->worker_input_buffers; - buffers[info->reactor_id] = addr; -} - -static void *php_swoole_server_worker_get_buffer(Server *serv, DataHead *info) { - zend_string *worker_buffer = php_swoole_server_worker_get_input_buffer(serv, info->reactor_id); - - if (worker_buffer == nullptr) { - worker_buffer = zend_string_alloc(info->len, 0); - worker_buffer->len = 0; - php_swoole_server_worker_set_buffer(serv, info, worker_buffer); - } - - return worker_buffer->val + worker_buffer->len; -} - -static size_t php_swoole_server_worker_get_buffer_len(Server *serv, DataHead *info) { - zend_string *worker_buffer = php_swoole_server_worker_get_input_buffer(serv, info->reactor_id); - - return worker_buffer == nullptr ? 0 : worker_buffer->len; -} - -static void php_swoole_server_worker_add_buffer_len(Server *serv, DataHead *info, size_t len) { - zend_string *worker_buffer = php_swoole_server_worker_get_input_buffer(serv, info->reactor_id); - worker_buffer->len += len; -} - -static void php_swoole_server_worker_move_buffer(Server *serv, PipeBuffer *buffer) { - zend_string *worker_buffer = php_swoole_server_worker_get_input_buffer(serv, buffer->info.reactor_id); - memcpy(buffer->data, &worker_buffer, sizeof(worker_buffer)); - worker_buffer->val[worker_buffer->len] = '\0'; - php_swoole_server_worker_set_buffer(serv, &buffer->info, nullptr); -} - -static size_t php_swoole_server_worker_get_packet(Server *serv, EventData *req, char **data_ptr) { - size_t length; - if (req->info.flags & SW_EVENT_DATA_PTR) { - PacketPtr *task = (PacketPtr *) req; - *data_ptr = task->data.str; - length = task->data.length; - } else if (req->info.flags & SW_EVENT_DATA_OBJ_PTR) { - zend_string *worker_buffer; - memcpy(&worker_buffer, req->data, sizeof(worker_buffer)); - *data_ptr = worker_buffer->val; - length = worker_buffer->len; - } else { - *data_ptr = req->data; - length = req->info.len; - } - - return length; -} - static PHP_METHOD(swoole_server, __construct) { ServerObject *server_object = server_fetch_object(Z_OBJ_P(ZEND_THIS)); Server *serv = server_object->serv; diff --git a/ext-src/swoole_socket_coro.cc b/ext-src/swoole_socket_coro.cc index 2b52d41e9f4..4054781e801 100644 --- a/ext-src/swoole_socket_coro.cc +++ b/ext-src/swoole_socket_coro.cc @@ -17,9 +17,12 @@ */ #include "php_swoole_cxx.h" +#include "swoole_string.h" +#include "swoole_socket.h" #include "swoole_util.h" #include "swoole_protocol.h" #include "swoole_mqtt.h" + #include "thirdparty/php/sockets/php_sockets_cxx.h" #include @@ -1343,7 +1346,7 @@ static PHP_METHOD(swoole_socket_coro, recvPacket) { sock->socket->set_err(ENOMEM); RETURN_FALSE; } else { - sw_set_zend_string(return_value, strval, retval); + zend::assign_zend_string_by_val(return_value, strval, retval); } } } diff --git a/ext-src/swoole_table.cc b/ext-src/swoole_table.cc index c30885c8fbc..a6105e08e7b 100644 --- a/ext-src/swoole_table.cc +++ b/ext-src/swoole_table.cc @@ -351,7 +351,7 @@ PHP_METHOD(swoole_table, __construct) { RETURN_FALSE; } table->set_hash_func([](const char *key, size_t len) -> uint64_t { - return zend_string_hash_val(sw_get_zend_string((void *) key)); + return zend_string_hash_val(zend::fetch_zend_string_by_val((void *) key)); }); php_swoole_table_set_ptr(ZEND_THIS, table); } diff --git a/include/swoole.h b/include/swoole.h index e91d0720f1a..5aeadfe9e39 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -453,9 +453,10 @@ enum swEventData_flag { SW_EVENT_DATA_NORMAL, SW_EVENT_DATA_PTR = 1u << 1, SW_EVENT_DATA_CHUNK = 1u << 2, - SW_EVENT_DATA_END = 1u << 3, - SW_EVENT_DATA_OBJ_PTR = 1u << 4, - SW_EVENT_DATA_POP_PTR = 1u << 5, + SW_EVENT_DATA_BEGIN = 1u << 3, + SW_EVENT_DATA_END = 1u << 4, + SW_EVENT_DATA_OBJ_PTR = 1u << 5, + SW_EVENT_DATA_POP_PTR = 1u << 6, }; #define swTask_type(task) ((task)->info.server_fd) @@ -575,6 +576,7 @@ typedef uint8_t ReactorId; struct DataHead { SessionId fd; + uint64_t msg_id; uint32_t len; int16_t reactor_id; uint8_t type; diff --git a/include/swoole_error.h b/include/swoole_error.h index f4ea2f1ed98..b5ac35e8516 100644 --- a/include/swoole_error.h +++ b/include/swoole_error.h @@ -144,6 +144,8 @@ enum swErrorCode { * Process exit timeout, forced to end. */ SW_ERROR_SERVER_WORKER_EXIT_TIMEOUT, + SW_ERROR_SERVER_WORKER_ABNORMAL_PIPE_DATA, + SW_ERROR_SERVER_WORKER_UNPROCESSED_DATA, /** * Coroutine diff --git a/include/swoole_server.h b/include/swoole_server.h index f0af35a1c05..62c749c3974 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -551,7 +552,6 @@ class Server { int worker_uid = 0; int worker_groupid = 0; - void **worker_input_buffers = nullptr; /** * worker process max request @@ -567,6 +567,9 @@ class Server { uint32_t max_wait_time = SW_WORKER_MAX_WAIT_TIME; /*----------------------------Reactor schedule--------------------------------*/ + const Allocator *worker_buffer_allocator; + std::unordered_map> worker_buffers; + std::atomic worker_msg_id; sw_atomic_t worker_round_id = 0; /** @@ -848,13 +851,29 @@ class Server { /** * Chunk control */ - void **(*create_buffers)(Server *serv, uint32_t buffer_num) = nullptr; - void (*free_buffers)(Server *serv, uint32_t buffer_num, void **buffers) = nullptr; - void *(*get_buffer)(Server *serv, DataHead *info) = nullptr; - size_t (*get_buffer_len)(Server *serv, DataHead *info) = nullptr; - void (*add_buffer_len)(Server *serv, DataHead *info, size_t len) = nullptr; - void (*move_buffer)(Server *serv, PipeBuffer *buffer) = nullptr; - size_t (*get_packet)(Server *serv, EventData *req, char **data_ptr) = nullptr; + size_t get_packet(EventData *req, char **data_ptr); + + String *get_worker_buffer(DataHead *info) { + auto iter = worker_buffers.find(info->msg_id); + if (iter == worker_buffers.end()) { + if (info->flags & SW_EVENT_DATA_BEGIN) { + auto buffer = make_string(info->len, worker_buffer_allocator); + worker_buffers.emplace(info->msg_id, buffer); + return buffer; + } + return nullptr; + } + return iter->second.get(); + } + + void pop_worker_buffer(DataHead *info) { + uint64_t msg_id = info->msg_id; + auto iter = worker_buffers.find(msg_id); + if (iter != worker_buffers.end()) { + iter->second.get()->str = nullptr; + } + } + /** * Hook */ @@ -1033,14 +1052,6 @@ class Server { return worker_num + task_worker_num + user_worker_num; } - inline String *get_worker_input_buffer(int reactor_id) { - if (is_base_mode()) { - return (String *) worker_input_buffers[0]; - } else { - return (String *) worker_input_buffers[reactor_id]; - } - } - inline ReactorThread *get_thread(int reactor_id) { return &reactor_threads[reactor_id]; } diff --git a/include/swoole_util.h b/include/swoole_util.h index 6d8112a52a2..61a2bcf5004 100644 --- a/include/swoole_util.h +++ b/include/swoole_util.h @@ -64,6 +64,23 @@ static inline long time(bool steady = false) { } } +class DeferTask { + private: + std::stack list_; + public: + void add(Callback fn) { + list_.push(fn); + } + + ~DeferTask() { + while(!list_.empty()) { + auto fn = list_.top(); + fn(nullptr); + list_.pop(); + } + } +}; + template class ScopeGuard { public: diff --git a/src/server/master.cc b/src/server/master.cc index 600fa5dd2d6..08b6bba6b9e 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -32,14 +32,6 @@ namespace swoole { static void Server_signal_handler(int sig); -static void **Server_worker_create_buffers(Server *serv, uint32_t buffer_num); -static void Server_worker_free_buffers(Server *serv, uint32_t buffer_num, void **buffers); -static void *Server_worker_get_buffer(Server *serv, DataHead *info); -static size_t Server_worker_get_buffer_len(Server *serv, DataHead *info); -static void Server_worker_add_buffer_len(Server *serv, DataHead *info, size_t len); -static void Server_worker_move_buffer(Server *serv, PipeBuffer *buffer); -static size_t Server_worker_get_packet(Server *serv, EventData *req, char **data_ptr); - TimerCallback Server::get_timeout_callback(ListenPort *port, Reactor *reactor, Connection *conn) { return [this, port, conn, reactor](Timer *, TimerNode *) { if (conn->protect) { @@ -365,22 +357,6 @@ void Server::store_listen_socket() { } } -static void **Server_worker_create_buffers(Server *serv, uint32_t buffer_num) { - String **buffers = new String *[buffer_num]; - for (uint i = 0; i < buffer_num; i++) { - buffers[i] = new String(SW_BUFFER_SIZE_BIG); - } - return (void **) buffers; -} - -static void Server_worker_free_buffers(Server *serv, uint32_t buffer_num, void **_buffers) { - String **buffers = (String **) _buffers; - for (uint i = 0; i < buffer_num; i++) { - delete buffers[i]; - } - delete[] buffers; -} - /** * only the memory of the Worker structure is allocated, no process is fork */ @@ -478,11 +454,6 @@ void Server::init_worker(Worker *worker) { // signal init worker_signal_init(); - worker_input_buffers = (void **) create_buffers(this, get_worker_buffer_num()); - if (!worker_input_buffers) { - swError("failed to create worker buffers"); - } - if (max_request < 1) { SwooleWG.run_always = true; } else { @@ -664,16 +635,9 @@ Server::Server(enum Mode _mode) { if (gs == nullptr) { swError("[Master] Fatal Error: failed to allocate memory for Server->gs"); } - /** - * init method - */ - create_buffers = Server_worker_create_buffers; - free_buffers = Server_worker_free_buffers; - get_buffer = Server_worker_get_buffer; - get_buffer_len = Server_worker_get_buffer_len; - add_buffer_len = Server_worker_add_buffer_len; - move_buffer = Server_worker_move_buffer; - get_packet = Server_worker_get_packet; + + worker_msg_id = 1; + worker_buffer_allocator = sw_std_allocator(); g_server_instance = this; } @@ -1276,40 +1240,7 @@ bool Server::sendwait(SessionId session_id, const void *data, uint32_t length) { return conn->socket->send_blocking(data, length) == length; } -static sw_inline void Server_worker_set_buffer(Server *serv, DataHead *info, String *addr) { - String **buffers = (String **) serv->worker_input_buffers; - buffers[info->reactor_id] = addr; -} - -static void *Server_worker_get_buffer(Server *serv, DataHead *info) { - String *worker_buffer = serv->get_worker_input_buffer(info->reactor_id); - - if (worker_buffer == nullptr) { - worker_buffer = new String(info->len); - Server_worker_set_buffer(serv, info, worker_buffer); - } - - return worker_buffer->str + worker_buffer->length; -} - -static size_t Server_worker_get_buffer_len(Server *serv, DataHead *info) { - String *worker_buffer = serv->get_worker_input_buffer(info->reactor_id); - - return worker_buffer == nullptr ? 0 : worker_buffer->length; -} - -static void Server_worker_add_buffer_len(Server *serv, DataHead *info, size_t len) { - String *worker_buffer = serv->get_worker_input_buffer(info->reactor_id); - worker_buffer->length += len; -} - -static void Server_worker_move_buffer(Server *serv, PipeBuffer *buffer) { - String *worker_buffer = serv->get_worker_input_buffer(buffer->info.reactor_id); - memcpy(buffer->data, &worker_buffer, sizeof(worker_buffer)); - Server_worker_set_buffer(serv, &buffer->info, nullptr); -} - -static size_t Server_worker_get_packet(Server *serv, EventData *req, char **data_ptr) { +size_t Server::get_packet(EventData *req, char **data_ptr) { size_t length; if (req->info.flags & SW_EVENT_DATA_PTR) { PacketPtr *task = (PacketPtr *) req; diff --git a/src/server/process.cc b/src/server/process.cc index 1e4c667d2fd..a32d4c8d499 100644 --- a/src/server/process.cc +++ b/src/server/process.cc @@ -210,6 +210,7 @@ static bool process_send_packet(Server *serv, SendData *resp, SendFunc _send, vo struct iovec iov[2]; uint32_t max_length = serv->ipc_max_size - sizeof(resp->info); + resp->info.msg_id = serv->worker_msg_id.fetch_add(1); if (send_n <= max_length) { resp->info.flags = 0; @@ -240,7 +241,7 @@ static bool process_send_packet(Server *serv, SendData *resp, SendFunc _send, vo #ifdef __linux__ _ipc_use_chunk: #endif - resp->info.flags = SW_EVENT_DATA_CHUNK; + resp->info.flags = SW_EVENT_DATA_CHUNK | SW_EVENT_DATA_BEGIN; resp->info.len = send_n; while (send_n > 0) { @@ -268,6 +269,10 @@ static bool process_send_packet(Server *serv, SendData *resp, SendFunc _send, vo return false; } + if (resp->info.flags & SW_EVENT_DATA_BEGIN) { + resp->info.flags &= ~SW_EVENT_DATA_BEGIN; + } + send_n -= copy_n; offset += copy_n; } diff --git a/src/server/worker.cc b/src/server/worker.cc index 5c358500beb..f39f29fb772 100644 --- a/src/server/worker.cc +++ b/src/server/worker.cc @@ -21,6 +21,7 @@ #include #include "swoole_server.h" +#include "swoole_util.h" #include "swoole_memory.h" #include "swoole_msg_queue.h" #include "swoole_client.h" @@ -210,7 +211,7 @@ typedef std::function TaskCallback; static sw_inline void Worker_do_task(Server *serv, Worker *worker, EventData *task, const TaskCallback &callback) { RecvData recv_data; recv_data.info = task->info; - recv_data.info.len = serv->get_packet(serv, task, const_cast(&recv_data.data)); + recv_data.info.len = serv->get_packet(task, const_cast(&recv_data.data)); if (callback(serv, &recv_data) == SW_OK) { worker->request_count++; @@ -260,7 +261,7 @@ int Server::accept_task(EventData *task) { Connection *conn = get_connection_verify_no_ssl(task->info.fd); if (conn) { char *cert_data = nullptr; - size_t length = get_packet(this, task, &cert_data); + size_t length = get_packet(task, &cert_data); conn->ssl_client_cert = new String(cert_data, length); conn->ssl_client_cert_pid = SwooleG.pid; } @@ -399,8 +400,10 @@ void Server::worker_stop_callback() { if (onWorkerStop) { onWorkerStop(this, SwooleG.process_id); } - if (worker_input_buffers) { - free_buffers(this, get_worker_buffer_num(), worker_input_buffers); + if (!worker_buffers.empty()) { + swoole_error_log( + SW_LOG_WARNING, SW_ERROR_SERVER_WORKER_UNPROCESSED_DATA, "unprocessed data in the worker process buffer"); + worker_buffers.clear(); } } @@ -495,7 +498,7 @@ static void Worker_reactor_try_to_exit(Reactor *reactor) { call_worker_exit_func = 1; continue; } - int remaining_time = serv->max_wait_time - (time(nullptr) - SwooleWG.exit_time); + int remaining_time = serv->max_wait_time - (::time(nullptr) - SwooleWG.exit_time); if (remaining_time <= 0) { swoole_error_log( SW_LOG_WARNING, SW_ERROR_SERVER_WORKER_EXIT_TIMEOUT, "worker exit timeout, forced termination"); @@ -623,7 +626,6 @@ static int Worker_onPipeReceive(Reactor *reactor, Event *event) { ssize_t recv_n = 0; Server *serv = (Server *) reactor->ptr; PipeBuffer *pipe_buffer = serv->pipe_buffers[0]; - void *buffer; struct iovec buffers[2]; int recv_chunk_count = 0; DataHead *info = &pipe_buffer->info; @@ -638,24 +640,34 @@ static int Worker_onPipeReceive(Reactor *reactor, Event *event) { } if (pipe_buffer->info.flags & SW_EVENT_DATA_CHUNK) { - buffer = serv->get_buffer(serv, info); - size_t remain_len = pipe_buffer->info.len - serv->get_buffer_len(serv, info); + String *worker_buffer = serv->get_worker_buffer(info); + if (worker_buffer == nullptr) { + swoole_error_log(SW_LOG_WARNING, + SW_ERROR_SERVER_WORKER_ABNORMAL_PIPE_DATA, + "abnormal pipeline data, msg_id=%ld, pipe_fd=%d, reactor_id=%d", + info->msg_id, + event->fd, + info->reactor_id); + return SW_OK; + } + size_t remain_len = pipe_buffer->info.len - worker_buffer->length; buffers[0].iov_base = info; buffers[0].iov_len = sizeof(pipe_buffer->info); - buffers[1].iov_base = buffer; + buffers[1].iov_base = worker_buffer->str + worker_buffer->length; buffers[1].iov_len = SW_MIN(serv->ipc_max_size - sizeof(pipe_buffer->info), remain_len); recv_n = readv(event->fd, buffers, 2); if (recv_n == 0) { - swWarn("abnormal pipeline data, pipe_fd=%d, reactor_id=%d", event->fd, info->reactor_id); + swWarn("receive pipeline data error, pipe_fd=%d, reactor_id=%d", event->fd, info->reactor_id); return SW_ERR; } if (recv_n < 0 && event->socket->catch_error(errno) == SW_WAIT) { return SW_OK; } if (recv_n > 0) { - serv->add_buffer_len(serv, info, recv_n - sizeof(pipe_buffer->info)); + worker_buffer->length += (recv_n - sizeof(pipe_buffer->info)); + swTrace("append msgid=%ld, buffer=%p, n=%ld", pipe_buffer->info.msg_id, worker_buffer, recv_n); } recv_chunk_count++; @@ -677,20 +689,24 @@ static int Worker_onPipeReceive(Reactor *reactor, Event *event) { } goto _read_from_pipe; } else { - pipe_buffer->info.flags |= SW_EVENT_DATA_OBJ_PTR; /** - * Because we don't want to split the EventData parameters into swDataHead and data, + * Because we don't want to split the EventData parameters into DataHead and data, * we store the value of the worker_buffer pointer in EventData.data. * The value of this pointer will be fetched in the Server_worker_get_packet function. */ - serv->move_buffer(serv, pipe_buffer); + pipe_buffer->info.flags |= SW_EVENT_DATA_OBJ_PTR; + memcpy(pipe_buffer->data, &worker_buffer, sizeof(worker_buffer)); + swTrace("msg_id=%ld, len=%u", pipe_buffer->info.msg_id, pipe_buffer->info.len); } } else { recv_n = event->socket->read(pipe_buffer, serv->ipc_max_size); } - if (recv_n > 0) { - return serv->accept_task((EventData *) pipe_buffer); + if (recv_n > 0 && serv->accept_task((EventData *) pipe_buffer) == SW_OK) { + if (pipe_buffer->info.flags & SW_EVENT_DATA_END) { + serv->worker_buffers.erase(pipe_buffer->info.msg_id); + } + return SW_OK; } return SW_ERR; diff --git a/tests/swoole_server/length/03.phpt b/tests/swoole_server/length/03.phpt index c4439981321..3025eff130c 100644 --- a/tests/swoole_server/length/03.phpt +++ b/tests/swoole_server/length/03.phpt @@ -9,21 +9,21 @@ require __DIR__ . '/../../include/bootstrap.php'; $port = get_one_free_port(); $size = 8 * 1024 * 1024; +$_g_data = random_bytes($size); use Swoole\Server; $pm = new SwooleTest\ProcessManager; -$pm->parentFunc = function ($pid) use ($port, $pm, $size) { +$pm->parentFunc = function ($pid) use ($port, $pm, $size, $_g_data) { $cli = new Swoole\Client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC); $cli->connect(TCP_SERVER_HOST, $port, 1); - $data = str_repeat('A', $size); - $cli->send(pack('N', strlen($data)) . $data); + $cli->send(pack('N', strlen($_g_data)) . $_g_data); $recv_data = $cli->recv(); echo $recv_data; $pm->kill(); }; -$pm->childFunc = function () use ($pm, $port, $size) { +$pm->childFunc = function () use ($pm, $port, $size, $_g_data) { $serv = new Server(TCP_SERVER_HOST, $port); $serv->set([ "worker_num" => 1, @@ -37,8 +37,9 @@ $pm->childFunc = function () use ($pm, $port, $size) { $serv->on("WorkerStart", function (Server $serv) use ($pm) { $pm->wakeup(); }); - $serv->on("receive", function ($serv, $fd, $rid, $data) use ($size) { - Assert::assert(strlen($data) == $size + 4); + $serv->on("receive", function ($serv, $fd, $rid, $data) use ($size, $_g_data) { + Assert::eq(strlen($data), $size + 4); + Assert::eq($_g_data, substr($data, 4)); $serv->send($fd, "OK\n"); }); $serv->start(); From 7c3001ad57d39f7f2c3c4b31d0ecd972ab140c78 Mon Sep 17 00:00:00 2001 From: codinghuang Date: Fri, 23 Apr 2021 19:48:20 +0800 Subject: [PATCH 122/936] Update next version for 4.6.7-dev (#4165) --- CMakeLists.txt | 2 +- include/swoole_version.h | 8 ++++---- package.xml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e73dd3f3d78..33843e06ab4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ PROJECT(libswoole) ENABLE_LANGUAGE(ASM) -set(SWOOLE_VERSION 4.6.6) +set(SWOOLE_VERSION 4.6.7-dev) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g") diff --git a/include/swoole_version.h b/include/swoole_version.h index 5802bee8406..664fa71b24f 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -20,10 +20,10 @@ #define SWOOLE_MAJOR_VERSION 4 #define SWOOLE_MINOR_VERSION 6 -#define SWOOLE_RELEASE_VERSION 6 -#define SWOOLE_EXTRA_VERSION "" -#define SWOOLE_VERSION "4.6.6" -#define SWOOLE_VERSION_ID 40606 +#define SWOOLE_RELEASE_VERSION 7 +#define SWOOLE_EXTRA_VERSION "dev" +#define SWOOLE_VERSION "4.6.7-dev" +#define SWOOLE_VERSION_ID 40607 #define SWOOLE_API_VERSION_ID 0x202012a #define SWOOLE_BUG_REPORT \ diff --git a/package.xml b/package.xml index b27df2b3f3a..e0eeee5e15a 100644 --- a/package.xml +++ b/package.xml @@ -62,7 +62,7 @@ Enhancement --- - * Sended SIGTERM to the parent process on FreeBSD (#4150) (@devnexen) + * Sent SIGTERM to the manager process on FreeBSD when master process is dead (#4150) (@devnexen) * Supported static compilation with PHP (#4153) (@matyhtf) * Supported SNI for File Wrapper over HTTP proxy (#4158) (@matyhtf) From e86eac3320c6d2bb007346abbad15d10d1a72cd5 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Sat, 24 Apr 2021 23:32:25 +0800 Subject: [PATCH 123/936] fix compilation errors --- include/swoole_server.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/swoole_server.h b/include/swoole_server.h index 62c749c3974..fd96926b6ef 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -858,7 +858,7 @@ class Server { if (iter == worker_buffers.end()) { if (info->flags & SW_EVENT_DATA_BEGIN) { auto buffer = make_string(info->len, worker_buffer_allocator); - worker_buffers.emplace(info->msg_id, buffer); + worker_buffers.emplace(info->msg_id, std::shared_ptr(buffer)); return buffer; } return nullptr; From 012dd7ce3b81a9cecbe70b5038aa1163850bc5f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Sun, 25 Apr 2021 07:26:11 +0800 Subject: [PATCH 124/936] fix signal cannot be registered repeatedly (#4170) * fix signal cannot be registered repeatedly * fix tests * fix tests * fix tests * optimize code, add comment * fix tests[2] * fix compilation errors --- include/swoole_signal.h | 2 +- src/os/signal.cc | 83 +++++++++++++++----------- tests/swoole_process/signal_twice.phpt | 48 +++++++++++++++ 3 files changed, 97 insertions(+), 36 deletions(-) create mode 100644 tests/swoole_process/signal_twice.phpt diff --git a/include/swoole_signal.h b/include/swoole_signal.h index eae13a29dbd..ad3d8af7d0e 100644 --- a/include/swoole_signal.h +++ b/include/swoole_signal.h @@ -29,7 +29,7 @@ struct swSignal { #ifdef HAVE_SIGNALFD void swSignalfd_init(); -int swSignalfd_setup(swoole::Reactor *reactor); +bool swSignalfd_setup(swoole::Reactor *reactor); #endif swSignalHandler swSignal_set(int signo, swSignalHandler func); diff --git a/src/os/signal.cc b/src/os/signal.cc index 58b4d153b83..6831dde25fc 100644 --- a/src/os/signal.cc +++ b/src/os/signal.cc @@ -32,18 +32,18 @@ using swoole::Reactor; #ifdef HAVE_SIGNALFD static swSignalHandler swSignalfd_set(int signo, swSignalHandler handler); +static bool swSignalfd_create(); static void swSignalfd_clear(); static int swSignalfd_onSignal(Reactor *reactor, swEvent *event); - -static sigset_t signalfd_mask; -static int signal_fd = 0; -static swoole::network::Socket *signal_socket = nullptr; #elif HAVE_KQUEUE static swSignalHandler swKqueueSignal_set(int signo, swSignalHandler handler); #endif - static void swSignal_async_handler(int signo); +static sigset_t signalfd_mask; +static int signal_fd = 0; +static pid_t signalfd_create_pid; +static swoole::network::Socket *signal_socket = nullptr; static swSignal signals[SW_SIGNO_MAX]; static int _lock = 0; @@ -206,51 +206,66 @@ static swSignalHandler swSignalfd_set(int signo, swSignalHandler handler) { signals[signo].signo = signo; signals[signo].activated = true; } - if (signal_fd > 0) { - sigprocmask(SIG_SETMASK, &signalfd_mask, nullptr); - signalfd(signal_fd, &signalfd_mask, SFD_NONBLOCK | SFD_CLOEXEC); - } else if (sw_reactor()) { + + if (sw_reactor()) { + if (signal_fd == 0) { + swSignalfd_create(); + } else { + sigprocmask(SIG_SETMASK, &signalfd_mask, nullptr); + signalfd(signal_fd, &signalfd_mask, SFD_NONBLOCK | SFD_CLOEXEC); + } swSignalfd_setup(sw_reactor()); } return origin_handler; } -int swSignalfd_setup(Reactor *reactor) { +static bool swSignalfd_create() { if (signal_fd != 0) { - return SW_OK; + return false; } signal_fd = signalfd(-1, &signalfd_mask, SFD_NONBLOCK | SFD_CLOEXEC); if (signal_fd < 0) { swSysWarn("signalfd() failed"); - return SW_ERR; + return false; } signal_socket = swoole::make_socket(signal_fd, SW_FD_SIGNAL); if (sigprocmask(SIG_BLOCK, &signalfd_mask, nullptr) == -1) { swSysWarn("sigprocmask() failed"); - goto _error; - } - swoole_event_set_handler(SW_FD_SIGNAL, swSignalfd_onSignal); - if (swoole_event_add(signal_socket, SW_EVENT_READ) < 0) { - goto _error; + signal_socket->fd = -1; + signal_socket->free(); + close(signal_fd); + signal_fd = 0; + return false; } - reactor->set_exit_condition(Reactor::EXIT_CONDITION_SIGNALFD, [](Reactor *reactor, int &event_num) -> bool { - event_num--; - return true; - }); - + signalfd_create_pid = getpid(); SwooleG.signal_fd = signal_fd; - return SW_OK; - -_error: - signal_socket->fd = -1; - signal_socket->free(); - close(signal_fd); - signal_fd = 0; + return true; +} - return SW_ERR; +bool swSignalfd_setup(Reactor *reactor) { + if (signal_fd == 0 && !swSignalfd_create()) { + return false; + } + if (!swoole_event_isset_handler(SW_FD_SIGNAL)) { + swoole_event_set_handler(SW_FD_SIGNAL, swSignalfd_onSignal); + reactor->set_exit_condition(Reactor::EXIT_CONDITION_SIGNALFD, [](Reactor *reactor, int &event_num) -> bool { + event_num--; + return true; + }); + reactor->add_destroy_callback([](void *) { + // child process removes signal socket, parent process will not be able to trigger signal + if (signal_socket && signalfd_create_pid == getpid()) { + swoole_event_del(signal_socket); + } + }); + } + if (!(signal_socket->events & SW_EVENT_READ) && swoole_event_add(signal_socket, SW_EVENT_READ) < 0) { + return false; + } + return true; } static void swSignalfd_clear() { @@ -264,13 +279,12 @@ static void swSignalfd_clear() { } sw_memset_zero(&signalfd_mask, sizeof(signalfd_mask)); } - signal_fd = 0; + SwooleG.signal_fd = signal_fd = 0; } static int swSignalfd_onSignal(Reactor *reactor, swEvent *event) { - int n; struct signalfd_siginfo siginfo; - n = read(event->fd, &siginfo, sizeof(siginfo)); + ssize_t n = read(event->fd, &siginfo, sizeof(siginfo)); if (n < 0) { swSysWarn("read from signalfd failed"); return SW_OK; @@ -283,8 +297,7 @@ static int swSignalfd_onSignal(Reactor *reactor, swEvent *event) { swSignalHandler handler = signals[siginfo.ssi_signo].handler; if (handler == SIG_IGN) { return SW_OK; - } - else if (handler) { + } else if (handler) { handler(siginfo.ssi_signo); } else { swoole_error_log(SW_LOG_WARNING, diff --git a/tests/swoole_process/signal_twice.phpt b/tests/swoole_process/signal_twice.phpt new file mode 100644 index 00000000000..2471385c9fb --- /dev/null +++ b/tests/swoole_process/signal_twice.phpt @@ -0,0 +1,48 @@ +--TEST-- +swoole_process: signal +--SKIPIF-- + +--FILE-- +parentFunc = function ($pid) use ($pm) { + $n = N; + while($n--) { + Process::kill($pid, SIGUSR1); + $pm->wait(); + } + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm) { + $n = N; + while($n--) { + run(static function () use($n, $pm){ + $running = true; + Process::signal(SIGUSR1, function() use(&$running, $n) { + $running = false; + echo 'sigusr1 one-'.$n.PHP_EOL; + }); + $pm->wakeup(); + go(static function () use(&$running) { + while ($running) { + Co::sleep(0.1); + } + }); + }); + } + $pm->wakeup(); +}; +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +sigusr1 one-1 +sigusr1 one-0 From 7fe094067483ba5d05c2e1ebf01e34bef580e891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Tue, 27 Apr 2021 07:22:10 +0800 Subject: [PATCH 125/936] Change the log level of Request Entity Too Large to warning (#4175) --- src/server/port.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/server/port.cc b/src/server/port.cc index 626e5136dc3..1c6385d6d7a 100644 --- a/src/server/port.cc +++ b/src/server/port.cc @@ -571,7 +571,7 @@ static int Port_onRead_http(Reactor *reactor, ListenPort *port, Event *event) { } request_length = request->header_length_ + request->content_length_; if (request_length > protocol->package_max_length) { - swoole_error_log(SW_LOG_TRACE, + swoole_error_log(SW_LOG_WARNING, SW_ERROR_HTTP_INVALID_PROTOCOL, "Request Entity Too Large: request length (chunked) has already been greater than the " "package_max_length(%u)" CLIENT_INFO_FMT, @@ -593,7 +593,7 @@ static int Port_onRead_http(Reactor *reactor, ListenPort *port, Event *event) { } else { request_length = request->header_length_ + request->content_length_; if (request_length > protocol->package_max_length) { - swoole_error_log(SW_LOG_TRACE, + swoole_error_log(SW_LOG_WARNING, SW_ERROR_HTTP_INVALID_PROTOCOL, "Request Entity Too Large: header-length (%u) + content-length (%u) is greater than the " "package_max_length(%u)" CLIENT_INFO_FMT, @@ -629,7 +629,7 @@ static int Port_onRead_http(Reactor *reactor, ListenPort *port, Event *event) { if (buffer->length > request_length) { swoole_error_log(SW_LOG_TRACE, SW_ERROR_HTTP_INVALID_PROTOCOL, - "Invalid Request: %zu bytes has been disacard" CLIENT_INFO_FMT, + "Invalid Request: %zu bytes has been discard" CLIENT_INFO_FMT, buffer->length - request_length, CLIENT_INFO_ARGS); buffer->length = request_length; From 0a3be1a4af39b76069f52bf520cd787805653342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Wed, 28 Apr 2021 16:07:41 +0800 Subject: [PATCH 126/936] add core tests (#4179) * add core tests * fix * add tests * optimize tests * rename, optimize * revert --- core-tests/include/test_core.h | 1 + core-tests/src/os/process_pool.cpp | 117 +++++++++++++++++++++++++++++ core-tests/src/os/timer.cpp | 44 ++++++++--- ext-src/swoole_process_pool.cc | 7 +- ext-src/swoole_server.cc | 2 +- include/swoole_client.h | 2 +- include/swoole_process_pool.h | 22 +++--- src/network/stream.cc | 19 ++--- src/os/process_pool.cc | 115 +++++++++++++++------------- src/server/master.cc | 7 +- src/server/reactor_process.cc | 3 +- tests/include/lib/composer.lock | 12 +-- 12 files changed, 250 insertions(+), 101 deletions(-) create mode 100644 core-tests/src/os/process_pool.cpp diff --git a/core-tests/include/test_core.h b/core-tests/include/test_core.h index 76af3571573..2c64130ae0b 100644 --- a/core-tests/include/test_core.h +++ b/core-tests/include/test_core.h @@ -25,6 +25,7 @@ #define TEST_HTTP_PROXY_HOST "127.0.0.1" #define ASSERT_MEMEQ(x,y,n) ASSERT_EQ(memcmp((x), (y), n), 0) +#define EXPECT_MEMEQ(x,y,n) EXPECT_EQ(memcmp((x), (y), n), 0) namespace swoole { namespace test { const std::string &get_root_path(); diff --git a/core-tests/src/os/process_pool.cpp b/core-tests/src/os/process_pool.cpp new file mode 100644 index 00000000000..d335b64a9af --- /dev/null +++ b/core-tests/src/os/process_pool.cpp @@ -0,0 +1,117 @@ +#include "test_core.h" +#include "swoole_process_pool.h" + +using namespace swoole; + +static void test_func(ProcessPool &pool) { + EventData data{}; + data.info.len = strlen(TEST_JPG_MD5SUM); + strcpy(data.data, TEST_JPG_MD5SUM); + + int worker_id = -1; + ASSERT_EQ(pool.dispatch_blocking(&data, &worker_id), SW_OK); + + pool.running = true; + pool.onTask = [](ProcessPool *pool, EventData *task) -> int { + pool->running = false; + EXPECT_MEMEQ(task->data, TEST_JPG_MD5SUM, task->info.len); + return 0; + }; + pool.main_loop(&pool, pool.get_worker(0)); + pool.destroy(); +} + +TEST(process_pool, tcp) { + ProcessPool pool{}; + ASSERT_EQ(pool.create(1, 0, SW_IPC_SOCKET), SW_OK); + ASSERT_EQ(pool.listen(TEST_HOST, TEST_PORT, 128), SW_OK); + + test_func(pool); +} + +TEST(process_pool, unix_sock) { + ProcessPool pool{}; + signal(SIGPIPE, SIG_IGN); + ASSERT_EQ(pool.create(1, 0, SW_IPC_SOCKET), SW_OK); + ASSERT_EQ(pool.listen(TEST_TMP_FILE, 128), SW_OK); + + test_func(pool); +} + +TEST(process_pool, tcp_raw) { + ProcessPool pool{}; + constexpr int size = 2*1024*1024; + ASSERT_EQ(pool.create(1, 0, SW_IPC_SOCKET), SW_OK); + ASSERT_EQ(pool.listen(TEST_HOST, TEST_PORT, 128), SW_OK); + pool.set_protocol(0, size); + + String data(size); + data.append_random_bytes(size-1); + data.append("\0"); + + ASSERT_EQ(pool.dispatch_blocking(data.str, data.length), SW_OK); + + pool.running = true; + pool.ptr = &data; + pool.onMessage = [](ProcessPool *pool, const char *recv_data, uint32_t len) -> void { + pool->running = false; + String *_data = (String *) pool->ptr; + EXPECT_MEMEQ(_data->str, recv_data, len); + }; + pool.main_loop(&pool, pool.get_worker(0)); + pool.destroy(); +} + +TEST(process_pool, msgqueue) { + ProcessPool pool{}; + ASSERT_EQ(pool.create(1, 0x9501, SW_IPC_MSGQUEUE), SW_OK); + + test_func(pool); +} + +constexpr int magic_number = 99900011; +static ProcessPool *current_pool = nullptr; + +TEST(process_pool, shutdown) { + ProcessPool pool{}; + int *shm_value = (int *) sw_mem_pool()->alloc(sizeof(int)); + ASSERT_EQ(pool.create(1, 0x9501, SW_IPC_MSGQUEUE), SW_OK); + + // init + pool.set_protocol(1, 8192); + pool.ptr = shm_value; + pool.onWorkerStart = [](ProcessPool *pool, int worker_id) { + int *shm_value = (int *) pool->ptr; + *shm_value = magic_number; + usleep(1); + }; + + pool.onTask = [](ProcessPool *pool, EventData *task) -> int { + kill(pool->master_pid, SIGTERM); + + return 0; + }; + + current_pool = &pool; + sysv_signal(SIGTERM, [](int sig) { + current_pool->running = false; + }); + + // start + ASSERT_EQ(pool.start(), SW_OK); + + EventData msg{}; + msg.info.len = 128; + swoole_random_string(msg.data, msg.info.len); + int worker_id = -1; + pool.dispatch_blocking(&msg, &worker_id); + + // wait + ASSERT_EQ(pool.wait(), SW_OK); + + // shutdown + pool.shutdown(); + pool.destroy(); + + ASSERT_EQ(*shm_value, magic_number); +} \ No newline at end of file diff --git a/core-tests/src/os/timer.cpp b/core-tests/src/os/timer.cpp index 71450a3e0c9..aca79a0ea21 100644 --- a/core-tests/src/os/timer.cpp +++ b/core-tests/src/os/timer.cpp @@ -20,27 +20,24 @@ #include "test_core.h" #include "swoole_util.h" -static int timer1_count = 0; -static int timer2_count = 0; -static int timer_running = false; - using swoole::Timer; using swoole::TimerNode; TEST(timer, sys) { SwooleG.use_signalfd = 0; - timer_running = true; - timer1_count = timer2_count = 0; + int timer1_count = 0; + int timer2_count = 0; + int timer_running = true; uint64_t ms1 = swoole::time(); swoole_timer_add( - 20, false, [](Timer *, TimerNode *) { timer1_count++; }, nullptr); + 20, false, [&](Timer *, TimerNode *) { timer1_count++; }, nullptr); swoole_timer_add( 100, true, - [](Timer *, TimerNode *tnode) { + [&](Timer *, TimerNode *tnode) { timer2_count++; if (timer2_count == 5) { swoole_timer_del(tnode); @@ -63,5 +60,34 @@ TEST(timer, sys) { swoole_timer_free(); - ASSERT_LE(ms2 - ms1, 505); + ASSERT_LE(ms2 - ms1, 510); + ASSERT_EQ(timer1_count, 1); + ASSERT_EQ(timer2_count, 5); +} + +TEST(timer, async) { + int timer1_count = 0; + int timer2_count = 0; + + swoole_event_init(SW_EVENTLOOP_WAIT_EXIT); + + uint64_t ms1 = swoole::time(); + swoole_timer_after( + 20, [&](Timer *, TimerNode *) { timer1_count++; }, nullptr); + + swoole_timer_tick( + 100, + [&](Timer *, TimerNode *tnode) { + timer2_count++; + if (timer2_count == 5) { + swoole_timer_del(tnode); + } + }, + nullptr); + + swoole_event_wait(); + uint64_t ms2 = swoole::time(); + ASSERT_LE(ms2 - ms1, 510); + ASSERT_EQ(timer1_count, 1); + ASSERT_EQ(timer2_count, 5); } diff --git a/ext-src/swoole_process_pool.cc b/ext-src/swoole_process_pool.cc index a198ca4bab3..c2132f6a5d9 100644 --- a/ext-src/swoole_process_pool.cc +++ b/ext-src/swoole_process_pool.cc @@ -307,7 +307,8 @@ static PHP_METHOD(swoole_process_pool, __construct) { } ProcessPool *pool = (ProcessPool *) emalloc(sizeof(*pool)); - if (ProcessPool::create(pool, worker_num, (key_t) msgq_key, ipc_type) < 0) { + *pool = {}; + if (pool->create(worker_num, (key_t) msgq_key, (swIPC_type) ipc_type) < 0) { zend_throw_exception_ex(swoole_exception_ce, errno, "failed to create process pool"); efree(pool); RETURN_FALSE; @@ -450,9 +451,9 @@ static PHP_METHOD(swoole_process_pool, listen) { int ret; // unix socket if (SW_STRCASECT(host, l_host, "unix:/")) { - ret = pool->create_unix_socket(host + 5, backlog); + ret = pool->listen(host + 5, backlog); } else { - ret = pool->create_tcp_socket(host, port, backlog); + ret = pool->listen(host, port, backlog); } pool->stream_info_->socket->set_fd_option(0, 1); diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 1a84ad31575..af7d68ae8e0 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -3120,7 +3120,7 @@ static PHP_METHOD(swoole_server, taskwait) { sw_atomic_fetch_add(&serv->gs->tasking_num, 1); - if (serv->gs->task_workers.dispatch_blocking(&buf, &_dst_worker_id) >= 0) { + if (serv->gs->task_workers.dispatch_blocking(&buf, &_dst_worker_id) == SW_OK) { while (1) { if (task_notify_socket->wait_event((int) (timeout * 1000), SW_EVENT_READ) != SW_OK) { break; diff --git a/include/swoole_client.h b/include/swoole_client.h index 50d67f53c37..195b8a2bee6 100644 --- a/include/swoole_client.h +++ b/include/swoole_client.h @@ -174,7 +174,7 @@ class Stream { } } ~Stream(); - static int recv_blocking(Socket *sock, void *__buf, size_t __len); + static ssize_t recv_blocking(Socket *sock, void *__buf, size_t __len); static void set_protocol(Protocol *protocol); private: diff --git a/include/swoole_process_pool.h b/include/swoole_process_pool.h index 6ea3a6fa136..0d869ce1d0d 100644 --- a/include/swoole_process_pool.h +++ b/include/swoole_process_pool.h @@ -45,10 +45,9 @@ class ExitStatus { private: pid_t pid_; int status_; - public: - ExitStatus(pid_t _pid, int _status) : pid_(_pid), status_(_status) { - } + public: + ExitStatus(pid_t _pid, int _status) : pid_(_pid), status_(_status) {} pid_t get_pid() const { return pid_; @@ -163,6 +162,7 @@ struct StreamInfo { network::Socket *socket; network::Socket *last_connection; char *socket_file; + int socket_port; String *response_buffer; }; @@ -176,6 +176,7 @@ struct ProcessPool { bool started; uint8_t dispatch_mode; uint8_t ipc_mode; + pid_t master_pid; uint32_t reload_worker_i; uint32_t max_wait_time; Worker *reload_workers; @@ -218,13 +219,12 @@ struct ProcessPool { uint8_t scheduler_warning; time_t warning_time; - int (*onTask)(ProcessPool *pool, swEventData *task); + int (*onTask)(ProcessPool *pool, EventData *task); void (*onWorkerStart)(ProcessPool *pool, int worker_id); void (*onMessage)(ProcessPool *pool, const char *data, uint32_t length); void (*onWorkerStop)(ProcessPool *pool, int worker_id); - - int (*main_loop)(ProcessPool *pool, Worker *worker); int (*onWorkerNotFound)(ProcessPool *pool, const ExitStatus &exit_status); + int (*main_loop)(ProcessPool *pool, Worker *worker); sw_atomic_t round_id; @@ -266,15 +266,15 @@ struct ProcessPool { pid_t spawn(Worker *worker); int dispatch(EventData *data, int *worker_id); int response(const char *data, int length); - int dispatch_blocking(swEventData *data, int *dst_worker_id); + int dispatch_blocking(EventData *data, int *dst_worker_id); + int dispatch_blocking(const char *data, uint32_t len); int add_worker(Worker *worker); int del_worker(Worker *worker); void destroy(); - int create_unix_socket(const char *socket_file, int blacklog); - int create_tcp_socket(const char *host, int port, int blacklog); + int create(uint32_t worker_num, key_t msgqueue_key = 0, swIPC_type ipc_mode = SW_IPC_NONE); + int listen(const char *socket_file, int blacklog); + int listen(const char *host, int port, int blacklog); int schedule(); - - static int create(ProcessPool *pool, uint32_t worker_num, key_t msgqueue_key, int ipc_mode); }; }; // namespace swoole diff --git a/src/network/stream.cc b/src/network/stream.cc index 9c287467111..3cd9e2f5857 100644 --- a/src/network/stream.cc +++ b/src/network/stream.cc @@ -128,26 +128,17 @@ int Stream::send(const char *data, size_t length) { return SW_OK; } -int Stream::recv_blocking(Socket *sock, void *__buf, size_t __len) { +ssize_t Stream::recv_blocking(Socket *sock, void *__buf, size_t __len) { int tmp = 0; ssize_t ret = sock->recv_blocking(&tmp, sizeof(tmp), MSG_WAITALL); - if (ret <= 0) { - return SW_CLOSE; + return SW_ERR; } int length = (int) ntohl(tmp); - if (length <= 0) { - return SW_CLOSE; - } else if (length > (int) __len) { - return SW_CLOSE; - } - - ret = sock->recv_blocking(__buf, length, MSG_WAITALL); - if (ret <= 0) { - return SW_CLOSE; - } else { - return SW_READY; + if (length <= 0 || length > (int) __len) { + return SW_ERR; } + return sock->recv_blocking(__buf, length, MSG_WAITALL); } } // namespace network diff --git a/src/os/process_pool.cc b/src/os/process_pool.cc index 4faf19f895f..fbe7732bc66 100644 --- a/src/os/process_pool.cc +++ b/src/os/process_pool.cc @@ -66,65 +66,63 @@ static void ProcessPool_kill_timeout_worker(Timer *timer, TimerNode *tnode) { /** * Process manager */ -int ProcessPool::create(ProcessPool *pool, uint32_t worker_num, key_t msgqueue_key, int ipc_mode) { - *pool = {}; - pool->worker_num = worker_num; - +int ProcessPool::create(uint32_t _worker_num, key_t _msgqueue_key, swIPC_type _ipc_mode) { + worker_num = _worker_num; /** * Shared memory is used here */ - pool->workers = (Worker *) sw_mem_pool()->alloc(worker_num * sizeof(Worker)); - if (pool->workers == nullptr) { + workers = (Worker *) sw_mem_pool()->alloc(_worker_num * sizeof(Worker)); + if (workers == nullptr) { swSysWarn("malloc[1] failed"); return SW_ERR; } - if (ipc_mode == SW_IPC_MSGQUEUE) { - pool->use_msgqueue = 1; - pool->msgqueue_key = msgqueue_key; - pool->queue = new MsgQueue(pool->msgqueue_key); - if (!pool->queue->ready()) { - delete pool->queue; - pool->queue = nullptr; + if (_ipc_mode == SW_IPC_MSGQUEUE) { + use_msgqueue = 1; + msgqueue_key = _msgqueue_key; + queue = new MsgQueue(msgqueue_key); + if (!queue->ready()) { + delete queue; + queue = nullptr; return SW_ERR; } - } else if (ipc_mode == SW_IPC_UNIXSOCK) { - pool->pipes = new std::vector>; - SW_LOOP_N(worker_num) { + } else if (_ipc_mode == SW_IPC_UNIXSOCK) { + pipes = new std::vector>; + SW_LOOP_N(_worker_num) { auto sock = new UnixSocket(true, SOCK_DGRAM); if (!sock->ready()) { delete sock; - delete pool->pipes; - pool->pipes = nullptr; + delete pipes; + pipes = nullptr; return SW_ERR; } - pool->pipes->emplace_back(sock); - pool->workers[i].pipe_master = sock->get_socket(true); - pool->workers[i].pipe_worker = sock->get_socket(false); - pool->workers[i].pipe_object = sock; - } - } else if (ipc_mode == SW_IPC_SOCKET) { - pool->use_socket = 1; - pool->stream_info_ = new StreamInfo(); + pipes->emplace_back(sock); + workers[i].pipe_master = sock->get_socket(true); + workers[i].pipe_worker = sock->get_socket(false); + workers[i].pipe_object = sock; + } + } else if (_ipc_mode == SW_IPC_SOCKET) { + use_socket = 1; + stream_info_ = new StreamInfo(); } else { - ipc_mode = SW_IPC_NONE; + _ipc_mode = SW_IPC_NONE; } - pool->map_ = new std::unordered_map; + map_ = new std::unordered_map; - pool->ipc_mode = ipc_mode; - if (ipc_mode > SW_IPC_NONE) { - pool->main_loop = ProcessPool_worker_loop; + ipc_mode = _ipc_mode; + if (_ipc_mode > SW_IPC_NONE) { + main_loop = ProcessPool_worker_loop; } - SW_LOOP_N(worker_num) { - pool->workers[i].pool = pool; + SW_LOOP_N(_worker_num) { + workers[i].pool = this; } return SW_OK; } -int ProcessPool::create_unix_socket(const char *socket_file, int blacklog) { +int ProcessPool::listen(const char *socket_file, int blacklog) { if (ipc_mode != SW_IPC_SOCKET) { swWarn("ipc_mode is not SW_IPC_SOCKET"); return SW_ERR; @@ -133,6 +131,7 @@ int ProcessPool::create_unix_socket(const char *socket_file, int blacklog) { if (stream_info_->socket_file == nullptr) { return SW_ERR; } + stream_info_->socket_port = 0; stream_info_->socket = make_server_socket(SW_SOCK_UNIX_STREAM, stream_info_->socket_file, 0, blacklog); if (!stream_info_->socket) { return SW_ERR; @@ -140,7 +139,7 @@ int ProcessPool::create_unix_socket(const char *socket_file, int blacklog) { return SW_OK; } -int ProcessPool::create_tcp_socket(const char *host, int port, int blacklog) { +int ProcessPool::listen(const char *host, int port, int blacklog) { if (ipc_mode != SW_IPC_SOCKET) { swWarn("ipc_mode is not SW_IPC_SOCKET"); return SW_ERR; @@ -149,6 +148,7 @@ int ProcessPool::create_tcp_socket(const char *host, int port, int blacklog) { if (stream_info_->socket_file == nullptr) { return SW_ERR; } + stream_info_->socket_port = port; stream_info_->socket = make_server_socket(SW_SOCK_TCP, host, port, blacklog); if (!stream_info_->socket) { return SW_ERR; @@ -167,6 +167,7 @@ int ProcessPool::start() { uint32_t i; running = started = true; + master_pid = getpid(); for (i = 0; i < worker_num; i++) { workers[i].pool = this; @@ -253,26 +254,37 @@ int ProcessPool::dispatch(EventData *data, int *dst_worker_id) { return ret; } +int ProcessPool::dispatch_blocking(const char *data, uint32_t len) { + assert(use_socket); + + network::Client _socket(stream_info_->socket->socket_type, false); + if (!_socket.socket) { + return SW_ERR; + } + if (_socket.connect(&_socket, stream_info_->socket_file, stream_info_->socket_port, -1, 0) < 0) { + return SW_ERR; + } + uint32_t packed_len = htonl(len); + if (_socket.send(&_socket, (char *) &packed_len, 4, 0) < 0) { + return SW_ERR; + } + if (_socket.send(&_socket, (char *) data, len, 0) < 0) { + return SW_ERR; + } + _socket.close(); + return SW_OK; +} + /** * dispatch data to worker + * @return SW_OK/SW_ERR */ -int ProcessPool::dispatch_blocking(swEventData *data, int *dst_worker_id) { +int ProcessPool::dispatch_blocking(EventData *data, int *dst_worker_id) { int ret = 0; int sendn = sizeof(data->info) + data->info.len; if (use_socket) { - swoole::network::Client _socket(SW_SOCK_UNIX_STREAM, false); - if (!_socket.socket) { - return SW_ERR; - } - if (_socket.connect(&_socket, stream_info_->socket_file, 0, -1, 0) < 0) { - return SW_ERR; - } - if (_socket.send(&_socket, (char *) data, sendn, 0) < 0) { - return SW_ERR; - } - _socket.close(); - return SW_OK; + return dispatch_blocking((char *) data, sendn); } if (*dst_worker_id < 0) { @@ -289,7 +301,7 @@ int ProcessPool::dispatch_blocking(swEventData *data, int *dst_worker_id) { sw_atomic_fetch_add(&worker->tasking_num, 1); } - return ret; + return ret > 0 ? SW_OK : SW_ERR; } void ProcessPool::shutdown() { @@ -380,7 +392,7 @@ void ProcessPool::set_max_request(uint32_t _max_request, uint32_t _max_request_g static int ProcessPool_worker_loop(ProcessPool *pool, Worker *worker) { struct { long mtype; - swEventData buf; + EventData buf; } out{}; ssize_t n = 0, ret, worker_task_always = 0; @@ -421,9 +433,8 @@ static int ProcessPool_worker_loop(ProcessPool *pool, Worker *worker) { break; } } - n = Stream::recv_blocking(conn, (void *) &out.buf, sizeof(out.buf)); - if (n == SW_CLOSE) { + if (n < 0) { conn->free(); continue; } diff --git a/src/server/master.cc b/src/server/master.cc index 08b6bba6b9e..512086b328c 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -362,7 +362,7 @@ void Server::store_listen_socket() { */ int Server::create_task_workers() { key_t key = 0; - int ipc_mode; + swIPC_type ipc_mode; if (task_ipc_mode == SW_TASK_IPC_MSGQUEUE || task_ipc_mode == SW_TASK_IPC_PREEMPTIVE) { key = message_queue_key; @@ -374,7 +374,8 @@ int Server::create_task_workers() { } ProcessPool *pool = &gs->task_workers; - if (ProcessPool::create(pool, task_worker_num, key, ipc_mode) < 0) { + *pool = {}; + if (pool->create(task_worker_num, key, ipc_mode) < 0) { swWarn("[Master] create task_workers failed"); return SW_ERR; } @@ -386,7 +387,7 @@ int Server::create_task_workers() { if (ipc_mode == SW_IPC_SOCKET) { char sockfile[sizeof(struct sockaddr_un)]; snprintf(sockfile, sizeof(sockfile), "/tmp/swoole.task.%d.sock", gs->master_pid); - if (gs->task_workers.create_unix_socket(sockfile, 2048) < 0) { + if (gs->task_workers.listen(sockfile, 2048) < 0) { return SW_ERR; } } diff --git a/src/server/reactor_process.cc b/src/server/reactor_process.cc index 78cf3d9caeb..8e67f4045f5 100644 --- a/src/server/reactor_process.cc +++ b/src/server/reactor_process.cc @@ -77,7 +77,8 @@ int Server::start_reactor_processes() { } ProcessPool *pool = &gs->event_workers; - if (ProcessPool::create(pool, worker_num, 0, SW_IPC_UNIXSOCK) < 0) { + *pool = {}; + if (pool->create(worker_num, 0, SW_IPC_UNIXSOCK) < 0) { return SW_ERR; } pool->set_max_request(max_request, max_request_grace); diff --git a/tests/include/lib/composer.lock b/tests/include/lib/composer.lock index 8e0e42d7ff8..a9550beb123 100644 --- a/tests/include/lib/composer.lock +++ b/tests/include/lib/composer.lock @@ -178,16 +178,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "1.8.1", + "version": "1.8.2", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "35ea11d335fd638b5882ff1725228b3d35496ab1" + "reference": "dc960a912984efb74d0a90222870c72c87f10c91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/35ea11d335fd638b5882ff1725228b3d35496ab1", - "reference": "35ea11d335fd638b5882ff1725228b3d35496ab1", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/dc960a912984efb74d0a90222870c72c87f10c91", + "reference": "dc960a912984efb74d0a90222870c72c87f10c91", "shasum": "", "mirrors": [ { @@ -253,9 +253,9 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/1.8.1" + "source": "https://github.com/guzzle/psr7/tree/1.8.2" }, - "time": "2021-03-21T16:25:00+00:00" + "time": "2021-04-26T09:17:50+00:00" }, { "name": "psr/http-client", From fd05cc157d7b94bcf6d758ae65aaa1c6b60c648b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Wed, 28 Apr 2021 19:36:42 +0800 Subject: [PATCH 127/936] remove useless header files (#4180) * remove useless header files * fix tests --- examples/cpp/test_server.cc | 2 +- ext-src/php_swoole.cc | 2 -- ext-src/swoole_async_coro.cc | 6 +----- ext-src/swoole_client.cc | 2 -- ext-src/swoole_client_coro.cc | 3 --- ext-src/swoole_http2_client_coro.cc | 6 +++--- ext-src/swoole_http2_server.cc | 4 +--- ext-src/swoole_http_client_coro.cc | 3 +-- ext-src/swoole_http_request.cc | 10 ---------- ext-src/swoole_http_response.cc | 12 ------------ ext-src/swoole_http_server.cc | 2 -- ext-src/swoole_http_server_coro.cc | 1 - ext-src/swoole_mysql_coro.cc | 2 ++ ext-src/swoole_process.cc | 4 +--- ext-src/swoole_runtime.cc | 1 - ext-src/swoole_websocket_server.cc | 8 -------- src/core/base.cc | 11 ++--------- src/core/error.cc | 2 -- src/core/timer.cc | 2 +- src/coroutine/channel.cc | 2 -- src/coroutine/file_lock.cc | 1 - src/coroutine/hook.cc | 3 --- src/coroutine/socket.cc | 1 - src/memory/global_memory.cc | 4 +--- src/network/address.cc | 4 ---- src/network/dns.cc | 2 +- src/network/socket.cc | 1 - src/network/stream.cc | 1 - src/os/base.cc | 4 ---- src/os/msg_queue.cc | 1 - src/os/pipe.cc | 2 -- src/os/process_pool.cc | 1 - src/os/signal.cc | 1 - src/os/timer.cc | 2 +- src/os/unix_socket.cc | 2 -- src/protocol/http.cc | 3 --- src/protocol/socks5.cc | 3 +-- src/reactor/base.cc | 3 --- src/reactor/epoll.cc | 3 +-- src/server/manager.cc | 1 - src/server/master.cc | 1 - src/server/reactor_thread.cc | 2 -- src/server/task_worker.cc | 1 - src/server/worker.cc | 3 --- src/wrapper/event.cc | 4 ---- 45 files changed, 18 insertions(+), 121 deletions(-) diff --git a/examples/cpp/test_server.cc b/examples/cpp/test_server.cc index 16b091983ad..80ab845c697 100644 --- a/examples/cpp/test_server.cc +++ b/examples/cpp/test_server.cc @@ -97,7 +97,7 @@ int my_onReceive(swServer *serv, swRecvData *req) { g_receive_count++; - swConnection *conn = serv->get_connection_by_session_id(req->info.fd); + Connection *conn = serv->get_connection_by_session_id(req->info.fd); memcpy(req_data, req->data, req->info.len); swoole::rtrim(req_data, req->info.len); diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index bbb78578d70..681d8ff3ec2 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -23,7 +23,6 @@ #include "zend_exceptions.h" BEGIN_EXTERN_C() -#include "ext/standard/php_var.h" #ifdef SW_USE_JSON #include "ext/json/php_json.h" #endif @@ -31,7 +30,6 @@ END_EXTERN_C() #include "swoole_mime_type.h" #include "swoole_server.h" -#include "swoole_client.h" #include "swoole_util.h" #include diff --git a/ext-src/swoole_async_coro.cc b/ext-src/swoole_async_coro.cc index 2615d7e4b46..4bd62a68050 100644 --- a/ext-src/swoole_async_coro.cc +++ b/ext-src/swoole_async_coro.cc @@ -15,11 +15,7 @@ */ #include "php_swoole_cxx.h" -#include "php_streams.h" -#include "php_network.h" - -#include "ext/standard/file.h" -#include "ext/standard/basic_functions.h" +#include "swoole_socket.h" #include #include diff --git a/ext-src/swoole_client.cc b/ext-src/swoole_client.cc index 515ce95f2ca..f84ef78e53d 100644 --- a/ext-src/swoole_client.cc +++ b/ext-src/swoole_client.cc @@ -29,8 +29,6 @@ using swoole::Socks5Proxy; using swoole::HttpProxy; using swoole::String; -#include "ext/standard/basic_functions.h" - struct ClientCallback { zend_fcall_info_cache cache_onConnect; zend_fcall_info_cache cache_onReceive; diff --git a/ext-src/swoole_client_coro.cc b/ext-src/swoole_client_coro.cc index 03f12a42c9a..45746a42bcf 100644 --- a/ext-src/swoole_client_coro.cc +++ b/ext-src/swoole_client_coro.cc @@ -19,9 +19,6 @@ #include "swoole_socket.h" #include "swoole_protocol.h" #include "swoole_proxy.h" -#include "swoole_mqtt.h" - -#include "ext/standard/basic_functions.h" using swoole::coroutine::Socket; using swoole::network::Address; diff --git a/ext-src/swoole_http2_client_coro.cc b/ext-src/swoole_http2_client_coro.cc index 28619eaa624..f143eb035c6 100644 --- a/ext-src/swoole_http2_client_coro.cc +++ b/ext-src/swoole_http2_client_coro.cc @@ -17,17 +17,17 @@ #include "php_swoole_cxx.h" #include "php_swoole_http.h" +#include "swoole_string.h" +#include "swoole_protocol.h" +#include "swoole_socket.h" #include "swoole_util.h" #ifdef SW_USE_HTTP2 -#include "swoole_http.h" #include "swoole_http2.h" #define HTTP2_CLIENT_HOST_HEADER_INDEX 3 -#include - using namespace swoole; using swoole::coroutine::Socket; diff --git a/ext-src/swoole_http2_server.cc b/ext-src/swoole_http2_server.cc index a4696f2e083..e57ec30ca0b 100644 --- a/ext-src/swoole_http2_server.cc +++ b/ext-src/swoole_http2_server.cc @@ -22,8 +22,6 @@ #include "main/php_variables.h" -#include - using namespace swoole; using std::string; using swoole::coroutine::System; @@ -954,7 +952,7 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { client->send_window += value; } else if (client->streams.find(stream_id) != client->streams.end()) { stream = client->streams[stream_id]; - Server *serv = (swServer *) stream->ctx->private_data; + Server *serv = (Server *) stream->ctx->private_data; stream->send_window += value; if (serv->send_yield && stream->waiting_coroutine) { diff --git a/ext-src/swoole_http_client_coro.cc b/ext-src/swoole_http_client_coro.cc index 557a0b262bd..e863238e892 100644 --- a/ext-src/swoole_http_client_coro.cc +++ b/ext-src/swoole_http_client_coro.cc @@ -21,6 +21,7 @@ #include "php_swoole_http.h" #include "swoole_string.h" +#include "swoole_protocol.h" #include "swoole_file.h" #include "swoole_util.h" #include "swoole_websocket.h" @@ -32,8 +33,6 @@ SW_EXTERN_C_BEGIN #include "thirdparty/swoole_http_parser.h" -#include "ext/standard/basic_functions.h" -#include "ext/standard/php_http.h" #include "ext/standard/base64.h" #ifdef SW_HAVE_ZLIB diff --git a/ext-src/swoole_http_request.cc b/ext-src/swoole_http_request.cc index bc381f2959f..426453724f9 100644 --- a/ext-src/swoole_http_request.cc +++ b/ext-src/swoole_http_request.cc @@ -18,20 +18,10 @@ SW_EXTERN_C_BEGIN #include "ext/standard/url.h" -#include "ext/standard/sha1.h" -#include "ext/standard/php_var.h" -#include "ext/standard/php_string.h" -#include "ext/standard/php_math.h" -#include "ext/standard/php_array.h" -#include "ext/date/php_date.h" -#include "ext/standard/md5.h" SW_EXTERN_C_END -#include "main/rfc1867.h" #include "main/php_variables.h" -#include "swoole_base64.h" - #ifdef SW_HAVE_ZLIB #include #endif diff --git a/ext-src/swoole_http_response.cc b/ext-src/swoole_http_response.cc index c0f3240cb65..6fd6bb9d3e7 100644 --- a/ext-src/swoole_http_response.cc +++ b/ext-src/swoole_http_response.cc @@ -16,18 +16,6 @@ #include "php_swoole_http_server.h" -extern "C" { -#include "ext/standard/url.h" -#include "ext/standard/sha1.h" -#include "ext/standard/php_var.h" -#include "ext/standard/php_string.h" -#include "ext/standard/php_math.h" -#include "ext/standard/php_array.h" -#include "ext/date/php_date.h" -#include "ext/standard/md5.h" -} - -#include "swoole_base64.h" #include "swoole_util.h" #ifdef SW_HAVE_ZLIB diff --git a/ext-src/swoole_http_server.cc b/ext-src/swoole_http_server.cc index 6933caad3b0..b036d59934e 100644 --- a/ext-src/swoole_http_server.cc +++ b/ext-src/swoole_http_server.cc @@ -16,8 +16,6 @@ #include "php_swoole_http_server.h" -#include "main/rfc1867.h" - using namespace swoole; using swoole::coroutine::Socket; using http_request = swoole::http::Request; diff --git a/ext-src/swoole_http_server_coro.cc b/ext-src/swoole_http_server_coro.cc index d1a02bfe221..9e0cd514520 100644 --- a/ext-src/swoole_http_server_coro.cc +++ b/ext-src/swoole_http_server_coro.cc @@ -18,7 +18,6 @@ #include #include -#include using swoole::PHPCoroutine; using swoole::coroutine::Socket; diff --git a/ext-src/swoole_mysql_coro.cc b/ext-src/swoole_mysql_coro.cc index ae4a6477fcb..45ea132eb03 100644 --- a/ext-src/swoole_mysql_coro.cc +++ b/ext-src/swoole_mysql_coro.cc @@ -20,6 +20,8 @@ #include "php_swoole_cxx.h" #include "php_swoole_mysql_proto.h" +#include "swoole_string.h" + // see mysqlnd 'L64' macro redefined #undef L64 diff --git a/ext-src/swoole_process.cc b/ext-src/swoole_process.cc index 4d7d08693a7..1942a4e126f 100644 --- a/ext-src/swoole_process.cc +++ b/ext-src/swoole_process.cc @@ -15,10 +15,8 @@ */ #include "php_swoole_cxx.h" -#include "php_streams.h" -#include "php_network.h" - #include "php_swoole_process.h" + #include "swoole_server.h" #include "swoole_msg_queue.h" #include "swoole_signal.h" diff --git a/ext-src/swoole_runtime.cc b/ext-src/swoole_runtime.cc index 3af1eff5d39..b3d131130dc 100644 --- a/ext-src/swoole_runtime.cc +++ b/ext-src/swoole_runtime.cc @@ -23,7 +23,6 @@ #endif #include -#include /* openssl */ #ifndef OPENSSL_NO_ECDH diff --git a/ext-src/swoole_websocket_server.cc b/ext-src/swoole_websocket_server.cc index aa8ece72f6e..06207f35cd1 100644 --- a/ext-src/swoole_websocket_server.cc +++ b/ext-src/swoole_websocket_server.cc @@ -16,19 +16,11 @@ #include "php_swoole_http_server.h" -#include - SW_EXTERN_C_BEGIN -#include "ext/standard/url.h" #include "ext/standard/sha1.h" -#include "ext/standard/php_var.h" -#include "ext/standard/php_string.h" -#include "ext/date/php_date.h" -#include "main/php_variables.h" SW_EXTERN_C_END #include "swoole_base64.h" -#include "thirdparty/swoole_http_parser.h" using swoole::Connection; using swoole::ListenPort; diff --git a/src/core/base.cc b/src/core/base.cc index def5efdfc2c..882518d6aed 100644 --- a/src/core/base.cc +++ b/src/core/base.cc @@ -22,23 +22,15 @@ #include #include -#include - -#ifdef HAVE_EXECINFO -#include -#endif #ifdef __MACH__ #include #endif -#include #include #include #include #include -#include -#include #include "swoole_api.h" #include "swoole_string.h" @@ -264,7 +256,7 @@ pid_t swoole_fork(int flags) { swFatalError(SW_ERROR_OPERATION_NOT_SUPPORT, "must be forked outside the coroutine"); } if (SwooleTG.async_threads) { - swTrace("aio_task_num=%d, reactor=%p", SwooleTG.async_threads->task_num, SwooleTG.reactor); + swTrace("aio_task_num=%d, reactor=%p", SwooleTG.async_threads->task_num, sw_reactor()); swFatalError(SW_ERROR_OPERATION_NOT_SUPPORT, "can not create server after using async file operation"); } } @@ -748,6 +740,7 @@ void swoole_print_backtrace(void) { std::cout << boost::stacktrace::stacktrace(); } #elif defined(HAVE_EXECINFO) +#include void swoole_print_backtrace(void) { int size = 16; void *array[16]; diff --git a/src/core/error.cc b/src/core/error.cc index 449e02b3228..905ac8c23ad 100644 --- a/src/core/error.cc +++ b/src/core/error.cc @@ -14,8 +14,6 @@ +----------------------------------------------------------------------+ */ -#include - #include "swoole.h" namespace swoole { diff --git a/src/core/timer.cc b/src/core/timer.cc index 187ccf3688f..93290141303 100644 --- a/src/core/timer.cc +++ b/src/core/timer.cc @@ -17,7 +17,7 @@ #include "swoole_api.h" #include "swoole_reactor.h" #include "swoole_timer.h" -#include "swoole_util.h" + #if !defined(HAVE_CLOCK_GETTIME) && defined(__MACH__) #include #include diff --git a/src/coroutine/channel.cc b/src/coroutine/channel.cc index 9762a4c9184..2317c12e465 100644 --- a/src/coroutine/channel.cc +++ b/src/coroutine/channel.cc @@ -16,8 +16,6 @@ #include "swoole_coroutine_channel.h" -#include - namespace swoole { namespace coroutine { diff --git a/src/coroutine/file_lock.cc b/src/coroutine/file_lock.cc index f184a172b93..02a69fdebee 100644 --- a/src/coroutine/file_lock.cc +++ b/src/coroutine/file_lock.cc @@ -14,7 +14,6 @@ +----------------------------------------------------------------------+ */ -#include #include #include diff --git a/src/coroutine/hook.cc b/src/coroutine/hook.cc index dde942ec886..58498e264ad 100644 --- a/src/coroutine/hook.cc +++ b/src/coroutine/hook.cc @@ -15,15 +15,12 @@ */ #include -#include #include #include #include #include #include -#include -#include #include #include diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index 50c6a7ba0aa..8ccf30da998 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -20,7 +20,6 @@ #include "swoole_coroutine_socket.h" #include -#include #include "swoole_util.h" #include "swoole_socket.h" diff --git a/src/memory/global_memory.cc b/src/memory/global_memory.cc index 8f552143849..011debd169b 100644 --- a/src/memory/global_memory.cc +++ b/src/memory/global_memory.cc @@ -16,16 +16,14 @@ #include "swoole.h" #include "swoole_memory.h" + #include -#include #include #define SW_MIN_PAGE_SIZE 4096 namespace swoole { -struct MemoryBlock; - struct GlobalMemoryImpl { bool shared; uint32_t pagesize; diff --git a/src/network/address.cc b/src/network/address.cc index 2175ef69172..9a8f4ebb473 100644 --- a/src/network/address.cc +++ b/src/network/address.cc @@ -16,10 +16,6 @@ #include "swoole_socket.h" -#include -#include -#include - namespace swoole { namespace network { diff --git a/src/network/dns.cc b/src/network/dns.cc index 1399af82ed0..faf4350caf7 100644 --- a/src/network/dns.cc +++ b/src/network/dns.cc @@ -17,7 +17,6 @@ #include "swoole.h" #include "swoole_coroutine_socket.h" -#include #include #include @@ -324,6 +323,7 @@ namespace swoole { namespace network { #ifndef HAVE_GETHOSTBYNAME2_R +#include static std::mutex g_gethostbyname2_lock; #endif diff --git a/src/network/socket.cc b/src/network/socket.cc index 7d8e0cf9ce8..f0183d19554 100644 --- a/src/network/socket.cc +++ b/src/network/socket.cc @@ -16,7 +16,6 @@ #include "swoole_socket.h" -#include #include #include "swoole_api.h" diff --git a/src/network/stream.cc b/src/network/stream.cc index 3cd9e2f5857..7b84a747193 100644 --- a/src/network/stream.cc +++ b/src/network/stream.cc @@ -18,7 +18,6 @@ #include "swoole_api.h" #include "swoole_string.h" #include "swoole_socket.h" -#include "swoole_reactor.h" #include "swoole_protocol.h" #include "swoole_client.h" diff --git a/src/os/base.cc b/src/os/base.cc index 662285446ce..49f97bf57c1 100644 --- a/src/os/base.cc +++ b/src/os/base.cc @@ -17,14 +17,10 @@ */ #include "swoole.h" -#include "swoole_string.h" #include "swoole_socket.h" #include "swoole_async.h" -#include -#include #include -#include #if __APPLE__ int swoole_daemon(int nochdir, int noclose) { diff --git a/src/os/msg_queue.cc b/src/os/msg_queue.cc index 08c00eab24f..561dbe1b327 100644 --- a/src/os/msg_queue.cc +++ b/src/os/msg_queue.cc @@ -17,7 +17,6 @@ #include "swoole.h" #include "swoole_msg_queue.h" -#include #include #include diff --git a/src/os/pipe.cc b/src/os/pipe.cc index c550c107bef..a31c64c3fa3 100644 --- a/src/os/pipe.cc +++ b/src/os/pipe.cc @@ -17,8 +17,6 @@ #include "swoole_pipe.h" #include "swoole_socket.h" -#include - namespace swoole { using network::Socket; diff --git a/src/os/process_pool.cc b/src/os/process_pool.cc index fbe7732bc66..56d05158e98 100644 --- a/src/os/process_pool.cc +++ b/src/os/process_pool.cc @@ -16,7 +16,6 @@ #include "swoole_api.h" #include "swoole_memory.h" -#include "swoole_signal.h" #include "swoole_socket.h" #include "swoole_string.h" #include "swoole_msg_queue.h" diff --git a/src/os/signal.cc b/src/os/signal.cc index 6831dde25fc..5d9ba4a24af 100644 --- a/src/os/signal.cc +++ b/src/os/signal.cc @@ -19,7 +19,6 @@ #include "swoole_signal.h" #include "swoole_socket.h" #include "swoole_reactor.h" -#include "swoole_string.h" #ifdef HAVE_SIGNALFD #include diff --git a/src/os/timer.cc b/src/os/timer.cc index 54e4e11ff98..bab72fc5aed 100644 --- a/src/os/timer.cc +++ b/src/os/timer.cc @@ -16,7 +16,7 @@ #include "swoole_timer.h" #include "swoole_signal.h" -#include "swoole_util.h" + #include namespace swoole { diff --git a/src/os/unix_socket.cc b/src/os/unix_socket.cc index 39cabd75753..70383058443 100644 --- a/src/os/unix_socket.cc +++ b/src/os/unix_socket.cc @@ -17,8 +17,6 @@ #include "swoole_pipe.h" #include "swoole_socket.h" -#include - namespace swoole { UnixSocket::UnixSocket(bool blocking, int _protocol) : SocketPair(blocking), protocol_(_protocol) { diff --git a/src/protocol/http.cc b/src/protocol/http.cc index 06972e5ac05..202ab0386f3 100644 --- a/src/protocol/http.cc +++ b/src/protocol/http.cc @@ -17,9 +17,6 @@ #include "swoole_http.h" #include "swoole_server.h" -#include -#include - #include #include "swoole_util.h" diff --git a/src/protocol/socks5.cc b/src/protocol/socks5.cc index 1c780c4ac53..fd25bfbf946 100644 --- a/src/protocol/socks5.cc +++ b/src/protocol/socks5.cc @@ -16,9 +16,8 @@ +----------------------------------------------------------------------+ */ -#include "swoole.h" #include "swoole_proxy.h" -#include "swoole_client.h" + namespace swoole { const char *Socks5Proxy::strerror(int code) { switch (code) { diff --git a/src/reactor/base.cc b/src/reactor/base.cc index 935bff51c00..109ea207a69 100644 --- a/src/reactor/base.cc +++ b/src/reactor/base.cc @@ -18,12 +18,9 @@ #include "swoole_socket.h" #include "swoole_signal.h" #include "swoole_reactor.h" -#include "swoole_timer.h" #include "swoole_api.h" #include "swoole_c_api.h" -#include - namespace swoole { using network::Socket; diff --git a/src/reactor/epoll.cc b/src/reactor/epoll.cc index cbd7f9a0add..a49cf6e2fea 100644 --- a/src/reactor/epoll.cc +++ b/src/reactor/epoll.cc @@ -18,8 +18,6 @@ #include "swoole_socket.h" #include "swoole_reactor.h" -#include - #define EVENT_DEBUG 0 #ifdef HAVE_EPOLL @@ -70,6 +68,7 @@ class ReactorEpoll : public ReactorImpl { }; #if EVENT_DEBUG +#include static thread_local std::unordered_map event_map; Socket *swoole_event_map_get(int sockfd) { diff --git a/src/server/manager.cc b/src/server/manager.cc index 58a4fecf452..e94009d13f1 100644 --- a/src/server/manager.cc +++ b/src/server/manager.cc @@ -20,7 +20,6 @@ #include #include -#include #if defined(__linux__) #include #elif defined(__FreeBSD__) diff --git a/src/server/master.cc b/src/server/master.cc index 512086b328c..edfa8c67ce6 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -16,7 +16,6 @@ #include "swoole_server.h" #include "swoole_memory.h" -#include "swoole_http.h" #include "swoole_lock.h" #include "swoole_util.h" diff --git a/src/server/reactor_thread.cc b/src/server/reactor_thread.cc index 7190ed98aed..a3b0a618086 100644 --- a/src/server/reactor_thread.cc +++ b/src/server/reactor_thread.cc @@ -17,10 +17,8 @@ #include "swoole_server.h" #include "swoole_memory.h" #include "swoole_hash.h" -#include "swoole_http.h" #include "swoole_client.h" #include "swoole_util.h" -#include "swoole_websocket.h" #include diff --git a/src/server/task_worker.cc b/src/server/task_worker.cc index 1ef7a9d27f3..4382ef2d29b 100644 --- a/src/server/task_worker.cc +++ b/src/server/task_worker.cc @@ -15,7 +15,6 @@ */ #include "swoole_server.h" -#include "swoole_util.h" namespace swoole { using network::Socket; diff --git a/src/server/worker.cc b/src/server/worker.cc index f39f29fb772..8c3eca6b7f8 100644 --- a/src/server/worker.cc +++ b/src/server/worker.cc @@ -14,18 +14,15 @@ +----------------------------------------------------------------------+ */ -#include #include #include #include #include #include "swoole_server.h" -#include "swoole_util.h" #include "swoole_memory.h" #include "swoole_msg_queue.h" #include "swoole_client.h" -#include "swoole_async.h" swoole::WorkerGlobal SwooleWG = {}; diff --git a/src/wrapper/event.cc b/src/wrapper/event.cc index c7c12988543..f180864ab2b 100644 --- a/src/wrapper/event.cc +++ b/src/wrapper/event.cc @@ -15,16 +15,12 @@ */ #include "swoole_api.h" -#include "swoole_socket.h" #include "swoole_reactor.h" #include "swoole_client.h" -#include "swoole_async.h" -#include "swoole_coroutine_c_api.h" #include "swoole_coroutine_socket.h" #include "swoole_coroutine_system.h" #include -#include using namespace swoole; From 63a47f840eb6f26573b848569d4d1048d10c43e4 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Wed, 5 May 2021 23:53:26 +0100 Subject: [PATCH 128/936] FreeBSD build fix swoole_get_local_ip (#4188) --- ext-src/php_swoole.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index 681d8ff3ec2..bca519a60af 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -38,7 +38,7 @@ END_EXTERN_C() #include #include -#if __MACH__ +#if defined(__MACH__) || defined(__FreeBSD__) #include #endif From dd3fd53b72931856a9f714f7f4cfeae4367b42a7 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Sat, 8 May 2021 13:23:34 +0800 Subject: [PATCH 129/936] optimize naming --- src/core/channel.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/core/channel.cc b/src/core/channel.cc index 739cf49cd08..aace9cc5571 100644 --- a/src/core/channel.cc +++ b/src/core/channel.cc @@ -27,7 +27,7 @@ namespace swoole { #define SW_CHANNEL_MIN_MEM (1024 * 64) -struct Channel_item { +struct ChannelSlice { int length; char data[0]; }; @@ -41,9 +41,9 @@ Channel *Channel::make(size_t size, size_t maxlen, int flags) { /** * overflow space */ - mem = sw_shm_malloc(size + sizeof(Channel) + maxlen + sizeof(Channel_item)); + mem = sw_shm_malloc(size + sizeof(Channel) + maxlen + sizeof(ChannelSlice)); } else { - mem = sw_malloc(size + sizeof(Channel) + maxlen + sizeof(Channel_item)); + mem = sw_malloc(size + sizeof(Channel) + maxlen + sizeof(ChannelSlice)); } if (mem == nullptr) { @@ -88,7 +88,7 @@ int Channel::in(const void *in_data, int data_length) { if (full()) { return SW_ERR; } - Channel_item *item; + ChannelSlice *item; int msize = sizeof(item->length) + data_length; if (tail < head) { @@ -96,10 +96,10 @@ int Channel::in(const void *in_data, int data_length) { if ((head - tail) < msize) { return SW_ERR; } - item = (Channel_item *) ((char *) mem + tail); + item = (ChannelSlice *) ((char *) mem + tail); tail += msize; } else { - item = (Channel_item *) ((char *) mem + tail); + item = (ChannelSlice *) ((char *) mem + tail); tail += msize; if (tail >= (off_t) size) { tail = 0; @@ -121,7 +121,7 @@ int Channel::out(void *out_buf, int buffer_length) { return SW_ERR; } - Channel_item *item = (Channel_item *) ((char *) mem + head); + ChannelSlice *item = (ChannelSlice *) ((char *) mem + head); assert(buffer_length >= item->length); memcpy(out_buf, item->data, item->length); head += (item->length + sizeof(item->length)); @@ -144,7 +144,7 @@ int Channel::peek(void *out, int buffer_length) { int length; lock->lock(); - Channel_item *item = (Channel_item *) ((char *) mem + head); + ChannelSlice *item = (ChannelSlice *) ((char *) mem + head); assert(buffer_length >= item->length); memcpy(out, item->data, item->length); length = item->length; From ca775ae04357b53ed166a76d06028d9b1fbe3e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Mon, 10 May 2021 11:20:59 +0800 Subject: [PATCH 130/936] Fix #4186 (#4190) * optimize naming * Support use process::signal in manager process * Support use process::signal in task process --- ext-src/swoole_process.cc | 19 +++++-- ext-src/swoole_server.cc | 4 +- include/swoole_server.h | 9 ++++ tests/swoole_process/signal_in_manager.phpt | 43 +++++++++++++++ .../swoole_process/signal_in_task_worker.phpt | 54 +++++++++++++++++++ 5 files changed, 122 insertions(+), 7 deletions(-) create mode 100644 tests/swoole_process/signal_in_manager.phpt create mode 100644 tests/swoole_process/signal_in_task_worker.phpt diff --git a/ext-src/swoole_process.cc b/ext-src/swoole_process.cc index 1942a4e126f..636025ce30c 100644 --- a/ext-src/swoole_process.cc +++ b/ext-src/swoole_process.cc @@ -534,10 +534,7 @@ static PHP_METHOD(swoole_process, signal) { RETURN_FALSE; } - php_swoole_check_reactor(); - swSignalHandler handler = swSignal_get_handler(signo); - if (handler && handler != php_swoole_onSignal) { php_swoole_fatal_error( E_WARNING, "signal [" ZEND_LONG_FMT "] processor has been registered by the system", signo); @@ -572,6 +569,18 @@ static PHP_METHOD(swoole_process, signal) { handler = php_swoole_onSignal; } + if (sw_server() && sw_server()->is_sync_process()) { + if (signal_fci_caches[signo]) { + sw_zend_fci_cache_free(signal_fci_caches[signo]); + } else { + SwooleTG.signal_listener_num++; + } + signal_fci_caches[signo] = fci_cache; + swSignal_set(signo, handler); + RETURN_TRUE; + } + + php_swoole_check_reactor(); // for swSignalfd_setup SwooleTG.reactor->check_signalfd = true; if (!SwooleTG.reactor->isset_exit_condition(Reactor::EXIT_CONDITION_SIGNAL_LISTENER)) { @@ -649,7 +658,7 @@ static void php_swoole_onSignal(int signo) { if (fci_cache) { zval argv[1]; - ZVAL_LONG(& argv[0], signo); + ZVAL_LONG(&argv[0], signo); if (UNEXPECTED(!zend::function::call(fci_cache, 1, argv, nullptr, php_swoole_is_enable_coroutine()))) { php_swoole_fatal_error( @@ -784,7 +793,7 @@ static PHP_METHOD(swoole_process, read) { zend_string *buf = zend_string_alloc(buf_size, 0); ssize_t ret = process->pipe_current->read(buf->val, buf_size); - + if (ret < 0) { efree(buf); if (errno != EINTR) { diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index af7d68ae8e0..1745d96c177 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -3777,7 +3777,7 @@ static PHP_METHOD(swoole_server, protect) { static PHP_METHOD(swoole_server, getWorkerId) { Server *serv = php_swoole_server_get_and_check_server(ZEND_THIS); - if (!serv->is_worker()) { + if (!serv->is_worker() && !serv->is_task_worker()) { RETURN_FALSE; } else { RETURN_LONG(SwooleG.process_id); @@ -3812,7 +3812,7 @@ static PHP_METHOD(swoole_server, getWorkerStatus) { static PHP_METHOD(swoole_server, getWorkerPid) { Server *serv = php_swoole_server_get_and_check_server(ZEND_THIS); - if (!serv->is_worker()) { + if (!serv->is_worker() && !serv->is_task_worker()) { zend_long worker_id = -1; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &worker_id) == FAILURE) { RETURN_FALSE; diff --git a/include/swoole_server.h b/include/swoole_server.h index fd96926b6ef..508cace3cd4 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -1080,6 +1080,15 @@ class Server { return SwooleG.process_type == SW_PROCESS_USERWORKER; } + bool is_sync_process() { + if (is_manager()) { + return true; + } + if (is_task_worker() && !task_enable_coroutine) { + return true; + } + return false; + } inline bool is_shutdown() { return gs->shutdown; } diff --git a/tests/swoole_process/signal_in_manager.phpt b/tests/swoole_process/signal_in_manager.phpt new file mode 100644 index 00000000000..8cdc27375c3 --- /dev/null +++ b/tests/swoole_process/signal_in_manager.phpt @@ -0,0 +1,43 @@ +--TEST-- +swoole_process: signal in manager +--SKIPIF-- + +--FILE-- +parentFunc = function ($pid) use ($pm) { + $manager_pid = file_get_contents(PID_FILE); + Process::kill($manager_pid, SIGINT); + $pm->wait(); + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm) { + $serv = new Server('127.0.0.1', $pm->getFreePort()); + $serv->set(["worker_num" => 1, 'log_file' => '/dev/null']); + $serv->on("ManagerStart", function (Server $serv) use ($pm) { + file_put_contents(PID_FILE, $serv->getManagerPid()); + $pm->wakeup(); + Process::signal(SIGINT, function () use($pm) { + echo "SIGINT triggered\n"; + $pm->wakeup(); + }); + }); + $serv->on("Receive", function (Server $serv, $fd, $reactorId, $data) { + }); + $serv->start(); +}; +$pm->childFirst(); +$pm->run(); +unlink(PID_FILE); +?> +--EXPECT-- +SIGINT triggered diff --git a/tests/swoole_process/signal_in_task_worker.phpt b/tests/swoole_process/signal_in_task_worker.phpt new file mode 100644 index 00000000000..e174e8355af --- /dev/null +++ b/tests/swoole_process/signal_in_task_worker.phpt @@ -0,0 +1,54 @@ +--TEST-- +swoole_process: signal in task worker +--SKIPIF-- + +--FILE-- +parentFunc = function ($pid) use ($pm) { + $_pid = file_get_contents(PID_FILE); + Process::kill($_pid, SIGINT); + $pm->wait(); + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm) { + $serv = new Server('127.0.0.1', $pm->getFreePort()); + $serv->set([ + 'worker_num' => 1, + 'task_worker_num' => 1, + 'log_file' => '/dev/null' + ]); + + $serv->on("WorkerStart", function (Server $serv) use ($pm) { + if ($serv->taskworker) { + file_put_contents(PID_FILE, $serv->getWorkerPid()); + $pm->wakeup(); + Process::signal(SIGINT, function () use($pm) { + echo "SIGINT triggered\n"; + $pm->wakeup(); + }); + } + }); + $serv->on("Task", function (Server $serv) use ($pm) { + + }); + $serv->on("Receive", function (Server $serv, $fd, $reactorId, $data) { + }); + $serv->start(); +}; +$pm->childFirst(); +$pm->run(); +unlink(PID_FILE); +?> +--EXPECT-- +SIGINT triggered From c265fba22d9c0819919b40c38c6ba1622e96db88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Mon, 10 May 2021 11:22:22 +0800 Subject: [PATCH 131/936] Remove .travis.yml and update codecov (#4191) --- .github/workflows/lib.yml | 13 ++++--- .travis.yml | 66 ------------------------------------ ext-src/php_swoole_library.h | 19 +++++++---- 3 files changed, 22 insertions(+), 76 deletions(-) delete mode 100644 .travis.yml diff --git a/.github/workflows/lib.yml b/.github/workflows/lib.yml index 068be733617..00d551a63b1 100644 --- a/.github/workflows/lib.yml +++ b/.github/workflows/lib.yml @@ -3,7 +3,7 @@ name: lib-swoole on: [push, pull_request] env: - CODECOV_TOKEN: "50513381-198e-43d3-a8b1-e36b95038927" # from: https://codecov.io/gh/swoole/swoole-src + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} jobs: build: @@ -41,6 +41,11 @@ jobs: run: sudo apt-get install lcov && sudo lcov --directory . --capture --output-file coverage.info && sudo lcov --remove coverage.info "${{runner.workspace}}/swoole-src/include/*" '/usr/*' --output-file coverage.info && - sudo lcov --list coverage.info && - sudo curl -s https://codecov.io/bash -o codecov.sh && - sudo chmod +x codecov.sh && sudo ./codecov.sh -f coverage.info -t ${CODECOV_TOKEN} + sudo lcov --list coverage.info + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: ./coverage.info + fail_ci_if_error: true diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a77299349b9..00000000000 --- a/.travis.yml +++ /dev/null @@ -1,66 +0,0 @@ -language: php - -compiler: - - gcc - - clang - -os: - - linux - -php: - - 7.2 - - 7.3 - - 7.4 - - nightly - -matrix: - fast_finish: true - allow_failures: - - php: nightly - -notifications: - email: team@swoole.com - -sudo: required - -env: - global: - - secure: "Mqg9ifSV0BLv2TIBw/x64aEuB8Y5aPXwXg7xAOq08oPlHBYSBgSYxroJL5PXs0fe7PszZF20bUBinwmEXYQzqgP/40Y1kmq/kfTsDXwTOc9qbAbA1pWvH+Sk1kDP5MLJRPWBCkqctyFd0I0u0SdzT1fgSqirqEz2bMnbAUVpSvo=" - - CODECOV_TOKEN=:50513381-198e-43d3-a8b1-e36b95038927 - -services: - - docker - -before_install: - - echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- - -addons: - coverity_scan: - project: - name: "swoole/swoole-src" - description: "Build submitted via Travis CI" - notification_email: team@swoole.com - build_command_prepend: "./configure; make clean" - build_command: "make -j 4" - branch_pattern: coverity_scan - -# compile -before_script: - - date - - env - - uname -a - - ulimit -a - - php -v - - ls -al - - pwd - - echo "`git log -20 --pretty --oneline`" - - echo "`git log -10 --stat --pretty --oneline`" - - ./travis/pecl-install.sh - - ./travis/simple-compile.sh - - php --ri swoole - -script: - - ./travis/route.sh - -after_success: - - bash <(curl -s https://codecov.io/bash) \ No newline at end of file diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index 9c812d3f201..e0541187a93 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: c1d47051d7a949c0a76ca595f6d523faa2ecc3b9 */ +/* $Id: b2d3486c3bca310c730de8575e71b27d2d0ee30d */ static const char* swoole_library_source_constants = "\n" @@ -2803,9 +2803,14 @@ static const char* swoole_library_source_core_database_pdo_proxy = " || $n === 0\n" " || $this->__object->inTransaction()\n" " ) {\n" - " $exception = new PDOException($errorInfo[2], $errorInfo[1]);\n" - " $exception->errorInfo = $errorInfo;\n" - " throw $exception;\n" + " /* '00000' means “no error.”, as specified by ANSI SQL and ODBC. */\n" + " if (!empty($errorInfo) && $errorInfo[0] !== '00000') {\n" + " $exception = new PDOException($errorInfo[2], $errorInfo[1]);\n" + " $exception->errorInfo = $errorInfo;\n" + " throw $exception;\n" + " }\n" + " /* no error info, just return false */\n" + " break;\n" " }\n" " $this->reconnect();\n" " continue;\n" @@ -2917,12 +2922,14 @@ static const char* swoole_library_source_core_database_pdo_statement_proxy = " ) {\n" " $errorInfo = $this->__object->errorInfo();\n" "\n" - " // '00000' means “no error.”, as specified by ANSI SQL and ODBC.\n" - " if ($errorInfo[0] !== '00000') {\n" + " /* '00000' means “no error.”, as specified by ANSI SQL and ODBC. */\n" + " if (!empty($errorInfo) && $errorInfo[0] !== '00000') {\n" " $exception = new PDOException($errorInfo[2], $errorInfo[1]);\n" " $exception->errorInfo = $errorInfo;\n" " throw $exception;\n" " }\n" + " /* no error info, just return false */\n" + " break;\n" " }\n" " if ($this->parent->getRound() === $this->parentRound) {\n" " /* if not equal, parent has reconnected */\n" From 6797e686730f42e2aa80fdaf5331e83b60f206ed Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Mon, 10 May 2021 04:26:31 +0100 Subject: [PATCH 132/936] OpenBSD/NetBSD build fixes (#4194) --- ext-src/php_swoole.cc | 2 +- src/os/signal.cc | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index bca519a60af..64d2636fae8 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -38,7 +38,7 @@ END_EXTERN_C() #include #include -#if defined(__MACH__) || defined(__FreeBSD__) +#if defined(__MACH__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) #include #endif diff --git a/src/os/signal.cc b/src/os/signal.cc index 5d9ba4a24af..4aa94f8555b 100644 --- a/src/os/signal.cc +++ b/src/os/signal.cc @@ -30,6 +30,10 @@ using swoole::Reactor; #ifdef HAVE_SIGNALFD +static sigset_t signalfd_mask; +static int signal_fd = 0; +static pid_t signalfd_create_pid; +static swoole::network::Socket *signal_socket = nullptr; static swSignalHandler swSignalfd_set(int signo, swSignalHandler handler); static bool swSignalfd_create(); static void swSignalfd_clear(); @@ -39,10 +43,6 @@ static swSignalHandler swKqueueSignal_set(int signo, swSignalHandler handler); #endif static void swSignal_async_handler(int signo); -static sigset_t signalfd_mask; -static int signal_fd = 0; -static pid_t signalfd_create_pid; -static swoole::network::Socket *signal_socket = nullptr; static swSignal signals[SW_SIGNO_MAX]; static int _lock = 0; From b1d183395eb51955d1f19836d0788766d38172a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Thu, 13 May 2021 10:56:07 +0800 Subject: [PATCH 133/936] fix Lost onclose event (#4204) * fix Lost onclose event * fix typo --- include/swoole.h | 1 + include/swoole_socket.h | 10 +++ src/os/signal.cc | 10 +-- src/reactor/base.cc | 11 ++- src/reactor/epoll.cc | 1 - src/server/master.cc | 5 +- src/server/reactor_thread.cc | 6 +- .../client_close_in_writable_event.phpt | 67 +++++++++++++++++++ 8 files changed, 93 insertions(+), 18 deletions(-) create mode 100644 tests/swoole_server/client_close_in_writable_event.phpt diff --git a/include/swoole.h b/include/swoole.h index 5aeadfe9e39..9501908e9fe 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -353,6 +353,7 @@ enum swReturn_code { SW_CLOSE = 3, SW_ERROR = 4, SW_READY = 5, + SW_INVALID = 6, }; enum swFd_type { diff --git a/include/swoole_socket.h b/include/swoole_socket.h index 6aa7c1630ec..71b6f619899 100644 --- a/include/swoole_socket.h +++ b/include/swoole_socket.h @@ -420,6 +420,14 @@ struct Socket { return true; } + bool isset_readable_event() { + return events & SW_EVENT_READ; + } + + bool isset_writable_event() { + return events & SW_EVENT_WRITE; + } + int wait_event(int timeout_ms, int events); void free(); @@ -488,6 +496,8 @@ struct Socket { abort(); return SW_ERROR; case EBADF: + case ENOENT: + return SW_INVALID; case ECONNRESET: case ECONNABORTED: case EPIPE: diff --git a/src/os/signal.cc b/src/os/signal.cc index 4aa94f8555b..1f82a6cf003 100644 --- a/src/os/signal.cc +++ b/src/os/signal.cc @@ -30,10 +30,6 @@ using swoole::Reactor; #ifdef HAVE_SIGNALFD -static sigset_t signalfd_mask; -static int signal_fd = 0; -static pid_t signalfd_create_pid; -static swoole::network::Socket *signal_socket = nullptr; static swSignalHandler swSignalfd_set(int signo, swSignalHandler handler); static bool swSignalfd_create(); static void swSignalfd_clear(); @@ -43,6 +39,12 @@ static swSignalHandler swKqueueSignal_set(int signo, swSignalHandler handler); #endif static void swSignal_async_handler(int signo); +#ifdef HAVE_SIGNALFD +static sigset_t signalfd_mask; +static int signal_fd = 0; +static pid_t signalfd_create_pid; +static swoole::network::Socket *signal_socket = nullptr; +#endif static swSignal signals[SW_SIGNO_MAX]; static int _lock = 0; diff --git a/src/reactor/base.cc b/src/reactor/base.cc index 109ea207a69..4e899670e83 100644 --- a/src/reactor/base.cc +++ b/src/reactor/base.cc @@ -267,8 +267,9 @@ static int write_func( } socket->out_buffer = buffer; } - - reactor->add_write_event(socket); + if (!socket->isset_writable_event()) { + reactor->add_write_event(socket); + } goto _append_buffer; } else if (errno == EINTR) { goto _do_send; @@ -340,9 +341,7 @@ int Reactor::_writable_callback(Reactor *reactor, Event *ev) { while (!Buffer::empty(buffer)) { BufferChunk *chunk = buffer->front(); if (chunk->type == BufferChunk::TYPE_CLOSE) { - _close_fd: - reactor->close(reactor, ev->socket); - return SW_OK; + return reactor->close(reactor, ev->socket); } else if (chunk->type == BufferChunk::TYPE_SENDFILE) { ret = socket->handle_sendfile(); } else { @@ -351,7 +350,7 @@ int Reactor::_writable_callback(Reactor *reactor, Event *ev) { if (ret < 0) { if (socket->close_wait) { - goto _close_fd; + return reactor->trigger_close_event(ev); } else if (socket->send_wait) { return SW_OK; } diff --git a/src/reactor/epoll.cc b/src/reactor/epoll.cc index a49cf6e2fea..fd0d440d983 100644 --- a/src/reactor/epoll.cc +++ b/src/reactor/epoll.cc @@ -60,7 +60,6 @@ class ReactorEpoll : public ReactorImpl { events |= EPOLLONESHOT; } if (Reactor::isset_error_event(fdtype)) { - // flag |= (EPOLLRDHUP); events |= (EPOLLRDHUP | EPOLLHUP | EPOLLERR); } return events; diff --git a/src/server/master.cc b/src/server/master.cc index edfa8c67ce6..ec87ee79782 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -1150,9 +1150,8 @@ int Server::send_to_connection(SendData *_send) { _socket->send_timer = swoole_timer_add(port->max_idle_time * 1000, true, timeout_callback); } - // listen EPOLLOUT event - if (reactor->set(_socket, SW_EVENT_WRITE | SW_EVENT_READ) < 0 && (errno == EBADF || errno == ENOENT)) { - goto _close_fd; + if (!_socket->isset_writable_event()) { + reactor->add_write_event(_socket); } return SW_OK; diff --git a/src/server/reactor_thread.cc b/src/server/reactor_thread.cc index a3b0a618086..0ea0e3ff442 100644 --- a/src/server/reactor_thread.cc +++ b/src/server/reactor_thread.cc @@ -648,9 +648,7 @@ static int ReactorThread_onWrite(Reactor *reactor, Event *ev) { while (!Buffer::empty(socket->out_buffer)) { BufferChunk *chunk = socket->out_buffer->front(); if (chunk->type == BufferChunk::TYPE_CLOSE) { - _close_fd: - reactor->close(reactor, socket); - return SW_OK; + return reactor->close(reactor, socket); } else if (chunk->type == BufferChunk::TYPE_SENDFILE) { ret = socket->handle_sendfile(); } else { @@ -663,7 +661,7 @@ static int ReactorThread_onWrite(Reactor *reactor, Event *ev) { if (ret < 0) { if (socket->close_wait) { conn->close_errno = errno; - goto _close_fd; + return reactor->trigger_close_event(ev); } else if (socket->send_wait) { break; } diff --git a/tests/swoole_server/client_close_in_writable_event.phpt b/tests/swoole_server/client_close_in_writable_event.phpt new file mode 100644 index 00000000000..3d5b1016c93 --- /dev/null +++ b/tests/swoole_server/client_close_in_writable_event.phpt @@ -0,0 +1,67 @@ +--TEST-- +swoole_server: client close in writable event +--SKIPIF-- + +--FILE-- +parentFunc = function ($pid) use ($pm) { + $client = new Client(SWOOLE_SOCK_TCP); + $client->set(['socket_buffer_size' => 128 * 1024]); + if (!$client->connect('127.0.0.1', $pm->getFreePort())) { + exit("connect failed\n"); + } + $client->send("begin"); + $pm->wait(); + usleep(100000); + $client->close(); + $pm->wait(); + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm) { + $serv = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_PROCESS); + $serv->set([ + 'worker_num' => 1, + 'log_file' => '/dev/null', + 'kernel_socket_send_buffer_size' => 128 * 1024, + 'buffer_output_size' => 4 * 1024 * 1024, + ]); + $serv->on(Constant::EVENT_WORKER_START, function ($serv) use ($pm) { + $pm->wakeup(); + }); + $serv->on(Constant::EVENT_CONNECT, function (Server $serv, $fd, $reactor_id) { + echo "CONNECT $fd\n"; + }); + $serv->on('receive', function (Server $serv, $fd, $reactor_id, $data) use ($pm) { + $n = 8; + $serv->pause($fd); + while ($n--) { + $serv->send($fd, str_repeat('A', 2 * 1024 * 1024) . "\r\n"); + } + $pm->wakeup(); + }); + $serv->on(Constant::EVENT_CLOSE, function (Server $serv, $fd, $reactor_id) use ($pm) { + echo "CLOSE $fd\n"; + $pm->wakeup(); + }); + $serv->start(); +}; + +$pm->childFirst(); +$pm->run(); +echo 'DONE'.PHP_EOL; +?> +--EXPECT-- +CONNECT 1 +CLOSE 1 +DONE From b2621460affd29f80696e594008f47d140b4b991 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 13 May 2021 04:57:29 +0200 Subject: [PATCH 134/936] get rid of inet_ntoa and inet_aton calls (#4199) * get rid of inet_ntoa and inet_aton calls * get rid of inet_aton in thirdparty --- ext-src/swoole_client.cc | 15 +++++++++++++-- src/coroutine/socket.cc | 2 +- src/network/address.cc | 4 +++- thirdparty/php/sockets/sockaddr_conv.cc | 2 +- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/ext-src/swoole_client.cc b/ext-src/swoole_client.cc index f84ef78e53d..21e8e7c4ff7 100644 --- a/ext-src/swoole_client.cc +++ b/ext-src/swoole_client.cc @@ -1210,7 +1210,12 @@ static PHP_METHOD(swoole_client, getsockname) { } } else { add_assoc_long(return_value, "port", ntohs(cli->socket->info.addr.inet_v4.sin_port)); - add_assoc_string(return_value, "host", inet_ntoa(cli->socket->info.addr.inet_v4.sin_addr)); + char tmp[INET_ADDRSTRLEN]; + if (inet_ntop(AF_INET, &cli->socket->info.addr.inet_v4.sin_addr, tmp, sizeof(tmp))) { + add_assoc_string(return_value, "host", tmp); + } else { + php_swoole_fatal_error(E_WARNING, "inet_ntop() failed"); + } } } @@ -1248,7 +1253,13 @@ static PHP_METHOD(swoole_client, getpeername) { if (cli->socket->socket_type == SW_SOCK_UDP) { array_init(return_value); add_assoc_long(return_value, "port", ntohs(cli->remote_addr.addr.inet_v4.sin_port)); - add_assoc_string(return_value, "host", inet_ntoa(cli->remote_addr.addr.inet_v4.sin_addr)); + char tmp[INET_ADDRSTRLEN]; + + if (inet_ntop(AF_INET, &cli->remote_addr.addr.inet_v4.sin_addr, tmp, sizeof(tmp))) { + add_assoc_string(return_value, "host", tmp); + } else { + php_swoole_fatal_error(E_WARNING, "inet_ntop() failed"); + } } else if (cli->socket->socket_type == SW_SOCK_UDP6) { array_init(return_value); add_assoc_long(return_value, "port", ntohs(cli->remote_addr.addr.inet_v6.sin6_port)); diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index 8ccf30da998..e41144279c4 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -1366,7 +1366,7 @@ ssize_t Socket::sendto(const std::string &host, int port, const void *__buf, siz for (size_t i = 0; i < 2; i++) { if (type == SW_SOCK_UDP) { - if (::inet_aton(ip.c_str(), &addr.in.sin_addr) == 0) { + if (::inet_pton(AF_INET, ip.c_str(), &addr.in.sin_addr) == 0) { read_co = write_co = Coroutine::get_current_safe(); ip = System::gethostbyname(host, sock_domain, dns_timeout); read_co = write_co = nullptr; diff --git a/src/network/address.cc b/src/network/address.cc index 9a8f4ebb473..9a760183e80 100644 --- a/src/network/address.cc +++ b/src/network/address.cc @@ -23,7 +23,9 @@ static thread_local char tmp_address[INET6_ADDRSTRLEN]; const char *Address::get_addr() { if (type == SW_SOCK_TCP || type == SW_SOCK_UDP) { - return inet_ntoa(addr.inet_v4.sin_addr); + if (inet_ntop(AF_INET, &addr.inet_v4.sin_addr, tmp_address, sizeof(tmp_address))) { + return tmp_address; + } } else if (type == SW_SOCK_TCP6 || type == SW_SOCK_UDP6) { if (inet_ntop(AF_INET6, &addr.inet_v6.sin6_addr, tmp_address, sizeof(tmp_address))) { return tmp_address; diff --git a/thirdparty/php/sockets/sockaddr_conv.cc b/thirdparty/php/sockets/sockaddr_conv.cc index 8102383b5d0..c32fee6bc8a 100644 --- a/thirdparty/php/sockets/sockaddr_conv.cc +++ b/thirdparty/php/sockets/sockaddr_conv.cc @@ -77,7 +77,7 @@ int php_set_inet_addr(struct sockaddr_in *sin, char *string, Socket *php_sock) / struct in_addr tmp; struct hostent *host_entry; - if (inet_aton(string, &tmp)) { + if (inet_pton(AF_INET, string, &tmp)) { sin->sin_addr.s_addr = tmp.s_addr; } else { #if PHP_VERSION_ID >= 70006 From 366b7d5d07341229df3f56e076a196bb30ed5033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Thu, 13 May 2021 22:55:08 +0800 Subject: [PATCH 135/936] Fix #4200 (#4208) * fix curl bug * fix tests --- tests/include/lib/composer.json | 12 +- tests/include/lib/composer.lock | 1446 ++++++++++++++++++++++++++-- tests/swoole_curl/symfony.phpt | 45 + thirdparty/php/curl/curl_private.h | 3 +- thirdparty/php/curl/interface.cc | 28 +- 5 files changed, 1472 insertions(+), 62 deletions(-) create mode 100644 tests/swoole_curl/symfony.phpt diff --git a/tests/include/lib/composer.json b/tests/include/lib/composer.json index 47c8add6c31..4318fbb6d24 100644 --- a/tests/include/lib/composer.json +++ b/tests/include/lib/composer.json @@ -13,6 +13,16 @@ } }, "require": { - "guzzlehttp/guzzle": "^7.3" + "guzzlehttp/guzzle": "^7.3", + "guzzlehttp/promises": "^1.4", + "guzzlehttp/psr7": "^1.7", + "php-http/async-client-implementation": "^1.0", + "php-http/client-common": "^1.5|^2.0", + "php-http/discovery": "^1.6.1", + "php-http/httplug": "^1.1|^2.0", + "php-http/message": "^1.5", + "psr/http-factory": "^1.0", + "symfony/http-client": "*", + "nyholm/psr7": "^1.4" } } diff --git a/tests/include/lib/composer.lock b/tests/include/lib/composer.lock index a9550beb123..8984ae0e67a 100644 --- a/tests/include/lib/composer.lock +++ b/tests/include/lib/composer.lock @@ -4,8 +4,80 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "0a9d23d195d548959fddf890a013c0cb", + "content-hash": "fd2d63ec611fa1880d98b39fab449415", "packages": [ + { + "name": "clue/stream-filter", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/clue/stream-filter.git", + "reference": "aeb7d8ea49c7963d3b581378955dbf5bc49aa320" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/clue/stream-filter/zipball/aeb7d8ea49c7963d3b581378955dbf5bc49aa320", + "reference": "aeb7d8ea49c7963d3b581378955dbf5bc49aa320", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "psr-4": { + "Clue\\StreamFilter\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "description": "A simple and modern approach to stream filtering in PHP", + "homepage": "https://github.com/clue/php-stream-filter", + "keywords": [ + "bucket brigade", + "callback", + "filter", + "php_user_filter", + "stream", + "stream_filter_append", + "stream_filter_register" + ], + "support": { + "issues": "https://github.com/clue/stream-filter/issues", + "source": "https://github.com/clue/stream-filter/tree/v1.5.0" + }, + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2020-10-02T12:38:20+00:00" + }, { "name": "guzzlehttp/guzzle", "version": "7.3.0", @@ -258,17 +330,17 @@ "time": "2021-04-26T09:17:50+00:00" }, { - "name": "psr/http-client", - "version": "1.0.1", + "name": "nyholm/psr7", + "version": "1.4.0", "source": { "type": "git", - "url": "https://github.com/php-fig/http-client.git", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + "url": "https://github.com/Nyholm/psr7.git", + "reference": "23ae1f00fbc6a886cbe3062ca682391b9cc7c37b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", - "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "url": "https://api.github.com/repos/Nyholm/psr7/zipball/23ae1f00fbc6a886cbe3062ca682391b9cc7c37b", + "reference": "23ae1f00fbc6a886cbe3062ca682391b9cc7c37b", "shasum": "", "mirrors": [ { @@ -278,18 +350,30 @@ ] }, "require": { - "php": "^7.0 || ^8.0", + "php": ">=7.1", + "php-http/message-factory": "^1.0", + "psr/http-factory": "^1.0", "psr/http-message": "^1.0" }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "http-interop/http-factory-tests": "^0.8", + "php-http/psr7-integration-tests": "^1.0", + "phpunit/phpunit": "^7.5 || 8.5 || 9.4", + "symfony/error-handler": "^4.4" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.4-dev" } }, "autoload": { "psr-4": { - "Psr\\Http\\Client\\": "src/" + "Nyholm\\Psr7\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -298,35 +382,129 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + }, + { + "name": "Martijn van der Ven", + "email": "martijn@vanderven.se" } ], - "description": "Common interface for HTTP clients", - "homepage": "https://github.com/php-fig/http-client", + "description": "A fast PHP7 implementation of PSR-7", + "homepage": "https://tnyholm.se", + "keywords": [ + "psr-17", + "psr-7" + ], + "support": { + "issues": "https://github.com/Nyholm/psr7/issues", + "source": "https://github.com/Nyholm/psr7/tree/1.4.0" + }, + "funding": [ + { + "url": "https://github.com/Zegnat", + "type": "github" + }, + { + "url": "https://github.com/nyholm", + "type": "github" + } + ], + "time": "2021-02-18T15:41:32+00:00" + }, + { + "name": "php-http/client-common", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/client-common.git", + "reference": "e37e46c610c87519753135fb893111798c69076a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/client-common/zipball/e37e46c610c87519753135fb893111798c69076a", + "reference": "e37e46c610c87519753135fb893111798c69076a", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.1 || ^8.0", + "php-http/httplug": "^2.0", + "php-http/message": "^1.6", + "php-http/message-factory": "^1.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0", + "symfony/options-resolver": "^2.6 || ^3.4.20 || ~4.0.15 || ~4.1.9 || ^4.2.1 || ^5.0", + "symfony/polyfill-php80": "^1.17" + }, + "require-dev": { + "doctrine/instantiator": "^1.1", + "guzzlehttp/psr7": "^1.4", + "nyholm/psr7": "^1.2", + "phpspec/phpspec": "^5.1 || ^6.0", + "phpspec/prophecy": "^1.10.2", + "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.3" + }, + "suggest": { + "ext-json": "To detect JSON responses with the ContentTypePlugin", + "ext-libxml": "To detect XML responses with the ContentTypePlugin", + "php-http/cache-plugin": "PSR-6 Cache plugin", + "php-http/logger-plugin": "PSR-3 Logger plugin", + "php-http/stopwatch-plugin": "Symfony Stopwatch plugin" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Client\\Common\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Common HTTP Client implementations and tools for HTTPlug", + "homepage": "http://httplug.io", "keywords": [ + "client", + "common", "http", - "http-client", - "psr", - "psr-18" + "httplug" ], "support": { - "source": "https://github.com/php-fig/http-client/tree/master" + "issues": "https://github.com/php-http/client-common/issues", + "source": "https://github.com/php-http/client-common/tree/2.3.0" }, - "time": "2020-06-29T06:28:15+00:00" + "time": "2020-07-21T10:04:13+00:00" }, { - "name": "psr/http-message", - "version": "1.0.1", + "name": "php-http/discovery", + "version": "1.13.0", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + "url": "https://github.com/php-http/discovery.git", + "reference": "788f72d64c43dc361e7fcc7464c3d947c64984a7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "url": "https://api.github.com/repos/php-http/discovery/zipball/788f72d64c43dc361e7fcc7464c3d947c64984a7", + "reference": "788f72d64c43dc361e7fcc7464c3d947c64984a7", "shasum": "", "mirrors": [ { @@ -336,17 +514,31 @@ ] }, "require": { - "php": ">=5.3.0" + "php": "^7.1 || ^8.0" + }, + "conflict": { + "nyholm/psr7": "<1.0" + }, + "require-dev": { + "graham-campbell/phpspec-skip-example-extension": "^5.0", + "php-http/httplug": "^1.0 || ^2.0", + "php-http/message-factory": "^1.0", + "phpspec/phpspec": "^5.1 || ^6.1", + "puli/composer-plugin": "1.0.0-beta10" + }, + "suggest": { + "php-http/message": "Allow to use Guzzle, Diactoros or Slim Framework factories", + "puli/composer-plugin": "Sets up Puli which is recommended for Discovery to work. Check http://docs.php-http.org/en/latest/discovery.html for more details." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.9-dev" } }, "autoload": { "psr-4": { - "Psr\\Http\\Message\\": "src/" + "Http\\Discovery\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -355,37 +547,39 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" } ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", + "description": "Finds installed HTTPlug implementations and PSR-7 message factories", + "homepage": "http://php-http.org", "keywords": [ + "adapter", + "client", + "discovery", + "factory", "http", - "http-message", - "psr", - "psr-7", - "request", - "response" + "message", + "psr7" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/master" + "issues": "https://github.com/php-http/discovery/issues", + "source": "https://github.com/php-http/discovery/tree/1.13.0" }, - "time": "2016-08-06T14:39:51+00:00" + "time": "2020-11-27T14:49:42+00:00" }, { - "name": "ralouphie/getallheaders", - "version": "3.0.3", + "name": "php-http/httplug", + "version": "2.2.0", "source": { "type": "git", - "url": "https://github.com/ralouphie/getallheaders.git", - "reference": "120b605dfeb996808c31b6477290a714d356e822" + "url": "https://github.com/php-http/httplug.git", + "reference": "191a0a1b41ed026b717421931f8d3bd2514ffbf9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", - "reference": "120b605dfeb996808c31b6477290a714d356e822", + "url": "https://api.github.com/repos/php-http/httplug/zipball/191a0a1b41ed026b717421931f8d3bd2514ffbf9", + "reference": "191a0a1b41ed026b717421931f8d3bd2514ffbf9", "shasum": "", "mirrors": [ { @@ -395,16 +589,108 @@ ] }, "require": { - "php": ">=5.6" + "php": "^7.1 || ^8.0", + "php-http/promise": "^1.1", + "psr/http-client": "^1.0", + "psr/http-message": "^1.0" }, "require-dev": { - "php-coveralls/php-coveralls": "^2.1", - "phpunit/phpunit": "^5 || ^6.5" + "friends-of-phpspec/phpspec-code-coverage": "^4.1", + "phpspec/phpspec": "^5.1 || ^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eric GELOEN", + "email": "geloen.eric@gmail.com" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "HTTPlug, the HTTP client abstraction for PHP", + "homepage": "http://httplug.io", + "keywords": [ + "client", + "http" + ], + "support": { + "issues": "https://github.com/php-http/httplug/issues", + "source": "https://github.com/php-http/httplug/tree/master" + }, + "time": "2020-07-13T15:43:23+00:00" + }, + { + "name": "php-http/message", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/message.git", + "reference": "fb0dbce7355cad4f4f6a225f537c34d013571f29" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/message/zipball/fb0dbce7355cad4f4f6a225f537c34d013571f29", + "reference": "fb0dbce7355cad4f4f6a225f537c34d013571f29", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "clue/stream-filter": "^1.5", + "php": "^7.1 || ^8.0", + "php-http/message-factory": "^1.0.2", + "psr/http-message": "^1.0" + }, + "provide": { + "php-http/message-factory-implementation": "1.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.6", + "ext-zlib": "*", + "guzzlehttp/psr7": "^1.0", + "laminas/laminas-diactoros": "^2.0", + "phpspec/phpspec": "^5.1 || ^6.3", + "slim/slim": "^3.0" + }, + "suggest": { + "ext-zlib": "Used with compressor/decompressor streams", + "guzzlehttp/psr7": "Used with Guzzle PSR-7 Factories", + "laminas/laminas-diactoros": "Used with Diactoros Factories", + "slim/slim": "Used with Slim Framework PSR-7 implementation" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, "autoload": { + "psr-4": { + "Http\\Message\\": "src/" + }, "files": [ - "src/getallheaders.php" + "src/filters.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -413,16 +699,1066 @@ ], "authors": [ { - "name": "Ralph Khattar", - "email": "ralph.khattar@gmail.com" + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" } ], - "description": "A polyfill for getallheaders.", + "description": "HTTP Message related tools", + "homepage": "http://php-http.org", + "keywords": [ + "http", + "message", + "psr-7" + ], "support": { - "issues": "https://github.com/ralouphie/getallheaders/issues", - "source": "https://github.com/ralouphie/getallheaders/tree/develop" + "issues": "https://github.com/php-http/message/issues", + "source": "https://github.com/php-http/message/tree/1.11.0" }, - "time": "2019-03-08T08:55:37+00:00" + "time": "2021-02-01T08:54:58+00:00" + }, + { + "name": "php-http/message-factory", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-http/message-factory.git", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/message-factory/zipball/a478cb11f66a6ac48d8954216cfed9aa06a501a1", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.4", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Factory interfaces for PSR-7 HTTP Message", + "homepage": "http://php-http.org", + "keywords": [ + "factory", + "http", + "message", + "stream", + "uri" + ], + "support": { + "issues": "https://github.com/php-http/message-factory/issues", + "source": "https://github.com/php-http/message-factory/tree/master" + }, + "time": "2015-12-19T14:08:53+00:00" + }, + { + "name": "php-http/promise", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/promise.git", + "reference": "4c4c1f9b7289a2ec57cde7f1e9762a5789506f88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/promise/zipball/4c4c1f9b7289a2ec57cde7f1e9762a5789506f88", + "reference": "4c4c1f9b7289a2ec57cde7f1e9762a5789506f88", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "friends-of-phpspec/phpspec-code-coverage": "^4.3.2", + "phpspec/phpspec": "^5.1.2 || ^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Joel Wurtz", + "email": "joel.wurtz@gmail.com" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Promise used for asynchronous HTTP requests", + "homepage": "http://httplug.io", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/php-http/promise/issues", + "source": "https://github.com/php-http/promise/tree/1.1.0" + }, + "time": "2020-07-07T09:29:14+00:00" + }, + { + "name": "psr/container", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.1" + }, + "time": "2021-03-05T17:36:06+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/master" + }, + "time": "2020-06-29T06:28:15+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-factory/tree/master" + }, + "time": "2019-04-30T12:38:16+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "psr/log", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, + "time": "2021-05-03T11:20:27+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627", + "reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-03-23T23:28:01+00:00" + }, + { + "name": "symfony/http-client", + "version": "v5.2.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client.git", + "reference": "a2baf9c3c5b25e04740cece0e429f0a0013002f2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client/zipball/a2baf9c3c5b25e04740cece0e429f0a0013002f2", + "reference": "a2baf9c3c5b25e04740cece0e429f0a0013002f2", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.2.5", + "psr/log": "^1.0", + "symfony/http-client-contracts": "^2.2", + "symfony/polyfill-php73": "^1.11", + "symfony/polyfill-php80": "^1.15", + "symfony/service-contracts": "^1.0|^2" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "1.0", + "symfony/http-client-implementation": "2.2" + }, + "require-dev": { + "amphp/amp": "^2.5", + "amphp/http-client": "^4.2.1", + "amphp/http-tunnel": "^1.0", + "amphp/socket": "^1.1", + "guzzlehttp/promises": "^1.4", + "nyholm/psr7": "^1.0", + "php-http/httplug": "^1.0|^2.0", + "psr/http-client": "^1.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/http-kernel": "^4.4.13|^5.1.5", + "symfony/process": "^4.4|^5.0", + "symfony/stopwatch": "^4.4|^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-client/tree/v5.2.8" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-05-10T14:39:23+00:00" + }, + { + "name": "symfony/http-client-contracts", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "7e82f6084d7cae521a75ef2cb5c9457bbda785f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/7e82f6084d7cae521a75ef2cb5c9457bbda785f4", + "reference": "7e82f6084d7cae521a75ef2cb5c9457bbda785f4", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.2.5" + }, + "suggest": { + "symfony/http-client-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v2.4.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-04-11T23:07:08+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v5.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce", + "reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-php73": "~1.0", + "symfony/polyfill-php80": "^1.15" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v5.2.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-27T12:56:27+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.22.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", + "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.22.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.22.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dc3063ba22c2a1fd2f45ed856374d79114998f91", + "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.22.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb", + "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v2.4.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2021-04-01T10:43:52+00:00" } ], "packages-dev": [], diff --git a/tests/swoole_curl/symfony.phpt b/tests/swoole_curl/symfony.phpt new file mode 100644 index 00000000000..9f69132267a --- /dev/null +++ b/tests/swoole_curl/symfony.phpt @@ -0,0 +1,45 @@ +--TEST-- +swoole_curl: symfony http client +--SKIPIF-- + +--FILE-- + 5]) + ); + $uid = uniqid(); + $req = Psr17FactoryDiscovery::findRequestFactory() + ->createRequest('POST', 'http://www.httpbin.org/post') + ->withHeader('Content-Type', 'application/json') + ->withBody(Psr17FactoryDiscovery::findStreamFactory()->createStream(json_encode(['key' => $uid]))); + + $res = (new PluginClient($httpClient))->sendAsyncRequest($req)->wait(); + + $json = $res->getBody()->getContents(); + Assert::notEmpty($json); + $data_1 = json_decode($json); + $data_2 = json_decode($data_1->data); + Assert::eq($data_2->key, $uid); + echo 'Done' . PHP_EOL; +}); + +Runtime::enableCoroutine(SWOOLE_HOOK_NATIVE_CURL); +?> +--EXPECT-- +Done diff --git a/thirdparty/php/curl/curl_private.h b/thirdparty/php/curl/curl_private.h index e7c8abafc3c..dd755edc611 100644 --- a/thirdparty/php/curl/curl_private.h +++ b/thirdparty/php/curl/curl_private.h @@ -111,8 +111,9 @@ typedef struct { zval postfields; /* CurlShareHandle object set using CURLOPT_SHARE. */ #if PHP_VERSION_ID >= 80000 - struct _php_curlsh *share; + struct _php_curlsh *share; #endif + const char *private_data; #if PHP_VERSION_ID >= 80000 zend_object std; #endif diff --git a/thirdparty/php/curl/interface.cc b/thirdparty/php/curl/interface.cc index 8a42277dfaa..caaa1293602 100644 --- a/thirdparty/php/curl/interface.cc +++ b/thirdparty/php/curl/interface.cc @@ -134,6 +134,24 @@ php_curl *_php_curl_get_handle(zval *zid, bool exclusive, bool required) { return ch; } +static long php_curl_easy_setopt_str(php_curl *ch, CURLoption option, const char *str) { + if (option == CURLOPT_PRIVATE) { + ch->private_data = str; + return CURLE_OK; + } else { + return curl_easy_setopt(ch->cp, option, str); + } +} + +static long php_curl_easy_getinfo_str(php_curl *ch, CURLINFO option, char **value) { + if (option == CURLINFO_PRIVATE) { + *value = (char *) ch->private_data; + return CURLE_OK; + } else { + return curl_easy_getinfo(ch->cp, option, value); + } +} + static int php_curl_option_str(php_curl *ch, zend_long option, const char *str, const size_t len, zend_bool make_copy) { long error = CURLE_OK; @@ -153,11 +171,11 @@ static int php_curl_option_str(php_curl *ch, zend_long option, const char *str, /* Strings passed to libcurl as 'char *' arguments, are copied by the library since 7.17.0 */ copystr = estrndup(str, len); - error = curl_easy_setopt(ch->cp, (CURLoption) option, copystr); + php_curl_easy_setopt_str(ch, (CURLoption) option, copystr); zend_llist_add_element(&ch->to_free->str, ©str); #if LIBCURL_VERSION_NUM >= 0x071100 } else { - error = curl_easy_setopt(ch->cp, (CURLoption) option, str); + error = php_curl_easy_setopt_str(ch, (CURLoption) option, str); } #endif @@ -2186,7 +2204,7 @@ PHP_FUNCTION(swoole_native_curl_setopt) { Z_PARAM_ZVAL(zvalue) ZEND_PARSE_PARAMETERS_END(); - if ((ch = _php_curl_get_handle(zid)) == NULL) { + if ((ch = _php_curl_get_handle(zid, false)) == NULL) { RETURN_FALSE; } @@ -2219,7 +2237,7 @@ PHP_FUNCTION(swoole_native_curl_setopt_array) { Z_PARAM_ARRAY(arr) ZEND_PARSE_PARAMETERS_END(); - if ((ch = _php_curl_get_handle(zid)) == NULL) { + if ((ch = _php_curl_get_handle(zid, false)) == NULL) { RETURN_FALSE; } @@ -2536,7 +2554,7 @@ PHP_FUNCTION(swoole_native_curl_getinfo) { case CURLINFO_STRING: { char *s_code = NULL; - if (curl_easy_getinfo(ch->cp, (CURLINFO) option, &s_code) == CURLE_OK && s_code) { + if (php_curl_easy_getinfo_str(ch, (CURLINFO) option, &s_code) == CURLE_OK && s_code) { RETURN_STRING(s_code); } else { RETURN_FALSE; From 6d8b5733b822be077fa924b27704ba73d1b2aa77 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Thu, 13 May 2021 23:06:19 +0800 Subject: [PATCH 136/936] Remove test for php 8.1 because it has not been released yet --- .github/workflows/test-linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml index 2c4785c25e7..35b68aa2af7 100644 --- a/.github/workflows/test-linux.yml +++ b/.github/workflows/test-linux.yml @@ -8,7 +8,7 @@ jobs: strategy: fail-fast: false matrix: - php: [7.2, 7.3, 7.4, 8.0, 8.1] + php: [7.2, 7.3, 7.4, 8.0] steps: - uses: actions/checkout@v1 - name: Setup PHP From 7bfb05a66c22e523027969675f85604e4b56a5f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Fri, 14 May 2021 08:22:11 +0800 Subject: [PATCH 137/936] Update .gitattributes --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index 5e42ccdfc11..5d0338a77d8 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,3 +2,4 @@ /benchmark/ export-ignore /core-tests/ export-ignore /.travis.yml export-ignore +*.h linguist-language=C++ From 66fcc3525d6761c4cc17f51c7b90646234e55c5c Mon Sep 17 00:00:00 2001 From: matyhtf Date: Fri, 14 May 2021 08:52:03 +0800 Subject: [PATCH 138/936] fix Http\Response::end() bad return value --- ext-src/swoole_http_server.cc | 3 +- tests/swoole_http_server/error_1203.phpt | 50 ++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 tests/swoole_http_server/error_1203.phpt diff --git a/ext-src/swoole_http_server.cc b/ext-src/swoole_http_server.cc index b036d59934e..34dfa878444 100644 --- a/ext-src/swoole_http_server.cc +++ b/ext-src/swoole_http_server.cc @@ -291,9 +291,8 @@ bool http_context_send_data(http_context *ctx, const char *data, size_t length) ZVAL_STRINGL(&yield_data, data, length); php_swoole_server_send_yield(serv, ctx->fd, &yield_data, &return_value); return Z_BVAL_P(&return_value); - } else { - return true; } + return retval; } static bool http_context_sendfile(http_context *ctx, const char *file, uint32_t l_file, off_t offset, size_t length) { diff --git a/tests/swoole_http_server/error_1203.phpt b/tests/swoole_http_server/error_1203.phpt new file mode 100644 index 00000000000..e8460db4dbc --- /dev/null +++ b/tests/swoole_http_server/error_1203.phpt @@ -0,0 +1,50 @@ +--TEST-- +swoole_http_server: http_compression +--SKIPIF-- + +--FILE-- +parentFunc = function () use ($pm) +{ + go(function () use ($pm) { + try { + $data = httpGetBody("http://127.0.0.1:{$pm->getFreePort()}/"); + } catch(Exception $e) { + Assert::contains($e->getMessage(), 'Connection reset by peer'); + } + $pm->kill(); + }); + Swoole\Event::wait(); + echo "DONE\n"; +}; + +$pm->childFunc = function () use ($pm) +{ + $http = new swoole_http_server('127.0.0.1', $pm->getFreePort()); + + $http->set([ + 'http_compression' => false, + 'log_file' => '/dev/null', + 'buffer_output_size' => 128 * 1024, + ]); + + $http->on("WorkerStart", function ($serv, $wid) use ($pm) { + $pm->wakeup(); + }); + + $http->on("request", function ($request, swoole_http_response $response) { + Assert::eq($response->end(str_repeat('A', 256 * 1024)), false); + Assert::eq(swoole_last_error(), SWOOLE_ERROR_DATA_LENGTH_TOO_LARGE); + }); + + $http->start(); +}; + +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +DONE From e93a455834930532fd494c5e99852e78ea832ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Fri, 14 May 2021 13:15:08 +0800 Subject: [PATCH 139/936] Update .gitattributes --- .gitattributes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index 5d0338a77d8..590f276f506 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,4 +2,4 @@ /benchmark/ export-ignore /core-tests/ export-ignore /.travis.yml export-ignore -*.h linguist-language=C++ +*.h linguist-language=cpp From 46ab345c5c05ec922b8aa56821d0dde326d524d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Fri, 14 May 2021 14:09:53 +0800 Subject: [PATCH 140/936] adjust output_buffer_size value (#4209) --- include/swoole_server.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/swoole_server.h b/include/swoole_server.h index 508cace3cd4..9975c08d3a4 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -693,7 +693,7 @@ class Server { TimerNode *heartbeat_timer = nullptr; /* buffer output/input setting*/ - uint32_t output_buffer_size = SW_OUTPUT_BUFFER_SIZE; + uint32_t output_buffer_size = UINT_MAX; uint32_t input_buffer_size = SW_INPUT_BUFFER_SIZE; uint32_t max_queued_bytes = 0; From 39d2f4ee157ade94db5b2cc9a54c09580e7660b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Fri, 14 May 2021 18:17:49 +0800 Subject: [PATCH 141/936] Fix typo and Add update package.xml (#4211) --- tools/next-version.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tools/next-version.php b/tools/next-version.php index 2dbd6a8a672..7e13f76e548 100755 --- a/tools/next-version.php +++ b/tools/next-version.php @@ -15,11 +15,11 @@ class Version function getVersion() { - $versoin = implode('.', [$this->major, $this->minor, $this->release]); + $version = implode('.', [$this->major, $this->minor, $this->release]); if ($this->extra) { - $versoin .= '-' . $this->extra; + $version .= '-' . $this->extra; } - return $versoin; + return $version; } function getVersionId() @@ -31,6 +31,7 @@ function getVersionId() $type = empty($argv[1]) ? 'release' : trim($argv[1]); $kernel_version_file = dirname(__DIR__) . '/include/swoole_version.h'; $cmake_file = dirname(__DIR__) . '/CMakeLists.txt'; +$package_file = dirname(__DIR__) . '/package.xml'; $versionInfo = file_get_contents($kernel_version_file); @@ -68,6 +69,15 @@ function getVersionId() exit("wrong version type"); } +if (empty($next->extra)) { + $doc = new DOMDocument(); + $doc->load($package_file); + $versions = $doc->getElementsByTagName("version"); + $versions[0]->getElementsByTagName('release')->item(0)->nodeValue = $next->getVersion(); + $versions[0]->getElementsByTagName('api')->item(0)->nodeValue = $next->major . '.0'; + $doc->save($package_file); +} + ob_start(); include __DIR__ . '/templates/version.tpl.h'; file_put_contents($kernel_version_file, ob_get_clean()); From 1ec32029fd148a83b5f92104f8dbd1ac9dff2fa3 Mon Sep 17 00:00:00 2001 From: codinghuang Date: Fri, 14 May 2021 18:21:04 +0800 Subject: [PATCH 142/936] Update version for Swoole 4.6.7 (#4210) --- CMakeLists.txt | 2 +- ext-src/php_swoole.cc | 2 ++ include/swoole_version.h | 4 ++-- package.xml | 32 ++++++++++++++++++++++++-------- src/core/error.cc | 4 ++++ 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 33843e06ab4..ce963eac751 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ PROJECT(libswoole) ENABLE_LANGUAGE(ASM) -set(SWOOLE_VERSION 4.6.7-dev) +set(SWOOLE_VERSION 4.6.7) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g") diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index 64d2636fae8..b35691ab43b 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -641,6 +641,8 @@ PHP_MINIT_FUNCTION(swoole) { SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_SERVER_INVALID_REQUEST", SW_ERROR_SERVER_INVALID_REQUEST); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_SERVER_CONNECT_FAIL", SW_ERROR_SERVER_CONNECT_FAIL); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_SERVER_WORKER_EXIT_TIMEOUT", SW_ERROR_SERVER_WORKER_EXIT_TIMEOUT); + SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_SERVER_WORKER_ABNORMAL_PIPE_DATA", SW_ERROR_SERVER_WORKER_ABNORMAL_PIPE_DATA); + SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_SERVER_WORKER_UNPROCESSED_DATA", SW_ERROR_SERVER_WORKER_UNPROCESSED_DATA); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_CO_OUT_OF_COROUTINE", SW_ERROR_CO_OUT_OF_COROUTINE); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_CO_HAS_BEEN_BOUND", SW_ERROR_CO_HAS_BEEN_BOUND); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_CO_HAS_BEEN_DISCARDED", SW_ERROR_CO_HAS_BEEN_DISCARDED); diff --git a/include/swoole_version.h b/include/swoole_version.h index 664fa71b24f..5b7263a29cf 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -21,8 +21,8 @@ #define SWOOLE_MAJOR_VERSION 4 #define SWOOLE_MINOR_VERSION 6 #define SWOOLE_RELEASE_VERSION 7 -#define SWOOLE_EXTRA_VERSION "dev" -#define SWOOLE_VERSION "4.6.7-dev" +#define SWOOLE_EXTRA_VERSION "" +#define SWOOLE_VERSION "4.6.7" #define SWOOLE_VERSION_ID 40607 #define SWOOLE_API_VERSION_ID 0x202012a diff --git a/package.xml b/package.xml index e0eeee5e15a..0d8c54e080a 100644 --- a/package.xml +++ b/package.xml @@ -48,10 +48,10 @@ lufei@php.net yes - 2021-04-22 - + 2021-05-14 + - 4.6.6 + 4.6.7 4.0 @@ -62,14 +62,23 @@ Enhancement --- - * Sent SIGTERM to the manager process on FreeBSD when master process is dead (#4150) (@devnexen) - * Supported static compilation with PHP (#4153) (@matyhtf) - * Supported SNI for File Wrapper over HTTP proxy (#4158) (@matyhtf) + * Supported call Process::signal() in Manager process and Worker process (#4190) (@matyhtf) Fixed --- - * Fixed sync-client async connect bugs (#4152) (@matyhtf) - * Fixed native curl multi mem leak (swoole/swoole-src@91bf243) (@matyhtf) + * Fixed signal cannot be registered repeatedly (#4170) (@matyhtf) + * Fixed build on OpenBSD/NetBSD (#4188) (#4194) (@devnexen) + * Fixed Lost onclose event (#4204) (@matyhtf) + * Fixed native curl with Symfony HttpClient (#4208) (@matyhtf) + * Fixed Http\Response::end() always return true (swoole/swoole-src@66fcc35) (@matyhtf) + * Fixed PDOException generated by PDOStatementProxy (swoole/library#104) (@twose) + + Kernel + --- + * Refactored worker buffer, add msg id for the event data (#4163) (@matyhtf) + * Changed the log level of "Request Entity Too Large" to warning (#4175) (@sy-records) + * Deleted inet_ntoa and inet_aton calls (#4199) (@remicollet) + * Adjusted output_buffer_size value to UINT_MAX (swoole/swoole-src@46ab345) (@matyhtf) @@ -137,6 +146,7 @@ + @@ -1101,6 +1111,7 @@ + @@ -1285,6 +1296,7 @@ + @@ -1445,6 +1457,9 @@ + + + @@ -1634,6 +1649,7 @@ + diff --git a/src/core/error.cc b/src/core/error.cc index 905ac8c23ad..7b1ee77bbad 100644 --- a/src/core/error.cc +++ b/src/core/error.cc @@ -183,6 +183,10 @@ const char *swoole_strerror(int code) { return "Server connect fail"; case SW_ERROR_SERVER_WORKER_EXIT_TIMEOUT: return "Server worker exit timeout"; + case SW_ERROR_SERVER_WORKER_ABNORMAL_PIPE_DATA: + return "Server worker abnormal pipe data"; + case SW_ERROR_SERVER_WORKER_UNPROCESSED_DATA: + return "Server worker unprocessed data"; case SW_ERROR_CO_OUT_OF_COROUTINE: return "Coroutine out of coroutine"; case SW_ERROR_CO_HAS_BEEN_BOUND: From 8ce5041aad6a0530ebccf2d6f90e710829ea142a Mon Sep 17 00:00:00 2001 From: matyhtf Date: Sat, 15 May 2021 10:52:12 +0800 Subject: [PATCH 143/936] Optimize error log of failed thread creation, fix #4202 --- include/swoole_coroutine.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/swoole_coroutine.h b/include/swoole_coroutine.h index 19d50eb65a7..67c8fc026a1 100644 --- a/include/swoole_coroutine.h +++ b/include/swoole_coroutine.h @@ -102,7 +102,17 @@ class Coroutine { static void bailout(BailoutCallback func); static inline long create(const coroutine_func_t &fn, void *args = nullptr) { +#ifdef SW_USE_THREAD_CONTEXT + try { + return (new Coroutine(fn, args))->run(); + } catch (const std::system_error& e) { + swoole_set_last_error(e.code().value()); + swWarn("failed to create coroutine, Error: %s[%d]", e.what(), swoole_get_last_error()); + return -1; + } +#else return (new Coroutine(fn, args))->run(); +#endif } static void activate(); From 49dcd2970c5818596245fbc58ef0b538d77e6a8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Tue, 18 May 2021 14:21:12 +0800 Subject: [PATCH 144/936] Update next version for 4.7.0-dev (#4220) * Update next version for 4.6.8-dev * Update next version for 4.7.0-dev --- .github/ISSUE-CN.md | 2 +- .github/ISSUE.md | 2 +- CMakeLists.txt | 2 +- include/swoole_version.h | 10 +++++----- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/ISSUE-CN.md b/.github/ISSUE-CN.md index 90aef4945fb..c08b7485d95 100644 --- a/.github/ISSUE-CN.md +++ b/.github/ISSUE-CN.md @@ -47,7 +47,7 @@ Please answer these questions before submitting your issue. Thanks! 更多时候, Valgrind比gdb更能发现内存问题, 通过以下指令运行你的程序, 直到触发BUG ```shell -USE_ZEND_ALLOC=0 valgrind --log-file=/tmp/valgrind.log php xxx.php +USE_ZEND_ALLOC=0 valgrind --log-file=/tmp/valgrind.log php your_file.php ``` * 当程序发生错误时, 可以通过键入 `ctrl+c` 退出, 然后上传 `/tmp/valgrind.log` 文件以便于开发组定位BUG. diff --git a/.github/ISSUE.md b/.github/ISSUE.md index 8ea842da8e0..3cbe4908678 100644 --- a/.github/ISSUE.md +++ b/.github/ISSUE.md @@ -32,7 +32,7 @@ The most important thing is to provide a simple script for reproducing the error In addition to using `gdb` analysis, you can use the `valgrind` tool to check if the program is working properly. ```shell -USE_ZEND_ALLOC=0 valgrind --log-file=/tmp/valgrind.log php xxx.php +USE_ZEND_ALLOC=0 valgrind --log-file=/tmp/valgrind.log php your_file.php ``` * After the program is executed to the wrong location, `ctrl+c` is interrupted, and upload the `/tmp/valgrind.log` file. diff --git a/CMakeLists.txt b/CMakeLists.txt index ce963eac751..5d3ddb3fc96 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ PROJECT(libswoole) ENABLE_LANGUAGE(ASM) -set(SWOOLE_VERSION 4.6.7) +set(SWOOLE_VERSION 4.7.0-dev) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g") diff --git a/include/swoole_version.h b/include/swoole_version.h index 5b7263a29cf..6bc7c5bb2c9 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -19,11 +19,11 @@ #define SWOOLE_VERSION_H_ #define SWOOLE_MAJOR_VERSION 4 -#define SWOOLE_MINOR_VERSION 6 -#define SWOOLE_RELEASE_VERSION 7 -#define SWOOLE_EXTRA_VERSION "" -#define SWOOLE_VERSION "4.6.7" -#define SWOOLE_VERSION_ID 40607 +#define SWOOLE_MINOR_VERSION 7 +#define SWOOLE_RELEASE_VERSION 0 +#define SWOOLE_EXTRA_VERSION "dev" +#define SWOOLE_VERSION "4.7.0-dev" +#define SWOOLE_VERSION_ID 40700 #define SWOOLE_API_VERSION_ID 0x202012a #define SWOOLE_BUG_REPORT \ From 234b2f376222f42b46e04fcec764c95fc0957950 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Tue, 18 May 2021 15:57:56 +0800 Subject: [PATCH 145/936] Add Cygwin build (#4222) --- .github/workflows/cygwin.yml | 76 ++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 .github/workflows/cygwin.yml diff --git a/.github/workflows/cygwin.yml b/.github/workflows/cygwin.yml new file mode 100644 index 00000000000..167b899417f --- /dev/null +++ b/.github/workflows/cygwin.yml @@ -0,0 +1,76 @@ +name: cygwin + +on: + push: + tags: + - 'v*' + +jobs: + build: + if: github.repository_owner == 'swoole' + runs-on: windows-latest + outputs: + version: ${{ steps.swoole_info.outputs.version }} + body: ${{ steps.swoole_info.outputs.upload_url }} + steps: + - name: Set up Cygwin + uses: egor-tensin/setup-cygwin@v3 + with: + platform: x64 + packages: cmake php php-devel gcc-g++ openssl libssl-devel libcurl-devel libpcre2-devel wget tar php-curl php-json php-sockets php-mysqli php-bcmath php-bz2 php-calendar php-ctype php-phar php-posix php-pspell php-exif php-recode php-fileinfo php-simplexml php-gd php-soap php-gettext php-sockets php-gmp php-gv php-iconv php-intl php-json php-tokenizer php-mbstring php-ming php-xmlreader php-xmlwriter php-opcache php-xsl php-zip php-pdo_mysql php-zlib php-redis + + - name: Get Swoole Info + id: swoole_info + run: | + wget https://api.github.com/repos/swoole/swoole-src/releases/latest -O latest + $g=cat .\latest | ConvertFrom-Json + $version=$g.tag_name + $upload_url=$g.upload_url + echo $version + echo $upload_url + echo "::set-output name=version::$version" + echo "::set-output name=upload_url::$upload_url" + + - name: Build Swoole + run: | + wget https://github.com/swoole/swoole-src/archive/${{ steps.swoole_info.outputs.version }}.tar.gz -O swoole.tar.gz + mkdir -p swoole + tar -xf swoole.tar.gz -C swoole --strip-components=1 + rm swoole.tar.gz + cd swoole + /bin/phpize + ./configure --enable-openssl --with-openssl_dir=/usr --enable-http2 --enable-mysqlnd + make -j6 + cp modules/swoole.dll /usr/lib/php/20180731 + echo 'extension=swoole.dll' > /etc/php.d/swoole.ini + php -v + php -m + php --ri swoole + php --ini + cd .. + shell: C:\tools\cygwin\bin\bash.exe --login --norc -eo pipefail -o igncr '{0}' + + - name: Run build + env: + VERSION: ${{ steps.swoole_info.outputs.version }} + run: | + C:\tools\php\php.exe -v + C:\tools\php\php.exe -m + wget https://github.com/lufei/cygwin/archive/refs/heads/master.tar.gz -O cygwin.tar.gz + mkdir -p swoole-cygwin + tar -xf cygwin.tar.gz -C swoole-cygwin --strip-components=1 + rm cygwin.tar.gz + cd swoole-cygwin + C:\tools\php\php.exe build.php + cd .. + + - name: Upload Release Asset + id: upload-release-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.swoole_info.outputs.upload_url }} + asset_path: .\swoole-cygwin\swoole-cygwin-${{ steps.swoole_info.outputs.version }}.zip + asset_name: swoole-cygwin-${{ steps.swoole_info.outputs.version }}.zip + asset_content_type: application/zip From e628afcdbe930b6e924957adfaa259b23fb82bd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Tue, 18 May 2021 18:05:04 +0800 Subject: [PATCH 146/936] add Process\Pool::detach() (#4221) * add Process\Pool::detach() * add tests --- examples/process_pool/detach.php | 30 ++++++++++++ examples/process_pool/send.php | 5 ++ ext-src/swoole_process_pool.cc | 13 +++++ include/swoole_process_pool.h | 12 +++++ src/os/process_pool.cc | 48 +++++++++++++++++-- src/reactor/base.cc | 4 +- tests/swoole_process_pool/detach.phpt | 68 +++++++++++++++++++++++++++ 7 files changed, 175 insertions(+), 5 deletions(-) create mode 100644 examples/process_pool/detach.php create mode 100644 examples/process_pool/send.php create mode 100644 tests/swoole_process_pool/detach.phpt diff --git a/examples/process_pool/detach.php b/examples/process_pool/detach.php new file mode 100644 index 00000000000..7a613698fa2 --- /dev/null +++ b/examples/process_pool/detach.php @@ -0,0 +1,30 @@ +on('WorkerStart', function (Process\Pool $pool, $workerId) { + echo("[Worker #{$workerId}] WorkerStart\n"); + if ($workerId == 1) { + + } +}); + +$pool->on('WorkerStop', function (\Swoole\Process\Pool $pool, $workerId) { + echo("[Worker #{$workerId}] WorkerStop\n"); +}); + +$pool->on('Message', function ($pool, $msg) { + var_dump($msg); + $pool->detach(); + + while(1) { + sleep(1); + echo "pid=".posix_getpid()."\n"; + }; +}); + +$pool->listen('127.0.0.1', 8089); + +$pool->start(); diff --git a/examples/process_pool/send.php b/examples/process_pool/send.php new file mode 100644 index 00000000000..b9ae046e911 --- /dev/null +++ b/examples/process_pool/send.php @@ -0,0 +1,5 @@ + 'hello', 'uid' => 1991]); +fwrite($fp, pack('N', strlen($msg)) . $msg); +sleep(1); diff --git a/ext-src/swoole_process_pool.cc b/ext-src/swoole_process_pool.cc index c2132f6a5d9..da440a60160 100644 --- a/ext-src/swoole_process_pool.cc +++ b/ext-src/swoole_process_pool.cc @@ -125,6 +125,7 @@ static PHP_METHOD(swoole_process_pool, set); static PHP_METHOD(swoole_process_pool, on); static PHP_METHOD(swoole_process_pool, listen); static PHP_METHOD(swoole_process_pool, write); +static PHP_METHOD(swoole_process_pool, detach); static PHP_METHOD(swoole_process_pool, getProcess); static PHP_METHOD(swoole_process_pool, start); static PHP_METHOD(swoole_process_pool, shutdown); @@ -174,6 +175,7 @@ static const zend_function_entry swoole_process_pool_methods[] = PHP_ME(swoole_process_pool, getProcess, arginfo_swoole_process_pool_getProcess, ZEND_ACC_PUBLIC) PHP_ME(swoole_process_pool, listen, arginfo_swoole_process_pool_listen, ZEND_ACC_PUBLIC) PHP_ME(swoole_process_pool, write, arginfo_swoole_process_pool_write, ZEND_ACC_PUBLIC) + PHP_ME(swoole_process_pool, detach, arginfo_swoole_process_pool_void, ZEND_ACC_PUBLIC) PHP_ME(swoole_process_pool, start, arginfo_swoole_process_pool_void, ZEND_ACC_PUBLIC) PHP_ME(swoole_process_pool, shutdown, arginfo_swoole_process_pool_void, ZEND_ACC_PUBLIC) PHP_FE_END @@ -266,6 +268,9 @@ static void pool_signal_handler(int sig) { current_pool->reloading = true; current_pool->reload_init = false; break; + case SIGIO: + current_pool->read_message = true; + break; default: break; } @@ -497,6 +502,7 @@ static PHP_METHOD(swoole_process_pool, start) { ori_handlers[SIGTERM] = swSignal_set(SIGTERM, pool_signal_handler); ori_handlers[SIGUSR1] = swSignal_set(SIGUSR1, pool_signal_handler); ori_handlers[SIGUSR2] = swSignal_set(SIGUSR2, pool_signal_handler); + ori_handlers[SIGIO] = swSignal_set(SIGIO, pool_signal_handler); if (pool->ipc_mode == SW_IPC_NONE || pp->enable_coroutine) { if (pp->onWorkerStart == nullptr) { @@ -542,6 +548,13 @@ static PHP_METHOD(swoole_process_pool, start) { extern void php_swoole_process_set_worker(zval *zobject, Worker *worker); +static PHP_METHOD(swoole_process_pool, detach) { + if (current_pool == nullptr) { + RETURN_FALSE; + } + RETURN_BOOL(current_pool->detach()); +} + static PHP_METHOD(swoole_process_pool, getProcess) { long worker_id = -1; diff --git a/include/swoole_process_pool.h b/include/swoole_process_pool.h index 0d869ce1d0d..0fd2c1c6972 100644 --- a/include/swoole_process_pool.h +++ b/include/swoole_process_pool.h @@ -24,6 +24,7 @@ #include "swoole_lock.h" #include "swoole_pipe.h" +#include "swoole_channel.h" #include "swoole_msg_queue.h" enum swWorker_status { @@ -173,6 +174,7 @@ struct ProcessPool { bool reloading; bool running; bool reload_init; + bool read_message; bool started; uint8_t dispatch_mode; uint8_t ipc_mode; @@ -234,6 +236,7 @@ struct ProcessPool { Reactor *reactor; MsgQueue *queue; StreamInfo *stream_info_; + Channel *message_box = nullptr; void *ptr; @@ -257,9 +260,18 @@ struct ProcessPool { return &(workers[worker_id - start_id]); } + Worker *get_worker_by_pid(pid_t pid) { + auto iter = map_->find(pid); + if (iter == map_->end()) { + return nullptr; + } + return iter->second; + } + void set_max_request(uint32_t _max_request, uint32_t _max_request_grace); int get_max_request(); int set_protocol(int task_protocol, uint32_t max_packet_size); + bool detach(); int wait(); int start(); void shutdown(); diff --git a/src/os/process_pool.cc b/src/os/process_pool.cc index 56d05158e98..8634ab4c073 100644 --- a/src/os/process_pool.cc +++ b/src/os/process_pool.cc @@ -76,6 +76,11 @@ int ProcessPool::create(uint32_t _worker_num, key_t _msgqueue_key, swIPC_type _i return SW_ERR; } + message_box = Channel::make(65536, sizeof(WorkerStopMessage), SW_CHAN_LOCK | SW_CHAN_SHM); + if (message_box == nullptr) { + return SW_ERR; + } + if (_ipc_mode == SW_IPC_MSGQUEUE) { use_msgqueue = 1; msgqueue_key = _msgqueue_key; @@ -605,6 +610,21 @@ int ProcessPool_add_worker(ProcessPool *pool, Worker *worker) { return SW_OK; } +bool ProcessPool::detach() { + WorkerStopMessage msg; + msg.pid = getpid(); + msg.worker_id = SwooleG.process_id; + + if (message_box && message_box->push(&msg, sizeof(msg)) < 0) { + return false; + } + if (swoole_kill(master_pid, SIGIO) < 0) { + return false; + } + running = false; + return true; +} + int ProcessPool::wait() { pid_t new_pid, reload_worker_pid = 0; int ret; @@ -622,6 +642,25 @@ int ProcessPool::wait() { SwooleG.signal_alarm = false; SwooleTG.timer->select(); } + if (read_message) { + WorkerStopMessage msg; + while (message_box->pop(&msg, sizeof(msg)) > 0) { + if (!running) { + continue; + } + Worker *exit_worker = get_worker_by_pid(msg.pid); + if (exit_worker == nullptr) { + continue; + } + pid_t new_pid = spawn(exit_worker); + if (new_pid < 0) { + swSysWarn("Fork worker process failed"); + return SW_ERR; + } + map_->erase(msg.pid); + } + read_message = false; + } if (exit_status.get_pid() < 0) { if (!running) { break; @@ -645,8 +684,8 @@ int ProcessPool::wait() { } if (running) { - auto iter = map_->find(exit_status.get_pid()); - if (iter == map_->end()) { + Worker *exit_worker = get_worker_by_pid(exit_status.get_pid()); + if (exit_worker == nullptr) { if (onWorkerNotFound) { onWorkerNotFound(this, exit_status); } else { @@ -655,7 +694,6 @@ int ProcessPool::wait() { continue; } - Worker *exit_worker = iter->second; if (!exit_status.is_normal_exit()) { swWarn("worker#%d abnormal exit, status=%d, signal=%d" "%s", @@ -732,6 +770,10 @@ void ProcessPool::destroy() { delete map_; } + if (message_box) { + message_box->destroy(); + } + sw_mem_pool()->free(workers); } diff --git a/src/reactor/base.cc b/src/reactor/base.cc index 4e899670e83..03bb5719716 100644 --- a/src/reactor/base.cc +++ b/src/reactor/base.cc @@ -301,7 +301,7 @@ int Reactor::_write(Reactor *reactor, Socket *socket, const void *buf, size_t n) send_bytes = socket->send(buf, n, 0); return send_bytes; }; - auto append_fn = [&send_bytes, socket, buf, n](Buffer *buffer) { + auto append_fn = [&send_bytes, buf, n](Buffer *buffer) { ssize_t offset = send_bytes > 0 ? send_bytes : 0; buffer->append((const char *) buf + offset, n - offset); }; @@ -325,7 +325,7 @@ int Reactor::_writev(Reactor *reactor, network::Socket *socket, const iovec *iov send_bytes = socket->writev(iov, iovcnt); return send_bytes; }; - auto append_fn = [&send_bytes, socket, iov, iovcnt](Buffer *buffer) { + auto append_fn = [&send_bytes, iov, iovcnt](Buffer *buffer) { ssize_t offset = send_bytes > 0 ? send_bytes : 0; buffer->append(iov, iovcnt, offset); }; diff --git a/tests/swoole_process_pool/detach.phpt b/tests/swoole_process_pool/detach.phpt new file mode 100644 index 00000000000..a7b92ef52ba --- /dev/null +++ b/tests/swoole_process_pool/detach.phpt @@ -0,0 +1,68 @@ +--TEST-- +swoole_process_pool: detach +--SKIPIF-- + +--FILE-- +initFreePorts(); + +$pm->parentFunc = function ($pid) use ($pm, $atomic) { + foreach (range(1, 2) as $i) { + $fp = stream_socket_client("tcp://127.0.0.1:".$pm->getFreePort(), $errno, $errstr) or die("error: $errstr\n"); + $msg = "HELLO-{$i}"; + fwrite($fp, pack('N', strlen($msg)) . $msg); + } + $pm->wait(); + Assert::eq($atomic->get(), N + 1); + echo "DONE\n"; + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm, $atomic) { + $pool = new Pool(1, SWOOLE_IPC_SOCKET); + + $pool->on('WorkerStart', function (Pool $pool, $workerId) use($pm, $atomic) { + echo("[Worker #{$workerId}] WorkerStart\n"); + if ($atomic->get() == 0) { + $pm->wakeup(); + } + }); + + $pool->on('Message', function (Pool $pool, $msg) use($pm, $atomic) { + if ($atomic->get() == 0) { + $atomic->add(); + $pool->detach(); + $n = N; + while($n--) { + usleep(1000); + $atomic->add(); + } + $pm->wakeup(); + } else { + echo $msg.PHP_EOL; + } + }); + + $pool->listen('127.0.0.1', $pm->getFreePort()); + $pool->start(); +}; + +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +[Worker #0] WorkerStart +[Worker #0] WorkerStart +HELLO-2 +DONE From af1722e43ab36eae0a137a6f2dbd2fb85fcb10d7 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Fri, 21 May 2021 12:12:59 +0800 Subject: [PATCH 147/936] defense --- ext-src/swoole_server.cc | 2 +- src/os/process_pool.cc | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 1745d96c177..b8a3346768f 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -3452,7 +3452,7 @@ static PHP_METHOD(swoole_server, sendMessage) { php_swoole_fatal_error(E_WARNING, "can't send messages to self"); RETURN_FALSE; } - if (worker_id >= serv->worker_num + serv->task_worker_num) { + if (worker_id < 0 && worker_id >= serv->worker_num + serv->task_worker_num) { php_swoole_fatal_error(E_WARNING, "worker_id[%d] is invalid", (int) worker_id); RETURN_FALSE; } diff --git a/src/os/process_pool.cc b/src/os/process_pool.cc index 8634ab4c073..f7f17bc08e5 100644 --- a/src/os/process_pool.cc +++ b/src/os/process_pool.cc @@ -611,6 +611,10 @@ int ProcessPool_add_worker(ProcessPool *pool, Worker *worker) { } bool ProcessPool::detach() { + if (!running) { + return false; + } + WorkerStopMessage msg; msg.pid = getpid(); msg.worker_id = SwooleG.process_id; @@ -622,6 +626,7 @@ bool ProcessPool::detach() { return false; } running = false; + return true; } From 7ca38fffa4d3923183d19d77d2c9e889cad1b48b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Fri, 21 May 2021 14:34:45 +0800 Subject: [PATCH 148/936] Add onDisconnect callback (#4230) * add onDisconnect * fix tests * fix tests[2] --- ext-src/php_swoole_server.h | 18 ++--- ext-src/swoole_http_server.cc | 13 ---- ext-src/swoole_server.cc | 34 +++++++--- ext-src/swoole_server_port.cc | 58 +++++++--------- tests/include/functions.php | 4 ++ tests/swoole_server_port/http.phpt | 18 ++--- .../swoole_websocket_server/onDisconnct.phpt | 66 +++++++++++++++++++ 7 files changed, 133 insertions(+), 78 deletions(-) create mode 100644 tests/swoole_websocket_server/onDisconnct.phpt diff --git a/ext-src/php_swoole_server.h b/ext-src/php_swoole_server.h index c54c3d769c8..088a6b2ed04 100644 --- a/ext-src/php_swoole_server.h +++ b/ext-src/php_swoole_server.h @@ -43,14 +43,15 @@ enum php_swoole_server_callback_type { }; //-------------------------------------------------------- enum php_swoole_server_port_callback_type { - SW_SERVER_CB_onConnect, // worker(event) - SW_SERVER_CB_onReceive, // worker(event) - SW_SERVER_CB_onClose, // worker(event) - SW_SERVER_CB_onPacket, // worker(event) - SW_SERVER_CB_onRequest, // http server - SW_SERVER_CB_onHandShake, // worker(event) - SW_SERVER_CB_onOpen, // worker(event) - SW_SERVER_CB_onMessage, // worker(event) + SW_SERVER_CB_onConnect, // stream, worker(event) + SW_SERVER_CB_onReceive, // stream, worker(event) + SW_SERVER_CB_onClose, // stream, worker(event) + SW_SERVER_CB_onPacket, // dgram, worker(event) + SW_SERVER_CB_onRequest, // http, worker(event) + SW_SERVER_CB_onHandShake, // websocket, worker(event) + SW_SERVER_CB_onOpen, // websocket, worker(event) + SW_SERVER_CB_onMessage, // websocket, worker(event) + SW_SERVER_CB_onDisconnect, // websocket (non websocket connection), worker(event) SW_SERVER_CB_onBufferFull, // worker(event) SW_SERVER_CB_onBufferEmpty, // worker(event) }; @@ -137,7 +138,6 @@ void php_swoole_server_onConnect(swServer *, swDataHead *); int php_swoole_server_onReceive(swServer *, swRecvData *); int php_swoole_http_server_onReceive(swServer *, swRecvData *); int php_swoole_redis_server_onReceive(swServer *serv, swRecvData *req); -void php_swoole_http_server_onClose(swServer *, swDataHead *); int php_swoole_server_onPacket(swServer *, swRecvData *); void php_swoole_server_onClose(swServer *, swDataHead *); void php_swoole_server_onBufferFull(swServer *, swDataHead *); diff --git a/ext-src/swoole_http_server.cc b/ext-src/swoole_http_server.cc index 34dfa878444..36d1e32fb3a 100644 --- a/ext-src/swoole_http_server.cc +++ b/ext-src/swoole_http_server.cc @@ -141,19 +141,6 @@ int php_swoole_http_server_onReceive(Server *serv, RecvData *req) { return SW_OK; } -void php_swoole_http_server_onClose(Server *serv, DataHead *ev) { - Connection *conn = serv->get_connection_by_session_id(ev->fd); - if (!conn) { - return; - } - php_swoole_server_onClose(serv, ev); -#ifdef SW_USE_HTTP2 - if (conn->http2_stream) { - swoole_http2_server_session_free(conn); - } -#endif -} - void php_swoole_http_server_minit(int module_number) { SW_INIT_CLASS_ENTRY_EX( swoole_http_server, "Swoole\\Http\\Server", "swoole_http_server", nullptr, nullptr, swoole_server); diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index b8a3346768f..04de5a896bd 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -15,6 +15,7 @@ */ #include "php_swoole_server.h" +#include "php_swoole_http_server.h" #include "php_swoole_process.h" #include "swoole_msg_queue.h" @@ -1156,9 +1157,6 @@ void ServerObject::on_before_start() { if (find_http_port) { serv->onReceive = php_swoole_http_server_onReceive; - if (serv->is_support_unsafe_events()) { - serv->onClose = php_swoole_http_server_onClose; - } php_swoole_http_server_init_global_variant(); } } @@ -1843,25 +1841,37 @@ void php_swoole_server_onConnect(Server *serv, DataHead *info) { void php_swoole_server_onClose(Server *serv, DataHead *info) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); + SessionId session_id = info->fd; if (serv->enable_coroutine && serv->send_yield) { - auto _i_coros_list = server_object->property->send_coroutine_map.find(info->fd); + auto _i_coros_list = server_object->property->send_coroutine_map.find(session_id); if (_i_coros_list != server_object->property->send_coroutine_map.end()) { auto coros_list = _i_coros_list->second; - server_object->property->send_coroutine_map.erase(info->fd); + server_object->property->send_coroutine_map.erase(session_id); while (!coros_list->empty()) { FutureTask *context = coros_list->front(); coros_list->pop_front(); swoole_set_last_error(ECONNRESET); zval_ptr_dtor(&context->coro_params); ZVAL_NULL(&context->coro_params); - php_swoole_server_send_resume(serv, context, info->fd); + php_swoole_server_send_resume(serv, context, session_id); } delete coros_list; } } - auto fci_cache = php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onClose); + auto *fci_cache = php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onClose); + Connection *conn = serv->get_connection_by_session_id(session_id); + if (!conn) { + return; + } + if (conn->websocket_status != WEBSOCKET_STATUS_ACTIVE) { + ListenPort *port = serv->get_port_by_server_fd(info->server_fd); + if (port && port->open_websocket_protocol + && php_swoole_server_isset_callback(serv, port, SW_SERVER_CB_onDisconnect)) { + fci_cache = php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onDisconnect); + } + } if (fci_cache) { zval *zserv = (zval *) serv->private_data_2; zval args[3]; @@ -1872,14 +1882,14 @@ void php_swoole_server_onClose(Server *serv, DataHead *info) { zval *object = &args[1]; object_init_ex(object, swoole_server_event_ce); zend_update_property_long( - swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("fd"), (zend_long) info->fd); + swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("fd"), (zend_long) session_id); zend_update_property_long( swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("reactor_id"), (zend_long) info->reactor_id); zend_update_property_double( swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("dispatch_time"), info->time); argc = 2; } else { - ZVAL_LONG(&args[1], info->fd); + ZVAL_LONG(&args[1], session_id); ZVAL_LONG(&args[2], info->reactor_id); argc = 3; } @@ -1892,6 +1902,12 @@ void php_swoole_server_onClose(Server *serv, DataHead *info) { zval_ptr_dtor(&args[1]); } } + +#ifdef SW_USE_HTTP2 + if (conn->http2_stream) { + swoole_http2_server_session_free(conn); + } +#endif } void php_swoole_server_onBufferFull(Server *serv, DataHead *info) { diff --git a/ext-src/swoole_server_port.cc b/ext-src/swoole_server_port.cc index 05f351be74c..25848fab0e7 100644 --- a/ext-src/swoole_server_port.cc +++ b/ext-src/swoole_server_port.cc @@ -36,6 +36,7 @@ static std::unordered_map server_port_event_map( { "handshake", server_port_event(SW_SERVER_CB_onHandShake, "Handshake") }, { "open", server_port_event(SW_SERVER_CB_onOpen, "Open") }, { "message", server_port_event(SW_SERVER_CB_onMessage, "Message") }, + { "disconnect", server_port_event(SW_SERVER_CB_onDisconnect, "Disconnect") }, }); // clang-format on @@ -184,6 +185,7 @@ void php_swoole_server_port_minit(int module_number) { zend_declare_property_null(swoole_server_port_ce, ZEND_STRL("onHandShake"), ZEND_ACC_PRIVATE); zend_declare_property_null(swoole_server_port_ce, ZEND_STRL("onOpen"), ZEND_ACC_PRIVATE); zend_declare_property_null(swoole_server_port_ce, ZEND_STRL("onMessage"), ZEND_ACC_PRIVATE); + zend_declare_property_null(swoole_server_port_ce, ZEND_STRL("onDisconnect"), ZEND_ACC_PRIVATE); zend_declare_property_null(swoole_server_port_ce, ZEND_STRL("host"), ZEND_ACC_PUBLIC); zend_declare_property_long(swoole_server_port_ce, ZEND_STRL("port"), 0, ZEND_ACC_PUBLIC); @@ -618,7 +620,7 @@ static PHP_METHOD(swoole_server_port, set) { static PHP_METHOD(swoole_server_port, on) { char *name = nullptr; - size_t len, i; + size_t len; zval *cb; ServerPortProperty *property = php_swoole_server_port_get_and_check_property(ZEND_THIS); @@ -640,55 +642,39 @@ static PHP_METHOD(swoole_server_port, on) { } efree(func_name); - const char *callback_name[PHP_SWOOLE_SERVER_PORT_CALLBACK_NUM] = { - "Connect", - "Receive", - "Close", - "Packet", - "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_SWOOLE_SERVER_PORT_CALLBACK_NUM; i++) { - if (!swoole_strcaseeq(name, len, callback_name[i], strlen(callback_name[i]))) { + bool found = false; + for (auto i = server_port_event_map.begin(); i!= server_port_event_map.end(); i++) { + if (!swoole_strcaseeq(name, len, i->first.c_str(), i->first.length())) { continue; } - 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_ce, SW_Z8_OBJ_P(ZEND_THIS), property_name, l_property_name, cb); - property->callbacks[i] = - sw_zend_read_property(swoole_server_port_ce, ZEND_THIS, property_name, l_property_name, 0); - sw_copy_to_stack(property->callbacks[i], property->_callbacks[i]); - if (property->caches[i]) { - efree(property->caches[i]); + found = true; + int index = i->second.type; + std::string property_name = std::string("on") + i->second.name; + zend_update_property(swoole_server_port_ce, SW_Z8_OBJ_P(ZEND_THIS), property_name.c_str(), property_name.length(), cb); + property->callbacks[index] = + sw_zend_read_property(swoole_server_port_ce, ZEND_THIS, property_name.c_str(), property_name.length(), 0); + sw_copy_to_stack(property->callbacks[index], property->_callbacks[index]); + if (property->caches[index]) { + efree(property->caches[index]); } - property->caches[i] = fci_cache; + property->caches[index] = fci_cache; - if (i == SW_SERVER_CB_onConnect && !serv->onConnect) { + if (index == SW_SERVER_CB_onConnect && !serv->onConnect) { serv->onConnect = php_swoole_server_onConnect; - } else if (i == SW_SERVER_CB_onPacket && !serv->onPacket) { + } else if (index == SW_SERVER_CB_onPacket && !serv->onPacket) { serv->onPacket = php_swoole_server_onPacket; - } else if (i == SW_SERVER_CB_onClose && !serv->onClose) { + } else if (index == SW_SERVER_CB_onClose && !serv->onClose) { serv->onClose = php_swoole_server_onClose; - } else if (i == SW_SERVER_CB_onBufferFull && !serv->onBufferFull) { + } else if (index == SW_SERVER_CB_onBufferFull && !serv->onBufferFull) { serv->onBufferFull = php_swoole_server_onBufferFull; - } else if (i == SW_SERVER_CB_onBufferEmpty && !serv->onBufferEmpty) { + } else if (index == SW_SERVER_CB_onBufferEmpty && !serv->onBufferEmpty) { serv->onBufferEmpty = php_swoole_server_onBufferEmpty; } break; } - if (l_property_name == 0) { + if (!found) { php_swoole_error(E_WARNING, "unknown event types[%s]", name); efree(fci_cache); RETURN_FALSE; diff --git a/tests/include/functions.php b/tests/include/functions.php index 6d9d66597e7..d41e8b78d89 100644 --- a/tests/include/functions.php +++ b/tests/include/functions.php @@ -19,6 +19,10 @@ function clear_php() `ps -A | grep php | grep -v phpstorm | grep -v 'run-tests' | awk '{print $1}' | xargs kill -9 > /dev/null 2>&1`; } +function puts($msg) { + echo $msg."\n"; +} + function top(int $pid) { static $available; diff --git a/tests/swoole_server_port/http.phpt b/tests/swoole_server_port/http.phpt index cfb87408b23..4e824a527cc 100644 --- a/tests/swoole_server_port/http.phpt +++ b/tests/swoole_server_port/http.phpt @@ -20,7 +20,7 @@ $pm->parentFunc = function ($pid) use ($pm) if (!$cli->connect('127.0.0.1', $pm->getFreePort(0), 0.5)) { fail: - echo "ERROR\n"; + echo "ERROR 1\n"; return; } //no eof, should be timeout here @@ -36,14 +36,13 @@ $pm->parentFunc = function ($pid) use ($pm) echo "OK\n"; }); - go(function () use ($pm) - { + go(function () use ($pm) { $cli = new Swoole\Coroutine\Http\Client('127.0.0.1', $pm->getFreePort(1)); - if ( $cli->get("/") ) { + if ($cli->get("/")) { echo $cli->body; Assert::same($cli->statusCode, 200); } else { - echo "ERROR\n"; + echo "ERROR 2\n"; } }); @@ -68,21 +67,18 @@ $pm->childFunc = function () use ($pm) $port2 = $server->listen('127.0.0.1', $pm->getFreePort(1), SWOOLE_SOCK_TCP); $port2->set(['open_http_protocol' => true,]); - $port2->on("request", function ($req, $resp) - { + $port2->on("request", function ($req, $resp) { $resp->end("hello swooler\n"); }); - $server->on("WorkerStart", function (\swoole_server $serv) - { + $server->on("WorkerStart", function (\swoole_server $serv) { /** * @var $pm ProcessManager */ global $pm; $pm->wakeup(); }); - $server->on('request', function (swoole_http_request $request, swoole_http_response $response) - { + $server->on('request', function (swoole_http_request $request, swoole_http_response $response) { $response->end("OK\n"); }); $server->start(); diff --git a/tests/swoole_websocket_server/onDisconnct.phpt b/tests/swoole_websocket_server/onDisconnct.phpt new file mode 100644 index 00000000000..69a20a1d26a --- /dev/null +++ b/tests/swoole_websocket_server/onDisconnct.phpt @@ -0,0 +1,66 @@ +--TEST-- +swoole_websocket_server: onDisconnect +--SKIPIF-- + +--FILE-- +parentFunc = function (int $pid) use ($pm) { + run(function () use ($pm) { + $data = httpGetBody('http://127.0.0.1:' . $pm->getFreePort() . '/'); + Assert::contains($data, 'HTTP 400 Bad Request'); + + $client = new Client('127.0.0.1', $pm->getFreePort()); + Assert::assert($client->upgrade('/websocket')); + Assert::eq($client->getStatusCode(), 101); + $client->push('hello world'); + $client->close(); + }); + puts('done!'); + $pm->kill(); +}; +$pm->childFunc = function () use ($pm) { + $serv = new swoole_websocket_server('127.0.0.1', $pm->getFreePort(), SERVER_MODE_RANDOM); + $serv->set([ + 'worker_num' => 1, + 'log_file' => '/dev/null' + ]); + $serv->on('WorkerStart', function () use ($pm) { + $pm->wakeup(); + }); + $serv->on('Message', function (swoole_websocket_server $serv, swoole_websocket_frame $frame) { + if ($frame->data == 'shutdown') { + $serv->disconnect($frame->fd, 4000, 'shutdown received'); + } + }); + $serv->on('connect', function ($s, $id) use ($pm) { + puts("connect ".$id); + }); + $serv->on('disconnect', function ($s, $id) use ($pm) { + puts("disconnect ".$id); + }); + $serv->on('open', function ($s, $req) use ($pm) { + puts("open ".$req->fd); + }); + $serv->on('close', function ($s, $id) use ($pm) { + puts("close ".$id); + }); + $serv->start(); +}; +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +connect 1 +disconnect 1 +connect 2 +open 2 +close 2 +done! + From 75013968ef7a7fd055e1cfb8dfde1127775d3c65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Sat, 22 May 2021 12:25:58 +0800 Subject: [PATCH 149/936] add codecov.yml, fix error (#4232) --- codecov.yml | 2 ++ ext-src/swoole_server.cc | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000000..58405861c1d --- /dev/null +++ b/codecov.yml @@ -0,0 +1,2 @@ +ignore: + - "src/core/error.cc" \ No newline at end of file diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 04de5a896bd..8b35987806e 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -3468,7 +3468,7 @@ static PHP_METHOD(swoole_server, sendMessage) { php_swoole_fatal_error(E_WARNING, "can't send messages to self"); RETURN_FALSE; } - if (worker_id < 0 && worker_id >= serv->worker_num + serv->task_worker_num) { + if (worker_id < 0 || worker_id >= serv->worker_num + serv->task_worker_num) { php_swoole_fatal_error(E_WARNING, "worker_id[%d] is invalid", (int) worker_id); RETURN_FALSE; } From e9a0a76b397a78347437931fe5f85df678e9a10e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Tue, 25 May 2021 14:12:58 +0800 Subject: [PATCH 150/936] Fix missing php_swoole.h (#4239) --- config.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.m4 b/config.m4 index b5f18aa098e..6904f53a075 100644 --- a/config.m4 +++ b/config.m4 @@ -746,7 +746,7 @@ if test "$PHP_SWOOLE" != "no"; then AC_MSG_RESULT([disabled]) fi - PHP_INSTALL_HEADERS([ext/swoole], [ext-src/*.h config.h include/*.h thirdparty/*.h thirdparty/hiredis/*.h]) + PHP_INSTALL_HEADERS([ext/swoole], [ext-src/*.h config.h php_swoole.h include/*.h thirdparty/*.h thirdparty/hiredis/*.h]) PHP_REQUIRE_CXX() From 8a4d2d62f0785d56f0ce44fcdf82baf5d5af3aa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Tue, 25 May 2021 16:31:19 +0800 Subject: [PATCH 151/936] Fix typo (#4234) * Fix typo * Fix unknown --- ext-src/swoole_coroutine_system.cc | 2 +- ext-src/swoole_event.cc | 10 +++++----- ext-src/swoole_server.cc | 8 ++++---- ext-src/swoole_server_port.cc | 6 +++--- src/coroutine/socket.cc | 2 +- src/os/process_pool.cc | 2 +- src/reactor/base.cc | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ext-src/swoole_coroutine_system.cc b/ext-src/swoole_coroutine_system.cc index aa2195a12ea..ae77fea3c32 100644 --- a/ext-src/swoole_coroutine_system.cc +++ b/ext-src/swoole_coroutine_system.cc @@ -671,7 +671,7 @@ PHP_METHOD(swoole_coroutine_system, waitEvent) { int fd = php_swoole_convert_to_fd(zfd); if (fd < 0) { - php_swoole_fatal_error(E_WARNING, "unknow fd type"); + php_swoole_fatal_error(E_WARNING, "unknown fd type"); RETURN_FALSE; } diff --git a/ext-src/swoole_event.cc b/ext-src/swoole_event.cc index 54d165e7240..1c0d9dea8c3 100644 --- a/ext-src/swoole_event.cc +++ b/ext-src/swoole_event.cc @@ -455,7 +455,7 @@ static PHP_FUNCTION(swoole_event_add) { int socket_fd = php_swoole_convert_to_fd(zfd); if (socket_fd < 0) { - php_swoole_fatal_error(E_WARNING, "unknow fd type"); + php_swoole_fatal_error(E_WARNING, "unknown fd type"); RETURN_FALSE; } if (socket_fd == 0 && (events & SW_EVENT_WRITE)) { @@ -523,7 +523,7 @@ static PHP_FUNCTION(swoole_event_write) { int socket_fd = php_swoole_convert_to_fd(zfd); if (socket_fd < 0) { - php_swoole_fatal_error(E_WARNING, "unknow type"); + php_swoole_fatal_error(E_WARNING, "unknown type"); RETURN_FALSE; } @@ -564,7 +564,7 @@ static PHP_FUNCTION(swoole_event_set) { int socket_fd = php_swoole_convert_to_fd(zfd); if (socket_fd < 0) { - php_swoole_fatal_error(E_WARNING, "unknow type"); + php_swoole_fatal_error(E_WARNING, "unknown type"); RETURN_FALSE; } @@ -622,7 +622,7 @@ static PHP_FUNCTION(swoole_event_del) { int socket_fd = php_swoole_convert_to_fd(zfd); if (socket_fd < 0) { - php_swoole_fatal_error(E_WARNING, "unknow type"); + php_swoole_fatal_error(E_WARNING, "unknown type"); RETURN_FALSE; } @@ -767,7 +767,7 @@ static PHP_FUNCTION(swoole_event_isset) { int socket_fd = php_swoole_convert_to_fd(zfd); if (socket_fd < 0) { - php_swoole_fatal_error(E_WARNING, "unknow type"); + php_swoole_fatal_error(E_WARNING, "unknown type"); RETURN_FALSE; } diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 8b35987806e..8986b0887a8 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -144,7 +144,7 @@ static sw_inline Server *server_get_ptr(zval *zobject) { Server *php_swoole_server_get_and_check_server(zval *zobject) { Server *serv = server_get_ptr(zobject); if (UNEXPECTED(!serv)) { - php_swoole_fatal_error(E_ERROR, "Invaild instance of %s", SW_Z_OBJCE_NAME_VAL_P(zobject)); + php_swoole_fatal_error(E_ERROR, "Invalid instance of %s", SW_Z_OBJCE_NAME_VAL_P(zobject)); } return serv; } @@ -221,7 +221,7 @@ static sw_inline ConnectionIterator *php_swoole_connection_iterator_get_ptr(zval ConnectionIterator *php_swoole_connection_iterator_get_and_check_ptr(zval *zobject) { ConnectionIterator *iterator = php_swoole_connection_iterator_get_ptr(zobject); if (UNEXPECTED(!iterator->serv)) { - php_swoole_fatal_error(E_ERROR, "Invaild instance of %s", SW_Z_OBJCE_NAME_VAL_P(zobject)); + php_swoole_fatal_error(E_ERROR, "Invalid instance of %s", SW_Z_OBJCE_NAME_VAL_P(zobject)); } return iterator; } @@ -252,7 +252,7 @@ static sw_inline ServerTaskObject *php_swoole_server_task_fetch_object(zend_obje static sw_inline Server *php_swoole_server_task_get_server(zval *zobject) { Server *serv = php_swoole_server_task_fetch_object(Z_OBJ_P(zobject))->serv; if (!serv) { - php_swoole_fatal_error(E_ERROR, "Invaild instance of %s", SW_Z_OBJCE_NAME_VAL_P(zobject)); + php_swoole_fatal_error(E_ERROR, "Invalid instance of %s", SW_Z_OBJCE_NAME_VAL_P(zobject)); } return serv; } @@ -264,7 +264,7 @@ static sw_inline void php_swoole_server_task_set_server(zval *zobject, Server *s static sw_inline DataHead *php_swoole_server_task_get_info(zval *zobject) { ServerTaskObject *task = php_swoole_server_task_fetch_object(Z_OBJ_P(zobject)); if (!task->serv) { - php_swoole_fatal_error(E_ERROR, "Invaild instance of %s", SW_Z_OBJCE_NAME_VAL_P(zobject)); + php_swoole_fatal_error(E_ERROR, "Invalid instance of %s", SW_Z_OBJCE_NAME_VAL_P(zobject)); } return &task->info; } diff --git a/ext-src/swoole_server_port.cc b/ext-src/swoole_server_port.cc index 25848fab0e7..7c981739a6f 100644 --- a/ext-src/swoole_server_port.cc +++ b/ext-src/swoole_server_port.cc @@ -60,7 +60,7 @@ static sw_inline ListenPort *php_swoole_server_port_get_ptr(zval *zobject) { ListenPort *php_swoole_server_port_get_and_check_ptr(zval *zobject) { ListenPort *port = php_swoole_server_port_get_ptr(zobject); if (UNEXPECTED(!port)) { - php_swoole_fatal_error(E_ERROR, "Invaild instance of %s", SW_Z_OBJCE_NAME_VAL_P(zobject)); + php_swoole_fatal_error(E_ERROR, "Invalid instance of %s", SW_Z_OBJCE_NAME_VAL_P(zobject)); } return port; } @@ -76,7 +76,7 @@ ServerPortProperty *php_swoole_server_port_get_property(zval *zobject) { static ServerPortProperty *php_swoole_server_port_get_and_check_property(zval *zobject) { ServerPortProperty *property = php_swoole_server_port_get_property(zobject); if (UNEXPECTED(!property->serv)) { - php_swoole_fatal_error(E_ERROR, "Invaild instance of %s", SW_Z_OBJCE_NAME_VAL_P(zobject)); + php_swoole_fatal_error(E_ERROR, "Invalid instance of %s", SW_Z_OBJCE_NAME_VAL_P(zobject)); } return property; } @@ -433,7 +433,7 @@ static PHP_METHOD(swoole_server_port, set) { port->protocol.package_length_type = str_v.val()[0]; port->protocol.package_length_size = swoole_type_size(port->protocol.package_length_type); if (port->protocol.package_length_size == 0) { - php_swoole_fatal_error(E_ERROR, "unknow package_length_type, see pack(). Link: http://php.net/pack"); + php_swoole_fatal_error(E_ERROR, "unknown package_length_type, see pack(). Link: http://php.net/pack"); RETURN_FALSE; } } diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index e41144279c4..c0a127773f1 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -702,7 +702,7 @@ bool Socket::connect(std::string _host, int _port, int flags) { _target_addr = (struct sockaddr *) &socket->info.addr.un; break; } else { - set_err(EINVAL, "unknow protocol[%d]"); + set_err(EINVAL, "unknown protocol[%d]"); return false; } } diff --git a/src/os/process_pool.cc b/src/os/process_pool.cc index f7f17bc08e5..3986d203ae7 100644 --- a/src/os/process_pool.cc +++ b/src/os/process_pool.cc @@ -694,7 +694,7 @@ int ProcessPool::wait() { if (onWorkerNotFound) { onWorkerNotFound(this, exit_status); } else { - swWarn("[Manager]unknow worker[pid=%d]", exit_status.get_pid()); + swWarn("[Manager]unknown worker[pid=%d]", exit_status.get_pid()); } continue; } diff --git a/src/reactor/base.cc b/src/reactor/base.cc index 03bb5719716..353363356dd 100644 --- a/src/reactor/base.cc +++ b/src/reactor/base.cc @@ -174,7 +174,7 @@ bool Reactor::set_handler(int _fdtype, ReactorHandler handler) { } else if (Reactor::isset_error_event(_fdtype)) { error_handler[fdtype] = handler; } else { - swWarn("unknow fdtype"); + swWarn("unknown fdtype"); return false; } From 527e083a2b540f97c928839fba2f892ffdf2b01f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Tue, 25 May 2021 16:32:11 +0800 Subject: [PATCH 152/936] Update constant to add event (#4236) * Update constant to add event * Fix missing unCamelize * Remove duplicate code --- tools/analysis.php | 0 tools/constant-generator.php | 48 ++++++++++++++++++++++++++++-------- tools/rename.php | 0 3 files changed, 38 insertions(+), 10 deletions(-) mode change 100644 => 100755 tools/analysis.php mode change 100644 => 100755 tools/rename.php diff --git a/tools/analysis.php b/tools/analysis.php old mode 100644 new mode 100755 diff --git a/tools/constant-generator.php b/tools/constant-generator.php index 7f1469a86de..05de99ff90c 100755 --- a/tools/constant-generator.php +++ b/tools/constant-generator.php @@ -26,17 +26,45 @@ $result .= space(4) . sprintf("public const OPTION_%s = '%s';\n\n", strtoupper($option), $option); } +$event_file = [ + "{$root_dir}/ext-src/swoole_server.cc", + "{$root_dir}/ext-src/swoole_server_port.cc" +]; + +$server_event_content = ''; +foreach ($event_file as $file) { + $server_event_content .= file_get_contents($file); +} +preg_match_all('/vent\(SW_SERVER_CB_on(.+?),/', $server_event_content, $server_event); +$server_events = array_unique($server_event[1]); + +$event_result = ''; +foreach ($server_events as $event) { + $event_result .= space(4) . sprintf("public const EVENT_%s = '%s';\n\n", strtoupper(unCamelize($event)), lcfirst($event)); +} + $constant_php_content = file_get_contents($constant_php); -$constant_php_content = preg_replace( - '/(\/\* \{\{\{ OPTION \*\/\n)([\s\S]*)(\/\* \}\}\} OPTION \*\/)/', - '${1}' . $result . space(4) . '${3}', - $constant_php_content, - 1, - $replaced -); - -if (!$replaced || !file_put_contents($constant_php, $constant_php_content)) { - swoole_error('Update Constant failed '); + +$event_pattern = '/(\/\* \{\{\{ EVENT \*\/\n)([\s\S]*)(\/\* \}\}\} EVENT \*\/)/'; +$option_pattern = '/(\/\* \{\{\{ OPTION \*\/\n)([\s\S]*)(\/\* \}\}\} OPTION \*\/)/'; + +function replaceConstantContent($pattern, $result, &$content) { + $content = preg_replace( + $pattern, + '${1}' . $result . space(4) . '${3}', + $content, + 1, + $replaced + ); + + return $replaced; +} + +$event_replaced = replaceConstantContent($event_pattern, $event_result, $constant_php_content); +$option_replaced = replaceConstantContent($option_pattern, $result, $constant_php_content); + +if (!$event_replaced || !$option_replaced || !file_put_contents($constant_php, $constant_php_content)) { + swoole_error('Update constant failed'); } swoole_success('Constant generator successfully done!'); diff --git a/tools/rename.php b/tools/rename.php old mode 100644 new mode 100755 From a21f53e5e51e48bbc3464424a7a13d8b61c8f9be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Tue, 25 May 2021 17:52:43 +0800 Subject: [PATCH 153/936] Update pid when worker process exit (#4240) --- ext-src/php_swoole_process.h | 2 ++ ext-src/swoole_process.cc | 4 +-- ext-src/swoole_process_pool.cc | 25 +++++++++++-- include/swoole_process_pool.h | 12 ------- tests/swoole_process_pool/getprocess_3.phpt | 39 +++++++++++++++++++++ 5 files changed, 65 insertions(+), 17 deletions(-) create mode 100644 tests/swoole_process_pool/getprocess_3.phpt diff --git a/ext-src/php_swoole_process.h b/ext-src/php_swoole_process.h index fc00293000a..3704b69c896 100644 --- a/ext-src/php_swoole_process.h +++ b/ext-src/php_swoole_process.h @@ -22,3 +22,5 @@ void php_swoole_process_clean(); int php_swoole_process_start(swoole::Worker *process, zval *zobject); +swoole::Worker *php_swoole_process_get_worker(zval *zobject); +void php_swoole_process_set_worker(zval *zobject, swoole::Worker *worker); diff --git a/ext-src/swoole_process.cc b/ext-src/swoole_process.cc index 636025ce30c..91ee3695173 100644 --- a/ext-src/swoole_process.cc +++ b/ext-src/swoole_process.cc @@ -41,7 +41,7 @@ static sw_inline ProcessObject *php_swoole_process_fetch_object(zend_object *obj return (ProcessObject *) ((char *) obj - swoole_process_handlers.offset); } -static sw_inline Worker *php_swoole_process_get_worker(zval *zobject) { +Worker *php_swoole_process_get_worker(zval *zobject) { return php_swoole_process_fetch_object(Z_OBJ_P(zobject))->worker; } @@ -506,7 +506,7 @@ static PHP_METHOD(swoole_process, kill) { int ret = swoole_kill((int) pid, (int) sig); if (ret < 0) { if (!(sig == 0 && errno == ESRCH)) { - php_swoole_sys_error(E_WARNING, "swKill(%d, %d) failed", (int) pid, (int) sig); + php_swoole_sys_error(E_WARNING, "kill(%d, %d) failed", (int) pid, (int) sig); } RETURN_FALSE; } diff --git a/ext-src/swoole_process_pool.cc b/ext-src/swoole_process_pool.cc index da440a60160..a0718a74d14 100644 --- a/ext-src/swoole_process_pool.cc +++ b/ext-src/swoole_process_pool.cc @@ -40,6 +40,8 @@ struct ProcessPoolObject { zend_object std; }; +static void pool_signal_handler(int sig); + static sw_inline ProcessPoolObject *php_swoole_process_pool_fetch_object(zend_object *obj) { return (ProcessPoolObject *) ((char *) obj - swoole_process_pool_handlers.offset); } @@ -128,6 +130,7 @@ static PHP_METHOD(swoole_process_pool, write); static PHP_METHOD(swoole_process_pool, detach); static PHP_METHOD(swoole_process_pool, getProcess); static PHP_METHOD(swoole_process_pool, start); +static PHP_METHOD(swoole_process_pool, stop); static PHP_METHOD(swoole_process_pool, shutdown); SW_EXTERN_C_END @@ -177,6 +180,7 @@ static const zend_function_entry swoole_process_pool_methods[] = PHP_ME(swoole_process_pool, write, arginfo_swoole_process_pool_write, ZEND_ACC_PUBLIC) PHP_ME(swoole_process_pool, detach, arginfo_swoole_process_pool_void, ZEND_ACC_PUBLIC) PHP_ME(swoole_process_pool, start, arginfo_swoole_process_pool_void, ZEND_ACC_PUBLIC) + PHP_ME(swoole_process_pool, stop, arginfo_swoole_process_pool_void, ZEND_ACC_PUBLIC) PHP_ME(swoole_process_pool, shutdown, arginfo_swoole_process_pool_void, ZEND_ACC_PUBLIC) PHP_FE_END }; @@ -205,7 +209,6 @@ static void pool_onWorkerStart(ProcessPool *pool, int worker_id) { php_swoole_process_clean(); SwooleG.process_id = worker_id; current_pool = pool; - // main function if (!pp->onWorkerStart) { return; @@ -214,6 +217,9 @@ static void pool_onWorkerStart(ProcessPool *pool, int worker_id) { if (pp->enable_coroutine && php_swoole_reactor_init() < 0) { return; } + if (!pp->enable_coroutine && pp->onMessage) { + swSignal_set(SIGTERM, pool_signal_handler); + } zval args[2]; args[0] = *zobject; ZVAL_LONG(&args[1], worker_id); @@ -259,6 +265,9 @@ static void pool_onWorkerStop(ProcessPool *pool, int worker_id) { } static void pool_signal_handler(int sig) { + if (!current_pool) { + return; + } switch (sig) { case SIGTERM: current_pool->running = false; @@ -546,8 +555,6 @@ static PHP_METHOD(swoole_process_pool, start) { } } -extern void php_swoole_process_set_worker(zval *zobject, Worker *worker); - static PHP_METHOD(swoole_process_pool, detach) { if (current_pool == nullptr) { RETURN_FALSE; @@ -608,11 +615,23 @@ static PHP_METHOD(swoole_process_pool, getProcess) { zend::Process *proc = new zend::Process(zend::PIPE_TYPE_STREAM, pp->enable_coroutine); worker->ptr2 = proc; (void) add_index_zval(zworkers, worker_id, zprocess); + } else { + auto _worker = php_swoole_process_get_worker(zprocess); + if (_worker->pid != current_pool->workers[worker_id].pid) { + _worker->pid = current_pool->workers[worker_id].pid; + zend_update_property_long(swoole_process_ce, SW_Z8_OBJ_P(zprocess), ZEND_STRL("pid"), _worker->pid); + } } RETURN_ZVAL(zprocess, 1, 0); } +static PHP_METHOD(swoole_process_pool, stop) { + if (current_pool) { + current_pool->running = false; + } +} + static PHP_METHOD(swoole_process_pool, shutdown) { zval *retval = sw_zend_read_property_ex(swoole_process_pool_ce, ZEND_THIS, SW_ZSTR_KNOWN(SW_ZEND_STR_MASTER_PID), 0); diff --git a/include/swoole_process_pool.h b/include/swoole_process_pool.h index 0fd2c1c6972..b4f10cf8004 100644 --- a/include/swoole_process_pool.h +++ b/include/swoole_process_pool.h @@ -87,18 +87,9 @@ struct ProcessPool; struct Worker; struct WorkerGlobal { - /** - * Always run - */ bool run_always; bool shutdown; - /** - * pipe_worker - */ - int pipe_used; - uint32_t max_request; - String **output_buffer; Worker *worker; time_t exit_time; @@ -299,9 +290,6 @@ static sw_inline int swoole_waitpid(pid_t __pid, int *__stat_loc, int __options) } static sw_inline int swoole_kill(pid_t __pid, int __sig) { - if (__pid <= 0) { - return -1; - } return kill(__pid, __sig); } diff --git a/tests/swoole_process_pool/getprocess_3.phpt b/tests/swoole_process_pool/getprocess_3.phpt new file mode 100644 index 00000000000..daed3045e31 --- /dev/null +++ b/tests/swoole_process_pool/getprocess_3.phpt @@ -0,0 +1,39 @@ +--TEST-- +swoole_process_pool: getProcess [3] +--SKIPIF-- + +--FILE-- +on('workerStart', function (Swoole\Process\Pool $pool, int $workerId) { + if ($workerId == 0) { + usleep(1000); + $process1 = $pool->getProcess(1); + phpt_var_dump($process1); + $pid1 = $process1->pid; + Process::kill($process1->pid, SIGTERM); + usleep(10000); + $process2 = $pool->getProcess(1); + phpt_var_dump($process2); + $pid2 = $process2->pid; + Assert::notEq($pid1, $pid2); + $pool->shutdown(); + } +}); + +$pool->on("message", function ($pool, $data) { + +}); + +$pool->start(); +?> +--EXPECT-- From e4caad296f1b694bb5759fa41e500a0c981cfb4a Mon Sep 17 00:00:00 2001 From: Yurun Date: Wed, 26 May 2021 13:46:01 +0800 Subject: [PATCH 154/936] Support mysql client prepare field type identification (#4238) * Support mysql client prepare field type identification * Fix test * Judge strict_type * fix --- ext-src/php_swoole_mysql_proto.h | 5 ++ ext-src/swoole_mysql_coro.cc | 44 ++++++++++++----- .../swoole_mysql_coro/prepare_field_type.phpt | 48 +++++++++++++++++++ 3 files changed, 84 insertions(+), 13 deletions(-) create mode 100644 tests/swoole_mysql_coro/prepare_field_type.phpt diff --git a/ext-src/php_swoole_mysql_proto.h b/ext-src/php_swoole_mysql_proto.h index dae89128c88..604d8661fe8 100644 --- a/ext-src/php_swoole_mysql_proto.h +++ b/ext-src/php_swoole_mysql_proto.h @@ -301,6 +301,11 @@ enum sw_mysql_server_status_flags sw_mysql_int4store((T),def_temp); \ sw_mysql_int4store((T+4),def_temp2); } while (0) +#define sw_mysql_doublestore(T,A) do { \ + double def_temp = (double) A; \ + memcpy(T, &def_temp, sizeof(double)); \ + } while (0) + #if defined(SW_DEBUG) && defined(SW_LOG_TRACE_OPEN) #define swMysqlPacketDump(length, number, data, title) \ if (SW_LOG_TRACE >= sw_logger()->get_level() && (SW_TRACE_MYSQL_CLIENT & SwooleG.trace_flags)) \ diff --git a/ext-src/swoole_mysql_coro.cc b/ext-src/swoole_mysql_coro.cc index 45ea132eb03..e802e8013bd 100644 --- a/ext-src/swoole_mysql_coro.cc +++ b/ext-src/swoole_mysql_coro.cc @@ -1246,19 +1246,37 @@ void mysql_statement::send_execute_request(zval *return_value, zval *params) { zend_ulong index = 0; zval *value; ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(params), value) { - if (ZVAL_IS_NULL(value)) { - *((buffer->str + null_start_offset) + (index / 8)) |= (1UL << (index % 8)); - sw_mysql_int2store((buffer->str + type_start_offset) + (index * 2), SW_MYSQL_TYPE_NULL); - } else { - zend::String str_value(value); - uint8_t lcb_size = mysql::write_lcb(stack_buffer, str_value.len()); - sw_mysql_int2store((buffer->str + type_start_offset) + (index * 2), SW_MYSQL_TYPE_VAR_STRING); - if (buffer->append(stack_buffer, lcb_size) < 0) { - RETURN_FALSE; - } - if (buffer->append(str_value.val(), str_value.len()) < 0) { - RETURN_FALSE; - } + switch (client->strict_type ? Z_TYPE_P(value) : (IS_NULL == Z_TYPE_P(value) ? IS_NULL : IS_STRING)) { + case IS_NULL: + *((buffer->str + null_start_offset) + (index / 8)) |= (1UL << (index % 8)); + sw_mysql_int2store((buffer->str + type_start_offset) + (index * 2), SW_MYSQL_TYPE_NULL); + break; + case IS_TRUE: + case IS_FALSE: + case IS_LONG: + sw_mysql_int2store((buffer->str + type_start_offset) + (index * 2), SW_MYSQL_TYPE_LONGLONG); + sw_mysql_int8store(stack_buffer, zval_get_long(value)); + if (buffer->append(stack_buffer, mysql::get_static_type_size(SW_MYSQL_TYPE_LONGLONG)) < 0) { + RETURN_FALSE; + } + break; + case IS_DOUBLE: + sw_mysql_int2store((buffer->str + type_start_offset) + (index * 2), SW_MYSQL_TYPE_DOUBLE); + sw_mysql_doublestore(stack_buffer, zval_get_double(value)); + if (buffer->append(stack_buffer, mysql::get_static_type_size(SW_MYSQL_TYPE_DOUBLE)) < 0) { + RETURN_FALSE; + } + break; + default: + zend::String str_value(value); + uint8_t lcb_size = mysql::write_lcb(stack_buffer, str_value.len()); + sw_mysql_int2store((buffer->str + type_start_offset) + (index * 2), SW_MYSQL_TYPE_VAR_STRING); + if (buffer->append(stack_buffer, lcb_size) < 0) { + RETURN_FALSE; + } + if (buffer->append(str_value.val(), str_value.len()) < 0) { + RETURN_FALSE; + } } index++; } diff --git a/tests/swoole_mysql_coro/prepare_field_type.phpt b/tests/swoole_mysql_coro/prepare_field_type.phpt new file mode 100644 index 00000000000..339ef2c6e11 --- /dev/null +++ b/tests/swoole_mysql_coro/prepare_field_type.phpt @@ -0,0 +1,48 @@ +--TEST-- +swoole_mysql_coro: mysql prepare field type +--SKIPIF-- + +--FILE-- + MYSQL_SERVER_HOST, + 'port' => MYSQL_SERVER_PORT, + 'user' => MYSQL_SERVER_USER, + 'password' => MYSQL_SERVER_PWD, + 'database' => MYSQL_SERVER_DB, + 'strict_type' => true, + ]; + + $ret1 = $db->connect($server); + if (! $ret1) { + echo "CONNECT ERROR\n"; + + return; + } + + $stmt = $db->prepare('SELECT ? as a, ? as b, ? as c, ? as d, ? + ? as e'); + if (! $stmt) { + echo "PREPARE ERROR\n"; + + return; + } + + $ret3 = $stmt->execute([123, 3.14, true, false, 11, 22]); + if (! $ret3) { + echo "EXECUTE ERROR#{$stmt->errno}: {$stmt->error}\n"; + + return; + } + if (Assert::isArray($ret3)) { + Assert::same(reset($ret3), ['a' => 123, 'b' => 3.14, 'c' => 1, 'd' => 0, 'e' => 33]); + } +}); + +?> +--EXPECT-- From 4eed1a6da8afed6edec2c3c78ec701063020b1e3 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Wed, 26 May 2021 17:42:56 +0800 Subject: [PATCH 155/936] Optimize code for setting heartbeat_idle_time --- ext-src/swoole_server.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 8986b0887a8..68e8dedf0b5 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -2390,7 +2390,8 @@ static PHP_METHOD(swoole_server, set) { php_swoole_fatal_error(E_WARNING, "heartbeat_idle_time must be greater than heartbeat_check_interval"); serv->heartbeat_check_interval = serv->heartbeat_idle_time / 2; } - } else if (serv->heartbeat_check_interval > 0) { + } + if (serv->heartbeat_idle_time == 0 && serv->heartbeat_check_interval > 0) { serv->heartbeat_idle_time = serv->heartbeat_check_interval * 2; } // max_request From f7ef45b64a81eea0d39004cde02ba59983e22c29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Thu, 3 Jun 2021 18:50:50 +0800 Subject: [PATCH 156/936] Support Co::cancel() (#4247) * socket/sleep * cancel api, yield/suspend * cancel AIO * rename, optimize * add tests, support cancel wait_signal, gethostbyname * optimize code, support cancel wait() * optimize tests, support cancel wait_event() * add Coroutine::isCanceled() * optimize, fix tests * Remove useless code * optimize naming, fix tests * Revert "Remove useless code" This reverts commit b64d2f24e5dbb27f8845ea13c1462d8b338e4ddb. * fix tests * fix tests[2] --- core-tests/include/test_coroutine.h | 12 +- core-tests/src/coroutine/async.cpp | 4 +- core-tests/src/coroutine/system.cpp | 11 + ext-src/php_swoole.cc | 3 + ext-src/php_swoole_library.h | 19 +- ext-src/swoole_coroutine.cc | 66 ++++- ext-src/swoole_coroutine_system.cc | 9 +- include/swoole_async.h | 6 +- include/swoole_coroutine.h | 31 ++- include/swoole_coroutine_context.h | 6 +- include/swoole_error.h | 4 + src/core/error.cc | 6 + src/coroutine/base.cc | 40 ++- src/coroutine/context.cc | 2 +- src/coroutine/socket.cc | 9 +- src/coroutine/system.cc | 245 ++++++++++-------- src/coroutine/thread_context.cc | 2 +- src/os/async_thread.cc | 8 +- src/os/base.cc | 8 +- src/os/wait.cc | 15 +- tests/swoole_coroutine/cancel/error.phpt | 23 ++ .../cancel/gethostbyname.phpt | 28 ++ tests/swoole_coroutine/cancel/sleep.phpt | 30 +++ tests/swoole_coroutine/cancel/socket.phpt | 34 +++ tests/swoole_coroutine/cancel/suspend.phpt | 28 ++ tests/swoole_coroutine/cancel/wait.phpt | 28 ++ tests/swoole_coroutine/cancel/wait_event.phpt | 32 +++ .../swoole_coroutine/cancel/wait_signal.phpt | 28 ++ 28 files changed, 562 insertions(+), 175 deletions(-) create mode 100644 tests/swoole_coroutine/cancel/error.phpt create mode 100644 tests/swoole_coroutine/cancel/gethostbyname.phpt create mode 100644 tests/swoole_coroutine/cancel/sleep.phpt create mode 100644 tests/swoole_coroutine/cancel/socket.phpt create mode 100644 tests/swoole_coroutine/cancel/suspend.phpt create mode 100644 tests/swoole_coroutine/cancel/wait.phpt create mode 100644 tests/swoole_coroutine/cancel/wait_event.phpt create mode 100644 tests/swoole_coroutine/cancel/wait_signal.phpt diff --git a/core-tests/include/test_coroutine.h b/core-tests/include/test_coroutine.h index e7a3c331d35..baf6a4933b4 100644 --- a/core-tests/include/test_coroutine.h +++ b/core-tests/include/test_coroutine.h @@ -13,7 +13,7 @@ namespace swoole { namespace test { class coroutine { public: - coroutine(const coroutine_func_t &_fn, void *_arg, int *_complete_num) : + coroutine(const CoroutineFunc &_fn, void *_arg, int *_complete_num) : fn(_fn), arg(_arg), complete_num(_complete_num) { } void start() @@ -22,7 +22,7 @@ class coroutine (*complete_num)++; } - inline static void create(const coroutine_func_t &fn, void *arg, int *complete_num) + inline static void create(const CoroutineFunc &fn, void *arg, int *complete_num) { auto test = new coroutine(fn, arg, complete_num); @@ -34,7 +34,7 @@ class coroutine ASSERT_GT(cid, 0); } - inline static void run(std::initializer_list> args) + inline static void run(std::initializer_list> args) { int complete_num = 0; swoole_event_init(SW_EVENTLOOP_WAIT_EXIT); @@ -45,7 +45,7 @@ class coroutine swoole_event_wait(); } - inline static void run(std::initializer_list fns) + inline static void run(std::initializer_list fns) { int complete_num = 0; swoole_event_init(SW_EVENTLOOP_WAIT_EXIT); @@ -56,7 +56,7 @@ class coroutine swoole_event_wait(); } - inline static void run(const coroutine_func_t &fn, void *arg = nullptr) + inline static void run(const CoroutineFunc &fn, void *arg = nullptr) { int complete_num = 0; swoole_event_init(SW_EVENTLOOP_WAIT_EXIT); @@ -65,7 +65,7 @@ class coroutine } private: - coroutine_func_t fn; + CoroutineFunc fn; void *arg; int *complete_num; }; diff --git a/core-tests/src/coroutine/async.cpp b/core-tests/src/coroutine/async.cpp index cf240ea8663..7c90c801c9d 100644 --- a/core-tests/src/coroutine/async.cpp +++ b/core-tests/src/coroutine/async.cpp @@ -19,11 +19,11 @@ TEST(coroutine_async, usleep) { bool retval = swoole::coroutine::async( [](AsyncEvent *event) { usleep(1000); - event->ret = magic_code; + event->retval = magic_code; }, ev); ASSERT_EQ(retval, true); - ASSERT_EQ(ev.ret, magic_code); + ASSERT_EQ(ev.retval, magic_code); }); } diff --git a/core-tests/src/coroutine/system.cpp b/core-tests/src/coroutine/system.cpp index f5617fcfb8b..4499b65112e 100644 --- a/core-tests/src/coroutine/system.cpp +++ b/core-tests/src/coroutine/system.cpp @@ -80,3 +80,14 @@ TEST(coroutine_system, flock) { swoole_event_wait(); unlink(test_file); } + +TEST(coroutine_system, cancel_sleep) { + coroutine::run([](void *arg) { + auto co = Coroutine::get_current_safe(); + Coroutine::create([co](void *){ + System::sleep(0.002); + co->cancel(); + }); + System::sleep(1000); + }); +} diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index b35691ab43b..5e609164555 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -657,6 +657,9 @@ PHP_MINIT_FUNCTION(swoole) { SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_CO_PROTECT_STACK_FAILED", SW_ERROR_CO_PROTECT_STACK_FAILED); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_CO_STD_THREAD_LINK_ERROR", SW_ERROR_CO_STD_THREAD_LINK_ERROR); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_CO_DISABLED_MULTI_THREAD", SW_ERROR_CO_DISABLED_MULTI_THREAD); + SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_CO_CANNOT_CANCEL", SW_ERROR_CO_CANNOT_CANCEL); + SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_CO_NOT_EXISTS", SW_ERROR_CO_NOT_EXISTS); + SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_CO_CANCELED", SW_ERROR_CO_CANCELED); /** * trace log diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index e0541187a93..2e8c8af2a89 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: b2d3486c3bca310c730de8575e71b27d2d0ee30d */ +/* $Id: 65ea83f61739de6203f1368150350fd3f91e3a7e */ static const char* swoole_library_source_constants = "\n" @@ -899,6 +899,19 @@ static const char* swoole_library_source_core_array_object = " }\n" "\n" " /**\n" + " * @param mixed $key\n" + " * @param mixed $default\n" + " * @return ArrayObject|StringObject\n" + " */\n" + " public function getOr($key, $default = null)\n" + " {\n" + " if (!$this->exists($key)) {\n" + " return $default;\n" + " }\n" + " return static::detectType($this->array[$key]);\n" + " }\n" + "\n" + " /**\n" " * @return mixed\n" " */\n" " public function last()\n" @@ -3375,7 +3388,7 @@ static const char* swoole_library_source_core_http_status = " self::UNSUPPORTED_MEDIA_TYPE => 'Unsupported Media Type',\n" " self::REQUESTED_RANGE_NOT_SATISFIABLE => 'Requested range not satisfiable',\n" " self::EXPECTATION_FAILED => 'Expectation Failed',\n" - " self::MISDIRECTED_REQUEST => 'Unprocessable Entity',\n" + " self::MISDIRECTED_REQUEST => 'Misdirected Request',\n" " self::UNPROCESSABLE_ENTITY => 'Unprocessable Entity',\n" " self::LOCKED => 'Locked',\n" " self::FAILED_DEPENDENCY => 'Failed Dependency',\n" @@ -6947,7 +6960,7 @@ static const char* swoole_library_source_core_coroutine_functions = "\n" "function go(callable $fn, ...$args)\n" "{\n" - " Coroutine::create($fn, ...$args);\n" + " return Coroutine::create($fn, ...$args);\n" "}\n" "\n" "function defer(callable $fn)\n" diff --git a/ext-src/swoole_coroutine.cc b/ext-src/swoole_coroutine.cc index ee2a68b81cb..999a8c73db3 100644 --- a/ext-src/swoole_coroutine.cc +++ b/ext-src/swoole_coroutine.cc @@ -88,6 +88,8 @@ SW_EXTERN_C_BEGIN static PHP_METHOD(swoole_coroutine, exists); static PHP_METHOD(swoole_coroutine, yield); static PHP_METHOD(swoole_coroutine, resume); +static PHP_METHOD(swoole_coroutine, cancel); +static PHP_METHOD(swoole_coroutine, isCanceled); static PHP_METHOD(swoole_coroutine, stats); static PHP_METHOD(swoole_coroutine, getCid); static PHP_METHOD(swoole_coroutine, getPcid); @@ -113,6 +115,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_coroutine_create, 0, 0, 1) ZEND_ARG_VARIADIC_INFO(0, params) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_coroutine_cancel, 0, 0, 1) + ZEND_ARG_INFO(0, cid) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_coroutine_resume, 0, 0, 1) ZEND_ARG_INFO(0, cid) ZEND_END_ARG_INFO() @@ -160,6 +166,8 @@ static const zend_function_entry swoole_coroutine_methods[] = PHP_ME(swoole_coroutine_scheduler, getOptions, arginfo_swoole_coroutine_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(swoole_coroutine, exists, arginfo_swoole_coroutine_exists, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(swoole_coroutine, yield, arginfo_swoole_coroutine_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(swoole_coroutine, cancel, arginfo_swoole_coroutine_cancel, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(swoole_coroutine, isCanceled, arginfo_swoole_coroutine_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_MALIAS(swoole_coroutine, suspend, yield, arginfo_swoole_coroutine_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(swoole_coroutine, resume, arginfo_swoole_coroutine_resume, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(swoole_coroutine, stats, arginfo_swoole_coroutine_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) @@ -352,7 +360,7 @@ void PHPCoroutine::activate() { /** * deactivate when reactor free. */ - SwooleTG.reactor->add_destroy_callback(deactivate, nullptr); + sw_reactor()->add_destroy_callback(deactivate, nullptr); Coroutine::activate(); activated = true; } @@ -954,9 +962,9 @@ PHP_FUNCTION(swoole_coroutine_defer) { PHPCoroutine::defer(defer_fci); } -PHP_METHOD(swoole_coroutine, stats) { +static PHP_METHOD(swoole_coroutine, stats) { array_init(return_value); - add_assoc_long_ex(return_value, ZEND_STRL("event_num"), SwooleTG.reactor ? SwooleTG.reactor->event_num : 0); + add_assoc_long_ex(return_value, ZEND_STRL("event_num"), sw_reactor() ? sw_reactor()->event_num : 0); add_assoc_long_ex( return_value, ZEND_STRL("signal_listener_num"), SwooleTG.signal_listener_num + SwooleTG.co_signal_listener_num); @@ -994,7 +1002,7 @@ PHP_METHOD(swoole_coroutine, getPcid) { RETURN_LONG(ret); } -PHP_METHOD(swoole_coroutine, getContext) { +static PHP_METHOD(swoole_coroutine, getContext) { zend_long cid = 0; ZEND_PARSE_PARAMETERS_START(0, 1) @@ -1005,6 +1013,7 @@ PHP_METHOD(swoole_coroutine, getContext) { PHPContext *task = (PHPContext *) (EXPECTED(cid == 0) ? Coroutine::get_current_task() : Coroutine::get_task_by_cid(cid)); if (UNEXPECTED(!task)) { + swoole_set_last_error(SW_ERROR_CO_NOT_EXISTS); RETURN_NULL(); } if (UNEXPECTED(task->context == (zend_object *) ~0)) { @@ -1020,7 +1029,7 @@ PHP_METHOD(swoole_coroutine, getContext) { RETURN_OBJ(task->context); } -PHP_METHOD(swoole_coroutine, getElapsed) { +static PHP_METHOD(swoole_coroutine, getElapsed) { zend_long cid = 0; zend_long ret; @@ -1033,7 +1042,7 @@ PHP_METHOD(swoole_coroutine, getElapsed) { RETURN_LONG(ret); } -PHP_METHOD(swoole_coroutine, exists) { +static PHP_METHOD(swoole_coroutine, exists) { zend_long cid; ZEND_PARSE_PARAMETERS_START(1, 1) @@ -1043,7 +1052,7 @@ PHP_METHOD(swoole_coroutine, exists) { RETURN_BOOL(Coroutine::get_by_cid(cid) != nullptr); } -PHP_METHOD(swoole_coroutine, resume) { +static PHP_METHOD(swoole_coroutine, resume) { long cid; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &cid) == FAILURE) { RETURN_FALSE; @@ -1058,16 +1067,47 @@ PHP_METHOD(swoole_coroutine, resume) { Coroutine *co = coroutine_iterator->second; user_yield_coros.erase(cid); co->resume(); + RETURN_TRUE; } -PHP_METHOD(swoole_coroutine, yield) { +static PHP_METHOD(swoole_coroutine, yield) { Coroutine *co = Coroutine::get_current_safe(); user_yield_coros[co->get_cid()] = co; - co->yield(); + + Coroutine::CancelFunc cancel_fn = [](Coroutine *co){ + user_yield_coros.erase(co->get_cid()); + co->resume(); + return true; + }; + co->yield(&cancel_fn); + if (co->is_canceled()) { + swoole_set_last_error(SW_ERROR_CO_CANCELED); + RETURN_FALSE; + } + RETURN_TRUE; } +static PHP_METHOD(swoole_coroutine, cancel) { + long cid; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &cid) == FAILURE) { + RETURN_FALSE; + } + + Coroutine *co = swoole_coroutine_get(cid); + if (!co) { + swoole_set_last_error(SW_ERROR_CO_NOT_EXISTS); + RETURN_FALSE; + } + RETURN_BOOL(co->cancel()); +} + +static PHP_METHOD(swoole_coroutine, isCanceled) { + Coroutine *co = Coroutine::get_current_safe(); + RETURN_BOOL(co->is_canceled()); +} + PHP_FUNCTION(swoole_test_kernel_coroutine) { if (!PHPCoroutine::is_activated()) { RETURN_FALSE; @@ -1089,7 +1129,7 @@ PHP_FUNCTION(swoole_test_kernel_coroutine) { }); } -PHP_METHOD(swoole_coroutine, getBackTrace) { +static PHP_METHOD(swoole_coroutine, getBackTrace) { zend_long cid = 0; zend_long options = DEBUG_BACKTRACE_PROVIDE_OBJECT; zend_long limit = 0; @@ -1106,6 +1146,7 @@ PHP_METHOD(swoole_coroutine, getBackTrace) { } else { PHPContext *task = (PHPContext *) PHPCoroutine::get_context_by_cid(cid); if (UNEXPECTED(!task)) { + swoole_set_last_error(SW_ERROR_CO_NOT_EXISTS); RETURN_FALSE; } zend_execute_data *ex_backup = EG(current_execute_data); @@ -1115,7 +1156,7 @@ PHP_METHOD(swoole_coroutine, getBackTrace) { } } -PHP_METHOD(swoole_coroutine, printBackTrace) { +static PHP_METHOD(swoole_coroutine, printBackTrace) { zend_long cid = 0; zend_long options = DEBUG_BACKTRACE_PROVIDE_OBJECT; zend_long limit = 0; @@ -1136,6 +1177,7 @@ PHP_METHOD(swoole_coroutine, printBackTrace) { } else { PHPContext *task = (PHPContext *) PHPCoroutine::get_context_by_cid(cid); if (UNEXPECTED(!task)) { + swoole_set_last_error(SW_ERROR_CO_NOT_EXISTS); RETURN_FALSE; } zend_execute_data *ex_backup = EG(current_execute_data); @@ -1145,7 +1187,7 @@ PHP_METHOD(swoole_coroutine, printBackTrace) { } } -PHP_METHOD(swoole_coroutine, list) { +static PHP_METHOD(swoole_coroutine, list) { zval zlist; array_init(&zlist); for (auto &co : Coroutine::coroutines) { diff --git a/ext-src/swoole_coroutine_system.cc b/ext-src/swoole_coroutine_system.cc index ae77fea3c32..55177dd4809 100644 --- a/ext-src/swoole_coroutine_system.cc +++ b/ext-src/swoole_coroutine_system.cc @@ -645,12 +645,12 @@ PHP_METHOD(swoole_coroutine_system, waitSignal) { ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); if (!System::wait_signal(signo, timeout)) { - if (errno == EBUSY) { + if (swoole_get_last_error() == EBUSY) { php_swoole_fatal_error(E_WARNING, "Unable to wait signal, async signal listener has been registered"); - } else if (errno == EINVAL) { + } else if (swoole_get_last_error() == EINVAL) { php_swoole_fatal_error(E_WARNING, "Invalid signal [" ZEND_LONG_FMT "]", signo); } - swoole_set_last_error(errno); + errno = swoole_get_last_error(); RETURN_FALSE; } @@ -676,6 +676,9 @@ PHP_METHOD(swoole_coroutine_system, waitEvent) { } events = System::wait_event(fd, events, timeout); + if (events < 0) { + RETURN_FALSE; + } RETURN_LONG(events); } diff --git a/include/swoole_async.h b/include/swoole_async.h index d2aeafbc229..f1ef612ac6b 100644 --- a/include/swoole_async.h +++ b/include/swoole_async.h @@ -50,7 +50,7 @@ struct AsyncEvent { /** * output */ - ssize_t ret; + ssize_t retval; int error; /** * internal use only @@ -60,6 +60,10 @@ struct AsyncEvent { void *object; void (*handler)(AsyncEvent *event); void (*callback)(AsyncEvent *event); + + bool catch_error() { + return (error == SW_ERROR_AIO_TIMEOUT || error == SW_ERROR_AIO_CANCELED); + } }; class AsyncThreads { diff --git a/include/swoole_coroutine.h b/include/swoole_coroutine.h index 67c8fc026a1..a8244eb115b 100644 --- a/include/swoole_coroutine.h +++ b/include/swoole_coroutine.h @@ -37,6 +37,7 @@ class Coroutine { public: void resume(); void yield(); + bool cancel(); void resume_naked(); void yield_naked(); @@ -61,6 +62,14 @@ class Coroutine { typedef void (*SwapCallback)(void *); typedef void (*BailoutCallback)(); + typedef std::function CancelFunc; + + void yield(CancelFunc *cancel_fn) { + set_cancel_fn(cancel_fn); + canceled_ = false; + yield(); + set_cancel_fn(nullptr); + } inline enum State get_state() { return state; @@ -90,10 +99,18 @@ class Coroutine { return ctx.is_end(); } + bool is_canceled() { + return canceled_; + } + inline void set_task(void *_task) { task = _task; } + void set_cancel_fn(CancelFunc *cancel_fn) { + cancel_fn_ = cancel_fn; + } + static std::unordered_map coroutines; static void set_on_yield(SwapCallback func); @@ -101,7 +118,7 @@ class Coroutine { static void set_on_close(SwapCallback func); static void bailout(BailoutCallback func); - static inline long create(const coroutine_func_t &fn, void *args = nullptr) { + static inline long create(const CoroutineFunc &fn, void *args = nullptr) { #ifdef SW_USE_THREAD_CONTEXT try { return (new Coroutine(fn, args))->run(); @@ -191,8 +208,10 @@ class Coroutine { void *task = nullptr; coroutine::Context ctx; Coroutine *origin = nullptr; - - Coroutine(const coroutine_func_t &fn, void *private_data) : ctx(stack_size, fn, private_data) { + CancelFunc *cancel_fn_ = nullptr; + bool canceled_ = false; + + Coroutine(const CoroutineFunc &fn, void *private_data) : ctx(stack_size, fn, private_data) { cid = ++last_cid; coroutines[cid] = this; if (sw_unlikely(count() > peak_num)) { @@ -226,7 +245,7 @@ class Coroutine { namespace coroutine { bool async(async::Handler handler, AsyncEvent &event, double timeout = -1); bool async(const std::function &fn, double timeout = -1); -bool run(const coroutine_func_t &fn, void *arg = nullptr); +bool run(const CoroutineFunc &fn, void *arg = nullptr); } // namespace coroutine //------------------------------------------------------------------------------- } // namespace swoole @@ -236,5 +255,5 @@ bool run(const coroutine_func_t &fn, void *arg = nullptr); */ swoole::Coroutine *swoole_coro_iterator_each(); void swoole_coro_iterator_reset(); -swoole::Coroutine *swoole_coro_get(long cid); -size_t swoole_coro_count(); +swoole::Coroutine *swoole_coroutine_get(long cid); +size_t swoole_coroutine_count(); diff --git a/include/swoole_coroutine_context.h b/include/swoole_coroutine_context.h index 88c5fc67472..6ff33f35666 100644 --- a/include/swoole_coroutine_context.h +++ b/include/swoole_coroutine_context.h @@ -44,14 +44,14 @@ typedef ucontext_t coroutine_context_t; typedef fcontext_t coroutine_context_t; #endif -typedef std::function coroutine_func_t; +typedef std::function CoroutineFunc; namespace swoole { namespace coroutine { class Context { public: - Context(size_t stack_size, const coroutine_func_t &fn, void *private_data); + Context(size_t stack_size, const CoroutineFunc &fn, void *private_data); ~Context(); bool swap_in(); bool swap_out(); @@ -62,7 +62,7 @@ class Context { return end_; } protected: - coroutine_func_t fn_; + CoroutineFunc fn_; #ifdef SW_USE_THREAD_CONTEXT std::thread thread_; std::mutex lock_; diff --git a/include/swoole_error.h b/include/swoole_error.h index b5ac35e8516..79cd50fa89a 100644 --- a/include/swoole_error.h +++ b/include/swoole_error.h @@ -167,6 +167,10 @@ enum swErrorCode { SW_ERROR_CO_STD_THREAD_LINK_ERROR, SW_ERROR_CO_DISABLED_MULTI_THREAD, + SW_ERROR_CO_CANNOT_CANCEL, + SW_ERROR_CO_NOT_EXISTS, + SW_ERROR_CO_CANCELED, + SW_ERROR_END }; diff --git a/src/core/error.cc b/src/core/error.cc index 7b1ee77bbad..5d97f6c1290 100644 --- a/src/core/error.cc +++ b/src/core/error.cc @@ -215,6 +215,12 @@ const char *swoole_strerror(int code) { return "Coroutine std thread link error"; case SW_ERROR_CO_DISABLED_MULTI_THREAD: return "Coroutine disabled multi thread"; + case SW_ERROR_CO_CANNOT_CANCEL: + return "Coroutine cannot cancel"; + case SW_ERROR_CO_NOT_EXISTS: + return "Coroutine not exists"; + case SW_ERROR_CO_CANCELED: + return "Coroutine canceled"; default: static char buffer[32]; #ifndef __MACH__ diff --git a/src/coroutine/base.cc b/src/coroutine/base.cc index bf9fa50b75e..b02ab87a43e 100644 --- a/src/coroutine/base.cc +++ b/src/coroutine/base.cc @@ -96,6 +96,17 @@ void Coroutine::resume_naked() { check_end(); } +bool Coroutine::cancel() { + if (!cancel_fn_) { + swoole_set_last_error(SW_ERROR_CO_CANNOT_CANCEL); + return false; + } + auto fn = *cancel_fn_; + set_cancel_fn(nullptr); + canceled_ = true; + return fn(this); +} + void Coroutine::close() { SW_ASSERT(current == this); state = STATE_END; @@ -171,8 +182,9 @@ void Coroutine::bailout(BailoutCallback func) { // expect that never here exit(1); } + namespace coroutine { -bool run(const coroutine_func_t &fn, void *arg) { +bool run(const CoroutineFunc &fn, void *arg) { if (swoole_event_init(SW_EVENTLOOP_WAIT_EXIT) < 0) { return false; } @@ -193,6 +205,19 @@ long swoole_coroutine_get_current_id() { return swoole::Coroutine::get_current_cid(); } +swoole::Coroutine *swoole_coroutine_get(long cid) { + auto i = swoole::Coroutine::coroutines.find(cid); + if (i == swoole::Coroutine::coroutines.end()) { + return nullptr; + } else { + return i->second; + } +} + +size_t swoole_coroutine_count() { + return swoole::Coroutine::coroutines.size(); +} + /** * for gdb */ @@ -211,16 +236,3 @@ swoole::Coroutine *swoole_coro_iterator_each() { return co; } } - -swoole::Coroutine *swoole_coro_get(long cid) { - auto i = swoole::Coroutine::coroutines.find(cid); - if (i == swoole::Coroutine::coroutines.end()) { - return nullptr; - } else { - return i->second; - } -} - -size_t swoole_coro_count() { - return swoole::Coroutine::coroutines.size(); -} diff --git a/src/coroutine/context.cc b/src/coroutine/context.cc index dd9d083c490..db8139a4d47 100644 --- a/src/coroutine/context.cc +++ b/src/coroutine/context.cc @@ -30,7 +30,7 @@ namespace swoole { namespace coroutine { -Context::Context(size_t stack_size, const coroutine_func_t &fn, void *private_data) +Context::Context(size_t stack_size, const CoroutineFunc &fn, void *private_data) : fn_(fn), stack_size_(stack_size), private_data_(private_data) { end_ = false; diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index c0a127773f1..d04975c7778 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -154,9 +154,14 @@ bool Socket::wait_event(const enum swEvent_type event, const void **__buf, size_ : socket->ssl_want_write ? "SSL WRITE" : #endif event == SW_EVENT_READ ? "READ" : "WRITE"); + + Coroutine::CancelFunc cancel_fn = [this, event](Coroutine *co){ + return cancel(event); + }; + if (sw_likely(event == SW_EVENT_READ)) { read_co = co; - read_co->yield(); + read_co->yield(&cancel_fn); read_co = nullptr; } else if (event == SW_EVENT_WRITE) { if (sw_unlikely(!zero_copy && __n > 0 && *__buf != get_write_buffer()->str)) { @@ -168,7 +173,7 @@ bool Socket::wait_event(const enum swEvent_type event, const void **__buf, size_ *__buf = write_buffer->str; } write_co = co; - write_co->yield(); + write_co->yield(&cancel_fn); write_co = nullptr; } else { assert(0); diff --git a/src/coroutine/system.cc b/src/coroutine/system.cc index 6eaa7f799b0..fe6599be015 100644 --- a/src/coroutine/system.cc +++ b/src/coroutine/system.cc @@ -21,11 +21,6 @@ namespace swoole { namespace coroutine { -struct AsyncTask { - Coroutine *co; - AsyncEvent *original_event; -}; - static size_t dns_cache_capacity = 1000; static time_t dns_cache_expire = 60; static LRUCache *dns_cache = nullptr; @@ -46,43 +41,50 @@ void System::clear_dns_cache() { } } -static void aio_onDNSCompleted(AsyncEvent *event) { - if (event->canceled) { +static void sleep_callback(Coroutine *co, bool *canceled) { + bool _canceled = *canceled; + delete canceled; + if (_canceled) { return; } - AsyncTask *task = (AsyncTask *) event->object; - task->original_event->ret = event->ret; - task->original_event->error = event->error; - ((Coroutine *) task->co)->resume(); -} - -static void aio_onDNSTimeout(Timer *timer, TimerNode *tnode) { - AsyncEvent *event = (AsyncEvent *) tnode->data; - event->canceled = 1; - AsyncTask *task = (AsyncTask *) event->object; - task->original_event->ret = -1; - task->original_event->error = SW_ERROR_DNSLOOKUP_RESOLVE_TIMEOUT; - ((Coroutine *) task->co)->resume(); -} - -static void sleep_timeout(Timer *timer, TimerNode *tnode) { - ((Coroutine *) tnode->data)->resume(); + co->resume(); } int System::sleep(double sec) { Coroutine *co = Coroutine::get_current_safe(); + + bool *canceled = new bool(false); + TimerNode *tnode = nullptr; + if (sec < SW_TIMER_MIN_SEC) { - swoole_event_defer([co](void *data) { co->resume(); }, nullptr); - } else if (swoole_timer_add((long) (sec * 1000), false, sleep_timeout, co) == nullptr) { - return -1; + swoole_event_defer([co, canceled](void *data) { sleep_callback(co, canceled); }, nullptr); + } else { + auto fn = [canceled](Timer *timer, TimerNode *tnode) { sleep_callback((Coroutine *) tnode->data, canceled); }; + tnode = swoole_timer_add((long) (sec * 1000), false, fn, co); + if (tnode == nullptr) { + delete canceled; + return -1; + } + } + Coroutine::CancelFunc cancel_fn = [canceled, tnode](Coroutine *co) { + *canceled = true; + if (tnode) { + swoole_timer_del(tnode); + } + co->resume(); + return true; + }; + co->yield(&cancel_fn); + if (co->is_canceled()) { + swoole_set_last_error(SW_ERROR_CO_CANCELED); + return SW_ERR; } - co->yield(); - return 0; + return SW_OK; } std::shared_ptr System::read_file(const char *file, bool lock) { std::shared_ptr result; - swoole::coroutine::async([&result, file, lock]() { + async([&result, file, lock]() { File fp(file, O_RDONLY); if (!fp.ready()) { swSysWarn("open(%s, O_RDONLY) failed", file); @@ -111,7 +113,7 @@ std::shared_ptr System::read_file(const char *file, bool lock) { ssize_t System::write_file(const char *file, char *buf, size_t length, bool lock, int flags) { ssize_t retval = -1; int file_flags = flags | O_CREAT | O_WRONLY; - swoole::coroutine::async([&]() { + async([&]() { File _file(file, file_flags, 0644); if (!_file.ready()) { swSysWarn("open(%s, %d) failed", file, file_flags); @@ -150,7 +152,6 @@ std::string System::gethostbyname(const std::string &hostname, int domain, doubl } AsyncEvent ev{}; - AsyncTask task; if (hostname.size() < SW_IP_MAX_LENGTH) { ev.nbytes = SW_IP_MAX_LENGTH + 1; @@ -158,9 +159,6 @@ std::string System::gethostbyname(const std::string &hostname, int domain, doubl ev.nbytes = hostname.size() + 1; } - task.co = Coroutine::get_current_safe(); - task.original_event = &ev; - ev.buf = sw_malloc(ev.nbytes); if (!ev.buf) { return ""; @@ -169,30 +167,14 @@ std::string System::gethostbyname(const std::string &hostname, int domain, doubl memcpy(ev.buf, hostname.c_str(), hostname.size()); ((char *) ev.buf)[hostname.size()] = 0; ev.flags = domain; - ev.object = (void *) &task; - ev.handler = async::handler_gethostbyname; - ev.callback = aio_onDNSCompleted; - /* TODO: find a better way */ - ev.ret = 1; + ev.retval = 1; - AsyncEvent *event = async::dispatch(&ev); - TimerNode *timer = nullptr; - if (timeout > 0) { - timer = swoole_timer_add((long) (timeout * 1000), false, aio_onDNSTimeout, event); - } - task.co->yield(); - if (ev.ret == 1) { - /* TODO: find a better way */ - /* canceled */ - event->canceled = 1; - ev.ret = -1; - ev.error = SW_ERROR_DNSLOOKUP_RESOLVE_FAILED; - } - if (timer) { - swoole_timer_del(timer); - } + coroutine::async(async::handler_gethostbyname, ev, timeout); - if (ev.ret == -1) { + if (ev.retval == -1) { + if (ev.error == SW_ERROR_AIO_TIMEOUT) { + ev.error = SW_ERROR_DNSLOOKUP_RESOLVE_TIMEOUT; + } swoole_set_last_error(ev.error); return ""; } else { @@ -217,11 +199,6 @@ std::vector System::getaddrinfo( AsyncEvent ev{}; network::GetaddrinfoRequest req{}; - AsyncTask task{Coroutine::get_current_safe(), &ev}; - - ev.object = &task; - ev.handler = async::handler_getaddrinfo; - ev.callback = aio_onDNSCompleted; ev.req = &req; struct sockaddr_in6 result_buffer[SW_DNS_HOST_BUFFER_SIZE]; @@ -233,19 +210,14 @@ std::vector System::getaddrinfo( req.service = service.empty() ? nullptr : service.c_str(); req.result = result_buffer; - AsyncEvent *event = async::dispatch(&ev); - TimerNode *timer = nullptr; - if (timeout > 0) { - timer = swoole_timer_add((long) (timeout * 1000), false, aio_onDNSTimeout, event); - } - task.co->yield(); - if (timer) { - swoole_timer_del(timer); - } + coroutine::async(async::handler_getaddrinfo, ev, timeout); std::vector retval; - if (ev.ret == -1 || req.error != 0) { + if (ev.retval == -1 || req.error != 0) { + if (ev.error == SW_ERROR_AIO_TIMEOUT) { + ev.error = SW_ERROR_DNSLOOKUP_RESOLVE_TIMEOUT; + } swoole_set_last_error(ev.error); } else { req.parse_result(retval); @@ -254,16 +226,19 @@ std::vector System::getaddrinfo( return retval; } +/** + * @error: swoole_get_last_error() + */ bool System::wait_signal(int signo, double timeout) { static Coroutine *listeners[SW_SIGNO_MAX]; Coroutine *co = Coroutine::get_current_safe(); if (SwooleTG.signal_listener_num > 0) { - errno = EBUSY; + swoole_set_last_error(EBUSY); return false; } if (signo < 0 || signo >= SW_SIGNO_MAX || signo == SIGCHLD) { - errno = EINVAL; + swoole_set_last_error(EINVAL); return false; } @@ -300,14 +275,21 @@ bool System::wait_signal(int signo, double timeout) { co); } - co->yield(); + Coroutine::CancelFunc cancel_fn = [timer](Coroutine *co) { + if (timer) { + swoole_timer_del(timer); + } + co->resume(); + return true; + }; + co->yield(&cancel_fn); swSignal_set(signo, nullptr); SwooleTG.co_signal_listener_num--; if (listeners[signo] != nullptr) { listeners[signo] = nullptr; - errno = ETIMEDOUT; + swoole_set_last_error(co->is_canceled() ? SW_ERROR_CO_CANCELED : ETIMEDOUT); return false; } @@ -315,7 +297,7 @@ bool System::wait_signal(int signo, double timeout) { swoole_timer_del(timer); } - return true; + return !co->is_canceled(); } struct CoroPollTask { @@ -485,13 +467,23 @@ struct EventWaiter { TimerNode *timer; Coroutine *co; int revents; + int error_; EventWaiter(int fd, int events, double timeout) { - revents = 0; + error_ = revents = 0; socket = swoole::make_socket(fd, SW_FD_CORO_EVENT); socket->object = this; timer = nullptr; - co = nullptr; + co = Coroutine::get_current_safe(); + + Coroutine::CancelFunc cancel_fn = [this](Coroutine *) { + if (timer) { + swoole_timer_del(timer); + } + error_ = SW_ERROR_CO_CANCELED; + co->resume(); + return true; + }; if (swoole_event_add(socket, events) < 0) { swoole_set_last_error(errno); @@ -504,18 +496,19 @@ struct EventWaiter { [](Timer *timer, TimerNode *tnode) { EventWaiter *waiter = (EventWaiter *) tnode->data; waiter->timer = nullptr; + waiter->error_ = ETIMEDOUT; waiter->co->resume(); }, this); } - co = Coroutine::get_current(); - co->yield(); + co->yield(&cancel_fn); if (timer != nullptr) { swoole_timer_del(timer); - } else if (timeout > 0) { - swoole_set_last_error(ETIMEDOUT); + } + if (error_) { + swoole_set_last_error(error_); } swoole_event_del(socket); _done: @@ -546,6 +539,9 @@ static int event_waiter_error_callback(Reactor *reactor, Event *event) { return SW_OK; } +/** + * @errror: errno & swoole_get_last_error() + */ int System::wait_event(int fd, int events, double timeout) { events &= SW_EVENT_READ | SW_EVENT_WRITE; if (events == 0) { @@ -569,8 +565,13 @@ int System::wait_event(int fd, int events, double timeout) { return 0; } - int revents = EventWaiter(fd, events, timeout).revents; + EventWaiter waiter(fd, events, timeout); + if (waiter.error_) { + errno = swoole_get_last_error(); + return SW_ERR; + } + int revents = waiter.revents; if (revents & SW_EVENT_ERROR) { revents ^= SW_EVENT_ERROR; if (events & SW_EVENT_READ) { @@ -600,28 +601,27 @@ static void async_task_completed(AsyncEvent *event) { if (event->canceled) { return; } - AsyncTask *task = (AsyncTask *) event->object; - task->original_event->error = event->error; - task->original_event->ret = event->ret; - task->co->resume(); + Coroutine *co = (Coroutine *) event->object; + co->resume(); } static void async_task_timeout(Timer *timer, TimerNode *tnode) { AsyncEvent *event = (AsyncEvent *) tnode->data; event->canceled = 1; - AsyncTask *task = (AsyncTask *) event->object; - task->original_event->error = SW_ERROR_AIO_TIMEOUT; - task->co->resume(); + event->retval = -1; + event->error = SW_ERROR_AIO_TIMEOUT; + Coroutine *co = (Coroutine *) event->object; + co->resume(); } +/** + * @error: swoole_get_last_error() + */ bool async(async::Handler handler, AsyncEvent &event, double timeout) { - AsyncTask task; TimerNode *timer = nullptr; + Coroutine *co = Coroutine::get_current_safe(); - task.co = Coroutine::get_current_safe(); - task.original_event = &event; - - event.object = (void *) &task; + event.object = co; event.handler = handler; event.callback = async_task_completed; @@ -632,15 +632,30 @@ bool async(async::Handler handler, AsyncEvent &event, double timeout) { if (timeout > 0) { timer = swoole_timer_add((long) (timeout * 1000), false, async_task_timeout, _ev); } - task.co->yield(); - if (event.error == SW_ERROR_AIO_TIMEOUT) { - return false; - } else { - if (timer) { - swoole_timer_del(timer); - } + + Coroutine::CancelFunc cancel_fn = [_ev](Coroutine *co) { + _ev->canceled = true; + _ev->error = SW_ERROR_AIO_CANCELED; + _ev->retval = -1; + co->resume(); return true; + }; + co->yield(&cancel_fn); + + event.canceled = _ev->canceled; + event.error = _ev->error; + event.retval = _ev->retval; + + errno = _ev->error; + swoole_set_last_error(_ev->error); + + if (event.catch_error()) { + return false; } + if (timer) { + swoole_timer_del(timer); + } + return true; } struct AsyncLambdaTask { @@ -652,7 +667,7 @@ static void async_lambda_handler(AsyncEvent *event) { AsyncLambdaTask *task = reinterpret_cast(event->object); task->fn(); event->error = errno; - event->ret = 0; + event->retval = 0; } static void async_lambda_callback(AsyncEvent *event) { @@ -679,17 +694,25 @@ bool async(const std::function &fn, double timeout) { if (timeout > 0) { timer = swoole_timer_add((long) (timeout * 1000), false, async_task_timeout, _ev); } - task.co->yield(); + + Coroutine::CancelFunc cancel_fn = [_ev](Coroutine *co) { + _ev->canceled = true; + _ev->error = SW_ERROR_AIO_CANCELED; + _ev->retval = -1; + co->resume(); + return true; + }; + task.co->yield(&cancel_fn); + errno = _ev->error; swoole_set_last_error(_ev->error); - if (_ev->error == SW_ERROR_AIO_TIMEOUT) { + if (_ev->catch_error()) { return false; - } else { - if (timer) { - swoole_timer_del(timer); - } - return true; } + if (timer) { + swoole_timer_del(timer); + } + return true; } } // namespace coroutine diff --git a/src/coroutine/thread_context.cc b/src/coroutine/thread_context.cc index 5af1d46ea47..ec5e0ed7382 100644 --- a/src/coroutine/thread_context.cc +++ b/src/coroutine/thread_context.cc @@ -56,7 +56,7 @@ void thread_context_clean() { g_lock.unlock(); } -Context::Context(size_t stack_size, const coroutine_func_t &fn, void *private_data) +Context::Context(size_t stack_size, const CoroutineFunc &fn, void *private_data) : fn_(fn), private_data_(private_data) { end_ = false; lock_.lock(); diff --git a/src/os/async_thread.cc b/src/os/async_thread.cc index f254aed96a3..ecd4d236a30 100644 --- a/src/os/async_thread.cc +++ b/src/os/async_thread.cc @@ -243,18 +243,18 @@ void ThreadPool::create_thread(const bool is_core_worker) { if (event) { if (sw_unlikely(event->handler == nullptr)) { event->error = SW_ERROR_AIO_BAD_REQUEST; - event->ret = -1; + event->retval = -1; } else if (sw_unlikely(event->canceled)) { event->error = SW_ERROR_AIO_CANCELED; - event->ret = -1; + event->retval = -1; } else { event->handler(event); } swTraceLog(SW_TRACE_AIO, "aio_thread %s. ret=%d, error=%d", - event->ret > 0 ? "ok" : "failed", - event->ret, + event->retval > 0 ? "ok" : "failed", + event->retval, event->error); _send_event: diff --git a/src/os/base.cc b/src/os/base.cc index 49f97bf57c1..ed237cf367c 100644 --- a/src/os/base.cc +++ b/src/os/base.cc @@ -85,7 +85,7 @@ namespace async { void handler_gethostbyname(AsyncEvent *event) { char addr[SW_IP_MAX_LENGTH]; - int ret = swoole::network::gethostbyname(event->flags, (char *) event->buf, addr); + int ret = network::gethostbyname(event->flags, (char *) event->buf, addr); sw_memset_zero(event->buf, event->nbytes); if (ret < 0) { @@ -99,12 +99,12 @@ void handler_gethostbyname(AsyncEvent *event) { ret = 0; } } - event->ret = ret; + event->retval = ret; } void handler_getaddrinfo(AsyncEvent *event) { - swoole::network::GetaddrinfoRequest *req = (swoole::network::GetaddrinfoRequest *) event->req; - event->ret = swoole::network::getaddrinfo(req); + network::GetaddrinfoRequest *req = (network::GetaddrinfoRequest *) event->req; + event->retval = network::getaddrinfo(req); event->error = req->error; } diff --git a/src/os/wait.cc b/src/os/wait.cc index d5db51d5e07..f3b86b5cf8e 100644 --- a/src/os/wait.cc +++ b/src/os/wait.cc @@ -93,6 +93,9 @@ pid_t System::wait(int *__stat_loc, double timeout) { return System::waitpid(-1, __stat_loc, 0, timeout); } +/** + * @error: errno & swoole_get_last_error() + */ pid_t System::waitpid(pid_t __pid, int *__stat_loc, int __options, double timeout) { if (__pid < 0) { if (!child_processes.empty()) { @@ -148,7 +151,14 @@ pid_t System::waitpid(pid_t __pid, int *__stat_loc, int __options, double timeou task.co); } - task.co->yield(); + Coroutine::CancelFunc cancel_fn = [timer](Coroutine *co) { + if (timer) { + swoole_timer_del(timer); + } + co->resume(); + return true; + }; + task.co->yield(&cancel_fn); /* dequeue */ if (__pid < 0) { @@ -169,7 +179,8 @@ pid_t System::waitpid(pid_t __pid, int *__stat_loc, int __options, double timeou } *__stat_loc = task.status; } else { - errno = ETIMEDOUT; + swoole_set_last_error(task.co->is_canceled() ? SW_ERROR_CO_CANCELED : ETIMEDOUT); + errno = swoole_get_last_error(); } return task.pid; diff --git a/tests/swoole_coroutine/cancel/error.phpt b/tests/swoole_coroutine/cancel/error.phpt new file mode 100644 index 00000000000..6ad96775168 --- /dev/null +++ b/tests/swoole_coroutine/cancel/error.phpt @@ -0,0 +1,23 @@ +--TEST-- +swoole_coroutine/cancel: error +--SKIPIF-- + +--FILE-- + +--EXPECT-- diff --git a/tests/swoole_coroutine/cancel/gethostbyname.phpt b/tests/swoole_coroutine/cancel/gethostbyname.phpt new file mode 100644 index 00000000000..d438050e719 --- /dev/null +++ b/tests/swoole_coroutine/cancel/gethostbyname.phpt @@ -0,0 +1,28 @@ +--TEST-- +swoole_coroutine/cancel: gethostbyname +--SKIPIF-- + +--FILE-- + +--EXPECT-- +Done diff --git a/tests/swoole_coroutine/cancel/sleep.phpt b/tests/swoole_coroutine/cancel/sleep.phpt new file mode 100644 index 00000000000..e7fa72dd1a9 --- /dev/null +++ b/tests/swoole_coroutine/cancel/sleep.phpt @@ -0,0 +1,30 @@ +--TEST-- +swoole_coroutine/cancel: sleep +--SKIPIF-- + +--FILE-- + +--EXPECT-- +Done diff --git a/tests/swoole_coroutine/cancel/socket.phpt b/tests/swoole_coroutine/cancel/socket.phpt new file mode 100644 index 00000000000..0d365b735aa --- /dev/null +++ b/tests/swoole_coroutine/cancel/socket.phpt @@ -0,0 +1,34 @@ +--TEST-- +swoole_coroutine/cancel: socket +--SKIPIF-- + +--FILE-- +bind('127.0.0.1', 9601); + // server + $cid = go(function () use ($socket) { + while (true) { + $peer = null; + $data = $socket->recvfrom($peer); + Assert::assert(empty($data)); + Assert::assert($socket->errCode == SOCKET_ECANCELED); + break; + } + echo "DONE\n"; + }); + + // client + co::sleep(0.1); + Assert::true(Coroutine::cancel($cid)); +}); +?> +--EXPECT-- +DONE diff --git a/tests/swoole_coroutine/cancel/suspend.phpt b/tests/swoole_coroutine/cancel/suspend.phpt new file mode 100644 index 00000000000..2f4945c7f59 --- /dev/null +++ b/tests/swoole_coroutine/cancel/suspend.phpt @@ -0,0 +1,28 @@ +--TEST-- +swoole_coroutine/cancel: suspend +--SKIPIF-- + +--FILE-- + +--EXPECT-- +Done diff --git a/tests/swoole_coroutine/cancel/wait.phpt b/tests/swoole_coroutine/cancel/wait.phpt new file mode 100644 index 00000000000..a847f978e4c --- /dev/null +++ b/tests/swoole_coroutine/cancel/wait.phpt @@ -0,0 +1,28 @@ +--TEST-- +swoole_coroutine/cancel: wait/waitpid +--SKIPIF-- + +--FILE-- + +--EXPECT-- +Done diff --git a/tests/swoole_coroutine/cancel/wait_event.phpt b/tests/swoole_coroutine/cancel/wait_event.phpt new file mode 100644 index 00000000000..ee412b62bad --- /dev/null +++ b/tests/swoole_coroutine/cancel/wait_event.phpt @@ -0,0 +1,32 @@ +--TEST-- +swoole_coroutine/cancel: waitEvent +--SKIPIF-- + +--FILE-- + +--EXPECT-- +Done diff --git a/tests/swoole_coroutine/cancel/wait_signal.phpt b/tests/swoole_coroutine/cancel/wait_signal.phpt new file mode 100644 index 00000000000..7631e30df42 --- /dev/null +++ b/tests/swoole_coroutine/cancel/wait_signal.phpt @@ -0,0 +1,28 @@ +--TEST-- +swoole_coroutine/cancel: waitSignal +--SKIPIF-- + +--FILE-- + +--EXPECT-- +Done From f1b1db698eefdfb792b80493e11087445051565e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Sat, 5 Jun 2021 16:16:39 +0800 Subject: [PATCH 157/936] Support cancel channel and curl operation (#4249) * Support cancel channel/curl * fix tests * fix tests * optimize code, fix curl_error * add core tests --- core-tests/src/coroutine/base.cpp | 21 ++++ ext-src/php_swoole.cc | 1 + ext-src/php_swoole_curl.h | 5 +- ext-src/swoole_channel_coro.cc | 32 +++---- ext-src/swoole_curl.cc | 79 +++++++++------ include/swoole_coroutine.h | 35 ++++--- include/swoole_coroutine_channel.h | 12 +++ include/swoole_coroutine_socket.h | 2 + include/swoole_error.h | 1 + include/swoole_socket.h | 3 +- src/core/error.cc | 2 + src/coroutine/base.cc | 43 ++++++++- src/coroutine/channel.cc | 35 ++++++- src/coroutine/socket.cc | 11 +-- tests/include/lib/src/ProcessManager.php | 15 ++- .../swoole_coroutine/cancel/channel_pop.phpt | 29 ++++++ .../swoole_coroutine/cancel/channel_push.phpt | 35 +++++++ tests/swoole_curl/cancel.phpt | 68 +++++++++++++ tests/swoole_curl/error.phpt | 2 +- tests/swoole_curl/select_cancel.phpt | 96 +++++++++++++++++++ tests/swoole_curl/select_timeout.phpt | 93 ++++++++++++++++++ thirdparty/php/curl/interface.cc | 6 +- thirdparty/php/curl/multi.cc | 2 +- 23 files changed, 545 insertions(+), 83 deletions(-) create mode 100644 tests/swoole_coroutine/cancel/channel_pop.phpt create mode 100644 tests/swoole_coroutine/cancel/channel_push.phpt create mode 100644 tests/swoole_curl/cancel.phpt create mode 100644 tests/swoole_curl/select_cancel.phpt create mode 100644 tests/swoole_curl/select_timeout.phpt diff --git a/core-tests/src/coroutine/base.cpp b/core-tests/src/coroutine/base.cpp index 750f87f0775..0a30d3ead15 100644 --- a/core-tests/src/coroutine/base.cpp +++ b/core-tests/src/coroutine/base.cpp @@ -1,6 +1,7 @@ #include "test_coroutine.h" using namespace swoole; +using swoole::coroutine::System; TEST(coroutine_base, create) { long _cid; @@ -178,3 +179,23 @@ TEST(coroutine_base, run) { }); ASSERT_GE(cid, 1); } + +TEST(coroutine_base, cancel) { + coroutine::run([](void *arg) { + auto co = Coroutine::get_current_safe(); + Coroutine::create([co](void *){ + System::sleep(0.002); + co->cancel(); + }); + ASSERT_EQ(co->yield_ex(-1), false); + ASSERT_EQ(co->is_canceled(), true); + }); +} + +TEST(coroutine_base, timeout) { + coroutine::run([](void *arg) { + auto co = Coroutine::get_current_safe(); + ASSERT_EQ(co->yield_ex(0.005), false); + ASSERT_EQ(co->is_timedout(), true); + }); +} diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index 5e609164555..8c4a3166659 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -660,6 +660,7 @@ PHP_MINIT_FUNCTION(swoole) { SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_CO_CANNOT_CANCEL", SW_ERROR_CO_CANNOT_CANCEL); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_CO_NOT_EXISTS", SW_ERROR_CO_NOT_EXISTS); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_CO_CANCELED", SW_ERROR_CO_CANCELED); + SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_CO_TIMEDOUT", SW_ERROR_CO_TIMEDOUT); /** * trace log diff --git a/ext-src/php_swoole_curl.h b/ext-src/php_swoole_curl.h index 35cae943b0c..5f159b50632 100644 --- a/ext-src/php_swoole_curl.h +++ b/ext-src/php_swoole_curl.h @@ -46,17 +46,18 @@ struct Handle { struct Selector { bool defer_callback = false; + bool timer_callback = false; std::set active_handles; }; class Multi { CURLM *multi_handle_; TimerNode *timer = nullptr; - bool timedout = false; long timeout_ms_ = 0; Coroutine *co = nullptr; int running_handles_ = 0; int last_sockfd; + int event_count_ = 0; std::unique_ptr selector; CURLcode read_info(); @@ -144,7 +145,7 @@ class Multi { } CURLcode exec(php_curl *ch); - long select(php_curlm *mh); + long select(php_curlm *mh, double timeout = -1); void callback(Handle *handle, int event_bitmask); static int cb_readable(Reactor *reactor, Event *event); diff --git a/ext-src/swoole_channel_coro.cc b/ext-src/swoole_channel_coro.cc index 707f87f32b4..8c5ebee4c2b 100644 --- a/ext-src/swoole_channel_coro.cc +++ b/ext-src/swoole_channel_coro.cc @@ -73,12 +73,6 @@ static const zend_function_entry swoole_channel_coro_methods[] = }; // clang-format on -enum swChannelErrorCode { - SW_CHANNEL_OK = 0, - SW_CHANNEL_TIMEOUT = -1, - SW_CHANNEL_CLOSED = -2, -}; - static sw_inline ChannelObject *php_swoole_channel_coro_fetch_object(zend_object *obj) { return (ChannelObject *) ((char *) obj - swoole_channel_coro_handlers.offset); } @@ -142,9 +136,10 @@ void php_swoole_channel_coro_minit(int module_number) { zend_declare_property_long(swoole_channel_coro_ce, ZEND_STRL("capacity"), 0, ZEND_ACC_PUBLIC); zend_declare_property_long(swoole_channel_coro_ce, ZEND_STRL("errCode"), 0, ZEND_ACC_PUBLIC); - SW_REGISTER_LONG_CONSTANT("SWOOLE_CHANNEL_OK", SW_CHANNEL_OK); - SW_REGISTER_LONG_CONSTANT("SWOOLE_CHANNEL_TIMEOUT", SW_CHANNEL_TIMEOUT); - SW_REGISTER_LONG_CONSTANT("SWOOLE_CHANNEL_CLOSED", SW_CHANNEL_CLOSED); + SW_REGISTER_LONG_CONSTANT("SWOOLE_CHANNEL_OK", Channel::ERROR_OK); + SW_REGISTER_LONG_CONSTANT("SWOOLE_CHANNEL_TIMEOUT", Channel::ERROR_TIMEOUT); + SW_REGISTER_LONG_CONSTANT("SWOOLE_CHANNEL_CLOSED", Channel::ERROR_CLOSED); + SW_REGISTER_LONG_CONSTANT("SWOOLE_CHANNEL_CANCELED", Channel::ERROR_CANCELED); } static PHP_METHOD(swoole_channel_coro, __construct) { @@ -178,13 +173,12 @@ static PHP_METHOD(swoole_channel_coro, push) { Z_TRY_ADDREF_P(zdata); zdata = sw_zval_dup(zdata); if (chan->push(zdata, timeout)) { - zend_update_property_long(swoole_channel_coro_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errCode"), SW_CHANNEL_OK); + zend_update_property_long( + swoole_channel_coro_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errCode"), Channel::ERROR_OK); RETURN_TRUE; } else { - zend_update_property_long(swoole_channel_coro_ce, - SW_Z8_OBJ_P(ZEND_THIS), - ZEND_STRL("errCode"), - chan->is_closed() ? SW_CHANNEL_CLOSED : SW_CHANNEL_TIMEOUT); + zend_update_property_long( + swoole_channel_coro_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errCode"), chan->get_error()); Z_TRY_DELREF_P(zdata); efree(zdata); RETURN_FALSE; @@ -204,12 +198,11 @@ static PHP_METHOD(swoole_channel_coro, pop) { if (zdata) { RETVAL_ZVAL(zdata, 0, 0); efree(zdata); - zend_update_property_long(swoole_channel_coro_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errCode"), SW_CHANNEL_OK); + zend_update_property_long( + swoole_channel_coro_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errCode"), Channel::ERROR_OK); } else { - zend_update_property_long(swoole_channel_coro_ce, - SW_Z8_OBJ_P(ZEND_THIS), - ZEND_STRL("errCode"), - chan->is_closed() ? SW_CHANNEL_CLOSED : SW_CHANNEL_TIMEOUT); + zend_update_property_long( + swoole_channel_coro_ce, SW_Z8_OBJ_P(ZEND_THIS), ZEND_STRL("errCode"), chan->get_error()); RETURN_FALSE; } } @@ -241,4 +234,3 @@ static PHP_METHOD(swoole_channel_coro, stats) { add_assoc_long_ex(return_value, ZEND_STRL("producer_num"), chan->producer_num()); add_assoc_long_ex(return_value, ZEND_STRL("queue_num"), chan->length()); } - diff --git a/ext-src/swoole_curl.cc b/ext-src/swoole_curl.cc index cbc201652c5..2b4da3ca74b 100644 --- a/ext-src/swoole_curl.cc +++ b/ext-src/swoole_curl.cc @@ -84,8 +84,8 @@ Socket *Multi::create_socket(CURL *cp, curl_socket_t sockfd) { void Multi::del_event(CURL *cp, void *socket_ptr, curl_socket_t sockfd) { Socket *socket = (Socket *) socket_ptr; socket->silent_remove = 1; - if (socket->events && swoole_event_is_available()) { - swoole_event_del(socket); + if (socket->events && swoole_event_is_available() && swoole_event_del(socket) == SW_OK) { + event_count_--; } socket->fd = -1; socket->free(); @@ -111,12 +111,15 @@ void Multi::set_event(CURL *cp, void *socket_ptr, curl_socket_t sockfd, int acti if (socket->events) { swoole_event_set(socket, events); } else { - swoole_event_add(socket, events); + if (swoole_event_add(socket, events) == SW_OK) { + event_count_++; + } } Handle *handle = get_handle(cp); handle->action = action; - swTraceLog(SW_TRACE_CO_CURL, SW_ECHO_GREEN " handle=%p, curl=%p, fd=%d, events=%d", "[ADD]", handle, cp, sockfd, events); + swTraceLog( + SW_TRACE_CO_CURL, SW_ECHO_GREEN " handle=%p, curl=%p, fd=%d, events=%d", "[ADD]", handle, cp, sockfd, events); } CURLMcode Multi::add_handle(CURL *cp) { @@ -156,14 +159,23 @@ CURLcode Multi::exec(php_curl *ch) { Handle *handle = get_handle(ch->cp); + Coroutine::CancelFunc cancel_fn = [](Coroutine *co) { + co->resume(); + return true; + }; + SW_LOOP { - co->yield(); + co->yield(&cancel_fn); + if (co->is_canceled()) { + swoole_set_last_error(SW_ERROR_CO_CANCELED); + break; + } int sockfd = last_sockfd; int bitmask = 0; if (sockfd >= 0) { bitmask = handle->event_bitmask; - if (handle->socket && !handle->socket->removed) { - swoole_event_del(handle->socket); + if (handle->socket && !handle->socket->removed && swoole_event_del(handle->socket) == SW_OK) { + event_count_--; } } del_timer(); @@ -173,7 +185,9 @@ CURLcode Multi::exec(php_curl *ch) { } set_timer(); if (sockfd >= 0 && handle->socket && handle->socket->removed) { - swoole_event_add(handle->socket, get_event(handle->action)); + if (swoole_event_add(handle->socket, get_event(handle->action)) == SW_OK) { + event_count_++; + } } if (!timer && handle->socket->removed) { break; @@ -182,7 +196,7 @@ CURLcode Multi::exec(php_curl *ch) { CURLcode retval = read_info(); remove_handle(ch->cp); - return retval; + return co->is_canceled() ? CURLE_ABORTED_BY_CALLBACK : retval; } CURLcode Multi::read_info() { @@ -222,7 +236,7 @@ int Multi::handle_timeout(CURLM *mh, long timeout_ms, void *userp) { return 0; } -long Multi::select(php_curlm *mh) { +long Multi::select(php_curlm *mh, double timeout) { co = check_bound_co(); if (zend_llist_count(&mh->easyh) == 0) { return 0; @@ -231,7 +245,6 @@ long Multi::select(php_curlm *mh) { co = nullptr; }; - int event_count = 0; for (zend_llist_element *element = mh->easyh.head; element; element = element->next) { zval *z_ch = (zval *) element->data; php_curl *ch; @@ -241,7 +254,7 @@ long Multi::select(php_curlm *mh) { Handle *handle = get_handle(ch->cp); if (handle && handle->socket && handle->socket->removed) { if (swoole_event_add(handle->socket, get_event(handle->action)) == SW_OK) { - event_count++; + event_count_++; } swTraceLog(SW_TRACE_CO_CURL, "resume, handle=%p, curl=%p, fd=%d", handle, ch->cp, handle->socket->get_fd()); } @@ -249,10 +262,12 @@ long Multi::select(php_curlm *mh) { set_timer(); // no events and timers, should not be suspended - if (!timer && event_count == 0) { + if (!timer && event_count_ == 0) { return 0; } - co->yield(); + + co->yield_ex(timeout); + auto count = selector->active_handles.size(); for (zend_llist_element *element = mh->easyh.head; element; element = element->next) { @@ -262,30 +277,33 @@ long Multi::select(php_curlm *mh) { continue; } Handle *handle = get_handle(ch->cp); - if (handle && handle->socket && !handle->socket->removed) { - swTraceLog(SW_TRACE_CO_CURL, "suspend, handle=%p, curl=%p, fd=%d", handle, ch->cp, handle->socket->get_fd()); - swoole_event_del(handle->socket); + if (handle && handle->socket && !handle->socket->removed && swoole_event_del(handle->socket) == SW_OK) { + swTraceLog( + SW_TRACE_CO_CURL, "suspend, handle=%p, curl=%p, fd=%d", handle, ch->cp, handle->socket->get_fd()); + event_count_--; } } del_timer(); + if (selector->timer_callback) { + selector->timer_callback = false; + curl_multi_socket_action(multi_handle_, -1, 0, &running_handles_); + swTraceLog(SW_TRACE_CO_CURL, "socket_action[timer], running_handles=%d", running_handles_); + } + for (auto iter = selector->active_handles.begin(); iter != selector->active_handles.end(); iter++) { Handle *handle = *iter; - int bitmask = 0; - int sockfd = -1; - if (handle) { - bitmask = handle->event_bitmask; - sockfd = handle->event_fd; - } - curl_multi_socket_action(multi_handle_, sockfd, bitmask, &running_handles_); - swTraceLog(SW_TRACE_CO_CURL, "socket_action, running_handles=%d", running_handles_); + curl_multi_socket_action(multi_handle_, handle->event_fd, handle->event_bitmask, &running_handles_); + swTraceLog(SW_TRACE_CO_CURL, "socket_action[socket], running_handles=%d", running_handles_); } + selector->active_handles.clear(); return count; } void Multi::callback(Handle *handle, int event_bitmask) { + swTraceLog(SW_TRACE_CO_CURL, "callback, handle=%p, event_bitmask=%d", handle, event_bitmask); if (handle) { last_sockfd = handle->event_fd; } else { @@ -293,15 +311,22 @@ void Multi::callback(Handle *handle, int event_bitmask) { } // for curl_multi_select if (selector.get()) { + if (!handle) { + selector->timer_callback = true; + } if (!co) { if (handle) { - swoole_event_del(handle->socket); + if (swoole_event_del(handle->socket) == SW_OK) { + event_count_--; + } } else { del_timer(); } return; } - selector->active_handles.insert(handle); + if (handle) { + selector->active_handles.insert(handle); + } if (selector->defer_callback) { return; } diff --git a/include/swoole_coroutine.h b/include/swoole_coroutine.h index a8244eb115b..ccfc07ed5d8 100644 --- a/include/swoole_coroutine.h +++ b/include/swoole_coroutine.h @@ -35,13 +35,6 @@ namespace swoole { class Coroutine { public: - void resume(); - void yield(); - bool cancel(); - - void resume_naked(); - void yield_naked(); - constexpr static int STACK_ALIGNED_SIZE = (4 * 1024); constexpr static int MIN_STACK_SIZE = (64 * 1024); constexpr static int MAX_STACK_SIZE = (16 * 1024 * 1024); @@ -60,16 +53,24 @@ class Coroutine { ERR_INVALID = -2, }; + enum ResumeCode { + RC_OK = 0, + RC_TIMEDOUT = -1, + RC_CANCELED = -2, + }; + typedef void (*SwapCallback)(void *); typedef void (*BailoutCallback)(); typedef std::function CancelFunc; - void yield(CancelFunc *cancel_fn) { - set_cancel_fn(cancel_fn); - canceled_ = false; - yield(); - set_cancel_fn(nullptr); - } + void resume(); + void yield(); + void yield(CancelFunc *cancel_fn); + bool cancel(); + + void resume_naked(); + void yield_naked(); + bool yield_ex(double timeout = -1); inline enum State get_state() { return state; @@ -100,7 +101,11 @@ class Coroutine { } bool is_canceled() { - return canceled_; + return resume_code_ == RC_CANCELED; + } + + bool is_timedout() { + return resume_code_ == RC_TIMEDOUT; } inline void set_task(void *_task) { @@ -203,13 +208,13 @@ class Coroutine { static bool activated; enum State state = STATE_INIT; + enum ResumeCode resume_code_ = RC_OK; long cid; long init_msec = Timer::get_absolute_msec(); void *task = nullptr; coroutine::Context ctx; Coroutine *origin = nullptr; CancelFunc *cancel_fn_ = nullptr; - bool canceled_ = false; Coroutine(const CoroutineFunc &fn, void *private_data) : ctx(stack_size, fn, private_data) { cid = ++last_cid; diff --git a/include/swoole_coroutine_channel.h b/include/swoole_coroutine_channel.h index b5b85fc8c24..ec860867bae 100644 --- a/include/swoole_coroutine_channel.h +++ b/include/swoole_coroutine_channel.h @@ -37,6 +37,13 @@ class Channel { CONSUMER = 2, }; + enum ErrorCode { + ERROR_OK = 0, + ERROR_TIMEOUT = -1, + ERROR_CLOSED = -2, + ERROR_CANCELED = -3, + }; + struct TimeoutMessage { Channel *chan; enum opcode type; @@ -99,9 +106,14 @@ class Channel { return data; } + int get_error() { + return error_; + } + protected: size_t capacity = 1; bool closed = false; + int error_ = 0; std::list producer_queue; std::list consumer_queue; std::queue data_queue; diff --git a/include/swoole_coroutine_socket.h b/include/swoole_coroutine_socket.h index 5329c6fa7de..860179d6f25 100644 --- a/include/swoole_coroutine_socket.h +++ b/include/swoole_coroutine_socket.h @@ -17,7 +17,9 @@ #pragma once +#include "swoole.h" #include "swoole_api.h" +#include "swoole_socket.h" #include "swoole_coroutine.h" #include "swoole_protocol.h" #include "swoole_proxy.h" diff --git a/include/swoole_error.h b/include/swoole_error.h index 79cd50fa89a..d563b5264d3 100644 --- a/include/swoole_error.h +++ b/include/swoole_error.h @@ -170,6 +170,7 @@ enum swErrorCode { SW_ERROR_CO_CANNOT_CANCEL, SW_ERROR_CO_NOT_EXISTS, SW_ERROR_CO_CANCELED, + SW_ERROR_CO_TIMEDOUT, SW_ERROR_END }; diff --git a/include/swoole_socket.h b/include/swoole_socket.h index 71b6f619899..c50c7187ef1 100644 --- a/include/swoole_socket.h +++ b/include/swoole_socket.h @@ -17,8 +17,6 @@ #pragma once -#include "swoole.h" - #include #include #include @@ -31,6 +29,7 @@ #include #include +#include "swoole.h" #include "swoole_ssl.h" #include "swoole_buffer.h" #include "swoole_file.h" diff --git a/src/core/error.cc b/src/core/error.cc index 5d97f6c1290..70885dee8a5 100644 --- a/src/core/error.cc +++ b/src/core/error.cc @@ -221,6 +221,8 @@ const char *swoole_strerror(int code) { return "Coroutine not exists"; case SW_ERROR_CO_CANCELED: return "Coroutine canceled"; + case SW_ERROR_CO_TIMEDOUT: + return "Coroutine timedout"; default: static char buffer[32]; #ifndef __MACH__ diff --git a/src/coroutine/base.cc b/src/coroutine/base.cc index b02ab87a43e..a28197f46ea 100644 --- a/src/coroutine/base.cc +++ b/src/coroutine/base.cc @@ -35,7 +35,7 @@ Coroutine::BailoutCallback Coroutine::on_bailout = nullptr; namespace coroutine { void thread_context_init(); void thread_context_clean(); -} +} // namespace coroutine #endif void Coroutine::activate() { @@ -55,6 +55,7 @@ void Coroutine::deactivate() { void Coroutine::yield() { SW_ASSERT(current == this || on_bailout != nullptr); state = STATE_WAITING; + resume_code_ = RC_OK; if (sw_likely(on_yield && task)) { on_yield(task); } @@ -62,6 +63,44 @@ void Coroutine::yield() { ctx.swap_out(); } +void Coroutine::yield(CancelFunc *cancel_fn) { + set_cancel_fn(cancel_fn); + yield(); + set_cancel_fn(nullptr); +} + +bool Coroutine::yield_ex(double timeout) { + TimerNode *timer = nullptr; + TimerCallback timer_callback = [this](Timer *timer, TimerNode *tnode) { + resume_code_ = RC_TIMEDOUT; + resume(); + }; + + if (timeout > 0) { + timer = swoole_timer_add((long) (timeout * 1000), false, timer_callback, nullptr); + } + + CancelFunc cancel_fn = [](Coroutine *co) { + co->resume(); + return true; + }; + + yield(&cancel_fn); + + if (is_timedout()) { + swoole_set_last_error(SW_ERROR_CO_TIMEDOUT); + return false; + } + if (timer) { + swoole_timer_del(timer); + } + if (is_canceled()) { + swoole_set_last_error(SW_ERROR_CO_CANCELED); + return false; + } + return true; +} + void Coroutine::resume() { SW_ASSERT(current != this); if (sw_unlikely(on_bailout)) { @@ -103,7 +142,7 @@ bool Coroutine::cancel() { } auto fn = *cancel_fn_; set_cancel_fn(nullptr); - canceled_ = true; + resume_code_ = RC_CANCELED; return fn(this); } diff --git a/src/coroutine/channel.cc b/src/coroutine/channel.cc index 2317c12e465..83b69ae99ee 100644 --- a/src/coroutine/channel.cc +++ b/src/coroutine/channel.cc @@ -40,12 +40,22 @@ void Channel::yield(enum opcode type) { consumer_queue.push_back(co); swTraceLog(SW_TRACE_CHANNEL, "consumer cid=%ld", co->get_cid()); } - co->yield(); + Coroutine::CancelFunc cancel_fn = [this, type](Coroutine *co) { + if (type == CONSUMER) { + consumer_remove(co); + } else { + producer_remove(co); + } + co->resume(); + return true; + }; + co->yield(&cancel_fn); } void *Channel::pop(double timeout) { Coroutine *current_co = Coroutine::get_current_safe(); if (closed && is_empty()) { + error_ = ERROR_CLOSED; return nullptr; } if (is_empty() || !consumer_queue.empty()) { @@ -65,7 +75,16 @@ void *Channel::pop(double timeout) { if (msg.timer) { swoole_timer_del(msg.timer); } - if (msg.error || (closed && is_empty())) { + if (current_co->is_canceled()) { + error_ = ERROR_CANCELED; + return nullptr; + } + if (msg.error) { + error_ = ERROR_TIMEOUT; + return nullptr; + } + if (closed && is_empty()) { + error_ = ERROR_CLOSED; return nullptr; } } @@ -87,6 +106,7 @@ void *Channel::pop(double timeout) { bool Channel::push(void *data, double timeout) { Coroutine *current_co = Coroutine::get_current_safe(); if (closed) { + error_ = ERROR_CLOSED; return false; } if (is_full() || !producer_queue.empty()) { @@ -106,7 +126,16 @@ bool Channel::push(void *data, double timeout) { if (msg.timer) { swoole_timer_del(msg.timer); } - if (msg.error || closed) { + if (current_co->is_canceled()) { + error_ = ERROR_CANCELED; + return false; + } + if (msg.error) { + error_ = ERROR_TIMEOUT; + return false; + } + if (closed) { + error_ = ERROR_CLOSED; return false; } } diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index d04975c7778..a06f0022ab6 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -17,16 +17,15 @@ +----------------------------------------------------------------------+ */ -#include "swoole_coroutine_socket.h" - -#include - +#include "swoole_string.h" #include "swoole_util.h" -#include "swoole_socket.h" -#include "swoole_coroutine_system.h" +#include "swoole_reactor.h" #include "swoole_buffer.h" #include "swoole_base64.h" +#include "swoole_coroutine_socket.h" +#include "swoole_coroutine_system.h" + namespace swoole { namespace coroutine { diff --git a/tests/include/lib/src/ProcessManager.php b/tests/include/lib/src/ProcessManager.php index 6655b89aa83..cf301f201d9 100644 --- a/tests/include/lib/src/ProcessManager.php +++ b/tests/include/lib/src/ProcessManager.php @@ -31,6 +31,8 @@ class ProcessManager */ protected $atomic; protected $alone = false; + protected $onlyChild = false; + protected $onlyParent = false; protected $freePorts = []; protected $randomFunc = 'get_safe_random'; protected $randomData = [[]]; @@ -271,14 +273,23 @@ public function run($redirectStdout = false) $this->alone = true; $this->initFreePorts(); if ($argv[1] == 'child') { - return $this->runChildFunc(); + $this->onlyChild = true; } elseif ($argv[1] == 'parent') { - return $this->runParentFunc(); + $this->onlyParent = true; } else { throw new RuntimeException("bad parameter \$1\n"); } } $this->initFreePorts(); + if ($this->alone) { + if ($this->onlyChild) { + return $this->runChildFunc(); + } elseif ($this->onlyParent) { + return $this->runParentFunc(); + } + $this->alone = false; + } + $this->childProcess = new Process(function () { if ($this->parentFirst) { $this->wait(); diff --git a/tests/swoole_coroutine/cancel/channel_pop.phpt b/tests/swoole_coroutine/cancel/channel_pop.phpt new file mode 100644 index 00000000000..a5c539391ca --- /dev/null +++ b/tests/swoole_coroutine/cancel/channel_pop.phpt @@ -0,0 +1,29 @@ +--TEST-- +swoole_coroutine/cancel: pop from channel +--SKIPIF-- + +--FILE-- +pop(100), false); + Assert::assert(Coroutine::isCanceled()); + Assert::eq($chan->errCode, SWOOLE_CHANNEL_CANCELED); + echo "Done\n"; +}); + +?> +--EXPECT-- +Done diff --git a/tests/swoole_coroutine/cancel/channel_push.phpt b/tests/swoole_coroutine/cancel/channel_push.phpt new file mode 100644 index 00000000000..95b6d40b171 --- /dev/null +++ b/tests/swoole_coroutine/cancel/channel_push.phpt @@ -0,0 +1,35 @@ +--TEST-- +swoole_coroutine/cancel: push to channel +--SKIPIF-- + +--FILE-- +push("hello world [1]", 100)); + Assert::eq(Coroutine::isCanceled(), false); + Assert::eq($chan->errCode, SWOOLE_CHANNEL_OK); + + Assert::eq($chan->push("hello world [2]", 100), false); + Assert::eq(Coroutine::isCanceled(), true); + Assert::eq($chan->errCode, SWOOLE_CHANNEL_CANCELED); + + echo "Done\n"; +}); + +?> +--EXPECT-- +Done diff --git a/tests/swoole_curl/cancel.phpt b/tests/swoole_curl/cancel.phpt new file mode 100644 index 00000000000..1f8f998abae --- /dev/null +++ b/tests/swoole_curl/cancel.phpt @@ -0,0 +1,68 @@ +--TEST-- +swoole_curl: sleep +--SKIPIF-- + +--FILE-- +parentFunc = function () use ($pm) { + Runtime::enableCoroutine(SWOOLE_HOOK_NATIVE_CURL); + $s = microtime(true); + run(function () use ($pm) { + $ch = curl_init(); + $code = uniqid('swoole_'); + $url = "http://127.0.0.1:".$pm->getFreePort()."/?code=".urlencode($code); + + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HEADER, 0); + + $cid = Coroutine::getCid(); + go(function () use ($cid) { + System::sleep(0.01); + Assert::true(Coroutine::cancel($cid)); + Assert::false(Coroutine::isCanceled()); + }); + + $output = curl_exec($ch); + Assert::isEmpty($output); + Assert::eq(swoole_last_error(), SWOOLE_ERROR_CO_CANCELED); + Assert::eq(curl_errno($ch), CURLE_ABORTED_BY_CALLBACK); + Assert::contains(curl_error($ch), 'Operation was aborted by an application callback'); + curl_close($ch); + }); + Assert::lessThan(microtime(true) - $s, 0.5); + $pm->kill(); + echo "Done\n"; +}; +$pm->childFunc = function () use ($pm) { + $http = new Swoole\Http\Server("127.0.0.1", $pm->getFreePort()); + $http->set(['worker_num' => 1, 'log_file' => '/dev/null']); + + $http->on("start", function ($server) use ($pm) { + $pm->wakeup(); + }); + + $http->on("request", function (Request $request, Response $response) { + usleep(300000); + $response->end("Hello World\n".$request->get['code']); + }); + $http->start(); +}; +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +Done diff --git a/tests/swoole_curl/error.phpt b/tests/swoole_curl/error.phpt index 0a0cd277a95..d543910b3c6 100644 --- a/tests/swoole_curl/error.phpt +++ b/tests/swoole_curl/error.phpt @@ -29,7 +29,7 @@ run(function () { $output = curl_exec($ch); Assert::isEmpty($output); Assert::eq(curl_errno($ch), CURLE_COULDNT_CONNECT); - + Assert::contains(curl_error($ch), 'Connection refused'); $info = curl_getinfo($ch); Assert::isArray($info); Assert::eq($info['http_code'], 0); diff --git a/tests/swoole_curl/select_cancel.phpt b/tests/swoole_curl/select_cancel.phpt new file mode 100644 index 00000000000..c1b68883187 --- /dev/null +++ b/tests/swoole_curl/select_cancel.phpt @@ -0,0 +1,96 @@ +--TEST-- +swoole_curl: select twice +--SKIPIF-- + +--FILE-- +parentFunc = function () use ($pm) { + Runtime::enableCoroutine(SWOOLE_HOOK_NATIVE_CURL); + run(function () use ($pm) { + $mh = curl_multi_init(); + + $add_handle = function ($url) use($mh) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HEADER, 0); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_multi_add_handle($mh, $ch); + return $ch; + }; + + $ch1 = $add_handle("http://127.0.0.1:{$pm->getFreePort()}/"); + + $active = null; + + do { + $mrc = curl_multi_exec($mh, $active); + } while ($mrc == CURLM_CALL_MULTI_PERFORM); + + $now = microtime(true); + + $cid = Coroutine::getCid(); + go(function () use($cid) { + System::sleep(0.005); + Coroutine::cancel($cid); + }); + + while ($active && $mrc == CURLM_OK) { + $n = curl_multi_select($mh, TIMEOUT); + phpt_var_dump('return value:'.$n); + phpt_var_dump('swoole error:'.swoole_last_error()); + if ($n != -1) { + do { + $mrc = curl_multi_exec($mh, $active); + } while ($mrc == CURLM_CALL_MULTI_PERFORM); + } + if (Coroutine::isCanceled()) { + Assert::eq(swoole_last_error(), SWOOLE_ERROR_CO_CANCELED); + echo "CANCELED\n"; + break; + } + } + + Assert::eq(curl_multi_info_read($mh), false); + curl_multi_remove_handle($mh, $ch1); + curl_multi_close($mh); + }); + $pm->kill(); + echo "Done\n"; +}; +$pm->childFunc = function () use ($pm) { + $http = new Swoole\Http\Server("127.0.0.1", $pm->getFreePort()); + $http->set(['worker_num' => 1, 'log_file' => '/dev/null']); + $http->on("start", function ($server) use ($pm) { + $pm->wakeup(); + }); + $http->on("request", function (Request $request, Response $response) { + sleep(20000); + }); + $http->start(); +}; +$pm->childFirst(); +$pm->run(); +?> +--EXPECTF-- +CANCELED +Done diff --git a/tests/swoole_curl/select_timeout.phpt b/tests/swoole_curl/select_timeout.phpt new file mode 100644 index 00000000000..53136b1304f --- /dev/null +++ b/tests/swoole_curl/select_timeout.phpt @@ -0,0 +1,93 @@ +--TEST-- +swoole_curl: select timeout +--SKIPIF-- + +--FILE-- +parentFunc = function () use ($pm) { + Runtime::enableCoroutine(SWOOLE_HOOK_NATIVE_CURL); + run(function () use ($pm) { + $mh = curl_multi_init(); + + $add_handle = function ($url) use($mh) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HEADER, 0); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_multi_add_handle($mh, $ch); + return $ch; + }; + + $ch1 = $add_handle("http://127.0.0.1:{$pm->getFreePort()}/"); + + $active = null; + + do { + $mrc = curl_multi_exec($mh, $active); + } while ($mrc == CURLM_CALL_MULTI_PERFORM); + + $now = microtime(true); + + while ($active && $mrc == CURLM_OK) { + $tm = microtime(true); + $n = curl_multi_select($mh, TIMEOUT); + Assert::lessThan(microtime(true) - $tm, TIMEOUT + 0.01); + + $error = swoole_last_error(); + phpt_var_dump('select return value: '.$n); + phpt_var_dump('swoole error: '.$error); + if ($n != -1) { + do { + $mrc = curl_multi_exec($mh, $active); + phpt_var_dump('exec return value: '.$mrc); + } while ($mrc == CURLM_CALL_MULTI_PERFORM); + } + if (microtime(true) - $now >= TIMEOUT * 4) { + echo "TIMEOUT\n"; + break; + } + } + + Assert::eq(curl_multi_info_read($mh), false); + curl_multi_remove_handle($mh, $ch1); + curl_multi_close($mh); + }); + $pm->kill(); + echo "Done\n"; +}; +$pm->childFunc = function () use ($pm) { + $http = new Swoole\Http\Server("127.0.0.1", $pm->getFreePort()); + $http->set(['worker_num' => 1, 'log_file' => '/dev/null', 'max_wait_time' => 1,]); + $http->on("start", function ($server) use ($pm) { + $pm->wakeup(); + }); + $http->on("request", function (Request $request, Response $response) { + sleep(20000); + }); + $http->start(); +}; +$pm->childFirst(); +$pm->run(); +?> +--EXPECTF-- +TIMEOUT +Done diff --git a/thirdparty/php/curl/interface.cc b/thirdparty/php/curl/interface.cc index caaa1293602..e255ab68248 100644 --- a/thirdparty/php/curl/interface.cc +++ b/thirdparty/php/curl/interface.cc @@ -444,8 +444,7 @@ int curl_cast_object(zend_object *obj, zval *result, int type) { } #endif -void swoole_native_curl_mshutdown() { -} +void swoole_native_curl_mshutdown() {} /* {{{ curl_write_nothing * Used as a work around. See _php_curl_close_ex @@ -2636,6 +2635,9 @@ PHP_FUNCTION(swoole_native_curl_error) { if (ch->err.no) { ch->err.str[CURL_ERROR_SIZE] = 0; + if (strlen(ch->err.str) == 0) { + RETURN_STRING(curl_easy_strerror((CURLcode) ch->err.no)); + } RETURN_STRING(ch->err.str); } else { RETURN_EMPTY_STRING(); diff --git a/thirdparty/php/curl/multi.cc b/thirdparty/php/curl/multi.cc index eb182b5770c..b5ffb1d8464 100644 --- a/thirdparty/php/curl/multi.cc +++ b/thirdparty/php/curl/multi.cc @@ -202,7 +202,7 @@ PHP_FUNCTION(swoole_native_curl_multi_select) { ZEND_PARSE_PARAMETERS_END(); mh = Z_CURL_MULTI_P(z_mh); - RETURN_LONG(mh->multi->select(mh)); + RETURN_LONG(mh->multi->select(mh, timeout)); } /* }}} */ From 8323445c801a77b833142bf82e1214d9116c5489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Tue, 8 Jun 2021 11:31:22 +0800 Subject: [PATCH 158/936] Fix EVENT_HANDSHAKE BC and Fix typo (#4248) --- src/network/dns.cc | 2 +- tools/constant-generator.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/network/dns.cc b/src/network/dns.cc index faf4350caf7..afb9828c714 100644 --- a/src/network/dns.cc +++ b/src/network/dns.cc @@ -30,7 +30,7 @@ enum swDNS_type { }; enum swDNS_error { - SW_DNS_NOT_EXIST, // Error: adress does not exist + SW_DNS_NOT_EXIST, // Error: address does not exist SW_DNS_TIMEOUT, // Lookup time expired SW_DNS_ERROR // No memory or other error }; diff --git a/tools/constant-generator.php b/tools/constant-generator.php index 05de99ff90c..1eb9602931b 100755 --- a/tools/constant-generator.php +++ b/tools/constant-generator.php @@ -40,6 +40,9 @@ $event_result = ''; foreach ($server_events as $event) { + if ($event === 'HandShake') { + $event = 'handshake'; + } $event_result .= space(4) . sprintf("public const EVENT_%s = '%s';\n\n", strtoupper(unCamelize($event)), lcfirst($event)); } From 2609899370fa95a67fc1c0254d8820d4f9609f95 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 8 Jun 2021 14:08:37 +0800 Subject: [PATCH 159/936] optimize code --- ext-src/swoole_curl.cc | 7 +------ src/server/reactor_thread.cc | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/ext-src/swoole_curl.cc b/ext-src/swoole_curl.cc index 2b4da3ca74b..dc115295b37 100644 --- a/ext-src/swoole_curl.cc +++ b/ext-src/swoole_curl.cc @@ -159,13 +159,8 @@ CURLcode Multi::exec(php_curl *ch) { Handle *handle = get_handle(ch->cp); - Coroutine::CancelFunc cancel_fn = [](Coroutine *co) { - co->resume(); - return true; - }; - SW_LOOP { - co->yield(&cancel_fn); + co->yield_ex(-1); if (co->is_canceled()) { swoole_set_last_error(SW_ERROR_CO_CANCELED); break; diff --git a/src/server/reactor_thread.cc b/src/server/reactor_thread.cc index 0ea0e3ff442..042391bc6d9 100644 --- a/src/server/reactor_thread.cc +++ b/src/server/reactor_thread.cc @@ -416,7 +416,7 @@ static int ReactorThread_onPipeRead(Reactor *reactor, Event *ev) { SW_ERROR_SESSION_NOT_EXIST, "force close connection failed, session#%ld does not exist", session_id); - return SW_ERR; + return SW_OK; } if (serv->disable_notify || conn->close_force) { From 5fdb4e0a3065ea9101545efc85d1dde1bd61292c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Fri, 25 Jun 2021 12:53:08 +0800 Subject: [PATCH 160/936] Support c-ares, Refactor DNS (#4275) * add core tests * fix * optimize * optimize [2] * optimize [3] * optimize [4] * optimize [5] * Refactor * Refactor [2] * Refactor [3] * fix * fix core tests * fix tests * fix core tests --- CMakeLists.txt | 17 +- config.m4 | 13 +- core-tests/src/coroutine/gethostbyname.cpp | 7 + core-tests/src/coroutine/system.cpp | 2 +- core-tests/src/network/dns.cpp | 43 ++- core-tests/src/os/process_pool.cpp | 8 +- examples/http/server.php | 4 + ext-src/php_swoole.cc | 13 +- ext-src/php_swoole_coroutine_system.h | 1 + ext-src/php_swoole_mysql_proto.h | 4 +- ext-src/php_swoole_private.h | 6 + ext-src/swoole_async_coro.cc | 5 +- ext-src/swoole_http_response.cc | 10 +- ext-src/swoole_mysql_coro.cc | 78 ++--- ext-src/swoole_mysql_proto.cc | 6 +- ext-src/swoole_server.cc | 2 +- include/swoole.h | 16 +- include/swoole_config.h | 1 + include/swoole_coroutine.h | 14 +- include/swoole_coroutine_socket.h | 6 +- include/swoole_coroutine_system.h | 1 + include/swoole_error.h | 8 +- include/swoole_log.h | 3 +- make.sh | 2 +- src/core/base.cc | 34 +++ src/core/string.cc | 2 +- src/core/timer.cc | 8 +- src/coroutine/system.cc | 61 ++-- src/network/dns.cc | 289 +++++++++++++++--- src/os/async_thread.cc | 2 +- src/protocol/websocket.cc | 2 +- src/server/base.cc | 2 +- tests/swoole_coroutine/dnslookup_1.phpt | 8 +- tests/swoole_coroutine/dnslookup_2.phpt | 8 +- tests/swoole_coroutine/dnslookup_3.phpt | 1 - tests/swoole_coroutine/dnslookup_4.phpt | 19 ++ tests/swoole_coroutine/dnslookup_ipv6.phpt | 19 ++ tests/swoole_http_client_coro/get_twice.phpt | 4 +- .../get_twice_keepalive.phpt | 4 +- tests/swoole_server/unregistered_signal.phpt | 2 +- 40 files changed, 566 insertions(+), 169 deletions(-) create mode 100644 tests/swoole_coroutine/dnslookup_4.phpt create mode 100644 tests/swoole_coroutine/dnslookup_ipv6.phpt diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d3ddb3fc96..0ec60ecfcbf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,13 +6,17 @@ set(SWOOLE_VERSION 4.7.0-dev) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +cmake_minimum_required(VERSION 2.8) + +file(READ ./config.h SWOOLE_CONFIG_FILE) set(CMAKE_MACOSX_RPATH 1) set(SWOOLE_LINK_LIBRARIES pthread dl) if (APPLE) set(CMAKE_SHARED_LINKER_FLAGS "-undefined dynamic_lookup") + include_directories(BEFORE /usr/local/include) + link_directories(BEFORE /usr/local/lib) else() list(APPEND SWOOLE_LINK_LIBRARIES rt crypt) endif() @@ -82,6 +86,17 @@ if (DEFINED brotli_dir) link_directories(${brotli_dir}/lib) endif() +foreach (LINE ${SWOOLE_CONFIG_FILE}) + if ("${LINE}" MATCHES "define SW_USE_CARES 1") + message(STATUS "enable c-ares") + list(APPEND SWOOLE_LINK_LIBRARIES cares) + endif() +endforeach() + +if (DEFINED enable_trace_log) + add_definitions(-DSW_LOG_TRACE_OPEN) +endif() + execute_process(COMMAND php-config --includes OUTPUT_VARIABLE PHP_INCLUDES OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND php-config --extension-dir OUTPUT_VARIABLE PHP_EXTENSION_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PHP_INCLUDES}") diff --git a/config.m4 b/config.m4 index 6904f53a075..cb7e639089f 100644 --- a/config.m4 +++ b/config.m4 @@ -50,6 +50,11 @@ PHP_ARG_ENABLE([mysqlnd], [enable mysqlnd support], [AS_HELP_STRING([--enable-mysqlnd], [Enable mysqlnd])], [no], [no]) + +PHP_ARG_ENABLE([cares], + [enable c-ares support], + [AS_HELP_STRING([--enable-cares], + [Enable cares])], [no], [no]) PHP_ARG_WITH([openssl_dir], [dir of openssl], @@ -354,7 +359,8 @@ if test "$PHP_SWOOLE" != "no"; then AC_CHECK_LIB(pthread, pthread_mutexattr_setrobust, AC_DEFINE(HAVE_PTHREAD_MUTEXATTR_SETROBUST, 1, [have pthread_mutexattr_setrobust])) AC_CHECK_LIB(pthread, pthread_mutex_consistent, AC_DEFINE(HAVE_PTHREAD_MUTEX_CONSISTENT, 1, [have pthread_mutex_consistent])) AC_CHECK_LIB(pcre, pcre_compile, AC_DEFINE(HAVE_PCRE, 1, [have pcre])) - + AC_CHECK_LIB(cares, ares_gethostbyname, AC_DEFINE(HAVE_CARES, 1, [have c-ares])) + if test "$PHP_SWOOLE_DEV" = "yes"; then AX_CHECK_COMPILE_FLAG(-Wbool-conversion, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wbool-conversion") AX_CHECK_COMPILE_FLAG(-Wignored-qualifiers, _MAINTAINER_CFLAGS="$_MAINTAINER_CFLAGS -Wignored-qualifiers") @@ -457,6 +463,11 @@ if test "$PHP_SWOOLE" != "no"; then if test "$PHP_THREAD" = "yes"; then AC_DEFINE(SW_USE_THREAD, 1, [enable thread support]) fi + + if test "$PHP_CARES" = "yes"; then + AC_DEFINE(SW_USE_CARES, 1, [do we enable c-ares support]) + PHP_ADD_LIBRARY(cares, 1, SWOOLE_SHARED_LIBADD) + fi AC_SWOOLE_CPU_AFFINITY AC_SWOOLE_HAVE_REUSEPORT diff --git a/core-tests/src/coroutine/gethostbyname.cpp b/core-tests/src/coroutine/gethostbyname.cpp index 26f2f59cf5a..02a009c4103 100644 --- a/core-tests/src/coroutine/gethostbyname.cpp +++ b/core-tests/src/coroutine/gethostbyname.cpp @@ -29,6 +29,13 @@ TEST(coroutine_gethostbyname, resolve_cache) { }); } +TEST(coroutine_gethostbyname, impl_async) { + coroutine::run([](void *arg) { + auto result = swoole::coroutine::gethostbyname_impl_with_async("www.baidu.com", AF_INET); + ASSERT_EQ(result.empty(), false); + }); +} + TEST(coroutine_gethostbyname, resolve_cache_inet4_and_inet6) { coroutine::run([](void *arg) { System::set_dns_cache_capacity(10); diff --git a/core-tests/src/coroutine/system.cpp b/core-tests/src/coroutine/system.cpp index 4499b65112e..179718f9743 100644 --- a/core-tests/src/coroutine/system.cpp +++ b/core-tests/src/coroutine/system.cpp @@ -82,7 +82,7 @@ TEST(coroutine_system, flock) { } TEST(coroutine_system, cancel_sleep) { - coroutine::run([](void *arg) { + test::coroutine::run([](void *arg) { auto co = Coroutine::get_current_safe(); Coroutine::create([co](void *){ System::sleep(0.002); diff --git a/core-tests/src/network/dns.cpp b/core-tests/src/network/dns.cpp index 5e0f72ab35d..c2961ae39e6 100644 --- a/core-tests/src/network/dns.cpp +++ b/core-tests/src/network/dns.cpp @@ -22,16 +22,55 @@ #include "swoole_socket.h" using namespace swoole; +using swoole::coroutine::Socket; +using swoole::coroutine::System; using namespace swoole::test; using namespace std; -TEST(dns, lookup) { +TEST(dns, lookup1) { test::coroutine::run([](void *arg) { - auto list = swoole::coroutine::dns_lookup("www.baidu.com", 10); + auto list = swoole::coroutine::dns_lookup("www.baidu.com", AF_INET, 10); ASSERT_GE(list.size(), 1); }); } +TEST(dns, lookup_ipv6) { + test::coroutine::run([](void *arg) { + auto list = swoole::coroutine::dns_lookup("www.google.com", AF_INET6, 2); + ASSERT_GE(list.size(), 1); + }); +} + +TEST(dns, domain_not_found) { + test::coroutine::run([](void *arg) { + auto list = swoole::coroutine::dns_lookup("www.baidu.com-not-found", AF_INET, 2); + ASSERT_EQ(list.size(), 0); + ASSERT_EQ(swoole_get_last_error(), SW_ERROR_DNSLOOKUP_RESOLVE_FAILED); + }); +} + +TEST(dns, bad_family) { + test::coroutine::run([](void *arg) { + auto list = swoole::coroutine::dns_lookup("www.google.com", 9999, 2); + ASSERT_GE(list.size(), 1); + }); +} + +TEST(dns, cancel) { + // swoole_set_trace_flags(SW_TRACE_CARES); + // swoole_set_log_level(SW_LOG_TRACE); + test::coroutine::run([](void *arg) { + auto co = Coroutine::get_current_safe(); + Coroutine::create([co](void *){ + System::sleep(0.002); + co->cancel(); + }); + auto list1 = swoole::coroutine::dns_lookup("www.baidu-not-found-for-cancel.com", AF_INET, 2); + ASSERT_EQ(list1.size(), 0); + ASSERT_EQ(swoole_get_last_error(), SW_ERROR_CO_CANCELED); + }); +} + TEST(dns, getaddrinfo) { char buf[1024] = {}; swoole::network::GetaddrinfoRequest req = {}; diff --git a/core-tests/src/os/process_pool.cpp b/core-tests/src/os/process_pool.cpp index d335b64a9af..75d5cbb29bb 100644 --- a/core-tests/src/os/process_pool.cpp +++ b/core-tests/src/os/process_pool.cpp @@ -1,6 +1,12 @@ #include "test_core.h" #include "swoole_process_pool.h" +#include + +#ifdef __MACH__ +#define sysv_signal signal +#endif + using namespace swoole; static void test_func(ProcessPool &pool) { @@ -114,4 +120,4 @@ TEST(process_pool, shutdown) { pool.destroy(); ASSERT_EQ(*shm_value, magic_number); -} \ No newline at end of file +} diff --git a/examples/http/server.php b/examples/http/server.php index a4a6325f742..b3ca4662285 100644 --- a/examples/http/server.php +++ b/examples/http/server.php @@ -17,6 +17,7 @@ function dump($var) //'open_cpu_affinity' => 1, //'task_worker_num' => 100, //'enable_port_reuse' => true, + // 'http_compression' => false, 'worker_num' => 1, //'log_file' => __DIR__.'/swoole.log', // 'reactor_num' => 24, @@ -89,6 +90,9 @@ function no_chunk(swoole_http_request $request, swoole_http_response $response) $response->status(404); $response->end(); return; + } else if ($request->server['request_uri'] == '/big_response') { + var_dump($response->end(str_repeat('A', 16 * 1024 * 1024))); + return; } else if ($request->server['request_uri'] == '/code') { $response->sendfile(__FILE__); return; diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index 8c4a3166659..be863d671e5 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -50,6 +50,10 @@ END_EXTERN_C() #include #endif +#ifdef SW_USE_CARES +#include +#endif + using swoole::network::Socket; ZEND_DECLARE_MODULE_GLOBALS(swoole) @@ -93,6 +97,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_async_dns_lookup_coro, 0, 0, 1) ZEND_ARG_INFO(0, domain_name) ZEND_ARG_INFO(0, timeout) + ZEND_ARG_INFO(0, type) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_coroutine_create, 0, 0, 1) @@ -344,10 +349,7 @@ void php_swoole_set_global_option(HashTable *vht) { SWOOLE_G(display_errors) = zval_is_true(ztmp); } if (php_swoole_array_get_value(vht, "dns_server", ztmp)) { - if (SwooleG.dns_server_v4) { - sw_free(SwooleG.dns_server_v4); - } - SwooleG.dns_server_v4 = zend::String(ztmp).dup(); + swoole_set_dns_server(zend::String(ztmp).to_std_string()); } auto timeout_format = [](zval *v) -> double { @@ -879,6 +881,9 @@ PHP_MINFO_FUNCTION(swoole) { #ifdef HAVE_PCRE php_info_print_table_row(2, "pcre", "enabled"); #endif +#ifdef SW_USE_CARES + php_info_print_table_row(2, "c-ares", ares_version(nullptr)); +#endif #ifdef SW_HAVE_ZLIB #ifdef ZLIB_VERSION php_info_print_table_row(2, "zlib", ZLIB_VERSION); diff --git a/ext-src/php_swoole_coroutine_system.h b/ext-src/php_swoole_coroutine_system.h index 185ae9f9e9e..16b7d7a9e8a 100644 --- a/ext-src/php_swoole_coroutine_system.h +++ b/ext-src/php_swoole_coroutine_system.h @@ -53,6 +53,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_coroutine_system_dnsLookup, 0, 0, 1) ZEND_ARG_INFO(0, domain_name) ZEND_ARG_INFO(0, timeout) + ZEND_ARG_INFO(0, type) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_coroutine_system_getaddrinfo, 0, 0, 1) diff --git a/ext-src/php_swoole_mysql_proto.h b/ext-src/php_swoole_mysql_proto.h index 604d8661fe8..858f55a4605 100644 --- a/ext-src/php_swoole_mysql_proto.h +++ b/ext-src/php_swoole_mysql_proto.h @@ -689,7 +689,7 @@ class lcb_packet : public server_packet { swMysqlPacketDump(header.length, header.number, data, "Protocol::LengthCodedBinary"); bytes_length = read_lcb(data + SW_MYSQL_PACKET_HEADER_SIZE, &length, &nul); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "binary_length=%" PRIu64 ", nul=%u", header.length, nul); + swTraceLog(SW_TRACE_MYSQL_CLIENT, "binary_length=%u, nul=%u", header.length, nul); } bool is_vaild() { @@ -801,7 +801,7 @@ class row_data_text swTraceLog( SW_TRACE_MYSQL_CLIENT, "text[%" PRIu64 "]: %.*s%s", - length, SW_MIN(64, length), body, + length, (int) SW_MIN(64, length), body, nul ? "null" : ((length > 64 /*|| length > readable_length*/) ? "..." : "") ); } diff --git a/ext-src/php_swoole_private.h b/ext-src/php_swoole_private.h index e09f5607e7e..22a2e0b9c7a 100644 --- a/ext-src/php_swoole_private.h +++ b/ext-src/php_swoole_private.h @@ -84,6 +84,12 @@ extern PHPAPI int php_array_merge(zend_array *dest, zend_array *src); #endif #endif +#ifdef SW_USE_CARES +#ifndef HAVE_CARES +#error "Enable c-ares support, require c-ares library" +#endif +#endif + #ifdef SW_SOCKETS #include "ext/sockets/php_sockets.h" #define SWOOLE_SOCKETS_SUPPORT diff --git a/ext-src/swoole_async_coro.cc b/ext-src/swoole_async_coro.cc index 4bd62a68050..777fe5ff748 100644 --- a/ext-src/swoole_async_coro.cc +++ b/ext-src/swoole_async_coro.cc @@ -119,8 +119,9 @@ PHP_FUNCTION(swoole_async_dns_lookup_coro) { Coroutine::get_current_safe(); zval *domain; + long type = AF_INET; double timeout = swoole::network::Socket::default_dns_timeout; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|d", &domain, &timeout) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|dl", &domain, &timeout, &type) == FAILURE) { RETURN_FALSE; } @@ -147,7 +148,7 @@ PHP_FUNCTION(swoole_async_dns_lookup_coro) { php_swoole_check_reactor(); - vector result = swoole::coroutine::dns_lookup(Z_STRVAL_P(domain), timeout); + vector result = swoole::coroutine::dns_lookup(Z_STRVAL_P(domain), type, timeout); if (result.empty()) { swoole_set_last_error(SW_ERROR_DNSLOOKUP_RESOLVE_FAILED); RETURN_FALSE; diff --git a/ext-src/swoole_http_response.cc b/ext-src/swoole_http_response.cc index 6fd6bb9d3e7..e2c9cf2f46a 100644 --- a/ext-src/swoole_http_response.cc +++ b/ext-src/swoole_http_response.cc @@ -37,8 +37,8 @@ using http_context = swoole::http::Context; zend_class_entry *swoole_http_response_ce; static zend_object_handlers swoole_http_response_handlers; -static void http_build_header(http_context *ctx, swString *response, size_t body_length); -static ssize_t http_build_trailer(http_context *ctx, swString *response); +static void http_build_header(http_context *ctx, String *response, size_t body_length); +static ssize_t http_build_trailer(http_context *ctx, String *response); static inline void http_header_key_format(char *key, int length) { int i, state = 0; @@ -360,7 +360,7 @@ static bool parse_header_flags(http_context *ctx, const char *key, size_t keylen return true; } -static void http_build_header(http_context *ctx, swString *response, size_t body_length) { +static void http_build_header(http_context *ctx, String *response, size_t body_length) { char *buf = sw_tg_buffer()->str; size_t l_buf = sw_tg_buffer()->size; int n; @@ -503,7 +503,7 @@ static void http_build_header(http_context *ctx, swString *response, size_t body ctx->send_header_ = 1; } -static ssize_t http_build_trailer(http_context *ctx, swString *response) { +static ssize_t http_build_trailer(http_context *ctx, String *response) { char *buf = sw_tg_buffer()->str; size_t l_buf = sw_tg_buffer()->size; int n; @@ -1257,7 +1257,7 @@ static PHP_METHOD(swoole_http_response, recv) { Socket *sock = (Socket *) ctx->private_data; ssize_t retval = sock->recv_packet(timeout); - swString _tmp; + String _tmp; if (retval < 0) { swoole_set_last_error(sock->errCode); diff --git a/ext-src/swoole_mysql_coro.cc b/ext-src/swoole_mysql_coro.cc index e802e8013bd..ff1b1159480 100644 --- a/ext-src/swoole_mysql_coro.cc +++ b/ext-src/swoole_mysql_coro.cc @@ -927,11 +927,11 @@ void mysql_client::handle_row_data_text(zval *return_value, mysql::row_data *row RETVAL_STRINGL(p, row_data->text.length); _return: swTraceLog(SW_TRACE_MYSQL_CLIENT, - "%.*s=[%zu]%.*s%s", + "%.*s=[%lu]%.*s%s", field->name_length, field->name, Z_STRLEN_P(return_value), - SW_MIN(32, Z_STRLEN_P(return_value)), + (int) SW_MIN(32, Z_STRLEN_P(return_value)), Z_STRVAL_P(return_value), (Z_STRLEN_P(return_value) > 32 ? "..." : "")); } @@ -1247,36 +1247,36 @@ void mysql_statement::send_execute_request(zval *return_value, zval *params) { zval *value; ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(params), value) { switch (client->strict_type ? Z_TYPE_P(value) : (IS_NULL == Z_TYPE_P(value) ? IS_NULL : IS_STRING)) { - case IS_NULL: - *((buffer->str + null_start_offset) + (index / 8)) |= (1UL << (index % 8)); - sw_mysql_int2store((buffer->str + type_start_offset) + (index * 2), SW_MYSQL_TYPE_NULL); - break; - case IS_TRUE: - case IS_FALSE: - case IS_LONG: - sw_mysql_int2store((buffer->str + type_start_offset) + (index * 2), SW_MYSQL_TYPE_LONGLONG); - sw_mysql_int8store(stack_buffer, zval_get_long(value)); - if (buffer->append(stack_buffer, mysql::get_static_type_size(SW_MYSQL_TYPE_LONGLONG)) < 0) { - RETURN_FALSE; - } - break; - case IS_DOUBLE: - sw_mysql_int2store((buffer->str + type_start_offset) + (index * 2), SW_MYSQL_TYPE_DOUBLE); - sw_mysql_doublestore(stack_buffer, zval_get_double(value)); - if (buffer->append(stack_buffer, mysql::get_static_type_size(SW_MYSQL_TYPE_DOUBLE)) < 0) { - RETURN_FALSE; - } - break; - default: - zend::String str_value(value); - uint8_t lcb_size = mysql::write_lcb(stack_buffer, str_value.len()); - sw_mysql_int2store((buffer->str + type_start_offset) + (index * 2), SW_MYSQL_TYPE_VAR_STRING); - if (buffer->append(stack_buffer, lcb_size) < 0) { - RETURN_FALSE; - } - if (buffer->append(str_value.val(), str_value.len()) < 0) { - RETURN_FALSE; - } + case IS_NULL: + *((buffer->str + null_start_offset) + (index / 8)) |= (1UL << (index % 8)); + sw_mysql_int2store((buffer->str + type_start_offset) + (index * 2), SW_MYSQL_TYPE_NULL); + break; + case IS_TRUE: + case IS_FALSE: + case IS_LONG: + sw_mysql_int2store((buffer->str + type_start_offset) + (index * 2), SW_MYSQL_TYPE_LONGLONG); + sw_mysql_int8store(stack_buffer, zval_get_long(value)); + if (buffer->append(stack_buffer, mysql::get_static_type_size(SW_MYSQL_TYPE_LONGLONG)) < 0) { + RETURN_FALSE; + } + break; + case IS_DOUBLE: + sw_mysql_int2store((buffer->str + type_start_offset) + (index * 2), SW_MYSQL_TYPE_DOUBLE); + sw_mysql_doublestore(stack_buffer, zval_get_double(value)); + if (buffer->append(stack_buffer, mysql::get_static_type_size(SW_MYSQL_TYPE_DOUBLE)) < 0) { + RETURN_FALSE; + } + break; + default: + zend::String str_value(value); + uint8_t lcb_size = mysql::write_lcb(stack_buffer, str_value.len()); + sw_mysql_int2store((buffer->str + type_start_offset) + (index * 2), SW_MYSQL_TYPE_VAR_STRING); + if (buffer->append(stack_buffer, lcb_size) < 0) { + RETURN_FALSE; + } + if (buffer->append(str_value.val(), str_value.len()) < 0) { + RETURN_FALSE; + } } index++; } @@ -1483,11 +1483,10 @@ void mysql_statement::fetch(zval *return_value) { case SW_MYSQL_TYPE_LONGLONG: if (field->flags & SW_MYSQL_UNSIGNED_FLAG) { add_assoc_ulong_safe_ex(return_value, field->name, field->name_length, *(uint64_t *) p); - swTraceLog( - SW_TRACE_MYSQL_CLIENT, "%.*s=%llu", field->name_length, field->name, *(uint64_t *) p); + swTraceLog(SW_TRACE_MYSQL_CLIENT, "%.*s=%lu", field->name_length, field->name, *(uint64_t *) p); } else { add_assoc_long_ex(return_value, field->name, field->name_length, *(int64_t *) p); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "%.*s=%lld", field->name_length, field->name, *(int64_t *) p); + swTraceLog(SW_TRACE_MYSQL_CLIENT, "%.*s=%ld", field->name_length, field->name, *(int64_t *) p); } break; case SW_MYSQL_TYPE_FLOAT: { @@ -1901,7 +1900,8 @@ static PHP_METHOD(swoole_mysql_coro, fetch) { mc->fetch(return_value); mc->del_timeout_controller(); if (sw_unlikely(Z_TYPE_P(return_value) == IS_FALSE)) { - swoole_mysql_coro_sync_error_properties(ZEND_THIS, mc->get_error_code(), mc->get_error_msg(), mc->is_connected()); + swoole_mysql_coro_sync_error_properties( + ZEND_THIS, mc->get_error_code(), mc->get_error_msg(), mc->is_connected()); } } @@ -1918,7 +1918,8 @@ static PHP_METHOD(swoole_mysql_coro, fetchAll) { mc->fetch_all(return_value); mc->del_timeout_controller(); if (sw_unlikely(Z_TYPE_P(return_value) == IS_FALSE)) { - swoole_mysql_coro_sync_error_properties(ZEND_THIS, mc->get_error_code(), mc->get_error_msg(), mc->is_connected()); + swoole_mysql_coro_sync_error_properties( + ZEND_THIS, mc->get_error_code(), mc->get_error_msg(), mc->is_connected()); } } @@ -1958,7 +1959,8 @@ static PHP_METHOD(swoole_mysql_coro, prepare) { mc->add_timeout_controller(timeout, Socket::TIMEOUT_RDWR); if (UNEXPECTED(!mc->send_prepare_request(statement, statement_length))) { _failed: - swoole_mysql_coro_sync_error_properties(ZEND_THIS, mc->get_error_code(), mc->get_error_msg(), mc->is_connected()); + swoole_mysql_coro_sync_error_properties( + ZEND_THIS, mc->get_error_code(), mc->get_error_msg(), mc->is_connected()); RETVAL_FALSE; } else if (UNEXPECTED(mc->get_defer())) { RETVAL_TRUE; diff --git a/ext-src/swoole_mysql_proto.cc b/ext-src/swoole_mysql_proto.cc index 8cf59cad8e3..50f3fa8d443 100644 --- a/ext-src/swoole_mysql_proto.cc +++ b/ext-src/swoole_mysql_proto.cc @@ -365,7 +365,7 @@ eof_packet::eof_packet(const char *data) : server_packet(data) { data += 2; // int<2> status_flags Status Flags server_status = sw_mysql_uint2korr2korr(data); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "EOF_Packet, warnings=%u, status_code=%u", warning_count, server_status); + swTraceLog(SW_TRACE_MYSQL_CLIENT, "EOF_Packet, warnings=%u, status_code=%u", warning_count, server_status.status); } ok_packet::ok_packet(const char *data) : server_packet(data) { @@ -388,7 +388,7 @@ ok_packet::ok_packet(const char *data) : server_packet(data) { "OK_Packet, affected_rows=%" PRIu64 ", insert_id=%" PRIu64 ", status_flags=0x%08x, warnings=%u", affected_rows, last_insert_id, - server_status, + server_status.status, warning_count); } @@ -494,7 +494,7 @@ greeting_packet::greeting_packet(const char *data) : server_packet(data) { server_version.c_str(), connection_id, capability_flags, - status_flags, + status_flags.status, auth_plugin_name.c_str(), auth_plugin_data_length, auth_plugin_data); diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 68e8dedf0b5..71b77de1029 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -1250,7 +1250,7 @@ static void php_swoole_onPipeMessage(Server *serv, EventData *req) { } swTraceLog(SW_TRACE_SERVER, - "PipeMessage: fd=%d|len=%d|src_worker_id=%d|data=%.*s\n", + "PipeMessage: fd=%ld|len=%d|src_worker_id=%d|data=%.*s\n", req->info.fd, req->info.len, req->info.reactor_id, diff --git a/include/swoole.h b/include/swoole.h index 9501908e9fe..84f225009da 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -380,6 +380,7 @@ enum swFd_type { */ SW_FD_SIGNAL, SW_FD_DNS_RESOLVER, + SW_FD_CARES, /** * SW_FD_USER or SW_FD_USER+n: for custom event */ @@ -633,7 +634,7 @@ struct Global { int signal_fd; bool signal_alarm; - uint32_t trace_flags; + long trace_flags; void (*fatal_error)(int code, const char *str, ...); @@ -647,18 +648,20 @@ struct Global { Allocator std_allocator; std::string task_tmpfile; //-----------------------[DNS]-------------------------- - char *dns_server_v4; - char *dns_server_v6; + std::string dns_server_host; + int dns_server_port; double dns_cache_refresh_time; + int dns_tries; + std::string dns_resolvconf_path; //-----------------------[AIO]-------------------------- uint32_t aio_core_worker_num; uint32_t aio_worker_num; double aio_max_wait_time; double aio_max_idle_time; - swoole::network::Socket *aio_default_socket; + network::Socket *aio_default_socket; //-----------------------[Hook]-------------------------- void *hooks[SW_MAX_HOOK_TYPE]; - std::function user_exit_condition; + std::function user_exit_condition; }; std::string dirname(const std::string &file); @@ -694,6 +697,9 @@ static inline int swoole_get_process_id() { SW_API const char *swoole_strerror(int code); SW_API void swoole_throw_error(int code); +SW_API void swoole_set_log_level(int level); +SW_API void swoole_set_trace_flags(int flags); +SW_API void swoole_set_dns_server(const std::string server); //----------------------------------------------- static sw_inline void sw_spinlock(sw_atomic_t *lock) { diff --git a/include/swoole_config.h b/include/swoole_config.h index 7ee5d23af01..239a743ae28 100644 --- a/include/swoole_config.h +++ b/include/swoole_config.h @@ -192,6 +192,7 @@ #define SW_DNS_HOST_BUFFER_SIZE 16 #define SW_DNS_SERVER_PORT 53 #define SW_DNS_DEFAULT_SERVER "8.8.8.8" +#define SW_DNS_RESOLV_CONF "/etc/resolv.conf" #define SW_Z_BEST_SPEED 1 #define SW_COMPRESSION_MIN_LENGTH_DEFAULT 20 diff --git a/include/swoole_coroutine.h b/include/swoole_coroutine.h index ccfc07ed5d8..2712a550563 100644 --- a/include/swoole_coroutine.h +++ b/include/swoole_coroutine.h @@ -72,15 +72,15 @@ class Coroutine { void yield_naked(); bool yield_ex(double timeout = -1); - inline enum State get_state() { + inline enum State get_state() const { return state; } - inline long get_init_msec() { + inline long get_init_msec() const { return init_msec; } - inline long get_cid() { + inline long get_cid() const { return cid; } @@ -100,14 +100,18 @@ class Coroutine { return ctx.is_end(); } - bool is_canceled() { + bool is_canceled() const { return resume_code_ == RC_CANCELED; } - bool is_timedout() { + bool is_timedout() const { return resume_code_ == RC_TIMEDOUT; } + bool is_suspending() const { + return state == STATE_WAITING; + } + inline void set_task(void *_task) { task = _task; } diff --git a/include/swoole_coroutine_socket.h b/include/swoole_coroutine_socket.h index 860179d6f25..e02236d2415 100644 --- a/include/swoole_coroutine_socket.h +++ b/include/swoole_coroutine_socket.h @@ -591,7 +591,11 @@ class ProtocolSwitch { } }; -std::vector dns_lookup(const char *domain, double timeout = 2.0); +std::vector dns_lookup(const char *domain, int family = AF_INET, double timeout = 2.0); +std::vector dns_lookup_impl_with_socket(const char *domain, int family, double timeout); +#ifdef SW_USE_CARES +std::vector dns_lookup_impl_with_cares(const char *domain, int family, double timeout); +#endif //------------------------------------------------------------------------------- } // namespace coroutine } // namespace swoole diff --git a/include/swoole_coroutine_system.h b/include/swoole_coroutine_system.h index 9404db8d1a8..fefaa4aeb8f 100644 --- a/include/swoole_coroutine_system.h +++ b/include/swoole_coroutine_system.h @@ -68,6 +68,7 @@ class System { /* event */ static int wait_event(int fd, int events, double timeout); }; +std::string gethostbyname_impl_with_async(const std::string &hostname, int domain, double timeout = -1); //------------------------------------------------------------------------------- } // namespace coroutine } // namespace swoole diff --git a/include/swoole_error.h b/include/swoole_error.h index d563b5264d3..251ef3f4ba2 100644 --- a/include/swoole_error.h +++ b/include/swoole_error.h @@ -38,10 +38,14 @@ enum swErrorCode { SW_ERROR_FILE_NOT_EXIST = 700, SW_ERROR_FILE_TOO_LARGE, SW_ERROR_FILE_EMPTY, - SW_ERROR_DNSLOOKUP_DUPLICATE_REQUEST, + + SW_ERROR_DNSLOOKUP_DUPLICATE_REQUEST = 710, SW_ERROR_DNSLOOKUP_RESOLVE_FAILED, SW_ERROR_DNSLOOKUP_RESOLVE_TIMEOUT, - SW_ERROR_BAD_IPV6_ADDRESS, + SW_ERROR_DNSLOOKUP_UNSUPPORTED, + SW_ERROR_DNSLOOKUP_NO_SERVER, + + SW_ERROR_BAD_IPV6_ADDRESS = 720, SW_ERROR_UNREGISTERED_SIGNAL, // EventLoop diff --git a/include/swoole_log.h b/include/swoole_log.h index 67a8607915a..a40a17b3d4c 100644 --- a/include/swoole_log.h +++ b/include/swoole_log.h @@ -243,8 +243,9 @@ enum swTrace_type { SW_TRACE_CO_HTTP_SERVER = 1u << 27, SW_TRACE_TABLE = 1u << 28, SW_TRACE_CO_CURL = 1u << 29, + SW_TRACE_CARES = 1u << 30, - SW_TRACE_ALL = 0xffffffff + SW_TRACE_ALL = 0x7fffffffffffffff }; #ifdef SW_LOG_TRACE_OPEN diff --git a/make.sh b/make.sh index 38c4e00abb3..54e64931cf6 100755 --- a/make.sh +++ b/make.sh @@ -1,6 +1,6 @@ #!/bin/sh -e __DIR__=$(cd "$(dirname "$0")";pwd) -COMPILE_PARAMS="--enable-openssl --enable-sockets --enable-mysqlnd --enable-http2 --enable-swoole-json --enable-swoole-curl" +COMPILE_PARAMS="--enable-openssl --enable-sockets --enable-mysqlnd --enable-http2 --enable-swoole-json --enable-swoole-curl --enable-cares" if [ "$(uname | grep -i darwin)"x != ""x ]; then CPU_COUNT="$(sysctl -n machdep.cpu.core_count)" diff --git a/src/core/base.cc b/src/core/base.cc index 882518d6aed..2622c5d4621 100644 --- a/src/core/base.cc +++ b/src/core/base.cc @@ -125,6 +125,10 @@ void swoole_init(void) { SwooleG.cpu_num = SW_MAX(1, sysconf(_SC_NPROCESSORS_ONLN)); SwooleG.pagesize = getpagesize(); + // DNS options + SwooleG.dns_tries = 1; + SwooleG.dns_resolvconf_path = SW_DNS_RESOLV_CONF; + // get system uname uname(&SwooleG.uname); // random seed @@ -225,9 +229,39 @@ void swoole_clean(void) { delete g_logger_instance; g_logger_instance = nullptr; } + if (SwooleTG.buffer_stack) { + delete SwooleTG.buffer_stack; + SwooleTG.buffer_stack = nullptr; + } SwooleG = {}; } +SW_API void swoole_set_log_level(int level) { + if (sw_logger()) { + sw_logger()->set_level(level); + } +} + +SW_API void swoole_set_trace_flags(int flags) { + SwooleG.trace_flags = flags; +} + +SW_API void swoole_set_dns_server(const std::string server) { + char *_port; + int dns_server_port = SW_DNS_SERVER_PORT; + char dns_server_host[32]; + strcpy(dns_server_host, server.c_str()); + if ((_port = strchr((char *)server.c_str(), ':'))) { + dns_server_port = atoi(_port + 1); + if (dns_server_port <= 0 || dns_server_port > 65535) { + dns_server_port = SW_DNS_SERVER_PORT; + } + dns_server_host[_port - server.c_str()] = '\0'; + } + SwooleG.dns_server_host = dns_server_host; + SwooleG.dns_server_port = dns_server_port; +} + bool swoole_set_task_tmpdir(const std::string &dir) { if (dir.at(0) != '/') { swWarn("wrong absolute path '%s'", dir.c_str()); diff --git a/src/core/string.cc b/src/core/string.cc index f117852d642..4c8bd7f4847 100644 --- a/src/core/string.cc +++ b/src/core/string.cc @@ -180,7 +180,7 @@ ssize_t String::split(const char *delimiter, size_t delimiter_length, const Stri while (delimiter_addr) { size_t _length = delimiter_addr - start_addr + delimiter_length; - swTraceLog(SW_TRACE_EOF_PROTOCOL, "#[4] count=%d, length=%d", count, _length + offset); + swTraceLog(SW_TRACE_EOF_PROTOCOL, "#[4] count=%d, length=%lu", count, _length + offset); if (handler((char *) start_addr - _offset, _length + _offset) == false) { return -1; } diff --git a/src/core/timer.cc b/src/core/timer.cc index 93290141303..dc58f44f7e2 100644 --- a/src/core/timer.cc +++ b/src/core/timer.cc @@ -142,7 +142,7 @@ TimerNode *Timer::add(long _msec, bool persistent, void *data, const TimerCallba } map.emplace(std::make_pair(tnode->id, tnode)); swTraceLog(SW_TRACE_TIMER, - "id=%ld, exec_msec=%" PRId64 ", msec=%ld, round=%" PRIu64 ", exist=%u", + "id=%ld, exec_msec=%" PRId64 ", msec=%ld, round=%" PRIu64 ", exist=%lu", tnode->id, tnode->exec_msec, _msec, @@ -158,7 +158,7 @@ bool Timer::remove(TimerNode *tnode) { if (sw_unlikely(_current_id > 0 && tnode->id == _current_id)) { tnode->removed = true; swTraceLog(SW_TRACE_TIMER, - "set-remove: id=%ld, exec_msec=%" PRId64 ", round=%" PRIu64 ", exist=%u", + "set-remove: id=%ld, exec_msec=%" PRId64 ", round=%" PRIu64 ", exist=%lu", tnode->id, tnode->exec_msec, tnode->round, @@ -175,7 +175,7 @@ bool Timer::remove(TimerNode *tnode) { tnode->destructor(tnode); } swTraceLog(SW_TRACE_TIMER, - "id=%ld, exec_msec=%" PRId64 ", round=%" PRIu64 ", exist=%u", + "id=%ld, exec_msec=%" PRId64 ", round=%" PRIu64 ", exist=%lu", tnode->id, tnode->exec_msec, tnode->round, @@ -204,7 +204,7 @@ int Timer::select() { _current_id = tnode->id; if (!tnode->removed) { swTraceLog(SW_TRACE_TIMER, - "id=%ld, exec_msec=%" PRId64 ", round=%" PRIu64 ", exist=%u", + "id=%ld, exec_msec=%" PRId64 ", round=%" PRIu64 ", exist=%lu", tnode->id, tnode->exec_msec, tnode->round, diff --git a/src/coroutine/system.cc b/src/coroutine/system.cc index fe6599be015..af03c28b1be 100644 --- a/src/coroutine/system.cc +++ b/src/coroutine/system.cc @@ -15,6 +15,7 @@ */ #include "swoole_coroutine_system.h" +#include "swoole_coroutine_socket.h" #include "swoole_lru_cache.h" #include "swoole_signal.h" @@ -135,22 +136,7 @@ ssize_t System::write_file(const char *file, char *buf, size_t length, bool lock return retval; } -std::string System::gethostbyname(const std::string &hostname, int domain, double timeout) { - if (dns_cache == nullptr && dns_cache_capacity != 0) { - dns_cache = new LRUCache(dns_cache_capacity); - } - - std::string cache_key; - if (dns_cache) { - cache_key.append(domain == AF_INET ? "4_" : "6_"); - cache_key.append(hostname); - auto cache = dns_cache->get(cache_key); - - if (cache) { - return *(std::string *) cache.get(); - } - } - +std::string gethostbyname_impl_with_async(const std::string &hostname, int domain, double timeout) { AsyncEvent ev{}; if (hostname.size() < SW_IP_MAX_LENGTH) { @@ -178,19 +164,48 @@ std::string System::gethostbyname(const std::string &hostname, int domain, doubl swoole_set_last_error(ev.error); return ""; } else { - if (dns_cache) { - std::string *addr = new std::string((char *) ev.buf); - dns_cache->set(cache_key, std::shared_ptr(addr), dns_cache_expire); - sw_free(ev.buf); - return *addr; - } - std::string addr((char *) ev.buf); sw_free(ev.buf); return addr; } } +std::string System::gethostbyname(const std::string &hostname, int domain, double timeout) { + if (dns_cache == nullptr && dns_cache_capacity != 0) { + dns_cache = new LRUCache(dns_cache_capacity); + } + + std::string cache_key; + std::string result; + + if (dns_cache) { + cache_key.append(domain == AF_INET ? "4_" : "6_"); + cache_key.append(hostname); + auto cache = dns_cache->get(cache_key); + + if (cache) { + return *(std::string *) cache.get(); + } + } + +#ifdef SW_USE_CARES + auto result_list = dns_lookup_impl_with_cares(hostname.c_str(), domain, timeout); + if (SwooleG.dns_lookup_random) { + result = result_list[rand() % result_list.size()]; + } else { + result = result_list[0]; + } +#else + result = gethostbyname_impl_with_async(hostname, domain, timeout); +#endif + + if (dns_cache) { + dns_cache->set(cache_key, std::make_shared(result), dns_cache_expire); + } + + return result; +} + std::vector System::getaddrinfo( const std::string &hostname, int family, int socktype, int protocol, const std::string &service, double timeout) { assert(!hostname.empty()); diff --git a/src/network/dns.cc b/src/network/dns.cc index afb9828c714..eb31534346f 100644 --- a/src/network/dns.cc +++ b/src/network/dns.cc @@ -18,11 +18,18 @@ #include "swoole_coroutine_socket.h" #include +#include #include -#define SW_DNS_SERVER_CONF "/etc/resolv.conf" +#ifdef SW_USE_CARES +#include +#endif + #define SW_DNS_SERVER_NUM 2 +namespace swoole { +namespace coroutine { + enum swDNS_type { SW_DNS_A_RECORD = 0x01, // Lookup IPv4 address SW_DNS_AAAA_RECORD = 0x1c, // Lookup IPv6 address @@ -36,7 +43,7 @@ enum swDNS_error { }; /* Struct for the DNS Header */ -typedef struct { +struct RecordHeader { uint16_t id; uchar rd : 1; uchar tc : 1; @@ -50,35 +57,36 @@ typedef struct { uint16_t ancount; uint16_t nscount; uint16_t arcount; -} swDNSResolver_header; +}; /* Struct for the flags for the DNS Question */ -typedef struct q_flags { +struct Q_FLAGS { uint16_t qtype; uint16_t qclass; -} Q_FLAGS; +}; /* Struct for the flags for the DNS RRs */ -typedef struct rr_flags { +struct RR_FLAGS { uint16_t type; uint16_t rdclass; uint32_t ttl; uint16_t rdlength; -} RR_FLAGS; +}; -static uint16_t swoole_dns_request_id = 1; +static uint16_t dns_request_id = 1; static int domain_encode(const char *src, int n, char *dest); static void domain_decode(char *str); static int get_dns_server(); +static std::string parse_ip_address(void *vaddr, int type); static int get_dns_server() { FILE *fp; char line[100]; char buf[16] = {}; - if ((fp = fopen(SW_DNS_SERVER_CONF, "rt")) == nullptr) { - swSysWarn("fopen(" SW_DNS_SERVER_CONF ") failed"); + if ((fp = fopen(SwooleG.dns_resolvconf_path.c_str(), "rt")) == nullptr) { + swSysWarn("fopen(%s) failed", SwooleG.dns_resolvconf_path.c_str()); return SW_ERR; } @@ -92,30 +100,53 @@ static int get_dns_server() { fclose(fp); if (strlen(buf) == 0) { - SwooleG.dns_server_v4 = sw_strdup(SW_DNS_DEFAULT_SERVER); + swoole_set_dns_server(SW_DNS_DEFAULT_SERVER); } else { - SwooleG.dns_server_v4 = sw_strdup(buf); + swoole_set_dns_server(buf); } return SW_OK; } -std::vector swoole::coroutine::dns_lookup(const char *domain, double timeout) { +static std::string parse_ip_address(void *vaddr, int type) { + auto addr = reinterpret_cast(vaddr); + std::string ip_addr; + if (type == AF_INET) { + char buff[4 * 4 + 3 + 1]; + sw_snprintf(buff, sizeof(buff), "%u.%u.%u.%u", addr[0], addr[1], addr[2], addr[3]); + return ip_addr.assign(buff); + } else if (type == AF_INET6) { + for (int i = 0; i < 16; i += 2) { + if (i > 0) { + ip_addr.append(":"); + } + char buf[4 + 1]; + size_t n = sw_snprintf(buf, sizeof(buf), "%02x%02x", addr[i], addr[i + 1]); + ip_addr.append(buf, n); + } + } else { + assert(0); + } + return ip_addr; +} + +std::vector dns_lookup_impl_with_socket(const char *domain, int family, double timeout) { char *_domain_name; Q_FLAGS *qflags = nullptr; char packet[SW_BUFFER_SIZE_STD]; - swDNSResolver_header *header = nullptr; + RecordHeader *header = nullptr; int steps = 0; - std::vector result; - if (SwooleG.dns_server_v4 == nullptr) { + + if (SwooleG.dns_server_host.empty()) { if (get_dns_server() < 0) { + swoole_set_last_error(SW_ERROR_DNSLOOKUP_NO_SERVER); return result; } } - header = (swDNSResolver_header *) packet; - int _request_id = swoole_dns_request_id++; + header = (RecordHeader *) packet; + int _request_id = dns_request_id++; header->id = htons(_request_id); header->qr = 0; header->opcode = 0; @@ -130,7 +161,7 @@ std::vector swoole::coroutine::dns_lookup(const char *domain, doubl header->nscount = 0x0000; header->arcount = 0x0000; - steps = sizeof(swDNSResolver_header); + steps = sizeof(RecordHeader); _domain_name = &packet[steps]; @@ -143,7 +174,7 @@ std::vector swoole::coroutine::dns_lookup(const char *domain, doubl steps += (strlen((const char *) _domain_name) + 1); qflags = (Q_FLAGS *) &packet[steps]; - qflags->qtype = htons(SW_DNS_A_RECORD); + qflags->qtype = htons(family == AF_INET6 ? SW_DNS_AAAA_RECORD : SW_DNS_A_RECORD); qflags->qclass = htons(0x0001); steps += sizeof(Q_FLAGS); @@ -151,16 +182,8 @@ std::vector swoole::coroutine::dns_lookup(const char *domain, doubl if (timeout > 0) { _sock.set_timeout(timeout); } - - char *_port; - int dns_server_port = SW_DNS_SERVER_PORT; - char dns_server_host[32]; - strcpy(dns_server_host, SwooleG.dns_server_v4); - if ((_port = strchr(SwooleG.dns_server_v4, ':'))) { - dns_server_port = atoi(_port + 1); - dns_server_host[_port - SwooleG.dns_server_v4] = '\0'; - } - if (!_sock.sendto(dns_server_host, dns_server_port, (char *) packet, steps)) { + if (!_sock.sendto(SwooleG.dns_server_host, SwooleG.dns_server_port, (char *) packet, steps)) { + swoole_set_last_error(SW_ERROR_DNSLOOKUP_RESOLVE_FAILED); return result; } @@ -181,14 +204,15 @@ std::vector swoole::coroutine::dns_lookup(const char *domain, doubl char name[10][254]; int i, j; - int ret = _sock.recv(packet, sizeof(packet) - 1); + auto ret = _sock.recv(packet, sizeof(packet) - 1); if (ret <= 0) { + swoole_set_last_error(_sock.errCode == ECANCELED ? SW_ERROR_CO_CANCELED: SW_ERROR_DNSLOOKUP_RESOLVE_FAILED); return result; } packet[ret] = 0; - header = (swDNSResolver_header *) packet; - steps = sizeof(swDNSResolver_header); + header = (RecordHeader *) packet; + steps = sizeof(RecordHeader); _domain_name = &packet[steps]; domain_decode(_domain_name); @@ -228,11 +252,9 @@ std::vector swoole::coroutine::dns_lookup(const char *domain, doubl steps = steps + sizeof(RR_FLAGS) - 2; /* Parsing the IPv4 address in the RR */ - if (ntohs(rrflags->type) == 1) { - for (j = 0; j < ntohs(rrflags->rdlength); ++j) { - rdata[i][j] = (uchar) packet[steps + j]; - } - type[i] = ntohs(rrflags->type); + type[i] = ntohs(rrflags->type); + for (j = 0; j < ntohs(rrflags->rdlength); ++j) { + rdata[i][j] = (uchar) packet[steps + j]; } /* Parsing the canonical name in the RR */ @@ -259,16 +281,17 @@ std::vector swoole::coroutine::dns_lookup(const char *domain, doubl int request_id = ntohs(header->id); // bad response if (request_id != _request_id) { + swoole_set_last_error(SW_ERROR_DNSLOOKUP_RESOLVE_FAILED); return result; } for (i = 0; i < ancount; i++) { - if (type[i] != SW_DNS_A_RECORD) { + if (type[i] != SW_DNS_A_RECORD && type[i] != SW_DNS_AAAA_RECORD) { continue; } - char address[16]; - size_t n = - sw_snprintf(address, sizeof(address), "%d.%d.%d.%d", rdata[i][0], rdata[i][1], rdata[i][2], rdata[i][3]); - result.push_back(std::string(address, n)); + result.push_back(parse_ip_address(rdata[i], type[i] == SW_DNS_A_RECORD ? AF_INET : AF_INET6)); + } + if (result.empty()) { + swoole_set_last_error(SW_ERROR_DNSLOOKUP_RESOLVE_FAILED); } return result; } @@ -319,7 +342,177 @@ static void domain_decode(char *str) { str[i - 1] = '\0'; } -namespace swoole { +#ifdef SW_USE_CARES +struct ResolvContext { + ares_channel channel; + ares_options ares_opts; + int ares_flags; + int error; + Coroutine *co; + std::unordered_map sockets; + std::vector result; +}; + +std::vector dns_lookup_impl_with_cares(const char *domain, int family, double timeout) { + if (!swoole_event_isset_handler(SW_FD_CARES)) { + ares_library_init(ARES_LIB_INIT_ALL); + swoole_event_set_handler(SW_FD_CARES | SW_EVENT_READ, [](Reactor *reactor, Event *event) -> int { + auto ctx = reinterpret_cast(event->socket->object); + swTraceLog(SW_TRACE_CARES, "[event callback] readable event, fd=%d", event->socket->fd); + ares_process_fd(ctx->channel, event->fd, ARES_SOCKET_BAD); + return SW_OK; + }); + swoole_event_set_handler(SW_FD_CARES | SW_EVENT_WRITE, [](Reactor *reactor, Event *event) -> int { + auto ctx = reinterpret_cast(event->socket->object); + swTraceLog(SW_TRACE_CARES, "[event callback] writable event, fd=%d", event->socket->fd); + ares_process_fd(ctx->channel, ARES_SOCKET_BAD, event->fd); + return SW_OK; + }); + sw_reactor()->add_destroy_callback([](void *_data) { ares_library_cleanup(); }, nullptr); + } + + ResolvContext ctx{}; + Coroutine *co = Coroutine::get_current_safe(); + ctx.co = co; + char lookups[] = "fb"; + int res; + ctx.ares_opts.lookups = lookups; + ctx.ares_opts.timeout = timeout * 1000; + ctx.ares_opts.tries = SwooleG.dns_tries; + ctx.ares_opts.sock_state_cb_data = &ctx; + ctx.ares_opts.sock_state_cb = [](void *arg, int fd, int readable, int writable) { + auto ctx = reinterpret_cast(arg); + int events = 0; + if (readable) { + events |= SW_EVENT_READ; + } + if (writable) { + events |= SW_EVENT_WRITE; + } + + swTraceLog(SW_TRACE_CARES, "[sock_state_cb], fd=%d, readable=%d, writable=%d", fd, readable, writable); + + network::Socket *_socket = nullptr; + if (ctx->sockets.find(fd) == ctx->sockets.end()) { + if (events == 0) { + swWarn("error events, fd=%d", fd); + return; + } + _socket = make_socket(fd, SW_FD_CARES); + _socket->object = ctx; + ctx->sockets[fd] = _socket; + } else { + _socket = ctx->sockets[fd]; + if (events == 0) { + swTraceLog(SW_TRACE_CARES, "[del event], fd=%d", fd); + swoole_event_del(_socket); + _socket->fd = -1; + _socket->free(); + ctx->sockets.erase(fd); + return; + } + } + + if (_socket->events) { + swoole_event_set(_socket, events); + swTraceLog(SW_TRACE_CARES, "[set event] fd=%d, events=%d", fd, events); + } else { + swoole_event_add(_socket, events); + swTraceLog(SW_TRACE_CARES, "[add event] fd=%d, events=%d", fd, events); + } + }; + ctx.ares_flags = ARES_OPT_TIMEOUTMS | ARES_OPT_TRIES | ARES_OPT_SOCK_STATE_CB | ARES_OPT_LOOKUPS; + + if ((res = ares_init_options(&ctx.channel, &ctx.ares_opts, ctx.ares_flags)) != ARES_SUCCESS) { + swWarn("ares_init_options() failed, Error: %s[%d]", ares_strerror(res), res); + goto _return; + } + + if (!SwooleG.dns_server_host.empty()) { + struct ares_addr_port_node servers; + servers.family = AF_INET; + servers.next = nullptr; + inet_pton(AF_INET, SwooleG.dns_server_host.c_str(), &servers.addr.addr4); + servers.tcp_port = 0; + servers.udp_port = SwooleG.dns_server_port; + ares_set_servers_ports(ctx.channel, &servers); + } + + ares_gethostbyname( + ctx.channel, + domain, + family, + [](void *data, int status, int timeouts, struct hostent *hostent) { + auto ctx = reinterpret_cast(data); + + swTraceLog(SW_TRACE_CARES, "[cares callback] status=%d, timeouts=%d", status, timeouts); + + if (timeouts > 0) { + ctx->error = SW_ERROR_DNSLOOKUP_RESOLVE_TIMEOUT; + goto _resume; + } + + if (status != ARES_SUCCESS) { + ctx->error = status; + goto _resume; + } + + if (hostent->h_addr_list) { + char **paddr = hostent->h_addr_list; + while (*paddr != nullptr) { + ctx->result.emplace_back(parse_ip_address(*paddr, hostent->h_addrtype)); + paddr++; + } + } + _resume: + if (ctx->co && ctx->co->is_suspending()) { + swoole_event_defer( + [](void *data) { + Coroutine *co = reinterpret_cast(data); + co->resume(); + }, + ctx->co); + ctx->co = nullptr; + } + }, + &ctx); + + if (ctx.error) { + goto _destroy; + } + + co->yield_ex(timeout); + if (co->is_canceled()) { + ares_cancel(ctx.channel); + } else if (co->is_timedout()) { + ares_process_fd(ctx.channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD); + swoole_set_last_error(SW_ERROR_DNSLOOKUP_RESOLVE_TIMEOUT); + } else { + swTraceLog(SW_TRACE_CARES, "lookup success, result_count=%lu", ctx.result.size()); + } +_destroy: + if (ctx.error) { + swoole_set_last_error(ctx.error == ARES_ECANCELLED ? SW_ERROR_CO_CANCELED : SW_ERROR_DNSLOOKUP_RESOLVE_FAILED); + } + ares_destroy(ctx.channel); +_return: + return ctx.result; +} +#endif + +std::vector dns_lookup(const char *domain, int family, double timeout) { +#ifdef SW_USE_CARES + return dns_lookup_impl_with_cares(domain, family, timeout); +#else + return dns_lookup_impl_with_socket(domain, family, timeout); +#endif +} + +} // namespace coroutine + +/** + * blocking-IO, Use in synchronous mode or AIO thread pool + */ namespace network { #ifndef HAVE_GETHOSTBYNAME2_R @@ -327,9 +520,6 @@ namespace network { static std::mutex g_gethostbyname2_lock; #endif -/** - * DNS lookup - */ #ifdef HAVE_GETHOSTBYNAME2_R int gethostbyname(int flags, const char *name, char *addr) { int __af = flags & (~SW_DNS_LOOKUP_RANDOM); @@ -363,7 +553,7 @@ int gethostbyname(int flags, const char *name, char *addr) { union { char v4[INET_ADDRSTRLEN]; char v6[INET6_ADDRSTRLEN]; - } addr_list[SW_DNS_HOST_BUFFER_SIZE] {}; + } addr_list[SW_DNS_HOST_BUFFER_SIZE]{}; int i = 0; for (i = 0; i < SW_DNS_HOST_BUFFER_SIZE; i++) { @@ -426,7 +616,7 @@ int gethostbyname(int flags, const char *name, char *addr) { int getaddrinfo(GetaddrinfoRequest *req) { struct addrinfo *result = nullptr; struct addrinfo *ptr = nullptr; - struct addrinfo hints{}; + struct addrinfo hints {}; hints.ai_family = req->family; hints.ai_socktype = req->socktype; @@ -483,6 +673,5 @@ void GetaddrinfoRequest::parse_result(std::vector &retval) { } } } - } // namespace network } // namespace swoole diff --git a/src/os/async_thread.cc b/src/os/async_thread.cc index ecd4d236a30..7994ccc1544 100644 --- a/src/os/async_thread.cc +++ b/src/os/async_thread.cc @@ -252,7 +252,7 @@ void ThreadPool::create_thread(const bool is_core_worker) { } swTraceLog(SW_TRACE_AIO, - "aio_thread %s. ret=%d, error=%d", + "aio_thread %s. ret=%ld, error=%d", event->retval > 0 ? "ok" : "failed", event->retval, event->error); diff --git a/src/protocol/websocket.cc b/src/protocol/websocket.cc index d67446ed936..4e5312d6e96 100644 --- a/src/protocol/websocket.cc +++ b/src/protocol/websocket.cc @@ -92,7 +92,7 @@ ssize_t swWebSocket_get_package_length(Protocol *protocol, Socket *conn, const c return 0; } } - swTraceLog(SW_TRACE_LENGTH_PROTOCOL, "header_length=%zu, payload_length=%u", header_length, payload_length); + swTraceLog(SW_TRACE_LENGTH_PROTOCOL, "header_length=%zu, payload_length=%lu", header_length, payload_length); return header_length + payload_length; } diff --git a/src/server/base.cc b/src/server/base.cc index aeeb01e9e12..33245e01bd3 100644 --- a/src/server/base.cc +++ b/src/server/base.cc @@ -200,7 +200,7 @@ bool BaseFactory::finish(SendData *data) { return false; } } - swTrace("proxy message, fd=%d, len=%ld", worker->pipe_master, sizeof(proxy_msg.info) + proxy_msg.info.len); + swTrace("proxy message, fd=%d, len=%ld", worker->pipe_master->fd, sizeof(proxy_msg.info) + proxy_msg.info.len); } else if (data->info.type == SW_SERVER_EVENT_SEND_FILE) { memcpy(&proxy_msg.info, &data->info, sizeof(proxy_msg.info)); memcpy(proxy_msg.data, data->data, data->info.len); diff --git a/tests/swoole_coroutine/dnslookup_1.phpt b/tests/swoole_coroutine/dnslookup_1.phpt index 26af90ddb51..59e41155393 100644 --- a/tests/swoole_coroutine/dnslookup_1.phpt +++ b/tests/swoole_coroutine/dnslookup_1.phpt @@ -8,10 +8,12 @@ skip_if_offline(); --EXPECT-- diff --git a/tests/swoole_coroutine/dnslookup_2.phpt b/tests/swoole_coroutine/dnslookup_2.phpt index 9de32793040..f1727cdc712 100644 --- a/tests/swoole_coroutine/dnslookup_2.phpt +++ b/tests/swoole_coroutine/dnslookup_2.phpt @@ -5,12 +5,14 @@ swoole_coroutine: async dns lookup timeout --FILE-- '192.0.0.1:10053']); + +use Swoole\Coroutine\System; +use function Swoole\Coroutine\run; + +run(function () { $host = Swoole\Coroutine::dnsLookup('www.' . uniqid() . '.' . uniqid(), 0.5); Assert::eq($host, false); Assert::eq(swoole_last_error(), SWOOLE_ERROR_DNSLOOKUP_RESOLVE_FAILED); - Swoole\Event::exit(); }); ?> --EXPECT-- diff --git a/tests/swoole_coroutine/dnslookup_3.phpt b/tests/swoole_coroutine/dnslookup_3.phpt index 82a7ce6f5b7..1f6c343d1a9 100644 --- a/tests/swoole_coroutine/dnslookup_3.phpt +++ b/tests/swoole_coroutine/dnslookup_3.phpt @@ -10,7 +10,6 @@ go(function () { $host = swoole_async_dns_lookup_coro('www.' . uniqid() . '.' . uniqid(), 15); Assert::eq($host, false); Assert::eq(swoole_last_error(), SWOOLE_ERROR_DNSLOOKUP_RESOLVE_FAILED); - Swoole\Event::exit(); }); swoole_event_wait(); ?> diff --git a/tests/swoole_coroutine/dnslookup_4.phpt b/tests/swoole_coroutine/dnslookup_4.phpt new file mode 100644 index 00000000000..0830b6d8c6e --- /dev/null +++ b/tests/swoole_coroutine/dnslookup_4.phpt @@ -0,0 +1,19 @@ +--TEST-- +swoole_coroutine: bad dns server +--SKIPIF-- + +--FILE-- + '192.0.0.1:10053']); + $host = Swoole\Coroutine::dnsLookup('www.baidu.com', 0.5); + Assert::eq($host, false); + Assert::eq(swoole_last_error(), SWOOLE_ERROR_DNSLOOKUP_RESOLVE_FAILED); +}); +?> +--EXPECT-- diff --git a/tests/swoole_coroutine/dnslookup_ipv6.phpt b/tests/swoole_coroutine/dnslookup_ipv6.phpt new file mode 100644 index 00000000000..af94e63859f --- /dev/null +++ b/tests/swoole_coroutine/dnslookup_ipv6.phpt @@ -0,0 +1,19 @@ +--TEST-- +swoole_coroutine: dns Lookup IPv6 +--SKIPIF-- + +--FILE-- + +--EXPECT-- diff --git a/tests/swoole_http_client_coro/get_twice.phpt b/tests/swoole_http_client_coro/get_twice.phpt index 1b7a9faec65..ce7063835eb 100644 --- a/tests/swoole_http_client_coro/get_twice.phpt +++ b/tests/swoole_http_client_coro/get_twice.phpt @@ -11,11 +11,11 @@ use Swoole\Coroutine\Http\Client; const N = 2; Swoole\Coroutine\Run(function () { - $client = new Client('www.zhe800.com', 443, true); + $client = new Client('www.baidu.com', 443, true); $client->set(['timeout' => 5,]); for ($i = 0; $i < N; $i++) { $rand = mt_rand(100000, 999999999); - $path = "/email_subscribe?email=" . $rand . "@" . substr(md5(microtime(true)), 0, 8) . ".com"; + $path = "/index.php?email=" . $rand . "@" . substr(md5(microtime(true)), 0, 8) . ".com"; $result = $client->get($path); if (!$result) { var_dump("ERROR: ".$client->getStatusCode()); diff --git a/tests/swoole_http_client_coro/get_twice_keepalive.phpt b/tests/swoole_http_client_coro/get_twice_keepalive.phpt index afed15f6fa8..963f09ec22f 100644 --- a/tests/swoole_http_client_coro/get_twice_keepalive.phpt +++ b/tests/swoole_http_client_coro/get_twice_keepalive.phpt @@ -11,11 +11,11 @@ use Swoole\Coroutine\Http\Client; const N = 2; Swoole\Coroutine\Run(function () { - $client = new Client('www.zhe800.com', 443, true); + $client = new Client('www.baidu.com', 443, true); $client->set(['timeout' => 5,]); for ($i = 0; $i < N; $i++) { $rand = mt_rand(100000, 999999999); - $path = "/email_subscribe?email=" . $rand . "@" . substr(md5(microtime(true)), 0, 8) . ".com"; + $path = "/index.php?email=" . $rand . "@" . substr(md5(microtime(true)), 0, 8) . ".com"; Assert::assert($client->get($path)); Assert::assert($client->getStatusCode() == 200); } diff --git a/tests/swoole_server/unregistered_signal.phpt b/tests/swoole_server/unregistered_signal.phpt index 8199bac5511..8abab97ec24 100644 --- a/tests/swoole_server/unregistered_signal.phpt +++ b/tests/swoole_server/unregistered_signal.phpt @@ -37,4 +37,4 @@ $pm->childFirst(); $pm->run(); ?> --EXPECTF-- -[%s] WARNING %s (ERRNO 707): Unable to find callback function for signal Broken pipe: 13 +[%s] WARNING %s (ERRNO 721): Unable to find callback function for signal Broken pipe: 13 From 5b2a9260981f3e72d275f369f76919d3f5ffe518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Fri, 25 Jun 2021 18:35:51 +0800 Subject: [PATCH 161/936] Upgrade hiredis and nghttp2 library (#4276) * sync hiredis-v1.0.0 * upgrade nghttp2 * improve redis result parser * fix tests * fix tests [2] * update library * fix tests --- CMakeLists.txt | 1 + config.m4 | 1 + ext-src/php_swoole_library.h | 57 +- ext-src/swoole_redis_coro.cc | 8 + include/swoole_coroutine_c_api.h | 1 + src/coroutine/hook.cc | 10 + thirdparty/hiredis/alloc.c | 86 + thirdparty/hiredis/alloc.h | 91 + thirdparty/hiredis/hiredis.c | 503 +- thirdparty/hiredis/hiredis.h | 155 +- thirdparty/hiredis/net.c | 238 +- thirdparty/hiredis/net.h | 6 + thirdparty/hiredis/read.c | 330 +- thirdparty/hiredis/read.h | 26 +- thirdparty/hiredis/sds.c | 38 +- thirdparty/hiredis/sds.h | 35 +- thirdparty/hiredis/sdsalloc.h | 8 +- thirdparty/nghttp2/COPYING | 23 + thirdparty/nghttp2/nghttp2.h | 169 +- thirdparty/nghttp2/nghttp2_buf.c | 6 +- thirdparty/nghttp2/nghttp2_buf.h | 2 +- thirdparty/nghttp2/nghttp2_hd.c | 44 +- thirdparty/nghttp2/nghttp2_hd.h | 13 +- thirdparty/nghttp2/nghttp2_hd_huffman.c | 222 +- thirdparty/nghttp2/nghttp2_hd_huffman.h | 30 +- thirdparty/nghttp2/nghttp2_hd_huffman_data.c | 8341 +++++++++--------- thirdparty/nghttp2/nghttp2_helper.c | 5 + thirdparty/nghttp2/nghttp2_mem.c | 13 +- 28 files changed, 5662 insertions(+), 4800 deletions(-) create mode 100644 thirdparty/hiredis/alloc.c create mode 100644 thirdparty/hiredis/alloc.h create mode 100644 thirdparty/nghttp2/COPYING diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ec60ecfcbf..33dfdbdeb86 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,7 @@ endif(CODE_COVERAGE) file(GLOB_RECURSE SRC_LIST FOLLOW_SYMLINKS src/*.c src/*.cc thirdparty/boost/asm/combined.S + thirdparty/hiredis/alloc.c thirdparty/hiredis/async.c thirdparty/hiredis/hiredis.c thirdparty/hiredis/net.c diff --git a/config.m4 b/config.m4 index cb7e639089f..498ff41a267 100644 --- a/config.m4 +++ b/config.m4 @@ -651,6 +651,7 @@ if test "$PHP_SWOOLE" != "no"; then swoole_source_file="$swoole_source_file \ thirdparty/hiredis/hiredis.c \ + thirdparty/hiredis/alloc.c \ thirdparty/hiredis/net.c \ thirdparty/hiredis/read.c \ thirdparty/hiredis/sds.c" diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index 2e8c8af2a89..c3c0033df03 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: 65ea83f61739de6203f1368150350fd3f91e3a7e */ +/* $Id: 1ed49dbae3a1850b3a67d9904e07dac9b96adb43 */ static const char* swoole_library_source_constants = "\n" @@ -81,43 +81,56 @@ static const char* swoole_library_source_core_constant = "\n" "class Constant\n" "{\n" - " public const EVENT_RECEIVE = 'receive';\n" - "\n" - " public const EVENT_CONNECT = 'connect';\n" - "\n" - " public const EVENT_CLOSE = 'close';\n" + " /* {{{ EVENT */\n" + " public const EVENT_START = 'start';\n" "\n" - " public const EVENT_PACKET = 'packet';\n" + " public const EVENT_SHUTDOWN = 'shutdown';\n" "\n" - " public const EVENT_REQUEST = 'request';\n" + " public const EVENT_WORKER_START = 'workerStart';\n" "\n" - " public const EVENT_MESSAGE = 'message';\n" + " public const EVENT_WORKER_STOP = 'workerStop';\n" "\n" - " public const EVENT_OPEN = 'open';\n" + " public const EVENT_BEFORE_RELOAD = 'beforeReload';\n" "\n" - " public const EVENT_HANDSHAKE = 'handshake';\n" + " public const EVENT_AFTER_RELOAD = 'afterReload';\n" "\n" " public const EVENT_TASK = 'task';\n" "\n" " public const EVENT_FINISH = 'finish';\n" "\n" - " public const EVENT_START = 'start';\n" - "\n" - " public const EVENT_SHUTDOWN = 'shutdown';\n" - "\n" - " public const EVENT_WORKER_START = 'workerStart';\n" - "\n" " public const EVENT_WORKER_EXIT = 'workerExit';\n" "\n" " public const EVENT_WORKER_ERROR = 'workerError';\n" "\n" - " public const EVENT_WORKER_STOP = 'workerStop';\n" + " public const EVENT_MANAGER_START = 'managerStart';\n" + "\n" + " public const EVENT_MANAGER_STOP = 'managerStop';\n" "\n" " public const EVENT_PIPE_MESSAGE = 'pipeMessage';\n" "\n" - " public const EVENT_MANAGER_START = 'managerStart';\n" + " public const EVENT_CONNECT = 'connect';\n" "\n" - " public const EVENT_MANAGER_STOP = 'managerStop';\n" + " public const EVENT_RECEIVE = 'receive';\n" + "\n" + " public const EVENT_CLOSE = 'close';\n" + "\n" + " public const EVENT_PACKET = 'packet';\n" + "\n" + " public const EVENT_BUFFER_FULL = 'bufferFull';\n" + "\n" + " public const EVENT_BUFFER_EMPTY = 'bufferEmpty';\n" + "\n" + " public const EVENT_REQUEST = 'request';\n" + "\n" + " public const EVENT_HANDSHAKE = 'handshake';\n" + "\n" + " public const EVENT_OPEN = 'open';\n" + "\n" + " public const EVENT_MESSAGE = 'message';\n" + "\n" + " public const EVENT_DISCONNECT = 'disconnect';\n" + "\n" + " /* }}} EVENT */\n" "\n" " public const EVENT_ERROR = 'error';\n" "\n" @@ -2031,7 +2044,7 @@ static const char* swoole_library_source_core_connection_pool = " }\n" " }\n" "\n" - " public function get()\n" + " public function get(float $timeout = -1)\n" " {\n" " if ($this->pool === null) {\n" " throw new RuntimeException('Pool has been closed');\n" @@ -2039,7 +2052,7 @@ static const char* swoole_library_source_core_connection_pool = " if ($this->pool->isEmpty() && $this->num < $this->size) {\n" " $this->make();\n" " }\n" - " return $this->pool->pop();\n" + " return $this->pool->pop($timeout);\n" " }\n" "\n" " public function put($connection): void\n" diff --git a/ext-src/swoole_redis_coro.cc b/ext-src/swoole_redis_coro.cc index a1955397d84..174201246c8 100644 --- a/ext-src/swoole_redis_coro.cc +++ b/ext-src/swoole_redis_coro.cc @@ -4413,6 +4413,14 @@ static void swoole_redis_coro_parse_result(RedisClient *redis, zval *return_valu ZVAL_LONG(return_value, reply->integer); break; + case REDIS_REPLY_DOUBLE: + ZVAL_DOUBLE(return_value, reply->dval); + break; + + case REDIS_REPLY_BOOL: + ZVAL_BOOL(return_value, reply->integer); + break; + case REDIS_REPLY_ERROR: ZVAL_FALSE(return_value); if (redis->context->err == 0) { diff --git a/include/swoole_coroutine_c_api.h b/include/swoole_coroutine_c_api.h index c5d689fc2be..8c3b51ea982 100644 --- a/include/swoole_coroutine_c_api.h +++ b/include/swoole_coroutine_c_api.h @@ -88,6 +88,7 @@ int swoole_coroutine_close(int fd); int swoole_coroutine_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); int swoole_coroutine_poll(struct pollfd *fds, nfds_t nfds, int timeout); int swoole_coroutine_socket_set_timeout(int fd, int which, double timeout); +int swoole_coroutine_socket_set_connect_timeout(int fd, double timeout); int swoole_coroutine_socket_wait_event(int fd, int event, double timeout); int swoole_coroutine_getaddrinfo(const char *name, const char *service, diff --git a/src/coroutine/hook.cc b/src/coroutine/hook.cc index 58498e264ad..eb60a2261aa 100644 --- a/src/coroutine/hook.cc +++ b/src/coroutine/hook.cc @@ -487,6 +487,16 @@ int swoole_coroutine_socket_set_timeout(int sockfd, int which, double timeout) { } } +int swoole_coroutine_socket_set_connect_timeout(int sockfd, double timeout) { + Socket *socket = get_socket_ex(sockfd); + if (sw_unlikely(socket == NULL)) { + errno = EINVAL; + return -1; + } + socket->set_timeout(timeout, Socket::TIMEOUT_DNS | Socket::TIMEOUT_CONNECT); + return 0; +} + int swoole_coroutine_socket_wait_event(int sockfd, int event, double timeout) { Socket *socket = get_socket_ex(sockfd); if (sw_unlikely(socket == NULL)) { diff --git a/thirdparty/hiredis/alloc.c b/thirdparty/hiredis/alloc.c new file mode 100644 index 00000000000..7fb6b35e778 --- /dev/null +++ b/thirdparty/hiredis/alloc.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2020, Michael Grunder + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Redis nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "fmacros.h" +#include "alloc.h" +#include +#include + +hiredisAllocFuncs hiredisAllocFns = { + .mallocFn = malloc, + .callocFn = calloc, + .reallocFn = realloc, + .strdupFn = strdup, + .freeFn = free, +}; + +/* Override hiredis' allocators with ones supplied by the user */ +hiredisAllocFuncs hiredisSetAllocators(hiredisAllocFuncs *override) { + hiredisAllocFuncs orig = hiredisAllocFns; + + hiredisAllocFns = *override; + + return orig; +} + +/* Reset allocators to use libc defaults */ +void hiredisResetAllocators(void) { + hiredisAllocFns = (hiredisAllocFuncs) { + .mallocFn = malloc, + .callocFn = calloc, + .reallocFn = realloc, + .strdupFn = strdup, + .freeFn = free, + }; +} + +#ifdef _WIN32 + +void *hi_malloc(size_t size) { + return hiredisAllocFns.mallocFn(size); +} + +void *hi_calloc(size_t nmemb, size_t size) { + return hiredisAllocFns.callocFn(nmemb, size); +} + +void *hi_realloc(void *ptr, size_t size) { + return hiredisAllocFns.reallocFn(ptr, size); +} + +char *hi_strdup(const char *str) { + return hiredisAllocFns.strdupFn(str); +} + +void hi_free(void *ptr) { + hiredisAllocFns.freeFn(ptr); +} + +#endif diff --git a/thirdparty/hiredis/alloc.h b/thirdparty/hiredis/alloc.h new file mode 100644 index 00000000000..34a05f49f31 --- /dev/null +++ b/thirdparty/hiredis/alloc.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2020, Michael Grunder + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Redis nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HIREDIS_ALLOC_H +#define HIREDIS_ALLOC_H + +#include /* for size_t */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Structure pointing to our actually configured allocators */ +typedef struct hiredisAllocFuncs { + void *(*mallocFn)(size_t); + void *(*callocFn)(size_t,size_t); + void *(*reallocFn)(void*,size_t); + char *(*strdupFn)(const char*); + void (*freeFn)(void*); +} hiredisAllocFuncs; + +hiredisAllocFuncs hiredisSetAllocators(hiredisAllocFuncs *ha); +void hiredisResetAllocators(void); + +#ifndef _WIN32 + +/* Hiredis' configured allocator function pointer struct */ +extern hiredisAllocFuncs hiredisAllocFns; + +static inline void *hi_malloc(size_t size) { + return hiredisAllocFns.mallocFn(size); +} + +static inline void *hi_calloc(size_t nmemb, size_t size) { + return hiredisAllocFns.callocFn(nmemb, size); +} + +static inline void *hi_realloc(void *ptr, size_t size) { + return hiredisAllocFns.reallocFn(ptr, size); +} + +static inline char *hi_strdup(const char *str) { + return hiredisAllocFns.strdupFn(str); +} + +static inline void hi_free(void *ptr) { + hiredisAllocFns.freeFn(ptr); +} + +#else + +void *hi_malloc(size_t size); +void *hi_calloc(size_t nmemb, size_t size); +void *hi_realloc(void *ptr, size_t size); +char *hi_strdup(const char *str); +void hi_free(void *ptr); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* HIREDIS_ALLOC_H */ diff --git a/thirdparty/hiredis/hiredis.c b/thirdparty/hiredis/hiredis.c index 69265eb9bbe..0a01e68754c 100644 --- a/thirdparty/hiredis/hiredis.c +++ b/thirdparty/hiredis/hiredis.c @@ -34,7 +34,6 @@ #include "fmacros.h" #include #include -#include #include #include #include @@ -45,11 +44,22 @@ #include "swoole_socket_hook.h" +extern int redisContextUpdateConnectTimeout(redisContext *c, const struct timeval *timeout); +extern int redisContextUpdateCommandTimeout(redisContext *c, const struct timeval *timeout); + +static redisContextFuncs redisContextDefaultFuncs = { + .free_privctx = NULL, + .read_ = redisNetRead, + .write_ = redisNetWrite +}; + static redisReply *createReplyObject(int type); static void *createStringObject(const redisReadTask *task, char *str, size_t len); -static void *createArrayObject(const redisReadTask *task, int elements); +static void *createArrayObject(const redisReadTask *task, size_t elements); static void *createIntegerObject(const redisReadTask *task, long long value); +static void *createDoubleObject(const redisReadTask *task, double value, char *str, size_t len); static void *createNilObject(const redisReadTask *task); +static void *createBoolObject(const redisReadTask *task, int bval); /* Default set of functions to build the reply. Keep in mind that such a * function returning NULL is interpreted as OOM. */ @@ -57,13 +67,15 @@ static redisReplyObjectFunctions defaultFunctions = { createStringObject, createArrayObject, createIntegerObject, + createDoubleObject, createNilObject, + createBoolObject, freeReplyObject }; /* Create a reply object */ static redisReply *createReplyObject(int type) { - redisReply *r = calloc(1,sizeof(*r)); + redisReply *r = hi_calloc(1,sizeof(*r)); if (r == NULL) return NULL; @@ -82,21 +94,29 @@ void freeReplyObject(void *reply) { switch(r->type) { case REDIS_REPLY_INTEGER: + case REDIS_REPLY_NIL: + case REDIS_REPLY_BOOL: break; /* Nothing to free */ case REDIS_REPLY_ARRAY: + case REDIS_REPLY_MAP: + case REDIS_REPLY_SET: + case REDIS_REPLY_PUSH: if (r->element != NULL) { for (j = 0; j < r->elements; j++) freeReplyObject(r->element[j]); - free(r->element); + hi_free(r->element); } break; case REDIS_REPLY_ERROR: case REDIS_REPLY_STATUS: case REDIS_REPLY_STRING: - free(r->str); + case REDIS_REPLY_DOUBLE: + case REDIS_REPLY_VERB: + case REDIS_REPLY_BIGNUM: + hi_free(r->str); break; } - free(r); + hi_free(r); } static void *createStringObject(const redisReadTask *task, char *str, size_t len) { @@ -107,39 +127,56 @@ static void *createStringObject(const redisReadTask *task, char *str, size_t len if (r == NULL) return NULL; - buf = malloc(len+1); - if (buf == NULL) { - freeReplyObject(r); - return NULL; - } - assert(task->type == REDIS_REPLY_ERROR || task->type == REDIS_REPLY_STATUS || - task->type == REDIS_REPLY_STRING); + task->type == REDIS_REPLY_STRING || + task->type == REDIS_REPLY_VERB || + task->type == REDIS_REPLY_BIGNUM); /* Copy string value */ - memcpy(buf,str,len); - buf[len] = '\0'; + if (task->type == REDIS_REPLY_VERB) { + buf = hi_malloc(len-4+1); /* Skip 4 bytes of verbatim type header. */ + if (buf == NULL) goto oom; + + memcpy(r->vtype,str,3); + r->vtype[3] = '\0'; + memcpy(buf,str+4,len-4); + buf[len-4] = '\0'; + r->len = len - 4; + } else { + buf = hi_malloc(len+1); + if (buf == NULL) goto oom; + + memcpy(buf,str,len); + buf[len] = '\0'; + r->len = len; + } r->str = buf; - r->len = len; if (task->parent) { parent = task->parent->obj; - assert(parent->type == REDIS_REPLY_ARRAY); + assert(parent->type == REDIS_REPLY_ARRAY || + parent->type == REDIS_REPLY_MAP || + parent->type == REDIS_REPLY_SET || + parent->type == REDIS_REPLY_PUSH); parent->element[task->idx] = r; } return r; + +oom: + freeReplyObject(r); + return NULL; } -static void *createArrayObject(const redisReadTask *task, int elements) { +static void *createArrayObject(const redisReadTask *task, size_t elements) { redisReply *r, *parent; - r = createReplyObject(REDIS_REPLY_ARRAY); + r = createReplyObject(task->type); if (r == NULL) return NULL; if (elements > 0) { - r->element = calloc(elements,sizeof(redisReply*)); + r->element = hi_calloc(elements,sizeof(redisReply*)); if (r->element == NULL) { freeReplyObject(r); return NULL; @@ -150,7 +187,10 @@ static void *createArrayObject(const redisReadTask *task, int elements) { if (task->parent) { parent = task->parent->obj; - assert(parent->type == REDIS_REPLY_ARRAY); + assert(parent->type == REDIS_REPLY_ARRAY || + parent->type == REDIS_REPLY_MAP || + parent->type == REDIS_REPLY_SET || + parent->type == REDIS_REPLY_PUSH); parent->element[task->idx] = r; } return r; @@ -167,7 +207,44 @@ static void *createIntegerObject(const redisReadTask *task, long long value) { if (task->parent) { parent = task->parent->obj; - assert(parent->type == REDIS_REPLY_ARRAY); + assert(parent->type == REDIS_REPLY_ARRAY || + parent->type == REDIS_REPLY_MAP || + parent->type == REDIS_REPLY_SET || + parent->type == REDIS_REPLY_PUSH); + parent->element[task->idx] = r; + } + return r; +} + +static void *createDoubleObject(const redisReadTask *task, double value, char *str, size_t len) { + redisReply *r, *parent; + + r = createReplyObject(REDIS_REPLY_DOUBLE); + if (r == NULL) + return NULL; + + r->dval = value; + r->str = hi_malloc(len+1); + if (r->str == NULL) { + freeReplyObject(r); + return NULL; + } + + /* The double reply also has the original protocol string representing a + * double as a null terminated string. This way the caller does not need + * to format back for string conversion, especially since Redis does efforts + * to make the string more human readable avoiding the calssical double + * decimal string conversion artifacts. */ + memcpy(r->str, str, len); + r->str[len] = '\0'; + r->len = len; + + if (task->parent) { + parent = task->parent->obj; + assert(parent->type == REDIS_REPLY_ARRAY || + parent->type == REDIS_REPLY_MAP || + parent->type == REDIS_REPLY_SET || + parent->type == REDIS_REPLY_PUSH); parent->element[task->idx] = r; } return r; @@ -182,7 +259,30 @@ static void *createNilObject(const redisReadTask *task) { if (task->parent) { parent = task->parent->obj; - assert(parent->type == REDIS_REPLY_ARRAY); + assert(parent->type == REDIS_REPLY_ARRAY || + parent->type == REDIS_REPLY_MAP || + parent->type == REDIS_REPLY_SET || + parent->type == REDIS_REPLY_PUSH); + parent->element[task->idx] = r; + } + return r; +} + +static void *createBoolObject(const redisReadTask *task, int bval) { + redisReply *r, *parent; + + r = createReplyObject(REDIS_REPLY_BOOL); + if (r == NULL) + return NULL; + + r->integer = bval != 0; + + if (task->parent) { + parent = task->parent->obj; + assert(parent->type == REDIS_REPLY_ARRAY || + parent->type == REDIS_REPLY_MAP || + parent->type == REDIS_REPLY_SET || + parent->type == REDIS_REPLY_PUSH); parent->element[task->idx] = r; } return r; @@ -200,6 +300,7 @@ static uint32_t countDigits(uint64_t v) { v /= 10000U; result += 4; } + return result; } /* Helper that calculates the bulk length given a certain string length. */ @@ -232,7 +333,7 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) { if (*c != '%' || c[1] == '\0') { if (*c == ' ') { if (touched) { - newargv = realloc(curargv,sizeof(char*)*(argc+1)); + newargv = hi_realloc(curargv,sizeof(char*)*(argc+1)); if (newargv == NULL) goto memory_err; curargv = newargv; curargv[argc++] = curarg; @@ -381,7 +482,7 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) { /* Add the last argument if needed */ if (touched) { - newargv = realloc(curargv,sizeof(char*)*(argc+1)); + newargv = hi_realloc(curargv,sizeof(char*)*(argc+1)); if (newargv == NULL) goto memory_err; curargv = newargv; curargv[argc++] = curarg; @@ -397,7 +498,7 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) { totlen += 1+countDigits(argc)+2; /* Build the command at protocol level */ - cmd = malloc(totlen+1); + cmd = hi_malloc(totlen+1); if (cmd == NULL) goto memory_err; pos = sprintf(cmd,"*%d\r\n",argc); @@ -412,7 +513,7 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) { assert(pos == totlen); cmd[pos] = '\0'; - free(curargv); + hi_free(curargv); *target = cmd; return totlen; @@ -428,11 +529,11 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) { if (curargv) { while(argc--) sdsfree(curargv[argc]); - free(curargv); + hi_free(curargv); } sdsfree(curarg); - free(cmd); + hi_free(cmd); return error_type; } @@ -473,7 +574,7 @@ int redisFormatCommand(char **target, const char *format, ...) { int redisFormatSdsCommandArgv(sds *target, int argc, const char **argv, const size_t *argvlen) { - sds cmd; + sds cmd, aux; unsigned long long totlen; int j; size_t len; @@ -495,9 +596,13 @@ int redisFormatSdsCommandArgv(sds *target, int argc, const char **argv, return -1; /* We already know how much storage we need */ - cmd = sdsMakeRoomFor(cmd, totlen); - if (cmd == NULL) + aux = sdsMakeRoomFor(cmd, totlen); + if (aux == NULL) { + sdsfree(cmd); return -1; + } + + cmd = aux; /* Construct command */ cmd = sdscatfmt(cmd, "*%i\r\n", argc); @@ -541,7 +646,7 @@ int redisFormatCommandArgv(char **target, int argc, const char **argv, const siz } /* Build the command at protocol level */ - cmd = malloc(totlen+1); + cmd = hi_malloc(totlen+1); if (cmd == NULL) return -1; @@ -562,7 +667,7 @@ int redisFormatCommandArgv(char **target, int argc, const char **argv, const siz } void redisFreeCommand(char *cmd) { - free(cmd); + hi_free(cmd); } void __redisSetError(redisContext *c, int type, const char *str) { @@ -585,15 +690,23 @@ redisReader *redisReaderCreate(void) { return redisReaderCreateWithFunctions(&defaultFunctions); } +static void redisPushAutoFree(void *privdata, void *reply) { + (void)privdata; + freeReplyObject(reply); +} + static redisContext *redisContextInit(void) { redisContext *c; - c = calloc(1,sizeof(redisContext)); + c = hi_calloc(1, sizeof(*c)); if (c == NULL) return NULL; + c->funcs = &redisContextDefaultFuncs; + c->obuf = sdsempty(); c->reader = redisReaderCreate(); + c->fd = REDIS_INVALID_FD; if (c->obuf == NULL || c->reader == NULL) { redisFree(c); @@ -606,22 +719,30 @@ static redisContext *redisContextInit(void) { void redisFree(redisContext *c) { if (c == NULL) return; - if (c->fd > 0) - close(c->fd); + redisNetClose(c); sdsfree(c->obuf); redisReaderFree(c->reader); - free(c->tcp.host); - free(c->tcp.source_addr); - free(c->unix_sock.path); - free(c->timeout); - free(c->saddr); - free(c); + hi_free(c->tcp.host); + hi_free(c->tcp.source_addr); + hi_free(c->unix_sock.path); + hi_free(c->connect_timeout); + hi_free(c->command_timeout); + hi_free(c->saddr); + + if (c->privdata && c->free_privdata) + c->free_privdata(c->privdata); + + if (c->funcs->free_privctx) + c->funcs->free_privctx(c->privctx); + + memset(c, 0xff, sizeof(*c)); + hi_free(c); } -int redisFreeKeepFd(redisContext *c) { - int fd = c->fd; - c->fd = -1; +redisFD redisFreeKeepFd(redisContext *c) { + redisFD fd = c->fd; + c->fd = REDIS_INVALID_FD; redisFree(c); return fd; } @@ -630,136 +751,163 @@ int redisReconnect(redisContext *c) { c->err = 0; memset(c->errstr, '\0', strlen(c->errstr)); - if (c->fd > 0) { - close(c->fd); + if (c->privctx && c->funcs->free_privctx) { + c->funcs->free_privctx(c->privctx); + c->privctx = NULL; } + redisNetClose(c); + sdsfree(c->obuf); redisReaderFree(c->reader); c->obuf = sdsempty(); c->reader = redisReaderCreate(); + if (c->obuf == NULL || c->reader == NULL) { + __redisSetError(c, REDIS_ERR_OOM, "Out of memory"); + return REDIS_ERR; + } + + int ret = REDIS_ERR; if (c->connection_type == REDIS_CONN_TCP) { - return redisContextConnectBindTcp(c, c->tcp.host, c->tcp.port, - c->timeout, c->tcp.source_addr); + ret = redisContextConnectBindTcp(c, c->tcp.host, c->tcp.port, + c->connect_timeout, c->tcp.source_addr); } else if (c->connection_type == REDIS_CONN_UNIX) { - return redisContextConnectUnix(c, c->unix_sock.path, c->timeout); + ret = redisContextConnectUnix(c, c->unix_sock.path, c->connect_timeout); } else { /* Something bad happened here and shouldn't have. There isn't enough information in the context to reconnect. */ __redisSetError(c,REDIS_ERR_OTHER,"Not enough information to reconnect"); + ret = REDIS_ERR; } - return REDIS_ERR; -} + if (c->command_timeout != NULL && (c->flags & REDIS_BLOCK) && c->fd != REDIS_INVALID_FD) { + redisContextSetTimeout(c, *c->command_timeout); + } -/* Connect to a Redis instance. On error the field error in the returned - * context will be set to the return value of the error function. - * When no set of reply functions is given, the default set will be used. */ -redisContext *redisConnect(const char *ip, int port) { - redisContext *c; + return ret; +} - c = redisContextInit(); - if (c == NULL) +redisContext *redisConnectWithOptions(const redisOptions *options) { + redisContext *c = redisContextInit(); + if (c == NULL) { return NULL; + } + if (!(options->options & REDIS_OPT_NONBLOCK)) { + c->flags |= REDIS_BLOCK; + } + if (options->options & REDIS_OPT_REUSEADDR) { + c->flags |= REDIS_REUSEADDR; + } + if (options->options & REDIS_OPT_NOAUTOFREE) { + c->flags |= REDIS_NO_AUTO_FREE; + } - c->flags |= REDIS_BLOCK; - redisContextConnectTcp(c,ip,port,NULL); - return c; -} + /* Set any user supplied RESP3 PUSH handler or use freeReplyObject + * as a default unless specifically flagged that we don't want one. */ + if (options->push_cb != NULL) + redisSetPushCallback(c, options->push_cb); + else if (!(options->options & REDIS_OPT_NO_PUSH_AUTOFREE)) + redisSetPushCallback(c, redisPushAutoFree); -redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv) { - redisContext *c; + c->privdata = options->privdata; + c->free_privdata = options->free_privdata; - c = redisContextInit(); - if (c == NULL) + if (redisContextUpdateConnectTimeout(c, options->connect_timeout) != REDIS_OK || + redisContextUpdateCommandTimeout(c, options->command_timeout) != REDIS_OK) { + __redisSetError(c, REDIS_ERR_OOM, "Out of memory"); + return c; + } + + if (options->type == REDIS_CONN_TCP) { + redisContextConnectBindTcp(c, options->endpoint.tcp.ip, + options->endpoint.tcp.port, options->connect_timeout, + options->endpoint.tcp.source_addr); + } else if (options->type == REDIS_CONN_UNIX) { + redisContextConnectUnix(c, options->endpoint.unix_socket, + options->connect_timeout); + } else if (options->type == REDIS_CONN_USERFD) { + c->fd = options->endpoint.fd; + c->flags |= REDIS_CONNECTED; + } else { + // Unknown type - FIXME - FREE return NULL; + } + + if (options->command_timeout != NULL && (c->flags & REDIS_BLOCK) && c->fd != REDIS_INVALID_FD) { + redisContextSetTimeout(c, *options->command_timeout); + } - c->flags |= REDIS_BLOCK; - redisContextConnectTcp(c,ip,port,&tv); return c; } -redisContext *redisConnectNonBlock(const char *ip, int port) { - redisContext *c; +/* Connect to a Redis instance. On error the field error in the returned + * context will be set to the return value of the error function. + * When no set of reply functions is given, the default set will be used. */ +redisContext *redisConnect(const char *ip, int port) { + redisOptions options = {0}; + REDIS_OPTIONS_SET_TCP(&options, ip, port); + return redisConnectWithOptions(&options); +} - c = redisContextInit(); - if (c == NULL) - return NULL; +redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv) { + redisOptions options = {0}; + REDIS_OPTIONS_SET_TCP(&options, ip, port); + options.connect_timeout = &tv; + return redisConnectWithOptions(&options); +} - c->flags &= ~REDIS_BLOCK; - redisContextConnectTcp(c,ip,port,NULL); - return c; +redisContext *redisConnectNonBlock(const char *ip, int port) { + redisOptions options = {0}; + REDIS_OPTIONS_SET_TCP(&options, ip, port); + options.options |= REDIS_OPT_NONBLOCK; + return redisConnectWithOptions(&options); } redisContext *redisConnectBindNonBlock(const char *ip, int port, const char *source_addr) { - redisContext *c = redisContextInit(); - if (c == NULL) - return NULL; - c->flags &= ~REDIS_BLOCK; - redisContextConnectBindTcp(c,ip,port,NULL,source_addr); - return c; + redisOptions options = {0}; + REDIS_OPTIONS_SET_TCP(&options, ip, port); + options.endpoint.tcp.source_addr = source_addr; + options.options |= REDIS_OPT_NONBLOCK; + return redisConnectWithOptions(&options); } redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port, const char *source_addr) { - redisContext *c = redisContextInit(); - if (c == NULL) - return NULL; - c->flags &= ~REDIS_BLOCK; - c->flags |= REDIS_REUSEADDR; - redisContextConnectBindTcp(c,ip,port,NULL,source_addr); - return c; + redisOptions options = {0}; + REDIS_OPTIONS_SET_TCP(&options, ip, port); + options.endpoint.tcp.source_addr = source_addr; + options.options |= REDIS_OPT_NONBLOCK|REDIS_OPT_REUSEADDR; + return redisConnectWithOptions(&options); } redisContext *redisConnectUnix(const char *path) { - redisContext *c; - - c = redisContextInit(); - if (c == NULL) - return NULL; - - c->flags |= REDIS_BLOCK; - redisContextConnectUnix(c,path,NULL); - return c; + redisOptions options = {0}; + REDIS_OPTIONS_SET_UNIX(&options, path); + return redisConnectWithOptions(&options); } redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv) { - redisContext *c; - - c = redisContextInit(); - if (c == NULL) - return NULL; - - c->flags |= REDIS_BLOCK; - redisContextConnectUnix(c,path,&tv); - return c; + redisOptions options = {0}; + REDIS_OPTIONS_SET_UNIX(&options, path); + options.connect_timeout = &tv; + return redisConnectWithOptions(&options); } redisContext *redisConnectUnixNonBlock(const char *path) { - redisContext *c; - - c = redisContextInit(); - if (c == NULL) - return NULL; - - c->flags &= ~REDIS_BLOCK; - redisContextConnectUnix(c,path,NULL); - return c; + redisOptions options = {0}; + REDIS_OPTIONS_SET_UNIX(&options, path); + options.options |= REDIS_OPT_NONBLOCK; + return redisConnectWithOptions(&options); } -redisContext *redisConnectFd(int fd) { - redisContext *c; - - c = redisContextInit(); - if (c == NULL) - return NULL; - - c->fd = fd; - c->flags |= REDIS_BLOCK | REDIS_CONNECTED; - return c; +redisContext *redisConnectFd(redisFD fd) { + redisOptions options = {0}; + options.type = REDIS_CONN_USERFD; + options.endpoint.fd = fd; + return redisConnectWithOptions(&options); } /* Set read/write timeout on a blocking socket. */ @@ -776,6 +924,13 @@ int redisEnableKeepAlive(redisContext *c) { return REDIS_OK; } +/* Set a user provided RESP3 PUSH handler and return any old one set. */ +redisPushFn *redisSetPushCallback(redisContext *c, redisPushFn *fn) { + redisPushFn *old = c->push_cb; + c->push_cb = fn; + return old; +} + /* Use this function to handle a read event on the descriptor. It will try * and read some bytes from the socket and feed them to the reply parser. * @@ -789,22 +944,13 @@ int redisBufferRead(redisContext *c) { if (c->err) return REDIS_ERR; - nread = read(c->fd,buf,sizeof(buf)); - if (nread == -1) { - if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) { - /* Try again later */ - } else { - __redisSetError(c,REDIS_ERR_IO,NULL); - return REDIS_ERR; - } - } else if (nread == 0) { - __redisSetError(c,REDIS_ERR_EOF,"Server closed the connection"); + nread = c->funcs->read_(c, buf, sizeof(buf)); + if (nread < 0) { + return REDIS_ERR; + } + if (nread > 0 && redisReaderFeed(c->reader, buf, nread) != REDIS_OK) { + __redisSetError(c, c->reader->err, c->reader->errstr); return REDIS_ERR; - } else { - if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) { - __redisSetError(c,c->reader->err,c->reader->errstr); - return REDIS_ERR; - } } return REDIS_OK; } @@ -819,41 +965,64 @@ int redisBufferRead(redisContext *c) { * c->errstr to hold the appropriate error string. */ int redisBufferWrite(redisContext *c, int *done) { - int nwritten; /* Return early when the context has seen an error. */ if (c->err) return REDIS_ERR; if (sdslen(c->obuf) > 0) { - nwritten = write(c->fd,c->obuf,sdslen(c->obuf)); - if (nwritten == -1) { - if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) { - /* Try again later */ - } else { - __redisSetError(c,REDIS_ERR_IO,NULL); - return REDIS_ERR; - } + ssize_t nwritten = c->funcs->write_(c); + if (nwritten < 0) { + return REDIS_ERR; } else if (nwritten > 0) { - if (nwritten == (signed)sdslen(c->obuf)) { + if (nwritten == (ssize_t)sdslen(c->obuf)) { sdsfree(c->obuf); c->obuf = sdsempty(); + if (c->obuf == NULL) + goto oom; } else { - sdsrange(c->obuf,nwritten,-1); + if (sdsrange(c->obuf,nwritten,-1) < 0) goto oom; } } } if (done != NULL) *done = (sdslen(c->obuf) == 0); return REDIS_OK; + +oom: + __redisSetError(c, REDIS_ERR_OOM, "Out of memory"); + return REDIS_ERR; +} + +/* Internal helper that returns 1 if the reply was a RESP3 PUSH + * message and we handled it with a user-provided callback. */ +static int redisHandledPushReply(redisContext *c, void *reply) { + if (reply && c->push_cb && redisIsPushReply(reply)) { + c->push_cb(c->privdata, reply); + return 1; + } + + return 0; } -/* Internal helper function to try and get a reply from the reader, - * or set an error in the context otherwise. */ +/* Get a reply from our reader or set an error in the context. */ int redisGetReplyFromReader(redisContext *c, void **reply) { - if (redisReaderGetReply(c->reader,reply) == REDIS_ERR) { + if (redisReaderGetReply(c->reader, reply) == REDIS_ERR) { __redisSetError(c,c->reader->err,c->reader->errstr); return REDIS_ERR; } + + return REDIS_OK; +} + +/* Internal helper to get the next reply from our reader while handling + * any PUSH messages we encounter along the way. This is separate from + * redisGetReplyFromReader so as to not change its behavior. */ +static int redisNextInBandReplyFromReader(redisContext *c, void **reply) { + do { + if (redisGetReplyFromReader(c, reply) == REDIS_ERR) + return REDIS_ERR; + } while (redisHandledPushReply(c, *reply)); + return REDIS_OK; } @@ -862,11 +1031,11 @@ int redisGetReply(redisContext *c, void **reply) { void *aux = NULL; /* Try to read pending replies */ - if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) + if (redisNextInBandReplyFromReader(c,&aux) == REDIS_ERR) return REDIS_ERR; /* For the blocking context, flush output buffer and read reply */ - if (aux == NULL && c->flags & REDIS_BLOCK) { + if (aux == NULL && (c->flags & REDIS_BLOCK)) { /* Write until done */ do { if (redisBufferWrite(c,&wdone) == REDIS_ERR) @@ -877,13 +1046,19 @@ int redisGetReply(redisContext *c, void **reply) { do { if (redisBufferRead(c) == REDIS_ERR) return REDIS_ERR; - if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) + + if (redisNextInBandReplyFromReader(c,&aux) == REDIS_ERR) return REDIS_ERR; } while (aux == NULL); } - /* Set reply object */ - if (reply != NULL) *reply = aux; + /* Set reply or free it if we were passed NULL */ + if (reply != NULL) { + *reply = aux; + } else { + freeReplyObject(aux); + } + return REDIS_OK; } @@ -930,11 +1105,11 @@ int redisvAppendCommand(redisContext *c, const char *format, va_list ap) { } if (__redisAppendCommand(c,cmd,len) != REDIS_OK) { - free(cmd); + hi_free(cmd); return REDIS_ERR; } - free(cmd); + hi_free(cmd); return REDIS_OK; } diff --git a/thirdparty/hiredis/hiredis.h b/thirdparty/hiredis/hiredis.h index 1b0d5e65929..dd29f0b1fc3 100644 --- a/thirdparty/hiredis/hiredis.h +++ b/thirdparty/hiredis/hiredis.h @@ -35,14 +35,20 @@ #define __HIREDIS_H #include "read.h" #include /* for va_list */ +#ifndef _MSC_VER #include /* for struct timeval */ +#else +struct timeval; /* forward declaration */ +typedef long long ssize_t; +#endif #include /* uintXX_t, etc */ #include "sds.h" /* for sds */ +#include "alloc.h" /* for allocation wrappers */ -#define HIREDIS_MAJOR 0 -#define HIREDIS_MINOR 14 -#define HIREDIS_PATCH 0 -#define HIREDIS_SONAME 0.14 +#define HIREDIS_MAJOR 1 +#define HIREDIS_MINOR 0 +#define HIREDIS_PATCH 1 +#define HIREDIS_SONAME 1.0.1-dev /* Connection type can be blocking or non-blocking and is set in the * least significant bit of the flags field in redisContext. */ @@ -74,12 +80,27 @@ /* Flag that is set when we should set SO_REUSEADDR before calling bind() */ #define REDIS_REUSEADDR 0x80 +/** + * Flag that indicates the user does not want the context to + * be automatically freed upon error + */ +#define REDIS_NO_AUTO_FREE 0x200 + #define REDIS_KEEPALIVE_INTERVAL 15 /* seconds */ /* number of times we retry to connect in the case of EADDRNOTAVAIL and * SO_REUSEADDR is being used. */ #define REDIS_CONNECT_RETRIES 10 +/* Forward declarations for structs defined elsewhere */ +struct redisAsyncContext; +struct redisContext; + +/* RESP3 push helpers and callback prototypes */ +#define redisIsPushReply(r) (((redisReply*)(r))->type == REDIS_REPLY_PUSH) +typedef void (redisPushFn)(void *, void *); +typedef void (redisAsyncPushFn)(struct redisAsyncContext *, void *); + #ifdef __cplusplus extern "C" { #endif @@ -88,8 +109,13 @@ extern "C" { typedef struct redisReply { int type; /* REDIS_REPLY_* */ long long integer; /* The integer when type is REDIS_REPLY_INTEGER */ + double dval; /* The double when type is REDIS_REPLY_DOUBLE */ size_t len; /* Length of string */ - char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */ + char *str; /* Used for REDIS_REPLY_ERROR, REDIS_REPLY_STRING + REDIS_REPLY_VERB, REDIS_REPLY_DOUBLE (in additional to dval), + and REDIS_REPLY_BIGNUM. */ + char vtype[4]; /* Used for REDIS_REPLY_VERB, contains the null + terminated 3 character content type, such as "txt". */ size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */ struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */ } redisReply; @@ -109,20 +135,113 @@ void redisFreeSdsCommand(sds cmd); enum redisConnectionType { REDIS_CONN_TCP, - REDIS_CONN_UNIX + REDIS_CONN_UNIX, + REDIS_CONN_USERFD }; +struct redisSsl; + +#define REDIS_OPT_NONBLOCK 0x01 +#define REDIS_OPT_REUSEADDR 0x02 + +/** + * Don't automatically free the async object on a connection failure, + * or other implicit conditions. Only free on an explicit call to disconnect() or free() + */ +#define REDIS_OPT_NOAUTOFREE 0x04 + +/* Don't automatically intercept and free RESP3 PUSH replies. */ +#define REDIS_OPT_NO_PUSH_AUTOFREE 0x08 + +/* In Unix systems a file descriptor is a regular signed int, with -1 + * representing an invalid descriptor. In Windows it is a SOCKET + * (32- or 64-bit unsigned integer depending on the architecture), where + * all bits set (~0) is INVALID_SOCKET. */ +#ifndef _WIN32 +typedef int redisFD; +#define REDIS_INVALID_FD -1 +#else +#ifdef _WIN64 +typedef unsigned long long redisFD; /* SOCKET = 64-bit UINT_PTR */ +#else +typedef unsigned long redisFD; /* SOCKET = 32-bit UINT_PTR */ +#endif +#define REDIS_INVALID_FD ((redisFD)(~0)) /* INVALID_SOCKET */ +#endif + +typedef struct { + /* + * the type of connection to use. This also indicates which + * `endpoint` member field to use + */ + int type; + /* bit field of REDIS_OPT_xxx */ + int options; + /* timeout value for connect operation. If NULL, no timeout is used */ + const struct timeval *connect_timeout; + /* timeout value for commands. If NULL, no timeout is used. This can be + * updated at runtime with redisSetTimeout/redisAsyncSetTimeout. */ + const struct timeval *command_timeout; + union { + /** use this field for tcp/ip connections */ + struct { + const char *source_addr; + const char *ip; + int port; + } tcp; + /** use this field for unix domain sockets */ + const char *unix_socket; + /** + * use this field to have hiredis operate an already-open + * file descriptor */ + redisFD fd; + } endpoint; + + /* Optional user defined data/destructor */ + void *privdata; + void (*free_privdata)(void *); + + /* A user defined PUSH message callback */ + redisPushFn *push_cb; + redisAsyncPushFn *async_push_cb; +} redisOptions; + +/** + * Helper macros to initialize options to their specified fields. + */ +#define REDIS_OPTIONS_SET_TCP(opts, ip_, port_) \ + (opts)->type = REDIS_CONN_TCP; \ + (opts)->endpoint.tcp.ip = ip_; \ + (opts)->endpoint.tcp.port = port_; + +#define REDIS_OPTIONS_SET_UNIX(opts, path) \ + (opts)->type = REDIS_CONN_UNIX; \ + (opts)->endpoint.unix_socket = path; + +#define REDIS_OPTIONS_SET_PRIVDATA(opts, data, dtor) \ + (opts)->privdata = data; \ + (opts)->free_privdata = dtor; \ + +typedef struct redisContextFuncs { + void (*free_privctx)(void *); + ssize_t (*read_)(struct redisContext *, char *, size_t); + ssize_t (*write_)(struct redisContext *); +} redisContextFuncs; + /* Context for a connection to Redis */ typedef struct redisContext { + const redisContextFuncs *funcs; /* Function table */ + int err; /* Error flags, 0 when there is no error */ char errstr[128]; /* String representation of error when applicable */ - int fd; + redisFD fd; int flags; char *obuf; /* Write buffer */ redisReader *reader; /* Protocol reader */ enum redisConnectionType connection_type; - struct timeval *timeout; + struct timeval *connect_timeout; + struct timeval *command_timeout; struct { char *host; @@ -135,10 +254,23 @@ typedef struct redisContext { } unix_sock; /* For non-blocking connect */ - struct sockadr *saddr; + struct sockaddr *saddr; size_t addrlen; + + /* Optional data and corresponding destructor users can use to provide + * context to a given redisContext. Not used by hiredis. */ + void *privdata; + void (*free_privdata)(void *); + + /* Internal context pointer presently used by hiredis to manage + * SSL connections. */ + void *privctx; + + /* An optional RESP3 PUSH handler */ + redisPushFn *push_cb; } redisContext; +redisContext *redisConnectWithOptions(const redisOptions *options); redisContext *redisConnect(const char *ip, int port); redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv); redisContext *redisConnectNonBlock(const char *ip, int port); @@ -149,7 +281,7 @@ redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port, redisContext *redisConnectUnix(const char *path); redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv); redisContext *redisConnectUnixNonBlock(const char *path); -redisContext *redisConnectFd(int fd); +redisContext *redisConnectFd(redisFD fd); /** * Reconnect the given context using the saved information. @@ -162,10 +294,11 @@ redisContext *redisConnectFd(int fd); */ int redisReconnect(redisContext *c); +redisPushFn *redisSetPushCallback(redisContext *c, redisPushFn *fn); int redisSetTimeout(redisContext *c, const struct timeval tv); int redisEnableKeepAlive(redisContext *c); void redisFree(redisContext *c); -int redisFreeKeepFd(redisContext *c); +redisFD redisFreeKeepFd(redisContext *c); int redisBufferRead(redisContext *c); int redisBufferWrite(redisContext *c, int *done); diff --git a/thirdparty/hiredis/net.c b/thirdparty/hiredis/net.c index bab9be254af..510df7d44a7 100644 --- a/thirdparty/hiredis/net.c +++ b/thirdparty/hiredis/net.c @@ -59,13 +59,52 @@ /* Defined in hiredis.c */ void __redisSetError(redisContext *c, int type, const char *str); -static void redisContextCloseFd(redisContext *c) { - if (c && c->fd >= 0) { +void redisNetClose(redisContext *c) { + if (c && c->fd != REDIS_INVALID_FD) { close(c->fd); - c->fd = -1; + c->fd = REDIS_INVALID_FD; } } +ssize_t redisNetRead(redisContext *c, char *buf, size_t bufcap) { + ssize_t nread = recv(c->fd, buf, bufcap, 0); + if (nread == -1) { + if ((errno == EWOULDBLOCK && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) { + /* Try again later */ + return 0; + } +#if 0 + else if(errno == ETIMEDOUT && (c->flags & REDIS_BLOCK)) { + /* especially in windows */ + __redisSetError(c, REDIS_ERR_TIMEOUT, "recv timeout"); + return -1; + } +#endif + else { + __redisSetError(c, REDIS_ERR_IO, NULL); + return -1; + } + } else if (nread == 0) { + __redisSetError(c, REDIS_ERR_EOF, "Server closed the connection"); + return -1; + } else { + return nread; + } +} + +ssize_t redisNetWrite(redisContext *c) { + ssize_t nwritten = send(c->fd, c->obuf, sdslen(c->obuf), 0); + if (nwritten < 0) { + if ((errno == EWOULDBLOCK && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) { + /* Try again later */ + } else { + __redisSetError(c, REDIS_ERR_IO, NULL); + return -1; + } + } + return nwritten; +} + static void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) { int errorno = errno; /* snprintf() may change errno */ char buf[128] = { 0 }; @@ -81,15 +120,15 @@ static int redisSetReuseAddr(redisContext *c) { int on = 1; if (setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - redisContextCloseFd(c); + redisNetClose(c); return REDIS_ERR; } return REDIS_OK; } static int redisCreateSocket(redisContext *c, int type) { - int s; - if ((s = socket(type, SOCK_STREAM, 0)) == -1) { + redisFD s; + if ((s = socket(type, SOCK_STREAM, 0)) == REDIS_INVALID_FD) { __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); return REDIS_ERR; } @@ -104,6 +143,7 @@ static int redisCreateSocket(redisContext *c, int type) { static int redisSetBlocking(redisContext *c, int blocking) { #if 0 +#ifndef _WIN32 int flags; /* Set the socket nonblocking. @@ -111,7 +151,7 @@ static int redisSetBlocking(redisContext *c, int blocking) { * interrupted by a signal. */ if ((flags = fcntl(c->fd, F_GETFL)) == -1) { __redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_GETFL)"); - redisContextCloseFd(c); + redisNetClose(c); return REDIS_ERR; } @@ -122,16 +162,24 @@ static int redisSetBlocking(redisContext *c, int blocking) { if (fcntl(c->fd, F_SETFL, flags) == -1) { __redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_SETFL)"); - redisContextCloseFd(c); + redisNetClose(c); return REDIS_ERR; } +#else + u_long mode = blocking ? 0 : 1; + if (ioctl(c->fd, FIONBIO, &mode) == -1) { + __redisSetErrorFromErrno(c, REDIS_ERR_IO, "ioctl(FIONBIO)"); + redisNetClose(c); + return REDIS_ERR; + } +#endif /* _WIN32 */ #endif return REDIS_OK; } int redisKeepAlive(redisContext *c, int interval) { int val = 1; - int fd = c->fd; + redisFD fd = c->fd; if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){ __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); @@ -170,11 +218,11 @@ int redisKeepAlive(redisContext *c, int interval) { return REDIS_OK; } -static int redisSetTcpNoDelay(redisContext *c) { +int redisSetTcpNoDelay(redisContext *c) { int yes = 1; if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) { __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(TCP_NODELAY)"); - redisContextCloseFd(c); + redisNetClose(c); return REDIS_ERR; } return REDIS_OK; @@ -184,7 +232,7 @@ static int redisSetTcpNoDelay(redisContext *c) { static int redisContextTimeoutMsec(redisContext *c, long *result) { - const struct timeval *timeout = c->timeout; + const struct timeval *timeout = c->connect_timeout; long msec = -1; /* Only use timeout when not NULL. */ @@ -216,12 +264,12 @@ static int redisContextWaitReady(redisContext *c, long msec) { if ((res = poll(wfd, 1, msec)) == -1) { __redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)"); - redisContextCloseFd(c); + redisNetClose(c); return REDIS_ERR; } else if (res == 0) { errno = ETIMEDOUT; __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - redisContextCloseFd(c); + redisNetClose(c); return REDIS_ERR; } @@ -234,7 +282,7 @@ static int redisContextWaitReady(redisContext *c, long msec) { } __redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL); - redisContextCloseFd(c); + redisNetClose(c); return REDIS_ERR; } @@ -281,21 +329,70 @@ int redisCheckSocketError(redisContext *c) { } int redisContextSetTimeout(redisContext *c, const struct timeval tv) { - if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) { +#if 0 + const void *to_ptr = &tv; + size_t to_sz = sizeof(tv); + + if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,to_ptr,to_sz) == -1) { __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_RCVTIMEO)"); return REDIS_ERR; } - if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv)) == -1) { + if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,to_ptr,to_sz) == -1) { __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_SNDTIMEO)"); return REDIS_ERR; } +#else + double timeout = tv.tv_sec ; + timeout += (double) tv.tv_usec / 1000 / 1000; + if (swoole_coroutine_socket_set_timeout(c->fd, SO_RCVTIMEO, timeout) == -1) { + __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_RCVTIMEO)"); + return REDIS_ERR; + } + if (swoole_coroutine_socket_set_timeout(c->fd, SO_SNDTIMEO, timeout) == -1) { + __redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_RCVTIMEO)"); + return REDIS_ERR; + } +#endif + return REDIS_OK; +} + +int redisContextUpdateConnectTimeout(redisContext *c, const struct timeval *timeout) { + /* Same timeval struct, short circuit */ + if (c->connect_timeout == timeout) + return REDIS_OK; + + /* Allocate context timeval if we need to */ + if (c->connect_timeout == NULL) { + c->connect_timeout = hi_malloc(sizeof(*c->connect_timeout)); + if (c->connect_timeout == NULL) + return REDIS_ERR; + } + + memcpy(c->connect_timeout, timeout, sizeof(*c->connect_timeout)); + return REDIS_OK; +} + +int redisContextUpdateCommandTimeout(redisContext *c, const struct timeval *timeout) { + /* Same timeval struct, short circuit */ + if (c->command_timeout == timeout) + return REDIS_OK; + + /* Allocate context timeval if we need to */ + if (c->command_timeout == NULL) { + c->command_timeout = hi_malloc(sizeof(*c->command_timeout)); + if (c->command_timeout == NULL) + return REDIS_ERR; + } + + memcpy(c->command_timeout, timeout, sizeof(*c->command_timeout)); return REDIS_OK; } static int _redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout, const char *source_addr) { - int s, rv, n; + redisFD s; + int rv, n; char _port[6]; /* strlen("65535"); */ struct addrinfo hints, *servinfo, *bservinfo, *p, *b; int blocking = (c->flags & REDIS_BLOCK); @@ -315,21 +412,19 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port, * This is a bit ugly, but atleast it works and doesn't leak memory. **/ if (c->tcp.host != addr) { - free(c->tcp.host); + hi_free(c->tcp.host); - c->tcp.host = strdup(addr); + c->tcp.host = hi_strdup(addr); + if (c->tcp.host == NULL) + goto oom; } if (timeout) { - if (c->timeout != timeout) { - if (c->timeout == NULL) - c->timeout = malloc(sizeof(struct timeval)); - - memcpy(c->timeout, timeout, sizeof(struct timeval)); - } + if (redisContextUpdateConnectTimeout(c, timeout) == REDIS_ERR) + goto oom; } else { - free(c->timeout); - c->timeout = NULL; + hi_free(c->connect_timeout); + c->connect_timeout = NULL; } if (redisContextTimeoutMsec(c, &timeout_msec) != REDIS_OK) { @@ -338,11 +433,11 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port, } if (source_addr == NULL) { - free(c->tcp.source_addr); + hi_free(c->tcp.source_addr); c->tcp.source_addr = NULL; } else if (c->tcp.source_addr != source_addr) { - free(c->tcp.source_addr); - c->tcp.source_addr = strdup(source_addr); + hi_free(c->tcp.source_addr); + c->tcp.source_addr = hi_strdup(source_addr); } snprintf(_port, 6, "%d", port); @@ -364,7 +459,7 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port, } for (p = servinfo; p != NULL; p = p->ai_next) { addrretry: - if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1) + if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == REDIS_INVALID_FD) continue; c->fd = s; @@ -405,23 +500,23 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port, } /* For repeat connection */ - if (c->saddr) { - free(c->saddr); - } - c->saddr = malloc(p->ai_addrlen); + hi_free(c->saddr); + c->saddr = hi_malloc(p->ai_addrlen); + if (c->saddr == NULL) + goto oom; + memcpy(c->saddr, p->ai_addr, p->ai_addrlen); c->addrlen = p->ai_addrlen; - if (blocking && c->timeout) { - struct pollfd _rfd[1]; - _rfd[0].fd = c->fd; - _rfd[0].events = POLLOUT; - poll(_rfd, 1, (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000)); + if (c->connect_timeout) { + double timeout = c->connect_timeout->tv_sec ; + timeout += (double) c->connect_timeout->tv_usec / 1000 / 1000; + swoole_coroutine_socket_set_connect_timeout(c->fd, timeout); } if (connect(s,p->ai_addr,p->ai_addrlen) == -1) { if (errno == EHOSTUNREACH) { - redisContextCloseFd(c); + redisNetClose(c); continue; } else if (errno == EINPROGRESS) { if (blocking) { @@ -435,19 +530,19 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port, if (++reuses >= REDIS_CONNECT_RETRIES) { goto error; } else { - redisContextCloseFd(c); + redisNetClose(c); goto addrretry; } } else { wait_for_ready: if (redisContextWaitReady(c,timeout_msec) != REDIS_OK) goto error; + if (redisSetTcpNoDelay(c) != REDIS_OK) + goto error; } } if (blocking && redisSetBlocking(c,1) != REDIS_OK) goto error; - if (redisSetTcpNoDelay(c) != REDIS_OK) - goto error; c->flags |= REDIS_CONNECTED; rv = REDIS_OK; @@ -460,6 +555,8 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port, goto error; } +oom: + __redisSetError(c, REDIS_ERR_OOM, "Out of memory"); error: rv = REDIS_ERR; end: @@ -482,8 +579,9 @@ int redisContextConnectBindTcp(redisContext *c, const char *addr, int port, } int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout) { +#ifndef _WIN32 int blocking = (c->flags & REDIS_BLOCK); - struct sockaddr_un sa; + struct sockaddr_un *sa; long timeout_msec = -1; if (redisCreateSocket(c,AF_UNIX) < 0) @@ -492,35 +590,36 @@ int redisContextConnectUnix(redisContext *c, const char *path, const struct time return REDIS_ERR; c->connection_type = REDIS_CONN_UNIX; - if (c->unix_sock.path != path) - c->unix_sock.path = strdup(path); + if (c->unix_sock.path != path) { + hi_free(c->unix_sock.path); - if (timeout) { - if (c->timeout != timeout) { - if (c->timeout == NULL) - c->timeout = malloc(sizeof(struct timeval)); + c->unix_sock.path = hi_strdup(path); + if (c->unix_sock.path == NULL) + goto oom; + } - memcpy(c->timeout, timeout, sizeof(struct timeval)); - } + if (timeout) { + if (redisContextUpdateConnectTimeout(c, timeout) == REDIS_ERR) + goto oom; } else { - free(c->timeout); - c->timeout = NULL; + hi_free(c->connect_timeout); + c->connect_timeout = NULL; } if (redisContextTimeoutMsec(c,&timeout_msec) != REDIS_OK) return REDIS_ERR; - sa.sun_family = AF_UNIX; - strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1); + /* Don't leak sockaddr if we're reconnecting */ + if (c->saddr) hi_free(c->saddr); - if (blocking && c->timeout) { - struct pollfd _rfd[1]; - _rfd[0].fd = c->fd; - _rfd[0].events = POLLOUT; - poll(_rfd, 1, (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000)); - } + sa = (struct sockaddr_un*)(c->saddr = hi_malloc(sizeof(struct sockaddr_un))); + if (sa == NULL) + goto oom; - if (connect(c->fd, (struct sockaddr*)&sa, sizeof(sa)) == -1) { + c->addrlen = sizeof(struct sockaddr_un); + sa->sun_family = AF_UNIX; + strncpy(sa->sun_path, path, sizeof(sa->sun_path) - 1); + if (connect(c->fd, (struct sockaddr*)sa, sizeof(*sa)) == -1) { if (errno == EINPROGRESS && !blocking) { /* This is ok. */ } else { @@ -535,4 +634,13 @@ int redisContextConnectUnix(redisContext *c, const char *path, const struct time c->flags |= REDIS_CONNECTED; return REDIS_OK; +#else + /* We currently do not support Unix sockets for Windows. */ + /* TODO(m): https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/ */ + errno = EPROTONOSUPPORT; + return REDIS_ERR; +#endif /* _WIN32 */ +oom: + __redisSetError(c, REDIS_ERR_OOM, "Out of memory"); + return REDIS_ERR; } diff --git a/thirdparty/hiredis/net.h b/thirdparty/hiredis/net.h index a11594e68df..9f43283a5f0 100644 --- a/thirdparty/hiredis/net.h +++ b/thirdparty/hiredis/net.h @@ -37,6 +37,10 @@ #include "hiredis.h" +void redisNetClose(redisContext *c); +ssize_t redisNetRead(redisContext *c, char *buf, size_t bufcap); +ssize_t redisNetWrite(redisContext *c); + int redisCheckSocketError(redisContext *c); int redisContextSetTimeout(redisContext *c, const struct timeval tv); int redisContextConnectTcp(redisContext *c, const char *addr, int port, const struct timeval *timeout); @@ -47,4 +51,6 @@ int redisContextConnectUnix(redisContext *c, const char *path, const struct time int redisKeepAlive(redisContext *c, int interval); int redisCheckConnectDone(redisContext *c, int *completed); +int redisSetTcpNoDelay(redisContext *c); + #endif diff --git a/thirdparty/hiredis/read.c b/thirdparty/hiredis/read.c index cc2126778a3..6253166ad4e 100644 --- a/thirdparty/hiredis/read.c +++ b/thirdparty/hiredis/read.c @@ -29,21 +29,26 @@ * POSSIBILITY OF SUCH DAMAGE. */ - #include "fmacros.h" #include #include #ifndef _MSC_VER #include +#include #endif #include #include #include #include +#include +#include "alloc.h" #include "read.h" #include "sds.h" +/* Initial size of our nested reply stack and how much we grow it when needd */ +#define REDIS_READER_STACK_SIZE 9 + static void __redisReaderSetError(redisReader *r, int type, const char *str) { size_t len; @@ -117,29 +122,28 @@ static char *readBytes(redisReader *r, unsigned int bytes) { /* Find pointer to \r\n. */ static char *seekNewline(char *s, size_t len) { - int pos = 0; - int _len = len-1; - - /* Position should be < len-1 because the character at "pos" should be - * followed by a \n. Note that strchr cannot be used because it doesn't - * allow to search a limited length and the buffer that is being searched - * might not have a trailing NULL character. */ - while (pos < _len) { - while(pos < _len && s[pos] != '\r') pos++; - if (pos==_len) { - /* Not found. */ - return NULL; - } else { - if (s[pos+1] == '\n') { - /* Found. */ - return s+pos; - } else { - /* Continue searching. */ - pos++; - } + char *ret; + + /* We cannot match with fewer than 2 bytes */ + if (len < 2) + return NULL; + + /* Search up to len - 1 characters */ + len--; + + /* Look for the \r */ + while ((ret = memchr(s, '\r', len)) != NULL) { + if (ret[1] == '\n') { + /* Found. */ + break; } + /* Continue searching. */ + ret++; + len -= ret - s; + s = ret; } - return NULL; + + return ret; } /* Convert a string into a long long. Returns REDIS_OK if the string could be @@ -241,9 +245,12 @@ static void moveToNextTask(redisReader *r) { return; } - cur = &(r->rstack[r->ridx]); - prv = &(r->rstack[r->ridx-1]); - assert(prv->type == REDIS_REPLY_ARRAY); + cur = r->task[r->ridx]; + prv = r->task[r->ridx-1]; + assert(prv->type == REDIS_REPLY_ARRAY || + prv->type == REDIS_REPLY_MAP || + prv->type == REDIS_REPLY_SET || + prv->type == REDIS_REPLY_PUSH); if (cur->idx == prv->elements-1) { r->ridx--; } else { @@ -258,26 +265,111 @@ static void moveToNextTask(redisReader *r) { } static int processLineItem(redisReader *r) { - redisReadTask *cur = &(r->rstack[r->ridx]); + redisReadTask *cur = r->task[r->ridx]; void *obj; char *p; int len; if ((p = readLine(r,&len)) != NULL) { if (cur->type == REDIS_REPLY_INTEGER) { + long long v; + + if (string2ll(p, len, &v) == REDIS_ERR) { + __redisReaderSetError(r,REDIS_ERR_PROTOCOL, + "Bad integer value"); + return REDIS_ERR; + } + if (r->fn && r->fn->createInteger) { - long long v; - if (string2ll(p, len, &v) == REDIS_ERR) { + obj = r->fn->createInteger(cur,v); + } else { + obj = (void*)REDIS_REPLY_INTEGER; + } + } else if (cur->type == REDIS_REPLY_DOUBLE) { + char buf[326], *eptr; + double d; + + if ((size_t)len >= sizeof(buf)) { + __redisReaderSetError(r,REDIS_ERR_PROTOCOL, + "Double value is too large"); + return REDIS_ERR; + } + + memcpy(buf,p,len); + buf[len] = '\0'; + + if (len == 3 && strcasecmp(buf,"inf") == 0) { + d = INFINITY; /* Positive infinite. */ + } else if (len == 4 && strcasecmp(buf,"-inf") == 0) { + d = -INFINITY; /* Negative infinite. */ + } else { + d = strtod((char*)buf,&eptr); + /* RESP3 only allows "inf", "-inf", and finite values, while + * strtod() allows other variations on infinity, NaN, + * etc. We explicity handle our two allowed infinite cases + * above, so strtod() should only result in finite values. */ + if (buf[0] == '\0' || eptr != &buf[len] || !isfinite(d)) { __redisReaderSetError(r,REDIS_ERR_PROTOCOL, - "Bad integer value"); + "Bad double value"); return REDIS_ERR; } - obj = r->fn->createInteger(cur,v); + } + + if (r->fn && r->fn->createDouble) { + obj = r->fn->createDouble(cur,d,buf,len); } else { - obj = (void*)REDIS_REPLY_INTEGER; + obj = (void*)REDIS_REPLY_DOUBLE; + } + } else if (cur->type == REDIS_REPLY_NIL) { + if (len != 0) { + __redisReaderSetError(r,REDIS_ERR_PROTOCOL, + "Bad nil value"); + return REDIS_ERR; + } + + if (r->fn && r->fn->createNil) + obj = r->fn->createNil(cur); + else + obj = (void*)REDIS_REPLY_NIL; + } else if (cur->type == REDIS_REPLY_BOOL) { + int bval; + + if (len != 1 || !strchr("tTfF", p[0])) { + __redisReaderSetError(r,REDIS_ERR_PROTOCOL, + "Bad bool value"); + return REDIS_ERR; + } + + bval = p[0] == 't' || p[0] == 'T'; + if (r->fn && r->fn->createBool) + obj = r->fn->createBool(cur,bval); + else + obj = (void*)REDIS_REPLY_BOOL; + } else if (cur->type == REDIS_REPLY_BIGNUM) { + /* Ensure all characters are decimal digits (with possible leading + * minus sign). */ + for (int i = 0; i < len; i++) { + /* XXX Consider: Allow leading '+'? Error on leading '0's? */ + if (i == 0 && p[0] == '-') continue; + if (p[i] < '0' || p[i] > '9') { + __redisReaderSetError(r,REDIS_ERR_PROTOCOL, + "Bad bignum value"); + return REDIS_ERR; + } } + if (r->fn && r->fn->createString) + obj = r->fn->createString(cur,p,len); + else + obj = (void*)REDIS_REPLY_BIGNUM; } else { /* Type will be error or status. */ + for (int i = 0; i < len; i++) { + if (p[i] == '\r' || p[i] == '\n') { + __redisReaderSetError(r,REDIS_ERR_PROTOCOL, + "Bad simple string value"); + return REDIS_ERR; + } + } if (r->fn && r->fn->createString) obj = r->fn->createString(cur,p,len); else @@ -299,7 +391,7 @@ static int processLineItem(redisReader *r) { } static int processBulkItem(redisReader *r) { - redisReadTask *cur = &(r->rstack[r->ridx]); + redisReadTask *cur = r->task[r->ridx]; void *obj = NULL; char *p, *s; long long len; @@ -335,10 +427,18 @@ static int processBulkItem(redisReader *r) { /* Only continue when the buffer contains the entire bulk item. */ bytelen += len+2; /* include \r\n */ if (r->pos+bytelen <= r->len) { + if ((cur->type == REDIS_REPLY_VERB && len < 4) || + (cur->type == REDIS_REPLY_VERB && s[5] != ':')) + { + __redisReaderSetError(r,REDIS_ERR_PROTOCOL, + "Verbatim string 4 bytes of content type are " + "missing or incorrectly encoded."); + return REDIS_ERR; + } if (r->fn && r->fn->createString) obj = r->fn->createString(cur,s+2,len); else - obj = (void*)REDIS_REPLY_STRING; + obj = (void*)(long)cur->type; success = 1; } } @@ -362,18 +462,42 @@ static int processBulkItem(redisReader *r) { return REDIS_ERR; } -static int processMultiBulkItem(redisReader *r) { - redisReadTask *cur = &(r->rstack[r->ridx]); +static int redisReaderGrow(redisReader *r) { + redisReadTask **aux; + int newlen; + + /* Grow our stack size */ + newlen = r->tasks + REDIS_READER_STACK_SIZE; + aux = hi_realloc(r->task, sizeof(*r->task) * newlen); + if (aux == NULL) + goto oom; + + r->task = aux; + + /* Allocate new tasks */ + for (; r->tasks < newlen; r->tasks++) { + r->task[r->tasks] = hi_calloc(1, sizeof(**r->task)); + if (r->task[r->tasks] == NULL) + goto oom; + } + + return REDIS_OK; +oom: + __redisReaderSetErrorOOM(r); + return REDIS_ERR; +} + +/* Process the array, map and set types. */ +static int processAggregateItem(redisReader *r) { + redisReadTask *cur = r->task[r->ridx]; void *obj; char *p; long long elements; int root = 0, len; - /* Set error for nested multi bulks with depth > 7 */ - if (r->ridx == 8) { - __redisReaderSetError(r,REDIS_ERR_PROTOCOL, - "No support for nested multi bulk replies with depth > 7"); - return REDIS_ERR; + if (r->ridx == r->tasks - 1) { + if (redisReaderGrow(r) == REDIS_ERR) + return REDIS_ERR; } if ((p = readLine(r,&len)) != NULL) { @@ -385,7 +509,9 @@ static int processMultiBulkItem(redisReader *r) { root = (r->ridx == 0); - if (elements < -1 || elements > INT_MAX) { + if (elements < -1 || (LLONG_MAX > SIZE_MAX && elements > SIZE_MAX) || + (r->maxelements > 0 && elements > r->maxelements)) + { __redisReaderSetError(r,REDIS_ERR_PROTOCOL, "Multi-bulk length out of range"); return REDIS_ERR; @@ -404,10 +530,12 @@ static int processMultiBulkItem(redisReader *r) { moveToNextTask(r); } else { + if (cur->type == REDIS_REPLY_MAP) elements *= 2; + if (r->fn && r->fn->createArray) obj = r->fn->createArray(cur,elements); else - obj = (void*)REDIS_REPLY_ARRAY; + obj = (void*)(long)cur->type; if (obj == NULL) { __redisReaderSetErrorOOM(r); @@ -419,12 +547,12 @@ static int processMultiBulkItem(redisReader *r) { cur->elements = elements; cur->obj = obj; r->ridx++; - r->rstack[r->ridx].type = -1; - r->rstack[r->ridx].elements = -1; - r->rstack[r->ridx].idx = 0; - r->rstack[r->ridx].obj = NULL; - r->rstack[r->ridx].parent = cur; - r->rstack[r->ridx].privdata = r->privdata; + r->task[r->ridx]->type = -1; + r->task[r->ridx]->elements = -1; + r->task[r->ridx]->idx = 0; + r->task[r->ridx]->obj = NULL; + r->task[r->ridx]->parent = cur; + r->task[r->ridx]->privdata = r->privdata; } else { moveToNextTask(r); } @@ -439,7 +567,7 @@ static int processMultiBulkItem(redisReader *r) { } static int processItem(redisReader *r) { - redisReadTask *cur = &(r->rstack[r->ridx]); + redisReadTask *cur = r->task[r->ridx]; char *p; /* check if we need to read type */ @@ -455,12 +583,36 @@ static int processItem(redisReader *r) { case ':': cur->type = REDIS_REPLY_INTEGER; break; + case ',': + cur->type = REDIS_REPLY_DOUBLE; + break; + case '_': + cur->type = REDIS_REPLY_NIL; + break; case '$': cur->type = REDIS_REPLY_STRING; break; case '*': cur->type = REDIS_REPLY_ARRAY; break; + case '%': + cur->type = REDIS_REPLY_MAP; + break; + case '~': + cur->type = REDIS_REPLY_SET; + break; + case '#': + cur->type = REDIS_REPLY_BOOL; + break; + case '=': + cur->type = REDIS_REPLY_VERB; + break; + case '>': + cur->type = REDIS_REPLY_PUSH; + break; + case '(': + cur->type = REDIS_REPLY_BIGNUM; + break; default: __redisReaderSetErrorProtocolByte(r,*p); return REDIS_ERR; @@ -476,11 +628,19 @@ static int processItem(redisReader *r) { case REDIS_REPLY_ERROR: case REDIS_REPLY_STATUS: case REDIS_REPLY_INTEGER: + case REDIS_REPLY_DOUBLE: + case REDIS_REPLY_NIL: + case REDIS_REPLY_BOOL: + case REDIS_REPLY_BIGNUM: return processLineItem(r); case REDIS_REPLY_STRING: + case REDIS_REPLY_VERB: return processBulkItem(r); case REDIS_REPLY_ARRAY: - return processMultiBulkItem(r); + case REDIS_REPLY_MAP: + case REDIS_REPLY_SET: + case REDIS_REPLY_PUSH: + return processAggregateItem(r); default: assert(NULL); return REDIS_ERR; /* Avoid warning. */ @@ -490,29 +650,53 @@ static int processItem(redisReader *r) { redisReader *redisReaderCreateWithFunctions(redisReplyObjectFunctions *fn) { redisReader *r; - r = calloc(1,sizeof(redisReader)); + r = hi_calloc(1,sizeof(redisReader)); if (r == NULL) return NULL; - r->fn = fn; r->buf = sdsempty(); - r->maxbuf = REDIS_READER_MAX_BUF; - if (r->buf == NULL) { - free(r); - return NULL; + if (r->buf == NULL) + goto oom; + + r->task = hi_calloc(REDIS_READER_STACK_SIZE, sizeof(*r->task)); + if (r->task == NULL) + goto oom; + + for (; r->tasks < REDIS_READER_STACK_SIZE; r->tasks++) { + r->task[r->tasks] = hi_calloc(1, sizeof(**r->task)); + if (r->task[r->tasks] == NULL) + goto oom; } + r->fn = fn; + r->maxbuf = REDIS_READER_MAX_BUF; + r->maxelements = REDIS_READER_MAX_ARRAY_ELEMENTS; r->ridx = -1; + return r; +oom: + redisReaderFree(r); + return NULL; } void redisReaderFree(redisReader *r) { if (r == NULL) return; + if (r->reply != NULL && r->fn && r->fn->freeObject) r->fn->freeObject(r->reply); + + if (r->task) { + /* We know r->task[i] is allocated if i < r->tasks */ + for (int i = 0; i < r->tasks; i++) { + hi_free(r->task[i]); + } + + hi_free(r->task); + } + sdsfree(r->buf); - free(r); + hi_free(r); } int redisReaderFeed(redisReader *r, const char *buf, size_t len) { @@ -528,23 +712,22 @@ int redisReaderFeed(redisReader *r, const char *buf, size_t len) { if (r->len == 0 && r->maxbuf != 0 && sdsavail(r->buf) > r->maxbuf) { sdsfree(r->buf); r->buf = sdsempty(); - r->pos = 0; + if (r->buf == 0) goto oom; - /* r->buf should not be NULL since we just free'd a larger one. */ - assert(r->buf != NULL); + r->pos = 0; } newbuf = sdscatlen(r->buf,buf,len); - if (newbuf == NULL) { - __redisReaderSetErrorOOM(r); - return REDIS_ERR; - } + if (newbuf == NULL) goto oom; r->buf = newbuf; r->len = sdslen(r->buf); } return REDIS_OK; +oom: + __redisReaderSetErrorOOM(r); + return REDIS_ERR; } int redisReaderGetReply(redisReader *r, void **reply) { @@ -562,12 +745,12 @@ int redisReaderGetReply(redisReader *r, void **reply) { /* Set first item to process when the stack is empty. */ if (r->ridx == -1) { - r->rstack[0].type = -1; - r->rstack[0].elements = -1; - r->rstack[0].idx = -1; - r->rstack[0].obj = NULL; - r->rstack[0].parent = NULL; - r->rstack[0].privdata = r->privdata; + r->task[0]->type = -1; + r->task[0]->elements = -1; + r->task[0]->idx = -1; + r->task[0]->obj = NULL; + r->task[0]->parent = NULL; + r->task[0]->privdata = r->privdata; r->ridx = 0; } @@ -583,15 +766,18 @@ int redisReaderGetReply(redisReader *r, void **reply) { /* Discard part of the buffer when we've consumed at least 1k, to avoid * doing unnecessary calls to memmove() in sds.c. */ if (r->pos >= 1024) { - sdsrange(r->buf,r->pos,-1); + if (sdsrange(r->buf,r->pos,-1) < 0) return REDIS_ERR; r->pos = 0; r->len = sdslen(r->buf); } /* Emit a reply when there is one. */ if (r->ridx == -1) { - if (reply != NULL) + if (reply != NULL) { *reply = r->reply; + } else if (r->reply != NULL && r->fn && r->fn->freeObject) { + r->fn->freeObject(r->reply); + } r->reply = NULL; } return REDIS_OK; diff --git a/thirdparty/hiredis/read.h b/thirdparty/hiredis/read.h index 2988aa453bd..2d74d77a5b4 100644 --- a/thirdparty/hiredis/read.h +++ b/thirdparty/hiredis/read.h @@ -45,6 +45,7 @@ #define REDIS_ERR_EOF 3 /* End of file */ #define REDIS_ERR_PROTOCOL 4 /* Protocol error */ #define REDIS_ERR_OOM 5 /* Out of memory */ +#define REDIS_ERR_TIMEOUT 6 /* Timed out */ #define REDIS_ERR_OTHER 2 /* Everything else... */ #define REDIS_REPLY_STRING 1 @@ -53,8 +54,20 @@ #define REDIS_REPLY_NIL 4 #define REDIS_REPLY_STATUS 5 #define REDIS_REPLY_ERROR 6 +#define REDIS_REPLY_DOUBLE 7 +#define REDIS_REPLY_BOOL 8 +#define REDIS_REPLY_MAP 9 +#define REDIS_REPLY_SET 10 +#define REDIS_REPLY_ATTR 11 +#define REDIS_REPLY_PUSH 12 +#define REDIS_REPLY_BIGNUM 13 +#define REDIS_REPLY_VERB 14 -#define REDIS_READER_MAX_BUF (1024*16) /* Default max unused reader buffer. */ +/* Default max unused reader buffer. */ +#define REDIS_READER_MAX_BUF (1024*16) + +/* Default multi-bulk element limit */ +#define REDIS_READER_MAX_ARRAY_ELEMENTS ((1LL<<32) - 1) #ifdef __cplusplus extern "C" { @@ -62,7 +75,7 @@ extern "C" { typedef struct redisReadTask { int type; - int elements; /* number of elements in multibulk container */ + long long elements; /* number of elements in multibulk container */ int idx; /* index in parent (array) object */ void *obj; /* holds user-generated value for a read task */ struct redisReadTask *parent; /* parent task */ @@ -71,9 +84,11 @@ typedef struct redisReadTask { typedef struct redisReplyObjectFunctions { void *(*createString)(const redisReadTask*, char*, size_t); - void *(*createArray)(const redisReadTask*, int); + void *(*createArray)(const redisReadTask*, size_t); void *(*createInteger)(const redisReadTask*, long long); + void *(*createDouble)(const redisReadTask*, double, char*, size_t); void *(*createNil)(const redisReadTask*); + void *(*createBool)(const redisReadTask*, int); void (*freeObject)(void*); } redisReplyObjectFunctions; @@ -85,8 +100,11 @@ typedef struct redisReader { size_t pos; /* Buffer cursor */ size_t len; /* Buffer length */ size_t maxbuf; /* Max length of unused buffer */ + long long maxelements; /* Max multi-bulk elements */ + + redisReadTask **task; + int tasks; - redisReadTask rstack[9]; int ridx; /* Index of current read task */ void *reply; /* Temporary reply pointer */ diff --git a/thirdparty/hiredis/sds.c b/thirdparty/hiredis/sds.c index 44777b10c65..35baa057eb9 100644 --- a/thirdparty/hiredis/sds.c +++ b/thirdparty/hiredis/sds.c @@ -30,11 +30,13 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include "fmacros.h" #include #include #include #include #include +#include #include "sds.h" #include "sdsalloc.h" @@ -70,7 +72,7 @@ static inline char sdsReqType(size_t string_size) { * and 'initlen'. * If NULL is used for 'init' the string is initialized with zero bytes. * - * The string is always null-termined (all the sds strings are, always) so + * The string is always null-terminated (all the sds strings are, always) so * even if you create an sds string with: * * mystring = sdsnewlen("abc",3); @@ -219,10 +221,7 @@ sds sdsMakeRoomFor(sds s, size_t addlen) { hdrlen = sdsHdrSize(type); if (oldtype==type) { newsh = s_realloc(sh, hdrlen+newlen+1); - if (newsh == NULL) { - s_free(sh); - return NULL; - } + if (newsh == NULL) return NULL; s = (char*)newsh+hdrlen; } else { /* Since the header size changes, need to move the string forward, @@ -416,7 +415,7 @@ sds sdscpylen(sds s, const char *t, size_t len) { return s; } -/* Like sdscpylen() but 't' must be a null-termined string so that the length +/* Like sdscpylen() but 't' must be a null-terminated string so that the length * of the string is obtained with strlen(). */ sds sdscpy(sds s, const char *t) { return sdscpylen(s, t, strlen(t)); @@ -715,15 +714,20 @@ sds sdstrim(sds s, const char *cset) { * * The string is modified in-place. * + * Return value: + * -1 (error) if sdslen(s) is larger than maximum positive ssize_t value. + * 0 on success. + * * Example: * * s = sdsnew("Hello World"); * sdsrange(s,1,-1); => "ello World" */ -void sdsrange(sds s, int start, int end) { +int sdsrange(sds s, ssize_t start, ssize_t end) { size_t newlen, len = sdslen(s); + if (len > SSIZE_MAX) return -1; - if (len == 0) return; + if (len == 0) return 0; if (start < 0) { start = len+start; if (start < 0) start = 0; @@ -734,9 +738,9 @@ void sdsrange(sds s, int start, int end) { } newlen = (start > end) ? 0 : (end-start)+1; if (newlen != 0) { - if (start >= (signed)len) { + if (start >= (ssize_t)len) { newlen = 0; - } else if (end >= (signed)len) { + } else if (end >= (ssize_t)len) { end = len-1; newlen = (start > end) ? 0 : (end-start)+1; } @@ -746,6 +750,7 @@ void sdsrange(sds s, int start, int end) { if (start && newlen) memmove(s, s+start, newlen); s[newlen] = 0; sdssetlen(s,newlen); + return 0; } /* Apply tolower() to every character of the sds string 's'. */ @@ -889,13 +894,6 @@ sds sdscatrepr(sds s, const char *p, size_t len) { return sdscatlen(s,"\"",1); } -/* Helper function for sdssplitargs() that returns non zero if 'c' - * is a valid hex digit. */ -int is_hex_digit(char c) { - return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || - (c >= 'A' && c <= 'F'); -} - /* Helper function for sdssplitargs() that converts a hex digit into an * integer from 0 to 15 */ int hex_digit_to_int(char c) { @@ -958,8 +956,8 @@ sds *sdssplitargs(const char *line, int *argc) { while(!done) { if (inq) { if (*p == '\\' && *(p+1) == 'x' && - is_hex_digit(*(p+2)) && - is_hex_digit(*(p+3))) + isxdigit(*(p+2)) && + isxdigit(*(p+3))) { unsigned char byte; @@ -1035,7 +1033,7 @@ sds *sdssplitargs(const char *line, int *argc) { s_free(vector); return NULL; } - + vector = new_vector; vector[*argc] = current; (*argc)++; diff --git a/thirdparty/hiredis/sds.h b/thirdparty/hiredis/sds.h index 13be75a9fca..eda8833b598 100644 --- a/thirdparty/hiredis/sds.h +++ b/thirdparty/hiredis/sds.h @@ -34,6 +34,11 @@ #define __SDS_H #define SDS_MAX_PREALLOC (1024*1024) +#ifdef _MSC_VER +#define __attribute__(x) +typedef long long ssize_t; +#define SSIZE_MAX (LLONG_MAX >> 1) +#endif #include #include @@ -132,20 +137,20 @@ static inline void sdssetlen(sds s, size_t newlen) { case SDS_TYPE_5: { unsigned char *fp = ((unsigned char*)s)-1; - *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); + *fp = (unsigned char)(SDS_TYPE_5 | (newlen << SDS_TYPE_BITS)); } break; case SDS_TYPE_8: - SDS_HDR(8,s)->len = newlen; + SDS_HDR(8,s)->len = (uint8_t)newlen; break; case SDS_TYPE_16: - SDS_HDR(16,s)->len = newlen; + SDS_HDR(16,s)->len = (uint16_t)newlen; break; case SDS_TYPE_32: - SDS_HDR(32,s)->len = newlen; + SDS_HDR(32,s)->len = (uint32_t)newlen; break; case SDS_TYPE_64: - SDS_HDR(64,s)->len = newlen; + SDS_HDR(64,s)->len = (uint64_t)newlen; break; } } @@ -156,21 +161,21 @@ static inline void sdsinclen(sds s, size_t inc) { case SDS_TYPE_5: { unsigned char *fp = ((unsigned char*)s)-1; - unsigned char newlen = SDS_TYPE_5_LEN(flags)+inc; + unsigned char newlen = SDS_TYPE_5_LEN(flags)+(unsigned char)inc; *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS); } break; case SDS_TYPE_8: - SDS_HDR(8,s)->len += inc; + SDS_HDR(8,s)->len += (uint8_t)inc; break; case SDS_TYPE_16: - SDS_HDR(16,s)->len += inc; + SDS_HDR(16,s)->len += (uint16_t)inc; break; case SDS_TYPE_32: - SDS_HDR(32,s)->len += inc; + SDS_HDR(32,s)->len += (uint32_t)inc; break; case SDS_TYPE_64: - SDS_HDR(64,s)->len += inc; + SDS_HDR(64,s)->len += (uint64_t)inc; break; } } @@ -200,16 +205,16 @@ static inline void sdssetalloc(sds s, size_t newlen) { /* Nothing to do, this type has no total allocation info. */ break; case SDS_TYPE_8: - SDS_HDR(8,s)->alloc = newlen; + SDS_HDR(8,s)->alloc = (uint8_t)newlen; break; case SDS_TYPE_16: - SDS_HDR(16,s)->alloc = newlen; + SDS_HDR(16,s)->alloc = (uint16_t)newlen; break; case SDS_TYPE_32: - SDS_HDR(32,s)->alloc = newlen; + SDS_HDR(32,s)->alloc = (uint32_t)newlen; break; case SDS_TYPE_64: - SDS_HDR(64,s)->alloc = newlen; + SDS_HDR(64,s)->alloc = (uint64_t)newlen; break; } } @@ -236,7 +241,7 @@ sds sdscatprintf(sds s, const char *fmt, ...); sds sdscatfmt(sds s, char const *fmt, ...); sds sdstrim(sds s, const char *cset); -void sdsrange(sds s, int start, int end); +int sdsrange(sds s, ssize_t start, ssize_t end); void sdsupdatelen(sds s); void sdsclear(sds s); int sdscmp(const sds s1, const sds s2); diff --git a/thirdparty/hiredis/sdsalloc.h b/thirdparty/hiredis/sdsalloc.h index f43023c4843..5538dd94c97 100644 --- a/thirdparty/hiredis/sdsalloc.h +++ b/thirdparty/hiredis/sdsalloc.h @@ -37,6 +37,8 @@ * the include of your alternate allocator if needed (not needed in order * to use the default libc allocator). */ -#define s_malloc malloc -#define s_realloc realloc -#define s_free free +#include "alloc.h" + +#define s_malloc hi_malloc +#define s_realloc hi_realloc +#define s_free hi_free diff --git a/thirdparty/nghttp2/COPYING b/thirdparty/nghttp2/COPYING new file mode 100644 index 00000000000..80201792ec7 --- /dev/null +++ b/thirdparty/nghttp2/COPYING @@ -0,0 +1,23 @@ +The MIT License + +Copyright (c) 2012, 2014, 2015, 2016 Tatsuhiro Tsujikawa +Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/thirdparty/nghttp2/nghttp2.h b/thirdparty/nghttp2/nghttp2.h index 55617d05484..cf099d2e0c8 100644 --- a/thirdparty/nghttp2/nghttp2.h +++ b/thirdparty/nghttp2/nghttp2.h @@ -28,7 +28,12 @@ /* Define WIN32 when build target is Win32 API (borrowed from libcurl) */ #if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) -#define WIN32 +# define WIN32 +#endif + +/* Compatibility for non-Clang compilers */ +#ifndef __has_declspec_attribute +# define __has_declspec_attribute(x) 0 #endif #ifdef __cplusplus @@ -40,9 +45,9 @@ extern "C" { /* MSVC < 2013 does not have inttypes.h because it is not C99 compliant. See compiler macros and version number in https://sourceforge.net/p/predef/wiki/Compilers/ */ -#include +# include #else /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */ -#include +# include #endif /* !defined(_MSC_VER) || (_MSC_VER >= 1800) */ #include #include @@ -66,20 +71,21 @@ static inline uint8_t *nghttp2_cpymem(uint8_t *dest, const void *src, size_t len const char *nghttp2_strerror(int error_code); #ifdef NGHTTP2_STATICLIB -#define NGHTTP2_EXTERN -#elif defined(WIN32) -#ifdef BUILDING_NGHTTP2 -#define NGHTTP2_EXTERN __declspec(dllexport) -#else /* !BUILDING_NGHTTP2 */ -#define NGHTTP2_EXTERN __declspec(dllimport) -#endif /* !BUILDING_NGHTTP2 */ -#else /* !defined(WIN32) */ -#ifdef BUILDING_NGHTTP2 -#define NGHTTP2_EXTERN __attribute__((visibility("default"))) -#else /* !BUILDING_NGHTTP2 */ -#define NGHTTP2_EXTERN -#endif /* !BUILDING_NGHTTP2 */ -#endif /* !defined(WIN32) */ +# define NGHTTP2_EXTERN +#elif defined(WIN32) || (__has_declspec_attribute(dllexport) && \ + __has_declspec_attribute(dllimport)) +# ifdef BUILDING_NGHTTP2 +# define NGHTTP2_EXTERN __declspec(dllexport) +# else /* !BUILDING_NGHTTP2 */ +# define NGHTTP2_EXTERN __declspec(dllimport) +# endif /* !BUILDING_NGHTTP2 */ +#else /* !defined(WIN32) */ +# ifdef BUILDING_NGHTTP2 +# define NGHTTP2_EXTERN __attribute__((visibility("default"))) +# else /* !BUILDING_NGHTTP2 */ +# define NGHTTP2_EXTERN +# endif /* !BUILDING_NGHTTP2 */ +#endif /* !defined(WIN32) */ /** * @macro @@ -229,6 +235,13 @@ typedef struct { */ #define NGHTTP2_CLIENT_MAGIC_LEN 24 +/** + * @macro + * + * The default max number of settings per SETTINGS frame + */ +#define NGHTTP2_DEFAULT_MAX_SETTINGS 32 + /** * @enum * @@ -395,12 +408,22 @@ typedef enum { */ NGHTTP2_ERR_CANCEL = -535, /** - * The errors < :enum:`NGHTTP2_ERR_FATAL` mean that the library is - * under unexpected condition and processing was terminated (e.g., - * out of memory). If application receives this error code, it must - * stop using that :type:`nghttp2_session` object and only allowed - * operation for that object is deallocate it using - * `nghttp2_session_del()`. + * When a local endpoint expects to receive SETTINGS frame, it + * receives an other type of frame. + */ + NGHTTP2_ERR_SETTINGS_EXPECTED = -536, + /** + * When a local endpoint receives too many settings entries + * in a single SETTINGS frame. + */ + NGHTTP2_ERR_TOO_MANY_SETTINGS = -537, + /** + * The errors < :enum:`nghttp2_error.NGHTTP2_ERR_FATAL` mean that + * the library is under unexpected condition and processing was + * terminated (e.g., out of memory). If application receives this + * error code, it must stop using that :type:`nghttp2_session` + * object and only allowed operation for that object is deallocate + * it using `nghttp2_session_del()`. */ NGHTTP2_ERR_FATAL = -900, /** @@ -520,9 +543,9 @@ typedef struct { * :type:`nghttp2_on_frame_send_callback`, and * :type:`nghttp2_on_frame_not_send_callback`), it may not be * NULL-terminated if header field is passed from application with - * the flag :enum:`NGHTTP2_NV_FLAG_NO_COPY_NAME`). When application - * is constructing this struct, |name| is not required to be - * NULL-terminated. + * the flag :enum:`nghttp2_nv_flag.NGHTTP2_NV_FLAG_NO_COPY_NAME`). + * When application is constructing this struct, |name| is not + * required to be NULL-terminated. */ uint8_t *name; /** @@ -533,9 +556,9 @@ typedef struct { * :type:`nghttp2_on_frame_send_callback`, and * :type:`nghttp2_on_frame_not_send_callback`), it may not be * NULL-terminated if header field is passed from application with - * the flag :enum:`NGHTTP2_NV_FLAG_NO_COPY_VALUE`). When - * application is constructing this struct, |value| is not required - * to be NULL-terminated. + * the flag :enum:`nghttp2_nv_flag.NGHTTP2_NV_FLAG_NO_COPY_VALUE`). + * When application is constructing this struct, |value| is not + * required to be NULL-terminated. */ uint8_t *value; /** @@ -604,7 +627,12 @@ typedef enum { * The ALTSVC frame, which is defined in `RFC 7383 * `_. */ - NGHTTP2_ALTSVC = 0x0a + NGHTTP2_ALTSVC = 0x0a, + /** + * The ORIGIN frame, which is defined by `RFC 8336 + * `_. + */ + NGHTTP2_ORIGIN = 0x0c } nghttp2_frame_type; /** @@ -668,7 +696,12 @@ typedef enum { /** * SETTINGS_MAX_HEADER_LIST_SIZE */ - NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 0x06 + NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 0x06, + /** + * SETTINGS_ENABLE_CONNECT_PROTOCOL + * (`RFC 8441 `_) + */ + NGHTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL = 0x08 } nghttp2_settings_id; /* Note: If we add SETTINGS, update the capacity of NGHTTP2_INBOUND_NUM_IV as well */ @@ -682,8 +715,8 @@ typedef enum { * * Default maximum number of incoming concurrent streams. Use * `nghttp2_submit_settings()` with - * :enum:`NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS` to change the - * maximum number of incoming concurrent streams. + * :enum:`nghttp2_settings_id.NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS` + * to change the maximum number of incoming concurrent streams. * * .. note:: * @@ -829,7 +862,6 @@ typedef enum { NGHTTP2_DATA_FLAG_NO_COPY = 0x04 } nghttp2_data_flag; - /** * @functypedef * @@ -886,7 +918,6 @@ typedef struct { nghttp2_realloc realloc; } nghttp2_mem; - /** * @struct * @@ -1260,7 +1291,7 @@ typedef struct nghttp2_hd_deflater nghttp2_hd_deflater; * This function returns 0 if it succeeds, or one of the following * negative error codes: * - * :enum:`NGHTTP2_ERR_NOMEM` + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` * Out of memory. */ NGHTTP2_EXTERN int @@ -1314,7 +1345,7 @@ NGHTTP2_EXTERN void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater); * This function returns 0 if it succeeds, or one of the following * negative error codes: * - * :enum:`NGHTTP2_ERR_NOMEM` + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` * Out of memory. */ NGHTTP2_EXTERN int @@ -1328,24 +1359,24 @@ nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater, * the |buf| of length |buflen|. * * If |buf| is not large enough to store the deflated header block, - * this function fails with :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`. The - * caller should use `nghttp2_hd_deflate_bound()` to know the upper - * bound of buffer size required to deflate given header name/value - * pairs. + * this function fails with + * :enum:`nghttp2_error.NGHTTP2_ERR_INSUFF_BUFSIZE`. The caller + * should use `nghttp2_hd_deflate_bound()` to know the upper bound of + * buffer size required to deflate given header name/value pairs. * * Once this function fails, subsequent call of this function always - * returns :enum:`NGHTTP2_ERR_HEADER_COMP`. + * returns :enum:`nghttp2_error.NGHTTP2_ERR_HEADER_COMP`. * * After this function returns, it is safe to delete the |nva|. * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: + * This function returns the number of bytes written to |buf| if it + * succeeds, or one of the following negative error codes: * - * :enum:`NGHTTP2_ERR_NOMEM` + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` * Out of memory. - * :enum:`NGHTTP2_ERR_HEADER_COMP` + * :enum:`nghttp2_error.NGHTTP2_ERR_HEADER_COMP` * Deflation process has failed. - * :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE` + * :enum:`nghttp2_error.NGHTTP2_ERR_INSUFF_BUFSIZE` * The provided |buflen| size is too small to hold the output. */ NGHTTP2_EXTERN ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, @@ -1361,23 +1392,24 @@ NGHTTP2_EXTERN ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, * must be set in len field of :type:`nghttp2_vec`. If and only if * one chunk is filled up completely, next chunk will be used. If * |vec| is not large enough to store the deflated header block, this - * function fails with :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`. The caller + * function fails with + * :enum:`nghttp2_error.NGHTTP2_ERR_INSUFF_BUFSIZE`. The caller * should use `nghttp2_hd_deflate_bound()` to know the upper bound of * buffer size required to deflate given header name/value pairs. * * Once this function fails, subsequent call of this function always - * returns :enum:`NGHTTP2_ERR_HEADER_COMP`. + * returns :enum:`nghttp2_error.NGHTTP2_ERR_HEADER_COMP`. * * After this function returns, it is safe to delete the |nva|. * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: + * This function returns the number of bytes written to |vec| if it + * succeeds, or one of the following negative error codes: * - * :enum:`NGHTTP2_ERR_NOMEM` + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` * Out of memory. - * :enum:`NGHTTP2_ERR_HEADER_COMP` + * :enum:`nghttp2_error.NGHTTP2_ERR_HEADER_COMP` * Deflation process has failed. - * :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE` + * :enum:`nghttp2_error.NGHTTP2_ERR_INSUFF_BUFSIZE` * The provided |buflen| size is too small to hold the output. */ NGHTTP2_EXTERN ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater, @@ -1457,7 +1489,7 @@ typedef struct nghttp2_hd_inflater nghttp2_hd_inflater; * This function returns 0 if it succeeds, or one of the following * negative error codes: * - * :enum:`NGHTTP2_ERR_NOMEM` + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` * Out of memory. */ NGHTTP2_EXTERN int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr); @@ -1506,9 +1538,9 @@ NGHTTP2_EXTERN void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater); * This function returns 0 if it succeeds, or one of the following * negative error codes: * - * :enum:`NGHTTP2_ERR_NOMEM` + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` * Out of memory. - * :enum:`NGHTTP2_ERR_INVALID_STATE` + * :enum:`nghttp2_error.NGHTTP2_ERR_INVALID_STATE` * The function is called while header block is being inflated. * Probably, application missed to call * `nghttp2_hd_inflate_end_headers()`. @@ -1546,7 +1578,8 @@ typedef enum { * * Inflates name/value block stored in |in| with length |inlen|. This * function performs decompression. For each successful emission of - * header name/value pair, :enum:`NGHTTP2_HD_INFLATE_EMIT` is set in + * header name/value pair, + * :enum:`nghttp2_hd_inflate_flag.NGHTTP2_HD_INFLATE_EMIT` is set in * |*inflate_flags| and name/value pair is assigned to the |nv_out| * and the function returns. The caller must not free the members of * |nv_out|. @@ -1569,11 +1602,11 @@ typedef enum { * This function returns the number of bytes processed if it succeeds, * or one of the following negative error codes: * - * :enum:`NGHTTP2_ERR_NOMEM` + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` * Out of memory. - * :enum:`NGHTTP2_ERR_HEADER_COMP` + * :enum:`nghttp2_error.NGHTTP2_ERR_HEADER_COMP` * Inflation process has failed. - * :enum:`NGHTTP2_ERR_BUFFER_ERROR` + * :enum:`nghttp2_error.NGHTTP2_ERR_BUFFER_ERROR` * The header field name or value is too large. * * Example follows:: @@ -1628,7 +1661,8 @@ NGHTTP2_EXTERN ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, * * Inflates name/value block stored in |in| with length |inlen|. This * function performs decompression. For each successful emission of - * header name/value pair, :enum:`NGHTTP2_HD_INFLATE_EMIT` is set in + * header name/value pair, + * :enum:`nghttp2_hd_inflate_flag.NGHTTP2_HD_INFLATE_EMIT` is set in * |*inflate_flags| and name/value pair is assigned to the |nv_out| * and the function returns. The caller must not free the members of * |nv_out|. @@ -1644,8 +1678,9 @@ NGHTTP2_EXTERN ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, * for the next header block input. * * In other words, if |in_final| is nonzero, and this function returns - * |inlen|, you can assert that :enum:`NGHTTP2_HD_INFLATE_FINAL` is - * set in |*inflate_flags|. + * |inlen|, you can assert that + * :enum:`nghttp2_hd_inflate_final.NGHTTP2_HD_INFLATE_FINAL` is set in + * |*inflate_flags|. * * The caller can feed complete compressed header block. It also can * feed it in several chunks. The caller must set |in_final| to @@ -1655,11 +1690,11 @@ NGHTTP2_EXTERN ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, * This function returns the number of bytes processed if it succeeds, * or one of the following negative error codes: * - * :enum:`NGHTTP2_ERR_NOMEM` + * :enum:`nghttp2_error.NGHTTP2_ERR_NOMEM` * Out of memory. - * :enum:`NGHTTP2_ERR_HEADER_COMP` + * :enum:`nghttp2_error.NGHTTP2_ERR_HEADER_COMP` * Inflation process has failed. - * :enum:`NGHTTP2_ERR_BUFFER_ERROR` + * :enum:`nghttp2_error.NGHTTP2_ERR_BUFFER_ERROR` * The header field name or value is too large. * * Example follows:: diff --git a/thirdparty/nghttp2/nghttp2_buf.c b/thirdparty/nghttp2/nghttp2_buf.c index 9d4bbead38f..e618400b012 100644 --- a/thirdparty/nghttp2/nghttp2_buf.c +++ b/thirdparty/nghttp2/nghttp2_buf.c @@ -79,8 +79,10 @@ void nghttp2_buf_reset(nghttp2_buf *buf) { } void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len) { - buf->begin = buf->pos = buf->last = buf->mark = begin; - buf->end = begin + len; + buf->begin = buf->pos = buf->last = buf->mark = buf->end = begin; + if (len) { + buf->end += len; + } } static int buf_chain_new(nghttp2_buf_chain **chain, size_t chunk_length, diff --git a/thirdparty/nghttp2/nghttp2_buf.h b/thirdparty/nghttp2/nghttp2_buf.h index 9a21004ad38..eaddd868527 100644 --- a/thirdparty/nghttp2/nghttp2_buf.h +++ b/thirdparty/nghttp2/nghttp2_buf.h @@ -393,7 +393,7 @@ int nghttp2_bufs_advance(nghttp2_bufs *bufs); void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs); /* - * Returns nonzero if bufs->cur->next is not emtpy. + * Returns nonzero if bufs->cur->next is not empty. */ int nghttp2_bufs_next_present(nghttp2_bufs *bufs); diff --git a/thirdparty/nghttp2/nghttp2_hd.c b/thirdparty/nghttp2/nghttp2_hd.c index 8d98abe0838..aa54243a665 100644 --- a/thirdparty/nghttp2/nghttp2_hd.c +++ b/thirdparty/nghttp2/nghttp2_hd.c @@ -41,7 +41,7 @@ /* 3rd parameter is nghttp2_token value for header field name. We use first enum value if same header names are repeated (e.g., :status). */ -static nghttp2_hd_static_entry static_table[] = { +static const nghttp2_hd_static_entry static_table[] = { MAKE_STATIC_ENT(":authority", "", 0, 3153725150u), MAKE_STATIC_ENT(":method", "GET", 1, 695666056u), MAKE_STATIC_ENT(":method", "POST", 1, 695666056u), @@ -267,6 +267,15 @@ static int32_t lookup_token(const uint8_t *name, size_t namelen) { break; } break; + case 9: + switch (name[8]) { + case 'l': + if (memeq(":protoco", name, 8)) { + return NGHTTP2_TOKEN__PROTOCOL; + } + break; + } + break; case 10: switch (name[9]) { case 'e': @@ -658,9 +667,9 @@ static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) { context->mem = mem; context->bad = 0; context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE; - rv = hd_ringbuf_init(&context->hd_table, context->hd_table_bufsize_max / - NGHTTP2_HD_ENTRY_OVERHEAD, - mem); + rv = hd_ringbuf_init( + &context->hd_table, + context->hd_table_bufsize_max / NGHTTP2_HD_ENTRY_OVERHEAD, mem); if (rv != 0) { return rv; } @@ -860,6 +869,11 @@ static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *fin, for (; in != last; ++in, shift += 7) { uint32_t add = *in & 0x7f; + if (shift >= 32) { + DEBUGF("inflate: shift exponent overflow\n"); + return -1; + } + if ((UINT32_MAX >> shift) < add) { DEBUGF("inflate: integer overflow on shift\n"); return -1; @@ -999,7 +1013,7 @@ static uint8_t pack_first_byte(int indexing_mode) { case NGHTTP2_HD_NEVER_INDEXING: return 0x10u; default: - abort(); + assert(0); } /* This is required to compile with android NDK r10d + --enable-werror */ @@ -1150,7 +1164,7 @@ static search_result search_static_table(const nghttp2_nv *nv, int32_t token, int name_only) { search_result res = {token, 0}; int i; - nghttp2_hd_static_entry *ent; + const nghttp2_hd_static_entry *ent; if (name_only) { return res; @@ -1175,7 +1189,7 @@ static search_result search_hd_table(nghttp2_hd_context *context, int indexing_mode, nghttp2_hd_map *map, uint32_t hash) { search_result res = {-1, 0}; - nghttp2_hd_entry *ent; + const nghttp2_hd_entry *ent; int exact_match; int name_only = indexing_mode == NGHTTP2_HD_NEVER_INDEXING; @@ -1280,8 +1294,9 @@ nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) { return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH) ->nv; } else { - nghttp2_hd_static_entry *ent = &static_table[idx]; - nghttp2_hd_nv nv = {&ent->name, &ent->value, ent->token, + const nghttp2_hd_static_entry *ent = &static_table[idx]; + nghttp2_hd_nv nv = {(nghttp2_rcbuf *)&ent->name, + (nghttp2_rcbuf *)&ent->value, ent->token, NGHTTP2_NV_FLAG_NONE}; return nv; } @@ -1371,7 +1386,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs, if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) { nghttp2_hd_nv hd_nv; - if (idx != -1 && idx < (ssize_t)NGHTTP2_STATIC_TABLE_LENGTH) { + if (idx != -1) { hd_nv.name = nghttp2_hd_table_get(&deflater->ctx, (size_t)idx).name; nghttp2_rcbuf_incref(hd_nv.name); } else { @@ -1532,6 +1547,7 @@ size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater, const nghttp2_nv *nva, size_t nvlen) { size_t n = 0; size_t i; + (void)deflater; /* Possible Maximum Header Table Size Change. Encoding (1u << 31) - 1 using 4 bit prefix requires 6 bytes. We may emit this at most @@ -2272,10 +2288,6 @@ ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *fin, return decode_length(res, shift_ptr, fin, initial, shift, in, last, prefix); } -static size_t hd_get_num_table_entries(nghttp2_hd_context *context) { - return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH; -} - static const nghttp2_nv *hd_get_table_entry(nghttp2_hd_context *context, size_t idx) { if (idx == 0) { @@ -2292,7 +2304,7 @@ static const nghttp2_nv *hd_get_table_entry(nghttp2_hd_context *context, } size_t nghttp2_hd_deflate_get_num_table_entries(nghttp2_hd_deflater *deflater) { - return hd_get_num_table_entries(&deflater->ctx); + return get_max_index(&deflater->ctx); } const nghttp2_nv * @@ -2311,7 +2323,7 @@ nghttp2_hd_deflate_get_max_dynamic_table_size(nghttp2_hd_deflater *deflater) { } size_t nghttp2_hd_inflate_get_num_table_entries(nghttp2_hd_inflater *inflater) { - return hd_get_num_table_entries(&inflater->ctx); + return get_max_index(&inflater->ctx); } const nghttp2_nv * diff --git a/thirdparty/nghttp2/nghttp2_hd.h b/thirdparty/nghttp2/nghttp2_hd.h index ac104462426..6cd75e1310a 100644 --- a/thirdparty/nghttp2/nghttp2_hd.h +++ b/thirdparty/nghttp2/nghttp2_hd.h @@ -106,6 +106,7 @@ typedef enum { NGHTTP2_TOKEN_KEEP_ALIVE, NGHTTP2_TOKEN_PROXY_CONNECTION, NGHTTP2_TOKEN_UPGRADE, + NGHTTP2_TOKEN__PROTOCOL, } nghttp2_token; struct nghttp2_hd_entry; @@ -206,7 +207,9 @@ typedef struct { #define HD_MAP_SIZE 128 -typedef struct { nghttp2_hd_entry *table[HD_MAP_SIZE]; } nghttp2_hd_map; +typedef struct { + nghttp2_hd_entry *table[HD_MAP_SIZE]; +} nghttp2_hd_map; struct nghttp2_hd_deflater { nghttp2_hd_context ctx; @@ -308,7 +311,7 @@ void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater); * * This function expands |bufs| as necessary to store the result. If * buffers is full and the process still requires more space, this - * funtion fails and returns NGHTTP2_ERR_HEADER_COMP. + * function fails and returns NGHTTP2_ERR_HEADER_COMP. * * After this function returns, it is safe to delete the |nva|. * @@ -422,4 +425,10 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, nghttp2_buf *buf, const uint8_t *src, size_t srclen, int fin); +/* + * nghttp2_hd_huff_decode_failure_state returns nonzero if |ctx| + * indicates that huffman decoding context is in failure state. + */ +int nghttp2_hd_huff_decode_failure_state(nghttp2_hd_huff_decode_context *ctx); + #endif /* NGHTTP2_HD_H */ diff --git a/thirdparty/nghttp2/nghttp2_hd_huffman.c b/thirdparty/nghttp2/nghttp2_hd_huffman.c index 8881aacb2e6..c0ea3bc3e6d 100644 --- a/thirdparty/nghttp2/nghttp2_hd_huffman.c +++ b/thirdparty/nghttp2/nghttp2_hd_huffman.c @@ -30,114 +30,6 @@ #include "nghttp2_hd.h" -/* - * Encodes huffman code |sym| into |*dest_ptr|, whose least |rembits| - * bits are not filled yet. The |rembits| must be in range [1, 8], - * inclusive. At the end of the process, the |*dest_ptr| is updated - * and points where next output should be placed. The number of - * unfilled bits in the pointed location is returned. - */ -static ssize_t huff_encode_sym(nghttp2_bufs *bufs, size_t *avail_ptr, - size_t rembits, const nghttp2_huff_sym *sym) { - int rv; - size_t nbits = sym->nbits; - uint32_t code = sym->code; - - /* We assume that sym->nbits <= 32 */ - if (rembits > nbits) { - nghttp2_bufs_fast_orb_hold(bufs, (uint8_t)(code << (rembits - nbits))); - return (ssize_t)(rembits - nbits); - } - - if (rembits == nbits) { - nghttp2_bufs_fast_orb(bufs, (uint8_t)code); - --*avail_ptr; - return 8; - } - - nghttp2_bufs_fast_orb(bufs, (uint8_t)(code >> (nbits - rembits))); - --*avail_ptr; - - nbits -= rembits; - if (nbits & 0x7) { - /* align code to MSB byte boundary */ - code <<= 8 - (nbits & 0x7); - } - - if (*avail_ptr < (nbits + 7) / 8) { - /* slow path */ - if (nbits > 24) { - rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 24)); - if (rv != 0) { - return rv; - } - nbits -= 8; - } - if (nbits > 16) { - rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 16)); - if (rv != 0) { - return rv; - } - nbits -= 8; - } - if (nbits > 8) { - rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 8)); - if (rv != 0) { - return rv; - } - nbits -= 8; - } - if (nbits == 8) { - rv = nghttp2_bufs_addb(bufs, (uint8_t)code); - if (rv != 0) { - return rv; - } - *avail_ptr = nghttp2_bufs_cur_avail(bufs); - return 8; - } - - rv = nghttp2_bufs_addb_hold(bufs, (uint8_t)code); - if (rv != 0) { - return rv; - } - *avail_ptr = nghttp2_bufs_cur_avail(bufs); - return (ssize_t)(8 - nbits); - } - - /* fast path, since most code is less than 8 */ - if (nbits < 8) { - nghttp2_bufs_fast_addb_hold(bufs, (uint8_t)code); - *avail_ptr = nghttp2_bufs_cur_avail(bufs); - return (ssize_t)(8 - nbits); - } - - /* handle longer code path */ - if (nbits > 24) { - nghttp2_bufs_fast_addb(bufs, (uint8_t)(code >> 24)); - nbits -= 8; - } - - if (nbits > 16) { - nghttp2_bufs_fast_addb(bufs, (uint8_t)(code >> 16)); - nbits -= 8; - } - - if (nbits > 8) { - nghttp2_bufs_fast_addb(bufs, (uint8_t)(code >> 8)); - nbits -= 8; - } - - if (nbits == 8) { - nghttp2_bufs_fast_addb(bufs, (uint8_t)code); - *avail_ptr = nghttp2_bufs_cur_avail(bufs); - return 8; - } - - nghttp2_bufs_fast_addb_hold(bufs, (uint8_t)code); - *avail_ptr = nghttp2_bufs_cur_avail(bufs); - return (ssize_t)(8 - nbits); -} - size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len) { size_t i; size_t nbits = 0; @@ -151,81 +43,101 @@ size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len) { int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src, size_t srclen) { - int rv; - ssize_t rembits = 8; - size_t i; + const nghttp2_huff_sym *sym; + const uint8_t *end = src + srclen; + uint64_t code = 0; + uint32_t x; + size_t nbits = 0; size_t avail; + int rv; avail = nghttp2_bufs_cur_avail(bufs); - for (i = 0; i < srclen; ++i) { - const nghttp2_huff_sym *sym = &huff_sym_table[src[i]]; - if (rembits == 8) { - if (avail) { - nghttp2_bufs_fast_addb_hold(bufs, 0); - } else { - rv = nghttp2_bufs_addb_hold(bufs, 0); - if (rv != 0) { - return rv; - } - avail = nghttp2_bufs_cur_avail(bufs); + for (; src != end;) { + sym = &huff_sym_table[*src++]; + code |= (uint64_t)sym->code << (32 - nbits); + nbits += sym->nbits; + if (nbits < 32) { + continue; + } + if (avail >= 4) { + x = htonl((uint32_t)(code >> 32)); + memcpy(bufs->cur->buf.last, &x, 4); + bufs->cur->buf.last += 4; + avail -= 4; + code <<= 32; + nbits -= 32; + continue; + } + + for (; nbits >= 8;) { + rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 56)); + if (rv != 0) { + return rv; } + code <<= 8; + nbits -= 8; } - rembits = huff_encode_sym(bufs, &avail, (size_t)rembits, sym); - if (rembits < 0) { - return (int)rembits; + + avail = nghttp2_bufs_cur_avail(bufs); + } + + for (; nbits >= 8;) { + rv = nghttp2_bufs_addb(bufs, (uint8_t)(code >> 56)); + if (rv != 0) { + return rv; } + code <<= 8; + nbits -= 8; } - /* 256 is special terminal symbol, pad with its prefix */ - if (rembits < 8) { - /* if rembits < 8, we should have at least 1 buffer space - available */ - const nghttp2_huff_sym *sym = &huff_sym_table[256]; - assert(avail); - /* Caution we no longer adjust avail here */ - nghttp2_bufs_fast_orb( - bufs, (uint8_t)(sym->code >> (sym->nbits - (size_t)rembits))); + + if (nbits) { + rv = nghttp2_bufs_addb( + bufs, (uint8_t)((uint8_t)(code >> 56) | ((1 << (8 - nbits)) - 1))); + if (rv != 0) { + return rv; + } } return 0; } void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) { - ctx->state = 0; - ctx->accept = 1; + ctx->fstate = NGHTTP2_HUFF_ACCEPTED; } ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, nghttp2_buf *buf, const uint8_t *src, size_t srclen, int final) { - size_t i; + const uint8_t *end = src + srclen; + nghttp2_huff_decode node = {ctx->fstate, 0}; + const nghttp2_huff_decode *t = &node; + uint8_t c; /* We use the decoding algorithm described in http://graphics.ics.uci.edu/pub/Prefix.pdf */ - for (i = 0; i < srclen; ++i) { - const nghttp2_huff_decode *t; - - t = &huff_decode_table[ctx->state][src[i] >> 4]; - if (t->flags & NGHTTP2_HUFF_FAIL) { - return NGHTTP2_ERR_HEADER_COMP; - } - if (t->flags & NGHTTP2_HUFF_SYM) { + for (; src != end;) { + c = *src++; + t = &huff_decode_table[t->fstate & 0x1ff][c >> 4]; + if (t->fstate & NGHTTP2_HUFF_SYM) { *buf->last++ = t->sym; } - t = &huff_decode_table[t->state][src[i] & 0xf]; - if (t->flags & NGHTTP2_HUFF_FAIL) { - return NGHTTP2_ERR_HEADER_COMP; - } - if (t->flags & NGHTTP2_HUFF_SYM) { + t = &huff_decode_table[t->fstate & 0x1ff][c & 0xf]; + if (t->fstate & NGHTTP2_HUFF_SYM) { *buf->last++ = t->sym; } - - ctx->state = t->state; - ctx->accept = (t->flags & NGHTTP2_HUFF_ACCEPTED) != 0; } - if (final && !ctx->accept) { + + ctx->fstate = t->fstate; + + if (final && !(ctx->fstate & NGHTTP2_HUFF_ACCEPTED)) { return NGHTTP2_ERR_HEADER_COMP; } - return (ssize_t)i; + + return (ssize_t)srclen; +} + +int nghttp2_hd_huff_decode_failure_state(nghttp2_hd_huff_decode_context *ctx) { + return ctx->fstate == 0x100; } diff --git a/thirdparty/nghttp2/nghttp2_hd_huffman.h b/thirdparty/nghttp2/nghttp2_hd_huffman.h index eadb7566a73..4bd850d9975 100644 --- a/thirdparty/nghttp2/nghttp2_hd_huffman.h +++ b/thirdparty/nghttp2/nghttp2_hd_huffman.h @@ -26,25 +26,25 @@ #define NGHTTP2_HD_HUFFMAN_H #include +#include typedef enum { /* FSA accepts this state as the end of huffman encoding sequence. */ - NGHTTP2_HUFF_ACCEPTED = 1, + NGHTTP2_HUFF_ACCEPTED = 1 << 14, /* This state emits symbol */ - NGHTTP2_HUFF_SYM = (1 << 1), - /* If state machine reaches this state, decoding fails. */ - NGHTTP2_HUFF_FAIL = (1 << 2) + NGHTTP2_HUFF_SYM = 1 << 15, } nghttp2_huff_decode_flag; typedef struct { - /* huffman decoding state, which is actually the node ID of internal - huffman tree. We have 257 leaf nodes, but they are identical to - root node other than emitting a symbol, so we have 256 internal - nodes [1..255], inclusive. */ - uint8_t state; - /* bitwise OR of zero or more of the nghttp2_huff_decode_flag */ - uint8_t flags; + /* fstate is the current huffman decoding state, which is actually + the node ID of internal huffman tree with + nghttp2_huff_decode_flag OR-ed. We have 257 leaf nodes, but they + are identical to root node other than emitting a symbol, so we + have 256 internal nodes [1..255], inclusive. The node ID 256 is + a special node and it is a terminal state that means decoding + failed. */ + uint16_t fstate; /* symbol if NGHTTP2_HUFF_SYM flag set */ uint8_t sym; } nghttp2_huff_decode; @@ -52,12 +52,8 @@ typedef struct { typedef nghttp2_huff_decode huff_decode_table_type[16]; typedef struct { - /* Current huffman decoding state. We stripped leaf nodes, so the - value range is [0..255], inclusive. */ - uint8_t state; - /* nonzero if we can say that the decoding process succeeds at this - state */ - uint8_t accept; + /* fstate is the current huffman decoding state. */ + uint16_t fstate; } nghttp2_hd_huff_decode_context; typedef struct { diff --git a/thirdparty/nghttp2/nghttp2_hd_huffman_data.c b/thirdparty/nghttp2/nghttp2_hd_huffman_data.c index 5ef4a956b93..2e2e13f7bee 100644 --- a/thirdparty/nghttp2/nghttp2_hd_huffman_data.c +++ b/thirdparty/nghttp2/nghttp2_hd_huffman_data.c @@ -27,4935 +27,4954 @@ /* Generated by mkhufftbl.py */ const nghttp2_huff_sym huff_sym_table[] = { - {13, 0x1ff8u}, {23, 0x7fffd8u}, {28, 0xfffffe2u}, {28, 0xfffffe3u}, - {28, 0xfffffe4u}, {28, 0xfffffe5u}, {28, 0xfffffe6u}, {28, 0xfffffe7u}, - {28, 0xfffffe8u}, {24, 0xffffeau}, {30, 0x3ffffffcu}, {28, 0xfffffe9u}, - {28, 0xfffffeau}, {30, 0x3ffffffdu}, {28, 0xfffffebu}, {28, 0xfffffecu}, - {28, 0xfffffedu}, {28, 0xfffffeeu}, {28, 0xfffffefu}, {28, 0xffffff0u}, - {28, 0xffffff1u}, {28, 0xffffff2u}, {30, 0x3ffffffeu}, {28, 0xffffff3u}, - {28, 0xffffff4u}, {28, 0xffffff5u}, {28, 0xffffff6u}, {28, 0xffffff7u}, - {28, 0xffffff8u}, {28, 0xffffff9u}, {28, 0xffffffau}, {28, 0xffffffbu}, - {6, 0x14u}, {10, 0x3f8u}, {10, 0x3f9u}, {12, 0xffau}, - {13, 0x1ff9u}, {6, 0x15u}, {8, 0xf8u}, {11, 0x7fau}, - {10, 0x3fau}, {10, 0x3fbu}, {8, 0xf9u}, {11, 0x7fbu}, - {8, 0xfau}, {6, 0x16u}, {6, 0x17u}, {6, 0x18u}, - {5, 0x0u}, {5, 0x1u}, {5, 0x2u}, {6, 0x19u}, - {6, 0x1au}, {6, 0x1bu}, {6, 0x1cu}, {6, 0x1du}, - {6, 0x1eu}, {6, 0x1fu}, {7, 0x5cu}, {8, 0xfbu}, - {15, 0x7ffcu}, {6, 0x20u}, {12, 0xffbu}, {10, 0x3fcu}, - {13, 0x1ffau}, {6, 0x21u}, {7, 0x5du}, {7, 0x5eu}, - {7, 0x5fu}, {7, 0x60u}, {7, 0x61u}, {7, 0x62u}, - {7, 0x63u}, {7, 0x64u}, {7, 0x65u}, {7, 0x66u}, - {7, 0x67u}, {7, 0x68u}, {7, 0x69u}, {7, 0x6au}, - {7, 0x6bu}, {7, 0x6cu}, {7, 0x6du}, {7, 0x6eu}, - {7, 0x6fu}, {7, 0x70u}, {7, 0x71u}, {7, 0x72u}, - {8, 0xfcu}, {7, 0x73u}, {8, 0xfdu}, {13, 0x1ffbu}, - {19, 0x7fff0u}, {13, 0x1ffcu}, {14, 0x3ffcu}, {6, 0x22u}, - {15, 0x7ffdu}, {5, 0x3u}, {6, 0x23u}, {5, 0x4u}, - {6, 0x24u}, {5, 0x5u}, {6, 0x25u}, {6, 0x26u}, - {6, 0x27u}, {5, 0x6u}, {7, 0x74u}, {7, 0x75u}, - {6, 0x28u}, {6, 0x29u}, {6, 0x2au}, {5, 0x7u}, - {6, 0x2bu}, {7, 0x76u}, {6, 0x2cu}, {5, 0x8u}, - {5, 0x9u}, {6, 0x2du}, {7, 0x77u}, {7, 0x78u}, - {7, 0x79u}, {7, 0x7au}, {7, 0x7bu}, {15, 0x7ffeu}, - {11, 0x7fcu}, {14, 0x3ffdu}, {13, 0x1ffdu}, {28, 0xffffffcu}, - {20, 0xfffe6u}, {22, 0x3fffd2u}, {20, 0xfffe7u}, {20, 0xfffe8u}, - {22, 0x3fffd3u}, {22, 0x3fffd4u}, {22, 0x3fffd5u}, {23, 0x7fffd9u}, - {22, 0x3fffd6u}, {23, 0x7fffdau}, {23, 0x7fffdbu}, {23, 0x7fffdcu}, - {23, 0x7fffddu}, {23, 0x7fffdeu}, {24, 0xffffebu}, {23, 0x7fffdfu}, - {24, 0xffffecu}, {24, 0xffffedu}, {22, 0x3fffd7u}, {23, 0x7fffe0u}, - {24, 0xffffeeu}, {23, 0x7fffe1u}, {23, 0x7fffe2u}, {23, 0x7fffe3u}, - {23, 0x7fffe4u}, {21, 0x1fffdcu}, {22, 0x3fffd8u}, {23, 0x7fffe5u}, - {22, 0x3fffd9u}, {23, 0x7fffe6u}, {23, 0x7fffe7u}, {24, 0xffffefu}, - {22, 0x3fffdau}, {21, 0x1fffddu}, {20, 0xfffe9u}, {22, 0x3fffdbu}, - {22, 0x3fffdcu}, {23, 0x7fffe8u}, {23, 0x7fffe9u}, {21, 0x1fffdeu}, - {23, 0x7fffeau}, {22, 0x3fffddu}, {22, 0x3fffdeu}, {24, 0xfffff0u}, - {21, 0x1fffdfu}, {22, 0x3fffdfu}, {23, 0x7fffebu}, {23, 0x7fffecu}, - {21, 0x1fffe0u}, {21, 0x1fffe1u}, {22, 0x3fffe0u}, {21, 0x1fffe2u}, - {23, 0x7fffedu}, {22, 0x3fffe1u}, {23, 0x7fffeeu}, {23, 0x7fffefu}, - {20, 0xfffeau}, {22, 0x3fffe2u}, {22, 0x3fffe3u}, {22, 0x3fffe4u}, - {23, 0x7ffff0u}, {22, 0x3fffe5u}, {22, 0x3fffe6u}, {23, 0x7ffff1u}, - {26, 0x3ffffe0u}, {26, 0x3ffffe1u}, {20, 0xfffebu}, {19, 0x7fff1u}, - {22, 0x3fffe7u}, {23, 0x7ffff2u}, {22, 0x3fffe8u}, {25, 0x1ffffecu}, - {26, 0x3ffffe2u}, {26, 0x3ffffe3u}, {26, 0x3ffffe4u}, {27, 0x7ffffdeu}, - {27, 0x7ffffdfu}, {26, 0x3ffffe5u}, {24, 0xfffff1u}, {25, 0x1ffffedu}, - {19, 0x7fff2u}, {21, 0x1fffe3u}, {26, 0x3ffffe6u}, {27, 0x7ffffe0u}, - {27, 0x7ffffe1u}, {26, 0x3ffffe7u}, {27, 0x7ffffe2u}, {24, 0xfffff2u}, - {21, 0x1fffe4u}, {21, 0x1fffe5u}, {26, 0x3ffffe8u}, {26, 0x3ffffe9u}, - {28, 0xffffffdu}, {27, 0x7ffffe3u}, {27, 0x7ffffe4u}, {27, 0x7ffffe5u}, - {20, 0xfffecu}, {24, 0xfffff3u}, {20, 0xfffedu}, {21, 0x1fffe6u}, - {22, 0x3fffe9u}, {21, 0x1fffe7u}, {21, 0x1fffe8u}, {23, 0x7ffff3u}, - {22, 0x3fffeau}, {22, 0x3fffebu}, {25, 0x1ffffeeu}, {25, 0x1ffffefu}, - {24, 0xfffff4u}, {24, 0xfffff5u}, {26, 0x3ffffeau}, {23, 0x7ffff4u}, - {26, 0x3ffffebu}, {27, 0x7ffffe6u}, {26, 0x3ffffecu}, {26, 0x3ffffedu}, - {27, 0x7ffffe7u}, {27, 0x7ffffe8u}, {27, 0x7ffffe9u}, {27, 0x7ffffeau}, - {27, 0x7ffffebu}, {28, 0xffffffeu}, {27, 0x7ffffecu}, {27, 0x7ffffedu}, - {27, 0x7ffffeeu}, {27, 0x7ffffefu}, {27, 0x7fffff0u}, {26, 0x3ffffeeu}, - {30, 0x3fffffffu}}; + {13, 0xffc00000u}, {23, 0xffffb000u}, {28, 0xfffffe20u}, {28, 0xfffffe30u}, + {28, 0xfffffe40u}, {28, 0xfffffe50u}, {28, 0xfffffe60u}, {28, 0xfffffe70u}, + {28, 0xfffffe80u}, {24, 0xffffea00u}, {30, 0xfffffff0u}, {28, 0xfffffe90u}, + {28, 0xfffffea0u}, {30, 0xfffffff4u}, {28, 0xfffffeb0u}, {28, 0xfffffec0u}, + {28, 0xfffffed0u}, {28, 0xfffffee0u}, {28, 0xfffffef0u}, {28, 0xffffff00u}, + {28, 0xffffff10u}, {28, 0xffffff20u}, {30, 0xfffffff8u}, {28, 0xffffff30u}, + {28, 0xffffff40u}, {28, 0xffffff50u}, {28, 0xffffff60u}, {28, 0xffffff70u}, + {28, 0xffffff80u}, {28, 0xffffff90u}, {28, 0xffffffa0u}, {28, 0xffffffb0u}, + {6, 0x50000000u}, {10, 0xfe000000u}, {10, 0xfe400000u}, {12, 0xffa00000u}, + {13, 0xffc80000u}, {6, 0x54000000u}, {8, 0xf8000000u}, {11, 0xff400000u}, + {10, 0xfe800000u}, {10, 0xfec00000u}, {8, 0xf9000000u}, {11, 0xff600000u}, + {8, 0xfa000000u}, {6, 0x58000000u}, {6, 0x5c000000u}, {6, 0x60000000u}, + {5, 0x0u}, {5, 0x8000000u}, {5, 0x10000000u}, {6, 0x64000000u}, + {6, 0x68000000u}, {6, 0x6c000000u}, {6, 0x70000000u}, {6, 0x74000000u}, + {6, 0x78000000u}, {6, 0x7c000000u}, {7, 0xb8000000u}, {8, 0xfb000000u}, + {15, 0xfff80000u}, {6, 0x80000000u}, {12, 0xffb00000u}, {10, 0xff000000u}, + {13, 0xffd00000u}, {6, 0x84000000u}, {7, 0xba000000u}, {7, 0xbc000000u}, + {7, 0xbe000000u}, {7, 0xc0000000u}, {7, 0xc2000000u}, {7, 0xc4000000u}, + {7, 0xc6000000u}, {7, 0xc8000000u}, {7, 0xca000000u}, {7, 0xcc000000u}, + {7, 0xce000000u}, {7, 0xd0000000u}, {7, 0xd2000000u}, {7, 0xd4000000u}, + {7, 0xd6000000u}, {7, 0xd8000000u}, {7, 0xda000000u}, {7, 0xdc000000u}, + {7, 0xde000000u}, {7, 0xe0000000u}, {7, 0xe2000000u}, {7, 0xe4000000u}, + {8, 0xfc000000u}, {7, 0xe6000000u}, {8, 0xfd000000u}, {13, 0xffd80000u}, + {19, 0xfffe0000u}, {13, 0xffe00000u}, {14, 0xfff00000u}, {6, 0x88000000u}, + {15, 0xfffa0000u}, {5, 0x18000000u}, {6, 0x8c000000u}, {5, 0x20000000u}, + {6, 0x90000000u}, {5, 0x28000000u}, {6, 0x94000000u}, {6, 0x98000000u}, + {6, 0x9c000000u}, {5, 0x30000000u}, {7, 0xe8000000u}, {7, 0xea000000u}, + {6, 0xa0000000u}, {6, 0xa4000000u}, {6, 0xa8000000u}, {5, 0x38000000u}, + {6, 0xac000000u}, {7, 0xec000000u}, {6, 0xb0000000u}, {5, 0x40000000u}, + {5, 0x48000000u}, {6, 0xb4000000u}, {7, 0xee000000u}, {7, 0xf0000000u}, + {7, 0xf2000000u}, {7, 0xf4000000u}, {7, 0xf6000000u}, {15, 0xfffc0000u}, + {11, 0xff800000u}, {14, 0xfff40000u}, {13, 0xffe80000u}, {28, 0xffffffc0u}, + {20, 0xfffe6000u}, {22, 0xffff4800u}, {20, 0xfffe7000u}, {20, 0xfffe8000u}, + {22, 0xffff4c00u}, {22, 0xffff5000u}, {22, 0xffff5400u}, {23, 0xffffb200u}, + {22, 0xffff5800u}, {23, 0xffffb400u}, {23, 0xffffb600u}, {23, 0xffffb800u}, + {23, 0xffffba00u}, {23, 0xffffbc00u}, {24, 0xffffeb00u}, {23, 0xffffbe00u}, + {24, 0xffffec00u}, {24, 0xffffed00u}, {22, 0xffff5c00u}, {23, 0xffffc000u}, + {24, 0xffffee00u}, {23, 0xffffc200u}, {23, 0xffffc400u}, {23, 0xffffc600u}, + {23, 0xffffc800u}, {21, 0xfffee000u}, {22, 0xffff6000u}, {23, 0xffffca00u}, + {22, 0xffff6400u}, {23, 0xffffcc00u}, {23, 0xffffce00u}, {24, 0xffffef00u}, + {22, 0xffff6800u}, {21, 0xfffee800u}, {20, 0xfffe9000u}, {22, 0xffff6c00u}, + {22, 0xffff7000u}, {23, 0xffffd000u}, {23, 0xffffd200u}, {21, 0xfffef000u}, + {23, 0xffffd400u}, {22, 0xffff7400u}, {22, 0xffff7800u}, {24, 0xfffff000u}, + {21, 0xfffef800u}, {22, 0xffff7c00u}, {23, 0xffffd600u}, {23, 0xffffd800u}, + {21, 0xffff0000u}, {21, 0xffff0800u}, {22, 0xffff8000u}, {21, 0xffff1000u}, + {23, 0xffffda00u}, {22, 0xffff8400u}, {23, 0xffffdc00u}, {23, 0xffffde00u}, + {20, 0xfffea000u}, {22, 0xffff8800u}, {22, 0xffff8c00u}, {22, 0xffff9000u}, + {23, 0xffffe000u}, {22, 0xffff9400u}, {22, 0xffff9800u}, {23, 0xffffe200u}, + {26, 0xfffff800u}, {26, 0xfffff840u}, {20, 0xfffeb000u}, {19, 0xfffe2000u}, + {22, 0xffff9c00u}, {23, 0xffffe400u}, {22, 0xffffa000u}, {25, 0xfffff600u}, + {26, 0xfffff880u}, {26, 0xfffff8c0u}, {26, 0xfffff900u}, {27, 0xfffffbc0u}, + {27, 0xfffffbe0u}, {26, 0xfffff940u}, {24, 0xfffff100u}, {25, 0xfffff680u}, + {19, 0xfffe4000u}, {21, 0xffff1800u}, {26, 0xfffff980u}, {27, 0xfffffc00u}, + {27, 0xfffffc20u}, {26, 0xfffff9c0u}, {27, 0xfffffc40u}, {24, 0xfffff200u}, + {21, 0xffff2000u}, {21, 0xffff2800u}, {26, 0xfffffa00u}, {26, 0xfffffa40u}, + {28, 0xffffffd0u}, {27, 0xfffffc60u}, {27, 0xfffffc80u}, {27, 0xfffffca0u}, + {20, 0xfffec000u}, {24, 0xfffff300u}, {20, 0xfffed000u}, {21, 0xffff3000u}, + {22, 0xffffa400u}, {21, 0xffff3800u}, {21, 0xffff4000u}, {23, 0xffffe600u}, + {22, 0xffffa800u}, {22, 0xffffac00u}, {25, 0xfffff700u}, {25, 0xfffff780u}, + {24, 0xfffff400u}, {24, 0xfffff500u}, {26, 0xfffffa80u}, {23, 0xffffe800u}, + {26, 0xfffffac0u}, {27, 0xfffffcc0u}, {26, 0xfffffb00u}, {26, 0xfffffb40u}, + {27, 0xfffffce0u}, {27, 0xfffffd00u}, {27, 0xfffffd20u}, {27, 0xfffffd40u}, + {27, 0xfffffd60u}, {28, 0xffffffe0u}, {27, 0xfffffd80u}, {27, 0xfffffda0u}, + {27, 0xfffffdc0u}, {27, 0xfffffde0u}, {27, 0xfffffe00u}, {26, 0xfffffb80u}, + {30, 0xfffffffcu}}; const nghttp2_huff_decode huff_decode_table[][16] = { /* 0 */ { - {4, 0x00, 0}, - {5, 0x00, 0}, - {7, 0x00, 0}, - {8, 0x00, 0}, - {11, 0x00, 0}, - {12, 0x00, 0}, - {16, 0x00, 0}, - {19, 0x00, 0}, - {25, 0x00, 0}, - {28, 0x00, 0}, - {32, 0x00, 0}, - {35, 0x00, 0}, - {42, 0x00, 0}, - {49, 0x00, 0}, - {57, 0x00, 0}, - {64, 0x01, 0}, + {0x04, 0}, + {0x05, 0}, + {0x07, 0}, + {0x08, 0}, + {0x0b, 0}, + {0x0c, 0}, + {0x10, 0}, + {0x13, 0}, + {0x19, 0}, + {0x1c, 0}, + {0x20, 0}, + {0x23, 0}, + {0x2a, 0}, + {0x31, 0}, + {0x39, 0}, + {0x4040, 0}, }, /* 1 */ { - {0, 0x03, 48}, - {0, 0x03, 49}, - {0, 0x03, 50}, - {0, 0x03, 97}, - {0, 0x03, 99}, - {0, 0x03, 101}, - {0, 0x03, 105}, - {0, 0x03, 111}, - {0, 0x03, 115}, - {0, 0x03, 116}, - {13, 0x00, 0}, - {14, 0x00, 0}, - {17, 0x00, 0}, - {18, 0x00, 0}, - {20, 0x00, 0}, - {21, 0x00, 0}, + {0xc000, 48}, + {0xc000, 49}, + {0xc000, 50}, + {0xc000, 97}, + {0xc000, 99}, + {0xc000, 101}, + {0xc000, 105}, + {0xc000, 111}, + {0xc000, 115}, + {0xc000, 116}, + {0x0d, 0}, + {0x0e, 0}, + {0x11, 0}, + {0x12, 0}, + {0x14, 0}, + {0x15, 0}, }, /* 2 */ { - {1, 0x02, 48}, - {22, 0x03, 48}, - {1, 0x02, 49}, - {22, 0x03, 49}, - {1, 0x02, 50}, - {22, 0x03, 50}, - {1, 0x02, 97}, - {22, 0x03, 97}, - {1, 0x02, 99}, - {22, 0x03, 99}, - {1, 0x02, 101}, - {22, 0x03, 101}, - {1, 0x02, 105}, - {22, 0x03, 105}, - {1, 0x02, 111}, - {22, 0x03, 111}, + {0x8001, 48}, + {0xc016, 48}, + {0x8001, 49}, + {0xc016, 49}, + {0x8001, 50}, + {0xc016, 50}, + {0x8001, 97}, + {0xc016, 97}, + {0x8001, 99}, + {0xc016, 99}, + {0x8001, 101}, + {0xc016, 101}, + {0x8001, 105}, + {0xc016, 105}, + {0x8001, 111}, + {0xc016, 111}, }, /* 3 */ { - {2, 0x02, 48}, - {9, 0x02, 48}, - {23, 0x02, 48}, - {40, 0x03, 48}, - {2, 0x02, 49}, - {9, 0x02, 49}, - {23, 0x02, 49}, - {40, 0x03, 49}, - {2, 0x02, 50}, - {9, 0x02, 50}, - {23, 0x02, 50}, - {40, 0x03, 50}, - {2, 0x02, 97}, - {9, 0x02, 97}, - {23, 0x02, 97}, - {40, 0x03, 97}, + {0x8002, 48}, + {0x8009, 48}, + {0x8017, 48}, + {0xc028, 48}, + {0x8002, 49}, + {0x8009, 49}, + {0x8017, 49}, + {0xc028, 49}, + {0x8002, 50}, + {0x8009, 50}, + {0x8017, 50}, + {0xc028, 50}, + {0x8002, 97}, + {0x8009, 97}, + {0x8017, 97}, + {0xc028, 97}, }, /* 4 */ { - {3, 0x02, 48}, - {6, 0x02, 48}, - {10, 0x02, 48}, - {15, 0x02, 48}, - {24, 0x02, 48}, - {31, 0x02, 48}, - {41, 0x02, 48}, - {56, 0x03, 48}, - {3, 0x02, 49}, - {6, 0x02, 49}, - {10, 0x02, 49}, - {15, 0x02, 49}, - {24, 0x02, 49}, - {31, 0x02, 49}, - {41, 0x02, 49}, - {56, 0x03, 49}, + {0x8003, 48}, + {0x8006, 48}, + {0x800a, 48}, + {0x800f, 48}, + {0x8018, 48}, + {0x801f, 48}, + {0x8029, 48}, + {0xc038, 48}, + {0x8003, 49}, + {0x8006, 49}, + {0x800a, 49}, + {0x800f, 49}, + {0x8018, 49}, + {0x801f, 49}, + {0x8029, 49}, + {0xc038, 49}, }, /* 5 */ { - {3, 0x02, 50}, - {6, 0x02, 50}, - {10, 0x02, 50}, - {15, 0x02, 50}, - {24, 0x02, 50}, - {31, 0x02, 50}, - {41, 0x02, 50}, - {56, 0x03, 50}, - {3, 0x02, 97}, - {6, 0x02, 97}, - {10, 0x02, 97}, - {15, 0x02, 97}, - {24, 0x02, 97}, - {31, 0x02, 97}, - {41, 0x02, 97}, - {56, 0x03, 97}, + {0x8003, 50}, + {0x8006, 50}, + {0x800a, 50}, + {0x800f, 50}, + {0x8018, 50}, + {0x801f, 50}, + {0x8029, 50}, + {0xc038, 50}, + {0x8003, 97}, + {0x8006, 97}, + {0x800a, 97}, + {0x800f, 97}, + {0x8018, 97}, + {0x801f, 97}, + {0x8029, 97}, + {0xc038, 97}, }, /* 6 */ { - {2, 0x02, 99}, - {9, 0x02, 99}, - {23, 0x02, 99}, - {40, 0x03, 99}, - {2, 0x02, 101}, - {9, 0x02, 101}, - {23, 0x02, 101}, - {40, 0x03, 101}, - {2, 0x02, 105}, - {9, 0x02, 105}, - {23, 0x02, 105}, - {40, 0x03, 105}, - {2, 0x02, 111}, - {9, 0x02, 111}, - {23, 0x02, 111}, - {40, 0x03, 111}, + {0x8002, 99}, + {0x8009, 99}, + {0x8017, 99}, + {0xc028, 99}, + {0x8002, 101}, + {0x8009, 101}, + {0x8017, 101}, + {0xc028, 101}, + {0x8002, 105}, + {0x8009, 105}, + {0x8017, 105}, + {0xc028, 105}, + {0x8002, 111}, + {0x8009, 111}, + {0x8017, 111}, + {0xc028, 111}, }, /* 7 */ { - {3, 0x02, 99}, - {6, 0x02, 99}, - {10, 0x02, 99}, - {15, 0x02, 99}, - {24, 0x02, 99}, - {31, 0x02, 99}, - {41, 0x02, 99}, - {56, 0x03, 99}, - {3, 0x02, 101}, - {6, 0x02, 101}, - {10, 0x02, 101}, - {15, 0x02, 101}, - {24, 0x02, 101}, - {31, 0x02, 101}, - {41, 0x02, 101}, - {56, 0x03, 101}, + {0x8003, 99}, + {0x8006, 99}, + {0x800a, 99}, + {0x800f, 99}, + {0x8018, 99}, + {0x801f, 99}, + {0x8029, 99}, + {0xc038, 99}, + {0x8003, 101}, + {0x8006, 101}, + {0x800a, 101}, + {0x800f, 101}, + {0x8018, 101}, + {0x801f, 101}, + {0x8029, 101}, + {0xc038, 101}, }, /* 8 */ { - {3, 0x02, 105}, - {6, 0x02, 105}, - {10, 0x02, 105}, - {15, 0x02, 105}, - {24, 0x02, 105}, - {31, 0x02, 105}, - {41, 0x02, 105}, - {56, 0x03, 105}, - {3, 0x02, 111}, - {6, 0x02, 111}, - {10, 0x02, 111}, - {15, 0x02, 111}, - {24, 0x02, 111}, - {31, 0x02, 111}, - {41, 0x02, 111}, - {56, 0x03, 111}, + {0x8003, 105}, + {0x8006, 105}, + {0x800a, 105}, + {0x800f, 105}, + {0x8018, 105}, + {0x801f, 105}, + {0x8029, 105}, + {0xc038, 105}, + {0x8003, 111}, + {0x8006, 111}, + {0x800a, 111}, + {0x800f, 111}, + {0x8018, 111}, + {0x801f, 111}, + {0x8029, 111}, + {0xc038, 111}, }, /* 9 */ { - {1, 0x02, 115}, - {22, 0x03, 115}, - {1, 0x02, 116}, - {22, 0x03, 116}, - {0, 0x03, 32}, - {0, 0x03, 37}, - {0, 0x03, 45}, - {0, 0x03, 46}, - {0, 0x03, 47}, - {0, 0x03, 51}, - {0, 0x03, 52}, - {0, 0x03, 53}, - {0, 0x03, 54}, - {0, 0x03, 55}, - {0, 0x03, 56}, - {0, 0x03, 57}, + {0x8001, 115}, + {0xc016, 115}, + {0x8001, 116}, + {0xc016, 116}, + {0xc000, 32}, + {0xc000, 37}, + {0xc000, 45}, + {0xc000, 46}, + {0xc000, 47}, + {0xc000, 51}, + {0xc000, 52}, + {0xc000, 53}, + {0xc000, 54}, + {0xc000, 55}, + {0xc000, 56}, + {0xc000, 57}, }, /* 10 */ { - {2, 0x02, 115}, - {9, 0x02, 115}, - {23, 0x02, 115}, - {40, 0x03, 115}, - {2, 0x02, 116}, - {9, 0x02, 116}, - {23, 0x02, 116}, - {40, 0x03, 116}, - {1, 0x02, 32}, - {22, 0x03, 32}, - {1, 0x02, 37}, - {22, 0x03, 37}, - {1, 0x02, 45}, - {22, 0x03, 45}, - {1, 0x02, 46}, - {22, 0x03, 46}, + {0x8002, 115}, + {0x8009, 115}, + {0x8017, 115}, + {0xc028, 115}, + {0x8002, 116}, + {0x8009, 116}, + {0x8017, 116}, + {0xc028, 116}, + {0x8001, 32}, + {0xc016, 32}, + {0x8001, 37}, + {0xc016, 37}, + {0x8001, 45}, + {0xc016, 45}, + {0x8001, 46}, + {0xc016, 46}, }, /* 11 */ { - {3, 0x02, 115}, - {6, 0x02, 115}, - {10, 0x02, 115}, - {15, 0x02, 115}, - {24, 0x02, 115}, - {31, 0x02, 115}, - {41, 0x02, 115}, - {56, 0x03, 115}, - {3, 0x02, 116}, - {6, 0x02, 116}, - {10, 0x02, 116}, - {15, 0x02, 116}, - {24, 0x02, 116}, - {31, 0x02, 116}, - {41, 0x02, 116}, - {56, 0x03, 116}, + {0x8003, 115}, + {0x8006, 115}, + {0x800a, 115}, + {0x800f, 115}, + {0x8018, 115}, + {0x801f, 115}, + {0x8029, 115}, + {0xc038, 115}, + {0x8003, 116}, + {0x8006, 116}, + {0x800a, 116}, + {0x800f, 116}, + {0x8018, 116}, + {0x801f, 116}, + {0x8029, 116}, + {0xc038, 116}, }, /* 12 */ { - {2, 0x02, 32}, - {9, 0x02, 32}, - {23, 0x02, 32}, - {40, 0x03, 32}, - {2, 0x02, 37}, - {9, 0x02, 37}, - {23, 0x02, 37}, - {40, 0x03, 37}, - {2, 0x02, 45}, - {9, 0x02, 45}, - {23, 0x02, 45}, - {40, 0x03, 45}, - {2, 0x02, 46}, - {9, 0x02, 46}, - {23, 0x02, 46}, - {40, 0x03, 46}, + {0x8002, 32}, + {0x8009, 32}, + {0x8017, 32}, + {0xc028, 32}, + {0x8002, 37}, + {0x8009, 37}, + {0x8017, 37}, + {0xc028, 37}, + {0x8002, 45}, + {0x8009, 45}, + {0x8017, 45}, + {0xc028, 45}, + {0x8002, 46}, + {0x8009, 46}, + {0x8017, 46}, + {0xc028, 46}, }, /* 13 */ { - {3, 0x02, 32}, - {6, 0x02, 32}, - {10, 0x02, 32}, - {15, 0x02, 32}, - {24, 0x02, 32}, - {31, 0x02, 32}, - {41, 0x02, 32}, - {56, 0x03, 32}, - {3, 0x02, 37}, - {6, 0x02, 37}, - {10, 0x02, 37}, - {15, 0x02, 37}, - {24, 0x02, 37}, - {31, 0x02, 37}, - {41, 0x02, 37}, - {56, 0x03, 37}, + {0x8003, 32}, + {0x8006, 32}, + {0x800a, 32}, + {0x800f, 32}, + {0x8018, 32}, + {0x801f, 32}, + {0x8029, 32}, + {0xc038, 32}, + {0x8003, 37}, + {0x8006, 37}, + {0x800a, 37}, + {0x800f, 37}, + {0x8018, 37}, + {0x801f, 37}, + {0x8029, 37}, + {0xc038, 37}, }, /* 14 */ { - {3, 0x02, 45}, - {6, 0x02, 45}, - {10, 0x02, 45}, - {15, 0x02, 45}, - {24, 0x02, 45}, - {31, 0x02, 45}, - {41, 0x02, 45}, - {56, 0x03, 45}, - {3, 0x02, 46}, - {6, 0x02, 46}, - {10, 0x02, 46}, - {15, 0x02, 46}, - {24, 0x02, 46}, - {31, 0x02, 46}, - {41, 0x02, 46}, - {56, 0x03, 46}, + {0x8003, 45}, + {0x8006, 45}, + {0x800a, 45}, + {0x800f, 45}, + {0x8018, 45}, + {0x801f, 45}, + {0x8029, 45}, + {0xc038, 45}, + {0x8003, 46}, + {0x8006, 46}, + {0x800a, 46}, + {0x800f, 46}, + {0x8018, 46}, + {0x801f, 46}, + {0x8029, 46}, + {0xc038, 46}, }, /* 15 */ { - {1, 0x02, 47}, - {22, 0x03, 47}, - {1, 0x02, 51}, - {22, 0x03, 51}, - {1, 0x02, 52}, - {22, 0x03, 52}, - {1, 0x02, 53}, - {22, 0x03, 53}, - {1, 0x02, 54}, - {22, 0x03, 54}, - {1, 0x02, 55}, - {22, 0x03, 55}, - {1, 0x02, 56}, - {22, 0x03, 56}, - {1, 0x02, 57}, - {22, 0x03, 57}, + {0x8001, 47}, + {0xc016, 47}, + {0x8001, 51}, + {0xc016, 51}, + {0x8001, 52}, + {0xc016, 52}, + {0x8001, 53}, + {0xc016, 53}, + {0x8001, 54}, + {0xc016, 54}, + {0x8001, 55}, + {0xc016, 55}, + {0x8001, 56}, + {0xc016, 56}, + {0x8001, 57}, + {0xc016, 57}, }, /* 16 */ { - {2, 0x02, 47}, - {9, 0x02, 47}, - {23, 0x02, 47}, - {40, 0x03, 47}, - {2, 0x02, 51}, - {9, 0x02, 51}, - {23, 0x02, 51}, - {40, 0x03, 51}, - {2, 0x02, 52}, - {9, 0x02, 52}, - {23, 0x02, 52}, - {40, 0x03, 52}, - {2, 0x02, 53}, - {9, 0x02, 53}, - {23, 0x02, 53}, - {40, 0x03, 53}, + {0x8002, 47}, + {0x8009, 47}, + {0x8017, 47}, + {0xc028, 47}, + {0x8002, 51}, + {0x8009, 51}, + {0x8017, 51}, + {0xc028, 51}, + {0x8002, 52}, + {0x8009, 52}, + {0x8017, 52}, + {0xc028, 52}, + {0x8002, 53}, + {0x8009, 53}, + {0x8017, 53}, + {0xc028, 53}, }, /* 17 */ { - {3, 0x02, 47}, - {6, 0x02, 47}, - {10, 0x02, 47}, - {15, 0x02, 47}, - {24, 0x02, 47}, - {31, 0x02, 47}, - {41, 0x02, 47}, - {56, 0x03, 47}, - {3, 0x02, 51}, - {6, 0x02, 51}, - {10, 0x02, 51}, - {15, 0x02, 51}, - {24, 0x02, 51}, - {31, 0x02, 51}, - {41, 0x02, 51}, - {56, 0x03, 51}, + {0x8003, 47}, + {0x8006, 47}, + {0x800a, 47}, + {0x800f, 47}, + {0x8018, 47}, + {0x801f, 47}, + {0x8029, 47}, + {0xc038, 47}, + {0x8003, 51}, + {0x8006, 51}, + {0x800a, 51}, + {0x800f, 51}, + {0x8018, 51}, + {0x801f, 51}, + {0x8029, 51}, + {0xc038, 51}, }, /* 18 */ { - {3, 0x02, 52}, - {6, 0x02, 52}, - {10, 0x02, 52}, - {15, 0x02, 52}, - {24, 0x02, 52}, - {31, 0x02, 52}, - {41, 0x02, 52}, - {56, 0x03, 52}, - {3, 0x02, 53}, - {6, 0x02, 53}, - {10, 0x02, 53}, - {15, 0x02, 53}, - {24, 0x02, 53}, - {31, 0x02, 53}, - {41, 0x02, 53}, - {56, 0x03, 53}, + {0x8003, 52}, + {0x8006, 52}, + {0x800a, 52}, + {0x800f, 52}, + {0x8018, 52}, + {0x801f, 52}, + {0x8029, 52}, + {0xc038, 52}, + {0x8003, 53}, + {0x8006, 53}, + {0x800a, 53}, + {0x800f, 53}, + {0x8018, 53}, + {0x801f, 53}, + {0x8029, 53}, + {0xc038, 53}, }, /* 19 */ { - {2, 0x02, 54}, - {9, 0x02, 54}, - {23, 0x02, 54}, - {40, 0x03, 54}, - {2, 0x02, 55}, - {9, 0x02, 55}, - {23, 0x02, 55}, - {40, 0x03, 55}, - {2, 0x02, 56}, - {9, 0x02, 56}, - {23, 0x02, 56}, - {40, 0x03, 56}, - {2, 0x02, 57}, - {9, 0x02, 57}, - {23, 0x02, 57}, - {40, 0x03, 57}, + {0x8002, 54}, + {0x8009, 54}, + {0x8017, 54}, + {0xc028, 54}, + {0x8002, 55}, + {0x8009, 55}, + {0x8017, 55}, + {0xc028, 55}, + {0x8002, 56}, + {0x8009, 56}, + {0x8017, 56}, + {0xc028, 56}, + {0x8002, 57}, + {0x8009, 57}, + {0x8017, 57}, + {0xc028, 57}, }, /* 20 */ { - {3, 0x02, 54}, - {6, 0x02, 54}, - {10, 0x02, 54}, - {15, 0x02, 54}, - {24, 0x02, 54}, - {31, 0x02, 54}, - {41, 0x02, 54}, - {56, 0x03, 54}, - {3, 0x02, 55}, - {6, 0x02, 55}, - {10, 0x02, 55}, - {15, 0x02, 55}, - {24, 0x02, 55}, - {31, 0x02, 55}, - {41, 0x02, 55}, - {56, 0x03, 55}, + {0x8003, 54}, + {0x8006, 54}, + {0x800a, 54}, + {0x800f, 54}, + {0x8018, 54}, + {0x801f, 54}, + {0x8029, 54}, + {0xc038, 54}, + {0x8003, 55}, + {0x8006, 55}, + {0x800a, 55}, + {0x800f, 55}, + {0x8018, 55}, + {0x801f, 55}, + {0x8029, 55}, + {0xc038, 55}, }, /* 21 */ { - {3, 0x02, 56}, - {6, 0x02, 56}, - {10, 0x02, 56}, - {15, 0x02, 56}, - {24, 0x02, 56}, - {31, 0x02, 56}, - {41, 0x02, 56}, - {56, 0x03, 56}, - {3, 0x02, 57}, - {6, 0x02, 57}, - {10, 0x02, 57}, - {15, 0x02, 57}, - {24, 0x02, 57}, - {31, 0x02, 57}, - {41, 0x02, 57}, - {56, 0x03, 57}, + {0x8003, 56}, + {0x8006, 56}, + {0x800a, 56}, + {0x800f, 56}, + {0x8018, 56}, + {0x801f, 56}, + {0x8029, 56}, + {0xc038, 56}, + {0x8003, 57}, + {0x8006, 57}, + {0x800a, 57}, + {0x800f, 57}, + {0x8018, 57}, + {0x801f, 57}, + {0x8029, 57}, + {0xc038, 57}, }, /* 22 */ { - {26, 0x00, 0}, - {27, 0x00, 0}, - {29, 0x00, 0}, - {30, 0x00, 0}, - {33, 0x00, 0}, - {34, 0x00, 0}, - {36, 0x00, 0}, - {37, 0x00, 0}, - {43, 0x00, 0}, - {46, 0x00, 0}, - {50, 0x00, 0}, - {53, 0x00, 0}, - {58, 0x00, 0}, - {61, 0x00, 0}, - {65, 0x00, 0}, - {68, 0x01, 0}, + {0x1a, 0}, + {0x1b, 0}, + {0x1d, 0}, + {0x1e, 0}, + {0x21, 0}, + {0x22, 0}, + {0x24, 0}, + {0x25, 0}, + {0x2b, 0}, + {0x2e, 0}, + {0x32, 0}, + {0x35, 0}, + {0x3a, 0}, + {0x3d, 0}, + {0x41, 0}, + {0x4044, 0}, }, /* 23 */ { - {0, 0x03, 61}, - {0, 0x03, 65}, - {0, 0x03, 95}, - {0, 0x03, 98}, - {0, 0x03, 100}, - {0, 0x03, 102}, - {0, 0x03, 103}, - {0, 0x03, 104}, - {0, 0x03, 108}, - {0, 0x03, 109}, - {0, 0x03, 110}, - {0, 0x03, 112}, - {0, 0x03, 114}, - {0, 0x03, 117}, - {38, 0x00, 0}, - {39, 0x00, 0}, + {0xc000, 61}, + {0xc000, 65}, + {0xc000, 95}, + {0xc000, 98}, + {0xc000, 100}, + {0xc000, 102}, + {0xc000, 103}, + {0xc000, 104}, + {0xc000, 108}, + {0xc000, 109}, + {0xc000, 110}, + {0xc000, 112}, + {0xc000, 114}, + {0xc000, 117}, + {0x26, 0}, + {0x27, 0}, }, /* 24 */ { - {1, 0x02, 61}, - {22, 0x03, 61}, - {1, 0x02, 65}, - {22, 0x03, 65}, - {1, 0x02, 95}, - {22, 0x03, 95}, - {1, 0x02, 98}, - {22, 0x03, 98}, - {1, 0x02, 100}, - {22, 0x03, 100}, - {1, 0x02, 102}, - {22, 0x03, 102}, - {1, 0x02, 103}, - {22, 0x03, 103}, - {1, 0x02, 104}, - {22, 0x03, 104}, + {0x8001, 61}, + {0xc016, 61}, + {0x8001, 65}, + {0xc016, 65}, + {0x8001, 95}, + {0xc016, 95}, + {0x8001, 98}, + {0xc016, 98}, + {0x8001, 100}, + {0xc016, 100}, + {0x8001, 102}, + {0xc016, 102}, + {0x8001, 103}, + {0xc016, 103}, + {0x8001, 104}, + {0xc016, 104}, }, /* 25 */ { - {2, 0x02, 61}, - {9, 0x02, 61}, - {23, 0x02, 61}, - {40, 0x03, 61}, - {2, 0x02, 65}, - {9, 0x02, 65}, - {23, 0x02, 65}, - {40, 0x03, 65}, - {2, 0x02, 95}, - {9, 0x02, 95}, - {23, 0x02, 95}, - {40, 0x03, 95}, - {2, 0x02, 98}, - {9, 0x02, 98}, - {23, 0x02, 98}, - {40, 0x03, 98}, + {0x8002, 61}, + {0x8009, 61}, + {0x8017, 61}, + {0xc028, 61}, + {0x8002, 65}, + {0x8009, 65}, + {0x8017, 65}, + {0xc028, 65}, + {0x8002, 95}, + {0x8009, 95}, + {0x8017, 95}, + {0xc028, 95}, + {0x8002, 98}, + {0x8009, 98}, + {0x8017, 98}, + {0xc028, 98}, }, /* 26 */ { - {3, 0x02, 61}, - {6, 0x02, 61}, - {10, 0x02, 61}, - {15, 0x02, 61}, - {24, 0x02, 61}, - {31, 0x02, 61}, - {41, 0x02, 61}, - {56, 0x03, 61}, - {3, 0x02, 65}, - {6, 0x02, 65}, - {10, 0x02, 65}, - {15, 0x02, 65}, - {24, 0x02, 65}, - {31, 0x02, 65}, - {41, 0x02, 65}, - {56, 0x03, 65}, + {0x8003, 61}, + {0x8006, 61}, + {0x800a, 61}, + {0x800f, 61}, + {0x8018, 61}, + {0x801f, 61}, + {0x8029, 61}, + {0xc038, 61}, + {0x8003, 65}, + {0x8006, 65}, + {0x800a, 65}, + {0x800f, 65}, + {0x8018, 65}, + {0x801f, 65}, + {0x8029, 65}, + {0xc038, 65}, }, /* 27 */ { - {3, 0x02, 95}, - {6, 0x02, 95}, - {10, 0x02, 95}, - {15, 0x02, 95}, - {24, 0x02, 95}, - {31, 0x02, 95}, - {41, 0x02, 95}, - {56, 0x03, 95}, - {3, 0x02, 98}, - {6, 0x02, 98}, - {10, 0x02, 98}, - {15, 0x02, 98}, - {24, 0x02, 98}, - {31, 0x02, 98}, - {41, 0x02, 98}, - {56, 0x03, 98}, + {0x8003, 95}, + {0x8006, 95}, + {0x800a, 95}, + {0x800f, 95}, + {0x8018, 95}, + {0x801f, 95}, + {0x8029, 95}, + {0xc038, 95}, + {0x8003, 98}, + {0x8006, 98}, + {0x800a, 98}, + {0x800f, 98}, + {0x8018, 98}, + {0x801f, 98}, + {0x8029, 98}, + {0xc038, 98}, }, /* 28 */ { - {2, 0x02, 100}, - {9, 0x02, 100}, - {23, 0x02, 100}, - {40, 0x03, 100}, - {2, 0x02, 102}, - {9, 0x02, 102}, - {23, 0x02, 102}, - {40, 0x03, 102}, - {2, 0x02, 103}, - {9, 0x02, 103}, - {23, 0x02, 103}, - {40, 0x03, 103}, - {2, 0x02, 104}, - {9, 0x02, 104}, - {23, 0x02, 104}, - {40, 0x03, 104}, + {0x8002, 100}, + {0x8009, 100}, + {0x8017, 100}, + {0xc028, 100}, + {0x8002, 102}, + {0x8009, 102}, + {0x8017, 102}, + {0xc028, 102}, + {0x8002, 103}, + {0x8009, 103}, + {0x8017, 103}, + {0xc028, 103}, + {0x8002, 104}, + {0x8009, 104}, + {0x8017, 104}, + {0xc028, 104}, }, /* 29 */ { - {3, 0x02, 100}, - {6, 0x02, 100}, - {10, 0x02, 100}, - {15, 0x02, 100}, - {24, 0x02, 100}, - {31, 0x02, 100}, - {41, 0x02, 100}, - {56, 0x03, 100}, - {3, 0x02, 102}, - {6, 0x02, 102}, - {10, 0x02, 102}, - {15, 0x02, 102}, - {24, 0x02, 102}, - {31, 0x02, 102}, - {41, 0x02, 102}, - {56, 0x03, 102}, + {0x8003, 100}, + {0x8006, 100}, + {0x800a, 100}, + {0x800f, 100}, + {0x8018, 100}, + {0x801f, 100}, + {0x8029, 100}, + {0xc038, 100}, + {0x8003, 102}, + {0x8006, 102}, + {0x800a, 102}, + {0x800f, 102}, + {0x8018, 102}, + {0x801f, 102}, + {0x8029, 102}, + {0xc038, 102}, }, /* 30 */ { - {3, 0x02, 103}, - {6, 0x02, 103}, - {10, 0x02, 103}, - {15, 0x02, 103}, - {24, 0x02, 103}, - {31, 0x02, 103}, - {41, 0x02, 103}, - {56, 0x03, 103}, - {3, 0x02, 104}, - {6, 0x02, 104}, - {10, 0x02, 104}, - {15, 0x02, 104}, - {24, 0x02, 104}, - {31, 0x02, 104}, - {41, 0x02, 104}, - {56, 0x03, 104}, + {0x8003, 103}, + {0x8006, 103}, + {0x800a, 103}, + {0x800f, 103}, + {0x8018, 103}, + {0x801f, 103}, + {0x8029, 103}, + {0xc038, 103}, + {0x8003, 104}, + {0x8006, 104}, + {0x800a, 104}, + {0x800f, 104}, + {0x8018, 104}, + {0x801f, 104}, + {0x8029, 104}, + {0xc038, 104}, }, /* 31 */ { - {1, 0x02, 108}, - {22, 0x03, 108}, - {1, 0x02, 109}, - {22, 0x03, 109}, - {1, 0x02, 110}, - {22, 0x03, 110}, - {1, 0x02, 112}, - {22, 0x03, 112}, - {1, 0x02, 114}, - {22, 0x03, 114}, - {1, 0x02, 117}, - {22, 0x03, 117}, - {0, 0x03, 58}, - {0, 0x03, 66}, - {0, 0x03, 67}, - {0, 0x03, 68}, + {0x8001, 108}, + {0xc016, 108}, + {0x8001, 109}, + {0xc016, 109}, + {0x8001, 110}, + {0xc016, 110}, + {0x8001, 112}, + {0xc016, 112}, + {0x8001, 114}, + {0xc016, 114}, + {0x8001, 117}, + {0xc016, 117}, + {0xc000, 58}, + {0xc000, 66}, + {0xc000, 67}, + {0xc000, 68}, }, /* 32 */ { - {2, 0x02, 108}, - {9, 0x02, 108}, - {23, 0x02, 108}, - {40, 0x03, 108}, - {2, 0x02, 109}, - {9, 0x02, 109}, - {23, 0x02, 109}, - {40, 0x03, 109}, - {2, 0x02, 110}, - {9, 0x02, 110}, - {23, 0x02, 110}, - {40, 0x03, 110}, - {2, 0x02, 112}, - {9, 0x02, 112}, - {23, 0x02, 112}, - {40, 0x03, 112}, + {0x8002, 108}, + {0x8009, 108}, + {0x8017, 108}, + {0xc028, 108}, + {0x8002, 109}, + {0x8009, 109}, + {0x8017, 109}, + {0xc028, 109}, + {0x8002, 110}, + {0x8009, 110}, + {0x8017, 110}, + {0xc028, 110}, + {0x8002, 112}, + {0x8009, 112}, + {0x8017, 112}, + {0xc028, 112}, }, /* 33 */ { - {3, 0x02, 108}, - {6, 0x02, 108}, - {10, 0x02, 108}, - {15, 0x02, 108}, - {24, 0x02, 108}, - {31, 0x02, 108}, - {41, 0x02, 108}, - {56, 0x03, 108}, - {3, 0x02, 109}, - {6, 0x02, 109}, - {10, 0x02, 109}, - {15, 0x02, 109}, - {24, 0x02, 109}, - {31, 0x02, 109}, - {41, 0x02, 109}, - {56, 0x03, 109}, + {0x8003, 108}, + {0x8006, 108}, + {0x800a, 108}, + {0x800f, 108}, + {0x8018, 108}, + {0x801f, 108}, + {0x8029, 108}, + {0xc038, 108}, + {0x8003, 109}, + {0x8006, 109}, + {0x800a, 109}, + {0x800f, 109}, + {0x8018, 109}, + {0x801f, 109}, + {0x8029, 109}, + {0xc038, 109}, }, /* 34 */ { - {3, 0x02, 110}, - {6, 0x02, 110}, - {10, 0x02, 110}, - {15, 0x02, 110}, - {24, 0x02, 110}, - {31, 0x02, 110}, - {41, 0x02, 110}, - {56, 0x03, 110}, - {3, 0x02, 112}, - {6, 0x02, 112}, - {10, 0x02, 112}, - {15, 0x02, 112}, - {24, 0x02, 112}, - {31, 0x02, 112}, - {41, 0x02, 112}, - {56, 0x03, 112}, + {0x8003, 110}, + {0x8006, 110}, + {0x800a, 110}, + {0x800f, 110}, + {0x8018, 110}, + {0x801f, 110}, + {0x8029, 110}, + {0xc038, 110}, + {0x8003, 112}, + {0x8006, 112}, + {0x800a, 112}, + {0x800f, 112}, + {0x8018, 112}, + {0x801f, 112}, + {0x8029, 112}, + {0xc038, 112}, }, /* 35 */ { - {2, 0x02, 114}, - {9, 0x02, 114}, - {23, 0x02, 114}, - {40, 0x03, 114}, - {2, 0x02, 117}, - {9, 0x02, 117}, - {23, 0x02, 117}, - {40, 0x03, 117}, - {1, 0x02, 58}, - {22, 0x03, 58}, - {1, 0x02, 66}, - {22, 0x03, 66}, - {1, 0x02, 67}, - {22, 0x03, 67}, - {1, 0x02, 68}, - {22, 0x03, 68}, + {0x8002, 114}, + {0x8009, 114}, + {0x8017, 114}, + {0xc028, 114}, + {0x8002, 117}, + {0x8009, 117}, + {0x8017, 117}, + {0xc028, 117}, + {0x8001, 58}, + {0xc016, 58}, + {0x8001, 66}, + {0xc016, 66}, + {0x8001, 67}, + {0xc016, 67}, + {0x8001, 68}, + {0xc016, 68}, }, /* 36 */ { - {3, 0x02, 114}, - {6, 0x02, 114}, - {10, 0x02, 114}, - {15, 0x02, 114}, - {24, 0x02, 114}, - {31, 0x02, 114}, - {41, 0x02, 114}, - {56, 0x03, 114}, - {3, 0x02, 117}, - {6, 0x02, 117}, - {10, 0x02, 117}, - {15, 0x02, 117}, - {24, 0x02, 117}, - {31, 0x02, 117}, - {41, 0x02, 117}, - {56, 0x03, 117}, + {0x8003, 114}, + {0x8006, 114}, + {0x800a, 114}, + {0x800f, 114}, + {0x8018, 114}, + {0x801f, 114}, + {0x8029, 114}, + {0xc038, 114}, + {0x8003, 117}, + {0x8006, 117}, + {0x800a, 117}, + {0x800f, 117}, + {0x8018, 117}, + {0x801f, 117}, + {0x8029, 117}, + {0xc038, 117}, }, /* 37 */ { - {2, 0x02, 58}, - {9, 0x02, 58}, - {23, 0x02, 58}, - {40, 0x03, 58}, - {2, 0x02, 66}, - {9, 0x02, 66}, - {23, 0x02, 66}, - {40, 0x03, 66}, - {2, 0x02, 67}, - {9, 0x02, 67}, - {23, 0x02, 67}, - {40, 0x03, 67}, - {2, 0x02, 68}, - {9, 0x02, 68}, - {23, 0x02, 68}, - {40, 0x03, 68}, + {0x8002, 58}, + {0x8009, 58}, + {0x8017, 58}, + {0xc028, 58}, + {0x8002, 66}, + {0x8009, 66}, + {0x8017, 66}, + {0xc028, 66}, + {0x8002, 67}, + {0x8009, 67}, + {0x8017, 67}, + {0xc028, 67}, + {0x8002, 68}, + {0x8009, 68}, + {0x8017, 68}, + {0xc028, 68}, }, /* 38 */ { - {3, 0x02, 58}, - {6, 0x02, 58}, - {10, 0x02, 58}, - {15, 0x02, 58}, - {24, 0x02, 58}, - {31, 0x02, 58}, - {41, 0x02, 58}, - {56, 0x03, 58}, - {3, 0x02, 66}, - {6, 0x02, 66}, - {10, 0x02, 66}, - {15, 0x02, 66}, - {24, 0x02, 66}, - {31, 0x02, 66}, - {41, 0x02, 66}, - {56, 0x03, 66}, + {0x8003, 58}, + {0x8006, 58}, + {0x800a, 58}, + {0x800f, 58}, + {0x8018, 58}, + {0x801f, 58}, + {0x8029, 58}, + {0xc038, 58}, + {0x8003, 66}, + {0x8006, 66}, + {0x800a, 66}, + {0x800f, 66}, + {0x8018, 66}, + {0x801f, 66}, + {0x8029, 66}, + {0xc038, 66}, }, /* 39 */ { - {3, 0x02, 67}, - {6, 0x02, 67}, - {10, 0x02, 67}, - {15, 0x02, 67}, - {24, 0x02, 67}, - {31, 0x02, 67}, - {41, 0x02, 67}, - {56, 0x03, 67}, - {3, 0x02, 68}, - {6, 0x02, 68}, - {10, 0x02, 68}, - {15, 0x02, 68}, - {24, 0x02, 68}, - {31, 0x02, 68}, - {41, 0x02, 68}, - {56, 0x03, 68}, + {0x8003, 67}, + {0x8006, 67}, + {0x800a, 67}, + {0x800f, 67}, + {0x8018, 67}, + {0x801f, 67}, + {0x8029, 67}, + {0xc038, 67}, + {0x8003, 68}, + {0x8006, 68}, + {0x800a, 68}, + {0x800f, 68}, + {0x8018, 68}, + {0x801f, 68}, + {0x8029, 68}, + {0xc038, 68}, }, /* 40 */ { - {44, 0x00, 0}, - {45, 0x00, 0}, - {47, 0x00, 0}, - {48, 0x00, 0}, - {51, 0x00, 0}, - {52, 0x00, 0}, - {54, 0x00, 0}, - {55, 0x00, 0}, - {59, 0x00, 0}, - {60, 0x00, 0}, - {62, 0x00, 0}, - {63, 0x00, 0}, - {66, 0x00, 0}, - {67, 0x00, 0}, - {69, 0x00, 0}, - {72, 0x01, 0}, + {0x2c, 0}, + {0x2d, 0}, + {0x2f, 0}, + {0x30, 0}, + {0x33, 0}, + {0x34, 0}, + {0x36, 0}, + {0x37, 0}, + {0x3b, 0}, + {0x3c, 0}, + {0x3e, 0}, + {0x3f, 0}, + {0x42, 0}, + {0x43, 0}, + {0x45, 0}, + {0x4048, 0}, }, /* 41 */ { - {0, 0x03, 69}, - {0, 0x03, 70}, - {0, 0x03, 71}, - {0, 0x03, 72}, - {0, 0x03, 73}, - {0, 0x03, 74}, - {0, 0x03, 75}, - {0, 0x03, 76}, - {0, 0x03, 77}, - {0, 0x03, 78}, - {0, 0x03, 79}, - {0, 0x03, 80}, - {0, 0x03, 81}, - {0, 0x03, 82}, - {0, 0x03, 83}, - {0, 0x03, 84}, + {0xc000, 69}, + {0xc000, 70}, + {0xc000, 71}, + {0xc000, 72}, + {0xc000, 73}, + {0xc000, 74}, + {0xc000, 75}, + {0xc000, 76}, + {0xc000, 77}, + {0xc000, 78}, + {0xc000, 79}, + {0xc000, 80}, + {0xc000, 81}, + {0xc000, 82}, + {0xc000, 83}, + {0xc000, 84}, }, /* 42 */ { - {1, 0x02, 69}, - {22, 0x03, 69}, - {1, 0x02, 70}, - {22, 0x03, 70}, - {1, 0x02, 71}, - {22, 0x03, 71}, - {1, 0x02, 72}, - {22, 0x03, 72}, - {1, 0x02, 73}, - {22, 0x03, 73}, - {1, 0x02, 74}, - {22, 0x03, 74}, - {1, 0x02, 75}, - {22, 0x03, 75}, - {1, 0x02, 76}, - {22, 0x03, 76}, + {0x8001, 69}, + {0xc016, 69}, + {0x8001, 70}, + {0xc016, 70}, + {0x8001, 71}, + {0xc016, 71}, + {0x8001, 72}, + {0xc016, 72}, + {0x8001, 73}, + {0xc016, 73}, + {0x8001, 74}, + {0xc016, 74}, + {0x8001, 75}, + {0xc016, 75}, + {0x8001, 76}, + {0xc016, 76}, }, /* 43 */ { - {2, 0x02, 69}, - {9, 0x02, 69}, - {23, 0x02, 69}, - {40, 0x03, 69}, - {2, 0x02, 70}, - {9, 0x02, 70}, - {23, 0x02, 70}, - {40, 0x03, 70}, - {2, 0x02, 71}, - {9, 0x02, 71}, - {23, 0x02, 71}, - {40, 0x03, 71}, - {2, 0x02, 72}, - {9, 0x02, 72}, - {23, 0x02, 72}, - {40, 0x03, 72}, + {0x8002, 69}, + {0x8009, 69}, + {0x8017, 69}, + {0xc028, 69}, + {0x8002, 70}, + {0x8009, 70}, + {0x8017, 70}, + {0xc028, 70}, + {0x8002, 71}, + {0x8009, 71}, + {0x8017, 71}, + {0xc028, 71}, + {0x8002, 72}, + {0x8009, 72}, + {0x8017, 72}, + {0xc028, 72}, }, /* 44 */ { - {3, 0x02, 69}, - {6, 0x02, 69}, - {10, 0x02, 69}, - {15, 0x02, 69}, - {24, 0x02, 69}, - {31, 0x02, 69}, - {41, 0x02, 69}, - {56, 0x03, 69}, - {3, 0x02, 70}, - {6, 0x02, 70}, - {10, 0x02, 70}, - {15, 0x02, 70}, - {24, 0x02, 70}, - {31, 0x02, 70}, - {41, 0x02, 70}, - {56, 0x03, 70}, + {0x8003, 69}, + {0x8006, 69}, + {0x800a, 69}, + {0x800f, 69}, + {0x8018, 69}, + {0x801f, 69}, + {0x8029, 69}, + {0xc038, 69}, + {0x8003, 70}, + {0x8006, 70}, + {0x800a, 70}, + {0x800f, 70}, + {0x8018, 70}, + {0x801f, 70}, + {0x8029, 70}, + {0xc038, 70}, }, /* 45 */ { - {3, 0x02, 71}, - {6, 0x02, 71}, - {10, 0x02, 71}, - {15, 0x02, 71}, - {24, 0x02, 71}, - {31, 0x02, 71}, - {41, 0x02, 71}, - {56, 0x03, 71}, - {3, 0x02, 72}, - {6, 0x02, 72}, - {10, 0x02, 72}, - {15, 0x02, 72}, - {24, 0x02, 72}, - {31, 0x02, 72}, - {41, 0x02, 72}, - {56, 0x03, 72}, + {0x8003, 71}, + {0x8006, 71}, + {0x800a, 71}, + {0x800f, 71}, + {0x8018, 71}, + {0x801f, 71}, + {0x8029, 71}, + {0xc038, 71}, + {0x8003, 72}, + {0x8006, 72}, + {0x800a, 72}, + {0x800f, 72}, + {0x8018, 72}, + {0x801f, 72}, + {0x8029, 72}, + {0xc038, 72}, }, /* 46 */ { - {2, 0x02, 73}, - {9, 0x02, 73}, - {23, 0x02, 73}, - {40, 0x03, 73}, - {2, 0x02, 74}, - {9, 0x02, 74}, - {23, 0x02, 74}, - {40, 0x03, 74}, - {2, 0x02, 75}, - {9, 0x02, 75}, - {23, 0x02, 75}, - {40, 0x03, 75}, - {2, 0x02, 76}, - {9, 0x02, 76}, - {23, 0x02, 76}, - {40, 0x03, 76}, + {0x8002, 73}, + {0x8009, 73}, + {0x8017, 73}, + {0xc028, 73}, + {0x8002, 74}, + {0x8009, 74}, + {0x8017, 74}, + {0xc028, 74}, + {0x8002, 75}, + {0x8009, 75}, + {0x8017, 75}, + {0xc028, 75}, + {0x8002, 76}, + {0x8009, 76}, + {0x8017, 76}, + {0xc028, 76}, }, /* 47 */ { - {3, 0x02, 73}, - {6, 0x02, 73}, - {10, 0x02, 73}, - {15, 0x02, 73}, - {24, 0x02, 73}, - {31, 0x02, 73}, - {41, 0x02, 73}, - {56, 0x03, 73}, - {3, 0x02, 74}, - {6, 0x02, 74}, - {10, 0x02, 74}, - {15, 0x02, 74}, - {24, 0x02, 74}, - {31, 0x02, 74}, - {41, 0x02, 74}, - {56, 0x03, 74}, + {0x8003, 73}, + {0x8006, 73}, + {0x800a, 73}, + {0x800f, 73}, + {0x8018, 73}, + {0x801f, 73}, + {0x8029, 73}, + {0xc038, 73}, + {0x8003, 74}, + {0x8006, 74}, + {0x800a, 74}, + {0x800f, 74}, + {0x8018, 74}, + {0x801f, 74}, + {0x8029, 74}, + {0xc038, 74}, }, /* 48 */ { - {3, 0x02, 75}, - {6, 0x02, 75}, - {10, 0x02, 75}, - {15, 0x02, 75}, - {24, 0x02, 75}, - {31, 0x02, 75}, - {41, 0x02, 75}, - {56, 0x03, 75}, - {3, 0x02, 76}, - {6, 0x02, 76}, - {10, 0x02, 76}, - {15, 0x02, 76}, - {24, 0x02, 76}, - {31, 0x02, 76}, - {41, 0x02, 76}, - {56, 0x03, 76}, + {0x8003, 75}, + {0x8006, 75}, + {0x800a, 75}, + {0x800f, 75}, + {0x8018, 75}, + {0x801f, 75}, + {0x8029, 75}, + {0xc038, 75}, + {0x8003, 76}, + {0x8006, 76}, + {0x800a, 76}, + {0x800f, 76}, + {0x8018, 76}, + {0x801f, 76}, + {0x8029, 76}, + {0xc038, 76}, }, /* 49 */ { - {1, 0x02, 77}, - {22, 0x03, 77}, - {1, 0x02, 78}, - {22, 0x03, 78}, - {1, 0x02, 79}, - {22, 0x03, 79}, - {1, 0x02, 80}, - {22, 0x03, 80}, - {1, 0x02, 81}, - {22, 0x03, 81}, - {1, 0x02, 82}, - {22, 0x03, 82}, - {1, 0x02, 83}, - {22, 0x03, 83}, - {1, 0x02, 84}, - {22, 0x03, 84}, + {0x8001, 77}, + {0xc016, 77}, + {0x8001, 78}, + {0xc016, 78}, + {0x8001, 79}, + {0xc016, 79}, + {0x8001, 80}, + {0xc016, 80}, + {0x8001, 81}, + {0xc016, 81}, + {0x8001, 82}, + {0xc016, 82}, + {0x8001, 83}, + {0xc016, 83}, + {0x8001, 84}, + {0xc016, 84}, }, /* 50 */ { - {2, 0x02, 77}, - {9, 0x02, 77}, - {23, 0x02, 77}, - {40, 0x03, 77}, - {2, 0x02, 78}, - {9, 0x02, 78}, - {23, 0x02, 78}, - {40, 0x03, 78}, - {2, 0x02, 79}, - {9, 0x02, 79}, - {23, 0x02, 79}, - {40, 0x03, 79}, - {2, 0x02, 80}, - {9, 0x02, 80}, - {23, 0x02, 80}, - {40, 0x03, 80}, + {0x8002, 77}, + {0x8009, 77}, + {0x8017, 77}, + {0xc028, 77}, + {0x8002, 78}, + {0x8009, 78}, + {0x8017, 78}, + {0xc028, 78}, + {0x8002, 79}, + {0x8009, 79}, + {0x8017, 79}, + {0xc028, 79}, + {0x8002, 80}, + {0x8009, 80}, + {0x8017, 80}, + {0xc028, 80}, }, /* 51 */ { - {3, 0x02, 77}, - {6, 0x02, 77}, - {10, 0x02, 77}, - {15, 0x02, 77}, - {24, 0x02, 77}, - {31, 0x02, 77}, - {41, 0x02, 77}, - {56, 0x03, 77}, - {3, 0x02, 78}, - {6, 0x02, 78}, - {10, 0x02, 78}, - {15, 0x02, 78}, - {24, 0x02, 78}, - {31, 0x02, 78}, - {41, 0x02, 78}, - {56, 0x03, 78}, + {0x8003, 77}, + {0x8006, 77}, + {0x800a, 77}, + {0x800f, 77}, + {0x8018, 77}, + {0x801f, 77}, + {0x8029, 77}, + {0xc038, 77}, + {0x8003, 78}, + {0x8006, 78}, + {0x800a, 78}, + {0x800f, 78}, + {0x8018, 78}, + {0x801f, 78}, + {0x8029, 78}, + {0xc038, 78}, }, /* 52 */ { - {3, 0x02, 79}, - {6, 0x02, 79}, - {10, 0x02, 79}, - {15, 0x02, 79}, - {24, 0x02, 79}, - {31, 0x02, 79}, - {41, 0x02, 79}, - {56, 0x03, 79}, - {3, 0x02, 80}, - {6, 0x02, 80}, - {10, 0x02, 80}, - {15, 0x02, 80}, - {24, 0x02, 80}, - {31, 0x02, 80}, - {41, 0x02, 80}, - {56, 0x03, 80}, + {0x8003, 79}, + {0x8006, 79}, + {0x800a, 79}, + {0x800f, 79}, + {0x8018, 79}, + {0x801f, 79}, + {0x8029, 79}, + {0xc038, 79}, + {0x8003, 80}, + {0x8006, 80}, + {0x800a, 80}, + {0x800f, 80}, + {0x8018, 80}, + {0x801f, 80}, + {0x8029, 80}, + {0xc038, 80}, }, /* 53 */ { - {2, 0x02, 81}, - {9, 0x02, 81}, - {23, 0x02, 81}, - {40, 0x03, 81}, - {2, 0x02, 82}, - {9, 0x02, 82}, - {23, 0x02, 82}, - {40, 0x03, 82}, - {2, 0x02, 83}, - {9, 0x02, 83}, - {23, 0x02, 83}, - {40, 0x03, 83}, - {2, 0x02, 84}, - {9, 0x02, 84}, - {23, 0x02, 84}, - {40, 0x03, 84}, + {0x8002, 81}, + {0x8009, 81}, + {0x8017, 81}, + {0xc028, 81}, + {0x8002, 82}, + {0x8009, 82}, + {0x8017, 82}, + {0xc028, 82}, + {0x8002, 83}, + {0x8009, 83}, + {0x8017, 83}, + {0xc028, 83}, + {0x8002, 84}, + {0x8009, 84}, + {0x8017, 84}, + {0xc028, 84}, }, /* 54 */ { - {3, 0x02, 81}, - {6, 0x02, 81}, - {10, 0x02, 81}, - {15, 0x02, 81}, - {24, 0x02, 81}, - {31, 0x02, 81}, - {41, 0x02, 81}, - {56, 0x03, 81}, - {3, 0x02, 82}, - {6, 0x02, 82}, - {10, 0x02, 82}, - {15, 0x02, 82}, - {24, 0x02, 82}, - {31, 0x02, 82}, - {41, 0x02, 82}, - {56, 0x03, 82}, + {0x8003, 81}, + {0x8006, 81}, + {0x800a, 81}, + {0x800f, 81}, + {0x8018, 81}, + {0x801f, 81}, + {0x8029, 81}, + {0xc038, 81}, + {0x8003, 82}, + {0x8006, 82}, + {0x800a, 82}, + {0x800f, 82}, + {0x8018, 82}, + {0x801f, 82}, + {0x8029, 82}, + {0xc038, 82}, }, /* 55 */ { - {3, 0x02, 83}, - {6, 0x02, 83}, - {10, 0x02, 83}, - {15, 0x02, 83}, - {24, 0x02, 83}, - {31, 0x02, 83}, - {41, 0x02, 83}, - {56, 0x03, 83}, - {3, 0x02, 84}, - {6, 0x02, 84}, - {10, 0x02, 84}, - {15, 0x02, 84}, - {24, 0x02, 84}, - {31, 0x02, 84}, - {41, 0x02, 84}, - {56, 0x03, 84}, + {0x8003, 83}, + {0x8006, 83}, + {0x800a, 83}, + {0x800f, 83}, + {0x8018, 83}, + {0x801f, 83}, + {0x8029, 83}, + {0xc038, 83}, + {0x8003, 84}, + {0x8006, 84}, + {0x800a, 84}, + {0x800f, 84}, + {0x8018, 84}, + {0x801f, 84}, + {0x8029, 84}, + {0xc038, 84}, }, /* 56 */ { - {0, 0x03, 85}, - {0, 0x03, 86}, - {0, 0x03, 87}, - {0, 0x03, 89}, - {0, 0x03, 106}, - {0, 0x03, 107}, - {0, 0x03, 113}, - {0, 0x03, 118}, - {0, 0x03, 119}, - {0, 0x03, 120}, - {0, 0x03, 121}, - {0, 0x03, 122}, - {70, 0x00, 0}, - {71, 0x00, 0}, - {73, 0x00, 0}, - {74, 0x01, 0}, + {0xc000, 85}, + {0xc000, 86}, + {0xc000, 87}, + {0xc000, 89}, + {0xc000, 106}, + {0xc000, 107}, + {0xc000, 113}, + {0xc000, 118}, + {0xc000, 119}, + {0xc000, 120}, + {0xc000, 121}, + {0xc000, 122}, + {0x46, 0}, + {0x47, 0}, + {0x49, 0}, + {0x404a, 0}, }, /* 57 */ { - {1, 0x02, 85}, - {22, 0x03, 85}, - {1, 0x02, 86}, - {22, 0x03, 86}, - {1, 0x02, 87}, - {22, 0x03, 87}, - {1, 0x02, 89}, - {22, 0x03, 89}, - {1, 0x02, 106}, - {22, 0x03, 106}, - {1, 0x02, 107}, - {22, 0x03, 107}, - {1, 0x02, 113}, - {22, 0x03, 113}, - {1, 0x02, 118}, - {22, 0x03, 118}, + {0x8001, 85}, + {0xc016, 85}, + {0x8001, 86}, + {0xc016, 86}, + {0x8001, 87}, + {0xc016, 87}, + {0x8001, 89}, + {0xc016, 89}, + {0x8001, 106}, + {0xc016, 106}, + {0x8001, 107}, + {0xc016, 107}, + {0x8001, 113}, + {0xc016, 113}, + {0x8001, 118}, + {0xc016, 118}, }, /* 58 */ { - {2, 0x02, 85}, - {9, 0x02, 85}, - {23, 0x02, 85}, - {40, 0x03, 85}, - {2, 0x02, 86}, - {9, 0x02, 86}, - {23, 0x02, 86}, - {40, 0x03, 86}, - {2, 0x02, 87}, - {9, 0x02, 87}, - {23, 0x02, 87}, - {40, 0x03, 87}, - {2, 0x02, 89}, - {9, 0x02, 89}, - {23, 0x02, 89}, - {40, 0x03, 89}, + {0x8002, 85}, + {0x8009, 85}, + {0x8017, 85}, + {0xc028, 85}, + {0x8002, 86}, + {0x8009, 86}, + {0x8017, 86}, + {0xc028, 86}, + {0x8002, 87}, + {0x8009, 87}, + {0x8017, 87}, + {0xc028, 87}, + {0x8002, 89}, + {0x8009, 89}, + {0x8017, 89}, + {0xc028, 89}, }, /* 59 */ { - {3, 0x02, 85}, - {6, 0x02, 85}, - {10, 0x02, 85}, - {15, 0x02, 85}, - {24, 0x02, 85}, - {31, 0x02, 85}, - {41, 0x02, 85}, - {56, 0x03, 85}, - {3, 0x02, 86}, - {6, 0x02, 86}, - {10, 0x02, 86}, - {15, 0x02, 86}, - {24, 0x02, 86}, - {31, 0x02, 86}, - {41, 0x02, 86}, - {56, 0x03, 86}, + {0x8003, 85}, + {0x8006, 85}, + {0x800a, 85}, + {0x800f, 85}, + {0x8018, 85}, + {0x801f, 85}, + {0x8029, 85}, + {0xc038, 85}, + {0x8003, 86}, + {0x8006, 86}, + {0x800a, 86}, + {0x800f, 86}, + {0x8018, 86}, + {0x801f, 86}, + {0x8029, 86}, + {0xc038, 86}, }, /* 60 */ { - {3, 0x02, 87}, - {6, 0x02, 87}, - {10, 0x02, 87}, - {15, 0x02, 87}, - {24, 0x02, 87}, - {31, 0x02, 87}, - {41, 0x02, 87}, - {56, 0x03, 87}, - {3, 0x02, 89}, - {6, 0x02, 89}, - {10, 0x02, 89}, - {15, 0x02, 89}, - {24, 0x02, 89}, - {31, 0x02, 89}, - {41, 0x02, 89}, - {56, 0x03, 89}, + {0x8003, 87}, + {0x8006, 87}, + {0x800a, 87}, + {0x800f, 87}, + {0x8018, 87}, + {0x801f, 87}, + {0x8029, 87}, + {0xc038, 87}, + {0x8003, 89}, + {0x8006, 89}, + {0x800a, 89}, + {0x800f, 89}, + {0x8018, 89}, + {0x801f, 89}, + {0x8029, 89}, + {0xc038, 89}, }, /* 61 */ { - {2, 0x02, 106}, - {9, 0x02, 106}, - {23, 0x02, 106}, - {40, 0x03, 106}, - {2, 0x02, 107}, - {9, 0x02, 107}, - {23, 0x02, 107}, - {40, 0x03, 107}, - {2, 0x02, 113}, - {9, 0x02, 113}, - {23, 0x02, 113}, - {40, 0x03, 113}, - {2, 0x02, 118}, - {9, 0x02, 118}, - {23, 0x02, 118}, - {40, 0x03, 118}, + {0x8002, 106}, + {0x8009, 106}, + {0x8017, 106}, + {0xc028, 106}, + {0x8002, 107}, + {0x8009, 107}, + {0x8017, 107}, + {0xc028, 107}, + {0x8002, 113}, + {0x8009, 113}, + {0x8017, 113}, + {0xc028, 113}, + {0x8002, 118}, + {0x8009, 118}, + {0x8017, 118}, + {0xc028, 118}, }, /* 62 */ { - {3, 0x02, 106}, - {6, 0x02, 106}, - {10, 0x02, 106}, - {15, 0x02, 106}, - {24, 0x02, 106}, - {31, 0x02, 106}, - {41, 0x02, 106}, - {56, 0x03, 106}, - {3, 0x02, 107}, - {6, 0x02, 107}, - {10, 0x02, 107}, - {15, 0x02, 107}, - {24, 0x02, 107}, - {31, 0x02, 107}, - {41, 0x02, 107}, - {56, 0x03, 107}, + {0x8003, 106}, + {0x8006, 106}, + {0x800a, 106}, + {0x800f, 106}, + {0x8018, 106}, + {0x801f, 106}, + {0x8029, 106}, + {0xc038, 106}, + {0x8003, 107}, + {0x8006, 107}, + {0x800a, 107}, + {0x800f, 107}, + {0x8018, 107}, + {0x801f, 107}, + {0x8029, 107}, + {0xc038, 107}, }, /* 63 */ { - {3, 0x02, 113}, - {6, 0x02, 113}, - {10, 0x02, 113}, - {15, 0x02, 113}, - {24, 0x02, 113}, - {31, 0x02, 113}, - {41, 0x02, 113}, - {56, 0x03, 113}, - {3, 0x02, 118}, - {6, 0x02, 118}, - {10, 0x02, 118}, - {15, 0x02, 118}, - {24, 0x02, 118}, - {31, 0x02, 118}, - {41, 0x02, 118}, - {56, 0x03, 118}, + {0x8003, 113}, + {0x8006, 113}, + {0x800a, 113}, + {0x800f, 113}, + {0x8018, 113}, + {0x801f, 113}, + {0x8029, 113}, + {0xc038, 113}, + {0x8003, 118}, + {0x8006, 118}, + {0x800a, 118}, + {0x800f, 118}, + {0x8018, 118}, + {0x801f, 118}, + {0x8029, 118}, + {0xc038, 118}, }, /* 64 */ { - {1, 0x02, 119}, - {22, 0x03, 119}, - {1, 0x02, 120}, - {22, 0x03, 120}, - {1, 0x02, 121}, - {22, 0x03, 121}, - {1, 0x02, 122}, - {22, 0x03, 122}, - {0, 0x03, 38}, - {0, 0x03, 42}, - {0, 0x03, 44}, - {0, 0x03, 59}, - {0, 0x03, 88}, - {0, 0x03, 90}, - {75, 0x00, 0}, - {78, 0x00, 0}, + {0x8001, 119}, + {0xc016, 119}, + {0x8001, 120}, + {0xc016, 120}, + {0x8001, 121}, + {0xc016, 121}, + {0x8001, 122}, + {0xc016, 122}, + {0xc000, 38}, + {0xc000, 42}, + {0xc000, 44}, + {0xc000, 59}, + {0xc000, 88}, + {0xc000, 90}, + {0x4b, 0}, + {0x4e, 0}, }, /* 65 */ { - {2, 0x02, 119}, - {9, 0x02, 119}, - {23, 0x02, 119}, - {40, 0x03, 119}, - {2, 0x02, 120}, - {9, 0x02, 120}, - {23, 0x02, 120}, - {40, 0x03, 120}, - {2, 0x02, 121}, - {9, 0x02, 121}, - {23, 0x02, 121}, - {40, 0x03, 121}, - {2, 0x02, 122}, - {9, 0x02, 122}, - {23, 0x02, 122}, - {40, 0x03, 122}, + {0x8002, 119}, + {0x8009, 119}, + {0x8017, 119}, + {0xc028, 119}, + {0x8002, 120}, + {0x8009, 120}, + {0x8017, 120}, + {0xc028, 120}, + {0x8002, 121}, + {0x8009, 121}, + {0x8017, 121}, + {0xc028, 121}, + {0x8002, 122}, + {0x8009, 122}, + {0x8017, 122}, + {0xc028, 122}, }, /* 66 */ { - {3, 0x02, 119}, - {6, 0x02, 119}, - {10, 0x02, 119}, - {15, 0x02, 119}, - {24, 0x02, 119}, - {31, 0x02, 119}, - {41, 0x02, 119}, - {56, 0x03, 119}, - {3, 0x02, 120}, - {6, 0x02, 120}, - {10, 0x02, 120}, - {15, 0x02, 120}, - {24, 0x02, 120}, - {31, 0x02, 120}, - {41, 0x02, 120}, - {56, 0x03, 120}, + {0x8003, 119}, + {0x8006, 119}, + {0x800a, 119}, + {0x800f, 119}, + {0x8018, 119}, + {0x801f, 119}, + {0x8029, 119}, + {0xc038, 119}, + {0x8003, 120}, + {0x8006, 120}, + {0x800a, 120}, + {0x800f, 120}, + {0x8018, 120}, + {0x801f, 120}, + {0x8029, 120}, + {0xc038, 120}, }, /* 67 */ { - {3, 0x02, 121}, - {6, 0x02, 121}, - {10, 0x02, 121}, - {15, 0x02, 121}, - {24, 0x02, 121}, - {31, 0x02, 121}, - {41, 0x02, 121}, - {56, 0x03, 121}, - {3, 0x02, 122}, - {6, 0x02, 122}, - {10, 0x02, 122}, - {15, 0x02, 122}, - {24, 0x02, 122}, - {31, 0x02, 122}, - {41, 0x02, 122}, - {56, 0x03, 122}, + {0x8003, 121}, + {0x8006, 121}, + {0x800a, 121}, + {0x800f, 121}, + {0x8018, 121}, + {0x801f, 121}, + {0x8029, 121}, + {0xc038, 121}, + {0x8003, 122}, + {0x8006, 122}, + {0x800a, 122}, + {0x800f, 122}, + {0x8018, 122}, + {0x801f, 122}, + {0x8029, 122}, + {0xc038, 122}, }, /* 68 */ { - {1, 0x02, 38}, - {22, 0x03, 38}, - {1, 0x02, 42}, - {22, 0x03, 42}, - {1, 0x02, 44}, - {22, 0x03, 44}, - {1, 0x02, 59}, - {22, 0x03, 59}, - {1, 0x02, 88}, - {22, 0x03, 88}, - {1, 0x02, 90}, - {22, 0x03, 90}, - {76, 0x00, 0}, - {77, 0x00, 0}, - {79, 0x00, 0}, - {81, 0x00, 0}, + {0x8001, 38}, + {0xc016, 38}, + {0x8001, 42}, + {0xc016, 42}, + {0x8001, 44}, + {0xc016, 44}, + {0x8001, 59}, + {0xc016, 59}, + {0x8001, 88}, + {0xc016, 88}, + {0x8001, 90}, + {0xc016, 90}, + {0x4c, 0}, + {0x4d, 0}, + {0x4f, 0}, + {0x51, 0}, }, /* 69 */ { - {2, 0x02, 38}, - {9, 0x02, 38}, - {23, 0x02, 38}, - {40, 0x03, 38}, - {2, 0x02, 42}, - {9, 0x02, 42}, - {23, 0x02, 42}, - {40, 0x03, 42}, - {2, 0x02, 44}, - {9, 0x02, 44}, - {23, 0x02, 44}, - {40, 0x03, 44}, - {2, 0x02, 59}, - {9, 0x02, 59}, - {23, 0x02, 59}, - {40, 0x03, 59}, + {0x8002, 38}, + {0x8009, 38}, + {0x8017, 38}, + {0xc028, 38}, + {0x8002, 42}, + {0x8009, 42}, + {0x8017, 42}, + {0xc028, 42}, + {0x8002, 44}, + {0x8009, 44}, + {0x8017, 44}, + {0xc028, 44}, + {0x8002, 59}, + {0x8009, 59}, + {0x8017, 59}, + {0xc028, 59}, }, /* 70 */ { - {3, 0x02, 38}, - {6, 0x02, 38}, - {10, 0x02, 38}, - {15, 0x02, 38}, - {24, 0x02, 38}, - {31, 0x02, 38}, - {41, 0x02, 38}, - {56, 0x03, 38}, - {3, 0x02, 42}, - {6, 0x02, 42}, - {10, 0x02, 42}, - {15, 0x02, 42}, - {24, 0x02, 42}, - {31, 0x02, 42}, - {41, 0x02, 42}, - {56, 0x03, 42}, + {0x8003, 38}, + {0x8006, 38}, + {0x800a, 38}, + {0x800f, 38}, + {0x8018, 38}, + {0x801f, 38}, + {0x8029, 38}, + {0xc038, 38}, + {0x8003, 42}, + {0x8006, 42}, + {0x800a, 42}, + {0x800f, 42}, + {0x8018, 42}, + {0x801f, 42}, + {0x8029, 42}, + {0xc038, 42}, }, /* 71 */ { - {3, 0x02, 44}, - {6, 0x02, 44}, - {10, 0x02, 44}, - {15, 0x02, 44}, - {24, 0x02, 44}, - {31, 0x02, 44}, - {41, 0x02, 44}, - {56, 0x03, 44}, - {3, 0x02, 59}, - {6, 0x02, 59}, - {10, 0x02, 59}, - {15, 0x02, 59}, - {24, 0x02, 59}, - {31, 0x02, 59}, - {41, 0x02, 59}, - {56, 0x03, 59}, + {0x8003, 44}, + {0x8006, 44}, + {0x800a, 44}, + {0x800f, 44}, + {0x8018, 44}, + {0x801f, 44}, + {0x8029, 44}, + {0xc038, 44}, + {0x8003, 59}, + {0x8006, 59}, + {0x800a, 59}, + {0x800f, 59}, + {0x8018, 59}, + {0x801f, 59}, + {0x8029, 59}, + {0xc038, 59}, }, /* 72 */ { - {2, 0x02, 88}, - {9, 0x02, 88}, - {23, 0x02, 88}, - {40, 0x03, 88}, - {2, 0x02, 90}, - {9, 0x02, 90}, - {23, 0x02, 90}, - {40, 0x03, 90}, - {0, 0x03, 33}, - {0, 0x03, 34}, - {0, 0x03, 40}, - {0, 0x03, 41}, - {0, 0x03, 63}, - {80, 0x00, 0}, - {82, 0x00, 0}, - {84, 0x00, 0}, + {0x8002, 88}, + {0x8009, 88}, + {0x8017, 88}, + {0xc028, 88}, + {0x8002, 90}, + {0x8009, 90}, + {0x8017, 90}, + {0xc028, 90}, + {0xc000, 33}, + {0xc000, 34}, + {0xc000, 40}, + {0xc000, 41}, + {0xc000, 63}, + {0x50, 0}, + {0x52, 0}, + {0x54, 0}, }, /* 73 */ { - {3, 0x02, 88}, - {6, 0x02, 88}, - {10, 0x02, 88}, - {15, 0x02, 88}, - {24, 0x02, 88}, - {31, 0x02, 88}, - {41, 0x02, 88}, - {56, 0x03, 88}, - {3, 0x02, 90}, - {6, 0x02, 90}, - {10, 0x02, 90}, - {15, 0x02, 90}, - {24, 0x02, 90}, - {31, 0x02, 90}, - {41, 0x02, 90}, - {56, 0x03, 90}, + {0x8003, 88}, + {0x8006, 88}, + {0x800a, 88}, + {0x800f, 88}, + {0x8018, 88}, + {0x801f, 88}, + {0x8029, 88}, + {0xc038, 88}, + {0x8003, 90}, + {0x8006, 90}, + {0x800a, 90}, + {0x800f, 90}, + {0x8018, 90}, + {0x801f, 90}, + {0x8029, 90}, + {0xc038, 90}, }, /* 74 */ { - {1, 0x02, 33}, - {22, 0x03, 33}, - {1, 0x02, 34}, - {22, 0x03, 34}, - {1, 0x02, 40}, - {22, 0x03, 40}, - {1, 0x02, 41}, - {22, 0x03, 41}, - {1, 0x02, 63}, - {22, 0x03, 63}, - {0, 0x03, 39}, - {0, 0x03, 43}, - {0, 0x03, 124}, - {83, 0x00, 0}, - {85, 0x00, 0}, - {88, 0x00, 0}, + {0x8001, 33}, + {0xc016, 33}, + {0x8001, 34}, + {0xc016, 34}, + {0x8001, 40}, + {0xc016, 40}, + {0x8001, 41}, + {0xc016, 41}, + {0x8001, 63}, + {0xc016, 63}, + {0xc000, 39}, + {0xc000, 43}, + {0xc000, 124}, + {0x53, 0}, + {0x55, 0}, + {0x58, 0}, }, /* 75 */ { - {2, 0x02, 33}, - {9, 0x02, 33}, - {23, 0x02, 33}, - {40, 0x03, 33}, - {2, 0x02, 34}, - {9, 0x02, 34}, - {23, 0x02, 34}, - {40, 0x03, 34}, - {2, 0x02, 40}, - {9, 0x02, 40}, - {23, 0x02, 40}, - {40, 0x03, 40}, - {2, 0x02, 41}, - {9, 0x02, 41}, - {23, 0x02, 41}, - {40, 0x03, 41}, + {0x8002, 33}, + {0x8009, 33}, + {0x8017, 33}, + {0xc028, 33}, + {0x8002, 34}, + {0x8009, 34}, + {0x8017, 34}, + {0xc028, 34}, + {0x8002, 40}, + {0x8009, 40}, + {0x8017, 40}, + {0xc028, 40}, + {0x8002, 41}, + {0x8009, 41}, + {0x8017, 41}, + {0xc028, 41}, }, /* 76 */ { - {3, 0x02, 33}, - {6, 0x02, 33}, - {10, 0x02, 33}, - {15, 0x02, 33}, - {24, 0x02, 33}, - {31, 0x02, 33}, - {41, 0x02, 33}, - {56, 0x03, 33}, - {3, 0x02, 34}, - {6, 0x02, 34}, - {10, 0x02, 34}, - {15, 0x02, 34}, - {24, 0x02, 34}, - {31, 0x02, 34}, - {41, 0x02, 34}, - {56, 0x03, 34}, + {0x8003, 33}, + {0x8006, 33}, + {0x800a, 33}, + {0x800f, 33}, + {0x8018, 33}, + {0x801f, 33}, + {0x8029, 33}, + {0xc038, 33}, + {0x8003, 34}, + {0x8006, 34}, + {0x800a, 34}, + {0x800f, 34}, + {0x8018, 34}, + {0x801f, 34}, + {0x8029, 34}, + {0xc038, 34}, }, /* 77 */ { - {3, 0x02, 40}, - {6, 0x02, 40}, - {10, 0x02, 40}, - {15, 0x02, 40}, - {24, 0x02, 40}, - {31, 0x02, 40}, - {41, 0x02, 40}, - {56, 0x03, 40}, - {3, 0x02, 41}, - {6, 0x02, 41}, - {10, 0x02, 41}, - {15, 0x02, 41}, - {24, 0x02, 41}, - {31, 0x02, 41}, - {41, 0x02, 41}, - {56, 0x03, 41}, + {0x8003, 40}, + {0x8006, 40}, + {0x800a, 40}, + {0x800f, 40}, + {0x8018, 40}, + {0x801f, 40}, + {0x8029, 40}, + {0xc038, 40}, + {0x8003, 41}, + {0x8006, 41}, + {0x800a, 41}, + {0x800f, 41}, + {0x8018, 41}, + {0x801f, 41}, + {0x8029, 41}, + {0xc038, 41}, }, /* 78 */ { - {2, 0x02, 63}, - {9, 0x02, 63}, - {23, 0x02, 63}, - {40, 0x03, 63}, - {1, 0x02, 39}, - {22, 0x03, 39}, - {1, 0x02, 43}, - {22, 0x03, 43}, - {1, 0x02, 124}, - {22, 0x03, 124}, - {0, 0x03, 35}, - {0, 0x03, 62}, - {86, 0x00, 0}, - {87, 0x00, 0}, - {89, 0x00, 0}, - {90, 0x00, 0}, + {0x8002, 63}, + {0x8009, 63}, + {0x8017, 63}, + {0xc028, 63}, + {0x8001, 39}, + {0xc016, 39}, + {0x8001, 43}, + {0xc016, 43}, + {0x8001, 124}, + {0xc016, 124}, + {0xc000, 35}, + {0xc000, 62}, + {0x56, 0}, + {0x57, 0}, + {0x59, 0}, + {0x5a, 0}, }, /* 79 */ { - {3, 0x02, 63}, - {6, 0x02, 63}, - {10, 0x02, 63}, - {15, 0x02, 63}, - {24, 0x02, 63}, - {31, 0x02, 63}, - {41, 0x02, 63}, - {56, 0x03, 63}, - {2, 0x02, 39}, - {9, 0x02, 39}, - {23, 0x02, 39}, - {40, 0x03, 39}, - {2, 0x02, 43}, - {9, 0x02, 43}, - {23, 0x02, 43}, - {40, 0x03, 43}, + {0x8003, 63}, + {0x8006, 63}, + {0x800a, 63}, + {0x800f, 63}, + {0x8018, 63}, + {0x801f, 63}, + {0x8029, 63}, + {0xc038, 63}, + {0x8002, 39}, + {0x8009, 39}, + {0x8017, 39}, + {0xc028, 39}, + {0x8002, 43}, + {0x8009, 43}, + {0x8017, 43}, + {0xc028, 43}, }, /* 80 */ { - {3, 0x02, 39}, - {6, 0x02, 39}, - {10, 0x02, 39}, - {15, 0x02, 39}, - {24, 0x02, 39}, - {31, 0x02, 39}, - {41, 0x02, 39}, - {56, 0x03, 39}, - {3, 0x02, 43}, - {6, 0x02, 43}, - {10, 0x02, 43}, - {15, 0x02, 43}, - {24, 0x02, 43}, - {31, 0x02, 43}, - {41, 0x02, 43}, - {56, 0x03, 43}, + {0x8003, 39}, + {0x8006, 39}, + {0x800a, 39}, + {0x800f, 39}, + {0x8018, 39}, + {0x801f, 39}, + {0x8029, 39}, + {0xc038, 39}, + {0x8003, 43}, + {0x8006, 43}, + {0x800a, 43}, + {0x800f, 43}, + {0x8018, 43}, + {0x801f, 43}, + {0x8029, 43}, + {0xc038, 43}, }, /* 81 */ { - {2, 0x02, 124}, - {9, 0x02, 124}, - {23, 0x02, 124}, - {40, 0x03, 124}, - {1, 0x02, 35}, - {22, 0x03, 35}, - {1, 0x02, 62}, - {22, 0x03, 62}, - {0, 0x03, 0}, - {0, 0x03, 36}, - {0, 0x03, 64}, - {0, 0x03, 91}, - {0, 0x03, 93}, - {0, 0x03, 126}, - {91, 0x00, 0}, - {92, 0x00, 0}, + {0x8002, 124}, + {0x8009, 124}, + {0x8017, 124}, + {0xc028, 124}, + {0x8001, 35}, + {0xc016, 35}, + {0x8001, 62}, + {0xc016, 62}, + {0xc000, 0}, + {0xc000, 36}, + {0xc000, 64}, + {0xc000, 91}, + {0xc000, 93}, + {0xc000, 126}, + {0x5b, 0}, + {0x5c, 0}, }, /* 82 */ { - {3, 0x02, 124}, - {6, 0x02, 124}, - {10, 0x02, 124}, - {15, 0x02, 124}, - {24, 0x02, 124}, - {31, 0x02, 124}, - {41, 0x02, 124}, - {56, 0x03, 124}, - {2, 0x02, 35}, - {9, 0x02, 35}, - {23, 0x02, 35}, - {40, 0x03, 35}, - {2, 0x02, 62}, - {9, 0x02, 62}, - {23, 0x02, 62}, - {40, 0x03, 62}, + {0x8003, 124}, + {0x8006, 124}, + {0x800a, 124}, + {0x800f, 124}, + {0x8018, 124}, + {0x801f, 124}, + {0x8029, 124}, + {0xc038, 124}, + {0x8002, 35}, + {0x8009, 35}, + {0x8017, 35}, + {0xc028, 35}, + {0x8002, 62}, + {0x8009, 62}, + {0x8017, 62}, + {0xc028, 62}, }, /* 83 */ { - {3, 0x02, 35}, - {6, 0x02, 35}, - {10, 0x02, 35}, - {15, 0x02, 35}, - {24, 0x02, 35}, - {31, 0x02, 35}, - {41, 0x02, 35}, - {56, 0x03, 35}, - {3, 0x02, 62}, - {6, 0x02, 62}, - {10, 0x02, 62}, - {15, 0x02, 62}, - {24, 0x02, 62}, - {31, 0x02, 62}, - {41, 0x02, 62}, - {56, 0x03, 62}, + {0x8003, 35}, + {0x8006, 35}, + {0x800a, 35}, + {0x800f, 35}, + {0x8018, 35}, + {0x801f, 35}, + {0x8029, 35}, + {0xc038, 35}, + {0x8003, 62}, + {0x8006, 62}, + {0x800a, 62}, + {0x800f, 62}, + {0x8018, 62}, + {0x801f, 62}, + {0x8029, 62}, + {0xc038, 62}, }, /* 84 */ { - {1, 0x02, 0}, - {22, 0x03, 0}, - {1, 0x02, 36}, - {22, 0x03, 36}, - {1, 0x02, 64}, - {22, 0x03, 64}, - {1, 0x02, 91}, - {22, 0x03, 91}, - {1, 0x02, 93}, - {22, 0x03, 93}, - {1, 0x02, 126}, - {22, 0x03, 126}, - {0, 0x03, 94}, - {0, 0x03, 125}, - {93, 0x00, 0}, - {94, 0x00, 0}, + {0x8001, 0}, + {0xc016, 0}, + {0x8001, 36}, + {0xc016, 36}, + {0x8001, 64}, + {0xc016, 64}, + {0x8001, 91}, + {0xc016, 91}, + {0x8001, 93}, + {0xc016, 93}, + {0x8001, 126}, + {0xc016, 126}, + {0xc000, 94}, + {0xc000, 125}, + {0x5d, 0}, + {0x5e, 0}, }, /* 85 */ { - {2, 0x02, 0}, - {9, 0x02, 0}, - {23, 0x02, 0}, - {40, 0x03, 0}, - {2, 0x02, 36}, - {9, 0x02, 36}, - {23, 0x02, 36}, - {40, 0x03, 36}, - {2, 0x02, 64}, - {9, 0x02, 64}, - {23, 0x02, 64}, - {40, 0x03, 64}, - {2, 0x02, 91}, - {9, 0x02, 91}, - {23, 0x02, 91}, - {40, 0x03, 91}, + {0x8002, 0}, + {0x8009, 0}, + {0x8017, 0}, + {0xc028, 0}, + {0x8002, 36}, + {0x8009, 36}, + {0x8017, 36}, + {0xc028, 36}, + {0x8002, 64}, + {0x8009, 64}, + {0x8017, 64}, + {0xc028, 64}, + {0x8002, 91}, + {0x8009, 91}, + {0x8017, 91}, + {0xc028, 91}, }, /* 86 */ { - {3, 0x02, 0}, - {6, 0x02, 0}, - {10, 0x02, 0}, - {15, 0x02, 0}, - {24, 0x02, 0}, - {31, 0x02, 0}, - {41, 0x02, 0}, - {56, 0x03, 0}, - {3, 0x02, 36}, - {6, 0x02, 36}, - {10, 0x02, 36}, - {15, 0x02, 36}, - {24, 0x02, 36}, - {31, 0x02, 36}, - {41, 0x02, 36}, - {56, 0x03, 36}, + {0x8003, 0}, + {0x8006, 0}, + {0x800a, 0}, + {0x800f, 0}, + {0x8018, 0}, + {0x801f, 0}, + {0x8029, 0}, + {0xc038, 0}, + {0x8003, 36}, + {0x8006, 36}, + {0x800a, 36}, + {0x800f, 36}, + {0x8018, 36}, + {0x801f, 36}, + {0x8029, 36}, + {0xc038, 36}, }, /* 87 */ { - {3, 0x02, 64}, - {6, 0x02, 64}, - {10, 0x02, 64}, - {15, 0x02, 64}, - {24, 0x02, 64}, - {31, 0x02, 64}, - {41, 0x02, 64}, - {56, 0x03, 64}, - {3, 0x02, 91}, - {6, 0x02, 91}, - {10, 0x02, 91}, - {15, 0x02, 91}, - {24, 0x02, 91}, - {31, 0x02, 91}, - {41, 0x02, 91}, - {56, 0x03, 91}, + {0x8003, 64}, + {0x8006, 64}, + {0x800a, 64}, + {0x800f, 64}, + {0x8018, 64}, + {0x801f, 64}, + {0x8029, 64}, + {0xc038, 64}, + {0x8003, 91}, + {0x8006, 91}, + {0x800a, 91}, + {0x800f, 91}, + {0x8018, 91}, + {0x801f, 91}, + {0x8029, 91}, + {0xc038, 91}, }, /* 88 */ { - {2, 0x02, 93}, - {9, 0x02, 93}, - {23, 0x02, 93}, - {40, 0x03, 93}, - {2, 0x02, 126}, - {9, 0x02, 126}, - {23, 0x02, 126}, - {40, 0x03, 126}, - {1, 0x02, 94}, - {22, 0x03, 94}, - {1, 0x02, 125}, - {22, 0x03, 125}, - {0, 0x03, 60}, - {0, 0x03, 96}, - {0, 0x03, 123}, - {95, 0x00, 0}, + {0x8002, 93}, + {0x8009, 93}, + {0x8017, 93}, + {0xc028, 93}, + {0x8002, 126}, + {0x8009, 126}, + {0x8017, 126}, + {0xc028, 126}, + {0x8001, 94}, + {0xc016, 94}, + {0x8001, 125}, + {0xc016, 125}, + {0xc000, 60}, + {0xc000, 96}, + {0xc000, 123}, + {0x5f, 0}, }, /* 89 */ { - {3, 0x02, 93}, - {6, 0x02, 93}, - {10, 0x02, 93}, - {15, 0x02, 93}, - {24, 0x02, 93}, - {31, 0x02, 93}, - {41, 0x02, 93}, - {56, 0x03, 93}, - {3, 0x02, 126}, - {6, 0x02, 126}, - {10, 0x02, 126}, - {15, 0x02, 126}, - {24, 0x02, 126}, - {31, 0x02, 126}, - {41, 0x02, 126}, - {56, 0x03, 126}, + {0x8003, 93}, + {0x8006, 93}, + {0x800a, 93}, + {0x800f, 93}, + {0x8018, 93}, + {0x801f, 93}, + {0x8029, 93}, + {0xc038, 93}, + {0x8003, 126}, + {0x8006, 126}, + {0x800a, 126}, + {0x800f, 126}, + {0x8018, 126}, + {0x801f, 126}, + {0x8029, 126}, + {0xc038, 126}, }, /* 90 */ { - {2, 0x02, 94}, - {9, 0x02, 94}, - {23, 0x02, 94}, - {40, 0x03, 94}, - {2, 0x02, 125}, - {9, 0x02, 125}, - {23, 0x02, 125}, - {40, 0x03, 125}, - {1, 0x02, 60}, - {22, 0x03, 60}, - {1, 0x02, 96}, - {22, 0x03, 96}, - {1, 0x02, 123}, - {22, 0x03, 123}, - {96, 0x00, 0}, - {110, 0x00, 0}, + {0x8002, 94}, + {0x8009, 94}, + {0x8017, 94}, + {0xc028, 94}, + {0x8002, 125}, + {0x8009, 125}, + {0x8017, 125}, + {0xc028, 125}, + {0x8001, 60}, + {0xc016, 60}, + {0x8001, 96}, + {0xc016, 96}, + {0x8001, 123}, + {0xc016, 123}, + {0x60, 0}, + {0x6e, 0}, }, /* 91 */ { - {3, 0x02, 94}, - {6, 0x02, 94}, - {10, 0x02, 94}, - {15, 0x02, 94}, - {24, 0x02, 94}, - {31, 0x02, 94}, - {41, 0x02, 94}, - {56, 0x03, 94}, - {3, 0x02, 125}, - {6, 0x02, 125}, - {10, 0x02, 125}, - {15, 0x02, 125}, - {24, 0x02, 125}, - {31, 0x02, 125}, - {41, 0x02, 125}, - {56, 0x03, 125}, + {0x8003, 94}, + {0x8006, 94}, + {0x800a, 94}, + {0x800f, 94}, + {0x8018, 94}, + {0x801f, 94}, + {0x8029, 94}, + {0xc038, 94}, + {0x8003, 125}, + {0x8006, 125}, + {0x800a, 125}, + {0x800f, 125}, + {0x8018, 125}, + {0x801f, 125}, + {0x8029, 125}, + {0xc038, 125}, }, /* 92 */ { - {2, 0x02, 60}, - {9, 0x02, 60}, - {23, 0x02, 60}, - {40, 0x03, 60}, - {2, 0x02, 96}, - {9, 0x02, 96}, - {23, 0x02, 96}, - {40, 0x03, 96}, - {2, 0x02, 123}, - {9, 0x02, 123}, - {23, 0x02, 123}, - {40, 0x03, 123}, - {97, 0x00, 0}, - {101, 0x00, 0}, - {111, 0x00, 0}, - {133, 0x00, 0}, + {0x8002, 60}, + {0x8009, 60}, + {0x8017, 60}, + {0xc028, 60}, + {0x8002, 96}, + {0x8009, 96}, + {0x8017, 96}, + {0xc028, 96}, + {0x8002, 123}, + {0x8009, 123}, + {0x8017, 123}, + {0xc028, 123}, + {0x61, 0}, + {0x65, 0}, + {0x6f, 0}, + {0x85, 0}, }, /* 93 */ { - {3, 0x02, 60}, - {6, 0x02, 60}, - {10, 0x02, 60}, - {15, 0x02, 60}, - {24, 0x02, 60}, - {31, 0x02, 60}, - {41, 0x02, 60}, - {56, 0x03, 60}, - {3, 0x02, 96}, - {6, 0x02, 96}, - {10, 0x02, 96}, - {15, 0x02, 96}, - {24, 0x02, 96}, - {31, 0x02, 96}, - {41, 0x02, 96}, - {56, 0x03, 96}, + {0x8003, 60}, + {0x8006, 60}, + {0x800a, 60}, + {0x800f, 60}, + {0x8018, 60}, + {0x801f, 60}, + {0x8029, 60}, + {0xc038, 60}, + {0x8003, 96}, + {0x8006, 96}, + {0x800a, 96}, + {0x800f, 96}, + {0x8018, 96}, + {0x801f, 96}, + {0x8029, 96}, + {0xc038, 96}, }, /* 94 */ { - {3, 0x02, 123}, - {6, 0x02, 123}, - {10, 0x02, 123}, - {15, 0x02, 123}, - {24, 0x02, 123}, - {31, 0x02, 123}, - {41, 0x02, 123}, - {56, 0x03, 123}, - {98, 0x00, 0}, - {99, 0x00, 0}, - {102, 0x00, 0}, - {105, 0x00, 0}, - {112, 0x00, 0}, - {119, 0x00, 0}, - {134, 0x00, 0}, - {153, 0x00, 0}, + {0x8003, 123}, + {0x8006, 123}, + {0x800a, 123}, + {0x800f, 123}, + {0x8018, 123}, + {0x801f, 123}, + {0x8029, 123}, + {0xc038, 123}, + {0x62, 0}, + {0x63, 0}, + {0x66, 0}, + {0x69, 0}, + {0x70, 0}, + {0x77, 0}, + {0x86, 0}, + {0x99, 0}, }, /* 95 */ { - {0, 0x03, 92}, - {0, 0x03, 195}, - {0, 0x03, 208}, - {100, 0x00, 0}, - {103, 0x00, 0}, - {104, 0x00, 0}, - {106, 0x00, 0}, - {107, 0x00, 0}, - {113, 0x00, 0}, - {116, 0x00, 0}, - {120, 0x00, 0}, - {126, 0x00, 0}, - {135, 0x00, 0}, - {142, 0x00, 0}, - {154, 0x00, 0}, - {169, 0x00, 0}, + {0xc000, 92}, + {0xc000, 195}, + {0xc000, 208}, + {0x64, 0}, + {0x67, 0}, + {0x68, 0}, + {0x6a, 0}, + {0x6b, 0}, + {0x71, 0}, + {0x74, 0}, + {0x78, 0}, + {0x7e, 0}, + {0x87, 0}, + {0x8e, 0}, + {0x9a, 0}, + {0xa9, 0}, }, /* 96 */ { - {1, 0x02, 92}, - {22, 0x03, 92}, - {1, 0x02, 195}, - {22, 0x03, 195}, - {1, 0x02, 208}, - {22, 0x03, 208}, - {0, 0x03, 128}, - {0, 0x03, 130}, - {0, 0x03, 131}, - {0, 0x03, 162}, - {0, 0x03, 184}, - {0, 0x03, 194}, - {0, 0x03, 224}, - {0, 0x03, 226}, - {108, 0x00, 0}, - {109, 0x00, 0}, + {0x8001, 92}, + {0xc016, 92}, + {0x8001, 195}, + {0xc016, 195}, + {0x8001, 208}, + {0xc016, 208}, + {0xc000, 128}, + {0xc000, 130}, + {0xc000, 131}, + {0xc000, 162}, + {0xc000, 184}, + {0xc000, 194}, + {0xc000, 224}, + {0xc000, 226}, + {0x6c, 0}, + {0x6d, 0}, }, /* 97 */ { - {2, 0x02, 92}, - {9, 0x02, 92}, - {23, 0x02, 92}, - {40, 0x03, 92}, - {2, 0x02, 195}, - {9, 0x02, 195}, - {23, 0x02, 195}, - {40, 0x03, 195}, - {2, 0x02, 208}, - {9, 0x02, 208}, - {23, 0x02, 208}, - {40, 0x03, 208}, - {1, 0x02, 128}, - {22, 0x03, 128}, - {1, 0x02, 130}, - {22, 0x03, 130}, + {0x8002, 92}, + {0x8009, 92}, + {0x8017, 92}, + {0xc028, 92}, + {0x8002, 195}, + {0x8009, 195}, + {0x8017, 195}, + {0xc028, 195}, + {0x8002, 208}, + {0x8009, 208}, + {0x8017, 208}, + {0xc028, 208}, + {0x8001, 128}, + {0xc016, 128}, + {0x8001, 130}, + {0xc016, 130}, }, /* 98 */ { - {3, 0x02, 92}, - {6, 0x02, 92}, - {10, 0x02, 92}, - {15, 0x02, 92}, - {24, 0x02, 92}, - {31, 0x02, 92}, - {41, 0x02, 92}, - {56, 0x03, 92}, - {3, 0x02, 195}, - {6, 0x02, 195}, - {10, 0x02, 195}, - {15, 0x02, 195}, - {24, 0x02, 195}, - {31, 0x02, 195}, - {41, 0x02, 195}, - {56, 0x03, 195}, + {0x8003, 92}, + {0x8006, 92}, + {0x800a, 92}, + {0x800f, 92}, + {0x8018, 92}, + {0x801f, 92}, + {0x8029, 92}, + {0xc038, 92}, + {0x8003, 195}, + {0x8006, 195}, + {0x800a, 195}, + {0x800f, 195}, + {0x8018, 195}, + {0x801f, 195}, + {0x8029, 195}, + {0xc038, 195}, }, /* 99 */ { - {3, 0x02, 208}, - {6, 0x02, 208}, - {10, 0x02, 208}, - {15, 0x02, 208}, - {24, 0x02, 208}, - {31, 0x02, 208}, - {41, 0x02, 208}, - {56, 0x03, 208}, - {2, 0x02, 128}, - {9, 0x02, 128}, - {23, 0x02, 128}, - {40, 0x03, 128}, - {2, 0x02, 130}, - {9, 0x02, 130}, - {23, 0x02, 130}, - {40, 0x03, 130}, + {0x8003, 208}, + {0x8006, 208}, + {0x800a, 208}, + {0x800f, 208}, + {0x8018, 208}, + {0x801f, 208}, + {0x8029, 208}, + {0xc038, 208}, + {0x8002, 128}, + {0x8009, 128}, + {0x8017, 128}, + {0xc028, 128}, + {0x8002, 130}, + {0x8009, 130}, + {0x8017, 130}, + {0xc028, 130}, }, /* 100 */ { - {3, 0x02, 128}, - {6, 0x02, 128}, - {10, 0x02, 128}, - {15, 0x02, 128}, - {24, 0x02, 128}, - {31, 0x02, 128}, - {41, 0x02, 128}, - {56, 0x03, 128}, - {3, 0x02, 130}, - {6, 0x02, 130}, - {10, 0x02, 130}, - {15, 0x02, 130}, - {24, 0x02, 130}, - {31, 0x02, 130}, - {41, 0x02, 130}, - {56, 0x03, 130}, + {0x8003, 128}, + {0x8006, 128}, + {0x800a, 128}, + {0x800f, 128}, + {0x8018, 128}, + {0x801f, 128}, + {0x8029, 128}, + {0xc038, 128}, + {0x8003, 130}, + {0x8006, 130}, + {0x800a, 130}, + {0x800f, 130}, + {0x8018, 130}, + {0x801f, 130}, + {0x8029, 130}, + {0xc038, 130}, }, /* 101 */ { - {1, 0x02, 131}, - {22, 0x03, 131}, - {1, 0x02, 162}, - {22, 0x03, 162}, - {1, 0x02, 184}, - {22, 0x03, 184}, - {1, 0x02, 194}, - {22, 0x03, 194}, - {1, 0x02, 224}, - {22, 0x03, 224}, - {1, 0x02, 226}, - {22, 0x03, 226}, - {0, 0x03, 153}, - {0, 0x03, 161}, - {0, 0x03, 167}, - {0, 0x03, 172}, + {0x8001, 131}, + {0xc016, 131}, + {0x8001, 162}, + {0xc016, 162}, + {0x8001, 184}, + {0xc016, 184}, + {0x8001, 194}, + {0xc016, 194}, + {0x8001, 224}, + {0xc016, 224}, + {0x8001, 226}, + {0xc016, 226}, + {0xc000, 153}, + {0xc000, 161}, + {0xc000, 167}, + {0xc000, 172}, }, /* 102 */ { - {2, 0x02, 131}, - {9, 0x02, 131}, - {23, 0x02, 131}, - {40, 0x03, 131}, - {2, 0x02, 162}, - {9, 0x02, 162}, - {23, 0x02, 162}, - {40, 0x03, 162}, - {2, 0x02, 184}, - {9, 0x02, 184}, - {23, 0x02, 184}, - {40, 0x03, 184}, - {2, 0x02, 194}, - {9, 0x02, 194}, - {23, 0x02, 194}, - {40, 0x03, 194}, + {0x8002, 131}, + {0x8009, 131}, + {0x8017, 131}, + {0xc028, 131}, + {0x8002, 162}, + {0x8009, 162}, + {0x8017, 162}, + {0xc028, 162}, + {0x8002, 184}, + {0x8009, 184}, + {0x8017, 184}, + {0xc028, 184}, + {0x8002, 194}, + {0x8009, 194}, + {0x8017, 194}, + {0xc028, 194}, }, /* 103 */ { - {3, 0x02, 131}, - {6, 0x02, 131}, - {10, 0x02, 131}, - {15, 0x02, 131}, - {24, 0x02, 131}, - {31, 0x02, 131}, - {41, 0x02, 131}, - {56, 0x03, 131}, - {3, 0x02, 162}, - {6, 0x02, 162}, - {10, 0x02, 162}, - {15, 0x02, 162}, - {24, 0x02, 162}, - {31, 0x02, 162}, - {41, 0x02, 162}, - {56, 0x03, 162}, + {0x8003, 131}, + {0x8006, 131}, + {0x800a, 131}, + {0x800f, 131}, + {0x8018, 131}, + {0x801f, 131}, + {0x8029, 131}, + {0xc038, 131}, + {0x8003, 162}, + {0x8006, 162}, + {0x800a, 162}, + {0x800f, 162}, + {0x8018, 162}, + {0x801f, 162}, + {0x8029, 162}, + {0xc038, 162}, }, /* 104 */ { - {3, 0x02, 184}, - {6, 0x02, 184}, - {10, 0x02, 184}, - {15, 0x02, 184}, - {24, 0x02, 184}, - {31, 0x02, 184}, - {41, 0x02, 184}, - {56, 0x03, 184}, - {3, 0x02, 194}, - {6, 0x02, 194}, - {10, 0x02, 194}, - {15, 0x02, 194}, - {24, 0x02, 194}, - {31, 0x02, 194}, - {41, 0x02, 194}, - {56, 0x03, 194}, + {0x8003, 184}, + {0x8006, 184}, + {0x800a, 184}, + {0x800f, 184}, + {0x8018, 184}, + {0x801f, 184}, + {0x8029, 184}, + {0xc038, 184}, + {0x8003, 194}, + {0x8006, 194}, + {0x800a, 194}, + {0x800f, 194}, + {0x8018, 194}, + {0x801f, 194}, + {0x8029, 194}, + {0xc038, 194}, }, /* 105 */ { - {2, 0x02, 224}, - {9, 0x02, 224}, - {23, 0x02, 224}, - {40, 0x03, 224}, - {2, 0x02, 226}, - {9, 0x02, 226}, - {23, 0x02, 226}, - {40, 0x03, 226}, - {1, 0x02, 153}, - {22, 0x03, 153}, - {1, 0x02, 161}, - {22, 0x03, 161}, - {1, 0x02, 167}, - {22, 0x03, 167}, - {1, 0x02, 172}, - {22, 0x03, 172}, + {0x8002, 224}, + {0x8009, 224}, + {0x8017, 224}, + {0xc028, 224}, + {0x8002, 226}, + {0x8009, 226}, + {0x8017, 226}, + {0xc028, 226}, + {0x8001, 153}, + {0xc016, 153}, + {0x8001, 161}, + {0xc016, 161}, + {0x8001, 167}, + {0xc016, 167}, + {0x8001, 172}, + {0xc016, 172}, }, /* 106 */ { - {3, 0x02, 224}, - {6, 0x02, 224}, - {10, 0x02, 224}, - {15, 0x02, 224}, - {24, 0x02, 224}, - {31, 0x02, 224}, - {41, 0x02, 224}, - {56, 0x03, 224}, - {3, 0x02, 226}, - {6, 0x02, 226}, - {10, 0x02, 226}, - {15, 0x02, 226}, - {24, 0x02, 226}, - {31, 0x02, 226}, - {41, 0x02, 226}, - {56, 0x03, 226}, + {0x8003, 224}, + {0x8006, 224}, + {0x800a, 224}, + {0x800f, 224}, + {0x8018, 224}, + {0x801f, 224}, + {0x8029, 224}, + {0xc038, 224}, + {0x8003, 226}, + {0x8006, 226}, + {0x800a, 226}, + {0x800f, 226}, + {0x8018, 226}, + {0x801f, 226}, + {0x8029, 226}, + {0xc038, 226}, }, /* 107 */ { - {2, 0x02, 153}, - {9, 0x02, 153}, - {23, 0x02, 153}, - {40, 0x03, 153}, - {2, 0x02, 161}, - {9, 0x02, 161}, - {23, 0x02, 161}, - {40, 0x03, 161}, - {2, 0x02, 167}, - {9, 0x02, 167}, - {23, 0x02, 167}, - {40, 0x03, 167}, - {2, 0x02, 172}, - {9, 0x02, 172}, - {23, 0x02, 172}, - {40, 0x03, 172}, + {0x8002, 153}, + {0x8009, 153}, + {0x8017, 153}, + {0xc028, 153}, + {0x8002, 161}, + {0x8009, 161}, + {0x8017, 161}, + {0xc028, 161}, + {0x8002, 167}, + {0x8009, 167}, + {0x8017, 167}, + {0xc028, 167}, + {0x8002, 172}, + {0x8009, 172}, + {0x8017, 172}, + {0xc028, 172}, }, /* 108 */ { - {3, 0x02, 153}, - {6, 0x02, 153}, - {10, 0x02, 153}, - {15, 0x02, 153}, - {24, 0x02, 153}, - {31, 0x02, 153}, - {41, 0x02, 153}, - {56, 0x03, 153}, - {3, 0x02, 161}, - {6, 0x02, 161}, - {10, 0x02, 161}, - {15, 0x02, 161}, - {24, 0x02, 161}, - {31, 0x02, 161}, - {41, 0x02, 161}, - {56, 0x03, 161}, + {0x8003, 153}, + {0x8006, 153}, + {0x800a, 153}, + {0x800f, 153}, + {0x8018, 153}, + {0x801f, 153}, + {0x8029, 153}, + {0xc038, 153}, + {0x8003, 161}, + {0x8006, 161}, + {0x800a, 161}, + {0x800f, 161}, + {0x8018, 161}, + {0x801f, 161}, + {0x8029, 161}, + {0xc038, 161}, }, /* 109 */ { - {3, 0x02, 167}, - {6, 0x02, 167}, - {10, 0x02, 167}, - {15, 0x02, 167}, - {24, 0x02, 167}, - {31, 0x02, 167}, - {41, 0x02, 167}, - {56, 0x03, 167}, - {3, 0x02, 172}, - {6, 0x02, 172}, - {10, 0x02, 172}, - {15, 0x02, 172}, - {24, 0x02, 172}, - {31, 0x02, 172}, - {41, 0x02, 172}, - {56, 0x03, 172}, + {0x8003, 167}, + {0x8006, 167}, + {0x800a, 167}, + {0x800f, 167}, + {0x8018, 167}, + {0x801f, 167}, + {0x8029, 167}, + {0xc038, 167}, + {0x8003, 172}, + {0x8006, 172}, + {0x800a, 172}, + {0x800f, 172}, + {0x8018, 172}, + {0x801f, 172}, + {0x8029, 172}, + {0xc038, 172}, }, /* 110 */ { - {114, 0x00, 0}, - {115, 0x00, 0}, - {117, 0x00, 0}, - {118, 0x00, 0}, - {121, 0x00, 0}, - {123, 0x00, 0}, - {127, 0x00, 0}, - {130, 0x00, 0}, - {136, 0x00, 0}, - {139, 0x00, 0}, - {143, 0x00, 0}, - {146, 0x00, 0}, - {155, 0x00, 0}, - {162, 0x00, 0}, - {170, 0x00, 0}, - {180, 0x00, 0}, + {0x72, 0}, + {0x73, 0}, + {0x75, 0}, + {0x76, 0}, + {0x79, 0}, + {0x7b, 0}, + {0x7f, 0}, + {0x82, 0}, + {0x88, 0}, + {0x8b, 0}, + {0x8f, 0}, + {0x92, 0}, + {0x9b, 0}, + {0xa2, 0}, + {0xaa, 0}, + {0xb4, 0}, }, /* 111 */ { - {0, 0x03, 176}, - {0, 0x03, 177}, - {0, 0x03, 179}, - {0, 0x03, 209}, - {0, 0x03, 216}, - {0, 0x03, 217}, - {0, 0x03, 227}, - {0, 0x03, 229}, - {0, 0x03, 230}, - {122, 0x00, 0}, - {124, 0x00, 0}, - {125, 0x00, 0}, - {128, 0x00, 0}, - {129, 0x00, 0}, - {131, 0x00, 0}, - {132, 0x00, 0}, + {0xc000, 176}, + {0xc000, 177}, + {0xc000, 179}, + {0xc000, 209}, + {0xc000, 216}, + {0xc000, 217}, + {0xc000, 227}, + {0xc000, 229}, + {0xc000, 230}, + {0x7a, 0}, + {0x7c, 0}, + {0x7d, 0}, + {0x80, 0}, + {0x81, 0}, + {0x83, 0}, + {0x84, 0}, }, /* 112 */ { - {1, 0x02, 176}, - {22, 0x03, 176}, - {1, 0x02, 177}, - {22, 0x03, 177}, - {1, 0x02, 179}, - {22, 0x03, 179}, - {1, 0x02, 209}, - {22, 0x03, 209}, - {1, 0x02, 216}, - {22, 0x03, 216}, - {1, 0x02, 217}, - {22, 0x03, 217}, - {1, 0x02, 227}, - {22, 0x03, 227}, - {1, 0x02, 229}, - {22, 0x03, 229}, + {0x8001, 176}, + {0xc016, 176}, + {0x8001, 177}, + {0xc016, 177}, + {0x8001, 179}, + {0xc016, 179}, + {0x8001, 209}, + {0xc016, 209}, + {0x8001, 216}, + {0xc016, 216}, + {0x8001, 217}, + {0xc016, 217}, + {0x8001, 227}, + {0xc016, 227}, + {0x8001, 229}, + {0xc016, 229}, }, /* 113 */ { - {2, 0x02, 176}, - {9, 0x02, 176}, - {23, 0x02, 176}, - {40, 0x03, 176}, - {2, 0x02, 177}, - {9, 0x02, 177}, - {23, 0x02, 177}, - {40, 0x03, 177}, - {2, 0x02, 179}, - {9, 0x02, 179}, - {23, 0x02, 179}, - {40, 0x03, 179}, - {2, 0x02, 209}, - {9, 0x02, 209}, - {23, 0x02, 209}, - {40, 0x03, 209}, + {0x8002, 176}, + {0x8009, 176}, + {0x8017, 176}, + {0xc028, 176}, + {0x8002, 177}, + {0x8009, 177}, + {0x8017, 177}, + {0xc028, 177}, + {0x8002, 179}, + {0x8009, 179}, + {0x8017, 179}, + {0xc028, 179}, + {0x8002, 209}, + {0x8009, 209}, + {0x8017, 209}, + {0xc028, 209}, }, /* 114 */ { - {3, 0x02, 176}, - {6, 0x02, 176}, - {10, 0x02, 176}, - {15, 0x02, 176}, - {24, 0x02, 176}, - {31, 0x02, 176}, - {41, 0x02, 176}, - {56, 0x03, 176}, - {3, 0x02, 177}, - {6, 0x02, 177}, - {10, 0x02, 177}, - {15, 0x02, 177}, - {24, 0x02, 177}, - {31, 0x02, 177}, - {41, 0x02, 177}, - {56, 0x03, 177}, + {0x8003, 176}, + {0x8006, 176}, + {0x800a, 176}, + {0x800f, 176}, + {0x8018, 176}, + {0x801f, 176}, + {0x8029, 176}, + {0xc038, 176}, + {0x8003, 177}, + {0x8006, 177}, + {0x800a, 177}, + {0x800f, 177}, + {0x8018, 177}, + {0x801f, 177}, + {0x8029, 177}, + {0xc038, 177}, }, /* 115 */ { - {3, 0x02, 179}, - {6, 0x02, 179}, - {10, 0x02, 179}, - {15, 0x02, 179}, - {24, 0x02, 179}, - {31, 0x02, 179}, - {41, 0x02, 179}, - {56, 0x03, 179}, - {3, 0x02, 209}, - {6, 0x02, 209}, - {10, 0x02, 209}, - {15, 0x02, 209}, - {24, 0x02, 209}, - {31, 0x02, 209}, - {41, 0x02, 209}, - {56, 0x03, 209}, + {0x8003, 179}, + {0x8006, 179}, + {0x800a, 179}, + {0x800f, 179}, + {0x8018, 179}, + {0x801f, 179}, + {0x8029, 179}, + {0xc038, 179}, + {0x8003, 209}, + {0x8006, 209}, + {0x800a, 209}, + {0x800f, 209}, + {0x8018, 209}, + {0x801f, 209}, + {0x8029, 209}, + {0xc038, 209}, }, /* 116 */ { - {2, 0x02, 216}, - {9, 0x02, 216}, - {23, 0x02, 216}, - {40, 0x03, 216}, - {2, 0x02, 217}, - {9, 0x02, 217}, - {23, 0x02, 217}, - {40, 0x03, 217}, - {2, 0x02, 227}, - {9, 0x02, 227}, - {23, 0x02, 227}, - {40, 0x03, 227}, - {2, 0x02, 229}, - {9, 0x02, 229}, - {23, 0x02, 229}, - {40, 0x03, 229}, + {0x8002, 216}, + {0x8009, 216}, + {0x8017, 216}, + {0xc028, 216}, + {0x8002, 217}, + {0x8009, 217}, + {0x8017, 217}, + {0xc028, 217}, + {0x8002, 227}, + {0x8009, 227}, + {0x8017, 227}, + {0xc028, 227}, + {0x8002, 229}, + {0x8009, 229}, + {0x8017, 229}, + {0xc028, 229}, }, /* 117 */ { - {3, 0x02, 216}, - {6, 0x02, 216}, - {10, 0x02, 216}, - {15, 0x02, 216}, - {24, 0x02, 216}, - {31, 0x02, 216}, - {41, 0x02, 216}, - {56, 0x03, 216}, - {3, 0x02, 217}, - {6, 0x02, 217}, - {10, 0x02, 217}, - {15, 0x02, 217}, - {24, 0x02, 217}, - {31, 0x02, 217}, - {41, 0x02, 217}, - {56, 0x03, 217}, + {0x8003, 216}, + {0x8006, 216}, + {0x800a, 216}, + {0x800f, 216}, + {0x8018, 216}, + {0x801f, 216}, + {0x8029, 216}, + {0xc038, 216}, + {0x8003, 217}, + {0x8006, 217}, + {0x800a, 217}, + {0x800f, 217}, + {0x8018, 217}, + {0x801f, 217}, + {0x8029, 217}, + {0xc038, 217}, }, /* 118 */ { - {3, 0x02, 227}, - {6, 0x02, 227}, - {10, 0x02, 227}, - {15, 0x02, 227}, - {24, 0x02, 227}, - {31, 0x02, 227}, - {41, 0x02, 227}, - {56, 0x03, 227}, - {3, 0x02, 229}, - {6, 0x02, 229}, - {10, 0x02, 229}, - {15, 0x02, 229}, - {24, 0x02, 229}, - {31, 0x02, 229}, - {41, 0x02, 229}, - {56, 0x03, 229}, + {0x8003, 227}, + {0x8006, 227}, + {0x800a, 227}, + {0x800f, 227}, + {0x8018, 227}, + {0x801f, 227}, + {0x8029, 227}, + {0xc038, 227}, + {0x8003, 229}, + {0x8006, 229}, + {0x800a, 229}, + {0x800f, 229}, + {0x8018, 229}, + {0x801f, 229}, + {0x8029, 229}, + {0xc038, 229}, }, /* 119 */ { - {1, 0x02, 230}, - {22, 0x03, 230}, - {0, 0x03, 129}, - {0, 0x03, 132}, - {0, 0x03, 133}, - {0, 0x03, 134}, - {0, 0x03, 136}, - {0, 0x03, 146}, - {0, 0x03, 154}, - {0, 0x03, 156}, - {0, 0x03, 160}, - {0, 0x03, 163}, - {0, 0x03, 164}, - {0, 0x03, 169}, - {0, 0x03, 170}, - {0, 0x03, 173}, + {0x8001, 230}, + {0xc016, 230}, + {0xc000, 129}, + {0xc000, 132}, + {0xc000, 133}, + {0xc000, 134}, + {0xc000, 136}, + {0xc000, 146}, + {0xc000, 154}, + {0xc000, 156}, + {0xc000, 160}, + {0xc000, 163}, + {0xc000, 164}, + {0xc000, 169}, + {0xc000, 170}, + {0xc000, 173}, }, /* 120 */ { - {2, 0x02, 230}, - {9, 0x02, 230}, - {23, 0x02, 230}, - {40, 0x03, 230}, - {1, 0x02, 129}, - {22, 0x03, 129}, - {1, 0x02, 132}, - {22, 0x03, 132}, - {1, 0x02, 133}, - {22, 0x03, 133}, - {1, 0x02, 134}, - {22, 0x03, 134}, - {1, 0x02, 136}, - {22, 0x03, 136}, - {1, 0x02, 146}, - {22, 0x03, 146}, + {0x8002, 230}, + {0x8009, 230}, + {0x8017, 230}, + {0xc028, 230}, + {0x8001, 129}, + {0xc016, 129}, + {0x8001, 132}, + {0xc016, 132}, + {0x8001, 133}, + {0xc016, 133}, + {0x8001, 134}, + {0xc016, 134}, + {0x8001, 136}, + {0xc016, 136}, + {0x8001, 146}, + {0xc016, 146}, }, /* 121 */ { - {3, 0x02, 230}, - {6, 0x02, 230}, - {10, 0x02, 230}, - {15, 0x02, 230}, - {24, 0x02, 230}, - {31, 0x02, 230}, - {41, 0x02, 230}, - {56, 0x03, 230}, - {2, 0x02, 129}, - {9, 0x02, 129}, - {23, 0x02, 129}, - {40, 0x03, 129}, - {2, 0x02, 132}, - {9, 0x02, 132}, - {23, 0x02, 132}, - {40, 0x03, 132}, + {0x8003, 230}, + {0x8006, 230}, + {0x800a, 230}, + {0x800f, 230}, + {0x8018, 230}, + {0x801f, 230}, + {0x8029, 230}, + {0xc038, 230}, + {0x8002, 129}, + {0x8009, 129}, + {0x8017, 129}, + {0xc028, 129}, + {0x8002, 132}, + {0x8009, 132}, + {0x8017, 132}, + {0xc028, 132}, }, /* 122 */ { - {3, 0x02, 129}, - {6, 0x02, 129}, - {10, 0x02, 129}, - {15, 0x02, 129}, - {24, 0x02, 129}, - {31, 0x02, 129}, - {41, 0x02, 129}, - {56, 0x03, 129}, - {3, 0x02, 132}, - {6, 0x02, 132}, - {10, 0x02, 132}, - {15, 0x02, 132}, - {24, 0x02, 132}, - {31, 0x02, 132}, - {41, 0x02, 132}, - {56, 0x03, 132}, + {0x8003, 129}, + {0x8006, 129}, + {0x800a, 129}, + {0x800f, 129}, + {0x8018, 129}, + {0x801f, 129}, + {0x8029, 129}, + {0xc038, 129}, + {0x8003, 132}, + {0x8006, 132}, + {0x800a, 132}, + {0x800f, 132}, + {0x8018, 132}, + {0x801f, 132}, + {0x8029, 132}, + {0xc038, 132}, }, /* 123 */ { - {2, 0x02, 133}, - {9, 0x02, 133}, - {23, 0x02, 133}, - {40, 0x03, 133}, - {2, 0x02, 134}, - {9, 0x02, 134}, - {23, 0x02, 134}, - {40, 0x03, 134}, - {2, 0x02, 136}, - {9, 0x02, 136}, - {23, 0x02, 136}, - {40, 0x03, 136}, - {2, 0x02, 146}, - {9, 0x02, 146}, - {23, 0x02, 146}, - {40, 0x03, 146}, + {0x8002, 133}, + {0x8009, 133}, + {0x8017, 133}, + {0xc028, 133}, + {0x8002, 134}, + {0x8009, 134}, + {0x8017, 134}, + {0xc028, 134}, + {0x8002, 136}, + {0x8009, 136}, + {0x8017, 136}, + {0xc028, 136}, + {0x8002, 146}, + {0x8009, 146}, + {0x8017, 146}, + {0xc028, 146}, }, /* 124 */ { - {3, 0x02, 133}, - {6, 0x02, 133}, - {10, 0x02, 133}, - {15, 0x02, 133}, - {24, 0x02, 133}, - {31, 0x02, 133}, - {41, 0x02, 133}, - {56, 0x03, 133}, - {3, 0x02, 134}, - {6, 0x02, 134}, - {10, 0x02, 134}, - {15, 0x02, 134}, - {24, 0x02, 134}, - {31, 0x02, 134}, - {41, 0x02, 134}, - {56, 0x03, 134}, + {0x8003, 133}, + {0x8006, 133}, + {0x800a, 133}, + {0x800f, 133}, + {0x8018, 133}, + {0x801f, 133}, + {0x8029, 133}, + {0xc038, 133}, + {0x8003, 134}, + {0x8006, 134}, + {0x800a, 134}, + {0x800f, 134}, + {0x8018, 134}, + {0x801f, 134}, + {0x8029, 134}, + {0xc038, 134}, }, /* 125 */ { - {3, 0x02, 136}, - {6, 0x02, 136}, - {10, 0x02, 136}, - {15, 0x02, 136}, - {24, 0x02, 136}, - {31, 0x02, 136}, - {41, 0x02, 136}, - {56, 0x03, 136}, - {3, 0x02, 146}, - {6, 0x02, 146}, - {10, 0x02, 146}, - {15, 0x02, 146}, - {24, 0x02, 146}, - {31, 0x02, 146}, - {41, 0x02, 146}, - {56, 0x03, 146}, + {0x8003, 136}, + {0x8006, 136}, + {0x800a, 136}, + {0x800f, 136}, + {0x8018, 136}, + {0x801f, 136}, + {0x8029, 136}, + {0xc038, 136}, + {0x8003, 146}, + {0x8006, 146}, + {0x800a, 146}, + {0x800f, 146}, + {0x8018, 146}, + {0x801f, 146}, + {0x8029, 146}, + {0xc038, 146}, }, /* 126 */ { - {1, 0x02, 154}, - {22, 0x03, 154}, - {1, 0x02, 156}, - {22, 0x03, 156}, - {1, 0x02, 160}, - {22, 0x03, 160}, - {1, 0x02, 163}, - {22, 0x03, 163}, - {1, 0x02, 164}, - {22, 0x03, 164}, - {1, 0x02, 169}, - {22, 0x03, 169}, - {1, 0x02, 170}, - {22, 0x03, 170}, - {1, 0x02, 173}, - {22, 0x03, 173}, + {0x8001, 154}, + {0xc016, 154}, + {0x8001, 156}, + {0xc016, 156}, + {0x8001, 160}, + {0xc016, 160}, + {0x8001, 163}, + {0xc016, 163}, + {0x8001, 164}, + {0xc016, 164}, + {0x8001, 169}, + {0xc016, 169}, + {0x8001, 170}, + {0xc016, 170}, + {0x8001, 173}, + {0xc016, 173}, }, /* 127 */ { - {2, 0x02, 154}, - {9, 0x02, 154}, - {23, 0x02, 154}, - {40, 0x03, 154}, - {2, 0x02, 156}, - {9, 0x02, 156}, - {23, 0x02, 156}, - {40, 0x03, 156}, - {2, 0x02, 160}, - {9, 0x02, 160}, - {23, 0x02, 160}, - {40, 0x03, 160}, - {2, 0x02, 163}, - {9, 0x02, 163}, - {23, 0x02, 163}, - {40, 0x03, 163}, + {0x8002, 154}, + {0x8009, 154}, + {0x8017, 154}, + {0xc028, 154}, + {0x8002, 156}, + {0x8009, 156}, + {0x8017, 156}, + {0xc028, 156}, + {0x8002, 160}, + {0x8009, 160}, + {0x8017, 160}, + {0xc028, 160}, + {0x8002, 163}, + {0x8009, 163}, + {0x8017, 163}, + {0xc028, 163}, }, /* 128 */ { - {3, 0x02, 154}, - {6, 0x02, 154}, - {10, 0x02, 154}, - {15, 0x02, 154}, - {24, 0x02, 154}, - {31, 0x02, 154}, - {41, 0x02, 154}, - {56, 0x03, 154}, - {3, 0x02, 156}, - {6, 0x02, 156}, - {10, 0x02, 156}, - {15, 0x02, 156}, - {24, 0x02, 156}, - {31, 0x02, 156}, - {41, 0x02, 156}, - {56, 0x03, 156}, + {0x8003, 154}, + {0x8006, 154}, + {0x800a, 154}, + {0x800f, 154}, + {0x8018, 154}, + {0x801f, 154}, + {0x8029, 154}, + {0xc038, 154}, + {0x8003, 156}, + {0x8006, 156}, + {0x800a, 156}, + {0x800f, 156}, + {0x8018, 156}, + {0x801f, 156}, + {0x8029, 156}, + {0xc038, 156}, }, /* 129 */ { - {3, 0x02, 160}, - {6, 0x02, 160}, - {10, 0x02, 160}, - {15, 0x02, 160}, - {24, 0x02, 160}, - {31, 0x02, 160}, - {41, 0x02, 160}, - {56, 0x03, 160}, - {3, 0x02, 163}, - {6, 0x02, 163}, - {10, 0x02, 163}, - {15, 0x02, 163}, - {24, 0x02, 163}, - {31, 0x02, 163}, - {41, 0x02, 163}, - {56, 0x03, 163}, + {0x8003, 160}, + {0x8006, 160}, + {0x800a, 160}, + {0x800f, 160}, + {0x8018, 160}, + {0x801f, 160}, + {0x8029, 160}, + {0xc038, 160}, + {0x8003, 163}, + {0x8006, 163}, + {0x800a, 163}, + {0x800f, 163}, + {0x8018, 163}, + {0x801f, 163}, + {0x8029, 163}, + {0xc038, 163}, }, /* 130 */ { - {2, 0x02, 164}, - {9, 0x02, 164}, - {23, 0x02, 164}, - {40, 0x03, 164}, - {2, 0x02, 169}, - {9, 0x02, 169}, - {23, 0x02, 169}, - {40, 0x03, 169}, - {2, 0x02, 170}, - {9, 0x02, 170}, - {23, 0x02, 170}, - {40, 0x03, 170}, - {2, 0x02, 173}, - {9, 0x02, 173}, - {23, 0x02, 173}, - {40, 0x03, 173}, + {0x8002, 164}, + {0x8009, 164}, + {0x8017, 164}, + {0xc028, 164}, + {0x8002, 169}, + {0x8009, 169}, + {0x8017, 169}, + {0xc028, 169}, + {0x8002, 170}, + {0x8009, 170}, + {0x8017, 170}, + {0xc028, 170}, + {0x8002, 173}, + {0x8009, 173}, + {0x8017, 173}, + {0xc028, 173}, }, /* 131 */ { - {3, 0x02, 164}, - {6, 0x02, 164}, - {10, 0x02, 164}, - {15, 0x02, 164}, - {24, 0x02, 164}, - {31, 0x02, 164}, - {41, 0x02, 164}, - {56, 0x03, 164}, - {3, 0x02, 169}, - {6, 0x02, 169}, - {10, 0x02, 169}, - {15, 0x02, 169}, - {24, 0x02, 169}, - {31, 0x02, 169}, - {41, 0x02, 169}, - {56, 0x03, 169}, + {0x8003, 164}, + {0x8006, 164}, + {0x800a, 164}, + {0x800f, 164}, + {0x8018, 164}, + {0x801f, 164}, + {0x8029, 164}, + {0xc038, 164}, + {0x8003, 169}, + {0x8006, 169}, + {0x800a, 169}, + {0x800f, 169}, + {0x8018, 169}, + {0x801f, 169}, + {0x8029, 169}, + {0xc038, 169}, }, /* 132 */ { - {3, 0x02, 170}, - {6, 0x02, 170}, - {10, 0x02, 170}, - {15, 0x02, 170}, - {24, 0x02, 170}, - {31, 0x02, 170}, - {41, 0x02, 170}, - {56, 0x03, 170}, - {3, 0x02, 173}, - {6, 0x02, 173}, - {10, 0x02, 173}, - {15, 0x02, 173}, - {24, 0x02, 173}, - {31, 0x02, 173}, - {41, 0x02, 173}, - {56, 0x03, 173}, + {0x8003, 170}, + {0x8006, 170}, + {0x800a, 170}, + {0x800f, 170}, + {0x8018, 170}, + {0x801f, 170}, + {0x8029, 170}, + {0xc038, 170}, + {0x8003, 173}, + {0x8006, 173}, + {0x800a, 173}, + {0x800f, 173}, + {0x8018, 173}, + {0x801f, 173}, + {0x8029, 173}, + {0xc038, 173}, }, /* 133 */ { - {137, 0x00, 0}, - {138, 0x00, 0}, - {140, 0x00, 0}, - {141, 0x00, 0}, - {144, 0x00, 0}, - {145, 0x00, 0}, - {147, 0x00, 0}, - {150, 0x00, 0}, - {156, 0x00, 0}, - {159, 0x00, 0}, - {163, 0x00, 0}, - {166, 0x00, 0}, - {171, 0x00, 0}, - {174, 0x00, 0}, - {181, 0x00, 0}, - {190, 0x00, 0}, + {0x89, 0}, + {0x8a, 0}, + {0x8c, 0}, + {0x8d, 0}, + {0x90, 0}, + {0x91, 0}, + {0x93, 0}, + {0x96, 0}, + {0x9c, 0}, + {0x9f, 0}, + {0xa3, 0}, + {0xa6, 0}, + {0xab, 0}, + {0xae, 0}, + {0xb5, 0}, + {0xbe, 0}, }, /* 134 */ { - {0, 0x03, 178}, - {0, 0x03, 181}, - {0, 0x03, 185}, - {0, 0x03, 186}, - {0, 0x03, 187}, - {0, 0x03, 189}, - {0, 0x03, 190}, - {0, 0x03, 196}, - {0, 0x03, 198}, - {0, 0x03, 228}, - {0, 0x03, 232}, - {0, 0x03, 233}, - {148, 0x00, 0}, - {149, 0x00, 0}, - {151, 0x00, 0}, - {152, 0x00, 0}, + {0xc000, 178}, + {0xc000, 181}, + {0xc000, 185}, + {0xc000, 186}, + {0xc000, 187}, + {0xc000, 189}, + {0xc000, 190}, + {0xc000, 196}, + {0xc000, 198}, + {0xc000, 228}, + {0xc000, 232}, + {0xc000, 233}, + {0x94, 0}, + {0x95, 0}, + {0x97, 0}, + {0x98, 0}, }, /* 135 */ { - {1, 0x02, 178}, - {22, 0x03, 178}, - {1, 0x02, 181}, - {22, 0x03, 181}, - {1, 0x02, 185}, - {22, 0x03, 185}, - {1, 0x02, 186}, - {22, 0x03, 186}, - {1, 0x02, 187}, - {22, 0x03, 187}, - {1, 0x02, 189}, - {22, 0x03, 189}, - {1, 0x02, 190}, - {22, 0x03, 190}, - {1, 0x02, 196}, - {22, 0x03, 196}, + {0x8001, 178}, + {0xc016, 178}, + {0x8001, 181}, + {0xc016, 181}, + {0x8001, 185}, + {0xc016, 185}, + {0x8001, 186}, + {0xc016, 186}, + {0x8001, 187}, + {0xc016, 187}, + {0x8001, 189}, + {0xc016, 189}, + {0x8001, 190}, + {0xc016, 190}, + {0x8001, 196}, + {0xc016, 196}, }, /* 136 */ { - {2, 0x02, 178}, - {9, 0x02, 178}, - {23, 0x02, 178}, - {40, 0x03, 178}, - {2, 0x02, 181}, - {9, 0x02, 181}, - {23, 0x02, 181}, - {40, 0x03, 181}, - {2, 0x02, 185}, - {9, 0x02, 185}, - {23, 0x02, 185}, - {40, 0x03, 185}, - {2, 0x02, 186}, - {9, 0x02, 186}, - {23, 0x02, 186}, - {40, 0x03, 186}, + {0x8002, 178}, + {0x8009, 178}, + {0x8017, 178}, + {0xc028, 178}, + {0x8002, 181}, + {0x8009, 181}, + {0x8017, 181}, + {0xc028, 181}, + {0x8002, 185}, + {0x8009, 185}, + {0x8017, 185}, + {0xc028, 185}, + {0x8002, 186}, + {0x8009, 186}, + {0x8017, 186}, + {0xc028, 186}, }, /* 137 */ { - {3, 0x02, 178}, - {6, 0x02, 178}, - {10, 0x02, 178}, - {15, 0x02, 178}, - {24, 0x02, 178}, - {31, 0x02, 178}, - {41, 0x02, 178}, - {56, 0x03, 178}, - {3, 0x02, 181}, - {6, 0x02, 181}, - {10, 0x02, 181}, - {15, 0x02, 181}, - {24, 0x02, 181}, - {31, 0x02, 181}, - {41, 0x02, 181}, - {56, 0x03, 181}, + {0x8003, 178}, + {0x8006, 178}, + {0x800a, 178}, + {0x800f, 178}, + {0x8018, 178}, + {0x801f, 178}, + {0x8029, 178}, + {0xc038, 178}, + {0x8003, 181}, + {0x8006, 181}, + {0x800a, 181}, + {0x800f, 181}, + {0x8018, 181}, + {0x801f, 181}, + {0x8029, 181}, + {0xc038, 181}, }, /* 138 */ { - {3, 0x02, 185}, - {6, 0x02, 185}, - {10, 0x02, 185}, - {15, 0x02, 185}, - {24, 0x02, 185}, - {31, 0x02, 185}, - {41, 0x02, 185}, - {56, 0x03, 185}, - {3, 0x02, 186}, - {6, 0x02, 186}, - {10, 0x02, 186}, - {15, 0x02, 186}, - {24, 0x02, 186}, - {31, 0x02, 186}, - {41, 0x02, 186}, - {56, 0x03, 186}, + {0x8003, 185}, + {0x8006, 185}, + {0x800a, 185}, + {0x800f, 185}, + {0x8018, 185}, + {0x801f, 185}, + {0x8029, 185}, + {0xc038, 185}, + {0x8003, 186}, + {0x8006, 186}, + {0x800a, 186}, + {0x800f, 186}, + {0x8018, 186}, + {0x801f, 186}, + {0x8029, 186}, + {0xc038, 186}, }, /* 139 */ { - {2, 0x02, 187}, - {9, 0x02, 187}, - {23, 0x02, 187}, - {40, 0x03, 187}, - {2, 0x02, 189}, - {9, 0x02, 189}, - {23, 0x02, 189}, - {40, 0x03, 189}, - {2, 0x02, 190}, - {9, 0x02, 190}, - {23, 0x02, 190}, - {40, 0x03, 190}, - {2, 0x02, 196}, - {9, 0x02, 196}, - {23, 0x02, 196}, - {40, 0x03, 196}, + {0x8002, 187}, + {0x8009, 187}, + {0x8017, 187}, + {0xc028, 187}, + {0x8002, 189}, + {0x8009, 189}, + {0x8017, 189}, + {0xc028, 189}, + {0x8002, 190}, + {0x8009, 190}, + {0x8017, 190}, + {0xc028, 190}, + {0x8002, 196}, + {0x8009, 196}, + {0x8017, 196}, + {0xc028, 196}, }, /* 140 */ { - {3, 0x02, 187}, - {6, 0x02, 187}, - {10, 0x02, 187}, - {15, 0x02, 187}, - {24, 0x02, 187}, - {31, 0x02, 187}, - {41, 0x02, 187}, - {56, 0x03, 187}, - {3, 0x02, 189}, - {6, 0x02, 189}, - {10, 0x02, 189}, - {15, 0x02, 189}, - {24, 0x02, 189}, - {31, 0x02, 189}, - {41, 0x02, 189}, - {56, 0x03, 189}, + {0x8003, 187}, + {0x8006, 187}, + {0x800a, 187}, + {0x800f, 187}, + {0x8018, 187}, + {0x801f, 187}, + {0x8029, 187}, + {0xc038, 187}, + {0x8003, 189}, + {0x8006, 189}, + {0x800a, 189}, + {0x800f, 189}, + {0x8018, 189}, + {0x801f, 189}, + {0x8029, 189}, + {0xc038, 189}, }, /* 141 */ { - {3, 0x02, 190}, - {6, 0x02, 190}, - {10, 0x02, 190}, - {15, 0x02, 190}, - {24, 0x02, 190}, - {31, 0x02, 190}, - {41, 0x02, 190}, - {56, 0x03, 190}, - {3, 0x02, 196}, - {6, 0x02, 196}, - {10, 0x02, 196}, - {15, 0x02, 196}, - {24, 0x02, 196}, - {31, 0x02, 196}, - {41, 0x02, 196}, - {56, 0x03, 196}, + {0x8003, 190}, + {0x8006, 190}, + {0x800a, 190}, + {0x800f, 190}, + {0x8018, 190}, + {0x801f, 190}, + {0x8029, 190}, + {0xc038, 190}, + {0x8003, 196}, + {0x8006, 196}, + {0x800a, 196}, + {0x800f, 196}, + {0x8018, 196}, + {0x801f, 196}, + {0x8029, 196}, + {0xc038, 196}, }, /* 142 */ { - {1, 0x02, 198}, - {22, 0x03, 198}, - {1, 0x02, 228}, - {22, 0x03, 228}, - {1, 0x02, 232}, - {22, 0x03, 232}, - {1, 0x02, 233}, - {22, 0x03, 233}, - {0, 0x03, 1}, - {0, 0x03, 135}, - {0, 0x03, 137}, - {0, 0x03, 138}, - {0, 0x03, 139}, - {0, 0x03, 140}, - {0, 0x03, 141}, - {0, 0x03, 143}, + {0x8001, 198}, + {0xc016, 198}, + {0x8001, 228}, + {0xc016, 228}, + {0x8001, 232}, + {0xc016, 232}, + {0x8001, 233}, + {0xc016, 233}, + {0xc000, 1}, + {0xc000, 135}, + {0xc000, 137}, + {0xc000, 138}, + {0xc000, 139}, + {0xc000, 140}, + {0xc000, 141}, + {0xc000, 143}, }, /* 143 */ { - {2, 0x02, 198}, - {9, 0x02, 198}, - {23, 0x02, 198}, - {40, 0x03, 198}, - {2, 0x02, 228}, - {9, 0x02, 228}, - {23, 0x02, 228}, - {40, 0x03, 228}, - {2, 0x02, 232}, - {9, 0x02, 232}, - {23, 0x02, 232}, - {40, 0x03, 232}, - {2, 0x02, 233}, - {9, 0x02, 233}, - {23, 0x02, 233}, - {40, 0x03, 233}, + {0x8002, 198}, + {0x8009, 198}, + {0x8017, 198}, + {0xc028, 198}, + {0x8002, 228}, + {0x8009, 228}, + {0x8017, 228}, + {0xc028, 228}, + {0x8002, 232}, + {0x8009, 232}, + {0x8017, 232}, + {0xc028, 232}, + {0x8002, 233}, + {0x8009, 233}, + {0x8017, 233}, + {0xc028, 233}, }, /* 144 */ { - {3, 0x02, 198}, - {6, 0x02, 198}, - {10, 0x02, 198}, - {15, 0x02, 198}, - {24, 0x02, 198}, - {31, 0x02, 198}, - {41, 0x02, 198}, - {56, 0x03, 198}, - {3, 0x02, 228}, - {6, 0x02, 228}, - {10, 0x02, 228}, - {15, 0x02, 228}, - {24, 0x02, 228}, - {31, 0x02, 228}, - {41, 0x02, 228}, - {56, 0x03, 228}, + {0x8003, 198}, + {0x8006, 198}, + {0x800a, 198}, + {0x800f, 198}, + {0x8018, 198}, + {0x801f, 198}, + {0x8029, 198}, + {0xc038, 198}, + {0x8003, 228}, + {0x8006, 228}, + {0x800a, 228}, + {0x800f, 228}, + {0x8018, 228}, + {0x801f, 228}, + {0x8029, 228}, + {0xc038, 228}, }, /* 145 */ { - {3, 0x02, 232}, - {6, 0x02, 232}, - {10, 0x02, 232}, - {15, 0x02, 232}, - {24, 0x02, 232}, - {31, 0x02, 232}, - {41, 0x02, 232}, - {56, 0x03, 232}, - {3, 0x02, 233}, - {6, 0x02, 233}, - {10, 0x02, 233}, - {15, 0x02, 233}, - {24, 0x02, 233}, - {31, 0x02, 233}, - {41, 0x02, 233}, - {56, 0x03, 233}, + {0x8003, 232}, + {0x8006, 232}, + {0x800a, 232}, + {0x800f, 232}, + {0x8018, 232}, + {0x801f, 232}, + {0x8029, 232}, + {0xc038, 232}, + {0x8003, 233}, + {0x8006, 233}, + {0x800a, 233}, + {0x800f, 233}, + {0x8018, 233}, + {0x801f, 233}, + {0x8029, 233}, + {0xc038, 233}, }, /* 146 */ { - {1, 0x02, 1}, - {22, 0x03, 1}, - {1, 0x02, 135}, - {22, 0x03, 135}, - {1, 0x02, 137}, - {22, 0x03, 137}, - {1, 0x02, 138}, - {22, 0x03, 138}, - {1, 0x02, 139}, - {22, 0x03, 139}, - {1, 0x02, 140}, - {22, 0x03, 140}, - {1, 0x02, 141}, - {22, 0x03, 141}, - {1, 0x02, 143}, - {22, 0x03, 143}, + {0x8001, 1}, + {0xc016, 1}, + {0x8001, 135}, + {0xc016, 135}, + {0x8001, 137}, + {0xc016, 137}, + {0x8001, 138}, + {0xc016, 138}, + {0x8001, 139}, + {0xc016, 139}, + {0x8001, 140}, + {0xc016, 140}, + {0x8001, 141}, + {0xc016, 141}, + {0x8001, 143}, + {0xc016, 143}, }, /* 147 */ { - {2, 0x02, 1}, - {9, 0x02, 1}, - {23, 0x02, 1}, - {40, 0x03, 1}, - {2, 0x02, 135}, - {9, 0x02, 135}, - {23, 0x02, 135}, - {40, 0x03, 135}, - {2, 0x02, 137}, - {9, 0x02, 137}, - {23, 0x02, 137}, - {40, 0x03, 137}, - {2, 0x02, 138}, - {9, 0x02, 138}, - {23, 0x02, 138}, - {40, 0x03, 138}, + {0x8002, 1}, + {0x8009, 1}, + {0x8017, 1}, + {0xc028, 1}, + {0x8002, 135}, + {0x8009, 135}, + {0x8017, 135}, + {0xc028, 135}, + {0x8002, 137}, + {0x8009, 137}, + {0x8017, 137}, + {0xc028, 137}, + {0x8002, 138}, + {0x8009, 138}, + {0x8017, 138}, + {0xc028, 138}, }, /* 148 */ { - {3, 0x02, 1}, - {6, 0x02, 1}, - {10, 0x02, 1}, - {15, 0x02, 1}, - {24, 0x02, 1}, - {31, 0x02, 1}, - {41, 0x02, 1}, - {56, 0x03, 1}, - {3, 0x02, 135}, - {6, 0x02, 135}, - {10, 0x02, 135}, - {15, 0x02, 135}, - {24, 0x02, 135}, - {31, 0x02, 135}, - {41, 0x02, 135}, - {56, 0x03, 135}, + {0x8003, 1}, + {0x8006, 1}, + {0x800a, 1}, + {0x800f, 1}, + {0x8018, 1}, + {0x801f, 1}, + {0x8029, 1}, + {0xc038, 1}, + {0x8003, 135}, + {0x8006, 135}, + {0x800a, 135}, + {0x800f, 135}, + {0x8018, 135}, + {0x801f, 135}, + {0x8029, 135}, + {0xc038, 135}, }, /* 149 */ { - {3, 0x02, 137}, - {6, 0x02, 137}, - {10, 0x02, 137}, - {15, 0x02, 137}, - {24, 0x02, 137}, - {31, 0x02, 137}, - {41, 0x02, 137}, - {56, 0x03, 137}, - {3, 0x02, 138}, - {6, 0x02, 138}, - {10, 0x02, 138}, - {15, 0x02, 138}, - {24, 0x02, 138}, - {31, 0x02, 138}, - {41, 0x02, 138}, - {56, 0x03, 138}, + {0x8003, 137}, + {0x8006, 137}, + {0x800a, 137}, + {0x800f, 137}, + {0x8018, 137}, + {0x801f, 137}, + {0x8029, 137}, + {0xc038, 137}, + {0x8003, 138}, + {0x8006, 138}, + {0x800a, 138}, + {0x800f, 138}, + {0x8018, 138}, + {0x801f, 138}, + {0x8029, 138}, + {0xc038, 138}, }, /* 150 */ { - {2, 0x02, 139}, - {9, 0x02, 139}, - {23, 0x02, 139}, - {40, 0x03, 139}, - {2, 0x02, 140}, - {9, 0x02, 140}, - {23, 0x02, 140}, - {40, 0x03, 140}, - {2, 0x02, 141}, - {9, 0x02, 141}, - {23, 0x02, 141}, - {40, 0x03, 141}, - {2, 0x02, 143}, - {9, 0x02, 143}, - {23, 0x02, 143}, - {40, 0x03, 143}, + {0x8002, 139}, + {0x8009, 139}, + {0x8017, 139}, + {0xc028, 139}, + {0x8002, 140}, + {0x8009, 140}, + {0x8017, 140}, + {0xc028, 140}, + {0x8002, 141}, + {0x8009, 141}, + {0x8017, 141}, + {0xc028, 141}, + {0x8002, 143}, + {0x8009, 143}, + {0x8017, 143}, + {0xc028, 143}, }, /* 151 */ { - {3, 0x02, 139}, - {6, 0x02, 139}, - {10, 0x02, 139}, - {15, 0x02, 139}, - {24, 0x02, 139}, - {31, 0x02, 139}, - {41, 0x02, 139}, - {56, 0x03, 139}, - {3, 0x02, 140}, - {6, 0x02, 140}, - {10, 0x02, 140}, - {15, 0x02, 140}, - {24, 0x02, 140}, - {31, 0x02, 140}, - {41, 0x02, 140}, - {56, 0x03, 140}, + {0x8003, 139}, + {0x8006, 139}, + {0x800a, 139}, + {0x800f, 139}, + {0x8018, 139}, + {0x801f, 139}, + {0x8029, 139}, + {0xc038, 139}, + {0x8003, 140}, + {0x8006, 140}, + {0x800a, 140}, + {0x800f, 140}, + {0x8018, 140}, + {0x801f, 140}, + {0x8029, 140}, + {0xc038, 140}, }, /* 152 */ { - {3, 0x02, 141}, - {6, 0x02, 141}, - {10, 0x02, 141}, - {15, 0x02, 141}, - {24, 0x02, 141}, - {31, 0x02, 141}, - {41, 0x02, 141}, - {56, 0x03, 141}, - {3, 0x02, 143}, - {6, 0x02, 143}, - {10, 0x02, 143}, - {15, 0x02, 143}, - {24, 0x02, 143}, - {31, 0x02, 143}, - {41, 0x02, 143}, - {56, 0x03, 143}, + {0x8003, 141}, + {0x8006, 141}, + {0x800a, 141}, + {0x800f, 141}, + {0x8018, 141}, + {0x801f, 141}, + {0x8029, 141}, + {0xc038, 141}, + {0x8003, 143}, + {0x8006, 143}, + {0x800a, 143}, + {0x800f, 143}, + {0x8018, 143}, + {0x801f, 143}, + {0x8029, 143}, + {0xc038, 143}, }, /* 153 */ { - {157, 0x00, 0}, - {158, 0x00, 0}, - {160, 0x00, 0}, - {161, 0x00, 0}, - {164, 0x00, 0}, - {165, 0x00, 0}, - {167, 0x00, 0}, - {168, 0x00, 0}, - {172, 0x00, 0}, - {173, 0x00, 0}, - {175, 0x00, 0}, - {177, 0x00, 0}, - {182, 0x00, 0}, - {185, 0x00, 0}, - {191, 0x00, 0}, - {207, 0x00, 0}, + {0x9d, 0}, + {0x9e, 0}, + {0xa0, 0}, + {0xa1, 0}, + {0xa4, 0}, + {0xa5, 0}, + {0xa7, 0}, + {0xa8, 0}, + {0xac, 0}, + {0xad, 0}, + {0xaf, 0}, + {0xb1, 0}, + {0xb6, 0}, + {0xb9, 0}, + {0xbf, 0}, + {0xcf, 0}, }, /* 154 */ { - {0, 0x03, 147}, - {0, 0x03, 149}, - {0, 0x03, 150}, - {0, 0x03, 151}, - {0, 0x03, 152}, - {0, 0x03, 155}, - {0, 0x03, 157}, - {0, 0x03, 158}, - {0, 0x03, 165}, - {0, 0x03, 166}, - {0, 0x03, 168}, - {0, 0x03, 174}, - {0, 0x03, 175}, - {0, 0x03, 180}, - {0, 0x03, 182}, - {0, 0x03, 183}, + {0xc000, 147}, + {0xc000, 149}, + {0xc000, 150}, + {0xc000, 151}, + {0xc000, 152}, + {0xc000, 155}, + {0xc000, 157}, + {0xc000, 158}, + {0xc000, 165}, + {0xc000, 166}, + {0xc000, 168}, + {0xc000, 174}, + {0xc000, 175}, + {0xc000, 180}, + {0xc000, 182}, + {0xc000, 183}, }, /* 155 */ { - {1, 0x02, 147}, - {22, 0x03, 147}, - {1, 0x02, 149}, - {22, 0x03, 149}, - {1, 0x02, 150}, - {22, 0x03, 150}, - {1, 0x02, 151}, - {22, 0x03, 151}, - {1, 0x02, 152}, - {22, 0x03, 152}, - {1, 0x02, 155}, - {22, 0x03, 155}, - {1, 0x02, 157}, - {22, 0x03, 157}, - {1, 0x02, 158}, - {22, 0x03, 158}, + {0x8001, 147}, + {0xc016, 147}, + {0x8001, 149}, + {0xc016, 149}, + {0x8001, 150}, + {0xc016, 150}, + {0x8001, 151}, + {0xc016, 151}, + {0x8001, 152}, + {0xc016, 152}, + {0x8001, 155}, + {0xc016, 155}, + {0x8001, 157}, + {0xc016, 157}, + {0x8001, 158}, + {0xc016, 158}, }, /* 156 */ { - {2, 0x02, 147}, - {9, 0x02, 147}, - {23, 0x02, 147}, - {40, 0x03, 147}, - {2, 0x02, 149}, - {9, 0x02, 149}, - {23, 0x02, 149}, - {40, 0x03, 149}, - {2, 0x02, 150}, - {9, 0x02, 150}, - {23, 0x02, 150}, - {40, 0x03, 150}, - {2, 0x02, 151}, - {9, 0x02, 151}, - {23, 0x02, 151}, - {40, 0x03, 151}, + {0x8002, 147}, + {0x8009, 147}, + {0x8017, 147}, + {0xc028, 147}, + {0x8002, 149}, + {0x8009, 149}, + {0x8017, 149}, + {0xc028, 149}, + {0x8002, 150}, + {0x8009, 150}, + {0x8017, 150}, + {0xc028, 150}, + {0x8002, 151}, + {0x8009, 151}, + {0x8017, 151}, + {0xc028, 151}, }, /* 157 */ { - {3, 0x02, 147}, - {6, 0x02, 147}, - {10, 0x02, 147}, - {15, 0x02, 147}, - {24, 0x02, 147}, - {31, 0x02, 147}, - {41, 0x02, 147}, - {56, 0x03, 147}, - {3, 0x02, 149}, - {6, 0x02, 149}, - {10, 0x02, 149}, - {15, 0x02, 149}, - {24, 0x02, 149}, - {31, 0x02, 149}, - {41, 0x02, 149}, - {56, 0x03, 149}, + {0x8003, 147}, + {0x8006, 147}, + {0x800a, 147}, + {0x800f, 147}, + {0x8018, 147}, + {0x801f, 147}, + {0x8029, 147}, + {0xc038, 147}, + {0x8003, 149}, + {0x8006, 149}, + {0x800a, 149}, + {0x800f, 149}, + {0x8018, 149}, + {0x801f, 149}, + {0x8029, 149}, + {0xc038, 149}, }, /* 158 */ { - {3, 0x02, 150}, - {6, 0x02, 150}, - {10, 0x02, 150}, - {15, 0x02, 150}, - {24, 0x02, 150}, - {31, 0x02, 150}, - {41, 0x02, 150}, - {56, 0x03, 150}, - {3, 0x02, 151}, - {6, 0x02, 151}, - {10, 0x02, 151}, - {15, 0x02, 151}, - {24, 0x02, 151}, - {31, 0x02, 151}, - {41, 0x02, 151}, - {56, 0x03, 151}, + {0x8003, 150}, + {0x8006, 150}, + {0x800a, 150}, + {0x800f, 150}, + {0x8018, 150}, + {0x801f, 150}, + {0x8029, 150}, + {0xc038, 150}, + {0x8003, 151}, + {0x8006, 151}, + {0x800a, 151}, + {0x800f, 151}, + {0x8018, 151}, + {0x801f, 151}, + {0x8029, 151}, + {0xc038, 151}, }, /* 159 */ { - {2, 0x02, 152}, - {9, 0x02, 152}, - {23, 0x02, 152}, - {40, 0x03, 152}, - {2, 0x02, 155}, - {9, 0x02, 155}, - {23, 0x02, 155}, - {40, 0x03, 155}, - {2, 0x02, 157}, - {9, 0x02, 157}, - {23, 0x02, 157}, - {40, 0x03, 157}, - {2, 0x02, 158}, - {9, 0x02, 158}, - {23, 0x02, 158}, - {40, 0x03, 158}, + {0x8002, 152}, + {0x8009, 152}, + {0x8017, 152}, + {0xc028, 152}, + {0x8002, 155}, + {0x8009, 155}, + {0x8017, 155}, + {0xc028, 155}, + {0x8002, 157}, + {0x8009, 157}, + {0x8017, 157}, + {0xc028, 157}, + {0x8002, 158}, + {0x8009, 158}, + {0x8017, 158}, + {0xc028, 158}, }, /* 160 */ { - {3, 0x02, 152}, - {6, 0x02, 152}, - {10, 0x02, 152}, - {15, 0x02, 152}, - {24, 0x02, 152}, - {31, 0x02, 152}, - {41, 0x02, 152}, - {56, 0x03, 152}, - {3, 0x02, 155}, - {6, 0x02, 155}, - {10, 0x02, 155}, - {15, 0x02, 155}, - {24, 0x02, 155}, - {31, 0x02, 155}, - {41, 0x02, 155}, - {56, 0x03, 155}, + {0x8003, 152}, + {0x8006, 152}, + {0x800a, 152}, + {0x800f, 152}, + {0x8018, 152}, + {0x801f, 152}, + {0x8029, 152}, + {0xc038, 152}, + {0x8003, 155}, + {0x8006, 155}, + {0x800a, 155}, + {0x800f, 155}, + {0x8018, 155}, + {0x801f, 155}, + {0x8029, 155}, + {0xc038, 155}, }, /* 161 */ { - {3, 0x02, 157}, - {6, 0x02, 157}, - {10, 0x02, 157}, - {15, 0x02, 157}, - {24, 0x02, 157}, - {31, 0x02, 157}, - {41, 0x02, 157}, - {56, 0x03, 157}, - {3, 0x02, 158}, - {6, 0x02, 158}, - {10, 0x02, 158}, - {15, 0x02, 158}, - {24, 0x02, 158}, - {31, 0x02, 158}, - {41, 0x02, 158}, - {56, 0x03, 158}, + {0x8003, 157}, + {0x8006, 157}, + {0x800a, 157}, + {0x800f, 157}, + {0x8018, 157}, + {0x801f, 157}, + {0x8029, 157}, + {0xc038, 157}, + {0x8003, 158}, + {0x8006, 158}, + {0x800a, 158}, + {0x800f, 158}, + {0x8018, 158}, + {0x801f, 158}, + {0x8029, 158}, + {0xc038, 158}, }, /* 162 */ { - {1, 0x02, 165}, - {22, 0x03, 165}, - {1, 0x02, 166}, - {22, 0x03, 166}, - {1, 0x02, 168}, - {22, 0x03, 168}, - {1, 0x02, 174}, - {22, 0x03, 174}, - {1, 0x02, 175}, - {22, 0x03, 175}, - {1, 0x02, 180}, - {22, 0x03, 180}, - {1, 0x02, 182}, - {22, 0x03, 182}, - {1, 0x02, 183}, - {22, 0x03, 183}, + {0x8001, 165}, + {0xc016, 165}, + {0x8001, 166}, + {0xc016, 166}, + {0x8001, 168}, + {0xc016, 168}, + {0x8001, 174}, + {0xc016, 174}, + {0x8001, 175}, + {0xc016, 175}, + {0x8001, 180}, + {0xc016, 180}, + {0x8001, 182}, + {0xc016, 182}, + {0x8001, 183}, + {0xc016, 183}, }, /* 163 */ { - {2, 0x02, 165}, - {9, 0x02, 165}, - {23, 0x02, 165}, - {40, 0x03, 165}, - {2, 0x02, 166}, - {9, 0x02, 166}, - {23, 0x02, 166}, - {40, 0x03, 166}, - {2, 0x02, 168}, - {9, 0x02, 168}, - {23, 0x02, 168}, - {40, 0x03, 168}, - {2, 0x02, 174}, - {9, 0x02, 174}, - {23, 0x02, 174}, - {40, 0x03, 174}, + {0x8002, 165}, + {0x8009, 165}, + {0x8017, 165}, + {0xc028, 165}, + {0x8002, 166}, + {0x8009, 166}, + {0x8017, 166}, + {0xc028, 166}, + {0x8002, 168}, + {0x8009, 168}, + {0x8017, 168}, + {0xc028, 168}, + {0x8002, 174}, + {0x8009, 174}, + {0x8017, 174}, + {0xc028, 174}, }, /* 164 */ { - {3, 0x02, 165}, - {6, 0x02, 165}, - {10, 0x02, 165}, - {15, 0x02, 165}, - {24, 0x02, 165}, - {31, 0x02, 165}, - {41, 0x02, 165}, - {56, 0x03, 165}, - {3, 0x02, 166}, - {6, 0x02, 166}, - {10, 0x02, 166}, - {15, 0x02, 166}, - {24, 0x02, 166}, - {31, 0x02, 166}, - {41, 0x02, 166}, - {56, 0x03, 166}, + {0x8003, 165}, + {0x8006, 165}, + {0x800a, 165}, + {0x800f, 165}, + {0x8018, 165}, + {0x801f, 165}, + {0x8029, 165}, + {0xc038, 165}, + {0x8003, 166}, + {0x8006, 166}, + {0x800a, 166}, + {0x800f, 166}, + {0x8018, 166}, + {0x801f, 166}, + {0x8029, 166}, + {0xc038, 166}, }, /* 165 */ { - {3, 0x02, 168}, - {6, 0x02, 168}, - {10, 0x02, 168}, - {15, 0x02, 168}, - {24, 0x02, 168}, - {31, 0x02, 168}, - {41, 0x02, 168}, - {56, 0x03, 168}, - {3, 0x02, 174}, - {6, 0x02, 174}, - {10, 0x02, 174}, - {15, 0x02, 174}, - {24, 0x02, 174}, - {31, 0x02, 174}, - {41, 0x02, 174}, - {56, 0x03, 174}, + {0x8003, 168}, + {0x8006, 168}, + {0x800a, 168}, + {0x800f, 168}, + {0x8018, 168}, + {0x801f, 168}, + {0x8029, 168}, + {0xc038, 168}, + {0x8003, 174}, + {0x8006, 174}, + {0x800a, 174}, + {0x800f, 174}, + {0x8018, 174}, + {0x801f, 174}, + {0x8029, 174}, + {0xc038, 174}, }, /* 166 */ { - {2, 0x02, 175}, - {9, 0x02, 175}, - {23, 0x02, 175}, - {40, 0x03, 175}, - {2, 0x02, 180}, - {9, 0x02, 180}, - {23, 0x02, 180}, - {40, 0x03, 180}, - {2, 0x02, 182}, - {9, 0x02, 182}, - {23, 0x02, 182}, - {40, 0x03, 182}, - {2, 0x02, 183}, - {9, 0x02, 183}, - {23, 0x02, 183}, - {40, 0x03, 183}, + {0x8002, 175}, + {0x8009, 175}, + {0x8017, 175}, + {0xc028, 175}, + {0x8002, 180}, + {0x8009, 180}, + {0x8017, 180}, + {0xc028, 180}, + {0x8002, 182}, + {0x8009, 182}, + {0x8017, 182}, + {0xc028, 182}, + {0x8002, 183}, + {0x8009, 183}, + {0x8017, 183}, + {0xc028, 183}, }, /* 167 */ { - {3, 0x02, 175}, - {6, 0x02, 175}, - {10, 0x02, 175}, - {15, 0x02, 175}, - {24, 0x02, 175}, - {31, 0x02, 175}, - {41, 0x02, 175}, - {56, 0x03, 175}, - {3, 0x02, 180}, - {6, 0x02, 180}, - {10, 0x02, 180}, - {15, 0x02, 180}, - {24, 0x02, 180}, - {31, 0x02, 180}, - {41, 0x02, 180}, - {56, 0x03, 180}, + {0x8003, 175}, + {0x8006, 175}, + {0x800a, 175}, + {0x800f, 175}, + {0x8018, 175}, + {0x801f, 175}, + {0x8029, 175}, + {0xc038, 175}, + {0x8003, 180}, + {0x8006, 180}, + {0x800a, 180}, + {0x800f, 180}, + {0x8018, 180}, + {0x801f, 180}, + {0x8029, 180}, + {0xc038, 180}, }, /* 168 */ { - {3, 0x02, 182}, - {6, 0x02, 182}, - {10, 0x02, 182}, - {15, 0x02, 182}, - {24, 0x02, 182}, - {31, 0x02, 182}, - {41, 0x02, 182}, - {56, 0x03, 182}, - {3, 0x02, 183}, - {6, 0x02, 183}, - {10, 0x02, 183}, - {15, 0x02, 183}, - {24, 0x02, 183}, - {31, 0x02, 183}, - {41, 0x02, 183}, - {56, 0x03, 183}, + {0x8003, 182}, + {0x8006, 182}, + {0x800a, 182}, + {0x800f, 182}, + {0x8018, 182}, + {0x801f, 182}, + {0x8029, 182}, + {0xc038, 182}, + {0x8003, 183}, + {0x8006, 183}, + {0x800a, 183}, + {0x800f, 183}, + {0x8018, 183}, + {0x801f, 183}, + {0x8029, 183}, + {0xc038, 183}, }, /* 169 */ { - {0, 0x03, 188}, - {0, 0x03, 191}, - {0, 0x03, 197}, - {0, 0x03, 231}, - {0, 0x03, 239}, - {176, 0x00, 0}, - {178, 0x00, 0}, - {179, 0x00, 0}, - {183, 0x00, 0}, - {184, 0x00, 0}, - {186, 0x00, 0}, - {187, 0x00, 0}, - {192, 0x00, 0}, - {199, 0x00, 0}, - {208, 0x00, 0}, - {223, 0x00, 0}, + {0xc000, 188}, + {0xc000, 191}, + {0xc000, 197}, + {0xc000, 231}, + {0xc000, 239}, + {0xb0, 0}, + {0xb2, 0}, + {0xb3, 0}, + {0xb7, 0}, + {0xb8, 0}, + {0xba, 0}, + {0xbb, 0}, + {0xc0, 0}, + {0xc7, 0}, + {0xd0, 0}, + {0xdf, 0}, }, /* 170 */ { - {1, 0x02, 188}, - {22, 0x03, 188}, - {1, 0x02, 191}, - {22, 0x03, 191}, - {1, 0x02, 197}, - {22, 0x03, 197}, - {1, 0x02, 231}, - {22, 0x03, 231}, - {1, 0x02, 239}, - {22, 0x03, 239}, - {0, 0x03, 9}, - {0, 0x03, 142}, - {0, 0x03, 144}, - {0, 0x03, 145}, - {0, 0x03, 148}, - {0, 0x03, 159}, + {0x8001, 188}, + {0xc016, 188}, + {0x8001, 191}, + {0xc016, 191}, + {0x8001, 197}, + {0xc016, 197}, + {0x8001, 231}, + {0xc016, 231}, + {0x8001, 239}, + {0xc016, 239}, + {0xc000, 9}, + {0xc000, 142}, + {0xc000, 144}, + {0xc000, 145}, + {0xc000, 148}, + {0xc000, 159}, }, /* 171 */ { - {2, 0x02, 188}, - {9, 0x02, 188}, - {23, 0x02, 188}, - {40, 0x03, 188}, - {2, 0x02, 191}, - {9, 0x02, 191}, - {23, 0x02, 191}, - {40, 0x03, 191}, - {2, 0x02, 197}, - {9, 0x02, 197}, - {23, 0x02, 197}, - {40, 0x03, 197}, - {2, 0x02, 231}, - {9, 0x02, 231}, - {23, 0x02, 231}, - {40, 0x03, 231}, + {0x8002, 188}, + {0x8009, 188}, + {0x8017, 188}, + {0xc028, 188}, + {0x8002, 191}, + {0x8009, 191}, + {0x8017, 191}, + {0xc028, 191}, + {0x8002, 197}, + {0x8009, 197}, + {0x8017, 197}, + {0xc028, 197}, + {0x8002, 231}, + {0x8009, 231}, + {0x8017, 231}, + {0xc028, 231}, }, /* 172 */ { - {3, 0x02, 188}, - {6, 0x02, 188}, - {10, 0x02, 188}, - {15, 0x02, 188}, - {24, 0x02, 188}, - {31, 0x02, 188}, - {41, 0x02, 188}, - {56, 0x03, 188}, - {3, 0x02, 191}, - {6, 0x02, 191}, - {10, 0x02, 191}, - {15, 0x02, 191}, - {24, 0x02, 191}, - {31, 0x02, 191}, - {41, 0x02, 191}, - {56, 0x03, 191}, + {0x8003, 188}, + {0x8006, 188}, + {0x800a, 188}, + {0x800f, 188}, + {0x8018, 188}, + {0x801f, 188}, + {0x8029, 188}, + {0xc038, 188}, + {0x8003, 191}, + {0x8006, 191}, + {0x800a, 191}, + {0x800f, 191}, + {0x8018, 191}, + {0x801f, 191}, + {0x8029, 191}, + {0xc038, 191}, }, /* 173 */ { - {3, 0x02, 197}, - {6, 0x02, 197}, - {10, 0x02, 197}, - {15, 0x02, 197}, - {24, 0x02, 197}, - {31, 0x02, 197}, - {41, 0x02, 197}, - {56, 0x03, 197}, - {3, 0x02, 231}, - {6, 0x02, 231}, - {10, 0x02, 231}, - {15, 0x02, 231}, - {24, 0x02, 231}, - {31, 0x02, 231}, - {41, 0x02, 231}, - {56, 0x03, 231}, + {0x8003, 197}, + {0x8006, 197}, + {0x800a, 197}, + {0x800f, 197}, + {0x8018, 197}, + {0x801f, 197}, + {0x8029, 197}, + {0xc038, 197}, + {0x8003, 231}, + {0x8006, 231}, + {0x800a, 231}, + {0x800f, 231}, + {0x8018, 231}, + {0x801f, 231}, + {0x8029, 231}, + {0xc038, 231}, }, /* 174 */ { - {2, 0x02, 239}, - {9, 0x02, 239}, - {23, 0x02, 239}, - {40, 0x03, 239}, - {1, 0x02, 9}, - {22, 0x03, 9}, - {1, 0x02, 142}, - {22, 0x03, 142}, - {1, 0x02, 144}, - {22, 0x03, 144}, - {1, 0x02, 145}, - {22, 0x03, 145}, - {1, 0x02, 148}, - {22, 0x03, 148}, - {1, 0x02, 159}, - {22, 0x03, 159}, + {0x8002, 239}, + {0x8009, 239}, + {0x8017, 239}, + {0xc028, 239}, + {0x8001, 9}, + {0xc016, 9}, + {0x8001, 142}, + {0xc016, 142}, + {0x8001, 144}, + {0xc016, 144}, + {0x8001, 145}, + {0xc016, 145}, + {0x8001, 148}, + {0xc016, 148}, + {0x8001, 159}, + {0xc016, 159}, }, /* 175 */ { - {3, 0x02, 239}, - {6, 0x02, 239}, - {10, 0x02, 239}, - {15, 0x02, 239}, - {24, 0x02, 239}, - {31, 0x02, 239}, - {41, 0x02, 239}, - {56, 0x03, 239}, - {2, 0x02, 9}, - {9, 0x02, 9}, - {23, 0x02, 9}, - {40, 0x03, 9}, - {2, 0x02, 142}, - {9, 0x02, 142}, - {23, 0x02, 142}, - {40, 0x03, 142}, + {0x8003, 239}, + {0x8006, 239}, + {0x800a, 239}, + {0x800f, 239}, + {0x8018, 239}, + {0x801f, 239}, + {0x8029, 239}, + {0xc038, 239}, + {0x8002, 9}, + {0x8009, 9}, + {0x8017, 9}, + {0xc028, 9}, + {0x8002, 142}, + {0x8009, 142}, + {0x8017, 142}, + {0xc028, 142}, }, /* 176 */ { - {3, 0x02, 9}, - {6, 0x02, 9}, - {10, 0x02, 9}, - {15, 0x02, 9}, - {24, 0x02, 9}, - {31, 0x02, 9}, - {41, 0x02, 9}, - {56, 0x03, 9}, - {3, 0x02, 142}, - {6, 0x02, 142}, - {10, 0x02, 142}, - {15, 0x02, 142}, - {24, 0x02, 142}, - {31, 0x02, 142}, - {41, 0x02, 142}, - {56, 0x03, 142}, + {0x8003, 9}, + {0x8006, 9}, + {0x800a, 9}, + {0x800f, 9}, + {0x8018, 9}, + {0x801f, 9}, + {0x8029, 9}, + {0xc038, 9}, + {0x8003, 142}, + {0x8006, 142}, + {0x800a, 142}, + {0x800f, 142}, + {0x8018, 142}, + {0x801f, 142}, + {0x8029, 142}, + {0xc038, 142}, }, /* 177 */ { - {2, 0x02, 144}, - {9, 0x02, 144}, - {23, 0x02, 144}, - {40, 0x03, 144}, - {2, 0x02, 145}, - {9, 0x02, 145}, - {23, 0x02, 145}, - {40, 0x03, 145}, - {2, 0x02, 148}, - {9, 0x02, 148}, - {23, 0x02, 148}, - {40, 0x03, 148}, - {2, 0x02, 159}, - {9, 0x02, 159}, - {23, 0x02, 159}, - {40, 0x03, 159}, + {0x8002, 144}, + {0x8009, 144}, + {0x8017, 144}, + {0xc028, 144}, + {0x8002, 145}, + {0x8009, 145}, + {0x8017, 145}, + {0xc028, 145}, + {0x8002, 148}, + {0x8009, 148}, + {0x8017, 148}, + {0xc028, 148}, + {0x8002, 159}, + {0x8009, 159}, + {0x8017, 159}, + {0xc028, 159}, }, /* 178 */ { - {3, 0x02, 144}, - {6, 0x02, 144}, - {10, 0x02, 144}, - {15, 0x02, 144}, - {24, 0x02, 144}, - {31, 0x02, 144}, - {41, 0x02, 144}, - {56, 0x03, 144}, - {3, 0x02, 145}, - {6, 0x02, 145}, - {10, 0x02, 145}, - {15, 0x02, 145}, - {24, 0x02, 145}, - {31, 0x02, 145}, - {41, 0x02, 145}, - {56, 0x03, 145}, + {0x8003, 144}, + {0x8006, 144}, + {0x800a, 144}, + {0x800f, 144}, + {0x8018, 144}, + {0x801f, 144}, + {0x8029, 144}, + {0xc038, 144}, + {0x8003, 145}, + {0x8006, 145}, + {0x800a, 145}, + {0x800f, 145}, + {0x8018, 145}, + {0x801f, 145}, + {0x8029, 145}, + {0xc038, 145}, }, /* 179 */ { - {3, 0x02, 148}, - {6, 0x02, 148}, - {10, 0x02, 148}, - {15, 0x02, 148}, - {24, 0x02, 148}, - {31, 0x02, 148}, - {41, 0x02, 148}, - {56, 0x03, 148}, - {3, 0x02, 159}, - {6, 0x02, 159}, - {10, 0x02, 159}, - {15, 0x02, 159}, - {24, 0x02, 159}, - {31, 0x02, 159}, - {41, 0x02, 159}, - {56, 0x03, 159}, + {0x8003, 148}, + {0x8006, 148}, + {0x800a, 148}, + {0x800f, 148}, + {0x8018, 148}, + {0x801f, 148}, + {0x8029, 148}, + {0xc038, 148}, + {0x8003, 159}, + {0x8006, 159}, + {0x800a, 159}, + {0x800f, 159}, + {0x8018, 159}, + {0x801f, 159}, + {0x8029, 159}, + {0xc038, 159}, }, /* 180 */ { - {0, 0x03, 171}, - {0, 0x03, 206}, - {0, 0x03, 215}, - {0, 0x03, 225}, - {0, 0x03, 236}, - {0, 0x03, 237}, - {188, 0x00, 0}, - {189, 0x00, 0}, - {193, 0x00, 0}, - {196, 0x00, 0}, - {200, 0x00, 0}, - {203, 0x00, 0}, - {209, 0x00, 0}, - {216, 0x00, 0}, - {224, 0x00, 0}, - {238, 0x00, 0}, + {0xc000, 171}, + {0xc000, 206}, + {0xc000, 215}, + {0xc000, 225}, + {0xc000, 236}, + {0xc000, 237}, + {0xbc, 0}, + {0xbd, 0}, + {0xc1, 0}, + {0xc4, 0}, + {0xc8, 0}, + {0xcb, 0}, + {0xd1, 0}, + {0xd8, 0}, + {0xe0, 0}, + {0xee, 0}, }, /* 181 */ { - {1, 0x02, 171}, - {22, 0x03, 171}, - {1, 0x02, 206}, - {22, 0x03, 206}, - {1, 0x02, 215}, - {22, 0x03, 215}, - {1, 0x02, 225}, - {22, 0x03, 225}, - {1, 0x02, 236}, - {22, 0x03, 236}, - {1, 0x02, 237}, - {22, 0x03, 237}, - {0, 0x03, 199}, - {0, 0x03, 207}, - {0, 0x03, 234}, - {0, 0x03, 235}, + {0x8001, 171}, + {0xc016, 171}, + {0x8001, 206}, + {0xc016, 206}, + {0x8001, 215}, + {0xc016, 215}, + {0x8001, 225}, + {0xc016, 225}, + {0x8001, 236}, + {0xc016, 236}, + {0x8001, 237}, + {0xc016, 237}, + {0xc000, 199}, + {0xc000, 207}, + {0xc000, 234}, + {0xc000, 235}, }, /* 182 */ { - {2, 0x02, 171}, - {9, 0x02, 171}, - {23, 0x02, 171}, - {40, 0x03, 171}, - {2, 0x02, 206}, - {9, 0x02, 206}, - {23, 0x02, 206}, - {40, 0x03, 206}, - {2, 0x02, 215}, - {9, 0x02, 215}, - {23, 0x02, 215}, - {40, 0x03, 215}, - {2, 0x02, 225}, - {9, 0x02, 225}, - {23, 0x02, 225}, - {40, 0x03, 225}, + {0x8002, 171}, + {0x8009, 171}, + {0x8017, 171}, + {0xc028, 171}, + {0x8002, 206}, + {0x8009, 206}, + {0x8017, 206}, + {0xc028, 206}, + {0x8002, 215}, + {0x8009, 215}, + {0x8017, 215}, + {0xc028, 215}, + {0x8002, 225}, + {0x8009, 225}, + {0x8017, 225}, + {0xc028, 225}, }, /* 183 */ { - {3, 0x02, 171}, - {6, 0x02, 171}, - {10, 0x02, 171}, - {15, 0x02, 171}, - {24, 0x02, 171}, - {31, 0x02, 171}, - {41, 0x02, 171}, - {56, 0x03, 171}, - {3, 0x02, 206}, - {6, 0x02, 206}, - {10, 0x02, 206}, - {15, 0x02, 206}, - {24, 0x02, 206}, - {31, 0x02, 206}, - {41, 0x02, 206}, - {56, 0x03, 206}, + {0x8003, 171}, + {0x8006, 171}, + {0x800a, 171}, + {0x800f, 171}, + {0x8018, 171}, + {0x801f, 171}, + {0x8029, 171}, + {0xc038, 171}, + {0x8003, 206}, + {0x8006, 206}, + {0x800a, 206}, + {0x800f, 206}, + {0x8018, 206}, + {0x801f, 206}, + {0x8029, 206}, + {0xc038, 206}, }, /* 184 */ { - {3, 0x02, 215}, - {6, 0x02, 215}, - {10, 0x02, 215}, - {15, 0x02, 215}, - {24, 0x02, 215}, - {31, 0x02, 215}, - {41, 0x02, 215}, - {56, 0x03, 215}, - {3, 0x02, 225}, - {6, 0x02, 225}, - {10, 0x02, 225}, - {15, 0x02, 225}, - {24, 0x02, 225}, - {31, 0x02, 225}, - {41, 0x02, 225}, - {56, 0x03, 225}, + {0x8003, 215}, + {0x8006, 215}, + {0x800a, 215}, + {0x800f, 215}, + {0x8018, 215}, + {0x801f, 215}, + {0x8029, 215}, + {0xc038, 215}, + {0x8003, 225}, + {0x8006, 225}, + {0x800a, 225}, + {0x800f, 225}, + {0x8018, 225}, + {0x801f, 225}, + {0x8029, 225}, + {0xc038, 225}, }, /* 185 */ { - {2, 0x02, 236}, - {9, 0x02, 236}, - {23, 0x02, 236}, - {40, 0x03, 236}, - {2, 0x02, 237}, - {9, 0x02, 237}, - {23, 0x02, 237}, - {40, 0x03, 237}, - {1, 0x02, 199}, - {22, 0x03, 199}, - {1, 0x02, 207}, - {22, 0x03, 207}, - {1, 0x02, 234}, - {22, 0x03, 234}, - {1, 0x02, 235}, - {22, 0x03, 235}, + {0x8002, 236}, + {0x8009, 236}, + {0x8017, 236}, + {0xc028, 236}, + {0x8002, 237}, + {0x8009, 237}, + {0x8017, 237}, + {0xc028, 237}, + {0x8001, 199}, + {0xc016, 199}, + {0x8001, 207}, + {0xc016, 207}, + {0x8001, 234}, + {0xc016, 234}, + {0x8001, 235}, + {0xc016, 235}, }, /* 186 */ { - {3, 0x02, 236}, - {6, 0x02, 236}, - {10, 0x02, 236}, - {15, 0x02, 236}, - {24, 0x02, 236}, - {31, 0x02, 236}, - {41, 0x02, 236}, - {56, 0x03, 236}, - {3, 0x02, 237}, - {6, 0x02, 237}, - {10, 0x02, 237}, - {15, 0x02, 237}, - {24, 0x02, 237}, - {31, 0x02, 237}, - {41, 0x02, 237}, - {56, 0x03, 237}, + {0x8003, 236}, + {0x8006, 236}, + {0x800a, 236}, + {0x800f, 236}, + {0x8018, 236}, + {0x801f, 236}, + {0x8029, 236}, + {0xc038, 236}, + {0x8003, 237}, + {0x8006, 237}, + {0x800a, 237}, + {0x800f, 237}, + {0x8018, 237}, + {0x801f, 237}, + {0x8029, 237}, + {0xc038, 237}, }, /* 187 */ { - {2, 0x02, 199}, - {9, 0x02, 199}, - {23, 0x02, 199}, - {40, 0x03, 199}, - {2, 0x02, 207}, - {9, 0x02, 207}, - {23, 0x02, 207}, - {40, 0x03, 207}, - {2, 0x02, 234}, - {9, 0x02, 234}, - {23, 0x02, 234}, - {40, 0x03, 234}, - {2, 0x02, 235}, - {9, 0x02, 235}, - {23, 0x02, 235}, - {40, 0x03, 235}, + {0x8002, 199}, + {0x8009, 199}, + {0x8017, 199}, + {0xc028, 199}, + {0x8002, 207}, + {0x8009, 207}, + {0x8017, 207}, + {0xc028, 207}, + {0x8002, 234}, + {0x8009, 234}, + {0x8017, 234}, + {0xc028, 234}, + {0x8002, 235}, + {0x8009, 235}, + {0x8017, 235}, + {0xc028, 235}, }, /* 188 */ { - {3, 0x02, 199}, - {6, 0x02, 199}, - {10, 0x02, 199}, - {15, 0x02, 199}, - {24, 0x02, 199}, - {31, 0x02, 199}, - {41, 0x02, 199}, - {56, 0x03, 199}, - {3, 0x02, 207}, - {6, 0x02, 207}, - {10, 0x02, 207}, - {15, 0x02, 207}, - {24, 0x02, 207}, - {31, 0x02, 207}, - {41, 0x02, 207}, - {56, 0x03, 207}, + {0x8003, 199}, + {0x8006, 199}, + {0x800a, 199}, + {0x800f, 199}, + {0x8018, 199}, + {0x801f, 199}, + {0x8029, 199}, + {0xc038, 199}, + {0x8003, 207}, + {0x8006, 207}, + {0x800a, 207}, + {0x800f, 207}, + {0x8018, 207}, + {0x801f, 207}, + {0x8029, 207}, + {0xc038, 207}, }, /* 189 */ { - {3, 0x02, 234}, - {6, 0x02, 234}, - {10, 0x02, 234}, - {15, 0x02, 234}, - {24, 0x02, 234}, - {31, 0x02, 234}, - {41, 0x02, 234}, - {56, 0x03, 234}, - {3, 0x02, 235}, - {6, 0x02, 235}, - {10, 0x02, 235}, - {15, 0x02, 235}, - {24, 0x02, 235}, - {31, 0x02, 235}, - {41, 0x02, 235}, - {56, 0x03, 235}, + {0x8003, 234}, + {0x8006, 234}, + {0x800a, 234}, + {0x800f, 234}, + {0x8018, 234}, + {0x801f, 234}, + {0x8029, 234}, + {0xc038, 234}, + {0x8003, 235}, + {0x8006, 235}, + {0x800a, 235}, + {0x800f, 235}, + {0x8018, 235}, + {0x801f, 235}, + {0x8029, 235}, + {0xc038, 235}, }, /* 190 */ { - {194, 0x00, 0}, - {195, 0x00, 0}, - {197, 0x00, 0}, - {198, 0x00, 0}, - {201, 0x00, 0}, - {202, 0x00, 0}, - {204, 0x00, 0}, - {205, 0x00, 0}, - {210, 0x00, 0}, - {213, 0x00, 0}, - {217, 0x00, 0}, - {220, 0x00, 0}, - {225, 0x00, 0}, - {231, 0x00, 0}, - {239, 0x00, 0}, - {246, 0x00, 0}, + {0xc2, 0}, + {0xc3, 0}, + {0xc5, 0}, + {0xc6, 0}, + {0xc9, 0}, + {0xca, 0}, + {0xcc, 0}, + {0xcd, 0}, + {0xd2, 0}, + {0xd5, 0}, + {0xd9, 0}, + {0xdc, 0}, + {0xe1, 0}, + {0xe7, 0}, + {0xef, 0}, + {0xf6, 0}, }, /* 191 */ { - {0, 0x03, 192}, - {0, 0x03, 193}, - {0, 0x03, 200}, - {0, 0x03, 201}, - {0, 0x03, 202}, - {0, 0x03, 205}, - {0, 0x03, 210}, - {0, 0x03, 213}, - {0, 0x03, 218}, - {0, 0x03, 219}, - {0, 0x03, 238}, - {0, 0x03, 240}, - {0, 0x03, 242}, - {0, 0x03, 243}, - {0, 0x03, 255}, - {206, 0x00, 0}, + {0xc000, 192}, + {0xc000, 193}, + {0xc000, 200}, + {0xc000, 201}, + {0xc000, 202}, + {0xc000, 205}, + {0xc000, 210}, + {0xc000, 213}, + {0xc000, 218}, + {0xc000, 219}, + {0xc000, 238}, + {0xc000, 240}, + {0xc000, 242}, + {0xc000, 243}, + {0xc000, 255}, + {0xce, 0}, }, /* 192 */ { - {1, 0x02, 192}, - {22, 0x03, 192}, - {1, 0x02, 193}, - {22, 0x03, 193}, - {1, 0x02, 200}, - {22, 0x03, 200}, - {1, 0x02, 201}, - {22, 0x03, 201}, - {1, 0x02, 202}, - {22, 0x03, 202}, - {1, 0x02, 205}, - {22, 0x03, 205}, - {1, 0x02, 210}, - {22, 0x03, 210}, - {1, 0x02, 213}, - {22, 0x03, 213}, + {0x8001, 192}, + {0xc016, 192}, + {0x8001, 193}, + {0xc016, 193}, + {0x8001, 200}, + {0xc016, 200}, + {0x8001, 201}, + {0xc016, 201}, + {0x8001, 202}, + {0xc016, 202}, + {0x8001, 205}, + {0xc016, 205}, + {0x8001, 210}, + {0xc016, 210}, + {0x8001, 213}, + {0xc016, 213}, }, /* 193 */ { - {2, 0x02, 192}, - {9, 0x02, 192}, - {23, 0x02, 192}, - {40, 0x03, 192}, - {2, 0x02, 193}, - {9, 0x02, 193}, - {23, 0x02, 193}, - {40, 0x03, 193}, - {2, 0x02, 200}, - {9, 0x02, 200}, - {23, 0x02, 200}, - {40, 0x03, 200}, - {2, 0x02, 201}, - {9, 0x02, 201}, - {23, 0x02, 201}, - {40, 0x03, 201}, + {0x8002, 192}, + {0x8009, 192}, + {0x8017, 192}, + {0xc028, 192}, + {0x8002, 193}, + {0x8009, 193}, + {0x8017, 193}, + {0xc028, 193}, + {0x8002, 200}, + {0x8009, 200}, + {0x8017, 200}, + {0xc028, 200}, + {0x8002, 201}, + {0x8009, 201}, + {0x8017, 201}, + {0xc028, 201}, }, /* 194 */ { - {3, 0x02, 192}, - {6, 0x02, 192}, - {10, 0x02, 192}, - {15, 0x02, 192}, - {24, 0x02, 192}, - {31, 0x02, 192}, - {41, 0x02, 192}, - {56, 0x03, 192}, - {3, 0x02, 193}, - {6, 0x02, 193}, - {10, 0x02, 193}, - {15, 0x02, 193}, - {24, 0x02, 193}, - {31, 0x02, 193}, - {41, 0x02, 193}, - {56, 0x03, 193}, + {0x8003, 192}, + {0x8006, 192}, + {0x800a, 192}, + {0x800f, 192}, + {0x8018, 192}, + {0x801f, 192}, + {0x8029, 192}, + {0xc038, 192}, + {0x8003, 193}, + {0x8006, 193}, + {0x800a, 193}, + {0x800f, 193}, + {0x8018, 193}, + {0x801f, 193}, + {0x8029, 193}, + {0xc038, 193}, }, /* 195 */ { - {3, 0x02, 200}, - {6, 0x02, 200}, - {10, 0x02, 200}, - {15, 0x02, 200}, - {24, 0x02, 200}, - {31, 0x02, 200}, - {41, 0x02, 200}, - {56, 0x03, 200}, - {3, 0x02, 201}, - {6, 0x02, 201}, - {10, 0x02, 201}, - {15, 0x02, 201}, - {24, 0x02, 201}, - {31, 0x02, 201}, - {41, 0x02, 201}, - {56, 0x03, 201}, + {0x8003, 200}, + {0x8006, 200}, + {0x800a, 200}, + {0x800f, 200}, + {0x8018, 200}, + {0x801f, 200}, + {0x8029, 200}, + {0xc038, 200}, + {0x8003, 201}, + {0x8006, 201}, + {0x800a, 201}, + {0x800f, 201}, + {0x8018, 201}, + {0x801f, 201}, + {0x8029, 201}, + {0xc038, 201}, }, /* 196 */ { - {2, 0x02, 202}, - {9, 0x02, 202}, - {23, 0x02, 202}, - {40, 0x03, 202}, - {2, 0x02, 205}, - {9, 0x02, 205}, - {23, 0x02, 205}, - {40, 0x03, 205}, - {2, 0x02, 210}, - {9, 0x02, 210}, - {23, 0x02, 210}, - {40, 0x03, 210}, - {2, 0x02, 213}, - {9, 0x02, 213}, - {23, 0x02, 213}, - {40, 0x03, 213}, + {0x8002, 202}, + {0x8009, 202}, + {0x8017, 202}, + {0xc028, 202}, + {0x8002, 205}, + {0x8009, 205}, + {0x8017, 205}, + {0xc028, 205}, + {0x8002, 210}, + {0x8009, 210}, + {0x8017, 210}, + {0xc028, 210}, + {0x8002, 213}, + {0x8009, 213}, + {0x8017, 213}, + {0xc028, 213}, }, /* 197 */ { - {3, 0x02, 202}, - {6, 0x02, 202}, - {10, 0x02, 202}, - {15, 0x02, 202}, - {24, 0x02, 202}, - {31, 0x02, 202}, - {41, 0x02, 202}, - {56, 0x03, 202}, - {3, 0x02, 205}, - {6, 0x02, 205}, - {10, 0x02, 205}, - {15, 0x02, 205}, - {24, 0x02, 205}, - {31, 0x02, 205}, - {41, 0x02, 205}, - {56, 0x03, 205}, + {0x8003, 202}, + {0x8006, 202}, + {0x800a, 202}, + {0x800f, 202}, + {0x8018, 202}, + {0x801f, 202}, + {0x8029, 202}, + {0xc038, 202}, + {0x8003, 205}, + {0x8006, 205}, + {0x800a, 205}, + {0x800f, 205}, + {0x8018, 205}, + {0x801f, 205}, + {0x8029, 205}, + {0xc038, 205}, }, /* 198 */ { - {3, 0x02, 210}, - {6, 0x02, 210}, - {10, 0x02, 210}, - {15, 0x02, 210}, - {24, 0x02, 210}, - {31, 0x02, 210}, - {41, 0x02, 210}, - {56, 0x03, 210}, - {3, 0x02, 213}, - {6, 0x02, 213}, - {10, 0x02, 213}, - {15, 0x02, 213}, - {24, 0x02, 213}, - {31, 0x02, 213}, - {41, 0x02, 213}, - {56, 0x03, 213}, + {0x8003, 210}, + {0x8006, 210}, + {0x800a, 210}, + {0x800f, 210}, + {0x8018, 210}, + {0x801f, 210}, + {0x8029, 210}, + {0xc038, 210}, + {0x8003, 213}, + {0x8006, 213}, + {0x800a, 213}, + {0x800f, 213}, + {0x8018, 213}, + {0x801f, 213}, + {0x8029, 213}, + {0xc038, 213}, }, /* 199 */ { - {1, 0x02, 218}, - {22, 0x03, 218}, - {1, 0x02, 219}, - {22, 0x03, 219}, - {1, 0x02, 238}, - {22, 0x03, 238}, - {1, 0x02, 240}, - {22, 0x03, 240}, - {1, 0x02, 242}, - {22, 0x03, 242}, - {1, 0x02, 243}, - {22, 0x03, 243}, - {1, 0x02, 255}, - {22, 0x03, 255}, - {0, 0x03, 203}, - {0, 0x03, 204}, + {0x8001, 218}, + {0xc016, 218}, + {0x8001, 219}, + {0xc016, 219}, + {0x8001, 238}, + {0xc016, 238}, + {0x8001, 240}, + {0xc016, 240}, + {0x8001, 242}, + {0xc016, 242}, + {0x8001, 243}, + {0xc016, 243}, + {0x8001, 255}, + {0xc016, 255}, + {0xc000, 203}, + {0xc000, 204}, }, /* 200 */ { - {2, 0x02, 218}, - {9, 0x02, 218}, - {23, 0x02, 218}, - {40, 0x03, 218}, - {2, 0x02, 219}, - {9, 0x02, 219}, - {23, 0x02, 219}, - {40, 0x03, 219}, - {2, 0x02, 238}, - {9, 0x02, 238}, - {23, 0x02, 238}, - {40, 0x03, 238}, - {2, 0x02, 240}, - {9, 0x02, 240}, - {23, 0x02, 240}, - {40, 0x03, 240}, + {0x8002, 218}, + {0x8009, 218}, + {0x8017, 218}, + {0xc028, 218}, + {0x8002, 219}, + {0x8009, 219}, + {0x8017, 219}, + {0xc028, 219}, + {0x8002, 238}, + {0x8009, 238}, + {0x8017, 238}, + {0xc028, 238}, + {0x8002, 240}, + {0x8009, 240}, + {0x8017, 240}, + {0xc028, 240}, }, /* 201 */ { - {3, 0x02, 218}, - {6, 0x02, 218}, - {10, 0x02, 218}, - {15, 0x02, 218}, - {24, 0x02, 218}, - {31, 0x02, 218}, - {41, 0x02, 218}, - {56, 0x03, 218}, - {3, 0x02, 219}, - {6, 0x02, 219}, - {10, 0x02, 219}, - {15, 0x02, 219}, - {24, 0x02, 219}, - {31, 0x02, 219}, - {41, 0x02, 219}, - {56, 0x03, 219}, + {0x8003, 218}, + {0x8006, 218}, + {0x800a, 218}, + {0x800f, 218}, + {0x8018, 218}, + {0x801f, 218}, + {0x8029, 218}, + {0xc038, 218}, + {0x8003, 219}, + {0x8006, 219}, + {0x800a, 219}, + {0x800f, 219}, + {0x8018, 219}, + {0x801f, 219}, + {0x8029, 219}, + {0xc038, 219}, }, /* 202 */ { - {3, 0x02, 238}, - {6, 0x02, 238}, - {10, 0x02, 238}, - {15, 0x02, 238}, - {24, 0x02, 238}, - {31, 0x02, 238}, - {41, 0x02, 238}, - {56, 0x03, 238}, - {3, 0x02, 240}, - {6, 0x02, 240}, - {10, 0x02, 240}, - {15, 0x02, 240}, - {24, 0x02, 240}, - {31, 0x02, 240}, - {41, 0x02, 240}, - {56, 0x03, 240}, + {0x8003, 238}, + {0x8006, 238}, + {0x800a, 238}, + {0x800f, 238}, + {0x8018, 238}, + {0x801f, 238}, + {0x8029, 238}, + {0xc038, 238}, + {0x8003, 240}, + {0x8006, 240}, + {0x800a, 240}, + {0x800f, 240}, + {0x8018, 240}, + {0x801f, 240}, + {0x8029, 240}, + {0xc038, 240}, }, /* 203 */ { - {2, 0x02, 242}, - {9, 0x02, 242}, - {23, 0x02, 242}, - {40, 0x03, 242}, - {2, 0x02, 243}, - {9, 0x02, 243}, - {23, 0x02, 243}, - {40, 0x03, 243}, - {2, 0x02, 255}, - {9, 0x02, 255}, - {23, 0x02, 255}, - {40, 0x03, 255}, - {1, 0x02, 203}, - {22, 0x03, 203}, - {1, 0x02, 204}, - {22, 0x03, 204}, + {0x8002, 242}, + {0x8009, 242}, + {0x8017, 242}, + {0xc028, 242}, + {0x8002, 243}, + {0x8009, 243}, + {0x8017, 243}, + {0xc028, 243}, + {0x8002, 255}, + {0x8009, 255}, + {0x8017, 255}, + {0xc028, 255}, + {0x8001, 203}, + {0xc016, 203}, + {0x8001, 204}, + {0xc016, 204}, }, /* 204 */ { - {3, 0x02, 242}, - {6, 0x02, 242}, - {10, 0x02, 242}, - {15, 0x02, 242}, - {24, 0x02, 242}, - {31, 0x02, 242}, - {41, 0x02, 242}, - {56, 0x03, 242}, - {3, 0x02, 243}, - {6, 0x02, 243}, - {10, 0x02, 243}, - {15, 0x02, 243}, - {24, 0x02, 243}, - {31, 0x02, 243}, - {41, 0x02, 243}, - {56, 0x03, 243}, + {0x8003, 242}, + {0x8006, 242}, + {0x800a, 242}, + {0x800f, 242}, + {0x8018, 242}, + {0x801f, 242}, + {0x8029, 242}, + {0xc038, 242}, + {0x8003, 243}, + {0x8006, 243}, + {0x800a, 243}, + {0x800f, 243}, + {0x8018, 243}, + {0x801f, 243}, + {0x8029, 243}, + {0xc038, 243}, }, /* 205 */ { - {3, 0x02, 255}, - {6, 0x02, 255}, - {10, 0x02, 255}, - {15, 0x02, 255}, - {24, 0x02, 255}, - {31, 0x02, 255}, - {41, 0x02, 255}, - {56, 0x03, 255}, - {2, 0x02, 203}, - {9, 0x02, 203}, - {23, 0x02, 203}, - {40, 0x03, 203}, - {2, 0x02, 204}, - {9, 0x02, 204}, - {23, 0x02, 204}, - {40, 0x03, 204}, + {0x8003, 255}, + {0x8006, 255}, + {0x800a, 255}, + {0x800f, 255}, + {0x8018, 255}, + {0x801f, 255}, + {0x8029, 255}, + {0xc038, 255}, + {0x8002, 203}, + {0x8009, 203}, + {0x8017, 203}, + {0xc028, 203}, + {0x8002, 204}, + {0x8009, 204}, + {0x8017, 204}, + {0xc028, 204}, }, /* 206 */ { - {3, 0x02, 203}, - {6, 0x02, 203}, - {10, 0x02, 203}, - {15, 0x02, 203}, - {24, 0x02, 203}, - {31, 0x02, 203}, - {41, 0x02, 203}, - {56, 0x03, 203}, - {3, 0x02, 204}, - {6, 0x02, 204}, - {10, 0x02, 204}, - {15, 0x02, 204}, - {24, 0x02, 204}, - {31, 0x02, 204}, - {41, 0x02, 204}, - {56, 0x03, 204}, + {0x8003, 203}, + {0x8006, 203}, + {0x800a, 203}, + {0x800f, 203}, + {0x8018, 203}, + {0x801f, 203}, + {0x8029, 203}, + {0xc038, 203}, + {0x8003, 204}, + {0x8006, 204}, + {0x800a, 204}, + {0x800f, 204}, + {0x8018, 204}, + {0x801f, 204}, + {0x8029, 204}, + {0xc038, 204}, }, /* 207 */ { - {211, 0x00, 0}, - {212, 0x00, 0}, - {214, 0x00, 0}, - {215, 0x00, 0}, - {218, 0x00, 0}, - {219, 0x00, 0}, - {221, 0x00, 0}, - {222, 0x00, 0}, - {226, 0x00, 0}, - {228, 0x00, 0}, - {232, 0x00, 0}, - {235, 0x00, 0}, - {240, 0x00, 0}, - {243, 0x00, 0}, - {247, 0x00, 0}, - {250, 0x00, 0}, + {0xd3, 0}, + {0xd4, 0}, + {0xd6, 0}, + {0xd7, 0}, + {0xda, 0}, + {0xdb, 0}, + {0xdd, 0}, + {0xde, 0}, + {0xe2, 0}, + {0xe4, 0}, + {0xe8, 0}, + {0xeb, 0}, + {0xf0, 0}, + {0xf3, 0}, + {0xf7, 0}, + {0xfa, 0}, }, /* 208 */ { - {0, 0x03, 211}, - {0, 0x03, 212}, - {0, 0x03, 214}, - {0, 0x03, 221}, - {0, 0x03, 222}, - {0, 0x03, 223}, - {0, 0x03, 241}, - {0, 0x03, 244}, - {0, 0x03, 245}, - {0, 0x03, 246}, - {0, 0x03, 247}, - {0, 0x03, 248}, - {0, 0x03, 250}, - {0, 0x03, 251}, - {0, 0x03, 252}, - {0, 0x03, 253}, + {0xc000, 211}, + {0xc000, 212}, + {0xc000, 214}, + {0xc000, 221}, + {0xc000, 222}, + {0xc000, 223}, + {0xc000, 241}, + {0xc000, 244}, + {0xc000, 245}, + {0xc000, 246}, + {0xc000, 247}, + {0xc000, 248}, + {0xc000, 250}, + {0xc000, 251}, + {0xc000, 252}, + {0xc000, 253}, }, /* 209 */ { - {1, 0x02, 211}, - {22, 0x03, 211}, - {1, 0x02, 212}, - {22, 0x03, 212}, - {1, 0x02, 214}, - {22, 0x03, 214}, - {1, 0x02, 221}, - {22, 0x03, 221}, - {1, 0x02, 222}, - {22, 0x03, 222}, - {1, 0x02, 223}, - {22, 0x03, 223}, - {1, 0x02, 241}, - {22, 0x03, 241}, - {1, 0x02, 244}, - {22, 0x03, 244}, + {0x8001, 211}, + {0xc016, 211}, + {0x8001, 212}, + {0xc016, 212}, + {0x8001, 214}, + {0xc016, 214}, + {0x8001, 221}, + {0xc016, 221}, + {0x8001, 222}, + {0xc016, 222}, + {0x8001, 223}, + {0xc016, 223}, + {0x8001, 241}, + {0xc016, 241}, + {0x8001, 244}, + {0xc016, 244}, }, /* 210 */ { - {2, 0x02, 211}, - {9, 0x02, 211}, - {23, 0x02, 211}, - {40, 0x03, 211}, - {2, 0x02, 212}, - {9, 0x02, 212}, - {23, 0x02, 212}, - {40, 0x03, 212}, - {2, 0x02, 214}, - {9, 0x02, 214}, - {23, 0x02, 214}, - {40, 0x03, 214}, - {2, 0x02, 221}, - {9, 0x02, 221}, - {23, 0x02, 221}, - {40, 0x03, 221}, + {0x8002, 211}, + {0x8009, 211}, + {0x8017, 211}, + {0xc028, 211}, + {0x8002, 212}, + {0x8009, 212}, + {0x8017, 212}, + {0xc028, 212}, + {0x8002, 214}, + {0x8009, 214}, + {0x8017, 214}, + {0xc028, 214}, + {0x8002, 221}, + {0x8009, 221}, + {0x8017, 221}, + {0xc028, 221}, }, /* 211 */ { - {3, 0x02, 211}, - {6, 0x02, 211}, - {10, 0x02, 211}, - {15, 0x02, 211}, - {24, 0x02, 211}, - {31, 0x02, 211}, - {41, 0x02, 211}, - {56, 0x03, 211}, - {3, 0x02, 212}, - {6, 0x02, 212}, - {10, 0x02, 212}, - {15, 0x02, 212}, - {24, 0x02, 212}, - {31, 0x02, 212}, - {41, 0x02, 212}, - {56, 0x03, 212}, + {0x8003, 211}, + {0x8006, 211}, + {0x800a, 211}, + {0x800f, 211}, + {0x8018, 211}, + {0x801f, 211}, + {0x8029, 211}, + {0xc038, 211}, + {0x8003, 212}, + {0x8006, 212}, + {0x800a, 212}, + {0x800f, 212}, + {0x8018, 212}, + {0x801f, 212}, + {0x8029, 212}, + {0xc038, 212}, }, /* 212 */ { - {3, 0x02, 214}, - {6, 0x02, 214}, - {10, 0x02, 214}, - {15, 0x02, 214}, - {24, 0x02, 214}, - {31, 0x02, 214}, - {41, 0x02, 214}, - {56, 0x03, 214}, - {3, 0x02, 221}, - {6, 0x02, 221}, - {10, 0x02, 221}, - {15, 0x02, 221}, - {24, 0x02, 221}, - {31, 0x02, 221}, - {41, 0x02, 221}, - {56, 0x03, 221}, + {0x8003, 214}, + {0x8006, 214}, + {0x800a, 214}, + {0x800f, 214}, + {0x8018, 214}, + {0x801f, 214}, + {0x8029, 214}, + {0xc038, 214}, + {0x8003, 221}, + {0x8006, 221}, + {0x800a, 221}, + {0x800f, 221}, + {0x8018, 221}, + {0x801f, 221}, + {0x8029, 221}, + {0xc038, 221}, }, /* 213 */ { - {2, 0x02, 222}, - {9, 0x02, 222}, - {23, 0x02, 222}, - {40, 0x03, 222}, - {2, 0x02, 223}, - {9, 0x02, 223}, - {23, 0x02, 223}, - {40, 0x03, 223}, - {2, 0x02, 241}, - {9, 0x02, 241}, - {23, 0x02, 241}, - {40, 0x03, 241}, - {2, 0x02, 244}, - {9, 0x02, 244}, - {23, 0x02, 244}, - {40, 0x03, 244}, + {0x8002, 222}, + {0x8009, 222}, + {0x8017, 222}, + {0xc028, 222}, + {0x8002, 223}, + {0x8009, 223}, + {0x8017, 223}, + {0xc028, 223}, + {0x8002, 241}, + {0x8009, 241}, + {0x8017, 241}, + {0xc028, 241}, + {0x8002, 244}, + {0x8009, 244}, + {0x8017, 244}, + {0xc028, 244}, }, /* 214 */ { - {3, 0x02, 222}, - {6, 0x02, 222}, - {10, 0x02, 222}, - {15, 0x02, 222}, - {24, 0x02, 222}, - {31, 0x02, 222}, - {41, 0x02, 222}, - {56, 0x03, 222}, - {3, 0x02, 223}, - {6, 0x02, 223}, - {10, 0x02, 223}, - {15, 0x02, 223}, - {24, 0x02, 223}, - {31, 0x02, 223}, - {41, 0x02, 223}, - {56, 0x03, 223}, + {0x8003, 222}, + {0x8006, 222}, + {0x800a, 222}, + {0x800f, 222}, + {0x8018, 222}, + {0x801f, 222}, + {0x8029, 222}, + {0xc038, 222}, + {0x8003, 223}, + {0x8006, 223}, + {0x800a, 223}, + {0x800f, 223}, + {0x8018, 223}, + {0x801f, 223}, + {0x8029, 223}, + {0xc038, 223}, }, /* 215 */ { - {3, 0x02, 241}, - {6, 0x02, 241}, - {10, 0x02, 241}, - {15, 0x02, 241}, - {24, 0x02, 241}, - {31, 0x02, 241}, - {41, 0x02, 241}, - {56, 0x03, 241}, - {3, 0x02, 244}, - {6, 0x02, 244}, - {10, 0x02, 244}, - {15, 0x02, 244}, - {24, 0x02, 244}, - {31, 0x02, 244}, - {41, 0x02, 244}, - {56, 0x03, 244}, + {0x8003, 241}, + {0x8006, 241}, + {0x800a, 241}, + {0x800f, 241}, + {0x8018, 241}, + {0x801f, 241}, + {0x8029, 241}, + {0xc038, 241}, + {0x8003, 244}, + {0x8006, 244}, + {0x800a, 244}, + {0x800f, 244}, + {0x8018, 244}, + {0x801f, 244}, + {0x8029, 244}, + {0xc038, 244}, }, /* 216 */ { - {1, 0x02, 245}, - {22, 0x03, 245}, - {1, 0x02, 246}, - {22, 0x03, 246}, - {1, 0x02, 247}, - {22, 0x03, 247}, - {1, 0x02, 248}, - {22, 0x03, 248}, - {1, 0x02, 250}, - {22, 0x03, 250}, - {1, 0x02, 251}, - {22, 0x03, 251}, - {1, 0x02, 252}, - {22, 0x03, 252}, - {1, 0x02, 253}, - {22, 0x03, 253}, + {0x8001, 245}, + {0xc016, 245}, + {0x8001, 246}, + {0xc016, 246}, + {0x8001, 247}, + {0xc016, 247}, + {0x8001, 248}, + {0xc016, 248}, + {0x8001, 250}, + {0xc016, 250}, + {0x8001, 251}, + {0xc016, 251}, + {0x8001, 252}, + {0xc016, 252}, + {0x8001, 253}, + {0xc016, 253}, }, /* 217 */ { - {2, 0x02, 245}, - {9, 0x02, 245}, - {23, 0x02, 245}, - {40, 0x03, 245}, - {2, 0x02, 246}, - {9, 0x02, 246}, - {23, 0x02, 246}, - {40, 0x03, 246}, - {2, 0x02, 247}, - {9, 0x02, 247}, - {23, 0x02, 247}, - {40, 0x03, 247}, - {2, 0x02, 248}, - {9, 0x02, 248}, - {23, 0x02, 248}, - {40, 0x03, 248}, + {0x8002, 245}, + {0x8009, 245}, + {0x8017, 245}, + {0xc028, 245}, + {0x8002, 246}, + {0x8009, 246}, + {0x8017, 246}, + {0xc028, 246}, + {0x8002, 247}, + {0x8009, 247}, + {0x8017, 247}, + {0xc028, 247}, + {0x8002, 248}, + {0x8009, 248}, + {0x8017, 248}, + {0xc028, 248}, }, /* 218 */ { - {3, 0x02, 245}, - {6, 0x02, 245}, - {10, 0x02, 245}, - {15, 0x02, 245}, - {24, 0x02, 245}, - {31, 0x02, 245}, - {41, 0x02, 245}, - {56, 0x03, 245}, - {3, 0x02, 246}, - {6, 0x02, 246}, - {10, 0x02, 246}, - {15, 0x02, 246}, - {24, 0x02, 246}, - {31, 0x02, 246}, - {41, 0x02, 246}, - {56, 0x03, 246}, + {0x8003, 245}, + {0x8006, 245}, + {0x800a, 245}, + {0x800f, 245}, + {0x8018, 245}, + {0x801f, 245}, + {0x8029, 245}, + {0xc038, 245}, + {0x8003, 246}, + {0x8006, 246}, + {0x800a, 246}, + {0x800f, 246}, + {0x8018, 246}, + {0x801f, 246}, + {0x8029, 246}, + {0xc038, 246}, }, /* 219 */ { - {3, 0x02, 247}, - {6, 0x02, 247}, - {10, 0x02, 247}, - {15, 0x02, 247}, - {24, 0x02, 247}, - {31, 0x02, 247}, - {41, 0x02, 247}, - {56, 0x03, 247}, - {3, 0x02, 248}, - {6, 0x02, 248}, - {10, 0x02, 248}, - {15, 0x02, 248}, - {24, 0x02, 248}, - {31, 0x02, 248}, - {41, 0x02, 248}, - {56, 0x03, 248}, + {0x8003, 247}, + {0x8006, 247}, + {0x800a, 247}, + {0x800f, 247}, + {0x8018, 247}, + {0x801f, 247}, + {0x8029, 247}, + {0xc038, 247}, + {0x8003, 248}, + {0x8006, 248}, + {0x800a, 248}, + {0x800f, 248}, + {0x8018, 248}, + {0x801f, 248}, + {0x8029, 248}, + {0xc038, 248}, }, /* 220 */ { - {2, 0x02, 250}, - {9, 0x02, 250}, - {23, 0x02, 250}, - {40, 0x03, 250}, - {2, 0x02, 251}, - {9, 0x02, 251}, - {23, 0x02, 251}, - {40, 0x03, 251}, - {2, 0x02, 252}, - {9, 0x02, 252}, - {23, 0x02, 252}, - {40, 0x03, 252}, - {2, 0x02, 253}, - {9, 0x02, 253}, - {23, 0x02, 253}, - {40, 0x03, 253}, + {0x8002, 250}, + {0x8009, 250}, + {0x8017, 250}, + {0xc028, 250}, + {0x8002, 251}, + {0x8009, 251}, + {0x8017, 251}, + {0xc028, 251}, + {0x8002, 252}, + {0x8009, 252}, + {0x8017, 252}, + {0xc028, 252}, + {0x8002, 253}, + {0x8009, 253}, + {0x8017, 253}, + {0xc028, 253}, }, /* 221 */ { - {3, 0x02, 250}, - {6, 0x02, 250}, - {10, 0x02, 250}, - {15, 0x02, 250}, - {24, 0x02, 250}, - {31, 0x02, 250}, - {41, 0x02, 250}, - {56, 0x03, 250}, - {3, 0x02, 251}, - {6, 0x02, 251}, - {10, 0x02, 251}, - {15, 0x02, 251}, - {24, 0x02, 251}, - {31, 0x02, 251}, - {41, 0x02, 251}, - {56, 0x03, 251}, + {0x8003, 250}, + {0x8006, 250}, + {0x800a, 250}, + {0x800f, 250}, + {0x8018, 250}, + {0x801f, 250}, + {0x8029, 250}, + {0xc038, 250}, + {0x8003, 251}, + {0x8006, 251}, + {0x800a, 251}, + {0x800f, 251}, + {0x8018, 251}, + {0x801f, 251}, + {0x8029, 251}, + {0xc038, 251}, }, /* 222 */ { - {3, 0x02, 252}, - {6, 0x02, 252}, - {10, 0x02, 252}, - {15, 0x02, 252}, - {24, 0x02, 252}, - {31, 0x02, 252}, - {41, 0x02, 252}, - {56, 0x03, 252}, - {3, 0x02, 253}, - {6, 0x02, 253}, - {10, 0x02, 253}, - {15, 0x02, 253}, - {24, 0x02, 253}, - {31, 0x02, 253}, - {41, 0x02, 253}, - {56, 0x03, 253}, + {0x8003, 252}, + {0x8006, 252}, + {0x800a, 252}, + {0x800f, 252}, + {0x8018, 252}, + {0x801f, 252}, + {0x8029, 252}, + {0xc038, 252}, + {0x8003, 253}, + {0x8006, 253}, + {0x800a, 253}, + {0x800f, 253}, + {0x8018, 253}, + {0x801f, 253}, + {0x8029, 253}, + {0xc038, 253}, }, /* 223 */ { - {0, 0x03, 254}, - {227, 0x00, 0}, - {229, 0x00, 0}, - {230, 0x00, 0}, - {233, 0x00, 0}, - {234, 0x00, 0}, - {236, 0x00, 0}, - {237, 0x00, 0}, - {241, 0x00, 0}, - {242, 0x00, 0}, - {244, 0x00, 0}, - {245, 0x00, 0}, - {248, 0x00, 0}, - {249, 0x00, 0}, - {251, 0x00, 0}, - {252, 0x00, 0}, + {0xc000, 254}, + {0xe3, 0}, + {0xe5, 0}, + {0xe6, 0}, + {0xe9, 0}, + {0xea, 0}, + {0xec, 0}, + {0xed, 0}, + {0xf1, 0}, + {0xf2, 0}, + {0xf4, 0}, + {0xf5, 0}, + {0xf8, 0}, + {0xf9, 0}, + {0xfb, 0}, + {0xfc, 0}, }, /* 224 */ { - {1, 0x02, 254}, - {22, 0x03, 254}, - {0, 0x03, 2}, - {0, 0x03, 3}, - {0, 0x03, 4}, - {0, 0x03, 5}, - {0, 0x03, 6}, - {0, 0x03, 7}, - {0, 0x03, 8}, - {0, 0x03, 11}, - {0, 0x03, 12}, - {0, 0x03, 14}, - {0, 0x03, 15}, - {0, 0x03, 16}, - {0, 0x03, 17}, - {0, 0x03, 18}, + {0x8001, 254}, + {0xc016, 254}, + {0xc000, 2}, + {0xc000, 3}, + {0xc000, 4}, + {0xc000, 5}, + {0xc000, 6}, + {0xc000, 7}, + {0xc000, 8}, + {0xc000, 11}, + {0xc000, 12}, + {0xc000, 14}, + {0xc000, 15}, + {0xc000, 16}, + {0xc000, 17}, + {0xc000, 18}, }, /* 225 */ { - {2, 0x02, 254}, - {9, 0x02, 254}, - {23, 0x02, 254}, - {40, 0x03, 254}, - {1, 0x02, 2}, - {22, 0x03, 2}, - {1, 0x02, 3}, - {22, 0x03, 3}, - {1, 0x02, 4}, - {22, 0x03, 4}, - {1, 0x02, 5}, - {22, 0x03, 5}, - {1, 0x02, 6}, - {22, 0x03, 6}, - {1, 0x02, 7}, - {22, 0x03, 7}, + {0x8002, 254}, + {0x8009, 254}, + {0x8017, 254}, + {0xc028, 254}, + {0x8001, 2}, + {0xc016, 2}, + {0x8001, 3}, + {0xc016, 3}, + {0x8001, 4}, + {0xc016, 4}, + {0x8001, 5}, + {0xc016, 5}, + {0x8001, 6}, + {0xc016, 6}, + {0x8001, 7}, + {0xc016, 7}, }, /* 226 */ { - {3, 0x02, 254}, - {6, 0x02, 254}, - {10, 0x02, 254}, - {15, 0x02, 254}, - {24, 0x02, 254}, - {31, 0x02, 254}, - {41, 0x02, 254}, - {56, 0x03, 254}, - {2, 0x02, 2}, - {9, 0x02, 2}, - {23, 0x02, 2}, - {40, 0x03, 2}, - {2, 0x02, 3}, - {9, 0x02, 3}, - {23, 0x02, 3}, - {40, 0x03, 3}, + {0x8003, 254}, + {0x8006, 254}, + {0x800a, 254}, + {0x800f, 254}, + {0x8018, 254}, + {0x801f, 254}, + {0x8029, 254}, + {0xc038, 254}, + {0x8002, 2}, + {0x8009, 2}, + {0x8017, 2}, + {0xc028, 2}, + {0x8002, 3}, + {0x8009, 3}, + {0x8017, 3}, + {0xc028, 3}, }, /* 227 */ { - {3, 0x02, 2}, - {6, 0x02, 2}, - {10, 0x02, 2}, - {15, 0x02, 2}, - {24, 0x02, 2}, - {31, 0x02, 2}, - {41, 0x02, 2}, - {56, 0x03, 2}, - {3, 0x02, 3}, - {6, 0x02, 3}, - {10, 0x02, 3}, - {15, 0x02, 3}, - {24, 0x02, 3}, - {31, 0x02, 3}, - {41, 0x02, 3}, - {56, 0x03, 3}, + {0x8003, 2}, + {0x8006, 2}, + {0x800a, 2}, + {0x800f, 2}, + {0x8018, 2}, + {0x801f, 2}, + {0x8029, 2}, + {0xc038, 2}, + {0x8003, 3}, + {0x8006, 3}, + {0x800a, 3}, + {0x800f, 3}, + {0x8018, 3}, + {0x801f, 3}, + {0x8029, 3}, + {0xc038, 3}, }, /* 228 */ { - {2, 0x02, 4}, - {9, 0x02, 4}, - {23, 0x02, 4}, - {40, 0x03, 4}, - {2, 0x02, 5}, - {9, 0x02, 5}, - {23, 0x02, 5}, - {40, 0x03, 5}, - {2, 0x02, 6}, - {9, 0x02, 6}, - {23, 0x02, 6}, - {40, 0x03, 6}, - {2, 0x02, 7}, - {9, 0x02, 7}, - {23, 0x02, 7}, - {40, 0x03, 7}, + {0x8002, 4}, + {0x8009, 4}, + {0x8017, 4}, + {0xc028, 4}, + {0x8002, 5}, + {0x8009, 5}, + {0x8017, 5}, + {0xc028, 5}, + {0x8002, 6}, + {0x8009, 6}, + {0x8017, 6}, + {0xc028, 6}, + {0x8002, 7}, + {0x8009, 7}, + {0x8017, 7}, + {0xc028, 7}, }, /* 229 */ { - {3, 0x02, 4}, - {6, 0x02, 4}, - {10, 0x02, 4}, - {15, 0x02, 4}, - {24, 0x02, 4}, - {31, 0x02, 4}, - {41, 0x02, 4}, - {56, 0x03, 4}, - {3, 0x02, 5}, - {6, 0x02, 5}, - {10, 0x02, 5}, - {15, 0x02, 5}, - {24, 0x02, 5}, - {31, 0x02, 5}, - {41, 0x02, 5}, - {56, 0x03, 5}, + {0x8003, 4}, + {0x8006, 4}, + {0x800a, 4}, + {0x800f, 4}, + {0x8018, 4}, + {0x801f, 4}, + {0x8029, 4}, + {0xc038, 4}, + {0x8003, 5}, + {0x8006, 5}, + {0x800a, 5}, + {0x800f, 5}, + {0x8018, 5}, + {0x801f, 5}, + {0x8029, 5}, + {0xc038, 5}, }, /* 230 */ { - {3, 0x02, 6}, - {6, 0x02, 6}, - {10, 0x02, 6}, - {15, 0x02, 6}, - {24, 0x02, 6}, - {31, 0x02, 6}, - {41, 0x02, 6}, - {56, 0x03, 6}, - {3, 0x02, 7}, - {6, 0x02, 7}, - {10, 0x02, 7}, - {15, 0x02, 7}, - {24, 0x02, 7}, - {31, 0x02, 7}, - {41, 0x02, 7}, - {56, 0x03, 7}, + {0x8003, 6}, + {0x8006, 6}, + {0x800a, 6}, + {0x800f, 6}, + {0x8018, 6}, + {0x801f, 6}, + {0x8029, 6}, + {0xc038, 6}, + {0x8003, 7}, + {0x8006, 7}, + {0x800a, 7}, + {0x800f, 7}, + {0x8018, 7}, + {0x801f, 7}, + {0x8029, 7}, + {0xc038, 7}, }, /* 231 */ { - {1, 0x02, 8}, - {22, 0x03, 8}, - {1, 0x02, 11}, - {22, 0x03, 11}, - {1, 0x02, 12}, - {22, 0x03, 12}, - {1, 0x02, 14}, - {22, 0x03, 14}, - {1, 0x02, 15}, - {22, 0x03, 15}, - {1, 0x02, 16}, - {22, 0x03, 16}, - {1, 0x02, 17}, - {22, 0x03, 17}, - {1, 0x02, 18}, - {22, 0x03, 18}, + {0x8001, 8}, + {0xc016, 8}, + {0x8001, 11}, + {0xc016, 11}, + {0x8001, 12}, + {0xc016, 12}, + {0x8001, 14}, + {0xc016, 14}, + {0x8001, 15}, + {0xc016, 15}, + {0x8001, 16}, + {0xc016, 16}, + {0x8001, 17}, + {0xc016, 17}, + {0x8001, 18}, + {0xc016, 18}, }, /* 232 */ { - {2, 0x02, 8}, - {9, 0x02, 8}, - {23, 0x02, 8}, - {40, 0x03, 8}, - {2, 0x02, 11}, - {9, 0x02, 11}, - {23, 0x02, 11}, - {40, 0x03, 11}, - {2, 0x02, 12}, - {9, 0x02, 12}, - {23, 0x02, 12}, - {40, 0x03, 12}, - {2, 0x02, 14}, - {9, 0x02, 14}, - {23, 0x02, 14}, - {40, 0x03, 14}, + {0x8002, 8}, + {0x8009, 8}, + {0x8017, 8}, + {0xc028, 8}, + {0x8002, 11}, + {0x8009, 11}, + {0x8017, 11}, + {0xc028, 11}, + {0x8002, 12}, + {0x8009, 12}, + {0x8017, 12}, + {0xc028, 12}, + {0x8002, 14}, + {0x8009, 14}, + {0x8017, 14}, + {0xc028, 14}, }, /* 233 */ { - {3, 0x02, 8}, - {6, 0x02, 8}, - {10, 0x02, 8}, - {15, 0x02, 8}, - {24, 0x02, 8}, - {31, 0x02, 8}, - {41, 0x02, 8}, - {56, 0x03, 8}, - {3, 0x02, 11}, - {6, 0x02, 11}, - {10, 0x02, 11}, - {15, 0x02, 11}, - {24, 0x02, 11}, - {31, 0x02, 11}, - {41, 0x02, 11}, - {56, 0x03, 11}, + {0x8003, 8}, + {0x8006, 8}, + {0x800a, 8}, + {0x800f, 8}, + {0x8018, 8}, + {0x801f, 8}, + {0x8029, 8}, + {0xc038, 8}, + {0x8003, 11}, + {0x8006, 11}, + {0x800a, 11}, + {0x800f, 11}, + {0x8018, 11}, + {0x801f, 11}, + {0x8029, 11}, + {0xc038, 11}, }, /* 234 */ { - {3, 0x02, 12}, - {6, 0x02, 12}, - {10, 0x02, 12}, - {15, 0x02, 12}, - {24, 0x02, 12}, - {31, 0x02, 12}, - {41, 0x02, 12}, - {56, 0x03, 12}, - {3, 0x02, 14}, - {6, 0x02, 14}, - {10, 0x02, 14}, - {15, 0x02, 14}, - {24, 0x02, 14}, - {31, 0x02, 14}, - {41, 0x02, 14}, - {56, 0x03, 14}, + {0x8003, 12}, + {0x8006, 12}, + {0x800a, 12}, + {0x800f, 12}, + {0x8018, 12}, + {0x801f, 12}, + {0x8029, 12}, + {0xc038, 12}, + {0x8003, 14}, + {0x8006, 14}, + {0x800a, 14}, + {0x800f, 14}, + {0x8018, 14}, + {0x801f, 14}, + {0x8029, 14}, + {0xc038, 14}, }, /* 235 */ { - {2, 0x02, 15}, - {9, 0x02, 15}, - {23, 0x02, 15}, - {40, 0x03, 15}, - {2, 0x02, 16}, - {9, 0x02, 16}, - {23, 0x02, 16}, - {40, 0x03, 16}, - {2, 0x02, 17}, - {9, 0x02, 17}, - {23, 0x02, 17}, - {40, 0x03, 17}, - {2, 0x02, 18}, - {9, 0x02, 18}, - {23, 0x02, 18}, - {40, 0x03, 18}, + {0x8002, 15}, + {0x8009, 15}, + {0x8017, 15}, + {0xc028, 15}, + {0x8002, 16}, + {0x8009, 16}, + {0x8017, 16}, + {0xc028, 16}, + {0x8002, 17}, + {0x8009, 17}, + {0x8017, 17}, + {0xc028, 17}, + {0x8002, 18}, + {0x8009, 18}, + {0x8017, 18}, + {0xc028, 18}, }, /* 236 */ { - {3, 0x02, 15}, - {6, 0x02, 15}, - {10, 0x02, 15}, - {15, 0x02, 15}, - {24, 0x02, 15}, - {31, 0x02, 15}, - {41, 0x02, 15}, - {56, 0x03, 15}, - {3, 0x02, 16}, - {6, 0x02, 16}, - {10, 0x02, 16}, - {15, 0x02, 16}, - {24, 0x02, 16}, - {31, 0x02, 16}, - {41, 0x02, 16}, - {56, 0x03, 16}, + {0x8003, 15}, + {0x8006, 15}, + {0x800a, 15}, + {0x800f, 15}, + {0x8018, 15}, + {0x801f, 15}, + {0x8029, 15}, + {0xc038, 15}, + {0x8003, 16}, + {0x8006, 16}, + {0x800a, 16}, + {0x800f, 16}, + {0x8018, 16}, + {0x801f, 16}, + {0x8029, 16}, + {0xc038, 16}, }, /* 237 */ { - {3, 0x02, 17}, - {6, 0x02, 17}, - {10, 0x02, 17}, - {15, 0x02, 17}, - {24, 0x02, 17}, - {31, 0x02, 17}, - {41, 0x02, 17}, - {56, 0x03, 17}, - {3, 0x02, 18}, - {6, 0x02, 18}, - {10, 0x02, 18}, - {15, 0x02, 18}, - {24, 0x02, 18}, - {31, 0x02, 18}, - {41, 0x02, 18}, - {56, 0x03, 18}, + {0x8003, 17}, + {0x8006, 17}, + {0x800a, 17}, + {0x800f, 17}, + {0x8018, 17}, + {0x801f, 17}, + {0x8029, 17}, + {0xc038, 17}, + {0x8003, 18}, + {0x8006, 18}, + {0x800a, 18}, + {0x800f, 18}, + {0x8018, 18}, + {0x801f, 18}, + {0x8029, 18}, + {0xc038, 18}, }, /* 238 */ { - {0, 0x03, 19}, - {0, 0x03, 20}, - {0, 0x03, 21}, - {0, 0x03, 23}, - {0, 0x03, 24}, - {0, 0x03, 25}, - {0, 0x03, 26}, - {0, 0x03, 27}, - {0, 0x03, 28}, - {0, 0x03, 29}, - {0, 0x03, 30}, - {0, 0x03, 31}, - {0, 0x03, 127}, - {0, 0x03, 220}, - {0, 0x03, 249}, - {253, 0x00, 0}, + {0xc000, 19}, + {0xc000, 20}, + {0xc000, 21}, + {0xc000, 23}, + {0xc000, 24}, + {0xc000, 25}, + {0xc000, 26}, + {0xc000, 27}, + {0xc000, 28}, + {0xc000, 29}, + {0xc000, 30}, + {0xc000, 31}, + {0xc000, 127}, + {0xc000, 220}, + {0xc000, 249}, + {0xfd, 0}, }, /* 239 */ { - {1, 0x02, 19}, - {22, 0x03, 19}, - {1, 0x02, 20}, - {22, 0x03, 20}, - {1, 0x02, 21}, - {22, 0x03, 21}, - {1, 0x02, 23}, - {22, 0x03, 23}, - {1, 0x02, 24}, - {22, 0x03, 24}, - {1, 0x02, 25}, - {22, 0x03, 25}, - {1, 0x02, 26}, - {22, 0x03, 26}, - {1, 0x02, 27}, - {22, 0x03, 27}, + {0x8001, 19}, + {0xc016, 19}, + {0x8001, 20}, + {0xc016, 20}, + {0x8001, 21}, + {0xc016, 21}, + {0x8001, 23}, + {0xc016, 23}, + {0x8001, 24}, + {0xc016, 24}, + {0x8001, 25}, + {0xc016, 25}, + {0x8001, 26}, + {0xc016, 26}, + {0x8001, 27}, + {0xc016, 27}, }, /* 240 */ { - {2, 0x02, 19}, - {9, 0x02, 19}, - {23, 0x02, 19}, - {40, 0x03, 19}, - {2, 0x02, 20}, - {9, 0x02, 20}, - {23, 0x02, 20}, - {40, 0x03, 20}, - {2, 0x02, 21}, - {9, 0x02, 21}, - {23, 0x02, 21}, - {40, 0x03, 21}, - {2, 0x02, 23}, - {9, 0x02, 23}, - {23, 0x02, 23}, - {40, 0x03, 23}, + {0x8002, 19}, + {0x8009, 19}, + {0x8017, 19}, + {0xc028, 19}, + {0x8002, 20}, + {0x8009, 20}, + {0x8017, 20}, + {0xc028, 20}, + {0x8002, 21}, + {0x8009, 21}, + {0x8017, 21}, + {0xc028, 21}, + {0x8002, 23}, + {0x8009, 23}, + {0x8017, 23}, + {0xc028, 23}, }, /* 241 */ { - {3, 0x02, 19}, - {6, 0x02, 19}, - {10, 0x02, 19}, - {15, 0x02, 19}, - {24, 0x02, 19}, - {31, 0x02, 19}, - {41, 0x02, 19}, - {56, 0x03, 19}, - {3, 0x02, 20}, - {6, 0x02, 20}, - {10, 0x02, 20}, - {15, 0x02, 20}, - {24, 0x02, 20}, - {31, 0x02, 20}, - {41, 0x02, 20}, - {56, 0x03, 20}, + {0x8003, 19}, + {0x8006, 19}, + {0x800a, 19}, + {0x800f, 19}, + {0x8018, 19}, + {0x801f, 19}, + {0x8029, 19}, + {0xc038, 19}, + {0x8003, 20}, + {0x8006, 20}, + {0x800a, 20}, + {0x800f, 20}, + {0x8018, 20}, + {0x801f, 20}, + {0x8029, 20}, + {0xc038, 20}, }, /* 242 */ { - {3, 0x02, 21}, - {6, 0x02, 21}, - {10, 0x02, 21}, - {15, 0x02, 21}, - {24, 0x02, 21}, - {31, 0x02, 21}, - {41, 0x02, 21}, - {56, 0x03, 21}, - {3, 0x02, 23}, - {6, 0x02, 23}, - {10, 0x02, 23}, - {15, 0x02, 23}, - {24, 0x02, 23}, - {31, 0x02, 23}, - {41, 0x02, 23}, - {56, 0x03, 23}, + {0x8003, 21}, + {0x8006, 21}, + {0x800a, 21}, + {0x800f, 21}, + {0x8018, 21}, + {0x801f, 21}, + {0x8029, 21}, + {0xc038, 21}, + {0x8003, 23}, + {0x8006, 23}, + {0x800a, 23}, + {0x800f, 23}, + {0x8018, 23}, + {0x801f, 23}, + {0x8029, 23}, + {0xc038, 23}, }, /* 243 */ { - {2, 0x02, 24}, - {9, 0x02, 24}, - {23, 0x02, 24}, - {40, 0x03, 24}, - {2, 0x02, 25}, - {9, 0x02, 25}, - {23, 0x02, 25}, - {40, 0x03, 25}, - {2, 0x02, 26}, - {9, 0x02, 26}, - {23, 0x02, 26}, - {40, 0x03, 26}, - {2, 0x02, 27}, - {9, 0x02, 27}, - {23, 0x02, 27}, - {40, 0x03, 27}, + {0x8002, 24}, + {0x8009, 24}, + {0x8017, 24}, + {0xc028, 24}, + {0x8002, 25}, + {0x8009, 25}, + {0x8017, 25}, + {0xc028, 25}, + {0x8002, 26}, + {0x8009, 26}, + {0x8017, 26}, + {0xc028, 26}, + {0x8002, 27}, + {0x8009, 27}, + {0x8017, 27}, + {0xc028, 27}, }, /* 244 */ { - {3, 0x02, 24}, - {6, 0x02, 24}, - {10, 0x02, 24}, - {15, 0x02, 24}, - {24, 0x02, 24}, - {31, 0x02, 24}, - {41, 0x02, 24}, - {56, 0x03, 24}, - {3, 0x02, 25}, - {6, 0x02, 25}, - {10, 0x02, 25}, - {15, 0x02, 25}, - {24, 0x02, 25}, - {31, 0x02, 25}, - {41, 0x02, 25}, - {56, 0x03, 25}, + {0x8003, 24}, + {0x8006, 24}, + {0x800a, 24}, + {0x800f, 24}, + {0x8018, 24}, + {0x801f, 24}, + {0x8029, 24}, + {0xc038, 24}, + {0x8003, 25}, + {0x8006, 25}, + {0x800a, 25}, + {0x800f, 25}, + {0x8018, 25}, + {0x801f, 25}, + {0x8029, 25}, + {0xc038, 25}, }, /* 245 */ { - {3, 0x02, 26}, - {6, 0x02, 26}, - {10, 0x02, 26}, - {15, 0x02, 26}, - {24, 0x02, 26}, - {31, 0x02, 26}, - {41, 0x02, 26}, - {56, 0x03, 26}, - {3, 0x02, 27}, - {6, 0x02, 27}, - {10, 0x02, 27}, - {15, 0x02, 27}, - {24, 0x02, 27}, - {31, 0x02, 27}, - {41, 0x02, 27}, - {56, 0x03, 27}, + {0x8003, 26}, + {0x8006, 26}, + {0x800a, 26}, + {0x800f, 26}, + {0x8018, 26}, + {0x801f, 26}, + {0x8029, 26}, + {0xc038, 26}, + {0x8003, 27}, + {0x8006, 27}, + {0x800a, 27}, + {0x800f, 27}, + {0x8018, 27}, + {0x801f, 27}, + {0x8029, 27}, + {0xc038, 27}, }, /* 246 */ { - {1, 0x02, 28}, - {22, 0x03, 28}, - {1, 0x02, 29}, - {22, 0x03, 29}, - {1, 0x02, 30}, - {22, 0x03, 30}, - {1, 0x02, 31}, - {22, 0x03, 31}, - {1, 0x02, 127}, - {22, 0x03, 127}, - {1, 0x02, 220}, - {22, 0x03, 220}, - {1, 0x02, 249}, - {22, 0x03, 249}, - {254, 0x00, 0}, - {255, 0x00, 0}, + {0x8001, 28}, + {0xc016, 28}, + {0x8001, 29}, + {0xc016, 29}, + {0x8001, 30}, + {0xc016, 30}, + {0x8001, 31}, + {0xc016, 31}, + {0x8001, 127}, + {0xc016, 127}, + {0x8001, 220}, + {0xc016, 220}, + {0x8001, 249}, + {0xc016, 249}, + {0xfe, 0}, + {0xff, 0}, }, /* 247 */ { - {2, 0x02, 28}, - {9, 0x02, 28}, - {23, 0x02, 28}, - {40, 0x03, 28}, - {2, 0x02, 29}, - {9, 0x02, 29}, - {23, 0x02, 29}, - {40, 0x03, 29}, - {2, 0x02, 30}, - {9, 0x02, 30}, - {23, 0x02, 30}, - {40, 0x03, 30}, - {2, 0x02, 31}, - {9, 0x02, 31}, - {23, 0x02, 31}, - {40, 0x03, 31}, + {0x8002, 28}, + {0x8009, 28}, + {0x8017, 28}, + {0xc028, 28}, + {0x8002, 29}, + {0x8009, 29}, + {0x8017, 29}, + {0xc028, 29}, + {0x8002, 30}, + {0x8009, 30}, + {0x8017, 30}, + {0xc028, 30}, + {0x8002, 31}, + {0x8009, 31}, + {0x8017, 31}, + {0xc028, 31}, }, /* 248 */ { - {3, 0x02, 28}, - {6, 0x02, 28}, - {10, 0x02, 28}, - {15, 0x02, 28}, - {24, 0x02, 28}, - {31, 0x02, 28}, - {41, 0x02, 28}, - {56, 0x03, 28}, - {3, 0x02, 29}, - {6, 0x02, 29}, - {10, 0x02, 29}, - {15, 0x02, 29}, - {24, 0x02, 29}, - {31, 0x02, 29}, - {41, 0x02, 29}, - {56, 0x03, 29}, + {0x8003, 28}, + {0x8006, 28}, + {0x800a, 28}, + {0x800f, 28}, + {0x8018, 28}, + {0x801f, 28}, + {0x8029, 28}, + {0xc038, 28}, + {0x8003, 29}, + {0x8006, 29}, + {0x800a, 29}, + {0x800f, 29}, + {0x8018, 29}, + {0x801f, 29}, + {0x8029, 29}, + {0xc038, 29}, }, /* 249 */ { - {3, 0x02, 30}, - {6, 0x02, 30}, - {10, 0x02, 30}, - {15, 0x02, 30}, - {24, 0x02, 30}, - {31, 0x02, 30}, - {41, 0x02, 30}, - {56, 0x03, 30}, - {3, 0x02, 31}, - {6, 0x02, 31}, - {10, 0x02, 31}, - {15, 0x02, 31}, - {24, 0x02, 31}, - {31, 0x02, 31}, - {41, 0x02, 31}, - {56, 0x03, 31}, + {0x8003, 30}, + {0x8006, 30}, + {0x800a, 30}, + {0x800f, 30}, + {0x8018, 30}, + {0x801f, 30}, + {0x8029, 30}, + {0xc038, 30}, + {0x8003, 31}, + {0x8006, 31}, + {0x800a, 31}, + {0x800f, 31}, + {0x8018, 31}, + {0x801f, 31}, + {0x8029, 31}, + {0xc038, 31}, }, /* 250 */ { - {2, 0x02, 127}, - {9, 0x02, 127}, - {23, 0x02, 127}, - {40, 0x03, 127}, - {2, 0x02, 220}, - {9, 0x02, 220}, - {23, 0x02, 220}, - {40, 0x03, 220}, - {2, 0x02, 249}, - {9, 0x02, 249}, - {23, 0x02, 249}, - {40, 0x03, 249}, - {0, 0x03, 10}, - {0, 0x03, 13}, - {0, 0x03, 22}, - {0, 0x04, 0}, + {0x8002, 127}, + {0x8009, 127}, + {0x8017, 127}, + {0xc028, 127}, + {0x8002, 220}, + {0x8009, 220}, + {0x8017, 220}, + {0xc028, 220}, + {0x8002, 249}, + {0x8009, 249}, + {0x8017, 249}, + {0xc028, 249}, + {0xc000, 10}, + {0xc000, 13}, + {0xc000, 22}, + {0x100, 0}, }, /* 251 */ { - {3, 0x02, 127}, - {6, 0x02, 127}, - {10, 0x02, 127}, - {15, 0x02, 127}, - {24, 0x02, 127}, - {31, 0x02, 127}, - {41, 0x02, 127}, - {56, 0x03, 127}, - {3, 0x02, 220}, - {6, 0x02, 220}, - {10, 0x02, 220}, - {15, 0x02, 220}, - {24, 0x02, 220}, - {31, 0x02, 220}, - {41, 0x02, 220}, - {56, 0x03, 220}, + {0x8003, 127}, + {0x8006, 127}, + {0x800a, 127}, + {0x800f, 127}, + {0x8018, 127}, + {0x801f, 127}, + {0x8029, 127}, + {0xc038, 127}, + {0x8003, 220}, + {0x8006, 220}, + {0x800a, 220}, + {0x800f, 220}, + {0x8018, 220}, + {0x801f, 220}, + {0x8029, 220}, + {0xc038, 220}, }, /* 252 */ { - {3, 0x02, 249}, - {6, 0x02, 249}, - {10, 0x02, 249}, - {15, 0x02, 249}, - {24, 0x02, 249}, - {31, 0x02, 249}, - {41, 0x02, 249}, - {56, 0x03, 249}, - {1, 0x02, 10}, - {22, 0x03, 10}, - {1, 0x02, 13}, - {22, 0x03, 13}, - {1, 0x02, 22}, - {22, 0x03, 22}, - {0, 0x04, 0}, - {0, 0x04, 0}, + {0x8003, 249}, + {0x8006, 249}, + {0x800a, 249}, + {0x800f, 249}, + {0x8018, 249}, + {0x801f, 249}, + {0x8029, 249}, + {0xc038, 249}, + {0x8001, 10}, + {0xc016, 10}, + {0x8001, 13}, + {0xc016, 13}, + {0x8001, 22}, + {0xc016, 22}, + {0x100, 0}, + {0x100, 0}, }, /* 253 */ { - {2, 0x02, 10}, - {9, 0x02, 10}, - {23, 0x02, 10}, - {40, 0x03, 10}, - {2, 0x02, 13}, - {9, 0x02, 13}, - {23, 0x02, 13}, - {40, 0x03, 13}, - {2, 0x02, 22}, - {9, 0x02, 22}, - {23, 0x02, 22}, - {40, 0x03, 22}, - {0, 0x04, 0}, - {0, 0x04, 0}, - {0, 0x04, 0}, - {0, 0x04, 0}, + {0x8002, 10}, + {0x8009, 10}, + {0x8017, 10}, + {0xc028, 10}, + {0x8002, 13}, + {0x8009, 13}, + {0x8017, 13}, + {0xc028, 13}, + {0x8002, 22}, + {0x8009, 22}, + {0x8017, 22}, + {0xc028, 22}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, }, /* 254 */ { - {3, 0x02, 10}, - {6, 0x02, 10}, - {10, 0x02, 10}, - {15, 0x02, 10}, - {24, 0x02, 10}, - {31, 0x02, 10}, - {41, 0x02, 10}, - {56, 0x03, 10}, - {3, 0x02, 13}, - {6, 0x02, 13}, - {10, 0x02, 13}, - {15, 0x02, 13}, - {24, 0x02, 13}, - {31, 0x02, 13}, - {41, 0x02, 13}, - {56, 0x03, 13}, + {0x8003, 10}, + {0x8006, 10}, + {0x800a, 10}, + {0x800f, 10}, + {0x8018, 10}, + {0x801f, 10}, + {0x8029, 10}, + {0xc038, 10}, + {0x8003, 13}, + {0x8006, 13}, + {0x800a, 13}, + {0x800f, 13}, + {0x8018, 13}, + {0x801f, 13}, + {0x8029, 13}, + {0xc038, 13}, }, /* 255 */ { - {3, 0x02, 22}, - {6, 0x02, 22}, - {10, 0x02, 22}, - {15, 0x02, 22}, - {24, 0x02, 22}, - {31, 0x02, 22}, - {41, 0x02, 22}, - {56, 0x03, 22}, - {0, 0x04, 0}, - {0, 0x04, 0}, - {0, 0x04, 0}, - {0, 0x04, 0}, - {0, 0x04, 0}, - {0, 0x04, 0}, - {0, 0x04, 0}, - {0, 0x04, 0}, + {0x8003, 22}, + {0x8006, 22}, + {0x800a, 22}, + {0x800f, 22}, + {0x8018, 22}, + {0x801f, 22}, + {0x8029, 22}, + {0xc038, 22}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + }, + /* 256 */ + { + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, + {0x100, 0}, }, }; diff --git a/thirdparty/nghttp2/nghttp2_helper.c b/thirdparty/nghttp2/nghttp2_helper.c index 9dbfa7ddfda..765e5492ce5 100644 --- a/thirdparty/nghttp2/nghttp2_helper.c +++ b/thirdparty/nghttp2/nghttp2_helper.c @@ -103,6 +103,9 @@ const char *nghttp2_strerror(int error_code) { return "Internal error"; case NGHTTP2_ERR_CANCEL: return "Cancel"; + case NGHTTP2_ERR_SETTINGS_EXPECTED: + return "When a local endpoint expects to receive SETTINGS frame, it " + "receives an other type of frame"; case NGHTTP2_ERR_NOMEM: return "Out of memory"; case NGHTTP2_ERR_CALLBACK_FAILURE: @@ -112,6 +115,8 @@ const char *nghttp2_strerror(int error_code) { case NGHTTP2_ERR_FLOODED: return "Flooding was detected in this HTTP/2 session, and it must be " "closed"; + case NGHTTP2_ERR_TOO_MANY_SETTINGS: + return "SETTINGS frame contained more than the maximum allowed entries"; default: return "Unknown error code"; } diff --git a/thirdparty/nghttp2/nghttp2_mem.c b/thirdparty/nghttp2/nghttp2_mem.c index 10c31ccf734..8ca2ed332fd 100644 --- a/thirdparty/nghttp2/nghttp2_mem.c +++ b/thirdparty/nghttp2/nghttp2_mem.c @@ -28,14 +28,21 @@ static void *default_malloc(size_t size, void *mem_user_data) { return malloc(size); } -static void default_free(void *ptr, void *mem_user_data) { free(ptr); } +static void default_free(void *ptr, void *mem_user_data) { + (void)mem_user_data; + + free(ptr); +} + +static void *default_calloc(size_t nmemb, size_t size, void *mem_user_data) { + (void)mem_user_data; -static void *default_calloc(size_t nmemb, size_t size, - void *mem_user_data) { return calloc(nmemb, size); } static void *default_realloc(void *ptr, size_t size, void *mem_user_data) { + (void)mem_user_data; + return realloc(ptr, size); } From 3b76d35e08ddbedd6c79a846aa94c705b7260a1d Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 29 Jun 2021 12:21:51 +0800 Subject: [PATCH 162/936] Compatible with low version c-ares library --- src/core/base.cc | 6 +++--- src/network/dns.cc | 13 +++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/core/base.cc b/src/core/base.cc index 2622c5d4621..8b7af46942c 100644 --- a/src/core/base.cc +++ b/src/core/base.cc @@ -805,7 +805,9 @@ static void swoole_fatal_error(int code, const char *format, ...) { exit(1); } -size_t swDataHead::dump(char *_buf, size_t _len) { +namespace swoole { +//------------------------------------------------------------------------------- +size_t DataHead::dump(char *_buf, size_t _len) { return sw_snprintf(_buf, _len, "swDataHead[%p]\n" @@ -826,8 +828,6 @@ size_t swDataHead::dump(char *_buf, size_t _len) { server_fd); } -namespace swoole { -//------------------------------------------------------------------------------- std::string dirname(const std::string &file) { size_t index = file.find_last_of('/'); if (index == std::string::npos) { diff --git a/src/network/dns.cc b/src/network/dns.cc index eb31534346f..40d2c94c27a 100644 --- a/src/network/dns.cc +++ b/src/network/dns.cc @@ -429,6 +429,7 @@ std::vector dns_lookup_impl_with_cares(const char *domain, int fami } if (!SwooleG.dns_server_host.empty()) { +#if (ARES_VERSION >= 0x010b00) struct ares_addr_port_node servers; servers.family = AF_INET; servers.next = nullptr; @@ -436,6 +437,18 @@ std::vector dns_lookup_impl_with_cares(const char *domain, int fami servers.tcp_port = 0; servers.udp_port = SwooleG.dns_server_port; ares_set_servers_ports(ctx.channel, &servers); +#elif (ARES_VERSION >= 0x010701) + struct ares_addr_node servers; + servers.family = AF_INET; + servers.next = nullptr; + inet_pton(AF_INET, SwooleG.dns_server_host.c_str(), &servers.addr.addr4); + ares_set_servers(ctx.channel, &servers); + if (dns_server_port != SW_DNS_SERVER_PORT) { + swWarn("not support to set port of dns server"); + } +#else + swWarn("not support to set dns server"); +#endif } ares_gethostbyname( From a11aa99567b22b3f9caf07130d8cf27be73770ba Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 29 Jun 2021 14:23:48 +0800 Subject: [PATCH 163/936] Fix compilation errors --- src/network/dns.cc | 2 +- thirdparty/hiredis/read.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/network/dns.cc b/src/network/dns.cc index 40d2c94c27a..0fd471292b9 100644 --- a/src/network/dns.cc +++ b/src/network/dns.cc @@ -443,7 +443,7 @@ std::vector dns_lookup_impl_with_cares(const char *domain, int fami servers.next = nullptr; inet_pton(AF_INET, SwooleG.dns_server_host.c_str(), &servers.addr.addr4); ares_set_servers(ctx.channel, &servers); - if (dns_server_port != SW_DNS_SERVER_PORT) { + if (SwooleG.dns_server_port != SW_DNS_SERVER_PORT) { swWarn("not support to set port of dns server"); } #else diff --git a/thirdparty/hiredis/read.c b/thirdparty/hiredis/read.c index 6253166ad4e..468877c1f11 100644 --- a/thirdparty/hiredis/read.c +++ b/thirdparty/hiredis/read.c @@ -348,7 +348,8 @@ static int processLineItem(redisReader *r) { } else if (cur->type == REDIS_REPLY_BIGNUM) { /* Ensure all characters are decimal digits (with possible leading * minus sign). */ - for (int i = 0; i < len; i++) { + int i; + for (i = 0; i < len; i++) { /* XXX Consider: Allow leading '+'? Error on leading '0's? */ if (i == 0 && p[0] == '-') continue; if (p[i] < '0' || p[i] > '9') { @@ -363,7 +364,8 @@ static int processLineItem(redisReader *r) { obj = (void*)REDIS_REPLY_BIGNUM; } else { /* Type will be error or status. */ - for (int i = 0; i < len; i++) { + int i; + for (i = 0; i < len; i++) { if (p[i] == '\r' || p[i] == '\n') { __redisReaderSetError(r,REDIS_ERR_PROTOCOL, "Bad simple string value"); From db3d335762f394b8561293b4ca89919125a7dc42 Mon Sep 17 00:00:00 2001 From: twosee Date: Tue, 29 Jun 2021 16:29:01 +0800 Subject: [PATCH 164/936] Do not hook disabled functions (#4283) --- ext-src/swoole_runtime.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ext-src/swoole_runtime.cc b/ext-src/swoole_runtime.cc index b3d131130dc..2ee1d9e0d16 100644 --- a/ext-src/swoole_runtime.cc +++ b/ext-src/swoole_runtime.cc @@ -1860,6 +1860,11 @@ static void hook_func(const char *name, size_t l_name, zif_handler handler, zend if (zf == nullptr) { return; } +#if PHP_VERSION_ID < 80000 + if (zf->internal_function.handler == ZEND_FN(display_disabled_function)) { + return; + } +#endif rf = (real_func *) emalloc(sizeof(real_func)); sw_memset_zero(rf, sizeof(*rf)); From 844191bdf2c404b2ad25f66415055156a384d156 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Wed, 30 Jun 2021 08:52:43 +0800 Subject: [PATCH 165/936] Add core test for server.schedule --- core-tests/src/server/server.cpp | 32 ++++++++++++++++++++++++++++++++ include/swoole_process_pool.h | 12 ++++++++++++ 2 files changed, 44 insertions(+) diff --git a/core-tests/src/server/server.cpp b/core-tests/src/server/server.cpp index 4b90421afcb..8487ecd8cbc 100644 --- a/core-tests/src/server/server.cpp +++ b/core-tests/src/server/server.cpp @@ -40,6 +40,38 @@ TEST(server, create_pipe_buffers) { } } +TEST(server, schedule) { + int ret; + Server serv(Server::MODE_PROCESS); + serv.worker_num = 6; + serv.dispatch_mode = SW_DISPATCH_QUEUE; + ret = serv.create(); + ASSERT_EQ(SW_OK, ret); + + for (uint32_t i = 0; i < serv.worker_num; i++) { + serv.workers[i].status = SW_WORKER_BUSY; + } + + std::set _worker_id_set; + + for (uint32_t i = 0; i < serv.worker_num; i++) { + auto worker_id = serv.schedule_worker(i*13, nullptr); + _worker_id_set.insert(worker_id); + } + ASSERT_EQ(_worker_id_set.size(), serv.worker_num); + + for (uint32_t i = 1; i < serv.worker_num - 1; i++) { + serv.workers[i].status = SW_WORKER_IDLE; + } + + _worker_id_set.clear(); + for (uint32_t i = 0; i < serv.worker_num; i++) { + auto worker_id = serv.schedule_worker(i*13, nullptr); + _worker_id_set.insert(worker_id); + } + ASSERT_EQ(_worker_id_set.size(), serv.worker_num - 2); +} + static const char *packet = "hello world\n"; TEST(server, base) { diff --git a/include/swoole_process_pool.h b/include/swoole_process_pool.h index b4f10cf8004..42a7bf78d7e 100644 --- a/include/swoole_process_pool.h +++ b/include/swoole_process_pool.h @@ -148,6 +148,18 @@ struct Worker { void *ptr2; ssize_t send_pipe_message(const void *buf, size_t n, int flags); + + void set_status(enum swWorker_status _status) { + status = _status; + } + + bool is_busy() { + return status == SW_WORKER_BUSY; + } + + bool is_idle() { + return status == SW_WORKER_IDLE; + } }; struct StreamInfo { From d365b6b439a90bc37ec4778da8eb0a71b616a520 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Wed, 30 Jun 2021 16:08:19 +0800 Subject: [PATCH 166/936] fix #4282 --- ext-src/swoole_process_pool.cc | 14 ++++++++++---- include/swoole_process_pool.h | 2 +- src/os/process_pool.cc | 4 +--- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/ext-src/swoole_process_pool.cc b/ext-src/swoole_process_pool.cc index a0718a74d14..eda655823cf 100644 --- a/ext-src/swoole_process_pool.cc +++ b/ext-src/swoole_process_pool.cc @@ -334,10 +334,7 @@ static PHP_METHOD(swoole_process_pool, __construct) { pool->main_loop = nullptr; } else { if (ipc_type > 0) { - if (pool->set_protocol(0, SW_INPUT_BUFFER_SIZE) < 0) { - zend_throw_exception_ex(swoole_exception_ce, errno, "failed to create process pool"); - RETURN_FALSE; - } + pool->set_protocol(0, SW_INPUT_BUFFER_SIZE); } } @@ -360,9 +357,18 @@ static PHP_METHOD(swoole_process_pool, set) { ProcessPoolProperty *pp = php_swoole_process_pool_get_and_check_pp(ZEND_THIS); + php_swoole_set_global_option(vht); + php_swoole_set_coroutine_option(vht); + php_swoole_set_aio_option(vht); + if (php_swoole_array_get_value(vht, "enable_coroutine", ztmp)) { pp->enable_coroutine = zval_is_true(ztmp); } + + ProcessPool *pool = php_swoole_process_pool_get_and_check_pool(ZEND_THIS); + if (pp->enable_coroutine) { + pool->main_loop = nullptr; + } } static PHP_METHOD(swoole_process_pool, on) { diff --git a/include/swoole_process_pool.h b/include/swoole_process_pool.h index b4f10cf8004..12a69326be9 100644 --- a/include/swoole_process_pool.h +++ b/include/swoole_process_pool.h @@ -261,7 +261,7 @@ struct ProcessPool { void set_max_request(uint32_t _max_request, uint32_t _max_request_grace); int get_max_request(); - int set_protocol(int task_protocol, uint32_t max_packet_size); + void set_protocol(int task_protocol, uint32_t max_packet_size); bool detach(); int wait(); int start(); diff --git a/src/os/process_pool.cc b/src/os/process_pool.cc index 3986d203ae7..0a8dbcd10ae 100644 --- a/src/os/process_pool.cc +++ b/src/os/process_pool.cc @@ -497,7 +497,7 @@ static int ProcessPool_worker_loop(ProcessPool *pool, Worker *worker) { return SW_OK; } -int ProcessPool::set_protocol(int task_protocol, uint32_t max_packet_size) { +void ProcessPool::set_protocol(int task_protocol, uint32_t max_packet_size) { if (task_protocol) { main_loop = ProcessPool_worker_loop; } else { @@ -508,8 +508,6 @@ int ProcessPool::set_protocol(int task_protocol, uint32_t max_packet_size) { max_packet_size_ = max_packet_size; main_loop = ProcessPool_worker_loop_ex; } - - return SW_OK; } static int ProcessPool_worker_loop_ex(ProcessPool *pool, Worker *worker) { From 4c8175b656b6b8e7ba6bc5977354942d7c04b56e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Wed, 30 Jun 2021 18:04:39 +0800 Subject: [PATCH 167/936] Fix #4281 (#4288) * Compatible with php-8.1 * Fix compilation errors * fix --- ext-src/php_swoole.cc | 80 ++++++++++++++++++++----------------- ext-src/swoole_coroutine.cc | 69 ++++++++++++++++++-------------- ext-src/swoole_runtime.cc | 3 +- ext-src/swoole_server.cc | 5 +++ 4 files changed, 88 insertions(+), 69 deletions(-) diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index be863d671e5..a44e20b4fc4 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -179,8 +179,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_mime_type_read, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() -const zend_function_entry swoole_functions[] = -{ +const zend_function_entry swoole_functions[] = { PHP_FE(swoole_version, arginfo_swoole_void) PHP_FE(swoole_cpu_num, arginfo_swoole_void) PHP_FE(swoole_last_error, arginfo_swoole_void) @@ -218,33 +217,24 @@ const zend_function_entry swoole_functions[] = PHP_FE(swoole_internal_call_user_shutdown_begin, arginfo_swoole_void) PHP_FE_END /* Must be the last line in swoole_functions[] */ }; -// clang-format on - -zend_class_entry *swoole_exception_ce; -zend_object_handlers swoole_exception_handlers; - -zend_class_entry *swoole_error_ce; -zend_object_handlers swoole_error_handlers; static const zend_module_dep swoole_deps[] = { #ifdef SW_USE_JSON - ZEND_MOD_REQUIRED("json") + ZEND_MOD_REQUIRED("json") #endif #ifdef SW_USE_MYSQLND - ZEND_MOD_REQUIRED("mysqlnd") + ZEND_MOD_REQUIRED("mysqlnd") #endif #ifdef SW_SOCKETS - ZEND_MOD_REQUIRED("sockets") + ZEND_MOD_REQUIRED("sockets") #endif #ifdef SW_USE_CURL - ZEND_MOD_REQUIRED("curl") + ZEND_MOD_REQUIRED("curl") #endif - ZEND_MOD_END + ZEND_MOD_END }; -// clang-format off -zend_module_entry swoole_module_entry = -{ +zend_module_entry swoole_module_entry = { STANDARD_MODULE_HEADER_EX, nullptr, swoole_deps, @@ -260,6 +250,12 @@ zend_module_entry swoole_module_entry = }; // clang-format on +zend_class_entry *swoole_exception_ce; +zend_object_handlers swoole_exception_handlers; + +zend_class_entry *swoole_error_ce; +zend_object_handlers swoole_error_handlers; + #ifdef COMPILE_DL_SWOOLE ZEND_GET_MODULE(swoole) #endif @@ -304,6 +300,14 @@ static void php_swoole_init_globals(zend_swoole_globals *swoole_globals) { void php_swoole_register_shutdown_function(const char *function) { php_shutdown_function_entry shutdown_function_entry; +#if PHP_VERSION_ID >= 80100 + zval function_name; + ZVAL_STRING(&function_name, function); + zend_fcall_info_init( + &function_name, 0, &shutdown_function_entry.fci, &shutdown_function_entry.fci_cache, NULL, NULL); + register_user_shutdown_function(Z_STRVAL(function_name), Z_STRLEN(function_name), &shutdown_function_entry); + zval_ptr_dtor(&function_name); +#else zval *function_name; #if PHP_VERSION_ID >= 80000 shutdown_function_entry.arg_count = 0; @@ -315,8 +319,8 @@ void php_swoole_register_shutdown_function(const char *function) { function_name = &shutdown_function_entry.arguments[0]; #endif ZVAL_STRING(function_name, function); - register_user_shutdown_function( - Z_STRVAL_P(function_name), Z_STRLEN_P(function_name), &shutdown_function_entry); + register_user_shutdown_function(Z_STRVAL_P(function_name), Z_STRLEN_P(function_name), &shutdown_function_entry); +#endif } void php_swoole_set_global_option(HashTable *vht) { @@ -398,14 +402,17 @@ SW_API bool php_swoole_is_enable_coroutine() { static void fatal_error(int code, const char *format, ...) { va_list args; va_start(args, format); - zend_object *exception = zend_throw_exception(swoole_error_ce, swoole::std_string::vformat(format, args).c_str(), code); + zend_object *exception = + zend_throw_exception(swoole_error_ce, swoole::std_string::vformat(format, args).c_str(), code); va_end(args); zend_try { zend_exception_error(exception, E_ERROR); - } zend_catch { + } + zend_catch { exit(255); - } zend_end_try(); + } + zend_end_try(); } /* {{{ PHP_MINIT_FUNCTION @@ -967,14 +974,14 @@ static void _sw_zend_string_free(void *address) { zend_string_free(zend::fetch_zend_string_by_val(address)); } -static swoole::Allocator php_allocator { +static swoole::Allocator php_allocator{ _sw_emalloc, _sw_ecalloc, _sw_erealloc, _sw_efree, }; -static swoole::Allocator zend_string_allocator { +static swoole::Allocator zend_string_allocator{ _sw_zend_string_malloc, _sw_zend_string_calloc, _sw_zend_string_realloc, @@ -1335,17 +1342,17 @@ static PHP_FUNCTION(swoole_internal_call_user_shutdown_begin) { static PHP_FUNCTION(swoole_substr_unserialize) { zend_long offset, length = 0; - char *buf = NULL; - size_t buf_len; + char *buf = NULL; + size_t buf_len; zval *options = NULL; - ZEND_PARSE_PARAMETERS_START(2, 4) + ZEND_PARSE_PARAMETERS_START(2, 4) Z_PARAM_STRING(buf, buf_len) Z_PARAM_LONG(offset) Z_PARAM_OPTIONAL Z_PARAM_LONG(length) Z_PARAM_ARRAY(options) - ZEND_PARSE_PARAMETERS_END(); + ZEND_PARSE_PARAMETERS_END(); if (buf_len == 0) { RETURN_FALSE; @@ -1366,13 +1373,13 @@ static PHP_FUNCTION(swoole_substr_unserialize) { static PHP_FUNCTION(swoole_substr_json_decode) { zend_long offset, length = 0; char *str; - size_t str_len; - zend_bool assoc = 0; /* return JS objects as PHP objects by default */ - zend_bool assoc_null = 1; - zend_long depth = PHP_JSON_PARSER_DEFAULT_DEPTH; - zend_long options = 0; + size_t str_len; + zend_bool assoc = 0; /* return JS objects as PHP objects by default */ + zend_bool assoc_null = 1; + zend_long depth = PHP_JSON_PARSER_DEFAULT_DEPTH; + zend_long options = 0; - ZEND_PARSE_PARAMETERS_START(2, 6) + ZEND_PARSE_PARAMETERS_START(2, 6) Z_PARAM_STRING(str, str_len) Z_PARAM_LONG(offset) Z_PARAM_OPTIONAL @@ -1380,7 +1387,7 @@ static PHP_FUNCTION(swoole_substr_json_decode) { Z_PARAM_BOOL_EX(assoc, assoc_null, 1, 0) Z_PARAM_LONG(depth) Z_PARAM_LONG(options) - ZEND_PARSE_PARAMETERS_END(); + ZEND_PARSE_PARAMETERS_END(); if (str_len == 0) { RETURN_FALSE; @@ -1397,7 +1404,7 @@ static PHP_FUNCTION(swoole_substr_json_decode) { /* For BC reasons, the bool $assoc overrides the long $options bit for PHP_JSON_OBJECT_AS_ARRAY */ if (!assoc_null) { if (assoc) { - options |= PHP_JSON_OBJECT_AS_ARRAY; + options |= PHP_JSON_OBJECT_AS_ARRAY; } else { options &= ~PHP_JSON_OBJECT_AS_ARRAY; } @@ -1405,4 +1412,3 @@ static PHP_FUNCTION(swoole_substr_json_decode) { zend::json_decode(return_value, str + offset, length, options, depth); } #endif - diff --git a/ext-src/swoole_coroutine.cc b/ext-src/swoole_coroutine.cc index 999a8c73db3..4ca574002b5 100644 --- a/ext-src/swoole_coroutine.cc +++ b/ext-src/swoole_coroutine.cc @@ -36,8 +36,8 @@ using swoole::PHPCoroutine; using swoole::coroutine::Socket; using swoole::coroutine::System; -#define PHP_CORO_TASK_SLOT \ - ((int) ((ZEND_MM_ALIGNED_SIZE(sizeof(PHPContext)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / \ +#define PHP_CORO_TASK_SLOT \ + ((int) ((ZEND_MM_ALIGNED_SIZE(sizeof(PHPContext)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / \ ZEND_MM_ALIGNED_SIZE(sizeof(zval)))) enum sw_exit_flags { SW_EXIT_IN_COROUTINE = 1 << 1, SW_EXIT_IN_SERVER = 1 << 2 }; @@ -45,14 +45,14 @@ enum sw_exit_flags { SW_EXIT_IN_COROUTINE = 1 << 1, SW_EXIT_IN_SERVER = 1 << 2 } bool PHPCoroutine::activated = false; zend_array *PHPCoroutine::options = nullptr; -PHPCoroutine::Config PHPCoroutine::config { +PHPCoroutine::Config PHPCoroutine::config{ SW_DEFAULT_MAX_CORO_NUM, 0, false, true, }; -PHPContext PHPCoroutine::main_task {}; +PHPContext PHPCoroutine::main_task{}; std::thread PHPCoroutine::interrupt_thread; bool PHPCoroutine::interrupt_thread_running = false; @@ -72,9 +72,15 @@ static unordered_map user_yield_coros; #define ZEND_ERROR_CB_LAST_ARG_RELAY message #endif +#if PHP_VERSION_ID < 80100 +typedef const char error_filename_t; +#else +typedef zend_string error_filename_t; +#endif + static void (*orig_interrupt_function)(zend_execute_data *execute_data) = nullptr; static void (*orig_error_function)(int type, - const char *error_filename, + error_filename_t *error_filename, const uint32_t error_lineno, ZEND_ERROR_CB_LAST_ARG_D) = nullptr; @@ -323,28 +329,31 @@ void PHPCoroutine::activate() { /* replace the error function to save execute_data */ orig_error_function = zend_error_cb; - zend_error_cb = [](int type, const char *error_filename, const uint32_t error_lineno, ZEND_ERROR_CB_LAST_ARG_D) { - if (sw_unlikely(type & E_FATAL_ERRORS)) { - if (activated) { - /* update the last coroutine's info */ - save_task(get_context()); - } - if (sw_reactor()) { - sw_reactor()->running = false; - sw_reactor()->bailout = true; - } + zend_error_cb = + [](int type, error_filename_t *error_filename, const uint32_t error_lineno, ZEND_ERROR_CB_LAST_ARG_D) { + if (sw_unlikely(type & E_FATAL_ERRORS)) { + if (activated) { + /* update the last coroutine's info */ + save_task(get_context()); + } + if (sw_reactor()) { + sw_reactor()->running = false; + sw_reactor()->bailout = true; + } #ifdef SW_EXIT_WHEN_OCCURS_FATAL_ERROR - zend_try { - orig_error_function(type, error_filename, error_lineno, ZEND_ERROR_CB_LAST_ARG_RELAY); - } zend_catch { - exit(255); - } zend_end_try(); + zend_try { + orig_error_function(type, error_filename, error_lineno, ZEND_ERROR_CB_LAST_ARG_RELAY); + } + zend_catch { + exit(255); + } + zend_end_try(); #endif - } - if (sw_likely(orig_error_function)) { - orig_error_function(type, error_filename, error_lineno, ZEND_ERROR_CB_LAST_ARG_RELAY); - } - }; + } + if (sw_likely(orig_error_function)) { + orig_error_function(type, error_filename, error_lineno, ZEND_ERROR_CB_LAST_ARG_RELAY); + } + }; if (SWOOLE_G(enable_preemptive_scheduler) || config.enable_preemptive_scheduler) { /* create a thread to interrupt the coroutine that takes up too much time */ @@ -757,10 +766,10 @@ void PHPCoroutine::main_func(void *arg) { defer_fci->fci.param_count = 1; defer_fci->fci.params = retval; #else - if (Z_TYPE_P(retval) != IS_UNDEF) { - defer_fci->fci.param_count = 1; - defer_fci->fci.params = retval; - } + if (Z_TYPE_P(retval) != IS_UNDEF) { + defer_fci->fci.param_count = 1; + defer_fci->fci.params = retval; + } #endif if (UNEXPECTED(sw_zend_call_function_anyway(&defer_fci->fci, &defer_fci->fci_cache) != SUCCESS)) { @@ -1075,7 +1084,7 @@ static PHP_METHOD(swoole_coroutine, yield) { Coroutine *co = Coroutine::get_current_safe(); user_yield_coros[co->get_cid()] = co; - Coroutine::CancelFunc cancel_fn = [](Coroutine *co){ + Coroutine::CancelFunc cancel_fn = [](Coroutine *co) { user_yield_coros.erase(co->get_cid()); co->resume(); return true; diff --git a/ext-src/swoole_runtime.cc b/ext-src/swoole_runtime.cc index 2ee1d9e0d16..eb2347b7704 100644 --- a/ext-src/swoole_runtime.cc +++ b/ext-src/swoole_runtime.cc @@ -1699,9 +1699,8 @@ static int stream_array_emulate_read_fd_set(zval *stream_array) { return 0; } - ZVAL_NEW_ARR(&new_array); + array_init_size(&new_array, zend_hash_num_elements(Z_ARRVAL_P(stream_array))); ht = Z_ARRVAL(new_array); - zend_hash_init(ht, zend_hash_num_elements(Z_ARRVAL_P(stream_array)), nullptr, ZVAL_PTR_DTOR, 0); ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(stream_array), num_ind, key, elem) { ZVAL_DEREF(elem); diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 71b77de1029..199e60857ed 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -100,7 +100,12 @@ void php_swoole_server_rshutdown() { #else PG(last_error_message)->val, #endif + +#if PHP_VERSION_ID >= 80100 + PG(last_error_file) ? PG(last_error_file)->val : "-", +#else PG(last_error_file) ? PG(last_error_file) : "-", +#endif PG(last_error_lineno)); } else { swoole_error_log( From 270f0a10d6ac75b674dbd8509e0e2f9b357bdc4d Mon Sep 17 00:00:00 2001 From: matyhtf Date: Wed, 30 Jun 2021 18:09:55 +0800 Subject: [PATCH 168/936] Fix #4287 --- ext-src/php_swoole_library.h | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index c3c0033df03..02bf3a3129b 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: 1ed49dbae3a1850b3a67d9904e07dac9b96adb43 */ +/* $Id: b591f704aaab92336e8906d2584b7030fde90e87 */ static const char* swoole_library_source_constants = "\n" @@ -618,34 +618,33 @@ static const char* swoole_library_source_core_string_object = " /**\n" " * @return static\n" " */\n" - " public function substr(int $offset, ?int $length = null)\n" + " public function substr(int $offset, ?int $length = null): self\n" " {\n" " return new static(substr($this->string, ...func_get_args()));\n" " }\n" "\n" - " public function repeat(int $n): StringObject\n" + " /**\n" + " * @return static\n" + " */\n" + " public function repeat(int $times): self\n" " {\n" - " return new static(str_repeat($this->string, $n));\n" + " return new static(str_repeat($this->string, $times));\n" " }\n" "\n" " /**\n" - " * @param $str\n" + " * @param mixed $str\n" + " * @return static\n" " */\n" - " public function append($str): StringObject\n" + " public function append($str): self\n" " {\n" - " if (is_string($str)) {\n" - " $this->string .= $str;\n" - " } else {\n" - " $this->string .= strval($str);\n" - " }\n" - " return $this;\n" + " return new static($this->string .= $str);\n" " }\n" "\n" " /**\n" " * @param null|int $count\n" " * @return static\n" " */\n" - " public function replace(string $search, string $replace, &$count = null)\n" + " public function replace(string $search, string $replace, &$count = null): self\n" " {\n" " return new static(str_replace($search, $replace, $this->string, $count));\n" " }\n" @@ -692,9 +691,9 @@ static const char* swoole_library_source_core_string_object = " /**\n" " * @return static\n" " */\n" - " public function chunkSplit(int $chunkLength = 76, string $chunkEnd = '')\n" + " public function chunkSplit(int $chunkLength = 76, string $chunkEnd = ''): self\n" " {\n" - " return new static(chunk_split($this->string, ...func_get_args()));\n" + " return new static(chunk_split($this->string, $chunkLength, $chunkEnd));\n" " }\n" "\n" " public function chunk(int $splitLength = 1): ArrayObject\n" @@ -3517,6 +3516,7 @@ static const char* swoole_library_source_core_curl_handler = " 'protocol' => 0,\n" " 'ssl_verifyresult' => 0,\n" " 'scheme' => '',\n" + " 'private' => '',\n" " ];\n" "\n" " private $withHeaderOut = false;\n" @@ -3880,6 +3880,9 @@ static const char* swoole_library_source_core_curl_handler = " case CURLOPT_TCP_NODELAY:\n" " $this->clientOptions[Constant::OPTION_OPEN_TCP_NODELAY] = boolval($value);\n" " break;\n" + " case CURLOPT_PRIVATE:\n" + " $this->info['private'] = $value;\n" + " break;\n" " /*\n" " * Ignore options\n" " */\n" @@ -7115,6 +7118,8 @@ static const char* swoole_library_source_ext_curl = " return $info['redirect_time'];\n" " case CURLINFO_HEADER_SIZE:\n" " return $info['header_size'];\n" + " case CURLINFO_PRIVATE:\n" + " return $info['private'];\n" " default:\n" " return null;\n" " }\n" From b0146b818ecc1474cd34c31e23a4dfe417b3b510 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Thu, 1 Jul 2021 14:51:33 +0800 Subject: [PATCH 169/936] Optimize code --- ext-src/php_swoole_library.h | 6 +++--- ext-src/swoole_server.cc | 24 +++++++++++++++++------- include/swoole_server.h | 2 +- src/server/reactor_thread.cc | 8 ++++++-- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index 02bf3a3129b..706f84e2226 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: b591f704aaab92336e8906d2584b7030fde90e87 */ +/* $Id: e07037baef45ea64d334257e203fe2ca82914c93 */ static const char* swoole_library_source_constants = "\n" @@ -618,7 +618,7 @@ static const char* swoole_library_source_core_string_object = " /**\n" " * @return static\n" " */\n" - " public function substr(int $offset, ?int $length = null): self\n" + " public function substr(int $offset, ?int $length = null)\n" " {\n" " return new static(substr($this->string, ...func_get_args()));\n" " }\n" @@ -693,7 +693,7 @@ static const char* swoole_library_source_core_string_object = " */\n" " public function chunkSplit(int $chunkLength = 76, string $chunkEnd = ''): self\n" " {\n" - " return new static(chunk_split($this->string, $chunkLength, $chunkEnd));\n" + " return new static(chunk_split($this->string, ...func_get_args()));\n" " }\n" "\n" " public function chunk(int $splitLength = 1): ArrayObject\n" diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 199e60857ed..8b7844e1f36 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -1872,8 +1872,8 @@ void php_swoole_server_onClose(Server *serv, DataHead *info) { } if (conn->websocket_status != WEBSOCKET_STATUS_ACTIVE) { ListenPort *port = serv->get_port_by_server_fd(info->server_fd); - if (port && port->open_websocket_protocol - && php_swoole_server_isset_callback(serv, port, SW_SERVER_CB_onDisconnect)) { + if (port && port->open_websocket_protocol && + php_swoole_server_isset_callback(serv, port, SW_SERVER_CB_onDisconnect)) { fci_cache = php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onDisconnect); } } @@ -3078,11 +3078,15 @@ static PHP_METHOD(swoole_server, heartbeat) { if (conn->protect || conn->last_recv_time == 0 || conn->last_recv_time > checktime) { return; } + SessionId session_id = conn->session_id; + if (session_id <= 0) { + return; + } if (close_connection) { conn->close_force = 1; - serv->close(conn->fd, false); + serv->close(session_id, false); } - add_next_index_long(return_value, conn->session_id); + add_next_index_long(return_value, session_id); }); } @@ -3713,7 +3717,11 @@ static PHP_METHOD(swoole_server, getClientList) { swTrace("maxfd=%d, fd=%d, find_count=%ld, start_fd=%ld", serv_max_fd, fd, find_count, start_session_id); Connection *conn = serv->get_connection_for_iterator(fd); if (conn) { - add_next_index_long(return_value, conn->session_id); + SessionId session_id = conn->session_id; + if (session_id <= 0) { + continue; + } + add_next_index_long(return_value, session_id); find_count--; } // finish fetch @@ -3931,10 +3939,12 @@ static PHP_METHOD(swoole_connection_iterator, valid) { if (!conn) { continue; } - if (iterator->port && (iterator->port->get_fd() < 0 || conn->server_fd != iterator->port->get_fd())) { + SessionId session_id = conn->session_id; + if (session_id <= 0 || + (iterator->port && (iterator->port->get_fd() < 0 || conn->server_fd != iterator->port->get_fd()))) { continue; } - iterator->session_id = conn->session_id; + iterator->session_id = session_id; iterator->current_fd = fd; iterator->index++; RETURN_TRUE; diff --git a/include/swoole_server.h b/include/swoole_server.h index 9975c08d3a4..2139847bf5f 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -1158,7 +1158,7 @@ class Server { inline Connection *get_connection_for_iterator(int fd) { Connection *conn = get_connection(fd); - if (conn && conn->active && !conn->closed && conn->session_id > 0) { + if (conn && conn->active && !conn->closed) { #ifdef SW_USE_OPENSSL if (conn->ssl && !conn->ssl_ready) { return nullptr; diff --git a/src/server/reactor_thread.cc b/src/server/reactor_thread.cc index 042391bc6d9..d50b4dcf296 100644 --- a/src/server/reactor_thread.cc +++ b/src/server/reactor_thread.cc @@ -1091,11 +1091,15 @@ void Server::start_heartbeat_thread() { if (conn->protect || conn->last_recv_time == 0 || conn->last_recv_time > checktime) { return; } + SessionId session_id = conn->session_id; + if (session_id <= 0) { + return; + } DataHead ev{}; ev.type = SW_SERVER_EVENT_CLOSE_FORCE; // convert fd to session_id, in order to verify the connection before the force close connection - ev.fd = conn->session_id; - Socket *_pipe_sock = get_reactor_thread_pipe(conn->session_id, conn->reactor_id); + ev.fd = session_id; + Socket *_pipe_sock = get_reactor_thread_pipe(session_id, conn->reactor_id); _pipe_sock->send_blocking((void *) &ev, sizeof(ev)); }); sleep(heartbeat_check_interval); From 9d34d5e991385165701fa37e944e74d8d098d2e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Fri, 2 Jul 2021 15:56:44 +0800 Subject: [PATCH 170/936] Support setting different idle time for each port (#4290) * Support setting different idle time for each port * optimize code * fix * Compatible * optimize code --- examples/server/echo.php | 4 +- ext-src/swoole_server.cc | 28 +++------ ext-src/swoole_server_port.cc | 18 ++++-- include/swoole_server.h | 6 +- src/server/master.cc | 27 +++++++++ src/server/reactor_process.cc | 10 +--- src/server/reactor_thread.cc | 13 ++--- tests/swoole_server_port/heartbeat_2.phpt | 70 +++++++++++++++++++++++ 8 files changed, 135 insertions(+), 41 deletions(-) create mode 100644 tests/swoole_server_port/heartbeat_2.phpt diff --git a/examples/server/echo.php b/examples/server/echo.php index 81ef81b4642..51544878716 100644 --- a/examples/server/echo.php +++ b/examples/server/echo.php @@ -1,5 +1,7 @@ on('connect', function ($serv, $fd, $reactor_id){ // echo "[#".posix_getpid()."]\tClient@[$fd:$reactor_id]: Connect.\n"; //}); diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 8b7844e1f36..9832211e04c 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -2385,19 +2385,9 @@ static PHP_METHOD(swoole_server, set) { if (php_swoole_array_get_value(vht, "heartbeat_check_interval", ztmp)) { zend_long v = zval_get_long(ztmp); serv->heartbeat_check_interval = SW_MAX(0, SW_MIN(v, UINT16_MAX)); - } - // heartbeat idle time - if (php_swoole_array_get_value(vht, "heartbeat_idle_time", ztmp)) { + } else if (php_swoole_array_get_value(vht, "heartbeat_idle_time", ztmp)) { zend_long v = zval_get_long(ztmp); - serv->heartbeat_idle_time = SW_MAX(0, SW_MIN(v, UINT16_MAX)); - - if (serv->heartbeat_check_interval > serv->heartbeat_idle_time) { - php_swoole_fatal_error(E_WARNING, "heartbeat_idle_time must be greater than heartbeat_check_interval"); - serv->heartbeat_check_interval = serv->heartbeat_idle_time / 2; - } - } - if (serv->heartbeat_idle_time == 0 && serv->heartbeat_check_interval > 0) { - serv->heartbeat_idle_time = serv->heartbeat_check_interval * 2; + serv->heartbeat_check_interval = v > 2 ? v / 2 : 1; } // max_request if (php_swoole_array_get_value(vht, "max_request", ztmp)) { @@ -3066,22 +3056,22 @@ static PHP_METHOD(swoole_server, heartbeat) { RETURN_FALSE; } - if (serv->heartbeat_idle_time < 1) { + if (serv->heartbeat_check_interval < 1) { RETURN_FALSE; } array_init(return_value); - double checktime = microtime() - serv->heartbeat_idle_time; + double now = microtime(); - serv->foreach_connection([serv, checktime, close_connection, return_value](Connection *conn) { - swTrace("heartbeat check fd=%d", conn->fd); - if (conn->protect || conn->last_recv_time == 0 || conn->last_recv_time > checktime) { - return; - } + serv->foreach_connection([serv, now, close_connection, return_value](Connection *conn) { SessionId session_id = conn->session_id; if (session_id <= 0) { return; } + swTrace("heartbeat check fd=%d", conn->fd); + if (serv->is_healthy_connection(now, conn)) { + return; + } if (close_connection) { conn->close_force = 1; serv->close(session_id, false); diff --git a/ext-src/swoole_server_port.cc b/ext-src/swoole_server_port.cc index 7c981739a6f..d657150ac9e 100644 --- a/ext-src/swoole_server_port.cc +++ b/ext-src/swoole_server_port.cc @@ -199,7 +199,10 @@ void php_swoole_server_port_minit(int module_number) { /** * [Master-Process] */ -static ssize_t php_swoole_server_length_func(Protocol *protocol, network::Socket *conn, const char *data, uint32_t length) { +static ssize_t php_swoole_server_length_func(Protocol *protocol, + network::Socket *conn, + const char *data, + uint32_t length) { Server *serv = (Server *) protocol->private_data_2; serv->lock(); @@ -309,6 +312,11 @@ static PHP_METHOD(swoole_server_port, set) { port->kernel_socket_send_buffer_size = INT_MAX; } } + // heartbeat idle time + if (php_swoole_array_get_value(vht, "heartbeat_idle_time", ztmp)) { + zend_long v = zval_get_long(ztmp); + port->heartbeat_idle_time = SW_MAX(0, SW_MIN(v, UINT16_MAX)); + } if (php_swoole_array_get_value(vht, "buffer_high_watermark", ztmp)) { zend_long v = zval_get_long(ztmp); port->buffer_high_watermark = SW_MAX(0, SW_MIN(v, UINT32_MAX)); @@ -590,7 +598,8 @@ static PHP_METHOD(swoole_server_port, set) { delete context; RETURN_FALSE; } - } ZEND_HASH_FOREACH_END(); + } + ZEND_HASH_FOREACH_END(); } if (!port->ssl_context->cert_file.empty() || port->sni_contexts.empty()) { @@ -643,7 +652,7 @@ static PHP_METHOD(swoole_server_port, on) { efree(func_name); bool found = false; - for (auto i = server_port_event_map.begin(); i!= server_port_event_map.end(); i++) { + for (auto i = server_port_event_map.begin(); i != server_port_event_map.end(); i++) { if (!swoole_strcaseeq(name, len, i->first.c_str(), i->first.length())) { continue; } @@ -651,7 +660,8 @@ static PHP_METHOD(swoole_server_port, on) { found = true; int index = i->second.type; std::string property_name = std::string("on") + i->second.name; - zend_update_property(swoole_server_port_ce, SW_Z8_OBJ_P(ZEND_THIS), property_name.c_str(), property_name.length(), cb); + zend_update_property( + swoole_server_port_ce, SW_Z8_OBJ_P(ZEND_THIS), property_name.c_str(), property_name.length(), cb); property->callbacks[index] = sw_zend_read_property(swoole_server_port_ce, ZEND_THIS, property_name.c_str(), property_name.length(), 0); sw_copy_to_stack(property->callbacks[index], property->_callbacks[index]); diff --git a/include/swoole_server.h b/include/swoole_server.h index 2139847bf5f..c9a6e7d1f69 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -255,6 +255,8 @@ struct ListenPort { network::Socket *socket = nullptr; pthread_t thread_id = 0; + uint16_t heartbeat_idle_time = 0; + /** * check data eof */ @@ -682,9 +684,7 @@ class Server { PipeBuffer **pipe_buffers = nullptr; double send_timeout = 0; - uint16_t heartbeat_idle_time = 0; uint16_t heartbeat_check_interval = 0; - uint32_t heartbeat_check_lasttime = 0; time_t reload_time = 0; time_t warning_time = 0; @@ -1098,6 +1098,8 @@ class Server { return (conn && conn->socket && conn->active && conn->socket->fd_type == SW_FD_SESSION); } + bool is_healthy_connection(double now, Connection *conn); + static int is_dgram_event(uint8_t type) { switch (type) { case SW_SERVER_EVENT_RECV_DGRAM: diff --git a/src/server/master.cc b/src/server/master.cc index ec87ee79782..6b874267648 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -315,6 +315,13 @@ int Server::start_check() { if (send_timeout > 0 && send_timeout < SW_TIMER_MIN_SEC) { send_timeout = SW_TIMER_MIN_SEC; } + if (heartbeat_check_interval > 0) { + for (auto ls : ports) { + if (ls->heartbeat_idle_time == 0) { + ls->heartbeat_idle_time = heartbeat_check_interval * 2; + } + } + } for (auto ls : ports) { if (ls->protocol.package_max_length < SW_BUFFER_MIN_SIZE) { ls->protocol.package_max_length = SW_BUFFER_MIN_SIZE; @@ -327,6 +334,12 @@ int Server::start_check() { swWarn("require onPacket callback"); return SW_ERR; } + if (ls->heartbeat_idle_time > 0) { + int expect_heartbeat_check_interval = ls->heartbeat_idle_time > 2 ? ls->heartbeat_idle_time / 2 : 1; + if (heartbeat_check_interval == 0 || heartbeat_check_interval > expect_heartbeat_check_interval) { + heartbeat_check_interval = expect_heartbeat_check_interval; + } + } } #ifdef SW_USE_OPENSSL /** @@ -1345,6 +1358,20 @@ void Server::check_port_type(ListenPort *ls) { } } +bool Server::is_healthy_connection(double now, Connection *conn) { + if (conn->protect || conn->last_recv_time == 0) { + return true; + } + auto lp = get_port_by_session_id(conn->session_id); + if (!lp) { + return true; + } + if (conn->last_recv_time > now - lp->heartbeat_idle_time) { + return true; + } + return false; +} + /** * Return the number of ports successfully */ diff --git a/src/server/reactor_process.cc b/src/server/reactor_process.cc index 8e67f4045f5..af855d12ff6 100644 --- a/src/server/reactor_process.cc +++ b/src/server/reactor_process.cc @@ -437,16 +437,10 @@ static void ReactorProcess_onTimeout(Timer *timer, TimerNode *tnode) { Event notify_ev{}; double now = microtime(); - if (now < serv->heartbeat_check_lasttime + 10) { - return; - } - notify_ev.type = SW_FD_SESSION; - int checktime = now - serv->heartbeat_idle_time; - - serv->foreach_connection([serv, checktime, reactor, ¬ify_ev](Connection *conn) { - if (conn->protect || conn->last_recv_time > checktime) { + serv->foreach_connection([serv, reactor, now, ¬ify_ev](Connection *conn) { + if (serv->is_healthy_connection(now, conn)) { return; } #ifdef SW_USE_OPENSSL diff --git a/src/server/reactor_thread.cc b/src/server/reactor_thread.cc index d50b4dcf296..4c3d8c3b878 100644 --- a/src/server/reactor_thread.cc +++ b/src/server/reactor_thread.cc @@ -780,8 +780,7 @@ int Server::start_reactor_threads() { /** * heartbeat thread */ - if (heartbeat_check_interval >= 1 && heartbeat_check_interval <= heartbeat_idle_time) { - swTrace("hb timer start, time: %d live time:%d", heartbeat_check_interval, heartbeat_idle_time); + if (heartbeat_check_interval >= 1) { start_heartbeat_thread(); } @@ -1086,15 +1085,15 @@ void Server::start_heartbeat_thread() { SwooleTG.id = reactor_num; while (running) { - double checktime = microtime() - heartbeat_idle_time; - foreach_connection([this, checktime](Connection *conn) { - if (conn->protect || conn->last_recv_time == 0 || conn->last_recv_time > checktime) { - return; - } + double now = microtime(); + foreach_connection([this, now](Connection *conn) { SessionId session_id = conn->session_id; if (session_id <= 0) { return; } + if (is_healthy_connection(now, conn)) { + return; + } DataHead ev{}; ev.type = SW_SERVER_EVENT_CLOSE_FORCE; // convert fd to session_id, in order to verify the connection before the force close connection diff --git a/tests/swoole_server_port/heartbeat_2.phpt b/tests/swoole_server_port/heartbeat_2.phpt new file mode 100644 index 00000000000..d558b3cc473 --- /dev/null +++ b/tests/swoole_server_port/heartbeat_2.phpt @@ -0,0 +1,70 @@ +--TEST-- +swoole_server_port: heartbeat 2 +--SKIPIF-- + +--FILE-- +initFreePorts(3); + +$pm->parentFunc = function ($pid) use ($pm) { + run(function () use ($pm) { + $test_func = function ($port_index, $sleep_seconds) use ($pm) { + $cli = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP); + $cli->connect('127.0.0.1', $pm->getFreePort($port_index)); + System::sleep($sleep_seconds); + return $cli->recv(0.01); + }; + go(function () use ($test_func) { + Assert::same($test_func(0, 1.3), ''); + echo "DONE 0\n"; + }); + go(function () use ($test_func) { + Assert::same($test_func(1, 2.3), ''); + echo "DONE 1\n"; + }); + go(function () use ($test_func) { + Assert::same($test_func(2, 3.3), false); + echo "DONE 2\n"; + }); + }); + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm) +{ + $server = new swoole_server('127.0.0.1', $pm->getFreePort(0), SWOOLE_BASE); + $server->set([ + 'heartbeat_check_interval' => 1, + 'heartbeat_idle_time' => 1, + ]); + $server->on('receive', function ($server, $fd, $reactorId, $data) { + $server->send($fd, 'ok'); + }); + + $port2 = $server->listen('127.0.0.1', $pm->getFreePort(1), SWOOLE_SOCK_TCP); + $port2->set([ + 'heartbeat_idle_time' => 2, + ]); + + $port3 = $server->listen('127.0.0.1', $pm->getFreePort(2), SWOOLE_SOCK_TCP); + $port3->set([ + 'heartbeat_idle_time' => 10, + ]); + + $server->start(); +}; + +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +DONE 0 +DONE 1 +DONE 2 From 7c984678f9bff8261ac629685c42df02d495120b Mon Sep 17 00:00:00 2001 From: codinghuang Date: Sat, 3 Jul 2021 13:56:10 +0800 Subject: [PATCH 171/936] Update to C99 (#4296) --- config.m4 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/config.m4 b/config.m4 index 498ff41a267..928a746cdea 100644 --- a/config.m4 +++ b/config.m4 @@ -327,9 +327,7 @@ AC_COMPILE_IFELSE([ ) AC_MSG_RESULT([$CLANG]) -if test "$CLANG" = "yes"; then - CFLAGS="$CFLAGS -std=gnu89" -fi +AC_PROG_CC_C99 AC_CANONICAL_HOST From 76202bd9b3e78dfe5819705a029f3593864adbce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Sat, 3 Jul 2021 13:56:32 +0800 Subject: [PATCH 172/936] Optimize code (#4295) * optimize code[2] * optimize code[3] * Refactor websocket, optimize code style * fix tests * fix core-tests * optimize code * Refactor http2, optimize code style * Optimize --- core-tests/include/httplib_client.h | 8 +- core-tests/src/_lib/http.cpp | 8 +- core-tests/src/server/http.cpp | 8 +- ext-src/swoole_http2_client_coro.cc | 58 +++--- ext-src/swoole_http2_server.cc | 106 +++++------ ext-src/swoole_http_client_coro.cc | 12 +- ext-src/swoole_http_request.cc | 62 +++---- ext-src/swoole_http_response.cc | 85 ++++----- ext-src/swoole_http_server.cc | 53 +++--- ext-src/swoole_http_server_coro.cc | 65 +++---- ext-src/swoole_server.cc | 2 +- ext-src/swoole_websocket_server.cc | 212 +++++++++++----------- include/swoole_http2.h | 29 +-- include/swoole_websocket.h | 132 +++++++------- src/protocol/http.cc | 18 +- src/protocol/http2.cc | 18 +- src/protocol/websocket.cc | 72 ++++---- src/server/master.cc | 3 + src/server/port.cc | 20 +- src/server/process.cc | 28 +-- tests/swoole_server_port/heartbeat.phpt | 87 --------- tests/swoole_server_port/heartbeat_1.phpt | 93 ++++++++++ tests/swoole_server_port/heartbeat_2.phpt | 6 +- tests/swoole_server_port/heartbeat_3.phpt | 60 ++++++ 24 files changed, 681 insertions(+), 564 deletions(-) delete mode 100644 tests/swoole_server_port/heartbeat.phpt create mode 100644 tests/swoole_server_port/heartbeat_1.phpt create mode 100644 tests/swoole_server_port/heartbeat_3.phpt diff --git a/core-tests/include/httplib_client.h b/core-tests/include/httplib_client.h index 6750258ad4f..aa22c03a87a 100644 --- a/core-tests/include/httplib_client.h +++ b/core-tests/include/httplib_client.h @@ -396,7 +396,7 @@ struct Response { std::function content_provider_resource_releaser_; }; -struct WebSocketFrame : public swWebSocket_frame { +struct WebSocketFrame : public swoole::websocket::Frame { WebSocketFrame() = default; ~WebSocketFrame() { if (payload) { @@ -544,10 +544,10 @@ class Client { std::shared_ptr Put(const char *path, const Headers &headers, const Params ¶ms); // websocket - inline bool Push(const std::string &data, int opcode = WEBSOCKET_OPCODE_TEXT) { - return Push(data.c_str(), data.length(), WEBSOCKET_OPCODE_TEXT); + inline bool Push(const std::string &data, int opcode = swoole::websocket::OPCODE_TEXT) { + return Push(data.c_str(), data.length(), swoole::websocket::OPCODE_TEXT); } - bool Push(const char *data, size_t length, int opcode = WEBSOCKET_OPCODE_TEXT); + bool Push(const char *data, size_t length, int opcode = swoole::websocket::OPCODE_TEXT); std::shared_ptr Recv(); std::shared_ptr Patch(const char *path, const std::string &body, const char *content_type); diff --git a/core-tests/src/_lib/http.cpp b/core-tests/src/_lib/http.cpp index b279a6dd848..bc78ccef284 100644 --- a/core-tests/src/_lib/http.cpp +++ b/core-tests/src/_lib/http.cpp @@ -2,6 +2,8 @@ #include "httplib_client.h" #include "swoole_http.h" +namespace websocket = swoole::websocket; + namespace httplib { bool Client::Upgrade(const char *_path, Headers &_headers) { @@ -29,7 +31,7 @@ bool Client::Push(const char *data, size_t length, int opcode) { buffer.size = sizeof(buf); buffer.str = buf; - swWebSocket_encode(&buffer, data, length, opcode, SW_WEBSOCKET_FLAG_FIN | SW_WEBSOCKET_FLAG_ENCODE_HEADER_ONLY); + websocket::encode(&buffer, data, length, opcode, websocket::FLAG_FIN | websocket::FLAG_ENCODE_HEADER_ONLY); strm.write(buffer.str, buffer.length); strm.write(data, length); return true; @@ -41,7 +43,7 @@ std::shared_ptr Client::Recv() { auto retval = process_socket(socket_, [&](Stream &strm) { swProtocol proto = {}; proto.package_length_size = SW_WEBSOCKET_HEADER_LEN; - proto.get_package_length = swWebSocket_get_package_length; + proto.get_package_length = websocket::get_package_length; proto.package_max_length = SW_INPUT_BUFFER_SIZE; char buf[1024]; @@ -83,7 +85,7 @@ std::shared_ptr Client::Recv() { read_bytes += n_read; } - return swWebSocket_decode(msg.get(), data, packet_len); + return websocket::decode(msg.get(), data, packet_len); }); return retval ? msg : nullptr; diff --git a/core-tests/src/server/http.cpp b/core-tests/src/server/http.cpp index fbb10b2d15d..b98af28aca8 100644 --- a/core-tests/src/server/http.cpp +++ b/core-tests/src/server/http.cpp @@ -117,11 +117,11 @@ static void test_run_server(function fn) { SessionId session_id = req->info.fd; auto conn = serv->get_connection_by_session_id(session_id); - if (conn->websocket_status == WEBSOCKET_STATUS_ACTIVE) { + if (conn->websocket_status == swoole::websocket::STATUS_ACTIVE) { sw_tg_buffer()->clear(); std::string resp = "Swoole: " + string(req->data, req->info.len); - swWebSocket_encode( - sw_tg_buffer(), resp.c_str(), resp.length(), WEBSOCKET_OPCODE_TEXT, SW_WEBSOCKET_FLAG_FIN); + swoole::websocket::encode( + sw_tg_buffer(), resp.c_str(), resp.length(), swoole::websocket::OPCODE_TEXT, swoole::websocket::FLAG_FIN); serv->send(session_id, sw_tg_buffer()->str, sw_tg_buffer()->length); return SW_OK; } @@ -151,7 +151,7 @@ static void test_run_server(function fn) { ctx.response(SW_HTTP_SWITCHING_PROTOCOLS); - conn->websocket_status = WEBSOCKET_STATUS_ACTIVE; + conn->websocket_status = swoole::websocket::STATUS_ACTIVE; return SW_OK; } diff --git a/ext-src/swoole_http2_client_coro.cc b/ext-src/swoole_http2_client_coro.cc index f143eb035c6..8417c729ee5 100644 --- a/ext-src/swoole_http2_client_coro.cc +++ b/ext-src/swoole_http2_client_coro.cc @@ -31,6 +31,8 @@ using namespace swoole; using swoole::coroutine::Socket; +namespace Http2 = swoole::http2; + static zend_class_entry *swoole_http2_client_coro_ce; static zend_object_handlers swoole_http2_client_coro_handlers; @@ -43,7 +45,9 @@ static zend_object_handlers swoole_http2_request_handlers; static zend_class_entry *swoole_http2_response_ce; static zend_object_handlers swoole_http2_response_handlers; -namespace swoole { namespace coroutine { namespace http2 { +namespace swoole { +namespace coroutine { +namespace http2 { struct Stream { uint32_t stream_id; @@ -76,8 +80,8 @@ class Client { uint32_t stream_id = 0; // the next send stream id uint32_t last_stream_id = 0; // the last received stream id - swHttp2_settings local_settings = {}; - swHttp2_settings remote_settings = {}; + Http2::Settings local_settings = {}; + Http2::Settings remote_settings = {}; std::unordered_map streams; @@ -91,7 +95,7 @@ class Client { open_ssl = _ssl; _zobject = *__zobject; zobject = &_zobject; - swHttp2_init_settings(&local_settings); + Http2::init_settings(&local_settings); } inline Stream *get_stream(uint32_t stream_id) { @@ -188,7 +192,9 @@ class Client { } }; -}}} +} // namespace http2 +} // namespace coroutine +} // namespace swoole using swoole::coroutine::http2::Client; using swoole::coroutine::http2::Stream; @@ -417,7 +423,7 @@ bool Client::connect() { client->protocol.package_length_size = SW_HTTP2_FRAME_HEADER_SIZE; client->protocol.package_length_offset = 0; client->protocol.package_body_offset = 0; - client->protocol.get_package_length = swHttp2_get_frame_length; + client->protocol.get_package_length = Http2::get_frame_length; apply_setting( sw_zend_read_property_ex(swoole_http2_client_coro_ce, zobject, SW_ZSTR_KNOWN(SW_ZEND_STR_SETTING), 0)); @@ -430,7 +436,7 @@ bool Client::connect() { stream_id = 1; // [init]: we must set default value, server is not always send all the settings - swHttp2_init_settings(&remote_settings); + Http2::init_settings(&remote_settings); int ret = nghttp2_hd_inflate_new2(&inflater, php_nghttp2_mem()); if (ret != 0) { @@ -493,7 +499,7 @@ enum swReturn_code Client::parse_frame(zval *return_value, bool pipeline_read) { uint8_t type = buf[3]; uint8_t flags = buf[4]; uint32_t stream_id = ntohl((*(int *) (buf + 5))) & 0x7fffffff; - ssize_t length = swHttp2_get_length(buf); + ssize_t length = Http2::get_length(buf); buf += SW_HTTP2_FRAME_HEADER_SIZE; char frame[SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_FRAME_PING_PAYLOAD_SIZE]; @@ -563,7 +569,7 @@ enum swReturn_code Client::parse_frame(zval *return_value, bool pipeline_read) { length -= sizeof(id) + sizeof(value); } - swHttp2_set_frame_header(frame, SW_HTTP2_TYPE_SETTINGS, 0, SW_HTTP2_FLAG_ACK, stream_id); + Http2::set_frame_header(frame, SW_HTTP2_TYPE_SETTINGS, 0, SW_HTTP2_FLAG_ACK, stream_id); if (!send(frame, SW_HTTP2_FRAME_HEADER_SIZE)) { return SW_ERROR; } @@ -585,7 +591,7 @@ enum swReturn_code Client::parse_frame(zval *return_value, bool pipeline_read) { case SW_HTTP2_TYPE_PING: { swHttp2FrameTraceLog(recv, "ping"); if (!(flags & SW_HTTP2_FLAG_ACK)) { - swHttp2_set_frame_header( + Http2::set_frame_header( frame, SW_HTTP2_TYPE_PING, SW_HTTP2_FRAME_PING_PAYLOAD_SIZE, SW_HTTP2_FLAG_ACK, stream_id); memcpy( frame + SW_HTTP2_FRAME_HEADER_SIZE, buf + SW_HTTP2_FRAME_HEADER_SIZE, SW_HTTP2_FRAME_PING_PAYLOAD_SIZE); @@ -838,18 +844,18 @@ bool Client::send_window_update(int stream_id, uint32_t size) { char frame[SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_WINDOW_UPDATE_SIZE]; swTraceLog(SW_TRACE_HTTP2, "[" SW_ECHO_YELLOW "] stream_id=%d, size=%d", "WINDOW_UPDATE", stream_id, size); *(uint32_t *) ((char *) frame + SW_HTTP2_FRAME_HEADER_SIZE) = htonl(size); - swHttp2_set_frame_header(frame, SW_HTTP2_TYPE_WINDOW_UPDATE, SW_HTTP2_WINDOW_UPDATE_SIZE, 0, stream_id); + Http2::set_frame_header(frame, SW_HTTP2_TYPE_WINDOW_UPDATE, SW_HTTP2_WINDOW_UPDATE_SIZE, 0, stream_id); return send(frame, SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_WINDOW_UPDATE_SIZE); } bool Client::send_setting() { - swHttp2_settings *settings = &local_settings; + Http2::Settings *settings = &local_settings; uint16_t id = 0; uint32_t value = 0; char frame[SW_HTTP2_FRAME_HEADER_SIZE + 18]; memset(frame, 0, sizeof(frame)); - swHttp2_set_frame_header(frame, SW_HTTP2_TYPE_SETTINGS, 18, 0, 0); + Http2::set_frame_header(frame, SW_HTTP2_TYPE_SETTINGS, 18, 0, 0); char *p = frame + SW_HTTP2_FRAME_HEADER_SIZE; /** @@ -880,7 +886,7 @@ bool Client::send_setting() { memcpy(p, &value, sizeof(value)); p += 4; - swTraceLog(SW_TRACE_HTTP2, "[" SW_ECHO_GREEN "]\t[length=%d]", swHttp2_get_type(SW_HTTP2_TYPE_SETTINGS), 18); + swTraceLog(SW_TRACE_HTTP2, "[" SW_ECHO_GREEN "]\t[length=%d]", Http2::get_type(SW_HTTP2_TYPE_SETTINGS), 18); return send(frame, SW_HTTP2_FRAME_HEADER_SIZE + 18); } @@ -1110,7 +1116,7 @@ Stream *Client::create_stream(uint32_t stream_id, uint8_t flags) { bool Client::send_ping_frame() { char frame[SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_FRAME_PING_PAYLOAD_SIZE]; - swHttp2_set_frame_header(frame, SW_HTTP2_TYPE_PING, SW_HTTP2_FRAME_PING_PAYLOAD_SIZE, SW_HTTP2_FLAG_NONE, 0); + Http2::set_frame_header(frame, SW_HTTP2_TYPE_PING, SW_HTTP2_FRAME_PING_PAYLOAD_SIZE, SW_HTTP2_FLAG_NONE, 0); return send(frame, SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_FRAME_PING_PAYLOAD_SIZE); } @@ -1126,7 +1132,7 @@ bool Client::send_data(uint32_t stream_id, const char *p, size_t len, int flag) send_len = len; send_flag = flag; } - swHttp2_set_frame_header(header, SW_HTTP2_TYPE_DATA, send_len, send_flag, stream_id); + Http2::set_frame_header(header, SW_HTTP2_TYPE_DATA, send_len, send_flag, stream_id); if (!send(header, SW_HTTP2_FRAME_HEADER_SIZE)) { return false; } @@ -1180,11 +1186,11 @@ uint32_t Client::send_request(zval *zrequest) { flags |= SW_HTTP2_FLAG_END_STREAM; } - swHttp2_set_frame_header(buffer, SW_HTTP2_TYPE_HEADERS, bytes, flags, stream->stream_id); + Http2::set_frame_header(buffer, SW_HTTP2_TYPE_HEADERS, bytes, flags, stream->stream_id); swTraceLog(SW_TRACE_HTTP2, "[" SW_ECHO_GREEN ", STREAM#%d] length=%zd", - swHttp2_get_type(SW_HTTP2_TYPE_HEADERS), + Http2::get_type(SW_HTTP2_TYPE_HEADERS), stream->stream_id, bytes); if (!send(buffer, SW_HTTP2_FRAME_HEADER_SIZE + bytes)) { @@ -1215,7 +1221,7 @@ uint32_t Client::send_request(zval *zrequest) { swTraceLog(SW_TRACE_HTTP2, "[" SW_ECHO_GREEN ", END, STREAM#%d] length=%zu", - swHttp2_get_type(SW_HTTP2_TYPE_DATA), + Http2::get_type(SW_HTTP2_TYPE_DATA), stream->stream_id, len); @@ -1253,10 +1259,10 @@ bool Client::write_data(uint32_t stream_id, zval *zdata, bool end) { php_swoole_error(E_WARNING, "http_build_query failed"); return false; } - swHttp2_set_frame_header(buffer, SW_HTTP2_TYPE_DATA, len, flag, stream_id); + Http2::set_frame_header(buffer, SW_HTTP2_TYPE_DATA, len, flag, stream_id); swTraceLog(SW_TRACE_HTTP2, "[" SW_ECHO_GREEN ",%s STREAM#%d] length=%zu", - swHttp2_get_type(SW_HTTP2_TYPE_DATA), + Http2::get_type(SW_HTTP2_TYPE_DATA), end ? " END," : "", stream_id, len); @@ -1267,10 +1273,10 @@ bool Client::write_data(uint32_t stream_id, zval *zdata, bool end) { smart_str_free(&formstr_s); } else { zend::String data(zdata); - swHttp2_set_frame_header(buffer, SW_HTTP2_TYPE_DATA, data.len(), flag, stream_id); + Http2::set_frame_header(buffer, SW_HTTP2_TYPE_DATA, data.len(), flag, stream_id); swTraceLog(SW_TRACE_HTTP2, "[" SW_ECHO_GREEN ",%s STREAM#%d] length=%zu", - swHttp2_get_type(SW_HTTP2_TYPE_DATA), + Http2::get_type(SW_HTTP2_TYPE_DATA), end ? " END," : "", stream_id, data.len()); @@ -1290,7 +1296,7 @@ bool Client::send_goaway_frame(zend_long error_code, const char *debug_data, siz size_t length = SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_GOAWAY_SIZE + debug_data_len; char *frame = (char *) ecalloc(1, length); bool ret; - swHttp2_set_frame_header(frame, SW_HTTP2_TYPE_GOAWAY, SW_HTTP2_GOAWAY_SIZE + debug_data_len, error_code, 0); + Http2::set_frame_header(frame, SW_HTTP2_TYPE_GOAWAY, SW_HTTP2_GOAWAY_SIZE + debug_data_len, error_code, 0); *(uint32_t *) (frame + SW_HTTP2_FRAME_HEADER_SIZE) = htonl(last_stream_id); *(uint32_t *) (frame + SW_HTTP2_FRAME_HEADER_SIZE + 4) = htonl(error_code); if (debug_data_len > 0) { @@ -1298,7 +1304,7 @@ bool Client::send_goaway_frame(zend_long error_code, const char *debug_data, siz } swTraceLog(SW_TRACE_HTTP2, "[" SW_ECHO_GREEN "] Send: last-sid=%u, error-code=%ld", - swHttp2_get_type(SW_HTTP2_TYPE_GOAWAY), + Http2::get_type(SW_HTTP2_TYPE_GOAWAY), last_stream_id, error_code); ret = send(frame, length); @@ -1371,7 +1377,7 @@ static PHP_METHOD(swoole_http2_client_coro, connect) { RETURN_BOOL(h2c->connect()); } -static sw_inline void http2_settings_to_array(swHttp2_settings *settings, zval *zarray) { +static sw_inline void http2_settings_to_array(Http2::Settings *settings, zval *zarray) { array_init(zarray); add_assoc_long_ex(zarray, ZEND_STRL("header_table_size"), settings->header_table_size); add_assoc_long_ex(zarray, ZEND_STRL("window_size"), settings->window_size); diff --git a/ext-src/swoole_http2_server.cc b/ext-src/swoole_http2_server.cc index e57ec30ca0b..414f954dc6e 100644 --- a/ext-src/swoole_http2_server.cc +++ b/ext-src/swoole_http2_server.cc @@ -27,14 +27,16 @@ using std::string; using swoole::coroutine::System; using swoole::http_server::StaticHandler; -using http_context = swoole::http::Context; -using Http2Stream = swoole::http2::Stream; -using Http2Session = swoole::http2::Session; +namespace Http2 = swoole::http2; + +using HttpContext = swoole::http::Context; +using Http2Stream = Http2::Stream; +using Http2Session = Http2::Session; static std::unordered_map http2_sessions; extern String *swoole_http_buffer; -static bool swoole_http2_server_respond(http_context *ctx, String *body); +static bool swoole_http2_server_respond(HttpContext *ctx, String *body); Http2Stream::Stream(Http2Session *client, uint32_t _id) { ctx = swoole_http_context_new(client->fd); @@ -57,7 +59,7 @@ void Http2Stream::reset(uint32_t error_code) { char frame[SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_RST_STREAM_SIZE]; swTraceLog(SW_TRACE_HTTP2, "send [" SW_ECHO_YELLOW "] stream_id=%u, error_code=%u", "RST_STREAM", id, error_code); *(uint32_t *) ((char *) frame + SW_HTTP2_FRAME_HEADER_SIZE) = htonl(error_code); - swHttp2_set_frame_header(frame, SW_HTTP2_TYPE_RST_STREAM, SW_HTTP2_RST_STREAM_SIZE, 0, id); + http2::set_frame_header(frame, SW_HTTP2_TYPE_RST_STREAM, SW_HTTP2_RST_STREAM_SIZE, 0, id); ctx->send(ctx, frame, SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_RST_STREAM_SIZE); } @@ -90,21 +92,21 @@ Http2Session::~Session() { http2_sessions.erase(fd); } -static void http2_server_send_window_update(http_context *ctx, uint32_t stream_id, uint32_t size) { +static void http2_server_send_window_update(HttpContext *ctx, uint32_t stream_id, uint32_t size) { char frame[SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_WINDOW_UPDATE_SIZE]; swTraceLog(SW_TRACE_HTTP2, "send [" SW_ECHO_YELLOW "] stream_id=%u, size=%u", "WINDOW_UPDATE", stream_id, size); *(uint32_t *) ((char *) frame + SW_HTTP2_FRAME_HEADER_SIZE) = htonl(size); - swHttp2_set_frame_header(frame, SW_HTTP2_TYPE_WINDOW_UPDATE, SW_HTTP2_WINDOW_UPDATE_SIZE, 0, stream_id); + Http2::set_frame_header(frame, SW_HTTP2_TYPE_WINDOW_UPDATE, SW_HTTP2_WINDOW_UPDATE_SIZE, 0, stream_id); ctx->send(ctx, frame, SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_WINDOW_UPDATE_SIZE); } -static ssize_t http2_build_trailer(http_context *ctx, uchar *buffer) { +static ssize_t http2_build_trailer(HttpContext *ctx, uchar *buffer) { zval *ztrailer = sw_zend_read_property_ex(swoole_http_response_ce, ctx->response.zobject, SW_ZSTR_KNOWN(SW_ZEND_STR_TRAILER), 0); uint32_t size = php_swoole_array_length_safe(ztrailer); if (size > 0) { - http2::HeaderSet trailer(size); + Http2::HeaderSet trailer(size); zend_string *key; zval *zvalue; @@ -149,7 +151,7 @@ static ssize_t http2_build_trailer(http_context *ctx, uchar *buffer) { return 0; } -static bool swoole_http2_is_static_file(Server *serv, http_context *ctx) { +static bool swoole_http2_is_static_file(Server *serv, HttpContext *ctx) { zval *zserver = ctx->request.zserver; zval *zrequest_uri = zend_hash_str_find(Z_ARR_P(zserver), ZEND_STRL("request_uri")); if (zrequest_uri && Z_TYPE_P(zrequest_uri) == IS_STRING) { @@ -195,7 +197,7 @@ static bool swoole_http2_is_static_file(Server *serv, http_context *ctx) { } static void swoole_http2_onRequest(Http2Session *client, Http2Stream *stream) { - http_context *ctx = stream->ctx; + HttpContext *ctx = stream->ctx; zval *zserver = ctx->request.zserver; Server *serv = (Server *) ctx->private_data; @@ -232,12 +234,12 @@ static void swoole_http2_onRequest(Http2Session *client, Http2Stream *stream) { zval_ptr_dtor(&args[1]); } -static ssize_t http2_build_header(http_context *ctx, uchar *buffer, size_t body_length) { +static ssize_t http2_build_header(HttpContext *ctx, uchar *buffer, size_t body_length) { zval *zheader = sw_zend_read_property_ex(swoole_http_response_ce, ctx->response.zobject, SW_ZSTR_KNOWN(SW_ZEND_STR_HEADER), 0); zval *zcookie = sw_zend_read_property_ex(swoole_http_response_ce, ctx->response.zobject, SW_ZSTR_KNOWN(SW_ZEND_STR_COOKIE), 0); - http2::HeaderSet headers(32 + php_swoole_array_length_safe(zheader) + php_swoole_array_length_safe(zcookie)); + Http2::HeaderSet headers(32 + php_swoole_array_length_safe(zheader) + php_swoole_array_length_safe(zcookie)); char *date_str = nullptr; char intbuf[2][16]; int ret; @@ -260,26 +262,27 @@ static ssize_t http2_build_header(http_context *ctx, uchar *buffer, size_t body_ zval *zvalue; int type; - auto add_header = [](http2::HeaderSet &headers, const char *key, size_t l_key, zval *value, uint32_t &header_flags) { - if (ZVAL_IS_NULL(value)) { - return; - } - zend::String str_value(value); - str_value.rtrim(); - if (swoole_http_has_crlf(str_value.val(), str_value.len())) { - return; - } - if (SW_STREQ(key, l_key, "server")) { - header_flags |= HTTP_HEADER_SERVER; - } else if (SW_STREQ(key, l_key, "content-length")) { - return; // ignore - } else if (SW_STREQ(key, l_key, "date")) { - header_flags |= HTTP_HEADER_DATE; - } else if (SW_STREQ(key, l_key, "content-type")) { - header_flags |= HTTP_HEADER_CONTENT_TYPE; - } - headers.add(key, l_key, str_value.val(), str_value.len()); - }; + auto add_header = + [](Http2::HeaderSet &headers, const char *key, size_t l_key, zval *value, uint32_t &header_flags) { + if (ZVAL_IS_NULL(value)) { + return; + } + zend::String str_value(value); + str_value.rtrim(); + if (swoole_http_has_crlf(str_value.val(), str_value.len())) { + return; + } + if (SW_STREQ(key, l_key, "server")) { + header_flags |= HTTP_HEADER_SERVER; + } else if (SW_STREQ(key, l_key, "content-length")) { + return; // ignore + } else if (SW_STREQ(key, l_key, "date")) { + header_flags |= HTTP_HEADER_DATE; + } else if (SW_STREQ(key, l_key, "content-type")) { + header_flags |= HTTP_HEADER_CONTENT_TYPE; + } + headers.add(key, l_key, str_value.val(), str_value.len()); + }; SW_HASHTABLE_FOREACH_START2(Z_ARRVAL_P(zheader), key, keylen, type, zvalue) { if (UNEXPECTED(!key || ZVAL_IS_NULL(zvalue))) { @@ -371,19 +374,19 @@ static ssize_t http2_build_header(http_context *ctx, uchar *buffer, size_t body_ return rv; } -int swoole_http2_server_ping(http_context *ctx) { +int swoole_http2_server_ping(HttpContext *ctx) { char frame[SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_FRAME_PING_PAYLOAD_SIZE]; - swHttp2_set_frame_header(frame, SW_HTTP2_TYPE_PING, SW_HTTP2_FRAME_PING_PAYLOAD_SIZE, SW_HTTP2_FLAG_NONE, 0); + Http2::set_frame_header(frame, SW_HTTP2_TYPE_PING, SW_HTTP2_FRAME_PING_PAYLOAD_SIZE, SW_HTTP2_FLAG_NONE, 0); return ctx->send(ctx, frame, SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_FRAME_PING_PAYLOAD_SIZE) ? SW_OK : SW_ERR; } -int swoole_http2_server_goaway(http_context *ctx, zend_long error_code, const char *debug_data, size_t debug_data_len) { +int swoole_http2_server_goaway(HttpContext *ctx, zend_long error_code, const char *debug_data, size_t debug_data_len) { size_t length = SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_GOAWAY_SIZE + debug_data_len; char *frame = (char *) ecalloc(1, length); bool ret; Http2Session *client = http2_sessions[ctx->fd]; uint32_t last_stream_id = client->last_stream_id; - swHttp2_set_frame_header(frame, SW_HTTP2_TYPE_GOAWAY, SW_HTTP2_GOAWAY_SIZE + debug_data_len, error_code, 0); + Http2::set_frame_header(frame, SW_HTTP2_TYPE_GOAWAY, SW_HTTP2_GOAWAY_SIZE + debug_data_len, error_code, 0); *(uint32_t *) (frame + SW_HTTP2_FRAME_HEADER_SIZE) = htonl(last_stream_id); *(uint32_t *) (frame + SW_HTTP2_FRAME_HEADER_SIZE + 4) = htonl(error_code); if (debug_data_len > 0) { @@ -420,10 +423,10 @@ bool Http2Stream::send_header(size_t body_length, bool end_stream) { char frame_header[SW_HTTP2_FRAME_HEADER_SIZE]; if (end_stream && body_length == 0) { - swHttp2_set_frame_header( + http2::set_frame_header( frame_header, SW_HTTP2_TYPE_HEADERS, bytes, SW_HTTP2_FLAG_END_HEADERS | SW_HTTP2_FLAG_END_STREAM, id); } else { - swHttp2_set_frame_header(frame_header, SW_HTTP2_TYPE_HEADERS, bytes, SW_HTTP2_FLAG_END_HEADERS, id); + http2::set_frame_header(frame_header, SW_HTTP2_TYPE_HEADERS, bytes, SW_HTTP2_FLAG_END_HEADERS, id); } swoole_http_buffer->append(frame_header, SW_HTTP2_FRAME_HEADER_SIZE); @@ -455,7 +458,7 @@ bool Http2Stream::send_body(swString *body, bool end_stream, size_t max_frame_si send_n = l; _send_flag = flag; } - swHttp2_set_frame_header(frame_header, SW_HTTP2_TYPE_DATA, send_n, _send_flag, id); + http2::set_frame_header(frame_header, SW_HTTP2_TYPE_DATA, send_n, _send_flag, id); swoole_http_buffer->append(frame_header, SW_HTTP2_FRAME_HEADER_SIZE); swoole_http_buffer->append(p, send_n); @@ -477,7 +480,7 @@ bool Http2Stream::send_trailer() { swoole_http_buffer->clear(); ssize_t bytes = http2_build_trailer(ctx, (uchar *) header_buffer); if (bytes > 0) { - swHttp2_set_frame_header( + http2::set_frame_header( frame_header, SW_HTTP2_TYPE_HEADERS, bytes, SW_HTTP2_FLAG_END_HEADERS | SW_HTTP2_FLAG_END_STREAM, id); swoole_http_buffer->append(frame_header, SW_HTTP2_FRAME_HEADER_SIZE); swoole_http_buffer->append(header_buffer, bytes); @@ -489,7 +492,7 @@ bool Http2Stream::send_trailer() { return true; } -static bool swoole_http2_server_respond(http_context *ctx, String *body) { +static bool swoole_http2_server_respond(HttpContext *ctx, String *body) { Http2Session *client = http2_sessions[ctx->fd]; Http2Stream *stream = ctx->stream; @@ -580,7 +583,7 @@ static bool swoole_http2_server_respond(http_context *ctx, String *body) { return !error; } -static bool http2_context_sendfile(http_context *ctx, const char *file, uint32_t l_file, off_t offset, size_t length) { +static bool http2_context_sendfile(HttpContext *ctx, const char *file, uint32_t l_file, off_t offset, size_t length) { Http2Session *client = http2_sessions[ctx->fd]; Http2Stream *stream = (Http2Stream *) ctx->stream; std::shared_ptr body; @@ -652,7 +655,7 @@ static bool http2_context_sendfile(http_context *ctx, const char *file, uint32_t return true; } -static int http2_parse_header(Http2Session *client, http_context *ctx, int flags, const char *in, size_t inlen) { +static int http2_parse_header(Http2Session *client, HttpContext *ctx, int flags, const char *in, size_t inlen) { nghttp2_hd_inflater *inflater = client->inflater; if (!inflater) { @@ -784,11 +787,12 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { } if (client->shutting_down) { - swoole_error_log(SW_LOG_WARNING, SW_ERROR_HTTP2_STREAM_IGNORE, "ignore http2 stream#%d after sending goaway", stream_id); + swoole_error_log( + SW_LOG_WARNING, SW_ERROR_HTTP2_STREAM_IGNORE, "ignore http2 stream#%d after sending goaway", stream_id); return retval; } - ssize_t length = swHttp2_get_length(buf); + ssize_t length = Http2::get_length(buf); buf += SW_HTTP2_FRAME_HEADER_SIZE; uint16_t id = 0; @@ -850,7 +854,7 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { case SW_HTTP2_TYPE_HEADERS: { stream = client->streams[stream_id]; swHttp2FrameTraceLog(recv, "%s", (stream ? "exist stream" : "new stream")); - http_context *ctx; + HttpContext *ctx; if (!stream) { stream = new Http2Stream(client, stream_id); if (sw_unlikely(!stream->ctx)) { @@ -884,7 +888,7 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { return SW_ERR; } stream = stream_iterator->second; - http_context *ctx = stream->ctx; + HttpContext *ctx = stream->ctx; zend_update_property_long( swoole_http_request_ce, SW_Z8_OBJ_P(ctx->request.zobject), ZEND_STRL("streamId"), stream_id); @@ -938,7 +942,7 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { swHttp2FrameTraceLog(recv, "ping"); if (!(flags & SW_HTTP2_FLAG_ACK)) { char ping_frame[SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_FRAME_PING_PAYLOAD_SIZE]; - swHttp2_set_frame_header( + Http2::set_frame_header( ping_frame, SW_HTTP2_TYPE_PING, SW_HTTP2_FRAME_PING_PAYLOAD_SIZE, SW_HTTP2_FLAG_ACK, stream_id); memcpy(ping_frame + SW_HTTP2_FRAME_HEADER_SIZE, buf, SW_HTTP2_FRAME_PING_PAYLOAD_SIZE); client->default_ctx->send( @@ -1010,7 +1014,7 @@ int swoole_http2_server_onFrame(Server *serv, Connection *conn, RecvData *req) { client->handle = swoole_http2_onRequest; if (!client->default_ctx) { - client->default_ctx = new http_context(); + client->default_ctx = new HttpContext(); client->default_ctx->init(serv); client->default_ctx->fd = session_id; client->default_ctx->http2 = true; @@ -1036,7 +1040,7 @@ void swoole_http2_server_session_free(Connection *conn) { delete client; } -void http_context::http2_end(zval *zdata, zval *return_value) { +void HttpContext::http2_end(zval *zdata, zval *return_value) { String http_body = {}; if (zdata) { http_body.length = php_swoole_get_send_data(zdata, &http_body.str); diff --git a/ext-src/swoole_http_client_coro.cc b/ext-src/swoole_http_client_coro.cc index e863238e892..b59142d135f 100644 --- a/ext-src/swoole_http_client_coro.cc +++ b/ext-src/swoole_http_client_coro.cc @@ -50,6 +50,8 @@ using swoole::String; using swoole::coroutine::Socket; using swoole::network::Address; +namespace WebSocket = swoole::websocket; + enum http_client_error_status_code { HTTP_CLIENT_ESTATUS_CONNECT_FAILED = -1, HTTP_CLIENT_ESTATUS_REQUEST_TIMEOUT = -2, @@ -179,7 +181,7 @@ class HttpClient { void recv(zval *zframe, double timeout = 0); bool recv_http_response(double timeout = 0); bool upgrade(std::string path); - bool push(zval *zdata, zend_long opcode = WEBSOCKET_OPCODE_TEXT, uint8_t flags = SW_WEBSOCKET_FLAG_FIN); + bool push(zval *zdata, zend_long opcode = websocket::OPCODE_TEXT, uint8_t flags = websocket::FLAG_FIN); bool close(const bool should_be_reset = true); void get_header_out(zval *return_value) { @@ -1391,7 +1393,7 @@ bool HttpClient::recv(double timeout) { socket->protocol.package_length_size = SW_WEBSOCKET_HEADER_LEN; socket->protocol.package_length_offset = 0; socket->protocol.package_body_offset = 0; - socket->protocol.get_package_length = swWebSocket_get_package_length; + socket->protocol.get_package_length = websocket::get_package_length; } // handler keep alive if (!keep_alive && !websocket) { @@ -2093,9 +2095,9 @@ static PHP_METHOD(swoole_http_client_coro, upgrade) { static PHP_METHOD(swoole_http_client_coro, push) { HttpClient *phc = php_swoole_get_phc(ZEND_THIS); zval *zdata; - zend_long opcode = WEBSOCKET_OPCODE_TEXT; + zend_long opcode = WebSocket::OPCODE_TEXT; zval *zflags = nullptr; - zend_long flags = SW_WEBSOCKET_FLAG_FIN; + zend_long flags = WebSocket::FLAG_FIN; ZEND_PARSE_PARAMETERS_START(1, 3) Z_PARAM_ZVAL(zdata) @@ -2108,7 +2110,7 @@ static PHP_METHOD(swoole_http_client_coro, push) { flags = zval_get_long(zflags); } - RETURN_BOOL(phc->push(zdata, opcode, flags & SW_WEBSOCKET_FLAGS_ALL)); + RETURN_BOOL(phc->push(zdata, opcode, flags & WebSocket::FLAGS_ALL)); } static PHP_METHOD(swoole_http_client_coro, recv) { diff --git a/ext-src/swoole_http_request.cc b/ext-src/swoole_http_request.cc index 426453724f9..73b9d24879d 100644 --- a/ext-src/swoole_http_request.cc +++ b/ext-src/swoole_http_request.cc @@ -40,12 +40,12 @@ enum http_upload_errno { HTTP_UPLOAD_ERR_CANT_WRITE, }; -using http_request = swoole::http::Request; -using http_context = swoole::http::Context; -using swoole::Server; +using HttpRequest = swoole::http::Request; +using HttpContext = swoole::http::Context; using swoole::Connection; using swoole::ListenPort; using swoole::microtime; +using swoole::Server; static int http_request_on_path(swoole_http_parser *parser, const char *at, size_t length); static int http_request_on_query_string(swoole_http_parser *parser, const char *at, size_t length); @@ -62,7 +62,7 @@ static int multipart_body_on_header_complete(multipart_parser *p); static int multipart_body_on_data_end(multipart_parser *p); static int http_request_on_path(swoole_http_parser *parser, const char *at, size_t length) { - http_context *ctx = (http_context *) parser->data; + HttpContext *ctx = (HttpContext *) parser->data; ctx->request.path = estrndup(at, length); ctx->request.path_len = length; return 0; @@ -126,7 +126,7 @@ static const multipart_parser_settings mt_parser_settings = }; // clang-format on -size_t http_context::parse(const char *data, size_t length) { +size_t HttpContext::parse(const char *data, size_t length) { return swoole_http_parser_execute(&parser, &http_parser_settings, data, length); } @@ -134,7 +134,7 @@ zend_class_entry *swoole_http_request_ce; static zend_object_handlers swoole_http_request_handlers; typedef struct { - http_context *ctx; + HttpContext *ctx; zend_object std; } http_request_t; @@ -142,17 +142,17 @@ static sw_inline http_request_t *php_swoole_http_request_fetch_object(zend_objec return (http_request_t *) ((char *) obj - swoole_http_request_handlers.offset); } -http_context *php_swoole_http_request_get_context(zval *zobject) { +HttpContext *php_swoole_http_request_get_context(zval *zobject) { return php_swoole_http_request_fetch_object(Z_OBJ_P(zobject))->ctx; } -void php_swoole_http_request_set_context(zval *zobject, http_context *ctx) { +void php_swoole_http_request_set_context(zval *zobject, HttpContext *ctx) { php_swoole_http_request_fetch_object(Z_OBJ_P(zobject))->ctx = ctx; } static void php_swoole_http_request_free_object(zend_object *object) { http_request_t *request = php_swoole_http_request_fetch_object(object); - http_context *ctx = request->ctx; + HttpContext *ctx = request->ctx; zval zobject, *ztmpfiles; ZVAL_OBJ(&zobject, object); @@ -248,7 +248,7 @@ void php_swoole_http_request_minit(int module_number) { } static int http_request_on_query_string(swoole_http_parser *parser, const char *at, size_t length) { - http_context *ctx = (http_context *) parser->data; + HttpContext *ctx = (HttpContext *) parser->data; add_assoc_stringl_ex(ctx->request.zserver, ZEND_STRL("query_string"), (char *) at, length); // parse url params sapi_module.treat_data(PARSE_STRING, @@ -259,13 +259,13 @@ static int http_request_on_query_string(swoole_http_parser *parser, const char * } static int http_request_on_header_field(swoole_http_parser *parser, const char *at, size_t length) { - http_context *ctx = (http_context *) parser->data; + HttpContext *ctx = (HttpContext *) parser->data; ctx->current_header_name = (char *) at; ctx->current_header_name_len = length; return 0; } -bool http_context::parse_form_data(const char *boundary_str, int boundary_len) { +bool HttpContext::parse_form_data(const char *boundary_str, int boundary_len) { mt_parser = multipart_parser_init(boundary_str, boundary_len, &mt_parser_settings); if (!mt_parser) { php_swoole_fatal_error(E_WARNING, "multipart_parser_init() failed"); @@ -363,7 +363,7 @@ void swoole_http_parse_cookie(zval *zarray, const char *at, size_t length) { static int http_request_on_header_value(swoole_http_parser *parser, const char *at, size_t length) { size_t offset = 0; - http_context *ctx = (http_context *) parser->data; + HttpContext *ctx = (HttpContext *) parser->data; zval *zheader = ctx->request.zheader; size_t header_len = ctx->current_header_name_len; char *header_name = zend_str_tolower_dup(ctx->current_header_name, header_len); @@ -388,7 +388,7 @@ static int http_request_on_header_value(swoole_http_parser *parser, const char * } ListenPort *port = serv->get_port_by_server_fd(conn->server_fd); if (port->open_websocket_protocol) { - conn->websocket_status = WEBSOCKET_STATUS_CONNECTION; + conn->websocket_status = swoole::websocket::STATUS_CONNECTION; } } else if ((parser->method == PHP_HTTP_POST || parser->method == PHP_HTTP_PUT || parser->method == PHP_HTTP_DELETE || parser->method == PHP_HTTP_PATCH) && @@ -445,7 +445,7 @@ static int http_request_on_header_value(swoole_http_parser *parser, const char * } static int http_request_on_headers_complete(swoole_http_parser *parser) { - http_context *ctx = (http_context *) parser->data; + HttpContext *ctx = (HttpContext *) parser->data; const char *vpath = ctx->request.path, *end = vpath + ctx->request.path_len, *p = end; zval *zserver = ctx->request.zserver; @@ -481,7 +481,7 @@ static int http_request_on_headers_complete(swoole_http_parser *parser) { } static int multipart_body_on_header_field(multipart_parser *p, const char *at, size_t length) { - http_context *ctx = (http_context *) p->data; + HttpContext *ctx = (HttpContext *) p->data; return http_request_on_header_field(&ctx->parser, at, length); } @@ -490,7 +490,7 @@ static int multipart_body_on_header_value(multipart_parser *p, const char *at, s int value_len; int ret = 0; - http_context *ctx = (http_context *) p->data; + HttpContext *ctx = (HttpContext *) p->data; /** * Hash collision attack */ @@ -584,7 +584,7 @@ static int multipart_body_on_header_value(multipart_parser *p, const char *at, s } static int multipart_body_on_data(multipart_parser *p, const char *at, size_t length) { - http_context *ctx = (http_context *) p->data; + HttpContext *ctx = (HttpContext *) p->data; if (ctx->current_form_data_name) { swoole_http_form_data_buffer->append(at, length); return 0; @@ -621,7 +621,7 @@ static void get_random_file_name(char *des, const char *src) #endif static int multipart_body_on_header_complete(multipart_parser *p) { - http_context *ctx = (http_context *) p->data; + HttpContext *ctx = (HttpContext *) p->data; if (!ctx->current_input_name) { return 0; } @@ -665,7 +665,7 @@ static int multipart_body_on_header_complete(multipart_parser *p) { } static int multipart_body_on_data_end(multipart_parser *p) { - http_context *ctx = (http_context *) p->data; + HttpContext *ctx = (HttpContext *) p->data; if (ctx->current_form_data_name) { php_register_variable_safe( @@ -745,7 +745,7 @@ static int http_request_on_body(swoole_http_parser *parser, const char *at, size return 0; } - http_context *ctx = (http_context *) parser->data; + HttpContext *ctx = (HttpContext *) parser->data; bool is_beginning = (ctx->request.chunked_body ? ctx->request.chunked_body->length : ctx->request.body_length) == 0; if (ctx->recv_chunked) { @@ -785,7 +785,7 @@ static int http_request_on_body(swoole_http_parser *parser, const char *at, size } static int http_request_message_complete(swoole_http_parser *parser) { - http_context *ctx = (http_context *) parser->data; + HttpContext *ctx = (HttpContext *) parser->data; size_t content_length = ctx->request.chunked_body ? ctx->request.chunked_body->length : ctx->request.body_length; if (ctx->request.chunked_body != nullptr && ctx->parse_body && ctx->request.post_form_urlencoded) { @@ -808,7 +808,7 @@ static int http_request_message_complete(swoole_http_parser *parser) { } #ifdef SW_HAVE_COMPRESSION -void http_context::set_compression_method(const char *accept_encoding, size_t length) { +void HttpContext::set_compression_method(const char *accept_encoding, size_t length) { #ifdef SW_HAVE_BROTLI if (swoole_strnpos(accept_encoding, length, ZEND_STRL("br")) >= 0) { accept_compression = 1; @@ -826,7 +826,7 @@ void http_context::set_compression_method(const char *accept_encoding, size_t le } } -const char *http_context::get_content_encoding() { +const char *HttpContext::get_content_encoding() { if (compression_method == HTTP_COMPRESS_GZIP) { return "gzip"; } else if (compression_method == HTTP_COMPRESS_DEFLATE) { @@ -844,12 +844,12 @@ const char *http_context::get_content_encoding() { #endif static PHP_METHOD(swoole_http_request, rawContent) { - http_context *ctx = php_swoole_http_request_get_and_check_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_request_get_and_check_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { RETURN_FALSE; } - http_request *req = &ctx->request; + HttpRequest *req = &ctx->request; if (req->body_length > 0) { zval *zdata = &req->zdata; RETURN_STRINGL(Z_STRVAL_P(zdata) + Z_STRLEN_P(zdata) - req->body_length, req->body_length); @@ -866,7 +866,7 @@ static PHP_METHOD(swoole_http_request, rawContent) { } static PHP_METHOD(swoole_http_request, getData) { - http_context *ctx = php_swoole_http_request_get_and_check_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_request_get_and_check_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { RETURN_FALSE; } @@ -893,7 +893,7 @@ static PHP_METHOD(swoole_http_request, create) { Z_PARAM_ARRAY(zoptions) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - http_context *ctx = new http_context(); + HttpContext *ctx = new HttpContext(); object_init_ex(return_value, swoole_http_request_ce); zval *zrequest_object = &ctx->request._zobject; ctx->request.zobject = zrequest_object; @@ -954,7 +954,7 @@ static PHP_METHOD(swoole_http_request, create) { } static PHP_METHOD(swoole_http_request, parse) { - http_context *ctx = php_swoole_http_request_get_and_check_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_request_get_and_check_context(ZEND_THIS); if (UNEXPECTED(!ctx) || ctx->completed) { RETURN_FALSE; } @@ -983,7 +983,7 @@ static PHP_METHOD(swoole_http_request, parse) { } static PHP_METHOD(swoole_http_request, getMethod) { - http_context *ctx = php_swoole_http_request_get_and_check_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_request_get_and_check_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { RETURN_FALSE; } @@ -992,7 +992,7 @@ static PHP_METHOD(swoole_http_request, getMethod) { } static PHP_METHOD(swoole_http_request, isCompleted) { - http_context *ctx = php_swoole_http_request_get_and_check_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_request_get_and_check_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { RETURN_FALSE; } diff --git a/ext-src/swoole_http_response.cc b/ext-src/swoole_http_response.cc index e2c9cf2f46a..f8edb299b2b 100644 --- a/ext-src/swoole_http_response.cc +++ b/ext-src/swoole_http_response.cc @@ -31,14 +31,17 @@ using swoole::Server; using swoole::String; using swoole::substr_len; using swoole::coroutine::Socket; -using http_response = swoole::http::Response; -using http_context = swoole::http::Context; + +using HttpResponse = swoole::http::Response; +using HttpContext = swoole::http::Context; + +namespace WebSocket = swoole::websocket; zend_class_entry *swoole_http_response_ce; static zend_object_handlers swoole_http_response_handlers; -static void http_build_header(http_context *ctx, String *response, size_t body_length); -static ssize_t http_build_trailer(http_context *ctx, String *response); +static void http_build_header(HttpContext *ctx, String *response, size_t body_length); +static ssize_t http_build_trailer(HttpContext *ctx, String *response); static inline void http_header_key_format(char *key, int length) { int i, state = 0; @@ -58,7 +61,7 @@ static inline void http_header_key_format(char *key, int length) { } } -String *http_context::get_write_buffer() { +String *HttpContext::get_write_buffer() { if (co_socket) { String *buffer = ((Socket *) private_data)->get_write_buffer(); if (buffer != nullptr) { @@ -69,7 +72,7 @@ String *http_context::get_write_buffer() { } typedef struct { - http_context *ctx; + HttpContext *ctx; zend_object std; } http_response_t; @@ -77,17 +80,17 @@ static sw_inline http_response_t *php_swoole_http_response_fetch_object(zend_obj return (http_response_t *) ((char *) obj - swoole_http_response_handlers.offset); } -http_context *php_swoole_http_response_get_context(zval *zobject) { +HttpContext *php_swoole_http_response_get_context(zval *zobject) { return php_swoole_http_response_fetch_object(Z_OBJ_P(zobject))->ctx; } -void php_swoole_http_response_set_context(zval *zobject, http_context *ctx) { +void php_swoole_http_response_set_context(zval *zobject, HttpContext *ctx) { php_swoole_http_response_fetch_object(Z_OBJ_P(zobject))->ctx = ctx; } static void php_swoole_http_response_free_object(zend_object *object) { http_response_t *response = php_swoole_http_response_fetch_object(object); - http_context *ctx = response->ctx; + HttpContext *ctx = response->ctx; zval ztmp; /* bool, not required to release it */ if (ctx) { @@ -282,7 +285,7 @@ static PHP_METHOD(swoole_http_response, write) { RETURN_FALSE; } - http_context *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { RETURN_FALSE; } @@ -343,7 +346,7 @@ static PHP_METHOD(swoole_http_response, write) { RETURN_BOOL(ctx->send(ctx, http_buffer->str, http_buffer->length)); } -static bool parse_header_flags(http_context *ctx, const char *key, size_t keylen, uint32_t &header_flags) { +static bool parse_header_flags(HttpContext *ctx, const char *key, size_t keylen, uint32_t &header_flags) { if (SW_STRCASEEQ(key, keylen, "Server")) { header_flags |= HTTP_HEADER_SERVER; } else if (SW_STRCASEEQ(key, keylen, "Connection")) { @@ -360,7 +363,7 @@ static bool parse_header_flags(http_context *ctx, const char *key, size_t keylen return true; } -static void http_build_header(http_context *ctx, String *response, size_t body_length) { +static void http_build_header(HttpContext *ctx, String *response, size_t body_length) { char *buf = sw_tg_buffer()->str; size_t l_buf = sw_tg_buffer()->size; int n; @@ -503,7 +506,7 @@ static void http_build_header(http_context *ctx, String *response, size_t body_l ctx->send_header_ = 1; } -static ssize_t http_build_trailer(http_context *ctx, String *response) { +static ssize_t http_build_trailer(HttpContext *ctx, String *response) { char *buf = sw_tg_buffer()->str; size_t l_buf = sw_tg_buffer()->size; int n; @@ -665,7 +668,7 @@ int swoole_http_response_compress(const char *data, size_t length, int method, i #endif static PHP_METHOD(swoole_http_response, initHeader) { - http_context *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { RETURN_FALSE; } @@ -680,7 +683,7 @@ static PHP_METHOD(swoole_http_response, initHeader) { } static PHP_METHOD(swoole_http_response, isWritable) { - http_context *ctx = php_swoole_http_response_get_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_response_get_context(ZEND_THIS); if (!ctx || (ctx->end_ || ctx->detached)) { RETURN_FALSE; } @@ -688,7 +691,7 @@ static PHP_METHOD(swoole_http_response, isWritable) { } static PHP_METHOD(swoole_http_response, end) { - http_context *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { RETURN_FALSE; } @@ -710,7 +713,7 @@ static PHP_METHOD(swoole_http_response, end) { } } -void http_context::send_trailer(zval *return_value) { +void HttpContext::send_trailer(zval *return_value) { String *http_buffer = get_write_buffer(); http_buffer->clear(); @@ -724,7 +727,7 @@ void http_context::send_trailer(zval *return_value) { } } -void http_context::end(zval *zdata, zval *return_value) { +void HttpContext::end(zval *zdata, zval *return_value) { struct { char *str; size_t length; @@ -821,12 +824,12 @@ void http_context::end(zval *zdata, zval *return_value) { if (upgrade && !co_socket) { Server *serv = (Server *) private_data; Connection *conn = serv->get_connection_verify(fd); - if (conn && conn->websocket_status == WEBSOCKET_STATUS_HANDSHAKE) { + if (conn && conn->websocket_status == websocket::STATUS_HANDSHAKE) { if (response.status == 101) { - conn->websocket_status = WEBSOCKET_STATUS_ACTIVE; + conn->websocket_status = websocket::STATUS_ACTIVE; } else { /* connection should be closed when handshake failed */ - conn->websocket_status = WEBSOCKET_STATUS_NONE; + conn->websocket_status = websocket::STATUS_NONE; keepalive = 0; } } @@ -838,14 +841,14 @@ void http_context::end(zval *zdata, zval *return_value) { RETURN_TRUE; } -bool http_context::set_header(const char *k, size_t klen, const char *v, size_t vlen, bool format) { +bool HttpContext::set_header(const char *k, size_t klen, const char *v, size_t vlen, bool format) { zval ztmp; ZVAL_STRINGL(&ztmp, v, vlen); Z_ADDREF(ztmp); return set_header(k, klen, &ztmp, format); } -bool http_context::set_header(const char *k, size_t klen, zval *zvalue, bool format) { +bool HttpContext::set_header(const char *k, size_t klen, zval *zvalue, bool format) { if (UNEXPECTED(klen > SW_HTTP_HEADER_KEY_SIZE - 1)) { php_swoole_error(E_WARNING, "header key is too long"); Z_TRY_DELREF_P(zvalue); @@ -876,7 +879,7 @@ bool http_context::set_header(const char *k, size_t klen, zval *zvalue, bool for } static PHP_METHOD(swoole_http_response, sendfile) { - http_context *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { RETURN_FALSE; } @@ -978,7 +981,7 @@ static void php_swoole_http_response_cookie(INTERNAL_FUNCTION_PARAMETERS, const Z_PARAM_STRING(priority, priority_len) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - http_context *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { RETURN_FALSE; } @@ -1078,7 +1081,7 @@ static PHP_METHOD(swoole_http_response, status) { Z_PARAM_STRING(reason, reason_len) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - http_context *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { RETURN_FALSE; } @@ -1101,7 +1104,7 @@ static PHP_METHOD(swoole_http_response, header) { Z_PARAM_BOOL(format) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - http_context *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { RETURN_FALSE; } @@ -1120,7 +1123,7 @@ static PHP_METHOD(swoole_http_response, trailer) { Z_PARAM_STRING_EX(v, vlen, 1, 0) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - http_context *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); if (!ctx) { RETURN_FALSE; } @@ -1142,7 +1145,7 @@ static PHP_METHOD(swoole_http_response, trailer) { } static PHP_METHOD(swoole_http_response, ping) { - http_context *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { RETURN_FALSE; } @@ -1154,7 +1157,7 @@ static PHP_METHOD(swoole_http_response, ping) { } static PHP_METHOD(swoole_http_response, goaway) { - http_context *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { RETURN_FALSE; } @@ -1175,7 +1178,7 @@ static PHP_METHOD(swoole_http_response, goaway) { #endif static PHP_METHOD(swoole_http_response, upgrade) { - http_context *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { RETURN_FALSE; } @@ -1187,7 +1190,7 @@ static PHP_METHOD(swoole_http_response, upgrade) { } static PHP_METHOD(swoole_http_response, push) { - http_context *ctx = php_swoole_http_response_get_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_response_get_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { swoole_set_last_error(SW_ERROR_SESSION_CLOSED); RETURN_FALSE; @@ -1198,9 +1201,9 @@ static PHP_METHOD(swoole_http_response, push) { } zval *zdata; - zend_long opcode = WEBSOCKET_OPCODE_TEXT; + zend_long opcode = WebSocket::OPCODE_TEXT; zval *zflags = nullptr; - zend_long flags = SW_WEBSOCKET_FLAG_FIN; + zend_long flags = WebSocket::FLAG_FIN; ZEND_PARSE_PARAMETERS_START(1, 3) Z_PARAM_ZVAL(zdata) @@ -1221,7 +1224,7 @@ static PHP_METHOD(swoole_http_response, push) { } } else { if (php_swoole_websocket_frame_pack( - http_buffer, zdata, opcode, flags & SW_WEBSOCKET_FLAGS_ALL, 0, ctx->websocket_compression) < 0) { + http_buffer, zdata, opcode, flags & WebSocket::FLAGS_ALL, 0, ctx->websocket_compression) < 0) { RETURN_FALSE; } } @@ -1229,7 +1232,7 @@ static PHP_METHOD(swoole_http_response, push) { } static PHP_METHOD(swoole_http_response, close) { - http_context *ctx = php_swoole_http_response_get_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_response_get_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { swoole_set_last_error(SW_ERROR_SESSION_CLOSED); RETURN_FALSE; @@ -1238,7 +1241,7 @@ static PHP_METHOD(swoole_http_response, close) { } static PHP_METHOD(swoole_http_response, recv) { - http_context *ctx = php_swoole_http_response_get_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_response_get_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { swoole_set_last_error(SW_ERROR_SESSION_CLOSED); RETURN_FALSE; @@ -1279,7 +1282,7 @@ static PHP_METHOD(swoole_http_response, recv) { } static PHP_METHOD(swoole_http_response, detach) { - http_context *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); if (!ctx) { RETURN_FALSE; } @@ -1293,7 +1296,7 @@ static PHP_METHOD(swoole_http_response, create) { zend_long fd = -1; Server *serv = nullptr; Socket *sock = nullptr; - http_context *ctx = nullptr; + HttpContext *ctx = nullptr; ZEND_PARSE_PARAMETERS_START(1, 2) Z_PARAM_ZVAL(zobject) @@ -1341,7 +1344,7 @@ static PHP_METHOD(swoole_http_response, create) { } if (!ctx) { - ctx = new http_context(); + ctx = new HttpContext(); ctx->keepalive = 1; if (serv) { @@ -1393,7 +1396,7 @@ static PHP_METHOD(swoole_http_response, redirect) { Z_PARAM_ZVAL_EX(zhttp_code, 1, 0) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - http_context *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); + HttpContext *ctx = php_swoole_http_response_get_and_check_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { RETURN_FALSE; } diff --git a/ext-src/swoole_http_server.cc b/ext-src/swoole_http_server.cc index 36d1e32fb3a..0d71470e924 100644 --- a/ext-src/swoole_http_server.cc +++ b/ext-src/swoole_http_server.cc @@ -18,9 +18,12 @@ using namespace swoole; using swoole::coroutine::Socket; -using http_request = swoole::http::Request; -using http_response = swoole::http::Response; -using http_context = swoole::http::Context; + +using HttpRequest = swoole::http::Request; +using HttpResponse = swoole::http::Response; +using HttpContext = swoole::http::Context; + +namespace WebSocket = swoole::websocket; String *swoole_http_buffer; #ifdef SW_HAVE_COMPRESSION @@ -32,9 +35,9 @@ String *swoole_http_form_data_buffer; zend_class_entry *swoole_http_server_ce; zend_object_handlers swoole_http_server_handlers; -static bool http_context_send_data(http_context *ctx, const char *data, size_t length); -static bool http_context_sendfile(http_context *ctx, const char *file, uint32_t l_file, off_t offset, size_t length); -static bool http_context_disconnect(http_context *ctx); +static bool http_context_send_data(HttpContext *ctx, const char *data, size_t length); +static bool http_context_sendfile(HttpContext *ctx, const char *file, uint32_t l_file, off_t offset, size_t length); +static bool http_context_disconnect(HttpContext *ctx); int php_swoole_http_server_onReceive(Server *serv, RecvData *req) { SessionId session_id = req->info.fd; @@ -53,7 +56,7 @@ int php_swoole_http_server_onReceive(Server *serv, RecvData *req) { return php_swoole_server_onReceive(serv, req); } // websocket client - if (conn->websocket_status == WEBSOCKET_STATUS_ACTIVE) { + if (conn->websocket_status == WebSocket::STATUS_ACTIVE) { return swoole_websocket_onMessage(serv, req); } #ifdef SW_USE_HTTP2 @@ -62,7 +65,7 @@ int php_swoole_http_server_onReceive(Server *serv, RecvData *req) { } #endif - http_context *ctx = swoole_http_context_new(session_id); + HttpContext *ctx = swoole_http_context_new(session_id); ctx->init(serv); zval *zdata = &ctx->request.zdata; @@ -108,13 +111,13 @@ int php_swoole_http_server_onReceive(Server *serv, RecvData *req) { do { zend_fcall_info_cache *fci_cache = nullptr; - if (conn->websocket_status == WEBSOCKET_STATUS_CONNECTION) { + if (conn->websocket_status == WebSocket::STATUS_CONNECTION) { fci_cache = php_swoole_server_get_fci_cache(serv, server_fd, SW_SERVER_CB_onHandShake); if (fci_cache == nullptr) { swoole_websocket_onHandshake(serv, port, ctx); goto _dtor_and_return; } else { - conn->websocket_status = WEBSOCKET_STATUS_HANDSHAKE; + conn->websocket_status = WebSocket::STATUS_HANDSHAKE; ctx->upgrade = 1; } } else { @@ -149,8 +152,8 @@ void php_swoole_http_server_minit(int module_number) { SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_http_server, sw_zend_class_unset_property_deny); } -http_context *swoole_http_context_new(SessionId fd) { - http_context *ctx = new http_context(); +HttpContext *swoole_http_context_new(SessionId fd) { + HttpContext *ctx = new HttpContext(); zval *zrequest_object = &ctx->request._zobject; ctx->request.zobject = zrequest_object; @@ -174,7 +177,7 @@ http_context *swoole_http_context_new(SessionId fd) { return ctx; } -void http_context::init(Server *serv) { +void HttpContext::init(Server *serv) { parse_cookie = serv->http_parse_cookie; parse_body = serv->http_parse_post; parse_files = serv->http_parse_files; @@ -187,14 +190,14 @@ void http_context::init(Server *serv) { bind(serv); } -void http_context::bind(Server *serv) { +void HttpContext::bind(Server *serv) { private_data = serv; send = http_context_send_data; sendfile = http_context_sendfile; close = http_context_disconnect; } -void http_context::copy(http_context *ctx) { +void HttpContext::copy(HttpContext *ctx) { parse_cookie = ctx->parse_cookie; parse_body = ctx->parse_body; parse_files = ctx->parse_files; @@ -210,7 +213,7 @@ void http_context::copy(http_context *ctx) { close = ctx->close; } -void http_context::free() { +void HttpContext::free() { /* http context can only be free'd after request and response were free'd */ if (request.zobject || response.zobject) { return; @@ -221,8 +224,8 @@ void http_context::free() { } #endif - http_request *req = &request; - http_response *res = &response; + HttpRequest *req = &request; + HttpResponse *res = &response; if (req->path) { efree(req->path); } @@ -253,16 +256,16 @@ void php_swoole_http_server_init_global_variant() { } } -http_context *php_swoole_http_request_get_and_check_context(zval *zobject) { - http_context *ctx = php_swoole_http_request_get_context(zobject); +HttpContext *php_swoole_http_request_get_and_check_context(zval *zobject) { + HttpContext *ctx = php_swoole_http_request_get_context(zobject); if (!ctx) { php_swoole_fatal_error(E_WARNING, "http request is unavailable (maybe it has been ended)"); } return ctx; } -http_context *php_swoole_http_response_get_and_check_context(zval *zobject) { - http_context *ctx = php_swoole_http_response_get_context(zobject); +HttpContext *php_swoole_http_response_get_and_check_context(zval *zobject) { + HttpContext *ctx = php_swoole_http_response_get_context(zobject); if (!ctx || (ctx->end_ || ctx->detached)) { php_swoole_fatal_error(E_WARNING, "http response is unavailable (maybe it has been ended or detached)"); return nullptr; @@ -270,7 +273,7 @@ http_context *php_swoole_http_response_get_and_check_context(zval *zobject) { return ctx; } -bool http_context_send_data(http_context *ctx, const char *data, size_t length) { +bool http_context_send_data(HttpContext *ctx, const char *data, size_t length) { Server *serv = (Server *) ctx->private_data; bool retval = serv->send(ctx->fd, (void *) data, length); if (!retval && swoole_get_last_error() == SW_ERROR_OUTPUT_SEND_YIELD) { @@ -282,12 +285,12 @@ bool http_context_send_data(http_context *ctx, const char *data, size_t length) return retval; } -static bool http_context_sendfile(http_context *ctx, const char *file, uint32_t l_file, off_t offset, size_t length) { +static bool http_context_sendfile(HttpContext *ctx, const char *file, uint32_t l_file, off_t offset, size_t length) { Server *serv = (Server *) ctx->private_data; return serv->sendfile(ctx->fd, file, l_file, offset, length); } -static bool http_context_disconnect(http_context *ctx) { +static bool http_context_disconnect(HttpContext *ctx) { Server *serv = (Server *) ctx->private_data; return serv->close(ctx->fd, 0); } diff --git a/ext-src/swoole_http_server_coro.cc b/ext-src/swoole_http_server_coro.cc index 9e0cd514520..78a63811127 100644 --- a/ext-src/swoole_http_server_coro.cc +++ b/ext-src/swoole_http_server_coro.cc @@ -19,26 +19,27 @@ #include #include +using swoole::microtime; using swoole::PHPCoroutine; using swoole::coroutine::Socket; using swoole::coroutine::System; -using swoole::microtime; -using http_request = swoole::http::Request; -using http_response = swoole::http::Response; -using http_context = swoole::http::Context; +using HttpRequest = swoole::http::Request; +using HttpResponse = swoole::http::Response; +using HttpContext = swoole::http::Context; #ifdef SW_USE_HTTP2 -using Http2Stream = swoole::http2::Stream; -using Http2Session = swoole::http2::Session; +namespace http2 = swoole::http2; +using Http2Stream = http2::Stream; +using Http2Session = http2::Session; #endif static zend_class_entry *swoole_http_server_coro_ce; static zend_object_handlers swoole_http_server_coro_handlers; -static bool http_context_send_data(http_context *ctx, const char *data, size_t length); -static bool http_context_sendfile(http_context *ctx, const char *file, uint32_t l_file, off_t offset, size_t length); -static bool http_context_disconnect(http_context *ctx); +static bool http_context_send_data(HttpContext *ctx, const char *data, size_t length); +static bool http_context_sendfile(HttpContext *ctx, const char *file, uint32_t l_file, off_t offset, size_t length); +static bool http_context_disconnect(HttpContext *ctx); #ifdef SW_USE_HTTP2 static void http2_server_onRequest(Http2Session *session, Http2Stream *stream); @@ -102,7 +103,7 @@ class http_server { add_assoc_zval_ex(&zcallbacks, pattern.c_str(), pattern.length(), zcallback); } - zend_fcall_info_cache *get_handler(http_context *ctx) { + zend_fcall_info_cache *get_handler(HttpContext *ctx) { for (auto i = handlers.begin(); i != handlers.end(); i++) { if (&i->second == default_handler) { continue; @@ -114,8 +115,8 @@ class http_server { return default_handler; } - http_context *create_context(Socket *conn, zval *zconn) { - http_context *ctx = swoole_http_context_new(conn->get_fd()); + HttpContext *create_context(Socket *conn, zval *zconn) { + HttpContext *ctx = swoole_http_context_new(conn->get_fd()); ctx->parse_body = http_parse_post; ctx->parse_cookie = http_parse_cookie; ctx->parse_files = http_parse_files; @@ -141,15 +142,15 @@ class http_server { } #ifdef SW_USE_HTTP2 - void recv_http2_frame(http_context *ctx) { + void recv_http2_frame(HttpContext *ctx) { Socket *sock = (Socket *) ctx->private_data; - swHttp2_send_setting_frame(&sock->protocol, sock->get_socket()); + http2::send_setting_frame(&sock->protocol, sock->get_socket()); sock->open_length_check = true; sock->protocol.package_length_size = SW_HTTP2_FRAME_HEADER_SIZE; sock->protocol.package_length_offset = 0; sock->protocol.package_body_offset = 0; - sock->protocol.get_package_length = swHttp2_get_frame_length; + sock->protocol.get_package_length = http2::get_frame_length; Http2Session session(ctx->fd); session.default_ctx = ctx; @@ -247,17 +248,17 @@ static inline void http_server_set_error(zval *zobject, Socket *sock) { zend_update_property_string(swoole_http_server_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errMsg"), sock->errMsg); } -static bool http_context_send_data(http_context *ctx, const char *data, size_t length) { +static bool http_context_send_data(HttpContext *ctx, const char *data, size_t length) { Socket *sock = (Socket *) ctx->private_data; return sock->send_all(data, length) == (ssize_t) length; } -static bool http_context_sendfile(http_context *ctx, const char *file, uint32_t l_file, off_t offset, size_t length) { +static bool http_context_sendfile(HttpContext *ctx, const char *file, uint32_t l_file, off_t offset, size_t length) { Socket *sock = (Socket *) ctx->private_data; return sock->sendfile(file, offset, length); } -static bool http_context_disconnect(http_context *ctx) { +static bool http_context_disconnect(HttpContext *ctx) { Socket *sock = (Socket *) ctx->private_data; return sock->close(); } @@ -272,7 +273,7 @@ static void php_swoole_http_server_coro_free_object(zend_object *object) { zend_object_std_dtor(&hsc->std); } -void http_context::init(Socket *sock) { +void HttpContext::init(Socket *sock) { parse_cookie = 1; parse_body = 1; parse_files = 1; @@ -287,7 +288,7 @@ void http_context::init(Socket *sock) { bind(sock); } -void http_context::bind(Socket *sock) { +void HttpContext::bind(Socket *sock) { private_data = sock; co_socket = 1; send = http_context_send_data; @@ -435,7 +436,8 @@ static PHP_METHOD(swoole_http_server_coro, start) { zend_fcall_info_cache fci_cache; zval zcallback; ZVAL_STRING(&zcallback, "onAccept"); - if (!sw_zend_is_callable_at_frame(&zcallback, ZEND_THIS, execute_data, 0, &func_name, nullptr, &fci_cache, nullptr)) { + if (!sw_zend_is_callable_at_frame( + &zcallback, ZEND_THIS, execute_data, 0, &func_name, nullptr, &fci_cache, nullptr)) { php_swoole_fatal_error(E_CORE_ERROR, "function '%s' is not callable", func_name); return; } @@ -546,7 +548,7 @@ static PHP_METHOD(swoole_http_server_coro, onAccept) { Socket *sock = php_swoole_get_socket(zconn); sock->set_buffer_allocator(sw_zend_string_allocator()); swString *buffer = sock->get_read_buffer(); - http_context *ctx = nullptr; + HttpContext *ctx = nullptr; bool header_completed = false; off_t header_crlf_offset = 0; @@ -560,21 +562,22 @@ static PHP_METHOD(swoole_http_server_coro, onAccept) { #endif while (true) { - _recv_request: { - ssize_t retval = sock->recv(buffer->str + buffer->length, buffer->size - buffer->length); - if (sw_unlikely(retval <= 0)) { - break; - } - buffer->length += retval; + _recv_request : { + ssize_t retval = sock->recv(buffer->str + buffer->length, buffer->size - buffer->length); + if (sw_unlikely(retval <= 0)) { + break; } + buffer->length += retval; + } - _parse_request: + _parse_request: if (!ctx) { ctx = hs->create_context(sock, zconn); } if (!header_completed) { - if (swoole_strnpos(buffer->str + header_crlf_offset, buffer->length - header_crlf_offset, ZEND_STRL("\r\n\r\n")) < 0) { + if (swoole_strnpos( + buffer->str + header_crlf_offset, buffer->length - header_crlf_offset, ZEND_STRL("\r\n\r\n")) < 0) { if (buffer->length == buffer->size) { ctx->response.status = SW_HTTP_REQUEST_ENTITY_TOO_LARGE; break; @@ -689,7 +692,7 @@ static PHP_METHOD(swoole_http_server_coro, shutdown) { #ifdef SW_USE_HTTP2 static void http2_server_onRequest(Http2Session *session, Http2Stream *stream) { - http_context *ctx = stream->ctx; + HttpContext *ctx = stream->ctx; http_server *hs = (http_server *) session->private_data; Socket *sock = (Socket *) ctx->private_data; zval *zserver = ctx->request.zserver; diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 9832211e04c..150cc824bff 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -1870,7 +1870,7 @@ void php_swoole_server_onClose(Server *serv, DataHead *info) { if (!conn) { return; } - if (conn->websocket_status != WEBSOCKET_STATUS_ACTIVE) { + if (conn->websocket_status != swoole::websocket::STATUS_ACTIVE) { ListenPort *port = serv->get_port_by_server_fd(info->server_fd); if (port && port->open_websocket_protocol && php_swoole_server_isset_callback(serv, port, SW_SERVER_CB_onDisconnect)) { diff --git a/ext-src/swoole_websocket_server.cc b/ext-src/swoole_websocket_server.cc index 06207f35cd1..55435e9334f 100644 --- a/ext-src/swoole_websocket_server.cc +++ b/ext-src/swoole_websocket_server.cc @@ -32,7 +32,9 @@ using swoole::coroutine::Socket; using http_request = swoole::http::Request; using http_response = swoole::http::Response; -using http_context = swoole::http::Context; +using HttpContext = swoole::http::Context; + +namespace WebSocket = swoole::websocket; zend_class_entry *swoole_websocket_server_ce; static zend_object_handlers swoole_websocket_server_handlers; @@ -110,7 +112,7 @@ static bool websocket_message_uncompress(String *buffer, const char *in, size_t #endif static void php_swoole_websocket_construct_frame(zval *zframe, zend_long opcode, zval *zpayload, uint8_t flags) { - if (opcode == WEBSOCKET_OPCODE_CLOSE) { + if (opcode == WebSocket::OPCODE_CLOSE) { const char *payload = Z_STRVAL_P(zpayload); size_t payload_length = Z_STRLEN_P(zpayload); object_init_ex(zframe, swoole_websocket_closeframe_ce); @@ -137,11 +139,11 @@ static void php_swoole_websocket_construct_frame(zval *zframe, zend_long opcode, zend_update_property_long(swoole_websocket_frame_ce, SW_Z8_OBJ_P(zframe), ZEND_STRL("flags"), flags); /* BC */ zend_update_property_bool( - swoole_websocket_frame_ce, SW_Z8_OBJ_P(zframe), ZEND_STRL("finish"), flags & SW_WEBSOCKET_FLAG_FIN); + swoole_websocket_frame_ce, SW_Z8_OBJ_P(zframe), ZEND_STRL("finish"), flags & WebSocket::FLAG_FIN); } void php_swoole_websocket_frame_unpack_ex(String *data, zval *zframe, uchar uncompress) { - swWebSocket_frame frame; + WebSocket::Frame frame; zval zpayload; uint8_t flags; @@ -151,8 +153,8 @@ void php_swoole_websocket_frame_unpack_ex(String *data, zval *zframe, uchar unco return; } - swWebSocket_decode(&frame, data); - flags = swWebSocket_get_flags(&frame); + WebSocket::decode(&frame, data); + flags = WebSocket::get_flags(&frame); #ifdef SW_HAVE_ZLIB if (uncompress && frame.header.RSV1) { swoole_zlib_buffer->clear(); @@ -163,7 +165,7 @@ void php_swoole_websocket_frame_unpack_ex(String *data, zval *zframe, uchar unco } frame.payload = swoole_zlib_buffer->str; frame.payload_length = swoole_zlib_buffer->length; - flags ^= (SW_WEBSOCKET_FLAG_RSV1 | SW_WEBSOCKET_FLAG_COMPRESS); + flags ^= (WebSocket::FLAG_RSV1 | WebSocket::FLAG_COMPRESS); } #endif /* TODO: optimize memory copy */ @@ -199,29 +201,29 @@ static sw_inline int php_swoole_websocket_frame_pack_ex(String *buffer, } if (mask) { - flags |= SW_WEBSOCKET_FLAG_MASK; + flags |= WebSocket::FLAG_MASK; } #ifdef SW_HAVE_ZLIB - if (flags & SW_WEBSOCKET_FLAG_COMPRESS) { + if (flags & WebSocket::FLAG_COMPRESS) { if (!allow_compress) { - flags ^= SW_WEBSOCKET_FLAG_COMPRESS; + flags ^= WebSocket::FLAG_COMPRESS; } else if (length > 0) { swoole_zlib_buffer->clear(); if (websocket_message_compress(swoole_zlib_buffer, data, length, Z_DEFAULT_COMPRESSION)) { data = swoole_zlib_buffer->str; length = swoole_zlib_buffer->length; - flags |= SW_WEBSOCKET_FLAG_RSV1; + flags |= WebSocket::FLAG_RSV1; } } } #endif switch (opcode) { - case WEBSOCKET_OPCODE_CLOSE: - return swWebSocket_pack_close_frame(buffer, code, data, length, flags); + case WebSocket::OPCODE_CLOSE: + return WebSocket::pack_close_frame(buffer, code, data, length, flags); default: - swWebSocket_encode(buffer, data, length, opcode, flags); + WebSocket::encode(buffer, data, length, opcode, flags); } return SW_OK; } @@ -229,21 +231,21 @@ static sw_inline int php_swoole_websocket_frame_pack_ex(String *buffer, int php_swoole_websocket_frame_pack_ex( String *buffer, zval *zdata, zend_long opcode, uint8_t flags, zend_bool mask, zend_bool allow_compress) { return php_swoole_websocket_frame_pack_ex( - buffer, zdata, opcode, WEBSOCKET_CLOSE_NORMAL, flags, mask, allow_compress); + buffer, zdata, opcode, WebSocket::CLOSE_NORMAL, flags, mask, allow_compress); } int php_swoole_websocket_frame_object_pack_ex(String *buffer, zval *zdata, zend_bool mask, zend_bool allow_compress) { zval *zframe = zdata; - zend_long opcode = WEBSOCKET_OPCODE_TEXT; - zend_long code = WEBSOCKET_CLOSE_NORMAL; - zend_long flags = SW_WEBSOCKET_FLAG_FIN; + zend_long opcode = WebSocket::OPCODE_TEXT; + zend_long code = WebSocket::CLOSE_NORMAL; + zend_long flags = WebSocket::FLAG_FIN; zval *ztmp = nullptr; zdata = nullptr; if ((ztmp = sw_zend_read_property_ex(swoole_websocket_frame_ce, zframe, SW_ZSTR_KNOWN(SW_ZEND_STR_OPCODE), 0))) { opcode = zval_get_long(ztmp); } - if (opcode == WEBSOCKET_OPCODE_CLOSE) { + if (opcode == WebSocket::OPCODE_CLOSE) { if ((ztmp = sw_zend_read_property_not_null_ex( swoole_websocket_frame_ce, zframe, SW_ZSTR_KNOWN(SW_ZEND_STR_CODE), 1))) { code = zval_get_long(ztmp); @@ -258,22 +260,22 @@ int php_swoole_websocket_frame_object_pack_ex(String *buffer, zval *zdata, zend_ zdata = ztmp; } if ((ztmp = sw_zend_read_property_ex(swoole_websocket_frame_ce, zframe, SW_ZSTR_KNOWN(SW_ZEND_STR_FLAGS), 0))) { - flags = zval_get_long(ztmp) & SW_WEBSOCKET_FLAGS_ALL; + flags = zval_get_long(ztmp) & WebSocket::FLAGS_ALL; } if ((ztmp = sw_zend_read_property_not_null_ex( swoole_websocket_frame_ce, zframe, SW_ZSTR_KNOWN(SW_ZEND_STR_FINISH), 0))) { if (zval_is_true(ztmp)) { - flags |= SW_WEBSOCKET_FLAG_FIN; + flags |= WebSocket::FLAG_FIN; } else { - flags &= ~SW_WEBSOCKET_FLAG_FIN; + flags &= ~WebSocket::FLAG_FIN; } } return php_swoole_websocket_frame_pack_ex( - buffer, zdata, opcode, code, flags & SW_WEBSOCKET_FLAGS_ALL, mask, allow_compress); + buffer, zdata, opcode, code, flags & WebSocket::FLAGS_ALL, mask, allow_compress); } -void swoole_websocket_onOpen(Server *serv, http_context *ctx) { +void swoole_websocket_onOpen(Server *serv, HttpContext *ctx) { Connection *conn = serv->get_connection_by_session_id(ctx->fd); if (!conn) { swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_CLOSED, "session[%ld] is closed", ctx->fd); @@ -294,7 +296,7 @@ void swoole_websocket_onOpen(Server *serv, http_context *ctx) { /** * default onRequest callback */ -void swoole_websocket_onRequest(http_context *ctx) { +void swoole_websocket_onRequest(HttpContext *ctx) { const char *bad_request = "HTTP/1.1 400 Bad Request\r\n" "Connection: close\r\n" "Content-Type: text/html; charset=UTF-8\r\n" @@ -315,7 +317,7 @@ void php_swoole_sha1(const char *str, int _len, unsigned char *digest) { PHP_SHA1Final(digest, &context); } -bool swoole_websocket_handshake(http_context *ctx) { +bool swoole_websocket_handshake(HttpContext *ctx) { char sec_buf[128]; zval *header = ctx->request.zheader; HashTable *ht = Z_ARRVAL_P(header); @@ -385,7 +387,7 @@ bool swoole_websocket_handshake(http_context *ctx) { #endif if (conn) { - conn->websocket_status = WEBSOCKET_STATUS_ACTIVE; + conn->websocket_status = WebSocket::STATUS_ACTIVE; ListenPort *port = serv->get_port_by_server_fd(conn->server_fd); if (port && !port->websocket_subprotocol.empty()) { ctx->set_header(ZEND_STRL("Sec-WebSocket-Protocol"), @@ -402,7 +404,7 @@ bool swoole_websocket_handshake(http_context *ctx) { sock->protocol.package_length_size = SW_WEBSOCKET_HEADER_LEN; sock->protocol.package_length_offset = 0; sock->protocol.package_body_offset = 0; - sock->protocol.get_package_length = swWebSocket_get_package_length; + sock->protocol.get_package_length = WebSocket::get_package_length; #ifdef SW_HAVE_ZLIB ctx->websocket_compression = websocket_compression; #endif @@ -554,19 +556,19 @@ int swoole_websocket_onMessage(Server *serv, RecvData *req) { php_swoole_get_recv_data(serv, &zdata, req); - // frame info has already decoded in swWebSocket_dispatch_frame + // frame info has already decoded in websocket::dispatch_frame flags = frame_header[0]; opcode = frame_header[1]; - if ((opcode == WEBSOCKET_OPCODE_CLOSE && !port->open_websocket_close_frame) || - (opcode == WEBSOCKET_OPCODE_PING && !port->open_websocket_ping_frame) || - (opcode == WEBSOCKET_OPCODE_PONG && !port->open_websocket_pong_frame)) { - if (opcode == WEBSOCKET_OPCODE_PING) { + if ((opcode == WebSocket::OPCODE_CLOSE && !port->open_websocket_close_frame) || + (opcode == WebSocket::OPCODE_PING && !port->open_websocket_ping_frame) || + (opcode == WebSocket::OPCODE_PONG && !port->open_websocket_pong_frame)) { + if (opcode == WebSocket::OPCODE_PING) { String send_frame = {}; char buf[SW_WEBSOCKET_HEADER_LEN + SW_WEBSOCKET_CLOSE_CODE_LEN + SW_WEBSOCKET_CLOSE_REASON_MAX_LEN]; send_frame.str = buf; send_frame.size = sizeof(buf); - swWebSocket_encode(&send_frame, req->data, req->info.len, WEBSOCKET_OPCODE_PONG, SW_WEBSOCKET_FLAG_FIN); + WebSocket::encode(&send_frame, req->data, req->info.len, WebSocket::OPCODE_PONG, WebSocket::FLAG_FIN); serv->send(fd, send_frame.str, send_frame.length); } zval_ptr_dtor(&zdata); @@ -577,7 +579,7 @@ int swoole_websocket_onMessage(Server *serv, RecvData *req) { /** * RFC 7692 */ - if (serv->websocket_compression && (flags & SW_WEBSOCKET_FLAG_RSV1)) { + if (serv->websocket_compression && (flags & WebSocket::FLAG_RSV1)) { swoole_zlib_buffer->clear(); if (!websocket_message_uncompress(swoole_zlib_buffer, Z_STRVAL(zdata), Z_STRLEN(zdata))) { zval_ptr_dtor(&zdata); @@ -585,7 +587,7 @@ int swoole_websocket_onMessage(Server *serv, RecvData *req) { } zval_ptr_dtor(&zdata); ZVAL_STRINGL(&zdata, swoole_zlib_buffer->str, swoole_zlib_buffer->length); - flags ^= (SW_WEBSOCKET_FLAG_RSV1 | SW_WEBSOCKET_FLAG_COMPRESS); + flags ^= (WebSocket::FLAG_RSV1 | WebSocket::FLAG_COMPRESS); } #endif @@ -608,7 +610,7 @@ int swoole_websocket_onMessage(Server *serv, RecvData *req) { return SW_OK; } -int swoole_websocket_onHandshake(Server *serv, ListenPort *port, http_context *ctx) { +int swoole_websocket_onHandshake(Server *serv, ListenPort *port, HttpContext *ctx) { SessionId fd = ctx->fd; bool success = swoole_websocket_handshake(ctx); if (success) { @@ -637,8 +639,8 @@ void php_swoole_websocket_server_minit(int module_number) { swoole_websocket_frame_methods); zend_declare_property_long(swoole_websocket_frame_ce, ZEND_STRL("fd"), 0, ZEND_ACC_PUBLIC); zend_declare_property_string(swoole_websocket_frame_ce, ZEND_STRL("data"), "", ZEND_ACC_PUBLIC); - zend_declare_property_long(swoole_websocket_frame_ce, ZEND_STRL("opcode"), WEBSOCKET_OPCODE_TEXT, ZEND_ACC_PUBLIC); - zend_declare_property_long(swoole_websocket_frame_ce, ZEND_STRL("flags"), SW_WEBSOCKET_FLAG_FIN, ZEND_ACC_PUBLIC); + zend_declare_property_long(swoole_websocket_frame_ce, ZEND_STRL("opcode"), WebSocket::OPCODE_TEXT, ZEND_ACC_PUBLIC); + zend_declare_property_long(swoole_websocket_frame_ce, ZEND_STRL("flags"), WebSocket::FLAG_FIN, ZEND_ACC_PUBLIC); zend_declare_property_null(swoole_websocket_frame_ce, ZEND_STRL("finish"), ZEND_ACC_PUBLIC); SW_INIT_CLASS_ENTRY_EX(swoole_websocket_closeframe, @@ -648,73 +650,73 @@ void php_swoole_websocket_server_minit(int module_number) { nullptr, swoole_websocket_frame); zend_declare_property_long( - swoole_websocket_closeframe_ce, ZEND_STRL("opcode"), WEBSOCKET_OPCODE_CLOSE, ZEND_ACC_PUBLIC); + swoole_websocket_closeframe_ce, ZEND_STRL("opcode"), WebSocket::OPCODE_CLOSE, ZEND_ACC_PUBLIC); zend_declare_property_long( - swoole_websocket_closeframe_ce, ZEND_STRL("code"), WEBSOCKET_CLOSE_NORMAL, ZEND_ACC_PUBLIC); + swoole_websocket_closeframe_ce, ZEND_STRL("code"), WebSocket::CLOSE_NORMAL, ZEND_ACC_PUBLIC); zend_declare_property_string(swoole_websocket_closeframe_ce, ZEND_STRL("reason"), "", ZEND_ACC_PUBLIC); /* {{{ swoole namespace */ // status - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_STATUS_CONNECTION", WEBSOCKET_STATUS_CONNECTION); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_STATUS_HANDSHAKE", WEBSOCKET_STATUS_HANDSHAKE); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_STATUS_ACTIVE", WEBSOCKET_STATUS_ACTIVE); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_STATUS_CLOSING", WEBSOCKET_STATUS_CLOSING); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_STATUS_CONNECTION", WebSocket::STATUS_CONNECTION); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_STATUS_HANDSHAKE", WebSocket::STATUS_HANDSHAKE); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_STATUS_ACTIVE", WebSocket::STATUS_ACTIVE); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_STATUS_CLOSING", WebSocket::STATUS_CLOSING); // all opcodes - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_OPCODE_CONTINUATION", WEBSOCKET_OPCODE_CONTINUATION); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_OPCODE_TEXT", WEBSOCKET_OPCODE_TEXT); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_OPCODE_BINARY", WEBSOCKET_OPCODE_BINARY); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_OPCODE_CLOSE", WEBSOCKET_OPCODE_CLOSE); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_OPCODE_PING", WEBSOCKET_OPCODE_PING); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_OPCODE_PONG", WEBSOCKET_OPCODE_PONG); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_OPCODE_CONTINUATION", WebSocket::OPCODE_CONTINUATION); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_OPCODE_TEXT", WebSocket::OPCODE_TEXT); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_OPCODE_BINARY", WebSocket::OPCODE_BINARY); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_OPCODE_CLOSE", WebSocket::OPCODE_CLOSE); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_OPCODE_PING", WebSocket::OPCODE_PING); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_OPCODE_PONG", WebSocket::OPCODE_PONG); // flags - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_FLAG_FIN", SW_WEBSOCKET_FLAG_FIN); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_FLAG_RSV1", SW_WEBSOCKET_FLAG_RSV1); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_FLAG_RSV2", SW_WEBSOCKET_FLAG_RSV2); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_FLAG_RSV3", SW_WEBSOCKET_FLAG_RSV3); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_FLAG_MASK", SW_WEBSOCKET_FLAG_MASK); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_FLAG_COMPRESS", SW_WEBSOCKET_FLAG_COMPRESS); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_FLAG_FIN", WebSocket::FLAG_FIN); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_FLAG_RSV1", WebSocket::FLAG_RSV1); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_FLAG_RSV2", WebSocket::FLAG_RSV2); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_FLAG_RSV3", WebSocket::FLAG_RSV3); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_FLAG_MASK", WebSocket::FLAG_MASK); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_FLAG_COMPRESS", WebSocket::FLAG_COMPRESS); // close error - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_NORMAL", WEBSOCKET_CLOSE_NORMAL); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_GOING_AWAY", WEBSOCKET_CLOSE_GOING_AWAY); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_PROTOCOL_ERROR", WEBSOCKET_CLOSE_PROTOCOL_ERROR); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_DATA_ERROR", WEBSOCKET_CLOSE_DATA_ERROR); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_STATUS_ERROR", WEBSOCKET_CLOSE_STATUS_ERROR); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_ABNORMAL", WEBSOCKET_CLOSE_ABNORMAL); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_MESSAGE_ERROR", WEBSOCKET_CLOSE_MESSAGE_ERROR); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_POLICY_ERROR", WEBSOCKET_CLOSE_POLICY_ERROR); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_MESSAGE_TOO_BIG", WEBSOCKET_CLOSE_MESSAGE_TOO_BIG); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_EXTENSION_MISSING", WEBSOCKET_CLOSE_EXTENSION_MISSING); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_SERVER_ERROR", WEBSOCKET_CLOSE_SERVER_ERROR); - SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_TLS", WEBSOCKET_CLOSE_TLS); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_NORMAL", WebSocket::CLOSE_NORMAL); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_GOING_AWAY", WebSocket::CLOSE_GOING_AWAY); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_PROTOCOL_ERROR", WebSocket::CLOSE_PROTOCOL_ERROR); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_DATA_ERROR", WebSocket::CLOSE_DATA_ERROR); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_STATUS_ERROR", WebSocket::CLOSE_STATUS_ERROR); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_ABNORMAL", WebSocket::CLOSE_ABNORMAL); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_MESSAGE_ERROR", WebSocket::CLOSE_MESSAGE_ERROR); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_POLICY_ERROR", WebSocket::CLOSE_POLICY_ERROR); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_MESSAGE_TOO_BIG", WebSocket::CLOSE_MESSAGE_TOO_BIG); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_EXTENSION_MISSING", WebSocket::CLOSE_EXTENSION_MISSING); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_SERVER_ERROR", WebSocket::CLOSE_SERVER_ERROR); + SW_REGISTER_LONG_CONSTANT("SWOOLE_WEBSOCKET_CLOSE_TLS", WebSocket::CLOSE_TLS); /* swoole namespace }}} */ /* BC */ // status - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_STATUS_CONNECTION", WEBSOCKET_STATUS_CONNECTION); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_STATUS_HANDSHAKE", WEBSOCKET_STATUS_HANDSHAKE); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_STATUS_FRAME", WEBSOCKET_STATUS_ACTIVE); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_STATUS_ACTIVE", WEBSOCKET_STATUS_ACTIVE); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_STATUS_CLOSING", WEBSOCKET_STATUS_CLOSING); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_STATUS_CONNECTION", WebSocket::STATUS_CONNECTION); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_STATUS_HANDSHAKE", WebSocket::STATUS_HANDSHAKE); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_STATUS_FRAME", WebSocket::STATUS_ACTIVE); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_STATUS_ACTIVE", WebSocket::STATUS_ACTIVE); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_STATUS_CLOSING", WebSocket::STATUS_CLOSING); // all opcodes - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_OPCODE_CONTINUATION", WEBSOCKET_OPCODE_CONTINUATION); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_OPCODE_TEXT", WEBSOCKET_OPCODE_TEXT); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_OPCODE_BINARY", WEBSOCKET_OPCODE_BINARY); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_OPCODE_CLOSE", WEBSOCKET_OPCODE_CLOSE); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_OPCODE_PING", WEBSOCKET_OPCODE_PING); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_OPCODE_PONG", WEBSOCKET_OPCODE_PONG); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_OPCODE_CONTINUATION", WebSocket::OPCODE_CONTINUATION); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_OPCODE_TEXT", WebSocket::OPCODE_TEXT); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_OPCODE_BINARY", WebSocket::OPCODE_BINARY); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_OPCODE_CLOSE", WebSocket::OPCODE_CLOSE); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_OPCODE_PING", WebSocket::OPCODE_PING); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_OPCODE_PONG", WebSocket::OPCODE_PONG); // close error - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_NORMAL", WEBSOCKET_CLOSE_NORMAL); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_GOING_AWAY", WEBSOCKET_CLOSE_GOING_AWAY); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_PROTOCOL_ERROR", WEBSOCKET_CLOSE_PROTOCOL_ERROR); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_DATA_ERROR", WEBSOCKET_CLOSE_DATA_ERROR); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_STATUS_ERROR", WEBSOCKET_CLOSE_STATUS_ERROR); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_ABNORMAL", WEBSOCKET_CLOSE_ABNORMAL); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_MESSAGE_ERROR", WEBSOCKET_CLOSE_MESSAGE_ERROR); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_POLICY_ERROR", WEBSOCKET_CLOSE_POLICY_ERROR); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_MESSAGE_TOO_BIG", WEBSOCKET_CLOSE_MESSAGE_TOO_BIG); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_EXTENSION_MISSING", WEBSOCKET_CLOSE_EXTENSION_MISSING); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_SERVER_ERROR", WEBSOCKET_CLOSE_SERVER_ERROR); - SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_TLS", WEBSOCKET_CLOSE_TLS); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_NORMAL", WebSocket::CLOSE_NORMAL); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_GOING_AWAY", WebSocket::CLOSE_GOING_AWAY); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_PROTOCOL_ERROR", WebSocket::CLOSE_PROTOCOL_ERROR); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_DATA_ERROR", WebSocket::CLOSE_DATA_ERROR); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_STATUS_ERROR", WebSocket::CLOSE_STATUS_ERROR); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_ABNORMAL", WebSocket::CLOSE_ABNORMAL); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_MESSAGE_ERROR", WebSocket::CLOSE_MESSAGE_ERROR); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_POLICY_ERROR", WebSocket::CLOSE_POLICY_ERROR); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_MESSAGE_TOO_BIG", WebSocket::CLOSE_MESSAGE_TOO_BIG); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_EXTENSION_MISSING", WebSocket::CLOSE_EXTENSION_MISSING); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_SERVER_ERROR", WebSocket::CLOSE_SERVER_ERROR); + SW_REGISTER_LONG_CONSTANT("WEBSOCKET_CLOSE_TLS", WebSocket::CLOSE_TLS); } static sw_inline bool swoole_websocket_server_push(Server *serv, SessionId fd, String *buffer) { @@ -724,7 +726,7 @@ static sw_inline bool swoole_websocket_server_push(Server *serv, SessionId fd, S } Connection *conn = serv->get_connection_by_session_id(fd); - if (!conn || conn->websocket_status < WEBSOCKET_STATUS_HANDSHAKE) { + if (!conn || conn->websocket_status < WebSocket::STATUS_HANDSHAKE) { swoole_set_last_error(SW_ERROR_WEBSOCKET_UNCONNECTED); php_swoole_fatal_error( E_WARNING, "the connected client of connection[%ld] is not a websocket client or closed", fd); @@ -752,7 +754,7 @@ static sw_inline bool swoole_websocket_server_close(Server *serv, SessionId fd, Connection *conn = serv->get_connection_by_session_id(fd); if (conn) { // Change status immediately to avoid double close - conn->websocket_status = WEBSOCKET_STATUS_CLOSING; + conn->websocket_status = WebSocket::STATUS_CLOSING; // Server close connection immediately return serv->close(fd, false); } else { @@ -768,7 +770,7 @@ static PHP_METHOD(swoole_websocket_server, disconnect) { } zend_long fd = 0; - zend_long code = WEBSOCKET_CLOSE_NORMAL; + zend_long code = WebSocket::CLOSE_NORMAL; char *data = nullptr; size_t length = 0; @@ -776,7 +778,7 @@ static PHP_METHOD(swoole_websocket_server, disconnect) { RETURN_FALSE; } swoole_http_buffer->clear(); - if (swWebSocket_pack_close_frame(swoole_http_buffer, code, data, length, 0) < 0) { + if (WebSocket::pack_close_frame(swoole_http_buffer, code, data, length, 0) < 0) { RETURN_FALSE; } RETURN_BOOL(swoole_websocket_server_close(serv, fd, swoole_http_buffer, 1)); @@ -791,9 +793,9 @@ static PHP_METHOD(swoole_websocket_server, push) { zend_long fd = 0; zval *zdata = nullptr; - zend_long opcode = WEBSOCKET_OPCODE_TEXT; + zend_long opcode = WebSocket::OPCODE_TEXT; zval *zflags = nullptr; - zend_long flags = SW_WEBSOCKET_FLAG_FIN; + zend_long flags = WebSocket::FLAG_FIN; #ifdef SW_HAVE_ZLIB zend_bool allow_compress = 0; #endif @@ -825,14 +827,14 @@ static PHP_METHOD(swoole_websocket_server, push) { } } else { if (php_swoole_websocket_frame_pack( - swoole_http_buffer, zdata, opcode, flags & SW_WEBSOCKET_FLAGS_ALL, 0, allow_compress) < 0) { + swoole_http_buffer, zdata, opcode, flags & WebSocket::FLAGS_ALL, 0, allow_compress) < 0) { RETURN_FALSE; } } switch (opcode) { - case WEBSOCKET_OPCODE_CLOSE: - RETURN_BOOL(swoole_websocket_server_close(serv, fd, swoole_http_buffer, flags & SW_WEBSOCKET_FLAG_FIN)); + case WebSocket::OPCODE_CLOSE: + RETURN_BOOL(swoole_websocket_server_close(serv, fd, swoole_http_buffer, flags & WebSocket::FLAG_FIN)); break; default: RETURN_BOOL(swoole_websocket_server_push(serv, fd, swoole_http_buffer)); @@ -842,9 +844,9 @@ static PHP_METHOD(swoole_websocket_server, push) { static PHP_METHOD(swoole_websocket_server, pack) { String *buffer = sw_tg_buffer(); zval *zdata; - zend_long opcode = WEBSOCKET_OPCODE_TEXT; + zend_long opcode = WebSocket::OPCODE_TEXT; zval *zflags = nullptr; - zend_long flags = SW_WEBSOCKET_FLAG_FIN; + zend_long flags = WebSocket::FLAG_FIN; ZEND_PARSE_PARAMETERS_START(1, 3) Z_PARAM_ZVAL(zdata) @@ -863,7 +865,7 @@ static PHP_METHOD(swoole_websocket_server, pack) { RETURN_EMPTY_STRING(); } } else { - if (php_swoole_websocket_frame_pack(buffer, zdata, opcode, flags & SW_WEBSOCKET_FLAGS_ALL, 0, 1) < 0) { + if (php_swoole_websocket_frame_pack(buffer, zdata, opcode, flags & WebSocket::FLAGS_ALL, 0, 1) < 0) { RETURN_EMPTY_STRING(); } } @@ -905,7 +907,7 @@ static PHP_METHOD(swoole_websocket_server, isEstablished) { Connection *conn = serv->get_connection_verify(session_id); // not isEstablished - if (!conn || conn->closed || conn->websocket_status < WEBSOCKET_STATUS_ACTIVE) { + if (!conn || conn->closed || conn->websocket_status < WebSocket::STATUS_ACTIVE) { RETURN_FALSE; } else { RETURN_TRUE; diff --git a/include/swoole_http2.h b/include/swoole_http2.h index d34550a7371..5bc05cddba7 100644 --- a/include/swoole_http2.h +++ b/include/swoole_http2.h @@ -102,15 +102,18 @@ enum swHttp2_stream_flag { "%s" \ "\e[0m" \ "] frame " str "%s%s%s%s%s", \ - swHttp2_get_type_color(type), \ - swHttp2_get_type(type), \ + swoole::http2::get_type_color(type), \ + swoole::http2::get_type(type), \ length, \ flags, \ stream_id, \ ##__VA_ARGS__, \ swHttp2FrameTraceLogFlags); -struct swHttp2_settings { +namespace swoole { +namespace http2 { + +struct Settings { uint32_t header_table_size; uint32_t window_size; uint32_t max_concurrent_streams; @@ -129,7 +132,7 @@ struct swHttp2_settings { | Frame Payload (0...) ... +---------------------------------------------------------------+ */ -struct swHttp2_frame { +struct Frame { uint32_t length : 24; uint32_t type : 8; uint32_t flags : 8; @@ -138,16 +141,16 @@ struct swHttp2_frame { char data[0]; }; -static sw_inline ssize_t swHttp2_get_length(const char *buf) { +static sw_inline ssize_t get_length(const char *buf) { return (((uint8_t) buf[0]) << 16) + (((uint8_t) buf[1]) << 8) + (uint8_t) buf[2]; } -ssize_t swHttp2_get_frame_length(swProtocol *protocol, swSocket *conn, const char *buf, uint32_t length); -int swHttp2_send_setting_frame(swProtocol *protocol, swSocket *conn); -const char *swHttp2_get_type(int type); -int swHttp2_get_type_color(int type); +ssize_t get_frame_length(Protocol *protocol, network::Socket *conn, const char *buf, uint32_t length); +int send_setting_frame(Protocol *protocol, network::Socket *conn); +const char *get_type(int type); +int get_type_color(int type); -static sw_inline void swHttp2_init_settings(swHttp2_settings *settings) { +static sw_inline void init_settings(Settings *settings) { settings->header_table_size = SW_HTTP2_DEFAULT_HEADER_TABLE_SIZE; settings->window_size = SW_HTTP2_DEFAULT_WINDOW_SIZE; settings->max_concurrent_streams = SW_HTTP2_MAX_MAX_CONCURRENT_STREAMS; @@ -166,8 +169,7 @@ static sw_inline void swHttp2_init_settings(swHttp2_settings *settings) { | Frame Payload (0...) ... +---------------------------------------------------------------+ */ -static sw_inline void swHttp2_set_frame_header( - char *buffer, uint8_t type, uint32_t length, uint8_t flags, uint32_t stream_id) { +static sw_inline void set_frame_header(char *buffer, uint8_t type, uint32_t length, uint8_t flags, uint32_t stream_id) { buffer[0] = length >> 16; buffer[1] = length >> 8; buffer[2] = length; @@ -175,3 +177,6 @@ static sw_inline void swHttp2_set_frame_header( buffer[4] = flags; *(uint32_t *) (buffer + 5) = htonl(stream_id); } + +} // namespace http2 +} // namespace swoole diff --git a/include/swoole_websocket.h b/include/swoole_websocket.h index 1383cbd5afd..8a8cd59ef4b 100644 --- a/include/swoole_websocket.h +++ b/include/swoole_websocket.h @@ -28,35 +28,34 @@ #define SW_WEBSOCKET_EXT64_LENGTH 0x7F #define SW_WEBSOCKET_CLOSE_CODE_LEN 2 #define SW_WEBSOCKET_CLOSE_REASON_MAX_LEN 125 -#define SW_WEBSOCKET_OPCODE_MAX WEBSOCKET_OPCODE_PONG - -enum swWebsocket_status { - WEBSOCKET_STATUS_NONE = 0, - WEBSOCKET_STATUS_CONNECTION = 1, - WEBSOCKET_STATUS_HANDSHAKE = 2, - WEBSOCKET_STATUS_ACTIVE = 3, - WEBSOCKET_STATUS_CLOSING = 4, +#define SW_WEBSOCKET_OPCODE_MAX swoole::websocket::OPCODE_PONG + +namespace swoole { +namespace websocket { + +enum Status { + STATUS_NONE = 0, + STATUS_CONNECTION = 1, + STATUS_HANDSHAKE = 2, + STATUS_ACTIVE = 3, + STATUS_CLOSING = 4, }; -enum swWebSocket_frame_flag { - SW_WEBSOCKET_FLAG_FIN = 1 << 0, /* BC: must be 1 */ - SW_WEBSOCKET_FLAG_COMPRESS = 1 << 1, +enum Flag { + FLAG_FIN = 1 << 0, /* BC: must be 1 */ + FLAG_COMPRESS = 1 << 1, // readonly for user - SW_WEBSOCKET_FLAG_RSV1 = 1 << 2, - SW_WEBSOCKET_FLAG_RSV2 = 1 << 3, - SW_WEBSOCKET_FLAG_RSV3 = 1 << 4, - SW_WEBSOCKET_FLAG_MASK = 1 << 5, + FLAG_RSV1 = 1 << 2, + FLAG_RSV2 = 1 << 3, + FLAG_RSV3 = 1 << 4, + FLAG_MASK = 1 << 5, // for encoder/decoder - SW_WEBSOCKET_FLAG_ENCODE_HEADER_ONLY = 1 << 6, + FLAG_ENCODE_HEADER_ONLY = 1 << 6, + FLAGS_ALL = /* used to prevent overflow */ + FLAG_FIN | FLAG_RSV1 | FLAG_RSV2 | FLAG_RSV3 | FLAG_MASK | FLAG_COMPRESS }; -enum swWebSocket_frame_union_flag { - SW_WEBSOCKET_FLAGS_ALL = /* used to prevent overflow */ - SW_WEBSOCKET_FLAG_FIN | SW_WEBSOCKET_FLAG_RSV1 | SW_WEBSOCKET_FLAG_RSV2 | SW_WEBSOCKET_FLAG_RSV3 | - SW_WEBSOCKET_FLAG_MASK | SW_WEBSOCKET_FLAG_COMPRESS -}; - -struct swWebSocket_frame_header { +struct Header { /** * fin:1 rsv1:1 rsv2:1 rsv3:1 opcode:4 */ @@ -69,8 +68,8 @@ struct swWebSocket_frame_header { uchar MASK : 1; }; -struct swWebSocket_frame { - swWebSocket_frame_header header; +struct Frame { + Header header; char mask_key[SW_WEBSOCKET_MASK_LEN]; uint16_t header_length; size_t payload_length; @@ -79,78 +78,81 @@ struct swWebSocket_frame { #define WEBSOCKET_VERSION 13 -enum swWebsocket_opcode { - WEBSOCKET_OPCODE_CONTINUATION = 0x0, - WEBSOCKET_OPCODE_TEXT = 0x1, - WEBSOCKET_OPCODE_BINARY = 0x2, - WEBSOCKET_OPCODE_CLOSE = 0x8, - WEBSOCKET_OPCODE_PING = 0x9, - WEBSOCKET_OPCODE_PONG = 0xa, +enum Opcode { + OPCODE_CONTINUATION = 0x0, + OPCODE_TEXT = 0x1, + OPCODE_BINARY = 0x2, + OPCODE_CLOSE = 0x8, + OPCODE_PING = 0x9, + OPCODE_PONG = 0xa, }; -enum swWebsocket_close_reason { - WEBSOCKET_CLOSE_NORMAL = 1000, - WEBSOCKET_CLOSE_GOING_AWAY = 1001, - WEBSOCKET_CLOSE_PROTOCOL_ERROR = 1002, - WEBSOCKET_CLOSE_DATA_ERROR = 1003, - WEBSOCKET_CLOSE_STATUS_ERROR = 1005, - WEBSOCKET_CLOSE_ABNORMAL = 1006, - WEBSOCKET_CLOSE_MESSAGE_ERROR = 1007, - WEBSOCKET_CLOSE_POLICY_ERROR = 1008, - WEBSOCKET_CLOSE_MESSAGE_TOO_BIG = 1009, - WEBSOCKET_CLOSE_EXTENSION_MISSING = 1010, - WEBSOCKET_CLOSE_SERVER_ERROR = 1011, - WEBSOCKET_CLOSE_TLS = 1015, +enum CloseReason { + CLOSE_NORMAL = 1000, + CLOSE_GOING_AWAY = 1001, + CLOSE_PROTOCOL_ERROR = 1002, + CLOSE_DATA_ERROR = 1003, + CLOSE_STATUS_ERROR = 1005, + CLOSE_ABNORMAL = 1006, + CLOSE_MESSAGE_ERROR = 1007, + CLOSE_POLICY_ERROR = 1008, + CLOSE_MESSAGE_TOO_BIG = 1009, + CLOSE_EXTENSION_MISSING = 1010, + CLOSE_SERVER_ERROR = 1011, + CLOSE_TLS = 1015, }; -static inline uchar swWebSocket_get_flags(swWebSocket_frame *frame) { +static inline uchar get_flags(Frame *frame) { uchar flags = 0; if (frame->header.FIN) { - flags |= SW_WEBSOCKET_FLAG_FIN; + flags |= FLAG_FIN; } if (frame->header.RSV1) { - flags |= SW_WEBSOCKET_FLAG_RSV1; + flags |= FLAG_RSV1; } if (frame->header.RSV2) { - flags |= SW_WEBSOCKET_FLAG_RSV2; + flags |= FLAG_RSV2; } if (frame->header.RSV3) { - flags |= SW_WEBSOCKET_FLAG_RSV3; + flags |= FLAG_RSV3; } if (frame->header.MASK) { - flags |= SW_WEBSOCKET_FLAG_MASK; + flags |= FLAG_MASK; } return flags; } -static inline uchar swWebSocket_set_flags(uchar fin, uchar mask, uchar rsv1, uchar rsv2, uchar rsv3) { +static inline uchar set_flags(uchar fin, uchar mask, uchar rsv1, uchar rsv2, uchar rsv3) { uchar flags = 0; if (fin) { - flags |= SW_WEBSOCKET_FLAG_FIN; + flags |= FLAG_FIN; } if (mask) { - flags |= SW_WEBSOCKET_FLAG_MASK; + flags |= FLAG_MASK; } if (rsv1) { - flags |= SW_WEBSOCKET_FLAG_RSV1; + flags |= FLAG_RSV1; } if (rsv2) { - flags |= SW_WEBSOCKET_FLAG_RSV2; + flags |= FLAG_RSV2; } if (rsv3) { - flags |= SW_WEBSOCKET_FLAG_RSV3; + flags |= FLAG_RSV3; } return flags; } -bool swWebSocket_encode(swString *buffer, const char *data, size_t length, char opcode, uint8_t flags); -bool swWebSocket_decode(swWebSocket_frame *frame, char *data, size_t length); -int swWebSocket_pack_close_frame(swString *buffer, int code, char *reason, size_t length, uint8_t flags); -void swWebSocket_print_frame(swWebSocket_frame *frame); +bool encode(String *buffer, const char *data, size_t length, char opcode, uint8_t flags); +bool decode(Frame *frame, char *data, size_t length); +int pack_close_frame(String *buffer, int code, char *reason, size_t length, uint8_t flags); +void print_frame(Frame *frame); -inline bool swWebSocket_decode(swWebSocket_frame *frame, swString *str) { - return swWebSocket_decode(frame, str->str, str->length); +static inline bool decode(Frame *frame, String *str) { + return decode(frame, str->str, str->length); } -ssize_t swWebSocket_get_package_length(swProtocol *protocol, swSocket *conn, const char *data, uint32_t length); -int swWebSocket_dispatch_frame(swProtocol *protocol, swSocket *conn, const char *data, uint32_t length); +ssize_t get_package_length(Protocol *protocol, network::Socket *conn, const char *data, uint32_t length); +int dispatch_frame(Protocol *protocol, network::Socket *conn, const char *data, uint32_t length); + +} // namespace websocket +} // namespace swoole diff --git a/src/protocol/http.cc b/src/protocol/http.cc index 202ab0386f3..f3cf89114eb 100644 --- a/src/protocol/http.cc +++ b/src/protocol/http.cc @@ -26,10 +26,10 @@ using namespace swoole; using std::string; -using swoole::network::Socket; -using swoole::network::SendfileTask; using swoole::http_server::Request; using swoole::http_server::StaticHandler; +using swoole::network::SendfileTask; +using swoole::network::Socket; // clang-format off static const char *method_strings[] = @@ -690,7 +690,7 @@ string Request::get_date_if_modified_since() { return string(""); } //----------------------------------------------------------------- -} // namespace http +} // namespace http_server } // namespace swoole void Server::destroy_http_request(Connection *conn) { @@ -714,10 +714,10 @@ static void protocol_status_error(Socket *socket, Connection *conn) { ssize_t swHttpMix_get_package_length(Protocol *protocol, Socket *socket, const char *data, uint32_t length) { Connection *conn = (Connection *) socket->object; - if (conn->websocket_status >= WEBSOCKET_STATUS_HANDSHAKE) { - return swWebSocket_get_package_length(protocol, socket, data, length); + if (conn->websocket_status >= websocket::STATUS_HANDSHAKE) { + return websocket::get_package_length(protocol, socket, data, length); } else if (conn->http2_stream) { - return swHttp2_get_frame_length(protocol, socket, data, length); + return http2::get_frame_length(protocol, socket, data, length); } else { protocol_status_error(socket, conn); return SW_ERR; @@ -726,7 +726,7 @@ ssize_t swHttpMix_get_package_length(Protocol *protocol, Socket *socket, const c uint8_t swHttpMix_get_package_length_size(Socket *socket) { Connection *conn = (Connection *) socket->object; - if (conn->websocket_status >= WEBSOCKET_STATUS_HANDSHAKE) { + if (conn->websocket_status >= websocket::STATUS_HANDSHAKE) { return SW_WEBSOCKET_HEADER_LEN + SW_WEBSOCKET_MASK_LEN + sizeof(uint64_t); } else if (conn->http2_stream) { return SW_HTTP2_FRAME_HEADER_SIZE; @@ -738,8 +738,8 @@ uint8_t swHttpMix_get_package_length_size(Socket *socket) { int swHttpMix_dispatch_frame(Protocol *proto, Socket *socket, const char *data, uint32_t length) { Connection *conn = (Connection *) socket->object; - if (conn->websocket_status >= WEBSOCKET_STATUS_HANDSHAKE) { - return swWebSocket_dispatch_frame(proto, socket, data, length); + if (conn->websocket_status >= websocket::STATUS_HANDSHAKE) { + return websocket::dispatch_frame(proto, socket, data, length); } else if (conn->http2_stream) { return Server::dispatch_task(proto, socket, data, length); } else { diff --git a/src/protocol/http2.cc b/src/protocol/http2.cc index 234918292e4..243e03edf4e 100644 --- a/src/protocol/http2.cc +++ b/src/protocol/http2.cc @@ -23,13 +23,16 @@ using swoole::Protocol; using swoole::network::Socket; -int swHttp2_send_setting_frame(Protocol *protocol, Socket *_socket) { +namespace swoole { +namespace http2 { + +int send_setting_frame(Protocol *protocol, Socket *_socket) { char setting_frame[SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_SETTING_OPTION_SIZE * 3]; char *p = setting_frame; uint16_t id; uint32_t value; - swHttp2_set_frame_header(p, SW_HTTP2_TYPE_SETTINGS, SW_HTTP2_SETTING_OPTION_SIZE * 3, 0, 0); + set_frame_header(p, SW_HTTP2_TYPE_SETTINGS, SW_HTTP2_SETTING_OPTION_SIZE * 3, 0, 0); p += SW_HTTP2_FRAME_HEADER_SIZE; id = htons(SW_HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS); @@ -63,14 +66,14 @@ int swHttp2_send_setting_frame(Protocol *protocol, Socket *_socket) { | Frame Payload (0...) ... +---------------------------------------------------------------+ */ -ssize_t swHttp2_get_frame_length(Protocol *protocol, Socket *conn, const char *buf, uint32_t length) { +ssize_t get_frame_length(Protocol *protocol, Socket *conn, const char *buf, uint32_t length) { if (length < SW_HTTP2_FRAME_HEADER_SIZE) { return 0; } - return swHttp2_get_length(buf) + SW_HTTP2_FRAME_HEADER_SIZE; + return get_length(buf) + SW_HTTP2_FRAME_HEADER_SIZE; } -const char *swHttp2_get_type(int type) { +const char *get_type(int type) { switch (type) { case SW_HTTP2_TYPE_DATA: return "DATA"; @@ -97,7 +100,7 @@ const char *swHttp2_get_type(int type) { } } -int swHttp2_get_type_color(int type) { +int get_type_color(int type) { switch (type) { case SW_HTTP2_TYPE_DATA: case SW_HTTP2_TYPE_WINDOW_UPDATE: @@ -116,3 +119,6 @@ int swHttp2_get_type_color(int type) { return SW_COLOR_RED; } } + +} // namespace http2 +} // namespace swoole diff --git a/src/protocol/websocket.cc b/src/protocol/websocket.cc index 4e5312d6e96..2ada7937f92 100644 --- a/src/protocol/websocket.cc +++ b/src/protocol/websocket.cc @@ -18,13 +18,15 @@ #include "swoole_server.h" #include "swoole_websocket.h" -using swoole::Server; using swoole::Connection; -using swoole::String; using swoole::Protocol; +using swoole::Server; +using swoole::String; using swoole::network::Socket; -static inline uint16_t swWebSocket_get_ext_flags(uchar opcode, uchar flags) { +namespace swoole { +namespace websocket { +static inline uint16_t get_ext_flags(uchar opcode, uchar flags) { uint16_t ext_flags = opcode; ext_flags = ext_flags << 8; ext_flags += flags; @@ -53,7 +55,7 @@ static inline uint16_t swWebSocket_get_ext_flags(uchar opcode, uchar flags) { +---------------------------------------------------------------+ */ -ssize_t swWebSocket_get_package_length(Protocol *protocol, Socket *conn, const char *buf, uint32_t length) { +ssize_t get_package_length(Protocol *protocol, Socket *conn, const char *buf, uint32_t length) { // need more data if (length < SW_WEBSOCKET_HEADER_LEN) { return 0; @@ -96,7 +98,7 @@ ssize_t swWebSocket_get_package_length(Protocol *protocol, Socket *conn, const c return header_length + payload_length; } -static sw_inline void swWebSocket_mask(char *data, size_t len, const char *mask_key) { +static sw_inline void mask(char *data, size_t len, const char *mask_key) { size_t n = len / 8; uint64_t mask_key64 = ((uint64_t)(*((uint32_t *) mask_key)) << 32) | *((uint32_t *) mask_key); size_t i; @@ -110,16 +112,16 @@ static sw_inline void swWebSocket_mask(char *data, size_t len, const char *mask_ } } -bool swWebSocket_encode(String *buffer, const char *data, size_t length, char opcode, uint8_t _flags) { +bool encode(String *buffer, const char *data, size_t length, char opcode, uint8_t _flags) { int pos = 0; char frame_header[16]; - swWebSocket_frame_header *header = (swWebSocket_frame_header *) frame_header; - header->FIN = !!(_flags & SW_WEBSOCKET_FLAG_FIN); + Header *header = (Header *) frame_header; + header->FIN = !!(_flags & FLAG_FIN); header->OPCODE = opcode; - header->RSV1 = !!(_flags & SW_WEBSOCKET_FLAG_RSV1); + header->RSV1 = !!(_flags & FLAG_RSV1); header->RSV2 = 0; header->RSV3 = 0; - header->MASK = !!(_flags & SW_WEBSOCKET_FLAG_MASK); + header->MASK = !!(_flags & FLAG_MASK); pos = 2; if (length < 126) { @@ -141,17 +143,17 @@ bool swWebSocket_encode(String *buffer, const char *data, size_t length, char op */ if (header->MASK) { buffer->append(SW_WEBSOCKET_MASK_DATA, SW_WEBSOCKET_MASK_LEN); - if (_flags & SW_WEBSOCKET_FLAG_ENCODE_HEADER_ONLY) { + if (_flags & FLAG_ENCODE_HEADER_ONLY) { return false; } if (length > 0) { size_t offset = buffer->length; // Warn: buffer may be extended, string pointer will change buffer->append(data, length); - swWebSocket_mask(buffer->str + offset, length, SW_WEBSOCKET_MASK_DATA); + mask(buffer->str + offset, length, SW_WEBSOCKET_MASK_DATA); } } else { - if (length > 0 and !(_flags & SW_WEBSOCKET_FLAG_ENCODE_HEADER_ONLY)) { + if (length > 0 and !(_flags & FLAG_ENCODE_HEADER_ONLY)) { buffer->append(data, length); } } @@ -159,7 +161,7 @@ bool swWebSocket_encode(String *buffer, const char *data, size_t length, char op return true; } -bool swWebSocket_decode(swWebSocket_frame *frame, char *data, size_t length) { +bool decode(Frame *frame, char *data, size_t length) { memcpy(frame, data, SW_WEBSOCKET_HEADER_LEN); // 0-125 @@ -189,7 +191,7 @@ bool swWebSocket_decode(swWebSocket_frame *frame, char *data, size_t length) { if (frame->header.MASK) { memcpy(frame->mask_key, data + header_length, SW_WEBSOCKET_MASK_LEN); header_length += SW_WEBSOCKET_MASK_LEN; - swWebSocket_mask(data + header_length, payload_length, frame->mask_key); + mask(data + header_length, payload_length, frame->mask_key); } frame->payload = data + header_length; @@ -199,7 +201,7 @@ bool swWebSocket_decode(swWebSocket_frame *frame, char *data, size_t length) { return true; } -int swWebSocket_pack_close_frame(String *buffer, int code, char *reason, size_t length, uint8_t flags) { +int pack_close_frame(String *buffer, int code, char *reason, size_t length, uint8_t flags) { if (sw_unlikely(length > SW_WEBSOCKET_CLOSE_REASON_MAX_LEN)) { swWarn("the max length of close reason is %d", SW_WEBSOCKET_CLOSE_REASON_MAX_LEN); return SW_ERR; @@ -211,12 +213,12 @@ int swWebSocket_pack_close_frame(String *buffer, int code, char *reason, size_t if (length > 0) { memcpy(payload + SW_WEBSOCKET_CLOSE_CODE_LEN, reason, length); } - flags |= SW_WEBSOCKET_FLAG_FIN; - swWebSocket_encode(buffer, payload, SW_WEBSOCKET_CLOSE_CODE_LEN + length, WEBSOCKET_OPCODE_CLOSE, flags); + flags |= FLAG_FIN; + encode(buffer, payload, SW_WEBSOCKET_CLOSE_CODE_LEN + length, OPCODE_CLOSE, flags); return SW_OK; } -void swWebSocket_print_frame(swWebSocket_frame *frame) { +void print_frame(Frame *frame) { printf("FIN: %x, RSV1: %d, RSV2: %d, RSV3: %d, opcode: %d, MASK: %d, length: %ld\n", frame->header.FIN, frame->header.RSV1, @@ -231,7 +233,7 @@ void swWebSocket_print_frame(swWebSocket_frame *frame) { } } -int swWebSocket_dispatch_frame(Protocol *proto, Socket *_socket, const char *data, uint32_t length) { +int dispatch_frame(Protocol *proto, Socket *_socket, const char *data, uint32_t length) { Server *serv = (Server *) proto->private_data_2; Connection *conn = (Connection *) _socket->object; @@ -240,8 +242,8 @@ int swWebSocket_dispatch_frame(Protocol *proto, Socket *_socket, const char *dat send_frame.str = buf; send_frame.size = sizeof(buf); - swWebSocket_frame ws; - swWebSocket_decode(&ws, const_cast(data), length); + Frame ws; + decode(&ws, const_cast(data), length); String *frame_buffer; int frame_length; @@ -249,7 +251,7 @@ int swWebSocket_dispatch_frame(Protocol *proto, Socket *_socket, const char *dat size_t offset; switch (ws.header.OPCODE) { - case WEBSOCKET_OPCODE_CONTINUATION: + case OPCODE_CONTINUATION: frame_buffer = conn->websocket_buffer; if (frame_buffer == nullptr) { swWarn("bad frame[opcode=0]. remote_addr=%s:%d", conn->info.get_ip(), conn->info.get_port()); @@ -268,17 +270,17 @@ int swWebSocket_dispatch_frame(Protocol *proto, Socket *_socket, const char *dat // frame is finished, do dispatch if (ws.header.FIN) { proto->ext_flags = conn->websocket_buffer->offset; - proto->ext_flags |= SW_WEBSOCKET_FLAG_FIN; + proto->ext_flags |= FLAG_FIN; Server::dispatch_task(proto, _socket, frame_buffer->str, frame_buffer->length); delete frame_buffer; conn->websocket_buffer = nullptr; } break; - case WEBSOCKET_OPCODE_TEXT: - case WEBSOCKET_OPCODE_BINARY: { + case OPCODE_TEXT: + case OPCODE_BINARY: { offset = length - ws.payload_length; - proto->ext_flags = swWebSocket_get_ext_flags(ws.header.OPCODE, swWebSocket_get_flags(&ws)); + proto->ext_flags = get_ext_flags(ws.header.OPCODE, get_flags(&ws)); if (!ws.header.FIN) { if (conn->websocket_buffer) { @@ -294,11 +296,11 @@ int swWebSocket_dispatch_frame(Protocol *proto, Socket *_socket, const char *dat } break; } - case WEBSOCKET_OPCODE_PING: - case WEBSOCKET_OPCODE_PONG: + case OPCODE_PING: + case OPCODE_PONG: if (length >= (sizeof(buf) - SW_WEBSOCKET_HEADER_LEN)) { swWarn("%s frame application data is too big. remote_addr=%s:%d", - ws.header.OPCODE == WEBSOCKET_OPCODE_PING ? "ping" : "pong", + ws.header.OPCODE == OPCODE_PING ? "ping" : "pong", conn->info.get_ip(), conn->info.get_port()); return SW_ERR; @@ -310,19 +312,19 @@ int swWebSocket_dispatch_frame(Protocol *proto, Socket *_socket, const char *dat data += offset; length -= offset; } - proto->ext_flags = swWebSocket_get_ext_flags(ws.header.OPCODE, swWebSocket_get_flags(&ws)); + proto->ext_flags = get_ext_flags(ws.header.OPCODE, get_flags(&ws)); Server::dispatch_task(proto, _socket, data, length); break; - case WEBSOCKET_OPCODE_CLOSE: + case OPCODE_CLOSE: if ((length - SW_WEBSOCKET_HEADER_LEN) > SW_WEBSOCKET_CLOSE_REASON_MAX_LEN) { return SW_ERR; } - if (conn->websocket_status != WEBSOCKET_STATUS_CLOSING) { + if (conn->websocket_status != STATUS_CLOSING) { // Dispatch the frame with the same format of message frame offset = length - ws.payload_length; - proto->ext_flags = swWebSocket_get_ext_flags(ws.header.OPCODE, swWebSocket_get_flags(&ws)); + proto->ext_flags = get_ext_flags(ws.header.OPCODE, get_flags(&ws)); Server::dispatch_task(proto, _socket, data + offset, length - offset); @@ -346,3 +348,5 @@ int swWebSocket_dispatch_frame(Protocol *proto, Socket *_socket, const char *dat } return SW_OK; } +} // namespace websocket +} // namespace swoole diff --git a/src/server/master.cc b/src/server/master.cc index 6b874267648..5c04c060bbb 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -1366,6 +1366,9 @@ bool Server::is_healthy_connection(double now, Connection *conn) { if (!lp) { return true; } + if (lp->heartbeat_idle_time == 0) { + return true; + } if (conn->last_recv_time > now - lp->heartbeat_idle_time) { return true; } diff --git a/src/server/port.cc b/src/server/port.cc index 1c6385d6d7a..f4bb2682e44 100644 --- a/src/server/port.cc +++ b/src/server/port.cc @@ -22,8 +22,8 @@ #include "swoole_redis.h" using swoole::http_server::Request; -using swoole::network::Socket; using swoole::network::Address; +using swoole::network::Socket; namespace swoole { @@ -81,7 +81,7 @@ static bool ssl_matches_wildcard_name(const char *subjectname, const char *certn * 3) no . between prefix and suffix **/ return strcasecmp(wildcard + 1, subjectname + subject_len - suffix_len) == 0 && - memchr(subjectname + prefix_len, '.', subject_len - suffix_len - prefix_len) == NULL; + memchr(subjectname + prefix_len, '.', subject_len - suffix_len - prefix_len) == NULL; } return 0; @@ -239,14 +239,14 @@ void Server::init_port_protocol(ListenPort *ls) { ls->protocol.onPackage = swHttpMix_dispatch_frame; } else if (ls->open_http2_protocol) { ls->protocol.package_length_size = SW_HTTP2_FRAME_HEADER_SIZE; - ls->protocol.get_package_length = swHttp2_get_frame_length; + ls->protocol.get_package_length = http2::get_frame_length; ls->protocol.onPackage = Server::dispatch_task; } else #endif if (ls->open_websocket_protocol) { ls->protocol.package_length_size = SW_WEBSOCKET_HEADER_LEN + SW_WEBSOCKET_MASK_LEN + sizeof(uint64_t); - ls->protocol.get_package_length = swWebSocket_get_package_length; - ls->protocol.onPackage = swWebSocket_dispatch_frame; + ls->protocol.get_package_length = websocket::get_package_length; + ls->protocol.onPackage = websocket::dispatch_frame; } ls->protocol.package_length_offset = 0; ls->protocol.package_body_offset = 0; @@ -271,7 +271,7 @@ bool ListenPort::import(int sock) { socket = new Socket(); socket->fd = sock; - + // get socket type if (socket->get_option(SOL_SOCKET, SO_TYPE, &_type) < 0) { swSysWarn("getsockopt(%d, SOL_SOCKET, SO_TYPE) failed", sock); @@ -380,10 +380,10 @@ static int Port_onRead_http(Reactor *reactor, ListenPort *port, Event *event) { Connection *conn = (Connection *) _socket->object; Server *serv = (Server *) reactor->ptr; - if (conn->websocket_status >= WEBSOCKET_STATUS_HANDSHAKE) { + if (conn->websocket_status >= websocket::STATUS_HANDSHAKE) { if (conn->http_upgrade == 0) { serv->destroy_http_request(conn); - conn->websocket_status = WEBSOCKET_STATUS_ACTIVE; + conn->websocket_status = websocket::STATUS_ACTIVE; conn->http_upgrade = 1; } return Port_onRead_check_length(reactor, port, event); @@ -487,7 +487,7 @@ static int Port_onRead_http(Reactor *reactor, ListenPort *port, Event *event) { #ifdef SW_USE_HTTP2 } conn->http2_stream = 1; - swHttp2_send_setting_frame(protocol, _socket); + http2::send_setting_frame(protocol, _socket); if (buffer->length == sizeof(SW_HTTP2_PRI_STRING) - 1) { serv->destroy_http_request(conn); buffer->clear(); @@ -723,4 +723,4 @@ void ListenPort::close() { } } -} +} // namespace swoole diff --git a/src/server/process.cc b/src/server/process.cc index a32d4c8d499..1a02540d2cf 100644 --- a/src/server/process.cc +++ b/src/server/process.cc @@ -137,11 +137,13 @@ bool ProcessFactory::notify(DataHead *ev) { return dispatch(&task); } -static inline int process_sendto_worker(Server *serv, DataHead *head, const iovec *iov, size_t iovcnt, void *private_data) { +static inline int process_sendto_worker( + Server *serv, DataHead *head, const iovec *iov, size_t iovcnt, void *private_data) { return serv->send_to_worker_from_master((Worker *) private_data, iov, iovcnt); } -static inline int process_sendto_reactor(Server *serv, DataHead *head, const iovec *iov, size_t iovcnt, void *private_data) { +static inline int process_sendto_reactor( + Server *serv, DataHead *head, const iovec *iov, size_t iovcnt, void *private_data) { return serv->send_to_reactor_thread(head, iov, iovcnt, ((Connection *) private_data)->session_id); } @@ -203,7 +205,7 @@ bool ProcessFactory::dispatch(SendData *task) { */ static bool process_send_packet(Server *serv, SendData *resp, SendFunc _send, void *private_data) { const char *data = resp->data; - uint32_t send_n = resp->info.len; + uint32_t l_payload = resp->info.len; off_t offset = 0; uint32_t copy_n; @@ -212,17 +214,17 @@ static bool process_send_packet(Server *serv, SendData *resp, SendFunc _send, vo uint32_t max_length = serv->ipc_max_size - sizeof(resp->info); resp->info.msg_id = serv->worker_msg_id.fetch_add(1); - if (send_n <= max_length) { + if (l_payload <= max_length) { resp->info.flags = 0; - resp->info.len = send_n; + resp->info.len = l_payload; size_t iovcnt; iov[0].iov_base = &resp->info; iov[0].iov_len = sizeof(resp->info); - if (resp->data) { + if (resp->data && l_payload > 0) { iov[1].iov_base = (void *) resp->data; - iov[1].iov_len = send_n; + iov[1].iov_len = l_payload; iovcnt = 2; } else { iovcnt = 1; @@ -242,14 +244,14 @@ static bool process_send_packet(Server *serv, SendData *resp, SendFunc _send, vo _ipc_use_chunk: #endif resp->info.flags = SW_EVENT_DATA_CHUNK | SW_EVENT_DATA_BEGIN; - resp->info.len = send_n; + resp->info.len = l_payload; - while (send_n > 0) { - if (send_n > max_length) { + while (l_payload > 0) { + if (l_payload > max_length) { copy_n = max_length; } else { resp->info.flags |= SW_EVENT_DATA_END; - copy_n = send_n; + copy_n = l_payload; } iov[0].iov_base = &resp->info; @@ -273,7 +275,7 @@ static bool process_send_packet(Server *serv, SendData *resp, SendFunc _send, vo resp->info.flags &= ~SW_EVENT_DATA_BEGIN; } - send_n -= copy_n; + l_payload -= copy_n; offset += copy_n; } @@ -416,7 +418,7 @@ bool ProcessFactory::end(SessionId session_id, int flags) { } } - _close: +_close: if (conn == nullptr || conn->active == 0) { swoole_set_last_error(SW_ERROR_SESSION_NOT_EXIST); return false; diff --git a/tests/swoole_server_port/heartbeat.phpt b/tests/swoole_server_port/heartbeat.phpt deleted file mode 100644 index 80d69c69f87..00000000000 --- a/tests/swoole_server_port/heartbeat.phpt +++ /dev/null @@ -1,87 +0,0 @@ ---TEST-- -swoole_server_port: heartbeat ---SKIPIF-- - ---FILE-- -initFreePorts(2); - -$pm->parentFunc = function ($pid) use ($pm) -{ - go(function () use ($pm) - { - $cli = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP); - $cli->connect('127.0.0.1', $pm->getFreePort(0)); - for ($i = 0; $i < 2; ++$i) { - $cli->send('hello'); - $data = $cli->recv(); - if ($data != 'ok') { - echo "ERROR\n"; - } - co::sleep(2); - } - co::sleep(3); - $cli->send('hello'); - $data = $cli->recv(); - if ($data == 'ok') { - echo "ERROR\n"; - } - }); - - go(function () use ($pm) - { - $cli = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP); - $cli->connect('127.0.0.1', $pm->getFreePort(1)); - for ($i = 0; $i < 2; ++$i) { - $cli->send('hello'); - $data = $cli->recv(); - if ($data != 'ok') { - echo "ERROR\n"; - } - co::sleep(2); - } - co::sleep(3); - $cli->send('hello'); - $data = $cli->recv(); - if ($data == 'ok') { - echo "ERROR\n"; - } else { - echo "OK"; - } - }); - - swoole_event_wait(); - swoole_process::kill($pid); -}; - -$pm->childFunc = function () use ($pm) -{ - $server = new swoole_server('127.0.0.1', $pm->getFreePort(0), SWOOLE_BASE); - $server->set([ - 'heartbeat_check_interval' => 1, - 'heartbeat_idle_time' => 3 - ]); - $server->on('receive', function ($server, $fd, $reactorId, $data) { - $server->send($fd, 'ok'); - }); - - $port2 = $server->listen('127.0.0.1', $pm->getFreePort(1), SWOOLE_SOCK_TCP); - // $port2->set([ - // 'heartbeat_check_interval' => 1, - // 'heartbeat_idle_time' => 5 - // ]); - $port2->on('receive', function ($server, $fd, $reactorId, $data) { - $server->send($fd, 'ok'); - }); - - $server->start(); -}; - -$pm->childFirst(); -$pm->run(); -?> ---EXPECT-- -OK diff --git a/tests/swoole_server_port/heartbeat_1.phpt b/tests/swoole_server_port/heartbeat_1.phpt new file mode 100644 index 00000000000..301809d339b --- /dev/null +++ b/tests/swoole_server_port/heartbeat_1.phpt @@ -0,0 +1,93 @@ +--TEST-- +swoole_server_port: heartbeat 1 +--SKIPIF-- + +--FILE-- +initFreePorts(2); + +$pm->parentFunc = function ($pid) use ($pm) +{ + run(function () use ($pm) { + go(function () use ($pm) { + $cli = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP); + $cli->connect('127.0.0.1', $pm->getFreePort(0)); + for ($i = 0; $i < 2; ++$i) { + $cli->send('hello'); + $data = $cli->recv(); + if ($data != 'ok') { + echo "ERROR\n"; + } + System::sleep(2); + } + System::sleep(3); + $cli->send('hello'); + $data = $cli->recv(); + if ($data == 'ok') { + echo "ERROR\n"; + } + }); + + go(function () use ($pm) { + $cli = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP); + $cli->connect('127.0.0.1', $pm->getFreePort(1)); + for ($i = 0; $i < 2; ++$i) { + $cli->send('hello'); + $data = $cli->recv(); + if ($data != 'ok') { + echo "ERROR\n"; + } + System::sleep(2); + } + System::sleep(3); + $cli->send('hello'); + $data = $cli->recv(); + if ($data == 'ok') { + echo "ERROR\n"; + } else { + echo "OK"; + } + }); + }); + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm) +{ + $server = new Server('127.0.0.1', $pm->getFreePort(0), SWOOLE_BASE); + $server->set([ + 'heartbeat_check_interval' => 1, + 'heartbeat_idle_time' => 3 + ]); + $server->on('receive', function (Server $server, $fd, $reactorId, $data) { + $server->send($fd, 'ok'); + }); + $server->on("WorkerStart", function (Server $serv) use ($pm) { + $pm->wakeup(); + }); + + $port2 = $server->listen('127.0.0.1', $pm->getFreePort(1), SWOOLE_SOCK_TCP); + // $port2->set([ + // 'heartbeat_check_interval' => 1, + // 'heartbeat_idle_time' => 5 + // ]); + $port2->on('receive', function (Server $server, $fd, $reactorId, $data) { + $server->send($fd, 'ok'); + }); + + $server->start(); +}; + +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +OK diff --git a/tests/swoole_server_port/heartbeat_2.phpt b/tests/swoole_server_port/heartbeat_2.phpt index d558b3cc473..2e74ef628ef 100644 --- a/tests/swoole_server_port/heartbeat_2.phpt +++ b/tests/swoole_server_port/heartbeat_2.phpt @@ -9,6 +9,7 @@ require __DIR__ . '/../include/bootstrap.php'; use function Swoole\Coroutine\go; use function Swoole\Coroutine\run; use Swoole\Coroutine\System; +use Swoole\Server; $pm = new ProcessManager; $pm->initFreePorts(3); @@ -39,11 +40,14 @@ $pm->parentFunc = function ($pid) use ($pm) { $pm->childFunc = function () use ($pm) { - $server = new swoole_server('127.0.0.1', $pm->getFreePort(0), SWOOLE_BASE); + $server = new Server('127.0.0.1', $pm->getFreePort(0), SWOOLE_BASE); $server->set([ 'heartbeat_check_interval' => 1, 'heartbeat_idle_time' => 1, ]); + $server->on("WorkerStart", function (Server $serv) use ($pm) { + $pm->wakeup(); + }); $server->on('receive', function ($server, $fd, $reactorId, $data) { $server->send($fd, 'ok'); }); diff --git a/tests/swoole_server_port/heartbeat_3.phpt b/tests/swoole_server_port/heartbeat_3.phpt new file mode 100644 index 00000000000..25e13d79154 --- /dev/null +++ b/tests/swoole_server_port/heartbeat_3.phpt @@ -0,0 +1,60 @@ +--TEST-- +swoole_server_port: heartbeat 3 +--SKIPIF-- + +--FILE-- +initFreePorts(3); + +$pm->parentFunc = function ($pid) use ($pm) { + run(function () use ($pm) { + $test_func = function ($port_index, $sleep_seconds) use ($pm) { + $cli = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP); + $cli->connect('127.0.0.1', $pm->getFreePort($port_index)); + System::sleep($sleep_seconds); + return $cli->recv(0.01); + }; + go(function () use ($test_func) { + Assert::same($test_func(0, 3), false); + echo "DONE 0\n"; + }); + go(function () use ($test_func) { + Assert::same($test_func(1, 2.3), ''); + echo "DONE 1\n"; + }); + }); + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm) +{ + $server = new swoole_server('127.0.0.1', $pm->getFreePort(0), SWOOLE_BASE); + $server->on('receive', function ($server, $fd, $reactorId, $data) { + $server->send($fd, 'ok'); + }); + $server->on("WorkerStart", function (Server $serv) use ($pm) { + $pm->wakeup(); + }); + + $port2 = $server->listen('127.0.0.1', $pm->getFreePort(1), SWOOLE_SOCK_TCP); + $port2->set([ + 'heartbeat_idle_time' => 2, + ]); + + $server->start(); +}; + +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +DONE 1 +DONE 0 From dc1377e298b321afa44bed16baa535e0681a1510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Mon, 5 Jul 2021 13:28:20 +0800 Subject: [PATCH 173/936] Added http_compression/body_decompression options for HttpClient (#4299) --- ext-src/swoole_http_client_coro.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ext-src/swoole_http_client_coro.cc b/ext-src/swoole_http_client_coro.cc index b59142d135f..40bc30931dc 100644 --- a/ext-src/swoole_http_client_coro.cc +++ b/ext-src/swoole_http_client_coro.cc @@ -117,6 +117,8 @@ class HttpClient { bool websocket = false; // if upgrade successfully bool chunked = false; // Transfer-Encoding: chunked bool websocket_mask = true; // enable websocket mask + bool body_decompression = true; + bool http_compression = true; #ifdef SW_HAVE_ZLIB bool websocket_compression = false; // allow to compress websocket messages #endif @@ -541,7 +543,7 @@ static int http_parser_on_headers_complete(swoole_http_parser *parser) { static int http_parser_on_body(swoole_http_parser *parser, const char *at, size_t length) { HttpClient *http = (HttpClient *) parser->data; #ifdef SW_HAVE_COMPRESSION - if (!http->compression_error && http->compress_method != HTTP_COMPRESS_NONE) { + if (http->body_decompression && !http->compression_error && http->compress_method != HTTP_COMPRESS_NONE) { if (!http->decompress_response(at, length)) { http->compression_error = true; goto _append_raw; @@ -774,6 +776,12 @@ void HttpClient::apply_setting(zval *zset, const bool check_all) { if (php_swoole_array_get_value(vht, "websocket_mask", ztmp)) { websocket_mask = zval_is_true(ztmp); } + if (php_swoole_array_get_value(vht, "http_compression", ztmp)) { + http_compression = zval_is_true(ztmp); + } + if (php_swoole_array_get_value(vht, "body_decompression", ztmp)) { + body_decompression = zval_is_true(ztmp); + } #ifdef SW_HAVE_ZLIB if (php_swoole_array_get_value(vht, "websocket_compression", ztmp)) { websocket_compression = zval_is_true(ztmp); @@ -1060,7 +1068,7 @@ bool HttpClient::send() { } } #ifdef SW_HAVE_COMPRESSION - if (!(header_flag & HTTP_HEADER_ACCEPT_ENCODING)) { + if (http_compression && !(header_flag & HTTP_HEADER_ACCEPT_ENCODING)) { add_headers(buffer, ZEND_STRL("Accept-Encoding"), #if defined(SW_HAVE_ZLIB) && defined(SW_HAVE_BROTLI) From e14072ce1f8c93121de736599c0dd64408c0af8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Mon, 5 Jul 2021 13:51:17 +0800 Subject: [PATCH 174/936] Optimize table iterator (#4297) * Remove Table ArrayAccess, Refactor TableIterator * Added Table::exists() * Remove row tests * refactor, add core tests --- core-tests/src/memory/table.cpp | 27 ++++ ext-src/swoole_table.cc | 269 ++------------------------------ include/swoole_table.h | 60 ++++++- src/memory/table.cc | 44 ++++-- tests/swoole_table/row.phpt | 25 --- 5 files changed, 128 insertions(+), 297 deletions(-) delete mode 100644 tests/swoole_table/row.phpt diff --git a/core-tests/src/memory/table.cpp b/core-tests/src/memory/table.cpp index a2c83c4c0b9..a7d9af58569 100644 --- a/core-tests/src/memory/table.cpp +++ b/core-tests/src/memory/table.cpp @@ -23,6 +23,7 @@ using namespace swoole; #include +#include struct exception_t : public std::exception { int code; @@ -119,6 +120,10 @@ class table_t { return table->count(); } + Table *ptr() { + return table; + } + ~table_t() { if (table) { table->destroy(); @@ -144,3 +149,25 @@ TEST(table, create) { ASSERT_TRUE(table.del("php")); ASSERT_FALSE(table.exists("php")); } + +TEST(table, iterator) { + table_t table(1024); + + table.set("php", {"php", 1, 1.245}); + table.set("java", {"java", 2, 3.1415926}); + table.set("c++", {"c++", 3, 4.888}); + + auto _ptr = table.ptr(); + _ptr->rewind(); + auto count = 0; + while (true) { + _ptr->forward(); + auto row = _ptr->current(); + if (row->key_len == 0) { + break; + } + ASSERT_TRUE(_ptr->exists(row->key, row->key_len)); + count++; + } + ASSERT_EQ(count, _ptr->count()); +} diff --git a/ext-src/swoole_table.cc b/ext-src/swoole_table.cc index a6105e08e7b..eb3949594cb 100644 --- a/ext-src/swoole_table.cc +++ b/ext-src/swoole_table.cc @@ -72,9 +72,6 @@ static inline void php_swoole_table_get_field_value( static zend_class_entry *swoole_table_ce; static zend_object_handlers swoole_table_handlers; -static zend_class_entry *swoole_table_row_ce; -static zend_object_handlers swoole_table_row_handlers; - struct TableObject { Table *ptr; zend_object std; @@ -124,43 +121,6 @@ static inline zend_object *php_swoole_table_create_object(zend_class_entry *ce) return &table->std; } -struct TableRowObject { - Table *ptr; - zend_object std; -}; - -static inline TableRowObject *php_swoole_table_row_fetch_object(zend_object *obj) { - return (TableRowObject *) ((char *) obj - swoole_table_row_handlers.offset); -} - -static inline Table *php_swoole_table_row_get_ptr(zval *zobject) { - return php_swoole_table_row_fetch_object(Z_OBJ_P(zobject))->ptr; -} - -static inline Table *php_swoole_table_row_get_and_check_ptr(zval *zobject) { - Table *table_row = php_swoole_table_row_get_ptr(zobject); - if (!table_row) { - php_swoole_fatal_error(E_ERROR, "you can only get Table\\Row from Table"); - } - return table_row; -} - -static inline void php_swoole_table_row_set_ptr(zval *zobject, Table *ptr) { - php_swoole_table_row_fetch_object(Z_OBJ_P(zobject))->ptr = ptr; -} - -static inline void php_swoole_table_row_free_object(zend_object *object) { - zend_object_std_dtor(object); -} - -static inline zend_object *php_swoole_table_row_create_object(zend_class_entry *ce) { - TableRowObject *table_row = (TableRowObject *) zend_object_alloc(sizeof(TableRowObject), ce); - zend_object_std_init(&table_row->std, ce); - object_properties_init(&table_row->std, ce); - table_row->std.handlers = &swoole_table_row_handlers; - return &table_row->std; -} - // clang-format off ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_table_void, 0, 0, 0) ZEND_END_ARG_INFO() @@ -190,23 +150,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_table_exists, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_table_offsetExists, 0, 0, 1) - ZEND_ARG_INFO(0, offset) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_table_offsetGet, 0, 0, 1) - ZEND_ARG_INFO(0, offset) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_table_offsetSet, 0, 0, 2) - ZEND_ARG_INFO(0, offset) - ZEND_ARG_INFO(0, value) -ZEND_END_ARG_INFO() - -ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_table_offsetUnset, 0, 0, 1) - ZEND_ARG_INFO(0, offset) -ZEND_END_ARG_INFO() - ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_table_del, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_END_ARG_INFO() @@ -238,10 +181,6 @@ static PHP_METHOD(swoole_table, count); static PHP_METHOD(swoole_table, destroy); static PHP_METHOD(swoole_table, getSize); static PHP_METHOD(swoole_table, getMemorySize); -static PHP_METHOD(swoole_table, offsetExists); -static PHP_METHOD(swoole_table, offsetGet); -static PHP_METHOD(swoole_table, offsetSet); -static PHP_METHOD(swoole_table, offsetUnset); static PHP_METHOD(swoole_table, rewind); static PHP_METHOD(swoole_table, next); @@ -249,11 +188,6 @@ static PHP_METHOD(swoole_table, current); static PHP_METHOD(swoole_table, key); static PHP_METHOD(swoole_table, valid); -static PHP_METHOD(swoole_table_row, offsetExists); -static PHP_METHOD(swoole_table_row, offsetGet); -static PHP_METHOD(swoole_table_row, offsetSet); -static PHP_METHOD(swoole_table_row, offsetUnset); -static PHP_METHOD(swoole_table_row, __destruct); SW_EXTERN_C_END // clang-format off @@ -274,27 +208,12 @@ static const zend_function_entry swoole_table_methods[] = PHP_ME(swoole_table, decr, arginfo_swoole_table_decr, ZEND_ACC_PUBLIC) PHP_ME(swoole_table, getSize, arginfo_swoole_table_void, ZEND_ACC_PUBLIC) PHP_ME(swoole_table, getMemorySize, arginfo_swoole_table_void, ZEND_ACC_PUBLIC) - // implement ArrayAccess - PHP_ME(swoole_table, offsetExists, arginfo_swoole_table_offsetExists, ZEND_ACC_PUBLIC) - PHP_ME(swoole_table, offsetGet, arginfo_swoole_table_offsetGet, ZEND_ACC_PUBLIC) - PHP_ME(swoole_table, offsetSet, arginfo_swoole_table_offsetSet, ZEND_ACC_PUBLIC) - PHP_ME(swoole_table, offsetUnset, arginfo_swoole_table_offsetUnset, ZEND_ACC_PUBLIC) // implement Iterator PHP_ME(swoole_table, rewind, arginfo_swoole_table_void, ZEND_ACC_PUBLIC) + PHP_ME(swoole_table, valid, arginfo_swoole_table_void, ZEND_ACC_PUBLIC) PHP_ME(swoole_table, next, arginfo_swoole_table_void, ZEND_ACC_PUBLIC) PHP_ME(swoole_table, current, arginfo_swoole_table_void, ZEND_ACC_PUBLIC) PHP_ME(swoole_table, key, arginfo_swoole_table_void, ZEND_ACC_PUBLIC) - PHP_ME(swoole_table, valid, arginfo_swoole_table_void, ZEND_ACC_PUBLIC) - PHP_FE_END -}; - -static const zend_function_entry swoole_table_row_methods[] = -{ - PHP_ME(swoole_table_row, offsetExists, arginfo_swoole_table_offsetExists, ZEND_ACC_PUBLIC) - PHP_ME(swoole_table_row, offsetGet, arginfo_swoole_table_offsetGet, ZEND_ACC_PUBLIC) - PHP_ME(swoole_table_row, offsetSet, arginfo_swoole_table_offsetSet, ZEND_ACC_PUBLIC) - PHP_ME(swoole_table_row, offsetUnset, arginfo_swoole_table_offsetUnset, ZEND_ACC_PUBLIC) - PHP_ME(swoole_table_row, __destruct, arginfo_swoole_table_void, ZEND_ACC_PUBLIC) PHP_FE_END }; // clang-format on @@ -306,7 +225,7 @@ void php_swoole_table_minit(int module_number) { SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_table, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT( swoole_table, php_swoole_table_create_object, php_swoole_table_free_object, TableObject, std); - zend_class_implements(swoole_table_ce, 2, zend_ce_iterator, zend_ce_arrayaccess); + zend_class_implements(swoole_table_ce, 1, zend_ce_iterator); #ifdef SW_HAVE_COUNTABLE zend_class_implements(swoole_table_ce, 1, zend_ce_countable); #endif @@ -317,17 +236,6 @@ void php_swoole_table_minit(int module_number) { zend_declare_class_constant_long(swoole_table_ce, ZEND_STRL("TYPE_INT"), TableColumn::TYPE_INT); zend_declare_class_constant_long(swoole_table_ce, ZEND_STRL("TYPE_STRING"), TableColumn::TYPE_STRING); zend_declare_class_constant_long(swoole_table_ce, ZEND_STRL("TYPE_FLOAT"), TableColumn::TYPE_FLOAT); - - SW_INIT_CLASS_ENTRY(swoole_table_row, "Swoole\\Table\\Row", "swoole_table_row", nullptr, swoole_table_row_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_table_row, zend_class_serialize_deny, zend_class_unserialize_deny); - SW_SET_CLASS_CLONEABLE(swoole_table_row, sw_zend_class_clone_deny); - SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_table_row, sw_zend_class_unset_property_deny); - SW_SET_CLASS_CUSTOM_OBJECT( - swoole_table_row, php_swoole_table_row_create_object, php_swoole_table_row_free_object, TableRowObject, std); - zend_class_implements(swoole_table_row_ce, 1, zend_ce_arrayaccess); - - zend_declare_property_null(swoole_table_row_ce, ZEND_STRL("key"), ZEND_ACC_PUBLIC); - zend_declare_property_null(swoole_table_row_ce, ZEND_STRL("value"), ZEND_ACC_PUBLIC); } PHP_METHOD(swoole_table, __construct) { @@ -482,10 +390,6 @@ static PHP_METHOD(swoole_table, set) { RETURN_TRUE; } -static PHP_METHOD(swoole_table, offsetSet) { - ZEND_MN(swoole_table_set)(INTERNAL_FUNCTION_PARAM_PASSTHRU); -} - static PHP_METHOD(swoole_table, incr) { Table *table = php_swoole_table_get_and_check_ptr2(ZEND_THIS); char *key; @@ -631,34 +535,6 @@ static PHP_METHOD(swoole_table, get) { _rowlock->unlock(); } -static PHP_METHOD(swoole_table, offsetGet) { - Table *table = php_swoole_table_get_and_check_ptr2(ZEND_THIS); - char *key; - size_t keylen; - char *field = nullptr; - size_t field_len = 0; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s", &key, &keylen, &field, &field_len) == FAILURE) { - RETURN_FALSE; - } - - zval value; - TableRow *_rowlock = nullptr; - TableRow *row = table->get(key, keylen, &_rowlock); - if (!row) { - array_init(&value); - } else { - php_swoole_table_row2array(table, row, &value); - } - _rowlock->unlock(); - - object_init_ex(return_value, swoole_table_row_ce); - zend_update_property(swoole_table_row_ce, SW_Z8_OBJ_P(return_value), ZEND_STRL("value"), &value); - zend_update_property_stringl(swoole_table_row_ce, SW_Z8_OBJ_P(return_value), ZEND_STRL("key"), key, keylen); - zval_ptr_dtor(&value); - php_swoole_table_row_set_ptr(return_value, table); -} - static PHP_METHOD(swoole_table, exists) { Table *table = php_swoole_table_get_and_check_ptr2(ZEND_THIS); char *key; @@ -667,19 +543,7 @@ static PHP_METHOD(swoole_table, exists) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &key, &keylen) == FAILURE) { RETURN_FALSE; } - - TableRow *_rowlock = nullptr; - TableRow *row = table->get(key, keylen, &_rowlock); - _rowlock->unlock(); - if (!row) { - RETURN_FALSE; - } else { - RETURN_TRUE; - } -} - -static PHP_METHOD(swoole_table, offsetExists) { - ZEND_MN(swoole_table_exists)(INTERNAL_FUNCTION_PARAM_PASSTHRU); + RETURN_BOOL(table->exists(key, keylen)); } static PHP_METHOD(swoole_table, del) { @@ -694,21 +558,15 @@ static PHP_METHOD(swoole_table, del) { RETURN_BOOL(table->del(key, keylen)); } -static PHP_METHOD(swoole_table, offsetUnset) { - ZEND_MN(swoole_table_del)(INTERNAL_FUNCTION_PARAM_PASSTHRU); -} - static PHP_METHOD(swoole_table, count) { #define COUNT_NORMAL 0 #define COUNT_RECURSIVE 1 - Table *table = php_swoole_table_get_ptr(ZEND_THIS); if (!table) { RETURN_LONG(0); } zend_long mode = COUNT_NORMAL; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &mode) == FAILURE) { RETURN_FALSE; } @@ -722,7 +580,6 @@ static PHP_METHOD(swoole_table, count) { static PHP_METHOD(swoole_table, getMemorySize) { Table *table = php_swoole_table_get_ptr(ZEND_THIS); - if (!table) { RETURN_LONG(0); } else { @@ -732,7 +589,6 @@ static PHP_METHOD(swoole_table, getMemorySize) { static PHP_METHOD(swoole_table, getSize) { Table *table = php_swoole_table_get_ptr(ZEND_THIS); - if (!table) { RETURN_LONG(0); } else { @@ -746,126 +602,31 @@ static PHP_METHOD(swoole_table, rewind) { table->forward(); } +static PHP_METHOD(swoole_table, valid) { + Table *table = php_swoole_table_get_and_check_ptr2(ZEND_THIS); + auto key = table->current(); + RETURN_BOOL(key->key_len != 0); +} + static PHP_METHOD(swoole_table, current) { Table *table = php_swoole_table_get_and_check_ptr2(ZEND_THIS); - TableRow *row = table->current(); - if (row) { - row->lock(); - php_swoole_table_row2array(table, row, return_value); - row->unlock(); - } else { + auto row = table->current(); + if (row->key_len == 0) { RETURN_NULL(); } + php_swoole_table_row2array(table, row, return_value); } static PHP_METHOD(swoole_table, key) { Table *table = php_swoole_table_get_and_check_ptr2(ZEND_THIS); - TableRow *row = table->current(); - if (row) { - row->lock(); - RETVAL_STRINGL(row->key, row->key_len); - row->unlock(); - } else { + auto row = table->current(); + if (row->key_len == 0) { RETURN_NULL(); } + RETVAL_STRINGL(row->key, row->key_len); } static PHP_METHOD(swoole_table, next) { Table *table = php_swoole_table_get_and_check_ptr2(ZEND_THIS); table->forward(); } - -static PHP_METHOD(swoole_table, valid) { - Table *table = php_swoole_table_get_and_check_ptr2(ZEND_THIS); - TableRow *row = table->current(); - RETURN_BOOL(row != nullptr); -} - -static PHP_METHOD(swoole_table_row, offsetExists) { - char *key; - size_t keylen; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &key, &keylen) == FAILURE) { - RETURN_FALSE; - } - - zval *zprop_value = sw_zend_read_property_ex(swoole_table_row_ce, ZEND_THIS, SW_ZSTR_KNOWN(SW_ZEND_STR_VALUE), 0); - RETURN_BOOL(zend_hash_str_exists(Z_ARRVAL_P(zprop_value), key, keylen)); -} - -static PHP_METHOD(swoole_table_row, offsetGet) { - char *key; - size_t keylen; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &key, &keylen) == FAILURE) { - RETURN_FALSE; - } - - zval *zprop_value = sw_zend_read_property_ex(swoole_table_row_ce, ZEND_THIS, SW_ZSTR_KNOWN(SW_ZEND_STR_VALUE), 0); - zval *retval = nullptr; - if (!(retval = zend_hash_str_find(Z_ARRVAL_P(zprop_value), key, keylen))) { - RETURN_FALSE; - } - RETURN_ZVAL(retval, 1, 0); -} - -static PHP_METHOD(swoole_table_row, offsetSet) { - Table *table = php_swoole_table_row_get_and_check_ptr(ZEND_THIS); - zval *value; - char *key; - size_t keylen; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz", &key, &keylen, &value) == FAILURE) { - RETURN_FALSE; - } - - zval *zprop_key = sw_zend_read_property_ex(swoole_table_row_ce, ZEND_THIS, SW_ZSTR_KNOWN(SW_ZEND_STR_KEY), 0); - - int out_flags; - TableRow *_rowlock = nullptr; - TableRow *row = table->set(Z_STRVAL_P(zprop_key), Z_STRLEN_P(zprop_key), &_rowlock, &out_flags); - if (!row) { - _rowlock->unlock(); - php_swoole_error(E_WARNING, "Unable to allocate memory"); - RETURN_FALSE; - } - - if (out_flags & SW_TABLE_FLAG_NEW_ROW) { - for (auto i = table->column_list->begin(); i != table->column_list->end(); i++) { - (*i)->clear(row); - } - } - - TableColumn *column = table->get_column(std::string(key, keylen)); - if (column == nullptr) { - _rowlock->unlock(); - php_swoole_fatal_error(E_WARNING, "column[%s] does not exist", key); - RETURN_FALSE; - } - - if (column->type == TableColumn::TYPE_STRING) { - zend_string *str = zval_get_string(value); - row->set_value(column, ZSTR_VAL(str), ZSTR_LEN(str)); - zend_string_release(str); - } else if (column->type == TableColumn::TYPE_FLOAT) { - double _value = zval_get_double(value); - row->set_value(column, &_value, 0); - } else { - long _value = zval_get_long(value); - row->set_value(column, &_value, 0); - } - _rowlock->unlock(); - - zval *zprop_value = sw_zend_read_property_ex(swoole_table_row_ce, ZEND_THIS, SW_ZSTR_KNOWN(SW_ZEND_STR_VALUE), 0); - Z_TRY_ADDREF_P(value); - add_assoc_zval_ex(zprop_value, key, keylen, value); - - RETURN_TRUE; -} - -static PHP_METHOD(swoole_table_row, offsetUnset) { - php_swoole_fatal_error(E_WARNING, "not supported"); - RETURN_FALSE; -} - -static PHP_METHOD(swoole_table_row, __destruct) {} diff --git a/include/swoole_table.h b/include/swoole_table.h index 40c44fd1605..19503f8fc95 100644 --- a/include/swoole_table.h +++ b/include/swoole_table.h @@ -73,9 +73,42 @@ struct TableRow { }; struct TableIterator { + size_t row_memory_size_; uint32_t absolute_index; uint32_t collision_index; - TableRow *row; + TableRow *current_; + Mutex *mutex_; + + TableIterator(size_t row_size) { + current_ = (TableRow *) sw_malloc(row_size); + if (!current_) { + throw std::bad_alloc(); + } + mutex_ = new Mutex(Mutex::PROCESS_SHARED); + row_memory_size_ = row_size; + reset(); + } + + void lock() { + mutex_->lock(); + } + + void unlock() { + mutex_->unlock(); + } + + void reset() { + absolute_index = 0; + collision_index = 0; + sw_memset_zero(current_, row_memory_size_); + } + + ~TableIterator() { + if (current_) { + sw_free(current_); + } + delete mutex_; + } }; enum TableFlag { @@ -183,6 +216,14 @@ class Table { return size; } + int lock() { + return mutex->lock(); + } + + int unlock() { + return mutex->unlock(); + } + TableRow *get_by_index(uint32_t index) { TableRow *row = rows[index]; return row->active ? row : nullptr; @@ -201,12 +242,25 @@ class Table { return row_num; } + bool exists(const char *key, uint16_t keylen) { + TableRow *_rowlock = nullptr; + const TableRow *row = get(key, keylen, &_rowlock); + _rowlock->unlock(); + return row != nullptr; + } + + bool exists(const std::string &key) { + return exists(key.c_str(), key.length()); + } + TableRow *current() { - return iterator->row; + return iterator->current_; } void rewind() { - sw_memset_zero(iterator, sizeof(*iterator)); + iterator->lock(); + iterator->reset(); + iterator->unlock(); } TableRow *hash(const char *key, int keylen) { diff --git a/src/memory/table.cc b/src/memory/table.cc index c9c8aa534b7..e0683a6b303 100644 --- a/src/memory/table.cc +++ b/src/memory/table.cc @@ -40,7 +40,7 @@ Table *Table::make(uint32_t rows_size, float conflict_proportion) { return nullptr; } table->mutex = new Mutex(Mutex::PROCESS_SHARED); - table->iterator = new TableIterator; + table->iterator = nullptr; table->column_map = new std::unordered_map; table->column_list = new std::vector; table->size = rows_size; @@ -52,14 +52,14 @@ Table *Table::make(uint32_t rows_size, float conflict_proportion) { table->hash_func = swoole_hash_austin; #endif - sw_memset_zero(table->iterator, sizeof(TableIterator)); - return table; } void Table::free() { delete mutex; - delete iterator; + if (iterator) { + delete iterator; + } delete column_map; delete column_list; } @@ -141,6 +141,7 @@ bool Table::create() { _memory = (char *) _memory + _row_memory_size * size; _memory_size -= _row_memory_size * size; pool = new FixedPool(_row_memory_size, _memory, _memory_size, true); + iterator = new TableIterator(_row_memory_size); created = true; return true; @@ -162,7 +163,9 @@ void Table::destroy() { } delete column_map; delete column_list; - delete iterator; + if (iterator) { + delete iterator; + } delete pool; if (memory) { sw_shm_free(memory); @@ -224,37 +227,48 @@ void TableRow::lock() { } void Table::forward() { + iterator->lock(); for (; iterator->absolute_index < size; iterator->absolute_index++) { TableRow *row = get_by_index(iterator->absolute_index); if (row == nullptr) { continue; - } else if (row->next == nullptr) { + } + row->lock(); + if (row->next == nullptr) { iterator->absolute_index++; - iterator->row = row; + memcpy(iterator->current_, row, iterator->row_memory_size_); + row->unlock(); + iterator->unlock(); return; } else { uint32_t i = 0; + TableRow *tmp_row = row; for (;; i++) { - if (row == nullptr) { + if (tmp_row == nullptr) { iterator->collision_index = 0; break; } if (i == iterator->collision_index) { iterator->collision_index++; - iterator->row = row; + memcpy(iterator->current_, tmp_row, iterator->row_memory_size_); + row->unlock(); + iterator->unlock(); return; } - row = row->next; + tmp_row = tmp_row->next; } } + row->unlock(); } - iterator->row = nullptr; + sw_memset_zero(iterator->current_, sizeof(TableRow)); + iterator->unlock(); } TableRow *Table::get(const char *key, uint16_t keylen, TableRow **rowlock) { check_key_length(&keylen); TableRow *row = hash(key, keylen); + *rowlock = row; row->lock(); @@ -292,7 +306,7 @@ TableRow *Table::set(const char *key, uint16_t keylen, TableRow **rowlock, int * if (sw_mem_equal(row->key, row->key_len, key, keylen)) { break; } else if (row->next == nullptr) { - mutex->lock(); + lock(); TableRow *new_row = (TableRow *) pool->alloc(0); #ifdef SW_TABLE_DEBUG conflict_count++; @@ -300,7 +314,7 @@ TableRow *Table::set(const char *key, uint16_t keylen, TableRow **rowlock, int * conflict_max_level = _conflict_level; } #endif - mutex->unlock(); + unlock(); if (!new_row) { return nullptr; } @@ -377,10 +391,10 @@ bool Table::del(const char *key, uint16_t keylen) { if (prev) { prev->next = tmp->next; } - mutex->lock(); + lock(); tmp->clear(); pool->free(tmp); - mutex->unlock(); + unlock(); } _delete_element: diff --git a/tests/swoole_table/row.phpt b/tests/swoole_table/row.phpt deleted file mode 100644 index 40311f0c5a0..00000000000 --- a/tests/swoole_table/row.phpt +++ /dev/null @@ -1,25 +0,0 @@ ---TEST-- -swoole_table: row ---SKIPIF-- - ---FILE-- -column('bar', swoole_table::TYPE_STRING, 255); -$table->create(); -$table->set('rpw', ['bar' => 'hello world']); -$row = $table['rpw']; -@$row['not_exist'] = '666'; -Assert::true(!isset($row['not_exist'])); -echo $row['bar'] . "\n"; -$row['bar'] = 'hello swoole'; -echo $row['bar'] . "\n"; -$row['bar'] = null; -echo $row['bar'] . "EOF\n"; -Assert::true(isset($row['bar'])); -?> ---EXPECT-- -hello world -hello swoole -EOF From 71ba6c0dd96282c4be1a8756b0399d2bdc5da92b Mon Sep 17 00:00:00 2001 From: zmyWL <86939621+zmyWL@users.noreply.github.com> Date: Tue, 6 Jul 2021 15:49:18 +0800 Subject: [PATCH 175/936] Fix SW_LOCK_CHECK_RETURN (#4302) * Fix SW_LOCK_CHECK_RETURN * Optimize code * Optimize code * Optimize code --- ext-src/php_swoole_private.h | 7 ++++--- tests/swoole_lock/lockwait_twice.phpt | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 tests/swoole_lock/lockwait_twice.phpt diff --git a/ext-src/php_swoole_private.h b/ext-src/php_swoole_private.h index 22a2e0b9c7a..c6af140254c 100644 --- a/ext-src/php_swoole_private.h +++ b/ext-src/php_swoole_private.h @@ -61,11 +61,12 @@ extern PHPAPI int php_array_merge(zend_array *dest, zend_array *src); } else { \ RETURN_TRUE; \ } -#define SW_LOCK_CHECK_RETURN(s) \ - if (s == 0) { \ +#define SW_LOCK_CHECK_RETURN(s) \ + zend_long ___tmp_return_value = s; \ + if (___tmp_return_value == 0) { \ RETURN_TRUE; \ } else { \ - zend_update_property_long(NULL, SW_Z8_OBJ_P(ZEND_THIS), SW_STRL("errCode"), s); \ + zend_update_property_long(NULL, SW_Z8_OBJ_P(ZEND_THIS), SW_STRL("errCode"), ___tmp_return_value ); \ RETURN_FALSE; \ } diff --git a/tests/swoole_lock/lockwait_twice.phpt b/tests/swoole_lock/lockwait_twice.phpt new file mode 100644 index 00000000000..89655b78cf4 --- /dev/null +++ b/tests/swoole_lock/lockwait_twice.phpt @@ -0,0 +1,23 @@ +--TEST-- +swoole_lock: test lock twice +--SKIPIF-- + +--FILE-- +lock()); + + +$start = microtime(true); +$ret = $lock->lockwait(0.2); +Assert::false($ret); +$end = microtime(true); + +Assert::eq($lock->errCode, SOCKET_ETIMEDOUT); +Assert::lessThan($end - $start, 0.2); + +?> +--EXPECT-- +bool(true) From 9d61e9bcff1e32f59da1a2dbc35f505981ce071c Mon Sep 17 00:00:00 2001 From: matyhtf Date: Fri, 9 Jul 2021 16:48:22 +0800 Subject: [PATCH 176/936] Optimize naming --- gdbinit | 10 +++++----- include/swoole_coroutine.h | 4 ++-- src/coroutine/base.cc | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/gdbinit b/gdbinit index 4c5d34eeb36..2c47fc1605e 100644 --- a/gdbinit +++ b/gdbinit @@ -58,10 +58,10 @@ define sw_hash_map_list end define co_list - call swoole_coro_iterator_reset() + call swoole_coroutine_iterator_reset() set $running = 1 while $running - set $co = swoole_coro_iterator_each() + set $co = swoole_coroutine_iterator_each() if $co printf "coroutine %ld ", $co->cid if $co->state == 0 @@ -83,7 +83,7 @@ define co_list end define co_bt - if swoole_coro_count() == 0 + if swoole_coroutine_count() == 0 printf "no coroutine is running\n" end ____sw_executor_globals @@ -111,7 +111,7 @@ end define __co_bt set $cid = (int)$arg0 - set $co = swoole_coro_get($cid) + set $co = swoole_coroutine_get($cid) if $co set $task = ('swoole::PHPContext' *) $co->get_task() if $task @@ -125,7 +125,7 @@ end define co_status printf "\t c_stack_size: %d\n", 'swoole::Coroutine::stack_size' printf "\t active: %d\n", 'swoole::PHPCoroutine::active' - printf "\t coro_num: %d\n", swoole_coro_count() + printf "\t coro_num: %d\n", swoole_coroutine_count() printf "\t peak_coro_num: %d\n", 'swoole::Coroutine::peak_num' printf "\t config: " print 'swoole::PHPCoroutine::config' diff --git a/include/swoole_coroutine.h b/include/swoole_coroutine.h index 2712a550563..804eb7b4121 100644 --- a/include/swoole_coroutine.h +++ b/include/swoole_coroutine.h @@ -262,7 +262,7 @@ bool run(const CoroutineFunc &fn, void *arg = nullptr); /** * for gdb */ -swoole::Coroutine *swoole_coro_iterator_each(); -void swoole_coro_iterator_reset(); +swoole::Coroutine *swoole_coroutine_iterator_each(); +void swoole_coroutine_iterator_reset(); swoole::Coroutine *swoole_coroutine_get(long cid); size_t swoole_coroutine_count(); diff --git a/src/coroutine/base.cc b/src/coroutine/base.cc index a28197f46ea..499a3ef041e 100644 --- a/src/coroutine/base.cc +++ b/src/coroutine/base.cc @@ -262,11 +262,11 @@ size_t swoole_coroutine_count() { */ static std::unordered_map::iterator _gdb_iterator; -void swoole_coro_iterator_reset() { +void swoole_coroutine_iterator_reset() { _gdb_iterator = swoole::Coroutine::coroutines.begin(); } -swoole::Coroutine *swoole_coro_iterator_each() { +swoole::Coroutine *swoole_coroutine_iterator_each() { if (_gdb_iterator == swoole::Coroutine::coroutines.end()) { return nullptr; } else { From 3d584ddca3e0759905640c6e7c0a6a4e6dbb94f2 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Fri, 9 Jul 2021 16:56:45 +0800 Subject: [PATCH 177/936] Optimize log format, fix typo --- ext-src/php_swoole.cc | 2 +- include/swoole_log.h | 6 +++--- src/coroutine/socket.cc | 8 +++++++- src/protocol/websocket.cc | 6 ++++++ src/server/master.cc | 13 ++++++++----- 5 files changed, 25 insertions(+), 10 deletions(-) diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index a44e20b4fc4..ce9b1aa1235 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -688,7 +688,7 @@ PHP_MINIT_FUNCTION(swoole) { SW_REGISTER_LONG_CONSTANT("SWOOLE_TRACE_EOF_PROTOCOL", SW_TRACE_EOF_PROTOCOL); SW_REGISTER_LONG_CONSTANT("SWOOLE_TRACE_LENGTH_PROTOCOL", SW_TRACE_LENGTH_PROTOCOL); SW_REGISTER_LONG_CONSTANT("SWOOLE_TRACE_CLOSE", SW_TRACE_CLOSE); - SW_REGISTER_LONG_CONSTANT("SWOOLE_TRACE_WEBSOCEKT", SW_TRACE_WEBSOCEKT); + SW_REGISTER_LONG_CONSTANT("SWOOLE_TRACE_WEBSOCKET", SW_TRACE_WEBSOCKET); SW_REGISTER_LONG_CONSTANT("SWOOLE_TRACE_REDIS_CLIENT", SW_TRACE_REDIS_CLIENT); SW_REGISTER_LONG_CONSTANT("SWOOLE_TRACE_MYSQL_CLIENT", SW_TRACE_MYSQL_CLIENT); SW_REGISTER_LONG_CONSTANT("SWOOLE_TRACE_HTTP_CLIENT", SW_TRACE_HTTP_CLIENT); diff --git a/include/swoole_log.h b/include/swoole_log.h index a40a17b3d4c..4290fecd7de 100644 --- a/include/swoole_log.h +++ b/include/swoole_log.h @@ -116,7 +116,7 @@ swoole::Logger *sw_logger(); #define swWarn(str, ...) \ do { \ if (SW_LOG_WARNING >= sw_logger()->get_level()) { \ - size_t _sw_error_len = sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s: " str, __func__, ##__VA_ARGS__); \ + size_t _sw_error_len = sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, str, ##__VA_ARGS__); \ sw_logger()->put(SW_LOG_WARNING, sw_error, _sw_error_len); \ } \ } while (0) @@ -169,7 +169,7 @@ swoole::Logger *sw_logger(); swoole_set_last_error(__errno); \ if (level >= sw_logger()->get_level()) { \ size_t _sw_error_len = \ - sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s (ERRNO %d): " str, __func__, __errno, ##__VA_ARGS__); \ + sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "(ERRNO %d): " str, __errno, ##__VA_ARGS__); \ sw_logger()->put(level, sw_error, _sw_error_len); \ } \ } while (0) @@ -222,7 +222,7 @@ enum swTrace_type { SW_TRACE_EOF_PROTOCOL = 1u << 12, SW_TRACE_LENGTH_PROTOCOL = 1u << 13, SW_TRACE_CLOSE = 1u << 14, - SW_TRACE_WEBSOCEKT = 1u << 15, + SW_TRACE_WEBSOCKET = 1u << 15, /** * Client */ diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index a06f0022ab6..20fe3f6ee49 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -1486,7 +1486,13 @@ ssize_t Socket::recv_packet_with_length_protocol() { goto _recv_header; } else if (packet_len > protocol.package_max_length) { read_buffer->clear(); - set_err(SW_ERROR_PACKAGE_LENGTH_TOO_LARGE, "remote packet is too big"); + swoole_error_log(SW_LOG_WARNING, + SW_ERROR_PACKAGE_LENGTH_TOO_LARGE, + "packet length is too big, remote_addr=%s:%d, length=%zu", + socket->info.get_ip(), + socket->info.get_port(), + packet_len); + set_err(SW_ERROR_PACKAGE_LENGTH_TOO_LARGE, sw_error); return -1; } diff --git a/src/protocol/websocket.cc b/src/protocol/websocket.cc index 2ada7937f92..1acc6a6b044 100644 --- a/src/protocol/websocket.cc +++ b/src/protocol/websocket.cc @@ -180,6 +180,12 @@ bool decode(Frame *frame, char *data, size_t length) { header_length += 8; } + swTraceLog(SW_TRACE_WEBSOCKET, + "decode frame, payload_length=%ld, mask=%d, opcode=%d", + payload_length, + frame->header.MASK, + frame->header.OPCODE); + if (payload_length == 0) { frame->header_length = header_length; frame->payload_length = 0; diff --git a/src/server/master.cc b/src/server/master.cc index 5c04c060bbb..b9ceeaca6d6 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -1004,13 +1004,13 @@ int Server::send_to_connection(SendData *_send) { if (_send->info.type == SW_SERVER_EVENT_RECV_DATA) { swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_NOT_EXIST, - "send %d byte failed, session#%ld does not exist", + "Server::send(): send %d byte failed, session#%ld does not exist", _send_length, session_id); } else { swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_NOT_EXIST, - "send event[%d] failed, session#%ld does not exist", + "Server::send(): send event[%d] failed, session#%ld does not exist", _send->info.type, session_id); } @@ -1129,7 +1129,8 @@ int Server::send_to_connection(SendData *_send) { else { // connection is closed if (conn->peer_closed) { - swWarn("connection#%d is closed by client", fd); + swoole_error_log( + SW_LOG_NOTICE, SW_ERROR_SESSION_CLOSED_BY_CLIENT, "Server::send(): socket#%d is closed by client", fd); return false; } // connection output buffer overflow @@ -1137,8 +1138,10 @@ int Server::send_to_connection(SendData *_send) { if (send_yield) { swoole_set_last_error(SW_ERROR_OUTPUT_SEND_YIELD); } else { - swoole_error_log( - SW_LOG_WARNING, SW_ERROR_OUTPUT_BUFFER_OVERFLOW, "connection#%d output buffer overflow", fd); + swoole_error_log(SW_LOG_WARNING, + SW_ERROR_OUTPUT_BUFFER_OVERFLOW, + "Server::send(): connection#%d output buffer overflow", + fd); } conn->overflow = 1; if (onBufferEmpty && onBufferFull == nullptr) { From 7fe4187c56c2bf9d006ff2f42d28ff7e4885dc5f Mon Sep 17 00:00:00 2001 From: matyhtf Date: Fri, 9 Jul 2021 16:57:16 +0800 Subject: [PATCH 178/936] Optimize namespace --- ext-src/swoole_http_client_coro.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext-src/swoole_http_client_coro.cc b/ext-src/swoole_http_client_coro.cc index 40bc30931dc..34c2bfcca9c 100644 --- a/ext-src/swoole_http_client_coro.cc +++ b/ext-src/swoole_http_client_coro.cc @@ -1443,7 +1443,7 @@ void HttpClient::recv(zval *zframe, double timeout) { close(); } } else { - swString msg; + String msg; msg.length = retval; msg.str = socket->get_read_buffer()->str; #ifdef SW_HAVE_ZLIB From 0c697df67dfaae8d45d4af4c9bb9b244013ced8e Mon Sep 17 00:00:00 2001 From: matyhtf Date: Fri, 9 Jul 2021 16:57:45 +0800 Subject: [PATCH 179/936] Add defense code --- ext-src/swoole_http_request.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ext-src/swoole_http_request.cc b/ext-src/swoole_http_request.cc index 73b9d24879d..4f4ca4e3f64 100644 --- a/ext-src/swoole_http_request.cc +++ b/ext-src/swoole_http_request.cc @@ -380,6 +380,9 @@ static int http_request_on_header_value(swoole_http_parser *parser, const char * goto _add_header; } Server *serv = (Server *) ctx->private_data; + if (!serv) { + goto _add_header; + } Connection *conn = serv->get_connection_by_session_id(ctx->fd); if (!conn) { swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_CLOSED, "session[%ld] is closed", ctx->fd); From e6fae2ed15e26b049cc2ec25ff18b8c4d6d11117 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Fri, 9 Jul 2021 16:58:13 +0800 Subject: [PATCH 180/936] Fix #4263 --- include/swoole_memory.h | 2 ++ src/memory/global_memory.cc | 1 + 2 files changed, 3 insertions(+) diff --git a/include/swoole_memory.h b/include/swoole_memory.h index 7241ed75c84..74f8f34dba9 100644 --- a/include/swoole_memory.h +++ b/include/swoole_memory.h @@ -22,6 +22,8 @@ //-------------------memory manager------------------------- namespace swoole { +#pragma pack(8) + class MemoryPool { public: virtual ~MemoryPool(){}; diff --git a/src/memory/global_memory.cc b/src/memory/global_memory.cc index 011debd169b..0d237528ff4 100644 --- a/src/memory/global_memory.cc +++ b/src/memory/global_memory.cc @@ -39,6 +39,7 @@ struct GlobalMemoryImpl { struct MemoryBlock { uint32_t size; + uint32_t reserved; char memory[0]; }; From 9168c1a02aec7357ba2f4bebee4d1d7f658be091 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Fri, 9 Jul 2021 17:39:01 +0800 Subject: [PATCH 181/936] Fix c-ares timeout when lookup local name --- include/swoole_log.h | 2 +- src/network/dns.cc | 6 +++++- tests/swoole_coroutine/dnslookup_5.phpt | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 tests/swoole_coroutine/dnslookup_5.phpt diff --git a/include/swoole_log.h b/include/swoole_log.h index 4290fecd7de..8096785480b 100644 --- a/include/swoole_log.h +++ b/include/swoole_log.h @@ -169,7 +169,7 @@ swoole::Logger *sw_logger(); swoole_set_last_error(__errno); \ if (level >= sw_logger()->get_level()) { \ size_t _sw_error_len = \ - sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "(ERRNO %d): " str, __errno, ##__VA_ARGS__); \ + sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "(ERRNO %d) " str, __errno, ##__VA_ARGS__); \ sw_logger()->put(level, sw_error, _sw_error_len); \ } \ } while (0) diff --git a/src/network/dns.cc b/src/network/dns.cc index 0fd471292b9..b0036aad651 100644 --- a/src/network/dns.cc +++ b/src/network/dns.cc @@ -348,6 +348,7 @@ struct ResolvContext { ares_options ares_opts; int ares_flags; int error; + bool completed; Coroutine *co; std::unordered_map sockets; std::vector result; @@ -374,6 +375,7 @@ std::vector dns_lookup_impl_with_cares(const char *domain, int fami ResolvContext ctx{}; Coroutine *co = Coroutine::get_current_safe(); ctx.co = co; + ctx.completed = false; char lookups[] = "fb"; int res; ctx.ares_opts.lookups = lookups; @@ -486,11 +488,13 @@ std::vector dns_lookup_impl_with_cares(const char *domain, int fami }, ctx->co); ctx->co = nullptr; + } else { + ctx->completed = true; } }, &ctx); - if (ctx.error) { + if (ctx.error || ctx.completed) { goto _destroy; } diff --git a/tests/swoole_coroutine/dnslookup_5.phpt b/tests/swoole_coroutine/dnslookup_5.phpt new file mode 100644 index 00000000000..7e602d2c163 --- /dev/null +++ b/tests/swoole_coroutine/dnslookup_5.phpt @@ -0,0 +1,18 @@ +--TEST-- +swoole_coroutine: async dns lookup [5] +--SKIPIF-- + +--FILE-- + +--EXPECT-- From 0e91dfc8dc9b12dc4f6b086da3e700afb32b82da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=93=AD=E6=98=95?= <715557344@qq.com> Date: Mon, 12 Jul 2021 09:24:23 +0800 Subject: [PATCH 182/936] Added alpine 3.13 and 3.14 into building test. (#4309) --- .github/workflows/alpine.Dockerfile | 4 +++- .github/workflows/ext.yml | 7 ++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/alpine.Dockerfile b/.github/workflows/alpine.Dockerfile index 790cb5be8db..ca4288faf3a 100644 --- a/.github/workflows/alpine.Dockerfile +++ b/.github/workflows/alpine.Dockerfile @@ -5,6 +5,8 @@ FROM hyperf/hyperf:${PHP_VERSION}-alpine-v${ALPINE_VERSION}-dev LABEL maintainer="Swoole Team " version="1.0" license="MIT" +ARG PHP_VERSION + COPY . /opt/www WORKDIR /opt/www @@ -13,7 +15,7 @@ RUN set -ex \ && phpize \ && ./configure --enable-openssl --enable-http2 --enable-swoole-curl --enable-swoole-json \ && make -s -j$(nproc) && make install \ - && echo "extension=swoole.so" > /etc/php7/conf.d/50_swoole.ini \ + && echo "extension=swoole.so" > /etc/php${PHP_VERSION%\.*}/conf.d/50_swoole.ini \ # check && php -v \ && php -m \ diff --git a/.github/workflows/ext.yml b/.github/workflows/ext.yml index 626154e288c..75b88982311 100644 --- a/.github/workflows/ext.yml +++ b/.github/workflows/ext.yml @@ -92,11 +92,8 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-version: [ '7.3', '7.4' ] - alpine-version: [ '3.9', '3.10', '3.11', '3.12' ] - exclude: - - php-version: '7.3' - alpine-version: '3.12' + php-version: [ '7.4', '8.0' ] + alpine-version: [ '3.11', '3.12', '3.13', '3.14' ] max-parallel: 8 fail-fast: false steps: From a7cf5c0962961546cc5328651a1068f850e3eac1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Mon, 12 Jul 2021 18:11:23 +0800 Subject: [PATCH 183/936] Optimize log format, fix tests (#4311) * Logger::get_pretty_name * fix tests * optimize error log * fix tests[2] * Added c-ares * Added c-ares * fix tests * fix tests[4] * Code reuse * fix tests[5] * fix core tests * fix core-tests [2] --- core-tests/src/core/channel.cpp | 6 +- core-tests/src/core/log.cpp | 29 +++++ core-tests/src/coroutine/async.cpp | 12 +- include/swoole_log.h | 28 ++--- include/swoole_process_pool.h | 1 + src/core/log.cc | 36 +++++- src/coroutine/system.cc | 79 ++++--------- src/network/dns.cc | 14 ++- src/os/process_pool.cc | 10 +- src/server/manager.cc | 12 +- src/server/master.cc | 4 +- src/server/task_worker.cc | 10 +- tests/include/lib/composer.lock | 110 +++++++++--------- tests/swoole_channel_coro/discard.phpt | 2 +- .../call_not_exists_func.phpt | 2 +- .../cancel/gethostbyname.phpt | 2 +- tests/swoole_coroutine/exception.phpt | 2 +- tests/swoole_coroutine/gethostbyname.phpt | 16 ++- .../aio_thread_num.phpt | 19 +-- .../buffer_output_size.phpt | 2 +- .../ssl_bad_client.phpt | 2 +- .../swoole_server/discard_timeout_packet.phpt | 2 +- tests/swoole_server/force_reload.phpt | 16 +-- tests/swoole_server/force_reload2.phpt | 8 +- tests/swoole_server/invalid_fd.phpt | 4 +- tests/swoole_server/ssl/bad_client.phpt | 2 +- tests/swoole_server/ssl/verify_02.phpt | 2 +- tests/swoole_server/task/finish_timeout.phpt | 4 +- .../swoole_server/task/scheduler_warning.phpt | 2 +- tests/swoole_table/force_unlock.phpt | 2 +- travis/docker-compile.sh | 3 +- travis/simple-compile-on-github.sh | 10 +- 32 files changed, 258 insertions(+), 195 deletions(-) diff --git a/core-tests/src/core/channel.cpp b/core-tests/src/core/channel.cpp index b5226f4e455..7cb06bd6e4e 100644 --- a/core-tests/src/core/channel.cpp +++ b/core-tests/src/core/channel.cpp @@ -43,7 +43,7 @@ TEST(channel, push) { bytes += n; } - swTrace("size=%d\n", m.size()); + swTrace("size=%lu", m.size()); thread t1([&]() { auto next = m.find(0); @@ -52,7 +52,7 @@ TEST(channel, push) { while (bytes < N) { if (c->push(next->second.c_str(), next->second.length()) == SW_OK) { - swTrace("[PUSH] index=%d, size=%d\n", index, next->second.length()); + swTrace("[PUSH] index=%d, size=%lu", index, next->second.length()); bytes += next->second.length(); next = m.find(index++); if (next == m.end()) { @@ -71,7 +71,7 @@ TEST(channel, push) { while (bytes < N) { int retval = c->pop(buf, sizeof(buf)); if (retval > 0) { - swTrace("[POP] index=%d, size=%ld\n", index, retval); + swTrace("[POP] index=%d, size=%d", index, retval); string &_data = m[index++]; bytes += retval; ASSERT_EQ(_data, string(buf, retval)); diff --git a/core-tests/src/core/log.cpp b/core-tests/src/core/log.cpp index 6c0a26d0ee8..9d96c1acf5d 100644 --- a/core-tests/src/core/log.cpp +++ b/core-tests/src/core/log.cpp @@ -119,3 +119,32 @@ TEST(log, redirect) { ASSERT_TRUE(content->contains(SW_STRL("hello world\n"))); } + +namespace TestA { +class TestPrettyName { + public: + static void fun(bool strip, const char *expect_str); +}; + +void TestPrettyName::fun(bool strip, const char *expect_str) { + ASSERT_STREQ(Logger::get_pretty_name(__PRETTY_FUNCTION__, strip).c_str(), expect_str); +} + +void test_pretty_name(bool strip, const char *expect_str) { + ASSERT_STREQ(Logger::get_pretty_name(__PRETTY_FUNCTION__, strip).c_str(), expect_str); +} +} // namespace TestA + +void test_pretty_name(bool strip, const char *expect_str) { + ASSERT_STREQ(Logger::get_pretty_name(__PRETTY_FUNCTION__, strip).c_str(), expect_str); +} + +TEST(log, pretty_name) { + TestA::TestPrettyName::fun(false, "TestA::TestPrettyName::fun"); + TestA::test_pretty_name(false, "TestA::test_pretty_name"); + test_pretty_name(false, "test_pretty_name"); + + TestA::TestPrettyName::fun(true, "TestPrettyName::fun"); + TestA::test_pretty_name(true, "test_pretty_name"); + test_pretty_name(true, "test_pretty_name"); +} diff --git a/core-tests/src/coroutine/async.cpp b/core-tests/src/coroutine/async.cpp index 7c90c801c9d..530c7ca430e 100644 --- a/core-tests/src/coroutine/async.cpp +++ b/core-tests/src/coroutine/async.cpp @@ -8,8 +8,8 @@ #include using namespace std; -using swoole::test::coroutine; using swoole::AsyncEvent; +using swoole::test::coroutine; const int magic_code = 0x7009501; @@ -52,3 +52,13 @@ TEST(coroutine_async, gethostbyname) { } }); } + +TEST(coroutine_async, error) { + coroutine::run([](void *arg) { + int retval; + const char *test_file = "/tmp/swoole_core_test_file_not_exists"; + swoole::coroutine::async([&](void) { retval = open(test_file, O_RDONLY); }, -1); + ASSERT_EQ(retval, -1); + ASSERT_EQ(errno, ENOENT); + }); +} diff --git a/include/swoole_log.h b/include/swoole_log.h index 8096785480b..2099eb8e6d9 100644 --- a/include/swoole_log.h +++ b/include/swoole_log.h @@ -76,6 +76,7 @@ class Logger { bool redirect_stdout_and_stderr(int enable); void set_date_with_microseconds(bool enable); std::string gen_real_file(const std::string &file); + static std::string get_pretty_name(const std::string &prettyFunction, bool strip = true); void display_backtrace() { display_backtrace_ = true; @@ -84,6 +85,7 @@ class Logger { } // namespace swoole swoole::Logger *sw_logger(); +#define __SW_FUNC__ (swoole::Logger::get_pretty_name(__PRETTY_FUNCTION__).c_str()) #define swInfo(str, ...) \ if (SW_LOG_INFO >= sw_logger()->get_level()) { \ @@ -104,7 +106,7 @@ swoole::Logger *sw_logger(); size_t _sw_error_len = sw_snprintf(sw_error, \ SW_ERROR_MSG_SIZE, \ "%s(:%d): " str ", Error: %s[%d]", \ - __func__, \ + __SW_FUNC__, \ __LINE__, \ ##__VA_ARGS__, \ swoole_strerror(errno), \ @@ -116,7 +118,7 @@ swoole::Logger *sw_logger(); #define swWarn(str, ...) \ do { \ if (SW_LOG_WARNING >= sw_logger()->get_level()) { \ - size_t _sw_error_len = sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, str, ##__VA_ARGS__); \ + size_t _sw_error_len = sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s(): " str, __SW_FUNC__, ##__VA_ARGS__); \ sw_logger()->put(SW_LOG_WARNING, sw_error, _sw_error_len); \ } \ } while (0) @@ -127,9 +129,8 @@ swoole::Logger *sw_logger(); if (SW_LOG_ERROR >= sw_logger()->get_level()) { \ size_t _sw_error_len = sw_snprintf(sw_error, \ SW_ERROR_MSG_SIZE, \ - "%s(:%d): " str ", Error: %s[%d]", \ - __func__, \ - __LINE__, \ + "%s(): " str ", Error: %s[%d]", \ + __SW_FUNC__, \ ##__VA_ARGS__, \ swoole_strerror(errno), \ errno); \ @@ -148,9 +149,8 @@ swoole::Logger *sw_logger(); do { \ size_t _sw_error_len = sw_snprintf(sw_error, \ SW_ERROR_MSG_SIZE, \ - "%s(:%d): " str ", Error: %s[%d]", \ - __func__, \ - __LINE__, \ + "%s(): " str ", Error: %s[%d]", \ + __SW_FUNC__, \ ##__VA_ARGS__, \ swoole_strerror(errno), \ errno); \ @@ -161,15 +161,15 @@ swoole::Logger *sw_logger(); #define swFatalError(code, str, ...) \ do { \ SwooleG.fatal_error(code, str, ##__VA_ARGS__); \ - exit(255); \ + exit(255); \ } while (0) -#define swoole_error_log(level, __errno, str, ...) \ +#define swoole_error_log(level, error, str, ...) \ do { \ - swoole_set_last_error(__errno); \ + swoole_set_last_error(error); \ if (level >= sw_logger()->get_level()) { \ size_t _sw_error_len = \ - sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "(ERRNO %d) " str, __errno, ##__VA_ARGS__); \ + sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s() (ERRNO %d): " str, __SW_FUNC__, error, ##__VA_ARGS__); \ sw_logger()->put(level, sw_error, _sw_error_len); \ } \ } while (0) @@ -178,7 +178,7 @@ swoole::Logger *sw_logger(); #define swDebug(str, ...) \ if (SW_LOG_DEBUG >= sw_logger()->get_level()) { \ size_t _sw_error_len = \ - sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s(:%d): " str, __func__, __LINE__, ##__VA_ARGS__); \ + sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s(:%d): " str, __SW_FUNC__, __LINE__, ##__VA_ARGS__); \ sw_logger()->put(SW_LOG_DEBUG, sw_error, _sw_error_len); \ } @@ -252,7 +252,7 @@ enum swTrace_type { #define swTraceLog(what, str, ...) \ if (SW_LOG_TRACE >= sw_logger()->get_level() && (what & SwooleG.trace_flags)) { \ size_t _sw_error_len = \ - sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s(:%d): " str, __func__, __LINE__, ##__VA_ARGS__); \ + sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s(:%d): " str, __SW_FUNC__, __LINE__, ##__VA_ARGS__); \ sw_logger()->put(SW_LOG_TRACE, sw_error, _sw_error_len); \ } #else diff --git a/include/swoole_process_pool.h b/include/swoole_process_pool.h index 6d0b03b1ea5..b59416f4f17 100644 --- a/include/swoole_process_pool.h +++ b/include/swoole_process_pool.h @@ -290,6 +290,7 @@ struct ProcessPool { int listen(const char *socket_file, int blacklog); int listen(const char *host, int port, int blacklog); int schedule(); + static void kill_timeout_worker(Timer *timer, TimerNode *tnode); }; }; // namespace swoole diff --git a/src/core/log.cc b/src/core/log.cc index d41b2af1d7e..9afc21983fa 100644 --- a/src/core/log.cc +++ b/src/core/log.cc @@ -25,6 +25,38 @@ namespace swoole { +std::string Logger::get_pretty_name(const std::string &pretty_function, bool strip) { + size_t brackets = pretty_function.find_first_of("("); + if (brackets == pretty_function.npos) { + return ""; + } + + size_t begin = pretty_function.substr(0, brackets).rfind(" ") + 1; + size_t end = brackets - begin; + if (!strip) { + return pretty_function.substr(begin, end); + } + + auto method_name = pretty_function.substr(begin, end); + size_t count = 0, index = method_name.length(); + while (true) { + index = method_name.rfind("::", index); + if (index == method_name.npos) { + if (count == 1) { + return method_name.substr(method_name.rfind("::") + 2); + } + break; + } + count++; + if (count == 2) { + return method_name.substr(index + 2); + } + index -= 2; + } + + return method_name; +} + bool Logger::open(const char *_log_file) { if (opened) { close(); @@ -256,8 +288,8 @@ void Logger::put(int level, const char *content, size_t length) { if (date_with_microseconds) { auto now_us = std::chrono::duration_cast(now.time_since_epoch()).count(); - l_data_str += - sw_snprintf(date_str + l_data_str, SW_LOG_DATE_STRLEN - l_data_str, "<.%lld>", (long long) now_us - now_sec * 1000000); + l_data_str += sw_snprintf( + date_str + l_data_str, SW_LOG_DATE_STRLEN - l_data_str, "<.%lld>", (long long) now_us - now_sec * 1000000); } char process_flag = '@'; diff --git a/src/coroutine/system.cc b/src/coroutine/system.cc index af03c28b1be..11ff4e20fcb 100644 --- a/src/coroutine/system.cc +++ b/src/coroutine/system.cc @@ -190,16 +190,18 @@ std::string System::gethostbyname(const std::string &hostname, int domain, doubl #ifdef SW_USE_CARES auto result_list = dns_lookup_impl_with_cares(hostname.c_str(), domain, timeout); - if (SwooleG.dns_lookup_random) { - result = result_list[rand() % result_list.size()]; - } else { - result = result_list[0]; + if (!result_list.empty()) { + if (SwooleG.dns_lookup_random) { + result = result_list[rand() % result_list.size()]; + } else { + result = result_list[0]; + } } #else result = gethostbyname_impl_with_async(hostname, domain, timeout); #endif - if (dns_cache) { + if (dns_cache && !result.empty()) { dns_cache->set(cache_key, std::make_shared(result), dns_cache_expire); } @@ -620,20 +622,10 @@ static void async_task_completed(AsyncEvent *event) { co->resume(); } -static void async_task_timeout(Timer *timer, TimerNode *tnode) { - AsyncEvent *event = (AsyncEvent *) tnode->data; - event->canceled = 1; - event->retval = -1; - event->error = SW_ERROR_AIO_TIMEOUT; - Coroutine *co = (Coroutine *) event->object; - co->resume(); -} - /** * @error: swoole_get_last_error() */ bool async(async::Handler handler, AsyncEvent &event, double timeout) { - TimerNode *timer = nullptr; Coroutine *co = Coroutine::get_current_safe(); event.object = co; @@ -644,33 +636,18 @@ bool async(async::Handler handler, AsyncEvent &event, double timeout) { if (_ev == nullptr) { return false; } - if (timeout > 0) { - timer = swoole_timer_add((long) (timeout * 1000), false, async_task_timeout, _ev); - } - - Coroutine::CancelFunc cancel_fn = [_ev](Coroutine *co) { - _ev->canceled = true; - _ev->error = SW_ERROR_AIO_CANCELED; - _ev->retval = -1; - co->resume(); - return true; - }; - co->yield(&cancel_fn); - - event.canceled = _ev->canceled; - event.error = _ev->error; - event.retval = _ev->retval; - - errno = _ev->error; - swoole_set_last_error(_ev->error); - if (event.catch_error()) { + if (!co->yield_ex(timeout)) { + event.canceled = _ev->canceled = true; + event.retval = -1; + event.error = errno = swoole_get_last_error(); return false; + } else { + event.canceled = _ev->canceled; + event.error = errno = _ev->error; + event.retval = _ev->retval; + return true; } - if (timer) { - swoole_timer_del(timer); - } - return true; } struct AsyncLambdaTask { @@ -694,7 +671,6 @@ static void async_lambda_callback(AsyncEvent *event) { } bool async(const std::function &fn, double timeout) { - TimerNode *timer = nullptr; AsyncEvent event{}; AsyncLambdaTask task{Coroutine::get_current_safe(), fn}; @@ -706,28 +682,15 @@ bool async(const std::function &fn, double timeout) { if (_ev == nullptr) { return false; } - if (timeout > 0) { - timer = swoole_timer_add((long) (timeout * 1000), false, async_task_timeout, _ev); - } - Coroutine::CancelFunc cancel_fn = [_ev](Coroutine *co) { + if (!task.co->yield_ex(timeout)) { _ev->canceled = true; - _ev->error = SW_ERROR_AIO_CANCELED; - _ev->retval = -1; - co->resume(); - return true; - }; - task.co->yield(&cancel_fn); - - errno = _ev->error; - swoole_set_last_error(_ev->error); - if (_ev->catch_error()) { + errno = swoole_get_last_error(); return false; + } else { + errno = _ev->error; + return true; } - if (timer) { - swoole_timer_del(timer); - } - return true; } } // namespace coroutine diff --git a/src/network/dns.cc b/src/network/dns.cc index b0036aad651..2bb1c173ac6 100644 --- a/src/network/dns.cc +++ b/src/network/dns.cc @@ -503,13 +503,23 @@ std::vector dns_lookup_impl_with_cares(const char *domain, int fami ares_cancel(ctx.channel); } else if (co->is_timedout()) { ares_process_fd(ctx.channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD); - swoole_set_last_error(SW_ERROR_DNSLOOKUP_RESOLVE_TIMEOUT); + ctx.error = ARES_ETIMEOUT; } else { swTraceLog(SW_TRACE_CARES, "lookup success, result_count=%lu", ctx.result.size()); } _destroy: if (ctx.error) { - swoole_set_last_error(ctx.error == ARES_ECANCELLED ? SW_ERROR_CO_CANCELED : SW_ERROR_DNSLOOKUP_RESOLVE_FAILED); + switch (ctx.error) { + case ARES_ECANCELLED: + swoole_set_last_error(SW_ERROR_CO_CANCELED); + break; + case ARES_ETIMEOUT: + swoole_set_last_error(SW_ERROR_DNSLOOKUP_RESOLVE_TIMEOUT); + break; + default: + swoole_set_last_error(SW_ERROR_DNSLOOKUP_RESOLVE_FAILED); + break; + } } ares_destroy(ctx.channel); _return: diff --git a/src/os/process_pool.cc b/src/os/process_pool.cc index 0a8dbcd10ae..aecee9f8871 100644 --- a/src/os/process_pool.cc +++ b/src/os/process_pool.cc @@ -39,7 +39,7 @@ static int ProcessPool_worker_loop(ProcessPool *pool, Worker *worker); */ static int ProcessPool_worker_loop_ex(ProcessPool *pool, Worker *worker); -static void ProcessPool_kill_timeout_worker(Timer *timer, TimerNode *tnode) { +void ProcessPool::kill_timeout_worker(Timer *timer, TimerNode *tnode) { uint32_t i; pid_t reload_worker_pid = 0; ProcessPool *pool = (ProcessPool *) tnode->data; @@ -52,9 +52,9 @@ static void ProcessPool_kill_timeout_worker(Timer *timer, TimerNode *tnode) { continue; } if (swoole_kill(reload_worker_pid, SIGKILL) < 0) { - swSysWarn("swKill(%d, SIGKILL) [%d] failed", pool->reload_workers[i].pid, i); + swSysWarn("failed to force kill worker process(pid=%d, id=%d)", pool->reload_workers[i].pid, i); } else { - swWarn("swKill(%d, SIGKILL) [%d]", pool->reload_workers[i].pid, i); + swWarn("force kill worker process(pid=%d, id=%d)", pool->reload_workers[i].pid, i); } } } @@ -657,7 +657,7 @@ int ProcessPool::wait() { } pid_t new_pid = spawn(exit_worker); if (new_pid < 0) { - swSysWarn("Fork worker process failed"); + swSysWarn("fork worker process failed"); return SW_ERR; } map_->erase(msg.pid); @@ -679,7 +679,7 @@ int ProcessPool::wait() { reload_init = true; memcpy(reload_workers, workers, sizeof(Worker) * worker_num); if (max_wait_time) { - swoole_timer_add((long) (max_wait_time * 1000), false, ProcessPool_kill_timeout_worker, this); + swoole_timer_add((long) (max_wait_time * 1000), false, kill_timeout_worker, this); } } goto _kill_worker; diff --git a/src/server/manager.cc b/src/server/manager.cc index e94009d13f1..8ef9f22c70c 100644 --- a/src/server/manager.cc +++ b/src/server/manager.cc @@ -70,13 +70,13 @@ void Manager::kill_timeout_process(Timer *timer, TimerNode *tnode) { continue; } if (swoole_kill(pid, SIGKILL) < 0) { - swSysWarn("swKill(%d, SIGKILL) [%u] failed", pid, worker_id); + swSysWarn("kill(%d, SIGKILL) [%u] failed", pid, worker_id); } else { swoole_error_log(SW_LOG_WARNING, SW_ERROR_SERVER_WORKER_EXIT_TIMEOUT, - "[Manager] Worker#%d[pid=%d] exit timeout, force kill the process", - worker_id, - pid); + "worker(pid=%d, id=%d) exit timeout, force kill the process", + pid, + worker_id); } } errno = 0; @@ -203,10 +203,10 @@ int Server::start_manager_process() { void Server::check_worker_exit_status(int worker_id, const ExitStatus &exit_status) { if (exit_status.get_status() != 0) { - swWarn("worker#%d[pid=%d] abnormal exit, status=%d, signal=%d" + swWarn("worker(pid=%d, id=%d) abnormal exit, status=%d, signal=%d" "%s", - worker_id, exit_status.get_pid(), + worker_id, exit_status.get_code(), exit_status.get_signal(), exit_status.get_signal() == SIGSEGV ? "\n" SWOOLE_BUG_REPORT : ""); diff --git a/src/server/master.cc b/src/server/master.cc index b9ceeaca6d6..2b1c8e1c47d 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -1004,13 +1004,13 @@ int Server::send_to_connection(SendData *_send) { if (_send->info.type == SW_SERVER_EVENT_RECV_DATA) { swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_NOT_EXIST, - "Server::send(): send %d byte failed, session#%ld does not exist", + "send %d byte failed, session#%ld does not exist", _send_length, session_id); } else { swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_NOT_EXIST, - "Server::send(): send event[%d] failed, session#%ld does not exist", + "send event[%d] failed, session#%ld does not exist", _send->info.type, session_id); } diff --git a/src/server/task_worker.cc b/src/server/task_worker.cc index 4382ef2d29b..8851d882cc2 100644 --- a/src/server/task_worker.cc +++ b/src/server/task_worker.cc @@ -226,18 +226,18 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even EventData buf; sw_memset_zero(&buf.info, sizeof(buf.info)); if (task_worker_num < 1) { - swWarn("cannot use task/finish, because no set task_worker_num"); + swWarn("cannot use Server::task()/Server::finish() method, because no set [task_worker_num]"); return SW_ERR; } if (current_task == nullptr) { current_task = last_task; } if (current_task->info.type == SW_SERVER_EVENT_PIPE_MESSAGE) { - swWarn("task/finish is not supported in onPipeMessage callback"); + swWarn("Server::task()/Server::finish() is not supported in onPipeMessage callback"); return SW_ERR; } if (swTask_type(current_task) & SW_TASK_NOREPLY) { - swWarn("task->finish() can only be used in the worker process"); + swWarn("Server::finish() can only be used in the worker process"); return SW_ERR; } @@ -337,9 +337,9 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even } if (ret < 0) { if (swoole_get_last_error() == EAGAIN || swoole_get_last_error() == SW_ERROR_SOCKET_POLL_TIMEOUT) { - swWarn("TaskWorker: send result to worker timed out"); + swWarn("send result to worker timed out"); } else { - swSysWarn("TaskWorker: send result to worker failed"); + swSysWarn("send result to worker failed"); } } return ret; diff --git a/tests/include/lib/composer.lock b/tests/include/lib/composer.lock index 8984ae0e67a..47899b5ae29 100644 --- a/tests/include/lib/composer.lock +++ b/tests/include/lib/composer.lock @@ -331,16 +331,16 @@ }, { "name": "nyholm/psr7", - "version": "1.4.0", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/Nyholm/psr7.git", - "reference": "23ae1f00fbc6a886cbe3062ca682391b9cc7c37b" + "reference": "2212385b47153ea71b1c1b1374f8cb5e4f7892ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Nyholm/psr7/zipball/23ae1f00fbc6a886cbe3062ca682391b9cc7c37b", - "reference": "23ae1f00fbc6a886cbe3062ca682391b9cc7c37b", + "url": "https://api.github.com/repos/Nyholm/psr7/zipball/2212385b47153ea71b1c1b1374f8cb5e4f7892ec", + "reference": "2212385b47153ea71b1c1b1374f8cb5e4f7892ec", "shasum": "", "mirrors": [ { @@ -360,7 +360,7 @@ "psr/http-message-implementation": "1.0" }, "require-dev": { - "http-interop/http-factory-tests": "^0.8", + "http-interop/http-factory-tests": "^0.9", "php-http/psr7-integration-tests": "^1.0", "phpunit/phpunit": "^7.5 || 8.5 || 9.4", "symfony/error-handler": "^4.4" @@ -398,7 +398,7 @@ ], "support": { "issues": "https://github.com/Nyholm/psr7/issues", - "source": "https://github.com/Nyholm/psr7/tree/1.4.0" + "source": "https://github.com/Nyholm/psr7/tree/1.4.1" }, "funding": [ { @@ -410,20 +410,20 @@ "type": "github" } ], - "time": "2021-02-18T15:41:32+00:00" + "time": "2021-07-02T08:32:20+00:00" }, { "name": "php-http/client-common", - "version": "2.3.0", + "version": "2.4.0", "source": { "type": "git", "url": "https://github.com/php-http/client-common.git", - "reference": "e37e46c610c87519753135fb893111798c69076a" + "reference": "29e0c60d982f04017069483e832b92074d0a90b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/client-common/zipball/e37e46c610c87519753135fb893111798c69076a", - "reference": "e37e46c610c87519753135fb893111798c69076a", + "url": "https://api.github.com/repos/php-http/client-common/zipball/29e0c60d982f04017069483e832b92074d0a90b2", + "reference": "29e0c60d982f04017069483e832b92074d0a90b2", "shasum": "", "mirrors": [ { @@ -489,22 +489,22 @@ ], "support": { "issues": "https://github.com/php-http/client-common/issues", - "source": "https://github.com/php-http/client-common/tree/2.3.0" + "source": "https://github.com/php-http/client-common/tree/2.4.0" }, - "time": "2020-07-21T10:04:13+00:00" + "time": "2021-07-05T08:19:25+00:00" }, { "name": "php-http/discovery", - "version": "1.13.0", + "version": "1.14.0", "source": { "type": "git", "url": "https://github.com/php-http/discovery.git", - "reference": "788f72d64c43dc361e7fcc7464c3d947c64984a7" + "reference": "778f722e29250c1fac0bbdef2c122fa5d038c9eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/discovery/zipball/788f72d64c43dc361e7fcc7464c3d947c64984a7", - "reference": "788f72d64c43dc361e7fcc7464c3d947c64984a7", + "url": "https://api.github.com/repos/php-http/discovery/zipball/778f722e29250c1fac0bbdef2c122fa5d038c9eb", + "reference": "778f722e29250c1fac0bbdef2c122fa5d038c9eb", "shasum": "", "mirrors": [ { @@ -527,8 +527,7 @@ "puli/composer-plugin": "1.0.0-beta10" }, "suggest": { - "php-http/message": "Allow to use Guzzle, Diactoros or Slim Framework factories", - "puli/composer-plugin": "Sets up Puli which is recommended for Discovery to work. Check http://docs.php-http.org/en/latest/discovery.html for more details." + "php-http/message": "Allow to use Guzzle, Diactoros or Slim Framework factories" }, "type": "library", "extra": { @@ -564,9 +563,9 @@ ], "support": { "issues": "https://github.com/php-http/discovery/issues", - "source": "https://github.com/php-http/discovery/tree/1.13.0" + "source": "https://github.com/php-http/discovery/tree/1.14.0" }, - "time": "2020-11-27T14:49:42+00:00" + "time": "2021-06-01T14:30:21+00:00" }, { "name": "php-http/httplug", @@ -638,16 +637,16 @@ }, { "name": "php-http/message", - "version": "1.11.0", + "version": "1.11.1", "source": { "type": "git", "url": "https://github.com/php-http/message.git", - "reference": "fb0dbce7355cad4f4f6a225f537c34d013571f29" + "reference": "887734d9c515ad9a564f6581a682fff87a6253cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/message/zipball/fb0dbce7355cad4f4f6a225f537c34d013571f29", - "reference": "fb0dbce7355cad4f4f6a225f537c34d013571f29", + "url": "https://api.github.com/repos/php-http/message/zipball/887734d9c515ad9a564f6581a682fff87a6253cc", + "reference": "887734d9c515ad9a564f6581a682fff87a6253cc", "shasum": "", "mirrors": [ { @@ -712,9 +711,9 @@ ], "support": { "issues": "https://github.com/php-http/message/issues", - "source": "https://github.com/php-http/message/tree/1.11.0" + "source": "https://github.com/php-http/message/tree/1.11.1" }, - "time": "2021-02-01T08:54:58+00:00" + "time": "2021-05-24T18:11:08+00:00" }, { "name": "php-http/message-factory", @@ -1252,16 +1251,16 @@ }, { "name": "symfony/http-client", - "version": "v5.2.8", + "version": "v5.3.3", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "a2baf9c3c5b25e04740cece0e429f0a0013002f2" + "reference": "fde4bdb10bf197f932ebccfcb9982881d296fc4c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/a2baf9c3c5b25e04740cece0e429f0a0013002f2", - "reference": "a2baf9c3c5b25e04740cece0e429f0a0013002f2", + "url": "https://api.github.com/repos/symfony/http-client/zipball/fde4bdb10bf197f932ebccfcb9982881d296fc4c", + "reference": "fde4bdb10bf197f932ebccfcb9982881d296fc4c", "shasum": "", "mirrors": [ { @@ -1273,7 +1272,8 @@ "require": { "php": ">=7.2.5", "psr/log": "^1.0", - "symfony/http-client-contracts": "^2.2", + "symfony/deprecation-contracts": "^2.1", + "symfony/http-client-contracts": "^2.4", "symfony/polyfill-php73": "^1.11", "symfony/polyfill-php80": "^1.15", "symfony/service-contracts": "^1.0|^2" @@ -1282,7 +1282,7 @@ "php-http/async-client-implementation": "*", "php-http/client-implementation": "*", "psr/http-client-implementation": "1.0", - "symfony/http-client-implementation": "2.2" + "symfony/http-client-implementation": "2.4" }, "require-dev": { "amphp/amp": "^2.5", @@ -1324,7 +1324,7 @@ "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-client/tree/v5.2.8" + "source": "https://github.com/symfony/http-client/tree/v5.3.3" }, "funding": [ { @@ -1340,7 +1340,7 @@ "type": "tidelift" } ], - "time": "2021-05-10T14:39:23+00:00" + "time": "2021-06-24T08:13:00+00:00" }, { "name": "symfony/http-client-contracts", @@ -1428,16 +1428,16 @@ }, { "name": "symfony/options-resolver", - "version": "v5.2.4", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce" + "reference": "162e886ca035869866d233a2bfef70cc28f9bbe5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce", - "reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/162e886ca035869866d233a2bfef70cc28f9bbe5", + "reference": "162e886ca035869866d233a2bfef70cc28f9bbe5", "shasum": "", "mirrors": [ { @@ -1483,7 +1483,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.2.4" + "source": "https://github.com/symfony/options-resolver/tree/v5.3.0" }, "funding": [ { @@ -1499,20 +1499,20 @@ "type": "tidelift" } ], - "time": "2021-01-27T12:56:27+00:00" + "time": "2021-05-26T17:43:10+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2" + "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", - "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fba8933c384d6476ab14fb7b8526e5287ca7e010", + "reference": "fba8933c384d6476ab14fb7b8526e5287ca7e010", "shasum": "", "mirrors": [ { @@ -1527,7 +1527,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1568,7 +1568,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.23.0" }, "funding": [ { @@ -1584,20 +1584,20 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2021-02-19T12:13:01+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.22.1", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91" + "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dc3063ba22c2a1fd2f45ed856374d79114998f91", - "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/eca0bf41ed421bed1b57c4958bab16aa86b757d0", + "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0", "shasum": "", "mirrors": [ { @@ -1612,7 +1612,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.22-dev" + "dev-main": "1.23-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1657,7 +1657,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.22.1" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.0" }, "funding": [ { @@ -1673,7 +1673,7 @@ "type": "tidelift" } ], - "time": "2021-01-07T16:49:33+00:00" + "time": "2021-02-19T12:13:01+00:00" }, { "name": "symfony/service-contracts", diff --git a/tests/swoole_channel_coro/discard.phpt b/tests/swoole_channel_coro/discard.phpt index 104701d24ae..03c54cfbe6f 100644 --- a/tests/swoole_channel_coro/discard.phpt +++ b/tests/swoole_channel_coro/discard.phpt @@ -23,4 +23,4 @@ var_dump('scheduler end'); --EXPECTF-- string(12) "push success" string(13) "scheduler end" -[%s] WARNING ~Channel (ERRNO 10003): channel is destroyed, 1 producers will be discarded +[%s] WARNING Channel::~Channel() (ERRNO 10003): channel is destroyed, 1 producers will be discarded diff --git a/tests/swoole_coroutine/call_not_exists_func.phpt b/tests/swoole_coroutine/call_not_exists_func.phpt index 891889fbd5a..234cbafb0a7 100644 --- a/tests/swoole_coroutine/call_not_exists_func.phpt +++ b/tests/swoole_coroutine/call_not_exists_func.phpt @@ -35,7 +35,7 @@ Fatal error: Uncaught Error: Call to undefined function none() in %s:%d Stack trace: #0 {main} thrown in %s on line %d -[%s] ERROR php_swoole_server_rshutdown (ERRNO %d): Fatal error: Uncaught Error: Call to undefined function none() in %s:%d +[%s] ERROR php_swoole_server_rshutdown() (ERRNO %d): Fatal error: Uncaught Error: Call to undefined function none() in %s:%d Stack trace: #0 {main} thrown in %s on line %d diff --git a/tests/swoole_coroutine/cancel/gethostbyname.phpt b/tests/swoole_coroutine/cancel/gethostbyname.phpt index d438050e719..d3029cb26d0 100644 --- a/tests/swoole_coroutine/cancel/gethostbyname.phpt +++ b/tests/swoole_coroutine/cancel/gethostbyname.phpt @@ -20,7 +20,7 @@ run(function () { $retval = System::gethostbyname('www.baidu.com'); echo "Done\n"; Assert::eq($retval, false); - Assert::eq(swoole_last_error(), SWOOLE_ERROR_AIO_CANCELED); + Assert::eq(swoole_last_error(), SWOOLE_ERROR_CO_CANCELED); }); ?> diff --git a/tests/swoole_coroutine/exception.phpt b/tests/swoole_coroutine/exception.phpt index 8540fc621d1..f7180aa1e17 100644 --- a/tests/swoole_coroutine/exception.phpt +++ b/tests/swoole_coroutine/exception.phpt @@ -32,7 +32,7 @@ Fatal error: Uncaught Exception: whoops in %s:%d Stack trace: #0 {main} thrown in %s on line %d -[%s] ERROR php_swoole_server_rshutdown (ERRNO %d): Fatal error: Uncaught Exception: whoops in %s:%d +[%s] ERROR php_swoole_server_rshutdown() (ERRNO %d): Fatal error: Uncaught Exception: whoops in %s:%d Stack trace: #0 {main} thrown in %s on line %d diff --git a/tests/swoole_coroutine/gethostbyname.phpt b/tests/swoole_coroutine/gethostbyname.phpt index 3a3453112a6..3cddd73a03b 100644 --- a/tests/swoole_coroutine/gethostbyname.phpt +++ b/tests/swoole_coroutine/gethostbyname.phpt @@ -8,7 +8,13 @@ skip_if_offline(); --FILE-- null, 'www.youtube.com' => null, @@ -22,7 +28,7 @@ Co\run(function () { $first_time = microtime(true); for ($n = MAX_CONCURRENCY_LOW; $n--;) { foreach ($map as $host => &$ip) { - $ip = co::gethostbyname($host); + $ip = System::gethostbyname($host); Assert::assert(preg_match(IP_REGEX, $ip)); } } @@ -33,7 +39,7 @@ Co\run(function () { $cache_time = microtime(true); for ($n = MAX_CONCURRENCY_LOW; $n--;) { foreach ($map as $host => $ip) { - $_ip = co::gethostbyname($host); + $_ip = System::gethostbyname($host); Assert::same($ip, $_ip); } } @@ -42,7 +48,7 @@ Co\run(function () { $no_cache_time = microtime(true); for ($n = MAX_CONCURRENCY_LOW; $n--;) { swoole_clear_dns_cache(); - $ip = co::gethostbyname(array_rand($map)); + $ip = System::gethostbyname(array_rand($map)); Assert::assert(preg_match(IP_REGEX, $ip)); } $no_cache_time = microtime(true) - $no_cache_time; @@ -52,7 +58,7 @@ Co\run(function () { for ($c = MAX_CONCURRENCY_LOW; $c--;) { go(function () use ($map, $chan) { swoole_clear_dns_cache(); - $ip = co::gethostbyname(array_rand($map)); + $ip = System::gethostbyname(array_rand($map)); Assert::assert(filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)); $chan->push(Assert::assert(preg_match(IP_REGEX, $ip))); }); diff --git a/tests/swoole_coroutine_system/aio_thread_num.phpt b/tests/swoole_coroutine_system/aio_thread_num.phpt index 81b801ee5a3..83d97297751 100644 --- a/tests/swoole_coroutine_system/aio_thread_num.phpt +++ b/tests/swoole_coroutine_system/aio_thread_num.phpt @@ -7,14 +7,19 @@ skip_if_offline(); --FILE-- swoole_cpu_num(), 'aio_max_wait_time' => 0.0005 ]); -// init aio core workers -Co\run(function () { - Co::readFile(__FILE__); +run(function () { + System::readFile(__FILE__); }); $sch = new Swoole\Coroutine\Scheduler(); @@ -23,15 +28,15 @@ $sch->add(function () { static $worker_num = 0; $n = 100; while ($n--) { - $worker_num = max($worker_num, Co::stats()['aio_worker_num']); + $worker_num = max($worker_num, Coroutine::stats()['aio_worker_num']); Swoole\Coroutine\System::sleep(0.001); } Assert::greaterThan($worker_num, swoole_cpu_num()); phpt_var_dump($worker_num); }); $sch->parallel(swoole_cpu_num() * [4, 16, 32, 64][PRESSURE_LEVEL], function () { - Co::sleep(mt_rand(1, 5) / 1000); - $result = Swoole\Coroutine\System::gethostbyname('www.baidu.com'); + System::sleep(mt_rand(1, 5) / 1000); + $result = Swoole\Coroutine\System::getaddrinfo('www.baidu.com'); Assert::notEmpty($result); }); $sch->start(); diff --git a/tests/swoole_http_server/buffer_output_size.phpt b/tests/swoole_http_server/buffer_output_size.phpt index 9d391771953..620fdc51474 100644 --- a/tests/swoole_http_server/buffer_output_size.phpt +++ b/tests/swoole_http_server/buffer_output_size.phpt @@ -40,5 +40,5 @@ $pm->childFirst(); $pm->run(); ?> --EXPECTF-- -[%s] WARNING finish (ERRNO %d): The length of data [%d] exceeds the output buffer size[%d], please use the sendfile, chunked transfer mode or adjust the output_buffer_size +[%s] WARNING ProcessFactory::finish() (ERRNO %d): The length of data [%d] exceeds the output buffer size[%d], please use the sendfile, chunked transfer mode or adjust the output_buffer_size DONE diff --git a/tests/swoole_http_server_coro/ssl_bad_client.phpt b/tests/swoole_http_server_coro/ssl_bad_client.phpt index 7db2e512c0e..bb0a0a008e1 100644 --- a/tests/swoole_http_server_coro/ssl_bad_client.phpt +++ b/tests/swoole_http_server_coro/ssl_bad_client.phpt @@ -46,5 +46,5 @@ $pm->childFirst(); $pm->run(); ?> --EXPECTF-- -[%s] WARNING ssl_accept: bad SSL client[127.0.0.1:%d], reason=%d, error_string=%s +[%s] WARNING Socket::ssl_accept(): bad SSL client[127.0.0.1:%d], reason=%d, error_string=%s

Stop

diff --git a/tests/swoole_server/discard_timeout_packet.phpt b/tests/swoole_server/discard_timeout_packet.phpt index ddd2277e879..07285db43e5 100644 --- a/tests/swoole_server/discard_timeout_packet.phpt +++ b/tests/swoole_server/discard_timeout_packet.phpt @@ -32,7 +32,7 @@ $pm->parentFunc = function () use ($pm) { }); $pm->kill(); Assert::eq(substr_count(file_get_contents(TMP_LOG_FILE), - 'Worker_discard_data (ERRNO 1007): [2] ignore data'), 8); + 'Worker_discard_data() (ERRNO 1007): [2] ignore data'), 8); unlink(TMP_LOG_FILE); }; diff --git a/tests/swoole_server/force_reload.phpt b/tests/swoole_server/force_reload.phpt index 5335c9c6845..07cdf14f164 100644 --- a/tests/swoole_server/force_reload.phpt +++ b/tests/swoole_server/force_reload.phpt @@ -66,14 +66,14 @@ $pm->run(); %d [%d] start %s start to reload [%s] INFO Server is reloading all workers now -[%s] WARNING kill_timeout_process (ERRNO 9012): [Manager] Worker#%d[pid=%d] exit timeout, force kill the process -[%s] WARNING kill_timeout_process (ERRNO 9012): [Manager] Worker#%d[pid=%d] exit timeout, force kill the process -[%s] WARNING kill_timeout_process (ERRNO 9012): [Manager] Worker#%d[pid=%d] exit timeout, force kill the process -[%s] WARNING kill_timeout_process (ERRNO 9012): [Manager] Worker#%d[pid=%d] exit timeout, force kill the process -[%s] WARNING check_worker_exit_status: worker#%d[pid=%d] abnormal exit, status=0, signal=9 -[%s] WARNING check_worker_exit_status: worker#%d[pid=%d] abnormal exit, status=0, signal=9 -[%s] WARNING check_worker_exit_status: worker#%d[pid=%d] abnormal exit, status=0, signal=9 -[%s] WARNING check_worker_exit_status: worker#%d[pid=%d] abnormal exit, status=0, signal=9 +[%s] WARNING Manager::kill_timeout_process() (ERRNO 9012): worker(pid=%d, id=%d) exit timeout, force kill the process +[%s] WARNING Manager::kill_timeout_process() (ERRNO 9012): worker(pid=%d, id=%d) exit timeout, force kill the process +[%s] WARNING Manager::kill_timeout_process() (ERRNO 9012): worker(pid=%d, id=%d) exit timeout, force kill the process +[%s] WARNING Manager::kill_timeout_process() (ERRNO 9012): worker(pid=%d, id=%d) exit timeout, force kill the process +[%s] WARNING Server::check_worker_exit_status(): worker(pid=%d, id=%d) abnormal exit, status=0, signal=9 +[%s] WARNING Server::check_worker_exit_status(): worker(pid=%d, id=%d) abnormal exit, status=0, signal=9 +[%s] WARNING Server::check_worker_exit_status(): worker(pid=%d, id=%d) abnormal exit, status=0, signal=9 +[%s] WARNING Server::check_worker_exit_status(): worker(pid=%d, id=%d) abnormal exit, status=0, signal=9 %d [%d] start %d [%d] start %d [%d] start diff --git a/tests/swoole_server/force_reload2.phpt b/tests/swoole_server/force_reload2.phpt index 8f19c5d9202..a551f562a5b 100644 --- a/tests/swoole_server/force_reload2.phpt +++ b/tests/swoole_server/force_reload2.phpt @@ -53,10 +53,10 @@ $pm->run(); %s 1 [%s] start to reload [%s] INFO reload workers -[%s] WARNING ProcessPool_kill_timeout_worker: swKill(%d, SIGKILL) [%d] -[%s] WARNING ProcessPool_kill_timeout_worker: swKill(%d, SIGKILL) [%d] -[%s] WARNING wait: worker#%d abnormal exit, status=0, signal=9 -[%s] WARNING wait: worker#%d abnormal exit, status=0, signal=9 +[%s] WARNING ProcessPool::kill_timeout_worker(): force kill worker process(pid=%d, id=%d) +[%s] WARNING ProcessPool::kill_timeout_worker(): force kill worker process(pid=%d, id=%d) +[%s] WARNING ProcessPool::wait(): worker#%d abnormal exit, status=0, signal=9 +[%s] WARNING ProcessPool::wait(): worker#%d abnormal exit, status=0, signal=9 %s %s [%s] INFO Server is shutdown now diff --git a/tests/swoole_server/invalid_fd.phpt b/tests/swoole_server/invalid_fd.phpt index f0fc1051ed8..d62c90ca268 100644 --- a/tests/swoole_server/invalid_fd.phpt +++ b/tests/swoole_server/invalid_fd.phpt @@ -44,5 +44,5 @@ $pm->run(); Warning: Swoole\Server::send(): fd can not be null in %s/tests/swoole_server/invalid_fd.php on line %d Warning: Swoole\Server::send(): invalid fd[-1] in %s/tests/swoole_server/invalid_fd.php on line %d -[%s] NOTICE send_to_connection (ERRNO 1005): send %d byte failed, session#100 does not exist -[%s] NOTICE send_to_connection (ERRNO 1005): send %d byte failed, session#9223372036854775807 does not exist +[%s] NOTICE Server::send_to_connection() (ERRNO 1005): send %d byte failed, session#100 does not exist +[%s] NOTICE Server::send_to_connection() (ERRNO 1005): send %d byte failed, session#9223372036854775807 does not exist diff --git a/tests/swoole_server/ssl/bad_client.phpt b/tests/swoole_server/ssl/bad_client.phpt index 2667d819233..783bf052f4c 100644 --- a/tests/swoole_server/ssl/bad_client.phpt +++ b/tests/swoole_server/ssl/bad_client.phpt @@ -45,4 +45,4 @@ readfile(ERROR_FILE); unlink(ERROR_FILE); ?> --EXPECTF-- -[%s] WARNING ssl_accept: bad SSL client[127.0.0.1:%d], reason=%d, error_string=%s +[%s] WARNING Socket::ssl_accept(): bad SSL client[127.0.0.1:%d], reason=%d, error_string=%s diff --git a/tests/swoole_server/ssl/verify_02.phpt b/tests/swoole_server/ssl/verify_02.phpt index 92e0e9dafbd..6ff94a87aee 100644 --- a/tests/swoole_server/ssl/verify_02.phpt +++ b/tests/swoole_server/ssl/verify_02.phpt @@ -47,4 +47,4 @@ $pm->childFirst(); $pm->run(); ?> --EXPECTF-- -[%s] NOTICE ssl_verify (ERRNO %d): can not verify peer from fd#%d with error#%d: certificate has expired +[%s] NOTICE Socket::ssl_verify() (ERRNO %d): can not verify peer from fd#%d with error#%d: certificate has expired diff --git a/tests/swoole_server/task/finish_timeout.phpt b/tests/swoole_server/task/finish_timeout.phpt index e08db352972..393c83531de 100644 --- a/tests/swoole_server/task/finish_timeout.phpt +++ b/tests/swoole_server/task/finish_timeout.phpt @@ -63,5 +63,5 @@ $pm->run(); unlink(TMP_LOG_FILE); ?> --EXPECTF-- -[%s] WARNING send_blocking(:%d): send %d bytes failed, Error: Resource temporarily unavailable[11] -[%s] WARNING reply_task_result: TaskWorker: send result to worker timed out +[%s] WARNING Socket::send_blocking(): send %d bytes failed, Error: Resource temporarily unavailable[11] +[%s] WARNING Server::reply_task_result(): send result to worker timed out diff --git a/tests/swoole_server/task/scheduler_warning.phpt b/tests/swoole_server/task/scheduler_warning.phpt index 4a8dbc9952d..9ddbf8564d0 100644 --- a/tests/swoole_server/task/scheduler_warning.phpt +++ b/tests/swoole_server/task/scheduler_warning.phpt @@ -72,4 +72,4 @@ unlink(LOG_FILE); ?> --EXPECTF-- DONE -[%s] WARNING timer_callback (ERRNO %d): No idle task worker is available +[%s] WARNING Server::timer_callback() (ERRNO %d): No idle task worker is available diff --git a/tests/swoole_table/force_unlock.phpt b/tests/swoole_table/force_unlock.phpt index fc5163f02d2..894da422193 100644 --- a/tests/swoole_table/force_unlock.phpt +++ b/tests/swoole_table/force_unlock.phpt @@ -43,5 +43,5 @@ Assert::eq($data['string'], $str_value); echo "Done\n"; ?> --EXPECTF-- -[%s] WARNING lock: lock process[%d] not exists, force unlock +[%s] WARNING TableRow::lock(): lock process[%d] not exists, force unlock Done diff --git a/travis/docker-compile.sh b/travis/docker-compile.sh index 7d529ffac25..523a66eaa95 100755 --- a/travis/docker-compile.sh +++ b/travis/docker-compile.sh @@ -10,7 +10,7 @@ fi #-----------compile------------ #-------print error only------- apt-get update -y -apt-get install -y libcurl4-openssl-dev +apt-get install -y libcurl4-openssl-dev libc-ares-dev cd "${__DIR__}" && cd ../ && \ ./clear.sh > /dev/null && \ phpize --clean > /dev/null && \ @@ -22,6 +22,7 @@ phpize > /dev/null && \ --enable-mysqlnd \ --enable-swoole-json \ --enable-swoole-curl \ +--enable-cares \ > /dev/null && \ make -j8 > /dev/null | tee /tmp/compile.log && \ (test "`cat /tmp/compile.log`"x = ""x || exit 255) && \ diff --git a/travis/simple-compile-on-github.sh b/travis/simple-compile-on-github.sh index bb96ad99533..e1d51643ded 100755 --- a/travis/simple-compile-on-github.sh +++ b/travis/simple-compile-on-github.sh @@ -1,17 +1,23 @@ #!/bin/sh -e +# shellcheck disable=SC2034 +# shellcheck disable=SC2006 __CURRENT__=`pwd` __DIR__=$(cd "$(dirname "$0")";pwd) if [ "${GITHUB_ACTIONS}" = true ]; then + # shellcheck disable=SC2028 echo "\n❌ This script is just for Github!" exit 255 fi -cd ${__DIR__} && cd ../ && \ +sudo apt-get update -y +sudo apt-get install -y libcurl4-openssl-dev libc-ares-dev + +cd "${__DIR__}" && cd ../ && \ ./clear.sh > /dev/null && \ phpize --clean > /dev/null && \ phpize > /dev/null && \ -./configure > /dev/null && \ +./configure --enable-openssl --enable-sockets --enable-mysqlnd --enable-http2 --enable-swoole-json --enable-swoole-curl --enable-cares > /dev/null && \ make -j8 > /dev/null | tee /tmp/compile.log && \ (test "`cat /tmp/compile.log`"x = ""x || exit 255) && \ make install && \ From d780f307342c2483af954dc472c0836f71c957f9 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 13 Jul 2021 17:09:59 +0800 Subject: [PATCH 184/936] Optimize DNS API, Optimize core-tests code --- core-tests/src/coroutine/async.cpp | 2 +- core-tests/src/network/dns.cpp | 7 ++++ include/swoole.h | 2 + include/swoole_config.h | 1 - include/swoole_version.h | 2 +- src/core/base.cc | 12 ++++++ src/network/dns.cc | 63 +++++++++++++----------------- 7 files changed, 51 insertions(+), 38 deletions(-) diff --git a/core-tests/src/coroutine/async.cpp b/core-tests/src/coroutine/async.cpp index 530c7ca430e..8e46f3a1edb 100644 --- a/core-tests/src/coroutine/async.cpp +++ b/core-tests/src/coroutine/async.cpp @@ -55,7 +55,7 @@ TEST(coroutine_async, gethostbyname) { TEST(coroutine_async, error) { coroutine::run([](void *arg) { - int retval; + int retval = 0x7009501; const char *test_file = "/tmp/swoole_core_test_file_not_exists"; swoole::coroutine::async([&](void) { retval = open(test_file, O_RDONLY); }, -1); ASSERT_EQ(retval, -1); diff --git a/core-tests/src/network/dns.cpp b/core-tests/src/network/dns.cpp index c2961ae39e6..3d7ede93fec 100644 --- a/core-tests/src/network/dns.cpp +++ b/core-tests/src/network/dns.cpp @@ -90,3 +90,10 @@ TEST(dns, getaddrinfo) { ASSERT_TRUE(swoole::network::Address::verify_ip(AF_INET, ip)); } } + +TEST(dns, load_resolv_conf) { + ASSERT_TRUE(swoole_load_resolv_conf()); + auto dns_server = swoole_get_dns_server(); + ASSERT_FALSE(dns_server.first.empty()); + ASSERT_NE(dns_server.second, 0); +} diff --git a/include/swoole.h b/include/swoole.h index 84f225009da..8c8727d355b 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -700,6 +700,8 @@ SW_API void swoole_throw_error(int code); SW_API void swoole_set_log_level(int level); SW_API void swoole_set_trace_flags(int flags); SW_API void swoole_set_dns_server(const std::string server); +SW_API std::pair swoole_get_dns_server(); +SW_API bool swoole_load_resolv_conf(); //----------------------------------------------- static sw_inline void sw_spinlock(sw_atomic_t *lock) { diff --git a/include/swoole_config.h b/include/swoole_config.h index 239a743ae28..fd6988dca45 100644 --- a/include/swoole_config.h +++ b/include/swoole_config.h @@ -191,7 +191,6 @@ #define SW_DNS_HOST_BUFFER_SIZE 16 #define SW_DNS_SERVER_PORT 53 -#define SW_DNS_DEFAULT_SERVER "8.8.8.8" #define SW_DNS_RESOLV_CONF "/etc/resolv.conf" #define SW_Z_BEST_SPEED 1 diff --git a/include/swoole_version.h b/include/swoole_version.h index 6bc7c5bb2c9..b981cb415a1 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -24,7 +24,7 @@ #define SWOOLE_EXTRA_VERSION "dev" #define SWOOLE_VERSION "4.7.0-dev" #define SWOOLE_VERSION_ID 40700 -#define SWOOLE_API_VERSION_ID 0x202012a +#define SWOOLE_API_VERSION_ID 0x202107a #define SWOOLE_BUG_REPORT \ "A bug occurred in Swoole-v" SWOOLE_VERSION ", please report it.\n" \ diff --git a/src/core/base.cc b/src/core/base.cc index 8b7af46942c..112b5e0077a 100644 --- a/src/core/base.cc +++ b/src/core/base.cc @@ -262,6 +262,18 @@ SW_API void swoole_set_dns_server(const std::string server) { SwooleG.dns_server_port = dns_server_port; } +SW_API std::pair swoole_get_dns_server() { + std::pair result; + if (SwooleG.dns_server_host.empty()) { + result.first = ""; + result.second = 0; + } else { + result.first = SwooleG.dns_server_host; + result.second = SwooleG.dns_server_port; + } + return result; +} + bool swoole_set_task_tmpdir(const std::string &dir) { if (dir.at(0) != '/') { swWarn("wrong absolute path '%s'", dir.c_str()); diff --git a/src/network/dns.cc b/src/network/dns.cc index 2bb1c173ac6..d234bee6d5d 100644 --- a/src/network/dns.cc +++ b/src/network/dns.cc @@ -25,7 +25,31 @@ #include #endif -#define SW_DNS_SERVER_NUM 2 +bool swoole_load_resolv_conf() { + FILE *fp; + char line[100]; + char buf[16] = {}; + + if ((fp = fopen(SwooleG.dns_resolvconf_path.c_str(), "rt")) == nullptr) { + swSysWarn("fopen(%s) failed", SwooleG.dns_resolvconf_path.c_str()); + return false; + } + + while (fgets(line, 100, fp)) { + if (strncmp(line, "nameserver", 10) == 0) { + strcpy(buf, strtok(line, " ")); + strcpy(buf, strtok(nullptr, "\n")); + break; + } + } + fclose(fp); + + if (strlen(buf) == 0) { + return false; + } + swoole_set_dns_server(buf); + return true; +} namespace swoole { namespace coroutine { @@ -77,37 +101,8 @@ static uint16_t dns_request_id = 1; static int domain_encode(const char *src, int n, char *dest); static void domain_decode(char *str); -static int get_dns_server(); static std::string parse_ip_address(void *vaddr, int type); -static int get_dns_server() { - FILE *fp; - char line[100]; - char buf[16] = {}; - - if ((fp = fopen(SwooleG.dns_resolvconf_path.c_str(), "rt")) == nullptr) { - swSysWarn("fopen(%s) failed", SwooleG.dns_resolvconf_path.c_str()); - return SW_ERR; - } - - while (fgets(line, 100, fp)) { - if (strncmp(line, "nameserver", 10) == 0) { - strcpy(buf, strtok(line, " ")); - strcpy(buf, strtok(nullptr, "\n")); - break; - } - } - fclose(fp); - - if (strlen(buf) == 0) { - swoole_set_dns_server(SW_DNS_DEFAULT_SERVER); - } else { - swoole_set_dns_server(buf); - } - - return SW_OK; -} - static std::string parse_ip_address(void *vaddr, int type) { auto addr = reinterpret_cast(vaddr); std::string ip_addr; @@ -138,11 +133,9 @@ std::vector dns_lookup_impl_with_socket(const char *domain, int fam int steps = 0; std::vector result; - if (SwooleG.dns_server_host.empty()) { - if (get_dns_server() < 0) { - swoole_set_last_error(SW_ERROR_DNSLOOKUP_NO_SERVER); - return result; - } + if (SwooleG.dns_server_host.empty() && !swoole_load_resolv_conf()) { + swoole_set_last_error(SW_ERROR_DNSLOOKUP_NO_SERVER); + return result; } header = (RecordHeader *) packet; From e9cbdeaf273faf78df1ed6f74816e035cf53ea26 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Wed, 14 Jul 2021 11:14:57 +0800 Subject: [PATCH 185/936] Fix compilation warning --- ext-src/swoole_curl.cc | 4 +- include/swoole_memory.h | 2 - thirdparty/php/curl/curl_private.h | 28 +++++------ thirdparty/php/curl/interface.cc | 76 +++++++++++++++--------------- thirdparty/php/curl/multi.cc | 36 +++++++------- 5 files changed, 72 insertions(+), 74 deletions(-) diff --git a/ext-src/swoole_curl.cc b/ext-src/swoole_curl.cc index dc115295b37..58c75793516 100644 --- a/ext-src/swoole_curl.cc +++ b/ext-src/swoole_curl.cc @@ -243,7 +243,7 @@ long Multi::select(php_curlm *mh, double timeout) { for (zend_llist_element *element = mh->easyh.head; element; element = element->next) { zval *z_ch = (zval *) element->data; php_curl *ch; - if ((ch = _php_curl_get_handle(z_ch, false)) == NULL) { + if ((ch = swoole_curl_get_handle(z_ch, false)) == NULL) { continue; } Handle *handle = get_handle(ch->cp); @@ -268,7 +268,7 @@ long Multi::select(php_curlm *mh, double timeout) { for (zend_llist_element *element = mh->easyh.head; element; element = element->next) { zval *z_ch = (zval *) element->data; php_curl *ch; - if ((ch = _php_curl_get_handle(z_ch, false)) == NULL) { + if ((ch = swoole_curl_get_handle(z_ch, false)) == NULL) { continue; } Handle *handle = get_handle(ch->cp); diff --git a/include/swoole_memory.h b/include/swoole_memory.h index 74f8f34dba9..7241ed75c84 100644 --- a/include/swoole_memory.h +++ b/include/swoole_memory.h @@ -22,8 +22,6 @@ //-------------------memory manager------------------------- namespace swoole { -#pragma pack(8) - class MemoryPool { public: virtual ~MemoryPool(){}; diff --git a/thirdparty/php/curl/curl_private.h b/thirdparty/php/curl/curl_private.h index dd755edc611..f83c0ca6609 100644 --- a/thirdparty/php/curl/curl_private.h +++ b/thirdparty/php/curl/curl_private.h @@ -150,12 +150,12 @@ typedef struct _php_curlsh { zend_object std; } php_curlsh; -php_curl *init_curl_handle_into_zval(zval *curl); -void init_curl_handle(php_curl *ch); -void _php_curl_cleanup_handle(php_curl *); -void _php_curl_multi_cleanup_list(void *data); -void _php_curl_verify_handlers(php_curl *ch, int reporterror); -void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source); +php_curl *swoole_curl_init_handle_into_zval(zval *curl); +void swoole_curl_init_handle(php_curl *ch); +void swoole_curl_cleanup_handle(php_curl *); +void swoole_curl_multi_cleanup_list(void *data); +void swoole_curl_verify_handlers(php_curl *ch, int reporterror); +void swoole_setup_easy_copy_handlers(php_curl *ch, php_curl *source); #if PHP_VERSION_ID >= 80000 static inline php_curl *curl_from_obj(zend_object *obj) { @@ -172,19 +172,19 @@ static inline php_curlsh *curl_share_from_obj(zend_object *obj) { void curl_multi_register_class(const zend_function_entry *method_entries); int curl_cast_object(zend_object *obj, zval *result, int type); #else -#define Z_CURL_P(zv) _php_curl_get_handle(zv) +#define Z_CURL_P(zv) swoole_curl_get_handle(zv) #endif /* PHP8 end */ -php_curl *_php_curl_get_handle(zval *zid, bool exclusive = true, bool required = true); +php_curl *swoole_curl_get_handle(zval *zid, bool exclusive = true, bool required = true); SW_EXTERN_C_BEGIN #if PHP_VERSION_ID < 80000 -void _php_curl_close_ex(php_curl *ch); -void _php_curl_close(zend_resource *rsrc); -void _php_curl_multi_close(zend_resource *rsrc); -php_curl *alloc_curl_handle(); -int _php_curl_get_le_curl(); -int _php_curl_get_le_curl_multi(); +void swoole_curl_close_ex(php_curl *ch); +void swoole_curl_close(zend_resource *rsrc); +void swoole_curl_multi_close(zend_resource *rsrc); +php_curl *swoole_curl_alloc_handle(); +int swoole_curl_get_le_curl(); +int swoole_curl_get_le_curl_multi(); #endif SW_EXTERN_C_END diff --git a/thirdparty/php/curl/interface.cc b/thirdparty/php/curl/interface.cc index e255ab68248..23f796e65b9 100644 --- a/thirdparty/php/curl/interface.cc +++ b/thirdparty/php/curl/interface.cc @@ -86,11 +86,11 @@ static zend_object_handlers swoole_native_curl_exception_handlers; static int le_curl; static int le_curl_multi_handle; -int _php_curl_get_le_curl() { +int swoole_curl_get_le_curl() { return le_curl; } -int _php_curl_get_le_curl_multi() { +int swoole_curl_get_le_curl_multi() { return le_curl_multi_handle; } @@ -112,7 +112,7 @@ int _php_curl_get_le_curl_multi() { return; #endif -php_curl *_php_curl_get_handle(zval *zid, bool exclusive, bool required) { +php_curl *swoole_curl_get_handle(zval *zid, bool exclusive, bool required) { php_curl *ch; #if PHP_VERSION_ID >= 80000 ch = Z_CURL_P(zid); @@ -223,7 +223,7 @@ static int php_curl_option_url(php_curl *ch, const char *url, const size_t len) } /* }}} */ -void _php_curl_verify_handlers(php_curl *ch, int reporterror) /* {{{ */ +void swoole_curl_verify_handlers(php_curl *ch, int reporterror) /* {{{ */ { php_stream *stream; @@ -329,9 +329,9 @@ void swoole_native_curl_minit(int module_number) { zend_register_functions(NULL, swoole_native_curl_functions, NULL, MODULE_PERSISTENT); #else - le_curl = zend_register_list_destructors_ex(_php_curl_close, NULL, le_curl_name, module_number); + le_curl = zend_register_list_destructors_ex(swoole_curl_close, NULL, le_curl_name, module_number); le_curl_multi_handle = - zend_register_list_destructors_ex(_php_curl_multi_close, NULL, le_curl_multi_handle_name, module_number); + zend_register_list_destructors_ex(swoole_curl_multi_close, NULL, le_curl_multi_handle_name, module_number); #endif SW_INIT_CLASS_ENTRY_EX(swoole_native_curl_exception, @@ -379,7 +379,7 @@ static zend_object *curl_clone_obj(zend_object *object) { } clone_ch->cp = cp; - _php_setup_easy_copy_handlers(clone_ch, ch); + swoole_setup_easy_copy_handlers(clone_ch, ch); postfields = &clone_ch->postfields; if (Z_TYPE_P(postfields) != IS_UNDEF) { @@ -518,7 +518,7 @@ static size_t fn_write(char *data, size_t size, size_t nmemb, void *ctx) { php_error_docref(NULL, E_WARNING, "Could not call the CURLOPT_WRITEFUNCTION"); length = -1; } else if (!Z_ISUNDEF(retval)) { - _php_curl_verify_handlers(ch, 1); + swoole_curl_verify_handlers(ch, 1); length = zval_get_long(&retval); } @@ -574,7 +574,7 @@ static int fn_fnmatch(void *ctx, const char *pattern, const char *string) { if (error == FAILURE) { php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_FNMATCH_FUNCTION"); } else if (!Z_ISUNDEF(retval)) { - _php_curl_verify_handlers(ch, 1); + swoole_curl_verify_handlers(ch, 1); rval = zval_get_long(&retval); } zval_ptr_dtor(&argv[0]); @@ -643,7 +643,7 @@ static size_t fn_progress(void *clientp, double dltotal, double dlnow, double ul if (error == FAILURE) { php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_PROGRESSFUNCTION"); } else if (!Z_ISUNDEF(retval)) { - _php_curl_verify_handlers(ch, 1); + swoole_curl_verify_handlers(ch, 1); if (0 != zval_get_long(&retval)) { rval = 1; } @@ -707,7 +707,7 @@ static size_t fn_read(char *data, size_t size, size_t nmemb, void *ctx) { php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_READFUNCTION"); length = CURL_READFUNC_ABORT; } else if (!Z_ISUNDEF(retval)) { - _php_curl_verify_handlers(ch, 1); + swoole_curl_verify_handlers(ch, 1); if (Z_TYPE(retval) == IS_STRING) { length = MIN((int) (size * nmemb), Z_STRLEN(retval)); memcpy(data, Z_STRVAL(retval), length); @@ -779,7 +779,7 @@ static size_t fn_write_header(char *data, size_t size, size_t nmemb, void *ctx) php_error_docref(NULL, E_WARNING, "Could not call the CURLOPT_HEADERFUNCTION"); length = -1; } else if (!Z_ISUNDEF(retval)) { - _php_curl_verify_handlers(ch, 1); + swoole_curl_verify_handlers(ch, 1); length = zval_get_long(&retval); } zval_ptr_dtor(&argv[0]); @@ -874,7 +874,7 @@ php_curl *init_curl_handle_into_zval(zval *curl) { #if PHP_VERSION_ID >= 80000 void init_curl_handle(php_curl *ch) #else -php_curl *alloc_curl_handle() +php_curl *swoole_curl_alloc_handle() #endif { #if PHP_VERSION_ID < 80000 @@ -1002,7 +1002,7 @@ PHP_FUNCTION(swoole_native_curl_init) { #if PHP_VERSION_ID >= 80000 ch = init_curl_handle_into_zval(return_value); #else - ch = alloc_curl_handle(); + ch = swoole_curl_alloc_handle(); #endif ch->cp = cp; @@ -1018,7 +1018,7 @@ PHP_FUNCTION(swoole_native_curl_init) { #if PHP_VERSION_ID >= 80000 zval_ptr_dtor(return_value); #else - _php_curl_close_ex(ch); + swoole_curl_close_ex(ch); #endif RETURN_FALSE; } @@ -1031,7 +1031,7 @@ PHP_FUNCTION(swoole_native_curl_init) { } /* }}} */ -void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source) { +void swoole_setup_easy_copy_handlers(php_curl *ch, php_curl *source) { if (!Z_ISUNDEF(source->handlers->write->stream)) { Z_ADDREF(source->handlers->write->stream); } @@ -1360,7 +1360,7 @@ PHP_FUNCTION(swoole_native_curl_copy_handle) { #endif ZEND_PARSE_PARAMETERS_END(); - if ((ch = _php_curl_get_handle(zid)) == NULL) { + if ((ch = swoole_curl_get_handle(zid)) == NULL) { RETURN_FALSE; } @@ -1373,11 +1373,11 @@ PHP_FUNCTION(swoole_native_curl_copy_handle) { #if PHP_VERSION_ID >= 80000 dupch = init_curl_handle_into_zval(return_value); #else - dupch = alloc_curl_handle(); + dupch = swoole_curl_alloc_handle(); #endif dupch->cp = cp; - _php_setup_easy_copy_handlers(dupch, ch); + swoole_setup_easy_copy_handlers(dupch, ch); #if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */ postfields = &ch->postfields; @@ -1386,7 +1386,7 @@ PHP_FUNCTION(swoole_native_curl_copy_handle) { #if PHP_VERSION_ID >= 80000 zval_ptr_dtor(return_value); #else - _php_curl_close_ex(dupch); + swoole_curl_close_ex(dupch); #endif php_error_docref(NULL, E_WARNING, "Cannot rebuild mime structure"); RETURN_FALSE; @@ -2203,7 +2203,7 @@ PHP_FUNCTION(swoole_native_curl_setopt) { Z_PARAM_ZVAL(zvalue) ZEND_PARSE_PARAMETERS_END(); - if ((ch = _php_curl_get_handle(zid, false)) == NULL) { + if ((ch = swoole_curl_get_handle(zid, false)) == NULL) { RETURN_FALSE; } @@ -2236,7 +2236,7 @@ PHP_FUNCTION(swoole_native_curl_setopt_array) { Z_PARAM_ARRAY(arr) ZEND_PARSE_PARAMETERS_END(); - if ((ch = _php_curl_get_handle(zid, false)) == NULL) { + if ((ch = swoole_curl_get_handle(zid, false)) == NULL) { RETURN_FALSE; } @@ -2262,7 +2262,7 @@ PHP_FUNCTION(swoole_native_curl_setopt_array) { /* {{{ _php_curl_cleanup_handle(ch) Cleanup an execution phase */ -void _php_curl_cleanup_handle(php_curl *ch) { +void swoole_curl_cleanup_handle(php_curl *ch) { smart_str_free(&ch->handlers->write->buf); if (ch->header.str) { zend_string_release(ch->header.str); @@ -2289,13 +2289,13 @@ PHP_FUNCTION(swoole_native_curl_exec) { #endif ZEND_PARSE_PARAMETERS_END(); - if ((ch = _php_curl_get_handle(zid)) == NULL) { + if ((ch = swoole_curl_get_handle(zid)) == NULL) { RETURN_FALSE; } - _php_curl_verify_handlers(ch, 1); + swoole_curl_verify_handlers(ch, 1); - _php_curl_cleanup_handle(ch); + swoole_curl_cleanup_handle(ch); Multi multi{}; error = multi.exec(ch); @@ -2362,7 +2362,7 @@ PHP_FUNCTION(swoole_native_curl_getinfo) { #endif ZEND_PARSE_PARAMETERS_END(); - if ((ch = _php_curl_get_handle(zid, false)) == NULL) { + if ((ch = swoole_curl_get_handle(zid, false)) == NULL) { RETURN_FALSE; } @@ -2629,7 +2629,7 @@ PHP_FUNCTION(swoole_native_curl_error) { #endif ZEND_PARSE_PARAMETERS_END(); - if ((ch = _php_curl_get_handle(zid, false)) == NULL) { + if ((ch = swoole_curl_get_handle(zid, false)) == NULL) { RETURN_FALSE; } @@ -2659,7 +2659,7 @@ PHP_FUNCTION(swoole_native_curl_errno) { #endif ZEND_PARSE_PARAMETERS_END(); - if ((ch = _php_curl_get_handle(zid, false)) == NULL) { + if ((ch = swoole_curl_get_handle(zid, false)) == NULL) { RETURN_FALSE; } @@ -2681,7 +2681,7 @@ PHP_FUNCTION(swoole_native_curl_close) { #endif ZEND_PARSE_PARAMETERS_END(); - if ((ch = _php_curl_get_handle(zid)) == NULL) { + if ((ch = swoole_curl_get_handle(zid)) == NULL) { RETURN_FALSE; } @@ -2787,7 +2787,7 @@ static void curl_free_obj(zend_object *object) { return; } - _php_curl_verify_handlers(ch, 0); + swoole_curl_verify_handlers(ch, 0); _php_curl_free(ch); zend_object_std_dtor(&ch->std); @@ -2797,12 +2797,12 @@ static void curl_free_obj(zend_object *object) { #if PHP_VERSION_ID < 80000 /* {{{ _php_curl_close_ex() List destructor for curl handles */ -void _php_curl_close_ex(php_curl *ch) { +void swoole_curl_close_ex(php_curl *ch) { #if PHP_CURL_DEBUG fprintf(stderr, "DTOR CALLED, ch = %x\n", ch); #endif - _php_curl_verify_handlers(ch, 0); + swoole_curl_verify_handlers(ch, 0); _php_curl_free(ch); efree(ch); } @@ -2810,9 +2810,9 @@ void _php_curl_close_ex(php_curl *ch) { /* {{{ _php_curl_close() List destructor for curl handles */ -void _php_curl_close(zend_resource *rsrc) { +void swoole_curl_close(zend_resource *rsrc) { php_curl *ch = (php_curl *) rsrc->ptr; - _php_curl_close_ex(ch); + swoole_curl_close_ex(ch); } #endif /* }}} */ @@ -2877,7 +2877,7 @@ PHP_FUNCTION(swoole_native_curl_reset) { #endif ZEND_PARSE_PARAMETERS_END(); - if ((ch = _php_curl_get_handle(zid)) == NULL) { + if ((ch = swoole_curl_get_handle(zid)) == NULL) { RETURN_FALSE; } @@ -2909,7 +2909,7 @@ PHP_FUNCTION(swoole_native_curl_escape) { Z_PARAM_STR(str) ZEND_PARSE_PARAMETERS_END(); - if ((ch = _php_curl_get_handle(zid)) == NULL) { + if ((ch = swoole_curl_get_handle(zid)) == NULL) { RETURN_FALSE; } @@ -2982,7 +2982,7 @@ PHP_FUNCTION(swoole_native_curl_pause) { Z_PARAM_LONG(bitmask) ZEND_PARSE_PARAMETERS_END(); - if ((ch = _php_curl_get_handle(zid)) == NULL) { + if ((ch = swoole_curl_get_handle(zid)) == NULL) { RETURN_FALSE; } diff --git a/thirdparty/php/curl/multi.cc b/thirdparty/php/curl/multi.cc index b5ffb1d8464..ec4b3b64367 100644 --- a/thirdparty/php/curl/multi.cc +++ b/thirdparty/php/curl/multi.cc @@ -47,7 +47,7 @@ static inline php_curlm *curl_multi_from_obj(zend_object *obj) { static inline php_curlm *Z_CURL_MULTI_P(zval *zv) { php_curlm *cm; if ((cm = (php_curlm *) zend_fetch_resource( - Z_RES_P(zv), le_curl_multi_handle_name, _php_curl_get_le_curl_multi())) == NULL) { + Z_RES_P(zv), le_curl_multi_handle_name, swoole_curl_get_le_curl_multi())) == NULL) { swFatalError(SW_ERROR_INVALID_PARAMS, "supplied resource is not a valid " le_curl_multi_handle_name " resource"); return nullptr; @@ -73,12 +73,12 @@ PHP_FUNCTION(swoole_native_curl_multi_init) { mh = Z_CURL_MULTI_P(return_value); #else mh = (php_curlm *) ecalloc(1, sizeof(php_curlm)); - RETVAL_RES(zend_register_resource(mh, _php_curl_get_le_curl_multi())); + RETVAL_RES(zend_register_resource(mh, swoole_curl_get_le_curl_multi())); #endif mh->multi = new Multi(); mh->multi->set_selector(new Selector()); mh->handlers = (php_curlm_handlers *) ecalloc(1, sizeof(php_curlm_handlers)); - zend_llist_init(&mh->easyh, sizeof(zval), _php_curl_multi_cleanup_list, 0); + zend_llist_init(&mh->easyh, sizeof(zval), swoole_curl_multi_cleanup_list, 0); } /* }}} */ @@ -103,9 +103,9 @@ PHP_FUNCTION(swoole_native_curl_multi_add_handle) { mh = Z_CURL_MULTI_P(z_mh); ch = Z_CURL_P(z_ch); - _php_curl_verify_handlers(ch, 1); + swoole_curl_verify_handlers(ch, 1); - _php_curl_cleanup_handle(ch); + swoole_curl_cleanup_handle(ch); Z_ADDREF_P(z_ch); zend_llist_add_element(&mh->easyh, z_ch); @@ -117,7 +117,7 @@ PHP_FUNCTION(swoole_native_curl_multi_add_handle) { } /* }}} */ -void _php_curl_multi_cleanup_list(void *data) /* {{{ */ +void swoole_curl_multi_cleanup_list(void *data) /* {{{ */ { zval *z_ch = (zval *) data; @@ -146,7 +146,7 @@ static zval *_php_curl_multi_find_easy_handle(php_curlm *mh, CURL *easy) /* {{{ continue; } #endif - tmp_ch = _php_curl_get_handle(pz_ch_temp, false, false); + tmp_ch = swoole_curl_get_handle(pz_ch_temp, false, false); if (tmp_ch && tmp_ch->cp == easy) { return pz_ch_temp; } @@ -242,7 +242,7 @@ PHP_FUNCTION(swoole_native_curl_multi_exec) { } #endif ch = Z_CURL_P(pz_ch); - _php_curl_verify_handlers(ch, 1); + swoole_curl_verify_handlers(ch, 1); } } @@ -331,7 +331,7 @@ PHP_FUNCTION(swoole_native_curl_multi_info_read) { zval *pz_ch = _php_curl_multi_find_easy_handle(mh, tmp_msg->easy_handle); if (pz_ch != NULL) { /* we must save result to be able to read error message */ - ch = _php_curl_get_handle(pz_ch, false, false); + ch = swoole_curl_get_handle(pz_ch, false, false); if (ch) { SAVE_CURL_ERROR(ch, tmp_msg->data.result); } @@ -371,7 +371,7 @@ PHP_FUNCTION(swoole_native_curl_multi_close) { if (!ch) { continue; } - _php_curl_verify_handlers(ch, 1); + swoole_curl_verify_handlers(ch, 1); mh->multi->remove_handle(ch->cp); } zend_llist_clean(&mh->easyh); @@ -440,15 +440,15 @@ static int _php_server_push_callback( return rval; } - parent = (php_curl *) zend_fetch_resource(Z_RES_P(pz_parent_ch), le_curl_name, _php_curl_get_le_curl()); + parent = (php_curl *) zend_fetch_resource(Z_RES_P(pz_parent_ch), le_curl_name, swoole_curl_get_le_curl()); - ch = alloc_curl_handle(); + ch = swoole_curl_alloc_handle(); ch->cp = easy; - _php_setup_easy_copy_handlers(ch, parent); + swoole_setup_easy_copy_handlers(ch, parent); Z_ADDREF_P(pz_parent_ch); - res = zend_register_resource(ch, _php_curl_get_le_curl()); + res = zend_register_resource(ch, swoole_curl_get_le_curl()); ch->res = res; ZVAL_RES(&pz_ch, res); @@ -511,7 +511,7 @@ static int _php_server_push_callback( ch = init_curl_handle_into_zval(&pz_ch); ch->cp = easy; - _php_setup_easy_copy_handlers(ch, parent); + swoole_setup_easy_copy_handlers(ch, parent); size_t i; array_init(&headers); @@ -705,7 +705,7 @@ void curl_multi_register_class(const zend_function_entry *method_entries) { swoole_coroutine_curl_multi_handle_handlers.cast_object = curl_cast_object; } #else -void _php_curl_multi_close(zend_resource *rsrc) /* {{{ */ +void swoole_curl_multi_close(zend_resource *rsrc) /* {{{ */ { php_curlm *mh = (php_curlm *) rsrc->ptr; if (mh) { @@ -726,8 +726,8 @@ static void _php_curl_multi_free(php_curlm *mh) { continue; } #endif - if ((ch = _php_curl_get_handle(z_ch, true, false))) { - _php_curl_verify_handlers(ch, 0); + if ((ch = swoole_curl_get_handle(z_ch, true, false))) { + swoole_curl_verify_handlers(ch, 0); mh->multi->remove_handle(ch->cp); } } From 0c948ee23c06805fcde443812c37af58a9941ecb Mon Sep 17 00:00:00 2001 From: matyhtf Date: Wed, 14 Jul 2021 21:25:40 +0800 Subject: [PATCH 186/936] Fix compilation warning (PHP8) --- thirdparty/php/curl/interface.cc | 4 ++-- thirdparty/php/curl/multi.cc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/thirdparty/php/curl/interface.cc b/thirdparty/php/curl/interface.cc index 23f796e65b9..0eb872d0d4b 100644 --- a/thirdparty/php/curl/interface.cc +++ b/thirdparty/php/curl/interface.cc @@ -369,7 +369,7 @@ static zend_object *curl_clone_obj(zend_object *object) { clone_object = curl_create_object(curl_ce); clone_ch = curl_from_obj(clone_object); - init_curl_handle(clone_ch); + swoole_curl_init_handle(clone_ch); ch = curl_from_obj(object); cp = curl_easy_duphandle(ch->cp); @@ -863,7 +863,7 @@ php_curl *init_curl_handle_into_zval(zval *curl) { object_init_ex(curl, swoole_coroutine_curl_handle_ce); ch = Z_CURL_P(curl); - init_curl_handle(ch); + swoole_curl_init_handle(ch); return ch; } diff --git a/thirdparty/php/curl/multi.cc b/thirdparty/php/curl/multi.cc index ec4b3b64367..6561af5b989 100644 --- a/thirdparty/php/curl/multi.cc +++ b/thirdparty/php/curl/multi.cc @@ -509,7 +509,7 @@ static int _php_server_push_callback( parent = Z_CURL_P(pz_parent_ch); - ch = init_curl_handle_into_zval(&pz_ch); + ch = swoole_curl_init_handle_into_zval(&pz_ch); ch->cp = easy; swoole_setup_easy_copy_handlers(ch, parent); From 3f2e960cda4bf8029d716ba5ba9ae888d75e9ecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Thu, 15 Jul 2021 13:11:58 +0800 Subject: [PATCH 187/936] Added dispatch_mode=8/9 (#4318) * dispatch_mode=8/9 * docker * fix * fix 2 * fix 3 --- ext-src/swoole_server.cc | 3 + include/swoole_process_pool.h | 1 + include/swoole_reactor.h | 1 + include/swoole_server.h | 19 +++- src/server/master.cc | 13 +++ src/server/worker.cc | 4 + tests/include/functions.php | 24 +++++ tests/swoole_server/dispatch_mode_7.phpt | 2 +- tests/swoole_server/dispatch_mode_8.phpt | 95 +++++++++++++++++++ tests/swoole_server/dispatch_mode_9.phpt | 115 +++++++++++++++++++++++ thirdparty/php/curl/interface.cc | 10 +- travis/route.sh | 2 +- 12 files changed, 281 insertions(+), 8 deletions(-) create mode 100644 tests/swoole_server/dispatch_mode_8.phpt create mode 100644 tests/swoole_server/dispatch_mode_9.phpt diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 150cc824bff..3824e860e4d 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -3628,6 +3628,9 @@ static PHP_METHOD(swoole_server, getClientInfo) { if (conn->uid > 0 || serv->dispatch_mode == SW_DISPATCH_UIDMOD) { add_assoc_long(return_value, "uid", conn->uid); } + if (conn->worker_id > 0 || serv->dispatch_mode == SW_DISPATCH_CO_CONN_LB) { + add_assoc_long(return_value, "worker_id", conn->worker_id); + } ListenPort *port = serv->get_port_by_fd(conn->fd); if (port && port->open_websocket_protocol) { diff --git a/include/swoole_process_pool.h b/include/swoole_process_pool.h index b59416f4f17..65b4d130f6e 100644 --- a/include/swoole_process_pool.h +++ b/include/swoole_process_pool.h @@ -130,6 +130,7 @@ struct Worker { long dispatch_count; long request_count; + size_t coroutine_num; /** * worker id diff --git a/include/swoole_reactor.h b/include/swoole_reactor.h index f2b04f0603d..8fda4ccb935 100644 --- a/include/swoole_reactor.h +++ b/include/swoole_reactor.h @@ -86,6 +86,7 @@ class Reactor { PRIORITY_SIGNAL_CALLBACK, PRIORITY_TRY_EXIT, PRIORITY_MALLOC_TRIM, + PRIORITY_WORKER_CALLBACK, }; enum ExitCondition { diff --git a/include/swoole_server.h b/include/swoole_server.h index c9a6e7d1f69..7ee38be73e4 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -61,6 +61,8 @@ enum swFactory_dispatch_mode { SW_DISPATCH_UIDMOD = 5, SW_DISPATCH_USERFUNC = 6, SW_DISPATCH_STREAM = 7, + SW_DISPATCH_CO_CONN_LB, + SW_DISPATCH_CO_REQ_LB, }; enum swFactory_dispatch_result { @@ -98,6 +100,7 @@ struct Connection { uint8_t active; enum swSocket_type socket_type; int fd; + int worker_id; SessionId session_id; //-------------------------------------------------------------- #ifdef SW_USE_OPENSSL @@ -998,7 +1001,8 @@ class Server { } inline bool is_hash_dispatch_mode() { - return dispatch_mode == SW_DISPATCH_FDMOD || dispatch_mode == SW_DISPATCH_IPMOD; + return dispatch_mode == SW_DISPATCH_FDMOD || dispatch_mode == SW_DISPATCH_IPMOD || + dispatch_mode == SW_DISPATCH_CO_CONN_LB; } inline bool is_support_send_yield() { @@ -1042,6 +1046,19 @@ class Server { return nullptr; } + int get_lowest_load_worker_id() { + uint32_t lowest_load_worker_id = 0; + size_t min_coroutine = workers[0].coroutine_num; + for (uint32_t i = 1; i < worker_num; i++) { + if (workers[i].coroutine_num < min_coroutine) { + min_coroutine = workers[i].coroutine_num; + lowest_load_worker_id = i; + continue; + } + } + return lowest_load_worker_id; + } + void stop_async_worker(Worker *worker); inline Pipe *get_pipe_object(int pipe_fd) { diff --git a/src/server/master.cc b/src/server/master.cc index 2b1c8e1c47d..738cee8b20d 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -964,6 +964,17 @@ int Server::schedule_worker(int fd, SendData *data) { } else { key = conn->uid; } + } else if (dispatch_mode == SW_DISPATCH_CO_CONN_LB) { + Connection *conn = get_connection(fd); + if (conn == nullptr) { + return key % worker_num; + } + if (conn->worker_id < 0) { + conn->worker_id = get_lowest_load_worker_id(); + } + return conn->worker_id; + } else if (dispatch_mode == SW_DISPATCH_CO_REQ_LB) { + return get_lowest_load_worker_id(); } // Preemptive distribution else { @@ -982,6 +993,7 @@ int Server::schedule_worker(int fd, SendData *data) { swTraceLog(SW_TRACE_SERVER, "schedule=%d, round=%d", key, worker_round_id); return key; } + return key % worker_num; } @@ -1659,6 +1671,7 @@ Connection *Server::add_connection(ListenPort *ls, Socket *_socket, int server_f connection->server_fd = (sw_atomic_t) server_fd; connection->last_recv_time = connection->connect_time = microtime(); connection->active = 1; + connection->worker_id = -1; connection->socket_type = ls->type; connection->socket = _socket; diff --git a/src/server/worker.cc b/src/server/worker.cc index 8c3eca6b7f8..b00c06ecdbc 100644 --- a/src/server/worker.cc +++ b/src/server/worker.cc @@ -23,6 +23,7 @@ #include "swoole_memory.h" #include "swoole_msg_queue.h" #include "swoole_client.h" +#include "swoole_coroutine.h" swoole::WorkerGlobal SwooleWG = {}; @@ -567,6 +568,9 @@ int Server::start_event_worker(Worker *worker) { stream_protocol.package_max_length = UINT_MAX; stream_protocol.onPackage = Worker_onStreamPackage; buffer_pool = new std::queue; + } else if (dispatch_mode == SW_DISPATCH_CO_CONN_LB || dispatch_mode == SW_DISPATCH_CO_REQ_LB) { + reactor->set_end_callback(Reactor::PRIORITY_WORKER_CALLBACK, + [worker](Reactor *) { worker->coroutine_num = Coroutine::count(); }); } worker->status = SW_WORKER_IDLE; diff --git a/tests/include/functions.php b/tests/include/functions.php index d41e8b78d89..98c954b799e 100644 --- a/tests/include/functions.php +++ b/tests/include/functions.php @@ -775,3 +775,27 @@ function curl_type_assert($ch, $resource_type, $class_type) Assert::eq(get_resource_type($ch), $resource_type); } } + +function swoole_get_variance($avg, $array, $is_swatch = false) +{ + $count = count($array); + if ($count == 1 && $is_swatch == true) { + return false; + } elseif ($count > 0) { + $total_var = 0; + foreach ($array as $lv) { + $total_var += pow(($lv - $avg), 2); + } + if ($count == 1 && $is_swatch == true) { + return false; + } + return $is_swatch ? sqrt($total_var / (count($array) - 1)) : sqrt($total_var / count($array)); + } else { + return false; + } +} + +function swoole_get_average($array) +{ + return array_sum($array) / count($array); +} \ No newline at end of file diff --git a/tests/swoole_server/dispatch_mode_7.phpt b/tests/swoole_server/dispatch_mode_7.phpt index a73b89425d4..e43877bf9fb 100644 --- a/tests/swoole_server/dispatch_mode_7.phpt +++ b/tests/swoole_server/dispatch_mode_7.phpt @@ -44,7 +44,7 @@ $pm->parentFunc = function ($pid) use ($pm) { }; $pm->childFunc = function () use ($pm) { - $serv = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_BASE); + $serv = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_PROCESS); $serv->set(array( 'package_eof' => "\r\n\r\n", 'open_eof_check' => true, diff --git a/tests/swoole_server/dispatch_mode_8.phpt b/tests/swoole_server/dispatch_mode_8.phpt new file mode 100644 index 00000000000..604aace14a3 --- /dev/null +++ b/tests/swoole_server/dispatch_mode_8.phpt @@ -0,0 +1,95 @@ +--TEST-- +swoole_server: dispatch_mode = 8 [co conn lb] +--SKIPIF-- + +--FILE-- +column('count', Table::TYPE_INT); +$table->create(); + +$pm = new SwooleTest\ProcessManager; +$pm->magic_code = rand(10000000, 90000000); +$pm->parentFunc = function ($pid) use ($pm, $table) { + run(function () use ($pm, $table) { + $n = 200; + while ($n--) { + go(function () use ($pm, $table) { + $client = new Client(SWOOLE_SOCK_TCP); + if (!$client->connect('127.0.0.1', $pm->getFreePort(), 0.5, 0)) { + echo "Over flow. errno=" . $client->errCode; + die("\n"); + } + + $data = array( + 'name' => __FILE__, + 'sid' => $pm->magic_code, + 'content' => str_repeat('A', 8192 * rand(1, 3)), + ); + + $_serialize_data = serialize($data) . "\r\n\r\n"; + $client->send($_serialize_data); + Assert::eq($client->recv(), "SUCCESS\n"); + }); + } + }); + + $pm->kill(); + + $array = array_column(iterator_to_array($table), 'count'); + $standard_deviation = sqrt(swoole_get_variance(swoole_get_average($array), $array)); + Assert::greaterThan($standard_deviation, 1); + Assert::lessThan($standard_deviation, 5); + echo 'DONE' . PHP_EOL; +}; + +$pm->childFunc = function () use ($pm, $table) { + $serv = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_PROCESS); + $serv->set(array( + 'package_eof' => "\r\n\r\n", + 'open_eof_check' => true, + 'open_eof_split' => true, + 'dispatch_mode' => 8, + 'package_max_length' => 1024 * 1024 * 2, + "worker_num" => 4, + 'log_file' => '/dev/null', + "reload_async" => true, + )); + $serv->on("WorkerStart", function (Server $serv, $worker_id) use ($pm) { + if ($worker_id == 0) { + $pm->wakeup(); + } + }); + $serv->on('connect', function (Server $serv, $fd, $rid) use ($table) { + $table->incr($serv->getWorkerId(), 'count'); + if (rand(1000, 9999) % 4 == 0) { + System::sleep(0.5); + } + }); + $serv->on('receive', function (Server $serv, $fd, $rid, $data) use ($pm) { + Assert::eq($serv->getClientInfo($fd)['worker_id'], $serv->getWorkerId()); + $_data = unserialize(rtrim($data)); + if ($_data and is_array($_data) and $_data['sid'] == $pm->magic_code) { + $serv->send($fd, "SUCCESS\n"); + } else { + $serv->send($fd, "ERROR\n"); + } + }); + $serv->start(); +}; + +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +DONE diff --git a/tests/swoole_server/dispatch_mode_9.phpt b/tests/swoole_server/dispatch_mode_9.phpt new file mode 100644 index 00000000000..cd64d9f9ee1 --- /dev/null +++ b/tests/swoole_server/dispatch_mode_9.phpt @@ -0,0 +1,115 @@ +--TEST-- +swoole_server: dispatch_mode = 9 [co req lb] +--SKIPIF-- + +--FILE-- +column('count', Table::TYPE_INT); +$table->create(); + +const N = 1024; +const EOF = "\r\n\r\n"; + +$pm = new SwooleTest\ProcessManager; +$pm->magic_code = rand(10000000, 90000000); +$pm->parentFunc = function ($pid) use ($pm, $table) { + run(function () use ($pm, $table) { + $client = new Client(SWOOLE_SOCK_TCP); + $client->set(array( + 'package_eof' => EOF, + 'open_eof_check' => true, + 'open_eof_split' => true, + )); + if (!$client->connect('127.0.0.1', $pm->getFreePort(), 0.5, 0)) { + echo "Over flow. errno=" . $client->errCode; + die("\n"); + } + + $rand = rand(1, 4); + + $data = array( + 'name' => __FILE__, + 'sid' => $pm->magic_code, + 'content' => str_repeat('A', 1024 * $rand), + ); + + $_serialize_data = serialize($data) . EOF; + + go(function () use ($client) { + $n = N; + while ($n--) { + Assert::eq($client->recv(), "SUCCESS" . EOF); + } + $client->close(); + }); + + $n = N; + while ($n--) { + $client->send($_serialize_data); + if ($n % 10 == 1) { + System::sleep(0.002); + } + } + }); + + $pm->kill(); + + $array = array_column(iterator_to_array($table), 'count'); + $standard_deviation = sqrt(swoole_get_variance(swoole_get_average($array), $array)); + Assert::greaterThan($standard_deviation, 1); + Assert::lessThan($standard_deviation, 5); + echo 'DONE' . PHP_EOL; +}; + +$pm->childFunc = function () use ($pm, $table) { + $serv = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_PROCESS); + + $serv->set(array( + 'package_eof' => "\r\n\r\n", + 'open_eof_check' => true, + 'open_eof_split' => true, + 'dispatch_mode' => 9, + 'package_max_length' => 1024 * 1024 * 2, + "worker_num" => 4, + 'log_file' => '/dev/null', + "reload_async" => true, + )); + + $serv->on("WorkerStart", function (Server $serv, $worker_id) use ($pm) { + if ($worker_id == 0) { + $pm->wakeup(); + } + }); + + $serv->on('receive', function (Server $serv, $fd, $rid, $data) use ($pm, $table) { + $table->incr($serv->getWorkerId(), 'count'); + if (rand(1000, 9999) % 10 == 0) { + System::sleep(0.5); + } + $_data = unserialize(rtrim($data)); + if ($_data and is_array($_data) and $_data['sid'] == $pm->magic_code) { + $serv->send($fd, "SUCCESS".EOF); + } else { + $serv->send($fd, "ERROR".EOF); + } + }); + + $serv->start(); +}; + +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +DONE diff --git a/thirdparty/php/curl/interface.cc b/thirdparty/php/curl/interface.cc index 0eb872d0d4b..b5817fd2d3c 100644 --- a/thirdparty/php/curl/interface.cc +++ b/thirdparty/php/curl/interface.cc @@ -857,7 +857,7 @@ static void curl_free_slist(zval *el) { /* }}} */ #if PHP_VERSION_ID >= 80000 -php_curl *init_curl_handle_into_zval(zval *curl) { +php_curl *swoole_curl_init_handle_into_zval(zval *curl) { php_curl *ch; object_init_ex(curl, swoole_coroutine_curl_handle_ce); @@ -872,7 +872,7 @@ php_curl *init_curl_handle_into_zval(zval *curl) { /* {{{ alloc_curl_handle */ #if PHP_VERSION_ID >= 80000 -void init_curl_handle(php_curl *ch) +void swoole_curl_init_handle(php_curl *ch) #else php_curl *swoole_curl_alloc_handle() #endif @@ -1000,7 +1000,7 @@ PHP_FUNCTION(swoole_native_curl_init) { } #if PHP_VERSION_ID >= 80000 - ch = init_curl_handle_into_zval(return_value); + ch = swoole_curl_init_handle_into_zval(return_value); #else ch = swoole_curl_alloc_handle(); #endif @@ -1371,7 +1371,7 @@ PHP_FUNCTION(swoole_native_curl_copy_handle) { } #if PHP_VERSION_ID >= 80000 - dupch = init_curl_handle_into_zval(return_value); + dupch = swoole_curl_init_handle_into_zval(return_value); #else dupch = swoole_curl_alloc_handle(); #endif @@ -2696,7 +2696,7 @@ PHP_FUNCTION(swoole_native_curl_close) { } /* }}} */ -void _php_curl_free(php_curl *ch) { +static void _php_curl_free(php_curl *ch) { /* * Libcurl is doing connection caching. When easy handle is cleaned up, * if the handle was previously used by the curl_multi_api, the connection diff --git a/travis/route.sh b/travis/route.sh index 4ef02165063..d7e521434a8 100755 --- a/travis/route.sh +++ b/travis/route.sh @@ -6,7 +6,7 @@ export DOCKER_COMPOSE_VERSION="1.21.0" [ -z "${TRAVIS_BRANCH}" ] && export TRAVIS_BRANCH="master" [ -z "${TRAVIS_BUILD_DIR}" ] && export TRAVIS_BUILD_DIR=$(cd "$(dirname "$0")";cd ../;pwd) [ -z "${PHP_VERSION_ID}" ] && export PHP_VERSION_ID=`php -r "echo PHP_VERSION_ID;"` -if [ ${PHP_VERSION_ID} -lt 70500 ]; then +if [ ${PHP_VERSION_ID} -lt 80100 ]; then export PHP_VERSION="`php -r "echo PHP_MAJOR_VERSION;"`.`php -r "echo PHP_MINOR_VERSION;"`" else export PHP_VERSION="rc" From db6deb0cd9469a6f1a34ab73426eacda545c9451 Mon Sep 17 00:00:00 2001 From: codinghuang Date: Fri, 16 Jul 2021 16:23:56 +0800 Subject: [PATCH 188/936] Update version for Swoole 4.7.0 (#4321) --- CMakeLists.txt | 2 +- ext-src/php_swoole.cc | 3 + ext-src/php_swoole_library.h | 59 +++++++++++--- include/swoole_version.h | 4 +- package.xml | 77 +++++++++++++++---- src/core/error.cc | 4 + .../swoole_websocket_server/onDisconnct.phpt | 1 - 7 files changed, 119 insertions(+), 31 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 33dfdbdeb86..667baaf60c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ PROJECT(libswoole) ENABLE_LANGUAGE(ASM) -set(SWOOLE_VERSION 4.7.0-dev) +set(SWOOLE_VERSION 4.7.0) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g") diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index ce9b1aa1235..54ef17cee85 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -588,6 +588,8 @@ PHP_MINIT_FUNCTION(swoole) { SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_DNSLOOKUP_DUPLICATE_REQUEST", SW_ERROR_DNSLOOKUP_DUPLICATE_REQUEST); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_DNSLOOKUP_RESOLVE_FAILED", SW_ERROR_DNSLOOKUP_RESOLVE_FAILED); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_DNSLOOKUP_RESOLVE_TIMEOUT", SW_ERROR_DNSLOOKUP_RESOLVE_TIMEOUT); + SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_DNSLOOKUP_UNSUPPORTED", SW_ERROR_DNSLOOKUP_UNSUPPORTED); + SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_DNSLOOKUP_NO_SERVER", SW_ERROR_DNSLOOKUP_NO_SERVER); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_BAD_IPV6_ADDRESS", SW_ERROR_BAD_IPV6_ADDRESS); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_UNREGISTERED_SIGNAL", SW_ERROR_UNREGISTERED_SIGNAL); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_EVENT_SOCKET_REMOVED", SW_ERROR_EVENT_SOCKET_REMOVED); @@ -703,6 +705,7 @@ PHP_MINIT_FUNCTION(swoole) { SW_REGISTER_LONG_CONSTANT("SWOOLE_TRACE_CO_HTTP_SERVER", SW_TRACE_CO_HTTP_SERVER); SW_REGISTER_LONG_CONSTANT("SWOOLE_TRACE_TABLE", SW_TRACE_TABLE); SW_REGISTER_LONG_CONSTANT("SWOOLE_TRACE_CO_CURL", SW_TRACE_CO_CURL); + SW_REGISTER_LONG_CONSTANT("SWOOLE_TRACE_CARES", SW_TRACE_CARES); SW_REGISTER_LONG_CONSTANT("SWOOLE_TRACE_ALL", SW_TRACE_ALL); /** diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index 706f84e2226..de28f50b76b 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: e07037baef45ea64d334257e203fe2ca82914c93 */ +/* $Id: 05b8161677541803bf1644f9a57057863c67937b */ static const char* swoole_library_source_constants = "\n" @@ -19,7 +19,8 @@ static const char* swoole_library_source_constants = "define('SWOOLE_LIBRARY', true);\n" "\n" "!defined('CURLOPT_HEADEROPT') && define('CURLOPT_HEADEROPT', 229);\n" - "!defined('CURLOPT_PROXYHEADER') && define('CURLOPT_PROXYHEADER', 10228);\n"; + "!defined('CURLOPT_PROXYHEADER') && define('CURLOPT_PROXYHEADER', 10228);\n" + "!defined('CURLOPT_RESOLVE') && define('CURLOPT_RESOLVE', 10203);\n"; static const char* swoole_library_source_std_exec = "\n" @@ -305,6 +306,10 @@ static const char* swoole_library_source_core_constant = "\n" " public const OPTION_WEBSOCKET_MASK = 'websocket_mask';\n" "\n" + " public const OPTION_HTTP_COMPRESSION = 'http_compression';\n" + "\n" + " public const OPTION_BODY_DECOMPRESSION = 'body_decompression';\n" + "\n" " public const OPTION_WEBSOCKET_COMPRESSION = 'websocket_compression';\n" "\n" " public const OPTION_HTTP_PARSE_COOKIE = 'http_parse_cookie';\n" @@ -313,8 +318,6 @@ static const char* swoole_library_source_core_constant = "\n" " public const OPTION_HTTP_PARSE_FILES = 'http_parse_files';\n" "\n" - " public const OPTION_HTTP_COMPRESSION = 'http_compression';\n" - "\n" " public const OPTION_HTTP_COMPRESSION_LEVEL = 'http_compression_level';\n" "\n" " public const OPTION_HTTP_GZIP_LEVEL = 'http_gzip_level';\n" @@ -3005,13 +3008,10 @@ static const char* swoole_library_source_core_database_pdo_statement_proxy = " return $this->__object->setAttribute($attribute, $value);\n" " }\n" "\n" - " public function setFetchMode(int $mode, $classNameObject = null, array $ctorarfg = []): bool\n" + " public function setFetchMode(int $mode, ...$args): bool\n" " {\n" - " $this->setFetchModeContext = [$mode, $classNameObject, $ctorarfg];\n" - " if (!isset($classNameObject)) {\n" - " return $this->__object->setFetchMode($mode);\n" - " }\n" - " return $this->__object->setFetchMode($mode, $classNameObject, $ctorarfg);\n" + " $this->setFetchModeContext = func_get_args();\n" + " return $this->__object->setFetchMode(...$this->setFetchModeContext);\n" " }\n" "\n" " public function bindParam($parameter, &$variable, $data_type = PDO::PARAM_STR, $length = null, $driver_options = null): bool\n" @@ -3587,6 +3587,8 @@ static const char* swoole_library_source_core_curl_handler = "\n" " private $cookieJar = '';\n" "\n" + " private $resolve = [];\n" + "\n" " public function __construct(string $url = '')\n" " {\n" " if ($url) {\n" @@ -3673,7 +3675,15 @@ static const char* swoole_library_source_core_curl_handler = " if ($urlInfo === null) {\n" " $urlInfo = $this->urlInfo;\n" " }\n" - " $this->client = new Client($urlInfo['host'], $urlInfo['port'], $urlInfo['scheme'] === 'https');\n" + " $host = $urlInfo['host'];\n" + " $port = $urlInfo['port'];\n" + " if (isset($this->resolve[$host])) {\n" + " if (!$this->hasHeader('Host')) {\n" + " $this->setHeader('Host', $host);\n" + " }\n" + " $this->urlInfo['host'] = $host = $this->resolve[$host][$port] ?? null ?: $host;\n" + " }\n" + " $this->client = new Client($host, $port, $urlInfo['scheme'] === 'https');\n" " }\n" "\n" " private function getUrl(): string\n" @@ -3761,7 +3771,7 @@ static const char* swoole_library_source_core_curl_handler = " private function setError($code, $msg = ''): void\n" " {\n" " $this->errCode = $code;\n" - " $this->errMsg = $msg ? $msg : curl_strerror($code);\n" + " $this->errMsg = $msg ?: curl_strerror($code);\n" " }\n" "\n" " private function hasHeader(string $headerName): bool\n" @@ -3870,6 +3880,25 @@ static const char* swoole_library_source_core_curl_handler = " $this->nobody = boolval($value);\n" " $this->method = 'HEAD';\n" " break;\n" + " case CURLOPT_RESOLVE:\n" + " foreach ((array) $value as $resolve) {\n" + " $flag = substr($resolve, 0, 1);\n" + " if ($flag === '+' || $flag === '-') {\n" + " // TODO: [+]HOST:PORT:ADDRESS\n" + " $resolve = substr($resolve, 1);\n" + " }\n" + " $tmpResolve = explode(':', $resolve, 3);\n" + " $host = $tmpResolve[0] ?? '';\n" + " $port = $tmpResolve[1] ?? 0;\n" + " $ip = $tmpResolve[2] ?? '';\n" + " if ($flag === '-') {\n" + " unset($this->resolve[$host][$port]);\n" + " } else {\n" + " // TODO: HOST:PORT:ADDRESS[,ADDRESS]...\n" + " $this->resolve[$host][$port] = explode(',', $ip)[0];\n" + " }\n" + " }\n" + " break;\n" " case CURLOPT_IPRESOLVE:\n" " if ($value !== CURL_IPRESOLVE_WHATEVER and $value !== CURL_IPRESOLVE_V4) {\n" " throw new Swoole\\Curl\\Exception(\n" @@ -4260,6 +4289,10 @@ static const char* swoole_library_source_core_curl_handler = " $this->info['redirect_time'] = microtime(true) - $redirectBeginTime;\n" " }\n" "\n" + " if (filter_var($this->urlInfo['host'], FILTER_VALIDATE_IP)) {\n" + " $this->info['primary_ip'] = $this->urlInfo['host'];\n" + " }\n" + "\n" " $headerContent = '';\n" " if ($client->headers) {\n" " $cb = $this->headerFunction;\n" @@ -7118,6 +7151,8 @@ static const char* swoole_library_source_ext_curl = " return $info['redirect_time'];\n" " case CURLINFO_HEADER_SIZE:\n" " return $info['header_size'];\n" + " case CURLINFO_PRIMARY_IP:\n" + " return $info['primary_ip'];\n" " case CURLINFO_PRIVATE:\n" " return $info['private'];\n" " default:\n" diff --git a/include/swoole_version.h b/include/swoole_version.h index b981cb415a1..7e57533779c 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -21,8 +21,8 @@ #define SWOOLE_MAJOR_VERSION 4 #define SWOOLE_MINOR_VERSION 7 #define SWOOLE_RELEASE_VERSION 0 -#define SWOOLE_EXTRA_VERSION "dev" -#define SWOOLE_VERSION "4.7.0-dev" +#define SWOOLE_EXTRA_VERSION "" +#define SWOOLE_VERSION "4.7.0" #define SWOOLE_VERSION_ID 40700 #define SWOOLE_API_VERSION_ID 0x202107a diff --git a/package.xml b/package.xml index 0d8c54e080a..1268fae4839 100644 --- a/package.xml +++ b/package.xml @@ -48,10 +48,10 @@ lufei@php.net yes - 2021-05-14 + 2021-07-16 - 4.6.7 + 4.7.0 4.0 @@ -60,25 +60,42 @@ Apache2.0 + New APIs + --- + * Added Process\Pool::detach() (#4221) (@matyhtf) + * Added onDisconnect callback for Swoole\Server (#4230) (@matyhtf) + * Added Coroutine::cancel() (#4247) (#4249) (@matyhtf) + * Added http_compression/body_decompression options for Http Client (#4299) (@matyhtf) + Enhancement --- - * Supported call Process::signal() in Manager process and Worker process (#4190) (@matyhtf) + * Supported mysql client prepare field type identification (#4238) (@Yurunsoft) + * Supported c-ares, Refactor DNS (#4275) (@matyhtf) + * Supported setting different idle time for each port (#4290) (@matyhtf) + * Supported SW_DISPATCH_CO_CONN_LB and SW_DISPATCH_CO_REQ_LB for Swoole\Server dispatch_mode (#4318) (@matyhtf) + * Supported timeout for Swoole\ConnectionPool::get (swoole/library#108) (@leocavalcante) + * Supported CURLOPT_PRIVATE for Hook Curl (swoole/library#112) (@sy-records) + * Optimized PDOStatementProxy::setFetchMode function prototype (swoole/library#109) (@yespire) Fixed --- - * Fixed signal cannot be registered repeatedly (#4170) (@matyhtf) - * Fixed build on OpenBSD/NetBSD (#4188) (#4194) (@devnexen) - * Fixed Lost onclose event (#4204) (@matyhtf) - * Fixed native curl with Symfony HttpClient (#4208) (@matyhtf) - * Fixed Http\Response::end() always return true (swoole/swoole-src@66fcc35) (@matyhtf) - * Fixed PDOException generated by PDOStatementProxy (swoole/library#104) (@twose) + * Fixed uncaught thread creation exception when creating a large number of coroutines (swoole/swoole-src@8ce5041) (@matyhtf) + * Fixed the "make install" missing php_swoole.h header file (#4239) (@sy-records) + * Fixed EVENT_HANDSHAKE BC (#4248) (@sy-records) + * Fixed SW_LOCK_CHECK_RETURN (#4302) (@zmyWL) + * Fixed problems with Swoole\Atomic\Long M1 chip (swoole/swoole-src@e6fae2e) (@matyhtf) + * Fixed missing return value of Coroutine\go (swoole/library@1ed49db) (@matyhtf) + * Fixed StringObject consistency between other methods and its immutability (swoole/library#111) (@leocavalcante) + * Fixed StringObject substr error (swoole/library#113) (@sy-records) Kernel --- - * Refactored worker buffer, add msg id for the event data (#4163) (@matyhtf) - * Changed the log level of "Request Entity Too Large" to warning (#4175) (@sy-records) - * Deleted inet_ntoa and inet_aton calls (#4199) (@remicollet) - * Adjusted output_buffer_size value to UINT_MAX (swoole/swoole-src@46ab345) (@matyhtf) + * Did not hook disabled functions (#4283) (@twose) + + Test + --- + * Added Cygwin build (#4222) (@sy-records) + * Added alpine 3.13 and 3.14 into building test (#4309) (@limingxinleo) @@ -94,6 +111,7 @@ + @@ -377,6 +395,8 @@ + + @@ -922,6 +942,16 @@ + + + + + + + + + + @@ -936,6 +966,9 @@ + + + @@ -1060,6 +1093,7 @@ + @@ -1099,6 +1133,8 @@ + + @@ -1389,6 +1425,7 @@ + @@ -1415,6 +1452,7 @@ + @@ -1482,11 +1520,13 @@ + + @@ -1667,6 +1707,8 @@ + + @@ -1826,7 +1868,9 @@ - + + + @@ -1897,7 +1941,6 @@ - @@ -1937,6 +1980,7 @@ + @@ -2003,6 +2047,8 @@ + + @@ -2015,6 +2061,7 @@ + diff --git a/src/core/error.cc b/src/core/error.cc index 70885dee8a5..19be32b6085 100644 --- a/src/core/error.cc +++ b/src/core/error.cc @@ -59,6 +59,10 @@ const char *swoole_strerror(int code) { return "DNS Lookup resolve failed"; case SW_ERROR_DNSLOOKUP_RESOLVE_TIMEOUT: return "DNS Lookup resolve timeout"; + case SW_ERROR_DNSLOOKUP_UNSUPPORTED: + return "DNS Lookup unsupported"; + case SW_ERROR_DNSLOOKUP_NO_SERVER: + return "DNS Lookup no server"; case SW_ERROR_BAD_IPV6_ADDRESS: return "Bad ipv6 address"; case SW_ERROR_UNREGISTERED_SIGNAL: diff --git a/tests/swoole_websocket_server/onDisconnct.phpt b/tests/swoole_websocket_server/onDisconnct.phpt index 69a20a1d26a..c13642de141 100644 --- a/tests/swoole_websocket_server/onDisconnct.phpt +++ b/tests/swoole_websocket_server/onDisconnct.phpt @@ -63,4 +63,3 @@ connect 2 open 2 close 2 done! - From 70b2664cd0436ef24f408945d62514551194f768 Mon Sep 17 00:00:00 2001 From: twosee Date: Mon, 19 Jul 2021 18:04:21 +0800 Subject: [PATCH 189/936] Fix memory error on shutdown (PHP-8.1) (#4325) Ref of function_name was held by zend_fcall_info_init(). --- ext-src/php_swoole.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index 54ef17cee85..db467313060 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -306,7 +306,6 @@ void php_swoole_register_shutdown_function(const char *function) { zend_fcall_info_init( &function_name, 0, &shutdown_function_entry.fci, &shutdown_function_entry.fci_cache, NULL, NULL); register_user_shutdown_function(Z_STRVAL(function_name), Z_STRLEN(function_name), &shutdown_function_entry); - zval_ptr_dtor(&function_name); #else zval *function_name; #if PHP_VERSION_ID >= 80000 From 029f174a1c218d220343713bb8994ff50f950eb9 Mon Sep 17 00:00:00 2001 From: Bruce Dou Date: Wed, 21 Jul 2021 12:27:43 +0100 Subject: [PATCH 190/936] Support trace log at make.sh (#4332) --- make.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/make.sh b/make.sh index 54e64931cf6..3aea7d6d79a 100755 --- a/make.sh +++ b/make.sh @@ -62,6 +62,7 @@ if [ "$1" = "help" ] ;then echo "./make.sh install-module" echo "./make.sh clean" echo "./make.sh debug" + echo "./make.sh trace" echo "./make.sh library [dev]" echo "./make.sh" exit 0 @@ -70,6 +71,8 @@ fi phpize if [ "$1" = "debug" ] ;then ./configure ${COMPILE_PARAMS} --enable-debug-log +elif [ "$1" = "trace" ] ;then + ./configure ${COMPILE_PARAMS} --enable-trace-log else ./configure ${COMPILE_PARAMS} fi From a034cbc06933a893cc5964f2125f0c7bfdb568e0 Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Tue, 27 Jul 2021 03:18:24 +0200 Subject: [PATCH 191/936] Fix not serializable classes for 8.1.0beta1 (#4335) --- ext-src/php_swoole_private.h | 11 ++++++++--- ext-src/swoole_atomic.cc | 4 ++-- ext-src/swoole_channel_coro.cc | 2 +- ext-src/swoole_client.cc | 2 +- ext-src/swoole_client_coro.cc | 2 +- ext-src/swoole_coroutine_scheduler.cc | 2 +- ext-src/swoole_http2_client_coro.cc | 6 +++--- ext-src/swoole_http_client_coro.cc | 2 +- ext-src/swoole_http_request.cc | 2 +- ext-src/swoole_http_response.cc | 2 +- ext-src/swoole_http_server.cc | 2 +- ext-src/swoole_http_server_coro.cc | 2 +- ext-src/swoole_lock.cc | 2 +- ext-src/swoole_mysql_coro.cc | 6 +++--- ext-src/swoole_process.cc | 2 +- ext-src/swoole_process_pool.cc | 2 +- ext-src/swoole_redis_coro.cc | 2 +- ext-src/swoole_redis_server.cc | 2 +- ext-src/swoole_server.cc | 6 +++--- ext-src/swoole_server_port.cc | 2 +- ext-src/swoole_socket_coro.cc | 2 +- ext-src/swoole_table.cc | 2 +- ext-src/swoole_websocket_server.cc | 2 +- thirdparty/php/curl/interface.cc | 2 +- thirdparty/php/curl/multi.cc | 4 ++-- 25 files changed, 40 insertions(+), 35 deletions(-) diff --git a/ext-src/php_swoole_private.h b/ext-src/php_swoole_private.h index c6af140254c..b16ec0fb219 100644 --- a/ext-src/php_swoole_private.h +++ b/ext-src/php_swoole_private.h @@ -634,9 +634,14 @@ static sw_inline void add_assoc_ulong_safe(zval *arg, const char *key, zend_ulon } \ } while (0) -#define SW_SET_CLASS_SERIALIZABLE(module, _serialize, _unserialize) \ - module##_ce->serialize = _serialize; \ - module##_ce->unserialize = _unserialize +#if PHP_VERSION_ID < 80100 +#define SW_SET_CLASS_NOT_SERIALIZABLE(module) \ + module##_ce->serialize = zend_class_serialize_deny; \ + module##_ce->unserialize = zend_class_unserialize_deny; +#else +#define SW_SET_CLASS_NOT_SERIALIZABLE(module) \ + module##_ce->ce_flags |= ZEND_ACC_NOT_SERIALIZABLE; +#endif #define sw_zend_class_clone_deny NULL #define SW_SET_CLASS_CLONEABLE(module, _clone_obj) module##_handlers.clone_obj = _clone_obj diff --git a/ext-src/swoole_atomic.cc b/ext-src/swoole_atomic.cc index ad6be3ec385..54bcf1f43ca 100644 --- a/ext-src/swoole_atomic.cc +++ b/ext-src/swoole_atomic.cc @@ -244,7 +244,7 @@ static const zend_function_entry swoole_atomic_long_methods[] = void php_swoole_atomic_minit(int module_number) { SW_INIT_CLASS_ENTRY(swoole_atomic, "Swoole\\Atomic", "swoole_atomic", nullptr, swoole_atomic_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_atomic, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_atomic); SW_SET_CLASS_CLONEABLE(swoole_atomic, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_atomic, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT( @@ -252,7 +252,7 @@ void php_swoole_atomic_minit(int module_number) { SW_INIT_CLASS_ENTRY( swoole_atomic_long, "Swoole\\Atomic\\Long", "swoole_atomic_long", nullptr, swoole_atomic_long_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_atomic_long, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_atomic_long); SW_SET_CLASS_CLONEABLE(swoole_atomic_long, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_atomic_long, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT(swoole_atomic_long, diff --git a/ext-src/swoole_channel_coro.cc b/ext-src/swoole_channel_coro.cc index 8c5ebee4c2b..28f7165aada 100644 --- a/ext-src/swoole_channel_coro.cc +++ b/ext-src/swoole_channel_coro.cc @@ -120,7 +120,7 @@ static zend_object *php_swoole_channel_coro_create_object(zend_class_entry *ce) void php_swoole_channel_coro_minit(int module_number) { SW_INIT_CLASS_ENTRY( swoole_channel_coro, "Swoole\\Coroutine\\Channel", nullptr, "Co\\Channel", swoole_channel_coro_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_channel_coro, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_channel_coro); SW_SET_CLASS_CLONEABLE(swoole_channel_coro, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_channel_coro, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT(swoole_channel_coro, diff --git a/ext-src/swoole_client.cc b/ext-src/swoole_client.cc index 21e8e7c4ff7..ff414733b88 100644 --- a/ext-src/swoole_client.cc +++ b/ext-src/swoole_client.cc @@ -240,7 +240,7 @@ static const zend_function_entry swoole_client_methods[] = void php_swoole_client_minit(int module_number) { SW_INIT_CLASS_ENTRY(swoole_client, "Swoole\\Client", "swoole_client", nullptr, swoole_client_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_client, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_client); SW_SET_CLASS_CLONEABLE(swoole_client, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_client, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT( diff --git a/ext-src/swoole_client_coro.cc b/ext-src/swoole_client_coro.cc index 45746a42bcf..312cda9f17b 100644 --- a/ext-src/swoole_client_coro.cc +++ b/ext-src/swoole_client_coro.cc @@ -169,7 +169,7 @@ static zend_object *php_swoole_client_coro_create_object(zend_class_entry *ce) { void php_swoole_client_coro_minit(int module_number) { SW_INIT_CLASS_ENTRY( swoole_client_coro, "Swoole\\Coroutine\\Client", nullptr, "Co\\Client", swoole_client_coro_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_client_coro, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_client_coro); SW_SET_CLASS_CLONEABLE(swoole_client_coro, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_client_coro, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT( diff --git a/ext-src/swoole_coroutine_scheduler.cc b/ext-src/swoole_coroutine_scheduler.cc index e39a9cf74fd..f735fce1b8d 100644 --- a/ext-src/swoole_coroutine_scheduler.cc +++ b/ext-src/swoole_coroutine_scheduler.cc @@ -111,7 +111,7 @@ void php_swoole_coroutine_scheduler_minit(int module_number) { nullptr, "Co\\Scheduler", swoole_coroutine_scheduler_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_coroutine_scheduler, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_coroutine_scheduler); SW_SET_CLASS_CLONEABLE(swoole_coroutine_scheduler, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_coroutine_scheduler, sw_zend_class_unset_property_deny); SW_SET_CLASS_CREATE_WITH_ITS_OWN_HANDLERS(swoole_coroutine_scheduler); diff --git a/ext-src/swoole_http2_client_coro.cc b/ext-src/swoole_http2_client_coro.cc index 8417c729ee5..7a3b3dc934c 100644 --- a/ext-src/swoole_http2_client_coro.cc +++ b/ext-src/swoole_http2_client_coro.cc @@ -317,7 +317,7 @@ void php_swoole_http2_client_coro_minit(int module_number) { nullptr, "Co\\Http2\\Client", swoole_http2_client_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_http2_client_coro, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_http2_client_coro); SW_SET_CLASS_CLONEABLE(swoole_http2_client_coro, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_http2_client_coro, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT(swoole_http2_client_coro, @@ -334,13 +334,13 @@ void php_swoole_http2_client_coro_minit(int module_number) { swoole_exception); SW_INIT_CLASS_ENTRY(swoole_http2_request, "Swoole\\Http2\\Request", "swoole_http2_request", nullptr, nullptr); - SW_SET_CLASS_SERIALIZABLE(swoole_http2_request, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_http2_request); SW_SET_CLASS_CLONEABLE(swoole_http2_request, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_http2_request, sw_zend_class_unset_property_deny); SW_SET_CLASS_CREATE_WITH_ITS_OWN_HANDLERS(swoole_http2_request); SW_INIT_CLASS_ENTRY(swoole_http2_response, "Swoole\\Http2\\Response", "swoole_http2_response", nullptr, nullptr); - SW_SET_CLASS_SERIALIZABLE(swoole_http2_response, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_http2_response); SW_SET_CLASS_CLONEABLE(swoole_http2_response, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_http2_response, sw_zend_class_unset_property_deny); SW_SET_CLASS_CREATE_WITH_ITS_OWN_HANDLERS(swoole_http2_response); diff --git a/ext-src/swoole_http_client_coro.cc b/ext-src/swoole_http_client_coro.cc index 34c2bfcca9c..cf7c7fa825e 100644 --- a/ext-src/swoole_http_client_coro.cc +++ b/ext-src/swoole_http_client_coro.cc @@ -1712,7 +1712,7 @@ void php_swoole_http_client_coro_minit(int module_number) { nullptr, "Co\\Http\\Client", swoole_http_client_coro_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_http_client_coro, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_http_client_coro); SW_SET_CLASS_CLONEABLE(swoole_http_client_coro, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_http_client_coro, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT(swoole_http_client_coro, diff --git a/ext-src/swoole_http_request.cc b/ext-src/swoole_http_request.cc index 4f4ca4e3f64..218bfcc175d 100644 --- a/ext-src/swoole_http_request.cc +++ b/ext-src/swoole_http_request.cc @@ -225,7 +225,7 @@ const zend_function_entry swoole_http_request_methods[] = void php_swoole_http_request_minit(int module_number) { SW_INIT_CLASS_ENTRY( swoole_http_request, "Swoole\\Http\\Request", "swoole_http_request", nullptr, swoole_http_request_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_http_request, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_http_request); SW_SET_CLASS_CLONEABLE(swoole_http_request, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_http_request, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT(swoole_http_request, diff --git a/ext-src/swoole_http_response.cc b/ext-src/swoole_http_response.cc index f8edb299b2b..a908e5d4f35 100644 --- a/ext-src/swoole_http_response.cc +++ b/ext-src/swoole_http_response.cc @@ -263,7 +263,7 @@ const zend_function_entry swoole_http_response_methods[] = void php_swoole_http_response_minit(int module_number) { SW_INIT_CLASS_ENTRY( swoole_http_response, "Swoole\\Http\\Response", "swoole_http_response", nullptr, swoole_http_response_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_http_response, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_http_response); SW_SET_CLASS_CLONEABLE(swoole_http_response, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_http_response, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT(swoole_http_response, diff --git a/ext-src/swoole_http_server.cc b/ext-src/swoole_http_server.cc index 0d71470e924..730667782da 100644 --- a/ext-src/swoole_http_server.cc +++ b/ext-src/swoole_http_server.cc @@ -147,7 +147,7 @@ int php_swoole_http_server_onReceive(Server *serv, RecvData *req) { void php_swoole_http_server_minit(int module_number) { SW_INIT_CLASS_ENTRY_EX( swoole_http_server, "Swoole\\Http\\Server", "swoole_http_server", nullptr, nullptr, swoole_server); - SW_SET_CLASS_SERIALIZABLE(swoole_http_server, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_http_server); SW_SET_CLASS_CLONEABLE(swoole_http_server, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_http_server, sw_zend_class_unset_property_deny); } diff --git a/ext-src/swoole_http_server_coro.cc b/ext-src/swoole_http_server_coro.cc index 78a63811127..7d7edf834a9 100644 --- a/ext-src/swoole_http_server_coro.cc +++ b/ext-src/swoole_http_server_coro.cc @@ -302,7 +302,7 @@ void php_swoole_http_server_coro_minit(int module_number) { nullptr, "Co\\Http\\Server", swoole_http_server_coro_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_http_server_coro, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_http_server_coro); SW_SET_CLASS_CLONEABLE(swoole_http_server_coro, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_http_server_coro, sw_zend_class_unset_property_deny); SW_SET_CLASS_CREATE_WITH_ITS_OWN_HANDLERS(swoole_http_server_coro); diff --git a/ext-src/swoole_lock.cc b/ext-src/swoole_lock.cc index 3420dda1de0..075f624c899 100644 --- a/ext-src/swoole_lock.cc +++ b/ext-src/swoole_lock.cc @@ -113,7 +113,7 @@ static const zend_function_entry swoole_lock_methods[] = void php_swoole_lock_minit(int module_number) { SW_INIT_CLASS_ENTRY(swoole_lock, "Swoole\\Lock", "swoole_lock", nullptr, swoole_lock_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_lock, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_lock); SW_SET_CLASS_CLONEABLE(swoole_lock, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_lock, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT( diff --git a/ext-src/swoole_mysql_coro.cc b/ext-src/swoole_mysql_coro.cc index ff1b1159480..574e9c028b6 100644 --- a/ext-src/swoole_mysql_coro.cc +++ b/ext-src/swoole_mysql_coro.cc @@ -1690,7 +1690,7 @@ static sw_inline void swoole_mysql_coro_sync_execute_result_properties(zval *zob void php_swoole_mysql_coro_minit(int module_number) { SW_INIT_CLASS_ENTRY(swoole_mysql_coro, "Swoole\\Coroutine\\MySQL", nullptr, "Co\\MySQL", swoole_mysql_coro_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_mysql_coro, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_mysql_coro); SW_SET_CLASS_CLONEABLE(swoole_mysql_coro, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_mysql_coro, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT( @@ -1701,7 +1701,7 @@ void php_swoole_mysql_coro_minit(int module_number) { nullptr, "Co\\MySQL\\Statement", swoole_mysql_coro_statement_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_mysql_coro_statement, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_mysql_coro_statement); SW_SET_CLASS_CLONEABLE(swoole_mysql_coro_statement, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_mysql_coro_statement, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT(swoole_mysql_coro_statement, @@ -1716,7 +1716,7 @@ void php_swoole_mysql_coro_minit(int module_number) { "Co\\MySQL\\Exception", nullptr, swoole_exception); - SW_SET_CLASS_SERIALIZABLE(swoole_mysql_coro_exception, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_mysql_coro_exception); SW_SET_CLASS_CLONEABLE(swoole_mysql_coro_exception, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_mysql_coro_exception, sw_zend_class_unset_property_deny); SW_SET_CLASS_CREATE_WITH_ITS_OWN_HANDLERS(swoole_mysql_coro_exception); diff --git a/ext-src/swoole_process.cc b/ext-src/swoole_process.cc index 91ee3695173..46a8298ebc3 100644 --- a/ext-src/swoole_process.cc +++ b/ext-src/swoole_process.cc @@ -258,7 +258,7 @@ static const zend_function_entry swoole_process_methods[] = void php_swoole_process_minit(int module_number) { SW_INIT_CLASS_ENTRY(swoole_process, "Swoole\\Process", "swoole_process", nullptr, swoole_process_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_process, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_process); SW_SET_CLASS_CLONEABLE(swoole_process, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_process, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT( diff --git a/ext-src/swoole_process_pool.cc b/ext-src/swoole_process_pool.cc index eda655823cf..c13a7d3ad6d 100644 --- a/ext-src/swoole_process_pool.cc +++ b/ext-src/swoole_process_pool.cc @@ -189,7 +189,7 @@ static const zend_function_entry swoole_process_pool_methods[] = void php_swoole_process_pool_minit(int module_number) { SW_INIT_CLASS_ENTRY( swoole_process_pool, "Swoole\\Process\\Pool", "swoole_process_pool", nullptr, swoole_process_pool_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_process_pool, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_process_pool); SW_SET_CLASS_CLONEABLE(swoole_process_pool, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_process_pool, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT(swoole_process_pool, diff --git a/ext-src/swoole_redis_coro.cc b/ext-src/swoole_redis_coro.cc index 174201246c8..343dad10531 100644 --- a/ext-src/swoole_redis_coro.cc +++ b/ext-src/swoole_redis_coro.cc @@ -1895,7 +1895,7 @@ static const zend_function_entry swoole_redis_coro_methods[] = void php_swoole_redis_coro_minit(int module_number) { SW_INIT_CLASS_ENTRY(swoole_redis_coro, "Swoole\\Coroutine\\Redis", nullptr, "Co\\Redis", swoole_redis_coro_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_redis_coro, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_redis_coro); SW_SET_CLASS_CLONEABLE(swoole_redis_coro, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_redis_coro, sw_zend_class_unset_property_deny); SW_SET_CLASS_CREATE_WITH_ITS_OWN_HANDLERS(swoole_redis_coro); diff --git a/ext-src/swoole_redis_server.cc b/ext-src/swoole_redis_server.cc index eb144ef9481..69f1dd1e062 100644 --- a/ext-src/swoole_redis_server.cc +++ b/ext-src/swoole_redis_server.cc @@ -71,7 +71,7 @@ void php_swoole_redis_server_minit(int module_number) { nullptr, swoole_redis_server_methods, swoole_server); - SW_SET_CLASS_SERIALIZABLE(swoole_redis_server, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_redis_server); SW_SET_CLASS_CLONEABLE(swoole_redis_server, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_redis_server, sw_zend_class_unset_property_deny); diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 3824e860e4d..3ab5a037bd4 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -608,7 +608,7 @@ static const zend_function_entry swoole_server_task_methods[] = void php_swoole_server_minit(int module_number) { // ---------------------------------------Server------------------------------------- SW_INIT_CLASS_ENTRY(swoole_server, "Swoole\\Server", "swoole_server", nullptr, swoole_server_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_server, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_server); SW_SET_CLASS_CLONEABLE(swoole_server, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_server, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT(swoole_server, server_create_object, server_free_object, ServerObject, std); @@ -623,7 +623,7 @@ void php_swoole_server_minit(int module_number) { SW_INIT_CLASS_ENTRY( swoole_server_task, "Swoole\\Server\\Task", "swoole_server_task", nullptr, swoole_server_task_methods); swoole_server_task_ce->ce_flags |= ZEND_ACC_FINAL; - SW_SET_CLASS_SERIALIZABLE(swoole_server_task, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_server_task); SW_SET_CLASS_CLONEABLE(swoole_server_task, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_server_task, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT(swoole_server_task, @@ -673,7 +673,7 @@ void php_swoole_server_minit(int module_number) { "swoole_connection_iterator", nullptr, swoole_connection_iterator_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_connection_iterator, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_connection_iterator); SW_SET_CLASS_CLONEABLE(swoole_connection_iterator, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_connection_iterator, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT(swoole_connection_iterator, diff --git a/ext-src/swoole_server_port.cc b/ext-src/swoole_server_port.cc index d657150ac9e..b22ab7847fb 100644 --- a/ext-src/swoole_server_port.cc +++ b/ext-src/swoole_server_port.cc @@ -166,7 +166,7 @@ const zend_function_entry swoole_server_port_methods[] = void php_swoole_server_port_minit(int module_number) { SW_INIT_CLASS_ENTRY( swoole_server_port, "Swoole\\Server\\Port", "swoole_server_port", nullptr, swoole_server_port_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_server_port, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_server_port); SW_SET_CLASS_CLONEABLE(swoole_server_port, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_server_port, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT(swoole_server_port, diff --git a/ext-src/swoole_socket_coro.cc b/ext-src/swoole_socket_coro.cc index 4054781e801..e3799f45665 100644 --- a/ext-src/swoole_socket_coro.cc +++ b/ext-src/swoole_socket_coro.cc @@ -803,7 +803,7 @@ static void swoole_socket_coro_register_constants(int module_number) { void php_swoole_socket_coro_minit(int module_number) { SW_INIT_CLASS_ENTRY( swoole_socket_coro, "Swoole\\Coroutine\\Socket", nullptr, "Co\\Socket", swoole_socket_coro_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_socket_coro, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_socket_coro); SW_SET_CLASS_CLONEABLE(swoole_socket_coro, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_socket_coro, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT(swoole_socket_coro, diff --git a/ext-src/swoole_table.cc b/ext-src/swoole_table.cc index eb3949594cb..9effa638282 100644 --- a/ext-src/swoole_table.cc +++ b/ext-src/swoole_table.cc @@ -220,7 +220,7 @@ static const zend_function_entry swoole_table_methods[] = void php_swoole_table_minit(int module_number) { SW_INIT_CLASS_ENTRY(swoole_table, "Swoole\\Table", "swoole_table", nullptr, swoole_table_methods); - SW_SET_CLASS_SERIALIZABLE(swoole_table, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_table); SW_SET_CLASS_CLONEABLE(swoole_table, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_table, sw_zend_class_unset_property_deny); SW_SET_CLASS_CUSTOM_OBJECT( diff --git a/ext-src/swoole_websocket_server.cc b/ext-src/swoole_websocket_server.cc index 55435e9334f..6cf7671631a 100644 --- a/ext-src/swoole_websocket_server.cc +++ b/ext-src/swoole_websocket_server.cc @@ -628,7 +628,7 @@ void php_swoole_websocket_server_minit(int module_number) { nullptr, swoole_websocket_server_methods, swoole_http_server); - SW_SET_CLASS_SERIALIZABLE(swoole_websocket_server, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_websocket_server); SW_SET_CLASS_CLONEABLE(swoole_websocket_server, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_websocket_server, sw_zend_class_unset_property_deny); diff --git a/thirdparty/php/curl/interface.cc b/thirdparty/php/curl/interface.cc index b5817fd2d3c..8db261760e3 100644 --- a/thirdparty/php/curl/interface.cc +++ b/thirdparty/php/curl/interface.cc @@ -315,7 +315,7 @@ void swoole_native_curl_minit(int module_number) { #if PHP_VERSION_ID >= 80000 SW_INIT_CLASS_ENTRY( swoole_coroutine_curl_handle, "Swoole\\Coroutine\\Curl\\Handle", nullptr, "Co\\Curl\\Handle", nullptr); - SW_SET_CLASS_SERIALIZABLE(swoole_coroutine_curl_handle, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE(swoole_coroutine_curl_handle); SW_SET_CLASS_CUSTOM_OBJECT(swoole_coroutine_curl_handle, curl_create_object, curl_free_obj, php_curl, std); swoole_coroutine_curl_handle_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NO_DYNAMIC_PROPERTIES; swoole_coroutine_curl_handle_handlers.get_gc = curl_get_gc; diff --git a/thirdparty/php/curl/multi.cc b/thirdparty/php/curl/multi.cc index 6561af5b989..cbca9c515b7 100644 --- a/thirdparty/php/curl/multi.cc +++ b/thirdparty/php/curl/multi.cc @@ -694,8 +694,8 @@ void curl_multi_register_class(const zend_function_entry *method_entries) { nullptr, "Co\\Curl\\MultiHandle", nullptr); - SW_SET_CLASS_SERIALIZABLE( - swoole_coroutine_curl_multi_handle, zend_class_serialize_deny, zend_class_unserialize_deny); + SW_SET_CLASS_NOT_SERIALIZABLE( + swoole_coroutine_curl_multi_handle); SW_SET_CLASS_CUSTOM_OBJECT( swoole_coroutine_curl_multi_handle, curl_multi_create_object, curl_multi_free_obj, php_curlm, std); swoole_coroutine_curl_multi_handle_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NO_DYNAMIC_PROPERTIES; From 067f594485bad723a26f1eeb23731ec7e94dcf5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Thu, 29 Jul 2021 13:30:48 +0800 Subject: [PATCH 192/936] Added --enable-cares build for test (#4342) --- .github/workflows/ext.yml | 18 +++++++++++++++--- travis/docker-compile.sh | 2 -- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ext.yml b/.github/workflows/ext.yml index 75b88982311..2280cfc200c 100644 --- a/.github/workflows/ext.yml +++ b/.github/workflows/ext.yml @@ -8,7 +8,7 @@ jobs: steps: - uses: actions/checkout@v1 - name: install-deps - run: sudo apt update -y && sudo apt install -y libcurl4-openssl-dev php-curl + run: sudo apt update -y && sudo apt install -y libcurl4-openssl-dev php-curl libc-ares-dev - name: phpize run: phpize - name: build1 @@ -32,13 +32,17 @@ jobs: run: ./configure --enable-sockets --enable-mysqlnd --enable-http2 --enable-swoole-curl --enable-swoole-json --enable-openssl --enable-debug-log && make clean && make -j$(sysctl -n hw.ncpu) + - name: build8 + run: ./configure --enable-sockets --enable-mysqlnd --enable-http2 --enable-swoole-curl --enable-swoole-json + --enable-openssl --enable-cares --enable-debug-log && + make clean && make -j$(sysctl -n hw.ncpu) build-ubuntu-old: runs-on: ubuntu-16.04 steps: - uses: actions/checkout@v1 - name: install-deps - run: sudo apt update -y && sudo apt install -y libcurl4-openssl-dev php-curl + run: sudo apt update -y && sudo apt install -y libcurl4-openssl-dev php-curl libc-ares-dev - name: phpize run: phpize - name: build1 @@ -59,12 +63,16 @@ jobs: run: ./configure --enable-sockets --enable-mysqlnd --enable-http2 --enable-swoole-curl --enable-swoole-json --enable-openssl --enable-debug-log && make clean && make -j$(sysctl -n hw.ncpu) + - name: build7 + run: ./configure --enable-sockets --enable-mysqlnd --enable-http2 --enable-swoole-curl --enable-swoole-json + --enable-openssl --enable-cares --enable-debug-log && + make clean && make -j$(sysctl -n hw.ncpu) build-macos-latest: runs-on: macos-latest steps: - name: install dependencies - run: brew install openssl && brew link openssl && brew install curl && brew link curl + run: brew install openssl && brew link openssl && brew install curl && brew link curl && brew install c-ares && brew link c-ares - uses: actions/checkout@v1 - name: phpize run: phpize @@ -87,6 +95,10 @@ jobs: run: ./configure --enable-sockets --enable-mysqlnd --enable-http2 --enable-swoole-curl --enable-swoole-json --enable-openssl --with-openssl-dir=/usr/local/opt/openssl@1.1 --enable-debug-log && make clean && make -j$(sysctl -n hw.ncpu) + - name: build7 + run: ./configure --enable-sockets --enable-mysqlnd --enable-http2 --enable-swoole-curl --enable-swoole-json + --enable-openssl --with-openssl-dir=/usr/local/opt/openssl@1.1 --enable-cares --enable-debug-log && + make clean && make -j$(sysctl -n hw.ncpu) build-alpine-latest: runs-on: ubuntu-latest diff --git a/travis/docker-compile.sh b/travis/docker-compile.sh index 523a66eaa95..54ebf6d36a8 100755 --- a/travis/docker-compile.sh +++ b/travis/docker-compile.sh @@ -9,8 +9,6 @@ fi #-----------compile------------ #-------print error only------- -apt-get update -y -apt-get install -y libcurl4-openssl-dev libc-ares-dev cd "${__DIR__}" && cd ../ && \ ./clear.sh > /dev/null && \ phpize --clean > /dev/null && \ From 4b9839d06c2c44063f1f1f98a407507762e71c80 Mon Sep 17 00:00:00 2001 From: zmyWL <86939621+zmyWL@users.noreply.github.com> Date: Thu, 29 Jul 2021 13:36:29 +0800 Subject: [PATCH 193/936] Support query /etc/hosts (#4341) * Support query /etc/hosts * Change NULL to nullptr --- .github/workflows/lib.yml | 3 +- core-tests/src/network/dns.cpp | 8 + include/swoole_coroutine_socket.h | 1 + include/swoole_socket.h | 1 + src/network/dns.cc | 161 +++++++++++++++++- .../dnslookup_query_hosts.phpt | 18 ++ 6 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 tests/swoole_coroutine/dnslookup_query_hosts.phpt diff --git a/.github/workflows/lib.yml b/.github/workflows/lib.yml index 00d551a63b1..71afc15a01c 100644 --- a/.github/workflows/lib.yml +++ b/.github/workflows/lib.yml @@ -34,7 +34,8 @@ jobs: sudo make install - name: make test - run: cd core-tests && ./run.sh + run: + cd core-tests && ./run.sh - name: run coverage shell: bash diff --git a/core-tests/src/network/dns.cpp b/core-tests/src/network/dns.cpp index 3d7ede93fec..91f13491481 100644 --- a/core-tests/src/network/dns.cpp +++ b/core-tests/src/network/dns.cpp @@ -97,3 +97,11 @@ TEST(dns, load_resolv_conf) { ASSERT_FALSE(dns_server.first.empty()); ASSERT_NE(dns_server.second, 0); } + +TEST(dns, gethosts) { + std::string ip = swoole::coroutine::get_ip_by_hosts("localhost"); + ASSERT_EQ(ip, "127.0.0.1"); + + ip = swoole::coroutine::get_ip_by_hosts("non.exist.com"); + ASSERT_EQ(ip, ""); +} diff --git a/include/swoole_coroutine_socket.h b/include/swoole_coroutine_socket.h index e02236d2415..f32a62d35a1 100644 --- a/include/swoole_coroutine_socket.h +++ b/include/swoole_coroutine_socket.h @@ -596,6 +596,7 @@ std::vector dns_lookup_impl_with_socket(const char *domain, int fam #ifdef SW_USE_CARES std::vector dns_lookup_impl_with_cares(const char *domain, int family, double timeout); #endif +std::string get_ip_by_hosts(std::string domain); //------------------------------------------------------------------------------- } // namespace coroutine } // namespace swoole diff --git a/include/swoole_socket.h b/include/swoole_socket.h index c50c7187ef1..443c7c12edf 100644 --- a/include/swoole_socket.h +++ b/include/swoole_socket.h @@ -595,3 +595,4 @@ network::Socket *make_server_socket(enum swSocket_type socket_type, int backlog = SW_BACKLOG); bool verify_ip(int __af, const std::string &str); } // namespace swoole + diff --git a/src/network/dns.cc b/src/network/dns.cc index d234bee6d5d..85f7d3b821f 100644 --- a/src/network/dns.cc +++ b/src/network/dns.cc @@ -16,11 +16,14 @@ #include "swoole.h" #include "swoole_coroutine_socket.h" +#include "swoole_util.h" #include #include #include +#define SW_PATH_HOSTS "/etc/hosts" + #ifdef SW_USE_CARES #include #endif @@ -103,6 +106,162 @@ static int domain_encode(const char *src, int n, char *dest); static void domain_decode(char *str); static std::string parse_ip_address(void *vaddr, int type); +static int read_line(FILE *fp, char **buf, size_t *bufsize) { + char *newbuf; + size_t offset = 0; + size_t len; + + if (*buf == nullptr) { + *buf = (char *) malloc(128); + if (!*buf) { + return SW_ERR; + } + *bufsize = 128; + } + + for (;;) { + int bytestoread = *bufsize - offset; + if (!fgets(*buf + offset, bytestoread, fp)) { + return SW_ERR; + } + + len = offset + strlen(*buf + offset); + if ((*buf)[len - 1] == '\n') { + (*buf)[len - 1] = 0; + break; + } + offset = len; + if (len < *bufsize - 1) { + continue; + } + newbuf = (char *) realloc(*buf, *bufsize * 2); + if (!newbuf) { + free(*buf); + *buf = nullptr; + return SW_ERR; + } + *buf = newbuf; + *bufsize *= 2; + } + + return SW_OK; +} + +static std::pair get_hostent(FILE *fp) { + char *line = nullptr, *p, *q; + char *txtaddr, *txthost, *txtalias; + int status; + size_t linesize, naliases; + + std::pair result{}; + + while ((status = read_line(fp, &line, &linesize)) == SW_OK) { + p = line; + while (*p && (*p != '#')) { + p++; + } + *p = '\0'; + + q = p - 1; + while ((q >= line) && isspace(*q)) { + q--; + } + *++q = '\0'; + + p = line; + while (*p && isspace(*q)) { + q--; + } + if (!*p) { + continue; + } + + txtaddr = p; + + while (*p && !isspace(*p)) { + p++; + } + if (!*p) { + continue; + } + + *p = '\0'; + + p++; + while (*p && isspace(*p)) { + p++; + } + if (!*p) { + continue; + } + + txthost = p; + + while (*p && !isspace(*p)) { + p++; + } + + txtalias = nullptr; + if (*p) { + q = p + 1; + while (*q && isspace(*q)) { + q++; + } + if (*q) { + txtalias = q; + } + } + + *p = '\0'; + + naliases = 0; + if (txtalias) { + p = txtalias; + while (*p) { + while (*p && !isspace(*p)) { + p++; + } + while (*p && isspace(*p)) { + p++; + } + naliases++; + } + } + + result.first = txthost; + result.second = txtaddr; + + free(line); + + return result; + } + + if (line) free(line); + + return result; +} + +std::string get_ip_by_hosts(std::string domain) { + std::unordered_map _map; + auto fp = fopen(SW_PATH_HOSTS, "r"); + if (fp == nullptr) { + return ""; + } + ON_SCOPE_EXIT { + fclose(fp); + }; + while (1) { + auto result = get_hostent(fp); + if (result.first == "") { + break; + } + if (result.first == domain) { + return result.second; + } + } + return ""; +} + static std::string parse_ip_address(void *vaddr, int type) { auto addr = reinterpret_cast(vaddr); std::string ip_addr; @@ -199,7 +358,7 @@ std::vector dns_lookup_impl_with_socket(const char *domain, int fam auto ret = _sock.recv(packet, sizeof(packet) - 1); if (ret <= 0) { - swoole_set_last_error(_sock.errCode == ECANCELED ? SW_ERROR_CO_CANCELED: SW_ERROR_DNSLOOKUP_RESOLVE_FAILED); + swoole_set_last_error(_sock.errCode == ECANCELED ? SW_ERROR_CO_CANCELED : SW_ERROR_DNSLOOKUP_RESOLVE_FAILED); return result; } diff --git a/tests/swoole_coroutine/dnslookup_query_hosts.phpt b/tests/swoole_coroutine/dnslookup_query_hosts.phpt new file mode 100644 index 00000000000..3cadd8eb15a --- /dev/null +++ b/tests/swoole_coroutine/dnslookup_query_hosts.phpt @@ -0,0 +1,18 @@ +--TEST-- +swoole_coroutine: dnslookup query hosts +--SKIPIF-- + +--FILE-- + +--EXPECT-- From 85ef982d3f683d9557e0122cbdf11746ed52c8bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Fri, 30 Jul 2021 14:22:25 +0800 Subject: [PATCH 194/936] Update README (#4346) --- README-CN.md | 26 ++++++++++++++++++-------- README.md | 16 ++++++++++++++-- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/README-CN.md b/README-CN.md index 43bbf6f53a4..978b6309f7b 100644 --- a/README-CN.md +++ b/README-CN.md @@ -1,26 +1,36 @@ [English](./README.md) | 中文 -# Swoole +

+Swoole Logo +

-[![Latest Version](https://img.shields.io/github/release/swoole/swoole-src.svg)](https://github.com/swoole/swoole-src/releases) -[![License](https://img.shields.io/badge/license-apache2-blue.svg)](LICENSE) [![lib-swoole](https://github.com/swoole/swoole-src/workflows/lib-swoole/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Alib-swoole) [![ext-swoole](https://github.com/swoole/swoole-src/workflows/ext-swoole/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Aext-swoole) [![test-linux](https://github.com/swoole/swoole-src/workflows/test-linux/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Atest-linux) [![Coverity Scan Build Status](https://scan.coverity.com/projects/11654/badge.svg)](https://scan.coverity.com/projects/swoole-swoole-src) [![codecov](https://codecov.io/gh/swoole/swoole-src/branch/master/graph/badge.svg)](https://codecov.io/gh/swoole/swoole-src) -![](./mascot.png) - **Swoole是一个C++编写的基于异步事件驱动和协程的并行网络通信引擎,为PHP提供高性能网络编程支持** -## ✨事件驱动 +## ⚙️ 快速启动 + +你可以直接使用 [Docker](https://github.com/swoole/docker-swoole) 来执行Swoole的代码,例如: + +```bash +docker run --rm phpswoole/swoole "php --ri swoole" +``` + +具体的使用方式可以查看:[如何使用此镜像](https://github.com/swoole/docker-swoole#how-to-use-this-image) 。 + +或者你可以在Swoole官网提供的 [在线编程页面](https://www.swoole.com/coding) 运行你的代码以及官网提供的示例代码。 + +## ✨ 事件驱动 -Swoole中的网络请求处理是基于事件的,并且充分利用了底层的epoll / kqueue实现,使得为数百万个请求提供服务变得非常容易。 +Swoole中的网络请求处理是基于事件的,并且充分利用了底层的 epoll/kqueue 实现,使得为数百万个请求提供服务变得非常容易。 Swoole4使用全新的协程内核引擎,现在它拥有一个全职的开发团队,因此我们正在进入PHP历史上前所未有的时期,为性能的高速提升提供了独一无二的可能性。 -## ⚡️协程 +## ⚡️ 协程 Swoole4或更高版本拥有高可用性的内置协程,您可以使用完全同步的代码来实现异步性能,PHP代码没有任何额外的关键字,底层会自动进行协程调度。 diff --git a/README.md b/README.md index 386c9a7a1f2..b5ef90ae0b2 100644 --- a/README.md +++ b/README.md @@ -12,13 +12,25 @@ English | [中文](./README-CN.md) **Swoole is an event-driven asynchronous & coroutine-based concurrency networking communication engine with high performance written in C++ for PHP.** -## ✨Event-based +## ⚙️ Quick Start + +You can use [Docker](https://github.com/swoole/docker-swoole) directly to execute Swoole's code, e.g. + +```bash +docker run --rm phpswoole/swoole "php --ri swoole" +``` + +For details on how to use it, see: [How to Use This Image](https://github.com/swoole/docker-swoole#how-to-use-this-image). + +Or you can run your code and the sample code provided on the Swoole website at the [online coding page](https://www.swoole.com/coding). + +## ✨ Event-based The network layer in Swoole is event-based and takes full advantage of the underlying epoll/kqueue implementation, making it really easy to serve millions of requests. Swoole 4.x uses a brand new engine kernel and now it has a full-time developer team, so we are entering an unprecedented period in PHP history which offers a unique possibility for rapid evolution in performance. -## ⚡️Coroutine +## ⚡ Coroutine Swoole 4.x or later supports the built-in coroutine with high availability, and you can use fully synchronized code to implement asynchronous performance. PHP code without any additional keywords, the underlying automatic coroutine-scheduling. From deeefe31ccab1235b56f830019b1404ba361ee74 Mon Sep 17 00:00:00 2001 From: NathanFreeman <33935209+NathanFreeman@users.noreply.github.com> Date: Fri, 30 Jul 2021 14:24:19 +0800 Subject: [PATCH 195/936] Fix bug #4327 mkdir create failed on coroutines (#4337) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix bug #4327 * fix bug #4327 * fix bug #4327 * unit test * 代码格式 * 单元测试 * 修复无符号和有符号之间的比较 * unit test * unit test --- tests/swoole_runtime/file_hook/bug_4327.phpt | 56 ++++++++++++++++++++ thirdparty/php/streams/plain_wrapper.c | 7 ++- 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 tests/swoole_runtime/file_hook/bug_4327.phpt diff --git a/tests/swoole_runtime/file_hook/bug_4327.phpt b/tests/swoole_runtime/file_hook/bug_4327.phpt new file mode 100644 index 00000000000..7b4311f197e --- /dev/null +++ b/tests/swoole_runtime/file_hook/bug_4327.phpt @@ -0,0 +1,56 @@ +--TEST-- +mkdir failed when coroutines: bug #4372 +--SKIPIF-- + +--FILE-- + + +--EXPECT-- +SUCCESS +SUCCESS +SUCCESS +SUCCESS diff --git a/thirdparty/php/streams/plain_wrapper.c b/thirdparty/php/streams/plain_wrapper.c index de6257368b2..79ededbda75 100644 --- a/thirdparty/php/streams/plain_wrapper.c +++ b/thirdparty/php/streams/plain_wrapper.c @@ -1085,7 +1085,7 @@ static int php_plain_files_mkdir( if (p == buf) { ret = mkdir(dir, mode); - } else if (!(ret = mkdir(buf, mode))) { + } else if (!(ret = mkdir(buf, mode)) || EEXIST == errno) { if (!p) { p = buf; } @@ -1094,6 +1094,11 @@ static int php_plain_files_mkdir( if (*p == '\0') { *p = DEFAULT_SLASH; if ((*(p + 1) != '\0') && (ret = mkdir(buf, (mode_t) mode)) < 0) { + // parent directory already exists and try to create child directories. + if (EEXIST == errno && (int) strlen(buf) < dir_len) { + continue; + } + if (options & REPORT_ERRORS) { php_error_docref(NULL, E_WARNING, "%s", strerror(errno)); } From 7c0f7d7f1406b49bd3bebac728154a476c4d2dd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Fri, 30 Jul 2021 19:08:14 +0800 Subject: [PATCH 196/936] Update README (#4347) --- README-CN.md | 4 ++-- README.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README-CN.md b/README-CN.md index 978b6309f7b..a418d8decd6 100644 --- a/README-CN.md +++ b/README-CN.md @@ -14,7 +14,7 @@ ## ⚙️ 快速启动 -你可以直接使用 [Docker](https://github.com/swoole/docker-swoole) 来执行Swoole的代码,例如: +可以直接使用 [Docker](https://github.com/swoole/docker-swoole) 来执行Swoole的代码,例如: ```bash docker run --rm phpswoole/swoole "php --ri swoole" @@ -22,7 +22,7 @@ docker run --rm phpswoole/swoole "php --ri swoole" 具体的使用方式可以查看:[如何使用此镜像](https://github.com/swoole/docker-swoole#how-to-use-this-image) 。 -或者你可以在Swoole官网提供的 [在线编程页面](https://www.swoole.com/coding) 运行你的代码以及官网提供的示例代码。 +或者可以在Swoole官网提供的 [在线编程](https://www.swoole.com/coding) 页面运行代码以及官网提供的示例代码。 ## ✨ 事件驱动 diff --git a/README.md b/README.md index b5ef90ae0b2..145143df500 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ English | [中文](./README-CN.md) ## ⚙️ Quick Start -You can use [Docker](https://github.com/swoole/docker-swoole) directly to execute Swoole's code, e.g. +Run Swoole program by [Docker](https://github.com/swoole/docker-swoole) ```bash docker run --rm phpswoole/swoole "php --ri swoole" @@ -22,7 +22,7 @@ docker run --rm phpswoole/swoole "php --ri swoole" For details on how to use it, see: [How to Use This Image](https://github.com/swoole/docker-swoole#how-to-use-this-image). -Or you can run your code and the sample code provided on the Swoole website at the [online coding page](https://www.swoole.com/coding). +Or code and run the Swoole program on the official website of Swoole. [Coding Online](https://www.swoole.com/coding) ## ✨ Event-based From 7043d255e552d28c3dd4992a943009393395dbd1 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Mon, 2 Aug 2021 13:34:40 +0800 Subject: [PATCH 197/936] Added pretty_name_lambda core test --- core-tests/src/core/log.cpp | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/core-tests/src/core/log.cpp b/core-tests/src/core/log.cpp index 9d96c1acf5d..06c93351a44 100644 --- a/core-tests/src/core/log.cpp +++ b/core-tests/src/core/log.cpp @@ -130,15 +130,30 @@ void TestPrettyName::fun(bool strip, const char *expect_str) { ASSERT_STREQ(Logger::get_pretty_name(__PRETTY_FUNCTION__, strip).c_str(), expect_str); } -void test_pretty_name(bool strip, const char *expect_str) { +static void test_pretty_name(bool strip, const char *expect_str) { ASSERT_STREQ(Logger::get_pretty_name(__PRETTY_FUNCTION__, strip).c_str(), expect_str); } + +static void test_pretty_name_lambda(bool strip, const char *expect_str) { + auto fn = [](bool strip, const char *expect_str) { + ASSERT_STREQ(Logger::get_pretty_name(__PRETTY_FUNCTION__, strip).c_str(), expect_str); + }; + fn(strip, expect_str); +} + } // namespace TestA -void test_pretty_name(bool strip, const char *expect_str) { +static void test_pretty_name(bool strip, const char *expect_str) { ASSERT_STREQ(Logger::get_pretty_name(__PRETTY_FUNCTION__, strip).c_str(), expect_str); } +static void test_pretty_name_lambda(bool strip, const char *expect_str) { + auto fn = [](bool strip, const char *expect_str) { + ASSERT_STREQ(Logger::get_pretty_name(__PRETTY_FUNCTION__, strip).c_str(), expect_str); + }; + fn(strip, expect_str); +} + TEST(log, pretty_name) { TestA::TestPrettyName::fun(false, "TestA::TestPrettyName::fun"); TestA::test_pretty_name(false, "TestA::test_pretty_name"); @@ -148,3 +163,11 @@ TEST(log, pretty_name) { TestA::test_pretty_name(true, "test_pretty_name"); test_pretty_name(true, "test_pretty_name"); } + +TEST(log, pretty_name_lambda) { + TestA::test_pretty_name_lambda(true, "test_pretty_name_lambda"); + test_pretty_name_lambda(true, "test_pretty_name_lambda"); + + TestA::test_pretty_name_lambda(false, "TestA::test_pretty_name_lambda"); + test_pretty_name_lambda(false, "test_pretty_name_lambda"); +} From c57e7dd23458b1cf60b2497a68aeae4fc033b940 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Wed, 4 Aug 2021 10:38:35 +0800 Subject: [PATCH 198/936] Optimize naming (#4350) * Optimize naming * Added pretty_name_lambda core test * Optimize naming [2] * fix tests * Optimize naming * Optimize --- core-tests/include/test_server.h | 2 +- core-tests/src/_lib/server.cpp | 2 +- core-tests/src/network/stream.cpp | 2 +- core-tests/src/os/signal.cpp | 10 +-- core-tests/src/protocol/redis.cpp | 6 +- core-tests/src/server/buffer.cpp | 2 +- core-tests/src/server/http.cpp | 12 ++-- core-tests/src/server/server.cpp | 10 +-- examples/cpp/test_server.cc | 32 +++++----- ext-src/php_swoole.cc | 7 ++- ext-src/swoole_coroutine.cc | 2 +- ext-src/swoole_event.cc | 4 +- ext-src/swoole_process.cc | 8 +-- ext-src/swoole_process_pool.cc | 12 ++-- ext-src/swoole_redis_server.cc | 50 +++++++-------- ext-src/swoole_server.cc | 20 +++--- ext-src/swoole_server_port.cc | 40 ++++++------ ext-src/swoole_websocket_server.cc | 2 - include/swoole.h | 2 - include/swoole_config.h | 2 +- include/swoole_process_pool.h | 2 +- include/swoole_redis.h | 50 ++++++++------- include/swoole_server.h | 78 +++++++++++------------ include/swoole_signal.h | 30 +++++---- src/core/base.cc | 4 +- src/coroutine/system.cc | 4 +- src/os/async_thread.cc | 2 +- src/os/process_pool.cc | 5 +- src/os/signal.cc | 99 +++++++++++++++++------------- src/os/timer.cc | 2 +- src/os/wait.cc | 6 +- src/protocol/redis.cc | 73 +++++++++++----------- src/protocol/websocket.cc | 2 +- src/reactor/base.cc | 2 +- src/reactor/kqueue.cc | 17 ++--- src/server/manager.cc | 18 +++--- src/server/master.cc | 48 +++++++-------- src/server/port.cc | 2 +- src/server/process.cc | 6 +- src/server/reactor_process.cc | 4 +- src/server/reactor_thread.cc | 14 ++--- src/server/task_worker.cc | 18 +++--- src/server/worker.cc | 20 +++--- 43 files changed, 374 insertions(+), 359 deletions(-) diff --git a/core-tests/include/test_server.h b/core-tests/include/test_server.h index e3d7fe318f9..771513639db 100644 --- a/core-tests/include/test_server.h +++ b/core-tests/include/test_server.h @@ -29,7 +29,7 @@ class Server { private: swoole::Server serv; - std::vector ports; + std::vector ports; std::unordered_map private_data; std::string host; int port; diff --git a/core-tests/src/_lib/server.cpp b/core-tests/src/_lib/server.cpp index 094afb32165..5955a5f557e 100644 --- a/core-tests/src/_lib/server.cpp +++ b/core-tests/src/_lib/server.cpp @@ -76,7 +76,7 @@ bool Server::start() { } bool Server::listen(std::string host, int port, enum swSocket_type type) { - swListenPort *ls = serv.add_port(type, (char *) host.c_str(), port); + ListenPort *ls = serv.add_port(type, (char *) host.c_str(), port); if (ls == nullptr) { return false; } diff --git a/core-tests/src/network/stream.cpp b/core-tests/src/network/stream.cpp index 2416bfe3e87..c1bd7e432eb 100644 --- a/core-tests/src/network/stream.cpp +++ b/core-tests/src/network/stream.cpp @@ -47,7 +47,7 @@ TEST(stream, send) { ASSERT_EQ(serv.create(), SW_OK); std::thread t1([&]() { - swSignal_none(); + swoole_signal_block_all(); lock.lock(); diff --git a/core-tests/src/os/signal.cpp b/core-tests/src/os/signal.cpp index a636d446898..46bb5b00956 100644 --- a/core-tests/src/os/signal.cpp +++ b/core-tests/src/os/signal.cpp @@ -17,17 +17,17 @@ TEST(os_signal, swSignalfd_set) { ret = sigismember(&curset, SIGUSR1); ASSERT_EQ(ret, 0); - swSignalfd_init(); - swSignal_set(SIGUSR1, sig_usr1); - swSignalfd_setup(SwooleTG.reactor); + swoole_signalfd_init(); + swoole_signal_set(SIGUSR1, sig_usr1); + swoole_signalfd_setup(SwooleTG.reactor); sigemptyset(&curset); sigprocmask(SIG_BLOCK, NULL, &curset); ret = sigismember(&curset, SIGUSR1); ASSERT_EQ(ret, 1); - swSignal_set(SIGUSR1, NULL); - swSignal_clear(); + swoole_signal_set(SIGUSR1, NULL); + swoole_signal_clear(); sigemptyset(&curset); sigprocmask(SIG_BLOCK, NULL, &curset); diff --git a/core-tests/src/protocol/redis.cpp b/core-tests/src/protocol/redis.cpp index 720e136ec99..c89b3095bf6 100644 --- a/core-tests/src/protocol/redis.cpp +++ b/core-tests/src/protocol/redis.cpp @@ -68,16 +68,16 @@ TEST(redis, server) { serv.onReceive = [](swServer *serv, swRecvData *req) -> int { int session_id = req->info.fd; - auto list = swRedis_parse(req->data, req->info.len); + auto list = redis::parse(req->data, req->info.len); String *buffer = sw_tg_buffer(); buffer->clear(); if (strcasecmp(list[0].c_str(), "GET") == 0) { - swRedis_format(buffer, SW_REDIS_REPLY_STRING, REDIS_TEST_VALUE); + redis::format(buffer, redis::REPLY_STRING, REDIS_TEST_VALUE); serv->send(session_id, buffer->str, buffer->length); } else if (strcasecmp(list[0].c_str(), "SET") == 0) { - swRedis_format(buffer, SW_REDIS_REPLY_STATUS, "OK"); + redis::format(buffer, redis::REPLY_STATUS, "OK"); serv->send(session_id, buffer->str, buffer->length); } diff --git a/core-tests/src/server/buffer.cpp b/core-tests/src/server/buffer.cpp index 0098cd9fafc..74479d0675c 100644 --- a/core-tests/src/server/buffer.cpp +++ b/core-tests/src/server/buffer.cpp @@ -43,7 +43,7 @@ TEST(server, send_buffer) { lock.lock(); std::thread t1([&]() { - swSignal_none(); + swoole_signal_block_all(); lock.lock(); diff --git a/core-tests/src/server/http.cpp b/core-tests/src/server/http.cpp index b98af28aca8..b80754b7ac0 100644 --- a/core-tests/src/server/http.cpp +++ b/core-tests/src/server/http.cpp @@ -175,7 +175,7 @@ static void test_run_server(function fn) { TEST(http_server, get) { test_run_server([](swServer *serv) { - swSignal_none(); + swoole_signal_block_all(); auto port = serv->get_primary_port(); @@ -190,7 +190,7 @@ TEST(http_server, get) { TEST(http_server, post) { test_run_server([](swServer *serv) { - swSignal_none(); + swoole_signal_block_all(); auto port = serv->get_primary_port(); @@ -208,7 +208,7 @@ TEST(http_server, post) { TEST(http_server, static_get) { test_run_server([](swServer *serv) { - swSignal_none(); + swoole_signal_block_all(); auto port = serv->get_primary_port(); @@ -241,7 +241,7 @@ static void websocket_test(int server_port, const char *data, size_t length) { TEST(http_server, websocket_small) { test_run_server([](swServer *serv) { - swSignal_none(); + swoole_signal_block_all(); websocket_test(serv->get_primary_port()->get_port(), SW_STRL("hello world, swoole is best!")); kill(getpid(), SIGTERM); }); @@ -249,7 +249,7 @@ TEST(http_server, websocket_small) { TEST(http_server, websocket_medium) { test_run_server([](swServer *serv) { - swSignal_none(); + swoole_signal_block_all(); swString str(8192); str.repeat("A", 1, 8192); @@ -261,7 +261,7 @@ TEST(http_server, websocket_medium) { TEST(http_server, websocket_big) { test_run_server([](swServer *serv) { - swSignal_none(); + swoole_signal_block_all(); swString str(128 * 1024); str.repeat("A", 1, str.capacity() - 1); diff --git a/core-tests/src/server/server.cpp b/core-tests/src/server/server.cpp index 8487ecd8cbc..dab84458a1d 100644 --- a/core-tests/src/server/server.cpp +++ b/core-tests/src/server/server.cpp @@ -44,7 +44,7 @@ TEST(server, schedule) { int ret; Server serv(Server::MODE_PROCESS); serv.worker_num = 6; - serv.dispatch_mode = SW_DISPATCH_QUEUE; + serv.dispatch_mode = Server::DISPATCH_IDLE_WORKER; ret = serv.create(); ASSERT_EQ(SW_OK, ret); @@ -89,7 +89,7 @@ TEST(server, base) { ASSERT_EQ(serv.create(), SW_OK); std::thread t1([&]() { - swSignal_none(); + swoole_signal_block_all(); lock.lock(); @@ -139,7 +139,7 @@ TEST(server, process) { serv.onStart = [&lock](swServer *serv) { thread t1([=]() { - swSignal_none(); + swoole_signal_block_all(); lock->lock(); @@ -199,7 +199,7 @@ TEST(server, ssl) { serv.onStart = [&lock](Server *serv) { thread t1([=]() { - swSignal_none(); + swoole_signal_block_all(); lock->lock(); @@ -262,7 +262,7 @@ TEST(server, dtls) { serv.onStart = [&lock](Server *serv) { thread t1([=]() { - swSignal_none(); + swoole_signal_block_all(); lock->lock(); diff --git a/examples/cpp/test_server.cc b/examples/cpp/test_server.cc index 80ab845c697..6bfc9547125 100644 --- a/examples/cpp/test_server.cc +++ b/examples/cpp/test_server.cc @@ -8,14 +8,14 @@ using namespace swoole; -int my_onPacket(swServer *serv, swRecvData *req); -int my_onReceive(swServer *serv, swRecvData *req); -void my_onStart(swServer *serv); -void my_onShutdown(swServer *serv); -void my_onConnect(swServer *serv, swDataHead *info); -void my_onClose(swServer *serv, swDataHead *info); -void my_onWorkerStart(swServer *serv, int worker_id); -void my_onWorkerStop(swServer *serv, int worker_id); +int my_onPacket(Server *serv, RecvData *req); +int my_onReceive(Server *serv, RecvData *req); +void my_onStart(Server *serv); +void my_onShutdown(Server *serv); +void my_onConnect(Server *serv, DataHead *info); +void my_onClose(Server *serv, DataHead *info); +void my_onWorkerStart(Server *serv, int worker_id); +void my_onWorkerStop(Server *serv, int worker_id); static int g_receive_count = 0; @@ -83,15 +83,15 @@ int main(int argc, char **argv) { return 0; } -void my_onWorkerStart(swServer *serv, int worker_id) { +void my_onWorkerStart(Server *serv, int worker_id) { swNotice("WorkerStart[%d]PID=%d", worker_id, getpid()); } -void my_onWorkerStop(swServer *serv, int worker_id) { +void my_onWorkerStop(Server *serv, int worker_id) { swNotice("WorkerStop[%d]PID=%d", worker_id, getpid()); } -int my_onReceive(swServer *serv, swRecvData *req) { +int my_onReceive(Server *serv, RecvData *req) { char req_data[SW_IPC_BUFFER_SIZE]; char resp_data[SW_IPC_BUFFER_SIZE]; @@ -118,7 +118,7 @@ int my_onReceive(swServer *serv, swRecvData *req) { return SW_OK; } -int my_onPacket(swServer *serv, swRecvData *req) { +int my_onPacket(Server *serv, RecvData *req) { char address[256]; int port = 0; int ret = 0; @@ -158,18 +158,18 @@ int my_onPacket(swServer *serv, swRecvData *req) { return SW_OK; } -void my_onStart(swServer *serv) { +void my_onStart(Server *serv) { swNotice("Server is running"); } -void my_onShutdown(swServer *serv) { +void my_onShutdown(Server *serv) { swNotice("Server is shutdown"); } -void my_onConnect(swServer *serv, swDataHead *info) { +void my_onConnect(Server *serv, DataHead *info) { swNotice("PID=%d\tConnect fd=%ld|reactor_id=%d", getpid(), info->fd, info->reactor_id); } -void my_onClose(swServer *serv, swDataHead *info) { +void my_onClose(Server *serv, DataHead *info) { swNotice("PID=%d\tClose fd=%ld|reactor_id=%d", getpid(), info->fd, info->reactor_id); } diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index db467313060..a64f6d93ce4 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -55,6 +55,7 @@ END_EXTERN_C() #endif using swoole::network::Socket; +using swoole::Server; ZEND_DECLARE_MODULE_GLOBALS(swoole) @@ -458,9 +459,9 @@ PHP_MINIT_FUNCTION(swoole) { /** * task ipc mode */ - SW_REGISTER_LONG_CONSTANT("SWOOLE_IPC_UNSOCK", SW_TASK_IPC_UNIXSOCK); - SW_REGISTER_LONG_CONSTANT("SWOOLE_IPC_MSGQUEUE", SW_TASK_IPC_MSGQUEUE); - SW_REGISTER_LONG_CONSTANT("SWOOLE_IPC_PREEMPTIVE", SW_TASK_IPC_PREEMPTIVE); + SW_REGISTER_LONG_CONSTANT("SWOOLE_IPC_UNSOCK", Server::TASK_IPC_UNIXSOCK); + SW_REGISTER_LONG_CONSTANT("SWOOLE_IPC_MSGQUEUE", Server::TASK_IPC_MSGQUEUE); + SW_REGISTER_LONG_CONSTANT("SWOOLE_IPC_PREEMPTIVE", Server::TASK_IPC_PREEMPTIVE); /** * socket type diff --git a/ext-src/swoole_coroutine.cc b/ext-src/swoole_coroutine.cc index 4ca574002b5..b123a51648f 100644 --- a/ext-src/swoole_coroutine.cc +++ b/ext-src/swoole_coroutine.cc @@ -434,7 +434,7 @@ void PHPCoroutine::interrupt_thread_start() { zend_vm_interrupt = &EG(vm_interrupt); interrupt_thread_running = true; interrupt_thread = std::thread([]() { - swSignal_none(); + swoole_signal_block_all(); while (interrupt_thread_running) { *zend_vm_interrupt = 1; std::this_thread::sleep_for(std::chrono::milliseconds(MAX_EXEC_MSEC / 2)); diff --git a/ext-src/swoole_event.cc b/ext-src/swoole_event.cc index 1c0d9dea8c3..d87d6233bfe 100644 --- a/ext-src/swoole_event.cc +++ b/ext-src/swoole_event.cc @@ -265,7 +265,7 @@ void php_swoole_event_wait() { } #ifdef HAVE_SIGNALFD if (sw_reactor()->check_signalfd) { - swSignalfd_setup(sw_reactor()); + swoole_signalfd_setup(sw_reactor()); } #endif if (!sw_reactor()->if_exit() && !sw_reactor()->bailout) { @@ -741,7 +741,7 @@ static PHP_FUNCTION(swoole_event_dispatch) { #ifdef HAVE_SIGNALFD if (sw_reactor()->check_signalfd) { - swSignalfd_setup(sw_reactor()); + swoole_signalfd_setup(sw_reactor()); } #endif diff --git a/ext-src/swoole_process.cc b/ext-src/swoole_process.cc index 46a8298ebc3..d233d435851 100644 --- a/ext-src/swoole_process.cc +++ b/ext-src/swoole_process.cc @@ -534,7 +534,7 @@ static PHP_METHOD(swoole_process, signal) { RETURN_FALSE; } - swSignalHandler handler = swSignal_get_handler(signo); + swSignalHandler handler = swoole_signal_get_handler(signo); if (handler && handler != php_swoole_onSignal) { php_swoole_fatal_error( E_WARNING, "signal [" ZEND_LONG_FMT "] processor has been registered by the system", signo); @@ -544,7 +544,7 @@ static PHP_METHOD(swoole_process, signal) { if (zcallback == nullptr) { fci_cache = signal_fci_caches[signo]; if (fci_cache) { - swSignal_set(signo, nullptr); + swoole_signal_set(signo, nullptr); signal_fci_caches[signo] = nullptr; swoole_event_defer(sw_zend_fci_cache_free, fci_cache); SwooleTG.signal_listener_num--; @@ -576,7 +576,7 @@ static PHP_METHOD(swoole_process, signal) { SwooleTG.signal_listener_num++; } signal_fci_caches[signo] = fci_cache; - swSignal_set(signo, handler); + swoole_signal_set(signo, handler); RETURN_TRUE; } @@ -601,7 +601,7 @@ static PHP_METHOD(swoole_process, signal) { // use user settings SwooleG.use_signalfd = SwooleG.enable_signalfd; - swSignal_set(signo, handler); + swoole_signal_set(signo, handler); RETURN_TRUE; } diff --git a/ext-src/swoole_process_pool.cc b/ext-src/swoole_process_pool.cc index c13a7d3ad6d..c3cdf485331 100644 --- a/ext-src/swoole_process_pool.cc +++ b/ext-src/swoole_process_pool.cc @@ -218,7 +218,7 @@ static void pool_onWorkerStart(ProcessPool *pool, int worker_id) { return; } if (!pp->enable_coroutine && pp->onMessage) { - swSignal_set(SIGTERM, pool_signal_handler); + swoole_signal_set(SIGTERM, pool_signal_handler); } zval args[2]; args[0] = *zobject; @@ -514,10 +514,10 @@ static PHP_METHOD(swoole_process_pool, start) { std::unordered_map ori_handlers; - ori_handlers[SIGTERM] = swSignal_set(SIGTERM, pool_signal_handler); - ori_handlers[SIGUSR1] = swSignal_set(SIGUSR1, pool_signal_handler); - ori_handlers[SIGUSR2] = swSignal_set(SIGUSR2, pool_signal_handler); - ori_handlers[SIGIO] = swSignal_set(SIGIO, pool_signal_handler); + ori_handlers[SIGTERM] = swoole_signal_set(SIGTERM, pool_signal_handler); + ori_handlers[SIGUSR1] = swoole_signal_set(SIGUSR1, pool_signal_handler); + ori_handlers[SIGUSR2] = swoole_signal_set(SIGUSR2, pool_signal_handler); + ori_handlers[SIGIO] = swoole_signal_set(SIGIO, pool_signal_handler); if (pool->ipc_mode == SW_IPC_NONE || pp->enable_coroutine) { if (pp->onWorkerStart == nullptr) { @@ -557,7 +557,7 @@ static PHP_METHOD(swoole_process_pool, start) { current_pool = nullptr; for (auto iter = ori_handlers.begin(); iter != ori_handlers.end(); iter++) { - swSignal_set(iter->first, iter->second); + swoole_signal_set(iter->first, iter->second); } } diff --git a/ext-src/swoole_redis_server.cc b/ext-src/swoole_redis_server.cc index 69f1dd1e062..ec8412675ba 100644 --- a/ext-src/swoole_redis_server.cc +++ b/ext-src/swoole_redis_server.cc @@ -29,6 +29,8 @@ using swoole::RecvData; using swoole::ListenPort; using swoole::Connection; +namespace Redis = swoole::redis; + zend_class_entry *swoole_redis_server_ce; zend_object_handlers swoole_redis_server_handlers; @@ -75,13 +77,13 @@ void php_swoole_redis_server_minit(int module_number) { SW_SET_CLASS_CLONEABLE(swoole_redis_server, sw_zend_class_clone_deny); SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_redis_server, sw_zend_class_unset_property_deny); - zend_declare_class_constant_long(swoole_redis_server_ce, ZEND_STRL("NIL"), SW_REDIS_REPLY_NIL); - zend_declare_class_constant_long(swoole_redis_server_ce, ZEND_STRL("ERROR"), SW_REDIS_REPLY_ERROR); - zend_declare_class_constant_long(swoole_redis_server_ce, ZEND_STRL("STATUS"), SW_REDIS_REPLY_STATUS); - zend_declare_class_constant_long(swoole_redis_server_ce, ZEND_STRL("INT"), SW_REDIS_REPLY_INT); - zend_declare_class_constant_long(swoole_redis_server_ce, ZEND_STRL("STRING"), SW_REDIS_REPLY_STRING); - zend_declare_class_constant_long(swoole_redis_server_ce, ZEND_STRL("SET"), SW_REDIS_REPLY_SET); - zend_declare_class_constant_long(swoole_redis_server_ce, ZEND_STRL("MAP"), SW_REDIS_REPLY_MAP); + zend_declare_class_constant_long(swoole_redis_server_ce, ZEND_STRL("NIL"), Redis::REPLY_NIL); + zend_declare_class_constant_long(swoole_redis_server_ce, ZEND_STRL("ERROR"), Redis::REPLY_ERROR); + zend_declare_class_constant_long(swoole_redis_server_ce, ZEND_STRL("STATUS"), Redis::REPLY_STATUS); + zend_declare_class_constant_long(swoole_redis_server_ce, ZEND_STRL("INT"), Redis::REPLY_INT); + zend_declare_class_constant_long(swoole_redis_server_ce, ZEND_STRL("STRING"), Redis::REPLY_STRING); + zend_declare_class_constant_long(swoole_redis_server_ce, ZEND_STRL("SET"), Redis::REPLY_SET); + zend_declare_class_constant_long(swoole_redis_server_ce, ZEND_STRL("MAP"), Redis::REPLY_MAP); } void php_swoole_redis_server_rshutdown() { @@ -115,38 +117,38 @@ int php_swoole_redis_server_onReceive(Server *serv, RecvData *req) { zval zparams{}; array_init(&zparams); - int state = SW_REDIS_RECEIVE_TOTAL_LINE; + int state = Redis::STATE_RECEIVE_TOTAL_LINE; int add_param = 0; const char *command = nullptr; int command_len = 0; do { switch (state) { - case SW_REDIS_RECEIVE_TOTAL_LINE: - if (*p == '*' && (p = swRedis_get_number(p, &ret))) { - state = SW_REDIS_RECEIVE_LENGTH; + case Redis::STATE_RECEIVE_TOTAL_LINE: + if (*p == '*' && (p = Redis::get_number(p, &ret))) { + state = Redis::STATE_RECEIVE_LENGTH; break; } /* no break */ - case SW_REDIS_RECEIVE_LENGTH: - if (*p == '$' && (p = swRedis_get_number(p, &ret))) { + case Redis::STATE_RECEIVE_LENGTH: + if (*p == '$' && (p = Redis::get_number(p, &ret))) { if (ret == -1) { add_next_index_null(&zparams); break; } length = ret; - state = SW_REDIS_RECEIVE_STRING; + state = Redis::STATE_RECEIVE_STRING; break; } // integer - else if (*p == ':' && (p = swRedis_get_number(p, &ret))) { + else if (*p == ':' && (p = Redis::get_number(p, &ret))) { add_next_index_long(&zparams, ret); break; } /* no break */ - case SW_REDIS_RECEIVE_STRING: + case Redis::STATE_RECEIVE_STRING: if (add_param == 0) { command = p; command_len = length; @@ -155,7 +157,7 @@ int php_swoole_redis_server_onReceive(Server *serv, RecvData *req) { add_next_index_stringl(&zparams, p, length); } p += length + SW_CRLF_LEN; - state = SW_REDIS_RECEIVE_LENGTH; + state = Redis::STATE_RECEIVE_LENGTH; break; default: @@ -275,9 +277,9 @@ static PHP_METHOD(swoole_redis_server, format) { swoole::String *format_buffer = sw_tg_buffer(); - if (type == SW_REDIS_REPLY_NIL) { + if (type == Redis::REPLY_NIL) { RETURN_STRINGL(SW_REDIS_RETURN_NIL, sizeof(SW_REDIS_RETURN_NIL) - 1); - } else if (type == SW_REDIS_REPLY_STATUS) { + } else if (type == Redis::REPLY_STATUS) { if (value) { zend::String str_value(value); length = sw_snprintf(message, sizeof(message), "+%.*s\r\n", (int) str_value.len(), str_value.val()); @@ -285,7 +287,7 @@ static PHP_METHOD(swoole_redis_server, format) { length = sw_snprintf(message, sizeof(message), "+%s\r\n", "OK"); } RETURN_STRINGL(message, length); - } else if (type == SW_REDIS_REPLY_ERROR) { + } else if (type == Redis::REPLY_ERROR) { if (value) { zend::String str_value(value); length = sw_snprintf(message, sizeof(message), "-%.*s\r\n", (int) str_value.len(), str_value.val()); @@ -293,13 +295,13 @@ static PHP_METHOD(swoole_redis_server, format) { length = sw_snprintf(message, sizeof(message), "-%s\r\n", "ERR"); } RETURN_STRINGL(message, length); - } else if (type == SW_REDIS_REPLY_INT) { + } else if (type == Redis::REPLY_INT) { if (!value) { goto _no_value; } length = sw_snprintf(message, sizeof(message), ":" ZEND_LONG_FMT "\r\n", zval_get_long(value)); RETURN_STRINGL(message, length); - } else if (type == SW_REDIS_REPLY_STRING) { + } else if (type == Redis::REPLY_STRING) { if (!value) { _no_value: php_swoole_fatal_error(E_WARNING, "require more parameters"); @@ -316,7 +318,7 @@ static PHP_METHOD(swoole_redis_server, format) { format_buffer->append(str_value.val(), str_value.len()); format_buffer->append(SW_CRLF, SW_CRLF_LEN); RETURN_STRINGL(format_buffer->str, format_buffer->length); - } else if (type == SW_REDIS_REPLY_SET) { + } else if (type == Redis::REPLY_SET) { if (!value) { goto _no_value; } @@ -337,7 +339,7 @@ static PHP_METHOD(swoole_redis_server, format) { SW_HASHTABLE_FOREACH_END(); RETURN_STRINGL(format_buffer->str, format_buffer->length); - } else if (type == SW_REDIS_REPLY_MAP) { + } else if (type == Redis::REPLY_MAP) { if (!value) { goto _no_value; } diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 3ab5a037bd4..342197c2abc 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -714,9 +714,9 @@ void php_swoole_server_minit(int module_number) { zend_declare_property_long(swoole_server_ce, ZEND_STRL("worker_pid"), 0, ZEND_ACC_PUBLIC); zend_declare_property_null(swoole_server_ce, ZEND_STRL("stats_timer"), ZEND_ACC_PUBLIC); - SW_REGISTER_LONG_CONSTANT("SWOOLE_DISPATCH_RESULT_DISCARD_PACKET", SW_DISPATCH_RESULT_DISCARD_PACKET); - SW_REGISTER_LONG_CONSTANT("SWOOLE_DISPATCH_RESULT_CLOSE_CONNECTION", SW_DISPATCH_RESULT_CLOSE_CONNECTION); - SW_REGISTER_LONG_CONSTANT("SWOOLE_DISPATCH_RESULT_USERFUNC_FALLBACK", SW_DISPATCH_RESULT_USERFUNC_FALLBACK); + SW_REGISTER_LONG_CONSTANT("SWOOLE_DISPATCH_RESULT_DISCARD_PACKET", Server::DISPATCH_RESULT_DISCARD_PACKET); + SW_REGISTER_LONG_CONSTANT("SWOOLE_DISPATCH_RESULT_CLOSE_CONNECTION", Server::DISPATCH_RESULT_CLOSE_CONNECTION); + SW_REGISTER_LONG_CONSTANT("SWOOLE_DISPATCH_RESULT_USERFUNC_FALLBACK", Server::DISPATCH_RESULT_USERFUNC_FALLBACK); SW_REGISTER_LONG_CONSTANT("SWOOLE_TASK_TMPFILE", SW_TASK_TMPFILE); SW_REGISTER_LONG_CONSTANT("SWOOLE_TASK_SERIALIZE", SW_TASK_SERIALIZE); @@ -1125,8 +1125,8 @@ void ServerObject::on_before_start() { php_swoole_fatal_error( E_ERROR, "server dispatch mode should be FDMOD(%d) or IPMOD(%d) if open_http2_protocol is true", - SW_DISPATCH_FDMOD, - SW_DISPATCH_IPMOD); + Server::DISPATCH_FDMOD, + Server::DISPATCH_IPMOD); return; } @@ -2273,7 +2273,7 @@ static PHP_METHOD(swoole_server, set) { if (php_swoole_array_get_value(vht, "send_yield", ztmp)) { serv->send_yield = zval_is_true(ztmp); if (serv->send_yield && - !(serv->dispatch_mode == SW_DISPATCH_FDMOD || serv->dispatch_mode == SW_DISPATCH_IPMOD)) { + !(serv->dispatch_mode == Server::DISPATCH_FDMOD || serv->dispatch_mode == Server::DISPATCH_IPMOD)) { php_swoole_error(E_WARNING, "'send_yield' option can only be set when using dispatch_mode=2/4"); serv->send_yield = 0; } @@ -2562,7 +2562,7 @@ static PHP_METHOD(swoole_server, set) { } if (serv->task_enable_coroutine && - (serv->task_ipc_mode == SW_TASK_IPC_MSGQUEUE || serv->task_ipc_mode == SW_TASK_IPC_PREEMPTIVE)) { + (serv->task_ipc_mode == Server::TASK_IPC_MSGQUEUE || serv->task_ipc_mode == Server::TASK_IPC_PREEMPTIVE)) { php_swoole_fatal_error(E_ERROR, "cannot use msgqueue when task_enable_coroutine is enable"); RETURN_FALSE; } @@ -3005,7 +3005,7 @@ static PHP_METHOD(swoole_server, stats) { add_assoc_long_ex(return_value, ZEND_STRL("worker_dispatch_count"), SwooleWG.worker->dispatch_count); } - if (serv->task_ipc_mode > SW_TASK_IPC_UNIXSOCK && serv->gs->task_workers.queue) { + if (serv->task_ipc_mode > Server::TASK_IPC_UNIXSOCK && serv->gs->task_workers.queue) { size_t queue_num = -1; size_t queue_bytes = -1; if (serv->gs->task_workers.queue->stat(&queue_num, &queue_bytes)) { @@ -3625,10 +3625,10 @@ static PHP_METHOD(swoole_server, getClientInfo) { } else { array_init(return_value); - if (conn->uid > 0 || serv->dispatch_mode == SW_DISPATCH_UIDMOD) { + if (conn->uid > 0 || serv->dispatch_mode == Server::DISPATCH_UIDMOD) { add_assoc_long(return_value, "uid", conn->uid); } - if (conn->worker_id > 0 || serv->dispatch_mode == SW_DISPATCH_CO_CONN_LB) { + if (conn->worker_id > 0 || serv->dispatch_mode == Server::DISPATCH_CO_CONN_LB) { add_assoc_long(return_value, "worker_id", conn->worker_id); } diff --git a/ext-src/swoole_server_port.cc b/ext-src/swoole_server_port.cc index b22ab7847fb..1a3891c6758 100644 --- a/ext-src/swoole_server_port.cc +++ b/ext-src/swoole_server_port.cc @@ -18,39 +18,39 @@ using namespace swoole; -struct server_port_event { +struct ServerPortEvent { enum php_swoole_server_port_callback_type type; std::string name; - server_port_event(enum php_swoole_server_port_callback_type type, std::string &&name) : type(type), name(name) {} + ServerPortEvent(enum php_swoole_server_port_callback_type type, std::string &&name) : type(type), name(name) {} }; // clang-format off -static std::unordered_map server_port_event_map({ - { "connect", server_port_event(SW_SERVER_CB_onConnect, "Connect") }, - { "receive", server_port_event(SW_SERVER_CB_onReceive, "Receive") }, - { "close", server_port_event(SW_SERVER_CB_onClose, "Close") }, - { "packet", server_port_event(SW_SERVER_CB_onPacket, "Packet") }, - { "bufferfull", server_port_event(SW_SERVER_CB_onBufferFull, "BufferFull") }, - { "bufferempty", server_port_event(SW_SERVER_CB_onBufferEmpty, "BufferEmpty") }, - { "request", server_port_event(SW_SERVER_CB_onRequest, "Request") }, - { "handshake", server_port_event(SW_SERVER_CB_onHandShake, "Handshake") }, - { "open", server_port_event(SW_SERVER_CB_onOpen, "Open") }, - { "message", server_port_event(SW_SERVER_CB_onMessage, "Message") }, - { "disconnect", server_port_event(SW_SERVER_CB_onDisconnect, "Disconnect") }, +static std::unordered_map server_port_event_map({ + { "connect", ServerPortEvent(SW_SERVER_CB_onConnect, "Connect") }, + { "receive", ServerPortEvent(SW_SERVER_CB_onReceive, "Receive") }, + { "close", ServerPortEvent(SW_SERVER_CB_onClose, "Close") }, + { "packet", ServerPortEvent(SW_SERVER_CB_onPacket, "Packet") }, + { "bufferfull", ServerPortEvent(SW_SERVER_CB_onBufferFull, "BufferFull") }, + { "bufferempty", ServerPortEvent(SW_SERVER_CB_onBufferEmpty, "BufferEmpty") }, + { "request", ServerPortEvent(SW_SERVER_CB_onRequest, "Request") }, + { "handshake", ServerPortEvent(SW_SERVER_CB_onHandShake, "Handshake") }, + { "open", ServerPortEvent(SW_SERVER_CB_onOpen, "Open") }, + { "message", ServerPortEvent(SW_SERVER_CB_onMessage, "Message") }, + { "disconnect", ServerPortEvent(SW_SERVER_CB_onDisconnect, "Disconnect") }, }); // clang-format on zend_class_entry *swoole_server_port_ce; static zend_object_handlers swoole_server_port_handlers; -struct server_port_t { +struct ServerPortObject { ListenPort *port; ServerPortProperty property; zend_object std; }; -static sw_inline server_port_t *php_swoole_server_port_fetch_object(zend_object *obj) { - return (server_port_t *) ((char *) obj - swoole_server_port_handlers.offset); +static sw_inline ServerPortObject *php_swoole_server_port_fetch_object(zend_object *obj) { + return (ServerPortObject *) ((char *) obj - swoole_server_port_handlers.offset); } static sw_inline ListenPort *php_swoole_server_port_get_ptr(zval *zobject) { @@ -83,7 +83,7 @@ static ServerPortProperty *php_swoole_server_port_get_and_check_property(zval *z // Dereference from server object void php_swoole_server_port_deref(zend_object *object) { - server_port_t *server_port = php_swoole_server_port_fetch_object(object); + ServerPortObject *server_port = php_swoole_server_port_fetch_object(object); ServerPortProperty *property = &server_port->property; if (property->serv) { for (int j = 0; j < PHP_SWOOLE_SERVER_PORT_CALLBACK_NUM; j++) { @@ -112,7 +112,7 @@ static void php_swoole_server_port_free_object(zend_object *object) { } static zend_object *php_swoole_server_port_create_object(zend_class_entry *ce) { - server_port_t *server_port = (server_port_t *) zend_object_alloc(sizeof(server_port_t), ce); + ServerPortObject *server_port = (ServerPortObject *) zend_object_alloc(sizeof(ServerPortObject), ce); zend_object_std_init(&server_port->std, ce); object_properties_init(&server_port->std, ce); server_port->std.handlers = &swoole_server_port_handlers; @@ -172,7 +172,7 @@ void php_swoole_server_port_minit(int module_number) { SW_SET_CLASS_CUSTOM_OBJECT(swoole_server_port, php_swoole_server_port_create_object, php_swoole_server_port_free_object, - server_port_t, + ServerPortObject, std); zend_declare_property_null(swoole_server_port_ce, ZEND_STRL("onConnect"), ZEND_ACC_PRIVATE); diff --git a/ext-src/swoole_websocket_server.cc b/ext-src/swoole_websocket_server.cc index 6cf7671631a..e8f2deccf7c 100644 --- a/ext-src/swoole_websocket_server.cc +++ b/ext-src/swoole_websocket_server.cc @@ -30,8 +30,6 @@ using swoole::SessionId; using swoole::String; using swoole::coroutine::Socket; -using http_request = swoole::http::Request; -using http_response = swoole::http::Response; using HttpContext = swoole::http::Context; namespace WebSocket = swoole::websocket; diff --git a/include/swoole.h b/include/swoole.h index 8c8727d355b..ec06f4bc166 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -205,8 +205,6 @@ typedef swoole::Protocol swProtocol; typedef swoole::EventData swEventData; typedef swoole::DataHead swDataHead; typedef swoole::Event swEvent; -typedef swoole::Pipe swPipe; -typedef swoole::Callback swCallback; /*----------------------------------String-------------------------------------*/ diff --git a/include/swoole_config.h b/include/swoole_config.h index fd6988dca45..64aaa1b2798 100644 --- a/include/swoole_config.h +++ b/include/swoole_config.h @@ -76,7 +76,7 @@ #else #define SW_IPC_MAX_SIZE 8192 // for IPC, dgram and message-queue max size #endif -#define SW_IPC_BUFFER_SIZE (SW_IPC_MAX_SIZE - sizeof(swDataHead)) +#define SW_IPC_BUFFER_SIZE (SW_IPC_MAX_SIZE - sizeof(swoole::DataHead)) // !!!End.------------------------------------------------------------------- #define SW_BUFFER_SIZE_STD 8192 diff --git a/include/swoole_process_pool.h b/include/swoole_process_pool.h index 65b4d130f6e..26ba7aaaf85 100644 --- a/include/swoole_process_pool.h +++ b/include/swoole_process_pool.h @@ -180,7 +180,7 @@ struct ProcessPool { bool reload_init; bool read_message; bool started; - uint8_t dispatch_mode; + bool schedule_by_sysvmsg; uint8_t ipc_mode; pid_t master_pid; uint32_t reload_worker_i; diff --git a/include/swoole_redis.h b/include/swoole_redis.h index f12dfc38be9..421fb11c4c2 100644 --- a/include/swoole_redis.h +++ b/include/swoole_redis.h @@ -21,29 +21,32 @@ #include #include -enum swRedis_receive_state { - SW_REDIS_RECEIVE_TOTAL_LINE, - SW_REDIS_RECEIVE_LENGTH, - SW_REDIS_RECEIVE_STRING, -}; - -enum swRedis_reply_type { - SW_REDIS_REPLY_ERROR, - SW_REDIS_REPLY_NIL, - SW_REDIS_REPLY_STATUS, - SW_REDIS_REPLY_INT, - SW_REDIS_REPLY_STRING, - SW_REDIS_REPLY_SET, - SW_REDIS_REPLY_MAP, -}; - #define SW_REDIS_RETURN_NIL "$-1\r\n" #define SW_REDIS_MAX_COMMAND_SIZE 64 #define SW_REDIS_MAX_LINES 128 #define SW_REDIS_MAX_STRING_SIZE 536870912 // 512M -static sw_inline const char *swRedis_get_number(const char *p, int *_ret) { +namespace swoole { +namespace redis { + +enum State { + STATE_RECEIVE_TOTAL_LINE, + STATE_RECEIVE_LENGTH, + STATE_RECEIVE_STRING, +}; + +enum ReplyType { + REPLY_ERROR, + REPLY_NIL, + REPLY_STATUS, + REPLY_INT, + REPLY_STRING, + REPLY_SET, + REPLY_MAP, +}; + +static sw_inline const char *get_number(const char *p, int *_ret) { char *endptr; p++; int ret = strtol(p, &endptr, 10); @@ -56,8 +59,11 @@ static sw_inline const char *swRedis_get_number(const char *p, int *_ret) { } } -int swRedis_recv_packet(swProtocol *protocol, swConnection *conn, swString *buffer); -std::vector swRedis_parse(const char *data, size_t len); -bool swRedis_format(swString *buf); -bool swRedis_format(swString *buf, enum swRedis_reply_type type, const std::string &value); -bool swRedis_format(swString *buf, enum swRedis_reply_type type, long value); +int recv_packet(Protocol *protocol, Connection *conn, String *buffer); +std::vector parse(const char *data, size_t len); +bool format(String *buf); +bool format(String *buf, enum ReplyType type, const std::string &value); +bool format(String *buf, enum ReplyType type, long value); + +} // namespace redis +} // namespace swoole diff --git a/include/swoole_server.h b/include/swoole_server.h index 7ee38be73e4..30cdc4beda4 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -43,40 +43,6 @@ #include #include -#define SW_REACTOR_NUM SW_CPU_NUM -#define SW_WORKER_NUM (SW_CPU_NUM * 2) - -enum swTask_ipc_mode { - SW_TASK_IPC_UNIXSOCK = 1, - SW_TASK_IPC_MSGQUEUE = 2, - SW_TASK_IPC_PREEMPTIVE = 3, - SW_TASK_IPC_STREAM = 4, -}; - -enum swFactory_dispatch_mode { - SW_DISPATCH_ROUND = 1, - SW_DISPATCH_FDMOD = 2, - SW_DISPATCH_QUEUE = 3, - SW_DISPATCH_IPMOD = 4, - SW_DISPATCH_UIDMOD = 5, - SW_DISPATCH_USERFUNC = 6, - SW_DISPATCH_STREAM = 7, - SW_DISPATCH_CO_CONN_LB, - SW_DISPATCH_CO_REQ_LB, -}; - -enum swFactory_dispatch_result { - SW_DISPATCH_RESULT_DISCARD_PACKET = -1, - SW_DISPATCH_RESULT_CLOSE_CONNECTION = -2, - SW_DISPATCH_RESULT_USERFUNC_FALLBACK = -3, -}; - -enum swThread_type { - SW_THREAD_MASTER = 1, - SW_THREAD_REACTOR = 2, - SW_THREAD_HEARTBEAT = 3, -}; - //------------------------------------Server------------------------------------------- namespace swoole { @@ -511,6 +477,37 @@ class Server { MODE_PROCESS = 2, }; + enum TaskIpcMode { + TASK_IPC_UNIXSOCK = 1, + TASK_IPC_MSGQUEUE = 2, + TASK_IPC_PREEMPTIVE = 3, + TASK_IPC_STREAM = 4, + }; + + enum ThreadType { + THREAD_MASTER = 1, + THREAD_REACTOR = 2, + THREAD_HEARTBEAT = 3, + }; + + enum DispatchMode { + DISPATCH_ROUND = 1, + DISPATCH_FDMOD = 2, + DISPATCH_IDLE_WORKER = 3, + DISPATCH_IPMOD = 4, + DISPATCH_UIDMOD = 5, + DISPATCH_USERFUNC = 6, + DISPATCH_STREAM = 7, + DISPATCH_CO_CONN_LB, + DISPATCH_CO_REQ_LB, + }; + + enum FactoryDispatchResult { + DISPATCH_RESULT_DISCARD_PACKET = -1, + DISPATCH_RESULT_CLOSE_CONNECTION = -2, + DISPATCH_RESULT_USERFUNC_FALLBACK = -3, + }; + enum HookType { HOOK_MASTER_START, HOOK_MASTER_TIMER, @@ -548,7 +545,7 @@ class Server { /** * package dispatch mode */ - uint8_t dispatch_mode = SW_DISPATCH_FDMOD; + uint8_t dispatch_mode = DISPATCH_FDMOD; /** * No idle work process is available. @@ -753,7 +750,7 @@ class Server { * task process */ uint32_t task_worker_num = 0; - uint8_t task_ipc_mode = SW_TASK_IPC_UNIXSOCK; + uint8_t task_ipc_mode = TASK_IPC_UNIXSOCK; uint32_t task_max_request = 0; uint32_t task_max_request_grace = 0; std::vector> task_notify_pipes; @@ -974,8 +971,8 @@ class Server { } inline bool is_support_unsafe_events() { - if (dispatch_mode != SW_DISPATCH_ROUND && dispatch_mode != SW_DISPATCH_QUEUE && - dispatch_mode != SW_DISPATCH_STREAM) { + if (dispatch_mode != DISPATCH_ROUND && dispatch_mode != DISPATCH_IDLE_WORKER && + dispatch_mode != DISPATCH_STREAM) { return true; } else { return enable_unsafe_event; @@ -1001,8 +998,8 @@ class Server { } inline bool is_hash_dispatch_mode() { - return dispatch_mode == SW_DISPATCH_FDMOD || dispatch_mode == SW_DISPATCH_IPMOD || - dispatch_mode == SW_DISPATCH_CO_CONN_LB; + return dispatch_mode == DISPATCH_FDMOD || dispatch_mode == DISPATCH_IPMOD || + dispatch_mode == DISPATCH_CO_CONN_LB; } inline bool is_support_send_yield() { @@ -1331,7 +1328,6 @@ class Server { typedef swoole::Server swServer; typedef swoole::ListenPort swListenPort; -typedef swoole::Connection swConnection; typedef swoole::RecvData swRecvData; extern swoole::Server *g_server_instance; diff --git a/include/swoole_signal.h b/include/swoole_signal.h index ad3d8af7d0e..256d8a0ae77 100644 --- a/include/swoole_signal.h +++ b/include/swoole_signal.h @@ -17,25 +17,31 @@ #pragma once #include "swoole.h" + #include -typedef void (*swSignalHandler)(int); +namespace swoole { +typedef void (*SignalHandler)(int); -struct swSignal { - swSignalHandler handler; +struct Signal { + SignalHandler handler; uint16_t signo; bool activated; }; +} // namespace swoole + +typedef swoole::SignalHandler swSignalHandler; #ifdef HAVE_SIGNALFD -void swSignalfd_init(); -bool swSignalfd_setup(swoole::Reactor *reactor); +void swoole_signalfd_init(); +bool swoole_signalfd_setup(swoole::Reactor *reactor); #endif -swSignalHandler swSignal_set(int signo, swSignalHandler func); -swSignalHandler swSignal_set(int signo, swSignalHandler func, int restart, int mask); -swSignalHandler swSignal_get_handler(int signo); -void swSignal_clear(void); -void swSignal_none(void); -char *swSignal_str(int sig); -void swSignal_callback(int signo); +SW_API swSignalHandler swoole_signal_set(int signo, swSignalHandler func); +SW_API swSignalHandler swoole_signal_set(int signo, swSignalHandler func, int restart, int mask); +SW_API swSignalHandler swoole_signal_get_handler(int signo); + +SW_API void swoole_signal_clear(void); +SW_API void swoole_signal_block_all(void); +SW_API char *swoole_signal_to_str(int sig); +SW_API void swoole_signal_callback(int signo); diff --git a/src/core/base.cc b/src/core/base.cc index 112b5e0077a..3705b677644 100644 --- a/src/core/base.cc +++ b/src/core/base.cc @@ -164,7 +164,7 @@ void swoole_init(void) { // init signalfd #ifdef HAVE_SIGNALFD - swSignalfd_init(); + swoole_signalfd_init(); SwooleG.use_signalfd = 1; SwooleG.enable_signalfd = 1; #endif @@ -344,7 +344,7 @@ pid_t swoole_fork(int flags) { /** * reset signal handler */ - swSignal_clear(); + swoole_signal_clear(); } return pid; diff --git a/src/coroutine/system.cc b/src/coroutine/system.cc index 11ff4e20fcb..b877cf6144b 100644 --- a/src/coroutine/system.cc +++ b/src/coroutine/system.cc @@ -271,7 +271,7 @@ bool System::wait_signal(int signo, double timeout) { } /* always enable signalfd */ SwooleG.use_signalfd = SwooleG.enable_signalfd = 1; - swSignal_set(signo, [](int signo) { + swoole_signal_set(signo, [](int signo) { Coroutine *co = listeners[signo]; if (co) { listeners[signo] = nullptr; @@ -301,7 +301,7 @@ bool System::wait_signal(int signo, double timeout) { }; co->yield(&cancel_fn); - swSignal_set(signo, nullptr); + swoole_signal_set(signo, nullptr); SwooleTG.co_signal_listener_num--; if (listeners[signo] != nullptr) { diff --git a/src/os/async_thread.cc b/src/os/async_thread.cc index 7994ccc1544..e8a48e9c108 100644 --- a/src/os/async_thread.cc +++ b/src/os/async_thread.cc @@ -231,7 +231,7 @@ void ThreadPool::create_thread(const bool is_core_worker) { SwooleTG.buffer_stack = nullptr; }; - swSignal_none(); + swoole_signal_block_all(); while (running) { event_mutex.lock(); diff --git a/src/os/process_pool.cc b/src/os/process_pool.cc index aecee9f8871..da2eaf51cf3 100644 --- a/src/os/process_pool.cc +++ b/src/os/process_pool.cc @@ -189,7 +189,8 @@ int ProcessPool::start() { } int ProcessPool::schedule() { - if (dispatch_mode == SW_DISPATCH_QUEUE) { + // schedule by system message queue + if (schedule_by_sysvmsg) { return 0; } @@ -411,7 +412,7 @@ static int ProcessPool_worker_loop(ProcessPool *pool, Worker *worker) { */ out.buf.info.server_fd = worker->id; - if (pool->dispatch_mode == SW_DISPATCH_QUEUE) { + if (pool->schedule_by_sysvmsg) { out.mtype = 0; } else { out.mtype = worker->id + 1; diff --git a/src/os/signal.cc b/src/os/signal.cc index 1f82a6cf003..df5cf59b8c2 100644 --- a/src/os/signal.cc +++ b/src/os/signal.cc @@ -23,32 +23,44 @@ #ifdef HAVE_SIGNALFD #include #endif + #ifdef HAVE_KQUEUE +#ifdef USE_KQUEUE_IDE_HELPER +#include "helper/kqueue.h" +#else #include #endif +#endif +using swoole::Event; using swoole::Reactor; +using swoole::Signal; +using swoole::SignalHandler; +using swoole::network::Socket; #ifdef HAVE_SIGNALFD -static swSignalHandler swSignalfd_set(int signo, swSignalHandler handler); -static bool swSignalfd_create(); -static void swSignalfd_clear(); -static int swSignalfd_onSignal(Reactor *reactor, swEvent *event); -#elif HAVE_KQUEUE -static swSignalHandler swKqueueSignal_set(int signo, swSignalHandler handler); +static SignalHandler swoole_signalfd_set(int signo, SignalHandler handler); +static bool swoole_signalfd_create(); +static void swoole_signalfd_clear(); +static int swoole_signalfd_event_callback(Reactor *reactor, Event *event); #endif -static void swSignal_async_handler(int signo); + +#ifdef HAVE_KQUEUE +static SignalHandler swoole_signal_kqueue_set(int signo, SignalHandler handler); +#endif + +static void swoole_signal_async_handler(int signo); #ifdef HAVE_SIGNALFD static sigset_t signalfd_mask; static int signal_fd = 0; static pid_t signalfd_create_pid; -static swoole::network::Socket *signal_socket = nullptr; +static Socket *signal_socket = nullptr; #endif -static swSignal signals[SW_SIGNO_MAX]; +static Signal signals[SW_SIGNO_MAX]; static int _lock = 0; -char *swSignal_str(int sig) { +char *swoole_signal_to_str(int sig) { static char buf[64]; snprintf(buf, sizeof(buf), "%s", strsignal(sig)); if (strchr(buf, ':') == 0) { @@ -61,7 +73,7 @@ char *swSignal_str(int sig) { /** * block all singal */ -void swSignal_none(void) { +void swoole_signal_block_all(void) { sigset_t mask; sigfillset(&mask); int ret = pthread_sigmask(SIG_BLOCK, &mask, nullptr); @@ -73,7 +85,7 @@ void swSignal_none(void) { /** * set new signal handler and return origin signal handler */ -swSignalHandler swSignal_set(int signo, swSignalHandler func, int restart, int mask) { +SignalHandler swoole_signal_set(int signo, SignalHandler func, int restart, int mask) { // ignore if (func == nullptr) { func = SIG_IGN; @@ -101,10 +113,10 @@ swSignalHandler swSignal_set(int signo, swSignalHandler func, int restart, int m /** * set new signal handler and return origin signal handler */ -swSignalHandler swSignal_set(int signo, swSignalHandler handler) { +SignalHandler swoole_signal_set(int signo, SignalHandler handler) { #ifdef HAVE_SIGNALFD if (SwooleG.use_signalfd) { - return swSignalfd_set(signo, handler); + return swoole_signalfd_set(signo, handler); } else #endif { @@ -113,19 +125,19 @@ swSignalHandler swSignal_set(int signo, swSignalHandler handler) { // see https://www.freebsd.org/cgi/man.cgi?kqueue // if there's no main reactor, signals cannot be monitored either if (signo != SIGCHLD && sw_reactor()) { - return swKqueueSignal_set(signo, handler); + return swoole_signal_kqueue_set(signo, handler); } else #endif { signals[signo].handler = handler; signals[signo].activated = true; signals[signo].signo = signo; - return swSignal_set(signo, swSignal_async_handler, 1, 0); + return swoole_signal_set(signo, swoole_signal_async_handler, 1, 0); } } } -static void swSignal_async_handler(int signo) { +static void swoole_signal_async_handler(int signo) { if (sw_reactor()) { sw_reactor()->singal_no = signo; } else { @@ -134,25 +146,26 @@ static void swSignal_async_handler(int signo) { return; } _lock = 1; - swSignal_callback(signo); + swoole_signal_callback(signo); _lock = 0; } } -void swSignal_callback(int signo) { +void swoole_signal_callback(int signo) { if (signo >= SW_SIGNO_MAX) { swWarn("signal[%d] numberis invalid", signo); return; } - swSignalHandler callback = signals[signo].handler; + SignalHandler callback = signals[signo].handler; if (!callback) { - swoole_error_log(SW_LOG_WARNING, SW_ERROR_UNREGISTERED_SIGNAL, SW_UNREGISTERED_SIGNAL_FMT, swSignal_str(signo)); + swoole_error_log( + SW_LOG_WARNING, SW_ERROR_UNREGISTERED_SIGNAL, SW_UNREGISTERED_SIGNAL_FMT, swoole_signal_to_str(signo)); return; } callback(signo); } -swSignalHandler swSignal_get_handler(int signo) { +SignalHandler swoole_signal_get_handler(int signo) { if (signo >= SW_SIGNO_MAX) { swWarn("signal[%d] numberis invalid", signo); return nullptr; @@ -161,10 +174,10 @@ swSignalHandler swSignal_get_handler(int signo) { } } -void swSignal_clear(void) { +void swoole_signal_clear(void) { #ifdef HAVE_SIGNALFD if (SwooleG.use_signalfd) { - swSignalfd_clear(); + swoole_signalfd_clear(); } else #endif { @@ -173,11 +186,11 @@ void swSignal_clear(void) { if (signals[i].activated) { #ifdef HAVE_KQUEUE if (signals[i].signo != SIGCHLD && sw_reactor()) { - swKqueueSignal_set(signals[i].signo, nullptr); + swoole_signal_kqueue_set(signals[i].signo, nullptr); } else #endif { - swSignal_set(signals[i].signo, (swSignalHandler) -1, 1, 0); + swoole_signal_set(signals[i].signo, (SignalHandler) -1, 1, 0); } } } @@ -186,7 +199,7 @@ void swSignal_clear(void) { } #ifdef HAVE_SIGNALFD -void swSignalfd_init() { +void swoole_signalfd_init() { sigemptyset(&signalfd_mask); sw_memset_zero(&signals, sizeof(signals)); } @@ -194,12 +207,12 @@ void swSignalfd_init() { /** * set new signal handler and return origin signal handler */ -static swSignalHandler swSignalfd_set(int signo, swSignalHandler handler) { - swSignalHandler origin_handler = nullptr; +static SignalHandler swoole_signalfd_set(int signo, SignalHandler handler) { + SignalHandler origin_handler = nullptr; if (handler == nullptr && signals[signo].activated) { sigdelset(&signalfd_mask, signo); - sw_memset_zero(&signals[signo], sizeof(swSignal)); + sw_memset_zero(&signals[signo], sizeof(Signal)); } else { sigaddset(&signalfd_mask, signo); origin_handler = signals[signo].handler; @@ -210,18 +223,18 @@ static swSignalHandler swSignalfd_set(int signo, swSignalHandler handler) { if (sw_reactor()) { if (signal_fd == 0) { - swSignalfd_create(); + swoole_signalfd_create(); } else { sigprocmask(SIG_SETMASK, &signalfd_mask, nullptr); signalfd(signal_fd, &signalfd_mask, SFD_NONBLOCK | SFD_CLOEXEC); } - swSignalfd_setup(sw_reactor()); + swoole_signalfd_setup(sw_reactor()); } return origin_handler; } -static bool swSignalfd_create() { +static bool swoole_signalfd_create() { if (signal_fd != 0) { return false; } @@ -246,12 +259,12 @@ static bool swSignalfd_create() { return true; } -bool swSignalfd_setup(Reactor *reactor) { - if (signal_fd == 0 && !swSignalfd_create()) { +bool swoole_signalfd_setup(Reactor *reactor) { + if (signal_fd == 0 && !swoole_signalfd_create()) { return false; } if (!swoole_event_isset_handler(SW_FD_SIGNAL)) { - swoole_event_set_handler(SW_FD_SIGNAL, swSignalfd_onSignal); + swoole_event_set_handler(SW_FD_SIGNAL, swoole_signalfd_event_callback); reactor->set_exit_condition(Reactor::EXIT_CONDITION_SIGNALFD, [](Reactor *reactor, int &event_num) -> bool { event_num--; return true; @@ -269,7 +282,7 @@ bool swSignalfd_setup(Reactor *reactor) { return true; } -static void swSignalfd_clear() { +static void swoole_signalfd_clear() { if (signal_fd) { if (sigprocmask(SIG_UNBLOCK, &signalfd_mask, nullptr) < 0) { swSysWarn("sigprocmask(SIG_UNBLOCK) failed"); @@ -283,7 +296,7 @@ static void swSignalfd_clear() { SwooleG.signal_fd = signal_fd = 0; } -static int swSignalfd_onSignal(Reactor *reactor, swEvent *event) { +static int swoole_signalfd_event_callback(Reactor *reactor, Event *event) { struct signalfd_siginfo siginfo; ssize_t n = read(event->fd, &siginfo, sizeof(siginfo)); if (n < 0) { @@ -295,7 +308,7 @@ static int swSignalfd_onSignal(Reactor *reactor, swEvent *event) { return SW_OK; } if (signals[siginfo.ssi_signo].activated) { - swSignalHandler handler = signals[siginfo.ssi_signo].handler; + SignalHandler handler = signals[siginfo.ssi_signo].handler; if (handler == SIG_IGN) { return SW_OK; } else if (handler) { @@ -304,7 +317,7 @@ static int swSignalfd_onSignal(Reactor *reactor, swEvent *event) { swoole_error_log(SW_LOG_WARNING, SW_ERROR_UNREGISTERED_SIGNAL, SW_UNREGISTERED_SIGNAL_FMT, - swSignal_str(siginfo.ssi_signo)); + swoole_signal_to_str(siginfo.ssi_signo)); } } @@ -316,15 +329,15 @@ static int swSignalfd_onSignal(Reactor *reactor, swEvent *event) { /** * set new signal handler and return origin signal handler */ -static swSignalHandler swKqueueSignal_set(int signo, swSignalHandler handler) { +static SignalHandler swoole_signal_kqueue_set(int signo, SignalHandler handler) { struct kevent ev; - swSignalHandler origin_handler = nullptr; + SignalHandler origin_handler = nullptr; Reactor *reactor = sw_reactor(); // clear signal if (handler == nullptr) { signal(signo, SIG_DFL); - sw_memset_zero(&signals[signo], sizeof(swSignal)); + sw_memset_zero(&signals[signo], sizeof(Signal)); EV_SET(&ev, signo, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL); } // add/update signal diff --git a/src/os/timer.cc b/src/os/timer.cc index bab72fc5aed..f473b329306 100644 --- a/src/os/timer.cc +++ b/src/os/timer.cc @@ -26,7 +26,7 @@ static int SystemTimer_set(Timer *timer, long next_msec); bool Timer::init_system_timer() { set = SystemTimer_set; close = [](Timer *timer) { SystemTimer_set(timer, -1); }; - swSignal_set(SIGALRM, [](int sig) { SwooleG.signal_alarm = true; }); + swoole_signal_set(SIGALRM, [](int sig) { SwooleG.signal_alarm = true; }); return true; } diff --git a/src/os/wait.cc b/src/os/wait.cc index f3b86b5cf8e..8301a76befa 100644 --- a/src/os/wait.cc +++ b/src/os/wait.cc @@ -69,10 +69,10 @@ static void signal_handler(int signo) { static void signal_init() { if (!signal_ready) { Reactor *reactor = SwooleTG.reactor; - swSignal_set(SIGCHLD, signal_handler); + swoole_signal_set(SIGCHLD, signal_handler); #ifdef HAVE_SIGNALFD if (SwooleG.use_signalfd && !reactor->isset_handler(SW_FD_SIGNAL)) { - swSignalfd_setup(reactor); + swoole_signalfd_setup(reactor); } #endif @@ -82,7 +82,7 @@ static void signal_init() { reactor->add_destroy_callback([](void *) { signal_ready = false; - swSignal_clear(); + swoole_signal_clear(); }); signal_ready = true; diff --git a/src/protocol/redis.cc b/src/protocol/redis.cc index d54239af2ab..68c314669c4 100644 --- a/src/protocol/redis.cc +++ b/src/protocol/redis.cc @@ -23,9 +23,10 @@ #include "swoole_server.h" #include "swoole_redis.h" -using namespace swoole; +namespace swoole { +namespace redis { -struct RedisRequest { +struct Request { uint8_t state; int n_lines_total; @@ -37,25 +38,25 @@ struct RedisRequest { int offset; }; -int swRedis_recv_packet(Protocol *protocol, Connection *conn, String *buffer) { +int recv_packet(Protocol *protocol, Connection *conn, String *buffer) { const char *p, *pe; int ret; char *buf_ptr; size_t buf_size; - RedisRequest *request; + Request *request; network::Socket *socket = conn->socket; if (conn->object == nullptr) { - request = (RedisRequest *) sw_malloc(sizeof(RedisRequest)); + request = (Request *) sw_malloc(sizeof(Request)); if (!request) { - swWarn("malloc(%ld) failed", sizeof(RedisRequest)); + swWarn("malloc(%ld) failed", sizeof(Request)); return SW_ERR; } - sw_memset_zero(request, sizeof(RedisRequest)); + sw_memset_zero(request, sizeof(Request)); conn->object = request; } else { - request = (RedisRequest *) conn->object; + request = (Request *) conn->object; } _recv_data: @@ -100,10 +101,10 @@ int swRedis_recv_packet(Protocol *protocol, Connection *conn, String *buffer) { do { switch (request->state) { - case SW_REDIS_RECEIVE_TOTAL_LINE: - if (*p == '*' && (p = swRedis_get_number(p, &ret))) { + case STATE_RECEIVE_TOTAL_LINE: + if (*p == '*' && (p = get_number(p, &ret))) { request->n_lines_total = ret; - request->state = SW_REDIS_RECEIVE_LENGTH; + request->state = STATE_RECEIVE_LENGTH; break; } if (p == nullptr) { @@ -111,8 +112,8 @@ int swRedis_recv_packet(Protocol *protocol, Connection *conn, String *buffer) { } /* no break */ - case SW_REDIS_RECEIVE_LENGTH: - if (*p == '$' && (p = swRedis_get_number(p, &ret))) { + case STATE_RECEIVE_LENGTH: + if (*p == '$' && (p = get_number(p, &ret))) { if (ret < 0) { break; } @@ -120,11 +121,11 @@ int swRedis_recv_packet(Protocol *protocol, Connection *conn, String *buffer) { goto _package_too_big; } request->n_bytes_total = ret; - request->state = SW_REDIS_RECEIVE_STRING; + request->state = STATE_RECEIVE_STRING; break; } // integer - else if (*p == ':' && (p = swRedis_get_number(p, &ret))) { + else if (*p == ':' && (p = get_number(p, &ret))) { break; } if (p == nullptr) { @@ -132,7 +133,7 @@ int swRedis_recv_packet(Protocol *protocol, Connection *conn, String *buffer) { } /* no break */ - case SW_REDIS_RECEIVE_STRING: + case STATE_RECEIVE_STRING: if (pe - p < request->n_bytes_total - request->n_bytes_received) { request->n_bytes_received += pe - p; return SW_OK; @@ -140,7 +141,7 @@ int swRedis_recv_packet(Protocol *protocol, Connection *conn, String *buffer) { p += request->n_bytes_total + SW_CRLF_LEN; request->n_bytes_total = 0; request->n_lines_received++; - request->state = SW_REDIS_RECEIVE_LENGTH; + request->state = STATE_RECEIVE_LENGTH; buffer->offset = buffer->length; if (request->n_lines_received == request->n_lines_total) { @@ -151,7 +152,7 @@ int swRedis_recv_packet(Protocol *protocol, Connection *conn, String *buffer) { return SW_OK; } buffer->clear(); - sw_memset_zero(request, sizeof(RedisRequest)); + sw_memset_zero(request, sizeof(Request)); return SW_OK; } } @@ -167,24 +168,24 @@ int swRedis_recv_packet(Protocol *protocol, Connection *conn, String *buffer) { return SW_ERR; } -bool swRedis_format(String *buf) { +bool format(String *buf) { return buf->append(SW_STRL(SW_REDIS_RETURN_NIL)) == SW_OK; } -bool swRedis_format(String *buf, enum swRedis_reply_type type, const std::string &value) { - if (type == SW_REDIS_REPLY_STATUS) { +bool format(String *buf, enum ReplyType type, const std::string &value) { + if (type == REPLY_STATUS) { if (value.empty()) { return buf->append(SW_STRL("+OK\r\n")) == SW_OK; } else { return buf->format("+%.*s\r\n", value.length(), value.c_str()) > 0; } - } else if (type == SW_REDIS_REPLY_ERROR) { + } else if (type == REPLY_ERROR) { if (value.empty()) { return buf->append(SW_STRL("-ERR\r\n")) == SW_OK; } else { return buf->format("-%.*s\r\n", value.length(), value.c_str()) > 0; } - } else if (type == SW_REDIS_REPLY_STRING) { + } else if (type == REPLY_STRING) { if (value.empty() or value.length() > SW_REDIS_MAX_STRING_SIZE) { return false; } else { @@ -199,12 +200,12 @@ bool swRedis_format(String *buf, enum swRedis_reply_type type, const std::string return false; } -bool swRedis_format(String *buf, enum swRedis_reply_type type, long value) { +bool format(String *buf, enum ReplyType type, long value) { return buf->format(":%" PRId64 "\r\n", value) > 0; } -std::vector swRedis_parse(const char *data, size_t len) { - int state = SW_REDIS_RECEIVE_TOTAL_LINE; +std::vector parse(const char *data, size_t len) { + int state = STATE_RECEIVE_TOTAL_LINE; const char *p = data; const char *pe = p + len; @@ -214,33 +215,33 @@ std::vector swRedis_parse(const char *data, size_t len) { std::vector result; do { switch (state) { - case SW_REDIS_RECEIVE_TOTAL_LINE: - if (*p == '*' && (p = swRedis_get_number(p, &ret))) { - state = SW_REDIS_RECEIVE_LENGTH; + case STATE_RECEIVE_TOTAL_LINE: + if (*p == '*' && (p = get_number(p, &ret))) { + state = STATE_RECEIVE_LENGTH; break; } /* no break */ - case SW_REDIS_RECEIVE_LENGTH: - if (*p == '$' && (p = swRedis_get_number(p, &ret))) { + case STATE_RECEIVE_LENGTH: + if (*p == '$' && (p = get_number(p, &ret))) { if (ret == -1) { break; } length = ret; - state = SW_REDIS_RECEIVE_STRING; + state = STATE_RECEIVE_STRING; break; } // integer - else if (*p == ':' && (p = swRedis_get_number(p, &ret))) { + else if (*p == ':' && (p = get_number(p, &ret))) { result.push_back(std::to_string(ret)); break; } /* no break */ - case SW_REDIS_RECEIVE_STRING: + case STATE_RECEIVE_STRING: result.push_back(std::string(p, length)); p += length + SW_CRLF_LEN; - state = SW_REDIS_RECEIVE_LENGTH; + state = STATE_RECEIVE_LENGTH; break; default: @@ -250,3 +251,5 @@ std::vector swRedis_parse(const char *data, size_t len) { return result; } +} // namespace redis +} // namespace swoole diff --git a/src/protocol/websocket.cc b/src/protocol/websocket.cc index 1acc6a6b044..1264a70d606 100644 --- a/src/protocol/websocket.cc +++ b/src/protocol/websocket.cc @@ -253,7 +253,7 @@ int dispatch_frame(Protocol *proto, Socket *_socket, const char *data, uint32_t String *frame_buffer; int frame_length; - swListenPort *port; + ListenPort *port; size_t offset; switch (ws.header.OPCODE) { diff --git a/src/reactor/base.cc b/src/reactor/base.cc index 353363356dd..795bacbd123 100644 --- a/src/reactor/base.cc +++ b/src/reactor/base.cc @@ -134,7 +134,7 @@ Reactor::Reactor(int max_event, Type _type) { set_end_callback(Reactor::PRIORITY_SIGNAL_CALLBACK, [](Reactor *reactor) { if (sw_unlikely(reactor->singal_no)) { - swSignal_callback(reactor->singal_no); + swoole_signal_callback(reactor->singal_no); reactor->singal_no = 0; } }); diff --git a/src/reactor/kqueue.cc b/src/reactor/kqueue.cc index 2b47b77db66..46c8d845154 100644 --- a/src/reactor/kqueue.cc +++ b/src/reactor/kqueue.cc @@ -199,7 +199,6 @@ int ReactorKqueue::del(Socket *socket) { auto sobj = reinterpret_cast(socket); #endif - if (socket->removed) { swoole_error_log( SW_LOG_WARNING, SW_ERROR_EVENT_SOCKET_REMOVED, "failed to delete event[%d], has been removed", socket->fd); @@ -305,21 +304,15 @@ int ReactorKqueue::wait(struct timeval *timeo) { break; } case EVFILT_SIGNAL: { - struct sw_signal { - swSignalHandler handler; - uint16_t signo; - uint16_t active; - }; - struct sw_signal *sw_signal = (struct sw_signal *) udata; - - if (sw_signal->active) { - if (sw_signal->handler) { - sw_signal->handler(sw_signal->signo); + Signal *signal_data = (Signal *) udata; + if (signal_data->activated) { + if (signal_data->handler) { + signal_data->handler(signal_data->signo); } else { swoole_error_log(SW_LOG_WARNING, SW_ERROR_UNREGISTERED_SIGNAL, SW_UNREGISTERED_SIGNAL_FMT, - swSignal_str(sw_signal->signo)); + swoole_signal_to_str(signal_data->signo)); } } break; diff --git a/src/server/manager.cc b/src/server/manager.cc index 8ef9f22c70c..b3a85f8069e 100644 --- a/src/server/manager.cc +++ b/src/server/manager.cc @@ -114,7 +114,7 @@ int Server::start_manager_process() { SW_LOOP_N(task_worker_num) { worker = &gs->task_workers.workers[i]; create_worker(worker); - if (task_ipc_mode == SW_TASK_IPC_UNIXSOCK) { + if (task_ipc_mode == TASK_IPC_UNIXSOCK) { store_pipe_fd(worker->pipe_object); } } @@ -231,15 +231,15 @@ void Manager::start(Server *_server) { }; // for reload - swSignal_set(SIGHUP, nullptr); - swSignal_set(SIGCHLD, signal_handler); - swSignal_set(SIGTERM, signal_handler); - swSignal_set(SIGUSR1, signal_handler); - swSignal_set(SIGUSR2, signal_handler); - swSignal_set(SIGIO, signal_handler); - swSignal_set(SIGALRM, signal_handler); + swoole_signal_set(SIGHUP, nullptr); + swoole_signal_set(SIGCHLD, signal_handler); + swoole_signal_set(SIGTERM, signal_handler); + swoole_signal_set(SIGUSR1, signal_handler); + swoole_signal_set(SIGUSR2, signal_handler); + swoole_signal_set(SIGIO, signal_handler); + swoole_signal_set(SIGALRM, signal_handler); #ifdef SIGRTMIN - swSignal_set(SIGRTMIN, signal_handler); + swoole_signal_set(SIGRTMIN, signal_handler); #endif // swSignal_set(SIGINT, signal_handler); #if defined(__linux__) diff --git a/src/server/master.cc b/src/server/master.cc index 738cee8b20d..d2a1ab7dffd 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -376,10 +376,10 @@ int Server::create_task_workers() { key_t key = 0; swIPC_type ipc_mode; - if (task_ipc_mode == SW_TASK_IPC_MSGQUEUE || task_ipc_mode == SW_TASK_IPC_PREEMPTIVE) { + if (task_ipc_mode == TASK_IPC_MSGQUEUE || task_ipc_mode == TASK_IPC_PREEMPTIVE) { key = message_queue_key; ipc_mode = SW_IPC_MSGQUEUE; - } else if (task_ipc_mode == SW_TASK_IPC_STREAM) { + } else if (task_ipc_mode == TASK_IPC_STREAM) { ipc_mode = SW_IPC_SOCKET; } else { ipc_mode = SW_IPC_UNIXSOCK; @@ -618,12 +618,10 @@ int Server::start() { Server::Server(enum Mode _mode) { swoole_init(); - reactor_num = SW_REACTOR_NUM > SW_REACTOR_MAX_THREAD ? SW_REACTOR_MAX_THREAD : SW_REACTOR_NUM; - + reactor_num = SW_CPU_NUM > SW_REACTOR_MAX_THREAD ? SW_REACTOR_MAX_THREAD : SW_CPU_NUM; worker_num = SW_CPU_NUM; max_connection = SW_MIN(SW_MAX_CONNECTION, SwooleG.max_sockets); mode_ = _mode; - factory = nullptr; // http server #ifdef SW_HAVE_COMPRESSION @@ -830,7 +828,7 @@ void Server::destroy() { ::close(null_fd); null_fd = -1; } - swSignal_clear(); + swoole_signal_clear(); /** * shutdown status */ @@ -923,21 +921,21 @@ int Server::schedule_worker(int fd, SendData *data) { if (dispatch_func) { int id = dispatch_func(this, get_connection(fd), data); - if (id != SW_DISPATCH_RESULT_USERFUNC_FALLBACK) { + if (id != DISPATCH_RESULT_USERFUNC_FALLBACK) { return id; } } // polling mode - if (dispatch_mode == SW_DISPATCH_ROUND) { + if (dispatch_mode == DISPATCH_ROUND) { key = sw_atomic_fetch_add(&worker_round_id, 1); } // Using the FD touch access to hash - else if (dispatch_mode == SW_DISPATCH_FDMOD) { + else if (dispatch_mode == DISPATCH_FDMOD) { key = fd; } // Using the IP touch access to hash - else if (dispatch_mode == SW_DISPATCH_IPMOD) { + else if (dispatch_mode == DISPATCH_IPMOD) { Connection *conn = get_connection(fd); // UDP if (conn == nullptr) { @@ -957,14 +955,14 @@ int Server::schedule_worker(int fd, SendData *data) { key = conn->info.addr.inet_v6.sin6_addr.s6_addr32[3]; #endif } - } else if (dispatch_mode == SW_DISPATCH_UIDMOD) { + } else if (dispatch_mode == DISPATCH_UIDMOD) { Connection *conn = get_connection(fd); if (conn == nullptr || conn->uid == 0) { key = fd; } else { key = conn->uid; } - } else if (dispatch_mode == SW_DISPATCH_CO_CONN_LB) { + } else if (dispatch_mode == DISPATCH_CO_CONN_LB) { Connection *conn = get_connection(fd); if (conn == nullptr) { return key % worker_num; @@ -973,10 +971,10 @@ int Server::schedule_worker(int fd, SendData *data) { conn->worker_id = get_lowest_load_worker_id(); } return conn->worker_id; - } else if (dispatch_mode == SW_DISPATCH_CO_REQ_LB) { + } else if (dispatch_mode == DISPATCH_CO_REQ_LB) { return get_lowest_load_worker_id(); } - // Preemptive distribution + // deliver tasks to idle worker processes else { uint32_t i; bool found = false; @@ -1298,21 +1296,21 @@ bool Server::close(SessionId session_id, bool reset) { } void Server::init_signal_handler() { - swSignal_set(SIGPIPE, nullptr); - swSignal_set(SIGHUP, nullptr); + swoole_signal_set(SIGPIPE, nullptr); + swoole_signal_set(SIGHUP, nullptr); if (is_process_mode()) { - swSignal_set(SIGCHLD, Server_signal_handler); + swoole_signal_set(SIGCHLD, Server_signal_handler); } else { - swSignal_set(SIGIO, Server_signal_handler); + swoole_signal_set(SIGIO, Server_signal_handler); } - swSignal_set(SIGUSR1, Server_signal_handler); - swSignal_set(SIGUSR2, Server_signal_handler); - swSignal_set(SIGTERM, Server_signal_handler); + swoole_signal_set(SIGUSR1, Server_signal_handler); + swoole_signal_set(SIGUSR2, Server_signal_handler); + swoole_signal_set(SIGTERM, Server_signal_handler); #ifdef SIGRTMIN - swSignal_set(SIGRTMIN, Server_signal_handler); + swoole_signal_set(SIGRTMIN, Server_signal_handler); #endif // for test - swSignal_set(SIGVTALRM, Server_signal_handler); + swoole_signal_set(SIGVTALRM, Server_signal_handler); set_minfd(SwooleG.signal_fd); } @@ -1517,7 +1515,7 @@ ListenPort *Server::add_port(enum swSocket_type type, const char *host, int port } static void Server_signal_handler(int sig) { - swTraceLog(SW_TRACE_SERVER, "signal[%d] %s triggered in %d", sig, swSignal_str(sig), getpid()); + swTraceLog(SW_TRACE_SERVER, "signal[%d] %s triggered in %d", sig, swoole_signal_to_str(sig), getpid()); Server *serv = sw_server(); if (!SwooleG.running or !serv) { @@ -1541,7 +1539,7 @@ static void Server_signal_handler(int sig) { if (pid > 0 && pid == serv->gs->manager_pid) { swWarn("Fatal Error: manager process exit. status=%d, signal=[%s]", WEXITSTATUS(status), - swSignal_str(WTERMSIG(status))); + swoole_signal_to_str(WTERMSIG(status))); } break; /** diff --git a/src/server/port.cc b/src/server/port.cc index f4bb2682e44..6ef73e3dd98 100644 --- a/src/server/port.cc +++ b/src/server/port.cc @@ -663,7 +663,7 @@ static int Port_onRead_redis(Reactor *reactor, ListenPort *port, Event *event) { return SW_ERR; } - if (swRedis_recv_packet(protocol, conn, buffer) < 0) { + if (redis::recv_packet(protocol, conn, buffer) < 0) { conn->close_errno = errno; reactor->trigger_close_event(event); } diff --git a/src/server/process.cc b/src/server/process.cc index 1a02540d2cf..bc3353fb79e 100644 --- a/src/server/process.cc +++ b/src/server/process.cc @@ -69,7 +69,7 @@ ProcessFactory::~ProcessFactory() { } bool ProcessFactory::start() { - if (server_->dispatch_mode == SW_DISPATCH_STREAM) { + if (server_->dispatch_mode == Server::DISPATCH_STREAM) { server_->stream_socket_file = swoole_string_format(64, "/tmp/swoole.%d.sock", server_->gs->master_pid); if (server_->stream_socket_file == nullptr) { return false; @@ -156,9 +156,9 @@ bool ProcessFactory::dispatch(SendData *task) { int target_worker_id = server_->schedule_worker(fd, task); if (target_worker_id < 0) { switch (target_worker_id) { - case SW_DISPATCH_RESULT_DISCARD_PACKET: + case Server::DISPATCH_RESULT_DISCARD_PACKET: return false; - case SW_DISPATCH_RESULT_CLOSE_CONNECTION: + case Server::DISPATCH_RESULT_CLOSE_CONNECTION: // TODO: close connection return false; default: diff --git a/src/server/reactor_process.cc b/src/server/reactor_process.cc index af855d12ff6..bae53abe1fd 100644 --- a/src/server/reactor_process.cc +++ b/src/server/reactor_process.cc @@ -316,7 +316,7 @@ static int ReactorProcess_loop(ProcessPool *pool, Worker *worker) { #ifdef HAVE_SIGNALFD if (SwooleG.use_signalfd) { - swSignalfd_setup(SwooleTG.reactor); + swoole_signalfd_setup(SwooleTG.reactor); } #endif @@ -347,7 +347,7 @@ static int ReactorProcess_loop(ProcessPool *pool, Worker *worker) { // task workers if (serv->task_worker_num > 0) { - if (serv->task_ipc_mode == SW_TASK_IPC_UNIXSOCK) { + if (serv->task_ipc_mode == Server::TASK_IPC_UNIXSOCK) { for (uint32_t i = 0; i < serv->gs->task_workers.worker_num; i++) { serv->gs->task_workers.workers[i].pipe_master->set_nonblock(); } diff --git a/src/server/reactor_thread.cc b/src/server/reactor_thread.cc index 4c3d8c3b878..062d0dc2e48 100644 --- a/src/server/reactor_thread.cc +++ b/src/server/reactor_thread.cc @@ -532,7 +532,7 @@ void Server::init_reactor(Reactor *reactor) { // Read reactor->set_handler(SW_FD_SESSION | SW_EVENT_READ, ReactorThread_onRead); - if (dispatch_mode == SW_DISPATCH_STREAM) { + if (dispatch_mode == DISPATCH_STREAM) { Client::init_reactor(reactor); } @@ -721,7 +721,7 @@ int Server::start_reactor_threads() { #ifdef HAVE_SIGNALFD if (SwooleG.use_signalfd) { - swSignalfd_setup(reactor); + swoole_signalfd_setup(reactor); } #endif @@ -784,7 +784,7 @@ int Server::start_reactor_threads() { start_heartbeat_thread(); } - SwooleTG.type = SW_THREAD_MASTER; + SwooleTG.type = THREAD_MASTER; SwooleTG.update_time = 1; SwooleTG.reactor = reactor; @@ -901,7 +901,7 @@ static int ReactorThread_init(Server *serv, Reactor *reactor, uint16_t reactor_i */ static void ReactorThread_loop(Server *serv, int reactor_id) { SwooleTG.id = reactor_id; - SwooleTG.type = SW_THREAD_REACTOR; + SwooleTG.type = Server::THREAD_REACTOR; SwooleTG.buffer_stack = new String(SW_STACK_BUFFER_SIZE); ON_SCOPE_EXIT { @@ -934,7 +934,7 @@ static void ReactorThread_loop(Server *serv, int reactor_id) { } #endif - swSignal_none(); + swoole_signal_block_all(); if (ReactorThread_init(serv, reactor, reactor_id) < 0) { return; @@ -1079,9 +1079,9 @@ void Server::destroy_reactor_threads() { void Server::start_heartbeat_thread() { heartbeat_thread = std::thread([this]() { - swSignal_none(); + swoole_signal_block_all(); - SwooleTG.type = SW_THREAD_HEARTBEAT; + SwooleTG.type = THREAD_HEARTBEAT; SwooleTG.id = reactor_num; while (running) { diff --git a/src/server/task_worker.cc b/src/server/task_worker.cc index 8851d882cc2..6575ed6a0b2 100644 --- a/src/server/task_worker.cc +++ b/src/server/task_worker.cc @@ -39,14 +39,14 @@ void Server::init_task_workers() { * Make the task worker support asynchronous */ if (task_enable_coroutine) { - if (task_ipc_mode == SW_TASK_IPC_MSGQUEUE || task_ipc_mode == SW_TASK_IPC_PREEMPTIVE) { + if (task_ipc_mode == TASK_IPC_MSGQUEUE || task_ipc_mode == TASK_IPC_PREEMPTIVE) { swError("cannot use msgqueue when task_enable_coroutine is enable"); return; } pool->main_loop = TaskWorker_loop_async; } - if (task_ipc_mode == SW_TASK_IPC_PREEMPTIVE) { - pool->dispatch_mode = SW_DISPATCH_QUEUE; + if (task_ipc_mode == TASK_IPC_PREEMPTIVE) { + pool->schedule_by_sysvmsg = true; } } @@ -119,13 +119,13 @@ static void TaskWorker_signal_init(ProcessPool *pool) { */ SwooleG.use_signalfd = SwooleG.enable_signalfd; - swSignal_set(SIGHUP, nullptr); - swSignal_set(SIGPIPE, nullptr); - swSignal_set(SIGUSR1, Server::worker_signal_handler); - swSignal_set(SIGUSR2, nullptr); - swSignal_set(SIGTERM, Server::worker_signal_handler); + swoole_signal_set(SIGHUP, nullptr); + swoole_signal_set(SIGPIPE, nullptr); + swoole_signal_set(SIGUSR1, Server::worker_signal_handler); + swoole_signal_set(SIGUSR2, nullptr); + swoole_signal_set(SIGTERM, Server::worker_signal_handler); #ifdef SIGRTMIN - swSignal_set(SIGRTMIN, Server::worker_signal_handler); + swoole_signal_set(SIGRTMIN, Server::worker_signal_handler); #endif } diff --git a/src/server/worker.cc b/src/server/worker.cc index b00c06ecdbc..7cefb98edbf 100644 --- a/src/server/worker.cc +++ b/src/server/worker.cc @@ -43,16 +43,16 @@ void Server::worker_signal_init(void) { */ SwooleG.use_signalfd = SwooleG.enable_signalfd; - swSignal_set(SIGHUP, nullptr); - swSignal_set(SIGPIPE, SIG_IGN); - swSignal_set(SIGUSR1, nullptr); - swSignal_set(SIGUSR2, nullptr); + swoole_signal_set(SIGHUP, nullptr); + swoole_signal_set(SIGPIPE, SIG_IGN); + swoole_signal_set(SIGUSR1, nullptr); + swoole_signal_set(SIGUSR2, nullptr); // swSignal_set(SIGINT, Server::worker_signal_handler); - swSignal_set(SIGTERM, Server::worker_signal_handler); + swoole_signal_set(SIGTERM, Server::worker_signal_handler); // for test - swSignal_set(SIGVTALRM, Server::worker_signal_handler); + swoole_signal_set(SIGVTALRM, Server::worker_signal_handler); #ifdef SIGRTMIN - swSignal_set(SIGRTMIN, Server::worker_signal_handler); + swoole_signal_set(SIGRTMIN, Server::worker_signal_handler); #endif } @@ -381,7 +381,7 @@ void Server::worker_start_callback() { #ifdef HAVE_SIGNALFD if (SwooleG.use_signalfd && SwooleTG.reactor && SwooleG.signal_fd == 0) { - swSignalfd_setup(SwooleTG.reactor); + swoole_signalfd_setup(SwooleTG.reactor); } #endif @@ -559,7 +559,7 @@ int Server::start_event_worker(Worker *worker) { reactor->add(worker->pipe_worker, SW_EVENT_READ); reactor->set_handler(SW_FD_PIPE, Worker_onPipeReceive); - if (dispatch_mode == SW_DISPATCH_STREAM) { + if (dispatch_mode == DISPATCH_STREAM) { reactor->add(stream_socket, SW_EVENT_READ); reactor->set_handler(SW_FD_STREAM_SERVER, Worker_onStreamAccept); reactor->set_handler(SW_FD_STREAM, Worker_onStreamRead); @@ -568,7 +568,7 @@ int Server::start_event_worker(Worker *worker) { stream_protocol.package_max_length = UINT_MAX; stream_protocol.onPackage = Worker_onStreamPackage; buffer_pool = new std::queue; - } else if (dispatch_mode == SW_DISPATCH_CO_CONN_LB || dispatch_mode == SW_DISPATCH_CO_REQ_LB) { + } else if (dispatch_mode == DISPATCH_CO_CONN_LB || dispatch_mode == DISPATCH_CO_REQ_LB) { reactor->set_end_callback(Reactor::PRIORITY_WORKER_CALLBACK, [worker](Reactor *) { worker->coroutine_num = Coroutine::count(); }); } From 301557fdf91f20c5446af13089bbc6eff648cdb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Wed, 4 Aug 2021 13:43:54 +0800 Subject: [PATCH 199/936] Refactor logger (#4351) * Optimize naming * Optimize naming[2] * Optimize naming[3] * Optimize naming[4] --- core-tests/include/httplib_server.h | 2 +- core-tests/src/_lib/server.cpp | 4 +- core-tests/src/core/channel.cpp | 8 +- core-tests/src/lock/lock.cpp | 2 +- core-tests/src/memory/ringbuffer.cpp | 2 +- core-tests/src/network/stream.cpp | 2 +- core-tests/src/os/pipe.cpp | 2 +- core-tests/src/server/buffer.cpp | 2 +- core-tests/src/server/http.cpp | 2 +- core-tests/src/server/server.cpp | 8 +- examples/cpp/repeat.cc | 8 +- examples/cpp/test_server.cc | 30 ++++---- ext-src/php_swoole_curl.h | 2 +- ext-src/php_swoole_http.h | 2 +- ext-src/php_swoole_mysql_proto.h | 16 ++-- ext-src/swoole_client.cc | 2 +- ext-src/swoole_coroutine.cc | 10 +-- ext-src/swoole_coroutine_system.cc | 6 +- ext-src/swoole_curl.cc | 16 ++-- ext-src/swoole_event.cc | 2 +- ext-src/swoole_http2_client_coro.cc | 34 ++++----- ext-src/swoole_http2_server.cc | 38 +++++----- ext-src/swoole_http_client_coro.cc | 22 +++--- ext-src/swoole_http_request.cc | 22 +++--- ext-src/swoole_http_response.cc | 8 +- ext-src/swoole_http_server.cc | 4 +- ext-src/swoole_http_server_coro.cc | 2 +- ext-src/swoole_mysql_coro.cc | 44 +++++------ ext-src/swoole_mysql_proto.cc | 34 ++++----- ext-src/swoole_process.cc | 2 +- ext-src/swoole_redis_coro.cc | 2 +- ext-src/swoole_redis_server.cc | 2 +- ext-src/swoole_server.cc | 10 +-- ext-src/swoole_websocket_server.cc | 10 +-- include/swoole_coroutine.h | 4 +- include/swoole_coroutine_channel.h | 4 +- include/swoole_coroutine_socket.h | 4 +- include/swoole_file.h | 2 +- include/swoole_http2.h | 2 +- include/swoole_log.h | 40 +++++----- include/swoole_server.h | 4 +- include/swoole_socket.h | 8 +- include/swoole_ssl.h | 4 +- src/core/base.cc | 38 +++++----- src/core/channel.cc | 4 +- src/core/log.cc | 14 ++-- src/core/string.cc | 8 +- src/core/timer.cc | 14 ++-- src/coroutine/base.cc | 4 +- src/coroutine/channel.cc | 8 +- src/coroutine/context.cc | 7 +- src/coroutine/socket.cc | 24 +++--- src/coroutine/system.cc | 16 ++-- src/lock/mutex.cc | 4 +- src/memory/buffer.cc | 4 +- src/memory/global_memory.cc | 6 +- src/memory/ring_buffer.cc | 8 +- src/memory/shared_memory.cc | 4 +- src/memory/table.cc | 10 +-- src/network/client.cc | 18 ++--- src/network/dns.cc | 30 ++++---- src/network/socket.cc | 106 +++++++++++++-------------- src/network/stream.cc | 2 +- src/os/async_thread.cc | 20 ++--- src/os/base.cc | 10 +-- src/os/file.cc | 10 +-- src/os/msg_queue.cc | 10 +-- src/os/pipe.cc | 2 +- src/os/process_pool.cc | 50 ++++++------- src/os/sendfile.cc | 8 +- src/os/signal.cc | 18 ++--- src/os/timer.cc | 4 +- src/os/unix_socket.cc | 2 +- src/protocol/base.cc | 10 +-- src/protocol/dtls.cc | 12 +-- src/protocol/redis.cc | 8 +- src/protocol/ssl.cc | 50 ++++++------- src/protocol/websocket.cc | 16 ++-- src/reactor/base.cc | 10 +-- src/reactor/epoll.cc | 20 ++--- src/reactor/kqueue.cc | 30 ++++---- src/reactor/poll.cc | 18 ++--- src/reactor/select.cc | 14 ++-- src/server/base.cc | 22 +++--- src/server/manager.cc | 36 ++++----- src/server/master.cc | 86 +++++++++++----------- src/server/port.cc | 40 +++++----- src/server/process.cc | 18 ++--- src/server/reactor_process.cc | 16 ++-- src/server/reactor_thread.cc | 32 ++++---- src/server/task_worker.cc | 30 ++++---- src/server/worker.cc | 28 +++---- src/wrapper/timer.cc | 18 ++--- thirdparty/php/curl/interface.cc | 2 +- thirdparty/php/curl/multi.cc | 2 +- 95 files changed, 708 insertions(+), 707 deletions(-) diff --git a/core-tests/include/httplib_server.h b/core-tests/include/httplib_server.h index 4f807ad275b..489893f2837 100644 --- a/core-tests/include/httplib_server.h +++ b/core-tests/include/httplib_server.h @@ -758,7 +758,7 @@ inline bool Server::listen_internal() { } else if (svr_sock_->errCode == ECANCELED) { break; } else { - swWarn("accept failed, Error: %s[%d]", svr_sock_->errMsg, svr_sock_->errCode); + swoole_warning("accept failed, Error: %s[%d]", svr_sock_->errMsg, svr_sock_->errCode); break; } } diff --git a/core-tests/src/_lib/server.cpp b/core-tests/src/_lib/server.cpp index 5955a5f557e..4c7aa55e690 100644 --- a/core-tests/src/_lib/server.cpp +++ b/core-tests/src/_lib/server.cpp @@ -37,12 +37,12 @@ Server::Server(std::string _host, int _port, swoole::Server::Mode _mode, int _ty serv.private_data_2 = this; if (!listen(host, port, (swSocket_type) type)) { - swWarn("listen(%s:%d) fail[error=%d].", host.c_str(), port, errno); + swoole_warning("listen(%s:%d) fail[error=%d].", host.c_str(), port, errno); exit(0); } if (serv.create() < 0) { - swWarn("create server fail[error=%d].", errno); + swoole_warning("create server fail[error=%d].", errno); exit(0); } } diff --git a/core-tests/src/core/channel.cpp b/core-tests/src/core/channel.cpp index 7cb06bd6e4e..c0a8df25966 100644 --- a/core-tests/src/core/channel.cpp +++ b/core-tests/src/core/channel.cpp @@ -36,14 +36,14 @@ TEST(channel, push) { char buf[8000]; int n = swoole_random_bytes(buf, (rand() % (sizeof(buf) / 2)) + (sizeof(buf) / 2)); if (n <= 0) { - swTrace("no enough data, n=%d, errno=%d\n", n, errno); + swoole_trace("no enough data, n=%d, errno=%d\n", n, errno); continue; } m[index++] = string(buf, n); bytes += n; } - swTrace("size=%lu", m.size()); + swoole_trace("size=%lu", m.size()); thread t1([&]() { auto next = m.find(0); @@ -52,7 +52,7 @@ TEST(channel, push) { while (bytes < N) { if (c->push(next->second.c_str(), next->second.length()) == SW_OK) { - swTrace("[PUSH] index=%d, size=%lu", index, next->second.length()); + swoole_trace("[PUSH] index=%d, size=%lu", index, next->second.length()); bytes += next->second.length(); next = m.find(index++); if (next == m.end()) { @@ -71,7 +71,7 @@ TEST(channel, push) { while (bytes < N) { int retval = c->pop(buf, sizeof(buf)); if (retval > 0) { - swTrace("[POP] index=%d, size=%d", index, retval); + swoole_trace("[POP] index=%d, size=%d", index, retval); string &_data = m[index++]; bytes += retval; ASSERT_EQ(_data, string(buf, retval)); diff --git a/core-tests/src/lock/lock.cpp b/core-tests/src/lock/lock.cpp index 24e9b426797..e803fa8ec22 100644 --- a/core-tests/src/lock/lock.cpp +++ b/core-tests/src/lock/lock.cpp @@ -107,7 +107,7 @@ TEST(lock, shared) { int status; pid_t _pid = waitpid(pid, &status, 0); if (_pid != pid ) { - swWarn("error pid=%d", _pid); + swoole_warning("error pid=%d", _pid); } ASSERT_EQ(*_num, magic_num); } diff --git a/core-tests/src/memory/ringbuffer.cpp b/core-tests/src/memory/ringbuffer.cpp index 5a2ba192107..00f7d327f21 100644 --- a/core-tests/src/memory/ringbuffer.cpp +++ b/core-tests/src/memory/ringbuffer.cpp @@ -75,7 +75,7 @@ static void thread_write(void) { } while (yield_count < 100); if (!ptr) { - swWarn("alloc failed. index=%d, break", i); + swoole_warning("alloc failed. index=%d, break", i); } ASSERT_NE(ptr, nullptr); diff --git a/core-tests/src/network/stream.cpp b/core-tests/src/network/stream.cpp index c1bd7e432eb..7fa068e4a3e 100644 --- a/core-tests/src/network/stream.cpp +++ b/core-tests/src/network/stream.cpp @@ -31,7 +31,7 @@ TEST(stream, send) { swListenPort *port = serv.add_port(SW_SOCK_TCP, TEST_HOST, TEST_PORT); if (!port) { - swWarn("listen failed, [error=%d]", swoole_get_last_error()); + swoole_warning("listen failed, [error=%d]", swoole_get_last_error()); exit(2); } diff --git a/core-tests/src/os/pipe.cpp b/core-tests/src/os/pipe.cpp index 5238acf7493..f966e0cb2ef 100644 --- a/core-tests/src/os/pipe.cpp +++ b/core-tests/src/os/pipe.cpp @@ -19,7 +19,7 @@ TEST(pipe, unixsock) { // 1 ret = p.read(buf, sizeof(buf)); if (ret < 0) { - swSysWarn("read() failed."); + swoole_sys_warning("read() failed."); } ASSERT_GT(ret, 0); ASSERT_EQ(strcmp("hello world1", buf), 0); diff --git a/core-tests/src/server/buffer.cpp b/core-tests/src/server/buffer.cpp index 74479d0675c..3b077fe8bd0 100644 --- a/core-tests/src/server/buffer.cpp +++ b/core-tests/src/server/buffer.cpp @@ -33,7 +33,7 @@ TEST(server, send_buffer) { swListenPort *port = serv.add_port(SW_SOCK_TCP, TEST_HOST, 0); if (!port) { - swWarn("listen failed, [error=%d]", swoole_get_last_error()); + swoole_warning("listen failed, [error=%d]", swoole_get_last_error()); exit(2); } diff --git a/core-tests/src/server/http.cpp b/core-tests/src/server/http.cpp index b80754b7ac0..f5bd757127d 100644 --- a/core-tests/src/server/http.cpp +++ b/core-tests/src/server/http.cpp @@ -100,7 +100,7 @@ static void test_run_server(function fn) { swListenPort *port = serv.add_port(SW_SOCK_TCP, TEST_HOST, 0); if (!port) { - swWarn("listen failed, [error=%d]", swoole_get_last_error()); + swoole_warning("listen failed, [error=%d]", swoole_get_last_error()); exit(2); } port->open_http_protocol = 1; diff --git a/core-tests/src/server/server.cpp b/core-tests/src/server/server.cpp index dab84458a1d..e1b9f897496 100644 --- a/core-tests/src/server/server.cpp +++ b/core-tests/src/server/server.cpp @@ -131,7 +131,7 @@ TEST(server, process) { ListenPort *port = serv.add_port(SW_SOCK_TCP, TEST_HOST, 0); if (!port) { - swWarn("listen failed, [error=%d]", swoole_get_last_error()); + swoole_warning("listen failed, [error=%d]", swoole_get_last_error()); exit(2); } @@ -187,7 +187,7 @@ TEST(server, ssl) { ListenPort *port = serv.add_port((enum swSocket_type )(SW_SOCK_TCP | SW_SOCK_SSL), TEST_HOST, 0); if (!port) { - swWarn("listen failed, [error=%d]", swoole_get_last_error()); + swoole_warning("listen failed, [error=%d]", swoole_get_last_error()); exit(2); } @@ -250,7 +250,7 @@ TEST(server, dtls) { ListenPort *port = serv.add_port((enum swSocket_type )(SW_SOCK_UDP | SW_SOCK_SSL), TEST_HOST, 0); if (!port) { - swWarn("listen failed, [error=%d]", swoole_get_last_error()); + swoole_warning("listen failed, [error=%d]", swoole_get_last_error()); exit(2); } @@ -307,7 +307,7 @@ TEST(server, task_worker) { swListenPort *port = serv.add_port(SW_SOCK_TCP, TEST_HOST, 0); if (!port) { - swWarn("listen failed, [error=%d]", swoole_get_last_error()); + swoole_warning("listen failed, [error=%d]", swoole_get_last_error()); exit(2); } diff --git a/examples/cpp/repeat.cc b/examples/cpp/repeat.cc index 1f6249fb79d..fb4587ef458 100644 --- a/examples/cpp/repeat.cc +++ b/examples/cpp/repeat.cc @@ -22,7 +22,7 @@ int main(int argc, char **argv) { serv.onPacket = [](Server *serv, RecvData *req) { return SW_OK; }; serv.onWorkerStart = [](Server *serv, int worker_id) { - swNotice("WorkerStart[%d]PID=%d, serv=%p,", worker_id, getpid(), serv); + swoole_notice("WorkerStart[%d]PID=%d, serv=%p,", worker_id, getpid(), serv); swoole_timer_after( 1000, [serv](Timer *, TimerNode *tnode) { @@ -42,7 +42,7 @@ int main(int argc, char **argv) { ListenPort *port = serv.add_port(SW_SOCK_TCP, "127.0.0.1", 9501); if (!port) { - swWarn("listen failed, [error=%d]", swoole_get_last_error()); + swoole_warning("listen failed, [error=%d]", swoole_get_last_error()); exit(2); } @@ -52,12 +52,12 @@ int main(int argc, char **argv) { memcpy(port->protocol.package_eof, SW_STRL("\r\n\r\n")); if (serv.create()) { - swWarn("create server fail[error=%d]", swoole_get_last_error()); + swoole_warning("create server fail[error=%d]", swoole_get_last_error()); exit(1); } if (serv.start() < 0) { - swWarn("start server fail[error=%d]", swoole_get_last_error()); + swoole_warning("start server fail[error=%d]", swoole_get_last_error()); exit(3); } } diff --git a/examples/cpp/test_server.cc b/examples/cpp/test_server.cc index 6bfc9547125..fe3fca106b4 100644 --- a/examples/cpp/test_server.cc +++ b/examples/cpp/test_server.cc @@ -62,7 +62,7 @@ int main(int argc, char **argv) { swListenPort *port = serv.add_port(SW_SOCK_TCP, "127.0.0.1", 9501); if (!port) { - swWarn("listen failed, [error=%d]", swoole_get_last_error()); + swoole_warning("listen failed, [error=%d]", swoole_get_last_error()); exit(2); } @@ -72,23 +72,23 @@ int main(int argc, char **argv) { memcpy(port->protocol.package_eof, SW_STRL("\r\n\r\n")); if (serv.create()) { - swWarn("create server fail[error=%d]", swoole_get_last_error()); + swoole_warning("create server fail[error=%d]", swoole_get_last_error()); exit(1); } if (serv.start() < 0) { - swWarn("start server fail[error=%d]", swoole_get_last_error()); + swoole_warning("start server fail[error=%d]", swoole_get_last_error()); exit(3); } return 0; } void my_onWorkerStart(Server *serv, int worker_id) { - swNotice("WorkerStart[%d]PID=%d", worker_id, getpid()); + swoole_notice("WorkerStart[%d]PID=%d", worker_id, getpid()); } void my_onWorkerStop(Server *serv, int worker_id) { - swNotice("WorkerStop[%d]PID=%d", worker_id, getpid()); + swoole_notice("WorkerStop[%d]PID=%d", worker_id, getpid()); } int my_onReceive(Server *serv, RecvData *req) { @@ -101,7 +101,7 @@ int my_onReceive(Server *serv, RecvData *req) { memcpy(req_data, req->data, req->info.len); swoole::rtrim(req_data, req->info.len); - swNotice("onReceive[%d]: ip=%s|port=%d Data=%s|Len=%d", + swoole_notice("onReceive[%d]: ip=%s|port=%d Data=%s|Len=%d", g_receive_count, conn->info.get_ip(), conn->info.get_port(), @@ -111,9 +111,9 @@ int my_onReceive(Server *serv, RecvData *req) { int n = sw_snprintf(resp_data, SW_IPC_BUFFER_SIZE, "Server: %.*s\n", req->info.len, req_data); if (!serv->send(req->info.fd, resp_data, n)) { - swNotice("send to client fail. errno=%d", errno); + swoole_notice("send to client fail. errno=%d", errno); } else { - swNotice("send %d bytes to client success. data=%s", n, resp_data); + swoole_notice("send %d bytes to client success. data=%s", n, resp_data); } return SW_OK; } @@ -142,7 +142,7 @@ int my_onPacket(Server *serv, RecvData *req) { char *data = packet->data; uint32_t length = packet->length; - swNotice("Packet[client=%s:%d, %d bytes]: data=%.*s", address, port, length, length, data); + swoole_notice("Packet[client=%s:%d, %d bytes]: data=%.*s", address, port, length, length, data); char resp_data[SW_IPC_BUFFER_SIZE]; int n = sw_snprintf(resp_data, SW_IPC_BUFFER_SIZE, "Server: %.*s", length, data); @@ -150,26 +150,26 @@ int my_onPacket(Server *serv, RecvData *req) { ret = serv_socket->sendto(address, port, resp_data, n); if (ret < 0) { - swNotice("send to client fail. errno=%d", errno); + swoole_notice("send to client fail. errno=%d", errno); } else { - swNotice("send %d bytes to client success. data=%s", n, resp_data); + swoole_notice("send %d bytes to client success. data=%s", n, resp_data); } return SW_OK; } void my_onStart(Server *serv) { - swNotice("Server is running"); + swoole_notice("Server is running"); } void my_onShutdown(Server *serv) { - swNotice("Server is shutdown"); + swoole_notice("Server is shutdown"); } void my_onConnect(Server *serv, DataHead *info) { - swNotice("PID=%d\tConnect fd=%ld|reactor_id=%d", getpid(), info->fd, info->reactor_id); + swoole_notice("PID=%d\tConnect fd=%ld|reactor_id=%d", getpid(), info->fd, info->reactor_id); } void my_onClose(Server *serv, DataHead *info) { - swNotice("PID=%d\tClose fd=%ld|reactor_id=%d", getpid(), info->fd, info->reactor_id); + swoole_notice("PID=%d\tClose fd=%ld|reactor_id=%d", getpid(), info->fd, info->reactor_id); } diff --git a/ext-src/php_swoole_curl.h b/ext-src/php_swoole_curl.h index 5f159b50632..e2950364c50 100644 --- a/ext-src/php_swoole_curl.h +++ b/ext-src/php_swoole_curl.h @@ -138,7 +138,7 @@ class Multi { Coroutine *check_bound_co() { if (co) { - swFatalError(SW_ERROR_CO_HAS_BEEN_BOUND, "cURL is executing, cannot be operated"); + swoole_fatal_error(SW_ERROR_CO_HAS_BEEN_BOUND, "cURL is executing, cannot be operated"); return nullptr; } return Coroutine::get_current_safe(); diff --git a/ext-src/php_swoole_http.h b/ext-src/php_swoole_http.h index 0ff0946fda6..d0969f20b6c 100644 --- a/ext-src/php_swoole_http.h +++ b/ext-src/php_swoole_http.h @@ -363,7 +363,7 @@ class HeaderSet { memcpy(nv->value, value, value_len); nv->valuelen = value_len; nv->flags = flags | NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE; - swTraceLog(SW_TRACE_HTTP2, + swoole_trace_log(SW_TRACE_HTTP2, "name=(%zu)[%.*s], value=(%zu)[%.*s]", name_len, (int) name_len, diff --git a/ext-src/php_swoole_mysql_proto.h b/ext-src/php_swoole_mysql_proto.h index 858f55a4605..95b71c8c85d 100644 --- a/ext-src/php_swoole_mysql_proto.h +++ b/ext-src/php_swoole_mysql_proto.h @@ -310,9 +310,9 @@ enum sw_mysql_server_status_flags #define swMysqlPacketDump(length, number, data, title) \ if (SW_LOG_TRACE >= sw_logger()->get_level() && (SW_TRACE_MYSQL_CLIENT & SwooleG.trace_flags)) \ { \ - swDebug("+----------+------------+-------------------------------------------------------+"); \ - swDebug("| P#%-6u | L%-9u | %-10u %42s |", number, SW_MYSQL_PACKET_HEADER_SIZE + length, length, title); \ - swHexDump(data, length); \ + swoole_debug("+----------+------------+-------------------------------------------------------+"); \ + swoole_debug("| P#%-6u | L%-9u | %-10u %42s |", number, SW_MYSQL_PACKET_HEADER_SIZE + length, length, title); \ + swoole_hex_dump(data, length); \ } #else #define swMysqlPacketDump(length, number, data, title) @@ -486,7 +486,7 @@ class server_status inline bool more_results_exists() { bool b = !!(status & SW_MYSQL_SERVER_MORE_RESULTS_EXISTS); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "More results exist = %u", b); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "More results exist = %u", b); return b; } }; @@ -689,7 +689,7 @@ class lcb_packet : public server_packet { swMysqlPacketDump(header.length, header.number, data, "Protocol::LengthCodedBinary"); bytes_length = read_lcb(data + SW_MYSQL_PACKET_HEADER_SIZE, &length, &nul); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "binary_length=%u, nul=%u", header.length, nul); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "binary_length=%u, nul=%u", header.length, nul); } bool is_vaild() { @@ -798,7 +798,7 @@ class row_data_text { body = *pp + read_lcb(*pp, &length, &nul); *pp = body + length; - swTraceLog( + swoole_trace_log( SW_TRACE_MYSQL_CLIENT, "text[%" PRIu64 "]: %.*s%s", length, (int) SW_MIN(64, length), body, @@ -970,7 +970,7 @@ class statement : public server_packet data += 1; // warning_count (2) -- number of warnings warning_count = sw_mysql_uint2korr2korr(data); - swTraceLog( + swoole_trace_log( SW_TRACE_MYSQL_CLIENT, "statement_id=%u, field_count=%u, param_count=%u, warning_count=%u", id, field_count, param_count, warning_count ); @@ -989,7 +989,7 @@ class null_bitmap { map = new char[size]; memcpy(map, p, size); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "null_count=%u", size); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "null_count=%u", size); } inline bool is_null(size_t i) { diff --git a/ext-src/swoole_client.cc b/ext-src/swoole_client.cc index ff414733b88..8f457dfc275 100644 --- a/ext-src/swoole_client.cc +++ b/ext-src/swoole_client.cc @@ -488,7 +488,7 @@ bool php_swoole_client_check_setting(Client *cli, zval *zset) { _open_tcp_nodelay: if (cli->socket->socket_type == SW_SOCK_TCP || cli->socket->socket_type == SW_SOCK_TCP6) { if (cli->socket->set_tcp_nodelay() < 0) { - swSysWarn("setsockopt(%d, TCP_NODELAY) failed", cli->socket->fd); + swoole_sys_warning("setsockopt(%d, TCP_NODELAY) failed", cli->socket->fd); } } } diff --git a/ext-src/swoole_coroutine.cc b/ext-src/swoole_coroutine.cc index b123a51648f..08b149444a2 100644 --- a/ext-src/swoole_coroutine.cc +++ b/ext-src/swoole_coroutine.cc @@ -282,7 +282,7 @@ static int coro_end_silence_handler(zend_execute_data *execute_data) { static void coro_interrupt_resume(void *data) { Coroutine *co = (Coroutine *) data; if (co && !co->is_end()) { - swTraceLog(SW_TRACE_COROUTINE, "interrupt_callback cid=%ld ", co->get_cid()); + swoole_trace_log(SW_TRACE_COROUTINE, "interrupt_callback cid=%ld ", co->get_cid()); co->resume(); } } @@ -584,7 +584,7 @@ void PHPCoroutine::restore_task(PHPContext *task) { void PHPCoroutine::on_yield(void *arg) { PHPContext *task = (PHPContext *) arg; PHPContext *origin_task = get_origin_context(task); - swTraceLog( + swoole_trace_log( SW_TRACE_COROUTINE, "php_coro_yield from cid=%ld to cid=%ld", task->co->get_cid(), task->co->get_origin_cid()); save_task(task); restore_task(origin_task); @@ -596,7 +596,7 @@ void PHPCoroutine::on_resume(void *arg) { save_task(current_task); restore_task(task); record_last_msec(task); - swTraceLog(SW_TRACE_COROUTINE, + swoole_trace_log(SW_TRACE_COROUTINE, "php_coro_resume from cid=%ld to cid=%ld", Coroutine::get_current_cid(), task->co->get_cid()); @@ -634,7 +634,7 @@ void PHPCoroutine::on_close(void *arg) { vm_stack_destroy(); restore_task(origin_task); - swTraceLog(SW_TRACE_COROUTINE, + swoole_trace_log(SW_TRACE_COROUTINE, "coro close cid=%ld and resume to %ld, %zu remained. usage size: %zu. malloc size: %zu", cid, origin_cid, @@ -731,7 +731,7 @@ void PHPCoroutine::main_func(void *arg) { save_vm_stack(task); record_last_msec(task); - swTraceLog(SW_TRACE_COROUTINE, + swoole_trace_log(SW_TRACE_COROUTINE, "Create coro id: %ld, origin cid: %ld, coro total count: %zu, heap size: %zu", task->co->get_cid(), task->co->get_origin_cid(), diff --git a/ext-src/swoole_coroutine_system.cc b/ext-src/swoole_coroutine_system.cc index 55177dd4809..7371b2c5ce5 100644 --- a/ext-src/swoole_coroutine_system.cc +++ b/ext-src/swoole_coroutine_system.cc @@ -233,7 +233,7 @@ PHP_METHOD(swoole_coroutine_system, fread) { } buf[length] = 0; int ret = -1; - swTrace("fd=%d, length=%ld", fd, length); + swoole_trace("fd=%d, length=%ld", fd, length); php_swoole_check_reactor(); bool async_success = swoole::coroutine::async([&]() { while (1) { @@ -297,7 +297,7 @@ PHP_METHOD(swoole_coroutine_system, fgets) { } int ret = 0; - swTrace("fd=%d, length=%ld", fd, stream->readbuflen); + swoole_trace("fd=%d, length=%ld", fd, stream->readbuflen); php_swoole_check_reactor(); bool async_success = swoole::coroutine::async([&]() { char *data = fgets((char *) stream->readbuf, stream->readbuflen, file); @@ -352,7 +352,7 @@ PHP_METHOD(swoole_coroutine_system, fwrite) { } int ret = -1; - swTrace("fd=%d, length=%ld", fd, length); + swoole_trace("fd=%d, length=%ld", fd, length); php_swoole_check_reactor(); bool async_success = swoole::coroutine::async([&]() { while (1) { diff --git a/ext-src/swoole_curl.cc b/ext-src/swoole_curl.cc index 58c75793516..a888ba52975 100644 --- a/ext-src/swoole_curl.cc +++ b/ext-src/swoole_curl.cc @@ -94,7 +94,7 @@ void Multi::del_event(CURL *cp, void *socket_ptr, curl_socket_t sockfd) { Handle *handle = get_handle(cp); handle->socket = nullptr; - swTraceLog(SW_TRACE_CO_CURL, SW_ECHO_RED " handle=%p, curl=%p, fd=%d", "[DEL]", handle, cp, sockfd); + swoole_trace_log(SW_TRACE_CO_CURL, SW_ECHO_RED " handle=%p, curl=%p, fd=%d", "[DEL]", handle, cp, sockfd); } void Multi::set_event(CURL *cp, void *socket_ptr, curl_socket_t sockfd, int action) { @@ -118,7 +118,7 @@ void Multi::set_event(CURL *cp, void *socket_ptr, curl_socket_t sockfd, int acti Handle *handle = get_handle(cp); handle->action = action; - swTraceLog( + swoole_trace_log( SW_TRACE_CO_CURL, SW_ECHO_GREEN " handle=%p, curl=%p, fd=%d, events=%d", "[ADD]", handle, cp, sockfd, events); } @@ -208,7 +208,7 @@ CURLcode Multi::read_info() { curl_easy_cleanup." */ return message->data.result; default: - swWarn("CURLMSG default"); + swoole_warning("CURLMSG default"); break; } } @@ -251,7 +251,7 @@ long Multi::select(php_curlm *mh, double timeout) { if (swoole_event_add(handle->socket, get_event(handle->action)) == SW_OK) { event_count_++; } - swTraceLog(SW_TRACE_CO_CURL, "resume, handle=%p, curl=%p, fd=%d", handle, ch->cp, handle->socket->get_fd()); + swoole_trace_log(SW_TRACE_CO_CURL, "resume, handle=%p, curl=%p, fd=%d", handle, ch->cp, handle->socket->get_fd()); } } set_timer(); @@ -273,7 +273,7 @@ long Multi::select(php_curlm *mh, double timeout) { } Handle *handle = get_handle(ch->cp); if (handle && handle->socket && !handle->socket->removed && swoole_event_del(handle->socket) == SW_OK) { - swTraceLog( + swoole_trace_log( SW_TRACE_CO_CURL, "suspend, handle=%p, curl=%p, fd=%d", handle, ch->cp, handle->socket->get_fd()); event_count_--; } @@ -283,13 +283,13 @@ long Multi::select(php_curlm *mh, double timeout) { if (selector->timer_callback) { selector->timer_callback = false; curl_multi_socket_action(multi_handle_, -1, 0, &running_handles_); - swTraceLog(SW_TRACE_CO_CURL, "socket_action[timer], running_handles=%d", running_handles_); + swoole_trace_log(SW_TRACE_CO_CURL, "socket_action[timer], running_handles=%d", running_handles_); } for (auto iter = selector->active_handles.begin(); iter != selector->active_handles.end(); iter++) { Handle *handle = *iter; curl_multi_socket_action(multi_handle_, handle->event_fd, handle->event_bitmask, &running_handles_); - swTraceLog(SW_TRACE_CO_CURL, "socket_action[socket], running_handles=%d", running_handles_); + swoole_trace_log(SW_TRACE_CO_CURL, "socket_action[socket], running_handles=%d", running_handles_); } selector->active_handles.clear(); @@ -298,7 +298,7 @@ long Multi::select(php_curlm *mh, double timeout) { } void Multi::callback(Handle *handle, int event_bitmask) { - swTraceLog(SW_TRACE_CO_CURL, "callback, handle=%p, event_bitmask=%d", handle, event_bitmask); + swoole_trace_log(SW_TRACE_CO_CURL, "callback, handle=%p, event_bitmask=%d", handle, event_bitmask); if (handle) { last_sockfd = handle->event_fd; } else { diff --git a/ext-src/swoole_event.cc b/ext-src/swoole_event.cc index d87d6233bfe..df72baa30f8 100644 --- a/ext-src/swoole_event.cc +++ b/ext-src/swoole_event.cc @@ -241,7 +241,7 @@ int php_swoole_reactor_init() { } } if (!sw_reactor()) { - swTraceLog(SW_TRACE_PHP, "init reactor"); + swoole_trace_log(SW_TRACE_PHP, "init reactor"); if (swoole_event_init(SW_EVENTLOOP_WAIT_EXIT) < 0) { php_swoole_fatal_error(E_ERROR, "Unable to create event-loop reactor"); diff --git a/ext-src/swoole_http2_client_coro.cc b/ext-src/swoole_http2_client_coro.cc index 7a3b3dc934c..5b0cb43ff1e 100644 --- a/ext-src/swoole_http2_client_coro.cc +++ b/ext-src/swoole_http2_client_coro.cc @@ -532,19 +532,19 @@ enum swReturn_code Client::parse_frame(zval *return_value, bool pipeline_read) { return SW_ERROR; } } - swTraceLog(SW_TRACE_HTTP2, "setting: header_compression_table_max=%u", value); + swoole_trace_log(SW_TRACE_HTTP2, "setting: header_compression_table_max=%u", value); break; case SW_HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS: remote_settings.max_concurrent_streams = value; - swTraceLog(SW_TRACE_HTTP2, "setting: max_concurrent_streams=%u", value); + swoole_trace_log(SW_TRACE_HTTP2, "setting: max_concurrent_streams=%u", value); break; case SW_HTTP2_SETTINGS_INIT_WINDOW_SIZE: remote_settings.window_size = value; - swTraceLog(SW_TRACE_HTTP2, "setting: init_send_window=%u", value); + swoole_trace_log(SW_TRACE_HTTP2, "setting: init_send_window=%u", value); break; case SW_HTTP2_SETTINGS_MAX_FRAME_SIZE: remote_settings.max_frame_size = value; - swTraceLog(SW_TRACE_HTTP2, "setting: max_frame_size=%u", value); + swoole_trace_log(SW_TRACE_HTTP2, "setting: max_frame_size=%u", value); break; case SW_HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: if (value != remote_settings.max_header_list_size) { @@ -558,11 +558,11 @@ enum swReturn_code Client::parse_frame(zval *return_value, bool pipeline_read) { } */ } - swTraceLog(SW_TRACE_HTTP2, "setting: max_header_list_size=%u", value); + swoole_trace_log(SW_TRACE_HTTP2, "setting: max_header_list_size=%u", value); break; default: // disable warning and ignore it because some websites are not following http2 protocol totally - // swWarn("unknown option[%d]: %d", id, value); + // swoole_warning("unknown option[%d]: %d", id, value); break; } buf += sizeof(id) + sizeof(value); @@ -652,7 +652,7 @@ enum swReturn_code Client::parse_frame(zval *return_value, bool pipeline_read) { Stream *stream = get_stream(stream_id); // The stream is not found or has closed if (stream == nullptr) { - swNotice("http2 stream#%d belongs to an unknown type or it never registered", stream_id); + swoole_notice("http2 stream#%d belongs to an unknown type or it never registered", stream_id); return SW_CONTINUE; } if (type == SW_HTTP2_TYPE_HEADERS) { @@ -668,7 +668,7 @@ enum swReturn_code Client::parse_frame(zval *return_value, bool pipeline_read) { #ifdef SW_HAVE_ZLIB if (stream->gzip) { if (php_swoole_zlib_decompress(&stream->gzip_stream, stream->gzip_buffer, buf, length) == SW_ERR) { - swWarn("decompress failed"); + swoole_warning("decompress failed"); return SW_ERROR; } stream->buffer->append(stream->gzip_buffer->str, stream->gzip_buffer->length); @@ -842,7 +842,7 @@ static PHP_METHOD(swoole_http2_client_coro, set) { bool Client::send_window_update(int stream_id, uint32_t size) { char frame[SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_WINDOW_UPDATE_SIZE]; - swTraceLog(SW_TRACE_HTTP2, "[" SW_ECHO_YELLOW "] stream_id=%d, size=%d", "WINDOW_UPDATE", stream_id, size); + swoole_trace_log(SW_TRACE_HTTP2, "[" SW_ECHO_YELLOW "] stream_id=%d, size=%d", "WINDOW_UPDATE", stream_id, size); *(uint32_t *) ((char *) frame + SW_HTTP2_FRAME_HEADER_SIZE) = htonl(size); Http2::set_frame_header(frame, SW_HTTP2_TYPE_WINDOW_UPDATE, SW_HTTP2_WINDOW_UPDATE_SIZE, 0, stream_id); return send(frame, SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_WINDOW_UPDATE_SIZE); @@ -886,7 +886,7 @@ bool Client::send_setting() { memcpy(p, &value, sizeof(value)); p += 4; - swTraceLog(SW_TRACE_HTTP2, "[" SW_ECHO_GREEN "]\t[length=%d]", Http2::get_type(SW_HTTP2_TYPE_SETTINGS), 18); + swoole_trace_log(SW_TRACE_HTTP2, "[" SW_ECHO_GREEN "]\t[length=%d]", Http2::get_type(SW_HTTP2_TYPE_SETTINGS), 18); return send(frame, SW_HTTP2_FRAME_HEADER_SIZE + 18); } @@ -924,7 +924,7 @@ int Client::parse_header(Stream *stream, int flags, char *in, size_t inlen) { in += (size_t) rv; inlen -= (size_t) rv; - swTraceLog(SW_TRACE_HTTP2, + swoole_trace_log(SW_TRACE_HTTP2, "[" SW_ECHO_GREEN "] %.*s[%lu]: %.*s[%lu]", "HEADER", (int) nv.namelen, @@ -958,7 +958,7 @@ int Client::parse_header(Stream *stream, int flags, char *in, size_t inlen) { * zlib decode */ if (Z_OK != inflateInit2(&stream->gzip_stream, MAX_WBITS + 16)) { - swWarn("inflateInit2() failed"); + swoole_warning("inflateInit2() failed"); return SW_ERR; } } else @@ -1188,7 +1188,7 @@ uint32_t Client::send_request(zval *zrequest) { Http2::set_frame_header(buffer, SW_HTTP2_TYPE_HEADERS, bytes, flags, stream->stream_id); - swTraceLog(SW_TRACE_HTTP2, + swoole_trace_log(SW_TRACE_HTTP2, "[" SW_ECHO_GREEN ", STREAM#%d] length=%zd", Http2::get_type(SW_HTTP2_TYPE_HEADERS), stream->stream_id, @@ -1219,7 +1219,7 @@ uint32_t Client::send_request(zval *zrequest) { len = str_zpost_data.len(); } - swTraceLog(SW_TRACE_HTTP2, + swoole_trace_log(SW_TRACE_HTTP2, "[" SW_ECHO_GREEN ", END, STREAM#%d] length=%zu", Http2::get_type(SW_HTTP2_TYPE_DATA), stream->stream_id, @@ -1260,7 +1260,7 @@ bool Client::write_data(uint32_t stream_id, zval *zdata, bool end) { return false; } Http2::set_frame_header(buffer, SW_HTTP2_TYPE_DATA, len, flag, stream_id); - swTraceLog(SW_TRACE_HTTP2, + swoole_trace_log(SW_TRACE_HTTP2, "[" SW_ECHO_GREEN ",%s STREAM#%d] length=%zu", Http2::get_type(SW_HTTP2_TYPE_DATA), end ? " END," : "", @@ -1274,7 +1274,7 @@ bool Client::write_data(uint32_t stream_id, zval *zdata, bool end) { } else { zend::String data(zdata); Http2::set_frame_header(buffer, SW_HTTP2_TYPE_DATA, data.len(), flag, stream_id); - swTraceLog(SW_TRACE_HTTP2, + swoole_trace_log(SW_TRACE_HTTP2, "[" SW_ECHO_GREEN ",%s STREAM#%d] length=%zu", Http2::get_type(SW_HTTP2_TYPE_DATA), end ? " END," : "", @@ -1302,7 +1302,7 @@ bool Client::send_goaway_frame(zend_long error_code, const char *debug_data, siz if (debug_data_len > 0) { memcpy(frame + SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_GOAWAY_SIZE, debug_data, debug_data_len); } - swTraceLog(SW_TRACE_HTTP2, + swoole_trace_log(SW_TRACE_HTTP2, "[" SW_ECHO_GREEN "] Send: last-sid=%u, error-code=%ld", Http2::get_type(SW_HTTP2_TYPE_GOAWAY), last_stream_id, diff --git a/ext-src/swoole_http2_server.cc b/ext-src/swoole_http2_server.cc index 414f954dc6e..ba4ab9d40ec 100644 --- a/ext-src/swoole_http2_server.cc +++ b/ext-src/swoole_http2_server.cc @@ -57,7 +57,7 @@ Http2Stream::~Stream() { void Http2Stream::reset(uint32_t error_code) { char frame[SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_RST_STREAM_SIZE]; - swTraceLog(SW_TRACE_HTTP2, "send [" SW_ECHO_YELLOW "] stream_id=%u, error_code=%u", "RST_STREAM", id, error_code); + swoole_trace_log(SW_TRACE_HTTP2, "send [" SW_ECHO_YELLOW "] stream_id=%u, error_code=%u", "RST_STREAM", id, error_code); *(uint32_t *) ((char *) frame + SW_HTTP2_FRAME_HEADER_SIZE) = htonl(error_code); http2::set_frame_header(frame, SW_HTTP2_TYPE_RST_STREAM, SW_HTTP2_RST_STREAM_SIZE, 0, id); ctx->send(ctx, frame, SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_RST_STREAM_SIZE); @@ -94,7 +94,7 @@ Http2Session::~Session() { static void http2_server_send_window_update(HttpContext *ctx, uint32_t stream_id, uint32_t size) { char frame[SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_WINDOW_UPDATE_SIZE]; - swTraceLog(SW_TRACE_HTTP2, "send [" SW_ECHO_YELLOW "] stream_id=%u, size=%u", "WINDOW_UPDATE", stream_id, size); + swoole_trace_log(SW_TRACE_HTTP2, "send [" SW_ECHO_YELLOW "] stream_id=%u, size=%u", "WINDOW_UPDATE", stream_id, size); *(uint32_t *) ((char *) frame + SW_HTTP2_FRAME_HEADER_SIZE) = htonl(size); Http2::set_frame_header(frame, SW_HTTP2_TYPE_WINDOW_UPDATE, SW_HTTP2_WINDOW_UPDATE_SIZE, 0, stream_id); ctx->send(ctx, frame, SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_WINDOW_UPDATE_SIZE); @@ -127,7 +127,7 @@ static ssize_t http2_build_trailer(HttpContext *ctx, uchar *buffer) { if (!deflater) { int ret = nghttp2_hd_deflate_new2(&deflater, SW_HTTP2_DEFAULT_HEADER_TABLE_SIZE, php_nghttp2_mem()); if (ret != 0) { - swWarn("nghttp2_hd_deflate_new2() failed with error: %s", nghttp2_strerror(ret)); + swoole_warning("nghttp2_hd_deflate_new2() failed with error: %s", nghttp2_strerror(ret)); return -1; } client->deflater = deflater; @@ -143,7 +143,7 @@ static ssize_t http2_build_trailer(HttpContext *ctx, uchar *buffer) { */ rv = nghttp2_hd_deflate_hd(deflater, (uchar *) buffer, buflen, trailer.get(), trailer.len()); if (rv < 0) { - swWarn("nghttp2_hd_deflate_hd() failed with error: %s", nghttp2_strerror((int) rv)); + swoole_warning("nghttp2_hd_deflate_hd() failed with error: %s", nghttp2_strerror((int) rv)); return -1; } return rv; @@ -350,7 +350,7 @@ static ssize_t http2_build_header(HttpContext *ctx, uchar *buffer, size_t body_l if (!deflater) { ret = nghttp2_hd_deflate_new2(&deflater, client->header_table_size, php_nghttp2_mem()); if (ret != 0) { - swWarn("nghttp2_hd_deflate_new2() failed with error: %s", nghttp2_strerror(ret)); + swoole_warning("nghttp2_hd_deflate_new2() failed with error: %s", nghttp2_strerror(ret)); return -1; } client->deflater = deflater; @@ -366,7 +366,7 @@ static ssize_t http2_build_header(HttpContext *ctx, uchar *buffer, size_t body_l */ ssize_t rv = nghttp2_hd_deflate_hd(deflater, (uchar *) buffer, buflen, headers.get(), headers.len()); if (rv < 0) { - swWarn("nghttp2_hd_deflate_hd() failed with error: %s", nghttp2_strerror((int) rv)); + swoole_warning("nghttp2_hd_deflate_hd() failed with error: %s", nghttp2_strerror((int) rv)); return -1; } @@ -527,7 +527,7 @@ static bool swoole_http2_server_respond(HttpContext *ctx, String *body) { // If send_yield is not supported, ignore flow control if (ctx->co_socket || !((Server *) ctx->private_data)->send_yield) { if (body->length > client->send_window) { - swWarn("The data sent exceeded send_window"); + swoole_warning("The data sent exceeded send_window"); } if (!stream->send_body(body, end_stream, client->max_frame_size)) { error = true; @@ -553,7 +553,7 @@ static bool swoole_http2_server_respond(HttpContext *ctx, String *body) { error = !stream->send_body(body, false, client->max_frame_size, body->offset, send_len); } if (!error) { - swTraceLog(SW_TRACE_HTTP2, "body: send length=%zu", send_len); + swoole_trace_log(SW_TRACE_HTTP2, "body: send length=%zu", send_len); body->offset += send_len; if (send_len > stream->send_window) { @@ -661,7 +661,7 @@ static int http2_parse_header(Http2Session *client, HttpContext *ctx, int flags, if (!inflater) { int ret = nghttp2_hd_inflate_new2(&inflater, php_nghttp2_mem()); if (ret != 0) { - swWarn("nghttp2_hd_inflate_new2() failed, Error: %s[%d]", nghttp2_strerror(ret), ret); + swoole_warning("nghttp2_hd_inflate_new2() failed, Error: %s[%d]", nghttp2_strerror(ret), ret); return SW_ERR; } client->inflater = inflater; @@ -685,7 +685,7 @@ static int http2_parse_header(Http2Session *client, HttpContext *ctx, int flags, rv = nghttp2_hd_inflate_hd(inflater, &nv, &inflate_flags, (uchar *) in, inlen, 1); if (rv < 0) { - swWarn("inflate failed, Error: %s[%zd]", nghttp2_strerror(rv), rv); + swoole_warning("inflate failed, Error: %s[%zd]", nghttp2_strerror(rv), rv); return SW_ERR; } @@ -695,7 +695,7 @@ static int http2_parse_header(Http2Session *client, HttpContext *ctx, int flags, inlen -= proclen; if (inflate_flags & NGHTTP2_HD_INFLATE_EMIT) { - swTraceLog( + swoole_trace_log( SW_TRACE_HTTP2, "Header: " SW_ECHO_BLUE "[%zu]: %s[%zu]", nv.name, nv.namelen, nv.value, nv.valuelen); if (nv.name[0] == ':') { @@ -739,7 +739,7 @@ static int http2_parse_header(Http2Session *client, HttpContext *ctx, int flags, } else if (SW_STRCASECT((char *) nv.value, nv.valuelen, "multipart/form-data")) { int boundary_len = nv.valuelen - (sizeof("multipart/form-data; boundary=") - 1); if (boundary_len <= 0) { - swWarn("invalid multipart/form-data body fd:%ld", ctx->fd); + swoole_warning("invalid multipart/form-data body fd:%ld", ctx->fd); return SW_ERR; } ctx->parse_form_data((char *) nv.value + nv.valuelen - boundary_len, boundary_len); @@ -816,34 +816,34 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { if (client->deflater) { int ret = nghttp2_hd_deflate_change_table_size(client->deflater, value); if (ret != 0) { - swWarn("nghttp2_hd_deflate_change_table_size() failed, errno=%d, errmsg=%s", + swoole_warning("nghttp2_hd_deflate_change_table_size() failed, errno=%d, errmsg=%s", ret, nghttp2_strerror(ret)); return SW_ERR; } } } - swTraceLog(SW_TRACE_HTTP2, "setting: header_table_size=%u", value); + swoole_trace_log(SW_TRACE_HTTP2, "setting: header_table_size=%u", value); break; case SW_HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS: client->max_concurrent_streams = value; - swTraceLog(SW_TRACE_HTTP2, "setting: max_concurrent_streams=%u", value); + swoole_trace_log(SW_TRACE_HTTP2, "setting: max_concurrent_streams=%u", value); break; case SW_HTTP2_SETTINGS_INIT_WINDOW_SIZE: client->send_window = value; - swTraceLog(SW_TRACE_HTTP2, "setting: init_send_window=%u", value); + swoole_trace_log(SW_TRACE_HTTP2, "setting: init_send_window=%u", value); break; case SW_HTTP2_SETTINGS_MAX_FRAME_SIZE: client->max_frame_size = value; - swTraceLog(SW_TRACE_HTTP2, "setting: max_frame_size=%u", value); + swoole_trace_log(SW_TRACE_HTTP2, "setting: max_frame_size=%u", value); break; case SW_HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: // client->max_header_list_size = value; // useless now - swTraceLog(SW_TRACE_HTTP2, "setting: max_header_list_size=%u", value); + swoole_trace_log(SW_TRACE_HTTP2, "setting: max_header_list_size=%u", value); break; default: // disable warning and ignore it because some websites are not following http2 protocol totally - // swWarn("unknown option[%d]: %d", id, value); + // swoole_warning("unknown option[%d]: %d", id, value); break; } buf += sizeof(id) + sizeof(value); diff --git a/ext-src/swoole_http_client_coro.cc b/ext-src/swoole_http_client_coro.cc index cf7c7fa825e..832650386a8 100644 --- a/ext-src/swoole_http_client_coro.cc +++ b/ext-src/swoole_http_client_coro.cc @@ -563,17 +563,17 @@ static int http_parser_on_body(swoole_http_parser *parser, const char *at, size_ char *download_file_name = http->download_file_name.val(); std::unique_ptr fp(new File(download_file_name, O_CREAT | O_WRONLY, 0664)); if (!fp->ready()) { - swSysWarn("open(%s, O_CREAT | O_WRONLY) failed", download_file_name); + swoole_sys_warning("open(%s, O_CREAT | O_WRONLY) failed", download_file_name); return false; } if (http->download_offset == 0) { if (!fp->truncate(0)) { - swSysWarn("ftruncate(%s) failed", download_file_name); + swoole_sys_warning("ftruncate(%s) failed", download_file_name); return false; } } else { if (!fp->set_offest(http->download_offset)) { - swSysWarn("fseek(%s, %jd) failed", download_file_name, (intmax_t) http->download_offset); + swoole_sys_warning("fseek(%s, %jd) failed", download_file_name, (intmax_t) http->download_offset); return false; } } @@ -651,7 +651,7 @@ bool HttpClient::decompress_response(const char *in, size_t in_len) { // gzip_stream.total_out = 0; status = inflateInit2(&gzip_stream, encoding); if (status != Z_OK) { - swWarn("inflateInit2() failed by %s", zError(status)); + swoole_warning("inflateInit2() failed by %s", zError(status)); return false; } gzip_stream_active = true; @@ -692,7 +692,7 @@ bool HttpClient::decompress_response(const char *in, size_t in_len) { goto _retry; } - swWarn("HttpClient::decompress_response failed by %s", zError(status)); + swoole_warning("HttpClient::decompress_response failed by %s", zError(status)); body->length = reserved_body_length; return false; } @@ -702,7 +702,7 @@ bool HttpClient::decompress_response(const char *in, size_t in_len) { if (!brotli_decoder_state) { brotli_decoder_state = BrotliDecoderCreateInstance(php_brotli_alloc, php_brotli_free, nullptr); if (!brotli_decoder_state) { - swWarn("BrotliDecoderCreateInstance() failed"); + swoole_warning("BrotliDecoderCreateInstance() failed"); return false; } } @@ -726,11 +726,11 @@ bool HttpClient::decompress_response(const char *in, size_t in_len) { return true; } else if (result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) { if (!body->extend()) { - swWarn("BrotliDecoderDecompressStream() failed, no memory is available"); + swoole_warning("BrotliDecoderDecompressStream() failed, no memory is available"); break; } } else { - swWarn("BrotliDecoderDecompressStream() failed, %s", + swoole_warning("BrotliDecoderDecompressStream() failed, %s", BrotliDecoderErrorString(BrotliDecoderGetErrorCode(brotli_decoder_state))); break; } @@ -744,7 +744,7 @@ bool HttpClient::decompress_response(const char *in, size_t in_len) { break; } - swWarn("HttpClient::decompress_response unknown compress method [%d]", compress_method); + swoole_warning("HttpClient::decompress_response unknown compress method [%d]", compress_method); return false; } #endif @@ -1332,7 +1332,7 @@ bool HttpClient::send() { } } - swTraceLog(SW_TRACE_HTTP_CLIENT, + swoole_trace_log(SW_TRACE_HTTP_CLIENT, "to [%s:%u%s] by fd#%d in cid#%ld with [%zu] bytes: <str, retval); - swTraceLog(SW_TRACE_HTTP_CLIENT, + swoole_trace_log(SW_TRACE_HTTP_CLIENT, "parsed_n=%ld, retval=%ld, total_bytes=%ld, completed=%d", parsed_n, retval, diff --git a/ext-src/swoole_http_request.cc b/ext-src/swoole_http_request.cc index 218bfcc175d..a87281d33e6 100644 --- a/ext-src/swoole_http_request.cc +++ b/ext-src/swoole_http_request.cc @@ -291,7 +291,7 @@ void swoole_http_parse_cookie(zval *zarray, const char *at, size_t length) { if (state <= 0 && *_c == '=') { klen = i - j + 1; if (klen >= SW_HTTP_COOKIE_KEYLEN) { - swWarn("cookie[%.*s...] name length %d is exceed the max name len %d", + swoole_warning("cookie[%.*s...] name length %d is exceed the max name len %d", 8, (char *) at + j, klen, @@ -306,7 +306,7 @@ void swoole_http_parse_cookie(zval *zarray, const char *at, size_t length) { } else if (state == 1 && *_c == ';') { vlen = i - j; if (vlen >= SW_HTTP_COOKIE_VALLEN) { - swWarn("cookie[%s]'s value[v=%.*s...] length %d is exceed the max value len %d", + swoole_warning("cookie[%s]'s value[v=%.*s...] length %d is exceed the max value len %d", keybuf, 8, (char *) at + j, @@ -337,13 +337,13 @@ void swoole_http_parse_cookie(zval *zarray, const char *at, size_t length) { if (j < (off_t) length) { vlen = i - j; if (klen >= SW_HTTP_COOKIE_KEYLEN) { - swWarn( + swoole_warning( "cookie[%.*s...] name length %d is exceed the max name len %d", 8, keybuf, klen, SW_HTTP_COOKIE_KEYLEN); return; } keybuf[klen - 1] = 0; if (vlen >= SW_HTTP_COOKIE_VALLEN) { - swWarn("cookie[%s]'s value[v=%.*s...] length %d is exceed the max value len %d", + swoole_warning("cookie[%s]'s value[v=%.*s...] length %d is exceed the max value len %d", keybuf, 8, (char *) at + j, @@ -417,7 +417,7 @@ static int http_request_on_header_value(swoole_http_parser *parser, const char * } } if (boundary_len <= 0) { - swWarn("invalid multipart/form-data body fd:%ld", ctx->fd); + swoole_warning("invalid multipart/form-data body fd:%ld", ctx->fd); /* make it same with protocol error */ ctx->parser.state = s_dead; return -1; @@ -427,7 +427,7 @@ static int http_request_on_header_value(swoole_http_parser *parser, const char * boundary_str++; boundary_len -= 2; } - swTraceLog(SW_TRACE_HTTP, "form_data, boundary_str=%s", boundary_str); + swoole_trace_log(SW_TRACE_HTTP, "form_data, boundary_str=%s", boundary_str); ctx->parse_form_data(boundary_str, boundary_len); } } @@ -526,7 +526,7 @@ static int multipart_body_on_header_value(multipart_parser *p, const char *at, s } if (Z_STRLEN_P(zform_name) >= SW_HTTP_FORM_KEYLEN) { - swWarn("form_name[%s] is too large", Z_STRVAL_P(zform_name)); + swoole_warning("form_name[%s] is too large", Z_STRVAL_P(zform_name)); ret = -1; goto _end; } @@ -544,7 +544,7 @@ static int multipart_body_on_header_value(multipart_parser *p, const char *at, s // upload file else { if (Z_STRLEN_P(zfilename) >= SW_HTTP_FORM_KEYLEN) { - swWarn("filename[%s] is too large", Z_STRVAL_P(zfilename)); + swoole_warning("filename[%s] is too large", Z_STRVAL_P(zfilename)); ret = -1; goto _end; } @@ -603,7 +603,7 @@ static int multipart_body_on_data(multipart_parser *p, const char *at, size_t le fclose((FILE *) p->fp); p->fp = nullptr; - swSysWarn("write upload file failed"); + swoole_sys_warning("write upload file failed"); } return 0; } @@ -648,7 +648,7 @@ static int multipart_body_on_header_complete(multipart_parser *p) { FILE *fp = fdopen(tmpfile, "wb+"); if (fp == nullptr) { add_assoc_long(z_multipart_header, "error", HTTP_UPLOAD_ERR_NO_TMP_DIR); - swSysWarn("fopen(%s) failed", file_path); + swoole_sys_warning("fopen(%s) failed", file_path); return 0; } @@ -805,7 +805,7 @@ static int http_request_message_complete(swoole_http_parser *parser) { } ctx->completed = 1; - swTraceLog(SW_TRACE_HTTP, "request body length=%ld", content_length); + swoole_trace_log(SW_TRACE_HTTP, "request body length=%ld", content_length); return 1; /* return from execute */ } diff --git a/ext-src/swoole_http_response.cc b/ext-src/swoole_http_response.cc index a908e5d4f35..197f756b9fc 100644 --- a/ext-src/swoole_http_response.cc +++ b/ext-src/swoole_http_response.cc @@ -608,7 +608,7 @@ int swoole_http_response_compress(const char *data, size_t length, int method, i input_buffer, &encoded_size, encoded_buffer)) { - swWarn("BrotliEncoderCompress() failed"); + swoole_warning("BrotliEncoderCompress() failed"); return SW_ERR; } else { swoole_zlib_buffer->length = encoded_size; @@ -617,7 +617,7 @@ int swoole_http_response_compress(const char *data, size_t length, int method, i } #endif else { - swWarn("Unknown compression method"); + swoole_warning("Unknown compression method"); return SW_ERR; } #ifdef SW_HAVE_ZLIB @@ -644,7 +644,7 @@ int swoole_http_response_compress(const char *data, size_t length, int method, i status = deflateInit2(&zstream, level, Z_DEFLATED, encoding, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); if (status != Z_OK) { - swWarn("deflateInit2() failed, Error: [%d]", status); + swoole_warning("deflateInit2() failed, Error: [%d]", status); return SW_ERR; } @@ -656,7 +656,7 @@ int swoole_http_response_compress(const char *data, size_t length, int method, i status = deflate(&zstream, Z_FINISH); deflateEnd(&zstream); if (status != Z_STREAM_END) { - swWarn("deflate() failed, Error: [%d]", status); + swoole_warning("deflate() failed, Error: [%d]", status); return SW_ERR; } diff --git a/ext-src/swoole_http_server.cc b/ext-src/swoole_http_server.cc index 730667782da..667454d37af 100644 --- a/ext-src/swoole_http_server.cc +++ b/ext-src/swoole_http_server.cc @@ -71,7 +71,7 @@ int php_swoole_http_server_onReceive(Server *serv, RecvData *req) { zval *zdata = &ctx->request.zdata; php_swoole_get_recv_data(serv, zdata, req); - swTraceLog(SW_TRACE_SERVER, + swoole_trace_log(SW_TRACE_SERVER, "http request from %ld with %d bytes: <send(ctx, SW_STRL(SW_HTTP_BAD_REQUEST_PACKET)); #endif ctx->close(ctx); - swNotice("request is illegal and it has been discarded, %ld bytes unprocessed", Z_STRLEN_P(zdata) - parsed_n); + swoole_notice("request is illegal and it has been discarded, %ld bytes unprocessed", Z_STRLEN_P(zdata) - parsed_n); goto _dtor_and_return; } diff --git a/ext-src/swoole_http_server_coro.cc b/ext-src/swoole_http_server_coro.cc index 7d7edf834a9..2c5ba26ed22 100644 --- a/ext-src/swoole_http_server_coro.cc +++ b/ext-src/swoole_http_server_coro.cc @@ -593,7 +593,7 @@ static PHP_METHOD(swoole_http_server_coro, onAccept) { size_t parsed_n = ctx->parse(buffer->str + buffer->offset, buffer->length - buffer->offset); buffer->offset += parsed_n; - swTraceLog(SW_TRACE_CO_HTTP_SERVER, + swoole_trace_log(SW_TRACE_CO_HTTP_SERVER, "parsed_n=%ld, length=%ld, offset=%ld, completed=%d", parsed_n, buffer->length, diff --git a/ext-src/swoole_mysql_coro.cc b/ext-src/swoole_mysql_coro.cc index 574e9c028b6..778a030ba6e 100644 --- a/ext-src/swoole_mysql_coro.cc +++ b/ext-src/swoole_mysql_coro.cc @@ -610,7 +610,7 @@ const char *mysql_client::recv_length(size_t need_length, const bool try_to_recy off_t offset = buffer->offset; // save offset instead of buffer point (due to realloc) size_t read_n = buffer->length - buffer->offset; // readable bytes if (try_to_recycle && read_n == 0) { - swTraceLog(SW_TRACE_MYSQL_CLIENT, + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "mysql buffer will be recycled, length=%zu, offset=%jd", buffer->length, (intmax_t) offset); @@ -628,7 +628,7 @@ const char *mysql_client::recv_length(size_t need_length, const bool try_to_recy non_sql_error(MYSQLND_CR_OUT_OF_MEMORY, strerror(ENOMEM)); return nullptr; } else { - swTraceLog(SW_TRACE_MYSQL_CLIENT, "mysql buffer extend to %zu", buffer->size); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "mysql buffer extend to %zu", buffer->size); } } retval = socket->recv(buffer->str + buffer->length, buffer->size - buffer->length); @@ -653,7 +653,7 @@ const char *mysql_client::recv_packet() { return nullptr; } length = mysql::packet::get_length(p); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "recv packet length=%u, number=%u", length, mysql::packet::get_number(p)); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "recv packet length=%u, number=%u", length, mysql::packet::get_number(p)); p = recv_length(length); if (sw_unlikely(!p)) { return nullptr; @@ -921,12 +921,12 @@ void mysql_client::handle_row_data_text(zval *return_value, mysql::row_data *row } } if (row_data->text.nul || field->type == SW_MYSQL_TYPE_NULL) { - swTraceLog(SW_TRACE_MYSQL_CLIENT, "%.*s is null", field->name_length, field->name); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "%.*s is null", field->name_length, field->name); RETURN_NULL(); } else { RETVAL_STRINGL(p, row_data->text.length); _return: - swTraceLog(SW_TRACE_MYSQL_CLIENT, + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "%.*s=[%lu]%.*s%s", field->name_length, field->name, @@ -1005,7 +1005,7 @@ void mysql_client::handle_strict_type(zval *ztext, mysql::field_packet *field) { break; } default: { - swWarn("unknown type[%d] for field [%.*s].", field->type, field->name_length, field->name); + swoole_warning("unknown type[%d] for field [%.*s].", field->type, field->name_length, field->name); break; } } @@ -1380,7 +1380,7 @@ void mysql_statement::fetch(zval *return_value) { /* to check Null-Bitmap @see https://dev.mysql.com/doc/internals/en/null-bitmap.html */ if (null_bitmap.is_null(i) || field->type == SW_MYSQL_TYPE_NULL) { - swTraceLog(SW_TRACE_MYSQL_CLIENT, "%.*s is null", field->name_length, field->name); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "%.*s is null", field->name_length, field->name); add_assoc_null_ex(return_value, field->name, field->name_length); continue; } @@ -1428,26 +1428,26 @@ void mysql_statement::fetch(zval *return_value) { std::string datetime = mysql::datetime(p, row_data.text.length, field->decimals); add_assoc_stringl_ex( return_value, field->name, field->name_length, (char *) datetime.c_str(), datetime.length()); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "%.*s=%s", field->name_length, field->name, datetime.c_str()); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "%.*s=%s", field->name_length, field->name, datetime.c_str()); break; } case SW_MYSQL_TYPE_TIME: { std::string time = mysql::time(p, row_data.text.length, field->decimals); add_assoc_stringl_ex( return_value, field->name, field->name_length, (char *) time.c_str(), time.length()); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "%.*s=%s", field->name_length, field->name, time.c_str()); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "%.*s=%s", field->name_length, field->name, time.c_str()); break; } case SW_MYSQL_TYPE_DATE: { std::string date = mysql::date(p, row_data.text.length); add_assoc_stringl_ex( return_value, field->name, field->name_length, (char *) date.c_str(), date.length()); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "%.*s=%s", field->name_length, field->name, date.c_str()); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "%.*s=%s", field->name_length, field->name, date.c_str()); break; } case SW_MYSQL_TYPE_YEAR: { add_assoc_long_ex(return_value, field->name, field->name_length, sw_mysql_uint2korr2korr(p)); - swTraceLog( + swoole_trace_log( SW_TRACE_MYSQL_CLIENT, "%.*s=%d", field->name_length, field->name, sw_mysql_uint2korr2korr(p)); break; } @@ -1455,51 +1455,51 @@ void mysql_statement::fetch(zval *return_value) { case SW_MYSQL_TYPE_TINY: if (field->flags & SW_MYSQL_UNSIGNED_FLAG) { add_assoc_long_ex(return_value, field->name, field->name_length, *(uint8_t *) p); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "%.*s=%u", field->name_length, field->name, *(uint8_t *) p); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "%.*s=%u", field->name_length, field->name, *(uint8_t *) p); } else { add_assoc_long_ex(return_value, field->name, field->name_length, *(int8_t *) p); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "%.*s=%d", field->name_length, field->name, *(int8_t *) p); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "%.*s=%d", field->name_length, field->name, *(int8_t *) p); } break; case SW_MYSQL_TYPE_SHORT: if (field->flags & SW_MYSQL_UNSIGNED_FLAG) { add_assoc_long_ex(return_value, field->name, field->name_length, *(uint16_t *) p); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "%.*s=%u", field->name_length, field->name, *(uint16_t *) p); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "%.*s=%u", field->name_length, field->name, *(uint16_t *) p); } else { add_assoc_long_ex(return_value, field->name, field->name_length, *(int16_t *) p); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "%.*s=%d", field->name_length, field->name, *(int16_t *) p); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "%.*s=%d", field->name_length, field->name, *(int16_t *) p); } break; case SW_MYSQL_TYPE_INT24: case SW_MYSQL_TYPE_LONG: if (field->flags & SW_MYSQL_UNSIGNED_FLAG) { add_assoc_long_ex(return_value, field->name, field->name_length, *(uint32_t *) p); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "%.*s=%u", field->name_length, field->name, *(uint32_t *) p); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "%.*s=%u", field->name_length, field->name, *(uint32_t *) p); } else { add_assoc_long_ex(return_value, field->name, field->name_length, *(int32_t *) p); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "%.*s=%d", field->name_length, field->name, *(int32_t *) p); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "%.*s=%d", field->name_length, field->name, *(int32_t *) p); } break; case SW_MYSQL_TYPE_LONGLONG: if (field->flags & SW_MYSQL_UNSIGNED_FLAG) { add_assoc_ulong_safe_ex(return_value, field->name, field->name_length, *(uint64_t *) p); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "%.*s=%lu", field->name_length, field->name, *(uint64_t *) p); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "%.*s=%lu", field->name_length, field->name, *(uint64_t *) p); } else { add_assoc_long_ex(return_value, field->name, field->name_length, *(int64_t *) p); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "%.*s=%ld", field->name_length, field->name, *(int64_t *) p); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "%.*s=%ld", field->name_length, field->name, *(int64_t *) p); } break; case SW_MYSQL_TYPE_FLOAT: { double dv = sw_php_math_round(*(float *) p, 5, PHP_ROUND_HALF_DOWN); add_assoc_double_ex(return_value, field->name, field->name_length, dv); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "%.*s=%.7f", field->name_length, field->name, dv); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "%.*s=%.7f", field->name_length, field->name, dv); } break; case SW_MYSQL_TYPE_DOUBLE: { add_assoc_double_ex(return_value, field->name, field->name_length, *(double *) p); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "%.*s=%.16f", field->name_length, field->name, *(double *) p); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "%.*s=%.16f", field->name_length, field->name, *(double *) p); } break; default: - swWarn("unknown type[%d] for field [%.*s].", field->type, field->name_length, field->name); + swoole_warning("unknown type[%d] for field [%.*s].", field->type, field->name_length, field->name); goto _add_string; } } diff --git a/ext-src/swoole_mysql_proto.cc b/ext-src/swoole_mysql_proto.cc index 50f3fa8d443..fac8cd809bb 100644 --- a/ext-src/swoole_mysql_proto.cc +++ b/ext-src/swoole_mysql_proto.cc @@ -349,7 +349,7 @@ static sw_inline uint32_t mysql_auth_encrypt_dispatch(char *buf, } else if (auth_plugin_name == "caching_sha2_password") { return sha256_password_with_nonce(buf, nonce, password); } else { - swWarn("Unknown auth plugin: %s", auth_plugin_name.c_str()); + swoole_warning("Unknown auth plugin: %s", auth_plugin_name.c_str()); return 0; } } @@ -365,7 +365,7 @@ eof_packet::eof_packet(const char *data) : server_packet(data) { data += 2; // int<2> status_flags Status Flags server_status = sw_mysql_uint2korr2korr(data); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "EOF_Packet, warnings=%u, status_code=%u", warning_count, server_status.status); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "EOF_Packet, warnings=%u, status_code=%u", warning_count, server_status.status); } ok_packet::ok_packet(const char *data) : server_packet(data) { @@ -384,7 +384,7 @@ ok_packet::ok_packet(const char *data) : server_packet(data) { // int<2> warnings number of warnings warning_count = sw_mysql_uint2korr2korr(data); // p += 2; - swTraceLog(SW_TRACE_MYSQL_CLIENT, + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "OK_Packet, affected_rows=%" PRIu64 ", insert_id=%" PRIu64 ", status_flags=0x%08x, warnings=%u", affected_rows, last_insert_id, @@ -409,7 +409,7 @@ err_packet::err_packet(const char *data) : server_packet(data) { data += 5; // string error_message human readable error message msg = std::string(data, header.length - 9); - swTraceLog(SW_TRACE_MYSQL_CLIENT, + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "ERR_Packet, error_code=%u, sql_state=%s, status_msg=[%s]", code, sql_state, @@ -484,10 +484,10 @@ greeting_packet::greeting_packet(const char *data) : server_packet(data) { } if (capability_flags & SW_MYSQL_CLIENT_PLUGIN_AUTH) { auth_plugin_name = std::string(p, strlen(p)); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "use %s auth plugin", auth_plugin_name.c_str()); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "use %s auth plugin", auth_plugin_name.c_str()); } } - swTraceLog(SW_TRACE_MYSQL_CLIENT, + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "Server protocol=%d, version=%s, connection_id=%d, capabilites=0x%08x, status=%u, auth_plugin_name=%s, " "auth_plugin_data=L%u[%s]", protocol_version, @@ -512,12 +512,12 @@ login_packet::login_packet(greeting_packet *greeting_packet, SW_MYSQL_CLIENT_CONNECT_WITH_DB | SW_MYSQL_CLIENT_PLUGIN_AUTH | SW_MYSQL_CLIENT_MULTI_RESULTS; memcpy(p, &tint, sizeof(tint)); p += sizeof(tint); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "Client capabilites=0x%08x", tint); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "Client capabilites=0x%08x", tint); // max-packet size tint = 300; memcpy(p, &tint, sizeof(tint)); p += sizeof(tint); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "Client max packet=%u", tint); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "Client max packet=%u", tint); // use the server character_set when the character_set is not set. *p = charset ? charset : greeting_packet->charset; p += 1; @@ -533,7 +533,7 @@ login_packet::login_packet(greeting_packet *greeting_packet, } else { *p = 0; } - swTraceLog(SW_TRACE_MYSQL_CLIENT, + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "Client charset=%u, user=%s, password=%s, hased=L%d[%.*s], database=%s, auth_plugin_name=%s", charset, user.c_str(), @@ -566,7 +566,7 @@ auth_switch_request_packet::auth_switch_request_packet(const char *data) : serve data += (auth_method_name.length() + 1); // string[NUL] auth_method_data strcpy(auth_method_data, data); - swTraceLog(SW_TRACE_MYSQL_CLIENT, "auth switch plugin name=%s", auth_method_name.c_str()); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "auth switch plugin name=%s", auth_method_name.c_str()); } auth_switch_response_packet::auth_switch_response_packet(auth_switch_request_packet *req, const std::string &password) { @@ -584,7 +584,7 @@ auth_signature_response_packet::auth_signature_response_packet(raw_data_packet * const char *auth_plugin_data) { #ifndef SW_MYSQL_RSA_SUPPORT { - swWarn(SW_MYSQL_NO_RSA_ERROR); + swoole_warning(SW_MYSQL_NO_RSA_ERROR); #else if (0) { _error: @@ -603,7 +603,7 @@ auth_signature_response_packet::auth_signature_response_packet(raw_data_packet * char rsa_public_key[rsa_public_key_length + 1]; // rsa + '\0' memcpy((char *) rsa_public_key, tmp, rsa_public_key_length); rsa_public_key[rsa_public_key_length] = '\0'; - swTraceLog(SW_TRACE_MYSQL_CLIENT, + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "rsa_public_key_length=%d;\nrsa_public_key=[%.*s]", rsa_public_key_length, rsa_public_key_length, @@ -623,7 +623,7 @@ auth_signature_response_packet::auth_signature_response_packet(raw_data_packet * BIO *bio = nullptr; RSA *public_rsa = nullptr; if (sw_unlikely((bio = BIO_new_mem_buf((void *) rsa_public_key, -1)) == nullptr)) { - swWarn("BIO_new_mem_buf publicKey error!"); + swoole_warning("BIO_new_mem_buf publicKey error!"); goto _error; } // PEM_read_bio_RSA_PUBKEY @@ -632,7 +632,7 @@ auth_signature_response_packet::auth_signature_response_packet(raw_data_packet * char err_buf[512]; ERR_load_crypto_strings(); ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf)); - swWarn("[PEM_read_bio_RSA_PUBKEY ERROR]: %s", err_buf); + swoole_warning("[PEM_read_bio_RSA_PUBKEY ERROR]: %s", err_buf); goto _error; } BIO_free_all(bio); @@ -643,7 +643,7 @@ auth_signature_response_packet::auth_signature_response_packet(raw_data_packet * ERR_clear_error(); size_t flen = rsa_len - 42; flen = password_bytes_length > flen ? flen : password_bytes_length; - swTraceLog(SW_TRACE_MYSQL_CLIENT, "rsa_len=%d", rsa_len); + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "rsa_len=%d", rsa_len); if (sw_unlikely(RSA_public_encrypt(flen, (const unsigned char *) password_bytes, (unsigned char *) encrypt_msg, @@ -652,7 +652,7 @@ auth_signature_response_packet::auth_signature_response_packet(raw_data_packet * char err_buf[512]; ERR_load_crypto_strings(); ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf)); - swWarn("[RSA_public_encrypt ERROR]: %s", err_buf); + swoole_warning("[RSA_public_encrypt ERROR]: %s", err_buf); goto _error; } RSA_free(public_rsa); @@ -717,7 +717,7 @@ void field_packet::parse(const char *data) { p += def_length; } swMysqlPacketDump(header.length, header.number, data, (*name == '?' ? "Protocol::Param" : "Protocol::Field")); - swTraceLog(SW_TRACE_MYSQL_CLIENT, + swoole_trace_log(SW_TRACE_MYSQL_CLIENT, "catalog=%.*s, database=%.*s, table=%.*s, org_table=%.*s, name=%.*s, org_name=%.*s," "charset=%u, binary_length=%" PRIu64 ", type=%u, flags=0x%08x, decimals=%u, def=[%.*s]", catalog_length, diff --git a/ext-src/swoole_process.cc b/ext-src/swoole_process.cc index d233d435851..858d12684ba 100644 --- a/ext-src/swoole_process.cc +++ b/ext-src/swoole_process.cc @@ -998,7 +998,7 @@ static PHP_METHOD(swoole_process, daemon) { int new_fd = php_swoole_convert_to_fd(elem); if (new_fd >= 0) { if (dup2(new_fd, fd) < 0) { - swSysWarn("dup2(%d, %d) failed", new_fd, fd); + swoole_sys_warning("dup2(%d, %d) failed", new_fd, fd); } } } diff --git a/ext-src/swoole_redis_coro.cc b/ext-src/swoole_redis_coro.cc index 343dad10531..abb0a1cfa7f 100644 --- a/ext-src/swoole_redis_coro.cc +++ b/ext-src/swoole_redis_coro.cc @@ -941,7 +941,7 @@ static sw_inline bool swoole_redis_coro_close(RedisClient *redis) { if (redis->context) { int sockfd = redis->context->fd; Socket *socket = swoole_redis_coro_get_socket(redis->context); - swTraceLog(SW_TRACE_REDIS_CLIENT, "redis connection closed, fd=%d", sockfd); + swoole_trace_log(SW_TRACE_REDIS_CLIENT, "redis connection closed, fd=%d", sockfd); zend_update_property_bool(swoole_redis_coro_ce, SW_Z8_OBJ_P(redis->zobject), ZEND_STRL("connected"), 0); if (!(socket && socket->has_bound())) { redisFreeKeepFd(redis->context); diff --git a/ext-src/swoole_redis_server.cc b/ext-src/swoole_redis_server.cc index ec8412675ba..944a1625c03 100644 --- a/ext-src/swoole_redis_server.cc +++ b/ext-src/swoole_redis_server.cc @@ -97,7 +97,7 @@ int php_swoole_redis_server_onReceive(Server *serv, RecvData *req) { int fd = req->info.fd; Connection *conn = serv->get_connection_by_session_id(fd); if (!conn) { - swWarn("connection[%d] is closed", fd); + swoole_warning("connection[%d] is closed", fd); return SW_ERR; } diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 342197c2abc..da3d0c859b3 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -994,7 +994,7 @@ void ServerObject::on_before_start() { auto primary_port = serv->get_primary_port(); #ifdef SW_LOG_TRACE_OPEN - swTraceLog(SW_TRACE_SERVER, + swoole_trace_log(SW_TRACE_SERVER, "Create Server: host=%s, port=%d, mode=%d, type=%d", primary_port->host.c_str(), (int) primary_port->port, @@ -1254,7 +1254,7 @@ static void php_swoole_onPipeMessage(Server *serv, EventData *req) { return; } - swTraceLog(SW_TRACE_SERVER, + swoole_trace_log(SW_TRACE_SERVER, "PipeMessage: fd=%ld|len=%d|src_worker_id=%d|data=%.*s\n", req->info.fd, req->info.len, @@ -1954,7 +1954,7 @@ static void php_swoole_server_onSendTimeout(Timer *timer, TimerNode *tnode) { server_object->property->send_coroutine_map.erase(session_id); } } else { - swWarn("send coroutine[session#%ld] not exists", session_id); + swoole_warning("send coroutine[session#%ld] not exists", session_id); return; } @@ -3068,7 +3068,7 @@ static PHP_METHOD(swoole_server, heartbeat) { if (session_id <= 0) { return; } - swTrace("heartbeat check fd=%d", conn->fd); + swoole_trace("heartbeat check fd=%d", conn->fd); if (serv->is_healthy_connection(now, conn)) { return; } @@ -3707,7 +3707,7 @@ static PHP_METHOD(swoole_server, getClientList) { int fd = start_fd + 1; for (; fd <= serv_max_fd; fd++) { - swTrace("maxfd=%d, fd=%d, find_count=%ld, start_fd=%ld", serv_max_fd, fd, find_count, start_session_id); + swoole_trace("maxfd=%d, fd=%d, find_count=%ld, start_fd=%ld", serv_max_fd, fd, find_count, start_session_id); Connection *conn = serv->get_connection_for_iterator(fd); if (conn) { SessionId session_id = conn->session_id; diff --git a/ext-src/swoole_websocket_server.cc b/ext-src/swoole_websocket_server.cc index e8f2deccf7c..f95213efd43 100644 --- a/ext-src/swoole_websocket_server.cc +++ b/ext-src/swoole_websocket_server.cc @@ -427,7 +427,7 @@ static bool websocket_message_uncompress(String *buffer, const char *in, size_t // gzip_stream.total_out = 0; status = inflateInit2(&zstream, SW_ZLIB_ENCODING_RAW); if (status != Z_OK) { - swWarn("inflateInit2() failed by %s", zError(status)); + swoole_warning("inflateInit2() failed by %s", zError(status)); return false; } @@ -459,7 +459,7 @@ static bool websocket_message_uncompress(String *buffer, const char *in, size_t inflateEnd(&zstream); if (!ret) { - swWarn("inflate() failed, Error: %s[%d]", zError(status), status); + swoole_warning("inflate() failed, Error: %s[%d]", zError(status), status); return false; } return true; @@ -481,7 +481,7 @@ static bool websocket_message_compress(String *buffer, const char *data, size_t status = deflateInit2(&zstream, level, Z_DEFLATED, SW_ZLIB_ENCODING_RAW, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); if (status != Z_OK) { - swWarn("deflateInit2() failed, Error: [%d]", status); + swoole_warning("deflateInit2() failed, Error: [%d]", status); return false; } @@ -524,12 +524,12 @@ static bool websocket_message_compress(String *buffer, const char *data, size_t deflateEnd(&zstream); if (result != Z_BUF_ERROR || bytes_written < 4) { - swWarn("Failed to compress outgoing frame"); + swoole_warning("Failed to compress outgoing frame"); return false; } if (status != Z_OK) { - swWarn("deflate() failed, Error: [%d]", status); + swoole_warning("deflate() failed, Error: [%d]", status); return false; } diff --git a/include/swoole_coroutine.h b/include/swoole_coroutine.h index 804eb7b4121..c2833c006b9 100644 --- a/include/swoole_coroutine.h +++ b/include/swoole_coroutine.h @@ -133,7 +133,7 @@ class Coroutine { return (new Coroutine(fn, args))->run(); } catch (const std::system_error& e) { swoole_set_last_error(e.code().value()); - swWarn("failed to create coroutine, Error: %s[%d]", e.what(), swoole_get_last_error()); + swoole_warning("failed to create coroutine, Error: %s[%d]", e.what(), swoole_get_last_error()); return -1; } #else @@ -150,7 +150,7 @@ class Coroutine { static inline Coroutine *get_current_safe() { if (sw_unlikely(!current)) { - swFatalError(SW_ERROR_CO_OUT_OF_COROUTINE, "API must be called in the coroutine"); + swoole_fatal_error(SW_ERROR_CO_OUT_OF_COROUTINE, "API must be called in the coroutine"); } return current; } diff --git a/include/swoole_coroutine_channel.h b/include/swoole_coroutine_channel.h index ec860867bae..0a4face8fc9 100644 --- a/include/swoole_coroutine_channel.h +++ b/include/swoole_coroutine_channel.h @@ -135,12 +135,12 @@ class Channel { if (type == PRODUCER) { co = producer_queue.front(); producer_queue.pop_front(); - swTraceLog(SW_TRACE_CHANNEL, "resume producer cid=%ld", co->get_cid()); + swoole_trace_log(SW_TRACE_CHANNEL, "resume producer cid=%ld", co->get_cid()); } else // if (type == CONSUMER) { co = consumer_queue.front(); consumer_queue.pop_front(); - swTraceLog(SW_TRACE_CHANNEL, "resume consumer cid=%ld", co->get_cid()); + swoole_trace_log(SW_TRACE_CHANNEL, "resume consumer cid=%ld", co->get_cid()); } return co; } diff --git a/include/swoole_coroutine_socket.h b/include/swoole_coroutine_socket.h index f32a62d35a1..3440bc9e6cd 100644 --- a/include/swoole_coroutine_socket.h +++ b/include/swoole_coroutine_socket.h @@ -231,7 +231,7 @@ class Socket { inline void check_bound_co(const enum swEvent_type event) { long cid = get_bound_cid(event); if (sw_unlikely(cid)) { - swFatalError(SW_ERROR_CO_HAS_BEEN_BOUND, + swoole_fatal_error(SW_ERROR_CO_HAS_BEEN_BOUND, "Socket#%d has already been bound to another coroutine#%ld, " "%s of the same socket in coroutine#%ld at the same time is not allowed", sock_fd, @@ -301,7 +301,7 @@ class Socket { inline bool set_option(int level, int optname, int optval) { if (socket->set_option(level, optname, optval) < 0) { - swSysWarn("setsockopt(%d, %d, %d, %d) failed", sock_fd, level, optname, optval); + swoole_sys_warning("setsockopt(%d, %d, %d, %d) failed", sock_fd, level, optname, optval); return false; } return true; diff --git a/include/swoole_file.h b/include/swoole_file.h index beee86436d2..dd7a2bb75e3 100644 --- a/include/swoole_file.h +++ b/include/swoole_file.h @@ -105,7 +105,7 @@ class File { bool stat(FileStatus *_stat) const { if (::fstat(fd_, _stat) < 0) { - swSysWarn("fstat() failed"); + swoole_sys_warning("fstat() failed"); return false; } else { return true; diff --git a/include/swoole_http2.h b/include/swoole_http2.h index 5bc05cddba7..d3dc7363fd9 100644 --- a/include/swoole_http2.h +++ b/include/swoole_http2.h @@ -94,7 +94,7 @@ enum swHttp2_stream_flag { ((flags & SW_HTTP2_FLAG_PRIORITY) ? "\nEND_PRIORITY |" : "") #define swHttp2FrameTraceLog(recv, str, ...) \ - swTraceLog(SW_TRACE_HTTP2, \ + swoole_trace_log(SW_TRACE_HTTP2, \ "\nrecv [" \ "\e[3" \ "%d" \ diff --git a/include/swoole_log.h b/include/swoole_log.h index 2099eb8e6d9..62317967cbf 100644 --- a/include/swoole_log.h +++ b/include/swoole_log.h @@ -25,7 +25,7 @@ #define SW_LOG_DATE_STRLEN 128 #define SW_LOG_DEFAULT_DATE_FORMAT "%F %T" -enum swLog_level { +enum swLogLevel { SW_LOG_DEBUG = 0, SW_LOG_TRACE, SW_LOG_INFO, @@ -35,7 +35,7 @@ enum swLog_level { SW_LOG_NONE, }; -enum swLog_rotation_type { +enum swLogRotationType { SW_LOG_ROTATION_SINGLE = 0, SW_LOG_ROTATION_MONTHLY, SW_LOG_ROTATION_DAILY, @@ -87,19 +87,19 @@ class Logger { swoole::Logger *sw_logger(); #define __SW_FUNC__ (swoole::Logger::get_pretty_name(__PRETTY_FUNCTION__).c_str()) -#define swInfo(str, ...) \ +#define swoole_info(str, ...) \ if (SW_LOG_INFO >= sw_logger()->get_level()) { \ size_t _sw_error_len = sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, str, ##__VA_ARGS__); \ sw_logger()->put(SW_LOG_INFO, sw_error, _sw_error_len); \ } -#define swNotice(str, ...) \ +#define swoole_notice(str, ...) \ if (SW_LOG_NOTICE >= sw_logger()->get_level()) { \ size_t _sw_error_len = sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, str, ##__VA_ARGS__); \ sw_logger()->put(SW_LOG_NOTICE, sw_error, _sw_error_len); \ } -#define swSysNotice(str, ...) \ +#define swoole_sys_notice(str, ...) \ do { \ swoole_set_last_error(errno); \ if (SW_LOG_ERROR >= sw_logger()->get_level()) { \ @@ -115,7 +115,7 @@ swoole::Logger *sw_logger(); } \ } while (0) -#define swWarn(str, ...) \ +#define swoole_warning(str, ...) \ do { \ if (SW_LOG_WARNING >= sw_logger()->get_level()) { \ size_t _sw_error_len = sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s(): " str, __SW_FUNC__, ##__VA_ARGS__); \ @@ -123,7 +123,7 @@ swoole::Logger *sw_logger(); } \ } while (0) -#define swSysWarn(str, ...) \ +#define swoole_sys_warning(str, ...) \ do { \ swoole_set_last_error(errno); \ if (SW_LOG_ERROR >= sw_logger()->get_level()) { \ @@ -138,14 +138,14 @@ swoole::Logger *sw_logger(); } \ } while (0) -#define swError(str, ...) \ +#define swoole_error(str, ...) \ do { \ size_t _sw_error_len = sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, str, ##__VA_ARGS__); \ sw_logger()->put(SW_LOG_ERROR, sw_error, _sw_error_len); \ exit(1); \ } while (0) -#define swSysError(str, ...) \ +#define swoole_sys_error(str, ...) \ do { \ size_t _sw_error_len = sw_snprintf(sw_error, \ SW_ERROR_MSG_SIZE, \ @@ -158,7 +158,7 @@ swoole::Logger *sw_logger(); exit(1); \ } while (0) -#define swFatalError(code, str, ...) \ +#define swoole_fatal_error(code, str, ...) \ do { \ SwooleG.fatal_error(code, str, ##__VA_ARGS__); \ exit(255); \ @@ -175,18 +175,18 @@ swoole::Logger *sw_logger(); } while (0) #ifdef SW_DEBUG -#define swDebug(str, ...) \ +#define swoole_debug(str, ...) \ if (SW_LOG_DEBUG >= sw_logger()->get_level()) { \ size_t _sw_error_len = \ sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s(:%d): " str, __SW_FUNC__, __LINE__, ##__VA_ARGS__); \ sw_logger()->put(SW_LOG_DEBUG, sw_error, _sw_error_len); \ } -#define swHexDump(data, length) \ +#define swoole_hex_dump(data, length) \ do { \ const char *__data = (data); \ size_t __length = (length); \ - swDebug("+----------+------------+-----------+-----------+------------+------------------+"); \ + swoole_debug("+----------+------------+-----------+-----------+------------+------------------+"); \ for (size_t of = 0; of < __length; of += 16) { \ char hex[16 * 3 + 1]; \ char str[16 + 1]; \ @@ -195,13 +195,13 @@ swoole::Logger *sw_logger(); hof += sprintf(hex + hof, "%02x ", (__data)[i] & 0xff); \ sof += sprintf(str + sof, "%c", isprint((int) (__data)[i]) ? (__data)[i] : '.'); \ } \ - swDebug("| %08x | %-48s| %-16s |", of, hex, str); \ + swoole_debug("| %08x | %-48s| %-16s |", of, hex, str); \ } \ - swDebug("+----------+------------+-----------+-----------+------------+------------------+"); \ + swoole_debug("+----------+------------+-----------+-----------+------------+------------------+"); \ } while (0) #else -#define swDebug(str, ...) -#define swHexDump(data, length) +#define swoole_debug(str, ...) +#define swoole_hex_dump(data, length) #endif enum swTrace_type { @@ -249,14 +249,14 @@ enum swTrace_type { }; #ifdef SW_LOG_TRACE_OPEN -#define swTraceLog(what, str, ...) \ +#define swoole_trace_log(what, str, ...) \ if (SW_LOG_TRACE >= sw_logger()->get_level() && (what & SwooleG.trace_flags)) { \ size_t _sw_error_len = \ sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s(:%d): " str, __SW_FUNC__, __LINE__, ##__VA_ARGS__); \ sw_logger()->put(SW_LOG_TRACE, sw_error, _sw_error_len); \ } #else -#define swTraceLog(what, str, ...) +#define swoole_trace_log(what, str, ...) #endif -#define swTrace(str, ...) swTraceLog(SW_TRACE_NORMAL, str, ##__VA_ARGS__) +#define swoole_trace(str, ...) swoole_trace_log(SW_TRACE_NORMAL, str, ##__VA_ARGS__) diff --git a/include/swoole_server.h b/include/swoole_server.h index 30cdc4beda4..2ee3e215080 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -885,13 +885,13 @@ class Server { bool set_document_root(const std::string &path) { if (path.length() > PATH_MAX) { - swWarn("The length of document_root must be less than %d", PATH_MAX); + swoole_warning("The length of document_root must be less than %d", PATH_MAX); return false; } char _realpath[PATH_MAX]; if (!realpath(path.c_str(), _realpath)) { - swWarn("document_root[%s] does not exist", path.c_str()); + swoole_warning("document_root[%s] does not exist", path.c_str()); return false; } diff --git a/include/swoole_socket.h b/include/swoole_socket.h index 443c7c12edf..0b0373ff568 100644 --- a/include/swoole_socket.h +++ b/include/swoole_socket.h @@ -390,13 +390,13 @@ struct Socket { } #ifdef TCP_CORK if (set_tcp_nopush(1) < 0) { - swSysWarn("set_tcp_nopush(fd=%d, ON) failed", fd); + swoole_sys_warning("set_tcp_nopush(fd=%d, ON) failed", fd); return false; } #endif // Need to turn off tcp nodelay when using nopush if (tcp_nodelay && set_tcp_nodelay(0) != 0) { - swSysWarn("set_tcp_nodelay(fd=%d, OFF) failed", fd); + swoole_sys_warning("set_tcp_nodelay(fd=%d, OFF) failed", fd); } return true; } @@ -407,13 +407,13 @@ struct Socket { } #ifdef TCP_CORK if (set_tcp_nopush(0) < 0) { - swSysWarn("set_tcp_nopush(fd=%d, OFF) failed", fd); + swoole_sys_warning("set_tcp_nopush(fd=%d, OFF) failed", fd); return false; } #endif // Restore tcp_nodelay setting if (enable_tcp_nodelay && tcp_nodelay == 0 && set_tcp_nodelay(1) != 0) { - swSysWarn("set_tcp_nodelay(fd=%d, ON) failed", fd); + swoole_sys_warning("set_tcp_nodelay(fd=%d, ON) failed", fd); return false; } return true; diff --git a/include/swoole_ssl.h b/include/swoole_ssl.h index d212a0fa461..557f65a71ac 100644 --- a/include/swoole_ssl.h +++ b/include/swoole_ssl.h @@ -136,7 +136,7 @@ struct SSLContext { bool set_cert_file(const std::string &_cert_file) { if (access(_cert_file.c_str(), R_OK) < 0) { - swWarn("ssl cert file[%s] not found", _cert_file.c_str()); + swoole_warning("ssl cert file[%s] not found", _cert_file.c_str()); return false; } cert_file = _cert_file; @@ -145,7 +145,7 @@ struct SSLContext { bool set_key_file(const std::string &_key_file) { if (access(_key_file.c_str(), R_OK) < 0) { - swWarn("ssl key file[%s] not found", _key_file.c_str()); + swoole_warning("ssl key file[%s] not found", _key_file.c_str()); return false; } key_file = _key_file; diff --git a/src/core/base.cc b/src/core/base.cc index 3705b677644..1450c7c8482 100644 --- a/src/core/base.cc +++ b/src/core/base.cc @@ -88,7 +88,7 @@ char *sw_error_() { __thread char sw_error[SW_ERROR_MSG_SIZE]; #endif -static void swoole_fatal_error(int code, const char *format, ...); +static void swoole_fatal_error_impl(int code, const char *format, ...); swoole::Logger *sw_logger() { return g_logger_instance; @@ -121,7 +121,7 @@ void swoole_init(void) { SwooleG.running = 1; SwooleG.init = 1; SwooleG.std_allocator = { malloc, calloc, realloc, free }; - SwooleG.fatal_error = swoole_fatal_error; + SwooleG.fatal_error = swoole_fatal_error_impl; SwooleG.cpu_num = SW_MAX(1, sysconf(_SC_NPROCESSORS_ONLN)); SwooleG.pagesize = getpagesize(); @@ -150,7 +150,7 @@ void swoole_init(void) { SwooleG.max_sockets = SW_MAX_SOCKETS_DEFAULT; struct rlimit rlmt; if (getrlimit(RLIMIT_NOFILE, &rlmt) < 0) { - swSysWarn("getrlimit() failed"); + swoole_sys_warning("getrlimit() failed"); } else { SwooleG.max_sockets = SW_MAX((uint32_t) rlmt.rlim_cur, SW_MAX_SOCKETS_DEFAULT); SwooleG.max_sockets = SW_MIN((uint32_t) rlmt.rlim_cur, SW_SESSION_LIST_SIZE); @@ -176,7 +176,7 @@ SW_API int swoole_add_function(const char *name, void *func) { std::string _name(name); auto iter = functions.find(_name); if (iter != functions.end()) { - swWarn("Function '%s' has already been added", name); + swoole_warning("Function '%s' has already been added", name); return SW_ERR; } else { functions.emplace(std::make_pair(_name, func)); @@ -276,12 +276,12 @@ SW_API std::pair swoole_get_dns_server() { bool swoole_set_task_tmpdir(const std::string &dir) { if (dir.at(0) != '/') { - swWarn("wrong absolute path '%s'", dir.c_str()); + swoole_warning("wrong absolute path '%s'", dir.c_str()); return false; } if (access(dir.c_str(), R_OK) < 0 && !swoole_mkdir_recursive(dir)) { - swWarn("create task tmp dir(%s) failed", dir.c_str()); + swoole_warning("create task tmp dir(%s) failed", dir.c_str()); return false; } @@ -289,7 +289,7 @@ bool swoole_set_task_tmpdir(const std::string &dir) { SwooleG.task_tmpfile = sw_tg_buffer()->to_std_string(); if (SwooleG.task_tmpfile.length() >= SW_TASK_TMP_PATH_SIZE) { - swWarn("task tmp_dir is too large, the max size is '%d'", SW_TASK_TMP_PATH_SIZE - 1); + swoole_warning("task tmp_dir is too large, the max size is '%d'", SW_TASK_TMP_PATH_SIZE - 1); return false; } @@ -299,11 +299,11 @@ bool swoole_set_task_tmpdir(const std::string &dir) { pid_t swoole_fork(int flags) { if (!(flags & SW_FORK_EXEC)) { if (swoole_coroutine_is_in()) { - swFatalError(SW_ERROR_OPERATION_NOT_SUPPORT, "must be forked outside the coroutine"); + swoole_fatal_error(SW_ERROR_OPERATION_NOT_SUPPORT, "must be forked outside the coroutine"); } if (SwooleTG.async_threads) { - swTrace("aio_task_num=%d, reactor=%p", SwooleTG.async_threads->task_num, sw_reactor()); - swFatalError(SW_ERROR_OPERATION_NOT_SUPPORT, "can not create server after using async file operation"); + swoole_trace("aio_task_num=%d, reactor=%p", SwooleTG.async_threads->task_num, sw_reactor()); + swoole_fatal_error(SW_ERROR_OPERATION_NOT_SUPPORT, "can not create server after using async file operation"); } } if (flags & SW_FORK_PRECHECK) { @@ -333,7 +333,7 @@ pid_t swoole_fork(int flags) { // reset eventLoop if (swoole_event_is_available()) { swoole_event_free(); - swTraceLog(SW_TRACE_REACTOR, "reactor has been destroyed"); + swoole_trace_log(SW_TRACE_REACTOR, "reactor has been destroyed"); } } else { /** @@ -395,7 +395,7 @@ bool swoole_mkdir_recursive(const std::string &dir) { // PATH_MAX limit includes string trailing null character if (len + 1 > PATH_MAX) { - swWarn("mkdir(%s) failed. Path exceeds the limit of %d characters", dir.c_str(), PATH_MAX - 1); + swoole_warning("mkdir(%s) failed. Path exceeds the limit of %d characters", dir.c_str(), PATH_MAX - 1); return false; } swoole_strlcpy(tmp, dir.c_str(), PATH_MAX); @@ -410,7 +410,7 @@ bool swoole_mkdir_recursive(const std::string &dir) { tmp[i] = 0; if (access(tmp, R_OK) != 0) { if (mkdir(tmp, 0755) == -1) { - swSysWarn("mkdir(%s) failed", tmp); + swoole_sys_warning("mkdir(%s) failed", tmp); return -1; } } @@ -523,7 +523,7 @@ int swoole_system_random(int min, int max) { bytes_to_read = sizeof(random_value); if (read(dev_random_fd, next_random_byte, bytes_to_read) < bytes_to_read) { - swSysWarn("read() from /dev/urandom failed"); + swoole_sys_warning("read() from /dev/urandom failed"); return SW_ERR; } return min + (random_value % (max - min + 1)); @@ -531,10 +531,10 @@ int swoole_system_random(int min, int max) { void swoole_redirect_stdout(int new_fd) { if (dup2(new_fd, STDOUT_FILENO) < 0) { - swSysWarn("dup2(STDOUT_FILENO) failed"); + swoole_sys_warning("dup2(STDOUT_FILENO) failed"); } if (dup2(new_fd, STDERR_FILENO) < 0) { - swSysWarn("dup2(STDERR_FILENO) failed"); + swoole_sys_warning("dup2(STDERR_FILENO) failed"); } } @@ -672,7 +672,7 @@ int swoole_shell_exec(const char *command, pid_t *pid, bool get_error_stream) { } if ((child_pid = fork()) == -1) { - swSysWarn("fork() failed"); + swoole_sys_warning("fork() failed"); close(fds[0]); close(fds[1]); return SW_ERR; @@ -770,7 +770,7 @@ bool swoole_get_env(const char *name, int *value) { int swoole_get_systemd_listen_fds() { int ret; if (!swoole_get_env("LISTEN_FDS", &ret)) { - swWarn("invalid LISTEN_FDS"); + swoole_warning("invalid LISTEN_FDS"); return -1; } else if (ret >= SW_MAX_LISTEN_PORT) { swoole_error_log(SW_LOG_ERROR, SW_ERROR_SERVER_TOO_MANY_LISTEN_PORT, "LISTEN_FDS is too big"); @@ -805,7 +805,7 @@ void swoole_print_backtrace(void) { } #endif -static void swoole_fatal_error(int code, const char *format, ...) { +static void swoole_fatal_error_impl(int code, const char *format, ...) { size_t retval = 0; va_list args; diff --git a/src/core/channel.cc b/src/core/channel.cc index aace9cc5571..02f0da317d4 100644 --- a/src/core/channel.cc +++ b/src/core/channel.cc @@ -47,7 +47,7 @@ Channel *Channel::make(size_t size, size_t maxlen, int flags) { } if (mem == nullptr) { - swWarn("alloc(%ld) failed", size); + swoole_warning("alloc(%ld) failed", size); return nullptr; } @@ -71,7 +71,7 @@ Channel *Channel::make(size_t size, size_t maxlen, int flags) { if (flags & SW_CHAN_NOTIFY) { object->notify_pipe = new Pipe(true); if (!object->notify_pipe->ready()) { - swWarn("notify_fd init failed"); + swoole_warning("notify_fd init failed"); delete object->notify_pipe; return nullptr; } diff --git a/src/core/log.cc b/src/core/log.cc index 9afc21983fa..2993398c5d9 100644 --- a/src/core/log.cc +++ b/src/core/log.cc @@ -116,33 +116,33 @@ void Logger::set_rotation(int _rotation) { bool Logger::redirect_stdout_and_stderr(int enable) { if (enable) { if (!opened) { - swWarn("no log file opened"); + swoole_warning("no log file opened"); return false; } if (redirected) { - swWarn("has been redirected"); + swoole_warning("has been redirected"); return false; } if ((stdout_fd = dup(STDOUT_FILENO)) < 0) { - swSysWarn("dup(STDOUT_FILENO) failed"); + swoole_sys_warning("dup(STDOUT_FILENO) failed"); return false; } if ((stderr_fd = dup(STDERR_FILENO)) < 0) { - swSysWarn("dup(STDERR_FILENO) failed"); + swoole_sys_warning("dup(STDERR_FILENO) failed"); return false; } swoole_redirect_stdout(log_fd); redirected = true; } else { if (!redirected) { - swWarn("no redirected"); + swoole_warning("no redirected"); return false; } if (dup2(stdout_fd, STDOUT_FILENO) < 0) { - swSysWarn("dup2(STDOUT_FILENO) failed"); + swoole_sys_warning("dup2(STDOUT_FILENO) failed"); } if (dup2(stderr_fd, STDERR_FILENO) < 0) { - swSysWarn("dup2(STDERR_FILENO) failed"); + swoole_sys_warning("dup2(STDERR_FILENO) failed"); } ::close(stdout_fd); ::close(stderr_fd); diff --git a/src/core/string.cc b/src/core/string.cc index 4c8bd7f4847..2569a65661d 100644 --- a/src/core/string.cc +++ b/src/core/string.cc @@ -176,11 +176,11 @@ ssize_t String::split(const char *delimiter, size_t delimiter_length, const Stri off_t _offset = offset; size_t ret; - swTraceLog(SW_TRACE_EOF_PROTOCOL, "#[0] count=%d, length=%ld, size=%ld, offset=%ld", count, length, size, offset); + swoole_trace_log(SW_TRACE_EOF_PROTOCOL, "#[0] count=%d, length=%ld, size=%ld, offset=%ld", count, length, size, offset); while (delimiter_addr) { size_t _length = delimiter_addr - start_addr + delimiter_length; - swTraceLog(SW_TRACE_EOF_PROTOCOL, "#[4] count=%d, length=%lu", count, _length + offset); + swoole_trace_log(SW_TRACE_EOF_PROTOCOL, "#[4] count=%d, length=%lu", count, _length + offset); if (handler((char *) start_addr - _offset, _length + _offset) == false) { return -1; } @@ -203,9 +203,9 @@ ssize_t String::split(const char *delimiter, size_t delimiter_length, const Stri ret = start_addr - str - _offset; if (ret > 0 && ret < length) { - swTraceLog(SW_TRACE_EOF_PROTOCOL, "#[5] count=%d, remaining_length=%zu", count, length - offset); + swoole_trace_log(SW_TRACE_EOF_PROTOCOL, "#[5] count=%d, remaining_length=%zu", count, length - offset); } else if (ret >= length) { - swTraceLog(SW_TRACE_EOF_PROTOCOL, "#[3] length=%ld, size=%ld, offset=%ld", length, size, offset); + swoole_trace_log(SW_TRACE_EOF_PROTOCOL, "#[3] length=%ld, size=%ld, offset=%ld", length, size, offset); } return ret; diff --git a/src/core/timer.cc b/src/core/timer.cc index dc58f44f7e2..bb5f785043a 100644 --- a/src/core/timer.cc +++ b/src/core/timer.cc @@ -141,7 +141,7 @@ TimerNode *Timer::add(long _msec, bool persistent, void *data, const TimerCallba return nullptr; } map.emplace(std::make_pair(tnode->id, tnode)); - swTraceLog(SW_TRACE_TIMER, + swoole_trace_log(SW_TRACE_TIMER, "id=%ld, exec_msec=%" PRId64 ", msec=%ld, round=%" PRIu64 ", exist=%lu", tnode->id, tnode->exec_msec, @@ -157,7 +157,7 @@ bool Timer::remove(TimerNode *tnode) { } if (sw_unlikely(_current_id > 0 && tnode->id == _current_id)) { tnode->removed = true; - swTraceLog(SW_TRACE_TIMER, + swoole_trace_log(SW_TRACE_TIMER, "set-remove: id=%ld, exec_msec=%" PRId64 ", round=%" PRIu64 ", exist=%lu", tnode->id, tnode->exec_msec, @@ -174,7 +174,7 @@ bool Timer::remove(TimerNode *tnode) { if (tnode->destructor) { tnode->destructor(tnode); } - swTraceLog(SW_TRACE_TIMER, + swoole_trace_log(SW_TRACE_TIMER, "id=%ld, exec_msec=%" PRId64 ", round=%" PRIu64 ", exist=%lu", tnode->id, tnode->exec_msec, @@ -193,7 +193,7 @@ int Timer::select() { TimerNode *tnode = nullptr; HeapNode *tmp; - swTraceLog(SW_TRACE_TIMER, "timer msec=%" PRId64 ", round=%" PRId64, now_msec, round); + swoole_trace_log(SW_TRACE_TIMER, "timer msec=%" PRId64 ", round=%" PRId64, now_msec, round); while ((tmp = heap.top())) { tnode = (TimerNode *) tmp->data; @@ -203,7 +203,7 @@ int Timer::select() { _current_id = tnode->id; if (!tnode->removed) { - swTraceLog(SW_TRACE_TIMER, + swoole_trace_log(SW_TRACE_TIMER, "id=%ld, exec_msec=%" PRId64 ", round=%" PRIu64 ", exist=%lu", tnode->id, tnode->exec_msec, @@ -246,14 +246,14 @@ int Timer::select() { int Timer::now(struct timeval *time) { struct timespec _now; if (clock_gettime(CLOCK_MONOTONIC, &_now) < 0) { - swSysWarn("clock_gettime(CLOCK_MONOTONIC) failed"); + swoole_sys_warning("clock_gettime(CLOCK_MONOTONIC) failed"); return SW_ERR; } time->tv_sec = _now.tv_sec; time->tv_usec = _now.tv_nsec / 1000; #else if (gettimeofday(time, nullptr) < 0) { - swSysWarn("gettimeofday() failed"); + swoole_sys_warning("gettimeofday() failed"); return SW_ERR; } #endif diff --git a/src/coroutine/base.cc b/src/coroutine/base.cc index 499a3ef041e..9ffa46db609 100644 --- a/src/coroutine/base.cc +++ b/src/coroutine/base.cc @@ -153,7 +153,7 @@ void Coroutine::close() { on_close(task); } #if !defined(SW_USE_THREAD_CONTEXT) && defined(SW_CONTEXT_DETECT_STACK_USAGE) - swTraceLog( + swoole_trace_log( SW_TRACE_CONTEXT, "coroutine#%ld stack memory use less than %ld bytes", get_cid(), ctx.get_stack_usage()); #endif current = origin; @@ -205,7 +205,7 @@ void Coroutine::bailout(BailoutCallback func) { return; } if (!func) { - swError("bailout without bailout function"); + swoole_error("bailout without bailout function"); } if (!co->task) { // TODO: decoupling diff --git a/src/coroutine/channel.cc b/src/coroutine/channel.cc index 83b69ae99ee..f04e99c5d96 100644 --- a/src/coroutine/channel.cc +++ b/src/coroutine/channel.cc @@ -35,10 +35,10 @@ void Channel::yield(enum opcode type) { Coroutine *co = Coroutine::get_current_safe(); if (type == PRODUCER) { producer_queue.push_back(co); - swTraceLog(SW_TRACE_CHANNEL, "producer cid=%ld", co->get_cid()); + swoole_trace_log(SW_TRACE_CHANNEL, "producer cid=%ld", co->get_cid()); } else { consumer_queue.push_back(co); - swTraceLog(SW_TRACE_CHANNEL, "consumer cid=%ld", co->get_cid()); + swoole_trace_log(SW_TRACE_CHANNEL, "consumer cid=%ld", co->get_cid()); } Coroutine::CancelFunc cancel_fn = [this, type](Coroutine *co) { if (type == CONSUMER) { @@ -143,7 +143,7 @@ bool Channel::push(void *data, double timeout) { * push data */ data_queue.push(data); - swTraceLog(SW_TRACE_CHANNEL, "push data to channel, count=%ld", length()); + swoole_trace_log(SW_TRACE_CHANNEL, "push data to channel, count=%ld", length()); /** * notify consumer */ @@ -158,7 +158,7 @@ bool Channel::close() { if (closed) { return false; } - swTraceLog(SW_TRACE_CHANNEL, "channel closed"); + swoole_trace_log(SW_TRACE_CHANNEL, "channel closed"); closed = true; while (!producer_queue.empty()) { Coroutine *co = pop_coroutine(PRODUCER); diff --git a/src/coroutine/context.cc b/src/coroutine/context.cc index db8139a4d47..faa830794c7 100644 --- a/src/coroutine/context.cc +++ b/src/coroutine/context.cc @@ -15,6 +15,7 @@ */ #include "swoole_coroutine_context.h" + #ifdef SW_CONTEXT_PROTECT_STACK_PAGE #include #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) @@ -46,10 +47,10 @@ Context::Context(size_t stack_size, const CoroutineFunc &fn, void *private_data) stack_ = (char *) sw_malloc(stack_size_); #endif if (!stack_) { - swFatalError(SW_ERROR_MALLOC_FAIL, "failed to malloc stack memory."); + swoole_fatal_error(SW_ERROR_MALLOC_FAIL, "failed to malloc stack memory."); exit(254); } - swTraceLog(SW_TRACE_COROUTINE, "alloc stack: size=%u, ptr=%p", stack_size_, stack_); + swoole_trace_log(SW_TRACE_COROUTINE, "alloc stack: size=%u, ptr=%p", stack_size_, stack_); void *sp = (void *) ((char *) stack_ + stack_size_); #ifdef USE_VALGRIND @@ -86,7 +87,7 @@ Context::Context(size_t stack_size, const CoroutineFunc &fn, void *private_data) Context::~Context() { if (stack_) { - swTraceLog(SW_TRACE_COROUTINE, "free stack: ptr=%p", stack_); + swoole_trace_log(SW_TRACE_COROUTINE, "free stack: ptr=%p", stack_); #ifdef USE_VALGRIND VALGRIND_STACK_DEREGISTER(valgrind_stack_id); #endif diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index 20fe3f6ee49..97037a50fc9 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -144,7 +144,7 @@ bool Socket::wait_event(const enum swEvent_type event, const void **__buf, size_ if (sw_unlikely(!add_event(event))) { return false; } - swTraceLog(SW_TRACE_SOCKET, + swoole_trace_log(SW_TRACE_SOCKET, "socket#%d blongs to cid#%ld is waiting for %s event", sock_fd, co->get_cid(), @@ -194,7 +194,7 @@ bool Socket::wait_event(const enum swEvent_type event, const void **__buf, size_ #ifdef SW_USE_OPENSSL want_event = SW_EVENT_NULL; #endif - swTraceLog(SW_TRACE_SOCKET, + swoole_trace_log(SW_TRACE_SOCKET, "socket#%d blongs to cid#%ld trigger %s event", sock_fd, co->get_cid(), @@ -376,7 +376,7 @@ bool Socket::http_proxy_handshake() { http_proxy->target_port); } - swTraceLog(SW_TRACE_HTTP_CLIENT, "proxy request: <str); + swoole_trace_log(SW_TRACE_HTTP_CLIENT, "proxy request: <str); send_buffer->length = n; if (send(send_buffer->str, n) != n) { @@ -399,7 +399,7 @@ bool Socket::http_proxy_handshake() { return false; } - swTraceLog(SW_TRACE_HTTP_CLIENT, "proxy response: <str); + swoole_trace_log(SW_TRACE_HTTP_CLIENT, "proxy response: <str); bool ret = false; char *buf = recv_buffer->str; @@ -915,7 +915,7 @@ ssize_t Socket::readv_all(network::IOVector *io_vector) { TimerController timer(&read_timer, read_timeout, this, timer_callback); retval = socket->readv(io_vector); - swTraceLog(SW_TRACE_SOCKET, "readv %ld bytes, errno=%d", retval, errno); + swoole_trace_log(SW_TRACE_SOCKET, "readv %ld bytes, errno=%d", retval, errno); if (retval < 0 && socket->catch_error(errno) != SW_WAIT) { set_err(errno); @@ -977,7 +977,7 @@ ssize_t Socket::writev_all(network::IOVector *io_vector) { TimerController timer(&write_timer, write_timeout, this, timer_callback); retval = socket->writev(io_vector); - swTraceLog(SW_TRACE_SOCKET, "writev %ld bytes, errno=%d", retval, errno); + swoole_trace_log(SW_TRACE_SOCKET, "writev %ld bytes, errno=%d", retval, errno); if (retval < 0 && socket->catch_error(errno) != SW_WAIT) { set_err(errno); @@ -1175,7 +1175,7 @@ Socket *Socket::accept(double timeout) { Socket *client_sock = new Socket(conn, this); if (sw_unlikely(client_sock->get_fd() < 0)) { - swSysWarn("new Socket() failed"); + swoole_sys_warning("new Socket() failed"); set_err(errno); delete client_sock; return nullptr; @@ -1195,13 +1195,13 @@ bool Socket::ssl_check_context() { ssl_context->protocols = SW_SSL_DTLS; socket->chunk_size = SW_SSL_BUFFER_SIZE; #else - swWarn("DTLS support require openssl-1.1 or later"); + swoole_warning("DTLS support require openssl-1.1 or later"); return false; #endif } ssl_context->http_v2 = http2; if (!ssl_context->create()) { - swWarn("swSSL_get_context() error"); + swoole_warning("swSSL_get_context() error"); return false; } socket->ssl_send_ = 1; @@ -1417,7 +1417,7 @@ ssize_t Socket::sendto(const std::string &host, int port, const void *__buf, siz TimerController timer(&write_timer, write_timeout, this, timer_callback); do { retval = ::sendto(sock_fd, __buf, __n, 0, (struct sockaddr *) &addr, addr_size); - swTraceLog(SW_TRACE_SOCKET, "sendto %ld/%ld bytes, errno=%d", retval, __n, errno); + swoole_trace_log(SW_TRACE_SOCKET, "sendto %ld/%ld bytes, errno=%d", retval, __n, errno); } while (retval < 0 && (errno == EINTR || (socket->catch_error(errno) == SW_WAIT && timer.start() && wait_event(SW_EVENT_WRITE, &__buf, __n)))); check_return_value(retval); @@ -1442,7 +1442,7 @@ ssize_t Socket::recvfrom(void *__buf, size_t __n, struct sockaddr *_addr, sockle TimerController timer(&read_timer, read_timeout, this, timer_callback); do { retval = ::recvfrom(sock_fd, __buf, __n, 0, _addr, _socklen); - swTraceLog(SW_TRACE_SOCKET, "recvfrom %ld/%ld bytes, errno=%d", retval, __n, errno); + swoole_trace_log(SW_TRACE_SOCKET, "recvfrom %ld/%ld bytes, errno=%d", retval, __n, errno); } while (retval < 0 && ((errno == EINTR) || (socket->catch_error(errno) == SW_WAIT && timer.start() && wait_event(SW_EVENT_READ)))); check_return_value(retval); @@ -1475,7 +1475,7 @@ ssize_t Socket::recv_packet_with_length_protocol() { _get_length: protocol.real_header_length = 0; packet_len = protocol.get_package_length(&protocol, socket, read_buffer->str, (uint32_t) read_buffer->length); - swTraceLog(SW_TRACE_SOCKET, "packet_len=%ld, length=%ld", packet_len, read_buffer->length); + swoole_trace_log(SW_TRACE_SOCKET, "packet_len=%ld, length=%ld", packet_len, read_buffer->length); if (packet_len < 0) { set_err(SW_ERROR_PACKAGE_LENGTH_NOT_FOUND, "get package length failed"); return 0; diff --git a/src/coroutine/system.cc b/src/coroutine/system.cc index b877cf6144b..5d13a132d60 100644 --- a/src/coroutine/system.cc +++ b/src/coroutine/system.cc @@ -88,11 +88,11 @@ std::shared_ptr System::read_file(const char *file, bool lock) { async([&result, file, lock]() { File fp(file, O_RDONLY); if (!fp.ready()) { - swSysWarn("open(%s, O_RDONLY) failed", file); + swoole_sys_warning("open(%s, O_RDONLY) failed", file); return; } if (lock && !fp.lock(LOCK_SH)) { - swSysWarn("flock(%s, LOCK_SH) failed", file); + swoole_sys_warning("flock(%s, LOCK_SH) failed", file); return; } ssize_t filesize = fp.get_size(); @@ -105,7 +105,7 @@ std::shared_ptr System::read_file(const char *file, bool lock) { result = fp.read_content(); } if (lock && !fp.unlock()) { - swSysWarn("flock(%s, LOCK_UN) failed", file); + swoole_sys_warning("flock(%s, LOCK_UN) failed", file); } }); return result; @@ -117,19 +117,19 @@ ssize_t System::write_file(const char *file, char *buf, size_t length, bool lock async([&]() { File _file(file, file_flags, 0644); if (!_file.ready()) { - swSysWarn("open(%s, %d) failed", file, file_flags); + swoole_sys_warning("open(%s, %d) failed", file, file_flags); return; } if (lock && !_file.lock(LOCK_EX)) { - swSysWarn("flock(%s, LOCK_EX) failed", file); + swoole_sys_warning("flock(%s, LOCK_EX) failed", file); return; } size_t bytes = _file.write_all(buf, length); if ((file_flags & SW_AIO_WRITE_FSYNC) && !_file.sync()) { - swSysWarn("fsync(%s) failed", file); + swoole_sys_warning("fsync(%s) failed", file); } if (lock && !_file.unlock()) { - swSysWarn("flock(%s, LOCK_UN) failed", file); + swoole_sys_warning("flock(%s, LOCK_UN) failed", file); } retval = bytes; }); @@ -431,7 +431,7 @@ bool System::socket_poll(std::unordered_map &fds, double timeou if (timeout == 0) { struct pollfd *event_list = (struct pollfd *) sw_calloc(fds.size(), sizeof(struct pollfd)); if (!event_list) { - swWarn("calloc() failed"); + swoole_warning("calloc() failed"); return false; } int n = 0; diff --git a/src/lock/mutex.cc b/src/lock/mutex.cc index 32c4448013a..9ef10cc2089 100644 --- a/src/lock/mutex.cc +++ b/src/lock/mutex.cc @@ -43,7 +43,7 @@ Mutex::Mutex(int flags) : Lock() { #ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED pthread_mutexattr_setpshared(&impl->attr_, PTHREAD_PROCESS_SHARED); #else - swWarn("PTHREAD_MUTEX_PSHARED is not supported"); + swoole_warning("PTHREAD_MUTEX_PSHARED is not supported"); #endif } @@ -51,7 +51,7 @@ Mutex::Mutex(int flags) : Lock() { #ifdef HAVE_PTHREAD_MUTEXATTR_SETROBUST pthread_mutexattr_setrobust(&impl->attr_, PTHREAD_MUTEX_ROBUST); #else - swWarn("PTHREAD_MUTEX_ROBUST is not supported"); + swoole_warning("PTHREAD_MUTEX_ROBUST is not supported"); #endif } diff --git a/src/memory/buffer.cc b/src/memory/buffer.cc index 40520ced0d5..661e01b9a65 100644 --- a/src/memory/buffer.cc +++ b/src/memory/buffer.cc @@ -75,7 +75,7 @@ void Buffer::append(const void *data, uint32_t size) { memcpy(chunk->value.ptr, _pos, _n); chunk->length = _n; - swTraceLog(SW_TRACE_BUFFER, "chunk_n=%lu|size=%u|chunk_len=%u|chunk=%p", count(), _n, chunk->length, chunk); + swoole_trace_log(SW_TRACE_BUFFER, "chunk_n=%lu|size=%u|chunk_len=%u|chunk=%p", count(), _n, chunk->length, chunk); _pos += _n; _length -= _n; @@ -125,7 +125,7 @@ void Buffer::append(const struct iovec *iov, size_t iovcnt, off_t offset) { total_length += _n; _length -= _n; - swTraceLog(SW_TRACE_BUFFER, "chunk_n=%lu|size=%lu|chunk_len=%u|chunk=%p", count(), _n, chunk->length, chunk); + swoole_trace_log(SW_TRACE_BUFFER, "chunk_n=%lu|size=%lu|chunk_len=%u|chunk=%p", count(), _n, chunk->length, chunk); chunk->length += _n; iov_remain_len -= _n; diff --git a/src/memory/global_memory.cc b/src/memory/global_memory.cc index 0d237528ff4..a29f317a273 100644 --- a/src/memory/global_memory.cc +++ b/src/memory/global_memory.cc @@ -84,7 +84,7 @@ void *GlobalMemory::alloc(uint32_t size) { std::unique_lock lock(impl->lock); if (alloc_size > impl->pagesize) { - swWarn("failed to alloc %d bytes, exceed the maximum size[%d]", size, impl->pagesize); + swoole_warning("failed to alloc %d bytes, exceed the maximum size[%d]", size, impl->pagesize); return nullptr; } @@ -93,12 +93,12 @@ void *GlobalMemory::alloc(uint32_t size) { impl = new GlobalMemoryImpl(old_impl->pagesize, old_impl->shared); } - swTrace("alloc_size=%u, size=%u", alloc_size, size); + swoole_trace("alloc_size=%u, size=%u", alloc_size, size); if (impl->alloc_offset + alloc_size > impl->pagesize) { char *page = impl->new_page(); if (page == nullptr) { - swWarn("alloc memory error"); + swoole_warning("alloc memory error"); return nullptr; } } diff --git a/src/memory/ring_buffer.cc b/src/memory/ring_buffer.cc index f0da0e8f94a..ce490492eb3 100644 --- a/src/memory/ring_buffer.cc +++ b/src/memory/ring_buffer.cc @@ -69,7 +69,7 @@ RingBuffer::RingBuffer(uint32_t size, bool shared) { impl->shared = shared; impl->memory = mem; - swDebug("memory: ptr=%p", mem); + swoole_debug("memory: ptr=%p", mem); } void RingBufferImpl::collect() { @@ -134,7 +134,7 @@ void *RingBuffer::alloc(uint32_t size) { impl->alloc_offset += alloc_size; impl->alloc_count++; - swDebug("alloc: ptr=%p", (void *) (item->data - (char *) impl->memory)); + swoole_debug("alloc: ptr=%p", (void *) (item->data - (char *) impl->memory)); return item->data; } @@ -147,12 +147,12 @@ void RingBuffer::free(void *ptr) { assert(item->lock == 1); if (item->lock != 1) { - swDebug("invalid free: index=%d, ptr=%p", item->index, (void *) (item->data - (char *) impl->memory)); + swoole_debug("invalid free: index=%d, ptr=%p", item->index, (void *) (item->data - (char *) impl->memory)); } else { item->lock = 0; } - swDebug("free: ptr=%p", (void *) (item->data - (char *) impl->memory)); + swoole_debug("free: ptr=%p", (void *) (item->data - (char *) impl->memory)); sw_atomic_t *free_count = &impl->free_count; sw_atomic_fetch_add(free_count, 1); diff --git a/src/memory/shared_memory.cc b/src/memory/shared_memory.cc index 00757df87c7..c1d2f2b2b62 100644 --- a/src/memory/shared_memory.cc +++ b/src/memory/shared_memory.cc @@ -62,7 +62,7 @@ void *SharedMemory::alloc(size_t size) { if (!mem) #endif { - swSysWarn("mmap(%lu) failed", size); + swoole_sys_warning("mmap(%lu) failed", size); return nullptr; } else { object.size_ = size; @@ -75,7 +75,7 @@ void SharedMemory::free(void *ptr) { SharedMemory *object = SharedMemory::fetch_object(ptr); size_t size = object->size_; if (munmap(object, size) < 0) { - swSysWarn("munmap(%p, %lu) failed", object, size); + swoole_sys_warning("munmap(%p, %lu) failed", object, size); } } diff --git a/src/memory/table.cc b/src/memory/table.cc index e0683a6b303..a2b7c9c72b1 100644 --- a/src/memory/table.cc +++ b/src/memory/table.cc @@ -66,7 +66,7 @@ void Table::free() { bool Table::add_column(const std::string &_name, enum TableColumn::Type _type, size_t _size) { if (_type < TableColumn::TYPE_INT || _type > TableColumn::TYPE_STRING) { - swWarn("unknown column type"); + swoole_warning("unknown column type"); return false; } @@ -110,7 +110,7 @@ size_t Table::get_memory_size() { memory_size = _memory_size; - swTrace("_memory_size=%lu, _row_num=%lu, _row_memory_size=%lu", _memory_size, _row_num, _row_memory_size); + swoole_trace("_memory_size=%lu, _row_num=%lu, _row_memory_size=%lu", _memory_size, _row_num, _row_memory_size); return _memory_size; } @@ -203,7 +203,7 @@ void TableRow::lock() { */ if (kill(lock_pid, 0) < 0 && errno == ESRCH) { *lock = 1; - swWarn("lock process[%d] not exists, force unlock", lock_pid); + swoole_warning("lock process[%d] not exists, force unlock", lock_pid); goto _success; } /** @@ -219,7 +219,7 @@ void TableRow::lock() { */ else if ((swoole::time(true) - t) > SW_TABLE_FORCE_UNLOCK_TIME) { *lock = 1; - swWarn("timeout, force unlock"); + swoole_warning("timeout, force unlock"); goto _success; } sw_yield(); @@ -426,7 +426,7 @@ void TableRow::set_value(TableColumn *col, void *value, size_t vlen) { break; default: if (vlen > (col->size - sizeof(TableStringLength))) { - swWarn("[key=%s,field=%s]string value is too long", key, col->name.c_str()); + swoole_warning("[key=%s,field=%s]string value is too long", key, col->name.c_str()); vlen = col->size - sizeof(TableStringLength); } if (value == nullptr) { diff --git a/src/network/client.cc b/src/network/client.cc index 31988e58276..8322872f9c1 100644 --- a/src/network/client.cc +++ b/src/network/client.cc @@ -72,7 +72,7 @@ Client::Client(enum swSocket_type _type, bool _async) : async(_async) { fd_type = Socket::is_stream(_type) ? SW_FD_STREAM_CLIENT : SW_FD_DGRAM_CLIENT; socket = swoole::make_socket(_type, fd_type, (async ? SW_SOCK_NONBLOCK : 0) | SW_SOCK_CLOEXEC); if (socket == nullptr) { - swSysWarn("socket() failed"); + swoole_sys_warning("socket() failed"); return; } @@ -283,7 +283,7 @@ int Client::enable_ssl_encrypt() { } #else { - swWarn("DTLS support require openssl-1.1 or later"); + swoole_warning("DTLS support require openssl-1.1 or later"); return SW_ERR; } #endif @@ -609,7 +609,7 @@ static int Client_tcp_connect_async(Client *cli, const char *host, int port, dou } if (!(cli->onConnect && cli->onError && cli->onClose && cli->onReceive)) { - swWarn("onConnect/onError/onReceive/onClose callback have not set"); + swoole_warning("onConnect/onError/onReceive/onClose callback have not set"); return SW_ERR; } @@ -633,7 +633,7 @@ static int Client_tcp_connect_async(Client *cli, const char *host, int port, dou ev.buf = sw_malloc(ev.nbytes); if (!ev.buf) { - swWarn("malloc failed"); + swoole_warning("malloc failed"); return SW_ERR; } @@ -797,7 +797,7 @@ static int Client_udp_connect(Client *cli, const char *host, int port, double ti } if (cli->async && !cli->onReceive) { - swWarn("onReceive callback have not set"); + swoole_warning("onReceive callback have not set"); return SW_ERR; } @@ -816,7 +816,7 @@ static int Client_udp_connect(Client *cli, const char *host, int port, double ti unlink(client_addr->sun_path); if (bind(cli->socket->fd, (struct sockaddr *) client_addr, sizeof(cli->socket->info.addr.un)) < 0) { - swSysWarn("bind(%s) failed", client_addr->sun_path); + swoole_sys_warning("bind(%s) failed", client_addr->sun_path); return SW_ERR; } } @@ -830,7 +830,7 @@ static int Client_udp_connect(Client *cli, const char *host, int port, double ti } #else { - swWarn("DTLS support require openssl-1.1 or later"); + swoole_warning("DTLS support require openssl-1.1 or later"); return SW_ERR; } #endif @@ -1062,7 +1062,7 @@ static int Client_onStreamRead(Reactor *reactor, Event *event) { if (n < 0) { switch (event->socket->catch_error(errno)) { case SW_ERROR: - swSysWarn("Read from socket[%d] failed", event->fd); + swoole_sys_warning("Read from socket[%d] failed", event->fd); return SW_OK; case SW_CLOSE: goto __close; @@ -1186,7 +1186,7 @@ static int Client_onWrite(Reactor *reactor, Event *event) { ret = _socket->get_option(SOL_SOCKET, SO_ERROR, &err); swoole_set_last_error(err); if (ret < 0) { - swSysWarn("getsockopt(%d) failed", event->fd); + swoole_sys_warning("getsockopt(%d) failed", event->fd); return SW_ERR; } diff --git a/src/network/dns.cc b/src/network/dns.cc index 85f7d3b821f..77bb86a582b 100644 --- a/src/network/dns.cc +++ b/src/network/dns.cc @@ -34,7 +34,7 @@ bool swoole_load_resolv_conf() { char buf[16] = {}; if ((fp = fopen(SwooleG.dns_resolvconf_path.c_str(), "rt")) == nullptr) { - swSysWarn("fopen(%s) failed", SwooleG.dns_resolvconf_path.c_str()); + swoole_sys_warning("fopen(%s) failed", SwooleG.dns_resolvconf_path.c_str()); return false; } @@ -319,7 +319,7 @@ std::vector dns_lookup_impl_with_socket(const char *domain, int fam int len = strlen(domain); if (domain_encode(domain, len, _domain_name) < 0) { - swWarn("invalid domain[%s]", domain); + swoole_warning("invalid domain[%s]", domain); return result; } @@ -511,13 +511,13 @@ std::vector dns_lookup_impl_with_cares(const char *domain, int fami ares_library_init(ARES_LIB_INIT_ALL); swoole_event_set_handler(SW_FD_CARES | SW_EVENT_READ, [](Reactor *reactor, Event *event) -> int { auto ctx = reinterpret_cast(event->socket->object); - swTraceLog(SW_TRACE_CARES, "[event callback] readable event, fd=%d", event->socket->fd); + swoole_trace_log(SW_TRACE_CARES, "[event callback] readable event, fd=%d", event->socket->fd); ares_process_fd(ctx->channel, event->fd, ARES_SOCKET_BAD); return SW_OK; }); swoole_event_set_handler(SW_FD_CARES | SW_EVENT_WRITE, [](Reactor *reactor, Event *event) -> int { auto ctx = reinterpret_cast(event->socket->object); - swTraceLog(SW_TRACE_CARES, "[event callback] writable event, fd=%d", event->socket->fd); + swoole_trace_log(SW_TRACE_CARES, "[event callback] writable event, fd=%d", event->socket->fd); ares_process_fd(ctx->channel, ARES_SOCKET_BAD, event->fd); return SW_OK; }); @@ -544,12 +544,12 @@ std::vector dns_lookup_impl_with_cares(const char *domain, int fami events |= SW_EVENT_WRITE; } - swTraceLog(SW_TRACE_CARES, "[sock_state_cb], fd=%d, readable=%d, writable=%d", fd, readable, writable); + swoole_trace_log(SW_TRACE_CARES, "[sock_state_cb], fd=%d, readable=%d, writable=%d", fd, readable, writable); network::Socket *_socket = nullptr; if (ctx->sockets.find(fd) == ctx->sockets.end()) { if (events == 0) { - swWarn("error events, fd=%d", fd); + swoole_warning("error events, fd=%d", fd); return; } _socket = make_socket(fd, SW_FD_CARES); @@ -558,7 +558,7 @@ std::vector dns_lookup_impl_with_cares(const char *domain, int fami } else { _socket = ctx->sockets[fd]; if (events == 0) { - swTraceLog(SW_TRACE_CARES, "[del event], fd=%d", fd); + swoole_trace_log(SW_TRACE_CARES, "[del event], fd=%d", fd); swoole_event_del(_socket); _socket->fd = -1; _socket->free(); @@ -569,16 +569,16 @@ std::vector dns_lookup_impl_with_cares(const char *domain, int fami if (_socket->events) { swoole_event_set(_socket, events); - swTraceLog(SW_TRACE_CARES, "[set event] fd=%d, events=%d", fd, events); + swoole_trace_log(SW_TRACE_CARES, "[set event] fd=%d, events=%d", fd, events); } else { swoole_event_add(_socket, events); - swTraceLog(SW_TRACE_CARES, "[add event] fd=%d, events=%d", fd, events); + swoole_trace_log(SW_TRACE_CARES, "[add event] fd=%d, events=%d", fd, events); } }; ctx.ares_flags = ARES_OPT_TIMEOUTMS | ARES_OPT_TRIES | ARES_OPT_SOCK_STATE_CB | ARES_OPT_LOOKUPS; if ((res = ares_init_options(&ctx.channel, &ctx.ares_opts, ctx.ares_flags)) != ARES_SUCCESS) { - swWarn("ares_init_options() failed, Error: %s[%d]", ares_strerror(res), res); + swoole_warning("ares_init_options() failed, Error: %s[%d]", ares_strerror(res), res); goto _return; } @@ -598,10 +598,10 @@ std::vector dns_lookup_impl_with_cares(const char *domain, int fami inet_pton(AF_INET, SwooleG.dns_server_host.c_str(), &servers.addr.addr4); ares_set_servers(ctx.channel, &servers); if (SwooleG.dns_server_port != SW_DNS_SERVER_PORT) { - swWarn("not support to set port of dns server"); + swoole_warning("not support to set port of dns server"); } #else - swWarn("not support to set dns server"); + swoole_warning("not support to set dns server"); #endif } @@ -612,7 +612,7 @@ std::vector dns_lookup_impl_with_cares(const char *domain, int fami [](void *data, int status, int timeouts, struct hostent *hostent) { auto ctx = reinterpret_cast(data); - swTraceLog(SW_TRACE_CARES, "[cares callback] status=%d, timeouts=%d", status, timeouts); + swoole_trace_log(SW_TRACE_CARES, "[cares callback] status=%d, timeouts=%d", status, timeouts); if (timeouts > 0) { ctx->error = SW_ERROR_DNSLOOKUP_RESOLVE_TIMEOUT; @@ -657,7 +657,7 @@ std::vector dns_lookup_impl_with_cares(const char *domain, int fami ares_process_fd(ctx.channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD); ctx.error = ARES_ETIMEOUT; } else { - swTraceLog(SW_TRACE_CARES, "lookup success, result_count=%lu", ctx.result.size()); + swoole_trace_log(SW_TRACE_CARES, "lookup success, result_count=%lu", ctx.result.size()); } _destroy: if (ctx.error) { @@ -818,7 +818,7 @@ int getaddrinfo(GetaddrinfoRequest *req) { memcpy((char *) buffer + (i * sizeof(struct sockaddr_in6)), ptr->ai_addr, sizeof(struct sockaddr_in6)); break; default: - swWarn("unknown socket family[%d]", ptr->ai_family); + swoole_warning("unknown socket family[%d]", ptr->ai_family); break; } i++; diff --git a/src/network/socket.cc b/src/network/socket.cc index f0183d19554..c00a38d3281 100644 --- a/src/network/socket.cc +++ b/src/network/socket.cc @@ -89,7 +89,7 @@ int Socket::sendfile_blocking(const char *filename, off_t offset, size_t length, File file(filename, O_RDONLY); if (!file.ready()) { - swSysWarn("open(%s) failed", filename); + swoole_sys_warning("open(%s) failed", filename); return SW_ERR; } @@ -111,7 +111,7 @@ int Socket::sendfile_blocking(const char *filename, off_t offset, size_t length, sendn = (length - offset > SW_SENDFILE_CHUNK_SIZE) ? SW_SENDFILE_CHUNK_SIZE : length - offset; n = ::swoole_sendfile(fd, file.get_fd(), &offset, sendn); if (n <= 0) { - swSysWarn("sendfile(%d, %s) failed", fd, filename); + swoole_sys_warning("sendfile(%d, %s) failed", fd, filename); return SW_ERR; } else { continue; @@ -131,7 +131,7 @@ ssize_t Socket::writev_blocking(const struct iovec *iov, size_t iovcnt) { wait_event((int) (send_timeout_ * 1000), SW_EVENT_WRITE) == SW_OK) { continue; } else { - swSysWarn("send %lu bytes failed", iov[1].iov_len); + swoole_sys_warning("send %lu bytes failed", iov[1].iov_len); return SW_ERR; } } else { @@ -174,7 +174,7 @@ int Socket::wait_event(int timeout_ms, int events) { swoole_set_last_error(SW_ERROR_SOCKET_POLL_TIMEOUT); return SW_ERR; } else if (ret < 0 && errno != EINTR) { - swSysWarn("poll() failed"); + swoole_sys_warning("poll() failed"); return SW_ERR; } else { return SW_OK; @@ -203,7 +203,7 @@ ssize_t Socket::send_blocking(const void *__data, size_t __len) { wait_event((int) (send_timeout_ * 1000), SW_EVENT_WRITE) == SW_OK) { continue; } else { - swSysWarn("send %lu bytes failed", __len); + swoole_sys_warning("send %lu bytes failed", __len); return SW_ERR; } } @@ -308,7 +308,7 @@ ssize_t Socket::recvfrom_blocking(char *__buf, size_t __len, int flags, Address static void socket_free_defer(void *ptr) { Socket *sock = (Socket *) ptr; if (sock->fd != -1 && close(sock->fd) != 0) { - swSysWarn("close(%d) failed", sock->fd); + swoole_sys_warning("close(%d) failed", sock->fd); } delete sock; } @@ -335,12 +335,12 @@ int Socket::bind(const std::string &_host, int *port) { const char *host = _host.c_str(); if (set_reuse_addr() < 0) { - swSysWarn("setsockopt(%d, SO_REUSEADDR) failed", fd); + swoole_sys_warning("setsockopt(%d, SO_REUSEADDR) failed", fd); } // UnixSocket if (socket_type == SW_SOCK_UNIX_DGRAM || socket_type == SW_SOCK_UNIX_STREAM) { if (l_host == 0 || l_host > sizeof(address.addr.un) - 1) { - swWarn("bad unix socket file"); + swoole_warning("bad unix socket file"); errno = EINVAL; return SW_ERR; } @@ -355,7 +355,7 @@ int Socket::bind(const std::string &_host, int *port) { host = "::"; } if (inet_pton(AF_INET6, host, &address.addr.inet_v6.sin6_addr) < 0) { - swSysWarn("inet_pton(AF_INET6, %s) failed", host); + swoole_sys_warning("inet_pton(AF_INET6, %s) failed", host); return SW_ERR; } address.addr.inet_v6.sin6_port = htons(*port); @@ -374,7 +374,7 @@ int Socket::bind(const std::string &_host, int *port) { host = "0.0.0.0"; } if (inet_pton(AF_INET, host, &address.addr.inet_v4.sin_addr) < 0) { - swSysWarn("inet_pton(AF_INET, %s) failed", host); + swoole_sys_warning("inet_pton(AF_INET, %s) failed", host); return SW_ERR; } address.addr.inet_v4.sin_port = htons(*port); @@ -411,7 +411,7 @@ bool Socket::set_buffer_size(uint32_t _buffer_size) { bool Socket::set_recv_buffer_size(uint32_t _buffer_size) { if (set_option(SOL_SOCKET, SO_RCVBUF, _buffer_size) != 0) { - swSysWarn("setsockopt(%d, SOL_SOCKET, SO_SNDBUF, %d) failed", fd, _buffer_size); + swoole_sys_warning("setsockopt(%d, SOL_SOCKET, SO_SNDBUF, %d) failed", fd, _buffer_size); return false; } return true; @@ -419,7 +419,7 @@ bool Socket::set_recv_buffer_size(uint32_t _buffer_size) { bool Socket::set_send_buffer_size(uint32_t _buffer_size) { if (set_option(SOL_SOCKET, SO_SNDBUF, _buffer_size) != 0) { - swSysWarn("setsockopt(%d, SOL_SOCKET, SO_RCVBUF, %d) failed", fd, _buffer_size); + swoole_sys_warning("setsockopt(%d, SOL_SOCKET, SO_RCVBUF, %d) failed", fd, _buffer_size); return false; } return true; @@ -436,7 +436,7 @@ static bool _set_timeout(int fd, int type, double timeout) { timeo.tv_usec = (int) ((timeout - timeo.tv_sec) * 1000 * 1000); ret = setsockopt(fd, SOL_SOCKET, type, (void *) &timeo, sizeof(timeo)); if (ret < 0) { - swSysWarn("setsockopt(SO_SNDTIMEO, %s) failed", type == SO_SNDTIMEO ? "SEND" : "RECV"); + swoole_sys_warning("setsockopt(SO_SNDTIMEO, %s) failed", type == SO_SNDTIMEO ? "SEND" : "RECV"); return false; } else { return true; @@ -452,7 +452,7 @@ static bool _fcntl_set_option(int sock, int nonblock, int cloexec) { } while (opts < 0 && errno == EINTR); if (opts < 0) { - swSysWarn("fcntl(%d, GETFL) failed", sock); + swoole_sys_warning("fcntl(%d, GETFL) failed", sock); } if (nonblock) { @@ -466,7 +466,7 @@ static bool _fcntl_set_option(int sock, int nonblock, int cloexec) { } while (ret < 0 && errno == EINTR); if (ret < 0) { - swSysWarn("fcntl(%d, SETFL, opts) failed", sock); + swoole_sys_warning("fcntl(%d, SETFL, opts) failed", sock); return false; } } @@ -478,7 +478,7 @@ static bool _fcntl_set_option(int sock, int nonblock, int cloexec) { } while (opts < 0 && errno == EINTR); if (opts < 0) { - swSysWarn("fcntl(%d, GETFL) failed", sock); + swoole_sys_warning("fcntl(%d, GETFL) failed", sock); } if (cloexec) { @@ -492,7 +492,7 @@ static bool _fcntl_set_option(int sock, int nonblock, int cloexec) { } while (ret < 0 && errno == EINTR); if (ret < 0) { - swSysWarn("fcntl(%d, SETFD, opts) failed", sock); + swoole_sys_warning("fcntl(%d, SETFD, opts) failed", sock); return false; } } @@ -551,12 +551,12 @@ int Socket::handle_sendfile() { ret = ::swoole_sendfile(fd, task->file.get_fd(), &task->offset, sendn); } - swTrace("ret=%d|task->offset=%ld|sendn=%lu|filesize=%lu", ret, (long) task->offset, sendn, task->length); + swoole_trace("ret=%d|task->offset=%ld|sendn=%lu|filesize=%lu", ret, (long) task->offset, sendn, task->length); if (ret <= 0) { switch (catch_error(errno)) { case SW_ERROR: - swSysWarn("sendfile(%s, %ld, %zu) failed", task->file.get_path().c_str(), (long) task->offset, sendn); + swoole_sys_warning("sendfile(%s, %ld, %zu) failed", task->file.get_path().c_str(), (long) task->offset, sendn); buffer->pop(); return SW_OK; case SW_CLOSE: @@ -600,7 +600,7 @@ int Socket::handle_send() { if (ret < 0) { switch (catch_error(errno)) { case SW_ERROR: - swSysWarn("send to fd[%d] failed", fd); + swoole_sys_warning("send to fd[%d] failed", fd); break; case SW_CLOSE: close_wait = 1; @@ -635,18 +635,18 @@ static void Socket_sendfile_destructor(BufferChunk *chunk) { int Socket::sendfile(const char *filename, off_t offset, size_t length) { std::unique_ptr task(new SendfileRequest(filename, offset, length)); if (!task->file.ready()) { - swSysWarn("open(%s) failed", filename); + swoole_sys_warning("open(%s) failed", filename); return SW_OK; } FileStatus file_stat; if (!task->file.stat(&file_stat)) { - swSysWarn("fstat(%s) failed", filename); + swoole_sys_warning("fstat(%s) failed", filename); return SW_ERR; } if (file_stat.st_size == 0) { - swWarn("empty file[%s]", filename); + swoole_warning("empty file[%s]", filename); return SW_ERR; } @@ -714,7 +714,7 @@ ssize_t Socket::recv(void *__buf, size_t __n, int __flags) { total_bytes = 0; } - swTraceLog(SW_TRACE_SOCKET, "recv %ld/%ld bytes, errno=%d", total_bytes, __n, errno); + swoole_trace_log(SW_TRACE_SOCKET, "recv %ld/%ld bytes, errno=%d", total_bytes, __n, errno); return total_bytes; } @@ -740,7 +740,7 @@ ssize_t Socket::send(const void *__buf, size_t __n, int __flags) { } } - swTraceLog(SW_TRACE_SOCKET, "send %ld/%ld bytes, errno=%d", retval, __n, errno); + swoole_trace_log(SW_TRACE_SOCKET, "send %ld/%ld bytes, errno=%d", retval, __n, errno); return retval; } @@ -804,7 +804,7 @@ ssize_t Socket::peek(void *__buf, size_t __n, int __flags) { } } while (retval < 0 && errno == EINTR); - swTraceLog(SW_TRACE_SOCKET, "peek %ld/%ld bytes, errno=%d", retval, __n, errno); + swoole_trace_log(SW_TRACE_SOCKET, "peek %ld/%ld bytes, errno=%d", retval, __n, errno); return retval; } @@ -855,7 +855,7 @@ bool Socket::ssl_check_host(const char *tls_host_name) { #ifdef X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT /* X509_check_host() is only available in OpenSSL 1.0.2+ */ if (X509_check_host(cert, tls_host_name, strlen(tls_host_name), 0, nullptr) != 1) { - swWarn("X509_check_host(): no match"); + swoole_warning("X509_check_host(): no match"); goto _failed; } goto _found; @@ -884,16 +884,16 @@ bool Socket::ssl_check_host(const char *tls_host_name) { } str = altname->d.dNSName; - swTrace("SSL subjectAltName: \"%.*s\"", ASN1_STRING_length(str), ASN1_STRING_data(str)); + swoole_trace("SSL subjectAltName: \"%.*s\"", ASN1_STRING_length(str), ASN1_STRING_data(str)); if (ssl_check_name(tls_host_name, str) == SW_OK) { - swTrace("SSL subjectAltName: match"); + swoole_trace("SSL subjectAltName: match"); GENERAL_NAMES_free(altnames); goto _found; } } - swTrace("SSL subjectAltName: no match"); + swoole_trace("SSL subjectAltName: no match"); GENERAL_NAMES_free(altnames); goto _failed; } @@ -920,14 +920,14 @@ bool Socket::ssl_check_host(const char *tls_host_name) { entry = X509_NAME_get_entry(sname, i); str = X509_NAME_ENTRY_get_data(entry); - swTrace("SSL commonName: \"%.*s\"", ASN1_STRING_length(str), ASN1_STRING_data(str)); + swoole_trace("SSL commonName: \"%.*s\"", ASN1_STRING_length(str), ASN1_STRING_data(str)); if (ssl_check_name(tls_host_name, str) == SW_OK) { - swTrace("SSL commonName: match"); + swoole_trace("SSL commonName: match"); goto _found; } } - swTrace("SSL commonName: no match"); + swoole_trace("SSL commonName: no match"); #endif _failed: @@ -987,18 +987,18 @@ static int _ssl_read_x509_file(X509 *cert, char *buffer, size_t length) { }; if (bio == nullptr) { - swWarn("BIO_new() failed"); + swoole_warning("BIO_new() failed"); return -1; } if (PEM_write_bio_X509(bio, cert) == 0) { - swWarn("PEM_write_bio_X509() failed"); + swoole_warning("PEM_write_bio_X509() failed"); return -1; } len = BIO_pending(bio); if (len < 0 && len > (long) length) { - swWarn("certificate length[%ld] is too big", len); + swoole_warning("certificate length[%ld] is too big", len); return -1; } return BIO_read(bio, buffer, len); @@ -1088,7 +1088,7 @@ enum swReturn_code Socket::ssl_accept() { } else if (err == SSL_ERROR_SSL) { int reason; const char *error_string = ssl_get_error_reason(&reason); - swWarn( + swoole_warning( "bad SSL client[%s:%d], reason=%d, error_string=%s", info.get_ip(), info.get_port(), reason, error_string); return SW_ERROR; } else if (err == SSL_ERROR_SYSCALL) { @@ -1100,7 +1100,7 @@ enum swReturn_code Socket::ssl_accept() { #endif return SW_ERROR; } - swWarn("SSL_do_handshake() failed. Error: %s[%ld|%d]", strerror(errno), err, errno); + swoole_warning("SSL_do_handshake() failed. Error: %s[%ld|%d]", strerror(errno), err, errno); return SW_ERROR; } @@ -1114,7 +1114,7 @@ int Socket::ssl_connect() { #ifdef SW_LOG_TRACE_OPEN const char *ssl_version = SSL_get_version(ssl); const char *ssl_cipher = SSL_get_cipher_name(ssl); - swTraceLog(SW_TRACE_SSL, "connected (%s %s)", ssl_version, ssl_cipher); + swoole_trace_log(SW_TRACE_SSL, "connected (%s %s)", ssl_version, ssl_cipher); #endif return SW_OK; @@ -1132,7 +1132,7 @@ int Socket::ssl_connect() { ssl_state = SW_SSL_STATE_WAIT_STREAM; return SW_OK; } else if (err == SSL_ERROR_ZERO_RETURN) { - swDebug("SSL_connect(fd=%d) closed", fd); + swoole_debug("SSL_connect(fd=%d) closed", fd); return SW_ERR; } else if (err == SSL_ERROR_SYSCALL) { if (n) { @@ -1143,7 +1143,7 @@ int Socket::ssl_connect() { long err_code = ERR_get_error(); char *msg = ERR_error_string(err_code, sw_tg_buffer()->str); - swNotice("Socket::ssl_connect(fd=%d) to server[%s:%d] failed. Error: %s[%ld|%d]", fd, info.get_ip(), info.get_port(), msg, + swoole_notice("Socket::ssl_connect(fd=%d) to server[%s:%d] failed. Error: %s[%ld|%d]", fd, info.get_ip(), info.get_port(), msg, err, ERR_GET_REASON(err_code)); return SW_ERR; @@ -1158,15 +1158,15 @@ int Socket::ssl_sendfile(const File &fp, off_t *_offset, size_t _size) { ssize_t ret = ssl_send(buf, n); if (ret < 0) { if (catch_error(errno) == SW_ERROR) { - swSysWarn("write() failed"); + swoole_sys_warning("write() failed"); } } else { *_offset += ret; } - swTraceLog(SW_TRACE_REACTOR, "fd=%d, readn=%ld, n=%ld, ret=%ld", fd, readn, n, ret); + swoole_trace_log(SW_TRACE_REACTOR, "fd=%d, readn=%ld, n=%ld, ret=%ld", fd, readn, n, ret); return ret; } else { - swSysWarn("pread() failed"); + swoole_sys_warning("pread() failed"); return SW_ERR; } } @@ -1191,19 +1191,19 @@ bool Socket::ssl_shutdown() { int n = SSL_shutdown(ssl); ssl_closed_ = 1; - swTrace("SSL_shutdown: %d", n); + swoole_trace("SSL_shutdown: %d", n); int sslerr = 0; /* before 0.9.8m SSL_shutdown() returned 0 instead of -1 on errors */ if (n != 1 && ERR_peek_error()) { sslerr = SSL_get_error(ssl, n); - swTrace("SSL_get_error: %d", sslerr); + swoole_trace("SSL_get_error: %d", sslerr); } if (!(n == 1 || sslerr == 0 || sslerr == SSL_ERROR_ZERO_RETURN)) { int reason; const char *error_string = ssl_get_error_reason(&reason); - swWarn("SSL_shutdown() failed, reason=%d, error_string=%s", reason, error_string); + swoole_warning("SSL_shutdown() failed, reason=%d, error_string=%s", reason, error_string); return false; } @@ -1403,12 +1403,12 @@ int Socket::ssl_create(SSLContext *ssl_context, int _flags) { ssl = SSL_new(ssl_context->get_context()); if (ssl == nullptr) { - swWarn("SSL_new() failed"); + swoole_warning("SSL_new() failed"); return SW_ERR; } if (!SSL_set_fd(ssl, fd)) { long err = ERR_get_error(); - swWarn("SSL_set_fd() failed. Error: %s[%ld]", ERR_reason_error_string(err), err); + swoole_warning("SSL_set_fd() failed. Error: %s[%ld]", ERR_reason_error_string(err), err); return SW_ERR; } if (_flags & SW_SSL_CLIENT) { @@ -1417,7 +1417,7 @@ int Socket::ssl_create(SSLContext *ssl_context, int _flags) { SSL_set_accept_state(ssl); } if (SSL_set_ex_data(ssl, swSSL_get_ex_connection_index(), this) == 0) { - swWarn("SSL_set_ex_data() failed"); + swoole_warning("SSL_set_ex_data() failed"); return SW_ERR; } ssl_state = 0; @@ -1435,7 +1435,7 @@ Socket *make_socket(enum swSocket_type type, enum swFd_type fd_type, int flags) int sock_type; if (Socket::get_domain_and_type(type, &sock_domain, &sock_type) < 0) { - swWarn("unknown socket type [%d]", type); + swoole_warning("unknown socket type [%d]", type); errno = ESOCKTNOSUPPORT; return nullptr; } @@ -1477,7 +1477,7 @@ Socket *make_socket(enum swSocket_type type, enum swFd_type fd_type, int flags) Socket *make_server_socket(enum swSocket_type type, const char *address, int port, int backlog) { Socket *sock = swoole::make_socket(type, SW_FD_STREAM_SERVER, SW_SOCK_CLOEXEC); if (sock == nullptr) { - swSysWarn("socket() failed"); + swoole_sys_warning("socket() failed"); return nullptr; } if (sock->bind(address, &port) < 0) { @@ -1485,7 +1485,7 @@ Socket *make_server_socket(enum swSocket_type type, const char *address, int por return nullptr; } if (sock->is_stream() && sock->listen(backlog) < 0) { - swSysWarn("listen(%s:%d, %d) failed", address, port, backlog); + swoole_sys_warning("listen(%s:%d, %d) failed", address, port, backlog); sock->free(); return nullptr; } diff --git a/src/network/stream.cc b/src/network/stream.cc index 7b84a747193..e62002d12c0 100644 --- a/src/network/stream.cc +++ b/src/network/stream.cc @@ -89,7 +89,7 @@ Stream::Stream(const char *dst_host, int dst_port, enum swSocket_type type) : cl set_protocol(&client.protocol); if (client.connect(&client, dst_host, dst_port, -1, 0) < 0) { - swSysWarn("failed to connect to [%s:%d]", dst_host, dst_port); + swoole_sys_warning("failed to connect to [%s:%d]", dst_host, dst_port); return; } connected = true; diff --git a/src/os/async_thread.cc b/src/os/async_thread.cc index e8a48e9c108..387e93df7b0 100644 --- a/src/os/async_thread.cc +++ b/src/os/async_thread.cc @@ -128,7 +128,7 @@ class ThreadPool { if (threads.size() + n > worker_num) { n = worker_num - threads.size(); } - swTraceLog(SW_TRACE_AIO, + swoole_trace_log(SW_TRACE_AIO, "Create %zu thread due to wait %fs, we will have %zu threads", n, _max_wait_time, @@ -152,7 +152,7 @@ class ThreadPool { _queue.push(_event_copy); _cv.notify_one(); event_mutex.unlock(); - swDebug("push and notify one: %f", microtime()); + swoole_debug("push and notify one: %f", microtime()); return _event_copy; } @@ -174,11 +174,11 @@ class ThreadPool { void release_thread(std::thread::id tid) { auto i = threads.find(tid); if (i == threads.end()) { - swWarn("AIO thread#%s is missing", get_thread_id(tid).c_str()); + swoole_warning("AIO thread#%s is missing", get_thread_id(tid).c_str()); return; } else { std::thread *_thread = i->second; - swTraceLog(SW_TRACE_AIO, + swoole_trace_log(SW_TRACE_AIO, "release idle thread#%s, we have %zu now", get_thread_id(tid).c_str(), threads.size() - 1); @@ -238,7 +238,7 @@ void ThreadPool::create_thread(const bool is_core_worker) { AsyncEvent *event = _queue.pop(); event_mutex.unlock(); - swDebug("%s: %f", event ? "pop 1 event" : "no event", microtime()); + swoole_debug("%s: %f", event ? "pop 1 event" : "no event", microtime()); if (event) { if (sw_unlikely(event->handler == nullptr)) { @@ -251,7 +251,7 @@ void ThreadPool::create_thread(const bool is_core_worker) { event->handler(event); } - swTraceLog(SW_TRACE_AIO, + swoole_trace_log(SW_TRACE_AIO, "aio_thread %s. ret=%ld, error=%d", event->retval > 0 ? "ok" : "failed", event->retval, @@ -268,7 +268,7 @@ void ThreadPool::create_thread(const bool is_core_worker) { continue; } else { delete event; - swSysWarn("sendto swoole_aio_pipe_write failed"); + swoole_sys_warning("sendto swoole_aio_pipe_write failed"); } } break; @@ -319,7 +319,7 @@ void ThreadPool::create_thread(const bool is_core_worker) { }); threads[_thread->get_id()] = _thread; } catch (const std::system_error &e) { - swSysNotice("create aio thread failed, please check your system configuration or adjust aio_worker_num"); + swoole_sys_notice("create aio thread failed, please check your system configuration or adjust aio_worker_num"); return; } } @@ -346,7 +346,7 @@ int AsyncThreads::callback(Reactor *reactor, Event *event) { AsyncEvent *events[SW_AIO_EVENT_NUM]; ssize_t n = event->socket->read(events, sizeof(AsyncEvent *) * SW_AIO_EVENT_NUM); if (n < 0) { - swSysWarn("read() aio events failed"); + swoole_sys_warning("read() aio events failed"); return SW_ERR; } for (size_t i = 0; i < n / sizeof(AsyncEvent *); i++) { @@ -373,7 +373,7 @@ void AsyncThreads::notify_one() { AsyncThreads::AsyncThreads() { if (!SwooleTG.reactor) { - swWarn("no event loop, cannot initialized"); + swoole_warning("no event loop, cannot initialized"); throw swoole::Exception(SW_ERROR_WRONG_OPERATION); } diff --git a/src/os/base.cc b/src/os/base.cc index ed237cf367c..1d1efc15543 100644 --- a/src/os/base.cc +++ b/src/os/base.cc @@ -27,20 +27,20 @@ int swoole_daemon(int nochdir, int noclose) { pid_t pid; if (!nochdir && chdir("/") != 0) { - swSysWarn("chdir() failed"); + swoole_sys_warning("chdir() failed"); return -1; } if (!noclose) { int fd = open("/dev/null", O_RDWR); if (fd < 0) { - swSysWarn("open() failed"); + swoole_sys_warning("open() failed"); return -1; } if (dup2(fd, 0) < 0 || dup2(fd, 1) < 0 || dup2(fd, 2) < 0) { close(fd); - swSysWarn("dup2() failed"); + swoole_sys_warning("dup2() failed"); return -1; } @@ -49,14 +49,14 @@ int swoole_daemon(int nochdir, int noclose) { pid = swoole_fork(SW_FORK_DAEMON); if (pid < 0) { - swSysWarn("fork() failed"); + swoole_sys_warning("fork() failed"); return -1; } if (pid > 0) { _exit(0); } if (setsid() < 0) { - swSysWarn("setsid() failed"); + swoole_sys_warning("setsid() failed"); return -1; } return 0; diff --git a/src/os/file.cc b/src/os/file.cc index 0ce290e1b07..93f86fb5ff0 100644 --- a/src/os/file.cc +++ b/src/os/file.cc @@ -24,7 +24,7 @@ int swoole_tmpfile(char *filename) { #endif if (tmp_fd < 0) { - swSysWarn("mkstemp(%s) failed", filename); + swoole_sys_warning("mkstemp(%s) failed", filename); return SW_ERR; } else { return tmp_fd; @@ -63,7 +63,7 @@ ssize_t file_get_size(int fd) { std::shared_ptr file_get_contents(const std::string &filename) { File fp(filename, O_RDONLY); if (!fp.ready()) { - swSysWarn("open(%s) failed", filename.c_str()); + swoole_sys_warning("open(%s) failed", filename.c_str()); return nullptr; } @@ -107,7 +107,7 @@ bool file_put_contents(const std::string &filename, const char *content, size_t } File file(filename, O_WRONLY | O_TRUNC | O_CREAT, 0666); if (!file.ready()) { - swSysWarn("open(%s) failed", filename.c_str()); + swoole_sys_warning("open(%s) failed", filename.c_str()); return false; } return file.write_all(content, length); @@ -130,7 +130,7 @@ size_t File::write_all(const void *data, size_t len) { if (errno == EINTR) { continue; } else if (!(errno == EAGAIN || errno == EWOULDBLOCK)) { - swSysWarn("pwrite(%d, %p, %lu, %lu) failed", fd_, data, len - written_bytes, written_bytes); + swoole_sys_warning("pwrite(%d, %p, %lu, %lu) failed", fd_, data, len - written_bytes, written_bytes); } break; } @@ -150,7 +150,7 @@ size_t File::read_all(void *buf, size_t len) { if (errno == EINTR) { continue; } else if (!(errno == EAGAIN || errno == EWOULDBLOCK)) { - swSysWarn("pread(%d, %p, %lu, %lu) failed", fd_, buf, len - read_bytes, read_bytes); + swoole_sys_warning("pread(%d, %p, %lu, %lu) failed", fd_, buf, len - read_bytes, read_bytes); } break; } diff --git a/src/os/msg_queue.cc b/src/os/msg_queue.cc index 561dbe1b327..bf668a531d4 100644 --- a/src/os/msg_queue.cc +++ b/src/os/msg_queue.cc @@ -24,7 +24,7 @@ namespace swoole { bool MsgQueue::destroy() { if (msgctl(msg_id_, IPC_RMID, 0) < 0) { - swSysWarn("msgctl(%d, IPC_RMID) failed", msg_id_); + swoole_sys_warning("msgctl(%d, IPC_RMID) failed", msg_id_); return false; } msg_id_ = -1; @@ -49,7 +49,7 @@ MsgQueue::MsgQueue(key_t msg_key, bool blocking, int perms) { blocking_ = blocking; msg_id_ = msgget(msg_key, IPC_CREAT | perms); if (msg_id_ < 0) { - swSysWarn("msgget() failed"); + swoole_sys_warning("msgget() failed"); } else { set_blocking(blocking); } @@ -67,7 +67,7 @@ ssize_t MsgQueue::pop(QueueNode *data, size_t mdata_size) { if (ret < 0) { swoole_set_last_error(errno); if (errno != ENOMSG && errno != EINTR) { - swSysWarn("msgrcv(%d, %zu, %ld) failed", msg_id_, mdata_size, data->mtype); + swoole_sys_warning("msgrcv(%d, %zu, %ld) failed", msg_id_, mdata_size, data->mtype); } } return ret; @@ -82,7 +82,7 @@ bool MsgQueue::push(QueueNode *in, size_t mdata_length) { continue; } if (errno != EAGAIN) { - swSysWarn("msgsnd(%d, %lu, %ld) failed", msg_id_, mdata_length, in->mtype); + swoole_sys_warning("msgsnd(%d, %lu, %ld) failed", msg_id_, mdata_length, in->mtype); } swoole_set_last_error(errno); break; @@ -113,7 +113,7 @@ bool MsgQueue::set_capacity(size_t queue_bytes) { } __stat.msg_qbytes = queue_bytes; if (msgctl(msg_id_, IPC_SET, &__stat)) { - swSysWarn("msgctl(msqid=%d, IPC_SET, msg_qbytes=%lu) failed", msg_id_, queue_bytes); + swoole_sys_warning("msgctl(msqid=%d, IPC_SET, msg_qbytes=%lu) failed", msg_id_, queue_bytes); return false; } return true; diff --git a/src/os/pipe.cc b/src/os/pipe.cc index a31c64c3fa3..2f183f8ce11 100644 --- a/src/os/pipe.cc +++ b/src/os/pipe.cc @@ -40,7 +40,7 @@ bool SocketPair::init_socket(int master_fd, int worker_fd) { Pipe::Pipe(bool _blocking) : SocketPair(_blocking) { if (pipe(socks) < 0) { - swSysWarn("pipe() failed"); + swoole_sys_warning("pipe() failed"); return; } if (!init_socket(socks[1], socks[0])) { diff --git a/src/os/process_pool.cc b/src/os/process_pool.cc index da2eaf51cf3..10f649c3919 100644 --- a/src/os/process_pool.cc +++ b/src/os/process_pool.cc @@ -52,9 +52,9 @@ void ProcessPool::kill_timeout_worker(Timer *timer, TimerNode *tnode) { continue; } if (swoole_kill(reload_worker_pid, SIGKILL) < 0) { - swSysWarn("failed to force kill worker process(pid=%d, id=%d)", pool->reload_workers[i].pid, i); + swoole_sys_warning("failed to force kill worker process(pid=%d, id=%d)", pool->reload_workers[i].pid, i); } else { - swWarn("force kill worker process(pid=%d, id=%d)", pool->reload_workers[i].pid, i); + swoole_warning("force kill worker process(pid=%d, id=%d)", pool->reload_workers[i].pid, i); } } } @@ -72,7 +72,7 @@ int ProcessPool::create(uint32_t _worker_num, key_t _msgqueue_key, swIPC_type _i */ workers = (Worker *) sw_mem_pool()->alloc(_worker_num * sizeof(Worker)); if (workers == nullptr) { - swSysWarn("malloc[1] failed"); + swoole_sys_warning("malloc[1] failed"); return SW_ERR; } @@ -128,7 +128,7 @@ int ProcessPool::create(uint32_t _worker_num, key_t _msgqueue_key, swIPC_type _i int ProcessPool::listen(const char *socket_file, int blacklog) { if (ipc_mode != SW_IPC_SOCKET) { - swWarn("ipc_mode is not SW_IPC_SOCKET"); + swoole_warning("ipc_mode is not SW_IPC_SOCKET"); return SW_ERR; } stream_info_->socket_file = sw_strdup(socket_file); @@ -145,7 +145,7 @@ int ProcessPool::listen(const char *socket_file, int blacklog) { int ProcessPool::listen(const char *host, int port, int blacklog) { if (ipc_mode != SW_IPC_SOCKET) { - swWarn("ipc_mode is not SW_IPC_SOCKET"); + swoole_warning("ipc_mode is not SW_IPC_SOCKET"); return SW_ERR; } stream_info_->socket_file = sw_strdup(host); @@ -165,7 +165,7 @@ int ProcessPool::listen(const char *host, int port, int blacklog) { */ int ProcessPool::start() { if (ipc_mode == SW_IPC_SOCKET && (stream_info_ == nullptr || stream_info_->socket == 0)) { - swWarn("must first listen to an tcp port"); + swoole_warning("must first listen to an tcp port"); return SW_ERR; } @@ -253,7 +253,7 @@ int ProcessPool::dispatch(EventData *data, int *dst_worker_id) { if (ret >= 0) { sw_atomic_fetch_add(&worker->tasking_num, 1); } else { - swWarn("send %d bytes to worker#%d failed", sendn, *dst_worker_id); + swoole_warning("send %d bytes to worker#%d failed", sendn, *dst_worker_id); } return ret; @@ -301,7 +301,7 @@ int ProcessPool::dispatch_blocking(EventData *data, int *dst_worker_id) { ret = worker->send_pipe_message(data, sendn, SW_PIPE_MASTER); if (ret < 0) { - swWarn("send %d bytes to worker#%d failed", sendn, *dst_worker_id); + swoole_warning("send %d bytes to worker#%d failed", sendn, *dst_worker_id); } else { sw_atomic_fetch_add(&worker->tasking_num, 1); } @@ -319,14 +319,14 @@ void ProcessPool::shutdown() { for (i = 0; i < worker_num; i++) { worker = &workers[i]; if (swoole_kill(worker->pid, SIGTERM) < 0) { - swSysWarn("swKill(%d) failed", worker->pid); + swoole_sys_warning("swKill(%d) failed", worker->pid); continue; } } for (i = 0; i < worker_num; i++) { worker = &workers[i]; if (swoole_waitpid(worker->pid, &status, 0) < 0) { - swSysWarn("waitpid(%d) failed", worker->pid); + swoole_sys_warning("waitpid(%d) failed", worker->pid); } } started = false; @@ -360,7 +360,7 @@ pid_t ProcessPool::spawn(Worker *worker) { exit(ret_code); break; case -1: - swSysWarn("fork() failed"); + swoole_sys_warning("fork() failed"); break; // parent default: @@ -425,7 +425,7 @@ static int ProcessPool_worker_loop(ProcessPool *pool, Worker *worker) { if (pool->use_msgqueue) { n = pool->queue->pop((QueueNode *) &out, sizeof(out.buf)); if (n < 0 && errno != EINTR) { - swSysWarn("[Worker#%d] msgrcv() failed", worker->id); + swoole_sys_warning("[Worker#%d] msgrcv() failed", worker->id); break; } } else if (pool->use_socket) { @@ -434,7 +434,7 @@ static int ProcessPool_worker_loop(ProcessPool *pool, Worker *worker) { if (errno == EAGAIN || errno == EINTR) { continue; } else { - swSysWarn("accept(%d) failed", pool->stream_info_->socket->get_fd()); + swoole_sys_warning("accept(%d) failed", pool->stream_info_->socket->get_fd()); break; } } @@ -447,7 +447,7 @@ static int ProcessPool_worker_loop(ProcessPool *pool, Worker *worker) { } else { n = worker->pipe_worker->read(&out.buf, sizeof(out.buf)); if (n < 0 && errno != EINTR) { - swSysWarn("[Worker#%d] read(%d) failed", worker->id, worker->pipe_worker->fd); + swoole_sys_warning("[Worker#%d] read(%d) failed", worker->id, worker->pipe_worker->fd); } } @@ -464,7 +464,7 @@ static int ProcessPool_worker_loop(ProcessPool *pool, Worker *worker) { } if (n != (ssize_t)(out.buf.info.len + sizeof(out.buf.info))) { - swWarn("bad task packet, The received data-length[%ld] is inconsistent with the packet-length[%ld]", + swoole_warning("bad task packet, The received data-length[%ld] is inconsistent with the packet-length[%ld]", n, out.buf.info.len + sizeof(out.buf.info)); continue; @@ -525,7 +525,7 @@ static int ProcessPool_worker_loop_ex(ProcessPool *pool, Worker *worker) { if (pool->use_msgqueue) { n = pool->queue->pop(outbuf, SW_MSGMAX); if (n < 0 && errno != EINTR) { - swSysWarn("[Worker#%d] msgrcv() failed", worker->id); + swoole_sys_warning("[Worker#%d] msgrcv() failed", worker->id); break; } data = outbuf->mdata; @@ -536,7 +536,7 @@ static int ProcessPool_worker_loop_ex(ProcessPool *pool, Worker *worker) { if (errno == EAGAIN || errno == EINTR) { continue; } else { - swSysWarn("accept(%d) failed", pool->stream_info_->socket->get_fd()); + swoole_sys_warning("accept(%d) failed", pool->stream_info_->socket->get_fd()); break; } } @@ -560,7 +560,7 @@ static int ProcessPool_worker_loop_ex(ProcessPool *pool, Worker *worker) { } else { n = worker->pipe_worker->read(pool->packet_buffer, pool->max_packet_size_); if (n < 0 && errno != EINTR) { - swSysWarn("[Worker#%d] read(%d) failed", worker->id, worker->pipe_worker->fd); + swoole_sys_warning("[Worker#%d] read(%d) failed", worker->id, worker->pipe_worker->fd); } data = pool->packet_buffer; } @@ -658,7 +658,7 @@ int ProcessPool::wait() { } pid_t new_pid = spawn(exit_worker); if (new_pid < 0) { - swSysWarn("fork worker process failed"); + swoole_sys_warning("fork worker process failed"); return SW_ERR; } map_->erase(msg.pid); @@ -671,12 +671,12 @@ int ProcessPool::wait() { } if (!reloading) { if (errno > 0 && errno != EINTR) { - swSysWarn("[Manager] wait failed"); + swoole_sys_warning("[Manager] wait failed"); } continue; } else { if (!reload_init) { - swInfo("reload workers"); + swoole_info("reload workers"); reload_init = true; memcpy(reload_workers, workers, sizeof(Worker) * worker_num); if (max_wait_time) { @@ -693,13 +693,13 @@ int ProcessPool::wait() { if (onWorkerNotFound) { onWorkerNotFound(this, exit_status); } else { - swWarn("[Manager]unknown worker[pid=%d]", exit_status.get_pid()); + swoole_warning("[Manager]unknown worker[pid=%d]", exit_status.get_pid()); } continue; } if (!exit_status.is_normal_exit()) { - swWarn("worker#%d abnormal exit, status=%d, signal=%d" + swoole_warning("worker#%d abnormal exit, status=%d, signal=%d" "%s", exit_worker->id, exit_status.get_code(), @@ -708,7 +708,7 @@ int ProcessPool::wait() { } new_pid = spawn(exit_worker); if (new_pid < 0) { - swSysWarn("Fork worker process failed"); + swoole_sys_warning("Fork worker process failed"); return SW_ERR; } map_->erase(exit_status.get_pid()); @@ -732,7 +732,7 @@ int ProcessPool::wait() { reload_worker_i++; goto _kill_worker; } - swSysWarn("[Manager]swKill(%d) failed", reload_workers[reload_worker_i].pid); + swoole_sys_warning("[Manager]swKill(%d) failed", reload_workers[reload_worker_i].pid); continue; } } diff --git a/src/os/sendfile.cc b/src/os/sendfile.cc index 90a28a8f612..e8f192e7481 100644 --- a/src/os/sendfile.cc +++ b/src/os/sendfile.cc @@ -40,7 +40,7 @@ int swoole_sendfile(int out_fd, int in_fd, off_t *offset, size_t size) { #endif // sent_bytes = (off_t)size; - swTrace( + swoole_trace( "send file, ret:%d, out_fd:%d, in_fd:%d, offset:%jd, size:%zu", ret, out_fd, in_fd, (intmax_t) *offset, size); #ifdef __MACH__ @@ -58,7 +58,7 @@ int swoole_sendfile(int out_fd, int in_fd, off_t *offset, size_t size) { } else if (ret == 0) { return size; } else { - swSysWarn("sendfile failed"); + swoole_sys_warning("sendfile failed"); return SW_ERR; } return SW_OK; @@ -72,13 +72,13 @@ int swoole_sendfile(int out_fd, int in_fd, off_t *offset, size_t size) { if (n > 0) { ssize_t ret = write(out_fd, buf, n); if (ret < 0) { - swSysWarn("write() failed"); + swoole_sys_warning("write() failed"); } else { *offset += ret; } return ret; } else { - swSysWarn("pread() failed"); + swoole_sys_warning("pread() failed"); return SW_ERR; } } diff --git a/src/os/signal.cc b/src/os/signal.cc index df5cf59b8c2..8c40f342f6f 100644 --- a/src/os/signal.cc +++ b/src/os/signal.cc @@ -78,7 +78,7 @@ void swoole_signal_block_all(void) { sigfillset(&mask); int ret = pthread_sigmask(SIG_BLOCK, &mask, nullptr); if (ret < 0) { - swSysWarn("pthread_sigmask() failed"); + swoole_sys_warning("pthread_sigmask() failed"); } } @@ -153,7 +153,7 @@ static void swoole_signal_async_handler(int signo) { void swoole_signal_callback(int signo) { if (signo >= SW_SIGNO_MAX) { - swWarn("signal[%d] numberis invalid", signo); + swoole_warning("signal[%d] numberis invalid", signo); return; } SignalHandler callback = signals[signo].handler; @@ -167,7 +167,7 @@ void swoole_signal_callback(int signo) { SignalHandler swoole_signal_get_handler(int signo) { if (signo >= SW_SIGNO_MAX) { - swWarn("signal[%d] numberis invalid", signo); + swoole_warning("signal[%d] numberis invalid", signo); return nullptr; } else { return signals[signo].handler; @@ -241,12 +241,12 @@ static bool swoole_signalfd_create() { signal_fd = signalfd(-1, &signalfd_mask, SFD_NONBLOCK | SFD_CLOEXEC); if (signal_fd < 0) { - swSysWarn("signalfd() failed"); + swoole_sys_warning("signalfd() failed"); return false; } signal_socket = swoole::make_socket(signal_fd, SW_FD_SIGNAL); if (sigprocmask(SIG_BLOCK, &signalfd_mask, nullptr) == -1) { - swSysWarn("sigprocmask() failed"); + swoole_sys_warning("sigprocmask() failed"); signal_socket->fd = -1; signal_socket->free(); close(signal_fd); @@ -285,7 +285,7 @@ bool swoole_signalfd_setup(Reactor *reactor) { static void swoole_signalfd_clear() { if (signal_fd) { if (sigprocmask(SIG_UNBLOCK, &signalfd_mask, nullptr) < 0) { - swSysWarn("sigprocmask(SIG_UNBLOCK) failed"); + swoole_sys_warning("sigprocmask(SIG_UNBLOCK) failed"); } if (signal_socket) { signal_socket->free(); @@ -300,11 +300,11 @@ static int swoole_signalfd_event_callback(Reactor *reactor, Event *event) { struct signalfd_siginfo siginfo; ssize_t n = read(event->fd, &siginfo, sizeof(siginfo)); if (n < 0) { - swSysWarn("read from signalfd failed"); + swoole_sys_warning("read from signalfd failed"); return SW_OK; } if (siginfo.ssi_signo >= SW_SIGNO_MAX) { - swWarn("unknown signal[%d]", siginfo.ssi_signo); + swoole_warning("unknown signal[%d]", siginfo.ssi_signo); return SW_OK; } if (signals[siginfo.ssi_signo].activated) { @@ -357,7 +357,7 @@ static SignalHandler swoole_signal_kqueue_set(int signo, SignalHandler handler) } int n = kevent(reactor->native_handle, &ev, 1, nullptr, 0, nullptr); if (n < 0 && sw_unlikely(handler)) { - swSysWarn("kevent set signal[%d] error", signo); + swoole_sys_warning("kevent set signal[%d] error", signo); } return origin_handler; diff --git a/src/os/timer.cc b/src/os/timer.cc index f473b329306..f28e75a1b4c 100644 --- a/src/os/timer.cc +++ b/src/os/timer.cc @@ -37,7 +37,7 @@ static int SystemTimer_set(Timer *timer, long next_msec) { struct itimerval timer_set; struct timeval now; if (gettimeofday(&now, nullptr) < 0) { - swSysWarn("gettimeofday() failed"); + swoole_sys_warning("gettimeofday() failed"); return SW_ERR; } @@ -58,7 +58,7 @@ static int SystemTimer_set(Timer *timer, long next_msec) { } if (setitimer(ITIMER_REAL, &timer_set, nullptr) < 0) { - swSysWarn("setitimer() failed"); + swoole_sys_warning("setitimer() failed"); return SW_ERR; } return SW_OK; diff --git a/src/os/unix_socket.cc b/src/os/unix_socket.cc index 70383058443..c9f066a09ca 100644 --- a/src/os/unix_socket.cc +++ b/src/os/unix_socket.cc @@ -21,7 +21,7 @@ namespace swoole { UnixSocket::UnixSocket(bool blocking, int _protocol) : SocketPair(blocking), protocol_(_protocol) { if (socketpair(AF_UNIX, protocol_, 0, socks) < 0) { - swSysWarn("socketpair() failed"); + swoole_sys_warning("socketpair() failed"); return; } if (!init_socket(socks[1], socks[0])) { diff --git a/src/protocol/base.cc b/src/protocol/base.cc index 1da9433b4b4..1ad076b669c 100644 --- a/src/protocol/base.cc +++ b/src/protocol/base.cc @@ -45,14 +45,14 @@ ssize_t Protocol::default_length_func(Protocol *protocol, network::Socket *socke // Length error // Protocol length is not legitimate, out of bounds or exceed the allocated length if (body_length < 0) { - swWarn("invalid package (size=%d) from socket#%u<%s:%d>", + swoole_warning("invalid package (size=%d) from socket#%u<%s:%d>", size, socket->fd, socket->info.get_ip(), socket->info.get_port()); return SW_ERR; } - swDebug("length=%d", protocol->package_body_offset + body_length); + swoole_debug("length=%d", protocol->package_body_offset + body_length); // total package length return protocol->package_body_offset + body_length; @@ -136,7 +136,7 @@ int Protocol::recv_with_length_protocol(network::Socket *socket, String *buffer) if (recv_n < 0) { switch (socket->catch_error(errno)) { case SW_ERROR: - swSysWarn("recv(%d, %d) failed", socket->fd, recv_size); + swoole_sys_warning("recv(%d, %d) failed", socket->fd, recv_size); return SW_OK; case SW_CLOSE: return SW_ERR; @@ -240,7 +240,7 @@ int Protocol::recv_with_eof_protocol(network::Socket *socket, String *buffer) { if (n < 0) { switch (socket->catch_error(errno)) { case SW_ERROR: - swSysWarn("recv from socket#%d failed", socket->fd); + swoole_sys_warning("recv from socket#%d failed", socket->fd); return SW_OK; case SW_CLOSE: return SW_ERR; @@ -284,7 +284,7 @@ int Protocol::recv_with_eof_protocol(network::Socket *socket, String *buffer) { // over max length, will discard if (buffer->length == package_max_length) { - swWarn("Package is too big. package_length=%d", (int) buffer->length); + swoole_warning("Package is too big. package_length=%d", (int) buffer->length); return SW_ERR; } diff --git a/src/protocol/dtls.cc b/src/protocol/dtls.cc index 1008c1c4b1e..c684b675af2 100644 --- a/src/protocol/dtls.cc +++ b/src/protocol/dtls.cc @@ -6,7 +6,7 @@ namespace dtls { //------------------------------------------------------------------------------- int BIO_write(BIO *b, const char *data, int dlen) { - swTraceLog(SW_TRACE_SSL, "BIO_write(%d)", dlen); + swoole_trace_log(SW_TRACE_SSL, "BIO_write(%d)", dlen); Session *session = (Session *) BIO_get_data(b); return session->socket->write(data, dlen); @@ -20,7 +20,7 @@ int BIO_read(BIO *b, char *data, int len) { if (!session->rxqueue.empty()) { buffer = session->rxqueue.front(); - swTrace("BIO_read(%d, peek=%d)=%d", len, session->peek_mode, buffer->length); + swoole_trace("BIO_read(%d, peek=%d)=%d", len, session->peek_mode, buffer->length); int n = (buffer->length <= len) ? buffer->length : len; memmove(data, buffer->data, n); @@ -41,7 +41,7 @@ long BIO_ctrl(BIO *b, int cmd, long lval, void *ptrval) { long retval = 0; Session *session = (Session *) BIO_get_data(b); - swTraceLog(SW_TRACE_SSL, "BIO_ctrl(BIO[0x%016lX], cmd[%d], lval[%ld], ptrval[0x%016lX])", b, cmd, lval, ptrval); + swoole_trace_log(SW_TRACE_SSL, "BIO_ctrl(BIO[0x%016lX], cmd[%d], lval[%ld], ptrval[0x%016lX])", b, cmd, lval, ptrval); switch (cmd) { case BIO_CTRL_EOF: @@ -88,7 +88,7 @@ long BIO_ctrl(BIO *b, int cmd, long lval, void *ptrval) { retval = 0; break; default: - swWarn("unknown cmd: %d", cmd); + swoole_warning("unknown cmd: %d", cmd); retval = 0; break; } @@ -101,7 +101,7 @@ int BIO_create(BIO *b) { } int BIO_destroy(BIO *b) { - swTraceLog(SW_TRACE_SSL, "BIO_destroy(BIO[0x%016lX])\n", b); + swoole_trace_log(SW_TRACE_SSL, "BIO_destroy(BIO[0x%016lX])\n", b); return 1; } @@ -170,7 +170,7 @@ bool Session::listen() { return true; } else if (retval < 0) { int reason = ERR_GET_REASON(ERR_peek_error()); - swWarn("DTLSv1_listen() failed, client[%s:%d], reason=%d, error_string=%s", + swoole_warning("DTLSv1_listen() failed, client[%s:%d], reason=%d, error_string=%s", socket->info.get_ip(), socket->info.get_port(), reason, diff --git a/src/protocol/redis.cc b/src/protocol/redis.cc index 68c314669c4..184ffa0602e 100644 --- a/src/protocol/redis.cc +++ b/src/protocol/redis.cc @@ -50,7 +50,7 @@ int recv_packet(Protocol *protocol, Connection *conn, String *buffer) { if (conn->object == nullptr) { request = (Request *) sw_malloc(sizeof(Request)); if (!request) { - swWarn("malloc(%ld) failed", sizeof(Request)); + swoole_warning("malloc(%ld) failed", sizeof(Request)); return SW_ERR; } sw_memset_zero(request, sizeof(Request)); @@ -67,7 +67,7 @@ int recv_packet(Protocol *protocol, Connection *conn, String *buffer) { if (n < 0) { switch (socket->catch_error(errno)) { case SW_ERROR: - swSysWarn("recv from socket#%d failed", conn->fd); + swoole_sys_warning("recv from socket#%d failed", conn->fd); return SW_OK; case SW_CLOSE: return SW_ERR; @@ -90,7 +90,7 @@ int recv_packet(Protocol *protocol, Connection *conn, String *buffer) { } } else if (buffer->length == buffer->size) { _package_too_big: - swWarn("Package is too big. package_length=%ld", buffer->length); + swoole_warning("Package is too big. package_length=%ld", buffer->length); return SW_ERR; } goto _recv_data; @@ -164,7 +164,7 @@ int recv_packet(Protocol *protocol, Connection *conn, String *buffer) { } while (p < pe); } _failed: - swWarn("redis protocol error"); + swoole_warning("redis protocol error"); return SW_ERR; } diff --git a/src/protocol/ssl.cc b/src/protocol/ssl.cc index d4a0e980716..64d7aa92f53 100644 --- a/src/protocol/ssl.cc +++ b/src/protocol/ssl.cc @@ -72,13 +72,13 @@ void swSSL_init(void) { ssl_connection_index = SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr); if (ssl_connection_index < 0) { - swError("SSL_get_ex_new_index() failed"); + swoole_error("SSL_get_ex_new_index() failed"); return; } ssl_port_index = SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr); if (ssl_port_index < 0) { - swError("SSL_get_ex_new_index() failed"); + swoole_error("SSL_get_ex_new_index() failed"); return; } @@ -181,7 +181,7 @@ static void swSSL_info_callback(const SSL *ssl, int where, int ret) { if (sock->ssl_state == SW_SSL_STATE_READY) { sock->ssl_renegotiation = 1; - swDebug("SSL renegotiation"); + swoole_debug("SSL renegotiation"); } } @@ -267,11 +267,11 @@ static int ssl_select_next_proto_cb(SSL *ssl, uchar **out, uchar *outlen, const for (unsigned int i = 0; i < inlen; i += in[i] + 1) { info += " * " + std::string(reinterpret_cast(&in[i + 1]), in[i]); } - swTraceLog(SW_TRACE_HTTP2, "[NPN] server offers: %s", info.c_str()); + swoole_trace_log(SW_TRACE_HTTP2, "[NPN] server offers: %s", info.c_str()); #endif SSLContext *ctx = (SSLContext *) arg; if (ctx->http_v2 && !ssl_select_h2(const_cast(out), outlen, in, inlen)) { - swWarn("HTTP/2 protocol was not selected, expects [h2]"); + swoole_warning("HTTP/2 protocol was not selected, expects [h2]"); return SSL_TLSEXT_ERR_NOACK; } else if (ctx->http) { *out = (uchar*) HTTP1_NPN.c_str(); @@ -314,7 +314,7 @@ bool SSLContext::create() { context = SSL_CTX_new(method); if (context == nullptr) { int error = ERR_get_error(); - swWarn("SSL_CTX_new() failed, Error: %s[%d]", ERR_reason_error_string(error), error); + swoole_warning("SSL_CTX_new() failed, Error: %s[%d]", ERR_reason_error_string(error), error); return false; } @@ -423,7 +423,7 @@ bool SSLContext::create() { */ if (SSL_CTX_use_certificate_file(context, cert_file.c_str(), SSL_FILETYPE_PEM) <= 0) { int error = ERR_get_error(); - swWarn("SSL_CTX_use_certificate_file(%s) failed, Error: %s[%d]", cert_file.c_str(), + swoole_warning("SSL_CTX_use_certificate_file(%s) failed, Error: %s[%d]", cert_file.c_str(), ERR_reason_error_string(error), error); return true; } @@ -433,7 +433,7 @@ bool SSLContext::create() { */ if (SSL_CTX_use_certificate_chain_file(context, cert_file.c_str()) <= 0) { int error = ERR_get_error(); - swWarn("SSL_CTX_use_certificate_chain_file(%s) failed, Error: %s[%d]", cert_file.c_str(), + swoole_warning("SSL_CTX_use_certificate_chain_file(%s) failed, Error: %s[%d]", cert_file.c_str(), ERR_reason_error_string(error), error); return false; } @@ -444,7 +444,7 @@ bool SSLContext::create() { */ if (SSL_CTX_use_PrivateKey_file(context, key_file.c_str(), SSL_FILETYPE_PEM) <= 0) { int error = ERR_get_error(); - swWarn("SSL_CTX_use_PrivateKey_file(%s) failed, Error: %s[%d]", key_file.c_str(), + swoole_warning("SSL_CTX_use_PrivateKey_file(%s) failed, Error: %s[%d]", key_file.c_str(), ERR_reason_error_string(error), error); return false; } @@ -452,7 +452,7 @@ bool SSLContext::create() { * verify private key */ if (!SSL_CTX_check_private_key(context)) { - swWarn("Private key does not match the public certificate"); + swoole_warning("Private key does not match the public certificate"); return false; } } @@ -496,12 +496,12 @@ bool SSLContext::create() { #endif if (!client_cert_file.empty() && !set_client_certificate()) { - swWarn("set_client_certificate() error"); + swoole_warning("set_client_certificate() error"); return false; } if (!set_ciphers()) { - swWarn("set_cipher() error"); + swoole_warning("set_cipher() error"); return false; } @@ -517,7 +517,7 @@ bool SSLContext::set_capath() { } } else { if (!SSL_CTX_set_default_verify_paths(context)) { - swWarn("Unable to set default verify locations and no CA settings specified"); + swoole_warning("Unable to set default verify locations and no CA settings specified"); return false; } } @@ -536,7 +536,7 @@ bool SSLContext::set_ciphers() { if (!ciphers.empty()) { if (SSL_CTX_set_cipher_list(context, ciphers.c_str()) == 0) { - swWarn("SSL_CTX_set_cipher_list(\"%s\") failed", ciphers.c_str()); + swoole_warning("SSL_CTX_set_cipher_list(\"%s\") failed", ciphers.c_str()); return false; } if (prefer_server_ciphers) { @@ -572,14 +572,14 @@ bool SSLContext::set_client_certificate() { SSL_CTX_set_verify_depth(context, depth); if (SSL_CTX_load_verify_locations(context, cert_file, nullptr) == 0) { - swWarn("SSL_CTX_load_verify_locations(\"%s\") failed", cert_file); + swoole_warning("SSL_CTX_load_verify_locations(\"%s\") failed", cert_file); return false; } ERR_clear_error(); list = SSL_load_client_CA_file(cert_file); if (list == nullptr) { - swWarn("SSL_load_client_CA_file(\"%s\") failed", cert_file); + swoole_warning("SSL_load_client_CA_file(\"%s\") failed", cert_file); return false; } @@ -618,7 +618,7 @@ bool SSLContext::set_ecdh_curve() { return true; } if (SSL_CTX_set1_curves_list(context, ecdh_curve.c_str()) == 0) { - swWarn("SSL_CTX_set1_curves_list(\"%s\") failed", ecdh_curve.c_str()); + swoole_warning("SSL_CTX_set1_curves_list(\"%s\") failed", ecdh_curve.c_str()); return false; } #else @@ -631,13 +631,13 @@ bool SSLContext::set_ecdh_curve() { */ int nid = OBJ_sn2nid(ecdh_curve.c_str()); if (nid == 0) { - swWarn("Unknown curve name \"%s\"", ecdh_curve.c_str()); + swoole_warning("Unknown curve name \"%s\"", ecdh_curve.c_str()); return false; } ecdh = EC_KEY_new_by_curve_name(nid); if (ecdh == nullptr) { - swWarn("Unable to create curve \"%s\"", ecdh_curve.c_str()); + swoole_warning("Unable to create curve \"%s\"", ecdh_curve.c_str()); return false; } @@ -659,13 +659,13 @@ bool SSLContext::set_dhparam() { bio = BIO_new_file(file, "r"); if (bio == nullptr) { - swWarn("BIO_new_file(%s) failed", file); + swoole_warning("BIO_new_file(%s) failed", file); return false; } dh = PEM_read_bio_DHparams(bio, nullptr, nullptr, nullptr); if (dh == nullptr) { - swWarn("PEM_read_bio_DHparams(%s) failed", file); + swoole_warning("PEM_read_bio_DHparams(%s) failed", file); BIO_free(bio); return false; } @@ -700,7 +700,7 @@ static int swSSL_verify_callback(int ok, X509_STORE_CTX *x509_store) { iname = X509_get_issuer_name(cert); issuer = iname ? X509_NAME_oneline(iname, nullptr, 0) : "(none)"; - swWarn("verify:%d, error:%d, depth:%d, subject:\"%s\", issuer:\"%s\"", ok, err, depth, subject, issuer); + swoole_warning("verify:%d, error:%d, depth:%d, subject:\"%s\", issuer:\"%s\"", ok, err, depth, subject, issuer); if (sname) { @@ -757,7 +757,7 @@ static int swSSL_generate_cookie(SSL *ssl, uchar *cookie, uint *cookie_len) { buffer = (uchar *) OPENSSL_malloc(length); if (buffer == nullptr) { - swSysWarn("out of memory"); + swoole_sys_warning("out of memory"); return 0; } @@ -803,7 +803,7 @@ static RSA *swSSL_rsa_key_callback(SSL *ssl, int is_export, int key_length) { BIGNUM *bn = BN_new(); if (bn == nullptr) { - swWarn("allocation error generating RSA key"); + swoole_warning("allocation error generating RSA key"); return nullptr; } @@ -835,7 +835,7 @@ static int swSSL_set_default_dhparam(SSL_CTX *ssl_context) { static unsigned char dh1024_g[] = {0x02}; dh = DH_new(); if (dh == nullptr) { - swWarn("DH_new() failed"); + swoole_warning("DH_new() failed"); return SW_ERR; } diff --git a/src/protocol/websocket.cc b/src/protocol/websocket.cc index 1264a70d606..606c291184f 100644 --- a/src/protocol/websocket.cc +++ b/src/protocol/websocket.cc @@ -94,7 +94,7 @@ ssize_t get_package_length(Protocol *protocol, Socket *conn, const char *buf, ui return 0; } } - swTraceLog(SW_TRACE_LENGTH_PROTOCOL, "header_length=%zu, payload_length=%lu", header_length, payload_length); + swoole_trace_log(SW_TRACE_LENGTH_PROTOCOL, "header_length=%zu, payload_length=%lu", header_length, payload_length); return header_length + payload_length; } @@ -180,7 +180,7 @@ bool decode(Frame *frame, char *data, size_t length) { header_length += 8; } - swTraceLog(SW_TRACE_WEBSOCKET, + swoole_trace_log(SW_TRACE_WEBSOCKET, "decode frame, payload_length=%ld, mask=%d, opcode=%d", payload_length, frame->header.MASK, @@ -209,7 +209,7 @@ bool decode(Frame *frame, char *data, size_t length) { int pack_close_frame(String *buffer, int code, char *reason, size_t length, uint8_t flags) { if (sw_unlikely(length > SW_WEBSOCKET_CLOSE_REASON_MAX_LEN)) { - swWarn("the max length of close reason is %d", SW_WEBSOCKET_CLOSE_REASON_MAX_LEN); + swoole_warning("the max length of close reason is %d", SW_WEBSOCKET_CLOSE_REASON_MAX_LEN); return SW_ERR; } @@ -260,7 +260,7 @@ int dispatch_frame(Protocol *proto, Socket *_socket, const char *data, uint32_t case OPCODE_CONTINUATION: frame_buffer = conn->websocket_buffer; if (frame_buffer == nullptr) { - swWarn("bad frame[opcode=0]. remote_addr=%s:%d", conn->info.get_ip(), conn->info.get_port()); + swoole_warning("bad frame[opcode=0]. remote_addr=%s:%d", conn->info.get_ip(), conn->info.get_port()); return SW_ERR; } offset = length - ws.payload_length; @@ -268,7 +268,7 @@ int dispatch_frame(Protocol *proto, Socket *_socket, const char *data, uint32_t port = serv->get_port_by_fd(conn->fd); // frame data overflow if (frame_buffer->length + frame_length > port->protocol.package_max_length) { - swWarn("websocket frame is too big, remote_addr=%s:%d", conn->info.get_ip(), conn->info.get_port()); + swoole_warning("websocket frame is too big, remote_addr=%s:%d", conn->info.get_ip(), conn->info.get_port()); return SW_ERR; } // merge incomplete data @@ -290,7 +290,7 @@ int dispatch_frame(Protocol *proto, Socket *_socket, const char *data, uint32_t if (!ws.header.FIN) { if (conn->websocket_buffer) { - swWarn("merging incomplete frame, bad request. remote_addr=%s:%d", + swoole_warning("merging incomplete frame, bad request. remote_addr=%s:%d", conn->info.get_ip(), conn->info.get_port()); return SW_ERR; @@ -305,7 +305,7 @@ int dispatch_frame(Protocol *proto, Socket *_socket, const char *data, uint32_t case OPCODE_PING: case OPCODE_PONG: if (length >= (sizeof(buf) - SW_WEBSOCKET_HEADER_LEN)) { - swWarn("%s frame application data is too big. remote_addr=%s:%d", + swoole_warning("%s frame application data is too big. remote_addr=%s:%d", ws.header.OPCODE == OPCODE_PING ? "ping" : "pong", conn->info.get_ip(), conn->info.get_port()); @@ -349,7 +349,7 @@ int dispatch_frame(Protocol *proto, Socket *_socket, const char *data, uint32_t return SW_ERR; default: - swWarn("unknown opcode [%d]", ws.header.OPCODE); + swoole_warning("unknown opcode [%d]", ws.header.OPCODE); break; } return SW_OK; diff --git a/src/reactor/base.cc b/src/reactor/base.cc index 795bacbd123..0d6aad873f0 100644 --- a/src/reactor/base.cc +++ b/src/reactor/base.cc @@ -50,7 +50,7 @@ ReactorImpl *make_reactor_select(Reactor *_reactor); void ReactorImpl::after_removal_failure(network::Socket *_socket) { if (!_socket->silent_remove) { - swSysWarn("failed to delete events[fd=%d#%d, type=%d, events=%d]", + swoole_sys_warning("failed to delete events[fd=%d#%d, type=%d, events=%d]", _socket->fd, reactor_->id, _socket->fd_type, @@ -163,7 +163,7 @@ bool Reactor::set_handler(int _fdtype, ReactorHandler handler) { int fdtype = get_fd_type(_fdtype); if (fdtype >= SW_MAX_FDTYPE) { - swWarn("fdtype > SW_MAX_FDTYPE[%d]", SW_MAX_FDTYPE); + swoole_warning("fdtype > SW_MAX_FDTYPE[%d]", SW_MAX_FDTYPE); return false; } @@ -174,7 +174,7 @@ bool Reactor::set_handler(int _fdtype, ReactorHandler handler) { } else if (Reactor::isset_error_event(_fdtype)) { error_handler[fdtype] = handler; } else { - swWarn("unknown fdtype"); + swoole_warning("unknown fdtype"); return false; } @@ -211,7 +211,7 @@ int Reactor::_close(Reactor *reactor, Socket *socket) { socket->in_buffer = nullptr; } - swTraceLog(SW_TRACE_CLOSE, "fd=%d", socket->fd); + swoole_trace_log(SW_TRACE_CLOSE, "fd=%d", socket->fd); socket->free(); @@ -262,7 +262,7 @@ static int write_func( if (!socket->out_buffer) { buffer = new Buffer(socket->chunk_size); if (!buffer) { - swWarn("create worker buffer failed"); + swoole_warning("create worker buffer failed"); return SW_ERR; } socket->out_buffer = buffer; diff --git a/src/reactor/epoll.cc b/src/reactor/epoll.cc index fd0d440d983..7d167cc1b05 100644 --- a/src/reactor/epoll.cc +++ b/src/reactor/epoll.cc @@ -82,7 +82,7 @@ ReactorImpl *make_reactor_epoll(Reactor *_reactor, int max_events) { ReactorEpoll::ReactorEpoll(Reactor *_reactor, int max_events) : ReactorImpl(_reactor) { epfd_ = epoll_create(512); if (!ready()) { - swSysWarn("epoll_create failed"); + swoole_sys_warning("epoll_create failed"); return; } @@ -109,7 +109,7 @@ int ReactorEpoll::add(Socket *socket, int events) { e.data.ptr = socket; if (epoll_ctl(epfd_, EPOLL_CTL_ADD, socket->fd, &e) < 0) { - swSysWarn( + swoole_sys_warning( "failed to add events[fd=%d#%d, type=%d, events=%d]", socket->fd, reactor_->id, socket->fd_type, events); return SW_ERR; } @@ -119,7 +119,7 @@ int ReactorEpoll::add(Socket *socket, int events) { #endif reactor_->_add(socket, events); - swTraceLog( + swoole_trace_log( SW_TRACE_EVENT, "add events[fd=%d#%d, type=%d, events=%d]", socket->fd, reactor_->id, socket->fd_type, events); return SW_OK; @@ -144,7 +144,7 @@ int ReactorEpoll::del(Socket *_socket) { event_map.erase(_socket->fd); #endif - swTraceLog(SW_TRACE_REACTOR, "remove event[reactor_id=%d|fd=%d]", reactor_->id, _socket->fd); + swoole_trace_log(SW_TRACE_REACTOR, "remove event[reactor_id=%d|fd=%d]", reactor_->id, _socket->fd); reactor_->_del(_socket); return SW_OK; @@ -158,12 +158,12 @@ int ReactorEpoll::set(Socket *socket, int events) { int ret = epoll_ctl(epfd_, EPOLL_CTL_MOD, socket->fd, &e); if (ret < 0) { - swSysWarn( + swoole_sys_warning( "failed to set events[fd=%d#%d, type=%d, events=%d]", socket->fd, reactor_->id, socket->fd_type, events); return SW_ERR; } - swTraceLog(SW_TRACE_EVENT, "set event[reactor_id=%d, fd=%d, events=%d]", reactor_->id, socket->fd, events); + swoole_trace_log(SW_TRACE_EVENT, "set event[reactor_id=%d, fd=%d, events=%d]", reactor_->id, socket->fd, events); reactor_->_set(socket, events); return SW_OK; @@ -194,7 +194,7 @@ int ReactorEpoll::wait(struct timeval *timeo) { n = epoll_wait(epfd_, events_, max_event_num, reactor_->get_timeout_msec()); if (n < 0) { if (!reactor_->catch_error()) { - swSysWarn("[Reactor#%d] epoll_wait failed", reactor_id); + swoole_sys_warning("[Reactor#%d] epoll_wait failed", reactor_id); return SW_ERR; } else { goto _continue; @@ -217,7 +217,7 @@ int ReactorEpoll::wait(struct timeval *timeo) { handler = reactor_->get_handler(SW_EVENT_READ, event.type); ret = handler(reactor_, &event); if (ret < 0) { - swSysWarn("EPOLLIN handle failed. fd=%d", event.fd); + swoole_sys_warning("EPOLLIN handle failed. fd=%d", event.fd); } } // write @@ -225,7 +225,7 @@ int ReactorEpoll::wait(struct timeval *timeo) { handler = reactor_->get_handler(SW_EVENT_WRITE, event.type); ret = handler(reactor_, &event); if (ret < 0) { - swSysWarn("EPOLLOUT handle failed. fd=%d", event.fd); + swoole_sys_warning("EPOLLOUT handle failed. fd=%d", event.fd); } } // error @@ -237,7 +237,7 @@ int ReactorEpoll::wait(struct timeval *timeo) { handler = reactor_->get_error_handler(event.type); ret = handler(reactor_, &event); if (ret < 0) { - swSysWarn("EPOLLERR handle failed. fd=%d", event.fd); + swoole_sys_warning("EPOLLERR handle failed. fd=%d", event.fd); } } if (!event.socket->removed && (event.socket->events & SW_EVENT_ONCE)) { diff --git a/src/reactor/kqueue.cc b/src/reactor/kqueue.cc index 46c8d845154..e2cffd89199 100644 --- a/src/reactor/kqueue.cc +++ b/src/reactor/kqueue.cc @@ -71,7 +71,7 @@ ReactorImpl *make_reactor_kqueue(Reactor *_reactor, int max_events) { ReactorKqueue::ReactorKqueue(Reactor *reactor, int max_events) : ReactorImpl(reactor) { epfd_ = kqueue(); if (epfd_ < 0) { - swWarn("[swReactorKqueueCreate] kqueue_create[0] fail"); + swoole_warning("[swReactorKqueueCreate] kqueue_create[0] fail"); return; } @@ -112,7 +112,7 @@ int ReactorKqueue::add(Socket *socket, int events) { EV_SET(&e, fd, EVFILT_READ, EV_ADD, fflags, 0, sobj); ret = ::kevent(epfd_, &e, 1, nullptr, 0, nullptr); if (ret < 0) { - swSysWarn( + swoole_sys_warning( "add events_[fd=%d, reactor_id=%d, type=%d, events=read] failed", fd, reactor_->id, socket->fd_type); return SW_ERR; } @@ -122,14 +122,14 @@ int ReactorKqueue::add(Socket *socket, int events) { EV_SET(&e, fd, EVFILT_WRITE, EV_ADD, 0, 0, sobj); ret = ::kevent(epfd_, &e, 1, nullptr, 0, nullptr); if (ret < 0) { - swSysWarn( + swoole_sys_warning( "add events_[fd=%d, reactor_id=%d, type=%d, events=write] failed", fd, reactor_->id, socket->fd_type); return SW_ERR; } } reactor_->_add(socket, events); - swTraceLog(SW_TRACE_EVENT, "[THREAD #%d]epfd=%d, fd=%d, events=%d", SwooleTG.id, epfd_, fd, socket->events); + swoole_trace_log(SW_TRACE_EVENT, "[THREAD #%d]epfd=%d, fd=%d, events=%d", SwooleTG.id, epfd_, fd, socket->events); return SW_OK; } @@ -154,14 +154,14 @@ int ReactorKqueue::set(Socket *socket, int events) { EV_SET(&e, fd, EVFILT_READ, EV_ADD, fflags, 0, sobj); ret = ::kevent(epfd_, &e, 1, nullptr, 0, nullptr); if (ret < 0) { - swSysWarn("kqueue->set(%d, SW_EVENT_READ) failed", fd); + swoole_sys_warning("kqueue->set(%d, SW_EVENT_READ) failed", fd); return SW_ERR; } } else { EV_SET(&e, fd, EVFILT_READ, EV_DELETE, 0, 0, sobj); ret = ::kevent(epfd_, &e, 1, nullptr, 0, nullptr); if (ret < 0) { - swSysWarn("kqueue->del(%d, SW_EVENT_READ) failed", fd); + swoole_sys_warning("kqueue->del(%d, SW_EVENT_READ) failed", fd); return SW_ERR; } } @@ -170,20 +170,20 @@ int ReactorKqueue::set(Socket *socket, int events) { EV_SET(&e, fd, EVFILT_WRITE, EV_ADD, 0, 0, sobj); ret = ::kevent(epfd_, &e, 1, nullptr, 0, nullptr); if (ret < 0) { - swSysWarn("kqueue->set(%d, SW_EVENT_WRITE) failed", fd); + swoole_sys_warning("kqueue->set(%d, SW_EVENT_WRITE) failed", fd); return SW_ERR; } } else { EV_SET(&e, fd, EVFILT_WRITE, EV_DELETE, 0, 0, sobj); ret = ::kevent(epfd_, &e, 1, nullptr, 0, nullptr); if (ret < 0) { - swSysWarn("kqueue->del(%d, SW_EVENT_WRITE) failed", fd); + swoole_sys_warning("kqueue->del(%d, SW_EVENT_WRITE) failed", fd); return SW_ERR; } } reactor_->_set(socket, events); - swTraceLog(SW_TRACE_EVENT, "[THREAD #%d]epfd=%d, fd=%d, events=%d", SwooleTG.id, epfd_, fd, socket->events); + swoole_trace_log(SW_TRACE_EVENT, "[THREAD #%d]epfd=%d, fd=%d, events=%d", SwooleTG.id, epfd_, fd, socket->events); return SW_OK; } @@ -209,7 +209,7 @@ int ReactorKqueue::del(Socket *socket) { EV_SET(&e, fd, EVFILT_READ, EV_DELETE, 0, 0, sobj); ret = ::kevent(epfd_, &e, 1, nullptr, 0, nullptr); if (ret < 0) { - swSysWarn("kqueue->del(%d, SW_EVENT_READ) failed", fd); + swoole_sys_warning("kqueue->del(%d, SW_EVENT_READ) failed", fd); if (errno != EBADF && errno != ENOENT) { return SW_ERR; } @@ -228,7 +228,7 @@ int ReactorKqueue::del(Socket *socket) { } reactor_->_del(socket); - swTraceLog(SW_TRACE_EVENT, "[THREAD #%d]epfd=%d, fd=%d", SwooleTG.id, epfd_, fd); + swoole_trace_log(SW_TRACE_EVENT, "[THREAD #%d]epfd=%d, fd=%d", SwooleTG.id, epfd_, fd); return SW_OK; } @@ -270,7 +270,7 @@ int ReactorKqueue::wait(struct timeval *timeo) { n = ::kevent(epfd_, nullptr, 0, events_, event_max_, t_ptr); if (n < 0) { if (!reactor_->catch_error()) { - swWarn("kqueue[#%d], epfd=%d", reactor_->id, epfd_); + swoole_warning("kqueue[#%d], epfd=%d", reactor_->id, epfd_); return SW_ERR; } else { goto _continue; @@ -280,7 +280,7 @@ int ReactorKqueue::wait(struct timeval *timeo) { SW_REACTOR_CONTINUE; } - swTraceLog(SW_TRACE_EVENT, "n %d events", n); + swoole_trace_log(SW_TRACE_EVENT, "n %d events", n); for (i = 0; i < n; i++) { struct kevent *kevent = &events_[i]; @@ -295,7 +295,7 @@ int ReactorKqueue::wait(struct timeval *timeo) { handler = reactor_->get_handler(kevent->filter == EVFILT_READ ? SW_EVENT_READ : SW_EVENT_WRITE, event.type); if (sw_unlikely(handler(reactor_, &event) < 0)) { - swSysWarn("kqueue event %s socket#%d handler failed", + swoole_sys_warning("kqueue event %s socket#%d handler failed", kevent->filter == EVFILT_READ ? "read" : "write", event.fd); } @@ -318,7 +318,7 @@ int ReactorKqueue::wait(struct timeval *timeo) { break; } default: - swWarn("unknown event filter[%d]", kevent->filter); + swoole_warning("unknown event filter[%d]", kevent->filter); break; } } diff --git a/src/reactor/poll.cc b/src/reactor/poll.cc index 9b46db01311..a0d7f89673d 100644 --- a/src/reactor/poll.cc +++ b/src/reactor/poll.cc @@ -62,19 +62,19 @@ ReactorPoll::~ReactorPoll() { int ReactorPoll::add(Socket *socket, int events) { int fd = socket->fd; if (exists(fd)) { - swWarn("fd#%d is already exists", fd); + swoole_warning("fd#%d is already exists", fd); return SW_ERR; } int cur = reactor_->event_num; if (reactor_->event_num == max_fd_num) { - swWarn("too many connection, more than %d", max_fd_num); + swoole_warning("too many connection, more than %d", max_fd_num); return SW_ERR; } reactor_->_add(socket, events); - swTrace("fd=%d, events=%d", fd, events); + swoole_trace("fd=%d, events=%d", fd, events); fds_[cur] = socket; events_[cur].fd = fd; @@ -96,7 +96,7 @@ int ReactorPoll::add(Socket *socket, int events) { int ReactorPoll::set(Socket *socket, int events) { uint32_t i; - swTrace("fd=%d, events=%d", socket->fd, events); + swoole_trace("fd=%d, events=%d", socket->fd, events); for (i = 0; i < reactor_->event_num; i++) { // found @@ -169,7 +169,7 @@ int ReactorPoll::wait(struct timeval *timeo) { ret = poll(events_, reactor_->event_num, reactor_->get_timeout_msec()); if (ret < 0) { if (!reactor_->catch_error()) { - swSysWarn("poll error"); + swoole_sys_warning("poll error"); break; } else { goto _continue; @@ -188,13 +188,13 @@ int ReactorPoll::wait(struct timeval *timeo) { event.socket->event_hup = 1; } - swTrace("Event: fd=%d|reactor_id=%d|type=%d", event.fd, reactor_->id, event.type); + swoole_trace("Event: fd=%d|reactor_id=%d|type=%d", event.fd, reactor_->id, event.type); // in if ((events_[i].revents & POLLIN) && !event.socket->removed) { handler = reactor_->get_handler(SW_EVENT_READ, event.type); ret = handler(reactor_, &event); if (ret < 0) { - swSysWarn("poll[POLLIN] handler failed. fd=%d", event.fd); + swoole_sys_warning("poll[POLLIN] handler failed. fd=%d", event.fd); } } // out @@ -202,7 +202,7 @@ int ReactorPoll::wait(struct timeval *timeo) { handler = reactor_->get_handler(SW_EVENT_WRITE, event.type); ret = handler(reactor_, &event); if (ret < 0) { - swSysWarn("poll[POLLOUT] handler failed. fd=%d", event.fd); + swoole_sys_warning("poll[POLLOUT] handler failed. fd=%d", event.fd); } } // error @@ -214,7 +214,7 @@ int ReactorPoll::wait(struct timeval *timeo) { handler = reactor_->get_error_handler(event.type); ret = handler(reactor_, &event); if (ret < 0) { - swSysWarn("poll[POLLERR] handler failed. fd=%d", event.fd); + swoole_sys_warning("poll[POLLERR] handler failed. fd=%d", event.fd); } } if (!event.socket->removed && (event.socket->events & SW_EVENT_ONCE)) { diff --git a/src/reactor/select.cc b/src/reactor/select.cc index 2cad587a1c6..1f4dab6a23f 100644 --- a/src/reactor/select.cc +++ b/src/reactor/select.cc @@ -67,7 +67,7 @@ ReactorSelect::ReactorSelect(Reactor *reactor) : ReactorImpl(reactor) { int ReactorSelect::add(Socket *socket, int events) { int fd = socket->fd; if (fd > FD_SETSIZE) { - swWarn("max fd value is FD_SETSIZE(%d).\n", FD_SETSIZE); + swoole_warning("max fd value is FD_SETSIZE(%d).\n", FD_SETSIZE); return SW_ERR; } @@ -90,7 +90,7 @@ int ReactorSelect::del(Socket *socket) { } int fd = socket->fd; if (fds.erase(fd) == 0) { - swWarn("swReactorSelect: fd[%d] not found", fd); + swoole_warning("swReactorSelect: fd[%d] not found", fd); return SW_ERR; } SW_FD_CLR(fd, &rfds); @@ -103,7 +103,7 @@ int ReactorSelect::del(Socket *socket) { int ReactorSelect::set(Socket *socket, int events) { auto i = fds.find(socket->fd); if (i == fds.end()) { - swWarn("swReactorSelect: sock[%d] not found", socket->fd); + swoole_warning("swReactorSelect: sock[%d] not found", socket->fd); return SW_ERR; } reactor_->_set(socket, events); @@ -163,7 +163,7 @@ int ReactorSelect::wait(struct timeval *timeo) { ret = select(maxfd + 1, &(rfds), &(wfds), &(efds), &timeout); if (ret < 0) { if (!reactor_->catch_error()) { - swSysWarn("select error"); + swoole_sys_warning("select error"); break; } else { goto _continue; @@ -187,7 +187,7 @@ int ReactorSelect::wait(struct timeval *timeo) { handler = reactor_->get_handler(SW_EVENT_READ, event.type); ret = handler(reactor_, &event); if (ret < 0) { - swSysWarn("[Reactor#%d] select event[type=READ, fd=%d] handler fail", reactor_->id, event.fd); + swoole_sys_warning("[Reactor#%d] select event[type=READ, fd=%d] handler fail", reactor_->id, event.fd); } } // write @@ -195,7 +195,7 @@ int ReactorSelect::wait(struct timeval *timeo) { handler = reactor_->get_handler(SW_EVENT_WRITE, event.type); ret = handler(reactor_, &event); if (ret < 0) { - swSysWarn("[Reactor#%d] select event[type=WRITE, fd=%d] handler fail", reactor_->id, event.fd); + swoole_sys_warning("[Reactor#%d] select event[type=WRITE, fd=%d] handler fail", reactor_->id, event.fd); } } // error @@ -203,7 +203,7 @@ int ReactorSelect::wait(struct timeval *timeo) { handler = reactor_->get_handler(SW_EVENT_ERROR, event.type); ret = handler(reactor_, &event); if (ret < 0) { - swSysWarn("[Reactor#%d] select event[type=ERROR, fd=%d] handler fail", reactor_->id, event.fd); + swoole_sys_warning("[Reactor#%d] select event[type=ERROR, fd=%d] handler fail", reactor_->id, event.fd); } } if (!event.socket->removed && (event.socket->events & SW_EVENT_ONCE)) { diff --git a/src/server/base.cc b/src/server/base.cc index 33245e01bd3..a1fb79cbfdc 100644 --- a/src/server/base.cc +++ b/src/server/base.cc @@ -34,12 +34,12 @@ bool BaseFactory::dispatch(SendData *task) { if (Server::is_stream_event(task->info.type)) { conn = server_->get_connection(task->info.fd); if (conn == nullptr || conn->active == 0) { - swWarn("dispatch[type=%d] failed, socket#%ld is not active", task->info.type, task->info.fd); + swoole_warning("dispatch[type=%d] failed, socket#%ld is not active", task->info.type, task->info.fd); return false; } // server active close, discard data. if (conn->closed) { - swWarn("dispatch[type=%d] failed, socket#%ld is closed by server", task->info.type, task->info.fd); + swoole_warning("dispatch[type=%d] failed, socket#%ld is closed by server", task->info.type, task->info.fd); return false; } // converted fd to session_id @@ -73,12 +73,12 @@ bool BaseFactory::dispatch(SendData *task) { bool BaseFactory::notify(DataHead *info) { Connection *conn = server_->get_connection(info->fd); if (conn == nullptr || conn->active == 0) { - swWarn("dispatch[type=%d] failed, socket#%ld is not active", info->type, info->fd); + swoole_warning("dispatch[type=%d] failed, socket#%ld is not active", info->type, info->fd); return false; } // server active close, discard data. if (conn->closed) { - swWarn("dispatch[type=%d] failed, session#%ld is closed by server", info->type, conn->session_id); + swoole_warning("dispatch[type=%d] failed, session#%ld is closed by server", info->type, conn->session_id); return false; } // converted fd to session_id @@ -106,7 +106,7 @@ bool BaseFactory::end(SessionId session_id, int flags) { if (session->reactor_id != SwooleG.process_id) { Worker *worker = server_->get_worker(session->reactor_id); if (worker->pipe_master->send_async((const char*) &_send.info, sizeof(_send.info)) < 0) { - swSysWarn("failed to send %lu bytes to pipe_master", sizeof(_send.info)); + swoole_sys_warning("failed to send %lu bytes to pipe_master", sizeof(_send.info)); return false; } return true; @@ -128,7 +128,7 @@ bool BaseFactory::end(SessionId session_id, int flags) { if (conn->close_force) { goto _do_close; } else if (conn->closing) { - swWarn("session#%ld is closing", session_id); + swoole_warning("session#%ld is closing", session_id); return false; } else if (conn->closed) { return false; @@ -151,7 +151,7 @@ bool BaseFactory::end(SessionId session_id, int flags) { conn->close_errno = 0; if (conn->socket == nullptr) { - swWarn("session#%ld->socket is nullptr", session_id); + swoole_warning("session#%ld->socket is nullptr", session_id); return false; } @@ -172,7 +172,7 @@ bool BaseFactory::finish(SendData *data) { Session *session = server_->get_session(session_id); if (session->reactor_id != SwooleG.process_id) { - swTrace("session->reactor_id=%d, SwooleG.process_id=%d", session->reactor_id, SwooleG.process_id); + swoole_trace("session->reactor_id=%d, SwooleG.process_id=%d", session->reactor_id, SwooleG.process_id); Worker *worker = server_->gs->event_workers.get_worker(session->reactor_id); EventData proxy_msg{}; @@ -196,18 +196,18 @@ bool BaseFactory::finish(SendData *data) { offset += proxy_msg.info.len; size_t __len = sizeof(proxy_msg.info) + proxy_msg.info.len; if (worker->pipe_master->send_async((const char*) &proxy_msg, __len) < 0) { - swSysWarn("failed to send %lu bytes to pipe_master", __len); + swoole_sys_warning("failed to send %lu bytes to pipe_master", __len); return false; } } - swTrace("proxy message, fd=%d, len=%ld", worker->pipe_master->fd, sizeof(proxy_msg.info) + proxy_msg.info.len); + swoole_trace("proxy message, fd=%d, len=%ld", worker->pipe_master->fd, sizeof(proxy_msg.info) + proxy_msg.info.len); } else if (data->info.type == SW_SERVER_EVENT_SEND_FILE) { memcpy(&proxy_msg.info, &data->info, sizeof(proxy_msg.info)); memcpy(proxy_msg.data, data->data, data->info.len); size_t __len = sizeof(proxy_msg.info) + proxy_msg.info.len; return worker->pipe_master->send_async((const char*) &proxy_msg, __len); } else { - swWarn("unkown event type[%d]", data->info.type); + swoole_warning("unkown event type[%d]", data->info.type); return false; } return true; diff --git a/src/server/manager.cc b/src/server/manager.cc index b3a85f8069e..642b36effff 100644 --- a/src/server/manager.cc +++ b/src/server/manager.cc @@ -70,7 +70,7 @@ void Manager::kill_timeout_process(Timer *timer, TimerNode *tnode) { continue; } if (swoole_kill(pid, SIGKILL) < 0) { - swSysWarn("kill(%d, SIGKILL) [%u] failed", pid, worker_id); + swoole_sys_warning("kill(%d, SIGKILL) [%u] failed", pid, worker_id); } else { swoole_error_log(SW_LOG_WARNING, SW_ERROR_SERVER_WORKER_EXIT_TIMEOUT, @@ -146,7 +146,7 @@ int Server::start_manager_process() { // wait master process SW_START_SLEEP; if (!is_started()) { - swError("master process is not running"); + swoole_error("master process is not running"); return SW_ERR; } @@ -154,7 +154,7 @@ int Server::start_manager_process() { if (task_worker_num > 0) { if (gs->task_workers.start() == SW_ERR) { - swError("failed to start task workers"); + swoole_error("failed to start task workers"); return SW_ERR; } } @@ -163,7 +163,7 @@ int Server::start_manager_process() { Worker *worker = get_worker(i); pid = spawn_event_worker(worker); if (pid < 0) { - swError("fork() failed"); + swoole_error("fork() failed"); return SW_ERR; } else { worker->pid = pid; @@ -177,7 +177,7 @@ int Server::start_manager_process() { } pid = spawn_user_worker(worker); if (pid < 0) { - swError("failed to start user workers"); + swoole_error("failed to start user workers"); return SW_ERR; } } @@ -195,7 +195,7 @@ int Server::start_manager_process() { gs->manager_pid = pid; break; case -1: - swError("fork() failed"); + swoole_error("fork() failed"); return SW_ERR; } return SW_OK; @@ -203,7 +203,7 @@ int Server::start_manager_process() { void Server::check_worker_exit_status(int worker_id, const ExitStatus &exit_status) { if (exit_status.get_status() != 0) { - swWarn("worker(pid=%d, id=%d) abnormal exit, status=%d, signal=%d" + swoole_warning("worker(pid=%d, id=%d) abnormal exit, status=%d, signal=%d" "%s", exit_status.get_pid(), worker_id, @@ -292,13 +292,13 @@ void Manager::start(Server *_server) { if (!reloading) { _error: if (errno > 0 && errno != EINTR) { - swSysWarn("wait() failed"); + swoole_sys_warning("wait() failed"); } continue; } // reload task & event workers else if (reload_all_worker) { - swInfo("Server is reloading all workers now"); + swoole_info("Server is reloading all workers now"); if (_server->onBeforeReload != nullptr) { _server->onBeforeReload(_server); } @@ -322,7 +322,7 @@ void Manager::start(Server *_server) { if (_server->reload_async) { SW_LOOP_N(_server->worker_num) { if (swoole_kill(reload_workers[i].pid, SIGTERM) < 0) { - swSysWarn("swKill(%d, SIGTERM) [%d] failed", reload_workers[i].pid, i); + swoole_sys_warning("swKill(%d, SIGTERM) [%d] failed", reload_workers[i].pid, i); } } reload_worker_i = _server->worker_num; @@ -335,11 +335,11 @@ void Manager::start(Server *_server) { // only reload task workers else if (reload_task_worker) { if (_server->task_worker_num == 0) { - swWarn("cannot reload task workers, task workers is not started"); + swoole_warning("cannot reload task workers, task workers is not started"); reloading = false; continue; } - swInfo("Server is reloading task workers now"); + swoole_info("Server is reloading task workers now"); if (_server->onBeforeReload != nullptr) { _server->onBeforeReload(_server); } @@ -415,7 +415,7 @@ void Manager::start(Server *_server) { reload_worker_i++; goto _kill_worker; } - swSysWarn("swKill(%d, SIGTERM) [%d] failed", reload_workers[reload_worker_i].pid, reload_worker_i); + swoole_sys_warning("swKill(%d, SIGTERM) [%d] failed", reload_workers[reload_worker_i].pid, reload_worker_i); } } } @@ -571,7 +571,7 @@ void Server::kill_user_workers() { for (auto &kv : *user_worker_map) { int __stat_loc; if (swoole_waitpid(kv.second->pid, &__stat_loc, 0) < 0) { - swSysWarn("waitpid(%d) failed", kv.second->pid); + swoole_sys_warning("waitpid(%d) failed", kv.second->pid); } } } @@ -587,12 +587,12 @@ void Server::kill_event_workers() { } for (uint32_t i = 0; i < worker_num; i++) { - swTrace("[Manager]kill worker processor"); + swoole_trace("[Manager]kill worker processor"); swoole_kill(workers[i].pid, SIGTERM); } for (uint32_t i = 0; i < worker_num; i++) { if (swoole_waitpid(workers[i].pid, &status, 0) < 0) { - swSysWarn("waitpid(%d) failed", workers[i].pid); + swoole_sys_warning("waitpid(%d) failed", workers[i].pid); } } } @@ -614,7 +614,7 @@ pid_t Server::spawn_event_worker(Worker *worker) { // fork() failed if (pid < 0) { - swSysWarn("Fork Worker failed"); + swoole_sys_warning("Fork Worker failed"); return SW_ERR; } // worker child processor @@ -631,7 +631,7 @@ pid_t Server::spawn_user_worker(Worker *worker) { pid_t pid = swoole_fork(0); if (pid < 0) { - swSysWarn("Fork Worker failed"); + swoole_sys_warning("Fork Worker failed"); return SW_ERR; } // child diff --git a/src/server/master.cc b/src/server/master.cc index d2a1ab7dffd..5cb0f020dba 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -109,12 +109,12 @@ int Server::accept_connection(Reactor *reactor, Event *event) { if (errno == EMFILE || errno == ENFILE) { serv->disable_accept(); } - swSysWarn("accept() failed"); + swoole_sys_warning("accept() failed"); return SW_OK; } } - swTrace("[Master] Accept new connection. maxfd=%d|minfd=%d|reactor_id=%d|conn=%d", + swoole_trace("[Master] Accept new connection. maxfd=%d|minfd=%d|reactor_id=%d|conn=%d", serv->get_maxfd(), serv->get_minfd(), reactor->id, @@ -220,14 +220,14 @@ dtls::Session *Server::accept_dtls_connection(ListenPort *port, Address *sa) { } if (sock->bind(port->socket->info) < 0) { - swSysWarn("bind() failed"); + swoole_sys_warning("bind() failed"); goto _cleanup; } if (sock->is_inet6()) { sock->set_option(IPPROTO_IPV6, IPV6_V6ONLY, 0); } if (sock->connect(sa) < 0) { - swSysWarn("connect(%s:%d) failed", sa->get_addr(), sa->get_port()); + swoole_sys_warning("connect(%s:%d) failed", sa->get_addr(), sa->get_port()); goto _cleanup; } @@ -262,7 +262,7 @@ dtls::Session *Server::accept_dtls_connection(ListenPort *port, Address *sa) { void Server::set_max_connection(uint32_t _max_connection) { if (connection_list != nullptr) { - swWarn("max_connection must be set before server create"); + swoole_warning("max_connection must be set before server create"); return; } max_connection = _max_connection; @@ -270,11 +270,11 @@ void Server::set_max_connection(uint32_t _max_connection) { max_connection = SW_MIN(SW_MAX_CONNECTION, SwooleG.max_sockets); } else if (max_connection > SW_SESSION_LIST_SIZE) { max_connection = SW_SESSION_LIST_SIZE; - swWarn("max_connection is exceed the SW_SESSION_LIST_SIZE, it's reset to %u", SW_SESSION_LIST_SIZE); + swoole_warning("max_connection is exceed the SW_SESSION_LIST_SIZE, it's reset to %u", SW_SESSION_LIST_SIZE); } if (SwooleG.max_sockets > 0 && max_connection > SwooleG.max_sockets) { max_connection = SwooleG.max_sockets; - swWarn("max_connection is exceed the maximum value, it's reset to %u", SwooleG.max_sockets); + swoole_warning("max_connection is exceed the maximum value, it's reset to %u", SwooleG.max_sockets); } } @@ -283,19 +283,19 @@ int Server::start_check() { if (is_process_mode()) { if (!is_support_unsafe_events()) { if (onConnect) { - swWarn("cannot set 'onConnect' event when using dispatch_mode=1/3/7"); + swoole_warning("cannot set 'onConnect' event when using dispatch_mode=1/3/7"); onConnect = nullptr; } if (onClose) { - swWarn("cannot set 'onClose' event when using dispatch_mode=1/3/7"); + swoole_warning("cannot set 'onClose' event when using dispatch_mode=1/3/7"); onClose = nullptr; } if (onBufferFull) { - swWarn("cannot set 'onBufferFull' event when using dispatch_mode=1/3/7"); + swoole_warning("cannot set 'onBufferFull' event when using dispatch_mode=1/3/7"); onBufferFull = nullptr; } if (onBufferEmpty) { - swWarn("cannot set 'onBufferEmpty' event when using dispatch_mode=1/3/7"); + swoole_warning("cannot set 'onBufferEmpty' event when using dispatch_mode=1/3/7"); onBufferEmpty = nullptr; } disable_notify = 1; @@ -308,7 +308,7 @@ int Server::start_check() { } if (task_worker_num > 0) { if (onTask == nullptr) { - swWarn("onTask event callback must be set"); + swoole_warning("onTask event callback must be set"); return SW_ERR; } } @@ -327,11 +327,11 @@ int Server::start_check() { ls->protocol.package_max_length = SW_BUFFER_MIN_SIZE; } if (if_require_receive_callback(ls, onReceive != nullptr)) { - swWarn("require onReceive callback"); + swoole_warning("require onReceive callback"); return SW_ERR; } if (if_require_packet_callback(ls, onPacket != nullptr)) { - swWarn("require onPacket callback"); + swoole_warning("require onPacket callback"); return SW_ERR; } if (ls->heartbeat_idle_time > 0) { @@ -388,7 +388,7 @@ int Server::create_task_workers() { ProcessPool *pool = &gs->task_workers; *pool = {}; if (pool->create(task_worker_num, key, ipc_mode) < 0) { - swWarn("[Master] create task_workers failed"); + swoole_warning("[Master] create task_workers failed"); return SW_ERR; } @@ -427,7 +427,7 @@ int Server::create_user_workers() { user_workers = (Worker *) sw_shm_calloc(user_worker_num, sizeof(Worker)); if (user_workers == nullptr) { - swSysWarn("gmalloc[server->user_workers] failed"); + swoole_sys_warning("gmalloc[server->user_workers] failed"); return SW_ERR; } @@ -460,7 +460,7 @@ void Server::init_worker(Worker *worker) { CPU_SET(SwooleG.process_id % SW_CPU_NUM, &cpu_set); } if (swoole_set_cpu_affinity(&cpu_set) < 0) { - swSysWarn("swoole_set_cpu_affinity() failed"); + swoole_sys_warning("swoole_set_cpu_affinity() failed"); } } #endif @@ -524,7 +524,7 @@ int Server::start() { if (null_fd > 0) { swoole_redirect_stdout(null_fd); } else { - swSysWarn("open(/dev/null) failed"); + swoole_sys_warning("open(/dev/null) failed"); } } @@ -558,7 +558,7 @@ int Server::start() { if (task_worker_num > 0 && worker_num > 0) { task_result = (EventData *) sw_shm_calloc(worker_num, sizeof(EventData)); if (!task_result) { - swWarn("malloc[task_result] failed"); + swoole_warning("malloc[task_result] failed"); return SW_ERR; } SW_LOOP_N(worker_num) { @@ -644,7 +644,7 @@ Server::Server(enum Mode _mode) { */ gs = (ServerGS *) sw_shm_malloc(sizeof(ServerGS)); if (gs == nullptr) { - swError("[Master] Fatal Error: failed to allocate memory for Server->gs"); + swoole_error("[Master] Fatal Error: failed to allocate memory for Server->gs"); } worker_msg_id = 1; @@ -670,13 +670,13 @@ int Server::create() { session_list = (Session *) sw_shm_calloc(SW_SESSION_LIST_SIZE, sizeof(Session)); if (session_list == nullptr) { - swError("sw_shm_calloc(%ld) for session_list failed", SW_SESSION_LIST_SIZE * sizeof(Session)); + swoole_error("sw_shm_calloc(%ld) for session_list failed", SW_SESSION_LIST_SIZE * sizeof(Session)); return SW_ERR; } port_connnection_num_list = (uint32_t *) sw_shm_calloc(ports.size(), sizeof(sw_atomic_t)); if (port_connnection_num_list == nullptr) { - swError("sw_shm_calloc() for port_connnection_num_array failed"); + swoole_error("sw_shm_calloc() for port_connnection_num_array failed"); return SW_ERR; } @@ -696,11 +696,11 @@ int Server::create() { } if (max_connection < minimum_connection) { max_connection = SwooleG.max_sockets; - swWarn("max_connection must be bigger than %u, it's reset to %u", minimum_connection, SwooleG.max_sockets); + swoole_warning("max_connection must be bigger than %u, it's reset to %u", minimum_connection, SwooleG.max_sockets); } // Reactor Thread Num if (reactor_num > SW_CPU_NUM * SW_MAX_THREAD_NCPU) { - swWarn("serv->reactor_num == %d, Too many threads, reset to max value %d", + swoole_warning("serv->reactor_num == %d, Too many threads, reset to max value %d", reactor_num, SW_CPU_NUM * SW_MAX_THREAD_NCPU); reactor_num = SW_CPU_NUM * SW_MAX_THREAD_NCPU; @@ -712,7 +712,7 @@ int Server::create() { } // Worker Process Num if (worker_num > SW_CPU_NUM * SW_MAX_WORKER_NCPU) { - swWarn( + swoole_warning( "worker_num == %d, Too many processes, reset to max value %d", worker_num, SW_CPU_NUM * SW_MAX_WORKER_NCPU); worker_num = SW_CPU_NUM * SW_MAX_WORKER_NCPU; } @@ -722,7 +722,7 @@ int Server::create() { // TaskWorker Process Num if (task_worker_num > 0) { if (task_worker_num > SW_CPU_NUM * SW_MAX_WORKER_NCPU) { - swWarn("serv->task_worker_num == %d, Too many processes, reset to max value %d", + swoole_warning("serv->task_worker_num == %d, Too many processes, reset to max value %d", task_worker_num, SW_CPU_NUM * SW_MAX_WORKER_NCPU); task_worker_num = SW_CPU_NUM * SW_MAX_WORKER_NCPU; @@ -730,7 +730,7 @@ int Server::create() { } workers = (Worker *) sw_shm_calloc(worker_num, sizeof(Worker)); if (workers == nullptr) { - swSysWarn("gmalloc[server->workers] failed"); + swoole_sys_warning("gmalloc[server->workers] failed"); return SW_ERR; } @@ -781,11 +781,11 @@ void Server::shutdown() { gs->event_workers.running = 0; } - swInfo("Server is shutdown now"); + swoole_info("Server is shutdown now"); } void Server::destroy() { - swTraceLog(SW_TRACE_SERVER, "release service"); + swoole_trace_log(SW_TRACE_SERVER, "release service"); if (SwooleG.hooks[SW_GLOBAL_HOOK_BEFORE_SERVER_SHUTDOWN]) { swoole_call_hook(SW_GLOBAL_HOOK_BEFORE_SERVER_SHUTDOWN, this); } @@ -794,13 +794,13 @@ void Server::destroy() { */ factory->shutdown(); if (is_base_mode()) { - swTraceLog(SW_TRACE_SERVER, "terminate task workers"); + swoole_trace_log(SW_TRACE_SERVER, "terminate task workers"); if (task_worker_num > 0) { gs->task_workers.shutdown(); gs->task_workers.destroy(); } } else { - swTraceLog(SW_TRACE_SERVER, "terminate reactor threads"); + swoole_trace_log(SW_TRACE_SERVER, "terminate reactor threads"); /** * Wait until all the end of the thread */ @@ -988,7 +988,7 @@ int Server::schedule_worker(int fd, SendData *data) { if (sw_unlikely(!found)) { scheduler_warning = true; } - swTraceLog(SW_TRACE_SERVER, "schedule=%d, round=%d", key, worker_round_id); + swoole_trace_log(SW_TRACE_SERVER, "schedule=%d, round=%d", key, worker_round_id); return key; } @@ -1394,7 +1394,7 @@ bool Server::is_healthy_connection(double now, Connection *conn) { int Server::add_systemd_socket() { int pid; if (!swoole_get_env("LISTEN_PID", &pid) && getpid() != pid) { - swWarn("invalid LISTEN_PID"); + swoole_warning("invalid LISTEN_PID"); return 0; } @@ -1410,7 +1410,7 @@ int Server::add_systemd_socket() { if (!swoole_get_env("LISTEN_FDS_START", &start_fd)) { start_fd = SW_SYSTEMD_FDS_START; } else if (start_fd < 0) { - swWarn("invalid LISTEN_FDS_START"); + swoole_warning("invalid LISTEN_FDS_START"); return 0; } @@ -1485,7 +1485,7 @@ ListenPort *Server::add_port(enum swSocket_type type, const char *host, int port ls->dtls_sessions = new std::unordered_map; #else - swWarn("DTLS support require openssl-1.1 or later"); + swoole_warning("DTLS support require openssl-1.1 or later"); return nullptr; #endif } @@ -1515,7 +1515,7 @@ ListenPort *Server::add_port(enum swSocket_type type, const char *host, int port } static void Server_signal_handler(int sig) { - swTraceLog(SW_TRACE_SERVER, "signal[%d] %s triggered in %d", sig, swoole_signal_to_str(sig), getpid()); + swoole_trace_log(SW_TRACE_SERVER, "signal[%d] %s triggered in %d", sig, swoole_signal_to_str(sig), getpid()); Server *serv = sw_server(); if (!SwooleG.running or !serv) { @@ -1537,7 +1537,7 @@ static void Server_signal_handler(int sig) { } pid = waitpid(-1, &status, WNOHANG); if (pid > 0 && pid == serv->gs->manager_pid) { - swWarn("Fatal Error: manager process exit. status=%d, signal=[%s]", + swoole_warning("Fatal Error: manager process exit. status=%d, signal=[%s]", WEXITSTATUS(status), swoole_signal_to_str(WTERMSIG(status))); } @@ -1546,7 +1546,7 @@ static void Server_signal_handler(int sig) { * for test */ case SIGVTALRM: - swWarn("SIGVTALRM coming"); + swoole_warning("SIGVTALRM coming"); break; /** * proxy the restart signal @@ -1645,7 +1645,7 @@ Connection *Server::add_connection(ListenPort *ls, Socket *_socket, int server_f // TCP Nodelay if (ls->open_tcp_nodelay && (ls->type == SW_SOCK_TCP || ls->type == SW_SOCK_TCP6)) { if (ls->socket->set_tcp_nodelay() != 0) { - swSysWarn("setsockopt(TCP_NODELAY) failed"); + swoole_sys_warning("setsockopt(TCP_NODELAY) failed"); } _socket->enable_tcp_nodelay = true; } @@ -1653,14 +1653,14 @@ Connection *Server::add_connection(ListenPort *ls, Socket *_socket, int server_f // socket recv buffer size if (ls->kernel_socket_recv_buffer_size > 0) { if (ls->socket->set_option(SOL_SOCKET, SO_RCVBUF, ls->kernel_socket_recv_buffer_size) != 0) { - swSysWarn("setsockopt(SO_RCVBUF, %d) failed", ls->kernel_socket_recv_buffer_size); + swoole_sys_warning("setsockopt(SO_RCVBUF, %d) failed", ls->kernel_socket_recv_buffer_size); } } // socket send buffer size if (ls->kernel_socket_send_buffer_size > 0) { if (ls->socket->set_option(SOL_SOCKET, SO_SNDBUF, ls->kernel_socket_send_buffer_size) != 0) { - swSysWarn("setsockopt(SO_SNDBUF, %d) failed", ls->kernel_socket_send_buffer_size); + swoole_sys_warning("setsockopt(SO_SNDBUF, %d) failed", ls->kernel_socket_send_buffer_size); } } @@ -1705,13 +1705,13 @@ void Server::set_ipc_max_size() { int Server::create_pipe_buffers() { pipe_buffers = (PipeBuffer **) sw_calloc(reactor_num, sizeof(PipeBuffer *)); if (pipe_buffers == nullptr) { - swSysError("malloc[buffers] failed"); + swoole_sys_error("malloc[buffers] failed"); return SW_ERR; } for (uint32_t i = 0; i < reactor_num; i++) { pipe_buffers[i] = (PipeBuffer *) sw_malloc(ipc_max_size); if (pipe_buffers[i] == nullptr) { - swSysError("malloc[sndbuf][%d] failed", i); + swoole_sys_error("malloc[sndbuf][%d] failed", i); return SW_ERR; } sw_memset_zero(pipe_buffers[i], sizeof(DataHead)); diff --git a/src/server/port.cc b/src/server/port.cc index 6ef73e3dd98..d4b4cca9944 100644 --- a/src/server/port.cc +++ b/src/server/port.cc @@ -125,7 +125,7 @@ bool ListenPort::ssl_create(Connection *conn, Socket *sock) { } conn->ssl = 1; if (SSL_set_ex_data(sock->ssl, swSSL_get_ex_port_index(), this) == 0) { - swWarn("SSL_set_ex_data() failed"); + swoole_warning("SSL_set_ex_data() failed"); return false; } return true; @@ -133,7 +133,7 @@ bool ListenPort::ssl_create(Connection *conn, Socket *sock) { bool ListenPort::ssl_create_context(SSLContext *context) { if (context->cert_file.empty() || context->key_file.empty()) { - swWarn("SSL error, require ssl_cert_file and ssl_key_file"); + swoole_warning("SSL error, require ssl_cert_file and ssl_key_file"); return false; } if (open_http_protocol) { @@ -143,7 +143,7 @@ bool ListenPort::ssl_create_context(SSLContext *context) { context->http_v2 = 1; } if (!context->create()) { - swWarn("swSSL_get_context() error"); + swoole_warning("swSSL_get_context() error"); return false; } return true; @@ -153,7 +153,7 @@ bool ListenPort::ssl_create_context(SSLContext *context) { int ListenPort::listen() { // listen stream socket if (!listening && socket->listen(backlog) < 0) { - swSysWarn("listen(%s:%d, %d) failed", host.c_str(), port, backlog); + swoole_sys_warning("listen(%s:%d, %d) failed", host.c_str(), port, backlog); return SW_ERR; } listening = true; @@ -161,7 +161,7 @@ int ListenPort::listen() { #ifdef TCP_DEFER_ACCEPT if (tcp_defer_accept) { if (socket->set_option(IPPROTO_TCP, TCP_DEFER_ACCEPT, tcp_defer_accept) != 0) { - swSysWarn("setsockopt(TCP_DEFER_ACCEPT) failed"); + swoole_sys_warning("setsockopt(TCP_DEFER_ACCEPT) failed"); } } #endif @@ -172,7 +172,7 @@ int ListenPort::listen() { memset(&a, 0, sizeof(a)); strcpy(a.af_name, "httpready"); if (socket->set_option(SOL_SOCKET, SO_ACCEPTFILTER, &a, sizeof(a)) != 0) { - swSysWarn("setsockopt(SO_ACCEPTFILTER) failed"); + swoole_sys_warning("setsockopt(SO_ACCEPTFILTER) failed"); } } #endif @@ -180,7 +180,7 @@ int ListenPort::listen() { #ifdef TCP_FASTOPEN if (tcp_fastopen) { if (socket->set_option(IPPROTO_TCP, TCP_FASTOPEN, tcp_fastopen) != 0) { - swSysWarn("setsockopt(TCP_FASTOPEN) failed"); + swoole_sys_warning("setsockopt(TCP_FASTOPEN) failed"); } } #endif @@ -188,22 +188,22 @@ int ListenPort::listen() { #ifdef SO_KEEPALIVE if (open_tcp_keepalive == 1) { if (socket->set_option(SOL_SOCKET, SO_KEEPALIVE, 1) != 0) { - swSysWarn("setsockopt(SO_KEEPALIVE) failed"); + swoole_sys_warning("setsockopt(SO_KEEPALIVE) failed"); } #ifdef TCP_KEEPIDLE if (socket->set_option(IPPROTO_TCP, TCP_KEEPIDLE, tcp_keepidle) < 0) { - swSysWarn("setsockopt(TCP_KEEPIDLE) failed"); + swoole_sys_warning("setsockopt(TCP_KEEPIDLE) failed"); } if (socket->set_option(IPPROTO_TCP, TCP_KEEPINTVL, tcp_keepinterval) < 0) { - swSysWarn("setsockopt(TCP_KEEPINTVL) failed"); + swoole_sys_warning("setsockopt(TCP_KEEPINTVL) failed"); } if (socket->set_option(IPPROTO_TCP, TCP_KEEPCNT, tcp_keepcount) < 0) { - swSysWarn("setsockopt(TCP_KEEPCNT) failed"); + swoole_sys_warning("setsockopt(TCP_KEEPCNT) failed"); } #endif #ifdef TCP_USER_TIMEOUT if (tcp_user_timeout > 0 && socket->set_option(IPPROTO_TCP, TCP_USER_TIMEOUT, tcp_user_timeout) != 0) { - swSysWarn("setsockopt(TCP_USER_TIMEOUT) failed"); + swoole_sys_warning("setsockopt(TCP_USER_TIMEOUT) failed"); } #endif } @@ -274,11 +274,11 @@ bool ListenPort::import(int sock) { // get socket type if (socket->get_option(SOL_SOCKET, SO_TYPE, &_type) < 0) { - swSysWarn("getsockopt(%d, SOL_SOCKET, SO_TYPE) failed", sock); + swoole_sys_warning("getsockopt(%d, SOL_SOCKET, SO_TYPE) failed", sock); return false; } if (socket->get_name(&socket->info) < 0) { - swSysWarn("getsockname(%d) failed", sock); + swoole_sys_warning("getsockname(%d) failed", sock); return false; } @@ -321,7 +321,7 @@ static int Port_onRead_raw(Reactor *reactor, ListenPort *port, Event *event) { if (n < 0) { switch (_socket->catch_error(errno)) { case SW_ERROR: - swSysWarn("recv from connection#%d failed", event->fd); + swoole_sys_warning("recv from connection#%d failed", event->fd); return SW_OK; case SW_CLOSE: conn->close_errno = errno; @@ -352,7 +352,7 @@ static int Port_onRead_check_length(Reactor *reactor, ListenPort *port, Event *e } if (protocol->recv_with_length_protocol(_socket, buffer) < 0) { - swTrace("Close Event.FD=%d|From=%d", event->fd, event->reactor_id); + swoole_trace("Close Event.FD=%d|From=%d", event->fd, event->reactor_id); conn->close_errno = errno; reactor->trigger_close_event(event); } @@ -420,7 +420,7 @@ static int Port_onRead_http(Reactor *reactor, ListenPort *port, Event *event) { if (n < 0) { switch (_socket->catch_error(errno)) { case SW_ERROR: - swSysWarn("recv from connection#%d failed", event->fd); + swoole_sys_warning("recv from connection#%d failed", event->fd); return SW_OK; case SW_CLOSE: conn->close_errno = errno; @@ -517,7 +517,7 @@ static int Port_onRead_http(Reactor *reactor, ListenPort *port, Event *event) { // parse http header and got http body length if (!request->header_parsed) { request->parse_header_info(); - swTraceLog(SW_TRACE_SERVER, + swoole_trace_log(SW_TRACE_SERVER, "content-length=%u, keep-alive=%u, chunked=%u", request->content_length_, request->keep_alive, @@ -589,7 +589,7 @@ static int Port_onRead_http(Reactor *reactor, ListenPort *port, Event *event) { } else { request_length = request->header_length_ + request->content_length_; } - swTraceLog(SW_TRACE_SERVER, "received chunked eof, real content-length=%u", request->content_length_); + swoole_trace_log(SW_TRACE_SERVER, "received chunked eof, real content-length=%u", request->content_length_); } else { request_length = request->header_length_ + request->content_length_; if (request_length > protocol->package_max_length) { @@ -614,7 +614,7 @@ static int Port_onRead_http(Reactor *reactor, ListenPort *port, Event *event) { if (request->has_expect_header()) { _socket->send(SW_STRL(SW_HTTP_100_CONTINUE_PACKET), 0); } else { - swTraceLog(SW_TRACE_SERVER, + swoole_trace_log(SW_TRACE_SERVER, "PostWait: request->content_length=%d, buffer->length=%zu, request->header_length=%d\n", request->content_length, buffer_->length, diff --git a/src/server/process.cc b/src/server/process.cc index bc3353fb79e..626ce939555 100644 --- a/src/server/process.cc +++ b/src/server/process.cc @@ -36,11 +36,11 @@ bool ProcessFactory::shutdown() { int status; if (swoole_kill(server_->gs->manager_pid, SIGTERM) < 0) { - swSysWarn("swKill(%d) failed", server_->gs->manager_pid); + swoole_sys_warning("swKill(%d) failed", server_->gs->manager_pid); } if (swoole_waitpid(server_->gs->manager_pid, &status, 0) < 0) { - swSysWarn("waitpid(%d) failed", server_->gs->manager_pid); + swoole_sys_warning("waitpid(%d) failed", server_->gs->manager_pid); } SW_LOOP_N(server_->worker_num) { @@ -112,7 +112,7 @@ bool ProcessFactory::start() { send_buffer = (PipeBuffer *) sw_malloc(server_->ipc_max_size); if (send_buffer == nullptr) { - swSysError("malloc[send_buffer] failed"); + swoole_sys_error("malloc[send_buffer] failed"); return false; } sw_memset_zero(send_buffer, sizeof(DataHead)); @@ -121,7 +121,7 @@ bool ProcessFactory::start() { * The manager process must be started first, otherwise it will have a thread fork */ if (server_->start_manager_process() < 0) { - swWarn("FactoryProcess_manager_start failed"); + swoole_warning("FactoryProcess_manager_start failed"); return false; } return true; @@ -162,7 +162,7 @@ bool ProcessFactory::dispatch(SendData *task) { // TODO: close connection return false; default: - swWarn("invalid target worker id[%d]", target_worker_id); + swoole_warning("invalid target worker id[%d]", target_worker_id); return false; } } @@ -170,7 +170,7 @@ bool ProcessFactory::dispatch(SendData *task) { if (Server::is_stream_event(task->info.type)) { Connection *conn = server_->get_connection(fd); if (conn == nullptr || conn->active == 0) { - swWarn("dispatch[type=%d] failed, connection#%d is not active", task->info.type, fd); + swoole_warning("dispatch[type=%d] failed, connection#%d is not active", task->info.type, fd); return false; } // server active close, discard data. @@ -259,7 +259,7 @@ static bool process_send_packet(Server *serv, SendData *resp, SendFunc _send, vo iov[1].iov_base = (void *) (data + offset); iov[1].iov_len = copy_n; - swTrace("finish, type=%d|len=%u", resp->info.type, copy_n); + swoole_trace("finish, type=%d|len=%u", resp->info.type, copy_n); if (_send(serv, &resp->info, iov, 2, private_data) < 0) { #ifdef __linux__ @@ -360,7 +360,7 @@ bool ProcessFactory::finish(SendData *resp) { task.info.reactor_id = conn->reactor_id; task.info.server_fd = SwooleG.process_id; - swTrace("worker_id=%d, type=%d", SwooleG.process_id, task.info.type); + swoole_trace("worker_id=%d, type=%d", SwooleG.process_id, task.info.type); return process_send_packet(server_, &task, process_sendto_reactor, conn); } @@ -387,7 +387,7 @@ bool ProcessFactory::end(SessionId session_id, int flags) { conn->close_actively = 1; } - swTraceLog(SW_TRACE_CLOSE, "session_id=%ld, fd=%d", session_id, conn->fd); + swoole_trace_log(SW_TRACE_CLOSE, "session_id=%ld, fd=%d", session_id, conn->fd); Worker *worker; DataHead ev = {}; diff --git a/src/server/reactor_process.cc b/src/server/reactor_process.cc index bae53abe1fd..be84f10dbb7 100644 --- a/src/server/reactor_process.cc +++ b/src/server/reactor_process.cc @@ -38,7 +38,7 @@ int Server::create_reactor_processes() { reactor_num = worker_num; connection_list = (Connection *) sw_calloc(max_connection, sizeof(Connection)); if (connection_list == nullptr) { - swSysWarn("calloc[2](%d) failed", (int) (max_connection * sizeof(Connection))); + swoole_sys_warning("calloc[2](%d) failed", (int) (max_connection * sizeof(Connection))); return SW_ERR; } return SW_OK; @@ -60,7 +60,7 @@ int Server::start_reactor_processes() { #ifdef HAVE_REUSEPORT if (enable_reuse_port) { if (::close(ls->socket->fd) < 0) { - swSysWarn("close(%d) failed", ls->socket->fd); + swoole_sys_warning("close(%d) failed", ls->socket->fd); } delete ls->socket; ls->socket = nullptr; @@ -127,7 +127,7 @@ int Server::start_reactor_processes() { if (user_worker_list) { user_workers = (Worker *) sw_shm_calloc(user_worker_num, sizeof(Worker)); if (user_workers == nullptr) { - swSysWarn("gmalloc[server->user_workers] failed"); + swoole_sys_warning("gmalloc[server->user_workers] failed"); return SW_ERR; } for (auto worker : *user_worker_list) { @@ -157,7 +157,7 @@ int Server::start_reactor_processes() { init_signal_handler(); if (onStart) { - swWarn("The onStart event with SWOOLE_BASE is deprecated"); + swoole_warning("The onStart event with SWOOLE_BASE is deprecated"); onStart(this); } @@ -192,7 +192,7 @@ static int ReactorProcess_onPipeRead(Reactor *reactor, Event *event) { if (retval <= 0) { return SW_ERR; } else if ((size_t) retval != task.info.len + sizeof(_send.info)) { - swWarn("bad pipeline data"); + swoole_warning("bad pipeline data"); return SW_OK; } @@ -211,7 +211,7 @@ static int ReactorProcess_onPipeRead(Reactor *reactor, Event *event) { case SW_SERVER_EVENT_PROXY_START: case SW_SERVER_EVENT_PROXY_END: if (task.info.reactor_id < 0 || task.info.reactor_id >= (int16_t) serv->get_all_worker_num()) { - swWarn("invalid worker_id=%d", task.info.reactor_id); + swoole_warning("invalid worker_id=%d", task.info.reactor_id); return SW_OK; } output_buffer = SwooleWG.output_buffer[task.info.reactor_id]; @@ -237,14 +237,14 @@ static int ReactorProcess_onPipeRead(Reactor *reactor, Event *event) { static int ReactorProcess_alloc_output_buffer(size_t n_buffer) { SwooleWG.output_buffer = (String **) sw_malloc(sizeof(String *) * n_buffer); if (SwooleWG.output_buffer == nullptr) { - swError("malloc for SwooleWG.output_buffer failed"); + swoole_error("malloc for SwooleWG.output_buffer failed"); return SW_ERR; } SW_LOOP_N(n_buffer) { SwooleWG.output_buffer[i] = new String(SW_BUFFER_SIZE_BIG); if (SwooleWG.output_buffer[i] == nullptr) { - swError("output_buffer init failed"); + swoole_error("output_buffer init failed"); return SW_ERR; } } diff --git a/src/server/reactor_thread.cc b/src/server/reactor_thread.cc index 062d0dc2e48..62ee9c7c1de 100644 --- a/src/server/reactor_thread.cc +++ b/src/server/reactor_thread.cc @@ -141,7 +141,7 @@ static int ReactorThread_onPacketReceived(Reactor *reactor, Event *event) { if (errno == EAGAIN) { return SW_OK; } else { - swSysWarn("recvfrom(%d) failed", fd); + swoole_sys_warning("recvfrom(%d) failed", fd); return SW_ERR; } } @@ -218,7 +218,7 @@ int Server::close_connection(Reactor *reactor, Socket *socket) { sw_atomic_fetch_add(&serv->gs->close_count, 1); sw_atomic_fetch_sub(&serv->gs->connection_num, 1); - swTrace("Close Event.fd=%d|from=%d", socket->fd, reactor->id); + swoole_trace("Close Event.fd=%d|from=%d", socket->fd, reactor->id); #ifdef SW_USE_OPENSSL if (socket->ssl) { @@ -256,7 +256,7 @@ int Server::close_connection(Reactor *reactor, Socket *socket) { linger.l_onoff = 1; linger.l_linger = 0; if (conn->socket->set_option(SOL_SOCKET, SO_LINGER, &linger, sizeof(struct linger)) != 0) { - swSysWarn("setsockopt(SO_LINGER) failed"); + swoole_sys_warning("setsockopt(SO_LINGER) failed"); } } #endif @@ -271,7 +271,7 @@ int Server::close_connection(Reactor *reactor, Socket *socket) { serv->lock(); if (fd == serv->get_maxfd()) { int find_max_fd = fd - 1; - swTrace("set_maxfd=%d|close_fd=%d\n", find_max_fd, fd); + swoole_trace("set_maxfd=%d|close_fd=%d\n", find_max_fd, fd); // find the new max_fd for (; !serv->is_valid_connection(serv->get_connection(find_max_fd)) && find_max_fd > serv->get_minfd(); find_max_fd--) { @@ -301,7 +301,7 @@ static int ReactorThread_onClose(Reactor *reactor, Event *event) { notify_ev.fd = fd; notify_ev.type = SW_SERVER_EVENT_CLOSE; - swTraceLog(SW_TRACE_CLOSE, "client[fd=%d] close the connection", fd); + swoole_trace_log(SW_TRACE_CLOSE, "client[fd=%d] close the connection", fd); Connection *conn = serv->get_connection(fd); if (conn == nullptr || conn->active == 0) { @@ -447,7 +447,7 @@ static int ReactorThread_onPipeRead(Reactor *reactor, Event *ev) { } else if (errno == EAGAIN) { return SW_OK; } else { - swSysWarn("read(worker_pipe) failed"); + swoole_sys_warning("read(worker_pipe) failed"); return SW_ERR; } } @@ -513,7 +513,7 @@ static int ReactorThread_onPipeWrite(Reactor *reactor, Event *ev) { if (Buffer::empty(buffer)) { if (reactor->remove_write_event(ev->socket) < 0) { - swSysWarn("reactor->set(%d) failed", ev->fd); + swoole_sys_warning("reactor->set(%d) failed", ev->fd); } } @@ -625,7 +625,7 @@ static int ReactorThread_onWrite(Reactor *reactor, Event *ev) { return SW_ERR; } - swTraceLog(SW_TRACE_REACTOR, + swoole_trace_log(SW_TRACE_REACTOR, "fd=%d, conn->close_notify=%d, serv->disable_notify=%d, conn->close_force=%d", fd, conn->close_notify, @@ -702,7 +702,7 @@ int Server::create_reactor_threads() { */ connection_list = (Connection *) sw_shm_calloc(max_connection, sizeof(Connection)); if (connection_list == nullptr) { - swError("calloc[1] failed"); + swoole_error("calloc[1] failed"); return SW_ERR; } reactor_pipe_num = worker_num / reactor_num; @@ -866,7 +866,7 @@ static int ReactorThread_init(Server *serv, Reactor *reactor, uint16_t reactor_i int max_pipe_fd = serv->get_worker(serv->worker_num - 1)->pipe_master->fd + 2; thread->pipe_sockets = (Socket *) sw_calloc(max_pipe_fd, sizeof(Socket)); if (!thread->pipe_sockets) { - swSysError("calloc(%d, %ld) failed", max_pipe_fd, sizeof(Socket)); + swoole_sys_error("calloc(%d, %ld) failed", max_pipe_fd, sizeof(Socket)); return SW_ERR; } @@ -929,7 +929,7 @@ static void ReactorThread_loop(Server *serv, int reactor_id) { } if (0 != pthread_setaffinity_np(pthread_self(), sizeof(cpu_set), &cpu_set)) { - swSysWarn("pthread_setaffinity_np() failed"); + swoole_sys_warning("pthread_setaffinity_np() failed"); } } #endif @@ -990,7 +990,7 @@ int Server::dispatch_task(Protocol *proto, Socket *_socket, const char *data, ui task.info.type = SW_SERVER_EVENT_RECV_DATA; task.info.time = conn->last_recv_time; - swTrace("send string package, size=%ld bytes", (long) length); + swoole_trace("send string package, size=%ld bytes", (long) length); if (serv->stream_socket_file) { Stream *stream = Stream::create(serv->stream_socket_file, 0, SW_SOCK_UNIX_STREAM); @@ -1025,7 +1025,7 @@ int Server::dispatch_task(Protocol *proto, Socket *_socket, const char *data, ui } if (length > 0) { sw_atomic_fetch_add(&conn->recv_queued_bytes, length); - swTraceLog(SW_TRACE_SERVER, "[Master] len=%d, qb=%d\n", length, conn->recv_queued_bytes); + swoole_trace_log(SW_TRACE_SERVER, "[Master] len=%d, qb=%d\n", length, conn->recv_queued_bytes); } return SW_OK; } @@ -1040,9 +1040,9 @@ void Server::join_reactor_thread() { * Shutdown heartbeat thread */ if (heartbeat_thread.joinable()) { - swTraceLog(SW_TRACE_SERVER, "terminate heartbeat thread"); + swoole_trace_log(SW_TRACE_SERVER, "terminate heartbeat thread"); if (pthread_cancel(heartbeat_thread.native_handle()) < 0) { - swSysWarn("pthread_cancel(%ld) failed", (ulong_t) heartbeat_thread.native_handle()); + swoole_sys_warning("pthread_cancel(%ld) failed", (ulong_t) heartbeat_thread.native_handle()); } // wait thread heartbeat_thread.join(); @@ -1061,7 +1061,7 @@ void Server::join_reactor_thread() { } else { _cancel: if (pthread_cancel(thread->thread.native_handle()) < 0) { - swSysWarn("pthread_cancel(%ld) failed", (long) thread->thread.native_handle()); + swoole_sys_warning("pthread_cancel(%ld) failed", (long) thread->thread.native_handle()); } } thread->thread.join(); diff --git a/src/server/task_worker.cc b/src/server/task_worker.cc index 6575ed6a0b2..05fee76b4b1 100644 --- a/src/server/task_worker.cc +++ b/src/server/task_worker.cc @@ -40,7 +40,7 @@ void Server::init_task_workers() { */ if (task_enable_coroutine) { if (task_ipc_mode == TASK_IPC_MSGQUEUE || task_ipc_mode == TASK_IPC_PREEMPTIVE) { - swError("cannot use msgqueue when task_enable_coroutine is enable"); + swoole_error("cannot use msgqueue when task_enable_coroutine is enable"); return; } pool->main_loop = TaskWorker_loop_async; @@ -78,7 +78,7 @@ bool EventData::pack(const void *_data, size_t _length) { } if (file.write_all(_data, _length) != _length) { - swWarn("write to tmpfile failed"); + swoole_warning("write to tmpfile failed"); return false; } @@ -97,7 +97,7 @@ bool EventData::unpack(String *buffer) { File fp(_pkg.tmpfile, O_RDONLY); if (!fp.ready()) { - swSysWarn("open(%s) failed", _pkg.tmpfile); + swoole_sys_warning("open(%s) failed", _pkg.tmpfile); return false; } if (buffer->size < _pkg.length && !buffer->extend(_pkg.length)) { @@ -138,7 +138,7 @@ static void TaskWorker_onStart(ProcessPool *pool, int worker_id) { */ if (serv->task_enable_coroutine) { if (swoole_event_init(0) < 0) { - swError("[TaskWorker] create reactor failed"); + swoole_error("[TaskWorker] create reactor failed"); return; } SwooleG.enable_signalfd = 1; @@ -192,7 +192,7 @@ static int TaskWorker_onPipeReceive(Reactor *reactor, Event *event) { } return retval; } else { - swSysWarn("read(%d, %ld) failed", event->fd, sizeof(task)); + swoole_sys_warning("read(%d, %ld) failed", event->fd, sizeof(task)); return SW_ERR; } } @@ -226,18 +226,18 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even EventData buf; sw_memset_zero(&buf.info, sizeof(buf.info)); if (task_worker_num < 1) { - swWarn("cannot use Server::task()/Server::finish() method, because no set [task_worker_num]"); + swoole_warning("cannot use Server::task()/Server::finish() method, because no set [task_worker_num]"); return SW_ERR; } if (current_task == nullptr) { current_task = last_task; } if (current_task->info.type == SW_SERVER_EVENT_PIPE_MESSAGE) { - swWarn("Server::task()/Server::finish() is not supported in onPipeMessage callback"); + swoole_warning("Server::task()/Server::finish() is not supported in onPipeMessage callback"); return SW_ERR; } if (swTask_type(current_task) & SW_TASK_NOREPLY) { - swWarn("Server::finish() can only be used in the worker process"); + swoole_warning("Server::finish() can only be used in the worker process"); return SW_ERR; } @@ -245,7 +245,7 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even Worker *worker = get_worker(source_worker_id); if (worker == nullptr) { - swWarn("invalid worker_id[%d]", source_worker_id); + swoole_warning("invalid worker_id[%d]", source_worker_id); return SW_ERR; } @@ -266,7 +266,7 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even // write to file if (!buf.pack(data, data_len)) { - swWarn("large task pack failed()"); + swoole_warning("large task pack failed()"); return SW_ERR; } @@ -300,12 +300,12 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even buf.info.fd = current_task->info.fd; swTask_type(&buf) = flags; if (!buf.pack(data, data_len)) { - swWarn("large task pack failed()"); + swoole_warning("large task pack failed()"); buf.info.len = 0; } size_t bytes = sizeof(buf.info) + buf.info.len; if (file.write_all(&buf, bytes) != bytes) { - swSysWarn("write(%s, %ld) failed", _tmpfile, bytes); + swoole_sys_warning("write(%s, %ld) failed", _tmpfile, bytes); } sw_atomic_fetch_add(finish_count, 1); } @@ -316,7 +316,7 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even if (!result->pack(data, data_len)) { // unlock worker worker->lock->unlock(); - swWarn("large task pack failed()"); + swoole_warning("large task pack failed()"); return SW_ERR; } } @@ -337,9 +337,9 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even } if (ret < 0) { if (swoole_get_last_error() == EAGAIN || swoole_get_last_error() == SW_ERROR_SOCKET_POLL_TIMEOUT) { - swWarn("send result to worker timed out"); + swoole_warning("send result to worker timed out"); } else { - swSysWarn("send result to worker failed"); + swoole_sys_warning("send result to worker failed"); } } return ret; diff --git a/src/server/worker.cc b/src/server/worker.cc index 7cefb98edbf..39e74bed173 100644 --- a/src/server/worker.cc +++ b/src/server/worker.cc @@ -73,7 +73,7 @@ void Server::worker_signal_handler(int signo) { break; // for test case SIGVTALRM: - swWarn("SIGVTALRM coming"); + swoole_warning("SIGVTALRM coming"); break; case SIGUSR1: case SIGUSR2: @@ -122,7 +122,7 @@ static int Worker_onStreamAccept(Reactor *reactor, Event *event) { case EAGAIN: return SW_OK; default: - swSysWarn("accept() failed"); + swoole_sys_warning("accept() failed"); return SW_OK; } } @@ -228,7 +228,7 @@ int Server::accept_task(EventData *task) { if (conn) { if (task->info.len > 0) { sw_atomic_fetch_sub(&conn->recv_queued_bytes, task->info.len); - swTraceLog(SW_TRACE_SERVER, "[Worker] len=%d, qb=%d\n", task->info.len, conn->recv_queued_bytes); + swoole_trace_log(SW_TRACE_SERVER, "[Worker] len=%d, qb=%d\n", task->info.len, conn->recv_queued_bytes); } conn->last_dispatch_time = task->info.time; } @@ -292,7 +292,7 @@ int Server::accept_task(EventData *task) { break; } default: - swWarn("[Worker] error event[type=%d]", (int) task->info.type); + swoole_warning("[Worker] error event[type=%d]", (int) task->info.type); break; } @@ -322,32 +322,32 @@ void Server::worker_start_callback() { if (!group_.empty()) { _group = getgrnam(group_.c_str()); if (!_group) { - swWarn("get group [%s] info failed", group_.c_str()); + swoole_warning("get group [%s] info failed", group_.c_str()); } } // get user info if (!user_.empty()) { _passwd = getpwnam(user_.c_str()); if (!_passwd) { - swWarn("get user [%s] info failed", user_.c_str()); + swoole_warning("get user [%s] info failed", user_.c_str()); } } // set process group if (_group && setgid(_group->gr_gid) < 0) { - swSysWarn("setgid to [%s] failed", group_.c_str()); + swoole_sys_warning("setgid to [%s] failed", group_.c_str()); } // set process user if (_passwd && setuid(_passwd->pw_uid) < 0) { - swSysWarn("setuid to [%s] failed", user_.c_str()); + swoole_sys_warning("setuid to [%s] failed", user_.c_str()); } // chroot if (!chroot_.empty()) { if (::chroot(chroot_.c_str()) == 0) { if (chdir("/") < 0) { - swSysWarn("chdir(\"/\") failed"); + swoole_sys_warning("chdir(\"/\") failed"); } } else { - swSysWarn("chroot(\"%s\") failed", chroot_.c_str()); + swoole_sys_warning("chroot(\"%s\") failed", chroot_.c_str()); } } } @@ -660,7 +660,7 @@ static int Worker_onPipeReceive(Reactor *reactor, Event *event) { recv_n = readv(event->fd, buffers, 2); if (recv_n == 0) { - swWarn("receive pipeline data error, pipe_fd=%d, reactor_id=%d", event->fd, info->reactor_id); + swoole_warning("receive pipeline data error, pipe_fd=%d, reactor_id=%d", event->fd, info->reactor_id); return SW_ERR; } if (recv_n < 0 && event->socket->catch_error(errno) == SW_WAIT) { @@ -668,7 +668,7 @@ static int Worker_onPipeReceive(Reactor *reactor, Event *event) { } if (recv_n > 0) { worker_buffer->length += (recv_n - sizeof(pipe_buffer->info)); - swTrace("append msgid=%ld, buffer=%p, n=%ld", pipe_buffer->info.msg_id, worker_buffer, recv_n); + swoole_trace("append msgid=%ld, buffer=%p, n=%ld", pipe_buffer->info.msg_id, worker_buffer, recv_n); } recv_chunk_count++; @@ -682,7 +682,7 @@ static int Worker_onPipeReceive(Reactor *reactor, Event *event) { * the maximum number of consecutive chunks received by the worker is limited. */ if (recv_chunk_count >= SW_WORKER_MAX_RECV_CHUNK_COUNT) { - swTraceLog(SW_TRACE_WORKER, + swoole_trace_log(SW_TRACE_WORKER, "worker process[%u] receives the chunk data to the maximum[%d], return to event loop", SwooleG.process_id, recv_chunk_count); @@ -697,7 +697,7 @@ static int Worker_onPipeReceive(Reactor *reactor, Event *event) { */ pipe_buffer->info.flags |= SW_EVENT_DATA_OBJ_PTR; memcpy(pipe_buffer->data, &worker_buffer, sizeof(worker_buffer)); - swTrace("msg_id=%ld, len=%u", pipe_buffer->info.msg_id, pipe_buffer->info.len); + swoole_trace("msg_id=%ld, len=%u", pipe_buffer->info.msg_id, pipe_buffer->info.len); } } else { recv_n = event->socket->read(pipe_buffer, serv->ipc_max_size); diff --git a/src/wrapper/timer.cc b/src/wrapper/timer.cc index 9226b1d5fda..dad46c3e354 100644 --- a/src/wrapper/timer.cc +++ b/src/wrapper/timer.cc @@ -43,7 +43,7 @@ TimerNode *swoole_timer_add(long ms, bool persistent, const TimerCallback &callb bool swoole_timer_del(TimerNode *tnode) { if (!swoole_timer_is_available()) { - swWarn("timer is not available"); + swoole_warning("timer is not available"); return false; } return SwooleTG.timer->remove(tnode); @@ -51,7 +51,7 @@ bool swoole_timer_del(TimerNode *tnode) { void swoole_timer_delay(TimerNode *tnode, long delay_ms) { if (!swoole_timer_is_available()) { - swWarn("timer is not available"); + swoole_warning("timer is not available"); return; } return SwooleTG.timer->delay(tnode, delay_ms); @@ -59,7 +59,7 @@ void swoole_timer_delay(TimerNode *tnode, long delay_ms) { long swoole_timer_after(long ms, const TimerCallback &callback, void *private_data) { if (ms <= 0) { - swWarn("Timer must be greater than 0"); + swoole_warning("Timer must be greater than 0"); return SW_ERR; } TimerNode *tnode = swoole_timer_add(ms, false, callback, private_data); @@ -72,7 +72,7 @@ long swoole_timer_after(long ms, const TimerCallback &callback, void *private_da long swoole_timer_tick(long ms, const TimerCallback &callback, void *private_data) { if (ms <= 0) { - swWarn("Timer must be greater than 0"); + swoole_warning("Timer must be greater than 0"); return SW_ERR; } TimerNode *tnode = swoole_timer_add(ms, true, callback, private_data); @@ -85,7 +85,7 @@ long swoole_timer_tick(long ms, const TimerCallback &callback, void *private_dat bool swoole_timer_exists(long timer_id) { if (!swoole_timer_is_available()) { - swWarn("timer is not available"); + swoole_warning("timer is not available"); return false; } TimerNode *tnode = SwooleTG.timer->get(timer_id); @@ -94,7 +94,7 @@ bool swoole_timer_exists(long timer_id) { bool swoole_timer_clear(long timer_id) { if (!swoole_timer_is_available()) { - swWarn("timer is not available"); + swoole_warning("timer is not available"); return false; } return SwooleTG.timer->remove(SwooleTG.timer->get(timer_id)); @@ -102,7 +102,7 @@ bool swoole_timer_clear(long timer_id) { TimerNode *swoole_timer_get(long timer_id) { if (!swoole_timer_is_available()) { - swWarn("timer is not available"); + swoole_warning("timer is not available"); return nullptr; } return SwooleTG.timer->get(timer_id); @@ -110,7 +110,7 @@ TimerNode *swoole_timer_get(long timer_id) { void swoole_timer_free() { if (!swoole_timer_is_available()) { - swWarn("timer is not available"); + swoole_warning("timer is not available"); return; } delete SwooleTG.timer; @@ -120,7 +120,7 @@ void swoole_timer_free() { int swoole_timer_select() { if (!swoole_timer_is_available()) { - swWarn("timer is not available"); + swoole_warning("timer is not available"); return SW_ERR; } return SwooleTG.timer->select(); diff --git a/thirdparty/php/curl/interface.cc b/thirdparty/php/curl/interface.cc index 8db261760e3..6b7998b46d0 100644 --- a/thirdparty/php/curl/interface.cc +++ b/thirdparty/php/curl/interface.cc @@ -119,7 +119,7 @@ php_curl *swoole_curl_get_handle(zval *zid, bool exclusive, bool required) { #else if ((ch = (php_curl *) zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) { if (required) { - swFatalError(SW_ERROR_INVALID_PARAMS, "supplied resource is not a valid " le_curl_name " resource"); + swoole_fatal_error(SW_ERROR_INVALID_PARAMS, "supplied resource is not a valid " le_curl_name " resource"); } return nullptr; } diff --git a/thirdparty/php/curl/multi.cc b/thirdparty/php/curl/multi.cc index cbca9c515b7..df587f1082c 100644 --- a/thirdparty/php/curl/multi.cc +++ b/thirdparty/php/curl/multi.cc @@ -48,7 +48,7 @@ static inline php_curlm *Z_CURL_MULTI_P(zval *zv) { php_curlm *cm; if ((cm = (php_curlm *) zend_fetch_resource( Z_RES_P(zv), le_curl_multi_handle_name, swoole_curl_get_le_curl_multi())) == NULL) { - swFatalError(SW_ERROR_INVALID_PARAMS, + swoole_fatal_error(SW_ERROR_INVALID_PARAMS, "supplied resource is not a valid " le_curl_multi_handle_name " resource"); return nullptr; } From eda672034534248e86ff034712e8b18f1a7f4034 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Wed, 4 Aug 2021 14:08:37 +0800 Subject: [PATCH 200/936] Optimize naming of enum, use CamelCase style --- core-tests/include/test_server.h | 2 +- core-tests/src/_lib/server.cpp | 4 ++-- core-tests/src/network/socket.cpp | 2 +- core-tests/src/server/server.cpp | 4 ++-- ext-src/php_swoole_cxx.h | 4 ++-- ext-src/php_swoole_private.h | 4 ++-- ext-src/swoole_client_coro.cc | 2 +- ext-src/swoole_coroutine_system.cc | 4 ++-- ext-src/swoole_curl.cc | 2 +- ext-src/swoole_http2_client_coro.cc | 6 ++--- ext-src/swoole_http_client_coro.cc | 2 +- ext-src/swoole_http_server_coro.cc | 2 +- ext-src/swoole_server.cc | 10 ++++----- ext-src/swoole_socket_coro.cc | 4 ++-- include/swoole.h | 24 ++++++++++---------- include/swoole_api.h | 2 +- include/swoole_async.h | 2 +- include/swoole_client.h | 14 ++++++------ include/swoole_coroutine_channel.h | 8 +++---- include/swoole_coroutine_socket.h | 34 ++++++++++++++--------------- include/swoole_mqtt.h | 4 ++-- include/swoole_proxy.h | 26 +++++++++++----------- include/swoole_reactor.h | 12 +++++----- include/swoole_server.h | 10 ++++----- include/swoole_socket.h | 26 +++++++++++----------- src/coroutine/channel.cc | 2 +- src/coroutine/hook.cc | 2 +- src/coroutine/socket.cc | 18 +++++++-------- src/coroutine/system.cc | 4 ++-- src/network/address.cc | 2 +- src/network/client.cc | 2 +- src/network/socket.cc | 8 +++---- src/network/stream.cc | 2 +- src/protocol/mqtt.cc | 2 +- src/server/master.cc | 4 ++-- src/server/reactor_thread.cc | 6 ++--- 36 files changed, 133 insertions(+), 133 deletions(-) diff --git a/core-tests/include/test_server.h b/core-tests/include/test_server.h index 771513639db..bd1234f250a 100644 --- a/core-tests/include/test_server.h +++ b/core-tests/include/test_server.h @@ -43,7 +43,7 @@ class Server ~Server(); void on(std::string event, void *fn); bool start(); - bool listen(std::string host, int port, enum swSocket_type type); + bool listen(std::string host, int port, enum swSocketType type); int send(int session_id, const void *data, uint32_t length); ssize_t sendto(const swoole::network::Address &address, const char *__buf, size_t __n, int server_socket = -1); int close(int session_id, int reset); diff --git a/core-tests/src/_lib/server.cpp b/core-tests/src/_lib/server.cpp index 4c7aa55e690..e38d2ea8c83 100644 --- a/core-tests/src/_lib/server.cpp +++ b/core-tests/src/_lib/server.cpp @@ -36,7 +36,7 @@ Server::Server(std::string _host, int _port, swoole::Server::Mode _mode, int _ty serv.dispatch_mode = 2; serv.private_data_2 = this; - if (!listen(host, port, (swSocket_type) type)) { + if (!listen(host, port, (swSocketType) type)) { swoole_warning("listen(%s:%d) fail[error=%d].", host.c_str(), port, errno); exit(0); } @@ -75,7 +75,7 @@ bool Server::start() { return serv.start() == 0; } -bool Server::listen(std::string host, int port, enum swSocket_type type) { +bool Server::listen(std::string host, int port, enum swSocketType type) { ListenPort *ls = serv.add_port(type, (char *) host.c_str(), port); if (ls == nullptr) { return false; diff --git a/core-tests/src/network/socket.cpp b/core-tests/src/network/socket.cpp index 6f7b16e0bec..d3888dafb56 100644 --- a/core-tests/src/network/socket.cpp +++ b/core-tests/src/network/socket.cpp @@ -53,7 +53,7 @@ TEST(socket, sendto) { unlink(sock2_path); } -static void test_sendto(enum swSocket_type sock_type) { +static void test_sendto(enum swSocketType sock_type) { int port1 = 0, port2 = 0; const char *ip = sock_type == SW_SOCK_UDP ? "127.0.0.1" : "::1"; diff --git a/core-tests/src/server/server.cpp b/core-tests/src/server/server.cpp index e1b9f897496..80234fe1543 100644 --- a/core-tests/src/server/server.cpp +++ b/core-tests/src/server/server.cpp @@ -185,7 +185,7 @@ TEST(server, ssl) { Mutex *lock = new Mutex(Mutex::PROCESS_SHARED); lock->lock(); - ListenPort *port = serv.add_port((enum swSocket_type )(SW_SOCK_TCP | SW_SOCK_SSL), TEST_HOST, 0); + ListenPort *port = serv.add_port((enum swSocketType )(SW_SOCK_TCP | SW_SOCK_SSL), TEST_HOST, 0); if (!port) { swoole_warning("listen failed, [error=%d]", swoole_get_last_error()); exit(2); @@ -248,7 +248,7 @@ TEST(server, dtls) { Mutex *lock = new Mutex(Mutex::PROCESS_SHARED); lock->lock(); - ListenPort *port = serv.add_port((enum swSocket_type )(SW_SOCK_UDP | SW_SOCK_SSL), TEST_HOST, 0); + ListenPort *port = serv.add_port((enum swSocketType )(SW_SOCK_UDP | SW_SOCK_SSL), TEST_HOST, 0); if (!port) { swoole_warning("listen failed, [error=%d]", swoole_get_last_error()); exit(2); diff --git a/ext-src/php_swoole_cxx.h b/ext-src/php_swoole_cxx.h index 37a20b188a3..2e668620d19 100644 --- a/ext-src/php_swoole_cxx.h +++ b/ext-src/php_swoole_cxx.h @@ -81,9 +81,9 @@ extern zend_string **sw_zend_known_strings; SW_API bool php_swoole_is_enable_coroutine(); -SW_API zend_object *php_swoole_create_socket_from_fd(int fd, enum swSocket_type type); +SW_API zend_object *php_swoole_create_socket_from_fd(int fd, enum swSocketType type); SW_API bool php_swoole_export_socket(zval *zobject, swoole::coroutine::Socket *_socket); -SW_API zend_object *php_swoole_dup_socket(int fd, enum swSocket_type type); +SW_API zend_object *php_swoole_dup_socket(int fd, enum swSocketType type); SW_API void php_swoole_init_socket_object(zval *zobject, swoole::coroutine::Socket *socket); SW_API swoole::coroutine::Socket *php_swoole_get_socket(zval *zobject); #ifdef SW_USE_OPENSSL diff --git a/ext-src/php_swoole_private.h b/ext-src/php_swoole_private.h index b16ec0fb219..ea0d4b40051 100644 --- a/ext-src/php_swoole_private.h +++ b/ext-src/php_swoole_private.h @@ -151,8 +151,8 @@ enum php_swoole_req_status { }; //--------------------------------------------------------- -static sw_inline enum swSocket_type php_swoole_socktype(long type) { - return (enum swSocket_type)(type & (~SW_FLAG_SYNC) & (~SW_FLAG_ASYNC) & (~SW_FLAG_KEEP) & (~SW_SOCK_SSL)); +static sw_inline enum swSocketType php_swoole_socktype(long type) { + return (enum swSocketType)(type & (~SW_FLAG_SYNC) & (~SW_FLAG_ASYNC) & (~SW_FLAG_KEEP) & (~SW_SOCK_SSL)); } extern zend_class_entry *swoole_event_ce; diff --git a/ext-src/swoole_client_coro.cc b/ext-src/swoole_client_coro.cc index 312cda9f17b..86049b89f6d 100644 --- a/ext-src/swoole_client_coro.cc +++ b/ext-src/swoole_client_coro.cc @@ -209,7 +209,7 @@ static sw_inline Socket *client_get_ptr(zval *zobject, bool silent = false) { static Socket *client_coro_new(zval *zobject, int port) { zval *ztype = sw_zend_read_property_ex(Z_OBJCE_P(zobject), zobject, SW_ZSTR_KNOWN(SW_ZEND_STR_TYPE), 0); zend_long type = zval_get_long(ztype); - enum swSocket_type sock_type = php_swoole_socktype(type); + enum swSocketType sock_type = php_swoole_socktype(type); if ((sock_type == SW_SOCK_TCP || sock_type == SW_SOCK_TCP6) && (port <= 0 || port > SW_CLIENT_MAX_PORT)) { php_swoole_fatal_error(E_WARNING, "The port is invalid"); diff --git a/ext-src/swoole_coroutine_system.cc b/ext-src/swoole_coroutine_system.cc index 7371b2c5ce5..2a0663c4303 100644 --- a/ext-src/swoole_coroutine_system.cc +++ b/ext-src/swoole_coroutine_system.cc @@ -140,7 +140,7 @@ static void co_socket_read(int fd, zend_long length, INTERNAL_FUNCTION_PARAMETER TmpSocket *sock = (TmpSocket *) ecalloc(1, sizeof(TmpSocket)); sock->socket.fd = fd; - sock->socket.fd_type = (enum swFd_type) PHP_SWOOLE_FD_CO_UTIL; + sock->socket.fd_type = (enum swFdType) PHP_SWOOLE_FD_CO_UTIL; sock->socket.object = sock; if (swoole_event_add(&sock->socket, SW_EVENT_READ) < 0) { @@ -172,7 +172,7 @@ static void co_socket_write(int fd, char *str, size_t l_str, INTERNAL_FUNCTION_P sock = (TmpSocket *) ecalloc(1, sizeof(TmpSocket)); sock->socket.fd = fd; - sock->socket.fd_type = (enum swFd_type) PHP_SWOOLE_FD_CO_UTIL; + sock->socket.fd_type = (enum swFdType) PHP_SWOOLE_FD_CO_UTIL; sock->socket.object = sock; if (swoole_event_add(&sock->socket, SW_EVENT_WRITE) < 0) { diff --git a/ext-src/swoole_curl.cc b/ext-src/swoole_curl.cc index a888ba52975..589290ec434 100644 --- a/ext-src/swoole_curl.cc +++ b/ext-src/swoole_curl.cc @@ -70,7 +70,7 @@ Socket *Multi::create_socket(CURL *cp, curl_socket_t sockfd) { Socket *socket = new Socket(); socket->fd = sockfd; socket->removed = 1; - socket->fd_type = (enum swFd_type) PHP_SWOOLE_FD_CO_CURL; + socket->fd_type = (enum swFdType) PHP_SWOOLE_FD_CO_CURL; curl_multi_assign(multi_handle_, sockfd, (void *) socket); Handle *handle = get_handle(cp); diff --git a/ext-src/swoole_http2_client_coro.cc b/ext-src/swoole_http2_client_coro.cc index 5b0cb43ff1e..980e75dba62 100644 --- a/ext-src/swoole_http2_client_coro.cc +++ b/ext-src/swoole_http2_client_coro.cc @@ -172,7 +172,7 @@ class Client { uint32_t send_request(zval *zrequest); bool write_data(uint32_t stream_id, zval *zdata, bool end); bool send_goaway_frame(zend_long error_code, const char *debug_data, size_t debug_data_len); - enum swReturn_code parse_frame(zval *return_value, bool pipeline_read = false); + enum swReturnCode parse_frame(zval *return_value, bool pipeline_read = false); bool close(); ~Client() { @@ -494,7 +494,7 @@ bool Client::close() { return true; } -enum swReturn_code Client::parse_frame(zval *return_value, bool pipeline_read) { +enum swReturnCode Client::parse_frame(zval *return_value, bool pipeline_read) { char *buf = client->get_read_buffer()->str; uint8_t type = buf[3]; uint8_t flags = buf[4]; @@ -1350,7 +1350,7 @@ static void php_swoole_http2_client_coro_recv(INTERNAL_FUNCTION_PARAMETERS, bool if (!h2c->recv_packet(timeout)) { RETURN_FALSE; } - enum swReturn_code ret = h2c->parse_frame(return_value, pipeline_read); + enum swReturnCode ret = h2c->parse_frame(return_value, pipeline_read); if (ret == SW_CONTINUE) { continue; } else if (ret == SW_READY) { diff --git a/ext-src/swoole_http_client_coro.cc b/ext-src/swoole_http_client_coro.cc index 832650386a8..9948883b9b0 100644 --- a/ext-src/swoole_http_client_coro.cc +++ b/ext-src/swoole_http_client_coro.cc @@ -246,7 +246,7 @@ class HttpClient { private: Socket *socket = nullptr; - swSocket_type socket_type = SW_SOCK_TCP; + swSocketType socket_type = SW_SOCK_TCP; swoole_http_parser parser = {}; bool wait = false; }; diff --git a/ext-src/swoole_http_server_coro.cc b/ext-src/swoole_http_server_coro.cc index 2c5ba26ed22..170d3df3059 100644 --- a/ext-src/swoole_http_server_coro.cc +++ b/ext-src/swoole_http_server_coro.cc @@ -70,7 +70,7 @@ class http_server { uint32_t compression_min_length; #endif - http_server(enum swSocket_type type) { + http_server(enum swSocketType type) { socket = new Socket(type); default_handler = nullptr; array_init(&zcallbacks); diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index da3d0c859b3..57190f23294 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -77,7 +77,7 @@ static void php_swoole_server_onManagerStart(Server *serv); static void php_swoole_server_onManagerStop(Server *serv); static void php_swoole_server_onSendTimeout(Timer *timer, TimerNode *tnode); -static enum swReturn_code php_swoole_server_send_resume(Server *serv, FutureTask *context, SessionId fd); +static enum swReturnCode php_swoole_server_send_resume(Server *serv, FutureTask *context, SessionId fd); static void php_swoole_task_onTimeout(Timer *timer, TimerNode *tnode); static int php_swoole_server_dispatch_func(Server *serv, Connection *conn, SendData *data); static zval *php_swoole_server_add_port(ServerObject *server_object, ListenPort *port); @@ -1965,7 +1965,7 @@ static void php_swoole_server_onSendTimeout(Timer *timer, TimerNode *tnode) { efree(context); } -static enum swReturn_code php_swoole_server_send_resume(Server *serv, FutureTask *context, SessionId fd) { +static enum swReturnCode php_swoole_server_send_resume(Server *serv, FutureTask *context, SessionId fd) { char *data; zval *zdata = &context->coro_params; zval result; @@ -2154,7 +2154,7 @@ static PHP_METHOD(swoole_server, __construct) { RETURN_FALSE; } } else { - ListenPort *port = serv->add_port((enum swSocket_type) sock_type, host, serv_port); + ListenPort *port = serv->add_port((enum swSocketType) sock_type, host, serv_port); if (!port) { zend_throw_exception_ex(swoole_exception_ce, errno, @@ -2668,7 +2668,7 @@ static PHP_METHOD(swoole_server, listen) { RETURN_FALSE; } - ListenPort *ls = serv->add_port((enum swSocket_type) sock_type, host, (int) port); + ListenPort *ls = serv->add_port((enum swSocketType) sock_type, host, (int) port); if (!ls) { RETURN_FALSE; } @@ -2828,7 +2828,7 @@ static PHP_METHOD(swoole_server, sendto) { char *data; size_t len; zend_long server_socket_fd = -1; - enum swSocket_type type; + enum swSocketType type; ZEND_PARSE_PARAMETERS_START(3, 4) Z_PARAM_STRING(addr, addr_len) diff --git a/ext-src/swoole_socket_coro.cc b/ext-src/swoole_socket_coro.cc index e3799f45665..cdf037ed4da 100644 --- a/ext-src/swoole_socket_coro.cc +++ b/ext-src/swoole_socket_coro.cc @@ -863,7 +863,7 @@ SW_API bool php_swoole_export_socket(zval *zobject, Socket *_socket) { return true; } -SW_API zend_object *php_swoole_dup_socket(int fd, enum swSocket_type type) { +SW_API zend_object *php_swoole_dup_socket(int fd, enum swSocketType type) { php_swoole_check_reactor(); int new_fd = dup(fd); if (new_fd < 0) { @@ -873,7 +873,7 @@ SW_API zend_object *php_swoole_dup_socket(int fd, enum swSocket_type type) { return php_swoole_create_socket_from_fd(new_fd, type); } -SW_API zend_object *php_swoole_create_socket_from_fd(int fd, enum swSocket_type type) { +SW_API zend_object *php_swoole_create_socket_from_fd(int fd, enum swSocketType type) { zval zobject; zend_object *object = php_swoole_socket_coro_create_object(swoole_socket_coro_ce); SocketObject *sock = (SocketObject *) php_swoole_socket_coro_fetch_object(object); diff --git a/include/swoole.h b/include/swoole.h index ec06f4bc166..cd6298f9a42 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -340,12 +340,12 @@ static inline void swoole_strtolower(char *str, int length) { } /*--------------------------------Constants------------------------------------*/ -enum swResult_code { +enum swResultCode { SW_OK = 0, SW_ERR = -1, }; -enum swReturn_code { +enum swReturnCode { SW_CONTINUE = 1, SW_WAIT = 2, SW_CLOSE = 3, @@ -354,7 +354,7 @@ enum swReturn_code { SW_INVALID = 6, }; -enum swFd_type { +enum swFdType { SW_FD_SESSION, // server stream session SW_FD_STREAM_SERVER, // server stream port SW_FD_DGRAM_SERVER, // server dgram port @@ -387,13 +387,13 @@ enum swFd_type { SW_FD_DGRAM_CLIENT, }; -enum swSocket_flag { +enum swSocketFlag { SW_SOCK_NONBLOCK = 1 << 2, SW_SOCK_CLOEXEC = 1 << 3, SW_SOCK_SSL = (1u << 9), }; -enum swSocket_type { +enum swSocketType { SW_SOCK_TCP = 1, SW_SOCK_UDP = 2, SW_SOCK_TCP6 = 3, @@ -403,7 +403,7 @@ enum swSocket_type { SW_SOCK_RAW = 7, }; -enum swEvent_type { +enum swEventType { SW_EVENT_NULL = 0, SW_EVENT_DEAULT = 1u << 8, SW_EVENT_READ = 1u << 9, @@ -413,7 +413,7 @@ enum swEvent_type { SW_EVENT_ONCE = 1u << 12, }; -enum swFork_type { +enum swForkType { SW_FORK_SPAWN = 0, SW_FORK_EXEC = 1 << 1, SW_FORK_DAEMON = 1 << 2, @@ -449,7 +449,7 @@ static sw_inline size_t swoole_size_align(size_t size, int pagesize) { } //------------------------------Base-------------------------------- -enum swEventData_flag { +enum swEventDataFlag { SW_EVENT_DATA_NORMAL, SW_EVENT_DATA_PTR = 1u << 1, SW_EVENT_DATA_CHUNK = 1u << 2, @@ -464,7 +464,7 @@ enum swEventData_flag { /** * use swDataHead->server_fd, 1 byte 8 bit */ -enum swTask_type { +enum swTaskType { SW_TASK_TMPFILE = 1, // tmp file SW_TASK_SERIALIZE = 2, // php serialize SW_TASK_NONBLOCK = 4, // task @@ -475,7 +475,7 @@ enum swTask_type { SW_TASK_NOREPLY = 128, // don't reply }; -enum swDNSLookup_cache_type { +enum swDNSLookupFlag { SW_DNS_LOOKUP_RANDOM = (1u << 11), }; @@ -486,7 +486,7 @@ char *sw_error_(); extern __thread char sw_error[SW_ERROR_MSG_SIZE]; #endif -enum swProcess_type { +enum swProcessType { SW_PROCESS_MASTER = 1, SW_PROCESS_WORKER = 2, SW_PROCESS_MANAGER = 3, @@ -566,7 +566,7 @@ namespace swoole { struct Event { int fd; int16_t reactor_id; - enum swFd_type type; + enum swFdType type; network::Socket *socket; }; diff --git a/include/swoole_api.h b/include/swoole_api.h index 151c9c23590..2e354c52963 100644 --- a/include/swoole_api.h +++ b/include/swoole_api.h @@ -21,7 +21,7 @@ #include "swoole.h" #include "swoole_coroutine_c_api.h" -enum swEvent_init_flags { +enum swEventInitFlag { SW_EVENTLOOP_WAIT_EXIT = 1, }; diff --git a/include/swoole_async.h b/include/swoole_async.h index f1ef612ac6b..19049368724 100644 --- a/include/swoole_async.h +++ b/include/swoole_async.h @@ -29,7 +29,7 @@ namespace swoole { -enum AsyncFlags { +enum AsyncFlag { SW_AIO_WRITE_FSYNC = 1u << 1, SW_AIO_EOF = 1u << 2, }; diff --git a/include/swoole_client.h b/include/swoole_client.h index 195b8a2bee6..4a66fc7203e 100644 --- a/include/swoole_client.h +++ b/include/swoole_client.h @@ -35,7 +35,7 @@ class Client { int _sock_type = 0; int _sock_domain = 0; int _protocol = 0; - enum swFd_type fd_type; + enum swFdType fd_type; bool active = false; bool async = false; bool keep = false; @@ -118,7 +118,7 @@ class Client { ssize_t (*recv)(Client *cli, char *data, size_t length, int flags) = nullptr; static void init_reactor(Reactor *reactor); - Client(enum swSocket_type type, bool async); + Client(enum swSocketType type, bool async); ~Client(); void set_http_proxy(const std::string &host, int port) { @@ -164,7 +164,7 @@ class Stream { int send(const char *data, size_t length); void set_max_length(uint32_t max_length); - inline static Stream *create(const char *dst_host, int dst_port, enum swSocket_type type) { + inline static Stream *create(const char *dst_host, int dst_port, enum swSocketType type) { Stream *stream = new Stream(dst_host, dst_port, type); if (!stream->connected) { delete stream; @@ -178,7 +178,7 @@ class Stream { static void set_protocol(Protocol *protocol); private: - Stream(const char *dst_host, int dst_port, enum swSocket_type type); + Stream(const char *dst_host, int dst_port, enum swSocketType type); }; //----------------------------------------Stream End------------------------------------ @@ -188,10 +188,10 @@ class SyncClient { bool connected = false; bool created; bool async = false; - enum swSocket_type type; + enum swSocketType type; public: - SyncClient(enum swSocket_type _type, bool _async = false) : client(_type, _async), async(_async), type(_type) { + SyncClient(enum swSocketType _type, bool _async = false) : client(_type, _async), async(_async), type(_type) { created = client.socket != nullptr; } @@ -252,7 +252,7 @@ class AsyncClient : public SyncClient { std::function _onReceive = nullptr; public: - AsyncClient(enum swSocket_type _type) : SyncClient(_type, true) {} + AsyncClient(enum swSocketType _type) : SyncClient(_type, true) {} bool connect(const char *host, int port, double timeout = -1) { client.object = this; diff --git a/include/swoole_coroutine_channel.h b/include/swoole_coroutine_channel.h index 0a4face8fc9..6ba1315acf4 100644 --- a/include/swoole_coroutine_channel.h +++ b/include/swoole_coroutine_channel.h @@ -32,7 +32,7 @@ namespace coroutine { //------------------------------------------------------------------------------- class Channel { public: - enum opcode { + enum Opcode { PRODUCER = 1, CONSUMER = 2, }; @@ -46,7 +46,7 @@ class Channel { struct TimeoutMessage { Channel *chan; - enum opcode type; + Opcode type; Coroutine *co; bool error; TimerNode *timer; @@ -120,7 +120,7 @@ class Channel { static void timer_callback(Timer *timer, TimerNode *tnode); - void yield(enum opcode type); + void yield(enum Opcode type); inline void consumer_remove(Coroutine *co) { consumer_queue.remove(co); @@ -130,7 +130,7 @@ class Channel { producer_queue.remove(co); } - inline Coroutine *pop_coroutine(enum opcode type) { + inline Coroutine *pop_coroutine(enum Opcode type) { Coroutine *co; if (type == PRODUCER) { co = producer_queue.front(); diff --git a/include/swoole_coroutine_socket.h b/include/swoole_coroutine_socket.h index 3440bc9e6cd..bb13bb592e1 100644 --- a/include/swoole_coroutine_socket.h +++ b/include/swoole_coroutine_socket.h @@ -62,13 +62,13 @@ class Socket { Socket(int domain, int type, int protocol); Socket(int _fd, int _domain, int _type, int _protocol); - Socket(enum swSocket_type type = SW_SOCK_TCP); - Socket(int _fd, enum swSocket_type _type); + Socket(enum swSocketType type = SW_SOCK_TCP); + Socket(int _fd, enum swSocketType _type); ~Socket(); bool connect(std::string host, int port, int flags = 0); bool connect(const struct sockaddr *addr, socklen_t addrlen); bool shutdown(int how = SHUT_RDWR); - bool cancel(const enum swEvent_type event); + bool cancel(const enum swEventType event); bool close(); inline bool is_connected() { @@ -106,7 +106,7 @@ class Socket { } } - bool poll(enum swEvent_type type); + bool poll(enum swEventType type); Socket *accept(double timeout = 0); bool bind(std::string address, int port = 0); bool bind(const struct sockaddr *sa, socklen_t len); @@ -152,11 +152,11 @@ class Socket { reactor->set_handler(SW_FD_CORO_SOCKET | SW_EVENT_ERROR, error_event_callback); } - inline enum swSocket_type get_type() { + inline enum swSocketType get_type() { return type; } - inline enum swFd_type get_fd_type() { + inline enum swFdType get_fd_type() { return socket->fd_type; } @@ -195,11 +195,11 @@ class Socket { return socket->info.get_port(); } - inline bool has_bound(const enum swEvent_type event = SW_EVENT_RDWR) { + inline bool has_bound(const enum swEventType event = SW_EVENT_RDWR) { return get_bound_co(event) != nullptr; } - inline Coroutine *get_bound_co(const enum swEvent_type event) { + inline Coroutine *get_bound_co(const enum swEventType event) { if (event & SW_EVENT_READ) { if (read_co) { return read_co; @@ -213,12 +213,12 @@ class Socket { return nullptr; } - inline long get_bound_cid(const enum swEvent_type event = SW_EVENT_RDWR) { + inline long get_bound_cid(const enum swEventType event = SW_EVENT_RDWR) { Coroutine *co = get_bound_co(event); return co ? co->get_cid() : 0; } - const char *get_event_str(const enum swEvent_type event) { + const char *get_event_str(const enum swEventType event) { if (event == SW_EVENT_READ) { return "reading"; } else if (event == SW_EVENT_WRITE) { @@ -228,7 +228,7 @@ class Socket { } } - inline void check_bound_co(const enum swEvent_type event) { + inline void check_bound_co(const enum swEventType event) { long cid = get_bound_cid(event); if (sw_unlikely(cid)) { swoole_fatal_error(SW_ERROR_CO_HAS_BEEN_BOUND, @@ -373,7 +373,7 @@ class Socket { #endif private: - enum swSocket_type type; + enum swSocketType type; network::Socket *socket = nullptr; int sock_domain = 0; int sock_type = 0; @@ -383,7 +383,7 @@ class Socket { Coroutine *read_co = nullptr; Coroutine *write_co = nullptr; #ifdef SW_USE_OPENSSL - enum swEvent_type want_event = SW_EVENT_NULL; + enum swEventType want_event = SW_EVENT_NULL; #endif std::string connect_host; @@ -431,7 +431,7 @@ class Socket { static int writable_event_callback(Reactor *reactor, Event *event); static int error_event_callback(Reactor *reactor, Event *event); - inline void init_sock_type(enum swSocket_type _type); + inline void init_sock_type(enum swSocketType _type); inline bool init_sock(); bool init_reactor_socket(int fd); @@ -454,13 +454,13 @@ class Socket { protocol.package_max_length = SW_INPUT_BUFFER_SIZE; } - bool add_event(const enum swEvent_type event); - bool wait_event(const enum swEvent_type event, const void **__buf = nullptr, size_t __n = 0); + bool add_event(const enum swEventType event); + bool wait_event(const enum swEventType event, const void **__buf = nullptr, size_t __n = 0); ssize_t recv_packet_with_length_protocol(); ssize_t recv_packet_with_eof_protocol(); - inline bool is_available(const enum swEvent_type event) { + inline bool is_available(const enum swEventType event) { if (event != SW_EVENT_NULL) { check_bound_co(event); } diff --git a/include/swoole_mqtt.h b/include/swoole_mqtt.h index 0a954d29cac..3abbf4739a6 100644 --- a/include/swoole_mqtt.h +++ b/include/swoole_mqtt.h @@ -24,7 +24,7 @@ #define SW_MQTT_MAX_LENGTH_SIZE 4 #define SW_MQTT_MAX_PAYLOAD_SIZE 268435455 -enum swMqtt_opcode { +enum swMqttOpcode { SW_MQTT_CONNECT = 0x10, SW_MQTT_CONNACK = 0x20, SW_MQTT_PUBLISH = 0x30, @@ -41,7 +41,7 @@ enum swMqtt_opcode { SW_MQTT_DISCONNECT = 0xE0, }; -struct swMqtt_packet { +struct swMqttPacket { uint8_t type : 4; uint8_t dup : 1; uint8_t qos : 2; diff --git a/include/swoole_proxy.h b/include/swoole_proxy.h index a94279762a0..5ff58a0e9f2 100644 --- a/include/swoole_proxy.h +++ b/include/swoole_proxy.h @@ -20,12 +20,24 @@ #define SW_SOCKS5_VERSION_CODE 0x05 -enum swHttp_proxy_state { +enum swHttpProxyState { SW_HTTP_PROXY_STATE_WAIT = 0, SW_HTTP_PROXY_STATE_HANDSHAKE, SW_HTTP_PROXY_STATE_READY, }; +enum swSocks5State { + SW_SOCKS5_STATE_WAIT = 0, + SW_SOCKS5_STATE_HANDSHAKE, + SW_SOCKS5_STATE_AUTH, + SW_SOCKS5_STATE_CONNECT, + SW_SOCKS5_STATE_READY, +}; + +enum swSocks5Method { + SW_SOCKS5_METHOD_AUTH = 0x02, +}; + namespace swoole { struct HttpProxy { uint8_t state; @@ -63,15 +75,3 @@ struct Socks5Proxy { } }; } // namespace swoole - -enum swSocks5_state { - SW_SOCKS5_STATE_WAIT = 0, - SW_SOCKS5_STATE_HANDSHAKE, - SW_SOCKS5_STATE_AUTH, - SW_SOCKS5_STATE_CONNECT, - SW_SOCKS5_STATE_READY, -}; - -enum swSocks5_method { - SW_SOCKS5_METHOD_AUTH = 0x02, -}; diff --git a/include/swoole_reactor.h b/include/swoole_reactor.h index 8fda4ccb935..10068c6bb54 100644 --- a/include/swoole_reactor.h +++ b/include/swoole_reactor.h @@ -205,14 +205,14 @@ class Reactor { return read_handler[fdtype] != nullptr; } - inline int add_event(network::Socket *_socket, enum swEvent_type event_type) { + inline int add_event(network::Socket *_socket, enum swEventType event_type) { if (!(_socket->events & event_type)) { return set(_socket, _socket->events | event_type); } return SW_OK; } - inline int del_event(network::Socket *_socket, enum swEvent_type event_type) { + inline int del_event(network::Socket *_socket, enum swEventType event_type) { if (_socket->events & event_type) { return set(_socket, _socket->events & (~event_type)); } @@ -263,7 +263,7 @@ class Reactor { return defer_tasks == nullptr ? timeout_msec : 0; } - inline ReactorHandler get_handler(enum swEvent_type event_type, enum swFd_type fd_type) { + inline ReactorHandler get_handler(enum swEventType event_type, enum swFdType fd_type) { switch (event_type) { case SW_EVENT_READ: return read_handler[fd_type]; @@ -278,7 +278,7 @@ class Reactor { return nullptr; } - inline ReactorHandler get_error_handler(enum swFd_type fd_type) { + inline ReactorHandler get_error_handler(enum swFdType fd_type) { ReactorHandler handler = get_handler(SW_EVENT_ERROR, fd_type); // error callback is not set, try to use readable or writable callback if (handler == nullptr) { @@ -333,8 +333,8 @@ class Reactor { void activate_future_task(); - static enum swFd_type get_fd_type(int flags) { - return (enum swFd_type)(flags & (~SW_EVENT_READ) & (~SW_EVENT_WRITE) & (~SW_EVENT_ERROR) & (~SW_EVENT_ONCE)); + static enum swFdType get_fd_type(int flags) { + return (enum swFdType)(flags & (~SW_EVENT_READ) & (~SW_EVENT_WRITE) & (~SW_EVENT_ERROR) & (~SW_EVENT_ONCE)); } static bool isset_read_event(int events) { diff --git a/include/swoole_server.h b/include/swoole_server.h index 2ee3e215080..c43208a8780 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -64,7 +64,7 @@ struct Connection { * system fd must be 0. en: signalfd, listen socket */ uint8_t active; - enum swSocket_type socket_type; + enum swSocketType socket_type; int fd; int worker_id; SessionId session_id; @@ -168,7 +168,7 @@ struct PipeBuffer { }; struct DgramPacket { - enum swSocket_type socket_type; + enum swSocketType socket_type; network::Address socket_addr; uint32_t length; char data[0]; @@ -217,7 +217,7 @@ struct ListenPort { uint32_t buffer_high_watermark = 0; uint32_t buffer_low_watermark = 0; - enum swSocket_type type = SW_SOCK_TCP; + enum swSocketType type = SW_SOCK_TCP; uint8_t ssl = 0; std::string host; int port = 0; @@ -358,7 +358,7 @@ struct ListenPort { const char *get_host() { return host.c_str(); } - enum swSocket_type get_type() { + enum swSocketType get_type() { return type; } int get_fd() { @@ -908,7 +908,7 @@ class Server { void shutdown(); int add_worker(Worker *worker); - ListenPort *add_port(enum swSocket_type type, const char *host, int port); + ListenPort *add_port(enum swSocketType type, const char *host, int port); int add_systemd_socket(); int add_hook(enum HookType type, const Callback &func, int push_back); Connection *add_connection(ListenPort *ls, network::Socket *_socket, int server_fd); diff --git a/include/swoole_socket.h b/include/swoole_socket.h index 0b0373ff568..8a76052f46d 100644 --- a/include/swoole_socket.h +++ b/include/swoole_socket.h @@ -94,9 +94,9 @@ struct Address { struct sockaddr_un un; } addr; socklen_t len; - enum swSocket_type type; + enum swSocketType type; - bool assign(enum swSocket_type _type, const std::string &_host, int _port); + bool assign(enum swSocketType _type, const std::string &_host, int _port); const char *get_ip() { return get_addr(); } @@ -156,8 +156,8 @@ struct Socket { static uint32_t default_buffer_size; int fd; - enum swFd_type fd_type; - enum swSocket_type socket_type; + enum swFdType fd_type; + enum swSocketType socket_type; int events; bool enable_tcp_nodelay; @@ -360,7 +360,7 @@ struct Socket { } int ssl_create(SSLContext *_ssl_context, int _flags); int ssl_connect(); - enum swReturn_code ssl_accept(); + enum swReturnCode ssl_accept(); ssize_t ssl_recv(void *__buf, size_t __n); ssize_t ssl_send(const void *__buf, size_t __n); ssize_t ssl_readv(IOVector *io_vector); @@ -430,11 +430,11 @@ struct Socket { int wait_event(int timeout_ms, int events); void free(); - static inline int is_dgram(swSocket_type type) { + static inline int is_dgram(swSocketType type) { return (type == SW_SOCK_UDP || type == SW_SOCK_UDP6 || type == SW_SOCK_UNIX_DGRAM); } - static inline int is_stream(swSocket_type type) { + static inline int is_stream(swSocketType type) { return (type == SW_SOCK_TCP || type == SW_SOCK_TCP6 || type == SW_SOCK_UNIX_STREAM); } @@ -524,7 +524,7 @@ struct Socket { } } - static inline enum swSocket_type convert_to_type(int domain, int type, int protocol = 0) { + static inline enum swSocketType convert_to_type(int domain, int type, int protocol = 0) { switch (domain) { case AF_INET: return type == SOCK_STREAM ? SW_SOCK_TCP : SW_SOCK_UDP; @@ -537,7 +537,7 @@ struct Socket { } } - static inline enum swSocket_type convert_to_type(std::string &host) { + static inline enum swSocketType convert_to_type(std::string &host) { if (host.compare(0, 6, "unix:/", 0, 6) == 0) { host = host.substr(sizeof("unix:") - 1); host.erase(0, host.find_first_not_of('/') - 1); @@ -549,7 +549,7 @@ struct Socket { } } - static inline int get_domain_and_type(enum swSocket_type type, int *sock_domain, int *sock_type) { + static inline int get_domain_and_type(enum swSocketType type, int *sock_domain, int *sock_type) { switch (type) { case SW_SOCK_TCP6: *sock_domain = AF_INET6; @@ -587,9 +587,9 @@ int gethostbyname(int type, const char *name, char *addr); int getaddrinfo(GetaddrinfoRequest *req); } // namespace network -network::Socket *make_socket(int fd, enum swFd_type fd_type); -network::Socket *make_socket(enum swSocket_type socket_type, enum swFd_type fd_type, int flags); -network::Socket *make_server_socket(enum swSocket_type socket_type, +network::Socket *make_socket(int fd, enum swFdType fd_type); +network::Socket *make_socket(enum swSocketType socket_type, enum swFdType fd_type, int flags); +network::Socket *make_server_socket(enum swSocketType socket_type, const char *address, int port = 0, int backlog = SW_BACKLOG); diff --git a/src/coroutine/channel.cc b/src/coroutine/channel.cc index f04e99c5d96..2526257ce81 100644 --- a/src/coroutine/channel.cc +++ b/src/coroutine/channel.cc @@ -31,7 +31,7 @@ void Channel::timer_callback(Timer *timer, TimerNode *tnode) { msg->co->resume(); } -void Channel::yield(enum opcode type) { +void Channel::yield(enum Opcode type) { Coroutine *co = Coroutine::get_current_safe(); if (type == PRODUCER) { producer_queue.push_back(co); diff --git a/src/coroutine/hook.cc b/src/coroutine/hook.cc index eb60a2261aa..2c17c8de83c 100644 --- a/src/coroutine/hook.cc +++ b/src/coroutine/hook.cc @@ -505,7 +505,7 @@ int swoole_coroutine_socket_wait_event(int sockfd, int event, double timeout) { } double ori_timeout = socket->get_timeout(event == SW_EVENT_READ ? Socket::TIMEOUT_READ : Socket::TIMEOUT_WRITE); socket->set_timeout(timeout); - bool retval = socket->poll((enum swEvent_type) event); + bool retval = socket->poll((enum swEventType) event); socket->set_timeout(ori_timeout); return retval ? SW_OK : SW_ERR; } diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index 97037a50fc9..772b326a65a 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -99,7 +99,7 @@ int Socket::error_event_callback(Reactor *reactor, Event *event) { return SW_OK; } -bool Socket::add_event(const enum swEvent_type event) { +bool Socket::add_event(const enum swEventType event) { bool ret = true; if (sw_likely(!(socket->events & event))) { if (socket->removed) { @@ -119,8 +119,8 @@ bool Socket::add_event(const enum swEvent_type event) { * We only need to set the errCode for the socket operation when wait_event returns true, * which means that the exception's error code priority is greater than the current event error priority. */ -bool Socket::wait_event(const enum swEvent_type event, const void **__buf, size_t __n) { - enum swEvent_type added_event = event; +bool Socket::wait_event(const enum swEventType event, const void **__buf, size_t __n) { + enum swEventType added_event = event; Coroutine *co = Coroutine::get_current_safe(); if (!co) { return false; @@ -451,7 +451,7 @@ bool Socket::http_proxy_handshake() { return ret; } -void Socket::init_sock_type(enum swSocket_type _sw_type) { +void Socket::init_sock_type(enum swSocketType _sw_type) { type = _sw_type; network::Socket::get_domain_and_type(_sw_type, &sock_domain, &sock_type); } @@ -487,7 +487,7 @@ Socket::Socket(int _domain, int _type, int _protocol) init_options(); } -Socket::Socket(enum swSocket_type _type) { +Socket::Socket(enum swSocketType _type) { init_sock_type(_type); if (sw_unlikely(!init_sock())) { return; @@ -495,7 +495,7 @@ Socket::Socket(enum swSocket_type _type) { init_options(); } -Socket::Socket(int _fd, enum swSocket_type _type) { +Socket::Socket(int _fd, enum swSocketType _type) { init_sock_type(_type); if (sw_unlikely(!init_reactor_socket(_fd))) { return; @@ -765,7 +765,7 @@ ssize_t Socket::peek(void *__buf, size_t __n) { return retval; } -bool Socket::poll(enum swEvent_type type) { +bool Socket::poll(enum swEventType type) { if (sw_unlikely(!is_available(type))) { return -1; } @@ -1257,7 +1257,7 @@ bool Socket::ssl_handshake() { } } } else { - enum swReturn_code retval; + enum swReturnCode retval; TimerController timer(&read_timer, read_timeout, this, timer_callback); do { @@ -1670,7 +1670,7 @@ bool Socket::ssl_shutdown() { } #endif -bool Socket::cancel(const enum swEvent_type event) { +bool Socket::cancel(const enum swEventType event) { if (!has_bound(event)) { return false; } diff --git a/src/coroutine/system.cc b/src/coroutine/system.cc index 5d13a132d60..bf40f982b91 100644 --- a/src/coroutine/system.cc +++ b/src/coroutine/system.cc @@ -359,7 +359,7 @@ static void socket_poll_completed(void *data) { task->co->resume(); } -static inline void socket_poll_trigger_event(Reactor *reactor, CoroPollTask *task, int fd, enum swEvent_type event) { +static inline void socket_poll_trigger_event(Reactor *reactor, CoroPollTask *task, int fd, enum swEventType event) { auto i = task->fds->find(fd); if (event == SW_EVENT_ERROR && !(i->second.events & SW_EVENT_ERROR)) { if (i->second.events & SW_EVENT_READ) { @@ -534,7 +534,7 @@ struct EventWaiter { } }; -static inline void event_waiter_callback(Reactor *reactor, EventWaiter *waiter, enum swEvent_type event) { +static inline void event_waiter_callback(Reactor *reactor, EventWaiter *waiter, enum swEventType event) { if (waiter->revents == 0) { reactor->defer([waiter](void *data) { waiter->co->resume(); }); } diff --git a/src/network/address.cc b/src/network/address.cc index 9a760183e80..d30340e510a 100644 --- a/src/network/address.cc +++ b/src/network/address.cc @@ -46,7 +46,7 @@ int Address::get_port() { } } -bool Address::assign(enum swSocket_type _type, const std::string &_host, int _port) { +bool Address::assign(enum swSocketType _type, const std::string &_host, int _port) { type = _type; const char *host = _host.c_str(); if (_type == SW_SOCK_TCP || _type == SW_SOCK_UDP) { diff --git a/src/network/client.cc b/src/network/client.cc index 8322872f9c1..5f97d34395a 100644 --- a/src/network/client.cc +++ b/src/network/client.cc @@ -68,7 +68,7 @@ void Client::init_reactor(Reactor *reactor) { reactor->set_handler(SW_FD_STREAM_CLIENT | SW_EVENT_ERROR, Client_onError); } -Client::Client(enum swSocket_type _type, bool _async) : async(_async) { +Client::Client(enum swSocketType _type, bool _async) : async(_async) { fd_type = Socket::is_stream(_type) ? SW_FD_STREAM_CLIENT : SW_FD_DGRAM_CLIENT; socket = swoole::make_socket(_type, fd_type, (async ? SW_SOCK_NONBLOCK : 0) | SW_SOCK_CLOEXEC); if (socket == nullptr) { diff --git a/src/network/socket.cc b/src/network/socket.cc index c00a38d3281..2bbeb4a8b08 100644 --- a/src/network/socket.cc +++ b/src/network/socket.cc @@ -1051,7 +1051,7 @@ const char *Socket::ssl_get_error_reason(int *reason) { return ERR_reason_error_string(error); } -enum swReturn_code Socket::ssl_accept() { +enum swReturnCode Socket::ssl_accept() { ssl_clear_error(); int n = SSL_accept(ssl); @@ -1430,7 +1430,7 @@ int Socket::ssl_create(SSLContext *ssl_context, int _flags) { using network::Socket; -Socket *make_socket(enum swSocket_type type, enum swFd_type fd_type, int flags) { +Socket *make_socket(enum swSocketType type, enum swFdType fd_type, int flags) { int sock_domain; int sock_type; @@ -1474,7 +1474,7 @@ Socket *make_socket(enum swSocket_type type, enum swFd_type fd_type, int flags) return _socket; } -Socket *make_server_socket(enum swSocket_type type, const char *address, int port, int backlog) { +Socket *make_server_socket(enum swSocketType type, const char *address, int port, int backlog) { Socket *sock = swoole::make_socket(type, SW_FD_STREAM_SERVER, SW_SOCK_CLOEXEC); if (sock == nullptr) { swoole_sys_warning("socket() failed"); @@ -1492,7 +1492,7 @@ Socket *make_server_socket(enum swSocket_type type, const char *address, int por return sock; } -Socket *make_socket(int fd, enum swFd_type fd_type) { +Socket *make_socket(int fd, enum swFdType fd_type) { Socket *socket = new Socket(); socket->fd = fd; socket->fd_type = fd_type; diff --git a/src/network/stream.cc b/src/network/stream.cc index e62002d12c0..e8f62ab300b 100644 --- a/src/network/stream.cc +++ b/src/network/stream.cc @@ -74,7 +74,7 @@ static void Stream_onClose(Client *cli) { cli); } -Stream::Stream(const char *dst_host, int dst_port, enum swSocket_type type) : client(type, true) { +Stream::Stream(const char *dst_host, int dst_port, enum swSocketType type) : client(type, true) { if (client.socket == nullptr) { return; } diff --git a/src/protocol/mqtt.cc b/src/protocol/mqtt.cc index 52ee1aaf07d..a89f0cdb0d0 100644 --- a/src/protocol/mqtt.cc +++ b/src/protocol/mqtt.cc @@ -23,7 +23,7 @@ using swoole::Protocol; using swoole::network::Socket; -void swMqtt_print_package(swMqtt_packet *pkg) { +void swMqtt_print_package(swMqttPacket *pkg) { printf("type=%d, length=%d\n", pkg->type, pkg->length); } diff --git a/src/server/master.cc b/src/server/master.cc index 5cb0f020dba..e3ea4ae01ec 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -1434,7 +1434,7 @@ int Server::add_systemd_socket() { return count; } -ListenPort *Server::add_port(enum swSocket_type type, const char *host, int port) { +ListenPort *Server::add_port(enum swSocketType type, const char *host, int port) { if (session_list) { swoole_error_log(SW_LOG_ERROR, SW_ERROR_WRONG_OPERATION, "must add port before server is created"); return nullptr; @@ -1468,7 +1468,7 @@ ListenPort *Server::add_port(enum swSocket_type type, const char *host, int port #ifdef SW_USE_OPENSSL if (type & SW_SOCK_SSL) { - type = (enum swSocket_type)(type & (~SW_SOCK_SSL)); + type = (enum swSocketType)(type & (~SW_SOCK_SSL)); ls->type = type; ls->ssl = 1; ls->ssl_context = new SSLContext(); diff --git a/src/server/reactor_thread.cc b/src/server/reactor_thread.cc index 62ee9c7c1de..feb92205c7a 100644 --- a/src/server/reactor_thread.cc +++ b/src/server/reactor_thread.cc @@ -40,13 +40,13 @@ static void ReactorThread_shutdown(Reactor *reactor); static void ReactorThread_resume_data_receiving(Timer *timer, TimerNode *tnode); #ifdef SW_USE_OPENSSL -static inline enum swReturn_code ReactorThread_verify_ssl_state(Reactor *reactor, ListenPort *port, Socket *_socket) { +static inline enum swReturnCode ReactorThread_verify_ssl_state(Reactor *reactor, ListenPort *port, Socket *_socket) { Server *serv = (Server *) reactor->ptr; if (!_socket->ssl || _socket->ssl_state == SW_SSL_STATE_READY) { return SW_CONTINUE; } - enum swReturn_code code = _socket->ssl_accept(); + enum swReturnCode code = _socket->ssl_accept(); if (code != SW_READY) { return code; } @@ -573,7 +573,7 @@ static int ReactorThread_onRead(Reactor *reactor, Event *event) { } } #endif - enum swReturn_code code = ReactorThread_verify_ssl_state(reactor, port, event->socket); + enum swReturnCode code = ReactorThread_verify_ssl_state(reactor, port, event->socket); switch (code) { case SW_ERROR: return Server::close_connection(reactor, event->socket); From 49e992e5f62b10e42b4973f320dc2b38ad619a94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Thu, 5 Aug 2021 12:39:48 +0800 Subject: [PATCH 201/936] Optimize naming (#4352) * Optimize naming * fix * Optimize naming --- core-tests/src/server/http.cpp | 4 +- core-tests/src/server/server.cpp | 4 +- ext-src/php_swoole_http.h | 48 ++++++++--------- ext-src/swoole_client.cc | 6 +-- ext-src/swoole_curl.cc | 2 +- ext-src/swoole_http2_server.cc | 4 +- ext-src/swoole_http_client_coro.cc | 10 ++-- ext-src/swoole_http_response.cc | 3 +- ext-src/swoole_http_server_coro.cc | 14 ++--- ext-src/swoole_mysql_coro.cc | 6 +-- ext-src/swoole_server.cc | 32 ++++++------ ext-src/swoole_socket_coro.cc | 2 +- include/swoole.h | 22 ++++---- include/swoole_client.h | 14 ++--- include/swoole_coroutine_socket.h | 34 ++++++------- include/swoole_http.h | 31 +++++------ include/swoole_mqtt.h | 21 +++++--- include/swoole_reactor.h | 12 ++--- include/swoole_server.h | 10 ++-- include/swoole_socket.h | 24 ++++----- include/swoole_ssl.h | 23 +++++---- include/swoole_string.h | 2 +- src/coroutine/socket.cc | 16 +++--- src/coroutine/system.cc | 4 +- src/network/address.cc | 2 +- src/network/client.cc | 2 +- src/network/socket.cc | 8 +-- src/network/stream.cc | 2 +- src/protocol/dtls.cc | 2 +- src/protocol/http.cc | 82 +++++++++++++++--------------- src/protocol/mqtt.cc | 21 +++++--- src/protocol/ssl.cc | 66 ++++++++++++------------ src/server/master.cc | 6 +-- src/server/port.cc | 12 ++--- src/server/static_handler.cc | 2 +- src/server/task_worker.cc | 20 ++++---- 36 files changed, 297 insertions(+), 276 deletions(-) diff --git a/core-tests/src/server/http.cpp b/core-tests/src/server/http.cpp index f5bd757127d..4122f4a54a6 100644 --- a/core-tests/src/server/http.cpp +++ b/core-tests/src/server/http.cpp @@ -41,7 +41,7 @@ struct http_context { response_headers[key] = value; } - void response(enum swHttp_status_code code, string body) { + void response(enum swHttpStatusCode code, string body) { response_headers["Content-Length"] = to_string(body.length()); response(code); server->send(fd, body.c_str(), body.length()); @@ -49,7 +49,7 @@ struct http_context { void response(int code) { swString *buf = swoole::make_string(1024); - buf->length = sw_snprintf(buf->str, buf->size, "HTTP/1.1 %s\r\n", swHttp_get_status_message(code)); + buf->length = sw_snprintf(buf->str, buf->size, "HTTP/1.1 %s\r\n", http_server::get_status_message(code)); for (auto &kv : response_headers) { buf->append(kv.first.c_str(), kv.first.length()); buf->append(SW_STRL(": ")); diff --git a/core-tests/src/server/server.cpp b/core-tests/src/server/server.cpp index 80234fe1543..a167c222ad1 100644 --- a/core-tests/src/server/server.cpp +++ b/core-tests/src/server/server.cpp @@ -206,7 +206,7 @@ TEST(server, ssl) { ListenPort *port = serv->get_primary_port(); EXPECT_EQ(port->ssl, 1); - EXPECT_EQ(swSSL_is_thread_safety(), true); + EXPECT_EQ(swoole_ssl_is_thread_safety(), true); swoole::network::SyncClient c(SW_SOCK_TCP); c.connect(TEST_HOST, port->port); @@ -330,7 +330,7 @@ TEST(server, task_worker) { swEventData buf; memset(&buf.info, 0, sizeof(buf.info)); - swTask_type(&buf) |= SW_TASK_NOREPLY; + SW_TASK_TYPE(&buf) |= SW_TASK_NOREPLY; buf.info.len = strlen(packet); memcpy(buf.data, packet, strlen(packet)); diff --git a/ext-src/php_swoole_http.h b/ext-src/php_swoole_http.h index d0969f20b6c..8111419b7e1 100644 --- a/ext-src/php_swoole_http.h +++ b/ext-src/php_swoole_http.h @@ -37,13 +37,13 @@ #endif enum http_header_flag { - HTTP_HEADER_SERVER = 1u << 1, - HTTP_HEADER_CONNECTION = 1u << 2, - HTTP_HEADER_CONTENT_LENGTH = 1u << 3, - HTTP_HEADER_DATE = 1u << 4, - HTTP_HEADER_CONTENT_TYPE = 1u << 5, + HTTP_HEADER_SERVER = 1u << 1, + HTTP_HEADER_CONNECTION = 1u << 2, + HTTP_HEADER_CONTENT_LENGTH = 1u << 3, + HTTP_HEADER_DATE = 1u << 4, + HTTP_HEADER_CONTENT_TYPE = 1u << 5, HTTP_HEADER_TRANSFER_ENCODING = 1u << 6, - HTTP_HEADER_ACCEPT_ENCODING = 1u << 7, + HTTP_HEADER_ACCEPT_ENCODING = 1u << 7, }; enum http_compress_method { @@ -75,9 +75,9 @@ struct Request { zval zdata; size_t body_length; - swString *chunked_body; + String *chunked_body; #ifdef SW_USE_HTTP2 - swString *h2_data_buffer; + String *h2_data_buffer; #endif // Notice: Do not change the order @@ -236,11 +236,11 @@ class Session { uint32_t max_concurrent_streams; uint32_t max_frame_size; uint32_t last_stream_id; - bool shutting_down; - bool is_coro; + bool shutting_down; + bool is_coro; http::Context *default_ctx = nullptr; - void *private_data = nullptr; + void *private_data = nullptr; void (*handle)(Session *, Stream *) = nullptr; @@ -272,7 +272,7 @@ static sw_inline zval *swoole_http_init_and_read_property( // Notice: swoole http server properties can not be unset anymore, so we can read it without checking zval rv, *property = zend_read_property(ce, SW_Z8_OBJ_P(zobject), name, name_len, 0, &rv); array_init(property); - *zproperty_store_pp = (zval *) (zproperty_store_pp + 1); + *zproperty_store_pp = (zval *) (zproperty_store_pp + 1); **zproperty_store_pp = *property; } return *zproperty_store_pp; @@ -356,21 +356,21 @@ class HeaderSet { const uint8_t flags = NGHTTP2_NV_FLAG_NONE) { if (sw_likely(index < size || nvs[index].name == nullptr)) { nghttp2_nv *nv = &nvs[index]; - name = zend_str_tolower_dup(name, name_len); // auto to lower - nv->name = (uchar *) name; - nv->namelen = name_len; - nv->value = (uchar *) emalloc(value_len); + name = zend_str_tolower_dup(name, name_len); // auto to lower + nv->name = (uchar *) name; + nv->namelen = name_len; + nv->value = (uchar *) emalloc(value_len); memcpy(nv->value, value, value_len); nv->valuelen = value_len; - nv->flags = flags | NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE; + nv->flags = flags | NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE; swoole_trace_log(SW_TRACE_HTTP2, - "name=(%zu)[%.*s], value=(%zu)[%.*s]", - name_len, - (int) name_len, - name, - value_len, - (int) value_len, - value); + "name=(%zu)[%.*s], value=(%zu)[%.*s]", + name_len, + (int) name_len, + name, + value_len, + (int) value_len, + value); } else { php_swoole_fatal_error( E_WARNING, "unexpect http2 header [%.*s] (duplicated or overflow)", (int) name_len, name); diff --git a/ext-src/swoole_client.cc b/ext-src/swoole_client.cc index 8f457dfc275..5ca6650f5f3 100644 --- a/ext-src/swoole_client.cc +++ b/ext-src/swoole_client.cc @@ -366,7 +366,7 @@ bool php_swoole_client_check_setting(Client *cli, zval *zset) { if (php_swoole_array_get_value(vht, "open_mqtt_protocol", ztmp)) { cli->open_length_check = zval_is_true(ztmp); if (zval_is_true(ztmp)) { - swMqtt_set_protocol(&cli->protocol); + swoole::mqtt::set_protocol(&cli->protocol); } } // open length check @@ -1007,7 +1007,7 @@ static PHP_METHOD(swoole_client, recv) { cli->buffer = swoole::make_string(SW_BUFFER_SIZE_BIG, sw_zend_string_allocator()); } - swString *buffer = cli->buffer; + String *buffer = cli->buffer; ssize_t eof = -1; char *buf = nullptr; @@ -1088,7 +1088,7 @@ static PHP_METHOD(swoole_client, recv) { } else { cli->buffer->clear(); } - swString *buffer = cli->buffer; + String *buffer = cli->buffer; uint32_t header_len = protocol->package_length_offset + protocol->package_length_size; diff --git a/ext-src/swoole_curl.cc b/ext-src/swoole_curl.cc index 589290ec434..03159b2af40 100644 --- a/ext-src/swoole_curl.cc +++ b/ext-src/swoole_curl.cc @@ -70,7 +70,7 @@ Socket *Multi::create_socket(CURL *cp, curl_socket_t sockfd) { Socket *socket = new Socket(); socket->fd = sockfd; socket->removed = 1; - socket->fd_type = (enum swFdType) PHP_SWOOLE_FD_CO_CURL; + socket->fd_type = (FdType) PHP_SWOOLE_FD_CO_CURL; curl_multi_assign(multi_handle_, sockfd, (void *) socket); Handle *handle = get_handle(cp); diff --git a/ext-src/swoole_http2_server.cc b/ext-src/swoole_http2_server.cc index ba4ab9d40ec..f71333c05fe 100644 --- a/ext-src/swoole_http2_server.cc +++ b/ext-src/swoole_http2_server.cc @@ -440,7 +440,7 @@ bool Http2Stream::send_header(size_t body_length, bool end_stream) { return true; } -bool Http2Stream::send_body(swString *body, bool end_stream, size_t max_frame_size, off_t offset, size_t length) { +bool Http2Stream::send_body(String *body, bool end_stream, size_t max_frame_size, off_t offset, size_t length) { char frame_header[SW_HTTP2_FRAME_HEADER_SIZE]; char *p = body->str + offset; size_t l = length == 0 ? body->length : length; @@ -893,7 +893,7 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { zend_update_property_long( swoole_http_request_ce, SW_Z8_OBJ_P(ctx->request.zobject), ZEND_STRL("streamId"), stream_id); - swString *buffer = ctx->request.h2_data_buffer; + String *buffer = ctx->request.h2_data_buffer; if (!buffer) { buffer = new String(SW_HTTP2_DATA_BUFFER_SIZE); ctx->request.h2_data_buffer = buffer; diff --git a/ext-src/swoole_http_client_coro.cc b/ext-src/swoole_http_client_coro.cc index 9948883b9b0..4456cc2ca95 100644 --- a/ext-src/swoole_http_client_coro.cc +++ b/ext-src/swoole_http_client_coro.cc @@ -187,7 +187,7 @@ class HttpClient { bool close(const bool should_be_reset = true); void get_header_out(zval *return_value) { - swString *buffer = nullptr; + String *buffer = nullptr; if (socket == nullptr) { if (tmp_write_buffer) { buffer = tmp_write_buffer; @@ -913,7 +913,7 @@ bool HttpClient::send() { // clear errno swoole_set_last_error(0); // alloc buffer - swString *buffer = socket->get_write_buffer(); + String *buffer = socket->get_write_buffer(); buffer->clear(); // clear body body->clear(); @@ -958,7 +958,7 @@ bool HttpClient::send() { method = zbody ? "POST" : "GET"; method_len = strlen(method); } - this->method = swHttp_get_method(method, method_len); + this->method = http_server::get_method(method, method_len); buffer->append(method, method_len); buffer->append(ZEND_STRL(" ")); } @@ -1458,7 +1458,7 @@ void HttpClient::recv(zval *zframe, double timeout) { bool HttpClient::recv_http_response(double timeout) { ssize_t retval = 0; size_t total_bytes = 0, parsed_n = 0; - swString *buffer = socket->get_read_buffer(); + String *buffer = socket->get_read_buffer(); bool header_completed = false; off_t header_crlf_offset = 0; @@ -1583,7 +1583,7 @@ bool HttpClient::push(zval *zdata, zend_long opcode, uint8_t flags) { return false; } - swString *buffer = socket->get_write_buffer(); + String *buffer = socket->get_write_buffer(); buffer->clear(); if (php_swoole_websocket_frame_is_object(zdata)) { if (php_swoole_websocket_frame_object_pack(buffer, zdata, websocket_mask, websocket_compression) < 0) { diff --git a/ext-src/swoole_http_response.cc b/ext-src/swoole_http_response.cc index 197f756b9fc..77495790040 100644 --- a/ext-src/swoole_http_response.cc +++ b/ext-src/swoole_http_response.cc @@ -36,6 +36,7 @@ using HttpResponse = swoole::http::Response; using HttpContext = swoole::http::Context; namespace WebSocket = swoole::websocket; +namespace HttpServer = swoole::http_server; zend_class_entry *swoole_http_response_ce; static zend_object_handlers swoole_http_response_handlers; @@ -375,7 +376,7 @@ static void http_build_header(HttpContext *ctx, String *response, size_t body_le * http status line */ if (!ctx->response.reason) { - n = sw_snprintf(buf, l_buf, "HTTP/1.1 %s\r\n", swHttp_get_status_message(ctx->response.status)); + n = sw_snprintf(buf, l_buf, "HTTP/1.1 %s\r\n", HttpServer::get_status_message(ctx->response.status)); } else { n = sw_snprintf(buf, l_buf, "HTTP/1.1 %d %s\r\n", ctx->response.status, ctx->response.reason); } diff --git a/ext-src/swoole_http_server_coro.cc b/ext-src/swoole_http_server_coro.cc index 170d3df3059..6d8cc3b9afc 100644 --- a/ext-src/swoole_http_server_coro.cc +++ b/ext-src/swoole_http_server_coro.cc @@ -21,6 +21,8 @@ using swoole::microtime; using swoole::PHPCoroutine; +using swoole::Server; +using swoole::String; using swoole::coroutine::Socket; using swoole::coroutine::System; @@ -547,7 +549,7 @@ static PHP_METHOD(swoole_http_server_coro, onAccept) { Socket *sock = php_swoole_get_socket(zconn); sock->set_buffer_allocator(sw_zend_string_allocator()); - swString *buffer = sock->get_read_buffer(); + String *buffer = sock->get_read_buffer(); HttpContext *ctx = nullptr; bool header_completed = false; off_t header_crlf_offset = 0; @@ -594,11 +596,11 @@ static PHP_METHOD(swoole_http_server_coro, onAccept) { buffer->offset += parsed_n; swoole_trace_log(SW_TRACE_CO_HTTP_SERVER, - "parsed_n=%ld, length=%ld, offset=%ld, completed=%d", - parsed_n, - buffer->length, - buffer->offset, - ctx->completed); + "parsed_n=%ld, length=%ld, offset=%ld, completed=%d", + parsed_n, + buffer->length, + buffer->offset, + ctx->completed); if (!ctx->completed) { if (ctx->parser.state == s_dead) { diff --git a/ext-src/swoole_mysql_coro.cc b/ext-src/swoole_mysql_coro.cc index 778a030ba6e..1b6021e9577 100644 --- a/ext-src/swoole_mysql_coro.cc +++ b/ext-src/swoole_mysql_coro.cc @@ -241,7 +241,7 @@ class mysql_client { return false; } else { /* without unread data */ - swString *buffer = socket->get_read_buffer(); + String *buffer = socket->get_read_buffer(); SW_ASSERT(buffer->length == (size_t) buffer->offset); buffer->clear(); return true; @@ -606,7 +606,7 @@ bool mysql_client::connect(std::string host, uint16_t port, bool ssl) { const char *mysql_client::recv_length(size_t need_length, const bool try_to_recycle) { if (sw_likely(check_connection())) { ssize_t retval; - swString *buffer = socket->get_read_buffer(); + String *buffer = socket->get_read_buffer(); off_t offset = buffer->offset; // save offset instead of buffer point (due to realloc) size_t read_n = buffer->length - buffer->offset; // readable bytes if (try_to_recycle && read_n == 0) { @@ -1204,7 +1204,7 @@ void mysql_statement::send_execute_request(zval *return_value, zval *params) { RETURN_FALSE; } - swString *buffer = client->socket->get_write_buffer(); + String *buffer = client->socket->get_write_buffer(); char *p = buffer->str; memset(p, 0, 5); diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 57190f23294..15de471c428 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -763,14 +763,14 @@ TaskId php_swoole_task_pack(EventData *task, zval *zdata) { task->info.fd = SwooleG.current_task_id++; task->info.reactor_id = SwooleG.process_id; task->info.time = swoole::microtime(); - swTask_type(task) = 0; + SW_TASK_TYPE(task) = 0; char *task_data_str; size_t task_data_len = 0; // need serialize if (Z_TYPE_P(zdata) != IS_STRING) { // serialize - swTask_type(task) |= SW_TASK_SERIALIZE; + SW_TASK_TYPE(task) |= SW_TASK_SERIALIZE; PHP_VAR_SERIALIZE_INIT(var_hash); php_var_serialize(&serialized_data, zdata, &var_hash); @@ -839,7 +839,7 @@ zval *php_swoole_task_unpack(EventData *task_result) { /** * Large result package */ - if (swTask_type(task_result) & SW_TASK_TMPFILE) { + if (SW_TASK_TYPE(task_result) & SW_TASK_TMPFILE) { if (!task_result->unpack(sw_tg_buffer())) { return nullptr; } @@ -850,7 +850,7 @@ zval *php_swoole_task_unpack(EventData *task_result) { result_data_len = task_result->info.len; } - if (swTask_type(task_result) & SW_TASK_SERIALIZE) { + if (SW_TASK_TYPE(task_result) & SW_TASK_SERIALIZE) { result_unserialized_data = sw_malloc_zval(); PHP_VAR_UNSERIALIZE_INIT(var_hash); @@ -877,7 +877,7 @@ zval *php_swoole_task_unpack(EventData *task_result) { static void php_swoole_task_wait_co( Server *serv, EventData *req, double timeout, int dst_worker_id, INTERNAL_FUNCTION_PARAMETERS) { ServerObject *server_object = server_fetch_object(Z_OBJ_P((zval *) serv->private_data_2)); - swTask_type(req) |= (SW_TASK_NONBLOCK | SW_TASK_COROUTINE); + SW_TASK_TYPE(req) |= (SW_TASK_NONBLOCK | SW_TASK_COROUTINE); TaskCo *task_co = (TaskCo *) emalloc(sizeof(TaskCo)); sw_memset_zero(task_co, sizeof(*task_co)); @@ -1439,7 +1439,7 @@ static sw_inline void php_swoole_create_task_object(zval *ztask, Server *serv, E zend_update_property(swoole_server_task_ce, SW_Z8_OBJ_P(ztask), ZEND_STRL("data"), zdata); zend_update_property_double(swoole_server_task_ce, SW_Z8_OBJ_P(ztask), ZEND_STRL("dispatch_time"), req->info.time); zend_update_property_long( - swoole_server_task_ce, SW_Z8_OBJ_P(ztask), ZEND_STRL("flags"), (zend_long) swTask_type(req)); + swoole_server_task_ce, SW_Z8_OBJ_P(ztask), ZEND_STRL("flags"), (zend_long) SW_TASK_TYPE(req)); } static int php_swoole_server_onTask(Server *serv, EventData *req) { @@ -1499,7 +1499,7 @@ static int php_swoole_server_onFinish(Server *serv, EventData *req) { return SW_ERR; } - if (swTask_type(req) & SW_TASK_COROUTINE) { + if (SW_TASK_TYPE(req) & SW_TASK_COROUTINE) { TaskId task_id = req->info.fd; auto task_co_iterator = server_object->property->task_coroutine_map.find(task_id); @@ -1554,10 +1554,10 @@ static int php_swoole_server_onFinish(Server *serv, EventData *req) { } zend_fcall_info_cache *fci_cache = nullptr; - if (swTask_type(req) & SW_TASK_CALLBACK) { + if (SW_TASK_TYPE(req) & SW_TASK_CALLBACK) { auto callback_iterator = server_object->property->task_callbacks.find(req->info.fd); if (callback_iterator == server_object->property->task_callbacks.end()) { - swTask_type(req) = swTask_type(req) & (~SW_TASK_CALLBACK); + SW_TASK_TYPE(req) = SW_TASK_TYPE(req) & (~SW_TASK_CALLBACK); } else { fci_cache = &callback_iterator->second; } @@ -1596,7 +1596,7 @@ static int php_swoole_server_onFinish(Server *serv, EventData *req) { if (UNEXPECTED(!zend::function::call(fci_cache, argc, args, nullptr, serv->enable_coroutine))) { php_swoole_error(E_WARNING, "%s->onFinish handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } - if (swTask_type(req) & SW_TASK_CALLBACK) { + if (SW_TASK_TYPE(req) & SW_TASK_CALLBACK) { sw_zend_fci_cache_discard(fci_cache); server_object->property->task_callbacks.erase(req->info.fd); } @@ -3234,7 +3234,7 @@ static PHP_METHOD(swoole_server, taskWaitMulti) { php_swoole_fatal_error(E_WARNING, "task pack failed"); goto _fail; } - swTask_type(&buf) |= SW_TASK_WAITALL; + SW_TASK_TYPE(&buf) |= SW_TASK_WAITALL; dst_worker_id = -1; sw_atomic_fetch_add(&serv->gs->tasking_num, 1); if (serv->gs->task_workers.dispatch_blocking(&buf, &dst_worker_id) < 0) { @@ -3360,7 +3360,7 @@ static PHP_METHOD(swoole_server, taskCo) { php_swoole_fatal_error(E_WARNING, "failed to pack task"); goto _fail; } - swTask_type(&buf) |= (SW_TASK_NONBLOCK | SW_TASK_COROUTINE); + SW_TASK_TYPE(&buf) |= (SW_TASK_NONBLOCK | SW_TASK_COROUTINE); dst_worker_id = -1; sw_atomic_fetch_add(&serv->gs->tasking_num, 1); if (serv->gs->task_workers.dispatch(&buf, &dst_worker_id) < 0) { @@ -3426,14 +3426,14 @@ static PHP_METHOD(swoole_server, task) { } if (!serv->is_worker()) { - swTask_type(&buf) |= SW_TASK_NOREPLY; + SW_TASK_TYPE(&buf) |= SW_TASK_NOREPLY; } else if (fci.size) { - swTask_type(&buf) |= SW_TASK_CALLBACK; + SW_TASK_TYPE(&buf) |= SW_TASK_CALLBACK; sw_zend_fci_cache_persist(&fci_cache); server_object->property->task_callbacks[buf.info.fd] = fci_cache; } - swTask_type(&buf) |= SW_TASK_NONBLOCK; + SW_TASK_TYPE(&buf) |= SW_TASK_NONBLOCK; int _dst_worker_id = (int) dst_worker_id; sw_atomic_fetch_add(&serv->gs->tasking_num, 1); @@ -3539,7 +3539,7 @@ static PHP_METHOD(swoole_server_task, pack) { if (php_swoole_task_pack(&buf, zdata) < 0) { RETURN_FALSE; } - swTask_type(&buf) |= (SW_TASK_NONBLOCK | SW_TASK_NOREPLY); + SW_TASK_TYPE(&buf) |= (SW_TASK_NONBLOCK | SW_TASK_NOREPLY); RETURN_STRINGL((char *) &buf, sizeof(buf.info) + buf.info.len); } diff --git a/ext-src/swoole_socket_coro.cc b/ext-src/swoole_socket_coro.cc index cdf037ed4da..d5afe6a7cd5 100644 --- a/ext-src/swoole_socket_coro.cc +++ b/ext-src/swoole_socket_coro.cc @@ -980,7 +980,7 @@ SW_API bool php_swoole_socket_set_protocol(Socket *sock, zval *zset) { if (php_swoole_array_get_value(vht, "open_mqtt_protocol", ztmp)) { sock->open_length_check = zval_is_true(ztmp); if (zval_is_true(ztmp)) { - swMqtt_set_protocol(&sock->protocol); + swoole::mqtt::set_protocol(&sock->protocol); } } // open length check diff --git a/include/swoole.h b/include/swoole.h index cd6298f9a42..8613c45cc3b 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -459,11 +459,11 @@ enum swEventDataFlag { SW_EVENT_DATA_POP_PTR = 1u << 6, }; -#define swTask_type(task) ((task)->info.server_fd) - /** - * use swDataHead->server_fd, 1 byte 8 bit + * Use server_fd field to store flag of the server task */ +#define SW_TASK_TYPE(task) ((task)->info.server_fd) + enum swTaskType { SW_TASK_TMPFILE = 1, // tmp file SW_TASK_SERIALIZE = 2, // php serialize @@ -494,7 +494,7 @@ enum swProcessType { SW_PROCESS_USERWORKER = 5, }; -enum swPipe_type { +enum swPipeType { SW_PIPE_WORKER = 0, SW_PIPE_MASTER = 1, SW_PIPE_READ = 0, @@ -563,17 +563,21 @@ static inline struct timespec swoole_time_until(int milliseconds) { } namespace swoole { + +typedef long SessionId; +typedef long TaskId; +typedef uint8_t ReactorId; +typedef enum swEventType EventType; +typedef enum swSocketType SocketType; +typedef enum swFdType FdType; + struct Event { int fd; int16_t reactor_id; - enum swFdType type; + FdType type; network::Socket *socket; }; -typedef long SessionId; -typedef long TaskId; -typedef uint8_t ReactorId; - struct DataHead { SessionId fd; uint64_t msg_id; diff --git a/include/swoole_client.h b/include/swoole_client.h index 4a66fc7203e..198963a30fa 100644 --- a/include/swoole_client.h +++ b/include/swoole_client.h @@ -35,7 +35,7 @@ class Client { int _sock_type = 0; int _sock_domain = 0; int _protocol = 0; - enum swFdType fd_type; + FdType fd_type; bool active = false; bool async = false; bool keep = false; @@ -118,7 +118,7 @@ class Client { ssize_t (*recv)(Client *cli, char *data, size_t length, int flags) = nullptr; static void init_reactor(Reactor *reactor); - Client(enum swSocketType type, bool async); + Client(SocketType type, bool async); ~Client(); void set_http_proxy(const std::string &host, int port) { @@ -164,7 +164,7 @@ class Stream { int send(const char *data, size_t length); void set_max_length(uint32_t max_length); - inline static Stream *create(const char *dst_host, int dst_port, enum swSocketType type) { + inline static Stream *create(const char *dst_host, int dst_port, SocketType type) { Stream *stream = new Stream(dst_host, dst_port, type); if (!stream->connected) { delete stream; @@ -178,7 +178,7 @@ class Stream { static void set_protocol(Protocol *protocol); private: - Stream(const char *dst_host, int dst_port, enum swSocketType type); + Stream(const char *dst_host, int dst_port, SocketType type); }; //----------------------------------------Stream End------------------------------------ @@ -188,10 +188,10 @@ class SyncClient { bool connected = false; bool created; bool async = false; - enum swSocketType type; + SocketType type; public: - SyncClient(enum swSocketType _type, bool _async = false) : client(_type, _async), async(_async), type(_type) { + SyncClient(SocketType _type, bool _async = false) : client(_type, _async), async(_async), type(_type) { created = client.socket != nullptr; } @@ -252,7 +252,7 @@ class AsyncClient : public SyncClient { std::function _onReceive = nullptr; public: - AsyncClient(enum swSocketType _type) : SyncClient(_type, true) {} + AsyncClient(SocketType _type) : SyncClient(_type, true) {} bool connect(const char *host, int port, double timeout = -1) { client.object = this; diff --git a/include/swoole_coroutine_socket.h b/include/swoole_coroutine_socket.h index bb13bb592e1..6291e9fca2a 100644 --- a/include/swoole_coroutine_socket.h +++ b/include/swoole_coroutine_socket.h @@ -62,13 +62,13 @@ class Socket { Socket(int domain, int type, int protocol); Socket(int _fd, int _domain, int _type, int _protocol); - Socket(enum swSocketType type = SW_SOCK_TCP); - Socket(int _fd, enum swSocketType _type); + Socket(SocketType type = SW_SOCK_TCP); + Socket(int _fd, SocketType _type); ~Socket(); bool connect(std::string host, int port, int flags = 0); bool connect(const struct sockaddr *addr, socklen_t addrlen); bool shutdown(int how = SHUT_RDWR); - bool cancel(const enum swEventType event); + bool cancel(const EventType event); bool close(); inline bool is_connected() { @@ -106,7 +106,7 @@ class Socket { } } - bool poll(enum swEventType type); + bool poll(EventType type); Socket *accept(double timeout = 0); bool bind(std::string address, int port = 0); bool bind(const struct sockaddr *sa, socklen_t len); @@ -152,11 +152,11 @@ class Socket { reactor->set_handler(SW_FD_CORO_SOCKET | SW_EVENT_ERROR, error_event_callback); } - inline enum swSocketType get_type() { + inline SocketType get_type() { return type; } - inline enum swFdType get_fd_type() { + inline FdType get_fd_type() { return socket->fd_type; } @@ -195,11 +195,11 @@ class Socket { return socket->info.get_port(); } - inline bool has_bound(const enum swEventType event = SW_EVENT_RDWR) { + inline bool has_bound(const EventType event = SW_EVENT_RDWR) { return get_bound_co(event) != nullptr; } - inline Coroutine *get_bound_co(const enum swEventType event) { + inline Coroutine *get_bound_co(const EventType event) { if (event & SW_EVENT_READ) { if (read_co) { return read_co; @@ -213,12 +213,12 @@ class Socket { return nullptr; } - inline long get_bound_cid(const enum swEventType event = SW_EVENT_RDWR) { + inline long get_bound_cid(const EventType event = SW_EVENT_RDWR) { Coroutine *co = get_bound_co(event); return co ? co->get_cid() : 0; } - const char *get_event_str(const enum swEventType event) { + const char *get_event_str(const EventType event) { if (event == SW_EVENT_READ) { return "reading"; } else if (event == SW_EVENT_WRITE) { @@ -228,7 +228,7 @@ class Socket { } } - inline void check_bound_co(const enum swEventType event) { + inline void check_bound_co(const EventType event) { long cid = get_bound_cid(event); if (sw_unlikely(cid)) { swoole_fatal_error(SW_ERROR_CO_HAS_BEEN_BOUND, @@ -373,7 +373,7 @@ class Socket { #endif private: - enum swSocketType type; + SocketType type; network::Socket *socket = nullptr; int sock_domain = 0; int sock_type = 0; @@ -383,7 +383,7 @@ class Socket { Coroutine *read_co = nullptr; Coroutine *write_co = nullptr; #ifdef SW_USE_OPENSSL - enum swEventType want_event = SW_EVENT_NULL; + EventType want_event = SW_EVENT_NULL; #endif std::string connect_host; @@ -431,7 +431,7 @@ class Socket { static int writable_event_callback(Reactor *reactor, Event *event); static int error_event_callback(Reactor *reactor, Event *event); - inline void init_sock_type(enum swSocketType _type); + inline void init_sock_type(SocketType _type); inline bool init_sock(); bool init_reactor_socket(int fd); @@ -454,13 +454,13 @@ class Socket { protocol.package_max_length = SW_INPUT_BUFFER_SIZE; } - bool add_event(const enum swEventType event); - bool wait_event(const enum swEventType event, const void **__buf = nullptr, size_t __n = 0); + bool add_event(const EventType event); + bool wait_event(const EventType event, const void **__buf = nullptr, size_t __n = 0); ssize_t recv_packet_with_length_protocol(); ssize_t recv_packet_with_eof_protocol(); - inline bool is_available(const enum swEventType event) { + inline bool is_available(const EventType event) { if (event != SW_EVENT_NULL) { check_bound_co(event); } diff --git a/include/swoole_http.h b/include/swoole_http.h index 6d4209fae00..4d2e6a28397 100644 --- a/include/swoole_http.h +++ b/include/swoole_http.h @@ -17,14 +17,14 @@ #include "swoole.h" -enum swHttp_version { +enum swHttpVersion { SW_HTTP_VERSION_10 = 1, SW_HTTP_VERSION_11, SW_HTTP_VERSION_2, SW_HTTP_VERSION_3, }; -enum swHttp_method { +enum swHttpMethod { SW_HTTP_DELETE = 1, SW_HTTP_GET, SW_HTTP_HEAD, @@ -59,7 +59,7 @@ enum swHttp_method { SW_HTTP_PRI, }; -enum swHttp_status_code { +enum swHttpStatusCode { SW_HTTP_CONTINUE = 100, SW_HTTP_SWITCHING_PROTOCOLS = 101, SW_HTTP_PROCESSING = 102, @@ -127,7 +127,7 @@ struct Request { uint32_t header_length_; /* include request_line_length + \r\n */ uint32_t content_length_; - swString *buffer_; + String *buffer_; public: Request() { @@ -146,18 +146,19 @@ struct Request { bool has_expect_header(); #endif }; -//----------------------------------------------------------------- -} // namespace http -} // namespace swoole -int swHttp_get_method(const char *method_str, size_t method_len); -const char *swHttp_get_method_string(int method); -const char *swHttp_get_status_message(int code); -size_t swHttp_url_decode(char *str, size_t len); -char *swHttp_url_encode(char const *str, size_t len); +int get_method(const char *method_str, size_t method_len); +const char *get_method_string(int method); +const char *get_status_message(int code); +size_t url_decode(char *str, size_t len); +char *url_encode(char const *str, size_t len); #ifdef SW_USE_HTTP2 -ssize_t swHttpMix_get_package_length(swProtocol *protocol, swSocket *conn, const char *data, uint32_t length); -uint8_t swHttpMix_get_package_length_size(swSocket *conn); -int swHttpMix_dispatch_frame(swProtocol *protocol, swSocket *conn, const char *data, uint32_t length); +ssize_t get_package_length(Protocol *protocol, network::Socket *conn, const char *data, uint32_t length); +uint8_t get_package_length_size(network::Socket *conn); +int dispatch_frame(Protocol *protocol, network::Socket *conn, const char *data, uint32_t length); #endif + +//----------------------------------------------------------------- +} // namespace http_server +} // namespace swoole diff --git a/include/swoole_mqtt.h b/include/swoole_mqtt.h index 3abbf4739a6..4fa77192112 100644 --- a/include/swoole_mqtt.h +++ b/include/swoole_mqtt.h @@ -24,7 +24,14 @@ #define SW_MQTT_MAX_LENGTH_SIZE 4 #define SW_MQTT_MAX_PAYLOAD_SIZE 268435455 -enum swMqttOpcode { +#define SW_MQTT_SETRETAIN(HDR, R) (HDR | (R)) +#define SW_MQTT_SETQOS(HDR, Q) (HDR | ((Q) << 1)) +#define SW_MQTT_SETDUP(HDR, D) (HDR | ((D) << 3)) + +namespace swoole { +namespace mqtt { + +enum Opcode { SW_MQTT_CONNECT = 0x10, SW_MQTT_CONNACK = 0x20, SW_MQTT_PUBLISH = 0x30, @@ -41,7 +48,7 @@ enum swMqttOpcode { SW_MQTT_DISCONNECT = 0xE0, }; -struct swMqttPacket { +struct Packet { uint8_t type : 4; uint8_t dup : 1; uint8_t qos : 2; @@ -50,9 +57,7 @@ struct swMqttPacket { char protocol_name[8]; }; -#define SETRETAIN(HDR, R) (HDR | (R)) -#define SETQOS(HDR, Q) (HDR | ((Q) << 1)) -#define SETDUP(HDR, D) (HDR | ((D) << 3)) - -ssize_t swMqtt_get_package_length(swProtocol *protocol, swSocket *conn, const char *data, uint32_t size); -void swMqtt_set_protocol(swProtocol *protocol); +ssize_t get_package_length(swProtocol *protocol, swSocket *conn, const char *data, uint32_t size); +void set_protocol(swProtocol *protocol); +} // namespace mqtt +} // namespace swoole diff --git a/include/swoole_reactor.h b/include/swoole_reactor.h index 10068c6bb54..95eacd7a586 100644 --- a/include/swoole_reactor.h +++ b/include/swoole_reactor.h @@ -205,14 +205,14 @@ class Reactor { return read_handler[fdtype] != nullptr; } - inline int add_event(network::Socket *_socket, enum swEventType event_type) { + inline int add_event(network::Socket *_socket, EventType event_type) { if (!(_socket->events & event_type)) { return set(_socket, _socket->events | event_type); } return SW_OK; } - inline int del_event(network::Socket *_socket, enum swEventType event_type) { + inline int del_event(network::Socket *_socket, EventType event_type) { if (_socket->events & event_type) { return set(_socket, _socket->events & (~event_type)); } @@ -263,7 +263,7 @@ class Reactor { return defer_tasks == nullptr ? timeout_msec : 0; } - inline ReactorHandler get_handler(enum swEventType event_type, enum swFdType fd_type) { + inline ReactorHandler get_handler(EventType event_type, FdType fd_type) { switch (event_type) { case SW_EVENT_READ: return read_handler[fd_type]; @@ -278,7 +278,7 @@ class Reactor { return nullptr; } - inline ReactorHandler get_error_handler(enum swFdType fd_type) { + inline ReactorHandler get_error_handler(FdType fd_type) { ReactorHandler handler = get_handler(SW_EVENT_ERROR, fd_type); // error callback is not set, try to use readable or writable callback if (handler == nullptr) { @@ -333,8 +333,8 @@ class Reactor { void activate_future_task(); - static enum swFdType get_fd_type(int flags) { - return (enum swFdType)(flags & (~SW_EVENT_READ) & (~SW_EVENT_WRITE) & (~SW_EVENT_ERROR) & (~SW_EVENT_ONCE)); + static FdType get_fd_type(int flags) { + return (FdType)(flags & (~SW_EVENT_READ) & (~SW_EVENT_WRITE) & (~SW_EVENT_ERROR) & (~SW_EVENT_ONCE)); } static bool isset_read_event(int events) { diff --git a/include/swoole_server.h b/include/swoole_server.h index c43208a8780..bf2504f8f03 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -64,7 +64,7 @@ struct Connection { * system fd must be 0. en: signalfd, listen socket */ uint8_t active; - enum swSocketType socket_type; + SocketType socket_type; int fd; int worker_id; SessionId session_id; @@ -168,7 +168,7 @@ struct PipeBuffer { }; struct DgramPacket { - enum swSocketType socket_type; + SocketType socket_type; network::Address socket_addr; uint32_t length; char data[0]; @@ -217,7 +217,7 @@ struct ListenPort { uint32_t buffer_high_watermark = 0; uint32_t buffer_low_watermark = 0; - enum swSocketType type = SW_SOCK_TCP; + SocketType type = SW_SOCK_TCP; uint8_t ssl = 0; std::string host; int port = 0; @@ -358,7 +358,7 @@ struct ListenPort { const char *get_host() { return host.c_str(); } - enum swSocketType get_type() { + SocketType get_type() { return type; } int get_fd() { @@ -908,7 +908,7 @@ class Server { void shutdown(); int add_worker(Worker *worker); - ListenPort *add_port(enum swSocketType type, const char *host, int port); + ListenPort *add_port(SocketType type, const char *host, int port); int add_systemd_socket(); int add_hook(enum HookType type, const Callback &func, int push_back); Connection *add_connection(ListenPort *ls, network::Socket *_socket, int server_fd); diff --git a/include/swoole_socket.h b/include/swoole_socket.h index 8a76052f46d..4734531462a 100644 --- a/include/swoole_socket.h +++ b/include/swoole_socket.h @@ -94,9 +94,9 @@ struct Address { struct sockaddr_un un; } addr; socklen_t len; - enum swSocketType type; + SocketType type; - bool assign(enum swSocketType _type, const std::string &_host, int _port); + bool assign(SocketType _type, const std::string &_host, int _port); const char *get_ip() { return get_addr(); } @@ -156,8 +156,8 @@ struct Socket { static uint32_t default_buffer_size; int fd; - enum swFdType fd_type; - enum swSocketType socket_type; + FdType fd_type; + SocketType socket_type; int events; bool enable_tcp_nodelay; @@ -430,11 +430,11 @@ struct Socket { int wait_event(int timeout_ms, int events); void free(); - static inline int is_dgram(swSocketType type) { + static inline int is_dgram(SocketType type) { return (type == SW_SOCK_UDP || type == SW_SOCK_UDP6 || type == SW_SOCK_UNIX_DGRAM); } - static inline int is_stream(swSocketType type) { + static inline int is_stream(SocketType type) { return (type == SW_SOCK_TCP || type == SW_SOCK_TCP6 || type == SW_SOCK_UNIX_STREAM); } @@ -524,7 +524,7 @@ struct Socket { } } - static inline enum swSocketType convert_to_type(int domain, int type, int protocol = 0) { + static inline SocketType convert_to_type(int domain, int type, int protocol = 0) { switch (domain) { case AF_INET: return type == SOCK_STREAM ? SW_SOCK_TCP : SW_SOCK_UDP; @@ -537,7 +537,7 @@ struct Socket { } } - static inline enum swSocketType convert_to_type(std::string &host) { + static inline SocketType convert_to_type(std::string &host) { if (host.compare(0, 6, "unix:/", 0, 6) == 0) { host = host.substr(sizeof("unix:") - 1); host.erase(0, host.find_first_not_of('/') - 1); @@ -549,7 +549,7 @@ struct Socket { } } - static inline int get_domain_and_type(enum swSocketType type, int *sock_domain, int *sock_type) { + static inline int get_domain_and_type(SocketType type, int *sock_domain, int *sock_type) { switch (type) { case SW_SOCK_TCP6: *sock_domain = AF_INET6; @@ -587,9 +587,9 @@ int gethostbyname(int type, const char *name, char *addr); int getaddrinfo(GetaddrinfoRequest *req); } // namespace network -network::Socket *make_socket(int fd, enum swFdType fd_type); -network::Socket *make_socket(enum swSocketType socket_type, enum swFdType fd_type, int flags); -network::Socket *make_server_socket(enum swSocketType socket_type, +network::Socket *make_socket(int fd, FdType fd_type); +network::Socket *make_socket(SocketType socket_type, FdType fd_type, int flags); +network::Socket *make_server_socket(SocketType socket_type, const char *address, int port = 0, int backlog = SW_BACKLOG); diff --git a/include/swoole_ssl.h b/include/swoole_ssl.h index 557f65a71ac..0c440fb4c3c 100644 --- a/include/swoole_ssl.h +++ b/include/swoole_ssl.h @@ -42,18 +42,18 @@ #undef SW_SUPPORT_DTLS #endif -enum swSSL_create_flag { +enum swSSLCreateFlag { SW_SSL_SERVER = 1, SW_SSL_CLIENT = 2, }; -enum swSSL_state { +enum swSSLState { SW_SSL_STATE_HANDSHAKE = 0, SW_SSL_STATE_READY = 1, SW_SSL_STATE_WAIT_STREAM = 2, }; -enum swSSL_version { +enum swSSLVersion { SW_SSL_SSLv2 = 1u << 1, SW_SSL_SSLv3 = 1u << 2, SW_SSL_TLSv1 = 1u << 3, @@ -65,7 +65,7 @@ enum swSSL_version { #define SW_SSL_ALL (SW_SSL_SSLv2 | SW_SSL_SSLv3 | SW_SSL_TLSv1 | SW_SSL_TLSv1_1 | SW_SSL_TLSv1_2 | SW_SSL_TLSv1_3) -enum swSSL_method { +enum swSSLMethod { SW_SSLv23_METHOD = 0, SW_SSLv3_METHOD, SW_SSLv3_SERVER_METHOD, @@ -162,11 +162,12 @@ struct SSLContext { }; } -void swSSL_init(void); -void swSSL_init_thread_safety(); -bool swSSL_is_thread_safety(); -void swSSL_server_http_advise(swoole::SSLContext &); -const char *swSSL_get_error(); -int swSSL_get_ex_connection_index(); -int swSSL_get_ex_port_index(); +void swoole_ssl_init(void); +void swoole_ssl_init_thread_safety(); +bool swoole_ssl_is_thread_safety(); +void swoole_ssl_server_http_advise(swoole::SSLContext &); +const char *swoole_ssl_get_error(); +int swoole_ssl_get_ex_connection_index(); +int swoole_ssl_get_ex_port_index(); + #endif diff --git a/include/swoole_string.h b/include/swoole_string.h index 7a104aae8e1..f335e0d8e79 100644 --- a/include/swoole_string.h +++ b/include/swoole_string.h @@ -215,7 +215,7 @@ class String { return SW_OK; } - inline void write(off_t _offset, swString *write_str) { + inline void write(off_t _offset, String *write_str) { size_t new_length = _offset + write_str->length; if (new_length > size) { reserve(swoole_size_align(new_length * 2, SwooleG.pagesize)); diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index 772b326a65a..6ad8801aec2 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -99,7 +99,7 @@ int Socket::error_event_callback(Reactor *reactor, Event *event) { return SW_OK; } -bool Socket::add_event(const enum swEventType event) { +bool Socket::add_event(const EventType event) { bool ret = true; if (sw_likely(!(socket->events & event))) { if (socket->removed) { @@ -119,8 +119,8 @@ bool Socket::add_event(const enum swEventType event) { * We only need to set the errCode for the socket operation when wait_event returns true, * which means that the exception's error code priority is greater than the current event error priority. */ -bool Socket::wait_event(const enum swEventType event, const void **__buf, size_t __n) { - enum swEventType added_event = event; +bool Socket::wait_event(const EventType event, const void **__buf, size_t __n) { + EventType added_event = event; Coroutine *co = Coroutine::get_current_safe(); if (!co) { return false; @@ -451,7 +451,7 @@ bool Socket::http_proxy_handshake() { return ret; } -void Socket::init_sock_type(enum swSocketType _sw_type) { +void Socket::init_sock_type(SocketType _sw_type) { type = _sw_type; network::Socket::get_domain_and_type(_sw_type, &sock_domain, &sock_type); } @@ -487,7 +487,7 @@ Socket::Socket(int _domain, int _type, int _protocol) init_options(); } -Socket::Socket(enum swSocketType _type) { +Socket::Socket(SocketType _type) { init_sock_type(_type); if (sw_unlikely(!init_sock())) { return; @@ -495,7 +495,7 @@ Socket::Socket(enum swSocketType _type) { init_options(); } -Socket::Socket(int _fd, enum swSocketType _type) { +Socket::Socket(int _fd, SocketType _type) { init_sock_type(_type); if (sw_unlikely(!init_reactor_socket(_fd))) { return; @@ -765,7 +765,7 @@ ssize_t Socket::peek(void *__buf, size_t __n) { return retval; } -bool Socket::poll(enum swEventType type) { +bool Socket::poll(EventType type) { if (sw_unlikely(!is_available(type))) { return -1; } @@ -1670,7 +1670,7 @@ bool Socket::ssl_shutdown() { } #endif -bool Socket::cancel(const enum swEventType event) { +bool Socket::cancel(const EventType event) { if (!has_bound(event)) { return false; } diff --git a/src/coroutine/system.cc b/src/coroutine/system.cc index bf40f982b91..7df50b93433 100644 --- a/src/coroutine/system.cc +++ b/src/coroutine/system.cc @@ -359,7 +359,7 @@ static void socket_poll_completed(void *data) { task->co->resume(); } -static inline void socket_poll_trigger_event(Reactor *reactor, CoroPollTask *task, int fd, enum swEventType event) { +static inline void socket_poll_trigger_event(Reactor *reactor, CoroPollTask *task, int fd, EventType event) { auto i = task->fds->find(fd); if (event == SW_EVENT_ERROR && !(i->second.events & SW_EVENT_ERROR)) { if (i->second.events & SW_EVENT_READ) { @@ -534,7 +534,7 @@ struct EventWaiter { } }; -static inline void event_waiter_callback(Reactor *reactor, EventWaiter *waiter, enum swEventType event) { +static inline void event_waiter_callback(Reactor *reactor, EventWaiter *waiter, EventType event) { if (waiter->revents == 0) { reactor->defer([waiter](void *data) { waiter->co->resume(); }); } diff --git a/src/network/address.cc b/src/network/address.cc index d30340e510a..c608867c8d8 100644 --- a/src/network/address.cc +++ b/src/network/address.cc @@ -46,7 +46,7 @@ int Address::get_port() { } } -bool Address::assign(enum swSocketType _type, const std::string &_host, int _port) { +bool Address::assign(SocketType _type, const std::string &_host, int _port) { type = _type; const char *host = _host.c_str(); if (_type == SW_SOCK_TCP || _type == SW_SOCK_UDP) { diff --git a/src/network/client.cc b/src/network/client.cc index 5f97d34395a..61b52353983 100644 --- a/src/network/client.cc +++ b/src/network/client.cc @@ -68,7 +68,7 @@ void Client::init_reactor(Reactor *reactor) { reactor->set_handler(SW_FD_STREAM_CLIENT | SW_EVENT_ERROR, Client_onError); } -Client::Client(enum swSocketType _type, bool _async) : async(_async) { +Client::Client(SocketType _type, bool _async) : async(_async) { fd_type = Socket::is_stream(_type) ? SW_FD_STREAM_CLIENT : SW_FD_DGRAM_CLIENT; socket = swoole::make_socket(_type, fd_type, (async ? SW_SOCK_NONBLOCK : 0) | SW_SOCK_CLOEXEC); if (socket == nullptr) { diff --git a/src/network/socket.cc b/src/network/socket.cc index 2bbeb4a8b08..c240ef85aab 100644 --- a/src/network/socket.cc +++ b/src/network/socket.cc @@ -1416,7 +1416,7 @@ int Socket::ssl_create(SSLContext *ssl_context, int _flags) { } else if (_flags & SW_SSL_SERVER) { SSL_set_accept_state(ssl); } - if (SSL_set_ex_data(ssl, swSSL_get_ex_connection_index(), this) == 0) { + if (SSL_set_ex_data(ssl, swoole_ssl_get_ex_connection_index(), this) == 0) { swoole_warning("SSL_set_ex_data() failed"); return SW_ERR; } @@ -1430,7 +1430,7 @@ int Socket::ssl_create(SSLContext *ssl_context, int _flags) { using network::Socket; -Socket *make_socket(enum swSocketType type, enum swFdType fd_type, int flags) { +Socket *make_socket(SocketType type, FdType fd_type, int flags) { int sock_domain; int sock_type; @@ -1474,7 +1474,7 @@ Socket *make_socket(enum swSocketType type, enum swFdType fd_type, int flags) { return _socket; } -Socket *make_server_socket(enum swSocketType type, const char *address, int port, int backlog) { +Socket *make_server_socket(SocketType type, const char *address, int port, int backlog) { Socket *sock = swoole::make_socket(type, SW_FD_STREAM_SERVER, SW_SOCK_CLOEXEC); if (sock == nullptr) { swoole_sys_warning("socket() failed"); @@ -1492,7 +1492,7 @@ Socket *make_server_socket(enum swSocketType type, const char *address, int port return sock; } -Socket *make_socket(int fd, enum swFdType fd_type) { +Socket *make_socket(int fd, FdType fd_type) { Socket *socket = new Socket(); socket->fd = fd; socket->fd_type = fd_type; diff --git a/src/network/stream.cc b/src/network/stream.cc index e8f62ab300b..03019f11662 100644 --- a/src/network/stream.cc +++ b/src/network/stream.cc @@ -74,7 +74,7 @@ static void Stream_onClose(Client *cli) { cli); } -Stream::Stream(const char *dst_host, int dst_port, enum swSocketType type) : client(type, true) { +Stream::Stream(const char *dst_host, int dst_port, SocketType type) : client(type, true) { if (client.socket == nullptr) { return; } diff --git a/src/protocol/dtls.cc b/src/protocol/dtls.cc index c684b675af2..8632018a490 100644 --- a/src/protocol/dtls.cc +++ b/src/protocol/dtls.cc @@ -174,7 +174,7 @@ bool Session::listen() { socket->info.get_ip(), socket->info.get_port(), reason, - swSSL_get_error()); + swoole_ssl_get_error()); return false; } else { listened = true; diff --git a/src/protocol/http.cc b/src/protocol/http.cc index f3cf89114eb..86055a01634 100644 --- a/src/protocol/http.cc +++ b/src/protocol/http.cc @@ -24,7 +24,6 @@ #include "swoole_websocket.h" #include "swoole_static_handler.h" -using namespace swoole; using std::string; using swoole::http_server::Request; using swoole::http_server::StaticHandler; @@ -32,30 +31,14 @@ using swoole::network::SendfileTask; using swoole::network::Socket; // clang-format off -static const char *method_strings[] = -{ +static const char *method_strings[] = { "DELETE", "GET", "HEAD", "POST", "PUT", "PATCH", "CONNECT", "OPTIONS", "TRACE", "COPY", "LOCK", "MKCOL", "MOVE", "PROPFIND", "PROPPATCH", "UNLOCK", "REPORT", "MKACTIVITY", "CHECKOUT", "MERGE", "M-SEARCH", "NOTIFY", "SUBSCRIBE", "UNSUBSCRIBE", "PURGE", "PRI", }; // clang-format on -int swHttp_get_method(const char *method_str, size_t method_len) { - int i = 0; - for (; i < SW_HTTP_PRI; i++) { - if (swoole_strcaseeq(method_strings[i], strlen(method_strings[i]), method_str, method_len)) { - return i + 1; - } - } - return -1; -} - -const char *swHttp_get_method_string(int method) { - if (method < 0 || method > SW_HTTP_PRI) { - return nullptr; - } - return method_strings[method - 1]; -} +namespace swoole { bool Server::select_static_handler(http_server::Request *request, Connection *conn) { const char *url = request->buffer_->str + request->url_offset_; @@ -78,7 +61,7 @@ bool Server::select_static_handler(http_server::Request *request, Connection *co "Server: " SW_HTTP_SERVER_SOFTWARE "\r\n" "Content-Length: %zu\r\n" "\r\n%s", - swHttp_get_status_message(SW_HTTP_NOT_FOUND), + http_server::get_status_message(SW_HTTP_NOT_FOUND), sizeof(SW_HTTP_PAGE_404) - 1, SW_HTTP_PAGE_404); response.data = header_buffer; @@ -203,7 +186,19 @@ bool Server::select_static_handler(http_server::Request *request, Connection *co return true; } -const char *swHttp_get_status_message(int code) { +void Server::destroy_http_request(Connection *conn) { + auto request = reinterpret_cast(conn->object); + if (!request) { + return; + } + delete request; + conn->object = nullptr; +} + +namespace http_server { +//----------------------------------------------------------------- + +const char *get_status_message(int code) { switch (code) { case 100: return "100 Continue"; @@ -323,7 +318,7 @@ const char *swHttp_get_status_message(int code) { } } -static int sw_htoi(char *s) { +static int url_htoi(char *s) { int value; int c; @@ -343,7 +338,7 @@ static int sw_htoi(char *s) { } /* return value: length of decoded string */ -size_t swHttp_url_decode(char *str, size_t len) { +size_t url_decode(char *str, size_t len) { char *dest = str; char *data = str; @@ -351,7 +346,7 @@ size_t swHttp_url_decode(char *str, size_t len) { if (*data == '+') { *dest = ' '; } else if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1)) && isxdigit((int) *(data + 2))) { - *dest = (char) sw_htoi(data + 1); + *dest = (char) url_htoi(data + 1); data += 2; len -= 2; } else { @@ -365,7 +360,7 @@ size_t swHttp_url_decode(char *str, size_t len) { return dest - str; } -char *swHttp_url_encode(char const *str, size_t len) { +char *url_encode(char const *str, size_t len) { static uchar hexchars[] = "0123456789ABCDEF"; size_t x, y; @@ -395,9 +390,6 @@ char *swHttp_url_encode(char const *str, size_t len) { return ret; } -namespace swoole { -namespace http_server { -//----------------------------------------------------------------- /** * only GET/POST */ @@ -689,20 +681,28 @@ string Request::get_date_if_modified_since() { return string(""); } -//----------------------------------------------------------------- -} // namespace http_server -} // namespace swoole -void Server::destroy_http_request(Connection *conn) { - auto request = reinterpret_cast(conn->object); - if (!request) { - return; +int get_method(const char *method_str, size_t method_len) { + int i = 0; + for (; i < SW_HTTP_PRI; i++) { + if (swoole_strcaseeq(method_strings[i], strlen(method_strings[i]), method_str, method_len)) { + return i + 1; + } } - delete request; - conn->object = nullptr; + return -1; +} + +const char *get_method_string(int method) { + if (method < 0 || method > SW_HTTP_PRI) { + return nullptr; + } + return method_strings[method - 1]; } +//----------------------------------------------------------------- + #ifdef SW_USE_HTTP2 + static void protocol_status_error(Socket *socket, Connection *conn) { swoole_error_log(SW_LOG_WARNING, SW_ERROR_PROTOCOL_ERROR, @@ -712,7 +712,7 @@ static void protocol_status_error(Socket *socket, Connection *conn) { conn->info.get_port()); } -ssize_t swHttpMix_get_package_length(Protocol *protocol, Socket *socket, const char *data, uint32_t length) { +ssize_t get_package_length(Protocol *protocol, Socket *socket, const char *data, uint32_t length) { Connection *conn = (Connection *) socket->object; if (conn->websocket_status >= websocket::STATUS_HANDSHAKE) { return websocket::get_package_length(protocol, socket, data, length); @@ -724,7 +724,7 @@ ssize_t swHttpMix_get_package_length(Protocol *protocol, Socket *socket, const c } } -uint8_t swHttpMix_get_package_length_size(Socket *socket) { +uint8_t get_package_length_size(Socket *socket) { Connection *conn = (Connection *) socket->object; if (conn->websocket_status >= websocket::STATUS_HANDSHAKE) { return SW_WEBSOCKET_HEADER_LEN + SW_WEBSOCKET_MASK_LEN + sizeof(uint64_t); @@ -736,7 +736,7 @@ uint8_t swHttpMix_get_package_length_size(Socket *socket) { } } -int swHttpMix_dispatch_frame(Protocol *proto, Socket *socket, const char *data, uint32_t length) { +int dispatch_frame(Protocol *proto, Socket *socket, const char *data, uint32_t length) { Connection *conn = (Connection *) socket->object; if (conn->websocket_status >= websocket::STATUS_HANDSHAKE) { return websocket::dispatch_frame(proto, socket, data, length); @@ -748,3 +748,5 @@ int swHttpMix_dispatch_frame(Protocol *proto, Socket *socket, const char *data, } } #endif +} // namespace http_server +} // namespace swoole diff --git a/src/protocol/mqtt.cc b/src/protocol/mqtt.cc index a89f0cdb0d0..e4c7b85c8ae 100644 --- a/src/protocol/mqtt.cc +++ b/src/protocol/mqtt.cc @@ -20,29 +20,31 @@ #include "swoole_mqtt.h" #include "swoole_protocol.h" -using swoole::Protocol; using swoole::network::Socket; -void swMqtt_print_package(swMqttPacket *pkg) { +namespace swoole { +namespace mqtt { + +void print_package(Packet *pkg) { printf("type=%d, length=%d\n", pkg->type, pkg->length); } -void swMqtt_set_protocol(Protocol *protocol) { +void set_protocol(Protocol *protocol) { protocol->package_length_size = SW_MQTT_MAX_LENGTH_SIZE; protocol->package_length_offset = 1; protocol->package_body_offset = 0; - protocol->get_package_length = swMqtt_get_package_length; + protocol->get_package_length = get_package_length; } // recv variable_header packet twice may cause that the '*data' contain the payload data, // but there's no chance to read the next mqtt request ,because MQTT client will recv ACK blocking -#define MQTT_RECV_LEN_AGAIN 0 +#define SW_MQTT_RECV_LEN_AGAIN 0 -ssize_t swMqtt_get_package_length(Protocol *protocol, Socket *conn, const char *data, uint32_t size) { +ssize_t get_package_length(Protocol *protocol, Socket *conn, const char *data, uint32_t size) { //-1 cause the arg 'size' contain length_offset(1 byte len) uint32_t recv_variable_header_size = (size - 1); if (recv_variable_header_size < SW_MQTT_MIN_LENGTH_SIZE) { // recv continue - return MQTT_RECV_LEN_AGAIN; + return SW_MQTT_RECV_LEN_AGAIN; } uint8_t byte; @@ -65,9 +67,12 @@ ssize_t swMqtt_get_package_length(Protocol *protocol, Socket *conn, const char * return SW_ERR; } if (variable_header_byte_count >= recv_variable_header_size) { // length not enough - return MQTT_RECV_LEN_AGAIN; + return SW_MQTT_RECV_LEN_AGAIN; } } // payload_length + variable_header_byte_count + length_offset(1) return length + variable_header_byte_count + 1; } + +} // namespace mqtt +} // namespace swoole diff --git a/src/protocol/ssl.cc b/src/protocol/ssl.cc index 64d7aa92f53..b91ddc04011 100644 --- a/src/protocol/ssl.cc +++ b/src/protocol/ssl.cc @@ -35,17 +35,17 @@ static int ssl_connection_index = 0; static int ssl_port_index = 0; static pthread_mutex_t *lock_array; -static int swSSL_verify_callback(int ok, X509_STORE_CTX *x509_store); +static int swoole_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store); #ifndef OPENSSL_NO_RSA -static RSA *swSSL_rsa_key_callback(SSL *ssl, int is_export, int key_length); +static RSA *swoole_ssl_rsa_key_callback(SSL *ssl, int is_export, int key_length); #endif #if OPENSSL_VERSION_NUMBER < 0x10100000L -static int swSSL_set_default_dhparam(SSL_CTX *ssl_context); +static int swoole_ssl_set_default_dhparam(SSL_CTX *ssl_context); #endif #ifdef SW_SUPPORT_DTLS -static int swSSL_generate_cookie(SSL *ssl, uchar *cookie, uint *cookie_len); -static int swSSL_verify_cookie(SSL *ssl, const uchar *cookie, uint cookie_len); +static int swoole_ssl_generate_cookie(SSL *ssl, uchar *cookie, uint *cookie_len); +static int swoole_ssl_verify_cookie(SSL *ssl, const uchar *cookie, uint cookie_len); #endif #ifdef __GNUC__ @@ -54,9 +54,9 @@ static int swSSL_verify_cookie(SSL *ssl, const uchar *cookie, uint cookie_len); #define MAYBE_UNUSED #endif -static void MAYBE_UNUSED swSSL_lock_callback(int mode, int type, const char *file, int line); +static void MAYBE_UNUSED swoole_ssl_lock_callback(int mode, int type, const char *file, int line); -void swSSL_init(void) { +void swoole_ssl_init(void) { if (openssl_init) { return; } @@ -85,15 +85,15 @@ void swSSL_init(void) { openssl_init = true; } -int swSSL_get_ex_connection_index() { +int swoole_ssl_get_ex_connection_index() { return ssl_connection_index; } -int swSSL_get_ex_port_index() { +int swoole_ssl_get_ex_port_index() { return ssl_port_index; } -void swSSL_destroy() { +void swoole_ssl_destroy() { if (!openssl_init) { return; } @@ -114,7 +114,7 @@ void swSSL_destroy() { openssl_thread_safety_init = false; } -static void MAYBE_UNUSED swSSL_lock_callback(int mode, int type, const char *file, int line) { +static void MAYBE_UNUSED swoole_ssl_lock_callback(int mode, int type, const char *file, int line) { if (mode & CRYPTO_LOCK) { pthread_mutex_lock(&(lock_array[type])); } else { @@ -128,23 +128,23 @@ static int ssl_error_cb(const char *str, size_t len, void *buf) { return 0; } -const char *swSSL_get_error() { +const char *swoole_ssl_get_error() { ERR_print_errors_cb(ssl_error_cb, sw_tg_buffer()->str); return sw_tg_buffer()->str; } #if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_1_0_0 -static void MAYBE_UNUSED swSSL_id_callback(CRYPTO_THREADID *id) { +static void MAYBE_UNUSED swoole_ssl_id_callback(CRYPTO_THREADID *id) { CRYPTO_THREADID_set_numeric(id, (ulong_t) pthread_self()); } #else -static ulong_t swSSL_id_callback(void) { +static ulong_t swoole_ssl_id_callback(void) { return (ulong_t) pthread_self(); } #endif -void swSSL_init_thread_safety() { +void swoole_ssl_init_thread_safety() { if (!openssl_init) { return; } @@ -159,20 +159,20 @@ void swSSL_init_thread_safety() { } #if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_1_0_0 - (void) CRYPTO_THREADID_set_callback(swSSL_id_callback); + (void) CRYPTO_THREADID_set_callback(swoole_ssl_id_callback); #else - CRYPTO_set_id_callback(swSSL_id_callback); + CRYPTO_set_id_callback(swoole_ssl_id_callback); #endif - CRYPTO_set_locking_callback(swSSL_lock_callback); + CRYPTO_set_locking_callback(swoole_ssl_lock_callback); openssl_thread_safety_init = true; } -bool swSSL_is_thread_safety() { +bool swoole_ssl_is_thread_safety() { return openssl_thread_safety_init; } -static void swSSL_info_callback(const SSL *ssl, int where, int ret) { +static void swoole_ssl_info_callback(const SSL *ssl, int where, int ret) { BIO *rbio, *wbio; swSocket *sock; @@ -296,7 +296,7 @@ static int ssl_passwd_callback(char *buf, int num, int verify, void *data) { bool SSLContext::create() { if (!openssl_init) { - swSSL_init(); + swoole_ssl_init(); } const SSL_METHOD *method; @@ -410,7 +410,7 @@ bool SSLContext::create() { #endif SSL_CTX_set_read_ahead(context, 1); - SSL_CTX_set_info_callback(context, swSSL_info_callback); + SSL_CTX_set_info_callback(context, swoole_ssl_info_callback); if (!passphrase.empty()) { SSL_CTX_set_default_passwd_cb_userdata(context, this); @@ -459,8 +459,8 @@ bool SSLContext::create() { #ifdef SW_SUPPORT_DTLS if (protocols & SW_SSL_DTLS) { - SSL_CTX_set_cookie_generate_cb(context, swSSL_generate_cookie); - SSL_CTX_set_cookie_verify_cb(context, swSSL_verify_cookie); + SSL_CTX_set_cookie_generate_cb(context, swoole_ssl_generate_cookie); + SSL_CTX_set_cookie_verify_cb(context, swoole_ssl_verify_cookie); } #endif @@ -545,7 +545,7 @@ bool SSLContext::set_ciphers() { } #ifndef OPENSSL_NO_RSA - SSL_CTX_set_tmp_rsa_callback(context, swSSL_rsa_key_callback); + SSL_CTX_set_tmp_rsa_callback(context, swoole_ssl_rsa_key_callback); #endif if (!dhparam.empty() && !set_dhparam()) { @@ -553,7 +553,7 @@ bool SSLContext::set_ciphers() { } #if OPENSSL_VERSION_NUMBER < 0x10100000L else { - swSSL_set_default_dhparam(context); + swoole_ssl_set_default_dhparam(context); } #endif if (!ecdh_curve.empty() && !set_ecdh_curve()) { @@ -568,7 +568,7 @@ bool SSLContext::set_client_certificate() { const char *cert_file = client_cert_file.c_str(); int depth = verify_depth; - SSL_CTX_set_verify(context, SSL_VERIFY_PEER, swSSL_verify_callback); + SSL_CTX_set_verify(context, SSL_VERIFY_PEER, swoole_ssl_verify_callback); SSL_CTX_set_verify_depth(context, depth); if (SSL_CTX_load_verify_locations(context, cert_file, nullptr) == 0) { @@ -684,7 +684,7 @@ SSLContext::~SSLContext() { } -static int swSSL_verify_callback(int ok, X509_STORE_CTX *x509_store) { +static int swoole_ssl_verify_callback(int ok, X509_STORE_CTX *x509_store) { #if 0 char *subject, *issuer; int err, depth; @@ -729,7 +729,7 @@ static void calculate_cookie(SSL *ssl, uchar *cookie_secret, uint cookie_length) } } -static int swSSL_generate_cookie(SSL *ssl, uchar *cookie, uint *cookie_len) { +static int swoole_ssl_generate_cookie(SSL *ssl, uchar *cookie, uint *cookie_len) { uchar *buffer, result[EVP_MAX_MD_SIZE]; uint length = 0, result_len; Address sa{}; @@ -784,18 +784,18 @@ static int swSSL_generate_cookie(SSL *ssl, uchar *cookie, uint *cookie_len) { return 1; } -static int swSSL_verify_cookie(SSL *ssl, const uchar *cookie, uint cookie_len) { +static int swoole_ssl_verify_cookie(SSL *ssl, const uchar *cookie, uint cookie_len) { uint result_len = 0; uchar result[COOKIE_SECRET_LENGTH]; - swSSL_generate_cookie(ssl, result, &result_len); + swoole_ssl_generate_cookie(ssl, result, &result_len); return cookie_len == result_len && memcmp(result, cookie, result_len) == 0; } #endif #ifndef OPENSSL_NO_RSA -static RSA *swSSL_rsa_key_callback(SSL *ssl, int is_export, int key_length) { +static RSA *swoole_ssl_rsa_key_callback(SSL *ssl, int is_export, int key_length) { static RSA *rsa_tmp = nullptr; if (rsa_tmp) { return rsa_tmp; @@ -820,7 +820,7 @@ static RSA *swSSL_rsa_key_callback(SSL *ssl, int is_export, int key_length) { #endif #if OPENSSL_VERSION_NUMBER < 0x10100000L -static int swSSL_set_default_dhparam(SSL_CTX *ssl_context) { +static int swoole_ssl_set_default_dhparam(SSL_CTX *ssl_context) { DH *dh; static unsigned char dh1024_p[] = { 0xBB, 0xBC, 0x2D, 0xCA, 0xD8, 0x46, 0x74, 0x90, 0x7C, 0x43, 0xFC, 0xF5, 0x80, 0xE9, 0xCF, 0xDB, diff --git a/src/server/master.cc b/src/server/master.cc index e3ea4ae01ec..d5b3ed1687d 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -346,7 +346,7 @@ int Server::start_check() { * OpenSSL thread-safe */ if (is_process_mode() && !single_thread) { - swSSL_init_thread_safety(); + swoole_ssl_init_thread_safety(); } #endif @@ -1434,7 +1434,7 @@ int Server::add_systemd_socket() { return count; } -ListenPort *Server::add_port(enum swSocketType type, const char *host, int port) { +ListenPort *Server::add_port(SocketType type, const char *host, int port) { if (session_list) { swoole_error_log(SW_LOG_ERROR, SW_ERROR_WRONG_OPERATION, "must add port before server is created"); return nullptr; @@ -1468,7 +1468,7 @@ ListenPort *Server::add_port(enum swSocketType type, const char *host, int port) #ifdef SW_USE_OPENSSL if (type & SW_SOCK_SSL) { - type = (enum swSocketType)(type & (~SW_SOCK_SSL)); + type = (SocketType)(type & (~SW_SOCK_SSL)); ls->type = type; ls->ssl = 1; ls->ssl_context = new SSLContext(); diff --git a/src/server/port.cc b/src/server/port.cc index d4b4cca9944..baf496aeb5f 100644 --- a/src/server/port.cc +++ b/src/server/port.cc @@ -93,7 +93,7 @@ static int ssl_server_sni_callback(SSL *ssl, int *al, void *arg) { return SSL_TLSEXT_ERR_NOACK; } - ListenPort *port = (ListenPort *) SSL_get_ex_data(ssl, swSSL_get_ex_port_index()); + ListenPort *port = (ListenPort *) SSL_get_ex_data(ssl, swoole_ssl_get_ex_port_index()); if (port->sni_contexts.empty()) { return SSL_TLSEXT_ERR_NOACK; @@ -124,7 +124,7 @@ bool ListenPort::ssl_create(Connection *conn, Socket *sock) { return false; } conn->ssl = 1; - if (SSL_set_ex_data(sock->ssl, swSSL_get_ex_port_index(), this) == 0) { + if (SSL_set_ex_data(sock->ssl, swoole_ssl_get_ex_port_index(), this) == 0) { swoole_warning("SSL_set_ex_data() failed"); return false; } @@ -234,9 +234,9 @@ void Server::init_port_protocol(ListenPort *ls) { } else if (ls->open_http_protocol) { #ifdef SW_USE_HTTP2 if (ls->open_http2_protocol && ls->open_websocket_protocol) { - ls->protocol.get_package_length = swHttpMix_get_package_length; - ls->protocol.get_package_length_size = swHttpMix_get_package_length_size; - ls->protocol.onPackage = swHttpMix_dispatch_frame; + ls->protocol.get_package_length = http_server::get_package_length; + ls->protocol.get_package_length_size = http_server::get_package_length_size; + ls->protocol.onPackage = http_server::dispatch_frame; } else if (ls->open_http2_protocol) { ls->protocol.package_length_size = SW_HTTP2_FRAME_HEADER_SIZE; ls->protocol.get_package_length = http2::get_frame_length; @@ -252,7 +252,7 @@ void Server::init_port_protocol(ListenPort *ls) { ls->protocol.package_body_offset = 0; ls->onRead = Port_onRead_http; } else if (ls->open_mqtt_protocol) { - swMqtt_set_protocol(&ls->protocol); + mqtt::set_protocol(&ls->protocol); ls->protocol.onPackage = Server::dispatch_task; ls->onRead = Port_onRead_check_length; } else if (ls->open_redis_protocol) { diff --git a/src/server/static_handler.cc b/src/server/static_handler.cc index 7ff13f553e2..e745fb032a1 100644 --- a/src/server/static_handler.cc +++ b/src/server/static_handler.cc @@ -105,7 +105,7 @@ bool StaticHandler::hit() { } dir_path = std::string(url, n); - l_filename = swHttp_url_decode(task.filename, p - task.filename); + l_filename = http_server::url_decode(task.filename, p - task.filename); task.filename[l_filename] = '\0'; if (swoole_strnpos(url, n, SW_STRL("..")) == -1) { diff --git a/src/server/task_worker.cc b/src/server/task_worker.cc index 05fee76b4b1..d1dfacbc49d 100644 --- a/src/server/task_worker.cc +++ b/src/server/task_worker.cc @@ -83,7 +83,7 @@ bool EventData::pack(const void *_data, size_t _length) { } info.len = sizeof(pkg); - swTask_type(this) |= SW_TASK_TMPFILE; + SW_TASK_TYPE(this) |= SW_TASK_TMPFILE; swoole_strlcpy(pkg.tmpfile, file.get_path().c_str(), sizeof(pkg.tmpfile)); pkg.length = _length; memcpy(data, &pkg, sizeof(pkg)); @@ -106,7 +106,7 @@ bool EventData::unpack(String *buffer) { if (fp.read_all(buffer->str, _pkg.length) != _pkg.length) { return false; } - if (!(swTask_type(this) & SW_TASK_PEEK)) { + if (!(SW_TASK_TYPE(this) & SW_TASK_PEEK)) { unlink(_pkg.tmpfile); } buffer->length = _pkg.length; @@ -236,7 +236,7 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even swoole_warning("Server::task()/Server::finish() is not supported in onPipeMessage callback"); return SW_ERR; } - if (swTask_type(current_task) & SW_TASK_NOREPLY) { + if (SW_TASK_TYPE(current_task) & SW_TASK_NOREPLY) { swoole_warning("Server::finish() can only be used in the worker process"); return SW_ERR; } @@ -251,18 +251,18 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even int ret; // for swoole_server_task - if (swTask_type(current_task) & SW_TASK_NONBLOCK) { + if (SW_TASK_TYPE(current_task) & SW_TASK_NONBLOCK) { buf.info.type = SW_SERVER_EVENT_FINISH; buf.info.fd = current_task->info.fd; buf.info.time = microtime(); buf.info.reactor_id = SwooleWG.worker->id; // callback function - if (swTask_type(current_task) & SW_TASK_CALLBACK) { + if (SW_TASK_TYPE(current_task) & SW_TASK_CALLBACK) { flags |= SW_TASK_CALLBACK; - } else if (swTask_type(current_task) & SW_TASK_COROUTINE) { + } else if (SW_TASK_TYPE(current_task) & SW_TASK_COROUTINE) { flags |= SW_TASK_COROUTINE; } - swTask_type(&buf) = flags; + SW_TASK_TYPE(&buf) = flags; // write to file if (!buf.pack(data, data_len)) { @@ -291,14 +291,14 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even // lock worker worker->lock->lock(); - if (swTask_type(current_task) & SW_TASK_WAITALL) { + if (SW_TASK_TYPE(current_task) & SW_TASK_WAITALL) { sw_atomic_t *finish_count = (sw_atomic_t *) result->data; char *_tmpfile = result->data + 4; File file(_tmpfile, O_APPEND | O_WRONLY); if (file.ready()) { buf.info.type = SW_SERVER_EVENT_FINISH; buf.info.fd = current_task->info.fd; - swTask_type(&buf) = flags; + SW_TASK_TYPE(&buf) = flags; if (!buf.pack(data, data_len)) { swoole_warning("large task pack failed()"); buf.info.len = 0; @@ -312,7 +312,7 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even } else { result->info.type = SW_SERVER_EVENT_FINISH; result->info.fd = current_task->info.fd; - swTask_type(result) = flags; + SW_TASK_TYPE(result) = flags; if (!result->pack(data, data_len)) { // unlock worker worker->lock->unlock(); From 29b6c2cdf89618e61951b185918c8028296a8a28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Mon, 9 Aug 2021 12:07:46 +0800 Subject: [PATCH 202/936] Update swoole_table examples (#4357) --- examples/table/array.php | 18 ------------------ examples/table/server.php | 2 +- examples/table/simulation.php | 2 +- examples/table/usage.php | 13 +++++++++++++ 4 files changed, 15 insertions(+), 20 deletions(-) delete mode 100644 examples/table/array.php create mode 100644 examples/table/usage.php diff --git a/examples/table/array.php b/examples/table/array.php deleted file mode 100644 index 59fb1397616..00000000000 --- a/examples/table/array.php +++ /dev/null @@ -1,18 +0,0 @@ -column('id', swoole_table::TYPE_INT); -$table->column('name', swoole_table::TYPE_STRING, 64); -$table->column('num', swoole_table::TYPE_FLOAT); -$table->create(); - -$table['apple'] = array('id' => 145, 'name' => 'iPhone', 'num' => 3.1415); -$table['google'] = array('id' => 358, 'name' => "AlphaGo", 'num' => 3.1415); - -$table['microsoft']['name'] = "Windows"; -$table['microsoft']['num'] = '1997.03'; - -var_dump($table['apple']); -var_dump($table['microsoft']); - -$table['google']['num'] = 500.90; -var_dump($table['google']); diff --git a/examples/table/server.php b/examples/table/server.php index acb2bfdc7da..b93ec616f20 100644 --- a/examples/table/server.php +++ b/examples/table/server.php @@ -6,7 +6,7 @@ $table->create(); $serv = new swoole_server('127.0.0.1', 9501); -$serv->set(['dispatch_mode' => 1]); +$serv->set(['dispatch_mode' => 2]); $serv->table = $table; $serv->on('connect', function($serv, $fd, $reactor_id){ diff --git a/examples/table/simulation.php b/examples/table/simulation.php index 17b0d942655..367acd528a2 100644 --- a/examples/table/simulation.php +++ b/examples/table/simulation.php @@ -1,6 +1,6 @@ column('name', swoole_table::TYPE_STRING, 64); diff --git a/examples/table/usage.php b/examples/table/usage.php new file mode 100644 index 00000000000..67cf582ade7 --- /dev/null +++ b/examples/table/usage.php @@ -0,0 +1,13 @@ +column('id', swoole_table::TYPE_INT); +$table->column('name', swoole_table::TYPE_STRING, 64); +$table->column('num', swoole_table::TYPE_FLOAT); +$table->create(); + +$table->set('a', array('id' => 1, 'name' => 'swoole-co-uk', 'num' => 3.1415)); +$table->set('b', array('id' => 2, 'name' => "swoole-uk", 'num' => 3.1415)); +$table->set('hello@swoole.co.uk', array('id' => 3, 'name' => 'swoole', 'num' => 3.1415)); + +var_dump($table->get('a')); +var_dump($table->get('b', 'name')); From 1a5fd32f6e24dbc0384cb5bfcbf7a0c51f0feef4 Mon Sep 17 00:00:00 2001 From: Yun Dou Date: Mon, 9 Aug 2021 12:09:19 +0800 Subject: [PATCH 203/936] boost context suppoprt for mips64 support (#4358) * Add mips64 n64 boost context asm sources * Add mips64 n64 config.m4 support * Modify boost context asm code to "backport" it --- config.m4 | 7 + .../boost/asm/jump_mips64_n64_elf_gas.S | 139 ++++++++++++++++++ .../boost/asm/make_mips64_n64_elf_gas.S | 95 ++++++++++++ 3 files changed, 241 insertions(+) create mode 100644 thirdparty/boost/asm/jump_mips64_n64_elf_gas.S create mode 100644 thirdparty/boost/asm/make_mips64_n64_elf_gas.S diff --git a/config.m4 b/config.m4 index 928a746cdea..90f72a3c344 100644 --- a/config.m4 +++ b/config.m4 @@ -674,6 +674,7 @@ if test "$PHP_SWOOLE" != "no"; then [arm*], [SW_CPU="arm"], [aarch64*], [SW_CPU="arm64"], [arm64*], [SW_CPU="arm64"], + [mips64*], [SW_CPU="mips64"], [mips*], [SW_CPU="mips32"], [ SW_USE_ASM_CONTEXT="no" @@ -718,6 +719,12 @@ if test "$PHP_SWOOLE" != "no"; then else SW_USE_ASM_CONTEXT="no" fi + elif test "$SW_CPU" = "mips64"; then + if test "$SW_OS" = "LINUX"; then + SW_CONTEXT_ASM_FILE="mips64_n64_elf_gas.S" + else + SW_USE_ASM_CONTEXT="no" + fi elif test "$SW_CPU" = "mips32"; then if test "$SW_OS" = "LINUX"; then SW_CONTEXT_ASM_FILE="mips32_o32_elf_gas.S" diff --git a/thirdparty/boost/asm/jump_mips64_n64_elf_gas.S b/thirdparty/boost/asm/jump_mips64_n64_elf_gas.S new file mode 100644 index 00000000000..ba2b230dbcb --- /dev/null +++ b/thirdparty/boost/asm/jump_mips64_n64_elf_gas.S @@ -0,0 +1,139 @@ +/* + Copyright Jiaxun Yang 2018. + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +/* + "backported" version of original jump_mips64_n64_elf_gas.S +*/ + +/******************************************************* + * * + * ------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * + * ------------------------------------------------- * + * | 0 | 8 | 16 | 24 | * + * ------------------------------------------------- * + * | F24 | F25 | F26 | F27 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * + * ------------------------------------------------- * + * | 32 | 40 | 48 | 56 | * + * ------------------------------------------------- * + * | F28 | F29 | F30 | F31 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * + * ------------------------------------------------- * + * | 64 | 72 | 80 | 88 | * + * ------------------------------------------------- * + * | S0 | S1 | S2 | S3 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | * + * ------------------------------------------------- * + * | 96 | 100 | 104 | 108 | 112 | 116 | 120 | 124 | * + * ------------------------------------------------- * + * | S4 | S5 | S6 | S7 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | * + * ------------------------------------------------- * + * | 128 | 132 | 136 | 140 | 144 | 148 | 152 | 156 | * + * ------------------------------------------------- * + * | FP | GP | RA | PC | * + * ------------------------------------------------- * + * * + * *****************************************************/ + +.text +.globl jump_fcontext +.align 3 +.type jump_fcontext,@function +.ent jump_fcontext +jump_fcontext: + # reserve space on stack + daddiu $sp, $sp, -160 + + sd $s0, 64($sp) # save S0 + sd $s1, 72($sp) # save S1 + sd $s2, 80($sp) # save S2 + sd $s3, 88($sp) # save S3 + sd $s4, 96($sp) # save S4 + sd $s5, 104($sp) # save S5 + sd $s6, 112($sp) # save S6 + sd $s7, 120($sp) # save S7 + sd $fp, 128($sp) # save FP + sd $ra, 144($sp) # save RA + sd $ra, 152($sp) # save RA as PC + +#if defined(__mips_hard_float) + # test if fpu env should be preserved + beqz $a3, 1f + + s.d $f24, 0($sp) # save F24 + s.d $f25, 8($sp) # save F25 + s.d $f26, 16($sp) # save F26 + s.d $f27, 24($sp) # save F27 + s.d $f28, 32($sp) # save F28 + s.d $f29, 40($sp) # save F29 + s.d $f30, 48($sp) # save F30 + s.d $f31, 56($sp) # save F31 +1: +#endif + + # store SP (pointing to context-data) in A0 + sd $sp, ($a0) + + # restore SP (pointing to context-data) from A1 + move $sp, $a1 + +#if defined(__mips_hard_float) + # test if fpu env should be preserved + beqz $a3, 2f + + + l.d $f24, 0($sp) # restore F24 + l.d $f25, 8($sp) # restore F25 + l.d $f26, 16($sp) # restore F26 + l.d $f27, 24($sp) # restore F27 + l.d $f28, 32($sp) # restore F28 + l.d $f29, 40($sp) # restore F29 + l.d $f30, 48($sp) # restore F30 + l.d $f31, 56($sp) # restore F31 +2: +#endif + + ld $s0, 64($sp) # restore S0 + ld $s1, 72($sp) # restore S1 + ld $s2, 80($sp) # restore S2 + ld $s3, 88($sp) # restore S3 + ld $s4, 96($sp) # restore S4 + ld $s5, 104($sp) # restore S5 + ld $s6, 112($sp) # restore S6 + ld $s7, 120($sp) # restore S7 + ld $fp, 128($sp) # restore FP + ld $ra, 144($sp) # restore RAa + + # load PC + ld $t9, 152($sp) + + # adjust stack + daddiu $sp, $sp, 160 + + # use third arg as return value after jump + move $v0, $a2 + # use third arg as first arg in context function + move $a0, $a2 + + # jump to context + jr $t9 +.end jump_fcontext +.size jump_fcontext, .-jump_fcontext + +/* Mark that we don't need executable stack. */ +.section .note.GNU-stack,"",%progbits + diff --git a/thirdparty/boost/asm/make_mips64_n64_elf_gas.S b/thirdparty/boost/asm/make_mips64_n64_elf_gas.S new file mode 100644 index 00000000000..8899e3d203b --- /dev/null +++ b/thirdparty/boost/asm/make_mips64_n64_elf_gas.S @@ -0,0 +1,95 @@ +/* + Copyright Jiaxun Yang 2018. + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ + +/******************************************************* + * * + * ------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * + * ------------------------------------------------- * + * | 0 | 8 | 16 | 24 | * + * ------------------------------------------------- * + * | F24 | F25 | F26 | F27 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * + * ------------------------------------------------- * + * | 32 | 40 | 48 | 56 | * + * ------------------------------------------------- * + * | F28 | F29 | F30 | F31 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * + * ------------------------------------------------- * + * | 64 | 72 | 80 | 88 | * + * ------------------------------------------------- * + * | S0 | S1 | S2 | S3 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | * + * ------------------------------------------------- * + * | 96 | 100 | 104 | 108 | 112 | 116 | 120 | 124 | * + * ------------------------------------------------- * + * | S4 | S5 | S6 | S7 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | * + * ------------------------------------------------- * + * | 128 | 132 | 136 | 140 | 144 | 148 | 152 | 156 | * + * ------------------------------------------------- * + * | FP | GP | RA | PC | * + * ------------------------------------------------- * + * * + * *****************************************************/ + +.text +.globl make_fcontext +.align 3 +.type make_fcontext,@function +.ent make_fcontext +make_fcontext: +#ifdef __PIC__ +.set noreorder +.cpload $t9 +.set reorder +#endif + # shift address in A0 to lower 16 byte boundary + li $v1, 0xfffffffffffffff0 + and $v0, $v1, $a0 + + # reserve space for context-data on context-stack + daddiu $v0, $v0, -160 + + # third arg of make_fcontext() == address of context-function + sd $a2, 152($v0) + # save global pointer in context-data + sd $gp, 136($v0) + + # psudo instruction compute abs address of label finish based on GP + dla $t9, finish + + # save address of finish as return-address for context-function + # will be entered after context-function returns + sd $t9, 144($v0) + + jr $ra # return pointer to context-data + +finish: + # reload our gp register (needed for la) + daddiu $t0, $sp, -160 + ld $gp, 136($t0) + + # call _exit(0) + # the previous function should have left the 16 bytes incoming argument + # area on the stack which we reuse for calling _exit + dla $t9, _exit + move $a0, $zero + jr $t9 +.end make_fcontext +.size make_fcontext, .-make_fcontext + +/* Mark that we don't need executable stack. */ +.section .note.GNU-stack,"",%progbits From b078338065fda8bed623ecdb44d79718fb31da6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Tue, 10 Aug 2021 11:10:38 +0800 Subject: [PATCH 204/936] Fix curl co bugs (#4360) * Fix curl co bugs * fix * try to add event * defense code --- ext-src/swoole_curl.cc | 52 +++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/ext-src/swoole_curl.cc b/ext-src/swoole_curl.cc index 03159b2af40..35ae479b844 100644 --- a/ext-src/swoole_curl.cc +++ b/ext-src/swoole_curl.cc @@ -148,23 +148,31 @@ CURLMcode Multi::remove_handle(CURL *cp) { } CURLcode Multi::exec(php_curl *ch) { - co = check_bound_co(); - ON_SCOPE_EXIT { - co = nullptr; - }; - if (add_handle(ch->cp) != CURLM_OK) { return CURLE_FAILED_INIT; } Handle *handle = get_handle(ch->cp); + bool is_canceled = false; SW_LOOP { + if (handle->socket && handle->socket->removed) { + if (swoole_event_add(handle->socket, get_event(handle->action)) == SW_OK) { + event_count_++; + } + swoole_trace_log(SW_TRACE_CO_CURL, "resume, handle=%p, curl=%p, fd=%d", handle, ch->cp, handle->socket->get_fd()); + } + + co = check_bound_co(); co->yield_ex(-1); - if (co->is_canceled()) { + is_canceled = co->is_canceled(); + co = nullptr; + + if (is_canceled) { swoole_set_last_error(SW_ERROR_CO_CANCELED); break; } + int sockfd = last_sockfd; int bitmask = 0; if (sockfd >= 0) { @@ -191,7 +199,7 @@ CURLcode Multi::exec(php_curl *ch) { CURLcode retval = read_info(); remove_handle(ch->cp); - return co->is_canceled() ? CURLE_ABORTED_BY_CALLBACK : retval; + return is_canceled ? CURLE_ABORTED_BY_CALLBACK : retval; } CURLcode Multi::read_info() { @@ -232,13 +240,9 @@ int Multi::handle_timeout(CURLM *mh, long timeout_ms, void *userp) { } long Multi::select(php_curlm *mh, double timeout) { - co = check_bound_co(); if (zend_llist_count(&mh->easyh) == 0) { return 0; } - ON_SCOPE_EXIT { - co = nullptr; - }; for (zend_llist_element *element = mh->easyh.head; element; element = element->next) { zval *z_ch = (zval *) element->data; @@ -261,7 +265,9 @@ long Multi::select(php_curlm *mh, double timeout) { return 0; } + co = check_bound_co(); co->yield_ex(timeout); + co = nullptr; auto count = selector->active_handles.size(); @@ -304,21 +310,23 @@ void Multi::callback(Handle *handle, int event_bitmask) { } else { last_sockfd = -1; } - // for curl_multi_select if (selector.get()) { if (!handle) { selector->timer_callback = true; } - if (!co) { - if (handle) { - if (swoole_event_del(handle->socket) == SW_OK) { - event_count_--; - } - } else { - del_timer(); + + } + if (!co) { + if (handle) { + if (swoole_event_del(handle->socket) == SW_OK) { + event_count_--; } - return; + } else { + del_timer(); } + return; + } + if (selector.get()) { if (handle) { selector->active_handles.insert(handle); } @@ -329,7 +337,9 @@ void Multi::callback(Handle *handle, int event_bitmask) { swoole_event_defer( [this](void *data) { selector->defer_callback = false; - co->resume(); + if (co) { + co->resume(); + } }, nullptr); } else { From 2039f944b36abeb06552b96cd18ab25fbb6b5956 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 10 Aug 2021 12:03:23 +0800 Subject: [PATCH 205/936] Added SW_GLOBAL_HOOK_AFTER_SERVER_SHUTDOWN hook type --- ext-src/php_swoole_server.h | 2 ++ ext-src/swoole_server.cc | 8 ++++++++ include/swoole_c_api.h | 5 +++++ src/core/base.cc | 4 ++++ src/server/master.cc | 5 +++-- 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/ext-src/php_swoole_server.h b/ext-src/php_swoole_server.h index 088a6b2ed04..6f8230070e4 100644 --- a/ext-src/php_swoole_server.h +++ b/ext-src/php_swoole_server.h @@ -145,3 +145,5 @@ void php_swoole_server_onBufferEmpty(swServer *, swDataHead *); swServer *php_swoole_server_get_and_check_server(zval *zobject); void php_swoole_server_port_deref(zend_object *object); +swoole::ServerObject *php_swoole_server_get_zend_object(swoole::Server *serv); +zval *php_swoole_server_get_zval_object(swoole::Server *serv); diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 15de471c428..3665bebd607 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -154,6 +154,14 @@ Server *php_swoole_server_get_and_check_server(zval *zobject) { return serv; } +zval *php_swoole_server_get_zval_object(Server *serv) { + return (zval *) serv->private_data_2; +} + +ServerObject *php_swoole_server_get_zend_object(Server *serv) { + return server_fetch_object(Z_OBJ_P((zval *) serv->private_data_2)); +} + bool php_swoole_server_isset_callback(Server *serv, ListenPort *port, int event_type) { ServerObject *server_object = server_fetch_object(Z_OBJ_P((zval *) serv->private_data_2)); return server_object->isset_callback(port, event_type); diff --git a/include/swoole_c_api.h b/include/swoole_c_api.h index a711b631d8b..d3fc5e68e48 100644 --- a/include/swoole_c_api.h +++ b/include/swoole_c_api.h @@ -22,6 +22,7 @@ extern "C" { #endif #include +#include enum swGlobal_hook_type { SW_GLOBAL_HOOK_BEFORE_SERVER_START, @@ -31,6 +32,7 @@ enum swGlobal_hook_type { SW_GLOBAL_HOOK_ON_CORO_STOP, SW_GLOBAL_HOOK_ON_REACTOR_CREATE, SW_GLOBAL_HOOK_BEFORE_SERVER_SHUTDOWN, + SW_GLOBAL_HOOK_AFTER_SERVER_SHUTDOWN, SW_GLOBAL_HOOK_BEFORE_WORKER_STOP, SW_GLOBAL_HOOK_ON_REACTOR_DESTROY, SW_GLOBAL_HOOK_END = SW_MAX_HOOK_TYPE - 1, @@ -40,8 +42,11 @@ typedef void (*swHookFunc)(void *data); int swoole_add_function(const char *name, void *func); void *swoole_get_function(const char *name, uint32_t length); + int swoole_add_hook(enum swGlobal_hook_type type, swHookFunc cb, int push_back); void swoole_call_hook(enum swGlobal_hook_type type, void *arg); +bool swoole_isset_hook(enum swGlobal_hook_type type); + const char *swoole_version(void); int swoole_version_id(void); int swoole_api_version_id(void); diff --git a/src/core/base.cc b/src/core/base.cc index 1450c7c8482..0fec2c33d8d 100644 --- a/src/core/base.cc +++ b/src/core/base.cc @@ -201,6 +201,10 @@ SW_API void swoole_call_hook(enum swGlobal_hook_type type, void *arg) { swoole::hook_call(SwooleG.hooks, type, arg); } +SW_API bool swoole_isset_hook(enum swGlobal_hook_type type) { + return SwooleG.hooks[SW_GLOBAL_HOOK_BEFORE_SERVER_SHUTDOWN] != nullptr; +} + SW_API const char *swoole_version(void) { return SWOOLE_VERSION; } diff --git a/src/server/master.cc b/src/server/master.cc index d5b3ed1687d..64160810382 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -759,6 +759,7 @@ void Server::clear_timer() { } void Server::shutdown() { + swoole_call_hook(SW_GLOBAL_HOOK_BEFORE_SERVER_SHUTDOWN, this); if (getpid() != gs->master_pid) { kill(gs->master_pid, SIGTERM); return; @@ -786,8 +787,8 @@ void Server::shutdown() { void Server::destroy() { swoole_trace_log(SW_TRACE_SERVER, "release service"); - if (SwooleG.hooks[SW_GLOBAL_HOOK_BEFORE_SERVER_SHUTDOWN]) { - swoole_call_hook(SW_GLOBAL_HOOK_BEFORE_SERVER_SHUTDOWN, this); + if (SwooleG.hooks[SW_GLOBAL_HOOK_AFTER_SERVER_SHUTDOWN]) { + swoole_call_hook(SW_GLOBAL_HOOK_AFTER_SERVER_SHUTDOWN, this); } /** * shutdown workers From cb8841609c850f6adf1d68c93c201650939f637b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Tue, 10 Aug 2021 15:59:00 +0800 Subject: [PATCH 206/936] Remove legacy code (#4364) * Remove legacy code * Optimize * Optimize [2] * Optimize [3] * Optimize [4] --- core-tests/src/core/base.cpp | 1 + ext-src/php_swoole_coroutine.h | 14 -- ext-src/php_swoole_private.h | 4 - ext-src/php_swoole_server.h | 6 +- ext-src/swoole_coroutine.cc | 17 -- ext-src/swoole_coroutine_system.cc | 128 ++---------- ext-src/swoole_server.cc | 304 +++++++++-------------------- include/swoole_coroutine.h | 2 - include/swoole_coroutine_socket.h | 12 ++ src/core/base.cc | 2 +- src/coroutine/base.cc | 19 -- src/coroutine/socket.cc | 24 +-- src/network/client.cc | 8 - src/network/socket.cc | 6 + src/reactor/base.cc | 11 -- src/server/master.cc | 7 +- 16 files changed, 150 insertions(+), 415 deletions(-) diff --git a/core-tests/src/core/base.cpp b/core-tests/src/core/base.cpp index 4f0771e2114..d43b57d2fa1 100644 --- a/core-tests/src/core/base.cpp +++ b/core-tests/src/core/base.cpp @@ -207,6 +207,7 @@ TEST(base, hook) { int *_count = (int *) data; *_count = 9999; }, 1); + ASSERT_TRUE(swoole_isset_hook(SW_GLOBAL_HOOK_END)); swoole_call_hook(SW_GLOBAL_HOOK_END, &count); ASSERT_EQ(count, 9999); } diff --git a/ext-src/php_swoole_coroutine.h b/ext-src/php_swoole_coroutine.h index 8bb1513ec29..8af2860b5fc 100644 --- a/ext-src/php_swoole_coroutine.h +++ b/ext-src/php_swoole_coroutine.h @@ -44,16 +44,6 @@ struct Function; namespace swoole { -struct PHPContext; - -struct FutureTask { - zval coro_params; - zval *current_coro_return_value_ptr; - void *private_data; - TimerNode *timer; - PHPContext *current_task; -}; - struct PHPContext { JMP_BUF *bailout; zval *vm_stack_top; @@ -138,10 +128,6 @@ class PHPCoroutine { static void interrupt_thread_stop(); - // TODO: remove old coro APIs (Manual) - static void yield_m(zval *return_value, FutureTask *task); - static void resume_m(FutureTask *task, zval *retval); - static inline long get_cid() { return sw_likely(activated) ? Coroutine::get_current_cid() : -1; } diff --git a/ext-src/php_swoole_private.h b/ext-src/php_swoole_private.h index ea0d4b40051..cf7c8e7063d 100644 --- a/ext-src/php_swoole_private.h +++ b/ext-src/php_swoole_private.h @@ -135,10 +135,6 @@ enum php_swoole_fd_type { PHP_SWOOLE_FD_REDIS_CORO, PHP_SWOOLE_FD_POSTGRESQL, PHP_SWOOLE_FD_SOCKET, - /** - * for Co::fread/Co::fwrite - */ - PHP_SWOOLE_FD_CO_UTIL, PHP_SWOOLE_FD_CO_CURL, }; //--------------------------------------------------------- diff --git a/ext-src/php_swoole_server.h b/ext-src/php_swoole_server.h index 6f8230070e4..6737717d132 100644 --- a/ext-src/php_swoole_server.h +++ b/ext-src/php_swoole_server.h @@ -78,7 +78,7 @@ struct ServerProperty { zend_fcall_info_cache *callbacks[PHP_SWOOLE_SERVER_CALLBACK_NUM]; std::unordered_map task_callbacks; std::unordered_map task_coroutine_map; - std::unordered_map *> send_coroutine_map; + std::unordered_map *> send_coroutine_map; }; struct ServerObject { @@ -116,12 +116,10 @@ struct ServerObject { }; struct TaskCo { - FutureTask context; + Coroutine *co; int *list; uint32_t count; zval *result; - TimerNode *timer; - ServerObject *server_object; }; } // namespace swoole diff --git a/ext-src/swoole_coroutine.cc b/ext-src/swoole_coroutine.cc index 08b149444a2..c9a4f174a18 100644 --- a/ext-src/swoole_coroutine.cc +++ b/ext-src/swoole_coroutine.cc @@ -849,23 +849,6 @@ void PHPCoroutine::defer(zend::Function *fci) { task->defer_tasks->push(fci); } -void PHPCoroutine::yield_m(zval *return_value, FutureTask *task) { - PHPContext *ctx = get_context(); - task->current_coro_return_value_ptr = return_value; - task->current_task = ctx; - on_yield(ctx); - ctx->co->yield_naked(); -} - -void PHPCoroutine::resume_m(FutureTask *task, zval *retval) { - PHPContext *ctx = task->current_task; - on_resume(ctx); - if (retval) { - ZVAL_COPY(task->current_coro_return_value_ptr, retval); - } - ctx->co->resume_naked(); -} - void php_swoole_coroutine_minit(int module_number) { PHPCoroutine::init(); diff --git a/ext-src/swoole_coroutine_system.cc b/ext-src/swoole_coroutine_system.cc index 2a0663c4303..ada70e93311 100644 --- a/ext-src/swoole_coroutine_system.cc +++ b/ext-src/swoole_coroutine_system.cc @@ -8,21 +8,12 @@ using swoole::TimerNode; using swoole::Coroutine; using swoole::PHPCoroutine; -using swoole::FutureTask; using swoole::Reactor; using swoole::Event; using swoole::coroutine::Socket; using swoole::coroutine::System; using swoole::String; -struct TmpSocket { - FutureTask context; - swSocket socket; - zend_string *buf; - uint32_t nbytes; - TimerNode *timer; -}; - static zend_class_entry *swoole_coroutine_system_ce; // clang-format off @@ -74,116 +65,39 @@ PHP_METHOD(swoole_coroutine_system, sleep) { RETURN_BOOL(System::sleep(seconds) == 0); } -static int co_socket_onReadable(Reactor *reactor, Event *event) { - TmpSocket *sock = (TmpSocket *) event->socket->object; - FutureTask *context = &sock->context; - - zval result; - - swoole_event_del(event->socket); - - if (sock->timer) { - swoole_timer_del(sock->timer); - sock->timer = nullptr; - } +static void co_socket_read(int fd, zend_long length, INTERNAL_FUNCTION_PARAMETERS) { + php_swoole_check_reactor(); + Socket _socket(fd, SW_SOCK_RAW); - ssize_t n = event->socket->read(ZSTR_VAL(sock->buf), sock->nbytes); + zend_string *buf = zend_string_alloc(length + 1, 0); + size_t nbytes = length <= 0 ? SW_BUFFER_SIZE_STD : length; + ssize_t n = _socket.read(ZSTR_VAL(buf), nbytes); if (n < 0) { - ZVAL_FALSE(&result); - zend_string_free(sock->buf); + ZVAL_FALSE(return_value); + zend_string_free(buf); } else if (n == 0) { - ZVAL_EMPTY_STRING(&result); - zend_string_free(sock->buf); - } else { - ZSTR_VAL(sock->buf)[n] = 0; - ZSTR_LEN(sock->buf) = n; - ZVAL_STR(&result, sock->buf); - } - PHPCoroutine::resume_m(context, &result); - zval_ptr_dtor(&result); - efree(sock); - return SW_OK; -} - -static int co_socket_onWritable(Reactor *reactor, Event *event) { - TmpSocket *sock = (TmpSocket *) event->socket->object; - FutureTask *context = &sock->context; - - zval result; - - swoole_event_del(event->socket); - - if (sock->timer) { - swoole_timer_del(sock->timer); - sock->timer = nullptr; - } - - ssize_t n = event->socket->write(context->private_data, sock->nbytes); - if (n < 0) { - swoole_set_last_error(errno); - ZVAL_FALSE(&result); + ZVAL_EMPTY_STRING(return_value); + zend_string_free(buf); } else { - ZVAL_LONG(&result, n); + ZSTR_VAL(buf)[n] = 0; + ZSTR_LEN(buf) = n; + ZVAL_STR(return_value, buf); } - PHPCoroutine::resume_m(context, &result); - efree(sock); - return SW_OK; + _socket.move_fd(); } -static void co_socket_read(int fd, zend_long length, INTERNAL_FUNCTION_PARAMETERS) { +static void co_socket_write(int fd, char *str, size_t l_str, INTERNAL_FUNCTION_PARAMETERS) { php_swoole_check_reactor(); - if (!swoole_event_isset_handler(PHP_SWOOLE_FD_SOCKET)) { - swoole_event_set_handler(PHP_SWOOLE_FD_CO_UTIL | SW_EVENT_READ, co_socket_onReadable); - swoole_event_set_handler(PHP_SWOOLE_FD_CO_UTIL | SW_EVENT_WRITE, co_socket_onWritable); - } + Socket _socket(fd, SW_SOCK_RAW); - TmpSocket *sock = (TmpSocket *) ecalloc(1, sizeof(TmpSocket)); - - sock->socket.fd = fd; - sock->socket.fd_type = (enum swFdType) PHP_SWOOLE_FD_CO_UTIL; - sock->socket.object = sock; - - if (swoole_event_add(&sock->socket, SW_EVENT_READ) < 0) { - swoole_set_last_error(errno); - efree(sock); - RETURN_FALSE; - } - - sock->buf = zend_string_alloc(length + 1, 0); - sock->nbytes = length <= 0 ? SW_BUFFER_SIZE_STD : length; - - PHPCoroutine::yield_m(return_value, &sock->context); -} - -static void co_socket_write(int fd, char *str, size_t l_str, INTERNAL_FUNCTION_PARAMETERS) { - TmpSocket *sock; - ssize_t ret = write(fd, str, l_str); - if (ret < 0) { - if (errno == EAGAIN) { - goto _yield; - } + ssize_t n = _socket.write(str, l_str); + if (n < 0) { swoole_set_last_error(errno); - RETURN_FALSE; + ZVAL_FALSE(return_value); } else { - RETURN_LONG(ret); - } - -_yield: - sock = (TmpSocket *) ecalloc(1, sizeof(TmpSocket)); - - sock->socket.fd = fd; - sock->socket.fd_type = (enum swFdType) PHP_SWOOLE_FD_CO_UTIL; - sock->socket.object = sock; - - if (swoole_event_add(&sock->socket, SW_EVENT_WRITE) < 0) { - swoole_set_last_error(errno); - RETURN_FALSE; + ZVAL_LONG(return_value, n); } - - FutureTask *task = &sock->context; - task->private_data = str; - sock->nbytes = l_str; - PHPCoroutine::yield_m(return_value, task); + _socket.move_fd(); } PHP_METHOD(swoole_coroutine_system, fread) { diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 3665bebd607..edf38e0f4bd 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -60,7 +60,7 @@ static std::unordered_map server_event_map({ }); // clang-format on -static int php_swoole_task_finish(Server *serv, zval *zdata, EventData *current_task); +// server event callback static void php_swoole_onPipeMessage(Server *serv, EventData *req); static void php_swoole_onStart(Server *); static void php_swoole_onShutdown(Server *); @@ -75,10 +75,8 @@ static int php_swoole_server_onFinish(Server *, EventData *task); static void php_swoole_server_onWorkerError(Server *serv, int worker_id, const ExitStatus &exit_status); static void php_swoole_server_onManagerStart(Server *serv); static void php_swoole_server_onManagerStop(Server *serv); -static void php_swoole_server_onSendTimeout(Timer *timer, TimerNode *tnode); -static enum swReturnCode php_swoole_server_send_resume(Server *serv, FutureTask *context, SessionId fd); -static void php_swoole_task_onTimeout(Timer *timer, TimerNode *tnode); +static int php_swoole_task_finish(Server *serv, zval *zdata, EventData *current_task); static int php_swoole_server_dispatch_func(Server *serv, Connection *conn, SendData *data); static zval *php_swoole_server_add_port(ServerObject *server_object, ListenPort *port); @@ -882,62 +880,6 @@ zval *php_swoole_task_unpack(EventData *task_result) { return result_data; } -static void php_swoole_task_wait_co( - Server *serv, EventData *req, double timeout, int dst_worker_id, INTERNAL_FUNCTION_PARAMETERS) { - ServerObject *server_object = server_fetch_object(Z_OBJ_P((zval *) serv->private_data_2)); - SW_TASK_TYPE(req) |= (SW_TASK_NONBLOCK | SW_TASK_COROUTINE); - - TaskCo *task_co = (TaskCo *) emalloc(sizeof(TaskCo)); - sw_memset_zero(task_co, sizeof(*task_co)); - task_co->count = 1; - Z_LVAL(task_co->context.coro_params) = req->info.fd; - - sw_atomic_fetch_add(&serv->gs->tasking_num, 1); - if (serv->gs->task_workers.dispatch(req, &dst_worker_id) < 0) { - sw_atomic_fetch_sub(&serv->gs->tasking_num, 1); - RETURN_FALSE; - } else { - server_object->property->task_coroutine_map[req->info.fd] = task_co; - } - - long ms = (long) (timeout * 1000); - TimerNode *timer = swoole_timer_add(ms, false, php_swoole_task_onTimeout, task_co); - if (timer) { - task_co->timer = timer; - } - task_co->server_object = server_object; - PHPCoroutine::yield_m(return_value, &task_co->context); -} - -static void php_swoole_task_onTimeout(Timer *timer, TimerNode *tnode) { - TaskCo *task_co = (TaskCo *) tnode->data; - FutureTask *context = &task_co->context; - - // Server->taskwait, single task - if (task_co->list == nullptr) { - zval result; - ZVAL_FALSE(&result); - PHPCoroutine::resume_m(context, &result); - task_co->server_object->property->task_coroutine_map.erase(Z_LVAL(context->coro_params)); - efree(task_co); - return; - } - - uint32_t i; - zval *result = task_co->result; - - for (i = 0; i < task_co->count; i++) { - if (!zend_hash_index_exists(Z_ARRVAL_P(result), i)) { - add_index_bool(result, i, 0); - task_co->server_object->property->task_coroutine_map.erase(task_co->list[i]); - } - } - - PHPCoroutine::resume_m(context, result); - sw_zval_free(result); - efree(task_co); -} - extern ListenPort *php_swoole_server_port_get_and_check_ptr(zval *zobject); extern void php_swoole_server_port_set_ptr(zval *zobject, ListenPort *port); extern ServerPortProperty *php_swoole_server_port_get_property(zval *zobject); @@ -1003,11 +945,11 @@ void ServerObject::on_before_start() { #ifdef SW_LOG_TRACE_OPEN swoole_trace_log(SW_TRACE_SERVER, - "Create Server: host=%s, port=%d, mode=%d, type=%d", - primary_port->host.c_str(), - (int) primary_port->port, - serv->is_base_mode() ? Server::MODE_BASE : Server::MODE_PROCESS, - (int) primary_port->type); + "Create Server: host=%s, port=%d, mode=%d, type=%d", + primary_port->host.c_str(), + (int) primary_port->port, + serv->is_base_mode() ? Server::MODE_BASE : Server::MODE_PROCESS, + (int) primary_port->type); #endif if (serv->enable_coroutine) { @@ -1263,12 +1205,12 @@ static void php_swoole_onPipeMessage(Server *serv, EventData *req) { } swoole_trace_log(SW_TRACE_SERVER, - "PipeMessage: fd=%ld|len=%d|src_worker_id=%d|data=%.*s\n", - req->info.fd, - req->info.len, - req->info.reactor_id, - req->info.len, - req->data); + "PipeMessage: fd=%ld|len=%d|src_worker_id=%d|data=%.*s\n", + req->info.fd, + req->info.len, + req->info.reactor_id, + req->info.len, + req->data); zval args[3]; int argc; @@ -1520,14 +1462,8 @@ static int php_swoole_server_onFinish(Server *serv, EventData *req) { TaskCo *task_co = task_co_iterator->second; // Server->taskwait if (task_co->list == nullptr) { - if (task_co->timer) { - swoole_timer_del(task_co->timer); - } - FutureTask *context = &task_co->context; - PHPCoroutine::resume_m(context, zdata); - efree(task_co); - sw_zval_free(zdata); - server_object->property->task_coroutine_map.erase(task_id); + ZVAL_COPY_VALUE(task_co->result, zdata); + task_co->co->resume(); return SW_OK; } // Server->taskCo @@ -1549,14 +1485,7 @@ static int php_swoole_server_onFinish(Server *serv, EventData *req) { server_object->property->task_coroutine_map.erase(task_id); if (php_swoole_array_length(result) == task_co->count) { - if (task_co->timer) { - swoole_timer_del(task_co->timer); - task_co->timer = nullptr; - } - FutureTask *context = &task_co->context; - PHPCoroutine::resume_m(context, result); - sw_zval_free(result); - efree(task_co); + task_co->co->resume(); } return SW_OK; } @@ -1862,12 +1791,10 @@ void php_swoole_server_onClose(Server *serv, DataHead *info) { auto coros_list = _i_coros_list->second; server_object->property->send_coroutine_map.erase(session_id); while (!coros_list->empty()) { - FutureTask *context = coros_list->front(); + Coroutine *co = coros_list->front(); coros_list->pop_front(); swoole_set_last_error(ECONNRESET); - zval_ptr_dtor(&context->coro_params); - ZVAL_NULL(&context->coro_params); - php_swoole_server_send_resume(serv, context, session_id); + co->resume(); } delete coros_list; } @@ -1939,94 +1866,37 @@ void php_swoole_server_onBufferFull(Server *serv, DataHead *info) { } } -static void php_swoole_server_onSendTimeout(Timer *timer, TimerNode *tnode) { - FutureTask *context = (FutureTask *) tnode->data; - zval *zdata = &context->coro_params; - zval result; - - Server *serv = sw_server(); +void php_swoole_server_send_yield(Server *serv, SessionId session_id, zval *zdata, zval *return_value) { ServerObject *server_object = server_fetch_object(Z_OBJ_P((zval *) serv->private_data_2)); - - swoole_set_last_error(ETIMEDOUT); - ZVAL_FALSE(&result); - - SessionId session_id = (long) context->private_data; - - auto _i_coros_list = server_object->property->send_coroutine_map.find(session_id); - if (_i_coros_list != server_object->property->send_coroutine_map.end()) { - auto coros_list = _i_coros_list->second; - coros_list->remove(context); - // free memory - if (coros_list->size() == 0) { - delete coros_list; - server_object->property->send_coroutine_map.erase(session_id); - } - } else { - swoole_warning("send coroutine[session#%ld] not exists", session_id); - return; - } - - context->private_data = nullptr; - - PHPCoroutine::resume_m(context, &result); - zval_ptr_dtor(zdata); - efree(context); -} - -static enum swReturnCode php_swoole_server_send_resume(Server *serv, FutureTask *context, SessionId fd) { + std::list *coros_list; + Coroutine *co = Coroutine::get_current_safe(); char *data; - zval *zdata = &context->coro_params; - zval result; - - if (ZVAL_IS_NULL(zdata)) { - _fail: - ZVAL_FALSE(&result); - } else { - size_t length = php_swoole_get_send_data(zdata, &data); - if (length == 0) { - goto _fail; - } - bool ret = serv->send(fd, data, length); - if (!ret && swoole_get_last_error() == SW_ERROR_OUTPUT_SEND_YIELD && serv->send_yield) { - return SW_CONTINUE; - } - ZVAL_BOOL(&result, ret); - } + size_t length = php_swoole_get_send_data(zdata, &data); - if (context->timer) { - swoole_timer_del((TimerNode *) context->timer); - context->timer = nullptr; + if (length == 0) { + RETURN_FALSE; } - PHPCoroutine::resume_m(context, &result); - zval_ptr_dtor(zdata); - efree(context); - return SW_READY; -} - -void php_swoole_server_send_yield(Server *serv, SessionId session_id, zval *zdata, zval *return_value) { - ServerObject *server_object = server_fetch_object(Z_OBJ_P((zval *) serv->private_data_2)); - std::list *coros_list; auto coroutine_iterator = server_object->property->send_coroutine_map.find(session_id); - if (coroutine_iterator == server_object->property->send_coroutine_map.end()) { - coros_list = new std::list; + coros_list = new std::list; server_object->property->send_coroutine_map[session_id] = coros_list; } else { coros_list = coroutine_iterator->second; } - FutureTask *context = (FutureTask *) emalloc(sizeof(FutureTask)); - coros_list->push_back(context); - context->private_data = (void *) session_id; - if (serv->send_timeout > 0) { - context->timer = - swoole_timer_add((long) (serv->send_timeout * 1000), false, php_swoole_server_onSendTimeout, context); - } else { - context->timer = nullptr; + SW_LOOP { + coros_list->push_back(co); + if (!co->yield_ex(serv->send_timeout)) { + RETURN_FALSE; + } + bool ret = serv->send(session_id, data, length); + if (!ret && swoole_get_last_error() == SW_ERROR_OUTPUT_SEND_YIELD && serv->send_yield) { + continue; + } else { + RETURN_BOOL(ret); + } } - context->coro_params = *zdata; - PHPCoroutine::yield_m(return_value, context); } static int php_swoole_server_dispatch_func(Server *serv, Connection *conn, SendData *data) { @@ -2081,12 +1951,9 @@ void php_swoole_server_onBufferEmpty(Server *serv, DataHead *info) { auto coros_list = _i_coros_list->second; server_object->property->send_coroutine_map.erase(info->fd); while (!coros_list->empty()) { - FutureTask *context = coros_list->front(); + Coroutine *co = coros_list->front(); coros_list->pop_front(); - if (php_swoole_server_send_resume(serv, context, info->fd) == SW_CONTINUE) { - coros_list->push_back(context); - return; - } + co->resume(); } delete coros_list; } @@ -3120,15 +2987,34 @@ static PHP_METHOD(swoole_server, taskwait) { } int _dst_worker_id = (int) dst_worker_id; + TaskId task_id = buf.info.fd; // coroutine if (PHPCoroutine::get_cid() >= 0) { - php_swoole_task_wait_co(serv, &buf, timeout, _dst_worker_id, INTERNAL_FUNCTION_PARAM_PASSTHRU); + ServerObject *server_object = server_fetch_object(Z_OBJ_P((zval *) serv->private_data_2)); + SW_TASK_TYPE(&buf) |= (SW_TASK_NONBLOCK | SW_TASK_COROUTINE); + + TaskCo task_co{}; + task_co.co = Coroutine::get_current_safe(); + task_co.count = 1; + task_co.result = return_value; + + sw_atomic_fetch_add(&serv->gs->tasking_num, 1); + if (serv->gs->task_workers.dispatch(&buf, &_dst_worker_id) < 0) { + sw_atomic_fetch_sub(&serv->gs->tasking_num, 1); + RETURN_FALSE; + } + + server_object->property->task_coroutine_map[task_id] = &task_co; + auto retval = task_co.co->yield_ex(timeout); + server_object->property->task_coroutine_map.erase(task_id); + + if (!retval) { + RETURN_FALSE; + } return; } - TaskId task_id = buf.info.fd; - uint64_t notify; EventData *task_result = &(serv->task_result[SwooleG.process_id]); sw_memset_zero(task_result, sizeof(*task_result)); @@ -3351,37 +3237,32 @@ static PHP_METHOD(swoole_server, taskCo) { RETURN_FALSE; } - TaskCo *task_co = (TaskCo *) emalloc(sizeof(TaskCo)); - if (task_co == nullptr) { - efree(list); - RETURN_FALSE; - } + TaskCo task_co; + task_co.co = Coroutine::get_current_safe(); - task_co->server_object = server_object; + array_init_size(return_value, n_task); - zval *result = sw_malloc_zval(); - array_init(result); - - SW_HASHTABLE_FOREACH_START(Z_ARRVAL_P(ztasks), ztask) - task_id = php_swoole_task_pack(&buf, ztask); - if (task_id < 0) { - php_swoole_fatal_error(E_WARNING, "failed to pack task"); - goto _fail; - } - SW_TASK_TYPE(&buf) |= (SW_TASK_NONBLOCK | SW_TASK_COROUTINE); - dst_worker_id = -1; - sw_atomic_fetch_add(&serv->gs->tasking_num, 1); - if (serv->gs->task_workers.dispatch(&buf, &dst_worker_id) < 0) { - task_id = -1; - _fail: - add_index_bool(result, i, 0); - n_task--; - sw_atomic_fetch_sub(&serv->gs->tasking_num, 1); - } else { - server_object->property->task_coroutine_map[task_id] = task_co; + SW_HASHTABLE_FOREACH_START(Z_ARRVAL_P(ztasks), ztask) { + task_id = php_swoole_task_pack(&buf, ztask); + if (task_id < 0) { + php_swoole_fatal_error(E_WARNING, "failed to pack task"); + goto _fail; + } + SW_TASK_TYPE(&buf) |= (SW_TASK_NONBLOCK | SW_TASK_COROUTINE); + dst_worker_id = -1; + sw_atomic_fetch_add(&serv->gs->tasking_num, 1); + if (serv->gs->task_workers.dispatch(&buf, &dst_worker_id) < 0) { + task_id = -1; + _fail: + add_index_bool(return_value, i, 0); + n_task--; + sw_atomic_fetch_sub(&serv->gs->tasking_num, 1); + } else { + server_object->property->task_coroutine_map[task_id] = &task_co; + } + list[i] = task_id; + i++; } - list[i] = task_id; - i++; SW_HASHTABLE_FOREACH_END(); if (n_task == 0) { @@ -3389,17 +3270,18 @@ static PHP_METHOD(swoole_server, taskCo) { RETURN_FALSE; } - long ms = (long) (timeout * 1000); + task_co.result = return_value; + task_co.list = list; + task_co.count = n_task; - task_co->result = result; - task_co->list = list; - task_co->count = n_task; - - TimerNode *timer = swoole_timer_add(ms, false, php_swoole_task_onTimeout, task_co); - if (timer) { - task_co->timer = timer; + if (!task_co.co->yield_ex(timeout)) { + for (uint32_t i = 0; i < n_task; i++) { + if (!zend_hash_index_exists(Z_ARRVAL_P(return_value), i)) { + add_index_bool(return_value, i, 0); + server_object->property->task_coroutine_map.erase(list[i]); + } + } } - PHPCoroutine::yield_m(return_value, &task_co->context); } static PHP_METHOD(swoole_server, task) { diff --git a/include/swoole_coroutine.h b/include/swoole_coroutine.h index c2833c006b9..93997f838a6 100644 --- a/include/swoole_coroutine.h +++ b/include/swoole_coroutine.h @@ -68,8 +68,6 @@ class Coroutine { void yield(CancelFunc *cancel_fn); bool cancel(); - void resume_naked(); - void yield_naked(); bool yield_ex(double timeout = -1); inline enum State get_state() const { diff --git a/include/swoole_coroutine_socket.h b/include/swoole_coroutine_socket.h index 6291e9fca2a..5bca498e401 100644 --- a/include/swoole_coroutine_socket.h +++ b/include/swoole_coroutine_socket.h @@ -360,6 +360,18 @@ class Socket { buffer_init_size = size; } + int move_fd() { + int sockfd = socket->fd; + socket->fd = -1; + return sockfd; + } + + network::Socket *move_socket() { + network::Socket *_socket = socket; + socket = nullptr; + return _socket; + } + #ifdef SW_USE_OPENSSL inline bool ssl_is_available() { return socket && ssl_handshaked; diff --git a/src/core/base.cc b/src/core/base.cc index 0fec2c33d8d..3f9ed8f0a39 100644 --- a/src/core/base.cc +++ b/src/core/base.cc @@ -202,7 +202,7 @@ SW_API void swoole_call_hook(enum swGlobal_hook_type type, void *arg) { } SW_API bool swoole_isset_hook(enum swGlobal_hook_type type) { - return SwooleG.hooks[SW_GLOBAL_HOOK_BEFORE_SERVER_SHUTDOWN] != nullptr; + return SwooleG.hooks[type] != nullptr; } SW_API const char *swoole_version(void) { diff --git a/src/coroutine/base.cc b/src/coroutine/base.cc index 9ffa46db609..bf9d690a2c9 100644 --- a/src/coroutine/base.cc +++ b/src/coroutine/base.cc @@ -116,25 +116,6 @@ void Coroutine::resume() { check_end(); } -void Coroutine::yield_naked() { - SW_ASSERT(current == this); - state = STATE_WAITING; - current = origin; - ctx.swap_out(); -} - -void Coroutine::resume_naked() { - SW_ASSERT(current != this); - if (sw_unlikely(on_bailout)) { - return; - } - state = STATE_RUNNING; - origin = current; - current = this; - ctx.swap_in(); - check_end(); -} - bool Coroutine::cancel() { if (!cancel_fn_) { swoole_set_last_error(SW_ERROR_CO_CANNOT_CANCEL); diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index 6ad8801aec2..1078d5f14d9 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -1730,9 +1730,6 @@ bool Socket::close() { * 3. called close() and it return false but it will not be accessed anywhere else */ Socket::~Socket() { - if (socket == nullptr) { - return; - } #ifdef SW_DEBUG if (SwooleG.running) { SW_ASSERT(!has_bound() && socket->removed); @@ -1744,16 +1741,19 @@ Socket::~Socket() { if (write_buffer) { delete write_buffer; } + if (socks5_proxy) { + delete socks5_proxy; + } + if (http_proxy) { + delete http_proxy; + } + if (socket == nullptr) { + return; + } /* {{{ release socket resources */ #ifdef SW_USE_OPENSSL ssl_shutdown(); #endif - if (socket->in_buffer) { - delete socket->in_buffer; - } - if (socket->out_buffer) { - delete socket->out_buffer; - } if (sock_domain == AF_UNIX && !bind_address.empty()) { ::unlink(bind_address_info.addr.un.sun_path); bind_address_info = {}; @@ -1761,12 +1761,6 @@ Socket::~Socket() { if (socket->socket_type == SW_SOCK_UNIX_DGRAM) { ::unlink(socket->info.addr.un.sun_path); } - if (socks5_proxy) { - delete socks5_proxy; - } - if (http_proxy) { - delete http_proxy; - } socket->free(); } diff --git a/src/network/client.cc b/src/network/client.cc index 61b52353983..ddaad696956 100644 --- a/src/network/client.cc +++ b/src/network/client.cc @@ -427,14 +427,6 @@ Client::~Client() { if (server_str) { ::sw_free((void *) server_str); } - if (socket->out_buffer) { - delete socket->out_buffer; - socket->out_buffer = nullptr; - } - if (socket->in_buffer) { - delete socket->in_buffer; - socket->in_buffer = nullptr; - } if (socks5_proxy) { delete socks5_proxy; } diff --git a/src/network/socket.cc b/src/network/socket.cc index c240ef85aab..573364a95a9 100644 --- a/src/network/socket.cc +++ b/src/network/socket.cc @@ -320,6 +320,12 @@ void Socket::free() { if (send_timer) { swoole_timer_del(send_timer); } + if (in_buffer) { + delete in_buffer; + } + if (out_buffer) { + delete out_buffer; + } if (swoole_event_is_available()) { removed = 1; swoole_event_defer(socket_free_defer, this); diff --git a/src/reactor/base.cc b/src/reactor/base.cc index 0d6aad873f0..d8ac882341c 100644 --- a/src/reactor/base.cc +++ b/src/reactor/base.cc @@ -202,19 +202,8 @@ static void reactor_begin(Reactor *reactor) { } int Reactor::_close(Reactor *reactor, Socket *socket) { - if (socket->out_buffer) { - delete socket->out_buffer; - socket->out_buffer = nullptr; - } - if (socket->in_buffer) { - delete socket->in_buffer; - socket->in_buffer = nullptr; - } - swoole_trace_log(SW_TRACE_CLOSE, "fd=%d", socket->fd); - socket->free(); - return SW_OK; } diff --git a/src/server/master.cc b/src/server/master.cc index 64160810382..cd3ad48eec7 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -759,7 +759,10 @@ void Server::clear_timer() { } void Server::shutdown() { - swoole_call_hook(SW_GLOBAL_HOOK_BEFORE_SERVER_SHUTDOWN, this); + swoole_trace_log(SW_TRACE_SERVER, "shutdown service"); + if (swoole_isset_hook(SW_GLOBAL_HOOK_BEFORE_SERVER_SHUTDOWN)) { + swoole_call_hook(SW_GLOBAL_HOOK_BEFORE_SERVER_SHUTDOWN, this); + } if (getpid() != gs->master_pid) { kill(gs->master_pid, SIGTERM); return; @@ -787,7 +790,7 @@ void Server::shutdown() { void Server::destroy() { swoole_trace_log(SW_TRACE_SERVER, "release service"); - if (SwooleG.hooks[SW_GLOBAL_HOOK_AFTER_SERVER_SHUTDOWN]) { + if (swoole_isset_hook(SW_GLOBAL_HOOK_AFTER_SERVER_SHUTDOWN)) { swoole_call_hook(SW_GLOBAL_HOOK_AFTER_SERVER_SHUTDOWN, this); } /** From aeb906419293f48090b0a6891e83282f9c48b324 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 10 Aug 2021 16:01:54 +0800 Subject: [PATCH 207/936] Update version id --- CMakeLists.txt | 2 +- include/swoole_version.h | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 667baaf60c3..641bbde5931 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ PROJECT(libswoole) ENABLE_LANGUAGE(ASM) -set(SWOOLE_VERSION 4.7.0) +set(SWOOLE_VERSION 4.7.1-dev) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g") diff --git a/include/swoole_version.h b/include/swoole_version.h index 7e57533779c..ad7af8bdd52 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -20,11 +20,11 @@ #define SWOOLE_MAJOR_VERSION 4 #define SWOOLE_MINOR_VERSION 7 -#define SWOOLE_RELEASE_VERSION 0 -#define SWOOLE_EXTRA_VERSION "" -#define SWOOLE_VERSION "4.7.0" -#define SWOOLE_VERSION_ID 40700 -#define SWOOLE_API_VERSION_ID 0x202107a +#define SWOOLE_RELEASE_VERSION 1 +#define SWOOLE_EXTRA_VERSION "dev" +#define SWOOLE_VERSION "4.7.1-dev" +#define SWOOLE_VERSION_ID 40701 +#define SWOOLE_API_VERSION_ID 0x202108a #define SWOOLE_BUG_REPORT \ "A bug occurred in Swoole-v" SWOOLE_VERSION ", please report it.\n" \ From d039fd42b8f7c4689b2a1d7378470431473a164c Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 10 Aug 2021 19:05:01 +0800 Subject: [PATCH 208/936] Fix #4365 --- ext-src/swoole_http2_server.cc | 2 +- ext-src/swoole_server.cc | 4 ++- tests/swoole_http2_server/issue_4365.phpt | 39 +++++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 tests/swoole_http2_server/issue_4365.phpt diff --git a/ext-src/swoole_http2_server.cc b/ext-src/swoole_http2_server.cc index f71333c05fe..e76f3ce350d 100644 --- a/ext-src/swoole_http2_server.cc +++ b/ext-src/swoole_http2_server.cc @@ -525,7 +525,7 @@ static bool swoole_http2_server_respond(HttpContext *ctx, String *body) { bool error = false; // If send_yield is not supported, ignore flow control - if (ctx->co_socket || !((Server *) ctx->private_data)->send_yield) { + if (ctx->co_socket || !((Server *) ctx->private_data)->send_yield || !swoole_coroutine_is_in()) { if (body->length > client->send_window) { swoole_warning("The data sent exceeded send_window"); } diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index edf38e0f4bd..ce5a88acad0 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -2150,8 +2150,10 @@ static PHP_METHOD(swoole_server, set) { if (serv->send_yield && !(serv->dispatch_mode == Server::DISPATCH_FDMOD || serv->dispatch_mode == Server::DISPATCH_IPMOD)) { php_swoole_error(E_WARNING, "'send_yield' option can only be set when using dispatch_mode=2/4"); - serv->send_yield = 0; + serv->send_yield = false; } + } else { + serv->send_yield = serv->enable_coroutine; } if (php_swoole_array_get_value(vht, "dispatch_func", ztmp)) { Server::DispatchFunction c_dispatch_func = nullptr; diff --git a/tests/swoole_http2_server/issue_4365.phpt b/tests/swoole_http2_server/issue_4365.phpt new file mode 100644 index 00000000000..ab304338d1c --- /dev/null +++ b/tests/swoole_http2_server/issue_4365.phpt @@ -0,0 +1,39 @@ +--TEST-- +swoole_http2_server: github issue#4365 +--SKIPIF-- + +--FILE-- +parentFunc = function ($pid) use ($pm) { + if (Assert::assert(!empty($res = `curl -s --http2-prior-knowledge http://127.0.0.1:{$pm->getFreePort()}/ > /dev/stdout 2>/dev/null`))) { + Assert::length($res, N); + echo "DONE\n"; + } + $pm->kill(); +}; +$pm->childFunc = function () use ($pm) { + $http = new swoole_http_server('127.0.0.1', $pm->getFreePort(), SERVER_MODE_RANDOM); + $http->set([ + 'open_http2_protocol' => true, + 'enable_reuse_port' => true, + 'enable_coroutine' => false, + 'log_level' => 1, + 'log_file' => TEST_LOG_FILE, + ]); + $http->on('request', function ($request, $response) { + $response->end(str_repeat('x', N)); + }); + $http->start(); +}; +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +DONE From db85715dd983bc25f27332543e9df72afffda146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Wed, 11 Aug 2021 17:20:28 +0800 Subject: [PATCH 209/936] Fix #4355 (#4366) * Fix #4355 * remove debug code --- ext-src/php_swoole_curl.h | 7 +++--- ext-src/swoole_curl.cc | 44 +++++++++++++++++++-------------- tests/swoole_curl/upload/2.phpt | 34 +++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 23 deletions(-) create mode 100644 tests/swoole_curl/upload/2.phpt diff --git a/ext-src/php_swoole_curl.h b/ext-src/php_swoole_curl.h index e2950364c50..97ef863dc88 100644 --- a/ext-src/php_swoole_curl.h +++ b/ext-src/php_swoole_curl.h @@ -45,7 +45,6 @@ struct Handle { }; struct Selector { - bool defer_callback = false; bool timer_callback = false; std::set active_handles; }; @@ -58,6 +57,7 @@ class Multi { int running_handles_ = 0; int last_sockfd; int event_count_ = 0; + bool defer_callback = false; std::unique_ptr selector; CURLcode read_info(); @@ -78,8 +78,7 @@ class Multi { swoole_timer_del(timer); } timeout_ms_ = timeout_ms; - timer = swoole_timer_add( - timeout_ms, false, [this](Timer *timer, TimerNode *tnode) { + timer = swoole_timer_add(timeout_ms, false, [this](Timer *timer, TimerNode *tnode) { this->timer = nullptr; callback(nullptr, 0); }); @@ -154,6 +153,6 @@ class Multi { static int handle_socket(CURL *easy, curl_socket_t s, int action, void *userp, void *socketp); static int handle_timeout(CURLM *multi, long timeout_ms, void *userp); }; -}; +}; // namespace curl } // namespace swoole #endif diff --git a/ext-src/swoole_curl.cc b/ext-src/swoole_curl.cc index 35ae479b844..46cabe5ada8 100644 --- a/ext-src/swoole_curl.cc +++ b/ext-src/swoole_curl.cc @@ -24,7 +24,7 @@ namespace curl { static int execute_callback(Event *event, int bitmask) { Handle *handle = (Handle *) event->socket->object; - handle->event_bitmask = bitmask; + handle->event_bitmask |= bitmask; handle->event_fd = event->fd; handle->multi->callback(handle, bitmask); return 0; @@ -160,7 +160,8 @@ CURLcode Multi::exec(php_curl *ch) { if (swoole_event_add(handle->socket, get_event(handle->action)) == SW_OK) { event_count_++; } - swoole_trace_log(SW_TRACE_CO_CURL, "resume, handle=%p, curl=%p, fd=%d", handle, ch->cp, handle->socket->get_fd()); + swoole_trace_log( + SW_TRACE_CO_CURL, "resume, handle=%p, curl=%p, fd=%d", handle, ch->cp, handle->socket->get_fd()); } co = check_bound_co(); @@ -182,7 +183,14 @@ CURLcode Multi::exec(php_curl *ch) { } } del_timer(); + curl_multi_socket_action(multi_handle_, sockfd, bitmask, &running_handles_); + swoole_trace_log(SW_TRACE_CO_CURL, + "curl_multi_socket_action: handle=%p, sockfd=%d, bitmask=%d, running_handles_=%d", + handle, + sockfd, + bitmask, + running_handles_); if (running_handles_ == 0) { break; } @@ -255,7 +263,8 @@ long Multi::select(php_curlm *mh, double timeout) { if (swoole_event_add(handle->socket, get_event(handle->action)) == SW_OK) { event_count_++; } - swoole_trace_log(SW_TRACE_CO_CURL, "resume, handle=%p, curl=%p, fd=%d", handle, ch->cp, handle->socket->get_fd()); + swoole_trace_log( + SW_TRACE_CO_CURL, "resume, handle=%p, curl=%p, fd=%d", handle, ch->cp, handle->socket->get_fd()); } } set_timer(); @@ -304,7 +313,7 @@ long Multi::select(php_curlm *mh, double timeout) { } void Multi::callback(Handle *handle, int event_bitmask) { - swoole_trace_log(SW_TRACE_CO_CURL, "callback, handle=%p, event_bitmask=%d", handle, event_bitmask); + swoole_trace_log(SW_TRACE_CO_CURL, "handle=%p, event_bitmask=%d, co=%p", handle, event_bitmask, co); if (handle) { last_sockfd = handle->event_fd; } else { @@ -314,7 +323,6 @@ void Multi::callback(Handle *handle, int event_bitmask) { if (!handle) { selector->timer_callback = true; } - } if (!co) { if (handle) { @@ -330,21 +338,19 @@ void Multi::callback(Handle *handle, int event_bitmask) { if (handle) { selector->active_handles.insert(handle); } - if (selector->defer_callback) { - return; - } - selector->defer_callback = true; - swoole_event_defer( - [this](void *data) { - selector->defer_callback = false; - if (co) { - co->resume(); - } - }, - nullptr); - } else { - co->resume(); } + if (defer_callback) { + return; + } + defer_callback = true; + swoole_event_defer( + [this](void *data) { + defer_callback = false; + if (co) { + co->resume(); + } + }, + nullptr); } } // namespace curl } // namespace swoole diff --git a/tests/swoole_curl/upload/2.phpt b/tests/swoole_curl/upload/2.phpt new file mode 100644 index 00000000000..9277dd18295 --- /dev/null +++ b/tests/swoole_curl/upload/2.phpt @@ -0,0 +1,34 @@ +--TEST-- +swoole_curl/upload: CURL file uploading +--INI-- +--SKIPIF-- + +--FILE-- + $file)); + $result = curl_exec($ch); + Assert::notEmpty($result); + $json = json_decode($result); + Assert::notEmpty($json); + Assert::notEmpty($json->files->swoole_file); + $prefix = 'data:application/octet-stream;base64,'; + Assert::startsWith($json->files->swoole_file, $prefix); + $data = substr($json->files->swoole_file, strlen($prefix)); + Assert::eq(md5(base64_decode($data)), md5_file(TEST_IMAGE)); +}); +?> +--EXPECTF-- From bc1f5c7fa904cf4397fa2f945e6d1a335e56d843 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Wed, 11 Aug 2021 18:19:39 +0800 Subject: [PATCH 210/936] Optimize code --- ext-src/swoole_curl.cc | 6 ++---- include/swoole_c_api.h | 8 ++++---- src/core/base.cc | 6 +++--- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/ext-src/swoole_curl.cc b/ext-src/swoole_curl.cc index 46cabe5ada8..fe3ecaea20a 100644 --- a/ext-src/swoole_curl.cc +++ b/ext-src/swoole_curl.cc @@ -334,10 +334,8 @@ void Multi::callback(Handle *handle, int event_bitmask) { } return; } - if (selector.get()) { - if (handle) { - selector->active_handles.insert(handle); - } + if (selector.get() && handle) { + selector->active_handles.insert(handle); } if (defer_callback) { return; diff --git a/include/swoole_c_api.h b/include/swoole_c_api.h index d3fc5e68e48..03f348a0a0f 100644 --- a/include/swoole_c_api.h +++ b/include/swoole_c_api.h @@ -24,7 +24,7 @@ extern "C" { #include #include -enum swGlobal_hook_type { +enum swGlobalHookType { SW_GLOBAL_HOOK_BEFORE_SERVER_START, SW_GLOBAL_HOOK_BEFORE_CLIENT_START, SW_GLOBAL_HOOK_BEFORE_WORKER_START, @@ -43,9 +43,9 @@ typedef void (*swHookFunc)(void *data); int swoole_add_function(const char *name, void *func); void *swoole_get_function(const char *name, uint32_t length); -int swoole_add_hook(enum swGlobal_hook_type type, swHookFunc cb, int push_back); -void swoole_call_hook(enum swGlobal_hook_type type, void *arg); -bool swoole_isset_hook(enum swGlobal_hook_type type); +int swoole_add_hook(enum swGlobalHookType type, swHookFunc cb, int push_back); +void swoole_call_hook(enum swGlobalHookType type, void *arg); +bool swoole_isset_hook(enum swGlobalHookType type); const char *swoole_version(void); int swoole_version_id(void); diff --git a/src/core/base.cc b/src/core/base.cc index 3f9ed8f0a39..d7dc9b3bfcf 100644 --- a/src/core/base.cc +++ b/src/core/base.cc @@ -193,15 +193,15 @@ SW_API void *swoole_get_function(const char *name, uint32_t length) { } } -SW_API int swoole_add_hook(enum swGlobal_hook_type type, swHookFunc func, int push_back) { +SW_API int swoole_add_hook(enum swGlobalHookType type, swHookFunc func, int push_back) { return swoole::hook_add(SwooleG.hooks, type, func, push_back); } -SW_API void swoole_call_hook(enum swGlobal_hook_type type, void *arg) { +SW_API void swoole_call_hook(enum swGlobalHookType type, void *arg) { swoole::hook_call(SwooleG.hooks, type, arg); } -SW_API bool swoole_isset_hook(enum swGlobal_hook_type type) { +SW_API bool swoole_isset_hook(enum swGlobalHookType type) { return SwooleG.hooks[type] != nullptr; } From e64e5a3da7faf78c7df0a36e09c811d98d9ea829 Mon Sep 17 00:00:00 2001 From: MARiA so cute <33935209+NathanFreeman@users.noreply.github.com> Date: Thu, 12 Aug 2021 10:32:40 +0800 Subject: [PATCH 211/936] Enhancing the support for query of /etc/hosts and simplifying the code. (#4349) * enhance the query of /etc/hosts * change if statement position * comparison of integer expressions of different signedness * comparison of integer expressions of different signedness * unit test * repeat declare * hook.cpp * debug * cancel debug * unit test * unit test * unit test * remove nullptr * unit test * unit test * unit test * unit test * unit test * unit test * unit test * unit test * unit test * unit test * unit test change sstream to fstream * unit test * remove ofstream::out * change string to char * test * test * add rename exception * add rename * unit test * unit test * unit test * add ON_SCOPE_EXIT * add ; * optimize unit test * optimize unit test * optimize unit test * optimize unit test * optimize unit test * optimize unit test * optimize unit test * optimize unit test * optimize unit test * optimize unit test * clang format * optimize get_ip_by_hosts * add domains.clear() * add swoole_set_hosts_path api and optimize code. * add swoole_set_hosts_path api and optimize code. * clang-format --- core-tests/include/test_core.h | 2 + core-tests/src/network/dns.cpp | 36 ++++++- include/swoole_coroutine_socket.h | 4 +- src/network/dns.cc | 171 +++++++----------------------- 4 files changed, 76 insertions(+), 137 deletions(-) diff --git a/core-tests/include/test_core.h b/core-tests/include/test_core.h index 2c64130ae0b..c56deb9ee55 100644 --- a/core-tests/include/test_core.h +++ b/core-tests/include/test_core.h @@ -14,6 +14,8 @@ #include #include #include +#include + #define TEST_HOST "127.0.0.1" #define TEST_PORT 9501 diff --git a/core-tests/src/network/dns.cpp b/core-tests/src/network/dns.cpp index 91f13491481..5a68dc52bba 100644 --- a/core-tests/src/network/dns.cpp +++ b/core-tests/src/network/dns.cpp @@ -21,6 +21,8 @@ #include "swoole_socket.h" +#include "swoole_util.h" + using namespace swoole; using swoole::coroutine::Socket; using swoole::coroutine::System; @@ -61,7 +63,7 @@ TEST(dns, cancel) { // swoole_set_log_level(SW_LOG_TRACE); test::coroutine::run([](void *arg) { auto co = Coroutine::get_current_safe(); - Coroutine::create([co](void *){ + Coroutine::create([co](void *) { System::sleep(0.002); co->cancel(); }); @@ -99,9 +101,41 @@ TEST(dns, load_resolv_conf) { } TEST(dns, gethosts) { + char hosts_file[] = "/tmp/swoole_hosts"; + ofstream file(hosts_file); + if (!file.is_open()) { + std::cout << std::string("file open failed: ") + std::string(strerror(errno)) << std::endl; + throw strerror(errno); + } + + ON_SCOPE_EXIT { + unlink(hosts_file); + }; + + file << "\n"; + file << "127.0.0.1\n"; + file << "127.0.0.1 localhost\n"; + file << "# 127.0.0.1 aaa.com\n"; + file << " 127.0.0.1 bbb.com ccc.com #ddd.com\n"; + file.close(); + + swoole::coroutine::swoole_set_hosts_path(hosts_file); + std::string ip = swoole::coroutine::get_ip_by_hosts("localhost"); ASSERT_EQ(ip, "127.0.0.1"); + ip = swoole::coroutine::get_ip_by_hosts("aaa.com"); + ASSERT_EQ(ip, ""); + + ip = swoole::coroutine::get_ip_by_hosts("bbb.com"); + ASSERT_EQ(ip, "127.0.0.1"); + + ip = swoole::coroutine::get_ip_by_hosts("ccc.com"); + ASSERT_EQ(ip, "127.0.0.1"); + + ip = swoole::coroutine::get_ip_by_hosts("ddd.com"); + ASSERT_EQ(ip, ""); + ip = swoole::coroutine::get_ip_by_hosts("non.exist.com"); ASSERT_EQ(ip, ""); } diff --git a/include/swoole_coroutine_socket.h b/include/swoole_coroutine_socket.h index 5bca498e401..622d6d9f225 100644 --- a/include/swoole_coroutine_socket.h +++ b/include/swoole_coroutine_socket.h @@ -587,6 +587,7 @@ class ProtocolSwitch { bool ori_open_length_check; Protocol ori_protocol; Socket *socket_; + public: ProtocolSwitch(Socket *socket) { ori_open_eof_check = socket->open_eof_check; @@ -608,7 +609,8 @@ std::vector dns_lookup_impl_with_socket(const char *domain, int fam #ifdef SW_USE_CARES std::vector dns_lookup_impl_with_cares(const char *domain, int family, double timeout); #endif -std::string get_ip_by_hosts(std::string domain); +std::string get_ip_by_hosts(const std::string &domain); +void swoole_set_hosts_path(char *hosts_file); //------------------------------------------------------------------------------- } // namespace coroutine } // namespace swoole diff --git a/src/network/dns.cc b/src/network/dns.cc index 77bb86a582b..d54121b37ab 100644 --- a/src/network/dns.cc +++ b/src/network/dns.cc @@ -21,6 +21,9 @@ #include #include #include +#include +#include +#include #define SW_PATH_HOSTS "/etc/hosts" @@ -101,165 +104,63 @@ struct RR_FLAGS { }; static uint16_t dns_request_id = 1; +char *swoole_hosts = nullptr; static int domain_encode(const char *src, int n, char *dest); static void domain_decode(char *str); static std::string parse_ip_address(void *vaddr, int type); -static int read_line(FILE *fp, char **buf, size_t *bufsize) { - char *newbuf; - size_t offset = 0; - size_t len; - - if (*buf == nullptr) { - *buf = (char *) malloc(128); - if (!*buf) { - return SW_ERR; - } - *bufsize = 128; - } - - for (;;) { - int bytestoread = *bufsize - offset; - if (!fgets(*buf + offset, bytestoread, fp)) { - return SW_ERR; - } - - len = offset + strlen(*buf + offset); - if ((*buf)[len - 1] == '\n') { - (*buf)[len - 1] = 0; - break; - } - offset = len; - if (len < *bufsize - 1) { - continue; - } - newbuf = (char *) realloc(*buf, *bufsize * 2); - if (!newbuf) { - free(*buf); - *buf = nullptr; - return SW_ERR; - } - *buf = newbuf; - *bufsize *= 2; +std::string get_ip_by_hosts(const std::string &search_domain) { + std::ifstream file(swoole_hosts ? swoole_hosts : SW_PATH_HOSTS); + if (!file.is_open()) { + return ""; } - return SW_OK; -} - -static std::pair get_hostent(FILE *fp) { - char *line = nullptr, *p, *q; - char *txtaddr, *txthost, *txtalias; - int status; - size_t linesize, naliases; - - std::pair result{}; - - while ((status = read_line(fp, &line, &linesize)) == SW_OK) { - p = line; - while (*p && (*p != '#')) { - p++; - } - *p = '\0'; + std::string line; + std::string domain; + std::string txtaddr; + std::vector domains; + std::unordered_map result{}; - q = p - 1; - while ((q >= line) && isspace(*q)) { - q--; + while (getline(file, line)) { + std::string::size_type ops = line.find_first_of('#'); + if (ops != std::string::npos) { + line[ops] = '\0'; } - *++q = '\0'; - p = line; - while (*p && isspace(*q)) { - q--; - } - if (!*p) { - continue; - } - - txtaddr = p; - - while (*p && !isspace(*p)) { - p++; - } - if (!*p) { + if (line[0] == '\n' || line[0] == '\0' || line[0] == '\r') { continue; } - *p = '\0'; - - p++; - while (*p && isspace(*p)) { - p++; + std::istringstream stream(line); + while (stream >> domain) { + domains.push_back(domain); } - if (!*p) { + if (domains.empty() || domains.size() == 1) { + domains.clear(); continue; } - txthost = p; - - while (*p && !isspace(*p)) { - p++; + txtaddr = domains[0]; + for (size_t i = 1; i < domains.size(); i++) { + result.insert(std::make_pair(domains[i], txtaddr)); } - txtalias = nullptr; - if (*p) { - q = p + 1; - while (*q && isspace(*q)) { - q++; - } - if (*q) { - txtalias = q; - } - } - - *p = '\0'; - - naliases = 0; - if (txtalias) { - p = txtalias; - while (*p) { - while (*p && !isspace(*p)) { - p++; - } - while (*p && isspace(*p)) { - p++; - } - naliases++; - } + auto iter = result.find(search_domain); + if (iter != result.end()) { + return iter->second; + } else { + result.clear(); + domains.clear(); + continue; } - - result.first = txthost; - result.second = txtaddr; - - free(line); - - return result; } - if (line) free(line); - - return result; + return ""; } -std::string get_ip_by_hosts(std::string domain) { - std::unordered_map _map; - auto fp = fopen(SW_PATH_HOSTS, "r"); - if (fp == nullptr) { - return ""; - } - ON_SCOPE_EXIT { - fclose(fp); - }; - while (1) { - auto result = get_hostent(fp); - if (result.first == "") { - break; - } - if (result.first == domain) { - return result.second; - } - } - return ""; +void swoole_set_hosts_path(char *hosts_file) { + swoole_hosts = hosts_file; } static std::string parse_ip_address(void *vaddr, int type) { From dee0c6eb2f24e7e3bd809dc9d517039fd327d1ac Mon Sep 17 00:00:00 2001 From: matyhtf Date: Fri, 13 Aug 2021 15:44:25 +0800 Subject: [PATCH 212/936] Optimize code style --- core-tests/src/network/dns.cpp | 2 +- include/swoole.h | 2 ++ include/swoole_coroutine_socket.h | 1 - src/network/dns.cc | 15 +++++++-------- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/core-tests/src/network/dns.cpp b/core-tests/src/network/dns.cpp index 5a68dc52bba..664d3c799e8 100644 --- a/core-tests/src/network/dns.cpp +++ b/core-tests/src/network/dns.cpp @@ -119,7 +119,7 @@ TEST(dns, gethosts) { file << " 127.0.0.1 bbb.com ccc.com #ddd.com\n"; file.close(); - swoole::coroutine::swoole_set_hosts_path(hosts_file); + swoole_set_hosts_path(hosts_file); std::string ip = swoole::coroutine::get_ip_by_hosts("localhost"); ASSERT_EQ(ip, "127.0.0.1"); diff --git a/include/swoole.h b/include/swoole.h index 8613c45cc3b..ae268af03e4 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -655,6 +655,7 @@ struct Global { double dns_cache_refresh_time; int dns_tries; std::string dns_resolvconf_path; + std::string dns_hosts_path; //-----------------------[AIO]-------------------------- uint32_t aio_core_worker_num; uint32_t aio_worker_num; @@ -702,6 +703,7 @@ SW_API void swoole_throw_error(int code); SW_API void swoole_set_log_level(int level); SW_API void swoole_set_trace_flags(int flags); SW_API void swoole_set_dns_server(const std::string server); +SW_API void swoole_set_hosts_path(char *hosts_file); SW_API std::pair swoole_get_dns_server(); SW_API bool swoole_load_resolv_conf(); diff --git a/include/swoole_coroutine_socket.h b/include/swoole_coroutine_socket.h index 622d6d9f225..95b540686e7 100644 --- a/include/swoole_coroutine_socket.h +++ b/include/swoole_coroutine_socket.h @@ -610,7 +610,6 @@ std::vector dns_lookup_impl_with_socket(const char *domain, int fam std::vector dns_lookup_impl_with_cares(const char *domain, int family, double timeout); #endif std::string get_ip_by_hosts(const std::string &domain); -void swoole_set_hosts_path(char *hosts_file); //------------------------------------------------------------------------------- } // namespace coroutine } // namespace swoole diff --git a/src/network/dns.cc b/src/network/dns.cc index d54121b37ab..41be744911c 100644 --- a/src/network/dns.cc +++ b/src/network/dns.cc @@ -57,16 +57,20 @@ bool swoole_load_resolv_conf() { return true; } +void swoole_set_hosts_path(const char *hosts_file) { + SwooleG.dns_hosts_path = hosts_file; +} + namespace swoole { namespace coroutine { -enum swDNS_type { +enum RecordType { SW_DNS_A_RECORD = 0x01, // Lookup IPv4 address SW_DNS_AAAA_RECORD = 0x1c, // Lookup IPv6 address SW_DNS_MX_RECORD = 0x0f // Lookup mail server for domain }; -enum swDNS_error { +enum DNSError { SW_DNS_NOT_EXIST, // Error: address does not exist SW_DNS_TIMEOUT, // Lookup time expired SW_DNS_ERROR // No memory or other error @@ -104,14 +108,13 @@ struct RR_FLAGS { }; static uint16_t dns_request_id = 1; -char *swoole_hosts = nullptr; static int domain_encode(const char *src, int n, char *dest); static void domain_decode(char *str); static std::string parse_ip_address(void *vaddr, int type); std::string get_ip_by_hosts(const std::string &search_domain) { - std::ifstream file(swoole_hosts ? swoole_hosts : SW_PATH_HOSTS); + std::ifstream file(SwooleG.dns_hosts_path.empty() ? SW_PATH_HOSTS : SwooleG.dns_hosts_path); if (!file.is_open()) { return ""; } @@ -159,10 +162,6 @@ std::string get_ip_by_hosts(const std::string &search_domain) { return ""; } -void swoole_set_hosts_path(char *hosts_file) { - swoole_hosts = hosts_file; -} - static std::string parse_ip_address(void *vaddr, int type) { auto addr = reinterpret_cast(vaddr); std::string ip_addr; From 72c38ccd307e07fc97a62ebc297867f9bb03eb0b Mon Sep 17 00:00:00 2001 From: Bruce Dou Date: Fri, 13 Aug 2021 09:10:45 +0100 Subject: [PATCH 213/936] Support a new concurrency mode (#4330) --- ext-src/php_swoole.cc | 3 + ext-src/swoole_coroutine.cc | 25 ++++++++ include/swoole.h | 1 + include/swoole_process_pool.h | 1 + src/core/base.cc | 1 + tests/swoole_server/max_concurrency.phpt | 74 ++++++++++++++++++++++++ 6 files changed, 105 insertions(+) create mode 100644 tests/swoole_server/max_concurrency.phpt diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index a64f6d93ce4..9adabcacf72 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -385,6 +385,9 @@ void php_swoole_set_global_option(HashTable *vht) { if (php_swoole_array_get_value(vht, "socket_timeout", ztmp)) { Socket::default_read_timeout = Socket::default_write_timeout = timeout_format(ztmp); } + if (php_swoole_array_get_value(vht, "max_concurrency", ztmp)) { + SwooleG.max_concurrency = (uint32_t) SW_MAX(0, zval_get_long(ztmp)); + } } void php_swoole_register_rshutdown_callback(swoole::Callback cb, void *private_data) { diff --git a/ext-src/swoole_coroutine.cc b/ext-src/swoole_coroutine.cc index c9a4f174a18..5721d4465a3 100644 --- a/ext-src/swoole_coroutine.cc +++ b/ext-src/swoole_coroutine.cc @@ -631,6 +631,10 @@ void PHPCoroutine::on_close(void *arg) { efree(task->array_walk_fci); } #endif + + if(SwooleG.max_concurrency > 0 && task->pcid == -1) { + SwooleWG.worker_concurrency--; + } vm_stack_destroy(); restore_task(origin_task); @@ -738,6 +742,27 @@ void PHPCoroutine::main_func(void *arg) { (uintmax_t) Coroutine::count(), (uintmax_t) zend_memory_usage(0)); + if(SwooleG.max_concurrency > 0 && task->pcid == -1) { + // wait until concurrency slots are available + while(SwooleWG.worker_concurrency > SwooleG.max_concurrency - 1) { + + swTraceLog(SW_TRACE_COROUTINE, + "php_coro cid=%ld waiting for concurrency slots: max: %d, used: %d", + task->co->get_cid(), + SwooleG.max_concurrency, + SwooleWG.worker_concurrency); + + swoole_event_defer([](void *data) { + Coroutine *co = (Coroutine *) data; + co->resume(); + }, + (void *) task->co); + task->co->yield(); + } + + SwooleWG.worker_concurrency++; + } + if (SwooleG.hooks[SW_GLOBAL_HOOK_ON_CORO_START]) { swoole_call_hook(SW_GLOBAL_HOOK_ON_CORO_START, task); } diff --git a/include/swoole.h b/include/swoole.h index ae268af03e4..990f05a3977 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -645,6 +645,7 @@ struct Global { uint32_t pagesize; struct utsname uname; uint32_t max_sockets; + uint32_t max_concurrency; //-----------------------[Memory]-------------------------- MemoryPool *memory_pool; Allocator std_allocator; diff --git a/include/swoole_process_pool.h b/include/swoole_process_pool.h index 26ba7aaaf85..be89c2d2346 100644 --- a/include/swoole_process_pool.h +++ b/include/swoole_process_pool.h @@ -93,6 +93,7 @@ struct WorkerGlobal { String **output_buffer; Worker *worker; time_t exit_time; + uint32_t worker_concurrency = 0; }; struct Worker { diff --git a/src/core/base.cc b/src/core/base.cc index d7dc9b3bfcf..df76968b83f 100644 --- a/src/core/base.cc +++ b/src/core/base.cc @@ -148,6 +148,7 @@ void swoole_init(void) { // init global shared memory SwooleG.memory_pool = new swoole::GlobalMemory(SW_GLOBAL_MEMORY_PAGESIZE, true); SwooleG.max_sockets = SW_MAX_SOCKETS_DEFAULT; + SwooleG.max_concurrency = 0; struct rlimit rlmt; if (getrlimit(RLIMIT_NOFILE, &rlmt) < 0) { swoole_sys_warning("getrlimit() failed"); diff --git a/tests/swoole_server/max_concurrency.phpt b/tests/swoole_server/max_concurrency.phpt new file mode 100644 index 00000000000..77b57627f88 --- /dev/null +++ b/tests/swoole_server/max_concurrency.phpt @@ -0,0 +1,74 @@ +--TEST-- +swoole_server: max_concurrency +--SKIPIF-- + +--FILE-- +parentFunc = function ($pid) use ($pm) { + for ($i=0; $i < 5; $i++) { + go(function () use ($pm, $i) { + $client = new Client(SWOOLE_SOCK_TCP); + $client->set([ + "open_eof_check" => true, + "open_eof_split" => true, + "package_eof" => "\r\n\r\n", + ]); + $r = $client->connect('127.0.0.1', $pm->getFreePort(), -1); + $data = "$i\r\n\r\n"; + $client->send($data); + $ret = $client->recv(); + var_dump(trim($ret)); + $client->close(); + }); + } + + Event::wait(); + + swoole_process::kill($pid); +}; + +$pm->childFunc = function () use ($pm) +{ + Co::set(['max_concurrency' => 1]); + $serv = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_PROCESS); + $serv->set([ + 'worker_num' => 1, + 'dispatch_mode' => 1, + 'open_eof_split' => true, + 'package_eof' => "\r\n\r\n", + 'log_file' => '/dev/null', + ]); + $serv->on("WorkerStart", function (Server $serv) use ($pm) + { + $pm->wakeup(); + }); + $serv->on("Receive", function (Server $serv, $fd, $reactorId, $data) + { + global $count; + $count = 0; + co::sleep(0.05); + $count += 1; + $serv->send($fd, "$count\r\n\r\n"); + }); + $serv->start(); +}; + +$pm->childFirst(); +$pm->run(); + +?> +--EXPECT-- +string(1) "1" +string(1) "1" +string(1) "1" +string(1) "1" +string(1) "1" \ No newline at end of file From 417e395ed2fd6fc070ee84a2ce7b7ac0234f2e08 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Fri, 13 Aug 2021 17:29:57 +0800 Subject: [PATCH 214/936] Update library --- ext-src/php_swoole_library.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index de28f50b76b..ae8d929e656 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: 05b8161677541803bf1644f9a57057863c67937b */ +/* $Id: 1b421d51331d70d14a1b971c1a20c31c14b523d7 */ static const char* swoole_library_source_constants = "\n" @@ -3014,7 +3014,7 @@ static const char* swoole_library_source_core_database_pdo_statement_proxy = " return $this->__object->setFetchMode(...$this->setFetchModeContext);\n" " }\n" "\n" - " public function bindParam($parameter, &$variable, $data_type = PDO::PARAM_STR, $length = null, $driver_options = null): bool\n" + " public function bindParam($parameter, &$variable, $data_type = PDO::PARAM_STR, $length = 0, $driver_options = null): bool\n" " {\n" " $this->bindParamContext[$parameter] = [$variable, $data_type, $length, $driver_options];\n" " return $this->__object->bindParam($parameter, $variable, $data_type, $length, $driver_options);\n" @@ -3564,6 +3564,8 @@ static const char* swoole_library_source_core_curl_handler = " /** @var callable */\n" " private $writeFunction;\n" "\n" + " private $noProgress = true;\n" + "\n" " /** @var callable */\n" " private $progressFunction;\n" "\n" @@ -4072,6 +4074,9 @@ static const char* swoole_library_source_core_curl_handler = " case CURLOPT_WRITEFUNCTION:\n" " $this->writeFunction = $value;\n" " break;\n" + " case CURLOPT_NOPROGRESS:\n" + " $this->noProgress = $value;\n" + " break;\n" " case CURLOPT_PROGRESSFUNCTION:\n" " $this->progressFunction = $value;\n" " break;\n" From b5c647c9a6183e958782b204795ad1057b27b263 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Fri, 13 Aug 2021 17:34:58 +0800 Subject: [PATCH 215/936] Fix compilation errors, format code --- ext-src/php_swoole.cc | 2 +- ext-src/swoole_coroutine.cc | 59 ++++++++++++++++++------------------- 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index 9adabcacf72..854d4f23de2 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -54,8 +54,8 @@ END_EXTERN_C() #include #endif -using swoole::network::Socket; using swoole::Server; +using swoole::network::Socket; ZEND_DECLARE_MODULE_GLOBALS(swoole) diff --git a/ext-src/swoole_coroutine.cc b/ext-src/swoole_coroutine.cc index 5721d4465a3..2d859f77db0 100644 --- a/ext-src/swoole_coroutine.cc +++ b/ext-src/swoole_coroutine.cc @@ -597,9 +597,9 @@ void PHPCoroutine::on_resume(void *arg) { restore_task(task); record_last_msec(task); swoole_trace_log(SW_TRACE_COROUTINE, - "php_coro_resume from cid=%ld to cid=%ld", - Coroutine::get_current_cid(), - task->co->get_cid()); + "php_coro_resume from cid=%ld to cid=%ld", + Coroutine::get_current_cid(), + task->co->get_cid()); } void PHPCoroutine::on_close(void *arg) { @@ -632,19 +632,19 @@ void PHPCoroutine::on_close(void *arg) { } #endif - if(SwooleG.max_concurrency > 0 && task->pcid == -1) { + if (SwooleG.max_concurrency > 0 && task->pcid == -1) { SwooleWG.worker_concurrency--; } vm_stack_destroy(); restore_task(origin_task); swoole_trace_log(SW_TRACE_COROUTINE, - "coro close cid=%ld and resume to %ld, %zu remained. usage size: %zu. malloc size: %zu", - cid, - origin_cid, - (uintmax_t) Coroutine::count() - 1, - (uintmax_t) zend_memory_usage(0), - (uintmax_t) zend_memory_usage(1)); + "coro close cid=%ld and resume to %ld, %zu remained. usage size: %zu. malloc size: %zu", + cid, + origin_cid, + (uintmax_t) Coroutine::count() - 1, + (uintmax_t) zend_memory_usage(0), + (uintmax_t) zend_memory_usage(1)); } void PHPCoroutine::main_func(void *arg) { @@ -736,30 +736,29 @@ void PHPCoroutine::main_func(void *arg) { record_last_msec(task); swoole_trace_log(SW_TRACE_COROUTINE, - "Create coro id: %ld, origin cid: %ld, coro total count: %zu, heap size: %zu", - task->co->get_cid(), - task->co->get_origin_cid(), - (uintmax_t) Coroutine::count(), - (uintmax_t) zend_memory_usage(0)); + "Create coro id: %ld, origin cid: %ld, coro total count: %zu, heap size: %zu", + task->co->get_cid(), + task->co->get_origin_cid(), + (uintmax_t) Coroutine::count(), + (uintmax_t) zend_memory_usage(0)); - if(SwooleG.max_concurrency > 0 && task->pcid == -1) { + if (SwooleG.max_concurrency > 0 && task->pcid == -1) { // wait until concurrency slots are available - while(SwooleWG.worker_concurrency > SwooleG.max_concurrency - 1) { - - swTraceLog(SW_TRACE_COROUTINE, - "php_coro cid=%ld waiting for concurrency slots: max: %d, used: %d", - task->co->get_cid(), - SwooleG.max_concurrency, - SwooleWG.worker_concurrency); - - swoole_event_defer([](void *data) { - Coroutine *co = (Coroutine *) data; - co->resume(); - }, - (void *) task->co); + while (SwooleWG.worker_concurrency > SwooleG.max_concurrency - 1) { + swoole_trace_log(SW_TRACE_COROUTINE, + "php_coro cid=%ld waiting for concurrency slots: max: %d, used: %d", + task->co->get_cid(), + SwooleG.max_concurrency, + SwooleWG.worker_concurrency); + + swoole_event_defer( + [](void *data) { + Coroutine *co = (Coroutine *) data; + co->resume(); + }, + (void *) task->co); task->co->yield(); } - SwooleWG.worker_concurrency++; } From 27fee7f248fa6cda0a6c76f7687619704514bcee Mon Sep 17 00:00:00 2001 From: matyhtf Date: Fri, 13 Aug 2021 17:35:20 +0800 Subject: [PATCH 216/936] Added SW_GLOBAL_HOOK_BEFORE_SERVER_CREATE hook type --- include/swoole_c_api.h | 2 ++ src/server/master.cc | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/include/swoole_c_api.h b/include/swoole_c_api.h index 03f348a0a0f..88edd144ce8 100644 --- a/include/swoole_c_api.h +++ b/include/swoole_c_api.h @@ -35,6 +35,8 @@ enum swGlobalHookType { SW_GLOBAL_HOOK_AFTER_SERVER_SHUTDOWN, SW_GLOBAL_HOOK_BEFORE_WORKER_STOP, SW_GLOBAL_HOOK_ON_REACTOR_DESTROY, + SW_GLOBAL_HOOK_BEFORE_SERVER_CREATE, + SW_GLOBAL_HOOK_AFTER_SERVER_CREATE, SW_GLOBAL_HOOK_END = SW_MAX_HOOK_TYPE - 1, }; diff --git a/src/server/master.cc b/src/server/master.cc index cd3ad48eec7..dcc802523f4 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -668,6 +668,10 @@ int Server::create() { return SW_ERR; } + if (swoole_isset_hook(SW_GLOBAL_HOOK_BEFORE_SERVER_CREATE)) { + swoole_call_hook(SW_GLOBAL_HOOK_BEFORE_SERVER_CREATE, this); + } + session_list = (Session *) sw_shm_calloc(SW_SESSION_LIST_SIZE, sizeof(Session)); if (session_list == nullptr) { swoole_error("sw_shm_calloc(%ld) for session_list failed", SW_SESSION_LIST_SIZE * sizeof(Session)); @@ -734,13 +738,20 @@ int Server::create() { return SW_ERR; } + int retval; if (is_base_mode()) { factory = new BaseFactory(this); - return create_reactor_processes(); + retval = create_reactor_processes(); } else { factory = new ProcessFactory(this); - return create_reactor_threads(); + retval = create_reactor_threads(); } + + if (swoole_isset_hook(SW_GLOBAL_HOOK_AFTER_SERVER_CREATE)) { + swoole_call_hook(SW_GLOBAL_HOOK_AFTER_SERVER_CREATE, this); + } + + return retval; } void Server::clear_timer() { From a2ef8c00d6648610874fb64357e14aad8402b2a9 Mon Sep 17 00:00:00 2001 From: codinghuang Date: Sat, 14 Aug 2021 11:14:00 +0800 Subject: [PATCH 217/936] Update version for Swoole 4.7.1 (#4372) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update version for Swoole 4.7.1 * Optimize code * Update package.xml * Added introducing a new concurrency mode (#4330) Co-authored-by: matyhtf Co-authored-by: 沈唁 <52o@qq52o.cn> Co-authored-by: Bruce Dou --- CMakeLists.txt | 2 +- include/swoole.h | 4 +- include/swoole_version.h | 4 +- package.xml | 54 ++++++++------------ src/core/base.cc | 2 +- src/network/dns.cc | 2 +- tests/swoole_runtime/file_hook/bug_4327.phpt | 3 +- 7 files changed, 29 insertions(+), 42 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 641bbde5931..fe297de7b54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ PROJECT(libswoole) ENABLE_LANGUAGE(ASM) -set(SWOOLE_VERSION 4.7.1-dev) +set(SWOOLE_VERSION 4.7.1) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g") diff --git a/include/swoole.h b/include/swoole.h index 990f05a3977..6099cedafab 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -703,8 +703,8 @@ SW_API const char *swoole_strerror(int code); SW_API void swoole_throw_error(int code); SW_API void swoole_set_log_level(int level); SW_API void swoole_set_trace_flags(int flags); -SW_API void swoole_set_dns_server(const std::string server); -SW_API void swoole_set_hosts_path(char *hosts_file); +SW_API void swoole_set_dns_server(const std::string &server); +SW_API void swoole_set_hosts_path(const std::string &hosts_file); SW_API std::pair swoole_get_dns_server(); SW_API bool swoole_load_resolv_conf(); diff --git a/include/swoole_version.h b/include/swoole_version.h index ad7af8bdd52..a85f8623209 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -21,8 +21,8 @@ #define SWOOLE_MAJOR_VERSION 4 #define SWOOLE_MINOR_VERSION 7 #define SWOOLE_RELEASE_VERSION 1 -#define SWOOLE_EXTRA_VERSION "dev" -#define SWOOLE_VERSION "4.7.1-dev" +#define SWOOLE_EXTRA_VERSION "" +#define SWOOLE_VERSION "4.7.1" #define SWOOLE_VERSION_ID 40701 #define SWOOLE_API_VERSION_ID 0x202108a diff --git a/package.xml b/package.xml index 1268fae4839..6e0ca10c16a 100644 --- a/package.xml +++ b/package.xml @@ -48,10 +48,10 @@ lufei@php.net yes - 2021-07-16 - + 2021-08-13 + - 4.7.0 + 4.7.1 4.0 @@ -60,42 +60,24 @@ Apache2.0 - New APIs + New feature --- - * Added Process\Pool::detach() (#4221) (@matyhtf) - * Added onDisconnect callback for Swoole\Server (#4230) (@matyhtf) - * Added Coroutine::cancel() (#4247) (#4249) (@matyhtf) - * Added http_compression/body_decompression options for Http Client (#4299) (@matyhtf) + * Introduce a new concurrency mode (#4330) (@doubaokun) Enhancement --- - * Supported mysql client prepare field type identification (#4238) (@Yurunsoft) - * Supported c-ares, Refactor DNS (#4275) (@matyhtf) - * Supported setting different idle time for each port (#4290) (@matyhtf) - * Supported SW_DISPATCH_CO_CONN_LB and SW_DISPATCH_CO_REQ_LB for Swoole\Server dispatch_mode (#4318) (@matyhtf) - * Supported timeout for Swoole\ConnectionPool::get (swoole/library#108) (@leocavalcante) - * Supported CURLOPT_PRIVATE for Hook Curl (swoole/library#112) (@sy-records) - * Optimized PDOStatementProxy::setFetchMode function prototype (swoole/library#109) (@yespire) + * Supported query /etc/hosts for System::dnsLookup (#4341) (#4349) (@zmyWL) (@NathanFreeman) + * Supported boost context suppoprt for mips64 support (#4358) (@dixyes) + * Supported CURLOPT_RESOLVE option for SWOOLE_HOOK_CURL (swoole/library#107) (@sy-records) + * Support CURLOPT_NOPROGRESS for SWOOLE_HOOK_CURL (swoole/library#117) (@sy-records) Fixed --- - * Fixed uncaught thread creation exception when creating a large number of coroutines (swoole/swoole-src@8ce5041) (@matyhtf) - * Fixed the "make install" missing php_swoole.h header file (#4239) (@sy-records) - * Fixed EVENT_HANDSHAKE BC (#4248) (@sy-records) - * Fixed SW_LOCK_CHECK_RETURN (#4302) (@zmyWL) - * Fixed problems with Swoole\Atomic\Long M1 chip (swoole/swoole-src@e6fae2e) (@matyhtf) - * Fixed missing return value of Coroutine\go (swoole/library@1ed49db) (@matyhtf) - * Fixed StringObject consistency between other methods and its immutability (swoole/library#111) (@leocavalcante) - * Fixed StringObject substr error (swoole/library#113) (@sy-records) - - Kernel - --- - * Did not hook disabled functions (#4283) (@twose) - - Test - --- - * Added Cygwin build (#4222) (@sy-records) - * Added alpine 3.13 and 3.14 into building test (#4309) (@limingxinleo) + * Fixed memory error on shutdown (PHP-8.1) (#4325) (@twose) + * Fixed not serializable classes for 8.1.0beta1 (#4335) (@remicollet) + * Fixed multiple coroutines recursively creating directories (#4337) (@NathanFreeman) + * Fixed native curl bugs (#4360) (@matyhtf) + * Fixed PDOStatement::bindParam() expects parameter 1 to be string (swoole/library#116) (@sy-records) @@ -482,12 +464,12 @@ - + @@ -969,6 +951,7 @@ + @@ -1151,6 +1134,7 @@ + @@ -1228,6 +1212,7 @@ + @@ -1594,6 +1579,7 @@ + @@ -2006,6 +1992,7 @@ + @@ -2031,6 +2018,7 @@ + diff --git a/src/core/base.cc b/src/core/base.cc index df76968b83f..d9f9decb2a4 100644 --- a/src/core/base.cc +++ b/src/core/base.cc @@ -251,7 +251,7 @@ SW_API void swoole_set_trace_flags(int flags) { SwooleG.trace_flags = flags; } -SW_API void swoole_set_dns_server(const std::string server) { +SW_API void swoole_set_dns_server(const std::string &server) { char *_port; int dns_server_port = SW_DNS_SERVER_PORT; char dns_server_host[32]; diff --git a/src/network/dns.cc b/src/network/dns.cc index 41be744911c..3678c9c36ee 100644 --- a/src/network/dns.cc +++ b/src/network/dns.cc @@ -57,7 +57,7 @@ bool swoole_load_resolv_conf() { return true; } -void swoole_set_hosts_path(const char *hosts_file) { +void swoole_set_hosts_path(const std::string &hosts_file) { SwooleG.dns_hosts_path = hosts_file; } diff --git a/tests/swoole_runtime/file_hook/bug_4327.phpt b/tests/swoole_runtime/file_hook/bug_4327.phpt index 7b4311f197e..d776fad8703 100644 --- a/tests/swoole_runtime/file_hook/bug_4327.phpt +++ b/tests/swoole_runtime/file_hook/bug_4327.phpt @@ -1,5 +1,5 @@ --TEST-- -mkdir failed when coroutines: bug #4372 +swoole_runtime/file_hook: bug #4372 --SKIPIF-- - --EXPECT-- SUCCESS SUCCESS From 71502c2d200b801a7f1813cc4804fb67e90c4c9a Mon Sep 17 00:00:00 2001 From: Yun Dou Date: Mon, 16 Aug 2021 11:43:46 +0800 Subject: [PATCH 218/936] boost context suppoprt for riscv64 (#4375) * Add riscv64 boost context asm sources * Add riscv64 config.m4 support * Backport boost context asm for riscv64 --- config.m4 | 7 + .../boost/asm/jump_riscv64_sysv_elf_gas.S | 153 ++++++++++++++++++ .../boost/asm/make_riscv64_sysv_elf_gas.S | 91 +++++++++++ 3 files changed, 251 insertions(+) create mode 100644 thirdparty/boost/asm/jump_riscv64_sysv_elf_gas.S create mode 100644 thirdparty/boost/asm/make_riscv64_sysv_elf_gas.S diff --git a/config.m4 b/config.m4 index 90f72a3c344..9d97e8aa47a 100644 --- a/config.m4 +++ b/config.m4 @@ -676,6 +676,7 @@ if test "$PHP_SWOOLE" != "no"; then [arm64*], [SW_CPU="arm64"], [mips64*], [SW_CPU="mips64"], [mips*], [SW_CPU="mips32"], + [riscv64*], [SW_CPU="riscv64"], [ SW_USE_ASM_CONTEXT="no" ] @@ -731,6 +732,12 @@ if test "$PHP_SWOOLE" != "no"; then else SW_USE_ASM_CONTEXT="no" fi + elif test "$SW_CPU" = "riscv64"; then + if test "$SW_OS" = "LINUX"; then + SW_CONTEXT_ASM_FILE="riscv64_sysv_elf_gas.S" + else + SW_USE_ASM_CONTEXT="no" + fi else SW_USE_ASM_CONTEXT="no" fi diff --git a/thirdparty/boost/asm/jump_riscv64_sysv_elf_gas.S b/thirdparty/boost/asm/jump_riscv64_sysv_elf_gas.S new file mode 100644 index 00000000000..e134bae637e --- /dev/null +++ b/thirdparty/boost/asm/jump_riscv64_sysv_elf_gas.S @@ -0,0 +1,153 @@ +/* + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ +/******************************************************* + * * + * ------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * + * ------------------------------------------------- * + * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| * + * ------------------------------------------------- * + * | fs0 | fs1 | fs2 | fs3 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * + * ------------------------------------------------- * + * | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| * + * ------------------------------------------------- * + * | fs4 | fs5 | fs6 | fs7 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * + * ------------------------------------------------- * + * | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| * + * ------------------------------------------------- * + * | fs8 | fs9 | fs10 | fs11 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | * + * ------------------------------------------------- * + * | 0x60| 0x64| 0x68| 0x6c| 0x70| 0x74| 0x78| 0x7c| * + * ------------------------------------------------- * + * | s0 | s1 | s2 | s3 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | * + * ------------------------------------------------- * + * | 0x80| 0x84| 0x88| 0x8c| 0x90| 0x94| 0x98| 0x9c| * + * ------------------------------------------------- * + * | s4 | s5 | s6 | s7 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | * + * ------------------------------------------------- * + * | 0xa0| 0xa4| 0xa8| 0xac| 0xb0| 0xb4| 0xb8| 0xbc| * + * ------------------------------------------------- * + * | s8 | s9 | s10 | s11 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 48 | 49 | 50 | 51 | | | | | * + * ------------------------------------------------- * + * | 0xc0| 0xc4| 0xc8| 0xcc| | | | | * + * ------------------------------------------------- * + * | ra | pc | | | * + * ------------------------------------------------- * + * * + *******************************************************/ + +.file "jump_riscv64_sysv_elf_gas.S" +.text +.align 1 +.global jump_fcontext +.type jump_fcontext, %function +jump_fcontext: + # prepare stack for GP + FPU + addi sp, sp, -0xd0 + + beqz a3, .L1 + + # save fs0 - fs11 + fsd fs0, 0x00(sp) + fsd fs1, 0x08(sp) + fsd fs2, 0x10(sp) + fsd fs3, 0x18(sp) + fsd fs4, 0x20(sp) + fsd fs5, 0x28(sp) + fsd fs6, 0x30(sp) + fsd fs7, 0x38(sp) + fsd fs8, 0x40(sp) + fsd fs9, 0x48(sp) + fsd fs10, 0x50(sp) + fsd fs11, 0x58(sp) +.L1: + + # save s0-s11, ra + sd s0, 0x60(sp) + sd s1, 0x68(sp) + sd s2, 0x70(sp) + sd s3, 0x78(sp) + sd s4, 0x80(sp) + sd s5, 0x88(sp) + sd s6, 0x90(sp) + sd s7, 0x98(sp) + sd s8, 0xa0(sp) + sd s9, 0xa8(sp) + sd s10, 0xb0(sp) + sd s11, 0xb8(sp) + sd ra, 0xc0(sp) + + # save RA as PC + sd ra, 0xc8(sp) + + # store SP (pointing to context-data) in A0 + sd sp, (a0) + + # restore SP (pointing to context-data) from A1 + mv sp, a1 + + beqz a3, .L2 + # load fs0 - fs11 + fld fs0, 0x00(sp) + fld fs1, 0x08(sp) + fld fs2, 0x10(sp) + fld fs3, 0x18(sp) + fld fs4, 0x20(sp) + fld fs5, 0x28(sp) + fld fs6, 0x30(sp) + fld fs7, 0x38(sp) + fld fs8, 0x40(sp) + fld fs9, 0x48(sp) + fld fs10, 0x50(sp) + fld fs11, 0x58(sp) +.L2: + + # load s0-s11,ra + ld s0, 0x60(sp) + ld s1, 0x68(sp) + ld s2, 0x70(sp) + ld s3, 0x78(sp) + ld s4, 0x80(sp) + ld s5, 0x88(sp) + ld s6, 0x90(sp) + ld s7, 0x98(sp) + ld s8, 0xa0(sp) + ld s9, 0xa8(sp) + ld s10, 0xb0(sp) + ld s11, 0xb8(sp) + ld ra, 0xc0(sp) + + # use A2 as return value + mv a0, a2 + + # load pc + ld a2, 0xc8(sp) + + # restore stack from GP + FPU + addi sp, sp, 0xd0 + + jr a2 +.size jump_fcontext,.-jump_fcontext +# Mark that we don't need executable stack. +.section .note.GNU-stack,"",%progbits diff --git a/thirdparty/boost/asm/make_riscv64_sysv_elf_gas.S b/thirdparty/boost/asm/make_riscv64_sysv_elf_gas.S new file mode 100644 index 00000000000..5322e0fdbde --- /dev/null +++ b/thirdparty/boost/asm/make_riscv64_sysv_elf_gas.S @@ -0,0 +1,91 @@ +/* + Distributed under the Boost Software License, Version 1.0. + (See accompanying file LICENSE_1_0.txt or copy at + http://www.boost.org/LICENSE_1_0.txt) +*/ +/******************************************************* + * * + * ------------------------------------------------- * + * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | * + * ------------------------------------------------- * + * | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| * + * ------------------------------------------------- * + * | fs0 | fs1 | fs2 | fs3 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | * + * ------------------------------------------------- * + * | 0x20| 0x24| 0x28| 0x2c| 0x30| 0x34| 0x38| 0x3c| * + * ------------------------------------------------- * + * | fs4 | fs5 | fs6 | fs7 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | * + * ------------------------------------------------- * + * | 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58| 0x5c| * + * ------------------------------------------------- * + * | fs8 | fs9 | fs10 | fs11 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | * + * ------------------------------------------------- * + * | 0x60| 0x64| 0x68| 0x6c| 0x70| 0x74| 0x78| 0x7c| * + * ------------------------------------------------- * + * | s0 | s1 | s2 | s3 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | * + * ------------------------------------------------- * + * | 0x80| 0x84| 0x88| 0x8c| 0x90| 0x94| 0x98| 0x9c| * + * ------------------------------------------------- * + * | s4 | s5 | s6 | s7 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | * + * ------------------------------------------------- * + * | 0xa0| 0xa4| 0xa8| 0xac| 0xb0| 0xb4| 0xb8| 0xbc| * + * ------------------------------------------------- * + * | s8 | s9 | s10 | s11 | * + * ------------------------------------------------- * + * ------------------------------------------------- * + * | 48 | 49 | 50 | 51 | | | | | * + * ------------------------------------------------- * + * | 0xc0| 0xc4| 0xc8| 0xcc| | | | | * + * ------------------------------------------------- * + * | ra | pc | | | * + * ------------------------------------------------- * + * * + *******************************************************/ + +.file "make_riscv64_sysv_elf_gas.S" +.text +.align 1 +.global make_fcontext +.type make_fcontext, %function +make_fcontext: + # shift address in a0 (allocated stack) to lower 16 byte boundary + andi a0, a0, ~0xF + + # reserve space for context-data on context-stack + addi a0, a0, -0xd0 + + # third arg of make_fcontext() == address of context-function + # store address as a PC to jump in + sd a2, 0xc8(a0) + + # save address of finish as return-address for context-function + # will be entered after context-function returns (RA register) + lla a4, finish + sd a4, 0xc0(a0) + + ret // return pointer to context-data (a0) + +finish: + # exit code is zero + li a0, 0 + # exit application + tail _exit@plt + +.size make_fcontext,.-make_fcontext +# Mark that we don't need executable stack. +.section .note.GNU-stack,"",%progbits From 9f7e9d536a7a0a5498089d6afed4f1e2d19e8da5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Mon, 16 Aug 2021 13:30:44 +0800 Subject: [PATCH 219/936] Fix typo (#4376) * Fix typo * Update package.xml * Update package.xml --- package.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.xml b/package.xml index 6e0ca10c16a..a5138e4b7fb 100644 --- a/package.xml +++ b/package.xml @@ -67,9 +67,10 @@ Enhancement --- * Supported query /etc/hosts for System::dnsLookup (#4341) (#4349) (@zmyWL) (@NathanFreeman) - * Supported boost context suppoprt for mips64 support (#4358) (@dixyes) + * Supported boost context support for mips64 (#4358) (@dixyes) * Supported CURLOPT_RESOLVE option for SWOOLE_HOOK_CURL (swoole/library#107) (@sy-records) - * Support CURLOPT_NOPROGRESS for SWOOLE_HOOK_CURL (swoole/library#117) (@sy-records) + * Supported CURLOPT_NOPROGRESS for SWOOLE_HOOK_CURL (swoole/library#117) (@sy-records) + * Supported boost context support for riscv64 (#4375) (@dixyes) Fixed --- From 1a9a21541a2dbcd21e703bcf1bf7560e3786d145 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 17 Aug 2021 17:05:40 +0800 Subject: [PATCH 220/936] Fix coverity issue#1506497 --- src/os/signal.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/os/signal.cc b/src/os/signal.cc index 8c40f342f6f..0d736d64062 100644 --- a/src/os/signal.cc +++ b/src/os/signal.cc @@ -242,6 +242,7 @@ static bool swoole_signalfd_create() { signal_fd = signalfd(-1, &signalfd_mask, SFD_NONBLOCK | SFD_CLOEXEC); if (signal_fd < 0) { swoole_sys_warning("signalfd() failed"); + signal_fd = 0; return false; } signal_socket = swoole::make_socket(signal_fd, SW_FD_SIGNAL); @@ -250,6 +251,7 @@ static bool swoole_signalfd_create() { signal_socket->fd = -1; signal_socket->free(); close(signal_fd); + signal_socket = nullptr; signal_fd = 0; return false; } From 396edca9bd6bd63b9ff155e7147c3f70225a3e22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Wed, 18 Aug 2021 15:05:11 +0800 Subject: [PATCH 221/936] Rebuild php_swoole_library.h (#4377) --- ext-src/php_swoole_library.h | 4 +++- tests/swoole_server/max_concurrency.phpt | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index ae8d929e656..4772edd6449 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: 1b421d51331d70d14a1b971c1a20c31c14b523d7 */ +/* $Id: c996bdfe63d93ff643388f480678fec07483b2e8 */ static const char* swoole_library_source_constants = "\n" @@ -170,6 +170,8 @@ static const char* swoole_library_source_core_constant = "\n" " public const OPTION_SOCKET_TIMEOUT = 'socket_timeout';\n" "\n" + " public const OPTION_MAX_CONCURRENCY = 'max_concurrency';\n" + "\n" " public const OPTION_AIO_CORE_WORKER_NUM = 'aio_core_worker_num';\n" "\n" " public const OPTION_AIO_WORKER_NUM = 'aio_worker_num';\n" diff --git a/tests/swoole_server/max_concurrency.phpt b/tests/swoole_server/max_concurrency.phpt index 77b57627f88..2d073abfc6c 100644 --- a/tests/swoole_server/max_concurrency.phpt +++ b/tests/swoole_server/max_concurrency.phpt @@ -71,4 +71,4 @@ string(1) "1" string(1) "1" string(1) "1" string(1) "1" -string(1) "1" \ No newline at end of file +string(1) "1" From 7a9a5b17bb15f6fb99991be001435f71912effb4 Mon Sep 17 00:00:00 2001 From: zmyWL <86939621+zmyWL@users.noreply.github.com> Date: Wed, 18 Aug 2021 17:45:33 +0800 Subject: [PATCH 222/936] Optimize bug report message (#4368) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * update * update * update * Revert "update" This reverts commit cc2c58059cca46b37bfb811b3214155414f42c88. * update * update * Delete useless code * update * update * Update base.cc Co-authored-by: 韩天峰-Rango --- ext-src/php_swoole.cc | 10 ++++++++++ include/swoole.h | 3 +++ include/swoole_ssl.h | 2 ++ src/core/base.cc | 28 ++++++++++++++++++++++++++++ src/os/process_pool.cc | 2 +- src/protocol/ssl.cc | 9 +++++++++ src/server/manager.cc | 2 +- 7 files changed, 54 insertions(+), 2 deletions(-) diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index 854d4f23de2..79d3a7d4068 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -418,6 +418,13 @@ static void fatal_error(int code, const char *format, ...) { zend_end_try(); } +static void bug_report_message_init() { + SwooleG.bug_report_message += swoole::std_string::format( + "PHP_VERSION : %s\n", + PHP_VERSION + ); +} + /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(swoole) { @@ -745,6 +752,9 @@ PHP_MINIT_FUNCTION(swoole) { } swoole_init(); + + // init bug report message + bug_report_message_init(); if (strcmp("cli", sapi_module.name) == 0 || strcmp("phpdbg", sapi_module.name) == 0) { SWOOLE_G(cli) = 1; } diff --git a/include/swoole.h b/include/swoole.h index 6099cedafab..f9a68570125 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -666,6 +666,9 @@ struct Global { //-----------------------[Hook]-------------------------- void *hooks[SW_MAX_HOOK_TYPE]; std::function user_exit_condition; + + // bug report message + std::string bug_report_message = ""; }; std::string dirname(const std::string &file); diff --git a/include/swoole_ssl.h b/include/swoole_ssl.h index 0c440fb4c3c..c137bcc7e34 100644 --- a/include/swoole_ssl.h +++ b/include/swoole_ssl.h @@ -33,6 +33,7 @@ #include #include #include +#include #if OPENSSL_VERSION_NUMBER >= 0x10100000L #define SW_SUPPORT_DTLS @@ -169,5 +170,6 @@ void swoole_ssl_server_http_advise(swoole::SSLContext &); const char *swoole_ssl_get_error(); int swoole_ssl_get_ex_connection_index(); int swoole_ssl_get_ex_port_index(); +std::string swoole_ssl_get_version_message(); #endif diff --git a/src/core/base.cc b/src/core/base.cc index d9f9decb2a4..73df2f88b6d 100644 --- a/src/core/base.cc +++ b/src/core/base.cc @@ -41,6 +41,7 @@ #include "swoole_async.h" #include "swoole_c_api.h" #include "swoole_coroutine_c_api.h" +#include "swoole_ssl.h" using swoole::String; @@ -110,6 +111,30 @@ void *sw_realloc(void *ptr, size_t size) { return SwooleG.std_allocator.realloc(ptr, size); } +static void bug_report_message_init() { + SwooleG.bug_report_message += "\n" + std::string(SWOOLE_BUG_REPORT) + "\n"; + + struct utsname u; + if (uname(&u) != -1) { + SwooleG.bug_report_message += swoole::std_string::format( + "OS: %s %s %s %s\n", + u.sysname, + u.release, + u.version, + u.machine); + } + +#ifdef __VERSION__ + SwooleG.bug_report_message += swoole::std_string::format( + "GCC_VERSION: %s\n", + __VERSION__); +#endif + +#ifdef SW_USE_OPENSSL + SwooleG.bug_report_message += swoole_ssl_get_version_message(); + +#endif +} void swoole_init(void) { if (SwooleG.init) { return; @@ -169,6 +194,9 @@ void swoole_init(void) { SwooleG.use_signalfd = 1; SwooleG.enable_signalfd = 1; #endif + + // init bug report message + bug_report_message_init(); } SW_EXTERN_C_BEGIN diff --git a/src/os/process_pool.cc b/src/os/process_pool.cc index 10f649c3919..531a5a362a8 100644 --- a/src/os/process_pool.cc +++ b/src/os/process_pool.cc @@ -704,7 +704,7 @@ int ProcessPool::wait() { exit_worker->id, exit_status.get_code(), exit_status.get_signal(), - exit_status.get_signal() == SIGSEGV ? "\n" SWOOLE_BUG_REPORT : ""); + exit_status.get_signal() == SIGSEGV ? SwooleG.bug_report_message.c_str() : ""); } new_pid = spawn(exit_worker); if (new_pid < 0) { diff --git a/src/protocol/ssl.cc b/src/protocol/ssl.cc index b91ddc04011..0c132468952 100644 --- a/src/protocol/ssl.cc +++ b/src/protocol/ssl.cc @@ -18,6 +18,7 @@ #include "swoole_string.h" #include "swoole_socket.h" #include "swoole_ssl.h" +#include "swoole_util.h" #ifdef SW_USE_OPENSSL @@ -54,6 +55,14 @@ static int swoole_ssl_verify_cookie(SSL *ssl, const uchar *cookie, uint cookie_l #define MAYBE_UNUSED #endif +std::string swoole_ssl_get_version_message() { + std::string message = swoole::std_string::format( + "OPENSSL_VERSION: %s\n", + OPENSSL_VERSION_TEXT); + + return message; +} + static void MAYBE_UNUSED swoole_ssl_lock_callback(int mode, int type, const char *file, int line); void swoole_ssl_init(void) { diff --git a/src/server/manager.cc b/src/server/manager.cc index 642b36effff..759b478e861 100644 --- a/src/server/manager.cc +++ b/src/server/manager.cc @@ -209,7 +209,7 @@ void Server::check_worker_exit_status(int worker_id, const ExitStatus &exit_stat worker_id, exit_status.get_code(), exit_status.get_signal(), - exit_status.get_signal() == SIGSEGV ? "\n" SWOOLE_BUG_REPORT : ""); + exit_status.get_signal() == SIGSEGV ? SwooleG.bug_report_message.c_str() : ""); if (onWorkerError != nullptr) { onWorkerError(this, worker_id, exit_status); } From 75b7ffa9b2b947083ecd8e3c0a6782370fdefada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Wed, 18 Aug 2021 18:48:22 +0800 Subject: [PATCH 223/936] Fix memory invalid read/write (#4379) * Fix ipv6 address buffer overflow * Fix Socket::readVectorAll invalid write * Fix System::gethostbyname with c-ares invalid write. --- ext-src/swoole_async_coro.cc | 2 +- ext-src/swoole_socket_coro.cc | 54 +++++++++++++++++++---------------- src/network/dns.cc | 9 +++++- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/ext-src/swoole_async_coro.cc b/ext-src/swoole_async_coro.cc index 777fe5ff748..a1350c2e470 100644 --- a/ext-src/swoole_async_coro.cc +++ b/ext-src/swoole_async_coro.cc @@ -29,7 +29,7 @@ using swoole::Timer; using swoole::coroutine::Socket; struct DNSCacheEntity { - char address[16]; + char address[INET6_ADDRSTRLEN]; time_t update_time; }; diff --git a/ext-src/swoole_socket_coro.cc b/ext-src/swoole_socket_coro.cc index d5afe6a7cd5..dbbd7e03575 100644 --- a/ext-src/swoole_socket_coro.cc +++ b/ext-src/swoole_socket_coro.cc @@ -843,9 +843,12 @@ static void sw_inline php_swoole_init_socket(zval *zobject, SocketObject *sock) sock->socket->set_zero_copy(true); sock->socket->set_buffer_allocator(sw_zend_string_allocator()); zend_update_property_long(swoole_socket_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("fd"), sock->socket->get_fd()); - zend_update_property_long(swoole_socket_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("domain"), sock->socket->get_sock_domain()); - zend_update_property_long(swoole_socket_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("type"), sock->socket->get_sock_type()); - zend_update_property_long(swoole_socket_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("protocol"), sock->socket->get_sock_protocol()); + zend_update_property_long( + swoole_socket_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("domain"), sock->socket->get_sock_domain()); + zend_update_property_long( + swoole_socket_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("type"), sock->socket->get_sock_type()); + zend_update_property_long( + swoole_socket_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("protocol"), sock->socket->get_sock_protocol()); } SW_API bool php_swoole_export_socket(zval *zobject, Socket *_socket) { @@ -1479,26 +1482,27 @@ static void swoole_socket_coro_read_vector(INTERNAL_FUNCTION_PARAMETERS, const b std::unique_ptr iov(new iovec[iovcnt]); - SW_HASHTABLE_FOREACH_START(vht, zelement) - if (!ZVAL_IS_LONG(zelement)) { - zend_throw_exception_ex(swoole_socket_coro_exception_ce, - EINVAL, - "Item #[%d] must be of type int, %s given", - iov_index, - zend_get_type_by_const(Z_TYPE_P(zelement))); - RETURN_FALSE; - } - if (Z_LVAL_P(zelement) < 0) { - zend_throw_exception_ex( - swoole_socket_coro_exception_ce, EINVAL, "Item #[%d] must be greater than 0", iov_index); - RETURN_FALSE; - } - size_t iov_len = Z_LVAL_P(zelement); + SW_HASHTABLE_FOREACH_START(vht, zelement) { + if (!ZVAL_IS_LONG(zelement)) { + zend_throw_exception_ex(swoole_socket_coro_exception_ce, + EINVAL, + "Item #[%d] must be of type int, %s given", + iov_index, + zend_get_type_by_const(Z_TYPE_P(zelement))); + RETURN_FALSE; + } + if (Z_LVAL_P(zelement) < 0) { + zend_throw_exception_ex( + swoole_socket_coro_exception_ce, EINVAL, "Item #[%d] must be greater than 0", iov_index); + RETURN_FALSE; + } + size_t iov_len = Z_LVAL_P(zelement); - iov[iov_index].iov_base = zend_string_alloc(iov_len, 0)->val; - iov[iov_index].iov_len = iov_len; - iov_index++; - total_length += iov_len; + iov[iov_index].iov_base = zend_string_alloc(iov_len, 0)->val; + iov[iov_index].iov_len = iov_len; + iov_index++; + total_length += iov_len; + } SW_HASHTABLE_FOREACH_END(); swoole::network::IOVector io_vector((struct iovec *) iov.get(), iovcnt); @@ -1533,6 +1537,7 @@ static void swoole_socket_coro_read_vector(INTERNAL_FUNCTION_PARAMETERS, const b real_count = iov_index + 1; zend_string *str = zend::fetch_zend_string_by_val((char *) iov[iov_index].iov_base); iov[iov_index].iov_base = sw_zend_string_recycle(str, iov[iov_index].iov_len, offset_bytes)->val; + iov[iov_index].iov_len = offset_bytes; free_func(iov.get(), iovcnt, real_count); } else { real_count = iovcnt; @@ -1767,9 +1772,10 @@ static PHP_METHOD(swoole_socket_coro, getOption) { } case SO_RCVTIMEO: case SO_SNDTIMEO: { - double timeout = sock->socket->get_timeout(optname == SO_RCVTIMEO ? Socket::TIMEOUT_READ : Socket::TIMEOUT_WRITE); + double timeout = + sock->socket->get_timeout(optname == SO_RCVTIMEO ? Socket::TIMEOUT_READ : Socket::TIMEOUT_WRITE); array_init(return_value); - int sec = (int) timeout; + int sec = (int) timeout; add_assoc_long(return_value, "sec", (int) timeout); add_assoc_long(return_value, "usec", (timeout - (double) sec) * 1000000); break; diff --git a/src/network/dns.cc b/src/network/dns.cc index 3678c9c36ee..da5531bf269 100644 --- a/src/network/dns.cc +++ b/src/network/dns.cc @@ -402,6 +402,7 @@ struct ResolvContext { int error; bool completed; Coroutine *co; + std::shared_ptr defer_task_cancelled; std::unordered_map sockets; std::vector result; }; @@ -428,6 +429,7 @@ std::vector dns_lookup_impl_with_cares(const char *domain, int fami Coroutine *co = Coroutine::get_current_safe(); ctx.co = co; ctx.completed = false; + ctx.defer_task_cancelled = std::make_shared(false); char lookups[] = "fb"; int res; ctx.ares_opts.lookups = lookups; @@ -533,8 +535,12 @@ std::vector dns_lookup_impl_with_cares(const char *domain, int fami } _resume: if (ctx->co && ctx->co->is_suspending()) { + auto _cancelled = ctx->defer_task_cancelled; swoole_event_defer( - [](void *data) { + [_cancelled](void *data) { + if (*_cancelled) { + return; + } Coroutine *co = reinterpret_cast(data); co->resume(); }, @@ -573,6 +579,7 @@ std::vector dns_lookup_impl_with_cares(const char *domain, int fami break; } } + *ctx.defer_task_cancelled = true; ares_destroy(ctx.channel); _return: return ctx.result; From 0abf591da19de30cca9ac0bb90f795ba63c99fc0 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Thu, 26 Aug 2021 19:18:36 +0800 Subject: [PATCH 224/936] Added CURL INFILE test --- tests/include/lib/src/responder/get.php | 3 +++ tests/swoole_curl/upload/3.phpt | 32 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 tests/swoole_curl/upload/3.phpt diff --git a/tests/include/lib/src/responder/get.php b/tests/include/lib/src/responder/get.php index 5df7b009c3f..e88108a0fd5 100644 --- a/tests/include/lib/src/responder/get.php +++ b/tests/include/lib/src/responder/get.php @@ -63,6 +63,9 @@ header('abc: 123'); echo "a\nb\nc"; break; + case 'input': + echo file_get_contents('php://input'); + break; default: echo "Hello World!\n"; echo "Hello World!"; diff --git a/tests/swoole_curl/upload/3.phpt b/tests/swoole_curl/upload/3.phpt new file mode 100644 index 00000000000..a6fc94ad7c4 --- /dev/null +++ b/tests/swoole_curl/upload/3.phpt @@ -0,0 +1,32 @@ +--TEST-- +swoole_curl/upload: CURL file uploading[INFILE] +--INI-- +--SKIPIF-- + +--FILE-- +run(function ($host) { + Runtime::enableCoroutine(SWOOLE_HOOK_ALL); + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, "{$host}/get.php?test=input"); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_PUT, 1); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + $fp = fopen(TEST_IMAGE, 'r'); + curl_setopt($ch, CURLOPT_INFILE, $fp); + curl_setopt($ch, CURLOPT_HTTPHEADER, array("Expect:")); + curl_setopt($ch, CURLOPT_INFILESIZE, filesize(TEST_IMAGE)); + + $http_result = curl_exec($ch); + Assert::eq(md5($http_result), md5_file(TEST_IMAGE)); +}); + +?> +--EXPECTF-- From 848998a35c0fd1506ee3154544980ec01b359406 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Fri, 27 Aug 2021 14:39:37 +0800 Subject: [PATCH 225/936] Support server command (#4389) * server command * Update * Fix build error * Fix incorrect return value * Refactor * Fix ipc error * Refactor pipe packet buffer * Optimize name * Refactor ProcessFactory * Remove legacy code * Optimize * Optimize code * Refactor, add message_bus.cc * Optimize * Fix * Fix tests * Optimize code * Optimize code[2] * Fix core-tests * Fix tests[2] * Update example * Fix tests * Fix tests[2] * Optimize code, fix core-tests * Optimize code[3], add tests * Optimize code[4], add command supports for task_worker * revert name * Optimize performance Co-authored-by: codinghuang --- config.m4 | 1 + core-tests/src/core/base.cpp | 14 +- core-tests/src/reactor/base.cpp | 73 ++++- core-tests/src/server/message_bus.cpp | 198 ++++++++++++ core-tests/src/server/server.cpp | 82 +++-- examples/server/echo.php | 25 +- ext-src/php_swoole.cc | 13 - ext-src/php_swoole_library.h | 89 ++++- ext-src/php_swoole_server.h | 1 + ext-src/swoole_coroutine.cc | 2 +- ext-src/swoole_coroutine_scheduler.cc | 2 +- ext-src/swoole_process.cc | 4 +- ext-src/swoole_process_pool.cc | 2 +- ext-src/swoole_server.cc | 428 ++++++++++++++++--------- include/swoole.h | 108 +++---- include/swoole_error.h | 5 +- include/swoole_process_pool.h | 11 +- include/swoole_reactor.h | 33 +- include/swoole_server.h | 320 +++++++++++++----- include/swoole_string.h | 4 + src/core/base.cc | 23 +- src/core/timer.cc | 2 +- src/coroutine/socket.cc | 1 + src/coroutine/system.cc | 2 +- src/network/stream.cc | 2 +- src/os/async_thread.cc | 2 +- src/os/pipe.cc | 6 +- src/os/process_pool.cc | 2 +- src/os/signal.cc | 2 +- src/os/wait.cc | 2 +- src/protocol/http.cc | 2 +- src/reactor/base.cc | 44 +-- src/reactor/epoll.cc | 21 +- src/reactor/poll.cc | 18 +- src/server/base.cc | 69 ++-- src/server/manager.cc | 38 +-- src/server/master.cc | 353 ++++++++++++++------ src/server/message_bus.cc | 271 ++++++++++++++++ src/server/process.cc | 127 +------- src/server/reactor_process.cc | 133 +++----- src/server/reactor_thread.cc | 252 ++++++--------- src/server/task_worker.cc | 87 +++-- src/server/worker.cc | 208 ++++-------- src/wrapper/event.cc | 3 - tests/include/lib/composer.lock | 54 ++-- tests/swoole_server/bug_2308.phpt | 17 +- tests/swoole_server/command.phpt | 40 +++ tests/swoole_server/force_reload.phpt | 8 +- tests/swoole_server/force_reload4.phpt | 2 +- tests/swoole_server/send_2.phpt | 21 +- tests/swoole_server/slow_worker.phpt | 2 +- 51 files changed, 2058 insertions(+), 1171 deletions(-) create mode 100644 core-tests/src/server/message_bus.cpp create mode 100644 src/server/message_bus.cc create mode 100644 tests/swoole_server/command.phpt diff --git a/config.m4 b/config.m4 index 9d97e8aa47a..692d85bac3a 100644 --- a/config.m4 +++ b/config.m4 @@ -630,6 +630,7 @@ if test "$PHP_SWOOLE" != "no"; then src/server/static_handler.cc \ src/server/task_worker.cc \ src/server/worker.cc \ + src/server/message_bus.cc \ src/wrapper/event.cc \ src/wrapper/timer.cc" diff --git a/core-tests/src/core/base.cpp b/core-tests/src/core/base.cpp index d43b57d2fa1..f92da6c178e 100644 --- a/core-tests/src/core/base.cpp +++ b/core-tests/src/core/base.cpp @@ -18,6 +18,7 @@ */ #include "test_core.h" +#include "swoole_server.h" #include "swoole_file.h" #include "swoole_util.h" @@ -41,7 +42,7 @@ TEST(base, dec2hex) { sw_free(result); } -TEST(base, swoole_hex2dec) { +TEST(base, hex2dec) { size_t n_parsed; ASSERT_EQ(swoole_hex2dec("9fff9123", &n_parsed), 2684326179); ASSERT_EQ(n_parsed, 8); @@ -122,17 +123,18 @@ TEST(base, file_size) { } TEST(base, eventdata_pack) { - swEventData ed1 { }; + EventData ed1 { }; - ASSERT_TRUE(ed1.pack(test_data.c_str(), test_data.length())); + ASSERT_TRUE(Server::event_data_pack(&ed1, test_data.c_str(), test_data.length())); ASSERT_EQ(string(ed1.data, ed1.info.len), test_data); - swEventData ed2 { }; + EventData ed2 { }; ASSERT_EQ(swoole_random_bytes(sw_tg_buffer()->str, SW_BUFFER_SIZE_BIG), SW_BUFFER_SIZE_BIG); - ASSERT_TRUE(ed2.pack(sw_tg_buffer()->str, SW_BUFFER_SIZE_BIG)); + ASSERT_TRUE(Server::event_data_pack(&ed2, sw_tg_buffer()->str, SW_BUFFER_SIZE_BIG)); String _buffer(SW_BUFFER_SIZE_BIG); - ASSERT_TRUE(ed2.unpack(&_buffer)); + PacketPtr packet; + ASSERT_TRUE(Server::event_data_unpack(&ed2, &_buffer, &packet)); ASSERT_EQ(memcmp(sw_tg_buffer()->str, _buffer.str, SW_BUFFER_SIZE_BIG), 0); } diff --git a/core-tests/src/reactor/base.cpp b/core-tests/src/reactor/base.cpp index 5147703adfb..8395cbd25ef 100644 --- a/core-tests/src/reactor/base.cpp +++ b/core-tests/src/reactor/base.cpp @@ -106,12 +106,14 @@ TEST(reactor, write) { int ret; UnixSocket p(true, SOCK_DGRAM); ASSERT_TRUE(p.ready()); + p.set_blocking(false); + p.set_buffer_size(65536); ret = swoole_event_init(SW_EVENTLOOP_WAIT_EXIT); ASSERT_EQ(ret, SW_OK); ASSERT_NE(SwooleTG.reactor, nullptr); - swoole_event_set_handler(SW_FD_PIPE | SW_EVENT_READ, [](Reactor *reactor, swEvent *ev) -> int { + swoole_event_set_handler(SW_FD_PIPE | SW_EVENT_READ, [](Reactor *reactor, Event *ev) -> int { char buffer[16]; ssize_t n = read(ev->fd, buffer, sizeof(buffer)); @@ -125,21 +127,82 @@ TEST(reactor, write) { ret = swoole_event_add(p.get_socket(false), SW_EVENT_READ); ASSERT_EQ(ret, SW_OK); - ret = swoole_event_write(p.get_socket(true), (void *) SW_STRS("hello world")); - ASSERT_EQ(ret, sizeof("hello world")); + auto sock = p.get_socket(true); + + auto n = swoole_event_write(sock, (void *) SW_STRS("hello world")); + ASSERT_EQ(n, sizeof("hello world")); ret = swoole_event_wait(); ASSERT_EQ(ret, SW_OK); ASSERT_EQ(SwooleTG.reactor, nullptr); } +constexpr int DATA_SIZE = 2 * SW_NUM_MILLION; + +TEST(reactor, write_2m) { + int ret; + UnixSocket p(true, SOCK_STREAM); + ASSERT_TRUE(p.ready()); + + ret = swoole_event_init(SW_EVENTLOOP_WAIT_EXIT); + ASSERT_EQ(ret, SW_OK); + ASSERT_NE(SwooleTG.reactor, nullptr); + + swoole_event_set_handler(SW_FD_PIPE | SW_EVENT_READ, [](Reactor *reactor, Event *ev) -> int { + auto tg_buf = sw_tg_buffer(); + ssize_t n = read(ev->fd, tg_buf->str + tg_buf->length, tg_buf->size - tg_buf->length); + if (n <= 0) { + return SW_ERR; + } + tg_buf->grow(n); + if (tg_buf->length == DATA_SIZE) { + tg_buf->append('\0'); + reactor->del(ev->socket); + } + return SW_OK; + }); + + p.set_blocking(false); + p.set_buffer_size(65536); + + ret = swoole_event_add(p.get_socket(false), SW_EVENT_READ); + ASSERT_EQ(ret, SW_OK); + + String str(DATA_SIZE); + str.append_random_bytes(str.size - 1, false); + str.append('\0'); + + sw_tg_buffer()->clear(); + + auto n = swoole_event_write(p.get_socket(true), str.value(), str.get_length()); + ASSERT_EQ(n, str.get_length()); + ASSERT_GT(p.get_socket(true)->out_buffer->length(), 1024); + + ret = swoole_event_wait(); + ASSERT_EQ(ret, SW_OK); + ASSERT_FALSE(swoole_event_is_available()); + ASSERT_STREQ(sw_tg_buffer()->value(), str.value()); +} + +TEST(reactor, bad_fd) { + swoole_event_init(SW_EVENTLOOP_WAIT_EXIT); + auto sock = make_socket(999999, SW_FD_STREAM_CLIENT); + sock->nonblock = 1; + auto n = swoole_event_write(sock, SW_STRL("hello world")); + ASSERT_EQ(n, SW_ERR); + ASSERT_EQ(swoole_get_last_error(), EBADF); + swoole_event_free(); + sock->fd = -1; + sock->free(); +} + static const char *pkt = "hello world\r\n"; static void reactor_test_func(Reactor *reactor) { Pipe p(true); ASSERT_TRUE(p.ready()); - reactor->set_handler(SW_FD_PIPE | SW_EVENT_READ, [](Reactor *reactor, swEvent *event) -> int { + reactor->set_handler(SW_FD_PIPE | SW_EVENT_READ, [](Reactor *reactor, Event *event) -> int { char buf[1024]; size_t l = strlen(pkt); size_t n = read(event->fd, buf, sizeof(buf)); @@ -150,7 +213,7 @@ static void reactor_test_func(Reactor *reactor) { return SW_OK; }); - reactor->set_handler(SW_FD_PIPE | SW_EVENT_WRITE, [](Reactor *reactor, swEvent *event) -> int { + reactor->set_handler(SW_FD_PIPE | SW_EVENT_WRITE, [](Reactor *reactor, Event *event) -> int { size_t l = strlen(pkt); EXPECT_EQ(write(event->fd, pkt, l), l); reactor->del(event->socket); diff --git a/core-tests/src/server/message_bus.cpp b/core-tests/src/server/message_bus.cpp new file mode 100644 index 00000000000..c98568624ea --- /dev/null +++ b/core-tests/src/server/message_bus.cpp @@ -0,0 +1,198 @@ +/* + +----------------------------------------------------------------------+ + | 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. | + +----------------------------------------------------------------------+ + | @link https://www.swoole.com/ | + | @contact team@swoole.com | + | @license https://github.com/swoole/swoole-src/blob/master/LICENSE | + | @author Tianfeng Han | + +----------------------------------------------------------------------+ +*/ + +#include "test_core.h" + +#include "swoole_server.h" +#include "swoole_memory.h" +#include "swoole_signal.h" +#include "swoole_lock.h" + +using namespace std; +using namespace swoole; + +constexpr int DATA_SIZE = 2 * SW_NUM_MILLION; + +struct TestPacket { + SessionId fd; + std::string data; +}; + +struct TestMB { + std::vector q; + MessageBus mb; + std::function read_func; + + bool send_empty_packet(network::Socket *sock) { + SendData _data4; + _data4.data = "hello world"; + _data4.info.fd = 4; + _data4.info.len = 0; + if (!mb.write(sock, &_data4)) { + return false; + } + + SendData _data5; + _data5.data = nullptr; + _data5.info.fd = 5; + _data5.info.len = 10; + if (!mb.write(sock, &_data5)) { + return false; + } + + return true; + } + + int read(Event *ev) { + auto retval = read_func(ev->socket); + if (retval == 0) { + return SW_OK; + } else if (retval < 0) { + swoole_event_del(ev->socket); + return SW_ERR; + } + + auto packet = mb.get_packet(); + + q.push_back(TestPacket{ + mb.get_buffer()->info.fd, + std::string(packet.data, packet.length), + }); + + if (q.size() == 5) { + swoole_event_del(ev->socket); + } + + return SW_OK; + } +}; + +#define MB_SEND(i, s) \ + String pkt##i(s); \ + pkt##i.append_random_bytes(pkt##i.size - 1, false); \ + pkt##i.append('\0'); \ + \ + SendData _data##i{}; \ + _data##i.data = pkt##i.value(); \ + _data##i.info.fd = i; \ + _data##i.info.len = pkt##i.get_length(); \ + ASSERT_TRUE(tmb.mb.write(p.get_socket(true), &_data##i)); + +#define MB_ASSERT(i) \ + auto r##i = tmb.q.at(i - 1); \ + ASSERT_EQ(r##i.fd, i); \ + ASSERT_STREQ(r##i.data.c_str(), pkt##i.value()); + +TEST(message_bus, read) { + UnixSocket p(true, SOCK_STREAM); + ASSERT_TRUE(p.ready()); + + ASSERT_EQ(swoole_event_init(SW_EVENTLOOP_WAIT_EXIT), SW_OK); + p.set_blocking(false); + p.set_buffer_size(65536); + + uint64_t msg_id = 0; + + TestMB tmb{}; + tmb.mb.set_buffer_size(65536); + tmb.mb.set_id_generator([&msg_id]() { return msg_id++; }); + tmb.mb.alloc_buffer(); + + tmb.read_func = [&tmb](network::Socket *sock) { + return tmb.mb.read(sock); + }; + + sw_reactor()->ptr = &tmb; + + ASSERT_EQ(swoole_event_add(p.get_socket(false), SW_EVENT_READ), SW_OK); + + swoole_event_set_handler(SW_FD_PIPE | SW_EVENT_READ, [](Reactor *reactor, Event *ev) -> int { + TestMB *tmb = (TestMB *) reactor->ptr; + return tmb->read(ev); + }); + + MB_SEND(1, DATA_SIZE); + MB_SEND(2, tmb.mb.get_buffer_size()); + MB_SEND(3, 2341); + + tmb.send_empty_packet(p.get_socket(true)); + + ASSERT_EQ(swoole_event_wait(), SW_OK); + + MB_ASSERT(1); + MB_ASSERT(2); + MB_ASSERT(3); + + auto r4 = tmb.q.at(3); + ASSERT_EQ(r4.fd, 4); + ASSERT_STREQ(r4.data.c_str(), ""); + + auto r5 = tmb.q.at(4); + ASSERT_EQ(r5.fd, 5); + ASSERT_STREQ(r5.data.c_str(), ""); +} + +TEST(message_bus, read_with_buffer) { + UnixSocket p(true, SOCK_DGRAM); + ASSERT_TRUE(p.ready()); + + ASSERT_EQ(swoole_event_init(SW_EVENTLOOP_WAIT_EXIT), SW_OK); + p.set_blocking(false); + p.set_buffer_size(65536); + + uint64_t msg_id = 0; + + TestMB tmb{}; + tmb.mb.set_buffer_size(65536); + tmb.mb.set_id_generator([&msg_id]() { return msg_id++; }); + tmb.mb.alloc_buffer(); + + tmb.read_func = [&tmb](network::Socket *sock) { + return tmb.mb.read_with_buffer(sock); + }; + + sw_reactor()->ptr = &tmb; + + ASSERT_EQ(swoole_event_add(p.get_socket(false), SW_EVENT_READ), SW_OK); + + swoole_event_set_handler(SW_FD_PIPE | SW_EVENT_READ, [](Reactor *reactor, Event *ev) -> int { + TestMB *tmb = (TestMB *) reactor->ptr; + return tmb->read(ev); + }); + + MB_SEND(1, DATA_SIZE); + MB_SEND(2, tmb.mb.get_buffer_size()); + MB_SEND(3, 2341); + + tmb.send_empty_packet(p.get_socket(true)); + + ASSERT_EQ(swoole_event_wait(), SW_OK); + + MB_ASSERT(1); + MB_ASSERT(2); + MB_ASSERT(3); + + auto r4 = tmb.q.at(3); + ASSERT_EQ(r4.fd, 4); + ASSERT_STREQ(r4.data.c_str(), ""); + + auto r5 = tmb.q.at(4); + ASSERT_EQ(r5.fd, 5); + ASSERT_STREQ(r5.data.c_str(), ""); +} diff --git a/core-tests/src/server/server.cpp b/core-tests/src/server/server.cpp index a167c222ad1..5417a856199 100644 --- a/core-tests/src/server/server.cpp +++ b/core-tests/src/server/server.cpp @@ -27,19 +27,6 @@ using namespace std; using namespace swoole; -TEST(server, create_pipe_buffers) { - int ret; - Server serv(Server::MODE_PROCESS); - serv.create(); - - ret = serv.create_pipe_buffers(); - ASSERT_EQ(0, ret); - ASSERT_NE(nullptr, serv.pipe_buffers); - for (uint32_t i = 0; i < serv.reactor_num; i++) { - ASSERT_NE(nullptr, serv.pipe_buffers[i]); - } -} - TEST(server, schedule) { int ret; Server serv(Server::MODE_PROCESS); @@ -55,18 +42,18 @@ TEST(server, schedule) { std::set _worker_id_set; for (uint32_t i = 0; i < serv.worker_num; i++) { - auto worker_id = serv.schedule_worker(i*13, nullptr); + auto worker_id = serv.schedule_worker(i * 13, nullptr); _worker_id_set.insert(worker_id); } ASSERT_EQ(_worker_id_set.size(), serv.worker_num); - + for (uint32_t i = 1; i < serv.worker_num - 1; i++) { serv.workers[i].status = SW_WORKER_IDLE; } _worker_id_set.clear(); for (uint32_t i = 0; i < serv.worker_num; i++) { - auto worker_id = serv.schedule_worker(i*13, nullptr); + auto worker_id = serv.schedule_worker(i * 13, nullptr); _worker_id_set.insert(worker_id); } ASSERT_EQ(_worker_id_set.size(), serv.worker_num - 2); @@ -185,7 +172,7 @@ TEST(server, ssl) { Mutex *lock = new Mutex(Mutex::PROCESS_SHARED); lock->lock(); - ListenPort *port = serv.add_port((enum swSocketType )(SW_SOCK_TCP | SW_SOCK_SSL), TEST_HOST, 0); + ListenPort *port = serv.add_port((enum swSocketType)(SW_SOCK_TCP | SW_SOCK_SSL), TEST_HOST, 0); if (!port) { swoole_warning("listen failed, [error=%d]", swoole_get_last_error()); exit(2); @@ -248,7 +235,7 @@ TEST(server, dtls) { Mutex *lock = new Mutex(Mutex::PROCESS_SHARED); lock->lock(); - ListenPort *port = serv.add_port((enum swSocketType )(SW_SOCK_UDP | SW_SOCK_SSL), TEST_HOST, 0); + ListenPort *port = serv.add_port((enum swSocketType)(SW_SOCK_UDP | SW_SOCK_SSL), TEST_HOST, 0); if (!port) { swoole_warning("listen failed, [error=%d]", swoole_get_last_error()); exit(2); @@ -301,11 +288,11 @@ TEST(server, dtls) { #endif TEST(server, task_worker) { - swServer serv; + Server serv; serv.worker_num = 1; serv.task_worker_num = 1; - swListenPort *port = serv.add_port(SW_SOCK_TCP, TEST_HOST, 0); + ListenPort *port = serv.add_port(SW_SOCK_TCP, TEST_HOST, 0); if (!port) { swoole_warning("listen failed, [error=%d]", swoole_get_last_error()); exit(2); @@ -327,10 +314,10 @@ TEST(server, task_worker) { usleep(10000); - swEventData buf; + EventData buf; memset(&buf.info, 0, sizeof(buf.info)); - SW_TASK_TYPE(&buf) |= SW_TASK_NOREPLY; + buf.info.flags = SW_TASK_NOREPLY; buf.info.len = strlen(packet); memcpy(buf.data, packet, strlen(packet)); @@ -418,3 +405,54 @@ TEST(server, reactor_num_zero) { ASSERT_EQ(serv.reactor_num, SW_CPU_NUM); } + +TEST(server, command) { + Server serv(Server::MODE_PROCESS); + serv.worker_num = 4; + serv.reactor_num = 2; + + SwooleG.running = 1; + + sw_logger()->set_level(SW_LOG_WARNING); + + ListenPort *port = serv.add_port(SW_SOCK_TCP, TEST_HOST, 0); + if (!port) { + swoole_warning("listen failed, [error=%d]", swoole_get_last_error()); + exit(2); + } + + ASSERT_EQ(serv.create(), SW_OK); + + serv.add_command("test", Server::Command::ALL_PROCESS, [](Server *, const std::string &msg) -> std::string { + return std::string("json result, ") + msg; + }); + + serv.onStart = [](Server *serv) { + static Server::Command::Callback fn = [](Server *serv, const std::string &msg) { + if (msg == "json result, hello world [1]") { + serv->command(1, Server::Command::EVENT_WORKER, "test", "hello world [2]", fn); + } else if (msg == "json result, hello world [2]") { + swoole_timer_after(50, [serv](Timer *, TimerNode *) { + serv->shutdown(); + }); + } + }; + + serv->command(1, Server::Command::REACTOR_THREAD, "test", "hello world [1]", fn); + }; + + serv.onWorkerStart = [](Server *serv, int worker_id) { + + }; + + serv.onReceive = [](Server *serv, RecvData *req) -> int { + EXPECT_EQ(string(req->data, req->info.len), string(packet)); + + string resp = string("Server: ") + string(packet); + serv->send(req->info.fd, resp.c_str(), resp.length()); + + return SW_OK; + }; + + ASSERT_EQ(serv.start(), 0); +} diff --git a/examples/server/echo.php b/examples/server/echo.php index 51544878716..410f0183388 100644 --- a/examples/server/echo.php +++ b/examples/server/echo.php @@ -1,26 +1,29 @@ set([ + 'worker_num' =>1, +]); + +$serv->on('connect', function ($serv, $fd, $reactor_id){ + echo "[#".posix_getpid()."]\tClient@[$fd:$reactor_id]: Connect.\n"; +}); -//$serv->on('connect', function ($serv, $fd, $reactor_id){ -// echo "[#".posix_getpid()."]\tClient@[$fd:$reactor_id]: Connect.\n"; -//}); $serv->set(array( 'worker_num' => 1, - )); $serv->on('receive', function (swoole_server $serv, $fd, $reactor_id, $data) { echo "[#".$serv->worker_id."]\tClient[$fd] receive data: $data\n"; - if ($serv->send($fd, "hello {$data}\n") == false) - { + if ($serv->send($fd, "hello {$data}\n") == false) { echo "error\n"; } }); -//$serv->on('close', function ($serv, $fd, $reactor_id) { -// echo "[#".posix_getpid()."]\tClient@[$fd:$reactor_id]: Close.\n"; -//}); +$serv->on('close', function ($serv, $fd, $reactor_id) { + echo "[#".posix_getpid()."]\tClient@[$fd:$reactor_id]: Close.\n"; +}); $serv->start(); diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index 79d3a7d4068..587f12a20b7 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -460,19 +460,6 @@ PHP_MINIT_FUNCTION(swoole) { SW_REGISTER_BOOL_CONSTANT("SWOOLE_USE_SHORTNAME", SWOOLE_G(use_shortname)); - /** - * mode type - */ - SW_REGISTER_LONG_CONSTANT("SWOOLE_BASE", swoole::Server::MODE_BASE); - SW_REGISTER_LONG_CONSTANT("SWOOLE_PROCESS", swoole::Server::MODE_PROCESS); - - /** - * task ipc mode - */ - SW_REGISTER_LONG_CONSTANT("SWOOLE_IPC_UNSOCK", Server::TASK_IPC_UNIXSOCK); - SW_REGISTER_LONG_CONSTANT("SWOOLE_IPC_MSGQUEUE", Server::TASK_IPC_MSGQUEUE); - SW_REGISTER_LONG_CONSTANT("SWOOLE_IPC_PREEMPTIVE", Server::TASK_IPC_PREEMPTIVE); - /** * socket type */ diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index 4772edd6449..7f5f085e09f 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: c996bdfe63d93ff643388f480678fec07483b2e8 */ +/* $Id: 1b421d51331d70d14a1b971c1a20c31c14b523d7 */ static const char* swoole_library_source_constants = "\n" @@ -170,8 +170,6 @@ static const char* swoole_library_source_core_constant = "\n" " public const OPTION_SOCKET_TIMEOUT = 'socket_timeout';\n" "\n" - " public const OPTION_MAX_CONCURRENCY = 'max_concurrency';\n" - "\n" " public const OPTION_AIO_CORE_WORKER_NUM = 'aio_core_worker_num';\n" "\n" " public const OPTION_AIO_WORKER_NUM = 'aio_worker_num';\n" @@ -599,9 +597,13 @@ static const char* swoole_library_source_core_string_object = " /**\n" " * @return static\n" " */\n" - " public function trim(): self\n" + " public function trim($characters = ''): self\n" " {\n" - " return new static(trim($this->string));\n" + " if ($characters) {\n" + " return new static(trim($this->string, $characters));\n" + " } else {\n" + " return new static(trim($this->string));\n" + " }\n" " }\n" "\n" " /**\n" @@ -6802,8 +6804,13 @@ static const char* swoole_library_source_core_server_helper = "\n" "namespace Swoole\\Server;\n" "\n" + "use Swoole\\Coroutine;\n" "use Swoole\\Server;\n" "use Swoole\\Timer;\n" + "use Swoole\\Http\\Response;\n" + "use Swoole\\Http\\Request;\n" + "\n" + "use function Swoole\\Coroutine\\go;\n" "\n" "class Helper\n" "{\n" @@ -6944,6 +6951,7 @@ static const char* swoole_library_source_core_server_helper = "\n" " const HELPER_OPTIONS = [\n" " 'stats_file' => true,\n" + " 'admin_server' => true,\n" " ];\n" "\n" " public static function checkOptions(array $input_options)\n" @@ -6959,6 +6967,19 @@ static const char* swoole_library_source_core_server_helper = " }\n" " }\n" "\n" + " public static function onBeforeStart(Server $server)\n" + " {\n" + " if (!empty($server->setting['admin_server'])) {\n" + " $server->addCommand('coroutine_stats',\n" + " 'Get the statistical data of the coroutine scheduler, PATH: /api/coroutine_stats/{$workerId}, GET: [], POST: []',\n" + " SWOOLE_SERVER_COMMAND_EVENT_WORKER | SWOOLE_SERVER_COMMAND_TASK_WORKER,\n" + " function ($server, $msg) {\n" + " return json_encode(Coroutine::stats());\n" + " }\n" + " );\n" + " }\n" + " }\n" + "\n" " public static function onWorkerStart(Server $server, int $workerId)\n" " {\n" " if (!empty($server->setting['stats_file']) and $workerId == 0) {\n" @@ -6985,6 +7006,64 @@ static const char* swoole_library_source_core_server_helper = " public static function onWorkerStop(Server $server, int $workerId)\n" " {\n" " }\n" + "\n" + " public static function onStart(Server $server)\n" + " {\n" + " if (!empty($server->setting['admin_server'])) {\n" + " go(function () use ($server) {\n" + " $admin_server_uri = swoole_string($server->setting['admin_server']);\n" + " if ($admin_server_uri->startsWith('unix:/')) {\n" + " $admin_server = new Coroutine\\Http\\Server($admin_server_uri->toString());\n" + " } else {\n" + " list($host, $port) = $admin_server_uri->split(':', 2)->toArray();\n" + " $admin_server = new Coroutine\\Http\\Server($host, intval($port));\n" + " }\n" + " $admin_server->handle('/api', function (Request $req, Response $resp) use ($server) {\n" + " $path_array = swoole_string($req->server['request_uri'])->trim('/')->split('/');\n" + " $cmd = $path_array->get(1)->toString();\n" + " $worker_id = $path_array->get(2)->toString();\n" + " if ($req->getMethod() == 'GET') {\n" + " var_dump($cmd, intval($worker_id), $req->get);\n" + " $result = $server->command($cmd, intval($worker_id), $req->get);\n" + " } else {\n" + " $result = $server->command($cmd, intval($worker_id), $req->post);\n" + " }\n" + " if (!$result) {\n" + " $resp->end(json_encode(['code' => swoole_last_error(),]));\n" + " } else {\n" + " $resp->end(json_encode(['code' => 0, $result]));\n" + " }\n" + " });\n" + " $admin_server->handle('/app', function (Request $req, Response $resp) use ($server) {\n" + " });\n" + " $admin_server->start();\n" + " });\n" + " }\n" + " }\n" + "\n" + " public static function onShutdown(Server $server)\n" + " {\n" + " }\n" + "\n" + " public static function onBeforeReload(Server $server)\n" + " {\n" + " }\n" + "\n" + " public static function onAfterReload(Server $server)\n" + " {\n" + " }\n" + "\n" + " public static function onManagerStart(Server $server)\n" + " {\n" + " }\n" + "\n" + " public static function onManagerStop(Server $server)\n" + " {\n" + " }\n" + "\n" + " public static function onWorkerError(Server $server)\n" + " {\n" + " }\n" "}\n"; static const char* swoole_library_source_core_coroutine_functions = diff --git a/ext-src/php_swoole_server.h b/ext-src/php_swoole_server.h index 6737717d132..3554f6bb558 100644 --- a/ext-src/php_swoole_server.h +++ b/ext-src/php_swoole_server.h @@ -79,6 +79,7 @@ struct ServerProperty { std::unordered_map task_callbacks; std::unordered_map task_coroutine_map; std::unordered_map *> send_coroutine_map; + std::vector command_callbacks; }; struct ServerObject { diff --git a/ext-src/swoole_coroutine.cc b/ext-src/swoole_coroutine.cc index 2d859f77db0..d3c178fb267 100644 --- a/ext-src/swoole_coroutine.cc +++ b/ext-src/swoole_coroutine.cc @@ -980,7 +980,7 @@ PHP_FUNCTION(swoole_coroutine_defer) { static PHP_METHOD(swoole_coroutine, stats) { array_init(return_value); - add_assoc_long_ex(return_value, ZEND_STRL("event_num"), sw_reactor() ? sw_reactor()->event_num : 0); + add_assoc_long_ex(return_value, ZEND_STRL("event_num"), sw_reactor() ? sw_reactor()->get_event_num() : 0); add_assoc_long_ex( return_value, ZEND_STRL("signal_listener_num"), SwooleTG.signal_listener_num + SwooleTG.co_signal_listener_num); diff --git a/ext-src/swoole_coroutine_scheduler.cc b/ext-src/swoole_coroutine_scheduler.cc index f735fce1b8d..6ab6a345833 100644 --- a/ext-src/swoole_coroutine_scheduler.cc +++ b/ext-src/swoole_coroutine_scheduler.cc @@ -123,7 +123,7 @@ void php_swoole_coroutine_scheduler_minit(int module_number) { static zend_fcall_info_cache exit_condition_fci_cache; static bool exit_condition_cleaner; -static bool php_swoole_coroutine_reactor_can_exit(Reactor *reactor, int &event_num) { +static bool php_swoole_coroutine_reactor_can_exit(Reactor *reactor, size_t &event_num) { zval retval; int success; diff --git a/ext-src/swoole_process.cc b/ext-src/swoole_process.cc index 858d12684ba..636faccab29 100644 --- a/ext-src/swoole_process.cc +++ b/ext-src/swoole_process.cc @@ -367,7 +367,7 @@ static PHP_METHOD(swoole_process, __construct) { uint32_t base = 1; if (sw_server() && sw_server()->is_started()) { - base = sw_server()->worker_num + sw_server()->task_worker_num + sw_server()->user_worker_num; + base = sw_server()->worker_num + sw_server()->task_worker_num + sw_server()->get_user_worker_num(); } if (php_swoole_worker_round_id == 0) { php_swoole_worker_round_id = base; @@ -585,7 +585,7 @@ static PHP_METHOD(swoole_process, signal) { SwooleTG.reactor->check_signalfd = true; if (!SwooleTG.reactor->isset_exit_condition(Reactor::EXIT_CONDITION_SIGNAL_LISTENER)) { SwooleTG.reactor->set_exit_condition(Reactor::EXIT_CONDITION_SIGNAL_LISTENER, - [](Reactor *reactor, int &event_num) -> bool { + [](Reactor *reactor, size_t &event_num) -> bool { return SwooleTG.signal_listener_num == 0 or !SwooleG.wait_signal; }); } diff --git a/ext-src/swoole_process_pool.cc b/ext-src/swoole_process_pool.cc index c3cdf485331..41d0e59ad63 100644 --- a/ext-src/swoole_process_pool.cc +++ b/ext-src/swoole_process_pool.cc @@ -322,7 +322,7 @@ static PHP_METHOD(swoole_process_pool, __construct) { ProcessPool *pool = (ProcessPool *) emalloc(sizeof(*pool)); *pool = {}; - if (pool->create(worker_num, (key_t) msgq_key, (swIPC_type) ipc_type) < 0) { + if (pool->create(worker_num, (key_t) msgq_key, (swIPCMode) ipc_type) < 0) { zend_throw_exception_ex(swoole_exception_ce, errno, "failed to create process pool"); efree(pool); RETURN_FALSE; diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index ce5a88acad0..934443abd21 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -62,7 +62,7 @@ static std::unordered_map server_event_map({ // server event callback static void php_swoole_onPipeMessage(Server *serv, EventData *req); -static void php_swoole_onStart(Server *); +static void php_swoole_server_onStart(Server *); static void php_swoole_onShutdown(Server *); static void php_swoole_server_onWorkerStart(Server *, int worker_id); static void php_swoole_server_onBeforeReload(Server *serv); @@ -199,6 +199,11 @@ static void server_free_object(zend_object *object) { server_object->serv = nullptr; } + for (auto fci_cache : property->command_callbacks) { + sw_zend_fci_cache_discard(fci_cache); + efree(fci_cache); + } + delete property; zend_object_std_dtor(object); @@ -431,10 +436,24 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_server_sendMessage, 0, 0, 2) ZEND_ARG_INFO(0, dst_worker_id) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_server_command, 0, 0, 4) + ZEND_ARG_INFO(0, name) + ZEND_ARG_INFO(0, process_id) + ZEND_ARG_INFO(0, process_type) + ZEND_ARG_INFO(0, data) + ZEND_ARG_INFO(0, json_encode) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_server_addProcess, 0, 0, 1) ZEND_ARG_OBJ_INFO(0, process, swoole_process, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_server_addCommand, 0, 0, 3) + ZEND_ARG_INFO(0, name) + ZEND_ARG_INFO(0, accepted_process_types) + ZEND_ARG_CALLABLE_INFO(0, callback, 1) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_server_getClientInfo, 0, 0, 1) ZEND_ARG_INFO(0, fd) ZEND_ARG_INFO(0, reactor_id) @@ -444,6 +463,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_server_getWorkerStatus, 0, 0, 0) ZEND_ARG_INFO(0, worker_id) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_server_getWorkerPid, 0, 0, 0) + ZEND_ARG_INFO(0, worker_id) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_server_getClientList, 0, 0, 1) ZEND_ARG_INFO(0, start_fd) ZEND_ARG_INFO(0, find_count) @@ -478,6 +501,7 @@ static PHP_METHOD(swoole_server, getCallback); static PHP_METHOD(swoole_server, listen); static PHP_METHOD(swoole_server, sendMessage); static PHP_METHOD(swoole_server, addProcess); +static PHP_METHOD(swoole_server, addCommand); static PHP_METHOD(swoole_server, start); static PHP_METHOD(swoole_server, stop); static PHP_METHOD(swoole_server, send); @@ -499,6 +523,7 @@ static PHP_METHOD(swoole_server, finish); static PHP_METHOD(swoole_server, reload); static PHP_METHOD(swoole_server, shutdown); static PHP_METHOD(swoole_server, heartbeat); +static PHP_METHOD(swoole_server, command); static PHP_METHOD(swoole_server, getClientList); static PHP_METHOD(swoole_server, getClientInfo); static PHP_METHOD(swoole_server, getWorkerId); @@ -568,7 +593,7 @@ static zend_function_entry swoole_server_methods[] = { PHP_ME(swoole_server, getClientInfo, arginfo_swoole_server_getClientInfo, ZEND_ACC_PUBLIC) PHP_ME(swoole_server, getClientList, arginfo_swoole_server_getClientList, ZEND_ACC_PUBLIC) PHP_ME(swoole_server, getWorkerId, arginfo_swoole_void, ZEND_ACC_PUBLIC) - PHP_ME(swoole_server, getWorkerPid, arginfo_swoole_void, ZEND_ACC_PUBLIC) + PHP_ME(swoole_server, getWorkerPid, arginfo_swoole_server_getWorkerPid, ZEND_ACC_PUBLIC) PHP_ME(swoole_server, getWorkerStatus, arginfo_swoole_server_getWorkerStatus, ZEND_ACC_PUBLIC) PHP_ME(swoole_server, getManagerPid, arginfo_swoole_void, ZEND_ACC_PUBLIC) PHP_ME(swoole_server, getMasterPid, arginfo_swoole_void, ZEND_ACC_PUBLIC) @@ -577,6 +602,8 @@ static zend_function_entry swoole_server_methods[] = { PHP_MALIAS(swoole_server, connection_list, getClientList, arginfo_swoole_server_getClientList, ZEND_ACC_PUBLIC) //process PHP_ME(swoole_server, sendMessage, arginfo_swoole_server_sendMessage, ZEND_ACC_PUBLIC) + PHP_ME(swoole_server, command, arginfo_swoole_server_command, ZEND_ACC_PUBLIC) + PHP_ME(swoole_server, addCommand, arginfo_swoole_server_addCommand, ZEND_ACC_PUBLIC) PHP_ME(swoole_server, addProcess, arginfo_swoole_server_addProcess, ZEND_ACC_PUBLIC) PHP_ME(swoole_server, stats, arginfo_swoole_void, ZEND_ACC_PUBLIC) #ifdef SWOOLE_SOCKETS_SUPPORT @@ -720,6 +747,25 @@ void php_swoole_server_minit(int module_number) { zend_declare_property_long(swoole_server_ce, ZEND_STRL("worker_pid"), 0, ZEND_ACC_PUBLIC); zend_declare_property_null(swoole_server_ce, ZEND_STRL("stats_timer"), ZEND_ACC_PUBLIC); + /** + * mode type + */ + SW_REGISTER_LONG_CONSTANT("SWOOLE_BASE", swoole::Server::MODE_BASE); + SW_REGISTER_LONG_CONSTANT("SWOOLE_PROCESS", swoole::Server::MODE_PROCESS); + + /** + * task ipc mode + */ + SW_REGISTER_LONG_CONSTANT("SWOOLE_IPC_UNSOCK", Server::TASK_IPC_UNIXSOCK); + SW_REGISTER_LONG_CONSTANT("SWOOLE_IPC_MSGQUEUE", Server::TASK_IPC_MSGQUEUE); + SW_REGISTER_LONG_CONSTANT("SWOOLE_IPC_PREEMPTIVE", Server::TASK_IPC_PREEMPTIVE); + + SW_REGISTER_LONG_CONSTANT("SWOOLE_SERVER_COMMAND_MASTER", Server::Command::MASTER); + SW_REGISTER_LONG_CONSTANT("SWOOLE_SERVER_COMMAND_REACTOR_THREAD", Server::Command::REACTOR_THREAD); + SW_REGISTER_LONG_CONSTANT("SWOOLE_SERVER_COMMAND_EVENT_WORKER", Server::Command::EVENT_WORKER); + SW_REGISTER_LONG_CONSTANT("SWOOLE_SERVER_COMMAND_WORKER", Server::Command::EVENT_WORKER); + SW_REGISTER_LONG_CONSTANT("SWOOLE_SERVER_COMMAND_TASK_WORKER", Server::Command::TASK_WORKER); + SW_REGISTER_LONG_CONSTANT("SWOOLE_DISPATCH_RESULT_DISCARD_PACKET", Server::DISPATCH_RESULT_DISCARD_PACKET); SW_REGISTER_LONG_CONSTANT("SWOOLE_DISPATCH_RESULT_CLOSE_CONNECTION", Server::DISPATCH_RESULT_CLOSE_CONNECTION); SW_REGISTER_LONG_CONSTANT("SWOOLE_DISPATCH_RESULT_USERFUNC_FALLBACK", Server::DISPATCH_RESULT_USERFUNC_FALLBACK); @@ -765,18 +811,14 @@ TaskId php_swoole_task_pack(EventData *task, zval *zdata) { smart_str serialized_data = {}; php_serialize_data_t var_hash; - task->info.type = SW_SERVER_EVENT_TASK; - task->info.fd = SwooleG.current_task_id++; - task->info.reactor_id = SwooleG.process_id; - task->info.time = swoole::microtime(); - SW_TASK_TYPE(task) = 0; + task->info.flags = 0; char *task_data_str; size_t task_data_len = 0; // need serialize if (Z_TYPE_P(zdata) != IS_STRING) { // serialize - SW_TASK_TYPE(task) |= SW_TASK_SERIALIZE; + task->info.flags |= SW_TASK_SERIALIZE; PHP_VAR_SERIALIZE_INIT(var_hash); php_var_serialize(&serialized_data, zdata, &var_hash); @@ -792,7 +834,7 @@ TaskId php_swoole_task_pack(EventData *task, zval *zdata) { task_data_len = Z_STRLEN_P(zdata); } - if (!task->pack(task_data_str, task_data_len)) { + if (!Server::event_data_pack(task, task_data_str, task_data_len)) { php_swoole_fatal_error(E_WARNING, "large task pack failed"); task->info.fd = SW_ERR; task->info.len = 0; @@ -810,7 +852,7 @@ void php_swoole_get_recv_data(Server *serv, zval *zdata, RecvData *req) { } else { if (req->info.flags & SW_EVENT_DATA_OBJ_PTR) { zend::assign_zend_string_by_val(zdata, (char *) data, length); - serv->pop_worker_buffer(&req->info); + serv->message_bus.move_packet(); } else if (req->info.flags & SW_EVENT_DATA_POP_PTR) { String *recv_buffer = serv->get_recv_buffer(serv->get_connection_by_session_id(req->info.fd)->socket); zend::assign_zend_string_by_val(zdata, recv_buffer->pop(serv->recv_buffer_size), length); @@ -838,25 +880,17 @@ static sw_inline int php_swoole_check_task_param(Server *serv, zend_long dst_wor zval *php_swoole_task_unpack(EventData *task_result) { zval *result_data, *result_unserialized_data; - char *result_data_str; - size_t result_data_len = 0; php_unserialize_data_t var_hash; + PacketPtr packet; - /** - * Large result package - */ - if (SW_TASK_TYPE(task_result) & SW_TASK_TMPFILE) { - if (!task_result->unpack(sw_tg_buffer())) { - return nullptr; - } - result_data_str = sw_tg_buffer()->str; - result_data_len = sw_tg_buffer()->length; - } else { - result_data_str = task_result->data; - result_data_len = task_result->info.len; + if (Server::event_data_unpack(task_result, sw_tg_buffer(), &packet)) { + return nullptr; } - if (SW_TASK_TYPE(task_result) & SW_TASK_SERIALIZE) { + char *result_data_str = packet.data; + size_t result_data_len = packet.length; + + if (task_result->info.flags & SW_TASK_SERIALIZE) { result_unserialized_data = sw_malloc_zval(); PHP_VAR_UNSERIALIZE_INIT(var_hash); @@ -962,13 +996,10 @@ void ServerObject::on_before_start() { } } - /** - * init method - */ - serv->worker_buffer_allocator = sw_zend_string_allocator(); + serv->message_bus.set_allocator(sw_zend_string_allocator()); if (serv->is_base_mode()) { - serv->buffer_allocator = sw_zend_string_allocator(); + serv->recv_buffer_allocator = sw_zend_string_allocator(); } /** @@ -1114,49 +1145,30 @@ void ServerObject::on_before_start() { serv->onReceive = php_swoole_http_server_onReceive; php_swoole_http_server_init_global_variant(); } + + if (SWOOLE_G(enable_library)) { + zend::function::call("\\Swoole\\Server\\Helper::onBeforeStart", 1, zobject); + } } void ServerObject::register_callback() { - /* - * optional callback - */ - if (property->callbacks[SW_SERVER_CB_onStart] != nullptr) { - serv->onStart = php_swoole_onStart; - } + // control plane + serv->onStart = php_swoole_server_onStart; serv->onShutdown = php_swoole_onShutdown; - /** - * require callback, set the master/manager/worker PID - */ serv->onWorkerStart = php_swoole_server_onWorkerStart; - - if (property->callbacks[SW_SERVER_CB_onBeforeReload] != nullptr) { - serv->onBeforeReload = php_swoole_server_onBeforeReload; - } - - if (property->callbacks[SW_SERVER_CB_onAfterReload] != nullptr) { - serv->onAfterReload = php_swoole_server_onAfterReload; - } - - if (property->callbacks[SW_SERVER_CB_onWorkerStop] != nullptr) { - serv->onWorkerStop = php_swoole_server_onWorkerStop; - } + serv->onWorkerStop = php_swoole_server_onWorkerStop; serv->onWorkerExit = php_swoole_server_onWorkerExit; - /** - * Task Worker - */ + serv->onBeforeReload = php_swoole_server_onBeforeReload; + serv->onAfterReload = php_swoole_server_onAfterReload; + serv->onManagerStart = php_swoole_server_onManagerStart; + serv->onManagerStop = php_swoole_server_onManagerStop; + serv->onWorkerError = php_swoole_server_onWorkerError; + + // data plane if (property->callbacks[SW_SERVER_CB_onTask] != nullptr) { serv->onTask = php_swoole_server_onTask; serv->onFinish = php_swoole_server_onFinish; } - if (property->callbacks[SW_SERVER_CB_onWorkerError] != nullptr) { - serv->onWorkerError = php_swoole_server_onWorkerError; - } - if (property->callbacks[SW_SERVER_CB_onManagerStart] != nullptr) { - serv->onManagerStart = php_swoole_server_onManagerStart; - } - if (property->callbacks[SW_SERVER_CB_onManagerStop] != nullptr) { - serv->onManagerStop = php_swoole_server_onManagerStop; - } if (property->callbacks[SW_SERVER_CB_onPipeMessage] != nullptr) { serv->onPipeMessage = php_swoole_onPipeMessage; } @@ -1389,7 +1401,7 @@ static sw_inline void php_swoole_create_task_object(zval *ztask, Server *serv, E zend_update_property(swoole_server_task_ce, SW_Z8_OBJ_P(ztask), ZEND_STRL("data"), zdata); zend_update_property_double(swoole_server_task_ce, SW_Z8_OBJ_P(ztask), ZEND_STRL("dispatch_time"), req->info.time); zend_update_property_long( - swoole_server_task_ce, SW_Z8_OBJ_P(ztask), ZEND_STRL("flags"), (zend_long) SW_TASK_TYPE(req)); + swoole_server_task_ce, SW_Z8_OBJ_P(ztask), ZEND_STRL("flags"), (zend_long) req->info.flags); } static int php_swoole_server_onTask(Server *serv, EventData *req) { @@ -1449,7 +1461,7 @@ static int php_swoole_server_onFinish(Server *serv, EventData *req) { return SW_ERR; } - if (SW_TASK_TYPE(req) & SW_TASK_COROUTINE) { + if (req->info.flags & SW_TASK_COROUTINE) { TaskId task_id = req->info.fd; auto task_co_iterator = server_object->property->task_coroutine_map.find(task_id); @@ -1491,10 +1503,10 @@ static int php_swoole_server_onFinish(Server *serv, EventData *req) { } zend_fcall_info_cache *fci_cache = nullptr; - if (SW_TASK_TYPE(req) & SW_TASK_CALLBACK) { + if (req->info.flags & SW_TASK_CALLBACK) { auto callback_iterator = server_object->property->task_callbacks.find(req->info.fd); if (callback_iterator == server_object->property->task_callbacks.end()) { - SW_TASK_TYPE(req) = SW_TASK_TYPE(req) & (~SW_TASK_CALLBACK); + req->info.flags = req->info.flags & (~SW_TASK_CALLBACK); } else { fci_cache = &callback_iterator->second; } @@ -1533,7 +1545,7 @@ static int php_swoole_server_onFinish(Server *serv, EventData *req) { if (UNEXPECTED(!zend::function::call(fci_cache, argc, args, nullptr, serv->enable_coroutine))) { php_swoole_error(E_WARNING, "%s->onFinish handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } - if (SW_TASK_TYPE(req) & SW_TASK_CALLBACK) { + if (req->info.flags & SW_TASK_CALLBACK) { sw_zend_fci_cache_discard(fci_cache); server_object->property->task_callbacks.erase(req->info.fd); } @@ -1545,7 +1557,7 @@ static int php_swoole_server_onFinish(Server *serv, EventData *req) { return SW_OK; } -static void php_swoole_onStart(Server *serv) { +static void php_swoole_server_onStart(Server *serv) { serv->lock(); zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); @@ -1553,7 +1565,12 @@ static void php_swoole_onStart(Server *serv) { zend_update_property_long(swoole_server_ce, SW_Z8_OBJ_P(zserv), ZEND_STRL("master_pid"), serv->gs->master_pid); zend_update_property_long(swoole_server_ce, SW_Z8_OBJ_P(zserv), ZEND_STRL("manager_pid"), serv->gs->manager_pid); - if (UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, false))) { + + if (SWOOLE_G(enable_library)) { + zend::function::call("\\Swoole\\Server\\Helper::onStart", 1, zserv); + } + + if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, serv->is_enable_coroutine()))) { php_swoole_error(E_WARNING, "%s->onStart handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } serv->unlock(); @@ -1567,7 +1584,11 @@ static void php_swoole_server_onManagerStart(Server *serv) { zend_update_property_long(swoole_server_ce, SW_Z8_OBJ_P(zserv), ZEND_STRL("master_pid"), serv->gs->master_pid); zend_update_property_long(swoole_server_ce, SW_Z8_OBJ_P(zserv), ZEND_STRL("manager_pid"), serv->gs->manager_pid); - if (UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, false))) { + if (SWOOLE_G(enable_library)) { + zend::function::call("\\Swoole\\Server\\Helper::onManagerStart", 1, zserv); + } + + if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, false))) { php_swoole_error(E_WARNING, "%s->onManagerStart handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } } @@ -1577,7 +1598,11 @@ static void php_swoole_server_onManagerStop(Server *serv) { ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onManagerStop]; - if (UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, false))) { + if (SWOOLE_G(enable_library)) { + zend::function::call("\\Swoole\\Server\\Helper::onManagerStop", 1, zserv); + } + + if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, false))) { php_swoole_error(E_WARNING, "%s->onManagerStop handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } } @@ -1588,10 +1613,12 @@ static void php_swoole_onShutdown(Server *serv) { ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onShutdown]; - if (fci_cache != nullptr) { - if (UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, false))) { - php_swoole_error(E_WARNING, "%s->onShutdown handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); - } + if (SWOOLE_G(enable_library)) { + zend::function::call("\\Swoole\\Server\\Helper::onShutdown", 1, zserv); + } + + if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, false))) { + php_swoole_error(E_WARNING, "%s->onShutdown handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } serv->unlock(); } @@ -1619,10 +1646,8 @@ static void php_swoole_server_onWorkerStart(Server *serv, int worker_id) { zend::function::call("\\Swoole\\Server\\Helper::onWorkerStart", 2, args); } - if (fci_cache) { - if (UNEXPECTED(!zend::function::call(fci_cache, 2, args, nullptr, serv->is_enable_coroutine()))) { - php_swoole_error(E_WARNING, "%s->onWorkerStart handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); - } + if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, 2, args, nullptr, serv->is_enable_coroutine()))) { + php_swoole_error(E_WARNING, "%s->onWorkerStart handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } } @@ -1631,12 +1656,12 @@ static void php_swoole_server_onBeforeReload(Server *serv) { ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onBeforeReload]; - if (fci_cache) { - zval args[1]; - args[0] = *zserv; - if (UNEXPECTED(!zend::function::call(fci_cache, 1, args, nullptr, false))) { - php_swoole_error(E_WARNING, "%s->onBeforeReload handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); - } + if (SWOOLE_G(enable_library)) { + zend::function::call("\\Swoole\\Server\\Helper::onBeforeReload", 1, zserv); + } + + if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, false))) { + php_swoole_error(E_WARNING, "%s->onBeforeReload handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } } @@ -1645,12 +1670,12 @@ static void php_swoole_server_onAfterReload(Server *serv) { ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onAfterReload]; - if (fci_cache) { - zval args[1]; - args[0] = *zserv; - if (UNEXPECTED(!zend::function::call(fci_cache, 1, args, nullptr, false))) { - php_swoole_error(E_WARNING, "%s->onAfterReload handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); - } + if (SWOOLE_G(enable_library)) { + zend::function::call("\\Swoole\\Server\\Helper::onAfterReload", 1, zserv); + } + + if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, false))) { + php_swoole_error(E_WARNING, "%s->onAfterReload handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } } @@ -1671,7 +1696,7 @@ static void php_swoole_server_onWorkerStop(Server *serv, int worker_id) { zend::function::call("\\Swoole\\Server\\Helper::onWorkerStop", 2, args); } - if (UNEXPECTED(!zend::function::call(fci_cache, 2, args, nullptr, false))) { + if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, 2, args, nullptr, false))) { php_swoole_error(E_WARNING, "%s->onWorkerStop handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } } @@ -1689,10 +1714,8 @@ static void php_swoole_server_onWorkerExit(Server *serv, int worker_id) { zend::function::call("\\Swoole\\Server\\Helper::onWorkerExit", 2, args); } - if (fci_cache) { - if (UNEXPECTED(!zend::function::call(fci_cache, 2, args, nullptr, false))) { - php_swoole_error(E_WARNING, "%s->onWorkerExit handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); - } + if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, 2, args, nullptr, false))) { + php_swoole_error(E_WARNING, "%s->onWorkerExit handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } } @@ -1737,7 +1760,11 @@ static void php_swoole_server_onWorkerError(Server *serv, int worker_id, const E argc = 5; } - if (UNEXPECTED(!zend::function::call(fci_cache, argc, args, nullptr, false))) { + if (SWOOLE_G(enable_library)) { + zend::function::call("\\Swoole\\Server\\Helper::onWorkerError", 1, zserv); + } + + if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, argc, args, nullptr, false))) { php_swoole_error(E_WARNING, "%s->onWorkerError handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } @@ -1748,35 +1775,36 @@ static void php_swoole_server_onWorkerError(Server *serv, int worker_id, const E void php_swoole_server_onConnect(Server *serv, DataHead *info) { auto fci_cache = php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onConnect); - if (fci_cache) { - zval *zserv = (zval *) serv->private_data_2; - zval args[3]; - int argc; - args[0] = *zserv; + if (!fci_cache) { + return; + } - if (serv->event_object) { - zval *object = &args[1]; - object_init_ex(object, swoole_server_event_ce); - zend_update_property_long( - swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("fd"), (zend_long) info->fd); - zend_update_property_long( - swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("reactor_id"), (zend_long) info->reactor_id); - zend_update_property_double( - swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("dispatch_time"), info->time); - argc = 2; - } else { - ZVAL_LONG(&args[1], info->fd); - ZVAL_LONG(&args[2], info->reactor_id); - argc = 3; - } + zval *zserv = (zval *) serv->private_data_2; + zval args[3]; + int argc; + args[0] = *zserv; - if (UNEXPECTED(!zend::function::call(fci_cache, argc, args, nullptr, serv->enable_coroutine))) { - php_swoole_error(E_WARNING, "%s->onConnect handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); - } + if (serv->event_object) { + zval *object = &args[1]; + object_init_ex(object, swoole_server_event_ce); + zend_update_property_long(swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("fd"), (zend_long) info->fd); + zend_update_property_long( + swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("reactor_id"), (zend_long) info->reactor_id); + zend_update_property_double( + swoole_server_event_ce, SW_Z8_OBJ_P(object), ZEND_STRL("dispatch_time"), info->time); + argc = 2; + } else { + ZVAL_LONG(&args[1], info->fd); + ZVAL_LONG(&args[2], info->reactor_id); + argc = 3; + } - if (serv->event_object) { - zval_ptr_dtor(&args[1]); - } + if (UNEXPECTED(!zend::function::call(fci_cache, argc, args, nullptr, serv->enable_coroutine))) { + php_swoole_error(E_WARNING, "%s->onConnect handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); + } + + if (serv->event_object) { + zval_ptr_dtor(&args[1]); } } @@ -2605,6 +2633,59 @@ static PHP_METHOD(swoole_server, addProcess) { RETURN_LONG(id); } +static PHP_METHOD(swoole_server, addCommand) { + Server *serv = php_swoole_server_get_and_check_server(ZEND_THIS); + if (serv->is_started()) { + php_swoole_fatal_error(E_WARNING, "server is running, can't add command"); + RETURN_FALSE; + } + + char *name; + size_t l_name; + zend_long accepted_process_types; + zend_fcall_info fci; + zend_fcall_info_cache *fci_cache = (zend_fcall_info_cache *) ecalloc(1, sizeof(zend_fcall_info_cache)); + + ZEND_PARSE_PARAMETERS_START(3, 3) + Z_PARAM_STRING(name, l_name) + Z_PARAM_LONG(accepted_process_types) + Z_PARAM_FUNC(fci, *fci_cache) + ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + + if (accepted_process_types & Server::Command::REACTOR_THREAD) { + php_swoole_fatal_error(E_WARNING, "only support worker/task_worker process"); + RETURN_FALSE; + } + + Server::Command::Handler fn = [fci_cache](Server *serv, const std::string &msg) { + zval *zserv = (zval *) serv->private_data_2; + zval argv[2]; + argv[0] = *zserv; + ZVAL_STRINGL(&argv[1], msg.c_str(), msg.length()); + zval return_value; + + if (UNEXPECTED(!zend::function::call(fci_cache, 2, argv, &return_value, false))) { + php_swoole_fatal_error(E_WARNING, "%s: command handler error", ZSTR_VAL(swoole_server_ce->name)); + return std::string("{\"data\": \"failed to call function\", \"code\": -1}"); + } + + if (!ZVAL_IS_STRING(&return_value)) { + return std::string("{\"data\": \"wrong return type\", \"code\": -2}"); + } + + return std::string(Z_STRVAL(return_value), Z_STRLEN(return_value)); + }; + + if (!serv->add_command(std::string(name, l_name), accepted_process_types, fn)) { + RETURN_FALSE; + } + + ServerObject *server_object = server_fetch_object(Z_OBJ_P(ZEND_THIS)); + sw_zend_fci_cache_persist(fci_cache); + server_object->property->command_callbacks.push_back(fci_cache); + RETURN_TRUE; +} + static PHP_METHOD(swoole_server, start) { zval *zserv = ZEND_THIS; Server *serv = php_swoole_server_get_and_check_server(zserv); @@ -2994,7 +3075,7 @@ static PHP_METHOD(swoole_server, taskwait) { // coroutine if (PHPCoroutine::get_cid() >= 0) { ServerObject *server_object = server_fetch_object(Z_OBJ_P((zval *) serv->private_data_2)); - SW_TASK_TYPE(&buf) |= (SW_TASK_NONBLOCK | SW_TASK_COROUTINE); + buf.info.flags |= (SW_TASK_NONBLOCK | SW_TASK_COROUTINE); TaskCo task_co{}; task_co.co = Coroutine::get_current_safe(); @@ -3130,7 +3211,7 @@ static PHP_METHOD(swoole_server, taskWaitMulti) { php_swoole_fatal_error(E_WARNING, "task pack failed"); goto _fail; } - SW_TASK_TYPE(&buf) |= SW_TASK_WAITALL; + buf.info.flags |= SW_TASK_WAITALL; dst_worker_id = -1; sw_atomic_fetch_add(&serv->gs->tasking_num, 1); if (serv->gs->task_workers.dispatch_blocking(&buf, &dst_worker_id) < 0) { @@ -3250,7 +3331,7 @@ static PHP_METHOD(swoole_server, taskCo) { php_swoole_fatal_error(E_WARNING, "failed to pack task"); goto _fail; } - SW_TASK_TYPE(&buf) |= (SW_TASK_NONBLOCK | SW_TASK_COROUTINE); + buf.info.flags |= (SW_TASK_NONBLOCK | SW_TASK_COROUTINE); dst_worker_id = -1; sw_atomic_fetch_add(&serv->gs->tasking_num, 1); if (serv->gs->task_workers.dispatch(&buf, &dst_worker_id) < 0) { @@ -3318,14 +3399,14 @@ static PHP_METHOD(swoole_server, task) { } if (!serv->is_worker()) { - SW_TASK_TYPE(&buf) |= SW_TASK_NOREPLY; + buf.info.flags |= SW_TASK_NOREPLY; } else if (fci.size) { - SW_TASK_TYPE(&buf) |= SW_TASK_CALLBACK; + buf.info.flags |= SW_TASK_CALLBACK; sw_zend_fci_cache_persist(&fci_cache); server_object->property->task_callbacks[buf.info.fd] = fci_cache; } - SW_TASK_TYPE(&buf) |= SW_TASK_NONBLOCK; + buf.info.flags |= SW_TASK_NONBLOCK; int _dst_worker_id = (int) dst_worker_id; sw_atomic_fetch_add(&serv->gs->tasking_num, 1); @@ -3338,6 +3419,70 @@ static PHP_METHOD(swoole_server, task) { RETURN_FALSE; } +static PHP_METHOD(swoole_server, command) { + char *name; + size_t l_name; + zend_long process_id, process_type; + zval *zdata; + zend_bool json_decode = true; + + Server *serv = php_swoole_server_get_and_check_server(ZEND_THIS); + if (sw_unlikely(!serv->is_started())) { + php_swoole_fatal_error(E_WARNING, "server is not running"); + RETURN_FALSE; + } + + ZEND_PARSE_PARAMETERS_START(4, 5) + Z_PARAM_STRING(name, l_name) + Z_PARAM_LONG(process_id) + Z_PARAM_LONG(process_type) + Z_PARAM_ZVAL(zdata) + Z_PARAM_OPTIONAL + Z_PARAM_BOOL(json_decode) + ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + + std::string msg; + + auto result = zend::function::call("json_encode", 1, zdata); + if (!ZVAL_IS_STRING(&result.value)) { + RETURN_FALSE; + } + msg.append(Z_STRVAL(result.value), Z_STRLEN(result.value)); + + auto co = Coroutine::get_current_safe(); + bool donot_yield = false; + Server::Command::Callback fn = [co, return_value, json_decode, &donot_yield](Server *serv, const std::string &msg) { + if (json_decode) { + zval argv[2]; + ZVAL_STRINGL(&argv[0], msg.c_str(), msg.length()); + ZVAL_BOOL(&argv[1], true); + auto result = zend::function::call("json_decode", 2, argv); + if (!zend_is_true(&result.value)) { + RETURN_FALSE; + } else { + ZVAL_DUP(return_value, &result.value); + } + zval_dtor(&argv[0]); + } else { + ZVAL_STRINGL(return_value, msg.c_str(), msg.length()); + } + + if (co->is_suspending()) { + co->resume(); + } else { + donot_yield = true; + } + }; + + if (!serv->command( + (uint16_t) process_id, (Server::Command::ProcessType) process_type, std::string(name, l_name), msg, fn)) { + RETURN_FALSE; + } + if (!donot_yield) { + co->yield(); + } +} + static PHP_METHOD(swoole_server, sendMessage) { Server *serv = php_swoole_server_get_and_check_server(ZEND_THIS); if (sw_unlikely(!serv->is_started())) { @@ -3431,7 +3576,7 @@ static PHP_METHOD(swoole_server_task, pack) { if (php_swoole_task_pack(&buf, zdata) < 0) { RETURN_FALSE; } - SW_TASK_TYPE(&buf) |= (SW_TASK_NONBLOCK | SW_TASK_NOREPLY); + buf.info.flags |= (SW_TASK_NONBLOCK | SW_TASK_NOREPLY); RETURN_STRINGL((char *) &buf, sizeof(buf.info) + buf.info.len); } @@ -3727,18 +3872,15 @@ static PHP_METHOD(swoole_server, getWorkerStatus) { static PHP_METHOD(swoole_server, getWorkerPid) { Server *serv = php_swoole_server_get_and_check_server(ZEND_THIS); - if (!serv->is_worker() && !serv->is_task_worker()) { - zend_long worker_id = -1; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &worker_id) == FAILURE) { - RETURN_FALSE; - } - if (worker_id < 0) { - RETURN_FALSE; - } - RETURN_LONG(serv->get_worker(worker_id)->pid); - } else { - RETURN_LONG(SwooleG.pid); + zend_long worker_id = -1; + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &worker_id) == FAILURE) { + RETURN_FALSE; + } + Worker *worker = worker_id < 0 ? SwooleWG.worker : serv->get_worker(worker_id); + if (!worker) { + RETURN_FALSE; } + RETURN_LONG(serv->get_worker(worker_id)->pid); } static PHP_METHOD(swoole_server, getManagerPid) { @@ -3759,7 +3901,7 @@ static PHP_METHOD(swoole_server, shutdown) { } if (swoole_kill(serv->gs->master_pid, SIGTERM) < 0) { - php_swoole_sys_error(E_WARNING, "failed to shutdown. swKill(%d, SIGTERM) failed", serv->gs->master_pid); + php_swoole_sys_error(E_WARNING, "failed to shutdown, kill(%d, SIGTERM) failed", serv->gs->master_pid); RETURN_FALSE; } else { RETURN_TRUE; diff --git a/include/swoole.h b/include/swoole.h index f9a68570125..f62d7c0649f 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -140,8 +140,8 @@ typedef unsigned long ulong_t; #define MIN(A, B) SW_MIN(A, B) #endif -#define SW_NUM_BILLION (1000 * 1000 * 1000) -#define SW_NUM_MILLION (1000 * 1000) +#define SW_NUM_BILLION (1000 * 1000 * 1000) +#define SW_NUM_MILLION (1000 * 1000) #ifdef SW_DEBUG #define SW_ASSERT(e) assert(e) @@ -227,8 +227,7 @@ typedef swoole::Event swEvent; #endif /** always return less than size, zero termination */ -size_t sw_snprintf(char *buf, size_t size, const char *format, ...) - __attribute__ ((format (printf, 3, 4))); +size_t sw_snprintf(char *buf, size_t size, const char *format, ...) __attribute__((format(printf, 3, 4))); size_t sw_vsnprintf(char *buf, size_t size, const char *format, va_list args); #define sw_memset_zero(s, n) memset(s, '\0', n) @@ -341,17 +340,17 @@ static inline void swoole_strtolower(char *str, int length) { /*--------------------------------Constants------------------------------------*/ enum swResultCode { - SW_OK = 0, + SW_OK = 0, SW_ERR = -1, }; enum swReturnCode { SW_CONTINUE = 1, - SW_WAIT = 2, - SW_CLOSE = 3, - SW_ERROR = 4, - SW_READY = 5, - SW_INVALID = 6, + SW_WAIT = 2, + SW_CLOSE = 3, + SW_ERROR = 4, + SW_READY = 5, + SW_INVALID = 6, }; enum swFdType { @@ -389,34 +388,34 @@ enum swFdType { enum swSocketFlag { SW_SOCK_NONBLOCK = 1 << 2, - SW_SOCK_CLOEXEC = 1 << 3, - SW_SOCK_SSL = (1u << 9), + SW_SOCK_CLOEXEC = 1 << 3, + SW_SOCK_SSL = (1u << 9), }; enum swSocketType { - SW_SOCK_TCP = 1, - SW_SOCK_UDP = 2, - SW_SOCK_TCP6 = 3, - SW_SOCK_UDP6 = 4, + SW_SOCK_TCP = 1, + SW_SOCK_UDP = 2, + SW_SOCK_TCP6 = 3, + SW_SOCK_UDP6 = 4, SW_SOCK_UNIX_STREAM = 5, // unix sock stream - SW_SOCK_UNIX_DGRAM = 6, // unix sock dgram - SW_SOCK_RAW = 7, + SW_SOCK_UNIX_DGRAM = 6, // unix sock dgram + SW_SOCK_RAW = 7, }; enum swEventType { - SW_EVENT_NULL = 0, + SW_EVENT_NULL = 0, SW_EVENT_DEAULT = 1u << 8, - SW_EVENT_READ = 1u << 9, - SW_EVENT_WRITE = 1u << 10, - SW_EVENT_RDWR = SW_EVENT_READ | SW_EVENT_WRITE, - SW_EVENT_ERROR = 1u << 11, - SW_EVENT_ONCE = 1u << 12, + SW_EVENT_READ = 1u << 9, + SW_EVENT_WRITE = 1u << 10, + SW_EVENT_RDWR = SW_EVENT_READ | SW_EVENT_WRITE, + SW_EVENT_ERROR = 1u << 11, + SW_EVENT_ONCE = 1u << 12, }; enum swForkType { - SW_FORK_SPAWN = 0, - SW_FORK_EXEC = 1 << 1, - SW_FORK_DAEMON = 1 << 2, + SW_FORK_SPAWN = 0, + SW_FORK_EXEC = 1 << 1, + SW_FORK_DAEMON = 1 << 2, SW_FORK_PRECHECK = 1 << 3, }; @@ -451,28 +450,23 @@ static sw_inline size_t swoole_size_align(size_t size, int pagesize) { //------------------------------Base-------------------------------- enum swEventDataFlag { SW_EVENT_DATA_NORMAL, - SW_EVENT_DATA_PTR = 1u << 1, - SW_EVENT_DATA_CHUNK = 1u << 2, - SW_EVENT_DATA_BEGIN = 1u << 3, - SW_EVENT_DATA_END = 1u << 4, + SW_EVENT_DATA_PTR = 1u << 1, + SW_EVENT_DATA_CHUNK = 1u << 2, + SW_EVENT_DATA_BEGIN = 1u << 3, + SW_EVENT_DATA_END = 1u << 4, SW_EVENT_DATA_OBJ_PTR = 1u << 5, SW_EVENT_DATA_POP_PTR = 1u << 6, }; -/** - * Use server_fd field to store flag of the server task - */ -#define SW_TASK_TYPE(task) ((task)->info.server_fd) - -enum swTaskType { - SW_TASK_TMPFILE = 1, // tmp file - SW_TASK_SERIALIZE = 2, // php serialize - SW_TASK_NONBLOCK = 4, // task - SW_TASK_CALLBACK = 8, // callback - SW_TASK_WAITALL = 16, // for taskWaitAll - SW_TASK_COROUTINE = 32, // coroutine - SW_TASK_PEEK = 64, // peek - SW_TASK_NOREPLY = 128, // don't reply +enum swTaskFlag { + SW_TASK_TMPFILE = 1, + SW_TASK_SERIALIZE = 1u << 1, + SW_TASK_NONBLOCK = 1u << 2, + SW_TASK_CALLBACK = 1u << 3, + SW_TASK_WAITALL = 1u << 4, + SW_TASK_COROUTINE = 1u << 5, + SW_TASK_PEEK = 1u << 6, + SW_TASK_NOREPLY = 1u << 7, }; enum swDNSLookupFlag { @@ -487,18 +481,18 @@ extern __thread char sw_error[SW_ERROR_MSG_SIZE]; #endif enum swProcessType { - SW_PROCESS_MASTER = 1, - SW_PROCESS_WORKER = 2, - SW_PROCESS_MANAGER = 3, + SW_PROCESS_MASTER = 1, + SW_PROCESS_WORKER = 2, + SW_PROCESS_MANAGER = 3, SW_PROCESS_TASKWORKER = 4, SW_PROCESS_USERWORKER = 5, }; enum swPipeType { - SW_PIPE_WORKER = 0, - SW_PIPE_MASTER = 1, - SW_PIPE_READ = 0, - SW_PIPE_WRITE = 1, + SW_PIPE_WORKER = 0, + SW_PIPE_MASTER = 1, + SW_PIPE_READ = 0, + SW_PIPE_WRITE = 1, SW_PIPE_NONBLOCK = 2, }; @@ -538,7 +532,7 @@ int swoole_set_cpu_affinity(cpu_set_t *set); #endif #ifdef HAVE_CLOCK_GETTIME -#define swoole_clock_gettime clock_gettime +#define swoole_clock_gettime clock_gettime #else int swoole_clock_gettime(int which_clock, struct timespec *t); #endif @@ -567,9 +561,12 @@ namespace swoole { typedef long SessionId; typedef long TaskId; typedef uint8_t ReactorId; +typedef uint32_t WorkerId; typedef enum swEventType EventType; typedef enum swSocketType SocketType; typedef enum swFdType FdType; +typedef enum swReturnCode ReturnCode; +typedef enum swResultCode ResultCode; struct Event { int fd; @@ -594,8 +591,6 @@ struct DataHead { struct EventData { DataHead info; char data[SW_IPC_BUFFER_SIZE]; - bool pack(const void *data, size_t data_len); - bool unpack(String *buffer); }; struct ThreadGlobal { @@ -665,8 +660,7 @@ struct Global { network::Socket *aio_default_socket; //-----------------------[Hook]-------------------------- void *hooks[SW_MAX_HOOK_TYPE]; - std::function user_exit_condition; - + std::function user_exit_condition; // bug report message std::string bug_report_message = ""; }; diff --git a/include/swoole_error.h b/include/swoole_error.h index 251ef3f4ba2..a7398b8c40b 100644 --- a/include/swoole_error.h +++ b/include/swoole_error.h @@ -143,11 +143,12 @@ enum swErrorCode { SW_ERROR_SERVER_SEND_IN_MASTER, SW_ERROR_SERVER_INVALID_REQUEST, SW_ERROR_SERVER_CONNECT_FAIL, + SW_ERROR_SERVER_INVALID_COMMAND, /** * Process exit timeout, forced to end. */ - SW_ERROR_SERVER_WORKER_EXIT_TIMEOUT, + SW_ERROR_SERVER_WORKER_EXIT_TIMEOUT = 9101, SW_ERROR_SERVER_WORKER_ABNORMAL_PIPE_DATA, SW_ERROR_SERVER_WORKER_UNPROCESSED_DATA, @@ -187,4 +188,4 @@ class Exception { Exception(int code); }; -} +} // namespace swoole diff --git a/include/swoole_process_pool.h b/include/swoole_process_pool.h index be89c2d2346..56b635598d7 100644 --- a/include/swoole_process_pool.h +++ b/include/swoole_process_pool.h @@ -27,13 +27,13 @@ #include "swoole_channel.h" #include "swoole_msg_queue.h" -enum swWorker_status { +enum swWorkerStatus { SW_WORKER_BUSY = 1, SW_WORKER_IDLE = 2, SW_WORKER_EXIT = 3, }; -enum swIPC_type { +enum swIPCMode { SW_IPC_NONE = 0, SW_IPC_UNIXSOCK = 1, SW_IPC_MSGQUEUE = 2, @@ -90,7 +90,6 @@ struct WorkerGlobal { bool run_always; bool shutdown; uint32_t max_request; - String **output_buffer; Worker *worker; time_t exit_time; uint32_t worker_concurrency = 0; @@ -136,7 +135,7 @@ struct Worker { /** * worker id */ - uint32_t id; + WorkerId id; Mutex *lock; @@ -151,7 +150,7 @@ struct Worker { ssize_t send_pipe_message(const void *buf, size_t n, int flags); - void set_status(enum swWorker_status _status) { + void set_status(enum swWorkerStatus _status) { status = _status; } @@ -288,7 +287,7 @@ struct ProcessPool { int add_worker(Worker *worker); int del_worker(Worker *worker); void destroy(); - int create(uint32_t worker_num, key_t msgqueue_key = 0, swIPC_type ipc_mode = SW_IPC_NONE); + int create(uint32_t worker_num, key_t msgqueue_key = 0, swIPCMode ipc_mode = SW_IPC_NONE); int listen(const char *socket_file, int blacklog); int listen(const char *host, int port, int blacklog); int schedule(); diff --git a/include/swoole_reactor.h b/include/swoole_reactor.h index 95eacd7a586..08a8dbd9108 100644 --- a/include/swoole_reactor.h +++ b/include/swoole_reactor.h @@ -22,6 +22,7 @@ #include #include +#include namespace swoole { @@ -111,7 +112,6 @@ class Reactor { */ int singal_no = 0; - uint32_t event_num = 0; uint32_t max_event_num = 0; bool running = false; @@ -168,14 +168,15 @@ class Reactor { std::function onBegin; - int (*write)(Reactor *reactor, network::Socket *socket, const void *buf, size_t n) = nullptr; - int (*writev)(Reactor *reactor, network::Socket *socket, const iovec *iov, size_t iovcnt) = nullptr; + ssize_t (*write)(Reactor *reactor, network::Socket *socket, const void *buf, size_t n) = nullptr; + ssize_t (*writev)(Reactor *reactor, network::Socket *socket, const iovec *iov, size_t iovcnt) = nullptr; int (*close)(Reactor *reactor, network::Socket *socket) = nullptr; private: ReactorImpl *impl; std::map> end_callbacks; - std::map> exit_conditions; + std::map> exit_conditions; + std::unordered_map sockets_; public: Reactor(int max_event = SW_REACTOR_MAXEVENTS, Type _type = TYPE_AUTO); @@ -183,7 +184,7 @@ class Reactor { bool if_exit(); void defer(Callback cb, void *data = nullptr); void set_end_callback(enum EndCallback id, const std::function &fn); - void set_exit_condition(enum ExitCondition id, const std::function &fn); + void set_exit_condition(enum ExitCondition id, const std::function &fn); bool set_handler(int _fdtype, ReactorHandler handler); void add_destroy_callback(Callback cb, void *data = nullptr); void execute_end_callbacks(bool timedout = false); @@ -263,6 +264,20 @@ class Reactor { return defer_tasks == nullptr ? timeout_msec : 0; } + size_t get_event_num() { + return sockets_.size(); + } + + const std::unordered_map &get_sockets() { + return sockets_; + } + + void foreach_socket(const std::function &callback) { + for (auto kv : sockets_) { + callback(kv.first, kv.second); + } + } + inline ReactorHandler get_handler(EventType event_type, FdType fd_type) { switch (event_type) { case SW_EVENT_READ: @@ -305,7 +320,7 @@ class Reactor { inline void _add(network::Socket *_socket, int events) { _socket->events = events; _socket->removed = 0; - event_num++; + sockets_[_socket->fd] = _socket; } inline void _set(network::Socket *_socket, int events) { @@ -315,7 +330,7 @@ class Reactor { inline void _del(network::Socket *_socket) { _socket->events = 0; _socket->removed = 1; - event_num--; + sockets_.erase(_socket->fd); } bool catch_error() { @@ -326,8 +341,8 @@ class Reactor { return false; } - static int _write(Reactor *reactor, network::Socket *socket, const void *buf, size_t n); - static int _writev(Reactor *reactor, network::Socket *socket, const iovec *iov, size_t iovcnt); + static ssize_t _write(Reactor *reactor, network::Socket *socket, const void *buf, size_t n); + static ssize_t _writev(Reactor *reactor, network::Socket *socket, const iovec *iov, size_t iovcnt); static int _close(Reactor *reactor, network::Socket *socket); static int _writable_callback(Reactor *reactor, Event *ev); diff --git a/include/swoole_server.h b/include/swoole_server.h index bf2504f8f03..68a6c50c813 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -50,6 +50,9 @@ namespace http_server { struct Request; } +class Server; +struct Manager; + struct Session { SessionId id; int fd; @@ -139,14 +142,6 @@ struct Connection { sw_atomic_t lock; }; -struct ReactorThread { - std::thread thread; - network::Socket *notify_pipe = nullptr; - uint32_t pipe_num = 0; - network::Socket *pipe_sockets = nullptr; - std::unordered_map send_buffers; -}; - struct WorkerStopMessage { pid_t pid; uint16_t worker_id; @@ -165,6 +160,24 @@ struct RecvData { struct PipeBuffer { DataHead info; char data[0]; + + bool is_begin() { + return info.flags & SW_EVENT_DATA_BEGIN; + } + + bool is_chunked() { + return info.flags & SW_EVENT_DATA_CHUNK; + } + + bool is_end() { + return info.flags & SW_EVENT_DATA_END; + } +}; + +//------------------------------------Packet------------------------------------------- +struct PacketPtr { + size_t length; + char *data; }; struct DgramPacket { @@ -174,18 +187,142 @@ struct DgramPacket { char data[0]; }; -//------------------------------------Packet------------------------------------------- struct PacketTask { size_t length; char tmpfile[SW_TASK_TMP_PATH_SIZE]; }; -struct PacketPtr { - DataHead info; - struct { - uint32_t length; - char *str; - } data; +class MessageBus { + private: + const Allocator *allocator_; + std::unordered_map> packet_pool_; + std::function id_generator_; + size_t buffer_size_; + PipeBuffer *buffer_ = nullptr; + bool always_chunked_transfer_ = false; + + String *get_packet_buffer(); + ReturnCode prepare_packet(uint16_t &recv_chunk_count, String *packet_buffer); + + public: + MessageBus() { + allocator_ = sw_std_allocator(); + buffer_size_ = SW_BUFFER_SIZE_STD; + } + + ~MessageBus() { + allocator_->free(buffer_); + } + + bool empty() { + return packet_pool_.empty(); + } + + void clear() { + packet_pool_.clear(); + } + + void set_allocator(const Allocator *allocator) { + allocator_ = allocator; + } + + void set_id_generator(const std::function &id_generator) { + id_generator_ = id_generator; + } + + void set_buffer_size(size_t buffer_size) { + buffer_size_ = buffer_size; + } + + void set_always_chunked_transfer() { + always_chunked_transfer_ = true; + } + + size_t get_buffer_size() { + return buffer_size_; + } + + bool alloc_buffer() { + void *_ptr = allocator_->malloc(sizeof(*buffer_) + buffer_size_); + if (_ptr) { + buffer_ = (PipeBuffer *) _ptr; + sw_memset_zero(&buffer_->info, sizeof(buffer_->info)); + return true; + } else { + return false; + } + } + + void pass(SendData *task) { + memcpy(&buffer_->info, &task->info, sizeof(buffer_->info)); + if (task->info.len > 0) { + buffer_->info.flags = SW_EVENT_DATA_PTR; + PacketPtr pkt{task->info.len, (char *) task->data}; + buffer_->info.len = sizeof(pkt); + memcpy(buffer_->data, &pkt, sizeof(pkt)); + } + } + + /** + * Send data to socket. If the data sent is larger than Server::ipc_max_size, then it is sent in chunks. + * Otherwise send it directly. + * @return: send success returns MsgId(must be greater than 0), send failure returns 0. + */ + bool write(network::Socket *sock, SendData *packet); + /** + * Receive data from socket, if only one chunk is received, packet will be saved in packet_pool. + * Then continue to listen to readable events, waiting for more chunks. + * @return: >0: receive a complete packet, 0: continue to wait for data, -1: an error occurred + */ + ssize_t read(network::Socket *sock); + /** + * Receive data from pipeline, and store data to buffer + * @return: >0: receive a complete packet, 0: continue to wait for data, -1: an error occurred + */ + ssize_t read_with_buffer(network::Socket *sock); + /** + * The last chunk of data has been received, return address and length, start processing this packet. + */ + PacketPtr get_packet(); + PipeBuffer *get_buffer() { + return buffer_; + } + /** + * Pop the data memory address to the outer layer, no longer managed by MessageBus + */ + char *move_packet() { + uint64_t msg_id = buffer_->info.msg_id; + auto iter = packet_pool_.find(msg_id); + if (iter != packet_pool_.end()) { + auto str = iter->second.get(); + char *val = str->str; + str->str = nullptr; + return val; + } else { + return nullptr; + } + } + /** + * The processing of this data packet has been completed, and the relevant memory has been released + */ + void pop() { + if (buffer_->is_end()) { + packet_pool_.erase(buffer_->info.msg_id); + } + } +}; + +//------------------------------------ReactorThread------------------------------------------- +struct ReactorThread { + int id; + std::thread thread; + network::Socket *notify_pipe = nullptr; + uint32_t pipe_num = 0; + network::Socket *pipe_sockets = nullptr; + network::Socket *pipe_command = nullptr; + MessageBus message_bus; + + int init(Server *serv, Reactor *reactor, uint16_t reactor_id); }; struct ListenPort { @@ -304,7 +441,7 @@ struct ListenPort { Protocol protocol = {}; void *ptr = nullptr; - int (*onRead)(Reactor *reactor, ListenPort *port, swEvent *event) = nullptr; + int (*onRead)(Reactor *reactor, ListenPort *port, Event *event) = nullptr; inline bool is_dgram() { return network::Socket::is_dgram(type); @@ -384,6 +521,7 @@ struct ServerGS { sw_atomic_long_t close_count; sw_atomic_long_t request_count; sw_atomic_long_t dispatch_count; + sw_atomic_long_t pipe_packet_msg_id; sw_atomic_t spinlock; @@ -391,9 +529,6 @@ struct ServerGS { ProcessPool event_workers; }; -class Server; -struct Manager; - class Factory { protected: Server *server_; @@ -426,7 +561,6 @@ class BaseFactory : public Factory { class ProcessFactory : public Factory { private: std::vector> pipes; - PipeBuffer *send_buffer; public: ProcessFactory(Server *server); @@ -444,6 +578,7 @@ enum ServerEventType { SW_SERVER_EVENT_RECV_DATA, SW_SERVER_EVENT_RECV_DGRAM, // send data + SW_SERVER_EVENT_SEND_DATA, SW_SERVER_EVENT_SEND_FILE, // connection event SW_SERVER_EVENT_CLOSE, @@ -454,9 +589,6 @@ enum ServerEventType { SW_SERVER_EVENT_FINISH, // pipe SW_SERVER_EVENT_PIPE_MESSAGE, - // proxy - SW_SERVER_EVENT_PROXY_START, - SW_SERVER_EVENT_PROXY_END, // event operate SW_SERVER_EVENT_PAUSE_RECV, SW_SERVER_EVENT_RESUME_RECV, @@ -466,12 +598,28 @@ enum ServerEventType { // process message SW_SERVER_EVENT_INCOMING, SW_SERVER_EVENT_SHUTDOWN, + SW_SERVER_EVENT_COMMAND, }; class Server { public: typedef int (*DispatchFunction)(Server *, Connection *, SendData *); + struct Command { + typedef std::function Callback; + typedef std::function Handler; + enum ProcessType { + MASTER = 1u << 1, + REACTOR_THREAD = 1u << 2, + EVENT_WORKER = 1u << 3, + TASK_WORKER = 1u << 4, + ALL_PROCESS = MASTER | REACTOR_THREAD | EVENT_WORKER | TASK_WORKER, + }; + int id; + int accepted_process_types; + std::string name; + }; + enum Mode { MODE_BASE = 1, MODE_PROCESS = 2, @@ -569,9 +717,6 @@ class Server { uint32_t max_wait_time = SW_WORKER_MAX_WAIT_TIME; /*----------------------------Reactor schedule--------------------------------*/ - const Allocator *worker_buffer_allocator; - std::unordered_map> worker_buffers; - std::atomic worker_msg_id; sw_atomic_t worker_round_id = 0; /** @@ -681,7 +826,9 @@ class Server { int *cpu_affinity_available = 0; int cpu_affinity_available_num = 0; - PipeBuffer **pipe_buffers = nullptr; + UnixSocket *pipe_command = nullptr; + MessageBus message_bus; + double send_timeout = 0; uint16_t heartbeat_check_interval = 0; @@ -746,6 +893,26 @@ class Server { return connection_list[fd].socket; } + /** + * [ReactorThread] + */ + network::Socket *get_worker_pipe_socket(Worker *worker) { + return &get_thread(SwooleTG.id)->pipe_sockets[worker->pipe_master->fd]; + } + + /** + * [Worker|Master] + */ + inline network::Socket *get_reactor_pipe_socket(SessionId session_id, int reactor_id) { + int pipe_index = session_id % reactor_pipe_num; + /** + * pipe_worker_id: The pipe in which worker. + */ + int pipe_worker_id = reactor_id + (pipe_index * reactor_num); + Worker *worker = get_worker(pipe_worker_id); + return worker->pipe_worker; + } + /** * task process */ @@ -759,11 +926,16 @@ class Server { /** * user process */ - uint32_t user_worker_num = 0; - std::vector *user_worker_list = nullptr; - std::unordered_map *user_worker_map = nullptr; + std::vector user_worker_list; + std::unordered_map user_worker_map; Worker *user_workers = nullptr; + std::unordered_map commands; + std::unordered_map command_handlers; + std::unordered_map command_callbacks; + int command_current_id = 1; + int64_t command_current_request_id = 1; + Worker *workers = nullptr; Channel *message_box = nullptr; ServerGS *gs = nullptr; @@ -801,7 +973,7 @@ class Server { EventData *last_task = nullptr; std::queue *buffer_pool = nullptr; - const Allocator *buffer_allocator = &SwooleG.std_allocator; + const Allocator *recv_buffer_allocator = &SwooleG.std_allocator; size_t recv_buffer_size = SW_BUFFER_SIZE_BIG; int manager_alarm = 0; @@ -813,6 +985,7 @@ class Server { void *hooks[SW_MAX_HOOK_TYPE] = {}; + /*----------------------------Event Callback--------------------------------*/ /** * Master Process */ @@ -848,31 +1021,6 @@ class Server { */ std::function onTask; std::function onFinish; - /** - * Chunk control - */ - size_t get_packet(EventData *req, char **data_ptr); - - String *get_worker_buffer(DataHead *info) { - auto iter = worker_buffers.find(info->msg_id); - if (iter == worker_buffers.end()) { - if (info->flags & SW_EVENT_DATA_BEGIN) { - auto buffer = make_string(info->len, worker_buffer_allocator); - worker_buffers.emplace(info->msg_id, std::shared_ptr(buffer)); - return buffer; - } - return nullptr; - } - return iter->second.get(); - } - - void pop_worker_buffer(DataHead *info) { - uint64_t msg_id = info->msg_id; - auto iter = worker_buffers.find(msg_id); - if (iter != worker_buffers.end()) { - iter->second.get()->str = nullptr; - } - } /** * Hook @@ -911,6 +1059,7 @@ class Server { ListenPort *add_port(SocketType type, const char *host, int port); int add_systemd_socket(); int add_hook(enum HookType type, const Callback &func, int push_back); + bool add_command(const std::string &command, int accepted_process_types, const Command::Handler &func); Connection *add_connection(ListenPort *ls, network::Socket *_socket, int server_fd); int connection_incoming(Reactor *reactor, Connection *conn); @@ -943,7 +1092,7 @@ class Server { inline String *get_recv_buffer(swSocket *_socket) { String *buffer = _socket->recv_buffer; if (buffer == nullptr) { - buffer = swoole::make_string(SW_BUFFER_SIZE_BIG, buffer_allocator); + buffer = swoole::make_string(SW_BUFFER_SIZE_BIG, recv_buffer_allocator); if (!buffer) { return nullptr; } @@ -957,19 +1106,6 @@ class Server { return is_base_mode() ? 1 : reactor_num + dgram_port_num; } - /** - * reactor_id: The fd in which the reactor. - */ - inline swSocket *get_reactor_thread_pipe(SessionId session_id, int reactor_id) { - int pipe_index = session_id % reactor_pipe_num; - /** - * pipe_worker_id: The pipe in which worker. - */ - int pipe_worker_id = reactor_id + (pipe_index * reactor_num); - Worker *worker = get_worker(pipe_worker_id); - return worker->pipe_worker; - } - inline bool is_support_unsafe_events() { if (dispatch_mode != DISPATCH_ROUND && dispatch_mode != DISPATCH_IDLE_WORKER && dispatch_mode != DISPATCH_STREAM) { @@ -1035,7 +1171,7 @@ class Server { } // User Worker - uint32_t user_worker_max = task_worker_max + user_worker_num; + uint32_t user_worker_max = task_worker_max + user_worker_list.size(); if (worker_id < user_worker_max) { return &(user_workers[worker_id - task_worker_max]); } @@ -1063,7 +1199,11 @@ class Server { } size_t get_all_worker_num() { - return worker_num + task_worker_num + user_worker_num; + return worker_num + task_worker_num + get_user_worker_num(); + } + + size_t get_user_worker_num() { + return user_worker_list.size(); } inline ReactorThread *get_thread(int reactor_id) { @@ -1074,6 +1214,10 @@ class Server { return gs->start; } + bool is_created() { + return factory != nullptr; + } + bool is_master() { return SwooleG.process_type == SW_PROCESS_MASTER; } @@ -1094,6 +1238,10 @@ class Server { return SwooleG.process_type == SW_PROCESS_USERWORKER; } + bool is_reactor_thread() { + return SwooleG.process_type == SW_PROCESS_MASTER && SwooleTG.type == Server::THREAD_REACTOR; + } + bool is_sync_process() { if (is_manager()) { return true; @@ -1126,6 +1274,8 @@ class Server { static int is_stream_event(uint8_t type) { switch (type) { case SW_SERVER_EVENT_RECV_DATA: + case SW_SERVER_EVENT_SEND_DATA: + case SW_SERVER_EVENT_SEND_FILE: case SW_SERVER_EVENT_CONNECT: case SW_SERVER_EVENT_CLOSE: case SW_SERVER_EVENT_PAUSE_RECV: @@ -1211,22 +1361,26 @@ class Server { void call_hook(enum HookType type, void *arg); void call_worker_start_callback(Worker *worker); - + ResultCode call_command_handler(MessageBus &mb, uint16_t worker_id, network::Socket *sock); + std::string call_command_handler_in_master(int command_id, const std::string &msg); + void call_command_callback(int64_t request_id, const std::string &result); void foreach_connection(const std::function &callback); - - int accept_task(EventData *task); static int accept_connection(Reactor *reactor, Event *event); #ifdef SW_SUPPORT_DTLS dtls::Session *accept_dtls_connection(ListenPort *ls, network::Address *sa); #endif + static int accept_command_result(Reactor *reactor, Event *event); static int close_connection(Reactor *reactor, network::Socket *_socket); static int dispatch_task(Protocol *proto, network::Socket *_socket, const char *data, uint32_t length); int send_to_connection(SendData *); - ssize_t send_to_worker_from_master(Worker *worker, const iovec *iov, size_t iovcnt); ssize_t send_to_worker_from_worker(Worker *dst_worker, const void *buf, size_t len, int flags); + + ssize_t send_to_worker_from_worker(WorkerId id, EventData *data, int flags) { + return send_to_worker_from_worker(get_worker(id), data, sizeof(data->info) + data->info.len, flags); + } + ssize_t send_to_reactor_thread(const EventData *ev_data, size_t sendn, SessionId session_id); - ssize_t send_to_reactor_thread(const DataHead *head, const iovec *iov, size_t iovcnt, SessionId session_id); int reply_task_result(const char *data, size_t data_len, int flags, EventData *current_task); bool send(SessionId session_id, const void *data, uint32_t length); @@ -1236,14 +1390,19 @@ class Server { bool notify(Connection *conn, enum ServerEventType event); bool feedback(Connection *conn, enum ServerEventType event); + bool command(WorkerId process_id, + Command::ProcessType process_type, + const std::string &name, + const std::string &msg, + const Command::Callback &fn); void init_reactor(Reactor *reactor); void init_worker(Worker *worker); void init_task_workers(); void init_port_protocol(ListenPort *port); void init_signal_handler(); + void init_ipc_max_size(); - void set_ipc_max_size(); void set_max_connection(uint32_t _max_connection); inline uint32_t get_max_connection() { @@ -1258,6 +1417,7 @@ class Server { } int create_pipe_buffers(); + void release_pipe_buffers(); void create_worker(Worker *worker); void destroy_worker(Worker *worker); void disable_accept(); @@ -1287,8 +1447,11 @@ class Server { */ void worker_start_callback(); void worker_stop_callback(); + void worker_accept_event(DataHead *info); static void worker_signal_handler(int signo); static void worker_signal_init(void); + static bool event_data_pack(EventData *edata, const void *data, size_t data_len); + static bool event_data_unpack(EventData *edata, String *buffer, PacketPtr *packet); private: enum Mode mode_; @@ -1318,6 +1481,7 @@ class Server { int create_reactor_threads(); int start_reactor_threads(); int start_reactor_processes(); + int start_master_thread(); int start_event_worker(Worker *worker); void start_heartbeat_thread(); void join_reactor_thread(); diff --git a/include/swoole_string.h b/include/swoole_string.h index f335e0d8e79..408c66d0758 100644 --- a/include/swoole_string.h +++ b/include/swoole_string.h @@ -202,6 +202,10 @@ class String { return append(append_str.c_str(), append_str.length()); } + inline int append(char c) { + return append(&c, sizeof(c)); + } + inline int append(const String &append_str) { size_t new_size = length + append_str.length; if (new_size > size) { diff --git a/src/core/base.cc b/src/core/base.cc index 73df2f88b6d..d7bac888a96 100644 --- a/src/core/base.cc +++ b/src/core/base.cc @@ -145,7 +145,7 @@ void swoole_init(void) { SwooleG.running = 1; SwooleG.init = 1; - SwooleG.std_allocator = { malloc, calloc, realloc, free }; + SwooleG.std_allocator = {malloc, calloc, realloc, free}; SwooleG.fatal_error = swoole_fatal_error_impl; SwooleG.cpu_num = SW_MAX(1, sysconf(_SC_NPROCESSORS_ONLN)); SwooleG.pagesize = getpagesize(); @@ -184,7 +184,7 @@ void swoole_init(void) { SwooleTG.buffer_stack = new swoole::String(SW_STACK_BUFFER_SIZE); - if (!swoole_set_task_tmpdir(SW_TASK_TMP_DIR) ) { + if (!swoole_set_task_tmpdir(SW_TASK_TMP_DIR)) { exit(4); } @@ -284,7 +284,7 @@ SW_API void swoole_set_dns_server(const std::string &server) { int dns_server_port = SW_DNS_SERVER_PORT; char dns_server_host[32]; strcpy(dns_server_host, server.c_str()); - if ((_port = strchr((char *)server.c_str(), ':'))) { + if ((_port = strchr((char *) server.c_str(), ':'))) { dns_server_port = atoi(_port + 1); if (dns_server_port <= 0 || dns_server_port > 65535) { dns_server_port = SW_DNS_SERVER_PORT; @@ -336,7 +336,8 @@ pid_t swoole_fork(int flags) { } if (SwooleTG.async_threads) { swoole_trace("aio_task_num=%d, reactor=%p", SwooleTG.async_threads->task_num, sw_reactor()); - swoole_fatal_error(SW_ERROR_OPERATION_NOT_SUPPORT, "can not create server after using async file operation"); + swoole_fatal_error(SW_ERROR_OPERATION_NOT_SUPPORT, + "can not create server after using async file operation"); } } if (flags & SW_FORK_PRECHECK) { @@ -833,9 +834,7 @@ void swoole_print_backtrace(void) { free(stacktrace); } #else -void swoole_print_backtrace(void) { - -} +void swoole_print_backtrace(void) {} #endif static void swoole_fatal_error_impl(int code, const char *format, ...) { @@ -855,22 +854,28 @@ namespace swoole { size_t DataHead::dump(char *_buf, size_t _len) { return sw_snprintf(_buf, _len, - "swDataHead[%p]\n" + "DataHead[%p]\n" "{\n" " long fd = %ld;\n" + " uint64_t msg_id = %lu;\n" " uint32_t len = %d;\n" " int16_t reactor_id = %d;\n" " uint8_t type = %d;\n" " uint8_t flags = %d;\n" " uint16_t server_fd = %d;\n" + " uint16_t ext_flags = %d;\n" + " double time = %f;\n" "}\n", this, fd, + msg_id, len, reactor_id, type, flags, - server_fd); + server_fd, + ext_flags, + time); } std::string dirname(const std::string &file) { diff --git a/src/core/timer.cc b/src/core/timer.cc index bb5f785043a..619475dbffc 100644 --- a/src/core/timer.cc +++ b/src/core/timer.cc @@ -77,7 +77,7 @@ bool Timer::init_reactor(Reactor *reactor) { reactor->set_end_callback(Reactor::PRIORITY_TIMER, [this](Reactor *) { select(); }); reactor->set_exit_condition(Reactor::EXIT_CONDITION_TIMER, - [this](Reactor *reactor, int &event_num) -> bool { return count() == 0; }); + [this](Reactor *reactor, size_t &event_num) -> bool { return count() == 0; }); reactor->add_destroy_callback([](void *) { if (swoole_timer_is_available()) { diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index 1078d5f14d9..f553d566eb2 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -1150,6 +1150,7 @@ bool Socket::listen(int backlog) { set_err(errno); return false; } + socket->get_name(&socket->info); #ifdef SW_USE_OPENSSL ssl_is_server = true; #endif diff --git a/src/coroutine/system.cc b/src/coroutine/system.cc index 7df50b93433..04a4b562226 100644 --- a/src/coroutine/system.cc +++ b/src/coroutine/system.cc @@ -267,7 +267,7 @@ bool System::wait_signal(int signo, double timeout) { if (!sw_reactor()->isset_exit_condition(Reactor::EXIT_CONDITION_CO_SIGNAL_LISTENER)) { sw_reactor()->set_exit_condition( Reactor::EXIT_CONDITION_CO_SIGNAL_LISTENER, - [](Reactor *reactor, int &event_num) -> bool { return SwooleTG.co_signal_listener_num == 0; }); + [](Reactor *reactor, size_t &event_num) -> bool { return SwooleTG.co_signal_listener_num == 0; }); } /* always enable signalfd */ SwooleG.use_signalfd = SwooleG.enable_signalfd = 1; diff --git a/src/network/stream.cc b/src/network/stream.cc index 03019f11662..177ed4ef49a 100644 --- a/src/network/stream.cc +++ b/src/network/stream.cc @@ -106,8 +106,8 @@ Stream::~Stream() { */ void Stream::set_protocol(Protocol *protocol) { protocol->get_package_length = Protocol::default_length_func; - protocol->package_length_size = 4; protocol->package_length_type = 'N'; + protocol->package_length_size = swoole_type_size(protocol->package_length_type); protocol->package_body_offset = 4; protocol->package_length_offset = 0; } diff --git a/src/os/async_thread.cc b/src/os/async_thread.cc index 387e93df7b0..efe16c8337e 100644 --- a/src/os/async_thread.cc +++ b/src/os/async_thread.cc @@ -400,7 +400,7 @@ AsyncThreads::AsyncThreads() { SwooleTG.async_threads = nullptr; }); - sw_reactor()->set_exit_condition(Reactor::EXIT_CONDITION_AIO_TASK, [](Reactor *reactor, int &event_num) -> bool { + sw_reactor()->set_exit_condition(Reactor::EXIT_CONDITION_AIO_TASK, [](Reactor *reactor, size_t &event_num) -> bool { if (SwooleTG.async_threads && SwooleTG.async_threads->task_num == 0) { event_num--; } diff --git a/src/os/pipe.cc b/src/os/pipe.cc index 2f183f8ce11..7a8ca544548 100644 --- a/src/os/pipe.cc +++ b/src/os/pipe.cc @@ -89,12 +89,12 @@ bool SocketPair::close(int which) { } SocketPair::~SocketPair() { - if (!master_socket) { + if (master_socket) { close(SW_PIPE_CLOSE_MASTER); } - if (!worker_socket) { + if (worker_socket) { close(SW_PIPE_CLOSE_WORKER); } } -} +} // namespace swoole diff --git a/src/os/process_pool.cc b/src/os/process_pool.cc index 531a5a362a8..d9e85176e6a 100644 --- a/src/os/process_pool.cc +++ b/src/os/process_pool.cc @@ -65,7 +65,7 @@ void ProcessPool::kill_timeout_worker(Timer *timer, TimerNode *tnode) { /** * Process manager */ -int ProcessPool::create(uint32_t _worker_num, key_t _msgqueue_key, swIPC_type _ipc_mode) { +int ProcessPool::create(uint32_t _worker_num, key_t _msgqueue_key, swIPCMode _ipc_mode) { worker_num = _worker_num; /** * Shared memory is used here diff --git a/src/os/signal.cc b/src/os/signal.cc index 0d736d64062..d15be9aa8b8 100644 --- a/src/os/signal.cc +++ b/src/os/signal.cc @@ -267,7 +267,7 @@ bool swoole_signalfd_setup(Reactor *reactor) { } if (!swoole_event_isset_handler(SW_FD_SIGNAL)) { swoole_event_set_handler(SW_FD_SIGNAL, swoole_signalfd_event_callback); - reactor->set_exit_condition(Reactor::EXIT_CONDITION_SIGNALFD, [](Reactor *reactor, int &event_num) -> bool { + reactor->set_exit_condition(Reactor::EXIT_CONDITION_SIGNALFD, [](Reactor *reactor, size_t &event_num) -> bool { event_num--; return true; }); diff --git a/src/os/wait.cc b/src/os/wait.cc index 8301a76befa..32a3cec1337 100644 --- a/src/os/wait.cc +++ b/src/os/wait.cc @@ -76,7 +76,7 @@ static void signal_init() { } #endif - reactor->set_exit_condition(Reactor::EXIT_CONDITION_WAIT_PID, [](Reactor *reactor, int &event_num) -> bool { + reactor->set_exit_condition(Reactor::EXIT_CONDITION_WAIT_PID, [](Reactor *reactor, size_t &event_num) -> bool { return swoole_coroutine_wait_count() == 0; }); diff --git a/src/protocol/http.cc b/src/protocol/http.cc index 86055a01634..44a7838d99a 100644 --- a/src/protocol/http.cc +++ b/src/protocol/http.cc @@ -52,7 +52,7 @@ bool Server::select_static_handler(http_server::Request *request, Connection *co char header_buffer[1024]; SendData response; response.info.fd = conn->session_id; - response.info.type = SW_SERVER_EVENT_RECV_DATA; + response.info.type = SW_SERVER_EVENT_SEND_DATA; if (handler.status_code == SW_HTTP_NOT_FOUND) { response.info.len = sw_snprintf(header_buffer, diff --git a/src/reactor/base.cc b/src/reactor/base.cc index d8ac882341c..d4be6cba97e 100644 --- a/src/reactor/base.cc +++ b/src/reactor/base.cc @@ -51,10 +51,10 @@ ReactorImpl *make_reactor_select(Reactor *_reactor); void ReactorImpl::after_removal_failure(network::Socket *_socket) { if (!_socket->silent_remove) { swoole_sys_warning("failed to delete events[fd=%d#%d, type=%d, events=%d]", - _socket->fd, - reactor_->id, - _socket->fd_type, - _socket->events); + _socket->fd, + reactor_->id, + _socket->fd_type, + _socket->events); } } @@ -114,7 +114,7 @@ Reactor::Reactor(int max_event, Type _type) { swoole_call_hook(SW_GLOBAL_HOOK_ON_REACTOR_CREATE, this); } - set_end_callback(Reactor::PRIORITY_DEFER_TASK, [](Reactor *reactor) { + set_end_callback(PRIORITY_DEFER_TASK, [](Reactor *reactor) { CallbackManager *cm = reactor->defer_tasks; if (cm) { reactor->defer_tasks = nullptr; @@ -123,30 +123,30 @@ Reactor::Reactor(int max_event, Type _type) { } }); - set_exit_condition(Reactor::EXIT_CONDITION_DEFER_TASK, - [](Reactor *reactor, int &event_num) -> bool { return reactor->defer_tasks == nullptr; }); + set_exit_condition(EXIT_CONDITION_DEFER_TASK, + [](Reactor *reactor, size_t &event_num) -> bool { return reactor->defer_tasks == nullptr; }); - set_end_callback(Reactor::PRIORITY_IDLE_TASK, [](Reactor *reactor) { + set_end_callback(PRIORITY_IDLE_TASK, [](Reactor *reactor) { if (reactor->idle_task.callback) { reactor->idle_task.callback(reactor->idle_task.data); } }); - set_end_callback(Reactor::PRIORITY_SIGNAL_CALLBACK, [](Reactor *reactor) { + set_end_callback(PRIORITY_SIGNAL_CALLBACK, [](Reactor *reactor) { if (sw_unlikely(reactor->singal_no)) { swoole_signal_callback(reactor->singal_no); reactor->singal_no = 0; } }); - set_end_callback(Reactor::PRIORITY_TRY_EXIT, [](Reactor *reactor) { + set_end_callback(PRIORITY_TRY_EXIT, [](Reactor *reactor) { if (reactor->wait_exit && reactor->if_exit()) { reactor->running = false; } }); #ifdef SW_USE_MALLOC_TRIM - set_end_callback(Reactor::PRIORITY_MALLOC_TRIM, [](Reactor *reactor) { + set_end_callback(PRIORITY_MALLOC_TRIM, [](Reactor *reactor) { time_t now = ::time(nullptr); if (reactor->last_malloc_trim_time < now - SW_MALLOC_TRIM_INTERVAL) { malloc_trim(SW_MALLOC_TRIM_PAD); @@ -155,8 +155,8 @@ Reactor::Reactor(int max_event, Type _type) { }); #endif - set_exit_condition(Reactor::EXIT_CONDITION_DEFAULT, - [](Reactor *reactor, int &event_num) -> bool { return event_num == 0; }); + set_exit_condition(EXIT_CONDITION_DEFAULT, + [](Reactor *reactor, size_t &event_num) -> bool { return event_num == 0; }); } bool Reactor::set_handler(int _fdtype, ReactorHandler handler) { @@ -167,11 +167,11 @@ bool Reactor::set_handler(int _fdtype, ReactorHandler handler) { return false; } - if (Reactor::isset_read_event(_fdtype)) { + if (isset_read_event(_fdtype)) { read_handler[fdtype] = handler; - } else if (Reactor::isset_write_event(_fdtype)) { + } else if (isset_write_event(_fdtype)) { write_handler[fdtype] = handler; - } else if (Reactor::isset_error_event(_fdtype)) { + } else if (isset_error_event(_fdtype)) { error_handler[fdtype] = handler; } else { swoole_warning("unknown fdtype"); @@ -182,7 +182,7 @@ bool Reactor::set_handler(int _fdtype, ReactorHandler handler) { } bool Reactor::if_exit() { - int _event_num = event_num; + size_t _event_num = get_event_num(); for (auto &kv : exit_conditions) { if (kv.second(this, _event_num) == false) { return false; @@ -210,7 +210,7 @@ int Reactor::_close(Reactor *reactor, Socket *socket) { using SendFunc = std::function; using AppendFunc = std::function; -static int write_func( +static ssize_t write_func( Reactor *reactor, Socket *socket, const size_t __len, const SendFunc &send_fn, const AppendFunc &append_fn) { ssize_t retval; Buffer *buffer = socket->out_buffer; @@ -281,10 +281,10 @@ static int write_func( } append_fn(buffer); } - return SW_OK; + return __len; } -int Reactor::_write(Reactor *reactor, Socket *socket, const void *buf, size_t n) { +ssize_t Reactor::_write(Reactor *reactor, Socket *socket, const void *buf, size_t n) { ssize_t send_bytes = 0; auto send_fn = [&send_bytes, socket, buf, n]() -> ssize_t { send_bytes = socket->send(buf, n, 0); @@ -297,7 +297,7 @@ int Reactor::_write(Reactor *reactor, Socket *socket, const void *buf, size_t n) return write_func(reactor, socket, n, send_fn, append_fn); } -int Reactor::_writev(Reactor *reactor, network::Socket *socket, const iovec *iov, size_t iovcnt) { +ssize_t Reactor::_writev(Reactor *reactor, network::Socket *socket, const iovec *iov, size_t iovcnt) { #ifdef SW_USE_OPENSSL if (socket->ssl) { swoole_error_log(SW_LOG_WARNING, SW_ERROR_OPERATION_NOT_SUPPORT, "does not support SSL"); @@ -383,7 +383,7 @@ void Reactor::set_end_callback(enum EndCallback id, const std::function &fn) { +void Reactor::set_exit_condition(enum ExitCondition id, const std::function &fn) { exit_conditions[id] = fn; } diff --git a/src/reactor/epoll.cc b/src/reactor/epoll.cc index 7d167cc1b05..899433f6ace 100644 --- a/src/reactor/epoll.cc +++ b/src/reactor/epoll.cc @@ -18,8 +18,6 @@ #include "swoole_socket.h" #include "swoole_reactor.h" -#define EVENT_DEBUG 0 - #ifdef HAVE_EPOLL #include #ifndef EPOLLRDHUP @@ -66,15 +64,6 @@ class ReactorEpoll : public ReactorImpl { } }; -#if EVENT_DEBUG -#include -static thread_local std::unordered_map event_map; - -Socket *swoole_event_map_get(int sockfd) { - return event_map[sockfd]; -} -#endif - ReactorImpl *make_reactor_epoll(Reactor *_reactor, int max_events) { return new ReactorEpoll(_reactor, max_events); } @@ -114,10 +103,6 @@ int ReactorEpoll::add(Socket *socket, int events) { return SW_ERR; } -#if EVENT_DEBUG - event_map[socket->fd] = socket; -#endif - reactor_->_add(socket, events); swoole_trace_log( SW_TRACE_EVENT, "add events[fd=%d#%d, type=%d, events=%d]", socket->fd, reactor_->id, socket->fd_type, events); @@ -140,10 +125,6 @@ int ReactorEpoll::del(Socket *_socket) { } } -#if EVENT_DEBUG - event_map.erase(_socket->fd); -#endif - swoole_trace_log(SW_TRACE_REACTOR, "remove event[reactor_id=%d|fd=%d]", reactor_->id, _socket->fd); reactor_->_del(_socket); @@ -170,7 +151,7 @@ int ReactorEpoll::set(Socket *socket, int events) { } int ReactorEpoll::wait(struct timeval *timeo) { - swEvent event; + Event event; ReactorHandler handler; int i, n, ret; diff --git a/src/reactor/poll.cc b/src/reactor/poll.cc index a0d7f89673d..cea35d857f7 100644 --- a/src/reactor/poll.cc +++ b/src/reactor/poll.cc @@ -66,8 +66,8 @@ int ReactorPoll::add(Socket *socket, int events) { return SW_ERR; } - int cur = reactor_->event_num; - if (reactor_->event_num == max_fd_num) { + int cur = reactor_->get_event_num(); + if (reactor_->get_event_num() == max_fd_num) { swoole_warning("too many connection, more than %d", max_fd_num); return SW_ERR; } @@ -98,7 +98,7 @@ int ReactorPoll::set(Socket *socket, int events) { swoole_trace("fd=%d, events=%d", socket->fd, events); - for (i = 0; i < reactor_->event_num; i++) { + for (i = 0; i < reactor_->get_event_num(); i++) { // found if (events_[i].fd == socket->fd) { events_[i].events = 0; @@ -126,10 +126,10 @@ int ReactorPoll::del(Socket *socket) { return SW_ERR; } - for (uint32_t i = 0; i < reactor_->event_num; i++) { + for (uint32_t i = 0; i < reactor_->get_event_num(); i++) { if (events_[i].fd == socket->fd) { - for (; i < reactor_->event_num; i++) { - if (i == reactor_->event_num) { + for (; i < reactor_->get_event_num(); i++) { + if (i == reactor_->get_event_num()) { fds_[i] = nullptr; events_[i].fd = 0; events_[i].events = 0; @@ -166,7 +166,7 @@ int ReactorPoll::wait(struct timeval *timeo) { if (reactor_->onBegin != nullptr) { reactor_->onBegin(reactor_); } - ret = poll(events_, reactor_->event_num, reactor_->get_timeout_msec()); + ret = poll(events_, reactor_->get_event_num(), reactor_->get_timeout_msec()); if (ret < 0) { if (!reactor_->catch_error()) { swoole_sys_warning("poll error"); @@ -178,7 +178,7 @@ int ReactorPoll::wait(struct timeval *timeo) { reactor_->execute_end_callbacks(true); SW_REACTOR_CONTINUE; } else { - for (uint32_t i = 0; i < reactor_->event_num; i++) { + for (uint32_t i = 0; i < reactor_->get_event_num(); i++) { event.socket = fds_[i]; event.fd = events_[i].fd; event.reactor_id = reactor_->id; @@ -230,7 +230,7 @@ int ReactorPoll::wait(struct timeval *timeo) { } bool ReactorPoll::exists(int fd) { - for (uint32_t i = 0; i < reactor_->event_num; i++) { + for (uint32_t i = 0; i < reactor_->get_event_num(); i++) { if (events_[i].fd == fd) { return true; } diff --git a/src/server/base.cc b/src/server/base.cc index a1fb79cbfdc..9127baae0b3 100644 --- a/src/server/base.cc +++ b/src/server/base.cc @@ -28,7 +28,6 @@ bool BaseFactory::shutdown() { } bool BaseFactory::dispatch(SendData *task) { - PacketPtr pkg{}; Connection *conn = nullptr; if (Server::is_stream_event(task->info.type)) { @@ -46,25 +45,19 @@ bool BaseFactory::dispatch(SendData *task) { task->info.fd = conn->session_id; task->info.server_fd = conn->server_fd; } - // with data - if (task->info.len > 0) { - memcpy(&pkg.info, &task->info, sizeof(pkg.info)); - pkg.info.flags = SW_EVENT_DATA_PTR; - pkg.data.length = task->info.len; - pkg.data.str = (char *) task->data; + if (task->info.len > 0) { if (conn && conn->socket->recv_buffer && task->data == conn->socket->recv_buffer->str && conn->socket->recv_buffer->offset > 0 && conn->socket->recv_buffer->length == (size_t) conn->socket->recv_buffer->offset) { - pkg.info.flags |= SW_EVENT_DATA_POP_PTR; + task->info.flags |= SW_EVENT_DATA_POP_PTR; } - - return server_->accept_task((EventData *) &pkg) == SW_OK; - } - // no data - else { - return server_->accept_task((EventData *) &task->info) == SW_OK; } + + server_->message_bus.pass(task); + server_->worker_accept_event(&server_->message_bus.get_buffer()->info); + + return true; } /** @@ -86,7 +79,9 @@ bool BaseFactory::notify(DataHead *info) { info->server_fd = conn->server_fd; info->flags = SW_EVENT_DATA_NORMAL; - return server_->accept_task((EventData *) info) == SW_OK; + server_->worker_accept_event(info); + + return true; } bool BaseFactory::end(SessionId session_id, int flags) { @@ -98,14 +93,16 @@ bool BaseFactory::end(SessionId session_id, int flags) { Session *session = server_->get_session(session_id); if (!session->fd) { - swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_NOT_EXIST, - "failed to close connection, session#%ld does not exist", session_id); + swoole_error_log(SW_LOG_NOTICE, + SW_ERROR_SESSION_NOT_EXIST, + "failed to close connection, session#%ld does not exist", + session_id); return false; } if (session->reactor_id != SwooleG.process_id) { Worker *worker = server_->get_worker(session->reactor_id); - if (worker->pipe_master->send_async((const char*) &_send.info, sizeof(_send.info)) < 0) { + if (worker->pipe_master->send_async((const char *) &_send.info, sizeof(_send.info)) < 0) { swoole_sys_warning("failed to send %lu bytes to pipe_master", sizeof(_send.info)); return false; } @@ -116,7 +113,7 @@ bool BaseFactory::end(SessionId session_id, int flags) { if (conn == nullptr) { swoole_set_last_error(SW_ERROR_SESSION_NOT_EXIST); return false; - } + } // Reset send buffer, Immediately close the connection. if (flags & Server::CLOSE_RESET) { conn->close_reset = 1; @@ -176,36 +173,18 @@ bool BaseFactory::finish(SendData *data) { Worker *worker = server_->gs->event_workers.get_worker(session->reactor_id); EventData proxy_msg{}; - if (data->info.type == SW_SERVER_EVENT_RECV_DATA) { - proxy_msg.info.fd = session_id; - proxy_msg.info.reactor_id = SwooleG.process_id; - proxy_msg.info.type = SW_SERVER_EVENT_PROXY_START; - - size_t send_n = data->info.len; - size_t offset = 0; - - while (send_n > 0) { - if (send_n > SW_IPC_BUFFER_SIZE) { - proxy_msg.info.len = SW_IPC_BUFFER_SIZE; - } else { - proxy_msg.info.type = SW_SERVER_EVENT_PROXY_END; - proxy_msg.info.len = send_n; - } - memcpy(proxy_msg.data, data->data + offset, proxy_msg.info.len); - send_n -= proxy_msg.info.len; - offset += proxy_msg.info.len; - size_t __len = sizeof(proxy_msg.info) + proxy_msg.info.len; - if (worker->pipe_master->send_async((const char*) &proxy_msg, __len) < 0) { - swoole_sys_warning("failed to send %lu bytes to pipe_master", __len); - return false; - } + if (data->info.type == SW_SERVER_EVENT_SEND_DATA) { + if (!server_->message_bus.write(worker->pipe_master, data)) { + swoole_sys_warning("failed to send %u bytes to pipe_master", data->info.len); + return false; } - swoole_trace("proxy message, fd=%d, len=%ld", worker->pipe_master->fd, sizeof(proxy_msg.info) + proxy_msg.info.len); + swoole_trace( + "proxy message, fd=%d, len=%ld", worker->pipe_master->fd, sizeof(proxy_msg.info) + proxy_msg.info.len); } else if (data->info.type == SW_SERVER_EVENT_SEND_FILE) { memcpy(&proxy_msg.info, &data->info, sizeof(proxy_msg.info)); memcpy(proxy_msg.data, data->data, data->info.len); - size_t __len = sizeof(proxy_msg.info) + proxy_msg.info.len; - return worker->pipe_master->send_async((const char*) &proxy_msg, __len); + size_t __len = sizeof(proxy_msg.info) + proxy_msg.info.len; + return worker->pipe_master->send_async((const char *) &proxy_msg, __len); } else { swoole_warning("unkown event type[%d]", data->info.type); return false; diff --git a/src/server/manager.cc b/src/server/manager.cc index 759b478e861..7184b9d7b4c 100644 --- a/src/server/manager.cc +++ b/src/server/manager.cc @@ -121,13 +121,13 @@ int Server::start_manager_process() { } // User Worker Process - if (user_worker_num > 0) { + if (get_user_worker_num() > 0) { if (create_user_workers() < 0) { return SW_ERR; } int i = 0; - for (auto worker : *user_worker_list) { + for (auto worker : user_worker_list) { memcpy(&user_workers[i], worker, sizeof(user_workers[i])); create_worker(worker); i++; @@ -170,8 +170,8 @@ int Server::start_manager_process() { } } - if (user_worker_list) { - for (auto worker : *user_worker_list) { + if (!user_worker_list.empty()) { + for (auto worker : user_worker_list) { if (worker->pipe_object) { store_pipe_fd(worker->pipe_object); } @@ -210,6 +210,7 @@ void Server::check_worker_exit_status(int worker_id, const ExitStatus &exit_stat exit_status.get_code(), exit_status.get_signal(), exit_status.get_signal() == SIGSEGV ? SwooleG.bug_report_message.c_str() : ""); + if (onWorkerError != nullptr) { onWorkerError(this, worker_id, exit_status); } @@ -390,7 +391,7 @@ void Manager::start(Server *_server) { } } // user process - if (_server->user_worker_map != nullptr) { + if (!_server->user_worker_map.empty()) { Server::wait_other_worker(&_server->gs->event_workers, exit_status); } if (exit_status.get_pid() == reload_worker_pid && reloading) { @@ -415,7 +416,8 @@ void Manager::start(Server *_server) { reload_worker_i++; goto _kill_worker; } - swoole_sys_warning("swKill(%d, SIGTERM) [%d] failed", reload_workers[reload_worker_i].pid, reload_worker_i); + swoole_sys_warning( + "swKill(%d, SIGTERM) [%d] failed", reload_workers[reload_worker_i].pid, reload_worker_i); } } } @@ -434,8 +436,8 @@ void Manager::start(Server *_server) { kill_workers.push_back(_server->gs->task_workers.workers[i].pid); } } - if (_server->user_worker_map) { - for (auto kv : *_server->user_worker_map) { + if (!_server->user_worker_map.empty()) { + for (auto kv : _server->user_worker_map) { kill_workers.push_back(kv.second->pid); } } @@ -526,9 +528,9 @@ int Server::wait_other_worker(ProcessPool *pool, const ExitStatus &exit_status) break; } } - if (serv->user_worker_map) { - auto iter = serv->user_worker_map->find(exit_status.get_pid()); - if (iter != serv->user_worker_map->end()) { + if (!serv->user_worker_map.empty()) { + auto iter = serv->user_worker_map.find(exit_status.get_pid()); + if (iter != serv->user_worker_map.end()) { worker_type = SW_PROCESS_USERWORKER; exit_worker = iter->second; break; @@ -560,15 +562,15 @@ int Server::wait_other_worker(ProcessPool *pool, const ExitStatus &exit_status) * kill and wait all user process */ void Server::kill_user_workers() { - if (!user_worker_map) { + if (user_worker_map.empty()) { return; } - for (auto &kv : *user_worker_map) { + for (auto &kv : user_worker_map) { swoole_kill(kv.second->pid, SIGTERM); } - for (auto &kv : *user_worker_map) { + for (auto &kv : user_worker_map) { int __stat_loc; if (swoole_waitpid(kv.second->pid, &__stat_loc, 0) < 0) { swoole_sys_warning("waitpid(%d) failed", kv.second->pid); @@ -586,11 +588,11 @@ void Server::kill_event_workers() { return; } - for (uint32_t i = 0; i < worker_num; i++) { + SW_LOOP_N(worker_num) { swoole_trace("[Manager]kill worker processor"); swoole_kill(workers[i].pid, SIGTERM); } - for (uint32_t i = 0; i < worker_num; i++) { + SW_LOOP_N(worker_num) { if (swoole_waitpid(workers[i].pid, &status, 0) < 0) { swoole_sys_warning("waitpid(%d) failed", workers[i].pid); } @@ -646,14 +648,14 @@ pid_t Server::spawn_user_worker(Worker *worker) { // parent else { if (worker->pid) { - user_worker_map->erase(worker->pid); + user_worker_map.erase(worker->pid); } /** * worker: local memory * user_workers: shared memory */ get_worker(worker->id)->pid = worker->pid = pid; - user_worker_map->emplace(std::make_pair(pid, worker)); + user_worker_map.emplace(std::make_pair(pid, worker)); return pid; } } diff --git a/src/server/master.cc b/src/server/master.cc index dcc802523f4..33f6c967069 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -93,6 +93,68 @@ void Server::close_port(bool only_stream_port) { } } +void Server::call_command_callback(int64_t request_id, const std::string &result) { + auto iter = command_callbacks.find(request_id); + if (iter == command_callbacks.end()) { + swoole_error_log( + SW_LOG_ERROR, SW_ERROR_SERVER_INVALID_COMMAND, "Invalid command result[request_id=%lu]", request_id); + return; + } + iter->second(this, result); +} + +ResultCode Server::call_command_handler(MessageBus &mb, uint16_t worker_id, Socket *sock) { + PipeBuffer *buffer = mb.get_buffer(); + int command_id = buffer->info.server_fd; + auto iter = command_handlers.find(command_id); + if (iter == command_handlers.end()) { + swoole_error_log(SW_LOG_ERROR, SW_ERROR_SERVER_INVALID_COMMAND, "Unknown command[%d]", command_id); + return SW_OK; + } + + Server::Command::Handler handler = iter->second; + auto packet = mb.get_packet(); + auto result = handler(this, std::string(packet.data, packet.length)); + + SendData task{}; + task.info.fd = buffer->info.fd; + task.info.reactor_id = worker_id; + task.info.server_fd = -1; + task.info.type = SW_SERVER_EVENT_COMMAND; + task.info.len = result.length(); + task.data = result.c_str(); + + return mb.write(sock, &task) ? SW_OK : SW_ERR; +} + +std::string Server::call_command_handler_in_master(int command_id, const std::string &msg) { + auto iter = command_handlers.find(command_id); + if (iter == command_handlers.end()) { + swoole_error_log(SW_LOG_ERROR, SW_ERROR_SERVER_INVALID_COMMAND, "Unknown command[%d]", command_id); + return ""; + } + + Server::Command::Handler handler = iter->second; + return handler(this, msg); +} + +int Server::accept_command_result(Reactor *reactor, Event *event) { + Server *serv = (Server *) reactor->ptr; + + if (serv->message_bus.read(event->socket) <= 0) { + return SW_OK; + } + + auto packet = serv->message_bus.get_packet(); + std::string result(packet.data, packet.length); + + auto buffer = serv->message_bus.get_buffer(); + serv->call_command_callback(buffer->info.fd, result); + serv->message_bus.pop(); + + return SW_OK; +} + int Server::accept_connection(Reactor *reactor, Event *event) { Server *serv = (Server *) reactor->ptr; ListenPort *listen_host = serv->get_port_by_server_fd(event->fd); @@ -115,10 +177,10 @@ int Server::accept_connection(Reactor *reactor, Event *event) { } swoole_trace("[Master] Accept new connection. maxfd=%d|minfd=%d|reactor_id=%d|conn=%d", - serv->get_maxfd(), - serv->get_minfd(), - reactor->id, - sock->fd); + serv->get_maxfd(), + serv->get_minfd(), + reactor->id, + sock->fd); // too many connection if (sock->fd >= (int) serv->max_connection) { @@ -188,6 +250,7 @@ int Server::connection_incoming(Reactor *reactor, Connection *conn) { // notify worker process if (onConnect) { if (!notify(conn, SW_SERVER_EVENT_CONNECT)) { + printf("notify faile\n"); return SW_ERR; } } @@ -353,6 +416,46 @@ int Server::start_check() { return SW_OK; } +int Server::start_master_thread() { + SwooleTG.type = THREAD_MASTER; + SwooleTG.update_time = 1; + + Reactor *reactor = sw_reactor(); + + if (SwooleTG.timer && SwooleTG.timer->get_reactor() == nullptr) { + SwooleTG.timer->reinit(reactor); + } + + SwooleG.pid = getpid(); + SwooleG.process_type = SW_PROCESS_MASTER; + + reactor->ptr = this; + reactor->set_handler(SW_FD_STREAM_SERVER, Server::accept_connection); + + if (hooks[Server::HOOK_MASTER_START]) { + call_hook(Server::HOOK_MASTER_START, this); + } + + if (pipe_command) { + reactor->set_handler(SW_FD_PIPE, Server::accept_command_result); + reactor->add(pipe_command->get_socket(true), SW_EVENT_READ); + } + + /** + * 1 second timer + */ + if ((master_timer = swoole_timer_add(1000, true, Server::timer_callback, this)) == nullptr) { + swoole_event_free(); + return SW_ERR; + } + + if (onStart) { + onStart(this); + } + + return swoole_event_wait(); +} + void Server::store_listen_socket() { for (auto ls : ports) { int sockfd = ls->socket->fd; @@ -374,7 +477,7 @@ void Server::store_listen_socket() { */ int Server::create_task_workers() { key_t key = 0; - swIPC_type ipc_mode; + swIPCMode ipc_mode; if (task_ipc_mode == TASK_IPC_MSGQUEUE || task_ipc_mode == TASK_IPC_PREEMPTIVE) { key = message_queue_key; @@ -417,20 +520,11 @@ int Server::create_task_workers() { * @return: SW_OK|SW_ERR */ int Server::create_user_workers() { - /** - * if Swoole\Server::addProcess is called first, - * Server::user_worker_list is initialized in the Server_add_worker function - */ - if (user_worker_list == nullptr) { - user_worker_list = new std::vector; - } - - user_workers = (Worker *) sw_shm_calloc(user_worker_num, sizeof(Worker)); + user_workers = (Worker *) sw_shm_calloc(get_user_worker_num(), sizeof(Worker)); if (user_workers == nullptr) { swoole_sys_warning("gmalloc[server->user_workers] failed"); return SW_ERR; } - return SW_OK; } @@ -545,8 +639,7 @@ int Server::start() { gs->event_workers.worker_num = worker_num; gs->event_workers.use_msgqueue = 0; - uint32_t i; - for (i = 0; i < worker_num; i++) { + SW_LOOP_N(worker_num) { gs->event_workers.workers[i].pool = &gs->event_workers; gs->event_workers.workers[i].id = i; gs->event_workers.workers[i].type = SW_PROCESS_WORKER; @@ -572,16 +665,14 @@ int Server::start() { } } - /** - * user worker process - */ - if (user_worker_list) { - i = 0; - for (auto worker : *user_worker_list) { + if (!user_worker_list.empty()) { + uint32_t i = 0; + for (auto worker : user_worker_list) { worker->id = worker_num + task_worker_num + i; i++; } } + running = true; // factory start if (!factory->start()) { @@ -647,8 +738,8 @@ Server::Server(enum Mode _mode) { swoole_error("[Master] Fatal Error: failed to allocate memory for Server->gs"); } - worker_msg_id = 1; - worker_buffer_allocator = sw_std_allocator(); + gs->pipe_packet_msg_id = 1; + message_bus.set_id_generator([this]() { return sw_atomic_fetch_add(&gs->pipe_packet_msg_id, 1); }); g_server_instance = this; } @@ -664,7 +755,7 @@ Server::~Server() { } int Server::create() { - if (factory) { + if (is_created()) { return SW_ERR; } @@ -700,13 +791,14 @@ int Server::create() { } if (max_connection < minimum_connection) { max_connection = SwooleG.max_sockets; - swoole_warning("max_connection must be bigger than %u, it's reset to %u", minimum_connection, SwooleG.max_sockets); + swoole_warning( + "max_connection must be bigger than %u, it's reset to %u", minimum_connection, SwooleG.max_sockets); } // Reactor Thread Num if (reactor_num > SW_CPU_NUM * SW_MAX_THREAD_NCPU) { swoole_warning("serv->reactor_num == %d, Too many threads, reset to max value %d", - reactor_num, - SW_CPU_NUM * SW_MAX_THREAD_NCPU); + reactor_num, + SW_CPU_NUM * SW_MAX_THREAD_NCPU); reactor_num = SW_CPU_NUM * SW_MAX_THREAD_NCPU; } else if (reactor_num == 0) { reactor_num = SW_CPU_NUM; @@ -727,8 +819,8 @@ int Server::create() { if (task_worker_num > 0) { if (task_worker_num > SW_CPU_NUM * SW_MAX_WORKER_NCPU) { swoole_warning("serv->task_worker_num == %d, Too many processes, reset to max value %d", - task_worker_num, - SW_CPU_NUM * SW_MAX_WORKER_NCPU); + task_worker_num, + SW_CPU_NUM * SW_MAX_WORKER_NCPU); task_worker_num = SW_CPU_NUM * SW_MAX_WORKER_NCPU; } } @@ -789,6 +881,9 @@ void Server::shutdown() { } reactor->del(port->socket); } + if (pipe_command) { + reactor->del(pipe_command->get_socket(true)); + } clear_timer(); } @@ -826,15 +921,6 @@ void Server::destroy() { port->close(); } - /** - * because the Worker in user_worker_list is the memory allocated by emalloc, - * the efree function will be called when the user process is destructed, - * so there's no need to call the efree here. - */ - if (user_worker_list) { - delete user_worker_list; - user_worker_list = nullptr; - } if (user_workers) { sw_shm_free(user_workers); user_workers = nullptr; @@ -904,6 +990,102 @@ bool Server::feedback(Connection *conn, enum ServerEventType event) { } } +bool Server::command(WorkerId process_id, + Command::ProcessType process_type, + const std::string &name, + const std::string &msg, + const Command::Callback &fn) { + if (!is_started()) { + return false; + } + auto iter = commands.find(name); + if (iter == commands.end()) { + swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SERVER_INVALID_COMMAND, "Unknown command[%s]", name.c_str()); + return false; + } + + if (is_process_mode() && !is_master()) { + swoole_error_log(SW_LOG_NOTICE, SW_ERROR_INVALID_PARAMS, "command() can only be used in master process"); + return false; + } else if (is_base_mode() && SwooleWG.worker->id != 0) { + swoole_error_log(SW_LOG_NOTICE, SW_ERROR_INVALID_PARAMS, "command() can only be used in worker process 0"); + return false; + } + + if (is_base_mode() && process_type == Command::EVENT_WORKER && process_id == 0) { + process_type = Command::MASTER; + } + + int command_id = iter->second.id; + int64_t requset_id = command_current_request_id++; + Socket *pipe_sock; + + SendData task{}; + task.info.fd = requset_id; + task.info.reactor_id = process_id; + task.info.server_fd = command_id; + task.info.type = SW_SERVER_EVENT_COMMAND; + task.info.len = msg.length(); + task.data = msg.c_str(); + + if (!(process_type & iter->second.accepted_process_types)) { + swoole_error_log(SW_LOG_NOTICE, SW_ERROR_OPERATION_NOT_SUPPORT, "unsupported [process_type]"); + return false; + } + + if (process_type == Command::REACTOR_THREAD) { + if (!is_process_mode()) { + swoole_error_log(SW_LOG_NOTICE, SW_ERROR_OPERATION_NOT_SUPPORT, "unsupported [server_mode]"); + return false; + } + if (process_id >= reactor_num) { + swoole_error_log(SW_LOG_NOTICE, SW_ERROR_INVALID_PARAMS, "invalid thread_id[%d]", process_id); + return false; + } + pipe_sock = get_worker(process_id)->pipe_worker; + } else if (process_type == Command::EVENT_WORKER) { + if (process_id >= worker_num) { + swoole_error_log(SW_LOG_NOTICE, SW_ERROR_INVALID_PARAMS, "invalid worker_id[%d]", process_id); + return false; + } + pipe_sock = get_worker(process_id)->pipe_master; + } else if (process_type == Command::MASTER) { + if (!(iter->second.accepted_process_types & Command::MASTER)) { + swoole_error_log(SW_LOG_NOTICE, SW_ERROR_OPERATION_NOT_SUPPORT, "unsupported"); + return false; + } + auto result = call_command_handler_in_master(command_id, msg); + fn(this, result); + return true; + } else if (process_type == Command::TASK_WORKER) { + if (process_id >= task_worker_num) { + swoole_error_log(SW_LOG_NOTICE, SW_ERROR_INVALID_PARAMS, "invalid task_worker_id[%d]", process_id); + return false; + } + EventData buf; + memset(&buf.info, 0, sizeof(buf.info)); + if (!event_data_pack(&buf, msg.c_str(), msg.length())) { + return false; + } + buf.info.type = SW_SERVER_EVENT_COMMAND; + buf.info.fd = requset_id; + buf.info.server_fd = command_id; + if (send_to_worker_from_worker(worker_num + process_id, &buf, SW_PIPE_MASTER | SW_PIPE_NONBLOCK) <= 0) { + return false; + } + command_callbacks[requset_id] = fn; + return true; + } else { + swoole_error_log(SW_LOG_NOTICE, SW_ERROR_OPERATION_NOT_SUPPORT, "unsupported [process_type]"); + return false; + } + if (!message_bus.write(pipe_sock, &task)) { + return false; + } + command_callbacks[requset_id] = fn; + return true; +} + void Server::store_pipe_fd(UnixSocket *p) { Socket *master_socket = p->get_socket(true); Socket *worker_socket = p->get_socket(false); @@ -925,7 +1107,7 @@ void Server::store_pipe_fd(UnixSocket *p) { bool Server::send(SessionId session_id, const void *data, uint32_t length) { SendData _send{}; _send.info.fd = session_id; - _send.info.type = SW_SERVER_EVENT_RECV_DATA; + _send.info.type = SW_SERVER_EVENT_SEND_DATA; _send.data = (char *) data; _send.info.len = length; return factory->finish(&_send); @@ -1026,7 +1208,7 @@ int Server::send_to_connection(SendData *_send) { conn = get_connection_verify_no_ssl(session_id); } if (!conn) { - if (_send->info.type == SW_SERVER_EVENT_RECV_DATA) { + if (_send->info.type == SW_SERVER_EVENT_SEND_DATA) { swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_NOT_EXIST, "send %d byte failed, session#%ld does not exist", @@ -1202,7 +1384,7 @@ int Server::send_to_connection(SendData *_send) { * use in master process */ bool Server::notify(Connection *conn, enum ServerEventType event) { - DataHead notify_event = {}; + DataHead notify_event{}; notify_event.type = event; notify_event.reactor_id = conn->reactor_id; notify_event.fd = conn->fd; @@ -1280,25 +1462,6 @@ bool Server::sendwait(SessionId session_id, const void *data, uint32_t length) { return conn->socket->send_blocking(data, length) == length; } -size_t Server::get_packet(EventData *req, char **data_ptr) { - size_t length; - if (req->info.flags & SW_EVENT_DATA_PTR) { - PacketPtr *task = (PacketPtr *) req; - *data_ptr = task->data.str; - length = task->data.length; - } else if (req->info.flags & SW_EVENT_DATA_OBJ_PTR) { - String *worker_buffer; - memcpy(&worker_buffer, req->data, sizeof(worker_buffer)); - *data_ptr = worker_buffer->str; - length = worker_buffer->length; - } else { - *data_ptr = req->data; - length = req->info.len; - } - - return length; -} - void Server::call_hook(HookType type, void *arg) { swoole::hook_call(hooks, type, arg); } @@ -1351,16 +1514,7 @@ void Server::timer_callback(Timer *timer, TimerNode *tnode) { } int Server::add_worker(Worker *worker) { - if (user_worker_list == nullptr) { - user_worker_list = new std::vector(); - } - user_worker_num++; - user_worker_list->push_back(worker); - - if (!user_worker_map) { - user_worker_map = new std::unordered_map(); - } - + user_worker_list.push_back(worker); return worker->id; } @@ -1368,6 +1522,32 @@ int Server::add_hook(Server::HookType type, const Callback &func, int push_back) return swoole::hook_add(hooks, (int) type, func, push_back); } +bool Server::add_command(const std::string &name, int accepted_process_types, const Command::Handler &func) { + if (is_started()) { + return false; + } + if (commands.find(name) != commands.end()) { + return false; + } + if (is_process_mode() && pipe_command == nullptr) { + auto _pipe = new UnixSocket(false, SOCK_DGRAM); + if (!_pipe->ready()) { + delete _pipe; + return false; + } + pipe_command = _pipe; + } + int command_id = command_current_id++; + Command command{ + command_id, + accepted_process_types, + name, + }; + commands.emplace(name, command); + command_handlers[command_id] = func; + return true; +} + void Server::check_port_type(ListenPort *ls) { if (ls->is_dgram()) { // dgram socket, setting socket buffer size @@ -1553,8 +1733,8 @@ static void Server_signal_handler(int sig) { pid = waitpid(-1, &status, WNOHANG); if (pid > 0 && pid == serv->gs->manager_pid) { swoole_warning("Fatal Error: manager process exit. status=%d, signal=[%s]", - WEXITSTATUS(status), - swoole_signal_to_str(WTERMSIG(status))); + WEXITSTATUS(status), + swoole_signal_to_str(WTERMSIG(status))); } break; /** @@ -1585,7 +1765,7 @@ static void Server_signal_handler(int sig) { if (sig == SIGRTMIN) { uint32_t i; Worker *worker; - for (i = 0; i < serv->worker_num + serv->task_worker_num + serv->user_worker_num; i++) { + for (i = 0; i < serv->worker_num + serv->task_worker_num + serv->get_user_worker_num(); i++) { worker = serv->get_worker(i); swoole_kill(worker->pid, SIGRTMIN); } @@ -1699,7 +1879,7 @@ Connection *Server::add_connection(ListenPort *ls, Socket *_socket, int server_f return connection; } -void Server::set_ipc_max_size() { +void Server::init_ipc_max_size() { #ifdef HAVE_KQUEUE ipc_max_size = SW_IPC_MAX_SIZE; #else @@ -1718,21 +1898,8 @@ void Server::set_ipc_max_size() { * allocate memory for Server::pipe_buffers */ int Server::create_pipe_buffers() { - pipe_buffers = (PipeBuffer **) sw_calloc(reactor_num, sizeof(PipeBuffer *)); - if (pipe_buffers == nullptr) { - swoole_sys_error("malloc[buffers] failed"); - return SW_ERR; - } - for (uint32_t i = 0; i < reactor_num; i++) { - pipe_buffers[i] = (PipeBuffer *) sw_malloc(ipc_max_size); - if (pipe_buffers[i] == nullptr) { - swoole_sys_error("malloc[sndbuf][%d] failed", i); - return SW_ERR; - } - sw_memset_zero(pipe_buffers[i], sizeof(DataHead)); - } - - return SW_OK; + message_bus.set_buffer_size(ipc_max_size); + return message_bus.alloc_buffer() ? SW_OK : SW_ERR; } int Server::get_idle_worker_num() { @@ -1750,10 +1917,9 @@ int Server::get_idle_worker_num() { } int Server::get_idle_task_worker_num() { - uint32_t i; uint32_t idle_worker_num = 0; - for (i = worker_num; i < (worker_num + task_worker_num); i++) { + for (uint32_t i = worker_num; i < (worker_num + task_worker_num); i++) { Worker *worker = get_worker(i); if (worker->status == SW_WORKER_IDLE) { idle_worker_num++; @@ -1762,4 +1928,5 @@ int Server::get_idle_task_worker_num() { return idle_worker_num; } + } // namespace swoole diff --git a/src/server/message_bus.cc b/src/server/message_bus.cc new file mode 100644 index 00000000000..e7036829c90 --- /dev/null +++ b/src/server/message_bus.cc @@ -0,0 +1,271 @@ +#include "swoole_server.h" + +#include + +using swoole::network::Address; +using swoole::network::Socket; + +namespace swoole { + +PacketPtr MessageBus::get_packet() { + PacketPtr pkt; + if (buffer_->info.flags & SW_EVENT_DATA_PTR) { + memcpy(&pkt, buffer_->data, sizeof(pkt)); + } else if (buffer_->info.flags & SW_EVENT_DATA_OBJ_PTR) { + String *object; + memcpy(&object, buffer_->data, sizeof(object)); + pkt.data = object->str; + pkt.length = object->length; + } else { + pkt.data = buffer_->data; + pkt.length = buffer_->info.len; + } + + return pkt; +} + +String *MessageBus::get_packet_buffer() { + String *packet_buffer = nullptr; + + auto iter = packet_pool_.find(buffer_->info.msg_id); + if (iter == packet_pool_.end()) { + if (!buffer_->is_begin()) { + return nullptr; + } + packet_buffer = make_string(buffer_->info.len, allocator_); + packet_pool_.emplace(buffer_->info.msg_id, std::shared_ptr(packet_buffer)); + } else { + packet_buffer = iter->second.get(); + } + + return packet_buffer; +} + +ReturnCode MessageBus::prepare_packet(uint16_t &recv_chunk_count, String *packet_buffer) { + recv_chunk_count++; + if (!buffer_->is_end()) { + /** + * if the reactor thread sends too many chunks to the worker process, + * the worker process may receive chunks all the time, + * resulting in the worker process being unable to handle other tasks. + * in order to make the worker process handle tasks fairly, + * the maximum number of consecutive chunks received by the worker is limited. + */ + if (recv_chunk_count >= SW_WORKER_MAX_RECV_CHUNK_COUNT) { + swoole_trace_log(SW_TRACE_WORKER, + "worker process[%u] receives the chunk data to the maximum[%d], return to event loop", + SwooleG.process_id, + recv_chunk_count); + return SW_WAIT; + } + return SW_CONTINUE; + } else { + /** + * Because we don't want to split the EventData parameters into DataHead and data, + * we store the value of the worker_buffer pointer in EventData.data. + * The value of this pointer will be fetched in the Server::get_pipe_packet() function. + */ + buffer_->info.flags |= SW_EVENT_DATA_OBJ_PTR; + memcpy(buffer_->data, &packet_buffer, sizeof(packet_buffer)); + swoole_trace("msg_id=%ld, len=%u", buffer_->info.msg_id, buffer_->info.len); + + return SW_READY; + } +} + +ssize_t MessageBus::read(Socket *sock) { + ssize_t recv_n = 0; + uint16_t recv_chunk_count = 0; + DataHead *info = &buffer_->info; + struct iovec buffers[2]; + +_read_from_pipe: + recv_n = recv(sock->get_fd(), info, sizeof(buffer_->info), MSG_PEEK); + if (recv_n < 0) { + if (sock->catch_error(errno) == SW_WAIT) { + return SW_OK; + } + return SW_ERR; + } else if (recv_n == 0) { + swoole_warning("receive data from socket#%d returns 0", sock->get_fd()); + return SW_ERR; + } + + if (!buffer_->is_chunked()) { + return sock->read(buffer_, sizeof(buffer_->info) + buffer_->info.len); + } + + auto packet_buffer = get_packet_buffer(); + if (packet_buffer == nullptr) { + swoole_error_log(SW_LOG_WARNING, + SW_ERROR_SERVER_WORKER_ABNORMAL_PIPE_DATA, + "abnormal pipeline data, msg_id=%ld, pipe_fd=%d, reactor_id=%d", + info->msg_id, + sock->get_fd(), + info->reactor_id); + return SW_OK; + } + + size_t remain_len = buffer_->info.len - packet_buffer->length; + buffers[0].iov_base = info; + buffers[0].iov_len = sizeof(buffer_->info); + buffers[1].iov_base = packet_buffer->str + packet_buffer->length; + buffers[1].iov_len = SW_MIN(buffer_size_ - sizeof(buffer_->info), remain_len); + + recv_n = readv(sock->get_fd(), buffers, 2); + if (recv_n == 0) { + swoole_warning("receive pipeline data error, pipe_fd=%d, reactor_id=%d", sock->get_fd(), info->reactor_id); + return SW_ERR; + } + if (recv_n < 0 && sock->catch_error(errno) == SW_WAIT) { + return SW_OK; + } + if (recv_n > 0) { + packet_buffer->length += (recv_n - sizeof(buffer_->info)); + swoole_trace("append msgid=%ld, buffer=%p, n=%ld", buffer_->info.msg_id, packet_buffer, recv_n); + } + + switch (prepare_packet(recv_chunk_count, packet_buffer)) { + case SW_READY: + return recv_n; + case SW_CONTINUE: + goto _read_from_pipe; + case SW_WAIT: + return SW_OK; + default: + assert(0); + return SW_ERR; + } +} + +/** + * Notice: only supports dgram type socket + */ +ssize_t MessageBus::read_with_buffer(network::Socket *sock) { + ssize_t recv_n; + uint16_t recv_chunk_count = 0; + +_read_from_pipe: + recv_n = sock->read(buffer_, buffer_size_); + if (recv_n < 0) { + if (sock->catch_error(errno) == SW_WAIT) { + return SW_OK; + } + return SW_ERR; + } else if (recv_n == 0) { + swoole_warning("receive data from socket#%d returns 0", sock->get_fd()); + return SW_ERR; + } + + recv_chunk_count++; + + if (!buffer_->is_chunked()) { + return recv_n; + } + + String *packet_buffer = get_packet_buffer(); + if (packet_buffer == nullptr) { + swoole_error_log(SW_LOG_WARNING, + SW_ERROR_SERVER_WORKER_ABNORMAL_PIPE_DATA, + "abnormal pipeline data, msg_id=%ld, pipe_fd=%d, reactor_id=%d", + buffer_->info.msg_id, + sock->get_fd(), + buffer_->info.reactor_id); + return SW_ERR; + } + packet_buffer->append(buffer_->data, recv_n - sizeof(buffer_->info)); + + switch (prepare_packet(recv_chunk_count, packet_buffer)) { + case SW_READY: + return recv_n; + case SW_CONTINUE: + goto _read_from_pipe; + case SW_WAIT: + return SW_OK; + default: + assert(0); + return SW_ERR; + } +} + +bool MessageBus::write(Socket *sock, SendData *resp) { + const char *payload = resp->data; + uint32_t l_payload = resp->info.len; + off_t offset = 0; + uint32_t copy_n; + + struct iovec iov[2]; + + uint64_t msg_id = id_generator_(); + uint32_t max_length = buffer_size_ - sizeof(resp->info); + resp->info.msg_id = msg_id; + + auto send_fn = [](Socket *sock, const iovec *iov, size_t iovcnt) { + if (swoole_event_is_available()) { + return swoole_event_writev(sock, iov, iovcnt); + } else { + return sock->writev_blocking(iov, iovcnt); + } + }; + + if (l_payload == 0 || payload == nullptr) { + resp->info.flags = 0; + resp->info.len = 0; + iov[0].iov_base = &resp->info; + iov[0].iov_len = sizeof(resp->info); + return send_fn(sock, iov, 1) == (ssize_t) iov[0].iov_len; + } + + if (!always_chunked_transfer_ && l_payload <= max_length) { + resp->info.flags = 0; + resp->info.len = l_payload; + iov[0].iov_base = &resp->info; + iov[0].iov_len = sizeof(resp->info); + iov[1].iov_base = (void *) payload; + iov[1].iov_len = l_payload; + return send_fn(sock, iov, 2) == (ssize_t)(sizeof(resp->info) + l_payload); + } + + resp->info.flags = SW_EVENT_DATA_CHUNK | SW_EVENT_DATA_BEGIN; + resp->info.len = l_payload; + + while (l_payload > 0) { + if (l_payload > max_length) { + copy_n = max_length; + } else { + resp->info.flags |= SW_EVENT_DATA_END; + copy_n = l_payload; + } + + iov[0].iov_base = &resp->info; + iov[0].iov_len = sizeof(resp->info); + iov[1].iov_base = (void *) (payload + offset); + iov[1].iov_len = copy_n; + + swoole_trace("finish, type=%d|len=%u", resp->info.type, copy_n); + + if (send_fn(sock, iov, 2) < 0) { +#ifdef __linux__ + if (errno == ENOBUFS && max_length > SW_BUFFER_SIZE_STD) { + max_length = SW_IPC_BUFFER_SIZE; + if (resp->info.flags & SW_EVENT_DATA_END) { + resp->info.flags &= ~SW_EVENT_DATA_END; + } + continue; + } +#endif + return false; + } + + if (resp->info.flags & SW_EVENT_DATA_BEGIN) { + resp->info.flags &= ~SW_EVENT_DATA_BEGIN; + } + + l_payload -= copy_n; + offset += copy_n; + } + + return true; +} + +} // namespace swoole diff --git a/src/server/process.cc b/src/server/process.cc index 626ce939555..01602f5fb57 100644 --- a/src/server/process.cc +++ b/src/server/process.cc @@ -22,15 +22,7 @@ namespace swoole { using network::Socket; -typedef int (*SendFunc)(Server *serv, DataHead *head, const iovec *iov, size_t iovcnt, void *private_data); - -static bool process_send_packet(Server *serv, SendData *resp, SendFunc _send, void *private_data); -static int process_sendto_worker(Server *serv, DataHead *head, const iovec *iov, size_t iovcnt, void *private_data); -static int process_sendto_reactor(Server *serv, DataHead *head, const iovec *iov, size_t iovcnt, void *private_data); - -ProcessFactory::ProcessFactory(Server *server) : Factory(server) { - send_buffer = nullptr; -} +ProcessFactory::ProcessFactory(Server *server) : Factory(server) {} bool ProcessFactory::shutdown() { int status; @@ -52,20 +44,11 @@ bool ProcessFactory::shutdown() { } ProcessFactory::~ProcessFactory() { - if (server_->pipe_buffers) { - SW_LOOP_N(server_->reactor_num) { - sw_free(server_->pipe_buffers[i]); - } - sw_free(server_->pipe_buffers); - } if (server_->stream_socket_file) { unlink(server_->stream_socket_file); sw_free(server_->stream_socket_file); server_->stream_socket->free(); } - if (send_buffer) { - sw_free(send_buffer); - } } bool ProcessFactory::start() { @@ -105,18 +88,11 @@ bool ProcessFactory::start() { server_->store_pipe_fd(server_->workers[i].pipe_object); } - server_->set_ipc_max_size(); + server_->init_ipc_max_size(); if (server_->create_pipe_buffers() < 0) { return false; } - send_buffer = (PipeBuffer *) sw_malloc(server_->ipc_max_size); - if (send_buffer == nullptr) { - swoole_sys_error("malloc[send_buffer] failed"); - return false; - } - sw_memset_zero(send_buffer, sizeof(DataHead)); - /** * The manager process must be started first, otherwise it will have a thread fork */ @@ -137,16 +113,6 @@ bool ProcessFactory::notify(DataHead *ev) { return dispatch(&task); } -static inline int process_sendto_worker( - Server *serv, DataHead *head, const iovec *iov, size_t iovcnt, void *private_data) { - return serv->send_to_worker_from_master((Worker *) private_data, iov, iovcnt); -} - -static inline int process_sendto_reactor( - Server *serv, DataHead *head, const iovec *iov, size_t iovcnt, void *private_data) { - return serv->send_to_reactor_thread(head, iov, iovcnt, ((Connection *) private_data)->session_id); -} - /** * [ReactorThread] dispatch request to worker */ @@ -195,91 +161,7 @@ bool ProcessFactory::dispatch(SendData *task) { SendData _task; memcpy(&_task, task, sizeof(SendData)); - return process_send_packet(server_, &_task, process_sendto_worker, worker); -} - -/** - * @description: master process send data to worker process. - * If the data sent is larger than Server::ipc_max_size, then it is sent in chunks. Otherwise send it directly。 - * @return: send success returns SW_OK, send failure returns SW_ERR. - */ -static bool process_send_packet(Server *serv, SendData *resp, SendFunc _send, void *private_data) { - const char *data = resp->data; - uint32_t l_payload = resp->info.len; - off_t offset = 0; - uint32_t copy_n; - - struct iovec iov[2]; - - uint32_t max_length = serv->ipc_max_size - sizeof(resp->info); - resp->info.msg_id = serv->worker_msg_id.fetch_add(1); - - if (l_payload <= max_length) { - resp->info.flags = 0; - resp->info.len = l_payload; - - size_t iovcnt; - iov[0].iov_base = &resp->info; - iov[0].iov_len = sizeof(resp->info); - - if (resp->data && l_payload > 0) { - iov[1].iov_base = (void *) resp->data; - iov[1].iov_len = l_payload; - iovcnt = 2; - } else { - iovcnt = 1; - } - - int retval = _send(serv, &resp->info, iov, iovcnt, private_data); -#ifdef __linux__ - if (retval < 0 && errno == ENOBUFS) { - max_length = SW_IPC_BUFFER_SIZE; - goto _ipc_use_chunk; - } -#endif - return retval >= 0; - } - -#ifdef __linux__ -_ipc_use_chunk: -#endif - resp->info.flags = SW_EVENT_DATA_CHUNK | SW_EVENT_DATA_BEGIN; - resp->info.len = l_payload; - - while (l_payload > 0) { - if (l_payload > max_length) { - copy_n = max_length; - } else { - resp->info.flags |= SW_EVENT_DATA_END; - copy_n = l_payload; - } - - iov[0].iov_base = &resp->info; - iov[0].iov_len = sizeof(resp->info); - iov[1].iov_base = (void *) (data + offset); - iov[1].iov_len = copy_n; - - swoole_trace("finish, type=%d|len=%u", resp->info.type, copy_n); - - if (_send(serv, &resp->info, iov, 2, private_data) < 0) { -#ifdef __linux__ - if (errno == ENOBUFS && max_length > SW_BUFFER_SIZE_STD) { - max_length = SW_IPC_BUFFER_SIZE; - continue; - } -#endif - return false; - } - - if (resp->info.flags & SW_EVENT_DATA_BEGIN) { - resp->info.flags &= ~SW_EVENT_DATA_BEGIN; - } - - l_payload -= copy_n; - offset += copy_n; - } - - return true; + return server_->message_bus.write(server_->get_worker_pipe_socket(worker), &_task); } static bool inline process_is_supported_send_yield(Server *serv, Connection *conn) { @@ -362,7 +244,7 @@ bool ProcessFactory::finish(SendData *resp) { swoole_trace("worker_id=%d, type=%d", SwooleG.process_id, task.info.type); - return process_send_packet(server_, &task, process_sendto_reactor, conn); + return server_->message_bus.write(server_->get_reactor_pipe_socket(session_id, task.info.reactor_id), &task); } bool ProcessFactory::end(SessionId session_id, int flags) { @@ -448,4 +330,5 @@ bool ProcessFactory::end(SessionId session_id, int flags) { return finish(&_send); } } + } // namespace swoole diff --git a/src/server/reactor_process.cc b/src/server/reactor_process.cc index be84f10dbb7..167308c1871 100644 --- a/src/server/reactor_process.cc +++ b/src/server/reactor_process.cc @@ -31,7 +31,7 @@ static int ReactorProcess_reuse_port(ListenPort *ls); static bool Server_is_single(Server *serv) { return serv->worker_num == 1 && serv->task_worker_num == 0 && serv->max_request == 0 && - serv->user_worker_list == nullptr; + serv->user_worker_list.empty(); } int Server::create_reactor_processes() { @@ -91,6 +91,8 @@ int Server::start_reactor_processes() { gs->event_workers.use_msgqueue = 0; gs->event_workers.main_loop = ReactorProcess_loop; gs->event_workers.onWorkerNotFound = Server::wait_other_worker; + memcpy(workers, gs->event_workers.workers, sizeof(*workers) * worker_num); + gs->event_workers.workers = workers; SW_LOOP_N(worker_num) { gs->event_workers.workers[i].pool = &gs->event_workers; @@ -98,6 +100,11 @@ int Server::start_reactor_processes() { gs->event_workers.workers[i].type = SW_PROCESS_WORKER; } + init_ipc_max_size(); + if (create_pipe_buffers() < 0) { + return SW_ERR; + } + // single worker if (Server_is_single(this)) { int retval = ReactorProcess_loop(&gs->event_workers, &gs->event_workers.workers[0]); @@ -121,16 +128,14 @@ int Server::start_reactor_processes() { } } - /** - * create user worker process - */ - if (user_worker_list) { - user_workers = (Worker *) sw_shm_calloc(user_worker_num, sizeof(Worker)); + // create user worker process + if (!user_worker_list.empty()) { + user_workers = (Worker *) sw_shm_calloc(get_user_worker_num(), sizeof(Worker)); if (user_workers == nullptr) { swoole_sys_warning("gmalloc[server->user_workers] failed"); return SW_ERR; } - for (auto worker : *user_worker_list) { + for (auto worker : user_worker_list) { /** * store the pipe object */ @@ -156,11 +161,6 @@ int Server::start_reactor_processes() { init_signal_handler(); - if (onStart) { - swoole_warning("The onStart event with SWOOLE_BASE is deprecated"); - onStart(this); - } - if (onManagerStart) { onManagerStart(this); } @@ -182,82 +182,68 @@ int Server::start_reactor_processes() { } static int ReactorProcess_onPipeRead(Reactor *reactor, Event *event) { - EventData task; SendData _send; Server *serv = (Server *) reactor->ptr; Factory *factory = serv->factory; - String *output_buffer; + PipeBuffer *pipe_buffer = serv->message_bus.get_buffer(); - ssize_t retval = read(event->fd, &task, sizeof(task)); + ssize_t retval = serv->message_bus.read(event->socket); if (retval <= 0) { - return SW_ERR; - } else if ((size_t) retval != task.info.len + sizeof(_send.info)) { - swoole_warning("bad pipeline data"); return SW_OK; } - switch (task.info.type) { - case SW_SERVER_EVENT_PIPE_MESSAGE: - serv->onPipeMessage(serv, &task); + switch (pipe_buffer->info.type) { + case SW_SERVER_EVENT_PIPE_MESSAGE: { + serv->onPipeMessage(serv, (EventData *) pipe_buffer); break; - case SW_SERVER_EVENT_FINISH: - serv->onFinish(serv, &task); + } + case SW_SERVER_EVENT_FINISH: { + serv->onFinish(serv, (EventData *) pipe_buffer); break; - case SW_SERVER_EVENT_SEND_FILE: - _send.info = task.info; - _send.data = task.data; + } + case SW_SERVER_EVENT_SEND_FILE: { + _send.info = pipe_buffer->info; + _send.data = pipe_buffer->data; factory->finish(&_send); break; - case SW_SERVER_EVENT_PROXY_START: - case SW_SERVER_EVENT_PROXY_END: - if (task.info.reactor_id < 0 || task.info.reactor_id >= (int16_t) serv->get_all_worker_num()) { - swoole_warning("invalid worker_id=%d", task.info.reactor_id); + } + case SW_SERVER_EVENT_SEND_DATA: { + if (pipe_buffer->info.reactor_id < 0 || pipe_buffer->info.reactor_id >= (int16_t) serv->get_all_worker_num()) { + swoole_warning("invalid worker_id=%d", pipe_buffer->info.reactor_id); return SW_OK; } - output_buffer = SwooleWG.output_buffer[task.info.reactor_id]; - output_buffer->append(task.data, task.info.len); - if (task.info.type == SW_SERVER_EVENT_PROXY_END) { - memcpy(&_send.info, &task.info, sizeof(_send.info)); - _send.info.type = SW_SERVER_EVENT_RECV_DATA; - _send.data = output_buffer->str; - _send.info.len = output_buffer->length; - factory->finish(&_send); - output_buffer->clear(); - } + auto packet = serv->message_bus.get_packet(); + memcpy(&_send.info, &pipe_buffer->info, sizeof(_send.info)); + _send.info.type = SW_SERVER_EVENT_RECV_DATA; + _send.data = packet.data; + _send.info.len = packet.length; + factory->finish(&_send); break; - case SW_SERVER_EVENT_CLOSE: - factory->end(task.info.fd, Server::CLOSE_ACTIVELY); + } + case SW_SERVER_EVENT_CLOSE: { + factory->end(pipe_buffer->info.fd, Server::CLOSE_ACTIVELY); break; + } + case SW_SERVER_EVENT_COMMAND: { + WorkerId worker_id = SwooleWG.worker->id; + if (worker_id == 0) { + int64_t request_id = pipe_buffer->info.fd; + auto packet = serv->message_bus.get_packet(); + serv->call_command_callback(request_id, std::string(packet.data, packet.length)); + } else { + serv->call_command_handler(serv->message_bus, worker_id, serv->get_worker(0)->pipe_master); + } + break; + } default: break; } - return SW_OK; -} -static int ReactorProcess_alloc_output_buffer(size_t n_buffer) { - SwooleWG.output_buffer = (String **) sw_malloc(sizeof(String *) * n_buffer); - if (SwooleWG.output_buffer == nullptr) { - swoole_error("malloc for SwooleWG.output_buffer failed"); - return SW_ERR; - } + serv->message_bus.pop(); - SW_LOOP_N(n_buffer) { - SwooleWG.output_buffer[i] = new String(SW_BUFFER_SIZE_BIG); - if (SwooleWG.output_buffer[i] == nullptr) { - swoole_error("output_buffer init failed"); - return SW_ERR; - } - } return SW_OK; } -static void ReactorProcess_free_output_buffer(size_t n_buffer) { - SW_LOOP_N(n_buffer) { - delete SwooleWG.output_buffer[i]; - } - sw_free(SwooleWG.output_buffer); -} - static int ReactorProcess_loop(ProcessPool *pool, Worker *worker) { Server *serv = (Server *) pool->ptr; @@ -270,15 +256,10 @@ static int ReactorProcess_loop(ProcessPool *pool, Worker *worker) { } SwooleWG.max_request = serv->max_request; SwooleWG.worker = worker; - SwooleTG.id = 0; - if (worker->id == 0) { - SwooleTG.update_time = 1; - } serv->init_worker(worker); - // create reactor if (!SwooleTG.reactor) { if (swoole_event_init(0) < 0) { return SW_ERR; @@ -291,16 +272,10 @@ static int ReactorProcess_loop(ProcessPool *pool, Worker *worker) { SwooleTG.timer->reinit(reactor); } - size_t n_buffer = serv->get_all_worker_num(); - if (ReactorProcess_alloc_output_buffer(n_buffer)) { - return SW_ERR; - } - for (auto ls : serv->ports) { #ifdef HAVE_REUSEPORT if (ls->is_stream() && serv->enable_reuse_port) { if (ReactorProcess_reuse_port(ls) < 0) { - ReactorProcess_free_output_buffer(n_buffer); swoole_event_free(); return SW_ERR; } @@ -348,7 +323,7 @@ static int ReactorProcess_loop(ProcessPool *pool, Worker *worker) { // task workers if (serv->task_worker_num > 0) { if (serv->task_ipc_mode == Server::TASK_IPC_UNIXSOCK) { - for (uint32_t i = 0; i < serv->gs->task_workers.worker_num; i++) { + SW_LOOP_N(serv->gs->task_workers.worker_num) { serv->gs->task_workers.workers[i].pipe_master->set_nonblock(); } } @@ -356,8 +331,8 @@ static int ReactorProcess_loop(ProcessPool *pool, Worker *worker) { serv->init_reactor(reactor); - // single server trigger onStart event - if (Server_is_single(serv)) { + if (worker->id == 0) { + SwooleTG.update_time = 1; if (serv->onStart) { serv->onStart(serv); } @@ -368,7 +343,6 @@ static int ReactorProcess_loop(ProcessPool *pool, Worker *worker) { */ if ((serv->master_timer = swoole_timer_add(1000, true, Server::timer_callback, serv)) == nullptr) { _fail: - ReactorProcess_free_output_buffer(n_buffer); swoole_event_free(); return SW_ERR; } @@ -405,7 +379,6 @@ static int ReactorProcess_loop(ProcessPool *pool, Worker *worker) { swoole_event_free(); serv->worker_stop_callback(); - ReactorProcess_free_output_buffer(n_buffer); return retval; } diff --git a/src/server/reactor_thread.cc b/src/server/reactor_thread.cc index feb92205c7a..12763597bce 100644 --- a/src/server/reactor_thread.cc +++ b/src/server/reactor_thread.cc @@ -28,7 +28,6 @@ namespace swoole { using namespace network; static void ReactorThread_loop(Server *serv, int reactor_id); -static int ReactorThread_init(Server *serv, Reactor *reactor, uint16_t reactor_id); static int ReactorThread_onPipeWrite(Reactor *reactor, Event *ev); static int ReactorThread_onPipeRead(Reactor *reactor, Event *ev); static int ReactorThread_onRead(Reactor *reactor, Event *ev); @@ -172,7 +171,7 @@ static int ReactorThread_onPacketReceived(Reactor *reactor, Event *event) { ev.type = SW_SERVER_EVENT_INCOMING; ev.fd = conn->session_id; ev.reactor_id = conn->reactor_id; - if (serv->send_to_reactor_thread((EventData*) &ev, sizeof(ev), conn->session_id) < 0) { + if (serv->send_to_reactor_thread((EventData *) &ev, sizeof(ev), conn->session_id) < 0) { reactor->close(reactor, session->socket); return SW_OK; } @@ -357,114 +356,77 @@ static void ReactorThread_shutdown(Reactor *reactor) { */ static int ReactorThread_onPipeRead(Reactor *reactor, Event *ev) { SendData _send; - Server *serv = (Server *) reactor->ptr; ReactorThread *thread = serv->get_thread(reactor->id); - String *package = nullptr; - PipeBuffer *resp = serv->pipe_buffers[reactor->id]; #ifdef SW_REACTOR_RECV_AGAIN while (1) #endif { - ssize_t n = ev->socket->read(resp, serv->ipc_max_size); - if (n > 0) { - // packet chunk - if (resp->info.flags & SW_EVENT_DATA_CHUNK) { - int worker_id = resp->info.server_fd; - int key = (ev->fd << 16) + worker_id; - auto it = thread->send_buffers.find(key); - if (it == thread->send_buffers.end()) { - package = new String(SW_BUFFER_SIZE_BIG); - thread->send_buffers.emplace(std::make_pair(key, package)); - } else { - package = it->second; - } - // merge data to package buffer - package->append(resp->data, n - sizeof(resp->info)); - // wait more data - if (!(resp->info.flags & SW_EVENT_DATA_END)) { - return SW_OK; - } - _send.info = resp->info; - _send.data = package->str; - _send.info.len = package->length; - serv->send_to_connection(&_send); - delete package; - thread->send_buffers.erase(key); - } else { - /** - * connection incoming - */ - if (resp->info.type == SW_SERVER_EVENT_INCOMING) { - Connection *conn = serv->get_connection_by_session_id(resp->info.fd); - if (serv->connection_incoming(reactor, conn) < 0) { - return reactor->close(reactor, conn->socket); - } - } - /** - * server shutdown - */ - else if (resp->info.type == SW_SERVER_EVENT_SHUTDOWN) { - ReactorThread_shutdown(reactor); - } else if (resp->info.type == SW_SERVER_EVENT_CLOSE_FORCE) { - SessionId session_id = resp->info.fd; - Connection *conn = serv->get_connection_verify_no_ssl(session_id); - - if (!conn) { - swoole_error_log(SW_LOG_NOTICE, - SW_ERROR_SESSION_NOT_EXIST, - "force close connection failed, session#%ld does not exist", - session_id); - return SW_OK; - } - - if (serv->disable_notify || conn->close_force) { - return Server::close_connection(reactor, conn->socket); - } + PipeBuffer *resp = thread->message_bus.get_buffer(); + ssize_t n = thread->message_bus.read_with_buffer(ev->socket); + if (n <= 0) { + return n; + } + /** + * connection incoming + */ + if (resp->info.type == SW_SERVER_EVENT_INCOMING) { + Connection *conn = serv->get_connection_by_session_id(resp->info.fd); + if (serv->connection_incoming(reactor, conn) < 0) { + return reactor->close(reactor, conn->socket); + } + } else if (resp->info.type == SW_SERVER_EVENT_COMMAND) { + return serv->call_command_handler(thread->message_bus, thread->id, thread->pipe_command); + } + /** + * server shutdown + */ + else if (resp->info.type == SW_SERVER_EVENT_SHUTDOWN) { + ReactorThread_shutdown(reactor); + } else if (resp->info.type == SW_SERVER_EVENT_CLOSE_FORCE) { + SessionId session_id = resp->info.fd; + Connection *conn = serv->get_connection_verify_no_ssl(session_id); + + if (!conn) { + swoole_error_log(SW_LOG_NOTICE, + SW_ERROR_SESSION_NOT_EXIST, + "force close connection failed, session#%ld does not exist", + session_id); + return SW_OK; + } -#ifdef SW_USE_OPENSSL - /** - * SSL connections that have not completed the handshake, - * do not need to notify the workers, just close - */ - if (conn->ssl && !conn->ssl_ready) { - return Server::close_connection(reactor, conn->socket); - } -#endif + if (serv->disable_notify || conn->close_force) { + return Server::close_connection(reactor, conn->socket); + } - conn->close_force = 1; - Event _ev = {}; - _ev.fd = conn->fd; - _ev.socket = conn->socket; - reactor->trigger_close_event(&_ev); - } else { - _send.info = resp->info; - _send.data = resp->data; - serv->send_to_connection(&_send); - } +#ifdef SW_USE_OPENSSL + /** + * SSL connections that have not completed the handshake, + * do not need to notify the workers, just close + */ + if (conn->ssl && !conn->ssl_ready) { + return Server::close_connection(reactor, conn->socket); } - } else if (errno == EAGAIN) { - return SW_OK; +#endif + conn->close_force = 1; + Event _ev = {}; + _ev.fd = conn->fd; + _ev.socket = conn->socket; + reactor->trigger_close_event(&_ev); } else { - swoole_sys_warning("read(worker_pipe) failed"); - return SW_ERR; + PacketPtr packet = thread->message_bus.get_packet(); + _send.info = resp->info; + _send.info.len = packet.length; + _send.data = packet.data; + serv->send_to_connection(&_send); } + thread->message_bus.pop(); } return SW_OK; } -ssize_t Server::send_to_worker_from_master(Worker *worker, const iovec *iov, size_t iovcnt) { - if (SwooleTG.reactor) { - ReactorThread *thread = get_thread(SwooleTG.id); - Socket *socket = &thread->pipe_sockets[worker->pipe_master->fd]; - return swoole_event_writev(socket, iov, iovcnt); - } else { - return worker->pipe_master->writev_blocking(iov, iovcnt); - } -} - /** * [ReactorThread] worker pipe can write. */ @@ -626,11 +588,11 @@ static int ReactorThread_onWrite(Reactor *reactor, Event *ev) { } swoole_trace_log(SW_TRACE_REACTOR, - "fd=%d, conn->close_notify=%d, serv->disable_notify=%d, conn->close_force=%d", - fd, - conn->close_notify, - serv->disable_notify, - conn->close_force); + "fd=%d, conn->close_notify=%d, serv->disable_notify=%d, conn->close_force=%d", + fd, + conn->close_notify, + serv->disable_notify, + conn->close_force); if (conn->close_notify) { #ifdef SW_USE_OPENSSL @@ -717,7 +679,7 @@ int Server::start_reactor_threads() { return SW_ERR; } - Reactor *reactor = SwooleTG.reactor; + Reactor *reactor = sw_reactor(); #ifdef HAVE_SIGNALFD if (SwooleG.use_signalfd) { @@ -737,16 +699,10 @@ int Server::start_reactor_threads() { reactor->add(port->socket, SW_EVENT_READ); } - /** - * create reactor thread - */ - ReactorThread *thread; - int i; - store_listen_socket(); if (single_thread) { - ReactorThread_init(this, reactor, 0); + get_thread(0)->init(this, reactor, 0); goto _init_master_thread; } /** @@ -764,9 +720,8 @@ int Server::start_reactor_threads() { // init thread barrier pthread_barrier_init(&barrier, nullptr, reactor_num + 1); #endif - for (i = 0; i < reactor_num; i++) { - thread = &(reactor_threads[i]); - thread->thread = std::thread(ReactorThread_loop, this, i); + SW_LOOP_N(reactor_num) { + get_thread(i)->thread = std::thread(ReactorThread_loop, this, i); } #ifdef HAVE_PTHREAD_BARRIER // wait reactor thread @@ -784,50 +739,18 @@ int Server::start_reactor_threads() { start_heartbeat_thread(); } - SwooleTG.type = THREAD_MASTER; - SwooleTG.update_time = 1; - SwooleTG.reactor = reactor; - - if (SwooleTG.timer && SwooleTG.timer->get_reactor() == nullptr) { - SwooleTG.timer->reinit(reactor); - } - - SwooleG.pid = getpid(); - SwooleG.process_type = SW_PROCESS_MASTER; - - reactor->ptr = this; - reactor->set_handler(SW_FD_STREAM_SERVER, Server::accept_connection); - - if (hooks[Server::HOOK_MASTER_START]) { - call_hook(Server::HOOK_MASTER_START, this); - } - - /** - * 1 second timer - */ - if ((master_timer = swoole_timer_add(1000, true, Server::timer_callback, this)) == nullptr) { - swoole_event_free(); - return SW_ERR; - } - - if (onStart) { - onStart(this); - } - - return swoole_event_wait(); + return start_master_thread(); } -static int ReactorThread_init(Server *serv, Reactor *reactor, uint16_t reactor_id) { - ReactorThread *thread = serv->get_thread(reactor_id); - +int ReactorThread::init(Server *serv, Reactor *reactor, uint16_t reactor_id) { reactor->ptr = serv; reactor->id = reactor_id; reactor->wait_exit = 0; reactor->max_socket = serv->get_max_connection(); reactor->close = Server::close_connection; - reactor->set_exit_condition(Reactor::EXIT_CONDITION_DEFAULT, [thread](Reactor *reactor, int &event_num) -> bool { - return event_num == (int) thread->pipe_num; + reactor->set_exit_condition(Reactor::EXIT_CONDITION_DEFAULT, [this](Reactor *reactor, size_t &event_num) -> bool { + return event_num == (size_t) pipe_num; }); reactor->default_error_handler = ReactorThread_onClose; @@ -864,15 +787,27 @@ static int ReactorThread_init(Server *serv, Reactor *reactor, uint16_t reactor_i serv->init_reactor(reactor); int max_pipe_fd = serv->get_worker(serv->worker_num - 1)->pipe_master->fd + 2; - thread->pipe_sockets = (Socket *) sw_calloc(max_pipe_fd, sizeof(Socket)); - if (!thread->pipe_sockets) { + pipe_sockets = (Socket *) sw_calloc(max_pipe_fd, sizeof(Socket)); + if (!pipe_sockets) { swoole_sys_error("calloc(%d, %ld) failed", max_pipe_fd, sizeof(Socket)); return SW_ERR; } - for (uint32_t i = 0; i < serv->worker_num; i++) { + if (serv->pipe_command) { + pipe_command = make_socket(serv->pipe_command->get_socket(false)->get_fd(), SW_FD_PIPE); + pipe_command->buffer_size = UINT_MAX; + } + + message_bus.set_id_generator([serv]() { return sw_atomic_fetch_add(&serv->gs->pipe_packet_msg_id, 1); }); + message_bus.set_buffer_size(serv->ipc_max_size); + message_bus.set_always_chunked_transfer(); + if (!message_bus.alloc_buffer()) { + return SW_ERR; + } + + SW_LOOP_N(serv->worker_num) { int pipe_fd = serv->workers[i].pipe_master->fd; - Socket *socket = &thread->pipe_sockets[pipe_fd]; + Socket *socket = &pipe_sockets[pipe_fd]; socket->fd = pipe_fd; socket->fd_type = SW_FD_PIPE; @@ -887,10 +822,10 @@ static int ReactorThread_init(Server *serv, Reactor *reactor, uint16_t reactor_i if (reactor->add(socket, SW_EVENT_READ) < 0) { return SW_ERR; } - if (thread->notify_pipe == nullptr) { - thread->notify_pipe = serv->workers[i].pipe_worker; + if (notify_pipe == nullptr) { + notify_pipe = serv->workers[i].pipe_worker; } - thread->pipe_num++; + pipe_num++; } return SW_OK; @@ -914,6 +849,7 @@ static void ReactorThread_loop(Server *serv, int reactor_id) { } ReactorThread *thread = serv->get_thread(reactor_id); + thread->id = reactor_id; Reactor *reactor = sw_reactor(); #ifdef HAVE_CPU_AFFINITY @@ -936,7 +872,7 @@ static void ReactorThread_loop(Server *serv, int reactor_id) { swoole_signal_block_all(); - if (ReactorThread_init(serv, reactor, reactor_id) < 0) { + if (thread->init(serv, reactor, reactor_id) < 0) { return; } @@ -948,11 +884,11 @@ static void ReactorThread_loop(Server *serv, int reactor_id) { #endif // main loop swoole_event_wait(); - - for (auto it = thread->send_buffers.begin(); it != thread->send_buffers.end(); it++) { - delete it->second; - } sw_free(thread->pipe_sockets); + if (thread->pipe_command) { + thread->pipe_command->fd = -1; + delete thread->pipe_command; + } } static void ReactorThread_resume_data_receiving(Timer *timer, TimerNode *tnode) { @@ -1098,7 +1034,7 @@ void Server::start_heartbeat_thread() { ev.type = SW_SERVER_EVENT_CLOSE_FORCE; // convert fd to session_id, in order to verify the connection before the force close connection ev.fd = session_id; - Socket *_pipe_sock = get_reactor_thread_pipe(session_id, conn->reactor_id); + Socket *_pipe_sock = get_reactor_pipe_socket(session_id, conn->reactor_id); _pipe_sock->send_blocking((void *) &ev, sizeof(ev)); }); sleep(heartbeat_check_interval); diff --git a/src/server/task_worker.cc b/src/server/task_worker.cc index d1dfacbc49d..5fa19c68d8b 100644 --- a/src/server/task_worker.cc +++ b/src/server/task_worker.cc @@ -50,6 +50,36 @@ void Server::init_task_workers() { } } +static int TaskWorker_call_command_handler(ProcessPool *pool, EventData *req) { + Server *serv = (Server *) pool->ptr; + int command_id = req->info.server_fd; + auto iter = serv->command_handlers.find(command_id); + if (iter == serv->command_handlers.end()) { + swoole_error_log(SW_LOG_ERROR, SW_ERROR_SERVER_INVALID_COMMAND, "Unknown command[%d]", command_id); + return SW_OK; + } + + Server::Command::Handler handler = iter->second; + PacketPtr packet; + if (!Server::event_data_unpack(req, sw_tg_buffer(), &packet)) { + return SW_OK; + } + + auto result = handler(serv, std::string(packet.data, packet.length)); + + SendData task{}; + task.info.fd = req->info.fd; + task.info.reactor_id = SwooleWG.worker->id; + task.info.server_fd = -1; + task.info.type = SW_SERVER_EVENT_COMMAND; + task.info.len = result.length(); + task.data = result.c_str(); + + Socket *reply_sock = + serv->is_base_mode() ? serv->get_worker(0)->pipe_master : serv->pipe_command->get_socket(false); + return serv->message_bus.write(reply_sock, &task) ? SW_OK : SW_ERR; +} + static int TaskWorker_onTask(ProcessPool *pool, EventData *task) { int ret = SW_OK; Server *serv = (Server *) pool->ptr; @@ -57,6 +87,8 @@ static int TaskWorker_onTask(ProcessPool *pool, EventData *task) { if (task->info.type == SW_SERVER_EVENT_PIPE_MESSAGE) { serv->onPipeMessage(serv, task); + } else if (task->info.type == SW_SERVER_EVENT_COMMAND) { + ret = TaskWorker_call_command_handler(pool, task); } else { ret = serv->onTask(serv, task); } @@ -64,10 +96,15 @@ static int TaskWorker_onTask(ProcessPool *pool, EventData *task) { return ret; } -bool EventData::pack(const void *_data, size_t _length) { - if (_length < SW_IPC_MAX_SIZE - sizeof(info)) { - memcpy(data, _data, _length); - info.len = _length; +bool Server::event_data_pack(EventData *edata, const void *_data, size_t _length) { + edata->info.type = SW_SERVER_EVENT_TASK; + edata->info.fd = SwooleG.current_task_id++; + edata->info.reactor_id = SwooleG.process_id; + edata->info.time = swoole::microtime(); + + if (_length < SW_IPC_MAX_SIZE - sizeof(edata->info)) { + memcpy(edata->data, _data, _length); + edata->info.len = _length; return true; } @@ -82,18 +119,24 @@ bool EventData::pack(const void *_data, size_t _length) { return false; } - info.len = sizeof(pkg); - SW_TASK_TYPE(this) |= SW_TASK_TMPFILE; + edata->info.len = sizeof(pkg); + edata->info.flags |= SW_TASK_TMPFILE; swoole_strlcpy(pkg.tmpfile, file.get_path().c_str(), sizeof(pkg.tmpfile)); pkg.length = _length; - memcpy(data, &pkg, sizeof(pkg)); + memcpy(edata->data, &pkg, sizeof(pkg)); return true; } -bool EventData::unpack(String *buffer) { +bool Server::event_data_unpack(EventData *edata, String *buffer, PacketPtr *packet) { + if (!(edata->info.flags & SW_TASK_TMPFILE)) { + packet->data = edata->data; + packet->length = edata->info.len; + return true; + } + PacketTask _pkg{}; - memcpy(&_pkg, data, sizeof(_pkg)); + memcpy(&_pkg, edata->data, sizeof(_pkg)); File fp(_pkg.tmpfile, O_RDONLY); if (!fp.ready()) { @@ -106,10 +149,12 @@ bool EventData::unpack(String *buffer) { if (fp.read_all(buffer->str, _pkg.length) != _pkg.length) { return false; } - if (!(SW_TASK_TYPE(this) & SW_TASK_PEEK)) { + if (!(edata->info.flags & SW_TASK_PEEK)) { unlink(_pkg.tmpfile); } buffer->length = _pkg.length; + packet->data = buffer->str; + packet->length = buffer->length; return true; } @@ -236,7 +281,7 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even swoole_warning("Server::task()/Server::finish() is not supported in onPipeMessage callback"); return SW_ERR; } - if (SW_TASK_TYPE(current_task) & SW_TASK_NOREPLY) { + if (buf.info.flags & SW_TASK_NOREPLY) { swoole_warning("Server::finish() can only be used in the worker process"); return SW_ERR; } @@ -251,21 +296,21 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even int ret; // for swoole_server_task - if (SW_TASK_TYPE(current_task) & SW_TASK_NONBLOCK) { + if (current_task->info.flags & SW_TASK_NONBLOCK) { buf.info.type = SW_SERVER_EVENT_FINISH; buf.info.fd = current_task->info.fd; buf.info.time = microtime(); buf.info.reactor_id = SwooleWG.worker->id; // callback function - if (SW_TASK_TYPE(current_task) & SW_TASK_CALLBACK) { + if (current_task->info.flags & SW_TASK_CALLBACK) { flags |= SW_TASK_CALLBACK; - } else if (SW_TASK_TYPE(current_task) & SW_TASK_COROUTINE) { + } else if (current_task->info.flags & SW_TASK_COROUTINE) { flags |= SW_TASK_COROUTINE; } - SW_TASK_TYPE(&buf) = flags; + buf.info.flags = flags; // write to file - if (!buf.pack(data, data_len)) { + if (!event_data_pack(&buf, data, data_len)) { swoole_warning("large task pack failed()"); return SW_ERR; } @@ -291,15 +336,15 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even // lock worker worker->lock->lock(); - if (SW_TASK_TYPE(current_task) & SW_TASK_WAITALL) { + if (current_task->info.flags & SW_TASK_WAITALL) { sw_atomic_t *finish_count = (sw_atomic_t *) result->data; char *_tmpfile = result->data + 4; File file(_tmpfile, O_APPEND | O_WRONLY); if (file.ready()) { buf.info.type = SW_SERVER_EVENT_FINISH; buf.info.fd = current_task->info.fd; - SW_TASK_TYPE(&buf) = flags; - if (!buf.pack(data, data_len)) { + buf.info.flags = flags; + if (!event_data_pack(&buf, data, data_len)) { swoole_warning("large task pack failed()"); buf.info.len = 0; } @@ -312,8 +357,8 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even } else { result->info.type = SW_SERVER_EVENT_FINISH; result->info.fd = current_task->info.fd; - SW_TASK_TYPE(result) = flags; - if (!result->pack(data, data_len)) { + result->info.flags = flags; + if (!event_data_pack(result, data, data_len)) { // unlock worker worker->lock->unlock(); swoole_warning("large task pack failed()"); diff --git a/src/server/worker.cc b/src/server/worker.cc index 39e74bed173..04f36140d12 100644 --- a/src/server/worker.cc +++ b/src/server/worker.cc @@ -91,7 +91,7 @@ void Server::worker_signal_handler(int signo) { } } -static sw_inline bool Worker_discard_data(Server *serv, Connection *conn, EventData *task) { +static sw_inline bool Worker_discard_data(Server *serv, Connection *conn, DataHead *info) { if (conn == nullptr) { if (serv->disable_notify && !serv->discard_timeout_request) { return false; @@ -104,13 +104,13 @@ static sw_inline bool Worker_discard_data(Server *serv, Connection *conn, EventD return false; } } -_discard_data : { +_discard_data: swoole_error_log(SW_LOG_WARNING, SW_ERROR_SESSION_DISCARD_TIMEOUT_DATA, "[2] ignore data[%u bytes] received from session#%ld", - task->info.len, - task->info.fd); -} + info->len, + info->fd); + return true; } @@ -179,37 +179,32 @@ static int Worker_onStreamClose(Reactor *reactor, Event *event) { static int Worker_onStreamPackage(Protocol *proto, Socket *sock, const char *data, uint32_t length) { Server *serv = (Server *) proto->private_data_2; - /** - * passing memory pointer - */ - PacketPtr task{}; - memcpy(&task.info, data + 4, sizeof(task.info)); - task.info.flags = SW_EVENT_DATA_PTR; - task.data.length = length - (uint32_t) sizeof(task.info) - 4; - task.data.str = (char *) (data + 4 + sizeof(task.info)); + SendData task{}; + memcpy(&task.info, data + proto->package_length_size, sizeof(task.info)); + task.info.len = length - (uint32_t) sizeof(task.info) - proto->package_length_size; + if (task.info.len > 0) { + task.data = (char *) (data + proto->package_length_size + sizeof(task.info)); + } - /** - * do task - */ serv->last_stream_socket = sock; - serv->accept_task((EventData *) &task); + serv->message_bus.pass(&task); + serv->worker_accept_event(&serv->message_bus.get_buffer()->info); serv->last_stream_socket = nullptr; - /** - * stream end - */ int _end = 0; - SwooleTG.reactor->write(SwooleTG.reactor, sock, (void *) &_end, sizeof(_end)); + swoole_event_write(sock, (void *) &_end, sizeof(_end)); return SW_OK; } typedef std::function TaskCallback; -static sw_inline void Worker_do_task(Server *serv, Worker *worker, EventData *task, const TaskCallback &callback) { +static sw_inline void Worker_do_task(Server *serv, Worker *worker, DataHead *info, const TaskCallback &callback) { RecvData recv_data; - recv_data.info = task->info; - recv_data.info.len = serv->get_packet(task, const_cast(&recv_data.data)); + auto packet = serv->message_bus.get_packet(); + recv_data.info = *info; + recv_data.info.len = packet.length; + recv_data.data = packet.data; if (callback(serv, &recv_data) == SW_OK) { worker->request_count++; @@ -217,82 +212,85 @@ static sw_inline void Worker_do_task(Server *serv, Worker *worker, EventData *ta } } -int Server::accept_task(EventData *task) { +void Server::worker_accept_event(DataHead *info) { Worker *worker = SwooleWG.worker; // worker busy worker->status = SW_WORKER_BUSY; - switch (task->info.type) { + switch (info->type) { case SW_SERVER_EVENT_RECV_DATA: { - Connection *conn = get_connection_verify(task->info.fd); + Connection *conn = get_connection_verify(info->fd); if (conn) { - if (task->info.len > 0) { - sw_atomic_fetch_sub(&conn->recv_queued_bytes, task->info.len); - swoole_trace_log(SW_TRACE_SERVER, "[Worker] len=%d, qb=%d\n", task->info.len, conn->recv_queued_bytes); + if (info->len > 0) { + sw_atomic_fetch_sub(&conn->recv_queued_bytes, info->len); + swoole_trace_log(SW_TRACE_SERVER, "[Worker] len=%d, qb=%d\n", info->len, conn->recv_queued_bytes); } - conn->last_dispatch_time = task->info.time; + conn->last_dispatch_time = info->time; } - if (!Worker_discard_data(this, conn, task)) { - Worker_do_task(this, worker, task, onReceive); + if (!Worker_discard_data(this, conn, info)) { + Worker_do_task(this, worker, info, onReceive); } break; } case SW_SERVER_EVENT_RECV_DGRAM: { - Worker_do_task(this, worker, task, onPacket); + Worker_do_task(this, worker, info, onPacket); break; } case SW_SERVER_EVENT_CLOSE: { #ifdef SW_USE_OPENSSL - Connection *conn = get_connection_verify_no_ssl(task->info.fd); + Connection *conn = get_connection_verify_no_ssl(info->fd); if (conn && conn->ssl_client_cert && conn->ssl_client_cert_pid == SwooleG.pid) { delete conn->ssl_client_cert; conn->ssl_client_cert = nullptr; } #endif - factory->end(task->info.fd, false); + factory->end(info->fd, false); break; } case SW_SERVER_EVENT_CONNECT: { #ifdef SW_USE_OPENSSL // SSL client certificate - if (task->info.len > 0) { - Connection *conn = get_connection_verify_no_ssl(task->info.fd); + if (info->len > 0) { + Connection *conn = get_connection_verify_no_ssl(info->fd); if (conn) { - char *cert_data = nullptr; - size_t length = get_packet(task, &cert_data); - conn->ssl_client_cert = new String(cert_data, length); + auto packet = message_bus.get_packet(); + conn->ssl_client_cert = new String(packet.data, packet.length); conn->ssl_client_cert_pid = SwooleG.pid; } } #endif if (onConnect) { - onConnect(this, &task->info); + onConnect(this, info); } break; } case SW_SERVER_EVENT_BUFFER_FULL: { if (onBufferFull) { - onBufferFull(this, &task->info); + onBufferFull(this, info); } break; } case SW_SERVER_EVENT_BUFFER_EMPTY: { if (onBufferEmpty) { - onBufferEmpty(this, &task->info); + onBufferEmpty(this, info); } break; } case SW_SERVER_EVENT_FINISH: { - onFinish(this, task); + onFinish(this, (EventData *) message_bus.get_buffer()); break; } case SW_SERVER_EVENT_PIPE_MESSAGE: { - onPipeMessage(this, task); + onPipeMessage(this, (EventData *) message_bus.get_buffer()); + break; + } + case SW_SERVER_EVENT_COMMAND: { + call_command_handler(message_bus, worker->id, pipe_command->get_socket(false)); break; } default: - swoole_warning("[Worker] error event[type=%d]", (int) task->info.type); + swoole_warning("[Worker] error event[type=%d]", (int) info->type); break; } @@ -303,7 +301,6 @@ int Server::accept_task(EventData *task) { if (!SwooleWG.run_always && worker->request_count >= SwooleWG.max_request) { stop_async_worker(worker); } - return SW_OK; } void Server::worker_start_callback() { @@ -352,7 +349,7 @@ void Server::worker_start_callback() { } } - for (uint32_t i = 0; i < worker_num + task_worker_num; i++) { + SW_LOOP_N(worker_num + task_worker_num) { Worker *worker = get_worker(i); if (SwooleG.process_id == i) { continue; @@ -371,12 +368,6 @@ void Server::worker_start_callback() { if (is_process_mode()) { sw_shm_protect(session_list, PROT_READ); - /** - * Use only the first block of pipe_buffer memory in worker process - */ - for (uint32_t i = 1; i < reactor_num; i++) { - sw_free(pipe_buffers[i]); - } } #ifdef HAVE_SIGNALFD @@ -398,10 +389,10 @@ void Server::worker_stop_callback() { if (onWorkerStop) { onWorkerStop(this, SwooleG.process_id); } - if (!worker_buffers.empty()) { + if (!message_bus.empty()) { swoole_error_log( SW_LOG_WARNING, SW_ERROR_SERVER_WORKER_UNPROCESSED_DATA, "unprocessed data in the worker process buffer"); - worker_buffers.clear(); + message_bus.clear(); } } @@ -596,7 +587,7 @@ int Server::start_event_worker(Worker *worker) { * [Worker/TaskWorker/Master] Send data to ReactorThread */ ssize_t Server::send_to_reactor_thread(const EventData *ev_data, size_t sendn, SessionId session_id) { - Socket *pipe_sock = get_reactor_thread_pipe(session_id, ev_data->info.reactor_id); + Socket *pipe_sock = get_reactor_pipe_socket(session_id, ev_data->info.reactor_id); if (swoole_event_is_available()) { return swoole_event_write(pipe_sock, ev_data, sendn); } else { @@ -604,15 +595,6 @@ ssize_t Server::send_to_reactor_thread(const EventData *ev_data, size_t sendn, S } } -ssize_t Server::send_to_reactor_thread(const DataHead *head, const iovec *iov, size_t iovcnt, SessionId session_id) { - Socket *pipe_sock = get_reactor_thread_pipe(session_id, head->reactor_id); - if (swoole_event_is_available()) { - return swoole_event_writev(pipe_sock, iov, iovcnt); - } else { - return pipe_sock->writev_blocking(iov, iovcnt); - } -} - /** * send message from worker to another worker */ @@ -624,93 +606,17 @@ ssize_t Server::send_to_worker_from_worker(Worker *dst_worker, const void *buf, * receive data from reactor */ static int Worker_onPipeReceive(Reactor *reactor, Event *event) { - ssize_t recv_n = 0; Server *serv = (Server *) reactor->ptr; - PipeBuffer *pipe_buffer = serv->pipe_buffers[0]; - struct iovec buffers[2]; - int recv_chunk_count = 0; - DataHead *info = &pipe_buffer->info; - -_read_from_pipe: - recv_n = recv(event->fd, info, sizeof(pipe_buffer->info), MSG_PEEK); - if (recv_n < 0) { - if (event->socket->catch_error(errno) == SW_WAIT) { - return SW_OK; - } - return SW_ERR; - } - - if (pipe_buffer->info.flags & SW_EVENT_DATA_CHUNK) { - String *worker_buffer = serv->get_worker_buffer(info); - if (worker_buffer == nullptr) { - swoole_error_log(SW_LOG_WARNING, - SW_ERROR_SERVER_WORKER_ABNORMAL_PIPE_DATA, - "abnormal pipeline data, msg_id=%ld, pipe_fd=%d, reactor_id=%d", - info->msg_id, - event->fd, - info->reactor_id); - return SW_OK; - } - size_t remain_len = pipe_buffer->info.len - worker_buffer->length; - - buffers[0].iov_base = info; - buffers[0].iov_len = sizeof(pipe_buffer->info); - buffers[1].iov_base = worker_buffer->str + worker_buffer->length; - buffers[1].iov_len = SW_MIN(serv->ipc_max_size - sizeof(pipe_buffer->info), remain_len); - - recv_n = readv(event->fd, buffers, 2); - if (recv_n == 0) { - swoole_warning("receive pipeline data error, pipe_fd=%d, reactor_id=%d", event->fd, info->reactor_id); - return SW_ERR; - } - if (recv_n < 0 && event->socket->catch_error(errno) == SW_WAIT) { - return SW_OK; - } - if (recv_n > 0) { - worker_buffer->length += (recv_n - sizeof(pipe_buffer->info)); - swoole_trace("append msgid=%ld, buffer=%p, n=%ld", pipe_buffer->info.msg_id, worker_buffer, recv_n); - } - - recv_chunk_count++; - - if (!(pipe_buffer->info.flags & SW_EVENT_DATA_END)) { - /** - * if the reactor thread sends too many chunks to the worker process, - * the worker process may receive chunks all the time, - * resulting in the worker process being unable to handle other tasks. - * in order to make the worker process handle tasks fairly, - * the maximum number of consecutive chunks received by the worker is limited. - */ - if (recv_chunk_count >= SW_WORKER_MAX_RECV_CHUNK_COUNT) { - swoole_trace_log(SW_TRACE_WORKER, - "worker process[%u] receives the chunk data to the maximum[%d], return to event loop", - SwooleG.process_id, - recv_chunk_count); - return SW_OK; - } - goto _read_from_pipe; - } else { - /** - * Because we don't want to split the EventData parameters into DataHead and data, - * we store the value of the worker_buffer pointer in EventData.data. - * The value of this pointer will be fetched in the Server_worker_get_packet function. - */ - pipe_buffer->info.flags |= SW_EVENT_DATA_OBJ_PTR; - memcpy(pipe_buffer->data, &worker_buffer, sizeof(worker_buffer)); - swoole_trace("msg_id=%ld, len=%u", pipe_buffer->info.msg_id, pipe_buffer->info.len); - } - } else { - recv_n = event->socket->read(pipe_buffer, serv->ipc_max_size); - } + PipeBuffer *pipe_buffer = serv->message_bus.get_buffer(); - if (recv_n > 0 && serv->accept_task((EventData *) pipe_buffer) == SW_OK) { - if (pipe_buffer->info.flags & SW_EVENT_DATA_END) { - serv->worker_buffers.erase(pipe_buffer->info.msg_id); - } + if (serv->message_bus.read(event->socket) <= 0) { return SW_OK; } - return SW_ERR; + serv->worker_accept_event(&pipe_buffer->info); + serv->message_bus.pop(); + + return SW_OK; } ssize_t Worker::send_pipe_message(const void *buf, size_t n, int flags) { @@ -735,8 +641,8 @@ ssize_t Worker::send_pipe_message(const void *buf, size_t n, int flags) { return pool->queue->push((QueueNode *) &msg, n) ? n : -1; } - if ((flags & SW_PIPE_NONBLOCK) && SwooleTG.reactor) { - return SwooleTG.reactor->write(SwooleTG.reactor, pipe_sock, buf, n); + if ((flags & SW_PIPE_NONBLOCK) && swoole_event_is_available()) { + return swoole_event_write(pipe_sock, buf, n); } else { return pipe_sock->send_blocking(buf, n); } diff --git a/src/wrapper/event.cc b/src/wrapper/event.cc index f180864ab2b..d65d17f0a06 100644 --- a/src/wrapper/event.cc +++ b/src/wrapper/event.cc @@ -104,9 +104,6 @@ void swoole_event_defer(Callback cb, void *private_data) { SwooleTG.reactor->defer(cb, private_data); } -/** - * @return SW_OK or SW_ERR - */ ssize_t swoole_event_write(Socket *socket, const void *data, size_t len) { return SwooleTG.reactor->write(SwooleTG.reactor, socket, data, len); } diff --git a/tests/include/lib/composer.lock b/tests/include/lib/composer.lock index 47899b5ae29..83184e298e2 100644 --- a/tests/include/lib/composer.lock +++ b/tests/include/lib/composer.lock @@ -637,16 +637,16 @@ }, { "name": "php-http/message", - "version": "1.11.1", + "version": "1.11.2", "source": { "type": "git", "url": "https://github.com/php-http/message.git", - "reference": "887734d9c515ad9a564f6581a682fff87a6253cc" + "reference": "295c82867d07261f2fa4b3a26677519fc6f7f5f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-http/message/zipball/887734d9c515ad9a564f6581a682fff87a6253cc", - "reference": "887734d9c515ad9a564f6581a682fff87a6253cc", + "url": "https://api.github.com/repos/php-http/message/zipball/295c82867d07261f2fa4b3a26677519fc6f7f5f6", + "reference": "295c82867d07261f2fa4b3a26677519fc6f7f5f6", "shasum": "", "mirrors": [ { @@ -711,9 +711,9 @@ ], "support": { "issues": "https://github.com/php-http/message/issues", - "source": "https://github.com/php-http/message/tree/1.11.1" + "source": "https://github.com/php-http/message/tree/1.11.2" }, - "time": "2021-05-24T18:11:08+00:00" + "time": "2021-08-03T11:52:11+00:00" }, { "name": "php-http/message-factory", @@ -1251,16 +1251,16 @@ }, { "name": "symfony/http-client", - "version": "v5.3.3", + "version": "v5.3.4", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "fde4bdb10bf197f932ebccfcb9982881d296fc4c" + "reference": "67c177d4df8601d9a71f9d615c52171c98d22d74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/fde4bdb10bf197f932ebccfcb9982881d296fc4c", - "reference": "fde4bdb10bf197f932ebccfcb9982881d296fc4c", + "url": "https://api.github.com/repos/symfony/http-client/zipball/67c177d4df8601d9a71f9d615c52171c98d22d74", + "reference": "67c177d4df8601d9a71f9d615c52171c98d22d74", "shasum": "", "mirrors": [ { @@ -1271,11 +1271,11 @@ }, "require": { "php": ">=7.2.5", - "psr/log": "^1.0", + "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.1", "symfony/http-client-contracts": "^2.4", "symfony/polyfill-php73": "^1.11", - "symfony/polyfill-php80": "^1.15", + "symfony/polyfill-php80": "^1.16", "symfony/service-contracts": "^1.0|^2" }, "provide": { @@ -1324,7 +1324,7 @@ "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-client/tree/v5.3.3" + "source": "https://github.com/symfony/http-client/tree/v5.3.4" }, "funding": [ { @@ -1340,7 +1340,7 @@ "type": "tidelift" } ], - "time": "2021-06-24T08:13:00+00:00" + "time": "2021-07-23T15:55:36+00:00" }, { "name": "symfony/http-client-contracts", @@ -1428,16 +1428,16 @@ }, { "name": "symfony/options-resolver", - "version": "v5.3.0", + "version": "v5.3.4", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "162e886ca035869866d233a2bfef70cc28f9bbe5" + "reference": "a603e5701bd6e305cfc777a8b50bf081ef73105e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/162e886ca035869866d233a2bfef70cc28f9bbe5", - "reference": "162e886ca035869866d233a2bfef70cc28f9bbe5", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/a603e5701bd6e305cfc777a8b50bf081ef73105e", + "reference": "a603e5701bd6e305cfc777a8b50bf081ef73105e", "shasum": "", "mirrors": [ { @@ -1450,7 +1450,7 @@ "php": ">=7.2.5", "symfony/deprecation-contracts": "^2.1", "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.15" + "symfony/polyfill-php80": "^1.16" }, "type": "library", "autoload": { @@ -1483,7 +1483,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v5.3.0" + "source": "https://github.com/symfony/options-resolver/tree/v5.3.4" }, "funding": [ { @@ -1499,7 +1499,7 @@ "type": "tidelift" } ], - "time": "2021-05-26T17:43:10+00:00" + "time": "2021-07-23T15:55:36+00:00" }, { "name": "symfony/polyfill-php73", @@ -1588,16 +1588,16 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.23.0", + "version": "v1.23.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0" + "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/eca0bf41ed421bed1b57c4958bab16aa86b757d0", - "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be", + "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be", "shasum": "", "mirrors": [ { @@ -1657,7 +1657,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1" }, "funding": [ { @@ -1673,7 +1673,7 @@ "type": "tidelift" } ], - "time": "2021-02-19T12:13:01+00:00" + "time": "2021-07-28T13:41:28+00:00" }, { "name": "symfony/service-contracts", diff --git a/tests/swoole_server/bug_2308.phpt b/tests/swoole_server/bug_2308.phpt index 2708565ae5f..3da281ec2b3 100644 --- a/tests/swoole_server/bug_2308.phpt +++ b/tests/swoole_server/bug_2308.phpt @@ -6,13 +6,15 @@ swoole_server: bug Github#2308 parentFunc = function ($pid) use ($pm) { $pm->kill(); }; $pm->childFunc = function () use ($pm) { - $server = new \Swoole\Server('0.0.0.0', 9501, SWOOLE_BASE, SWOOLE_SOCK_TCP); + $server = new Server('0.0.0.0', 9501, SWOOLE_BASE, SWOOLE_SOCK_TCP); $server->set([ 'worker_num' => MAX_PROCESS_NUM, 'log_file' => '/dev/null', @@ -21,10 +23,11 @@ $pm->childFunc = function () use ($pm) { $server->on('start', function () { \Swoole\Coroutine::create(function () { $redis = new \Swoole\Coroutine\Redis(); - $redis->connect('127.0.0.1', 6379); - while (true) { - $msg = $redis->subscribe(['task']); - } + $redis->connect(REDIS_SERVER_HOST, REDIS_SERVER_PORT); + $ret = $redis->set('foo', 'bar'); + Assert::assert($ret); + $ret = $redis->get('foo'); + Assert::same($ret, 'bar'); }); }); $server->on('workerStart', function ($server) { @@ -32,7 +35,7 @@ $pm->childFunc = function () use ($pm) { $server->stop(); }); }); - $server->on('Receive', function (swoole_server $server, int $fd, int $reactor_id, string $data) { + $server->on('Receive', function (Server $server, int $fd, int $reactor_id, string $data) { }); $server->start(); }; @@ -41,4 +44,4 @@ $pm->childFirst(); $pm->run(); ?> --EXPECTF-- -Fatal error: Swoole\Coroutine::create(): Unable to use async-io in manager process in %s on line %d + diff --git a/tests/swoole_server/command.phpt b/tests/swoole_server/command.phpt new file mode 100644 index 00000000000..3f34b4f8696 --- /dev/null +++ b/tests/swoole_server/command.phpt @@ -0,0 +1,40 @@ +--TEST-- +swoole_server: command [1] +--SKIPIF-- + +--FILE-- +addCommand('test_getpid', SWOOLE_SERVER_COMMAND_MASTER | SWOOLE_SERVER_COMMAND_EVENT_WORKER, + function ($server) { + return json_encode(['pid' => posix_getpid()]); + }); +$server->set([ + 'log_file' => '/dev/null', + 'worker_num' => 2, +]); + +$server->on('start', function (Server $serv) { + $result = $serv->command('test_getpid', 0, SWOOLE_SERVER_COMMAND_MASTER, ['type' => 'master']); + Assert::eq($result['pid'], $serv->getMasterPid()); + $result = $serv->command('test_getpid', 1, SWOOLE_SERVER_COMMAND_EVENT_WORKER, ['type' => 'worker'],); + Assert::eq($result['pid'], $serv->getWorkerPid(1)); + $result = $serv->command('test_not_found', 1, SWOOLE_SERVER_COMMAND_EVENT_WORKER, ['type' => 'worker'],); + Assert::false($result); + + $serv->shutdown(); +}); + +$server->on('request', function (Request $request, Response $response) { +}); +$server->start(); +echo "DONE\n"; +?> +--EXPECT-- +DONE diff --git a/tests/swoole_server/force_reload.phpt b/tests/swoole_server/force_reload.phpt index 07cdf14f164..c5ccee679e0 100644 --- a/tests/swoole_server/force_reload.phpt +++ b/tests/swoole_server/force_reload.phpt @@ -66,10 +66,10 @@ $pm->run(); %d [%d] start %s start to reload [%s] INFO Server is reloading all workers now -[%s] WARNING Manager::kill_timeout_process() (ERRNO 9012): worker(pid=%d, id=%d) exit timeout, force kill the process -[%s] WARNING Manager::kill_timeout_process() (ERRNO 9012): worker(pid=%d, id=%d) exit timeout, force kill the process -[%s] WARNING Manager::kill_timeout_process() (ERRNO 9012): worker(pid=%d, id=%d) exit timeout, force kill the process -[%s] WARNING Manager::kill_timeout_process() (ERRNO 9012): worker(pid=%d, id=%d) exit timeout, force kill the process +[%s] WARNING Manager::kill_timeout_process() (ERRNO 9101): worker(pid=%d, id=%d) exit timeout, force kill the process +[%s] WARNING Manager::kill_timeout_process() (ERRNO 9101): worker(pid=%d, id=%d) exit timeout, force kill the process +[%s] WARNING Manager::kill_timeout_process() (ERRNO 9101): worker(pid=%d, id=%d) exit timeout, force kill the process +[%s] WARNING Manager::kill_timeout_process() (ERRNO 9101): worker(pid=%d, id=%d) exit timeout, force kill the process [%s] WARNING Server::check_worker_exit_status(): worker(pid=%d, id=%d) abnormal exit, status=0, signal=9 [%s] WARNING Server::check_worker_exit_status(): worker(pid=%d, id=%d) abnormal exit, status=0, signal=9 [%s] WARNING Server::check_worker_exit_status(): worker(pid=%d, id=%d) abnormal exit, status=0, signal=9 diff --git a/tests/swoole_server/force_reload4.phpt b/tests/swoole_server/force_reload4.phpt index 03b8007b464..821fe0b919c 100644 --- a/tests/swoole_server/force_reload4.phpt +++ b/tests/swoole_server/force_reload4.phpt @@ -41,5 +41,5 @@ $pm->run(); ?> --EXPECTF-- [%s] INFO Server is shutdown now -[%s] WARNING %s (ERRNO 9012): worker exit timeout, forced termination +[%s] WARNING %s (ERRNO 9101): worker exit timeout, forced termination OK diff --git a/tests/swoole_server/send_2.phpt b/tests/swoole_server/send_2.phpt index b31ebadea2f..16178eff59d 100644 --- a/tests/swoole_server/send_2.phpt +++ b/tests/swoole_server/send_2.phpt @@ -8,6 +8,8 @@ require __DIR__ . '/../include/skipif.inc'; parentFunc = function ($pid) use ($pm) { @@ -32,8 +34,9 @@ $pm->parentFunc = function ($pid) use ($pm) { Assert::assert($data); $char = chr(ord('A') + $n % 10); $info = unpack('Nlen', substr($data, 0, 4)); - -// echo "c=$i, n=$n, len={$info['len']}\n---------------------------------------------------------------------\n"; + if (VERBOSE) { + echo "[Client] c=$i, n=$n, len={$info['len']}\n---------------------------------------------------------------------\n"; + } Assert::same($info['len'], strlen($data) - 4); Assert::same(str_repeat($char, 1024), substr($data, rand(4, $info['len'] - 1024 - 4), 1024)); $total += strlen($data); @@ -41,14 +44,14 @@ $pm->parentFunc = function ($pid) use ($pm) { }); } swoole_event::wait(); - echo $total." bytes\n"; + echo $total . " bytes\n"; $pm->kill(); }; $pm->childFunc = function () use ($pm) { $serv = new Swoole\Server('127.0.0.1', $pm->getFreePort(), SWOOLE_PROCESS); $serv->set(array( - "worker_num" => IS_IN_TRAVIS ? 2 : 4, + "worker_num" => 1, 'log_level' => SWOOLE_LOG_ERROR, 'open_length_check' => true, 'package_max_length' => 4 * 1024 * 1024, @@ -61,19 +64,23 @@ $pm->childFunc = function () use ($pm) { $pm->wakeup(); }); $serv->on('connect', function (Swoole\Server $serv, $fd, $rid) { -// echo "new client, fd=$fd\n"; + if (VERBOSE) { + echo "new client, fd=$fd\n"; + } $n = MAX_REQUESTS; while ($n--) { $len = rand(8192, 1024 * 1024); $send_data = str_repeat(chr(ord('A') + $n % 10), $len); + if (VERBOSE) { + echo "[Server] c=$fd, n=$n, len=" . (strlen($send_data) + 4) . "\n---------------------------------------------------------------------\n"; + } $retval = $serv->send($fd, pack('N', $len) . $send_data); if ($retval === false) { - echo "send error, code=".swoole_last_error()."\n"; + echo "send error, code=" . swoole_last_error() . "\n"; } } }); $serv->on('receive', function (Swoole\Server $serv, $fd, $rid, $data) { - }); $serv->start(); }; diff --git a/tests/swoole_server/slow_worker.phpt b/tests/swoole_server/slow_worker.phpt index 1aafc4af0db..3c0dab84314 100644 --- a/tests/swoole_server/slow_worker.phpt +++ b/tests/swoole_server/slow_worker.phpt @@ -45,7 +45,7 @@ $pm->parentFunc = function ($pid) use ($pm, $counter_server, $counter_client, $d $pm->childFunc = function () use ($pm, $counter_server, $counter_client) { $serv = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_PROCESS); $serv->set(array( - "worker_num" => 1, + 'worker_num' => 1, 'log_file' => '/dev/null', 'open_length_check' => true, 'package_max_length' => 16 * 1024 * 1024, From a73780ef044cd024db467188367da0c7987ba588 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Fri, 27 Aug 2021 15:16:32 +0800 Subject: [PATCH 226/936] The uploaded file name does not need to be url-decoded --- ext-src/php_swoole_http.h | 2 +- ext-src/swoole_http_request.cc | 8 ++-- tests/swoole_http_server/upload4.phpt | 63 +++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 tests/swoole_http_server/upload4.phpt diff --git a/ext-src/php_swoole_http.h b/ext-src/php_swoole_http.h index 8111419b7e1..7bc7ebf096a 100644 --- a/ext-src/php_swoole_http.h +++ b/ext-src/php_swoole_http.h @@ -295,7 +295,7 @@ static inline bool swoole_http_has_crlf(const char *value, size_t length) { return false; } -void swoole_http_parse_cookie(zval *array, const char *at, size_t length); +void swoole_http_parse_cookie(zval *array, const char *at, size_t length, bool url_decode = true); swoole::http::Context *php_swoole_http_request_get_context(zval *zobject); void php_swoole_http_request_set_context(zval *zobject, swoole::http::Context *context); diff --git a/ext-src/swoole_http_request.cc b/ext-src/swoole_http_request.cc index a87281d33e6..4c5c808c349 100644 --- a/ext-src/swoole_http_request.cc +++ b/ext-src/swoole_http_request.cc @@ -276,7 +276,7 @@ bool HttpContext::parse_form_data(const char *boundary_str, int boundary_len) { return true; } -void swoole_http_parse_cookie(zval *zarray, const char *at, size_t length) { +void swoole_http_parse_cookie(zval *zarray, const char *at, size_t length, bool url_decode) { char keybuf[SW_HTTP_COOKIE_KEYLEN]; char valbuf[SW_HTTP_COOKIE_VALLEN]; char *_c = (char *) at; @@ -354,7 +354,9 @@ void swoole_http_parse_cookie(zval *zarray, const char *at, size_t length) { memcpy(valbuf, (char *) at + j, vlen); valbuf[vlen] = 0; _value = http_trim_double_quote(valbuf, &vlen); - vlen = php_url_decode(_value, vlen); + if (url_decode) { + vlen = php_url_decode(_value, vlen); + } if (klen > 1) { add_assoc_stringl_ex(zarray, keybuf, klen - 1, _value, vlen); } @@ -518,7 +520,7 @@ static int multipart_body_on_header_value(multipart_parser *p, const char *at, s zval tmp_array; array_init(&tmp_array); - swoole_http_parse_cookie(&tmp_array, at + sizeof("form-data;") - 1, length - sizeof("form-data;") + 1); + swoole_http_parse_cookie(&tmp_array, at + sizeof("form-data;") - 1, length - sizeof("form-data;") + 1, false); zval *zform_name; if (!(zform_name = zend_hash_str_find(Z_ARRVAL(tmp_array), ZEND_STRL("name")))) { diff --git a/tests/swoole_http_server/upload4.phpt b/tests/swoole_http_server/upload4.phpt new file mode 100644 index 00000000000..b06e84b0508 --- /dev/null +++ b/tests/swoole_http_server/upload4.phpt @@ -0,0 +1,63 @@ +--TEST-- +swoole_http_server: upload 04 +--SKIPIF-- + +--FILE-- +parentFunc = function () use ($pm) { + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, "http://127.0.0.1:{$pm->getFreePort()}"); + curl_setopt($ch, CURLOPT_HEADER, 0); + curl_setopt($ch, CURLOPT_POST, 1); //设置为POST方式 + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:')); + + $file = TEST_IMAGE; + + $post_data = array('test' => str_repeat('a', 80)); + + $cfile = curl_file_create($file); + $cfile->setPostFilename(FILENAME); + $post_data['file'] = $cfile; + + curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); //POST数据 + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + $res = curl_exec($ch); + Assert::assert(!empty($res)); + Assert::eq($res, FILENAME); + curl_close($ch); + + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm) { + $http = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_BASE); + + $http->set([ + 'log_file' => '/dev/null' + ]); + + $http->on("WorkerStart", function () use ($pm) { + $pm->wakeup(); + }); + + $http->on("request", function (swoole_http_request $request, swoole_http_response $response) { + $response->end($request->files['file']['name']); + }); + + $http->start(); +}; + +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- From 6f09d43c2771fd15bcb8045fc3020d5d05af2938 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Mon, 30 Aug 2021 19:31:28 +0800 Subject: [PATCH 227/936] Fix wrong branch condition --- ext-src/swoole_server.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 934443abd21..c4afc692aae 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -883,7 +883,7 @@ zval *php_swoole_task_unpack(EventData *task_result) { php_unserialize_data_t var_hash; PacketPtr packet; - if (Server::event_data_unpack(task_result, sw_tg_buffer(), &packet)) { + if (!Server::event_data_unpack(task_result, sw_tg_buffer(), &packet)) { return nullptr; } From d27c5a5d7456c94d79223501669adb543c91e730 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Mon, 30 Aug 2021 20:20:06 +0800 Subject: [PATCH 228/936] Set error code when websocket pack fails --- ext-src/swoole_websocket_server.cc | 4 ++++ include/swoole_error.h | 1 + 2 files changed, 5 insertions(+) diff --git a/ext-src/swoole_websocket_server.cc b/ext-src/swoole_websocket_server.cc index f95213efd43..b94cfcaff8d 100644 --- a/ext-src/swoole_websocket_server.cc +++ b/ext-src/swoole_websocket_server.cc @@ -813,6 +813,8 @@ static PHP_METHOD(swoole_websocket_server, push) { #ifdef SW_HAVE_ZLIB Connection *conn = serv->get_connection_verify(fd); if (!conn) { + swoole_set_last_error(SW_ERROR_SESSION_NOT_EXIST); + php_swoole_fatal_error(E_WARNING, "session#%ld does not exists", fd); RETURN_FALSE; } allow_compress = conn->websocket_compression; @@ -821,11 +823,13 @@ static PHP_METHOD(swoole_websocket_server, push) { swoole_http_buffer->clear(); if (php_swoole_websocket_frame_is_object(zdata)) { if (php_swoole_websocket_frame_object_pack(swoole_http_buffer, zdata, 0, allow_compress) < 0) { + swoole_set_last_error(SW_ERROR_WEBSOCKET_PACK_FAILED); RETURN_FALSE; } } else { if (php_swoole_websocket_frame_pack( swoole_http_buffer, zdata, opcode, flags & WebSocket::FLAGS_ALL, 0, allow_compress) < 0) { + swoole_set_last_error(SW_ERROR_WEBSOCKET_PACK_FAILED); RETURN_FALSE; } } diff --git a/include/swoole_error.h b/include/swoole_error.h index a7398b8c40b..78dac8f4f7e 100644 --- a/include/swoole_error.h +++ b/include/swoole_error.h @@ -128,6 +128,7 @@ enum swErrorCode { SW_ERROR_WEBSOCKET_BAD_OPCODE, SW_ERROR_WEBSOCKET_UNCONNECTED, SW_ERROR_WEBSOCKET_HANDSHAKE_FAILED, + SW_ERROR_WEBSOCKET_PACK_FAILED, /** * server global error From 8c99d68c7ca2e28ae0f2d7665fa02d856d221fe9 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Mon, 30 Aug 2021 20:20:40 +0800 Subject: [PATCH 229/936] Optimize signal-driven timer code --- src/core/timer.cc | 8 ++-- tests/swoole_server/task/timer.phpt | 69 +++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 tests/swoole_server/task/timer.phpt diff --git a/src/core/timer.cc b/src/core/timer.cc index 619475dbffc..8e0eca52573 100644 --- a/src/core/timer.cc +++ b/src/core/timer.cc @@ -231,11 +231,11 @@ int Timer::select() { next_msec_ = -1; set(this, -1); } else { - long next_msec = tnode->exec_msec - now_msec; - if (next_msec <= 0) { - next_msec = 1; + next_msec_ = tnode->exec_msec - now_msec; + if (next_msec_ <= 0) { + next_msec_ = 1; } - set(this, next_msec); + set(this, next_msec_); } round++; diff --git a/tests/swoole_server/task/timer.phpt b/tests/swoole_server/task/timer.phpt new file mode 100644 index 00000000000..03217ff7880 --- /dev/null +++ b/tests/swoole_server/task/timer.phpt @@ -0,0 +1,69 @@ +--TEST-- +swoole_server/task: timer +--SKIPIF-- + +--FILE-- +parentFunc = function (int $pid) use ($pm) { + run(function () use ($pm) { + $cli = new Client('127.0.0.1', $pm->getFreePort()); + $cli->set(['websocket_compression' => true, ]); + $cli->upgrade('/'); + $cli->push('Hello Swoole'); + $data = $cli->recv(5); + Assert::eq($data->data, 'OK'); + echo "DONE\n"; + }); + $pm->kill(); +}; +$pm->childFunc = function () use ($pm) { + $http = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_PROCESS); + $http->set([ + 'worker_num' => 1, + 'task_worker_num' => 1, + 'event_object' => true, + 'log_file' => '/dev/null', + ]); + $http->on('message', function (Server $server, Frame $frame) { + $server->task(['fd' => $frame->fd]); + }); + $http->on('WorkerStart', function (Server $server, int $workerId) { + if ($server->taskworker) { + swoole_timer_after(1, function () use ($server, $workerId) { + var_dump("after1 : " . time()); + }); + // never callback + swoole_timer_after(10000, function () use ($server, $workerId) { + var_dump("after2 : " . time()); + }); + } + }); + $http->on('task', function (Server $server, Task $task) { + var_dump('begin : ' . time()); + swoole_timer_after(2000, function () use ($server, $task) { + var_dump('end : ' . time()); + Assert::true($server->push($task->data['fd'], "OK")); + }); + }); + $http->start(); +}; +$pm->childFirst(); +$pm->run(); +?> +--EXPECTF-- +string(19) "after1 : %d" +string(18) "begin : %d" +string(16) "end : %d" +DONE From 8acb5efa1a34e0b5c17889d15c1a64a0d8fccd70 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 31 Aug 2021 10:56:14 +0800 Subject: [PATCH 230/936] Fix Server::getWorkerId() --- ext-src/swoole_server.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index c4afc692aae..e2a5fc462e4 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -3880,7 +3880,7 @@ static PHP_METHOD(swoole_server, getWorkerPid) { if (!worker) { RETURN_FALSE; } - RETURN_LONG(serv->get_worker(worker_id)->pid); + RETURN_LONG(worker->pid); } static PHP_METHOD(swoole_server, getManagerPid) { From b1f83ab503868d8d7d7a990be0cb4f62c20d89d9 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 31 Aug 2021 14:59:50 +0800 Subject: [PATCH 231/936] Optimize Server::task, use ext_flags, fix tests --- core-tests/src/core/base.cpp | 6 +- core-tests/src/server/server.cpp | 2 +- ext-src/php_swoole.cc | 10 ++-- ext-src/swoole_server.cc | 39 +++++++------ include/swoole.h | 2 + include/swoole_server.h | 4 +- src/core/base.cc | 17 +++--- src/server/master.cc | 2 +- src/server/task_worker.cc | 81 +++++++++++++-------------- tests/swoole_server/task/task_co.phpt | 50 ++++++++--------- 10 files changed, 105 insertions(+), 108 deletions(-) diff --git a/core-tests/src/core/base.cpp b/core-tests/src/core/base.cpp index f92da6c178e..47827a8d411 100644 --- a/core-tests/src/core/base.cpp +++ b/core-tests/src/core/base.cpp @@ -125,16 +125,16 @@ TEST(base, file_size) { TEST(base, eventdata_pack) { EventData ed1 { }; - ASSERT_TRUE(Server::event_data_pack(&ed1, test_data.c_str(), test_data.length())); + ASSERT_TRUE(Server::task_pack(&ed1, test_data.c_str(), test_data.length())); ASSERT_EQ(string(ed1.data, ed1.info.len), test_data); EventData ed2 { }; ASSERT_EQ(swoole_random_bytes(sw_tg_buffer()->str, SW_BUFFER_SIZE_BIG), SW_BUFFER_SIZE_BIG); - ASSERT_TRUE(Server::event_data_pack(&ed2, sw_tg_buffer()->str, SW_BUFFER_SIZE_BIG)); + ASSERT_TRUE(Server::task_pack(&ed2, sw_tg_buffer()->str, SW_BUFFER_SIZE_BIG)); String _buffer(SW_BUFFER_SIZE_BIG); PacketPtr packet; - ASSERT_TRUE(Server::event_data_unpack(&ed2, &_buffer, &packet)); + ASSERT_TRUE(Server::task_unpack(&ed2, &_buffer, &packet)); ASSERT_EQ(memcmp(sw_tg_buffer()->str, _buffer.str, SW_BUFFER_SIZE_BIG), 0); } diff --git a/core-tests/src/server/server.cpp b/core-tests/src/server/server.cpp index 5417a856199..1d357428ad7 100644 --- a/core-tests/src/server/server.cpp +++ b/core-tests/src/server/server.cpp @@ -317,7 +317,7 @@ TEST(server, task_worker) { EventData buf; memset(&buf.info, 0, sizeof(buf.info)); - buf.info.flags = SW_TASK_NOREPLY; + buf.info.ext_flags = SW_TASK_NOREPLY; buf.info.len = strlen(packet); memcpy(buf.data, packet, strlen(packet)); diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index 587f12a20b7..dd45d6d8f05 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -419,10 +419,7 @@ static void fatal_error(int code, const char *format, ...) { } static void bug_report_message_init() { - SwooleG.bug_report_message += swoole::std_string::format( - "PHP_VERSION : %s\n", - PHP_VERSION - ); + SwooleG.bug_report_message += swoole::std_string::format("PHP_VERSION : %s\n", PHP_VERSION); } /* {{{ PHP_MINIT_FUNCTION @@ -1110,11 +1107,12 @@ static PHP_FUNCTION(swoole_hashcode) { ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); switch (type) { + case 0: + RETURN_LONG(zend_hash_func(data, l_data)); case 1: RETURN_LONG(hashkit_one_at_a_time(data, l_data)); - break; /* ide */ default: - RETURN_LONG(zend_hash_func(data, l_data)); + RETURN_FALSE; } } diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index e2a5fc462e4..339a95265c3 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -811,14 +811,13 @@ TaskId php_swoole_task_pack(EventData *task, zval *zdata) { smart_str serialized_data = {}; php_serialize_data_t var_hash; - task->info.flags = 0; - + bool serialized = false; char *task_data_str; size_t task_data_len = 0; // need serialize if (Z_TYPE_P(zdata) != IS_STRING) { // serialize - task->info.flags |= SW_TASK_SERIALIZE; + serialized = true; PHP_VAR_SERIALIZE_INIT(var_hash); php_var_serialize(&serialized_data, zdata, &var_hash); @@ -834,12 +833,16 @@ TaskId php_swoole_task_pack(EventData *task, zval *zdata) { task_data_len = Z_STRLEN_P(zdata); } - if (!Server::event_data_pack(task, task_data_str, task_data_len)) { + if (!Server::task_pack(task, task_data_str, task_data_len)) { php_swoole_fatal_error(E_WARNING, "large task pack failed"); task->info.fd = SW_ERR; task->info.len = 0; } + if (serialized) { + task->info.ext_flags |= SW_TASK_SERIALIZE; + } + smart_str_free(&serialized_data); return task->info.fd; } @@ -883,14 +886,14 @@ zval *php_swoole_task_unpack(EventData *task_result) { php_unserialize_data_t var_hash; PacketPtr packet; - if (!Server::event_data_unpack(task_result, sw_tg_buffer(), &packet)) { + if (!Server::task_unpack(task_result, sw_tg_buffer(), &packet)) { return nullptr; } char *result_data_str = packet.data; size_t result_data_len = packet.length; - if (task_result->info.flags & SW_TASK_SERIALIZE) { + if (task_result->info.ext_flags & SW_TASK_SERIALIZE) { result_unserialized_data = sw_malloc_zval(); PHP_VAR_UNSERIALIZE_INIT(var_hash); @@ -1401,7 +1404,7 @@ static sw_inline void php_swoole_create_task_object(zval *ztask, Server *serv, E zend_update_property(swoole_server_task_ce, SW_Z8_OBJ_P(ztask), ZEND_STRL("data"), zdata); zend_update_property_double(swoole_server_task_ce, SW_Z8_OBJ_P(ztask), ZEND_STRL("dispatch_time"), req->info.time); zend_update_property_long( - swoole_server_task_ce, SW_Z8_OBJ_P(ztask), ZEND_STRL("flags"), (zend_long) req->info.flags); + swoole_server_task_ce, SW_Z8_OBJ_P(ztask), ZEND_STRL("flags"), (zend_long) req->info.ext_flags); } static int php_swoole_server_onTask(Server *serv, EventData *req) { @@ -1461,7 +1464,7 @@ static int php_swoole_server_onFinish(Server *serv, EventData *req) { return SW_ERR; } - if (req->info.flags & SW_TASK_COROUTINE) { + if (req->info.ext_flags & SW_TASK_COROUTINE) { TaskId task_id = req->info.fd; auto task_co_iterator = server_object->property->task_coroutine_map.find(task_id); @@ -1503,10 +1506,10 @@ static int php_swoole_server_onFinish(Server *serv, EventData *req) { } zend_fcall_info_cache *fci_cache = nullptr; - if (req->info.flags & SW_TASK_CALLBACK) { + if (req->info.ext_flags & SW_TASK_CALLBACK) { auto callback_iterator = server_object->property->task_callbacks.find(req->info.fd); if (callback_iterator == server_object->property->task_callbacks.end()) { - req->info.flags = req->info.flags & (~SW_TASK_CALLBACK); + req->info.ext_flags = req->info.ext_flags & (~SW_TASK_CALLBACK); } else { fci_cache = &callback_iterator->second; } @@ -1545,7 +1548,7 @@ static int php_swoole_server_onFinish(Server *serv, EventData *req) { if (UNEXPECTED(!zend::function::call(fci_cache, argc, args, nullptr, serv->enable_coroutine))) { php_swoole_error(E_WARNING, "%s->onFinish handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } - if (req->info.flags & SW_TASK_CALLBACK) { + if (req->info.ext_flags & SW_TASK_CALLBACK) { sw_zend_fci_cache_discard(fci_cache); server_object->property->task_callbacks.erase(req->info.fd); } @@ -3075,7 +3078,7 @@ static PHP_METHOD(swoole_server, taskwait) { // coroutine if (PHPCoroutine::get_cid() >= 0) { ServerObject *server_object = server_fetch_object(Z_OBJ_P((zval *) serv->private_data_2)); - buf.info.flags |= (SW_TASK_NONBLOCK | SW_TASK_COROUTINE); + buf.info.ext_flags |= (SW_TASK_NONBLOCK | SW_TASK_COROUTINE); TaskCo task_co{}; task_co.co = Coroutine::get_current_safe(); @@ -3211,7 +3214,7 @@ static PHP_METHOD(swoole_server, taskWaitMulti) { php_swoole_fatal_error(E_WARNING, "task pack failed"); goto _fail; } - buf.info.flags |= SW_TASK_WAITALL; + buf.info.ext_flags |= SW_TASK_WAITALL; dst_worker_id = -1; sw_atomic_fetch_add(&serv->gs->tasking_num, 1); if (serv->gs->task_workers.dispatch_blocking(&buf, &dst_worker_id) < 0) { @@ -3331,7 +3334,7 @@ static PHP_METHOD(swoole_server, taskCo) { php_swoole_fatal_error(E_WARNING, "failed to pack task"); goto _fail; } - buf.info.flags |= (SW_TASK_NONBLOCK | SW_TASK_COROUTINE); + buf.info.ext_flags |= (SW_TASK_NONBLOCK | SW_TASK_COROUTINE); dst_worker_id = -1; sw_atomic_fetch_add(&serv->gs->tasking_num, 1); if (serv->gs->task_workers.dispatch(&buf, &dst_worker_id) < 0) { @@ -3399,14 +3402,14 @@ static PHP_METHOD(swoole_server, task) { } if (!serv->is_worker()) { - buf.info.flags |= SW_TASK_NOREPLY; + buf.info.ext_flags |= SW_TASK_NOREPLY; } else if (fci.size) { - buf.info.flags |= SW_TASK_CALLBACK; + buf.info.ext_flags |= SW_TASK_CALLBACK; sw_zend_fci_cache_persist(&fci_cache); server_object->property->task_callbacks[buf.info.fd] = fci_cache; } - buf.info.flags |= SW_TASK_NONBLOCK; + buf.info.ext_flags |= SW_TASK_NONBLOCK; int _dst_worker_id = (int) dst_worker_id; sw_atomic_fetch_add(&serv->gs->tasking_num, 1); @@ -3576,7 +3579,7 @@ static PHP_METHOD(swoole_server_task, pack) { if (php_swoole_task_pack(&buf, zdata) < 0) { RETURN_FALSE; } - buf.info.flags |= (SW_TASK_NONBLOCK | SW_TASK_NOREPLY); + buf.info.ext_flags |= (SW_TASK_NONBLOCK | SW_TASK_NOREPLY); RETURN_STRINGL((char *) &buf, sizeof(buf.info) + buf.info.len); } diff --git a/include/swoole.h b/include/swoole.h index f62d7c0649f..1c9e76a2000 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -584,8 +584,10 @@ struct DataHead { uint8_t flags; uint16_t server_fd; uint16_t ext_flags; + uint32_t reserved; double time; size_t dump(char *buf, size_t len); + void print(); }; struct EventData { diff --git a/include/swoole_server.h b/include/swoole_server.h index 68a6c50c813..053f5315267 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -1450,8 +1450,8 @@ class Server { void worker_accept_event(DataHead *info); static void worker_signal_handler(int signo); static void worker_signal_init(void); - static bool event_data_pack(EventData *edata, const void *data, size_t data_len); - static bool event_data_unpack(EventData *edata, String *buffer, PacketPtr *packet); + static bool task_pack(EventData *task, const void *data, size_t data_len); + static bool task_unpack(EventData *task, String *buffer, PacketPtr *packet); private: enum Mode mode_; diff --git a/src/core/base.cc b/src/core/base.cc index d7bac888a96..af2a4b7d9d5 100644 --- a/src/core/base.cc +++ b/src/core/base.cc @@ -116,18 +116,12 @@ static void bug_report_message_init() { struct utsname u; if (uname(&u) != -1) { - SwooleG.bug_report_message += swoole::std_string::format( - "OS: %s %s %s %s\n", - u.sysname, - u.release, - u.version, - u.machine); + SwooleG.bug_report_message += + swoole::std_string::format("OS: %s %s %s %s\n", u.sysname, u.release, u.version, u.machine); } #ifdef __VERSION__ - SwooleG.bug_report_message += swoole::std_string::format( - "GCC_VERSION: %s\n", - __VERSION__); + SwooleG.bug_report_message += swoole::std_string::format("GCC_VERSION: %s\n", __VERSION__); #endif #ifdef SW_USE_OPENSSL @@ -878,6 +872,11 @@ size_t DataHead::dump(char *_buf, size_t _len) { time); } +void DataHead::print() { + sw_tg_buffer()->length = dump(sw_tg_buffer()->str, sw_tg_buffer()->size); + printf("%.*s", (int) sw_tg_buffer()->length, sw_tg_buffer()->str); +} + std::string dirname(const std::string &file) { size_t index = file.find_last_of('/'); if (index == std::string::npos) { diff --git a/src/server/master.cc b/src/server/master.cc index 33f6c967069..e905c55397b 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -1064,7 +1064,7 @@ bool Server::command(WorkerId process_id, } EventData buf; memset(&buf.info, 0, sizeof(buf.info)); - if (!event_data_pack(&buf, msg.c_str(), msg.length())) { + if (!task_pack(&buf, msg.c_str(), msg.length())) { return false; } buf.info.type = SW_SERVER_EVENT_COMMAND; diff --git a/src/server/task_worker.cc b/src/server/task_worker.cc index 5fa19c68d8b..b075f408723 100644 --- a/src/server/task_worker.cc +++ b/src/server/task_worker.cc @@ -61,7 +61,7 @@ static int TaskWorker_call_command_handler(ProcessPool *pool, EventData *req) { Server::Command::Handler handler = iter->second; PacketPtr packet; - if (!Server::event_data_unpack(req, sw_tg_buffer(), &packet)) { + if (!Server::task_unpack(req, sw_tg_buffer(), &packet)) { return SW_OK; } @@ -96,15 +96,15 @@ static int TaskWorker_onTask(ProcessPool *pool, EventData *task) { return ret; } -bool Server::event_data_pack(EventData *edata, const void *_data, size_t _length) { - edata->info.type = SW_SERVER_EVENT_TASK; - edata->info.fd = SwooleG.current_task_id++; - edata->info.reactor_id = SwooleG.process_id; - edata->info.time = swoole::microtime(); +bool Server::task_pack(EventData *task, const void *_data, size_t _length) { + task->info.type = SW_SERVER_EVENT_TASK; + task->info.fd = SwooleG.current_task_id++; + task->info.reactor_id = SwooleG.process_id; + task->info.time = swoole::microtime(); - if (_length < SW_IPC_MAX_SIZE - sizeof(edata->info)) { - memcpy(edata->data, _data, _length); - edata->info.len = _length; + if (_length < SW_IPC_MAX_SIZE - sizeof(task->info)) { + memcpy(task->data, _data, _length); + task->info.len = _length; return true; } @@ -119,24 +119,24 @@ bool Server::event_data_pack(EventData *edata, const void *_data, size_t _length return false; } - edata->info.len = sizeof(pkg); - edata->info.flags |= SW_TASK_TMPFILE; + task->info.len = sizeof(pkg); + task->info.ext_flags |= SW_TASK_TMPFILE; swoole_strlcpy(pkg.tmpfile, file.get_path().c_str(), sizeof(pkg.tmpfile)); pkg.length = _length; - memcpy(edata->data, &pkg, sizeof(pkg)); + memcpy(task->data, &pkg, sizeof(pkg)); return true; } -bool Server::event_data_unpack(EventData *edata, String *buffer, PacketPtr *packet) { - if (!(edata->info.flags & SW_TASK_TMPFILE)) { - packet->data = edata->data; - packet->length = edata->info.len; +bool Server::task_unpack(EventData *task, String *buffer, PacketPtr *packet) { + if (!(task->info.ext_flags & SW_TASK_TMPFILE)) { + packet->data = task->data; + packet->length = task->info.len; return true; } PacketTask _pkg{}; - memcpy(&_pkg, edata->data, sizeof(_pkg)); + memcpy(&_pkg, task->data, sizeof(_pkg)); File fp(_pkg.tmpfile, O_RDONLY); if (!fp.ready()) { @@ -149,7 +149,7 @@ bool Server::event_data_unpack(EventData *edata, String *buffer, PacketPtr *pack if (fp.read_all(buffer->str, _pkg.length) != _pkg.length) { return false; } - if (!(edata->info.flags & SW_TASK_PEEK)) { + if (!(task->info.ext_flags & SW_TASK_PEEK)) { unlink(_pkg.tmpfile); } buffer->length = _pkg.length; @@ -281,7 +281,7 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even swoole_warning("Server::task()/Server::finish() is not supported in onPipeMessage callback"); return SW_ERR; } - if (buf.info.flags & SW_TASK_NOREPLY) { + if (current_task->info.ext_flags & SW_TASK_NOREPLY) { swoole_warning("Server::finish() can only be used in the worker process"); return SW_ERR; } @@ -296,24 +296,21 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even int ret; // for swoole_server_task - if (current_task->info.flags & SW_TASK_NONBLOCK) { - buf.info.type = SW_SERVER_EVENT_FINISH; - buf.info.fd = current_task->info.fd; - buf.info.time = microtime(); - buf.info.reactor_id = SwooleWG.worker->id; - // callback function - if (current_task->info.flags & SW_TASK_CALLBACK) { - flags |= SW_TASK_CALLBACK; - } else if (current_task->info.flags & SW_TASK_COROUTINE) { - flags |= SW_TASK_COROUTINE; - } - buf.info.flags = flags; - + if (current_task->info.ext_flags & SW_TASK_NONBLOCK) { // write to file - if (!event_data_pack(&buf, data, data_len)) { + if (!task_pack(&buf, data, data_len)) { swoole_warning("large task pack failed()"); return SW_ERR; } + // callback function + if (current_task->info.ext_flags & SW_TASK_CALLBACK) { + flags |= SW_TASK_CALLBACK; + } else if (current_task->info.ext_flags & SW_TASK_COROUTINE) { + flags |= SW_TASK_COROUTINE; + } + buf.info.ext_flags |= flags; + buf.info.type = SW_SERVER_EVENT_FINISH; + buf.info.fd = current_task->info.fd; if (worker->pool->use_socket && worker->pool->stream_info_->last_connection) { uint32_t _len = htonl(data_len); @@ -336,18 +333,18 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even // lock worker worker->lock->lock(); - if (current_task->info.flags & SW_TASK_WAITALL) { + if (current_task->info.ext_flags & SW_TASK_WAITALL) { sw_atomic_t *finish_count = (sw_atomic_t *) result->data; char *_tmpfile = result->data + 4; File file(_tmpfile, O_APPEND | O_WRONLY); if (file.ready()) { - buf.info.type = SW_SERVER_EVENT_FINISH; - buf.info.fd = current_task->info.fd; - buf.info.flags = flags; - if (!event_data_pack(&buf, data, data_len)) { + if (!task_pack(&buf, data, data_len)) { swoole_warning("large task pack failed()"); buf.info.len = 0; } + buf.info.ext_flags |= flags; + buf.info.type = SW_SERVER_EVENT_FINISH; + buf.info.fd = current_task->info.fd; size_t bytes = sizeof(buf.info) + buf.info.len; if (file.write_all(&buf, bytes) != bytes) { swoole_sys_warning("write(%s, %ld) failed", _tmpfile, bytes); @@ -355,15 +352,15 @@ int Server::reply_task_result(const char *data, size_t data_len, int flags, Even sw_atomic_fetch_add(finish_count, 1); } } else { - result->info.type = SW_SERVER_EVENT_FINISH; - result->info.fd = current_task->info.fd; - result->info.flags = flags; - if (!event_data_pack(result, data, data_len)) { + if (!task_pack(result, data, data_len)) { // unlock worker worker->lock->unlock(); swoole_warning("large task pack failed()"); return SW_ERR; } + result->info.ext_flags |= flags; + result->info.type = SW_SERVER_EVENT_FINISH; + result->info.fd = current_task->info.fd; } // unlock worker diff --git a/tests/swoole_server/task/task_co.phpt b/tests/swoole_server/task/task_co.phpt index 7d05fcc575e..1c026f07863 100644 --- a/tests/swoole_server/task/task_co.phpt +++ b/tests/swoole_server/task/task_co.phpt @@ -9,8 +9,7 @@ Swoole\Runtime::enableCoroutine(); $pm = new SwooleTest\ProcessManager; $randoms = []; -for ($n = MAX_REQUESTS; $n--;) -{ +for ($n = MAX_REQUESTS; $n--;) { $randoms[] = random_bytes(mt_rand(0, 65536)); } @@ -27,6 +26,7 @@ $pm->parentFunc = function () use ($pm) { echo "DONE\n"; $pm->kill(); }; + $pm->childFunc = function () use ($pm, $randoms) { $server = new swoole_http_server('127.0.0.1', $pm->getFreePort(), SWOOLE_PROCESS); $server->set([ @@ -38,37 +38,35 @@ $pm->childFunc = function () use ($pm, $randoms) { $server->on('workerStart', function ($serv, $wid) use ($pm) { $pm->wakeup(); }); - $server->on('request', function (swoole_http_request $request, swoole_http_response $response) use ($server, $randoms) { - $n = $request->get['n']; - switch ($request->server['path_info']) - { - case '/task': - { - list($ret_n, $ret_random) = $server->taskCo([$n], 1)[0]; - if ($ret_n !== $n) + $server->on('request', + function (swoole_http_request $request, swoole_http_response $response) use ($server, $randoms) { + $n = $request->get['n']; + switch ($request->server['path_info']) { + case '/task': { - $response->end("ERROR MATCH {$ret_n} with {$n}"); - return; + list($ret_n, $ret_random) = $server->taskCo([$n], 1)[0]; + if ($ret_n !== $n) { + $response->end("ERROR MATCH {$ret_n} with {$n}"); + return; + } elseif ($ret_random !== $randoms[$n]) { + $response->end("ERROR EQUAL {$ret_n}(" . strlen($ret_random) . ") with {$n}(" . strlen($randoms[$n]) . ")"); + return; + } + $response->end('OK'); + break; } - elseif ($ret_random !== $randoms[$n]) + case '/random': { - $response->end("ERROR EQUAL {$ret_n}(" . strlen($ret_random) . ") with {$n}(" . strlen($randoms[$n]) . ")"); - return; + $response->end($randoms[$n]); + break; } - $response->end('OK'); - break; - } - case '/random': - { - $response->end($randoms[$n]); - break; } - } - }); + }); $server->on('task', function (swoole_http_server $server, swoole_server_task $task) use ($pm) { - $task->finish([$task->data , httpGetBody('http://127.0.0.1:' . $pm->getFreePort() . "/random?n={$task->data}")]); + $task->finish([$task->data, httpGetBody('http://127.0.0.1:' . $pm->getFreePort() . "/random?n={$task->data}")]); + }); + $server->on('finish', function () { }); - $server->on('finish', function () { }); $server->start(); }; $pm->childFirst(); From 4de49f06d2630aa94acf4c5267e4cb235451a2dc Mon Sep 17 00:00:00 2001 From: matyhtf Date: Mon, 6 Sep 2021 19:21:19 +0800 Subject: [PATCH 232/936] Optimize code --- ext-src/php_swoole_http.h | 2 +- ext-src/php_swoole_http_server.h | 2 +- ext-src/swoole_http2_server.cc | 56 ++++++++++++++++++++------------ ext-src/swoole_http_server.cc | 15 +++++---- ext-src/swoole_server.cc | 2 +- include/swoole.h | 9 +++++ 6 files changed, 55 insertions(+), 31 deletions(-) diff --git a/ext-src/php_swoole_http.h b/ext-src/php_swoole_http.h index 7bc7ebf096a..d20cec5c095 100644 --- a/ext-src/php_swoole_http.h +++ b/ext-src/php_swoole_http.h @@ -364,7 +364,7 @@ class HeaderSet { nv->valuelen = value_len; nv->flags = flags | NGHTTP2_NV_FLAG_NO_COPY_NAME | NGHTTP2_NV_FLAG_NO_COPY_VALUE; swoole_trace_log(SW_TRACE_HTTP2, - "name=(%zu)[%.*s], value=(%zu)[%.*s]", + "name=(%zu)[" SW_ECHO_LEN_BLUE "], value=(%zu)[" SW_ECHO_LEN_CYAN "]", name_len, (int) name_len, name, diff --git a/ext-src/php_swoole_http_server.h b/ext-src/php_swoole_http_server.h index 0e9b8620711..321fd5752a7 100644 --- a/ext-src/php_swoole_http_server.h +++ b/ext-src/php_swoole_http_server.h @@ -37,7 +37,7 @@ bool swoole_websocket_handshake(swoole::http::Context *ctx); #ifdef SW_USE_HTTP2 -int swoole_http2_server_onFrame(swoole::Server *serv, swoole::Connection *conn, swoole::RecvData *req); +int swoole_http2_server_onReceive(swoole::Server *serv, swoole::Connection *conn, swoole::RecvData *req); int swoole_http2_server_parse(swoole::http2::Session *client, const char *buf); void swoole_http2_server_session_free(swoole::Connection *conn); int swoole_http2_server_ping(swoole::http::Context *ctx); diff --git a/ext-src/swoole_http2_server.cc b/ext-src/swoole_http2_server.cc index e76f3ce350d..f7fa6cf123f 100644 --- a/ext-src/swoole_http2_server.cc +++ b/ext-src/swoole_http2_server.cc @@ -57,7 +57,8 @@ Http2Stream::~Stream() { void Http2Stream::reset(uint32_t error_code) { char frame[SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_RST_STREAM_SIZE]; - swoole_trace_log(SW_TRACE_HTTP2, "send [" SW_ECHO_YELLOW "] stream_id=%u, error_code=%u", "RST_STREAM", id, error_code); + swoole_trace_log( + SW_TRACE_HTTP2, "send [" SW_ECHO_YELLOW "] stream_id=%u, error_code=%u", "RST_STREAM", id, error_code); *(uint32_t *) ((char *) frame + SW_HTTP2_FRAME_HEADER_SIZE) = htonl(error_code); http2::set_frame_header(frame, SW_HTTP2_TYPE_RST_STREAM, SW_HTTP2_RST_STREAM_SIZE, 0, id); ctx->send(ctx, frame, SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_RST_STREAM_SIZE); @@ -94,7 +95,8 @@ Http2Session::~Session() { static void http2_server_send_window_update(HttpContext *ctx, uint32_t stream_id, uint32_t size) { char frame[SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_WINDOW_UPDATE_SIZE]; - swoole_trace_log(SW_TRACE_HTTP2, "send [" SW_ECHO_YELLOW "] stream_id=%u, size=%u", "WINDOW_UPDATE", stream_id, size); + swoole_trace_log( + SW_TRACE_HTTP2, "send [" SW_ECHO_YELLOW "] stream_id=%u, size=%u", "WINDOW_UPDATE", stream_id, size); *(uint32_t *) ((char *) frame + SW_HTTP2_FRAME_HEADER_SIZE) = htonl(size); Http2::set_frame_header(frame, SW_HTTP2_TYPE_WINDOW_UPDATE, SW_HTTP2_WINDOW_UPDATE_SIZE, 0, stream_id); ctx->send(ctx, frame, SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_WINDOW_UPDATE_SIZE); @@ -445,23 +447,26 @@ bool Http2Stream::send_body(String *body, bool end_stream, size_t max_frame_size char *p = body->str + offset; size_t l = length == 0 ? body->length : length; - int flag = end_stream ? SW_HTTP2_FLAG_END_STREAM : SW_HTTP2_FLAG_NONE; + int flags = end_stream ? SW_HTTP2_FLAG_END_STREAM : SW_HTTP2_FLAG_NONE; while (l > 0) { size_t send_n; - int _send_flag; + int _send_flags; swoole_http_buffer->clear(); if (l > max_frame_size) { send_n = max_frame_size; - _send_flag = 0; + _send_flags = 0; } else { send_n = l; - _send_flag = flag; + _send_flags = flags; } - http2::set_frame_header(frame_header, SW_HTTP2_TYPE_DATA, send_n, _send_flag, id); + http2::set_frame_header(frame_header, SW_HTTP2_TYPE_DATA, send_n, _send_flags, id); swoole_http_buffer->append(frame_header, SW_HTTP2_FRAME_HEADER_SIZE); swoole_http_buffer->append(p, send_n); + swoole_trace_log( + SW_TRACE_HTTP2, "send [" SW_ECHO_YELLOW "] stream_id=%u, flags=%d, send_n=%lu", "DATA", id, flags, send_n); + if (!ctx->send(ctx, swoole_http_buffer->str, swoole_http_buffer->length)) { return false; } else { @@ -545,15 +550,20 @@ static bool swoole_http2_server_respond(HttpContext *ctx, String *body) { stream->waiting_coroutine->yield(); stream->waiting_coroutine = nullptr; continue; - } else if (send_len <= stream->send_window) { - error = !stream->send_body(body, true && end_stream, client->max_frame_size, body->offset, send_len); - break; + } + + bool _end_stream; + if (send_len > stream->send_window) { + send_len = stream->send_window; + _end_stream = false; } else { - send_len = client->max_frame_size; - error = !stream->send_body(body, false, client->max_frame_size, body->offset, send_len); + _end_stream = true && end_stream; } + + error = !stream->send_body(body, _end_stream, client->max_frame_size, body->offset, send_len); if (!error) { - swoole_trace_log(SW_TRACE_HTTP2, "body: send length=%zu", send_len); + swoole_trace_log( + SW_TRACE_HTTP2, "body: send length=%zu, stream->send_window=%u", send_len, stream->send_window); body->offset += send_len; if (send_len > stream->send_window) { @@ -695,8 +705,12 @@ static int http2_parse_header(Http2Session *client, HttpContext *ctx, int flags, inlen -= proclen; if (inflate_flags & NGHTTP2_HD_INFLATE_EMIT) { - swoole_trace_log( - SW_TRACE_HTTP2, "Header: " SW_ECHO_BLUE "[%zu]: %s[%zu]", nv.name, nv.namelen, nv.value, nv.valuelen); + swoole_trace_log(SW_TRACE_HTTP2, + "name=(%zu)[" SW_ECHO_BLUE "], value=(%zu)[" SW_ECHO_CYAN "]", + nv.namelen, + nv.name, + nv.valuelen, + nv.value); if (nv.name[0] == ':') { if (SW_STRCASEEQ((char *) nv.name + 1, nv.namelen - 1, "method")) { @@ -817,8 +831,8 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { int ret = nghttp2_hd_deflate_change_table_size(client->deflater, value); if (ret != 0) { swoole_warning("nghttp2_hd_deflate_change_table_size() failed, errno=%d, errmsg=%s", - ret, - nghttp2_strerror(ret)); + ret, + nghttp2_strerror(ret)); return SW_ERR; } } @@ -903,6 +917,7 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { // flow control client->recv_window -= length; stream->recv_window -= length; + if (length > 0) { if (client->recv_window < (SW_HTTP2_MAX_WINDOW_SIZE / 4)) { http2_server_send_window_update(ctx, 0, SW_HTTP2_MAX_WINDOW_SIZE - client->recv_window); @@ -952,9 +967,8 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { } case SW_HTTP2_TYPE_WINDOW_UPDATE: { value = ntohl(*(uint32_t *) buf); - if (stream_id == 0) { - client->send_window += value; - } else if (client->streams.find(stream_id) != client->streams.end()) { + client->send_window += value; + if (stream_id > 0 && !client->is_coro && client->streams.find(stream_id) != client->streams.end()) { stream = client->streams[stream_id]; Server *serv = (Server *) stream->ctx->private_data; @@ -1005,7 +1019,7 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { /** * Http2 */ -int swoole_http2_server_onFrame(Server *serv, Connection *conn, RecvData *req) { +int swoole_http2_server_onReceive(Server *serv, Connection *conn, RecvData *req) { int session_id = req->info.fd; Http2Session *client = http2_sessions[session_id]; if (client == nullptr) { diff --git a/ext-src/swoole_http_server.cc b/ext-src/swoole_http_server.cc index 667454d37af..a7e1bc55e56 100644 --- a/ext-src/swoole_http_server.cc +++ b/ext-src/swoole_http_server.cc @@ -61,7 +61,7 @@ int php_swoole_http_server_onReceive(Server *serv, RecvData *req) { } #ifdef SW_USE_HTTP2 if (conn->http2_stream) { - return swoole_http2_server_onFrame(serv, conn, req); + return swoole_http2_server_onReceive(serv, conn, req); } #endif @@ -72,11 +72,11 @@ int php_swoole_http_server_onReceive(Server *serv, RecvData *req) { php_swoole_get_recv_data(serv, zdata, req); swoole_trace_log(SW_TRACE_SERVER, - "http request from %ld with %d bytes: <request.zobject; @@ -92,7 +92,8 @@ int php_swoole_http_server_onReceive(Server *serv, RecvData *req) { ctx->send(ctx, SW_STRL(SW_HTTP_BAD_REQUEST_PACKET)); #endif ctx->close(ctx); - swoole_notice("request is illegal and it has been discarded, %ld bytes unprocessed", Z_STRLEN_P(zdata) - parsed_n); + swoole_notice("request is illegal and it has been discarded, %ld bytes unprocessed", + Z_STRLEN_P(zdata) - parsed_n); goto _dtor_and_return; } diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 339a95265c3..3f743f2632d 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -451,7 +451,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_server_addCommand, 0, 0, 3) ZEND_ARG_INFO(0, name) ZEND_ARG_INFO(0, accepted_process_types) - ZEND_ARG_CALLABLE_INFO(0, callback, 1) + ZEND_ARG_CALLABLE_INFO(0, callback, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_server_getClientInfo, 0, 0, 1) diff --git a/include/swoole.h b/include/swoole.h index 1c9e76a2000..9fc49307ca9 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -107,6 +107,15 @@ typedef unsigned long ulong_t; #define SW_ECHO_MAGENTA "\e[35m%s\e[0m" #define SW_ECHO_CYAN "\e[36m%s\e[0m" #define SW_ECHO_WHITE "\e[37m%s\e[0m" + +#define SW_ECHO_LEN_RED "\e[31m%.*s\e[0m" +#define SW_ECHO_LEN_GREEN "\e[32m%.*s\e[0m" +#define SW_ECHO_LEN_YELLOW "\e[33m%.*s\e[0m" +#define SW_ECHO_LEN_BLUE "\e[34m%.*s\e[0m" +#define SW_ECHO_LEN_MAGENTA "\e[35m%.*s\e[0m" +#define SW_ECHO_LEN_CYAN "\e[36m%.*s\e[0m" +#define SW_ECHO_LEN_WHITE "\e[37m%.*s\e[0m" + #define SW_COLOR_RED 1 #define SW_COLOR_GREEN 2 #define SW_COLOR_YELLOW 3 From 3b9c9a5e884b5b96ec78d967f3bfac402a66a637 Mon Sep 17 00:00:00 2001 From: hantianfeng Date: Tue, 7 Sep 2021 00:16:36 +0800 Subject: [PATCH 233/936] Update version --- CMakeLists.txt | 2 +- include/swoole_version.h | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fe297de7b54..512c9bdb55f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ PROJECT(libswoole) ENABLE_LANGUAGE(ASM) -set(SWOOLE_VERSION 4.7.1) +set(SWOOLE_VERSION 4.7.2-dev) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g") diff --git a/include/swoole_version.h b/include/swoole_version.h index a85f8623209..30ffe704e68 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -20,11 +20,11 @@ #define SWOOLE_MAJOR_VERSION 4 #define SWOOLE_MINOR_VERSION 7 -#define SWOOLE_RELEASE_VERSION 1 -#define SWOOLE_EXTRA_VERSION "" -#define SWOOLE_VERSION "4.7.1" -#define SWOOLE_VERSION_ID 40701 -#define SWOOLE_API_VERSION_ID 0x202108a +#define SWOOLE_RELEASE_VERSION 2 +#define SWOOLE_EXTRA_VERSION "dev" +#define SWOOLE_VERSION "4.7.2-dev" +#define SWOOLE_VERSION_ID 40702 +#define SWOOLE_API_VERSION_ID 0x202109a #define SWOOLE_BUG_REPORT \ "A bug occurred in Swoole-v" SWOOLE_VERSION ", please report it.\n" \ From 03e6f6ddb08df473837f5f9f2c7fdca6656a08b4 Mon Sep 17 00:00:00 2001 From: hantianfeng Date: Tue, 7 Sep 2021 09:28:30 +0800 Subject: [PATCH 234/936] Optimize code --- src/network/client.cc | 9 +++++++-- src/protocol/base.cc | 1 + src/server/master.cc | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/network/client.cc b/src/network/client.cc index ddaad696956..55bbe3a7c15 100644 --- a/src/network/client.cc +++ b/src/network/client.cc @@ -749,7 +749,12 @@ static ssize_t Client_tcp_recv_no_buffer(Client *cli, char *data, size_t len, in while (1) { #ifdef HAVE_KQUEUE int timeout_ms = (int) (cli->timeout * 1000); - if (cli->socket->wait_event(timeout_ms, SW_EVENT_READ) < 0) { +#ifdef SW_USE_OPENSSL + if (cli->socket->ssl) { + timeout_ms = 0; + } +#endif + if (timeout_ms > 0 && cli->socket->wait_event(timeout_ms, SW_EVENT_READ) < 0) { return -1; } #endif @@ -768,7 +773,7 @@ static ssize_t Client_tcp_recv_no_buffer(Client *cli, char *data, size_t len, in } } #ifdef SW_USE_OPENSSL - if (errno == EAGAIN && cli->socket->ssl) { + if (cli->socket->catch_error(errno) == SW_WAIT && cli->socket->ssl) { int timeout_ms = (int) (cli->timeout * 1000); if (cli->socket->ssl_want_read && cli->socket->wait_event(timeout_ms, SW_EVENT_READ) == SW_OK) { continue; diff --git a/src/protocol/base.cc b/src/protocol/base.cc index 1ad076b669c..58356e28b27 100644 --- a/src/protocol/base.cc +++ b/src/protocol/base.cc @@ -20,6 +20,7 @@ #include "swoole_string.h" #include "swoole_socket.h" #include "swoole_protocol.h" + namespace swoole { /** * return the package total length diff --git a/src/server/master.cc b/src/server/master.cc index e905c55397b..67db43fba42 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -97,7 +97,7 @@ void Server::call_command_callback(int64_t request_id, const std::string &result auto iter = command_callbacks.find(request_id); if (iter == command_callbacks.end()) { swoole_error_log( - SW_LOG_ERROR, SW_ERROR_SERVER_INVALID_COMMAND, "Invalid command result[request_id=%lu]", request_id); + SW_LOG_ERROR, SW_ERROR_SERVER_INVALID_COMMAND, "Invalid command result[request_id=%ld]", request_id); return; } iter->second(this, result); From d213f33aff4d4dcc614bd3f47a64c34aba4af964 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 7 Sep 2021 11:24:58 +0800 Subject: [PATCH 235/936] Fix http2 code style --- ext-src/swoole_http2_client_coro.cc | 86 ++++++++++++++--------------- ext-src/swoole_http2_server.cc | 28 +++++----- include/swoole_http2.h | 66 +++++++++++++--------- 3 files changed, 96 insertions(+), 84 deletions(-) diff --git a/ext-src/swoole_http2_client_coro.cc b/ext-src/swoole_http2_client_coro.cc index 980e75dba62..b38e4139242 100644 --- a/ext-src/swoole_http2_client_coro.cc +++ b/ext-src/swoole_http2_client_coro.cc @@ -514,14 +514,14 @@ enum swReturnCode Client::parse_frame(zval *return_value, bool pipeline_read) { switch (type) { case SW_HTTP2_TYPE_SETTINGS: { if (flags & SW_HTTP2_FLAG_ACK) { - swHttp2FrameTraceLog(recv, "ACK"); + swoole_http2_frame_trace_log(recv, "ACK"); return SW_CONTINUE; } while (length > 0) { id = ntohs(*(uint16_t *) (buf)); value = ntohl(*(uint32_t *) (buf + sizeof(uint16_t))); - swHttp2FrameTraceLog(recv, "id=%d, value=%d", id, value); + swoole_http2_frame_trace_log(recv, "id=%d, value=%d", id, value); switch (id) { case SW_HTTP2_SETTING_HEADER_TABLE_SIZE: if (value != remote_settings.header_table_size) { @@ -577,7 +577,7 @@ enum swReturnCode Client::parse_frame(zval *return_value, bool pipeline_read) { } case SW_HTTP2_TYPE_WINDOW_UPDATE: { value = ntohl(*(uint32_t *) buf); - swHttp2FrameTraceLog(recv, "window_size_increment=%d", value); + swoole_http2_frame_trace_log(recv, "window_size_increment=%d", value); if (stream_id == 0) { remote_settings.window_size += value; } else { @@ -589,7 +589,7 @@ enum swReturnCode Client::parse_frame(zval *return_value, bool pipeline_read) { return SW_CONTINUE; } case SW_HTTP2_TYPE_PING: { - swHttp2FrameTraceLog(recv, "ping"); + swoole_http2_frame_trace_log(recv, "ping"); if (!(flags & SW_HTTP2_FLAG_ACK)) { Http2::set_frame_header( frame, SW_HTTP2_TYPE_PING, SW_HTTP2_FRAME_PING_PAYLOAD_SIZE, SW_HTTP2_FLAG_ACK, stream_id); @@ -606,12 +606,12 @@ enum swReturnCode Client::parse_frame(zval *return_value, bool pipeline_read) { buf += 4; value = ntohl(*(uint32_t *) (buf)); buf += 4; - swHttp2FrameTraceLog(recv, - "last_stream_id=%d, error_code=%d, opaque_data=[%.*s]", - server_last_stream_id, - value, - (int) (length - SW_HTTP2_GOAWAY_SIZE), - buf); + swoole_http2_frame_trace_log(recv, + "last_stream_id=%d, error_code=%d, opaque_data=[%.*s]", + server_last_stream_id, + value, + (int) (length - SW_HTTP2_GOAWAY_SIZE), + buf); // update goaway error code and error msg zend_update_property_long(swoole_http2_client_coro_ce, SW_Z8_OBJ_P(zobject), ZEND_STRL("errCode"), value); @@ -624,7 +624,7 @@ enum swReturnCode Client::parse_frame(zval *return_value, bool pipeline_read) { } case SW_HTTP2_TYPE_RST_STREAM: { value = ntohl(*(uint32_t *) (buf)); - swHttp2FrameTraceLog(recv, "error_code=%d", value); + swoole_http2_frame_trace_log(recv, "error_code=%d", value); // delete and free quietly delete_stream(stream_id); @@ -637,7 +637,7 @@ enum swReturnCode Client::parse_frame(zval *return_value, bool pipeline_read) { case SW_HTTP2_TYPE_PUSH_PROMISE: { #ifdef SW_DEBUG uint32_t promise_stream_id = ntohl(*(uint32_t *) (buf)) & 0x7fffffff; - swHttp2FrameTraceLog(recv, "promise_stream_id=%d", promise_stream_id); + swoole_http2_frame_trace_log(recv, "promise_stream_id=%d", promise_stream_id); #endif // auto promise_stream = create_stream(promise_stream_id, false); // RETVAL_ZVAL(promise_stream->response_object, 0, 0); @@ -645,7 +645,7 @@ enum swReturnCode Client::parse_frame(zval *return_value, bool pipeline_read) { return SW_CONTINUE; } default: { - swHttp2FrameTraceLog(recv, ""); + swoole_http2_frame_trace_log(recv, ""); } } @@ -925,14 +925,14 @@ int Client::parse_header(Stream *stream, int flags, char *in, size_t inlen) { inlen -= (size_t) rv; swoole_trace_log(SW_TRACE_HTTP2, - "[" SW_ECHO_GREEN "] %.*s[%lu]: %.*s[%lu]", - "HEADER", - (int) nv.namelen, - nv.name, - nv.namelen, - (int) nv.valuelen, - nv.value, - nv.valuelen); + "[" SW_ECHO_GREEN "] %.*s[%lu]: %.*s[%lu]", + "HEADER", + (int) nv.namelen, + nv.name, + nv.namelen, + (int) nv.valuelen, + nv.value, + nv.valuelen); if (inflate_flags & NGHTTP2_HD_INFLATE_EMIT) { if (nv.name[0] == ':') { @@ -1189,10 +1189,10 @@ uint32_t Client::send_request(zval *zrequest) { Http2::set_frame_header(buffer, SW_HTTP2_TYPE_HEADERS, bytes, flags, stream->stream_id); swoole_trace_log(SW_TRACE_HTTP2, - "[" SW_ECHO_GREEN ", STREAM#%d] length=%zd", - Http2::get_type(SW_HTTP2_TYPE_HEADERS), - stream->stream_id, - bytes); + "[" SW_ECHO_GREEN ", STREAM#%d] length=%zd", + Http2::get_type(SW_HTTP2_TYPE_HEADERS), + stream->stream_id, + bytes); if (!send(buffer, SW_HTTP2_FRAME_HEADER_SIZE + bytes)) { return 0; } @@ -1220,10 +1220,10 @@ uint32_t Client::send_request(zval *zrequest) { } swoole_trace_log(SW_TRACE_HTTP2, - "[" SW_ECHO_GREEN ", END, STREAM#%d] length=%zu", - Http2::get_type(SW_HTTP2_TYPE_DATA), - stream->stream_id, - len); + "[" SW_ECHO_GREEN ", END, STREAM#%d] length=%zu", + Http2::get_type(SW_HTTP2_TYPE_DATA), + stream->stream_id, + len); if (!send_data(stream->stream_id, p, len, flag)) { return 0; @@ -1261,11 +1261,11 @@ bool Client::write_data(uint32_t stream_id, zval *zdata, bool end) { } Http2::set_frame_header(buffer, SW_HTTP2_TYPE_DATA, len, flag, stream_id); swoole_trace_log(SW_TRACE_HTTP2, - "[" SW_ECHO_GREEN ",%s STREAM#%d] length=%zu", - Http2::get_type(SW_HTTP2_TYPE_DATA), - end ? " END," : "", - stream_id, - len); + "[" SW_ECHO_GREEN ",%s STREAM#%d] length=%zu", + Http2::get_type(SW_HTTP2_TYPE_DATA), + end ? " END," : "", + stream_id, + len); if (!send(buffer, SW_HTTP2_FRAME_HEADER_SIZE) || !send(formstr, len)) { smart_str_free(&formstr_s); return false; @@ -1275,11 +1275,11 @@ bool Client::write_data(uint32_t stream_id, zval *zdata, bool end) { zend::String data(zdata); Http2::set_frame_header(buffer, SW_HTTP2_TYPE_DATA, data.len(), flag, stream_id); swoole_trace_log(SW_TRACE_HTTP2, - "[" SW_ECHO_GREEN ",%s STREAM#%d] length=%zu", - Http2::get_type(SW_HTTP2_TYPE_DATA), - end ? " END," : "", - stream_id, - data.len()); + "[" SW_ECHO_GREEN ",%s STREAM#%d] length=%zu", + Http2::get_type(SW_HTTP2_TYPE_DATA), + end ? " END," : "", + stream_id, + data.len()); if (!send(buffer, SW_HTTP2_FRAME_HEADER_SIZE) || !send(data.val(), data.len())) { return false; } @@ -1303,10 +1303,10 @@ bool Client::send_goaway_frame(zend_long error_code, const char *debug_data, siz memcpy(frame + SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_GOAWAY_SIZE, debug_data, debug_data_len); } swoole_trace_log(SW_TRACE_HTTP2, - "[" SW_ECHO_GREEN "] Send: last-sid=%u, error-code=%ld", - Http2::get_type(SW_HTTP2_TYPE_GOAWAY), - last_stream_id, - error_code); + "[" SW_ECHO_GREEN "] Send: last-sid=%u, error-code=%ld", + Http2::get_type(SW_HTTP2_TYPE_GOAWAY), + last_stream_id, + error_code); ret = send(frame, length); efree(frame); return ret; diff --git a/ext-src/swoole_http2_server.cc b/ext-src/swoole_http2_server.cc index f7fa6cf123f..002cce9b67f 100644 --- a/ext-src/swoole_http2_server.cc +++ b/ext-src/swoole_http2_server.cc @@ -815,14 +815,14 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { switch (type) { case SW_HTTP2_TYPE_SETTINGS: { if (flags & SW_HTTP2_FLAG_ACK) { - swHttp2FrameTraceLog(recv, "ACK"); + swoole_http2_frame_trace_log(recv, "ACK"); break; } while (length > 0) { id = ntohs(*(uint16_t *) (buf)); value = ntohl(*(uint32_t *) (buf + sizeof(uint16_t))); - swHttp2FrameTraceLog(recv, "id=%d, value=%d", id, value); + swoole_http2_frame_trace_log(recv, "id=%d, value=%d", id, value); switch (id) { case SW_HTTP2_SETTING_HEADER_TABLE_SIZE: if (value != client->header_table_size) { @@ -867,7 +867,7 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { } case SW_HTTP2_TYPE_HEADERS: { stream = client->streams[stream_id]; - swHttp2FrameTraceLog(recv, "%s", (stream ? "exist stream" : "new stream")); + swoole_http2_frame_trace_log(recv, "%s", (stream ? "exist stream" : "new stream")); HttpContext *ctx; if (!stream) { stream = new Http2Stream(client, stream_id); @@ -895,7 +895,7 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { break; } case SW_HTTP2_TYPE_DATA: { - swHttp2FrameTraceLog(recv, "data"); + swoole_http2_frame_trace_log(recv, "data"); auto stream_iterator = client->streams.find(stream_id); if (stream_iterator == client->streams.end()) { swoole_error_log(SW_LOG_WARNING, SW_ERROR_HTTP2_STREAM_NOT_FOUND, "http2 stream#%d not found", stream_id); @@ -954,7 +954,7 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { break; } case SW_HTTP2_TYPE_PING: { - swHttp2FrameTraceLog(recv, "ping"); + swoole_http2_frame_trace_log(recv, "ping"); if (!(flags & SW_HTTP2_FLAG_ACK)) { char ping_frame[SW_HTTP2_FRAME_HEADER_SIZE + SW_HTTP2_FRAME_PING_PAYLOAD_SIZE]; Http2::set_frame_header( @@ -977,12 +977,12 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { stream->waiting_coroutine->resume(); } } - swHttp2FrameTraceLog(recv, "window_size_increment=%d", value); + swoole_http2_frame_trace_log(recv, "window_size_increment=%d", value); break; } case SW_HTTP2_TYPE_RST_STREAM: { value = ntohl(*(int *) (buf)); - swHttp2FrameTraceLog(recv, "error_code=%d", value); + swoole_http2_frame_trace_log(recv, "error_code=%d", value); if (client->streams.find(stream_id) != client->streams.end()) { // TODO: i onRequest and use request->recv // stream exist @@ -997,19 +997,19 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { buf += 4; value = ntohl(*(uint32_t *) (buf)); buf += 4; - swHttp2FrameTraceLog(recv, - "last_stream_id=%d, error_code=%d, opaque_data=[%.*s]", - server_last_stream_id, - value, - (int) (length - SW_HTTP2_GOAWAY_SIZE), - buf); + swoole_http2_frame_trace_log(recv, + "last_stream_id=%d, error_code=%d, opaque_data=[%.*s]", + server_last_stream_id, + value, + (int) (length - SW_HTTP2_GOAWAY_SIZE), + buf); // TODO: onRequest (void) server_last_stream_id; break; } default: { - swHttp2FrameTraceLog(recv, ""); + swoole_http2_frame_trace_log(recv, ""); } } diff --git a/include/swoole_http2.h b/include/swoole_http2.h index d3dc7363fd9..cd9a5f3cdcc 100644 --- a/include/swoole_http2.h +++ b/include/swoole_http2.h @@ -19,7 +19,7 @@ #define SW_HTTP2_PRI_STRING "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" -enum swHttp2_error_code { +enum swHttp2ErrorCode { SW_HTTP2_ERROR_NO_ERROR = 0, SW_HTTP2_ERROR_PROTOCOL_ERROR = 1, SW_HTTP2_ERROR_INTERNAL_ERROR = 2, @@ -35,7 +35,7 @@ enum swHttp2_error_code { SW_HTTP2_ERROR_INADEQUATE_SECURITY = 12, }; -enum swHttp2_frame_type { +enum swHttp2FrameType { SW_HTTP2_TYPE_DATA = 0, SW_HTTP2_TYPE_HEADERS = 1, SW_HTTP2_TYPE_PRIORITY = 2, @@ -48,7 +48,7 @@ enum swHttp2_frame_type { SW_HTTP2_TYPE_CONTINUATION = 9, }; -enum swHttp2_frame_flag { +enum swHttp2FrameFlag { SW_HTTP2_FLAG_NONE = 0x00, SW_HTTP2_FLAG_ACK = 0x01, SW_HTTP2_FLAG_END_STREAM = 0x01, @@ -57,7 +57,7 @@ enum swHttp2_frame_flag { SW_HTTP2_FLAG_PRIORITY = 0x20, }; -enum swHttp2_setting_id { +enum swHttp2SettingId { SW_HTTP2_SETTING_HEADER_TABLE_SIZE = 0x1, SW_HTTP2_SETTINGS_ENABLE_PUSH = 0x2, SW_HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS = 0x3, @@ -66,7 +66,7 @@ enum swHttp2_setting_id { SW_HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 0x6, }; -enum swHttp2_stream_flag { +enum swHttp2StreamFlag { SW_HTTP2_STREAM_NORMAL = 0, SW_HTTP2_STREAM_REQUEST_END = 1 << 0, SW_HTTP2_STREAM_PIPELINE_REQUEST = 1 << 1, @@ -87,28 +87,16 @@ enum swHttp2_stream_flag { #define SW_HTTP2_STREAM_ID_SIZE 4 #define SW_HTTP2_SETTINGS_PARAM_SIZE 6 -#define swHttp2FrameTraceLogFlags \ - ((flags & SW_HTTP2_FLAG_ACK) ? "\nEND_ACK |" : ""), ((flags & SW_HTTP2_FLAG_END_STREAM) ? "\nEND_STREAM |" : ""), \ - ((flags & SW_HTTP2_FLAG_END_HEADERS) ? "\nEND_HEADERS |" : ""), \ - ((flags & SW_HTTP2_FLAG_PADDED) ? "\nEND_PADDED |" : ""), \ - ((flags & SW_HTTP2_FLAG_PRIORITY) ? "\nEND_PRIORITY |" : "") - -#define swHttp2FrameTraceLog(recv, str, ...) \ - swoole_trace_log(SW_TRACE_HTTP2, \ - "\nrecv [" \ - "\e[3" \ - "%d" \ - "m" \ - "%s" \ - "\e[0m" \ - "] frame " str "%s%s%s%s%s", \ - swoole::http2::get_type_color(type), \ - swoole::http2::get_type(type), \ - length, \ - flags, \ - stream_id, \ - ##__VA_ARGS__, \ - swHttp2FrameTraceLogFlags); +#define swoole_http2_frame_trace_log(_trace_fn, _trace_str, ...) \ + swoole_trace_log(SW_TRACE_HTTP2, \ + "%s [" SW_ECHO_GREEN "] frame" \ + " " _trace_str, \ + #_trace_fn, \ + swoole::http2::get_type(type), \ + length, \ + swoole::http2::get_flag_string(flags).c_str(), \ + stream_id, \ + ##__VA_ARGS__) namespace swoole { namespace http2 { @@ -158,6 +146,30 @@ static sw_inline void init_settings(Settings *settings) { settings->max_header_list_size = SW_HTTP2_DEFAULT_MAX_HEADER_LIST_SIZE; } +static inline const std::string get_flag_string(int __flags) { + std::string str; + if (__flags & SW_HTTP2_FLAG_ACK) { + str.append("ACK|"); + } + if (__flags & SW_HTTP2_FLAG_END_STREAM) { + str.append("END_STREAM|"); + } + if (__flags & SW_HTTP2_FLAG_END_HEADERS) { + str.append("END_HEADERS|"); + } + if (__flags & SW_HTTP2_FLAG_PADDED) { + str.append("PADDED|"); + } + if (__flags & SW_HTTP2_FLAG_PRIORITY) { + str.append("PRIORITY|"); + } + if (str.back() == '|') { + return str.substr(0, str.length() - 1); + } else { + return "none"; + } +} + /** +-----------------------------------------------+ | Length (24) | From 4a576f601b52efa79dc12be243b2bc7b43d6745c Mon Sep 17 00:00:00 2001 From: twosee Date: Tue, 7 Sep 2021 16:37:47 +0800 Subject: [PATCH 236/936] Fix HTTP2 max_frame_size error (#4394) --- ext-src/php_swoole_http.h | 15 ++--- ext-src/swoole_http2_client_coro.cc | 16 +++-- ext-src/swoole_http2_server.cc | 90 +++++++++++++++-------------- 3 files changed, 61 insertions(+), 60 deletions(-) diff --git a/ext-src/php_swoole_http.h b/ext-src/php_swoole_http.h index d20cec5c095..f9a13a97f36 100644 --- a/ext-src/php_swoole_http.h +++ b/ext-src/php_swoole_http.h @@ -19,6 +19,9 @@ #pragma once #include "swoole_http.h" +#ifdef SW_USE_HTTP2 +#include "swoole_http2.h" +#endif #include "thirdparty/swoole_http_parser.h" #include "thirdparty/multipart_parser.h" @@ -208,8 +211,8 @@ class Stream { // uint8_t priority; // useless now uint32_t id; // flow control - uint32_t send_window; - uint32_t recv_window; + uint32_t remote_window_size; + uint32_t local_window_size; Coroutine *waiting_coroutine = nullptr; Stream(Session *client, uint32_t _id); @@ -230,11 +233,9 @@ class Session { nghttp2_hd_inflater *inflater = nullptr; nghttp2_hd_deflater *deflater = nullptr; - uint32_t header_table_size; - uint32_t send_window; - uint32_t recv_window; - uint32_t max_concurrent_streams; - uint32_t max_frame_size; + http2::Settings local_settings = {}; + http2::Settings remote_settings = {}; + uint32_t last_stream_id; bool shutting_down; bool is_coro; diff --git a/ext-src/swoole_http2_client_coro.cc b/ext-src/swoole_http2_client_coro.cc index b38e4139242..d7e93ee1afa 100644 --- a/ext-src/swoole_http2_client_coro.cc +++ b/ext-src/swoole_http2_client_coro.cc @@ -1068,13 +1068,11 @@ ssize_t Client::build_header(zval *zobject, zval *zrequest, char *buffer) { } size_t buflen = nghttp2_hd_deflate_bound(h2c->deflater, headers.get(), headers.len()); - /* - if (buflen > h2c->remote_settings.max_header_list_size) - { - php_swoole_error(E_WARNING, "header cannot bigger than remote max_header_list_size %u", - h2c->remote_settings.max_header_list_size); return -1; - } - */ + // if (buflen > h2c->remote_settings.max_header_list_size) { + // php_swoole_error(E_WARNING, "header cannot bigger than remote max_header_list_size %u", + // h2c->remote_settings.max_header_list_size); + // return -1; + // } ssize_t rv = nghttp2_hd_deflate_hd(h2c->deflater, (uchar *) buffer, buflen, headers.get(), headers.len()); if (rv < 0) { h2c->nghttp2_error(rv, "nghttp2_hd_deflate_hd() failed"); @@ -1125,8 +1123,8 @@ bool Client::send_data(uint32_t stream_id, const char *p, size_t len, int flag) uint32_t send_len; char header[SW_HTTP2_FRAME_HEADER_SIZE]; while (len > 0) { - if (len > remote_settings.max_frame_size) { - send_len = remote_settings.max_frame_size; + if (len > local_settings.max_frame_size) { + send_len = local_settings.max_frame_size; send_flag = 0; } else { send_len = len; diff --git a/ext-src/swoole_http2_server.cc b/ext-src/swoole_http2_server.cc index 002cce9b67f..e0400bbd85c 100644 --- a/ext-src/swoole_http2_server.cc +++ b/ext-src/swoole_http2_server.cc @@ -45,8 +45,8 @@ Http2Stream::Stream(Http2Session *client, uint32_t _id) { ctx->stream = this; ctx->keepalive = true; id = _id; - send_window = SW_HTTP2_DEFAULT_WINDOW_SIZE; - recv_window = SW_HTTP2_DEFAULT_WINDOW_SIZE; + local_window_size = SW_HTTP2_DEFAULT_WINDOW_SIZE; + remote_window_size = SW_HTTP2_DEFAULT_WINDOW_SIZE; } Http2Stream::~Stream() { @@ -66,11 +66,9 @@ void Http2Stream::reset(uint32_t error_code) { Http2Session::Session(SessionId _fd) { fd = _fd; - header_table_size = SW_HTTP2_DEFAULT_HEADER_TABLE_SIZE; - send_window = SW_HTTP2_DEFAULT_WINDOW_SIZE; - recv_window = SW_HTTP2_DEFAULT_WINDOW_SIZE; - max_concurrent_streams = SW_HTTP2_MAX_MAX_CONCURRENT_STREAMS; - max_frame_size = SW_HTTP2_MAX_MAX_FRAME_SIZE; + Http2::init_settings(&local_settings); + // [init]: we must set default value, peer is not always send all the settings + Http2::init_settings(&remote_settings); last_stream_id = 0; shutting_down = false; is_coro = false; @@ -350,7 +348,7 @@ static ssize_t http2_build_header(HttpContext *ctx, uchar *buffer, size_t body_l Http2Session *client = http2_sessions[ctx->fd]; nghttp2_hd_deflater *deflater = client->deflater; if (!deflater) { - ret = nghttp2_hd_deflate_new2(&deflater, client->header_table_size, php_nghttp2_mem()); + ret = nghttp2_hd_deflate_new2(&deflater, client->local_settings.header_table_size, php_nghttp2_mem()); if (ret != 0) { swoole_warning("nghttp2_hd_deflate_new2() failed with error: %s", nghttp2_strerror(ret)); return -1; @@ -531,10 +529,10 @@ static bool swoole_http2_server_respond(HttpContext *ctx, String *body) { // If send_yield is not supported, ignore flow control if (ctx->co_socket || !((Server *) ctx->private_data)->send_yield || !swoole_coroutine_is_in()) { - if (body->length > client->send_window) { - swoole_warning("The data sent exceeded send_window"); + if (body->length > client->remote_settings.window_size) { + swoole_warning("The data sent exceeded remote_window_size"); } - if (!stream->send_body(body, end_stream, client->max_frame_size)) { + if (!stream->send_body(body, end_stream, client->local_settings.max_frame_size)) { error = true; } } else { @@ -545,7 +543,7 @@ static bool swoole_http2_server_respond(HttpContext *ctx, String *body) { break; } - if (stream->send_window == 0) { + if (stream->remote_window_size == 0) { stream->waiting_coroutine = Coroutine::get_current(); stream->waiting_coroutine->yield(); stream->waiting_coroutine = nullptr; @@ -553,23 +551,23 @@ static bool swoole_http2_server_respond(HttpContext *ctx, String *body) { } bool _end_stream; - if (send_len > stream->send_window) { - send_len = stream->send_window; + if (send_len > stream->remote_window_size) { + send_len = stream->remote_window_size; _end_stream = false; } else { _end_stream = true && end_stream; } - error = !stream->send_body(body, _end_stream, client->max_frame_size, body->offset, send_len); + error = !stream->send_body(body, _end_stream, client->local_settings.max_frame_size, body->offset, send_len); if (!error) { swoole_trace_log( - SW_TRACE_HTTP2, "body: send length=%zu, stream->send_window=%u", send_len, stream->send_window); + SW_TRACE_HTTP2, "body: send length=%zu, stream->remote_window_size=%u", send_len, stream->remote_window_size); body->offset += send_len; - if (send_len > stream->send_window) { - stream->send_window = 0; + if (send_len > stream->remote_window_size) { + stream->remote_window_size = 0; } else { - stream->send_window -= send_len; + stream->remote_window_size -= send_len; } } } @@ -642,10 +640,10 @@ static bool http2_context_sendfile(HttpContext *ctx, const char *file, uint32_t bool error = false; if (body->length > 0) { - if (!stream->send_body(body.get(), end_stream, client->max_frame_size, offset, length)) { + if (!stream->send_body(body.get(), end_stream, client->local_settings.max_frame_size, offset, length)) { error = true; } else { - client->send_window -= length; // TODO: flow control? + client->remote_settings.window_size -= length; // TODO: flow control? } } @@ -825,8 +823,8 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { swoole_http2_frame_trace_log(recv, "id=%d, value=%d", id, value); switch (id) { case SW_HTTP2_SETTING_HEADER_TABLE_SIZE: - if (value != client->header_table_size) { - client->header_table_size = value; + if (value != client->remote_settings.header_table_size) { + client->remote_settings.header_table_size = value; if (client->deflater) { int ret = nghttp2_hd_deflate_change_table_size(client->deflater, value); if (ret != 0) { @@ -840,19 +838,19 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { swoole_trace_log(SW_TRACE_HTTP2, "setting: header_table_size=%u", value); break; case SW_HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS: - client->max_concurrent_streams = value; + client->remote_settings.max_concurrent_streams = value; swoole_trace_log(SW_TRACE_HTTP2, "setting: max_concurrent_streams=%u", value); break; case SW_HTTP2_SETTINGS_INIT_WINDOW_SIZE: - client->send_window = value; - swoole_trace_log(SW_TRACE_HTTP2, "setting: init_send_window=%u", value); + client->remote_settings.window_size = value; + swoole_trace_log(SW_TRACE_HTTP2, "setting: init_window_size=%u", value); break; case SW_HTTP2_SETTINGS_MAX_FRAME_SIZE: - client->max_frame_size = value; + client->remote_settings.max_frame_size = value; swoole_trace_log(SW_TRACE_HTTP2, "setting: max_frame_size=%u", value); break; case SW_HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: - // client->max_header_list_size = value; // useless now + client->remote_settings.max_header_list_size = value; // useless now swoole_trace_log(SW_TRACE_HTTP2, "setting: max_header_list_size=%u", value); break; default: @@ -915,17 +913,17 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { buffer->append(buf, length); // flow control - client->recv_window -= length; - stream->recv_window -= length; + client->local_settings.window_size -= length; + stream->local_window_size -= length; if (length > 0) { - if (client->recv_window < (SW_HTTP2_MAX_WINDOW_SIZE / 4)) { - http2_server_send_window_update(ctx, 0, SW_HTTP2_MAX_WINDOW_SIZE - client->recv_window); - client->recv_window = SW_HTTP2_MAX_WINDOW_SIZE; + if (client->local_settings.window_size < (SW_HTTP2_MAX_WINDOW_SIZE / 4)) { + http2_server_send_window_update(ctx, 0, SW_HTTP2_MAX_WINDOW_SIZE - client->local_settings.window_size); + client->local_settings.window_size = SW_HTTP2_MAX_WINDOW_SIZE; } - if (stream->recv_window < (SW_HTTP2_MAX_WINDOW_SIZE / 4)) { - http2_server_send_window_update(ctx, stream_id, SW_HTTP2_MAX_WINDOW_SIZE - stream->recv_window); - stream->recv_window = SW_HTTP2_MAX_WINDOW_SIZE; + if (stream->local_window_size < (SW_HTTP2_MAX_WINDOW_SIZE / 4)) { + http2_server_send_window_update(ctx, stream_id, SW_HTTP2_MAX_WINDOW_SIZE - stream->local_window_size); + stream->local_window_size = SW_HTTP2_MAX_WINDOW_SIZE; } } @@ -967,14 +965,18 @@ int swoole_http2_server_parse(Http2Session *client, const char *buf) { } case SW_HTTP2_TYPE_WINDOW_UPDATE: { value = ntohl(*(uint32_t *) buf); - client->send_window += value; - if (stream_id > 0 && !client->is_coro && client->streams.find(stream_id) != client->streams.end()) { - stream = client->streams[stream_id]; - Server *serv = (Server *) stream->ctx->private_data; - - stream->send_window += value; - if (serv->send_yield && stream->waiting_coroutine) { - stream->waiting_coroutine->resume(); + if (stream_id == 0) { + client->remote_settings.window_size += value; + } else { + if (client->streams.find(stream_id) != client->streams.end()) { + stream = client->streams[stream_id]; + stream->remote_window_size += value; + if (!client->is_coro) { + Server *serv = (Server *) stream->ctx->private_data; + if (serv->send_yield && stream->waiting_coroutine) { + stream->waiting_coroutine->resume(); + } + } } } swoole_http2_frame_trace_log(recv, "window_size_increment=%d", value); From a66a6c5aea069cb85f58c43af6e9d51ae5e2960f Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 7 Sep 2021 16:39:42 +0800 Subject: [PATCH 237/936] Optimize code --- ext-src/swoole_http2_client_coro.cc | 6 +++--- include/swoole_socket.h | 2 +- src/coroutine/socket.cc | 2 +- src/network/socket.cc | 2 +- src/server/reactor_thread.cc | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ext-src/swoole_http2_client_coro.cc b/ext-src/swoole_http2_client_coro.cc index b38e4139242..a7715ecb025 100644 --- a/ext-src/swoole_http2_client_coro.cc +++ b/ext-src/swoole_http2_client_coro.cc @@ -172,7 +172,7 @@ class Client { uint32_t send_request(zval *zrequest); bool write_data(uint32_t stream_id, zval *zdata, bool end); bool send_goaway_frame(zend_long error_code, const char *debug_data, size_t debug_data_len); - enum swReturnCode parse_frame(zval *return_value, bool pipeline_read = false); + ReturnCode parse_frame(zval *return_value, bool pipeline_read = false); bool close(); ~Client() { @@ -494,7 +494,7 @@ bool Client::close() { return true; } -enum swReturnCode Client::parse_frame(zval *return_value, bool pipeline_read) { +ReturnCode Client::parse_frame(zval *return_value, bool pipeline_read) { char *buf = client->get_read_buffer()->str; uint8_t type = buf[3]; uint8_t flags = buf[4]; @@ -1350,7 +1350,7 @@ static void php_swoole_http2_client_coro_recv(INTERNAL_FUNCTION_PARAMETERS, bool if (!h2c->recv_packet(timeout)) { RETURN_FALSE; } - enum swReturnCode ret = h2c->parse_frame(return_value, pipeline_read); + ReturnCode ret = h2c->parse_frame(return_value, pipeline_read); if (ret == SW_CONTINUE) { continue; } else if (ret == SW_READY) { diff --git a/include/swoole_socket.h b/include/swoole_socket.h index 4734531462a..7ede64599c2 100644 --- a/include/swoole_socket.h +++ b/include/swoole_socket.h @@ -360,7 +360,7 @@ struct Socket { } int ssl_create(SSLContext *_ssl_context, int _flags); int ssl_connect(); - enum swReturnCode ssl_accept(); + ReturnCode ssl_accept(); ssize_t ssl_recv(void *__buf, size_t __n); ssize_t ssl_send(const void *__buf, size_t __n); ssize_t ssl_readv(IOVector *io_vector); diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index f553d566eb2..567241a24fa 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -1258,7 +1258,7 @@ bool Socket::ssl_handshake() { } } } else { - enum swReturnCode retval; + ReturnCode retval; TimerController timer(&read_timer, read_timeout, this, timer_callback); do { diff --git a/src/network/socket.cc b/src/network/socket.cc index 573364a95a9..6380e0b8b5b 100644 --- a/src/network/socket.cc +++ b/src/network/socket.cc @@ -1057,7 +1057,7 @@ const char *Socket::ssl_get_error_reason(int *reason) { return ERR_reason_error_string(error); } -enum swReturnCode Socket::ssl_accept() { +ReturnCode Socket::ssl_accept() { ssl_clear_error(); int n = SSL_accept(ssl); diff --git a/src/server/reactor_thread.cc b/src/server/reactor_thread.cc index 12763597bce..1dda9e908ad 100644 --- a/src/server/reactor_thread.cc +++ b/src/server/reactor_thread.cc @@ -39,13 +39,13 @@ static void ReactorThread_shutdown(Reactor *reactor); static void ReactorThread_resume_data_receiving(Timer *timer, TimerNode *tnode); #ifdef SW_USE_OPENSSL -static inline enum swReturnCode ReactorThread_verify_ssl_state(Reactor *reactor, ListenPort *port, Socket *_socket) { +static inline ReturnCode ReactorThread_verify_ssl_state(Reactor *reactor, ListenPort *port, Socket *_socket) { Server *serv = (Server *) reactor->ptr; if (!_socket->ssl || _socket->ssl_state == SW_SSL_STATE_READY) { return SW_CONTINUE; } - enum swReturnCode code = _socket->ssl_accept(); + ReturnCode code = _socket->ssl_accept(); if (code != SW_READY) { return code; } @@ -535,7 +535,7 @@ static int ReactorThread_onRead(Reactor *reactor, Event *event) { } } #endif - enum swReturnCode code = ReactorThread_verify_ssl_state(reactor, port, event->socket); + ReturnCode code = ReactorThread_verify_ssl_state(reactor, port, event->socket); switch (code) { case SW_ERROR: return Server::close_connection(reactor, event->socket); From 5d1db99145e22ee8bf1876e44582dedafba6e710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Wed, 8 Sep 2021 15:38:02 +0800 Subject: [PATCH 238/936] Added Co::getStackUsage() (#4398) * Added Co::getStackUsage() * Fix get current stack usage * bytes Co-authored-by: twosee --- ext-src/swoole_coroutine.cc | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/ext-src/swoole_coroutine.cc b/ext-src/swoole_coroutine.cc index d3c178fb267..e6b2ff380ad 100644 --- a/ext-src/swoole_coroutine.cc +++ b/ext-src/swoole_coroutine.cc @@ -103,6 +103,7 @@ static PHP_METHOD(swoole_coroutine, getContext); static PHP_METHOD(swoole_coroutine, getBackTrace); static PHP_METHOD(swoole_coroutine, printBackTrace); static PHP_METHOD(swoole_coroutine, getElapsed); +static PHP_METHOD(swoole_coroutine, getStackUsage); static PHP_METHOD(swoole_coroutine, list); static PHP_METHOD(swoole_coroutine, enableScheduler); static PHP_METHOD(swoole_coroutine, disableScheduler); @@ -161,6 +162,10 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_coroutine_getElapsed, 0, 0, 0) ZEND_ARG_INFO(0, cid) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_coroutine_getStackUsage, 0, 0, 0) + ZEND_ARG_INFO(0, cid) +ZEND_END_ARG_INFO() + static const zend_function_entry swoole_coroutine_methods[] = { /** @@ -184,6 +189,7 @@ static const zend_function_entry swoole_coroutine_methods[] = PHP_ME(swoole_coroutine, getBackTrace, arginfo_swoole_coroutine_getBackTrace, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(swoole_coroutine, printBackTrace, arginfo_swoole_coroutine_printBackTrace, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(swoole_coroutine, getElapsed, arginfo_swoole_coroutine_getElapsed, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(swoole_coroutine, getStackUsage, arginfo_swoole_coroutine_getStackUsage, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(swoole_coroutine, list, arginfo_swoole_coroutine_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_MALIAS(swoole_coroutine, listCoroutines, list, arginfo_swoole_coroutine_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(swoole_coroutine, enableScheduler, arginfo_swoole_coroutine_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) @@ -1058,6 +1064,32 @@ static PHP_METHOD(swoole_coroutine, getElapsed) { RETURN_LONG(ret); } +static PHP_METHOD(swoole_coroutine, getStackUsage) { + zend_long current_cid = PHPCoroutine::get_cid(); + zend_long cid = current_cid; + + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(cid) + ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + + PHPContext *task = (PHPContext *) PHPCoroutine::get_context_by_cid(cid); + if (UNEXPECTED(!task)) { + swoole_set_last_error(SW_ERROR_CO_NOT_EXISTS); + RETURN_FALSE; + } + + zend_vm_stack stack = cid == current_cid ? EG(vm_stack) : task->vm_stack; + size_t usage = 0; + + while (stack) { + usage += (stack->end - stack->top) * sizeof(zval); + stack = stack->prev; + } + + RETURN_LONG(usage); +} + static PHP_METHOD(swoole_coroutine, exists) { zend_long cid; From f1ea7a7e9be1cbdd0051421a1de044922111b440 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Wed, 8 Sep 2021 15:38:26 +0800 Subject: [PATCH 239/936] send twice to reduce memory copy --- ext-src/swoole_http2_server.cc | 29 ++++++++++++++++++++--------- ext-src/swoole_http_response.cc | 16 +++------------- include/swoole_config.h | 1 - 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/ext-src/swoole_http2_server.cc b/ext-src/swoole_http2_server.cc index e0400bbd85c..c84ef5e0f38 100644 --- a/ext-src/swoole_http2_server.cc +++ b/ext-src/swoole_http2_server.cc @@ -450,7 +450,6 @@ bool Http2Stream::send_body(String *body, bool end_stream, size_t max_frame_size while (l > 0) { size_t send_n; int _send_flags; - swoole_http_buffer->clear(); if (l > max_frame_size) { send_n = max_frame_size; _send_flags = 0; @@ -459,18 +458,30 @@ bool Http2Stream::send_body(String *body, bool end_stream, size_t max_frame_size _send_flags = flags; } http2::set_frame_header(frame_header, SW_HTTP2_TYPE_DATA, send_n, _send_flags, id); - swoole_http_buffer->append(frame_header, SW_HTTP2_FRAME_HEADER_SIZE); - swoole_http_buffer->append(p, send_n); + + // send twice to reduce memory copy + if (send_n < SwooleG.pagesize) { + swoole_http_buffer->clear(); + swoole_http_buffer->append(frame_header, SW_HTTP2_FRAME_HEADER_SIZE); + swoole_http_buffer->append(p, send_n); + if (!ctx->send(ctx, swoole_http_buffer->str, swoole_http_buffer->length)) { + return false; + } + } else { + if (!ctx->send(ctx, frame_header, SW_HTTP2_FRAME_HEADER_SIZE)) { + return false; + } + if (!ctx->send(ctx, p, send_n)) { + return false; + } + } swoole_trace_log( SW_TRACE_HTTP2, "send [" SW_ECHO_YELLOW "] stream_id=%u, flags=%d, send_n=%lu", "DATA", id, flags, send_n); - if (!ctx->send(ctx, swoole_http_buffer->str, swoole_http_buffer->length)) { - return false; - } else { - l -= send_n; - p += send_n; - } + + l -= send_n; + p += send_n; } return true; diff --git a/ext-src/swoole_http_response.cc b/ext-src/swoole_http_response.cc index 77495790040..e1543046670 100644 --- a/ext-src/swoole_http_response.cc +++ b/ext-src/swoole_http_response.cc @@ -784,20 +784,13 @@ void HttpContext::end(zval *zdata, zval *return_value) { send_body_str = http_body.str; send_body_len = http_body.length; } - /** - * - */ -#ifdef SW_HTTP_SEND_TWICE - if (send_body_len < SwooleG.pagesize) -#endif - { + // send twice to reduce memory copy + if (send_body_len < SwooleG.pagesize) { if (http_buffer->append(send_body_str, send_body_len) < 0) { send_header_ = 0; RETURN_FALSE; } - } -#ifdef SW_HTTP_SEND_TWICE - else { + } else { if (!send(this, http_buffer->str, http_buffer->length)) { send_header_ = 0; RETURN_FALSE; @@ -809,7 +802,6 @@ void HttpContext::end(zval *zdata, zval *return_value) { } goto _skip_copy; } -#endif } if (!send(this, http_buffer->str, http_buffer->length)) { @@ -819,9 +811,7 @@ void HttpContext::end(zval *zdata, zval *return_value) { } } -#ifdef SW_HTTP_SEND_TWICE _skip_copy: -#endif if (upgrade && !co_socket) { Server *serv = (Server *) private_data; Connection *conn = serv->get_connection_verify(fd); diff --git a/include/swoole_config.h b/include/swoole_config.h index 64aaa1b2798..fa300648d8f 100644 --- a/include/swoole_config.h +++ b/include/swoole_config.h @@ -219,7 +219,6 @@ #define SW_HTTP_RFC1123_DATE_UTC "%a, %d %b %Y %T UTC" #define SW_HTTP_RFC850_DATE "%A, %d-%b-%y %T GMT" #define SW_HTTP_ASCTIME_DATE "%a %b %e %T %Y" -#define SW_HTTP_SEND_TWICE 1 // #define SW_HTTP_100_CONTINUE #define SW_HTTP_100_CONTINUE_PACKET "HTTP/1.1 100 Continue\r\n\r\n" From e080b3f9df5abefe495dbf74b488dd6dd02e7c1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Sat, 11 Sep 2021 11:27:16 +0800 Subject: [PATCH 240/936] Added Timer::exec_count field (#4402) --- ext-src/swoole_timer.cc | 1 + include/swoole_timer.h | 1 + src/core/timer.cc | 43 +++++++++++++++++++++-------------------- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/ext-src/swoole_timer.cc b/ext-src/swoole_timer.cc index c336e32b33f..10394ee9fa1 100644 --- a/ext-src/swoole_timer.cc +++ b/ext-src/swoole_timer.cc @@ -269,6 +269,7 @@ static PHP_FUNCTION(swoole_timer_info) { } array_init(return_value); add_assoc_long(return_value, "exec_msec", tnode->exec_msec); + add_assoc_long(return_value, "exec_count", tnode->exec_count); add_assoc_long(return_value, "interval", tnode->interval); add_assoc_long(return_value, "round", tnode->round); add_assoc_bool(return_value, "removed", tnode->removed); diff --git a/include/swoole_timer.h b/include/swoole_timer.h index 88b8c4832cb..3fcb3a043e9 100644 --- a/include/swoole_timer.h +++ b/include/swoole_timer.h @@ -41,6 +41,7 @@ struct TimerNode { enum Type type; int64_t exec_msec; int64_t interval; + uint64_t exec_count; uint64_t round; bool removed; HeapNode *heap_node; diff --git a/src/core/timer.cc b/src/core/timer.cc index 8e0eca52573..585cb0182e5 100644 --- a/src/core/timer.cc +++ b/src/core/timer.cc @@ -142,12 +142,12 @@ TimerNode *Timer::add(long _msec, bool persistent, void *data, const TimerCallba } map.emplace(std::make_pair(tnode->id, tnode)); swoole_trace_log(SW_TRACE_TIMER, - "id=%ld, exec_msec=%" PRId64 ", msec=%ld, round=%" PRIu64 ", exist=%lu", - tnode->id, - tnode->exec_msec, - _msec, - tnode->round, - count()); + "id=%ld, exec_msec=%" PRId64 ", msec=%ld, round=%" PRIu64 ", exist=%lu", + tnode->id, + tnode->exec_msec, + _msec, + tnode->round, + count()); return tnode; } @@ -158,11 +158,11 @@ bool Timer::remove(TimerNode *tnode) { if (sw_unlikely(_current_id > 0 && tnode->id == _current_id)) { tnode->removed = true; swoole_trace_log(SW_TRACE_TIMER, - "set-remove: id=%ld, exec_msec=%" PRId64 ", round=%" PRIu64 ", exist=%lu", - tnode->id, - tnode->exec_msec, - tnode->round, - count()); + "set-remove: id=%ld, exec_msec=%" PRId64 ", round=%" PRIu64 ", exist=%lu", + tnode->id, + tnode->exec_msec, + tnode->round, + count()); return true; } if (sw_unlikely(!map.erase(tnode->id))) { @@ -175,11 +175,11 @@ bool Timer::remove(TimerNode *tnode) { tnode->destructor(tnode); } swoole_trace_log(SW_TRACE_TIMER, - "id=%ld, exec_msec=%" PRId64 ", round=%" PRIu64 ", exist=%lu", - tnode->id, - tnode->exec_msec, - tnode->round, - count()); + "id=%ld, exec_msec=%" PRId64 ", round=%" PRIu64 ", exist=%lu", + tnode->id, + tnode->exec_msec, + tnode->round, + count()); delete tnode; return true; } @@ -204,11 +204,11 @@ int Timer::select() { _current_id = tnode->id; if (!tnode->removed) { swoole_trace_log(SW_TRACE_TIMER, - "id=%ld, exec_msec=%" PRId64 ", round=%" PRIu64 ", exist=%lu", - tnode->id, - tnode->exec_msec, - tnode->round, - count() - 1); + "id=%ld, exec_msec=%" PRId64 ", round=%" PRIu64 ", exist=%lu", + tnode->id, + tnode->exec_msec, + tnode->round, + count() - 1); tnode->callback(this, tnode); } _current_id = -1; @@ -218,6 +218,7 @@ int Timer::select() { while (tnode->exec_msec <= now_msec) { tnode->exec_msec += tnode->interval; } + tnode->exec_count++; heap.change_priority(tnode->exec_msec, tmp); continue; } From 8cfc1001f8d30544bff6d7064e143f3f7f26674f Mon Sep 17 00:00:00 2001 From: chrysanthemum Date: Tue, 14 Sep 2021 09:32:32 +0800 Subject: [PATCH 241/936] Added Redis Stream support (#4390) * Added Redis Stream support * Added Redis Stream support improvement code * Added Redis Stream support resolve conversation --- ext-src/swoole_redis_coro.cc | 992 ++++++++++++++++++++++++++++ tests/swoole_redis_coro/stream.phpt | 122 ++++ 2 files changed, 1114 insertions(+) create mode 100644 tests/swoole_redis_coro/stream.phpt diff --git a/ext-src/swoole_redis_coro.cc b/ext-src/swoole_redis_coro.cc index abb0a1cfa7f..02ac7643191 100644 --- a/ext-src/swoole_redis_coro.cc +++ b/ext-src/swoole_redis_coro.cc @@ -842,6 +842,126 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_zunionstore, 0, 0, 2) ZEND_ARG_INFO(0, weights) ZEND_ARG_INFO(0, aggregate) ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xLen, 0, 0, 1) + ZEND_ARG_INFO(0, key) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xAdd, 0, 0, 3) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, id) + ZEND_ARG_INFO(0, pairs) + ZEND_ARG_INFO(0, options) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xRead, 0, 0, 1) + ZEND_ARG_INFO(0, streams) + ZEND_ARG_INFO(0, options) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xDel, 0, 0, 2) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, id) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xRange, 0, 0, 3) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, start) + ZEND_ARG_INFO(0, end) + ZEND_ARG_INFO(0, count) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xRevRange, 0, 0, 3) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, start) + ZEND_ARG_INFO(0, end) + ZEND_ARG_INFO(0, count) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xTrim, 0, 0, 1) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, options) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xGroupCreate, 0, 0, 3) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, group_name) + ZEND_ARG_INFO(0, id) + ZEND_ARG_INFO(0, mkstream) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xGroupSetId, 0, 0, 3) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, group_name) + ZEND_ARG_INFO(0, id) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xGroupDestroy, 0, 0, 2) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, group_name) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xGroupCreateConsumer, 0, 0, 3) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, group_name) + ZEND_ARG_INFO(0, consumer_name) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xGroupDelConsumer, 0, 0, 3) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, group_name) + ZEND_ARG_INFO(0, consumer_name) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xReadGroup, 0, 0, 3) + ZEND_ARG_INFO(0, group_name) + ZEND_ARG_INFO(0, consumer_name) + ZEND_ARG_INFO(0, streams) + ZEND_ARG_INFO(0, options) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xPending, 0, 0, 2) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, group_name) + ZEND_ARG_INFO(0, options) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xAck, 0, 0, 3) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, group_name) + ZEND_ARG_INFO(0, id) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xClaim, 0, 0, 5) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, group_name) + ZEND_ARG_INFO(0, consumer_name) + ZEND_ARG_INFO(0, min_idle_time) + ZEND_ARG_INFO(0, id) + ZEND_ARG_INFO(0, options) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xAutoClaim, 0, 0, 5) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, group_name) + ZEND_ARG_INFO(0, consumer_name) + ZEND_ARG_INFO(0, min_idle_time) + ZEND_ARG_INFO(0, start) + ZEND_ARG_INFO(0, options) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xInfoConsumers, 0, 0, 2) + ZEND_ARG_INFO(0, key) + ZEND_ARG_INFO(0, group_name) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xInfoGroups, 0, 0, 1) + ZEND_ARG_INFO(0, key) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_redis_coro_xInfoStream, 0, 0, 1) + ZEND_ARG_INFO(0, key) +ZEND_END_ARG_INFO() // clang-format on #define IS_EX_PX_ARG(a) (IS_EX_ARG(a) || IS_PX_ARG(a)) @@ -908,6 +1028,21 @@ struct RedisClient { argv = stack_argv; \ } +#define SW_REDIS_COMMAND_INCREASE_ARGV(_new_argc) \ + if (_new_argc > SW_REDIS_COMMAND_BUFFER_SIZE && _new_argc > argc) { \ + size_t *tmp_argvlen; \ + char **tmp_argv; \ + tmp_argvlen = (size_t *) emalloc(sizeof(size_t) * (_new_argc)); \ + tmp_argv = (char **) emalloc(sizeof(char *) * (_new_argc)); \ + for (int argc_i = 0; argc_i < argc; argc_i++) { \ + tmp_argvlen[argc_i] = argvlen[argc_i]; \ + tmp_argv[argc_i] = argv[argc_i]; \ + } \ + argvlen = tmp_argvlen; \ + argv = tmp_argv; \ + } \ + argc = _new_argc; + #define SW_REDIS_COMMAND_FREE_ARGV \ if (argv != stack_argv) { \ efree(argvlen); \ @@ -1570,6 +1705,40 @@ static sw_inline void sw_redis_command_key_str_str(INTERNAL_FUNCTION_PARAMETERS, redis_request(redis, 4, argv, argvlen, return_value); } +static sw_inline void sw_redis_command_xrange(INTERNAL_FUNCTION_PARAMETERS, const char *cmd, int cmd_len) { + char *key, *val1, *val2; + size_t key_len, val1_len, val2_len; + zend_long count = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|l", &key, &key_len, &val1, &val1_len, &val2, &val2_len, &count) == FAILURE) { + RETURN_FALSE; + } + SW_REDIS_COMMAND_CHECK + + int i = 0, argc; + argc = ZEND_NUM_ARGS() == 4 ? 6 : 4; + SW_REDIS_COMMAND_ALLOC_ARGV + SW_REDIS_COMMAND_ARGV_FILL(cmd, cmd_len) + SW_REDIS_COMMAND_ARGV_FILL(key, key_len) + SW_REDIS_COMMAND_ARGV_FILL(val1, val1_len) + SW_REDIS_COMMAND_ARGV_FILL(val2, val2_len) + if (count > 0) { + SW_REDIS_COMMAND_ARGV_FILL("COUNT", 5) + char buf[32]; + size_t buf_len; + buf_len = sprintf(buf, ZEND_LONG_FMT, count); + SW_REDIS_COMMAND_ARGV_FILL((char *) buf, buf_len) + } + + redis_request(redis, argc, argv, argvlen, return_value); + + if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) { + swoole_redis_handle_assoc_array_result(return_value, true); + } + + SW_REDIS_COMMAND_FREE_ARGV +} + SW_EXTERN_C_BEGIN static PHP_METHOD(swoole_redis_coro, __construct); static PHP_METHOD(swoole_redis_coro, __destruct); @@ -1717,6 +1886,26 @@ static PHP_METHOD(swoole_redis_coro, exec); static PHP_METHOD(swoole_redis_coro, eval); static PHP_METHOD(swoole_redis_coro, evalSha); static PHP_METHOD(swoole_redis_coro, script); +static PHP_METHOD(swoole_redis_coro, xLen); +static PHP_METHOD(swoole_redis_coro, xAdd); +static PHP_METHOD(swoole_redis_coro, xRead); +static PHP_METHOD(swoole_redis_coro, xDel); +static PHP_METHOD(swoole_redis_coro, xRange); +static PHP_METHOD(swoole_redis_coro, xRevRange); +static PHP_METHOD(swoole_redis_coro, xTrim); +static PHP_METHOD(swoole_redis_coro, xGroupCreate); +static PHP_METHOD(swoole_redis_coro, xGroupSetId); +static PHP_METHOD(swoole_redis_coro, xGroupDestroy); +static PHP_METHOD(swoole_redis_coro, xGroupCreateConsumer); +static PHP_METHOD(swoole_redis_coro, xGroupDelConsumer); +static PHP_METHOD(swoole_redis_coro, xReadGroup); +static PHP_METHOD(swoole_redis_coro, xPending); +static PHP_METHOD(swoole_redis_coro, xAck); +static PHP_METHOD(swoole_redis_coro, xClaim); +static PHP_METHOD(swoole_redis_coro, xAutoClaim); +static PHP_METHOD(swoole_redis_coro, xInfoConsumers); +static PHP_METHOD(swoole_redis_coro, xInfoGroups); +static PHP_METHOD(swoole_redis_coro, xInfoStream); SW_EXTERN_C_END /*---------------------Redis Command End------------------------*/ // clang-format off @@ -1888,6 +2077,26 @@ static const zend_function_entry swoole_redis_coro_methods[] = PHP_ME(swoole_redis_coro, eval, arginfo_swoole_redis_coro_eval, ZEND_ACC_PUBLIC) PHP_ME(swoole_redis_coro, evalSha, arginfo_swoole_redis_coro_evalsha, ZEND_ACC_PUBLIC) PHP_ME(swoole_redis_coro, script, arginfo_swoole_redis_coro_script, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xLen, arginfo_swoole_redis_coro_xLen, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xAdd, arginfo_swoole_redis_coro_xAdd, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xRead, arginfo_swoole_redis_coro_xRead, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xDel, arginfo_swoole_redis_coro_xDel, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xRange, arginfo_swoole_redis_coro_xRange, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xRevRange, arginfo_swoole_redis_coro_xRevRange, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xTrim, arginfo_swoole_redis_coro_xTrim, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xGroupCreate, arginfo_swoole_redis_coro_xGroupCreate, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xGroupSetId, arginfo_swoole_redis_coro_xGroupSetId, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xGroupDestroy, arginfo_swoole_redis_coro_xGroupDestroy, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xGroupCreateConsumer, arginfo_swoole_redis_coro_xGroupCreateConsumer, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xGroupDelConsumer, arginfo_swoole_redis_coro_xGroupDelConsumer, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xReadGroup, arginfo_swoole_redis_coro_xReadGroup, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xPending, arginfo_swoole_redis_coro_xPending, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xAck, arginfo_swoole_redis_coro_xAck, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xClaim, arginfo_swoole_redis_coro_xClaim, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xAutoClaim, arginfo_swoole_redis_coro_xAutoClaim, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xInfoConsumers, arginfo_swoole_redis_coro_xInfoConsumers, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xInfoGroups, arginfo_swoole_redis_coro_xInfoGroups, ZEND_ACC_PUBLIC) + PHP_ME(swoole_redis_coro, xInfoStream, arginfo_swoole_redis_coro_xInfoStream, ZEND_ACC_PUBLIC) /*---------------------Redis Command End------------------------*/ PHP_FE_END }; @@ -4404,6 +4613,789 @@ static PHP_METHOD(swoole_redis_coro, script) { } } +static PHP_METHOD(swoole_redis_coro, xLen) { + sw_redis_command_key(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("XLEN")); +} + +static PHP_METHOD(swoole_redis_coro, xAdd) { + zval *z_options = nullptr, *z_ele; + HashTable *ht_opt, *ht_ele; + char *key, *id; + size_t key_len, id_len; + zval *z_arr; + int argc, options_argc = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssa|a", &key, &key_len, &id, &id_len, &z_arr, &z_options) == FAILURE) { + return; + } + if ((argc = zend_hash_num_elements(Z_ARRVAL_P(z_arr))) == 0) { + RETURN_FALSE; + } + SW_REDIS_COMMAND_CHECK + int i = 0; + argc = argc * 2 + 3; + zval *value; + char buf[32]; + size_t buf_len; + SW_REDIS_COMMAND_ALLOC_ARGV + SW_REDIS_COMMAND_ARGV_FILL("XADD", 4) + SW_REDIS_COMMAND_ARGV_FILL(key, key_len) + + // options + if (z_options && ZVAL_IS_ARRAY(z_options)) { + ht_opt = Z_ARRVAL_P(z_options); + int has_maxlen_minid = 0; + int can_limit = 0; + // NOMKSTREAM + if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("nomkstream"))) && Z_TYPE_P(z_ele) == IS_TRUE) { + SW_REDIS_COMMAND_ARGV_FILL("NOMKSTREAM", 10) + options_argc++; + } + // MAXLEN + if (has_maxlen_minid == 0 && (z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("maxlen")))) { + has_maxlen_minid = 1; + if (Z_TYPE_P(z_ele) == IS_LONG) { + SW_REDIS_COMMAND_ARGV_FILL("MAXLEN", 6) + buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele)); + SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len) + options_argc += 2; + } else if (Z_TYPE_P(z_ele) == IS_ARRAY) { + ht_ele = Z_ARRVAL_P(z_ele); + zval *z_maxlen_p1 = zend_hash_index_find(ht_ele, 0); + zval *z_maxlen_p2 = zend_hash_index_find(ht_ele, 1); + if (Z_TYPE_P(z_maxlen_p1) == IS_STRING && Z_TYPE_P(z_maxlen_p2) == IS_LONG) { + char *maxlen_p1 = Z_STRVAL_P(z_maxlen_p1); + zend_long maxlen_p2 = Z_LVAL_P(z_maxlen_p2); + if ((strcmp(maxlen_p1, "=") == 0 || strcmp(maxlen_p1, "~") == 0) && maxlen_p2 >= 0) { + if ((strcmp(maxlen_p1, "~") == 0)) { + can_limit = 1; + } + SW_REDIS_COMMAND_ARGV_FILL("MAXLEN", 6) + SW_REDIS_COMMAND_ARGV_FILL(maxlen_p1, 1) + buf_len = sprintf(buf, ZEND_LONG_FMT, maxlen_p2); + SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len) + options_argc += 3; + } + } + } + } + // MINID + if (has_maxlen_minid == 0 && (z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("minid")))) { + has_maxlen_minid = 1; + if (Z_TYPE_P(z_ele) == IS_STRING && Z_STRLEN_P(z_ele) > 0) { + SW_REDIS_COMMAND_ARGV_FILL("MINID", 5) + SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(z_ele), Z_STRLEN_P(z_ele)) + options_argc += 2; + } else if (Z_TYPE_P(z_ele) == IS_ARRAY) { + ht_ele = Z_ARRVAL_P(z_ele); + zval *z_minid_p1 = zend_hash_index_find(ht_ele, 0); + zval *z_minid_p2 = zend_hash_index_find(ht_ele, 1); + if (Z_TYPE_P(z_minid_p1) == IS_STRING && Z_TYPE_P(z_minid_p2) == IS_STRING) { + char *minid_p1 = Z_STRVAL_P(z_minid_p1); + char *minid_p2 = Z_STRVAL_P(z_minid_p2); + if ((strcmp(minid_p1, "=") == 0 || strcmp(minid_p1, "~") == 0) && strlen(minid_p2) > 0) { + if ((strcmp(minid_p1, "~") == 0)) { + can_limit = 1; + } + SW_REDIS_COMMAND_ARGV_FILL("MINID", 5) + SW_REDIS_COMMAND_ARGV_FILL(minid_p1, 1) + SW_REDIS_COMMAND_ARGV_FILL(minid_p2, strlen(minid_p2)) + options_argc += 3; + } + } + } + } + // LIMIT + if (can_limit == 1 && (z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("limit"))) && Z_TYPE_P(z_ele) == IS_LONG) { + SW_REDIS_COMMAND_ARGV_FILL("LIMIT", 5) + buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele)); + SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len) + options_argc += 2; + } + } + + SW_REDIS_COMMAND_INCREASE_ARGV(argc + options_argc) + + // id + SW_REDIS_COMMAND_ARGV_FILL(id, id_len) + + // k-v + zend_ulong idx; + zend_string *_key; + ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(z_arr), idx, _key, value) { + if (_key == nullptr) { + key_len = sw_snprintf(buf, sizeof(buf), ZEND_LONG_FMT, idx); + key = (char *) buf; + } else { + key_len = ZSTR_LEN(_key); + key = ZSTR_VAL(_key); + } + SW_REDIS_COMMAND_ARGV_FILL(key, key_len) + SW_REDIS_COMMAND_ARGV_FILL_WITH_SERIALIZE(value) + } + ZEND_HASH_FOREACH_END(); + + redis_request(redis, argc, argv, argvlen, return_value); + SW_REDIS_COMMAND_FREE_ARGV +} + +static PHP_METHOD(swoole_redis_coro, xRead) { + zval *z_streams = nullptr, *z_options = nullptr, *z_ele; + HashTable *ht_opt; + int i = 0, argc = 0, options_argc = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|a", &z_streams, &z_options) == FAILURE) { + RETURN_FALSE; + } + if ((argc = zend_hash_num_elements(Z_ARRVAL_P(z_streams))) == 0) { + RETURN_FALSE; + } + SW_REDIS_COMMAND_CHECK + + argc = argc * 2 + 2; + char buf[32]; + size_t buf_len; + SW_REDIS_COMMAND_ALLOC_ARGV + SW_REDIS_COMMAND_ARGV_FILL("XREAD", 5) + + // options + if (z_options && ZVAL_IS_ARRAY(z_options)) { + ht_opt = Z_ARRVAL_P(z_options); + // COUNT + if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("count"))) && Z_TYPE_P(z_ele) == IS_LONG) { + SW_REDIS_COMMAND_ARGV_FILL("COUNT", 5) + buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele)); + SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len) + options_argc += 2; + } + // BLOCK + if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("block"))) && Z_TYPE_P(z_ele) == IS_LONG) { + SW_REDIS_COMMAND_ARGV_FILL("BLOCK", 5) + buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele)); + SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len) + options_argc += 2; + } + } + + SW_REDIS_COMMAND_INCREASE_ARGV(argc + options_argc) + + // streams + SW_REDIS_COMMAND_ARGV_FILL("STREAMS", 7) + zend_long _num_key; + zend_string *_str_key; + zval *_val; + ZEND_HASH_FOREACH_KEY(Z_ARRVAL_P(z_streams), _num_key, _str_key) { + if (_str_key == NULL) { + _str_key = zend_long_to_str(_num_key); + } + SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(_str_key), ZSTR_LEN(_str_key)) + } + ZEND_HASH_FOREACH_END(); + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(z_streams), _val) { + convert_to_string(_val); + SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(_val), Z_STRLEN_P(_val)) + } + ZEND_HASH_FOREACH_END(); + + redis_request(redis, argc, argv, argvlen, return_value); + + if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) { + swoole_redis_handle_assoc_array_result(return_value, true); + } + + SW_REDIS_COMMAND_FREE_ARGV +} + +static PHP_METHOD(swoole_redis_coro, xRange) { + sw_redis_command_xrange(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("XRANGE")); +} + +static PHP_METHOD(swoole_redis_coro, xRevRange) { + sw_redis_command_xrange(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("XREVRANGE")); +} + +static PHP_METHOD(swoole_redis_coro, xTrim) { + zval *z_options = nullptr, *z_ele; + HashTable *ht_opt, *ht_ele; + int i = 0, argc = 2, options_argc = 0; + char buf[32], *key; + size_t buf_len, key_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|a", &key, &key_len, &z_options) == FAILURE) { + RETURN_FALSE; + } + if (zend_hash_num_elements(Z_ARRVAL_P(z_options)) < 1) { + RETURN_FALSE; + } + + SW_REDIS_COMMAND_CHECK + SW_REDIS_COMMAND_ALLOC_ARGV + SW_REDIS_COMMAND_ARGV_FILL("XTRIM", 5) + SW_REDIS_COMMAND_ARGV_FILL(key, key_len) + + // options + if (z_options && ZVAL_IS_ARRAY(z_options)) { + ht_opt = Z_ARRVAL_P(z_options); + int has_maxlen_minid = 0; + int can_limit = 0; + // MAXLEN + if (has_maxlen_minid == 0 && (z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("maxlen")))) { + has_maxlen_minid = 1; + if (Z_TYPE_P(z_ele) == IS_LONG) { + SW_REDIS_COMMAND_ARGV_FILL("MAXLEN", 6) + buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele)); + SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len) + options_argc += 2; + } else if (Z_TYPE_P(z_ele) == IS_ARRAY) { + ht_ele = Z_ARRVAL_P(z_ele); + zval *z_maxlen_p1 = zend_hash_index_find(ht_ele, 0); + zval *z_maxlen_p2 = zend_hash_index_find(ht_ele, 1); + if (Z_TYPE_P(z_maxlen_p1) == IS_STRING && Z_TYPE_P(z_maxlen_p2) == IS_LONG) { + char *maxlen_p1 = Z_STRVAL_P(z_maxlen_p1); + zend_long maxlen_p2 = Z_LVAL_P(z_maxlen_p2); + if ((strcmp(maxlen_p1, "=") == 0 || strcmp(maxlen_p1, "~") == 0) && maxlen_p2 >= 0) { + if ((strcmp(maxlen_p1, "~") == 0)) { + can_limit = 1; + } + SW_REDIS_COMMAND_ARGV_FILL("MAXLEN", 6) + SW_REDIS_COMMAND_ARGV_FILL(maxlen_p1, 1) + buf_len = sprintf(buf, ZEND_LONG_FMT, maxlen_p2); + SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len) + options_argc += 3; + } + } + } + } + // MINID + if (has_maxlen_minid == 0 && (z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("minid")))) { + has_maxlen_minid = 1; + if (Z_TYPE_P(z_ele) == IS_STRING && Z_STRLEN_P(z_ele) > 0) { + SW_REDIS_COMMAND_ARGV_FILL("MINID", 5) + SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(z_ele), Z_STRLEN_P(z_ele)) + options_argc += 2; + } else if (Z_TYPE_P(z_ele) == IS_ARRAY) { + ht_ele = Z_ARRVAL_P(z_ele); + zval *z_minid_p1 = zend_hash_index_find(ht_ele, 0); + zval *z_minid_p2 = zend_hash_index_find(ht_ele, 1); + if (Z_TYPE_P(z_minid_p1) == IS_STRING && Z_TYPE_P(z_minid_p2) == IS_STRING) { + char *minid_p1 = Z_STRVAL_P(z_minid_p1); + char *minid_p2 = Z_STRVAL_P(z_minid_p2); + if ((strcmp(minid_p1, "=") == 0 || strcmp(minid_p1, "~") == 0) && strlen(minid_p2) > 0) { + if ((strcmp(minid_p1, "~") == 0)) { + can_limit = 1; + } + SW_REDIS_COMMAND_ARGV_FILL("MINID", 5) + SW_REDIS_COMMAND_ARGV_FILL(minid_p1, 1) + SW_REDIS_COMMAND_ARGV_FILL(minid_p2, strlen(minid_p2)) + options_argc += 3; + } + } + } + } + // LIMIT + if (can_limit == 1 && (z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("limit"))) && Z_TYPE_P(z_ele) == IS_LONG) { + SW_REDIS_COMMAND_ARGV_FILL("LIMIT", 5) + buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele)); + SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len) + options_argc += 2; + } + } + + SW_REDIS_COMMAND_INCREASE_ARGV(argc + options_argc) + + redis_request(redis, argc, argv, argvlen, return_value); + + if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) { + swoole_redis_handle_assoc_array_result(return_value, true); + } + + SW_REDIS_COMMAND_FREE_ARGV +} + +static PHP_METHOD(swoole_redis_coro, xDel) { + sw_redis_command_key_var_val(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_STRL("XDEL")); +} + +static PHP_METHOD(swoole_redis_coro, xGroupCreate) { + char *key, *group_name, *id; + size_t key_len, group_name_len, id_len; + zend_bool mkstream = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|b", &key, &key_len, &group_name, &group_name_len, &id, &id_len, &mkstream) == FAILURE) { + return; + } + SW_REDIS_COMMAND_CHECK + int i = 0, argc = 5; + size_t argvlen[6]; + char *argv[6]; + SW_REDIS_COMMAND_ARGV_FILL("XGROUP", 6) + SW_REDIS_COMMAND_ARGV_FILL("CREATE", 6) + SW_REDIS_COMMAND_ARGV_FILL(key, key_len) + SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len) + SW_REDIS_COMMAND_ARGV_FILL(id, id_len) + if (mkstream) { + SW_REDIS_COMMAND_ARGV_FILL("MKSTREAM", 8) + argc = 6; + } + + redis_request(redis, argc, argv, argvlen, return_value); +} + +static PHP_METHOD(swoole_redis_coro, xGroupSetId) { + char *key, *group_name, *id; + size_t key_len, group_name_len, id_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss", &key, &key_len, &group_name, &group_name_len, &id, &id_len) == FAILURE) { + return; + } + SW_REDIS_COMMAND_CHECK + int i = 0, argc = 5; + size_t argvlen[5]; + char *argv[5]; + SW_REDIS_COMMAND_ARGV_FILL("XGROUP", 6) + SW_REDIS_COMMAND_ARGV_FILL("CREATECONSUMER", 14) + SW_REDIS_COMMAND_ARGV_FILL(key, key_len) + SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len) + SW_REDIS_COMMAND_ARGV_FILL(id, id_len) + + redis_request(redis, argc, argv, argvlen, return_value); +} + +static PHP_METHOD(swoole_redis_coro, xGroupDestroy) { + char *key, *group_name; + size_t key_len, group_name_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &key, &key_len, &group_name, &group_name_len) == FAILURE) { + return; + } + SW_REDIS_COMMAND_CHECK + int i = 0, argc = 4; + size_t argvlen[4]; + char *argv[4]; + SW_REDIS_COMMAND_ARGV_FILL("XGROUP", 6) + SW_REDIS_COMMAND_ARGV_FILL("DESTROY", 7) + SW_REDIS_COMMAND_ARGV_FILL(key, key_len) + SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len) + + redis_request(redis, argc, argv, argvlen, return_value); +} + +static PHP_METHOD(swoole_redis_coro, xGroupCreateConsumer) { + char *key, *group_name, *consumer_name; + size_t key_len, group_name_len, consumer_name_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss", &key, &key_len, &group_name, &group_name_len, &consumer_name, &consumer_name_len) == FAILURE) { + return; + } + SW_REDIS_COMMAND_CHECK + int i = 0, argc = 5; + size_t argvlen[5]; + char *argv[5]; + SW_REDIS_COMMAND_ARGV_FILL("XGROUP", 6) + SW_REDIS_COMMAND_ARGV_FILL("CREATECONSUMER", 14) + SW_REDIS_COMMAND_ARGV_FILL(key, key_len) + SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len) + SW_REDIS_COMMAND_ARGV_FILL(consumer_name, consumer_name_len) + + redis_request(redis, argc, argv, argvlen, return_value); +} + +static PHP_METHOD(swoole_redis_coro, xGroupDelConsumer) { + char *key, *group_name, *consumer_name; + size_t key_len, group_name_len, consumer_name_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss", &key, &key_len, &group_name, &group_name_len, &consumer_name, &consumer_name_len) == FAILURE) { + return; + } + SW_REDIS_COMMAND_CHECK + int i = 0, argc = 5; + size_t argvlen[5]; + char *argv[5]; + SW_REDIS_COMMAND_ARGV_FILL("XGROUP", 6) + SW_REDIS_COMMAND_ARGV_FILL("DELCONSUMER", 11) + SW_REDIS_COMMAND_ARGV_FILL(key, key_len) + SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len) + SW_REDIS_COMMAND_ARGV_FILL(consumer_name, consumer_name_len) + + redis_request(redis, argc, argv, argvlen, return_value); +} + +static PHP_METHOD(swoole_redis_coro, xReadGroup) { + char *group_name, *consumer_name; + size_t group_name_len, consumer_name_len; + zval *z_streams = nullptr, *z_options = nullptr, *z_ele; + HashTable *ht_opt; + int i = 0, argc = 0, options_argc = 0; + char buf[32]; + size_t buf_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssa|a", &group_name, &group_name_len, &consumer_name, &consumer_name_len, &z_streams, &z_options) == FAILURE) { + RETURN_FALSE; + } + if ((argc = zend_hash_num_elements(Z_ARRVAL_P(z_streams))) == 0) { + RETURN_FALSE; + } + SW_REDIS_COMMAND_CHECK + argc = argc * 2 + 5; + SW_REDIS_COMMAND_ALLOC_ARGV + SW_REDIS_COMMAND_ARGV_FILL("XREADGROUP", 10) + SW_REDIS_COMMAND_ARGV_FILL("GROUP", 5) + SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len) + SW_REDIS_COMMAND_ARGV_FILL(consumer_name, consumer_name_len) + + // options + if (z_options && ZVAL_IS_ARRAY(z_options)) { + ht_opt = Z_ARRVAL_P(z_options); + // COUNT + if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("count"))) && Z_TYPE_P(z_ele) == IS_LONG) { + SW_REDIS_COMMAND_ARGV_FILL("COUNT", 5) + buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele)); + SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len) + options_argc += 2; + } + // BLOCK + if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("block"))) && Z_TYPE_P(z_ele) == IS_LONG) { + SW_REDIS_COMMAND_ARGV_FILL("BLOCK", 5) + buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele)); + SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len) + options_argc += 2; + } + // NOACK + if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("noack"))) && Z_TYPE_P(z_ele) == IS_TRUE) { + SW_REDIS_COMMAND_ARGV_FILL("NOACK", 5) + options_argc++; + } + } + + SW_REDIS_COMMAND_INCREASE_ARGV(argc + options_argc) + + // streams + SW_REDIS_COMMAND_ARGV_FILL("STREAMS", 7) + zend_long _num_key; + zend_string *_str_key; + zval *_val; + ZEND_HASH_FOREACH_KEY(Z_ARRVAL_P(z_streams), _num_key, _str_key) { + if (_str_key == NULL) { + _str_key = zend_long_to_str(_num_key); + } + SW_REDIS_COMMAND_ARGV_FILL(ZSTR_VAL(_str_key), ZSTR_LEN(_str_key)) + } + ZEND_HASH_FOREACH_END(); + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(z_streams), _val) { + convert_to_string(_val); + SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(_val), Z_STRLEN_P(_val)) + } + ZEND_HASH_FOREACH_END(); + + redis_request(redis, argc, argv, argvlen, return_value); + + if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) { + swoole_redis_handle_assoc_array_result(return_value, true); + } + + SW_REDIS_COMMAND_FREE_ARGV +} + +static PHP_METHOD(swoole_redis_coro, xPending) { + char *key, *group_name; + size_t key_len, group_name_len; + zval *z_options = nullptr, *z_ele; + HashTable *ht_opt; + int i = 0, argc = 3, options_argc = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|a", &key, &key_len, &group_name, &group_name_len, &z_options) == FAILURE) { + RETURN_FALSE; + } + + char buf[32]; + size_t buf_len; + SW_REDIS_COMMAND_CHECK + SW_REDIS_COMMAND_ALLOC_ARGV + SW_REDIS_COMMAND_ARGV_FILL("XPENDING", 8) + SW_REDIS_COMMAND_ARGV_FILL(key, key_len) + SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len) + + // options + if (z_options && ZVAL_IS_ARRAY(z_options)) { + ht_opt = Z_ARRVAL_P(z_options); + // IDLE + if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("idle"))) && Z_TYPE_P(z_ele) == IS_LONG) { + SW_REDIS_COMMAND_ARGV_FILL("IDLE", 4) + buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele)); + SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len) + options_argc += 2; + } + // START + if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("start"))) && Z_TYPE_P(z_ele) == IS_STRING) { + SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(z_ele), Z_STRLEN_P(z_ele)) + options_argc++; + } + // END + if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("end"))) && Z_TYPE_P(z_ele) == IS_STRING) { + SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(z_ele), Z_STRLEN_P(z_ele)) + options_argc++; + } + // COUNT + if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("count"))) && Z_TYPE_P(z_ele) == IS_LONG) { + buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele)); + SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len) + options_argc++; + } + // CONSUMER + if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("consumer"))) && Z_TYPE_P(z_ele) == IS_TRUE) { + SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(z_ele), Z_STRLEN_P(z_ele)) + options_argc++; + } + } + + SW_REDIS_COMMAND_INCREASE_ARGV(argc + options_argc) + + redis_request(redis, argc, argv, argvlen, return_value); + + if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) { + swoole_redis_handle_assoc_array_result(return_value, true); + } + + SW_REDIS_COMMAND_FREE_ARGV +} + +static PHP_METHOD(swoole_redis_coro, xAck) { + char *key, *group_name; + size_t key_len, group_name_len; + zval *z_id = nullptr; + int i = 0, argc = 3, id_argc = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssa", &key, &key_len, &group_name, &group_name_len, &z_id) == FAILURE) { + RETURN_FALSE; + } + if ((id_argc = zend_hash_num_elements(Z_ARRVAL_P(z_id))) == 0) { + RETURN_FALSE; + } + argc += id_argc; + SW_REDIS_COMMAND_CHECK + SW_REDIS_COMMAND_ALLOC_ARGV + SW_REDIS_COMMAND_ARGV_FILL("XACK", 4) + SW_REDIS_COMMAND_ARGV_FILL(key, key_len) + SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len) + + // id + zval *_id; + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(z_id), _id) { + convert_to_string(_id); + SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(_id), Z_STRLEN_P(_id)) + } + ZEND_HASH_FOREACH_END(); + + redis_request(redis, argc, argv, argvlen, return_value); + + if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) { + swoole_redis_handle_assoc_array_result(return_value, true); + } + + SW_REDIS_COMMAND_FREE_ARGV +} + +static PHP_METHOD(swoole_redis_coro, xClaim) { + char *key, *group_name, *consumer_name; + size_t key_len, group_name_len, consumer_name_len; + zend_long min_idle_time = 0; + zval *z_id = nullptr, *z_options = nullptr, *z_ele; + HashTable *ht_opt; + int i = 0, argc = 5, id_argc = 0, options_argc = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sssla|a", &key, &key_len, &group_name, &group_name_len, &consumer_name, &consumer_name_len, &min_idle_time, &z_id, &z_options) == FAILURE) { + RETURN_FALSE; + } + + SW_REDIS_COMMAND_CHECK + id_argc = zend_hash_num_elements(Z_ARRVAL_P(z_id)); + argc += id_argc; + char buf[32]; + size_t buf_len; + SW_REDIS_COMMAND_ALLOC_ARGV + SW_REDIS_COMMAND_ARGV_FILL("XCLAIM", 6) + SW_REDIS_COMMAND_ARGV_FILL(key, key_len) + SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len) + SW_REDIS_COMMAND_ARGV_FILL(consumer_name, consumer_name_len) + buf_len = sprintf(buf, ZEND_LONG_FMT, min_idle_time); + SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len) + + // id + zval *_id; + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(z_id), _id) { + convert_to_string(_id); + SW_REDIS_COMMAND_ARGV_FILL(Z_STRVAL_P(_id), Z_STRLEN_P(_id)) + } + ZEND_HASH_FOREACH_END(); + + // options + if (z_options && ZVAL_IS_ARRAY(z_options)) { + ht_opt = Z_ARRVAL_P(z_options); + // IDLE + if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("idle"))) && Z_TYPE_P(z_ele) == IS_LONG) { + SW_REDIS_COMMAND_ARGV_FILL("IDLE", 4) + buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele)); + SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len) + options_argc += 2; + } + // TIME + if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("time"))) && Z_TYPE_P(z_ele) == IS_LONG) { + SW_REDIS_COMMAND_ARGV_FILL("TIME", 4) + buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele)); + SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len) + options_argc += 2; + } + // RETRYCOUNT + if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("retrycount"))) && Z_TYPE_P(z_ele) == IS_LONG) { + SW_REDIS_COMMAND_ARGV_FILL("RETRYCOUNT", 10) + buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele)); + SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len) + options_argc += 2; + } + // FORCE + if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("force"))) && Z_TYPE_P(z_ele) == IS_TRUE) { + SW_REDIS_COMMAND_ARGV_FILL("FORCE", 5) + options_argc++; + } + // JUSTID + if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("justid"))) && Z_TYPE_P(z_ele) == IS_TRUE) { + SW_REDIS_COMMAND_ARGV_FILL("JUSTID", 6) + options_argc++; + } + } + + SW_REDIS_COMMAND_INCREASE_ARGV(argc + options_argc) + + redis_request(redis, argc, argv, argvlen, return_value); + + if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) { + swoole_redis_handle_assoc_array_result(return_value, true); + } + + SW_REDIS_COMMAND_FREE_ARGV +} + +static PHP_METHOD(swoole_redis_coro, xAutoClaim) { + char *key, *group_name, *consumer_name, *start; + size_t key_len, group_name_len, consumer_name_len, start_len; + zend_long min_idle_time = 0; + zval *z_options = nullptr, *z_ele; + HashTable *ht_opt; + int i = 0, argc = 6, options_argc = 0; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sssls|a", &key, &key_len, &group_name, &group_name_len, &consumer_name, &consumer_name_len, &min_idle_time, &start, &start_len, &z_options) == FAILURE) { + RETURN_FALSE; + } + + SW_REDIS_COMMAND_CHECK + char buf[32]; + size_t buf_len; + SW_REDIS_COMMAND_ALLOC_ARGV + SW_REDIS_COMMAND_ARGV_FILL("XAUTOCLAIM", 10) + SW_REDIS_COMMAND_ARGV_FILL(key, key_len) + SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len) + SW_REDIS_COMMAND_ARGV_FILL(consumer_name, consumer_name_len) + buf_len = sprintf(buf, ZEND_LONG_FMT, min_idle_time); + SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len) + SW_REDIS_COMMAND_ARGV_FILL(start, start_len) + + // options + if (z_options && ZVAL_IS_ARRAY(z_options)) { + ht_opt = Z_ARRVAL_P(z_options); + // COUNT + if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("count"))) && Z_TYPE_P(z_ele) == IS_LONG) { + SW_REDIS_COMMAND_ARGV_FILL("COUNT", 5) + buf_len = sprintf(buf, ZEND_LONG_FMT, Z_LVAL_P(z_ele)); + SW_REDIS_COMMAND_ARGV_FILL(buf, buf_len) + options_argc += 2; + } + // JUSTID + if ((z_ele = zend_hash_str_find(ht_opt, ZEND_STRL("justid"))) && Z_TYPE_P(z_ele) == IS_TRUE) { + SW_REDIS_COMMAND_ARGV_FILL("JUSTID", 6) + options_argc++; + } + } + + SW_REDIS_COMMAND_INCREASE_ARGV(argc + options_argc) + + redis_request(redis, argc, argv, argvlen, return_value); + + if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) { + swoole_redis_handle_assoc_array_result(return_value, true); + } + + SW_REDIS_COMMAND_FREE_ARGV +} + +static PHP_METHOD(swoole_redis_coro, xInfoConsumers) { + char *key, *group_name; + size_t key_len, group_name_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &key, &key_len, &group_name, &group_name_len) == FAILURE) { + return; + } + + SW_REDIS_COMMAND_CHECK + int i = 0, argc = 4; + size_t argvlen[4]; + char *argv[4]; + SW_REDIS_COMMAND_ARGV_FILL("XINFO", 5) + SW_REDIS_COMMAND_ARGV_FILL("CONSUMERS", 9) + SW_REDIS_COMMAND_ARGV_FILL(key, key_len) + SW_REDIS_COMMAND_ARGV_FILL(group_name, group_name_len) + + redis_request(redis, argc, argv, argvlen, return_value); + + if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) { + swoole_redis_handle_assoc_array_result(return_value, true); + } +} + +static PHP_METHOD(swoole_redis_coro, xInfoGroups) { + char *key; + size_t key_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &key, &key_len) == FAILURE) { + return; + } + + SW_REDIS_COMMAND_CHECK + int i = 0, argc = 3; + size_t argvlen[3]; + char *argv[3]; + SW_REDIS_COMMAND_ARGV_FILL("XINFO", 5) + SW_REDIS_COMMAND_ARGV_FILL("GROUPS", 6) + SW_REDIS_COMMAND_ARGV_FILL(key, key_len) + + redis_request(redis, argc, argv, argvlen, return_value); + + if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) { + swoole_redis_handle_assoc_array_result(return_value, true); + } +} + +static PHP_METHOD(swoole_redis_coro, xInfoStream) { + char *key; + size_t key_len; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &key, &key_len) == FAILURE) { + return; + } + SW_REDIS_COMMAND_CHECK + int i = 0, argc = 3; + size_t argvlen[3]; + char *argv[3]; + SW_REDIS_COMMAND_ARGV_FILL("XINFO", 5) + SW_REDIS_COMMAND_ARGV_FILL("STREAM", 6) + SW_REDIS_COMMAND_ARGV_FILL(key, key_len) + + redis_request(redis, argc, argv, argvlen, return_value); + + if (redis->compatibility_mode && ZVAL_IS_ARRAY(return_value)) { + swoole_redis_handle_assoc_array_result(return_value, true); + } +} + static void swoole_redis_coro_parse_result(RedisClient *redis, zval *return_value, redisReply *reply) { int j; zval _val, *val = &_val; diff --git a/tests/swoole_redis_coro/stream.phpt b/tests/swoole_redis_coro/stream.phpt new file mode 100644 index 00000000000..5ca85aa9fd5 --- /dev/null +++ b/tests/swoole_redis_coro/stream.phpt @@ -0,0 +1,122 @@ +--TEST-- +swoole_redis_coro: stream +--SKIPIF-- + +--FILE-- + SWOOLE_LOG_TRACE, 'trace_flags' => SWOOLE_TRACE_ALL]); + +Co\run(function() { + $redis = new Swoole\Coroutine\Redis(); + $redis->connect(REDIS_SERVER_HOST, REDIS_SERVER_PORT); + + $ret = $redis->del('mystream'); + + // xGroupCreate + $ret = $redis->xGroupCreate('mystream', 'group1', '0-0', true); + Assert::assert($ret == '1'); + + // xGroupCreateConsumer + $ret = $redis->xGroupCreateConsumer('mystream', 'group1', 'consumer1'); + Assert::assert($ret == '1'); + $ret = $redis->xGroupCreateConsumer('mystream', 'group1', 'consumer2'); + Assert::assert($ret == '1'); + + // xAdd + $ret = $redis->xAdd('mystream', '0-1', ['field'=>'111'], ['nomkstream'=>true, 'maxlen'=>['~', 5], 'limit'=>5]); + Assert::assert($ret == '0-1'); + $ret = $redis->xAdd('mystream', '0-2', ['field'=>'222'], ['nomkstream'=>false, 'minid'=>['~', '0-0'], 'limit'=>5]); + Assert::assert($ret == '0-2'); + $ret = $redis->xAdd('mystream', '0-3', ['field'=>'333'], ['maxlen'=>['=', 5]]); + Assert::assert($ret == '0-3'); + $ret = $redis->xAdd('mystream', '0-4', ['field'=>'444'], ['maxlen'=>5]); + Assert::assert($ret, '0-4'); + $ret = $redis->xAdd('mystream', '0-5', ['field'=>'555']); + Assert::assert($ret, '0-5'); + + // xLen + $ret = $redis->xLen('mystream'); + Assert::assert($ret == '5'); + + // xRead + $ret = $redis->xRead(['mystream'=>'0-3'], ['count'=>1, 'block'=>100]); + Assert::assert($ret[0][1][0][0] == '0-4'); + + // xRange + $ret = $redis->xRange('mystream', '0-2', '0-3', 1); + Assert::assert($ret[0][0] == '0-2'); + + // xRevRange + $ret = $redis->xRevRange('mystream', '+', '-', 1); + Assert::assert($ret[0][0] == '0-5'); + + // xReadGroup + $ret = $redis->xReadGroup('group1', 'consumer1', ['mystream' => '>'], ['count'=>1, 'block'=>100, 'noack'=>true]); + Assert::assert($ret[0][1][0][0] == '0-1'); + $ret = $redis->xReadGroup('group1', 'consumer1', ['mystream' => '>'], ['count'=>1, 'block'=>100, 'noack'=>false]); + Assert::assert($ret[0][1][0][0] == '0-2'); + $ret = $redis->xReadGroup('group1', 'consumer1', ['mystream' => '>'], ['count'=>1]); + Assert::assert($ret[0][1][0][0] == '0-3'); + + // xPending + $ret = $redis->xPending('mystream', 'group1', ['start'=>'-', 'end'=>'+', 'count'=>5]); + Assert::assert(count($ret) == 2); + Assert::assert($ret[0][0] == '0-2'); + Assert::assert($ret[1][0] == '0-3'); + + // xAck + $ret = $redis->xAck('mystream', 'group1', ['0-2']); + Assert::assert($ret == '1'); + + // xClaim + $ret = $redis->xClaim('mystream', 'group1', 'consumer2', 0, ['0-3']); + Assert::assert($ret[0][0] == '0-3'); + + // xInfoConsumers + $ret = $redis->xInfoConsumers('mystream', 'group1'); + Assert::assert($ret[1][3] == '1'); + + // xAutoClaim + $ret = $redis->xAutoClaim('mystream', 'group1', 'consumer1', 0, '0-3'); + Assert::assert($ret[1][0][0] == '0-3'); + + // xInfoGroups + $ret = $redis->xInfoGroups('mystream'); + Assert::assert($ret[0][1] == 'group1'); + Assert::assert($ret[0][5] == '1'); + + // xInfoStream + $ret = $redis->xInfoStream('mystream'); + Assert::assert($ret[1] == '5'); + + // xDel + $ret = $redis->xDel('mystream', '0-1', '0-2'); + Assert::assert($ret == '2'); + + // xTrim + $ret = $redis->xTrim('mystream', ['maxlen'=>1]); + Assert::assert($ret == '2'); + $ret = $redis->xTrim('mystream', ['minid'=>['~', '0'], 'limit'=>1]); + Assert::assert($ret == '0'); + + // xGroupSetId + $ret = $redis->xGroupSetId('mystream', 'group1', '0-1'); + Assert::assert($ret == '1'); + + // xGroupDelConsumer + $ret = $redis->xGroupDelConsumer('mystream', 'group1', 'consumer1'); + Assert::assert($ret == '1'); + + // xGroupDestroy + $ret = $redis->xGroupDestroy('mystream', 'group1'); + Assert::assert($ret == '1'); + + $ret = $redis->del('mystream'); + + echo "OK\n"; +}); +?> +--EXPECT-- +OK From e6b0cb666f297dc9e001f00552cd615a2927b7c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Tue, 14 Sep 2021 13:01:38 +0800 Subject: [PATCH 242/936] Refactor manager message box (#4403) * Refactor Manager Message Box * Refactor Manager Message Box, Improve defer_tasks * add tests * fix tests * fix tests[2] * fix tests[3] * fix tests[4] * fix tests[5] * fix tests[6] * Add core-tests * fix tests[7] --- CMakeLists.txt | 4 +- core-tests/src/coroutine/http_server.cpp | 2 +- core-tests/src/os/process_pool.cpp | 3 +- core-tests/src/reactor/defer_task.cpp | 67 ++++++++++ core-tests/src/server/server.cpp | 40 ++++-- ext-src/swoole_process_pool.cc | 2 +- ext-src/swoole_server.cc | 1 + include/swoole_api.h | 1 + include/swoole_process_pool.h | 17 +++ include/swoole_reactor.h | 25 +++- include/swoole_server.h | 25 ++-- src/os/process_pool.cc | 90 +++++++++++--- src/reactor/base.cc | 8 ++ src/reactor/epoll.cc | 4 +- src/server/manager.cc | 150 ++++++++++++++--------- src/server/master.cc | 95 ++++++++++---- src/server/reactor_process.cc | 18 +-- src/server/reactor_thread.cc | 27 ++-- src/server/task_worker.cc | 8 +- src/server/worker.cc | 15 +-- src/wrapper/event.cc | 4 + tests/swoole_server/command.phpt | 4 +- 22 files changed, 444 insertions(+), 166 deletions(-) create mode 100644 core-tests/src/reactor/defer_task.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 512c9bdb55f..db511c86491 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -139,6 +139,8 @@ target_link_libraries(co swoole) # ext-swoole file(GLOB ext_cxx_files ext-src/*.cc) set(ext_src_list ${ext_cxx_files} + thirdparty/php/curl/interface.cc + thirdparty/php/curl/multi.cc thirdparty/php/sockets/multicast.cc thirdparty/php/sockets/sendrecvmsg.cc thirdparty/php/sockets/conversions.cc @@ -161,7 +163,7 @@ add_dependencies(ext-swoole lib-swoole) target_link_libraries(ext-swoole swoole) -#install +# install INSTALL(CODE "MESSAGE(\"Are you run command using root user?\")") INSTALL(TARGETS ext-swoole LIBRARY DESTINATION ${PHP_EXTENSION_DIR}) INSTALL(TARGETS lib-swoole LIBRARY DESTINATION lib ARCHIVE DESTINATION lib) diff --git a/core-tests/src/coroutine/http_server.cpp b/core-tests/src/coroutine/http_server.cpp index 9932df92d20..c77e71da986 100644 --- a/core-tests/src/coroutine/http_server.cpp +++ b/core-tests/src/coroutine/http_server.cpp @@ -53,7 +53,7 @@ TEST(coroutine_http_server, get) { svr.BeforeListen([&lock]() { lock.unlock(); }); - svr.listen(TEST_HOST, 8080); + ASSERT_TRUE(svr.listen(TEST_HOST, 8080)); }); t1.join(); diff --git a/core-tests/src/os/process_pool.cpp b/core-tests/src/os/process_pool.cpp index 75d5cbb29bb..87413f3c8a2 100644 --- a/core-tests/src/os/process_pool.cpp +++ b/core-tests/src/os/process_pool.cpp @@ -38,8 +38,7 @@ TEST(process_pool, tcp) { TEST(process_pool, unix_sock) { ProcessPool pool{}; signal(SIGPIPE, SIG_IGN); - ASSERT_EQ(pool.create(1, 0, SW_IPC_SOCKET), SW_OK); - ASSERT_EQ(pool.listen(TEST_TMP_FILE, 128), SW_OK); + ASSERT_EQ(pool.create(1, 0, SW_IPC_UNIXSOCK), SW_OK); test_func(pool); } diff --git a/core-tests/src/reactor/defer_task.cpp b/core-tests/src/reactor/defer_task.cpp new file mode 100644 index 00000000000..7fc823daa32 --- /dev/null +++ b/core-tests/src/reactor/defer_task.cpp @@ -0,0 +1,67 @@ +/* + +----------------------------------------------------------------------+ + | 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. | + +----------------------------------------------------------------------+ + | @link https://www.swoole.com/ | + | @contact team@swoole.com | + | @license https://github.com/swoole/swoole-src/blob/master/LICENSE | + | @author Tianfeng Han | + +----------------------------------------------------------------------+ +*/ + +#include "test_core.h" +#include "swoole_pipe.h" + +using namespace swoole; + +TEST(defer_task, defer) { + swoole_event_init(SW_EVENTLOOP_WAIT_EXIT); + Reactor *reactor = sw_reactor(); + ASSERT_EQ(reactor->max_event_num, SW_REACTOR_MAXEVENTS); + + int count = 0; + reactor->defer([&count](void *) { count++; }); + swoole_event_wait(); + ASSERT_EQ(count, 1); + swoole_event_free(); +} + +TEST(defer_task, cancel_1) { + swoole_event_init(SW_EVENTLOOP_WAIT_EXIT); + Reactor *reactor = sw_reactor(); + ASSERT_EQ(reactor->max_event_num, SW_REACTOR_MAXEVENTS); + + int count = 0; + reactor->defer([&count](void *) { count += 2; }); + auto iter = reactor->get_last_defer_task(); + reactor->remove_defer_task(iter); + + reactor->defer([&count](void *) { count += 5; }); + + swoole_event_wait(); + ASSERT_EQ(count, 5); + swoole_event_free(); +} + +TEST(defer_task, cancel_2) { + swoole_event_init(SW_EVENTLOOP_WAIT_EXIT); + Reactor *reactor = sw_reactor(); + ASSERT_EQ(reactor->max_event_num, SW_REACTOR_MAXEVENTS); + + int count = 0; + reactor->defer([&count](void *) { count += 2; }); + auto iter = reactor->get_last_defer_task(); + reactor->remove_defer_task(iter); + + swoole_event_wait(); + ASSERT_EQ(count, 0); + swoole_event_free(); +} diff --git a/core-tests/src/server/server.cpp b/core-tests/src/server/server.cpp index 1d357428ad7..97f6b4890cb 100644 --- a/core-tests/src/server/server.cpp +++ b/core-tests/src/server/server.cpp @@ -406,9 +406,10 @@ TEST(server, reactor_num_zero) { ASSERT_EQ(serv.reactor_num, SW_CPU_NUM); } -TEST(server, command) { - Server serv(Server::MODE_PROCESS); +void test_command(enum Server::Mode _mode) { + Server serv(_mode); serv.worker_num = 4; + serv.task_worker_num = 4; serv.reactor_num = 2; SwooleG.running = 1; @@ -428,23 +429,36 @@ TEST(server, command) { }); serv.onStart = [](Server *serv) { - static Server::Command::Callback fn = [](Server *serv, const std::string &msg) { - if (msg == "json result, hello world [1]") { + static Server::Command::Callback fn = [&](Server *serv, const std::string &msg) { + usleep(50000); + if (msg == "json result, hello world [0]") { + if (serv->is_base_mode()) { + goto _send_to_event_worker; + } else { + serv->command(1, Server::Command::REACTOR_THREAD, "test", "hello world [1]", fn); + } + } else if (msg == "json result, hello world [1]") { + _send_to_event_worker: serv->command(1, Server::Command::EVENT_WORKER, "test", "hello world [2]", fn); } else if (msg == "json result, hello world [2]") { - swoole_timer_after(50, [serv](Timer *, TimerNode *) { - serv->shutdown(); - }); + serv->command(1, Server::Command::TASK_WORKER, "test", "hello world [3]", fn); + } else if (msg == "json result, hello world [3]") { + serv->command(1, Server::Command::MANAGER, "test", "hello world [4]", fn); + } else if (msg == "json result, hello world [4]") { + swoole_timer_after(50, [serv](Timer *, TimerNode *) { serv->shutdown(); }); + } else { + ASSERT_TRUE(0); } }; - - serv->command(1, Server::Command::REACTOR_THREAD, "test", "hello world [1]", fn); + serv->command(1, Server::Command::MASTER, "test", "hello world [0]", fn); }; serv.onWorkerStart = [](Server *serv, int worker_id) { }; + serv.onTask = [](Server *, EventData *) -> int { return SW_OK; }; + serv.onReceive = [](Server *serv, RecvData *req) -> int { EXPECT_EQ(string(req->data, req->info.len), string(packet)); @@ -456,3 +470,11 @@ TEST(server, command) { ASSERT_EQ(serv.start(), 0); } + +TEST(server, command_1) { + test_command(Server::MODE_PROCESS); +} + +TEST(server, command_2) { + test_command(Server::MODE_BASE); +} diff --git a/ext-src/swoole_process_pool.cc b/ext-src/swoole_process_pool.cc index 41d0e59ad63..70e897b2024 100644 --- a/ext-src/swoole_process_pool.cc +++ b/ext-src/swoole_process_pool.cc @@ -274,7 +274,7 @@ static void pool_signal_handler(int sig) { break; case SIGUSR1: case SIGUSR2: - current_pool->reloading = true; + current_pool->reload(); current_pool->reload_init = false; break; case SIGIO: diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 3f743f2632d..d54a984601d 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -761,6 +761,7 @@ void php_swoole_server_minit(int module_number) { SW_REGISTER_LONG_CONSTANT("SWOOLE_IPC_PREEMPTIVE", Server::TASK_IPC_PREEMPTIVE); SW_REGISTER_LONG_CONSTANT("SWOOLE_SERVER_COMMAND_MASTER", Server::Command::MASTER); + SW_REGISTER_LONG_CONSTANT("SWOOLE_SERVER_COMMAND_MANAGER", Server::Command::MANAGER); SW_REGISTER_LONG_CONSTANT("SWOOLE_SERVER_COMMAND_REACTOR_THREAD", Server::Command::REACTOR_THREAD); SW_REGISTER_LONG_CONSTANT("SWOOLE_SERVER_COMMAND_EVENT_WORKER", Server::Command::EVENT_WORKER); SW_REGISTER_LONG_CONSTANT("SWOOLE_SERVER_COMMAND_WORKER", Server::Command::EVENT_WORKER); diff --git a/include/swoole_api.h b/include/swoole_api.h index 2e354c52963..827ab46fad0 100644 --- a/include/swoole_api.h +++ b/include/swoole_api.h @@ -46,6 +46,7 @@ SW_API int swoole_event_del(swoole::network::Socket *socket); SW_API void swoole_event_defer(swoole::Callback cb, void *private_data); SW_API ssize_t swoole_event_write(swoole::network::Socket *socket, const void *data, size_t len); SW_API ssize_t swoole_event_writev(swoole::network::Socket *socket, const iovec *iov, size_t iovcnt); +SW_API swoole::network::Socket *swoole_event_get_socket(int fd); SW_API int swoole_event_wait(); SW_API int swoole_event_free(); SW_API bool swoole_event_set_handler(int fdtype, swoole::ReactorHandler handler); diff --git a/include/swoole_process_pool.h b/include/swoole_process_pool.h index 56b635598d7..10c086d1593 100644 --- a/include/swoole_process_pool.h +++ b/include/swoole_process_pool.h @@ -42,6 +42,15 @@ enum swIPCMode { namespace swoole { +enum WorkerMessageType { + SW_WORKER_MESSAGE_STOP = 1, +}; + +struct WorkerStopMessage { + pid_t pid; + uint16_t worker_id; +}; + class ExitStatus { private: pid_t pid_; @@ -185,6 +194,8 @@ struct ProcessPool { pid_t master_pid; uint32_t reload_worker_i; uint32_t max_wait_time; + uint64_t reload_count; + time_t reload_last_time; Worker *reload_workers; /** @@ -229,6 +240,7 @@ struct ProcessPool { void (*onWorkerStart)(ProcessPool *pool, int worker_id); void (*onMessage)(ProcessPool *pool, const char *data, uint32_t length); void (*onWorkerStop)(ProcessPool *pool, int worker_id); + void (*onWorkerMessage)(ProcessPool *pool, EventData *msg); int (*onWorkerNotFound)(ProcessPool *pool, const ExitStatus &exit_status); int (*main_loop)(ProcessPool *pool, Worker *worker); @@ -279,6 +291,7 @@ struct ProcessPool { int wait(); int start(); void shutdown(); + bool reload(); pid_t spawn(Worker *worker); int dispatch(EventData *data, int *worker_id); int response(const char *data, int length); @@ -288,6 +301,10 @@ struct ProcessPool { int del_worker(Worker *worker); void destroy(); int create(uint32_t worker_num, key_t msgqueue_key = 0, swIPCMode ipc_mode = SW_IPC_NONE); + int create_message_box(size_t memory_size); + int push_message(uint8_t type, const void *data, size_t length); + int push_message(EventData *msg); + int pop_message(void *data, size_t size); int listen(const char *socket_file, int blacklog); int listen(const char *host, int port, int blacklog); int schedule(); diff --git a/include/swoole_reactor.h b/include/swoole_reactor.h index 08a8dbd9108..131aa1bc70e 100644 --- a/include/swoole_reactor.h +++ b/include/swoole_reactor.h @@ -52,13 +52,24 @@ class ReactorImpl { class CallbackManager { public: - inline void append(Callback fn, void *private_data) { + typedef std::list> TaskList; + void append(Callback fn, void *private_data) { list_.emplace_back(fn, private_data); } - inline void prepend(Callback fn, void *private_data) { + void prepend(Callback fn, void *private_data) { list_.emplace_front(fn, private_data); + auto t = list_.back(); } - inline void execute() { + TaskList::iterator back_position() { + return std::prev(list_.end()); + } + TaskList::iterator front_position() { + return list_.begin(); + } + void remove(TaskList::iterator iter) { + list_.erase(iter); + } + void execute() { while (!list_.empty()) { std::pair task = list_.front(); list_.pop_front(); @@ -67,7 +78,7 @@ class CallbackManager { } protected: - std::list> list_; + TaskList list_; }; class Reactor { @@ -183,6 +194,8 @@ class Reactor { ~Reactor(); bool if_exit(); void defer(Callback cb, void *data = nullptr); + CallbackManager::TaskList::iterator get_last_defer_task(); + void remove_defer_task(CallbackManager::TaskList::iterator iter); void set_end_callback(enum EndCallback id, const std::function &fn); void set_exit_condition(enum ExitCondition id, const std::function &fn); bool set_handler(int _fdtype, ReactorHandler handler); @@ -272,6 +285,10 @@ class Reactor { return sockets_; } + network::Socket *get_socket(int fd) { + return sockets_[fd]; + } + void foreach_socket(const std::function &callback) { for (auto kv : sockets_) { callback(kv.first, kv.second); diff --git a/include/swoole_server.h b/include/swoole_server.h index 053f5315267..32f390d618b 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -142,11 +142,6 @@ struct Connection { sw_atomic_t lock; }; -struct WorkerStopMessage { - pid_t pid; - uint16_t worker_id; -}; - struct SendData { DataHead info; const char *data; @@ -318,6 +313,7 @@ struct ReactorThread { std::thread thread; network::Socket *notify_pipe = nullptr; uint32_t pipe_num = 0; + uint64_t dispatch_count = 0; network::Socket *pipe_sockets = nullptr; network::Socket *pipe_command = nullptr; MessageBus message_bus; @@ -525,6 +521,11 @@ struct ServerGS { sw_atomic_t spinlock; +#ifdef HAVE_PTHREAD_BARRIER + pthread_barrier_t manager_barrier; + pthread_barrierattr_t manager_barrier_attr; +#endif + ProcessPool task_workers; ProcessPool event_workers; }; @@ -598,7 +599,8 @@ enum ServerEventType { // process message SW_SERVER_EVENT_INCOMING, SW_SERVER_EVENT_SHUTDOWN, - SW_SERVER_EVENT_COMMAND, + SW_SERVER_EVENT_COMMAND_REQUEST, + SW_SERVER_EVENT_COMMAND_RESPONSE, }; class Server { @@ -613,7 +615,8 @@ class Server { REACTOR_THREAD = 1u << 2, EVENT_WORKER = 1u << 3, TASK_WORKER = 1u << 4, - ALL_PROCESS = MASTER | REACTOR_THREAD | EVENT_WORKER | TASK_WORKER, + MANAGER = 1u << 5, + ALL_PROCESS = MASTER | REACTOR_THREAD | EVENT_WORKER | TASK_WORKER | MANAGER, }; int id; int accepted_process_types; @@ -900,6 +903,10 @@ class Server { return &get_thread(SwooleTG.id)->pipe_sockets[worker->pipe_master->fd]; } + network::Socket *get_command_reply_socket() { + return is_base_mode() ? get_worker(0)->pipe_master : pipe_command->get_socket(false); + } + /** * [Worker|Master] */ @@ -937,7 +944,6 @@ class Server { int64_t command_current_request_id = 1; Worker *workers = nullptr; - Channel *message_box = nullptr; ServerGS *gs = nullptr; std::unordered_set *types = nullptr; @@ -945,7 +951,7 @@ class Server { std::vector *http_index_files = nullptr; #ifdef HAVE_PTHREAD_BARRIER - pthread_barrier_t barrier = {}; + pthread_barrier_t reactor_thread_barrier = {}; #endif /** @@ -1437,6 +1443,7 @@ class Server { void kill_task_workers(); static int wait_other_worker(ProcessPool *pool, const ExitStatus &exit_status); + static void read_worker_message(ProcessPool *pool, EventData *msg); void drain_worker_pipe(); diff --git a/src/os/process_pool.cc b/src/os/process_pool.cc index d9e85176e6a..0cd02e70a80 100644 --- a/src/os/process_pool.cc +++ b/src/os/process_pool.cc @@ -52,7 +52,8 @@ void ProcessPool::kill_timeout_worker(Timer *timer, TimerNode *tnode) { continue; } if (swoole_kill(reload_worker_pid, SIGKILL) < 0) { - swoole_sys_warning("failed to force kill worker process(pid=%d, id=%d)", pool->reload_workers[i].pid, i); + swoole_sys_warning( + "failed to force kill worker process(pid=%d, id=%d)", pool->reload_workers[i].pid, i); } else { swoole_warning("force kill worker process(pid=%d, id=%d)", pool->reload_workers[i].pid, i); } @@ -62,6 +63,7 @@ void ProcessPool::kill_timeout_worker(Timer *timer, TimerNode *tnode) { pool->reload_worker_i = 0; pool->reload_init = false; } + /** * Process manager */ @@ -76,8 +78,7 @@ int ProcessPool::create(uint32_t _worker_num, key_t _msgqueue_key, swIPCMode _ip return SW_ERR; } - message_box = Channel::make(65536, sizeof(WorkerStopMessage), SW_CHAN_LOCK | SW_CHAN_SHM); - if (message_box == nullptr) { + if (create_message_box(65536) < 0) { return SW_ERR; } @@ -126,6 +127,14 @@ int ProcessPool::create(uint32_t _worker_num, key_t _msgqueue_key, swIPCMode _ip return SW_OK; } +int ProcessPool::create_message_box(size_t memory_size) { + message_box = Channel::make(memory_size, sizeof(EventData), SW_CHAN_LOCK | SW_CHAN_SHM); + if (message_box == nullptr) { + return SW_ERR; + } + return SW_OK; +} + int ProcessPool::listen(const char *socket_file, int blacklog) { if (ipc_mode != SW_IPC_SOCKET) { swoole_warning("ipc_mode is not SW_IPC_SOCKET"); @@ -219,6 +228,36 @@ int ProcessPool::response(const char *data, int length) { return stream_info_->response_buffer->append(data, length); } +int ProcessPool::push_message(EventData *msg) { + if (message_box->push(msg, sizeof(msg->info) + msg->info.len) < 0) { + return SW_ERR; + } + return swoole_kill(master_pid, SIGIO); +} + +int ProcessPool::push_message(uint8_t type, const void *data, size_t length) { + if (!message_box) { + return SW_ERR; + } + + EventData msg; + assert(length < sizeof(msg.data)); + + msg.info = {}; + msg.info.type = type; + msg.info.len = length; + memcpy(msg.data, data, length); + + return push_message(&msg); +} + +int ProcessPool::pop_message(void *data, size_t size) { + if (!message_box) { + return SW_ERR; + } + return message_box->pop(data, size); +} + /** * dispatch data to worker */ @@ -309,6 +348,16 @@ int ProcessPool::dispatch_blocking(EventData *data, int *dst_worker_id) { return ret > 0 ? SW_OK : SW_ERR; } +bool ProcessPool::reload() { + if (reloading) { + return false; + } + reloading = true; + reload_count++; + reload_last_time = ::time(NULL); + return true; +} + void ProcessPool::shutdown() { uint32_t i; int status; @@ -465,8 +514,8 @@ static int ProcessPool_worker_loop(ProcessPool *pool, Worker *worker) { if (n != (ssize_t)(out.buf.info.len + sizeof(out.buf.info))) { swoole_warning("bad task packet, The received data-length[%ld] is inconsistent with the packet-length[%ld]", - n, - out.buf.info.len + sizeof(out.buf.info)); + n, + out.buf.info.len + sizeof(out.buf.info)); continue; } @@ -610,7 +659,7 @@ int ProcessPool_add_worker(ProcessPool *pool, Worker *worker) { } bool ProcessPool::detach() { - if (!running) { + if (!running || !message_box) { return false; } @@ -618,10 +667,7 @@ bool ProcessPool::detach() { msg.pid = getpid(); msg.worker_id = SwooleG.process_id; - if (message_box && message_box->push(&msg, sizeof(msg)) < 0) { - return false; - } - if (swoole_kill(master_pid, SIGIO) < 0) { + if (push_message(SW_WORKER_MESSAGE_STOP, &msg, sizeof(msg)) < 0) { return false; } running = false; @@ -647,12 +693,18 @@ int ProcessPool::wait() { SwooleTG.timer->select(); } if (read_message) { - WorkerStopMessage msg; - while (message_box->pop(&msg, sizeof(msg)) > 0) { + EventData msg; + while (pop_message(&msg, sizeof(msg)) > 0) { if (!running) { continue; } - Worker *exit_worker = get_worker_by_pid(msg.pid); + if (msg.info.type != SW_WORKER_MESSAGE_STOP && onWorkerMessage) { + onWorkerMessage(this, &msg); + continue; + } + WorkerStopMessage worker_stop_msg; + memcpy(&worker_stop_msg, msg.data, sizeof(worker_stop_msg)); + Worker *exit_worker = get_worker_by_pid(worker_stop_msg.pid); if (exit_worker == nullptr) { continue; } @@ -661,7 +713,7 @@ int ProcessPool::wait() { swoole_sys_warning("fork worker process failed"); return SW_ERR; } - map_->erase(msg.pid); + map_->erase(worker_stop_msg.pid); } read_message = false; } @@ -700,11 +752,11 @@ int ProcessPool::wait() { if (!exit_status.is_normal_exit()) { swoole_warning("worker#%d abnormal exit, status=%d, signal=%d" - "%s", - exit_worker->id, - exit_status.get_code(), - exit_status.get_signal(), - exit_status.get_signal() == SIGSEGV ? SwooleG.bug_report_message.c_str() : ""); + "%s", + exit_worker->id, + exit_status.get_code(), + exit_status.get_signal(), + exit_status.get_signal() == SIGSEGV ? SwooleG.bug_report_message.c_str() : ""); } new_pid = spawn(exit_worker); if (new_pid < 0) { diff --git a/src/reactor/base.cc b/src/reactor/base.cc index d4be6cba97e..9d6fdaddc06 100644 --- a/src/reactor/base.cc +++ b/src/reactor/base.cc @@ -394,6 +394,14 @@ void Reactor::defer(Callback cb, void *data) { defer_tasks->append(cb, data); } +CallbackManager::TaskList::iterator Reactor::get_last_defer_task() { + return defer_tasks->back_position(); +} + +void Reactor::remove_defer_task(CallbackManager::TaskList::iterator iter) { + defer_tasks->remove(iter); +} + void Reactor::execute_end_callbacks(bool timedout) { for (auto &kv : end_callbacks) { kv.second(this); diff --git a/src/reactor/epoll.cc b/src/reactor/epoll.cc index 899433f6ace..9beb4c89e94 100644 --- a/src/reactor/epoll.cc +++ b/src/reactor/epoll.cc @@ -114,8 +114,8 @@ int ReactorEpoll::del(Socket *_socket) { if (_socket->removed) { swoole_error_log(SW_LOG_WARNING, SW_ERROR_EVENT_SOCKET_REMOVED, - "failed to delete events[%d], it has already been removed", - _socket->fd); + "failed to delete events[fd=%d, fd_type=%d], it has already been removed", + _socket->fd, _socket->fd_type); return SW_ERR; } if (epoll_ctl(epfd_, EPOLL_CTL_DEL, _socket->fd, nullptr) < 0) { diff --git a/src/server/manager.cc b/src/server/manager.cc index 7184b9d7b4c..3879c7662a0 100644 --- a/src/server/manager.cc +++ b/src/server/manager.cc @@ -31,16 +31,11 @@ namespace swoole { using ReloadWorkerList = std::unordered_map; struct Manager { - bool reloading; bool reload_all_worker; bool reload_task_worker; - bool reload_init; - bool read_message; bool force_kill; - uint32_t reload_worker_i; uint32_t reload_worker_num; pid_t reload_worker_pid; - Worker *reload_workers; Server *server_; std::vector kill_workers; @@ -134,8 +129,7 @@ int Server::start_manager_process() { } } - message_box = Channel::make(65536, sizeof(WorkerStopMessage), SW_CHAN_LOCK | SW_CHAN_SHM); - if (message_box == nullptr) { + if (gs->event_workers.create_message_box(65536) == SW_ERR) { return SW_ERR; } @@ -144,7 +138,6 @@ int Server::start_manager_process() { // fork manager process case 0: { // wait master process - SW_START_SLEEP; if (!is_started()) { swoole_error("master process is not running"); return SW_ERR; @@ -192,7 +185,7 @@ int Server::start_manager_process() { } // master process default: - gs->manager_pid = pid; + gs->event_workers.master_pid = gs->manager_pid = pid; break; case -1: swoole_error("fork() failed"); @@ -204,12 +197,12 @@ int Server::start_manager_process() { void Server::check_worker_exit_status(int worker_id, const ExitStatus &exit_status) { if (exit_status.get_status() != 0) { swoole_warning("worker(pid=%d, id=%d) abnormal exit, status=%d, signal=%d" - "%s", - exit_status.get_pid(), - worker_id, - exit_status.get_code(), - exit_status.get_signal(), - exit_status.get_signal() == SIGSEGV ? SwooleG.bug_report_message.c_str() : ""); + "%s", + exit_status.get_pid(), + worker_id, + exit_status.get_code(), + exit_status.get_signal(), + exit_status.get_signal() == SIGSEGV ? SwooleG.bug_report_message.c_str() : ""); if (onWorkerError != nullptr) { onWorkerError(this, worker_id, exit_status); @@ -221,13 +214,16 @@ void Manager::start(Server *_server) { server_ = _server; server_->manager = this; + ProcessPool *pool = &server_->gs->event_workers; + pool->onWorkerMessage = Server::read_worker_message; + SwooleG.use_signalfd = 0; SwooleTG.reactor = nullptr; - reload_workers = new Worker[_server->worker_num + _server->task_worker_num]; + pool->reload_workers = new Worker[_server->worker_num + _server->task_worker_num]; ON_SCOPE_EXIT { - delete[] reload_workers; - reload_workers = nullptr; + delete[] pool->reload_workers; + pool->reload_workers = nullptr; server_->manager = nullptr; }; @@ -250,6 +246,12 @@ void Manager::start(Server *_server) { procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &sigid); #endif +#ifdef HAVE_PTHREAD_BARRIER + pthread_barrier_wait(&_server->gs->manager_barrier); +#else + SW_START_SLEEP; +#endif + if (_server->hooks[Server::HOOK_MANAGER_START]) { _server->call_hook(Server::HOOK_MANAGER_START, _server); } @@ -265,23 +267,29 @@ void Manager::start(Server *_server) { while (_server->running) { ExitStatus exit_status = wait_process(); - if (read_message) { - WorkerStopMessage msg; - while (_server->message_box->pop(&msg, sizeof(msg)) > 0) { + if (pool->read_message) { + EventData msg; + while (pool->pop_message(&msg, sizeof(msg)) > 0) { if (!_server->running) { continue; } - if (msg.worker_id >= _server->worker_num) { - _server->spawn_task_worker(_server->get_worker(msg.worker_id)); + if (msg.info.type != SW_WORKER_MESSAGE_STOP && pool->onWorkerMessage) { + pool->onWorkerMessage(pool, &msg); + continue; + } + WorkerStopMessage worker_stop_msg; + memcpy(&worker_stop_msg, msg.data, sizeof(worker_stop_msg)); + if (worker_stop_msg.worker_id >= _server->worker_num) { + _server->spawn_task_worker(_server->get_worker(worker_stop_msg.worker_id)); } else { - Worker *worker = _server->get_worker(msg.worker_id); + Worker *worker = _server->get_worker(worker_stop_msg.worker_id); pid_t new_pid = _server->spawn_event_worker(worker); if (new_pid > 0) { worker->pid = new_pid; } } } - read_message = false; + pool->read_message = false; } if (SwooleG.signal_alarm && SwooleTG.timer) { @@ -290,7 +298,7 @@ void Manager::start(Server *_server) { } if (exit_status.get_pid() < 0) { - if (!reloading) { + if (!pool->reloading) { _error: if (errno > 0 && errno != EINTR) { swoole_sys_warning("wait() failed"); @@ -303,15 +311,15 @@ void Manager::start(Server *_server) { if (_server->onBeforeReload != nullptr) { _server->onBeforeReload(_server); } - if (!reload_init) { - reload_init = true; - memcpy(reload_workers, _server->workers, sizeof(Worker) * _server->worker_num); + if (!pool->reload_init) { + pool->reload_init = true; + memcpy(pool->reload_workers, _server->workers, sizeof(Worker) * _server->worker_num); add_timeout_killer(_server->workers, _server->worker_num); reload_worker_num = _server->worker_num; if (_server->task_worker_num > 0) { - memcpy(reload_workers + _server->worker_num, + memcpy(pool->reload_workers + _server->worker_num, _server->gs->task_workers.workers, sizeof(Worker) * _server->task_worker_num); reload_worker_num += _server->task_worker_num; @@ -322,13 +330,13 @@ void Manager::start(Server *_server) { reload_all_worker = false; if (_server->reload_async) { SW_LOOP_N(_server->worker_num) { - if (swoole_kill(reload_workers[i].pid, SIGTERM) < 0) { - swoole_sys_warning("swKill(%d, SIGTERM) [%d] failed", reload_workers[i].pid, i); + if (swoole_kill(pool->reload_workers[i].pid, SIGTERM) < 0) { + swoole_sys_warning("swKill(%d, SIGTERM) [%d] failed", pool->reload_workers[i].pid, i); } } - reload_worker_i = _server->worker_num; + pool->reload_worker_i = _server->worker_num; } else { - reload_worker_i = 0; + pool->reload_worker_i = 0; } } goto _kill_worker; @@ -337,20 +345,21 @@ void Manager::start(Server *_server) { else if (reload_task_worker) { if (_server->task_worker_num == 0) { swoole_warning("cannot reload task workers, task workers is not started"); - reloading = false; + pool->reloading = false; continue; } swoole_info("Server is reloading task workers now"); if (_server->onBeforeReload != nullptr) { _server->onBeforeReload(_server); } - if (!reload_init) { - memcpy( - reload_workers, _server->gs->task_workers.workers, sizeof(Worker) * _server->task_worker_num); + if (!pool->reload_init) { + memcpy(pool->reload_workers, + _server->gs->task_workers.workers, + sizeof(Worker) * _server->task_worker_num); add_timeout_killer(_server->gs->task_workers.workers, _server->task_worker_num); reload_worker_num = _server->task_worker_num; - reload_worker_i = 0; - reload_init = true; + pool->reload_worker_i = 0; + pool->reload_init = true; reload_task_worker = false; } goto _kill_worker; @@ -394,30 +403,31 @@ void Manager::start(Server *_server) { if (!_server->user_worker_map.empty()) { Server::wait_other_worker(&_server->gs->event_workers, exit_status); } - if (exit_status.get_pid() == reload_worker_pid && reloading) { - reload_worker_i++; + if (exit_status.get_pid() == reload_worker_pid && pool->reloading) { + pool->reload_worker_i++; } } // reload worker _kill_worker: - if (reloading) { + if (pool->reloading) { // reload finish - if (reload_worker_i >= reload_worker_num) { - reload_worker_pid = reload_worker_i = 0; - reload_init = reloading = false; + if (pool->reload_worker_i >= reload_worker_num) { + reload_worker_pid = pool->reload_worker_i = 0; + pool->reload_init = pool->reloading = false; if (_server->onAfterReload != nullptr) { _server->onAfterReload(_server); } continue; } - reload_worker_pid = reload_workers[reload_worker_i].pid; + reload_worker_pid = pool->reload_workers[pool->reload_worker_i].pid; if (swoole_kill(reload_worker_pid, SIGTERM) < 0) { if (errno == ECHILD || errno == ESRCH) { - reload_worker_i++; + pool->reload_worker_i++; goto _kill_worker; } - swoole_sys_warning( - "swKill(%d, SIGTERM) [%d] failed", reload_workers[reload_worker_i].pid, reload_worker_i); + swoole_sys_warning("kill(%d, SIGTERM) [%d] failed", + pool->reload_workers[pool->reload_worker_i].pid, + pool->reload_worker_i); } } } @@ -464,6 +474,7 @@ void Manager::signal_handler(int sig) { return; } Manager *manager = _server->manager; + ProcessPool *pool = &_server->gs->event_workers; switch (sig) { case SIGTERM: @@ -473,8 +484,7 @@ void Manager::signal_handler(int sig) { * reload all workers */ case SIGUSR1: - if (!manager->reloading) { - manager->reloading = true; + if (pool->reload()) { manager->reload_all_worker = true; } sw_logger()->reopen(); @@ -483,14 +493,13 @@ void Manager::signal_handler(int sig) { * only reload task workers */ case SIGUSR2: - if (!manager->reloading) { - manager->reloading = true; + if (pool->reload()) { manager->reload_task_worker = true; } sw_logger()->reopen(); break; case SIGIO: - manager->read_message = true; + pool->read_message = true; break; case SIGALRM: SwooleG.signal_alarm = 1; @@ -558,6 +567,37 @@ int Server::wait_other_worker(ProcessPool *pool, const ExitStatus &exit_status) return new_process_pid; } +/** + * [manager] + */ +void Server::read_worker_message(ProcessPool *pool, EventData *msg) { + if (msg->info.type != SW_SERVER_EVENT_COMMAND_REQUEST) { + swoole_warning("unknown worker message type[%d]", msg->info.type); + return; + } + + Server *serv = (Server *) pool->ptr; + int command_id = msg->info.server_fd; + auto iter = serv->command_handlers.find(command_id); + if (iter == serv->command_handlers.end()) { + swoole_error_log(SW_LOG_ERROR, SW_ERROR_SERVER_INVALID_COMMAND, "Unknown command[command_id=%d]", command_id); + return; + } + + Server::Command::Handler handler = iter->second; + auto result = handler(serv, std::string(msg->data, msg->info.len)); + + SendData task{}; + task.info.fd = msg->info.fd; + task.info.reactor_id = 0; + task.info.server_fd = -1; + task.info.type = SW_SERVER_EVENT_COMMAND_RESPONSE; + task.info.len = result.length(); + task.data = result.c_str(); + + serv->message_bus.write(serv->get_command_reply_socket(), &task); +} + /** * kill and wait all user process */ diff --git a/src/server/master.cc b/src/server/master.cc index 67db43fba42..876265059a3 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -108,7 +108,7 @@ ResultCode Server::call_command_handler(MessageBus &mb, uint16_t worker_id, Sock int command_id = buffer->info.server_fd; auto iter = command_handlers.find(command_id); if (iter == command_handlers.end()) { - swoole_error_log(SW_LOG_ERROR, SW_ERROR_SERVER_INVALID_COMMAND, "Unknown command[%d]", command_id); + swoole_error_log(SW_LOG_ERROR, SW_ERROR_SERVER_INVALID_COMMAND, "Unknown command[command_id=%d]", command_id); return SW_OK; } @@ -120,7 +120,7 @@ ResultCode Server::call_command_handler(MessageBus &mb, uint16_t worker_id, Sock task.info.fd = buffer->info.fd; task.info.reactor_id = worker_id; task.info.server_fd = -1; - task.info.type = SW_SERVER_EVENT_COMMAND; + task.info.type = SW_SERVER_EVENT_COMMAND_RESPONSE; task.info.len = result.length(); task.data = result.c_str(); @@ -432,23 +432,31 @@ int Server::start_master_thread() { reactor->ptr = this; reactor->set_handler(SW_FD_STREAM_SERVER, Server::accept_connection); - if (hooks[Server::HOOK_MASTER_START]) { - call_hook(Server::HOOK_MASTER_START, this); - } - if (pipe_command) { - reactor->set_handler(SW_FD_PIPE, Server::accept_command_result); + if (!single_thread) { + reactor->set_handler(SW_FD_PIPE, Server::accept_command_result); + } reactor->add(pipe_command->get_socket(true), SW_EVENT_READ); } - /** - * 1 second timer - */ if ((master_timer = swoole_timer_add(1000, true, Server::timer_callback, this)) == nullptr) { swoole_event_free(); return SW_ERR; } +#ifdef HAVE_PTHREAD_BARRIER + if (!single_thread) { + pthread_barrier_wait(&reactor_thread_barrier); + } + pthread_barrier_wait(&gs->manager_barrier); +#else + SW_START_SLEEP; +#endif + + if (hooks[Server::HOOK_MASTER_START]) { + call_hook(Server::HOOK_MASTER_START, this); + } + if (onStart) { onStart(this); } @@ -839,6 +847,14 @@ int Server::create() { retval = create_reactor_threads(); } +#ifdef HAVE_PTHREAD_BARRIER + if (is_process_mode()) { + pthread_barrier_init(&reactor_thread_barrier, nullptr, reactor_num + 1); + pthread_barrierattr_setpshared(&gs->manager_barrier_attr, PTHREAD_PROCESS_SHARED); + pthread_barrier_init(&gs->manager_barrier, &gs->manager_barrier_attr, 2); + } +#endif + if (swoole_isset_hook(SW_GLOBAL_HOOK_AFTER_SERVER_CREATE)) { swoole_call_hook(SW_GLOBAL_HOOK_AFTER_SERVER_CREATE, this); } @@ -959,7 +975,13 @@ void Server::destroy() { delete l; } } - +#ifdef HAVE_PTHREAD_BARRIER + if (is_process_mode()) { + pthread_barrier_destroy(&reactor_thread_barrier); + pthread_barrier_destroy(&gs->manager_barrier); + pthread_barrierattr_destroy(&gs->manager_barrier_attr); + } +#endif sw_shm_free(session_list); sw_shm_free(port_connnection_num_list); sw_shm_free(workers); @@ -1016,6 +1038,11 @@ bool Server::command(WorkerId process_id, process_type = Command::MASTER; } + if (is_process_mode() && process_type == Command::REACTOR_THREAD && process_id == reactor_num) { + process_type = Command::MASTER; + process_id = 0; + } + int command_id = iter->second.id; int64_t requset_id = command_current_request_id++; Socket *pipe_sock; @@ -1024,7 +1051,7 @@ bool Server::command(WorkerId process_id, task.info.fd = requset_id; task.info.reactor_id = process_id; task.info.server_fd = command_id; - task.info.type = SW_SERVER_EVENT_COMMAND; + task.info.type = SW_SERVER_EVENT_COMMAND_REQUEST; task.info.len = msg.length(); task.data = msg.c_str(); @@ -1049,14 +1076,6 @@ bool Server::command(WorkerId process_id, return false; } pipe_sock = get_worker(process_id)->pipe_master; - } else if (process_type == Command::MASTER) { - if (!(iter->second.accepted_process_types & Command::MASTER)) { - swoole_error_log(SW_LOG_NOTICE, SW_ERROR_OPERATION_NOT_SUPPORT, "unsupported"); - return false; - } - auto result = call_command_handler_in_master(command_id, msg); - fn(this, result); - return true; } else if (process_type == Command::TASK_WORKER) { if (process_id >= task_worker_num) { swoole_error_log(SW_LOG_NOTICE, SW_ERROR_INVALID_PARAMS, "invalid task_worker_id[%d]", process_id); @@ -1067,14 +1086,40 @@ bool Server::command(WorkerId process_id, if (!task_pack(&buf, msg.c_str(), msg.length())) { return false; } - buf.info.type = SW_SERVER_EVENT_COMMAND; + buf.info.type = SW_SERVER_EVENT_COMMAND_REQUEST; buf.info.fd = requset_id; buf.info.server_fd = command_id; - if (send_to_worker_from_worker(worker_num + process_id, &buf, SW_PIPE_MASTER | SW_PIPE_NONBLOCK) <= 0) { + int _dst_worker_id = process_id; + if (gs->task_workers.dispatch(&buf, &_dst_worker_id) <= 0) { return false; } command_callbacks[requset_id] = fn; return true; + } else if (process_type == Command::MANAGER) { + EventData buf; + if (msg.length() >= sizeof(buf.data)) { + swoole_error_log(SW_LOG_NOTICE, + SW_ERROR_DATA_LENGTH_TOO_LARGE, + "message is too large, maximum length is %lu, the given length is %lu", + sizeof(buf.data), + msg.length()); + return false; + } + memset(&buf.info, 0, sizeof(buf.info)); + buf.info.type = SW_SERVER_EVENT_COMMAND_REQUEST; + buf.info.fd = requset_id; + buf.info.server_fd = command_id; + buf.info.len = msg.length(); + memcpy(buf.data, msg.c_str(), msg.length()); + if (gs->event_workers.push_message(&buf) < 0) { + return false; + } + command_callbacks[requset_id] = fn; + return true; + } else if (process_type == Command::MASTER) { + auto result = call_command_handler_in_master(command_id, msg); + fn(this, result); + return true; } else { swoole_error_log(SW_LOG_NOTICE, SW_ERROR_OPERATION_NOT_SUPPORT, "unsupported [process_type]"); return false; @@ -1749,16 +1794,18 @@ static void Server_signal_handler(int sig) { case SIGUSR1: case SIGUSR2: if (serv->is_base_mode()) { - if (serv->gs->event_workers.reloading) { + if (!serv->gs->event_workers.reload()) { break; } - serv->gs->event_workers.reloading = true; serv->gs->event_workers.reload_init = false; } else { swoole_kill(serv->gs->manager_pid, sig); } sw_logger()->reopen(); break; + case SIGIO: + serv->gs->event_workers.read_message = true; + break; default: #ifdef SIGRTMIN diff --git a/src/server/reactor_process.cc b/src/server/reactor_process.cc index 167308c1871..78006dbac3b 100644 --- a/src/server/reactor_process.cc +++ b/src/server/reactor_process.cc @@ -157,6 +157,7 @@ int Server::start_reactor_processes() { */ SwooleG.use_signalfd = 0; + gs->event_workers.onWorkerMessage = read_worker_message; gs->event_workers.start(); init_signal_handler(); @@ -224,15 +225,14 @@ static int ReactorProcess_onPipeRead(Reactor *reactor, Event *event) { factory->end(pipe_buffer->info.fd, Server::CLOSE_ACTIVELY); break; } - case SW_SERVER_EVENT_COMMAND: { - WorkerId worker_id = SwooleWG.worker->id; - if (worker_id == 0) { - int64_t request_id = pipe_buffer->info.fd; - auto packet = serv->message_bus.get_packet(); - serv->call_command_callback(request_id, std::string(packet.data, packet.length)); - } else { - serv->call_command_handler(serv->message_bus, worker_id, serv->get_worker(0)->pipe_master); - } + case SW_SERVER_EVENT_COMMAND_REQUEST: { + serv->call_command_handler(serv->message_bus, SwooleWG.worker->id, serv->get_worker(0)->pipe_master); + break; + } + case SW_SERVER_EVENT_COMMAND_RESPONSE: { + int64_t request_id = pipe_buffer->info.fd; + auto packet = serv->message_bus.get_packet(); + serv->call_command_callback(request_id, std::string(packet.data, packet.length)); break; } default: diff --git a/src/server/reactor_thread.cc b/src/server/reactor_thread.cc index 1dda9e908ad..b8cf7a9bbe9 100644 --- a/src/server/reactor_thread.cc +++ b/src/server/reactor_thread.cc @@ -376,8 +376,12 @@ static int ReactorThread_onPipeRead(Reactor *reactor, Event *ev) { if (serv->connection_incoming(reactor, conn) < 0) { return reactor->close(reactor, conn->socket); } - } else if (resp->info.type == SW_SERVER_EVENT_COMMAND) { + } else if (resp->info.type == SW_SERVER_EVENT_COMMAND_REQUEST) { return serv->call_command_handler(thread->message_bus, thread->id, thread->pipe_command); + } else if (resp->info.type == SW_SERVER_EVENT_COMMAND_RESPONSE) { + auto packet = thread->message_bus.get_packet(); + serv->call_command_callback(resp->info.fd, std::string(packet.data, packet.length)); + return SW_OK; } /** * server shutdown @@ -716,19 +720,9 @@ int Server::start_reactor_threads() { SwooleTG.id = reactor_num; } -#ifdef HAVE_PTHREAD_BARRIER - // init thread barrier - pthread_barrier_init(&barrier, nullptr, reactor_num + 1); -#endif SW_LOOP_N(reactor_num) { get_thread(i)->thread = std::thread(ReactorThread_loop, this, i); } -#ifdef HAVE_PTHREAD_BARRIER - // wait reactor thread - pthread_barrier_wait(&barrier); -#else - SW_START_SLEEP; -#endif _init_master_thread: @@ -878,7 +872,7 @@ static void ReactorThread_loop(Server *serv, int reactor_id) { // wait other thread #ifdef HAVE_PTHREAD_BARRIER - pthread_barrier_wait(&serv->barrier); + pthread_barrier_wait(&serv->reactor_thread_barrier); #else SW_START_SLEEP; #endif @@ -926,6 +920,11 @@ int Server::dispatch_task(Protocol *proto, Socket *_socket, const char *data, ui task.info.type = SW_SERVER_EVENT_RECV_DATA; task.info.time = conn->last_recv_time; + if (serv->is_process_mode()) { + ReactorThread *thread = serv->get_thread(conn->reactor_id); + thread->dispatch_count++; + } + swoole_trace("send string package, size=%ld bytes", (long) length); if (serv->stream_socket_file) { @@ -1008,8 +1007,8 @@ void Server::destroy_reactor_threads() { sw_shm_free(connection_list); delete[] reactor_threads; - if (message_box) { - message_box->destroy(); + if (gs->event_workers.message_box) { + gs->event_workers.message_box->destroy(); } } diff --git a/src/server/task_worker.cc b/src/server/task_worker.cc index b075f408723..a5cfca046cd 100644 --- a/src/server/task_worker.cc +++ b/src/server/task_worker.cc @@ -71,13 +71,11 @@ static int TaskWorker_call_command_handler(ProcessPool *pool, EventData *req) { task.info.fd = req->info.fd; task.info.reactor_id = SwooleWG.worker->id; task.info.server_fd = -1; - task.info.type = SW_SERVER_EVENT_COMMAND; + task.info.type = SW_SERVER_EVENT_COMMAND_RESPONSE; task.info.len = result.length(); task.data = result.c_str(); - Socket *reply_sock = - serv->is_base_mode() ? serv->get_worker(0)->pipe_master : serv->pipe_command->get_socket(false); - return serv->message_bus.write(reply_sock, &task) ? SW_OK : SW_ERR; + return serv->message_bus.write(serv->get_command_reply_socket(), &task) ? SW_OK : SW_ERR; } static int TaskWorker_onTask(ProcessPool *pool, EventData *task) { @@ -87,7 +85,7 @@ static int TaskWorker_onTask(ProcessPool *pool, EventData *task) { if (task->info.type == SW_SERVER_EVENT_PIPE_MESSAGE) { serv->onPipeMessage(serv, task); - } else if (task->info.type == SW_SERVER_EVENT_COMMAND) { + } else if (task->info.type == SW_SERVER_EVENT_COMMAND_REQUEST) { ret = TaskWorker_call_command_handler(pool, task); } else { ret = serv->onTask(serv, task); diff --git a/src/server/worker.cc b/src/server/worker.cc index 04f36140d12..db86b05469b 100644 --- a/src/server/worker.cc +++ b/src/server/worker.cc @@ -285,7 +285,7 @@ void Server::worker_accept_event(DataHead *info) { onPipeMessage(this, (EventData *) message_bus.get_buffer()); break; } - case SW_SERVER_EVENT_COMMAND: { + case SW_SERVER_EVENT_COMMAND_REQUEST: { call_command_handler(message_bus, worker->id, pipe_command->get_socket(false)); break; } @@ -366,16 +366,16 @@ void Server::worker_start_callback() { SwooleWG.worker = get_worker(SwooleG.process_id); SwooleWG.worker->status = SW_WORKER_IDLE; - if (is_process_mode()) { - sw_shm_protect(session_list, PROT_READ); - } - #ifdef HAVE_SIGNALFD if (SwooleG.use_signalfd && SwooleTG.reactor && SwooleG.signal_fd == 0) { swoole_signalfd_setup(SwooleTG.reactor); } #endif + if (is_process_mode()) { + sw_shm_protect(session_list, PROT_READ); + } + call_worker_start_callback(SwooleWG.worker); } @@ -449,11 +449,8 @@ void Server::stop_async_worker(Worker *worker) { msg.pid = SwooleG.pid; msg.worker_id = SwooleG.process_id; - // send message to manager - if (message_box && message_box->push(&msg, sizeof(msg)) < 0) { + if (gs->event_workers.push_message(SW_WORKER_MESSAGE_STOP, &msg, sizeof(msg)) < 0) { running = 0; - } else { - swoole_kill(gs->manager_pid, SIGIO); } } diff --git a/src/wrapper/event.cc b/src/wrapper/event.cc index d65d17f0a06..52be0141548 100644 --- a/src/wrapper/event.cc +++ b/src/wrapper/event.cc @@ -123,3 +123,7 @@ bool swoole_event_isset_handler(int fdtype) { bool swoole_event_is_available() { return SwooleTG.reactor and !SwooleTG.reactor->destroyed; } + +Socket *swoole_event_get_socket(int fd) { + return SwooleTG.reactor->get_socket(fd); +} diff --git a/tests/swoole_server/command.phpt b/tests/swoole_server/command.phpt index 3f34b4f8696..6e894c6e31a 100644 --- a/tests/swoole_server/command.phpt +++ b/tests/swoole_server/command.phpt @@ -23,9 +23,9 @@ $server->set([ $server->on('start', function (Server $serv) { $result = $serv->command('test_getpid', 0, SWOOLE_SERVER_COMMAND_MASTER, ['type' => 'master']); Assert::eq($result['pid'], $serv->getMasterPid()); - $result = $serv->command('test_getpid', 1, SWOOLE_SERVER_COMMAND_EVENT_WORKER, ['type' => 'worker'],); + $result = $serv->command('test_getpid', 1, SWOOLE_SERVER_COMMAND_EVENT_WORKER, ['type' => 'worker']); Assert::eq($result['pid'], $serv->getWorkerPid(1)); - $result = $serv->command('test_not_found', 1, SWOOLE_SERVER_COMMAND_EVENT_WORKER, ['type' => 'worker'],); + $result = $serv->command('test_not_found', 1, SWOOLE_SERVER_COMMAND_EVENT_WORKER, ['type' => 'worker']); Assert::false($result); $serv->shutdown(); From e648f7cde64da689b0005c1dddb3476bf68f6e58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Tue, 14 Sep 2021 17:00:14 +0800 Subject: [PATCH 243/936] Add Table::stats() (#4405) * Add Table::stats() * Optimize code --- ext-src/php_swoole.cc | 2 + ext-src/swoole_table.cc | 20 ++++++++- include/swoole_memory.h | 4 +- include/swoole_table.h | 17 ++++---- src/core/error.cc | 4 ++ src/memory/fixed_pool.cc | 12 ++++++ src/memory/table.cc | 26 ++++++++---- tests/swoole_table/random_bytes.phpt | 4 +- tests/swoole_table/stats.phpt | 61 ++++++++++++++++++++++++++++ tools/build-library.php | 8 ++++ 10 files changed, 138 insertions(+), 20 deletions(-) create mode 100644 tests/swoole_table/stats.phpt diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index dd45d6d8f05..89d1a4b7879 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -634,6 +634,7 @@ PHP_MINIT_FUNCTION(swoole) { SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_WEBSOCKET_BAD_OPCODE", SW_ERROR_WEBSOCKET_BAD_OPCODE); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_WEBSOCKET_UNCONNECTED", SW_ERROR_WEBSOCKET_UNCONNECTED); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_WEBSOCKET_HANDSHAKE_FAILED", SW_ERROR_WEBSOCKET_HANDSHAKE_FAILED); + SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_WEBSOCKET_PACK_FAILED", SW_ERROR_WEBSOCKET_PACK_FAILED); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_SERVER_MUST_CREATED_BEFORE_CLIENT", SW_ERROR_SERVER_MUST_CREATED_BEFORE_CLIENT); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_SERVER_TOO_MANY_SOCKET", SW_ERROR_SERVER_TOO_MANY_SOCKET); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_SERVER_WORKER_TERMINATED", SW_ERROR_SERVER_WORKER_TERMINATED); @@ -645,6 +646,7 @@ PHP_MINIT_FUNCTION(swoole) { SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_SERVER_SEND_IN_MASTER", SW_ERROR_SERVER_SEND_IN_MASTER); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_SERVER_INVALID_REQUEST", SW_ERROR_SERVER_INVALID_REQUEST); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_SERVER_CONNECT_FAIL", SW_ERROR_SERVER_CONNECT_FAIL); + SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_SERVER_INVALID_COMMAND", SW_ERROR_SERVER_INVALID_COMMAND); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_SERVER_WORKER_EXIT_TIMEOUT", SW_ERROR_SERVER_WORKER_EXIT_TIMEOUT); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_SERVER_WORKER_ABNORMAL_PIPE_DATA", SW_ERROR_SERVER_WORKER_ABNORMAL_PIPE_DATA); SW_REGISTER_LONG_CONSTANT("SWOOLE_ERROR_SERVER_WORKER_UNPROCESSED_DATA", SW_ERROR_SERVER_WORKER_UNPROCESSED_DATA); diff --git a/ext-src/swoole_table.cc b/ext-src/swoole_table.cc index 9effa638282..5b55b80808f 100644 --- a/ext-src/swoole_table.cc +++ b/ext-src/swoole_table.cc @@ -181,6 +181,7 @@ static PHP_METHOD(swoole_table, count); static PHP_METHOD(swoole_table, destroy); static PHP_METHOD(swoole_table, getSize); static PHP_METHOD(swoole_table, getMemorySize); +static PHP_METHOD(swoole_table, stats); static PHP_METHOD(swoole_table, rewind); static PHP_METHOD(swoole_table, next); @@ -206,8 +207,9 @@ static const zend_function_entry swoole_table_methods[] = PHP_MALIAS(swoole_table, exist, exists, arginfo_swoole_table_exists, ZEND_ACC_PUBLIC) PHP_ME(swoole_table, incr, arginfo_swoole_table_incr, ZEND_ACC_PUBLIC) PHP_ME(swoole_table, decr, arginfo_swoole_table_decr, ZEND_ACC_PUBLIC) - PHP_ME(swoole_table, getSize, arginfo_swoole_table_void, ZEND_ACC_PUBLIC) + PHP_ME(swoole_table, getSize, arginfo_swoole_table_void, ZEND_ACC_PUBLIC) PHP_ME(swoole_table, getMemorySize, arginfo_swoole_table_void, ZEND_ACC_PUBLIC) + PHP_ME(swoole_table, stats, arginfo_swoole_table_void, ZEND_ACC_PUBLIC) // implement Iterator PHP_ME(swoole_table, rewind, arginfo_swoole_table_void, ZEND_ACC_PUBLIC) PHP_ME(swoole_table, valid, arginfo_swoole_table_void, ZEND_ACC_PUBLIC) @@ -596,6 +598,22 @@ static PHP_METHOD(swoole_table, getSize) { } } +static PHP_METHOD(swoole_table, stats) { + Table *table = php_swoole_table_get_ptr(ZEND_THIS); + if (!table) { + RETURN_FALSE; + } + array_init(return_value); + add_assoc_long(return_value, "num", table->count()); + add_assoc_long(return_value, "conflict_count", table->conflict_count); + add_assoc_long(return_value, "conflict_max_level", table->conflict_max_level); + add_assoc_long(return_value, "insert_count", table->insert_count); + add_assoc_long(return_value, "update_count", table->update_count); + add_assoc_long(return_value, "delete_count", table->delete_count); + add_assoc_long(return_value, "available_slice_num", table->get_available_slice_num()); + add_assoc_long(return_value, "total_slice_num", table->get_total_slice_num()); +} + static PHP_METHOD(swoole_table, rewind) { Table *table = php_swoole_table_get_and_check_ptr2(ZEND_THIS); table->rewind(); diff --git a/include/swoole_memory.h b/include/swoole_memory.h index 7241ed75c84..8541f1db224 100644 --- a/include/swoole_memory.h +++ b/include/swoole_memory.h @@ -44,7 +44,9 @@ class FixedPool : public MemoryPool { void *alloc(uint32_t size); void free(void *ptr); void debug(); - + uint32_t get_number_of_spare_slice(); + uint32_t get_number_of_total_slice(); + uint32_t get_slice_size(); static size_t sizeof_struct_slice(); static size_t sizeof_struct_impl(); }; diff --git a/include/swoole_table.h b/include/swoole_table.h index 19503f8fc95..23258e170ac 100644 --- a/include/swoole_table.h +++ b/include/swoole_table.h @@ -178,17 +178,19 @@ class Table { void *memory; -#ifdef SW_TABLE_DEBUG - int conflict_count; - int insert_count; - int conflict_max_level; -#endif - public: std::vector *column_list; + size_t conflict_count; + sw_atomic_long_t insert_count; + sw_atomic_long_t delete_count; + sw_atomic_long_t update_count; + uint32_t conflict_max_level; + static Table *make(uint32_t rows_size, float conflict_proportion); size_t get_memory_size(); + uint32_t get_available_slice_num(); + uint32_t get_total_slice_num(); bool create(); bool add_column(const std::string &name, enum TableColumn::Type type, size_t size); TableRow *set(const char *key, uint16_t keylen, TableRow **rowlock, int *out_flags); @@ -289,9 +291,6 @@ class Table { new_row->key_len = keylen; new_row->active = 1; sw_atomic_fetch_add(&(row_num), 1); -#ifdef SW_TABLE_DEBUG - insert_count++; -#endif } }; } // namespace swoole diff --git a/src/core/error.cc b/src/core/error.cc index 19be32b6085..34ffea50e77 100644 --- a/src/core/error.cc +++ b/src/core/error.cc @@ -163,6 +163,8 @@ const char *swoole_strerror(int code) { return "Websocket unconnected"; case SW_ERROR_WEBSOCKET_HANDSHAKE_FAILED: return "Websocket handshake failed"; + case SW_ERROR_WEBSOCKET_PACK_FAILED: + return "Websocket pack failed"; case SW_ERROR_SERVER_MUST_CREATED_BEFORE_CLIENT: return "Server must created before client"; case SW_ERROR_SERVER_TOO_MANY_SOCKET: @@ -185,6 +187,8 @@ const char *swoole_strerror(int code) { return "Server invalid request"; case SW_ERROR_SERVER_CONNECT_FAIL: return "Server connect fail"; + case SW_ERROR_SERVER_INVALID_COMMAND: + return "Server invalid command"; case SW_ERROR_SERVER_WORKER_EXIT_TIMEOUT: return "Server worker exit timeout"; case SW_ERROR_SERVER_WORKER_ABNORMAL_PIPE_DATA: diff --git a/src/memory/fixed_pool.cc b/src/memory/fixed_pool.cc index 66471dd5b1b..0517e059642 100644 --- a/src/memory/fixed_pool.cc +++ b/src/memory/fixed_pool.cc @@ -128,6 +128,18 @@ void FixedPoolImpl::init() { } while (1); } +uint32_t FixedPool::get_number_of_spare_slice() { + return impl->slice_num - impl->slice_use; +} + +uint32_t FixedPool::get_number_of_total_slice() { + return impl->slice_num; +} + +uint32_t FixedPool::get_slice_size() { + return impl->slice_size; +} + void *FixedPool::alloc(uint32_t size) { FixedPoolSlice *slice; diff --git a/src/memory/table.cc b/src/memory/table.cc index a2b7c9c72b1..224748b52fb 100644 --- a/src/memory/table.cc +++ b/src/memory/table.cc @@ -115,6 +115,17 @@ size_t Table::get_memory_size() { return _memory_size; } +uint32_t Table::get_available_slice_num() { + lock(); + uint32_t num = pool->get_number_of_spare_slice(); + unlock(); + return num; +} + +uint32_t Table::get_total_slice_num() { + return pool->get_number_of_total_slice(); +} + bool Table::create() { if (created) { return false; @@ -297,9 +308,7 @@ TableRow *Table::set(const char *key, uint16_t keylen, TableRow **rowlock, int * row->lock(); int _out_flags = 0; -#ifdef SW_TABLE_DEBUG - int _conflict_level = 0; -#endif + uint32_t _conflict_level = 1; if (row->active) { for (;;) { @@ -308,12 +317,10 @@ TableRow *Table::set(const char *key, uint16_t keylen, TableRow **rowlock, int * } else if (row->next == nullptr) { lock(); TableRow *new_row = (TableRow *) pool->alloc(0); -#ifdef SW_TABLE_DEBUG conflict_count++; if (_conflict_level > conflict_max_level) { conflict_max_level = _conflict_level; } -#endif unlock(); if (!new_row) { return nullptr; @@ -326,9 +333,7 @@ TableRow *Table::set(const char *key, uint16_t keylen, TableRow **rowlock, int * } else { row = row->next; _out_flags |= SW_TABLE_FLAG_CONFLICT; -#ifdef SW_TABLE_DEBUG _conflict_level++; -#endif } } } else { @@ -340,6 +345,12 @@ TableRow *Table::set(const char *key, uint16_t keylen, TableRow **rowlock, int * *out_flags = _out_flags; } + if (_out_flags & SW_TABLE_FLAG_NEW_ROW) { + sw_atomic_fetch_add(&(insert_count), 1); + } else { + sw_atomic_fetch_add(&(update_count), 1); + } + return row; } @@ -398,6 +409,7 @@ bool Table::del(const char *key, uint16_t keylen) { } _delete_element: + sw_atomic_fetch_add(&(delete_count), 1); sw_atomic_fetch_sub(&(row_num), 1); row->unlock(); diff --git a/tests/swoole_table/random_bytes.phpt b/tests/swoole_table/random_bytes.phpt index 1de7607e3a0..a34e652444c 100644 --- a/tests/swoole_table/random_bytes.phpt +++ b/tests/swoole_table/random_bytes.phpt @@ -17,8 +17,8 @@ $map = []; while($n--) { $key = "key-".rand(1000000, 9999999); $value = RandStr::getBytes(rand(100*1024, 250*1024)); - $data[$key] = $value; - $table->set($key, ['string' => $value]); + $map[$key] = $value; + $table->set($key, ['string' => $value]); } foreach($map as $k => $v) { diff --git a/tests/swoole_table/stats.phpt b/tests/swoole_table/stats.phpt new file mode 100644 index 00000000000..2c1887b70e2 --- /dev/null +++ b/tests/swoole_table/stats.phpt @@ -0,0 +1,61 @@ +--TEST-- +swoole_table: stats +--SKIPIF-- + +--FILE-- +column('string', Table::TYPE_STRING, 256); +$table->create(); + +$map = []; +$keys = []; + +$n = N; +while ($n--) { + $key = base64_decode(RandStr::getBytes(rand(10, 30))); + $value = RandStr::getBytes(rand(100, 250)); + if ($table->set($key, ['string' => $value])) { + $map[$key] = $value; + $keys[] = $key; + } +} + +$stats1 = $table->stats(); + +Assert::eq(count($keys), N); +Assert::eq(count(array_unique($keys)), $stats1['insert_count']); + +phpt_var_dump("insert\n".str_repeat('-', 64), $stats1); + +define('UPDATE_N', rand(100, 1000)); + +$_n = UPDATE_N; +while ($_n--) { + $key = array_rand($map); + $value = RandStr::getBytes(rand(100, 250)); + Assert::true($table->set($key, ['string' => $value])); + $map[$key] = $value; +} + +$stats2 = $table->stats(); +Assert::eq($stats1['update_count'] + UPDATE_N, $stats2['update_count']); +phpt_var_dump("update\n" . str_repeat('-', 64), $stats2); + +foreach($map as $k => $v) { + Assert::same($table->get($k)['string'], $v); + $table->del($k); +} + +$stats3 = $table->stats(); +Assert::eq($stats3['num'], 0); +Assert::eq($stats3['available_slice_num'], $stats3['total_slice_num']); +phpt_var_dump("delete\n" . str_repeat('-', 64), $stats3); +?> +--EXPECT-- diff --git a/tools/build-library.php b/tools/build-library.php index ee33397c3e4..9a77ac5b979 100755 --- a/tools/build-library.php +++ b/tools/build-library.php @@ -97,7 +97,15 @@ 'alias_ns.php', ]; +$ignore_files = ['vendor_init.php',]; + $diff_files = array_diff(swoole_library_files(), $files); +foreach ($diff_files as $k => $f) { + if (in_array($f, $ignore_files)) { + unset($diff_files[$k]); + } +} + if (!empty($diff_files)) { swoole_error('Some files are not loaded: ', ...$diff_files); } From 6345fe88ef29546403bc6eb70505fb573f9a7d71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Wed, 15 Sep 2021 09:56:50 +0800 Subject: [PATCH 244/936] Add Coroutine::join() (#4406) * Co::join() * Optimize code * Add tests, Fix bugs * Fix core tests --- core-tests/src/reactor/base.cpp | 12 +++ core-tests/src/reactor/defer_task.cpp | 67 ----------------- examples/coroutine/join.php | 36 +++++++++ ext-src/php_swoole_coroutine.h | 5 ++ ext-src/swoole_coroutine.cc | 102 +++++++++++++++++++++++--- include/swoole_reactor.h | 8 -- src/coroutine/system.cc | 8 +- src/reactor/base.cc | 8 -- tests/swoole_coroutine/join/1.phpt | 30 ++++++++ tests/swoole_coroutine/join/2.phpt | 35 +++++++++ tests/swoole_coroutine/join/3.phpt | 49 +++++++++++++ tests/swoole_coroutine/join/4.phpt | 33 +++++++++ 12 files changed, 296 insertions(+), 97 deletions(-) delete mode 100644 core-tests/src/reactor/defer_task.cpp create mode 100644 examples/coroutine/join.php create mode 100644 tests/swoole_coroutine/join/1.phpt create mode 100644 tests/swoole_coroutine/join/2.phpt create mode 100644 tests/swoole_coroutine/join/3.phpt create mode 100644 tests/swoole_coroutine/join/4.phpt diff --git a/core-tests/src/reactor/base.cpp b/core-tests/src/reactor/base.cpp index 8395cbd25ef..d753c544253 100644 --- a/core-tests/src/reactor/base.cpp +++ b/core-tests/src/reactor/base.cpp @@ -257,3 +257,15 @@ TEST(reactor, add_or_update) { swoole_event_free(); } + +TEST(reactor, defer_task) { + swoole_event_init(SW_EVENTLOOP_WAIT_EXIT); + Reactor *reactor = sw_reactor(); + ASSERT_EQ(reactor->max_event_num, SW_REACTOR_MAXEVENTS); + + int count = 0; + reactor->defer([&count](void *) { count++; }); + swoole_event_wait(); + ASSERT_EQ(count, 1); + swoole_event_free(); +} diff --git a/core-tests/src/reactor/defer_task.cpp b/core-tests/src/reactor/defer_task.cpp deleted file mode 100644 index 7fc823daa32..00000000000 --- a/core-tests/src/reactor/defer_task.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | 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. | - +----------------------------------------------------------------------+ - | @link https://www.swoole.com/ | - | @contact team@swoole.com | - | @license https://github.com/swoole/swoole-src/blob/master/LICENSE | - | @author Tianfeng Han | - +----------------------------------------------------------------------+ -*/ - -#include "test_core.h" -#include "swoole_pipe.h" - -using namespace swoole; - -TEST(defer_task, defer) { - swoole_event_init(SW_EVENTLOOP_WAIT_EXIT); - Reactor *reactor = sw_reactor(); - ASSERT_EQ(reactor->max_event_num, SW_REACTOR_MAXEVENTS); - - int count = 0; - reactor->defer([&count](void *) { count++; }); - swoole_event_wait(); - ASSERT_EQ(count, 1); - swoole_event_free(); -} - -TEST(defer_task, cancel_1) { - swoole_event_init(SW_EVENTLOOP_WAIT_EXIT); - Reactor *reactor = sw_reactor(); - ASSERT_EQ(reactor->max_event_num, SW_REACTOR_MAXEVENTS); - - int count = 0; - reactor->defer([&count](void *) { count += 2; }); - auto iter = reactor->get_last_defer_task(); - reactor->remove_defer_task(iter); - - reactor->defer([&count](void *) { count += 5; }); - - swoole_event_wait(); - ASSERT_EQ(count, 5); - swoole_event_free(); -} - -TEST(defer_task, cancel_2) { - swoole_event_init(SW_EVENTLOOP_WAIT_EXIT); - Reactor *reactor = sw_reactor(); - ASSERT_EQ(reactor->max_event_num, SW_REACTOR_MAXEVENTS); - - int count = 0; - reactor->defer([&count](void *) { count += 2; }); - auto iter = reactor->get_last_defer_task(); - reactor->remove_defer_task(iter); - - swoole_event_wait(); - ASSERT_EQ(count, 0); - swoole_event_free(); -} diff --git a/examples/coroutine/join.php b/examples/coroutine/join.php new file mode 100644 index 00000000000..4431e7e6af0 --- /dev/null +++ b/examples/coroutine/join.php @@ -0,0 +1,36 @@ + SwapCallback; + JMP_BUF *bailout; zval *vm_stack_top; zval *vm_stack_end; @@ -69,6 +71,9 @@ struct PHPContext { int tmp_error_reporting; Coroutine *co; std::stack *defer_tasks; + SwapCallback *on_yield; + SwapCallback *on_resume; + SwapCallback *on_close; long pcid; zend_object *context; int64_t last_msec; diff --git a/ext-src/swoole_coroutine.cc b/ext-src/swoole_coroutine.cc index e6b2ff380ad..378dec25a71 100644 --- a/ext-src/swoole_coroutine.cc +++ b/ext-src/swoole_coroutine.cc @@ -35,6 +35,7 @@ using swoole::PHPContext; using swoole::PHPCoroutine; using swoole::coroutine::Socket; using swoole::coroutine::System; +using swoole::CallbackManager; #define PHP_CORO_TASK_SLOT \ ((int) ((ZEND_MM_ALIGNED_SIZE(sizeof(PHPContext)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / \ @@ -94,6 +95,7 @@ SW_EXTERN_C_BEGIN static PHP_METHOD(swoole_coroutine, exists); static PHP_METHOD(swoole_coroutine, yield); static PHP_METHOD(swoole_coroutine, resume); +static PHP_METHOD(swoole_coroutine, join); static PHP_METHOD(swoole_coroutine, cancel); static PHP_METHOD(swoole_coroutine, isCanceled); static PHP_METHOD(swoole_coroutine, stats); @@ -130,6 +132,11 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_coroutine_resume, 0, 0, 1) ZEND_ARG_INFO(0, cid) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_coroutine_join, 0, 0, 1) + ZEND_ARG_INFO(0, cid_array) + ZEND_ARG_INFO(0, timeout) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_coroutine_exists, 0, 0, 1) ZEND_ARG_INFO(0, cid) ZEND_END_ARG_INFO() @@ -178,6 +185,7 @@ static const zend_function_entry swoole_coroutine_methods[] = PHP_ME(swoole_coroutine, exists, arginfo_swoole_coroutine_exists, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(swoole_coroutine, yield, arginfo_swoole_coroutine_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(swoole_coroutine, cancel, arginfo_swoole_coroutine_cancel, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) + PHP_ME(swoole_coroutine, join, arginfo_swoole_coroutine_join, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(swoole_coroutine, isCanceled, arginfo_swoole_coroutine_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_MALIAS(swoole_coroutine, suspend, yield, arginfo_swoole_coroutine_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) PHP_ME(swoole_coroutine, resume, arginfo_swoole_coroutine_resume, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC) @@ -590,10 +598,14 @@ void PHPCoroutine::restore_task(PHPContext *task) { void PHPCoroutine::on_yield(void *arg) { PHPContext *task = (PHPContext *) arg; PHPContext *origin_task = get_origin_context(task); - swoole_trace_log( - SW_TRACE_COROUTINE, "php_coro_yield from cid=%ld to cid=%ld", task->co->get_cid(), task->co->get_origin_cid()); save_task(task); restore_task(origin_task); + + if (task->on_yield) { + (*task->on_yield)(task); + } + + swoole_trace_log(SW_TRACE_COROUTINE, "from cid=%ld to cid=%ld", task->co->get_cid(), task->co->get_origin_cid()); } void PHPCoroutine::on_resume(void *arg) { @@ -602,10 +614,12 @@ void PHPCoroutine::on_resume(void *arg) { save_task(current_task); restore_task(task); record_last_msec(task); - swoole_trace_log(SW_TRACE_COROUTINE, - "php_coro_resume from cid=%ld to cid=%ld", - Coroutine::get_current_cid(), - task->co->get_cid()); + + if (task->on_resume) { + (*task->on_resume)(task); + } + + swoole_trace_log(SW_TRACE_COROUTINE, "from cid=%ld to cid=%ld", Coroutine::get_current_cid(), task->co->get_cid()); } void PHPCoroutine::on_close(void *arg) { @@ -638,9 +652,14 @@ void PHPCoroutine::on_close(void *arg) { } #endif + if (task->on_close) { + (*task->on_close)(task); + } + if (SwooleG.max_concurrency > 0 && task->pcid == -1) { SwooleWG.worker_concurrency--; } + vm_stack_destroy(); restore_task(origin_task); @@ -657,7 +676,6 @@ void PHPCoroutine::main_func(void *arg) { #ifdef SW_CORO_SUPPORT_BAILOUT zend_first_try { #endif - int i; Args *php_arg = (Args *) arg; zend_fcall_info_cache fci_cache = *php_arg->fci_cache; zend_function *func = fci_cache.function_handler; @@ -694,7 +712,7 @@ void PHPCoroutine::main_func(void *arg) { } while (0); #endif - for (i = 0; i < argc; ++i) { + SW_LOOP_N(argc) { zval *param; zval *arg = &argv[i]; if (Z_ISREF_P(arg) && !(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { @@ -736,6 +754,9 @@ void PHPCoroutine::main_func(void *arg) { task->defer_tasks = nullptr; task->pcid = task->co->get_origin_cid(); task->context = nullptr; + task->on_yield = nullptr; + task->on_resume = nullptr; + task->on_close = nullptr; task->enable_scheduler = true; save_vm_stack(task); @@ -1108,7 +1129,7 @@ static PHP_METHOD(swoole_coroutine, resume) { auto coroutine_iterator = user_yield_coros.find(cid); if (coroutine_iterator == user_yield_coros.end()) { - php_swoole_fatal_error(E_WARNING, "you can not resume the coroutine which is in IO operation or non-existent"); + php_swoole_fatal_error(E_WARNING, "can not resume the coroutine which is in IO operation or non-existent"); RETURN_FALSE; } @@ -1137,6 +1158,69 @@ static PHP_METHOD(swoole_coroutine, yield) { RETURN_TRUE; } +static PHP_METHOD(swoole_coroutine, join) { + Coroutine *co = Coroutine::get_current_safe(); + zval *cid_array; + double timeout = -1; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_ARRAY(cid_array) + Z_PARAM_OPTIONAL + Z_PARAM_DOUBLE(timeout) + ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + + auto count = php_swoole_array_length(cid_array); + if (count == 0) { + swoole_set_last_error(SW_ERROR_INVALID_PARAMS); + RETURN_FALSE; + } + + bool *canceled = new bool(false); + PHPContext::SwapCallback join_fn = [&count, canceled, co](PHPContext *task) { + if (--count > 0) { + return; + } + swoole_event_defer([co, canceled](void*) { + if (*canceled == false) { + co->resume(); + } + delete canceled; + }, nullptr); + }; + + zval *zcid; + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(cid_array), zcid) { + long cid = zval_get_long(zcid); + if (co->get_cid() == cid) { + swoole_set_last_error(SW_ERROR_WRONG_OPERATION); + php_swoole_error(E_WARNING, "can not join self"); + RETURN_FALSE; + } + auto ctx = PHPCoroutine::get_context_by_cid(cid); + if (ctx == nullptr) { + swoole_set_last_error(SW_ERROR_CO_NOT_EXISTS); + RETURN_FALSE; + } + ctx->on_close = &join_fn; + } + ZEND_HASH_FOREACH_END(); + + if (!co->yield_ex(timeout)) { + *canceled = true; + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(cid_array), zcid) { + long cid = zval_get_long(zcid); + auto ctx = PHPCoroutine::get_context_by_cid(cid); + if (ctx) { + ctx->on_close = nullptr; + } + } + ZEND_HASH_FOREACH_END(); + RETURN_FALSE; + } + + RETURN_TRUE; +} + static PHP_METHOD(swoole_coroutine, cancel) { long cid; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &cid) == FAILURE) { diff --git a/include/swoole_reactor.h b/include/swoole_reactor.h index 131aa1bc70e..17340a2a2ac 100644 --- a/include/swoole_reactor.h +++ b/include/swoole_reactor.h @@ -60,12 +60,6 @@ class CallbackManager { list_.emplace_front(fn, private_data); auto t = list_.back(); } - TaskList::iterator back_position() { - return std::prev(list_.end()); - } - TaskList::iterator front_position() { - return list_.begin(); - } void remove(TaskList::iterator iter) { list_.erase(iter); } @@ -194,8 +188,6 @@ class Reactor { ~Reactor(); bool if_exit(); void defer(Callback cb, void *data = nullptr); - CallbackManager::TaskList::iterator get_last_defer_task(); - void remove_defer_task(CallbackManager::TaskList::iterator iter); void set_end_callback(enum EndCallback id, const std::function &fn); void set_exit_condition(enum ExitCondition id, const std::function &fn); bool set_handler(int _fdtype, ReactorHandler handler); diff --git a/src/coroutine/system.cc b/src/coroutine/system.cc index 04a4b562226..a2336a1713e 100644 --- a/src/coroutine/system.cc +++ b/src/coroutine/system.cc @@ -43,12 +43,10 @@ void System::clear_dns_cache() { } static void sleep_callback(Coroutine *co, bool *canceled) { - bool _canceled = *canceled; - delete canceled; - if (_canceled) { - return; + if (*canceled == false) { + co->resume(); } - co->resume(); + delete canceled; } int System::sleep(double sec) { diff --git a/src/reactor/base.cc b/src/reactor/base.cc index 9d6fdaddc06..d4be6cba97e 100644 --- a/src/reactor/base.cc +++ b/src/reactor/base.cc @@ -394,14 +394,6 @@ void Reactor::defer(Callback cb, void *data) { defer_tasks->append(cb, data); } -CallbackManager::TaskList::iterator Reactor::get_last_defer_task() { - return defer_tasks->back_position(); -} - -void Reactor::remove_defer_task(CallbackManager::TaskList::iterator iter) { - defer_tasks->remove(iter); -} - void Reactor::execute_end_callbacks(bool timedout) { for (auto &kv : end_callbacks) { kv.second(this); diff --git a/tests/swoole_coroutine/join/1.phpt b/tests/swoole_coroutine/join/1.phpt new file mode 100644 index 00000000000..3461ff26421 --- /dev/null +++ b/tests/swoole_coroutine/join/1.phpt @@ -0,0 +1,30 @@ +--TEST-- +swoole_coroutine/join: 1 +--SKIPIF-- + +--FILE-- + +--EXPECT-- +ALL DONE diff --git a/tests/swoole_coroutine/join/2.phpt b/tests/swoole_coroutine/join/2.phpt new file mode 100644 index 00000000000..c3dcc76bd04 --- /dev/null +++ b/tests/swoole_coroutine/join/2.phpt @@ -0,0 +1,35 @@ +--TEST-- +swoole_coroutine/join: 2 +--SKIPIF-- + +--FILE-- + +--EXPECT-- +ALL DONE diff --git a/tests/swoole_coroutine/join/3.phpt b/tests/swoole_coroutine/join/3.phpt new file mode 100644 index 00000000000..5e99872f4f4 --- /dev/null +++ b/tests/swoole_coroutine/join/3.phpt @@ -0,0 +1,49 @@ +--TEST-- +swoole_coroutine/join: 3 +--SKIPIF-- + +--FILE-- + +--EXPECT-- diff --git a/tests/swoole_coroutine/join/4.phpt b/tests/swoole_coroutine/join/4.phpt new file mode 100644 index 00000000000..5ab8d152639 --- /dev/null +++ b/tests/swoole_coroutine/join/4.phpt @@ -0,0 +1,33 @@ +--TEST-- +swoole_coroutine/join: 4 +--SKIPIF-- + +--FILE-- + +--EXPECT-- +DEFER CALLBACK +DONE From 1c02a8703f194f9b01d2e92a39c93c6a82f1b49d Mon Sep 17 00:00:00 2001 From: MARiA so cute <33935209+NathanFreeman@users.noreply.github.com> Date: Wed, 15 Sep 2021 15:21:36 +0800 Subject: [PATCH 245/936] Open basedir (#4407) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix bug #4327 * fix bug #4327 * fix bug #4327 * unit test * 代码格式 * 单元测试 * 修复无符号和有符号之间的比较 * unit test * unit test * open_basedir * support open_basedir * support open_basedir * (void *)buf * (char *) memchr(buf, DEFAULT_SLASH, dir_len)) * clang-format --- .../file_hook/open_basedir.phpt | 28 ++++ thirdparty/php/streams/plain_wrapper.c | 149 ++++++++++-------- 2 files changed, 111 insertions(+), 66 deletions(-) create mode 100644 tests/swoole_runtime/file_hook/open_basedir.phpt diff --git a/tests/swoole_runtime/file_hook/open_basedir.phpt b/tests/swoole_runtime/file_hook/open_basedir.phpt new file mode 100644 index 00000000000..8ea74b4618a --- /dev/null +++ b/tests/swoole_runtime/file_hook/open_basedir.phpt @@ -0,0 +1,28 @@ +--TEST-- +support open_basedir config +--SKIPIF-- + +--FILE-- + +--EXPECTF-- + +Warning: mkdir(): open_basedir restriction in effect. File(%s) is not within the allowed path(s): (%s) in %s on line 7 +bool(true) +bool(true) +bool(true) \ No newline at end of file diff --git a/thirdparty/php/streams/plain_wrapper.c b/thirdparty/php/streams/plain_wrapper.c index 79ededbda75..4f11efd23ca 100644 --- a/thirdparty/php/streams/plain_wrapper.c +++ b/thirdparty/php/streams/plain_wrapper.c @@ -62,6 +62,7 @@ static int sw_php_stdiop_cast(php_stream *stream, int castas, void **ret); static void php_stream_mode_sanitize_fdopen_fopencookie(php_stream *stream, char *result); static php_stream *_sw_php_stream_fopen_from_fd_int(int fd, const char *mode, const char *persistent_id STREAMS_DC); static php_stream *_sw_php_stream_fopen_from_fd(int fd, const char *mode, const char *persistent_id STREAMS_DC); +static int sw_php_mkdir(const char *dir, zend_long mode); static inline zend_bool file_can_poll(zend_stat_t *_stat) { return S_ISCHR(_stat->st_mode) || S_ISSOCK(_stat->st_mode) || S_ISFIFO(_stat->st_mode); @@ -1030,90 +1031,92 @@ static int php_plain_files_rename( static int php_plain_files_mkdir( php_stream_wrapper *wrapper, const char *dir, int mode, int options, php_stream_context *context) { - int ret, recursive = options & PHP_STREAM_MKDIR_RECURSIVE; - char *p; - if (strncasecmp(dir, "file://", sizeof("file://") - 1) == 0) { dir += sizeof("file://") - 1; } - if (!recursive) { - ret = mkdir(dir, mode); - } else { - /* we look for directory separator from the end of string, thus hopefuly reducing our work load */ - char *e; - zend_stat_t sb; - int dir_len = (int) strlen(dir); - int offset = 0; - char buf[MAXPATHLEN]; - - if (!expand_filepath_with_mode(dir, buf, NULL, 0, CWD_EXPAND)) { - php_error_docref(NULL, E_WARNING, "Invalid path"); - return 0; - } + if (!(options & PHP_STREAM_MKDIR_RECURSIVE)) { + return sw_php_mkdir(dir, mode) == 0; + } - e = buf + strlen(buf); + char buf[MAXPATHLEN]; + if (!expand_filepath_with_mode(dir, buf, NULL, 0, CWD_EXPAND)) { + php_error_docref(NULL, E_WARNING, "Invalid path"); + return 0; + } - if ((p = (char *) memchr(buf, DEFAULT_SLASH, dir_len))) { - offset = p - buf + 1; - } + if (php_check_open_basedir(buf)) { + return 0; + } - if (p && dir_len == 1) { - /* buf == "DEFAULT_SLASH" */ - } else { - /* find a top level directory we need to create */ - while ((p = strrchr(buf + offset, DEFAULT_SLASH)) || (offset != 1 && (p = strrchr(buf, DEFAULT_SLASH)))) { - int n = 0; + /* we look for directory separator from the end of string, thus hopefully reducing our work load */ + char *p; + zend_stat_t sb; + size_t dir_len = strlen(dir), offset = 0; + char *e = buf + strlen(buf); + + if ((p = (char *) memchr(buf, DEFAULT_SLASH, dir_len))) { + offset = p - buf + 1; + } + if (p && dir_len == 1) { + /* buf == "DEFAULT_SLASH" */ + } else { + /* find a top level directory we need to create */ + while ((p = strrchr(buf + offset, DEFAULT_SLASH)) || (offset != 1 && (p = strrchr(buf, DEFAULT_SLASH)))) { + int n = 0; + + *p = '\0'; + while (p > buf && *(p - 1) == DEFAULT_SLASH) { + ++n; + --p; *p = '\0'; - while (p > buf && *(p - 1) == DEFAULT_SLASH) { - ++n; - --p; - *p = '\0'; - } - if (stat(buf, &sb) == 0) { - while (1) { - *p = DEFAULT_SLASH; - if (!n) break; - --n; - ++p; - } - break; + } + if (stat(buf, &sb) == 0) { + while (1) { + *p = DEFAULT_SLASH; + if (!n) break; + --n; + ++p; } + break; } } + } - if (p == buf) { - ret = mkdir(dir, mode); - } else if (!(ret = mkdir(buf, mode)) || EEXIST == errno) { - if (!p) { - p = buf; + if (!p) { + p = buf; + } + while (true) { + int ret = mkdir(buf, (mode_t) mode); + if (ret < 0 && errno != EEXIST) { + if (options & REPORT_ERRORS) { + php_error_docref(NULL, E_WARNING, "%s", strerror(errno)); } - /* create any needed directories if the creation of the 1st directory worked */ - while (++p != e) { - if (*p == '\0') { - *p = DEFAULT_SLASH; - if ((*(p + 1) != '\0') && (ret = mkdir(buf, (mode_t) mode)) < 0) { - // parent directory already exists and try to create child directories. - if (EEXIST == errno && (int) strlen(buf) < dir_len) { - continue; - } + return 0; + } - if (options & REPORT_ERRORS) { - php_error_docref(NULL, E_WARNING, "%s", strerror(errno)); - } - break; - } + bool replaced_slash = false; + while (++p != e) { + if (*p == '\0') { + replaced_slash = true; + *p = DEFAULT_SLASH; + if (*(p + 1) != '\0') { + break; } } } - } - if (ret < 0) { - /* Failure */ - return 0; - } else { - /* Success */ - return 1; + if (p == e || !replaced_slash) { + /* No more directories to create */ + /* issue a warning to client when the last directory was created failed */ + if (ret < 0) { + if (options & REPORT_ERRORS) { + php_error_docref(NULL, E_WARNING, "%s", strerror(errno)); + } + return 0; + } + return 1; + } } } @@ -1259,6 +1262,20 @@ static php_stream *_sw_php_stream_fopen_from_fd(int fd, const char *mode, const return stream; } +static int sw_php_mkdir(const char *dir, zend_long mode) { + int ret; + + if (php_check_open_basedir(dir)) { + return -1; + } + + if ((ret = mkdir(dir, (mode_t) mode)) < 0) { + php_error_docref(NULL, E_WARNING, "%s", strerror(errno)); + } + + return ret; +} + static void php_stream_mode_sanitize_fdopen_fopencookie(php_stream *stream, char *result) { /* replace modes not supported by fdopen and fopencookie, but supported * by PHP's fread(), so that their calls won't fail */ From 86708d6ad31ce4374bca9c1bfdee0e6af892ed11 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Wed, 15 Sep 2021 16:32:43 +0800 Subject: [PATCH 246/936] Optimize code --- ext-src/swoole_coroutine.cc | 1 - ext-src/swoole_server.cc | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/ext-src/swoole_coroutine.cc b/ext-src/swoole_coroutine.cc index 378dec25a71..7ca006033b5 100644 --- a/ext-src/swoole_coroutine.cc +++ b/ext-src/swoole_coroutine.cc @@ -35,7 +35,6 @@ using swoole::PHPContext; using swoole::PHPCoroutine; using swoole::coroutine::Socket; using swoole::coroutine::System; -using swoole::CallbackManager; #define PHP_CORO_TASK_SLOT \ ((int) ((ZEND_MM_ALIGNED_SIZE(sizeof(PHPContext)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval)) - 1) / \ diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index d54a984601d..8b43b876f40 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -3685,9 +3685,9 @@ static PHP_METHOD(swoole_server, getClientInfo) { } #endif // server socket - Connection *from_sock = serv->get_connection(conn->server_fd); - if (from_sock) { - add_assoc_long(return_value, "server_port", from_sock->info.get_port()); + Connection *server_socket = serv->get_connection(conn->server_fd); + if (server_socket) { + add_assoc_long(return_value, "server_port", server_socket->info.get_port()); } add_assoc_long(return_value, "server_fd", conn->server_fd); add_assoc_long(return_value, "socket_fd", conn->fd); From 6d2b2e36b1911ac1d5f1ccb426337aa898cc3a77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Fri, 17 Sep 2021 10:12:50 +0800 Subject: [PATCH 247/936] Refactor Server::close() with reset (#4408) * Refactor Server::close() with reset * remove debug code --- src/server/base.cc | 67 +++++++++++----------- src/server/master.cc | 2 +- src/server/process.cc | 43 +++++++------- tests/swoole_server/close_reset.phpt | 85 ++++++++++++++++++++++++++++ 4 files changed, 138 insertions(+), 59 deletions(-) create mode 100644 tests/swoole_server/close_reset.phpt diff --git a/src/server/base.cc b/src/server/base.cc index 9127baae0b3..c23fb5d9f90 100644 --- a/src/server/base.cc +++ b/src/server/base.cc @@ -122,45 +122,44 @@ bool BaseFactory::end(SessionId session_id, int flags) { if (flags & Server::CLOSE_ACTIVELY) { conn->close_actively = 1; } - if (conn->close_force) { - goto _do_close; - } else if (conn->closing) { - swoole_warning("session#%ld is closing", session_id); + + if (conn->closing) { + swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_CLOSING, "session#%ld is closing", session_id); return false; - } else if (conn->closed) { + } else if (!(conn->close_force || conn->close_reset) && conn->closed) { + swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_CLOSED, "session#%ld is closed", session_id); return false; - } else { - _do_close: - conn->closing = 1; - if (server_->onClose != nullptr) { - DataHead info{}; - info.fd = session_id; - if (conn->close_actively) { - info.reactor_id = -1; - } else { - info.reactor_id = conn->reactor_id; - } - info.server_fd = conn->server_fd; - server_->onClose(server_, &info); - } - conn->closing = 0; - conn->closed = 1; - conn->close_errno = 0; - - if (conn->socket == nullptr) { - swoole_warning("session#%ld->socket is nullptr", session_id); - return false; - } + } - if (Buffer::empty(conn->socket->out_buffer) || conn->peer_closed || conn->close_force) { - Reactor *reactor = SwooleTG.reactor; - return Server::close_connection(reactor, conn->socket) == SW_OK; + conn->closing = 1; + if (server_->onClose != nullptr && !conn->closed) { + DataHead info{}; + info.fd = session_id; + if (conn->close_actively) { + info.reactor_id = -1; } else { - BufferChunk *chunk = conn->socket->out_buffer->alloc(BufferChunk::TYPE_CLOSE, 0); - chunk->value.data.val1 = _send.info.type; - conn->close_queued = 1; - return true; + info.reactor_id = conn->reactor_id; } + info.server_fd = conn->server_fd; + server_->onClose(server_, &info); + } + conn->closing = 0; + conn->closed = 1; + conn->close_errno = 0; + + if (conn->socket == nullptr) { + swoole_warning("session#%ld->socket is nullptr", session_id); + return false; + } + + if (Buffer::empty(conn->socket->out_buffer) || (conn->close_reset || conn->peer_closed || conn->close_force)) { + Reactor *reactor = SwooleTG.reactor; + return Server::close_connection(reactor, conn->socket) == SW_OK; + } else { + BufferChunk *chunk = conn->socket->out_buffer->alloc(BufferChunk::TYPE_CLOSE, 0); + chunk->value.data.val1 = _send.info.type; + conn->close_queued = 1; + return true; } } diff --git a/src/server/master.cc b/src/server/master.cc index 876265059a3..714cc5202cf 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -1515,7 +1515,7 @@ void Server::call_hook(HookType type, void *arg) { * [Worker] */ bool Server::close(SessionId session_id, bool reset) { - return factory->end(session_id, reset ? CLOSE_ACTIVELY | CLOSE_RESET : CLOSE_ACTIVELY); + return factory->end(session_id, reset ? (CLOSE_ACTIVELY | CLOSE_RESET) : CLOSE_ACTIVELY); } void Server::init_signal_handler() { diff --git a/src/server/process.cc b/src/server/process.cc index 01602f5fb57..32eba8dd9d0 100644 --- a/src/server/process.cc +++ b/src/server/process.cc @@ -257,11 +257,12 @@ bool ProcessFactory::end(SessionId session_id, int flags) { Connection *conn = server_->get_connection_verify_no_ssl(session_id); if (!conn) { - swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_NOT_EXIST, "session[%ld] is closed", session_id); + swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_NOT_EXIST, "session#%ld is closed", session_id); return false; } // Reset send buffer, Immediately close the connection. if (flags & Server::CLOSE_RESET) { + swoole_warning("close session=%ld, force", session_id); conn->close_reset = 1; } // Server is initiative to close the connection @@ -301,34 +302,28 @@ bool ProcessFactory::end(SessionId session_id, int flags) { } _close: - if (conn == nullptr || conn->active == 0) { - swoole_set_last_error(SW_ERROR_SESSION_NOT_EXIST); - return false; - } else if (conn->close_force) { - goto _do_close; - } else if (conn->closing) { + if (conn->closing) { swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_CLOSING, "session#%ld is closing", session_id); return false; - } else if (conn->closed) { + } else if (!(conn->close_force || conn->close_reset) && conn->closed) { + swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_CLOSED, "session#%ld is closed", session_id); return false; - } else { - _do_close: - conn->closing = 1; - if (server_->onClose != nullptr) { - info.fd = session_id; - if (conn->close_actively) { - info.reactor_id = -1; - } else { - info.reactor_id = conn->reactor_id; - } - info.server_fd = conn->server_fd; - server_->onClose(server_, &info); + } + + if (server_->onClose != nullptr && !conn->closed) { + info.fd = session_id; + if (conn->close_actively) { + info.reactor_id = -1; + } else { + info.reactor_id = conn->reactor_id; } + info.server_fd = conn->server_fd; + conn->closing = 1; + server_->onClose(server_, &info); conn->closing = 0; - conn->closed = 1; - conn->close_errno = 0; - return finish(&_send); } + conn->closed = 1; + conn->close_errno = 0; + return finish(&_send); } - } // namespace swoole diff --git a/tests/swoole_server/close_reset.phpt b/tests/swoole_server/close_reset.phpt new file mode 100644 index 00000000000..4dcfdd3338c --- /dev/null +++ b/tests/swoole_server/close_reset.phpt @@ -0,0 +1,85 @@ +--TEST-- +swoole_server: close with reset +--SKIPIF-- + +--FILE-- +parentFunc = function ($pid) use ($pm) { + go(function () use ($pm) { + $client = new Client(SWOOLE_SOCK_TCP); + $client->set(['socket_buffer_size' => 128 * 1024]); + if (!$client->connect('127.0.0.1', $pm->getFreePort())) { + exit("connect failed\n"); + } + $client->send("close"); + Co::sleep(1); + $data = ''; + + while (true) { + $ret = $client->recv(); + if (empty($ret)) { + break; + } + $data .= $ret; + if (substr($ret, -2, 2) == "\r\n") { + break; + } + } + Assert::lessThan(strlen($data), N); + echo "DONE\n"; + }); + Swoole\Event::wait(); + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm) { + $serv = new Server('127.0.0.1', $pm->getFreePort(), SERVER_MODE_RANDOM); + $serv->set([ + 'worker_num' => 1, + 'log_file' => TEST_LOG_FILE, + 'kernel_socket_send_buffer_size' => 128 * 1024, + 'socket_buffer_size' => 8 * 1024 * 1024, + ]); + $serv->on("workerStart", function ($serv) use ($pm) { + $pm->wakeup(); + }); + $serv->on('receive', function (Server $serv, $fd, $reactor_id, $data) { + $serv->send($fd, str_repeat('A', N) . "\r\n"); + Assert::eq($serv->stats()['connection_num'], 1); + phpt_var_dump("close[0]"); + Assert::true($serv->close($fd)); + usleep(50000); + phpt_var_dump("close[1]"); + Assert::false($serv->close($fd)); + Assert::eq(swoole_last_error(), SWOOLE_ERROR_SESSION_CLOSED); + Assert::eq($serv->stats()['connection_num'], 1); + Timer::after(100, function () use ($fd, $serv) { + phpt_var_dump("close[2]"); + $serv->close($fd, true); + usleep(50000); + Assert::eq($serv->stats()['connection_num'], 0); + }); + }); + $serv->on(Constant::EVENT_CLOSE, function (Server $serv, $fd, $reactor_id) { + }); + $serv->start(); +}; + +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +DONE From 808f0bdef5bd9cd6017a7b2f1b3fa3cccb79bab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Wed, 22 Sep 2021 10:27:26 +0800 Subject: [PATCH 248/936] Improve stats (#4410) * Improve stats * Fix tests * add tests * fix tests --- core-tests/src/os/async.cpp | 45 +++++++++++++++++++++++++- ext-src/swoole_coroutine.cc | 6 ++-- ext-src/swoole_server.cc | 5 +++ include/swoole_async.h | 9 ++++-- include/swoole_memory.h | 1 + include/swoole_server.h | 5 ++- src/memory/global_memory.cc | 4 +++ src/os/async_thread.cc | 12 ++++--- src/server/message_bus.cc | 8 +++++ src/server/port.cc | 46 +++++++++++++++++++++------ src/server/process.cc | 5 ++- tests/swoole_server/bug_11000_01.phpt | 12 ++++++- tests/swoole_server/stats_file.phpt | 5 +++ 13 files changed, 140 insertions(+), 23 deletions(-) diff --git a/core-tests/src/os/async.cpp b/core-tests/src/os/async.cpp index dffcf9011b3..9a0e514548c 100644 --- a/core-tests/src/os/async.cpp +++ b/core-tests/src/os/async.cpp @@ -24,7 +24,7 @@ #include -using swoole::AsyncEvent; +using namespace swoole; static int callback_count; @@ -48,3 +48,46 @@ TEST(async, dispatch) { ASSERT_EQ(handle_count, 1000); ASSERT_EQ(callback_count, 1000); } + +TEST(async, schedule) { + callback_count = 0; + std::atomic handle_count(0); + + int N = 1000; + + swoole_event_init(SW_EVENTLOOP_WAIT_EXIT); + + AsyncEvent event{}; + event.object = &handle_count; + event.callback = [](AsyncEvent *event) { callback_count++; }; + event.handler = [](AsyncEvent *event) { + usleep(swoole_rand(50000, 100000)); + (*(std::atomic *) event->object)++; + }; + + SwooleG.aio_core_worker_num = 4; + SwooleG.aio_worker_num = 128; + SwooleG.aio_max_wait_time = 0.05; + SwooleG.aio_max_idle_time = 0.5; + + int count = N; + swoole_timer_tick(2, [&count, &event, N](Timer *, TimerNode *timer) { + SW_LOOP_N(swoole_rand(5, 15)) { + auto ret = swoole::async::dispatch(&event); + EXPECT_EQ(ret->object, event.object); + count--; + if (count == 0) { + swoole_timer_del(timer); + ASSERT_EQ(SwooleTG.async_threads->get_worker_num(), 128); + ASSERT_GT(SwooleTG.async_threads->get_queue_size(), 100); + ASSERT_GT(SwooleTG.async_threads->get_task_num(), 100); + break; + } + } + }); + + swoole_event_wait(); + + ASSERT_EQ(handle_count, N); + ASSERT_EQ(callback_count, N); +} diff --git a/ext-src/swoole_coroutine.cc b/ext-src/swoole_coroutine.cc index 7ca006033b5..bd8eb9b7d4e 100644 --- a/ext-src/swoole_coroutine.cc +++ b/ext-src/swoole_coroutine.cc @@ -1011,11 +1011,13 @@ static PHP_METHOD(swoole_coroutine, stats) { return_value, ZEND_STRL("signal_listener_num"), SwooleTG.signal_listener_num + SwooleTG.co_signal_listener_num); if (SwooleTG.async_threads) { - add_assoc_long_ex(return_value, ZEND_STRL("aio_task_num"), SwooleTG.async_threads->task_num); - add_assoc_long_ex(return_value, ZEND_STRL("aio_worker_num"), SwooleTG.async_threads->thread_count()); + add_assoc_long_ex(return_value, ZEND_STRL("aio_task_num"), SwooleTG.async_threads->get_task_num()); + add_assoc_long_ex(return_value, ZEND_STRL("aio_worker_num"), SwooleTG.async_threads->get_worker_num()); + add_assoc_long_ex(return_value, ZEND_STRL("aio_queue_size"), SwooleTG.async_threads->get_queue_size()); } else { add_assoc_long_ex(return_value, ZEND_STRL("aio_task_num"), 0); add_assoc_long_ex(return_value, ZEND_STRL("aio_worker_num"), 0); + add_assoc_long_ex(return_value, ZEND_STRL("aio_queue_size"), 0); } add_assoc_long_ex(return_value, ZEND_STRL("c_stack_size"), Coroutine::get_stack_size()); add_assoc_long_ex(return_value, ZEND_STRL("coroutine_num"), Coroutine::count()); diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 8b43b876f40..21485d607d8 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -2961,6 +2961,10 @@ static PHP_METHOD(swoole_server, stats) { add_assoc_long_ex(return_value, ZEND_STRL("tasking_num"), tasking_num); add_assoc_long_ex(return_value, ZEND_STRL("request_count"), serv->gs->request_count); add_assoc_long_ex(return_value, ZEND_STRL("dispatch_count"), serv->gs->dispatch_count); + add_assoc_long_ex(return_value, ZEND_STRL("pipe_packet_msg_id"), serv->gs->pipe_packet_msg_id); + add_assoc_long_ex(return_value, ZEND_STRL("session_round"), serv->gs->session_round); + add_assoc_long_ex(return_value, ZEND_STRL("min_fd"), serv->gs->min_fd); + add_assoc_long_ex(return_value, ZEND_STRL("max_fd"), serv->gs->max_fd); if (SwooleWG.worker) { add_assoc_long_ex(return_value, ZEND_STRL("worker_request_count"), SwooleWG.worker->request_count); @@ -2982,6 +2986,7 @@ static PHP_METHOD(swoole_server, stats) { } add_assoc_long_ex(return_value, ZEND_STRL("coroutine_num"), Coroutine::count()); + add_assoc_long_ex(return_value, ZEND_STRL("coroutine_peek_num"), Coroutine::get_peak_num()); } static PHP_METHOD(swoole_server, reload) { diff --git a/include/swoole_async.h b/include/swoole_async.h index 19049368724..c069a5d588d 100644 --- a/include/swoole_async.h +++ b/include/swoole_async.h @@ -69,7 +69,7 @@ struct AsyncEvent { class AsyncThreads { public: bool schedule = false; - uint32_t task_num = 0; + size_t task_num = 0; Pipe *pipe = nullptr; async::ThreadPool *pool = nullptr; network::Socket *read_socket = nullptr; @@ -78,7 +78,12 @@ class AsyncThreads { AsyncThreads(); ~AsyncThreads(); - size_t thread_count(); + size_t get_task_num() { + return task_num; + } + + size_t get_queue_size(); + size_t get_worker_num(); void notify_one(); static int callback(Reactor *reactor, Event *event); diff --git a/include/swoole_memory.h b/include/swoole_memory.h index 8541f1db224..0f9f30aafe4 100644 --- a/include/swoole_memory.h +++ b/include/swoole_memory.h @@ -79,6 +79,7 @@ class GlobalMemory : public MemoryPool { void free(void *ptr); void destroy(); size_t capacity(); + size_t get_memory_size(); }; } // namespace swoole diff --git a/include/swoole_server.h b/include/swoole_server.h index 32f390d618b..c548b44481a 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -237,6 +237,8 @@ class MessageBus { return buffer_size_; } + size_t get_memory_size(); + bool alloc_buffer() { void *_ptr = allocator_->malloc(sizeof(*buffer_) + buffer_size_); if (_ptr) { @@ -467,6 +469,8 @@ struct ListenPort { int listen(); void close(); bool import(int sock); + const char *get_protocols(); + #ifdef SW_USE_OPENSSL bool ssl_create_context(SSLContext *context); bool ssl_create(Connection *conn, network::Socket *sock); @@ -476,7 +480,6 @@ struct ListenPort { void ssl_set_key_file(const std::string &file) { ssl_context->key_file = file; } - void ssl_set_cert_file(const std::string &file) { ssl_context->cert_file = file; } diff --git a/src/memory/global_memory.cc b/src/memory/global_memory.cc index a29f317a273..682d7cc7417 100644 --- a/src/memory/global_memory.cc +++ b/src/memory/global_memory.cc @@ -124,6 +124,10 @@ size_t GlobalMemory::capacity() { return impl->pagesize - impl->alloc_offset; } +size_t GlobalMemory::get_memory_size() { + return impl->pagesize * impl->pages.size(); +} + GlobalMemory::~GlobalMemory() { delete impl; } diff --git a/src/os/async_thread.cc b/src/os/async_thread.cc index efe16c8337e..16ae5c3e179 100644 --- a/src/os/async_thread.cc +++ b/src/os/async_thread.cc @@ -156,11 +156,11 @@ class ThreadPool { return _event_copy; } - inline size_t worker_count() { + inline size_t get_worker_num() { return threads.size(); } - inline size_t queue_count() { + inline size_t get_queue_size() { std::unique_lock lock(event_mutex); return _queue.count(); } @@ -361,8 +361,12 @@ int AsyncThreads::callback(Reactor *reactor, Event *event) { return SW_OK; } -size_t AsyncThreads::thread_count() { - return pool ? pool->worker_count() : 0; +size_t AsyncThreads::get_worker_num() { + return pool ? pool->get_worker_num() : 0; +} + +size_t AsyncThreads::get_queue_size() { + return pool ? pool->get_queue_size() : 0; } void AsyncThreads::notify_one() { diff --git a/src/server/message_bus.cc b/src/server/message_bus.cc index e7036829c90..408aa3fc90f 100644 --- a/src/server/message_bus.cc +++ b/src/server/message_bus.cc @@ -268,4 +268,12 @@ bool MessageBus::write(Socket *sock, SendData *resp) { return true; } +size_t MessageBus::get_memory_size() { + size_t size = buffer_size_; + for (auto p : packet_pool_) { + size += p.second->size; + } + return size; +} + } // namespace swoole diff --git a/src/server/port.cc b/src/server/port.cc index baf496aeb5f..8bf86645ba3 100644 --- a/src/server/port.cc +++ b/src/server/port.cc @@ -518,10 +518,10 @@ static int Port_onRead_http(Reactor *reactor, ListenPort *port, Event *event) { if (!request->header_parsed) { request->parse_header_info(); swoole_trace_log(SW_TRACE_SERVER, - "content-length=%u, keep-alive=%u, chunked=%u", - request->content_length_, - request->keep_alive, - request->chunked); + "content-length=%u, keep-alive=%u, chunked=%u", + request->content_length_, + request->keep_alive, + request->chunked); } // content length (equal to 0) or (field not found but not chunked) @@ -614,11 +614,12 @@ static int Port_onRead_http(Reactor *reactor, ListenPort *port, Event *event) { if (request->has_expect_header()) { _socket->send(SW_STRL(SW_HTTP_100_CONTINUE_PACKET), 0); } else { - swoole_trace_log(SW_TRACE_SERVER, - "PostWait: request->content_length=%d, buffer->length=%zu, request->header_length=%d\n", - request->content_length, - buffer_->length, - request->header_length); + swoole_trace_log( + SW_TRACE_SERVER, + "PostWait: request->content_length=%d, buffer->length=%zu, request->header_length=%d\n", + request->content_length, + buffer_->length, + request->header_length); } #endif goto _recv_data; @@ -723,4 +724,31 @@ void ListenPort::close() { } } +const char *ListenPort::get_protocols() { + if (open_eof_check) { + return "eof"; + } else if (open_length_check) { + return "length"; + } else if (open_http_protocol) { +#ifdef SW_USE_HTTP2 + if (open_http2_protocol && open_websocket_protocol) { + return "http|http2|websocket"; + } else if (open_http2_protocol) { + return "http|http2"; + } else +#endif + if (open_websocket_protocol) { + return "http|websocket"; + } else { + return "http"; + } + } else if (open_mqtt_protocol) { + return "mqtt"; + } else if (open_redis_protocol) { + return "redis"; + } else { + return "raw"; + } +} + } // namespace swoole diff --git a/src/server/process.cc b/src/server/process.cc index 32eba8dd9d0..e467b993c46 100644 --- a/src/server/process.cc +++ b/src/server/process.cc @@ -28,7 +28,7 @@ bool ProcessFactory::shutdown() { int status; if (swoole_kill(server_->gs->manager_pid, SIGTERM) < 0) { - swoole_sys_warning("swKill(%d) failed", server_->gs->manager_pid); + swoole_sys_warning("kill(%d) failed", server_->gs->manager_pid); } if (swoole_waitpid(server_->gs->manager_pid, &status, 0) < 0) { @@ -97,7 +97,7 @@ bool ProcessFactory::start() { * The manager process must be started first, otherwise it will have a thread fork */ if (server_->start_manager_process() < 0) { - swoole_warning("FactoryProcess_manager_start failed"); + swoole_warning("failed to start"); return false; } return true; @@ -262,7 +262,6 @@ bool ProcessFactory::end(SessionId session_id, int flags) { } // Reset send buffer, Immediately close the connection. if (flags & Server::CLOSE_RESET) { - swoole_warning("close session=%ld, force", session_id); conn->close_reset = 1; } // Server is initiative to close the connection diff --git a/tests/swoole_server/bug_11000_01.phpt b/tests/swoole_server/bug_11000_01.phpt index 968c10655c8..ab00d3558e8 100644 --- a/tests/swoole_server/bug_11000_01.phpt +++ b/tests/swoole_server/bug_11000_01.phpt @@ -26,7 +26,7 @@ $pm->childFirst(); $pm->run(); ?> --EXPECTF-- -array(13) { +array(%d) { ["start_time"]=> int(%d) ["connection_num"]=> @@ -47,10 +47,20 @@ array(13) { int(0) ["dispatch_count"]=> int(0) + ["pipe_packet_msg_id"]=> + int(%d) + ["session_round"]=> + int(0) + ["min_fd"]=> + int(%d) + ["max_fd"]=> + int(%d) ["worker_request_count"]=> int(0) ["worker_dispatch_count"]=> int(0) ["coroutine_num"]=> int(0) + ["coroutine_peek_num"]=> + int(0) } diff --git a/tests/swoole_server/stats_file.phpt b/tests/swoole_server/stats_file.phpt index c58bca9302e..9c08d692b5b 100644 --- a/tests/swoole_server/stats_file.phpt +++ b/tests/swoole_server/stats_file.phpt @@ -69,6 +69,11 @@ task_worker_num: %d tasking_num: %d request_count: %d dispatch_count: %d +pipe_packet_msg_id: %d +session_round: %d +min_fd: %d +max_fd: %d worker_request_count: %d worker_dispatch_count: %d coroutine_num: %d +coroutine_peek_num: %d From ce9b63e131e57e1d6e9c766d8ef72c999c33338e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Sun, 26 Sep 2021 13:56:01 +0800 Subject: [PATCH 249/936] Improve stats 2 (#4412) * Improve server stats * Fix tests * Optimize code --- ext-src/swoole_server.cc | 26 ++++--- include/swoole_process_pool.h | 4 +- include/swoole_server.h | 25 +++++-- src/server/master.cc | 68 ++++++++++++------- src/server/process.cc | 3 +- src/server/reactor_thread.cc | 47 +++++++++---- .../websocket/ssl_1.phpt | 4 +- tests/swoole_redis_coro/stream.phpt | 4 +- tests/swoole_server/bug_11000_01.phpt | 45 ++---------- tests/swoole_server/stats_file.phpt | 42 ++++-------- 10 files changed, 137 insertions(+), 131 deletions(-) diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 21485d607d8..6804eea3303 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -2939,6 +2939,7 @@ static PHP_METHOD(swoole_server, stats) { array_init(return_value); add_assoc_long_ex(return_value, ZEND_STRL("start_time"), serv->gs->start_time); add_assoc_long_ex(return_value, ZEND_STRL("connection_num"), serv->gs->connection_num); + add_assoc_long_ex(return_value, ZEND_STRL("abort_count"), serv->gs->abort_count); add_assoc_long_ex(return_value, ZEND_STRL("accept_count"), serv->gs->accept_count); add_assoc_long_ex(return_value, ZEND_STRL("close_count"), serv->gs->close_count); /** @@ -2949,18 +2950,16 @@ static PHP_METHOD(swoole_server, stats) { tasking_num = serv->gs->tasking_num = 0; } - uint32_t idle_worker_num = 0; - uint32_t worker_num = serv->worker_num; - uint32_t task_worker_num = serv->task_worker_num; - - add_assoc_long_ex(return_value, ZEND_STRL("worker_num"), worker_num); - idle_worker_num = serv->get_idle_worker_num(); - - add_assoc_long_ex(return_value, ZEND_STRL("idle_worker_num"), idle_worker_num); - add_assoc_long_ex(return_value, ZEND_STRL("task_worker_num"), task_worker_num); + add_assoc_long_ex(return_value, ZEND_STRL("worker_num"), serv->worker_num); + add_assoc_long_ex(return_value, ZEND_STRL("task_worker_num"), serv->task_worker_num); + add_assoc_long_ex(return_value, ZEND_STRL("user_worker_num"), serv->get_user_worker_num()); + add_assoc_long_ex(return_value, ZEND_STRL("idle_worker_num"), serv->get_idle_worker_num()); add_assoc_long_ex(return_value, ZEND_STRL("tasking_num"), tasking_num); - add_assoc_long_ex(return_value, ZEND_STRL("request_count"), serv->gs->request_count); add_assoc_long_ex(return_value, ZEND_STRL("dispatch_count"), serv->gs->dispatch_count); + add_assoc_long_ex(return_value, ZEND_STRL("request_count"), serv->gs->request_count); + add_assoc_long_ex(return_value, ZEND_STRL("response_count"), serv->gs->response_count); + add_assoc_long_ex(return_value, ZEND_STRL("total_recv_bytes"), serv->gs->total_recv_bytes); + add_assoc_long_ex(return_value, ZEND_STRL("total_send_bytes"), serv->gs->total_send_bytes); add_assoc_long_ex(return_value, ZEND_STRL("pipe_packet_msg_id"), serv->gs->pipe_packet_msg_id); add_assoc_long_ex(return_value, ZEND_STRL("session_round"), serv->gs->session_round); add_assoc_long_ex(return_value, ZEND_STRL("min_fd"), serv->gs->min_fd); @@ -2980,9 +2979,8 @@ static PHP_METHOD(swoole_server, stats) { } } - if (task_worker_num > 0) { - idle_worker_num = serv->get_idle_task_worker_num(); - add_assoc_long_ex(return_value, ZEND_STRL("task_idle_worker_num"), idle_worker_num); + if (serv->task_worker_num > 0) { + add_assoc_long_ex(return_value, ZEND_STRL("task_idle_worker_num"), serv->get_idle_task_worker_num()); } add_assoc_long_ex(return_value, ZEND_STRL("coroutine_num"), Coroutine::count()); @@ -4007,7 +4005,7 @@ static PHP_METHOD(swoole_connection_iterator, key) { static PHP_METHOD(swoole_connection_iterator, count) { ConnectionIterator *iterator = php_swoole_connection_iterator_get_and_check_ptr(ZEND_THIS); if (iterator->port) { - RETURN_LONG(*iterator->port->connection_num); + RETURN_LONG(iterator->port->gs->connection_num); } else { RETURN_LONG(iterator->serv->gs->connection_num); } diff --git a/include/swoole_process_pool.h b/include/swoole_process_pool.h index 10c086d1593..18d538738fa 100644 --- a/include/swoole_process_pool.h +++ b/include/swoole_process_pool.h @@ -137,8 +137,8 @@ struct Worker { time_t start_time; - long dispatch_count; - long request_count; + sw_atomic_long_t dispatch_count; + sw_atomic_long_t request_count; size_t coroutine_num; /** diff --git a/include/swoole_server.h b/include/swoole_server.h index c548b44481a..b54b54f02cb 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -323,6 +323,18 @@ struct ReactorThread { int init(Server *serv, Reactor *reactor, uint16_t reactor_id); }; +struct ServerPortGS { + sw_atomic_t connection_num; + sw_atomic_long_t abort_count; + sw_atomic_long_t accept_count; + sw_atomic_long_t close_count; + sw_atomic_long_t dispatch_count; + sw_atomic_long_t request_count; + sw_atomic_long_t response_count; + sw_atomic_long_t total_recv_bytes; + sw_atomic_long_t total_send_bytes; +}; + struct ListenPort { /** * tcp socket listen backlog @@ -434,7 +446,7 @@ struct ListenPort { #endif #endif - sw_atomic_t *connection_num = nullptr; + ServerPortGS *gs = nullptr; Protocol protocol = {}; void *ptr = nullptr; @@ -516,10 +528,14 @@ struct ServerGS { time_t start_time; sw_atomic_t connection_num; sw_atomic_t tasking_num; + sw_atomic_long_t abort_count; sw_atomic_long_t accept_count; sw_atomic_long_t close_count; - sw_atomic_long_t request_count; sw_atomic_long_t dispatch_count; + sw_atomic_long_t request_count; + sw_atomic_long_t response_count; + sw_atomic_long_t total_recv_bytes; + sw_atomic_long_t total_send_bytes; sw_atomic_long_t pipe_packet_msg_id; sw_atomic_t spinlock; @@ -907,7 +923,7 @@ class Server { } network::Socket *get_command_reply_socket() { - return is_base_mode() ? get_worker(0)->pipe_master : pipe_command->get_socket(false); + return is_base_mode() ? get_worker(0)->pipe_master : pipe_command->get_socket(false); } /** @@ -1070,6 +1086,7 @@ class Server { int add_hook(enum HookType type, const Callback &func, int push_back); bool add_command(const std::string &command, int accepted_process_types, const Command::Handler &func); Connection *add_connection(ListenPort *ls, network::Socket *_socket, int server_fd); + void abort_connection(Reactor *reactor, ListenPort *ls, network::Socket *_socket); int connection_incoming(Reactor *reactor, Connection *conn); int get_idle_worker_num(); @@ -1467,7 +1484,7 @@ class Server { enum Mode mode_; Connection *connection_list = nullptr; Session *session_list = nullptr; - uint32_t *port_connnection_num_list = nullptr; + ServerPortGS *port_gs_list = nullptr; /** * http static file directory */ diff --git a/src/server/master.cc b/src/server/master.cc index 714cc5202cf..4b5123e8a71 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -186,7 +186,7 @@ int Server::accept_connection(Reactor *reactor, Event *event) { if (sock->fd >= (int) serv->max_connection) { swoole_error_log( SW_LOG_WARNING, SW_ERROR_SERVER_TOO_MANY_SOCKET, "Too many connections [now: %d]", sock->fd); - sock->free(); + serv->abort_connection(reactor, listen_host, sock); serv->disable_accept(); return SW_OK; } @@ -194,7 +194,7 @@ int Server::accept_connection(Reactor *reactor, Event *event) { // add to connection_list Connection *conn = serv->add_connection(listen_host, sock, event->fd); if (conn == nullptr) { - sock->free(); + serv->abort_connection(reactor, listen_host, sock); return SW_OK; } sock->chunk_size = SW_SEND_BUFFER_SIZE; @@ -202,7 +202,7 @@ int Server::accept_connection(Reactor *reactor, Event *event) { #ifdef SW_USE_OPENSSL if (listen_host->ssl) { if (!listen_host->ssl_create(conn, sock)) { - reactor->close(reactor, sock); + serv->abort_connection(reactor, listen_host, sock); return SW_OK; } } else { @@ -211,7 +211,7 @@ int Server::accept_connection(Reactor *reactor, Event *event) { #endif if (serv->single_thread) { if (serv->connection_incoming(reactor, conn) < 0) { - reactor->close(reactor, sock); + serv->abort_connection(reactor, listen_host, sock); return SW_OK; } } else { @@ -220,7 +220,7 @@ int Server::accept_connection(Reactor *reactor, Event *event) { ev.fd = conn->session_id; ev.reactor_id = conn->reactor_id; if (serv->send_to_reactor_thread((EventData *) &ev, sizeof(ev), conn->session_id) < 0) { - reactor->close(reactor, sock); + serv->abort_connection(reactor, listen_host, sock); return SW_OK; } } @@ -250,7 +250,6 @@ int Server::connection_incoming(Reactor *reactor, Connection *conn) { // notify worker process if (onConnect) { if (!notify(conn, SW_SERVER_EVENT_CONNECT)) { - printf("notify faile\n"); return SW_ERR; } } @@ -777,15 +776,15 @@ int Server::create() { return SW_ERR; } - port_connnection_num_list = (uint32_t *) sw_shm_calloc(ports.size(), sizeof(sw_atomic_t)); - if (port_connnection_num_list == nullptr) { + port_gs_list = (ServerPortGS *) sw_shm_calloc(ports.size(), sizeof(ServerPortGS)); + if (port_gs_list == nullptr) { swoole_error("sw_shm_calloc() for port_connnection_num_array failed"); return SW_ERR; } int index = 0; for (auto port : ports) { - port->connection_num = &port_connnection_num_list[index++]; + port->gs = &port_gs_list[index++]; } if (enable_static_handler and locations == nullptr) { @@ -983,11 +982,11 @@ void Server::destroy() { } #endif sw_shm_free(session_list); - sw_shm_free(port_connnection_num_list); + sw_shm_free(port_gs_list); sw_shm_free(workers); session_list = nullptr; - port_connnection_num_list = nullptr; + port_gs_list = nullptr; workers = nullptr; delete factory; @@ -1155,7 +1154,17 @@ bool Server::send(SessionId session_id, const void *data, uint32_t length) { _send.info.type = SW_SERVER_EVENT_SEND_DATA; _send.data = (char *) data; _send.info.len = length; - return factory->finish(&_send); + if (factory->finish(&_send)) { + sw_atomic_fetch_add(&gs->response_count, 1); + sw_atomic_fetch_add(&gs->total_send_bytes, length); + ListenPort *port = get_port_by_session_id(session_id); + if (port) { + sw_atomic_fetch_add(&port->gs->response_count, 1); + sw_atomic_fetch_add(&port->gs->total_send_bytes, length); + } + return true; + } + return false; } int Server::schedule_worker(int fd, SendData *data) { @@ -1835,24 +1844,22 @@ void Server::foreach_connection(const std::function &callbac } } +void Server::abort_connection(Reactor *reactor, ListenPort *ls, Socket *_socket) { + sw_atomic_fetch_add(&gs->abort_count, 1); + sw_atomic_fetch_add(&ls->gs->abort_count, 1); + if (_socket->object) { + reactor->close(reactor, _socket); + } else { + _socket->free(); + } +} + /** * new connection */ Connection *Server::add_connection(ListenPort *ls, Socket *_socket, int server_fd) { - gs->accept_count++; - sw_atomic_fetch_add(&gs->connection_num, 1); - sw_atomic_fetch_add(ls->connection_num, 1); - int fd = _socket->fd; - lock(); - if (fd > get_maxfd()) { - set_maxfd(fd); - } else if (fd < get_minfd()) { - set_minfd(fd); - } - unlock(); - Connection *connection = &(connection_list[fd]); ReactorId reactor_id = is_base_mode() ? SwooleG.process_id : fd % reactor_num; *connection = {}; @@ -1923,6 +1930,19 @@ Connection *Server::add_connection(ListenPort *ls, Socket *_socket, int server_f _socket->direct_send = 1; } + lock(); + if (fd > get_maxfd()) { + set_maxfd(fd); + } else if (fd < get_minfd()) { + set_minfd(fd); + } + unlock(); + + gs->accept_count++; + ls->gs->accept_count++; + sw_atomic_fetch_add(&gs->connection_num, 1); + sw_atomic_fetch_add(&ls->gs->connection_num, 1); + return connection; } diff --git a/src/server/process.cc b/src/server/process.cc index e467b993c46..605007244c9 100644 --- a/src/server/process.cc +++ b/src/server/process.cc @@ -154,8 +154,7 @@ bool ProcessFactory::dispatch(SendData *task) { Worker *worker = server_->get_worker(target_worker_id); if (task->info.type == SW_SERVER_EVENT_RECV_DATA) { - worker->dispatch_count++; - server_->gs->dispatch_count++; + sw_atomic_fetch_add(&worker->dispatch_count, 1); } SendData _task; diff --git a/src/server/reactor_thread.cc b/src/server/reactor_thread.cc index b8cf7a9bbe9..0607d8d3d4e 100644 --- a/src/server/reactor_thread.cc +++ b/src/server/reactor_thread.cc @@ -217,6 +217,9 @@ int Server::close_connection(Reactor *reactor, Socket *socket) { sw_atomic_fetch_add(&serv->gs->close_count, 1); sw_atomic_fetch_sub(&serv->gs->connection_num, 1); + sw_atomic_fetch_add(&port->gs->close_count, 1); + sw_atomic_fetch_sub(&port->gs->connection_num, 1); + swoole_trace("Close Event.fd=%d|from=%d", socket->fd, reactor->id); #ifdef SW_USE_OPENSSL @@ -239,8 +242,6 @@ int Server::close_connection(Reactor *reactor, Socket *socket) { socket->recv_buffer = nullptr; } - sw_atomic_fetch_sub(port->connection_num, 1); - if (port->open_http_protocol && conn->object) { serv->destroy_http_request(conn); } @@ -534,7 +535,7 @@ static int ReactorThread_onRead(Reactor *reactor, Event *event) { dtls::Session *session = port->dtls_sessions->find(event->fd)->second; session->append(buffer); if (!session->listened && !session->listen()) { - Server::close_connection(reactor, event->socket); + serv->abort_connection(reactor, port, event->socket); return SW_OK; } } @@ -542,7 +543,8 @@ static int ReactorThread_onRead(Reactor *reactor, Event *event) { ReturnCode code = ReactorThread_verify_ssl_state(reactor, port, event->socket); switch (code) { case SW_ERROR: - return Server::close_connection(reactor, event->socket); + serv->abort_connection(reactor, port, event->socket); + return SW_OK; case SW_READY: #ifdef SW_SUPPORT_DTLS if (event->socket->dtls) { @@ -560,8 +562,15 @@ static int ReactorThread_onRead(Reactor *reactor, Event *event) { #endif conn->last_recv_time = microtime(); + long last_recv_bytes = event->socket->total_recv_bytes; int retval = port->onRead(reactor, port, event); + + long socket_recv_bytes = event->socket->total_recv_bytes - last_recv_bytes; + if (socket_recv_bytes > 0) { + sw_atomic_fetch_add(&port->gs->total_recv_bytes, socket_recv_bytes); + sw_atomic_fetch_add(&serv->gs->total_recv_bytes, socket_recv_bytes); + } if (!conn->active) { return retval; } @@ -911,6 +920,7 @@ int Server::dispatch_task(Protocol *proto, Socket *_socket, const char *data, ui SendData task; Connection *conn = (Connection *) _socket->object; + ListenPort *port = serv->get_port_by_fd(conn->fd); sw_memset_zero(&task.info, sizeof(task.info)); task.info.server_fd = conn->server_fd; @@ -920,23 +930,20 @@ int Server::dispatch_task(Protocol *proto, Socket *_socket, const char *data, ui task.info.type = SW_SERVER_EVENT_RECV_DATA; task.info.time = conn->last_recv_time; - if (serv->is_process_mode()) { - ReactorThread *thread = serv->get_thread(conn->reactor_id); - thread->dispatch_count++; - } + int return_code = SW_OK; swoole_trace("send string package, size=%ld bytes", (long) length); if (serv->stream_socket_file) { Stream *stream = Stream::create(serv->stream_socket_file, 0, SW_SOCK_UNIX_STREAM); if (!stream) { - return SW_ERR; + return_code = SW_ERR; + goto _return; } stream->response = ReactorThread_onStreamResponse; stream->private_data = serv; stream->private_data_2 = conn; stream->private_data_fd = conn->session_id; - ListenPort *port = serv->get_port_by_fd(conn->fd); stream->set_max_length(port->protocol.package_max_length); task.info.fd = conn->session_id; @@ -945,25 +952,37 @@ int Server::dispatch_task(Protocol *proto, Socket *_socket, const char *data, ui _cancel: stream->cancel = 1; delete stream; - return SW_ERR; + return_code = SW_ERR; + goto _return; } if (stream->send(data, length) < 0) { goto _cancel; } - return SW_OK; } else { task.info.fd = conn->fd; task.info.len = length; task.data = data; if (!serv->factory->dispatch(&task)) { - return SW_ERR; + return_code = SW_ERR; + goto _return; } if (length > 0) { sw_atomic_fetch_add(&conn->recv_queued_bytes, length); swoole_trace_log(SW_TRACE_SERVER, "[Master] len=%d, qb=%d\n", length, conn->recv_queued_bytes); } - return SW_OK; } + +_return: + if (return_code == SW_OK) { + if (serv->is_process_mode()) { + ReactorThread *thread = serv->get_thread(conn->reactor_id); + thread->dispatch_count++; + } + sw_atomic_fetch_add(&serv->gs->dispatch_count, 1); + sw_atomic_fetch_add(&port->gs->dispatch_count, 1); + } + + return return_code; } void Server::join_reactor_thread() { diff --git a/tests/swoole_http_client_coro/websocket/ssl_1.phpt b/tests/swoole_http_client_coro/websocket/ssl_1.phpt index eed5932b4ea..49514e592b1 100644 --- a/tests/swoole_http_client_coro/websocket/ssl_1.phpt +++ b/tests/swoole_http_client_coro/websocket/ssl_1.phpt @@ -1,7 +1,9 @@ --TEST-- swoole_http_client_coro/websocket: ssl recv --SKIPIF-- - + --FILE-- + --FILE-- childFunc = function () { $serv = new Server(TCP_SERVER_HOST, $port); $process = new \Swoole\Process(function ($process) use ($serv) { usleep(10000); - var_dump($serv->stats()); + $stats = $serv->stats(); + Assert::isArray($stats); + Assert::keyExists($stats, 'connection_num'); + Assert::keyExists($stats, 'request_count'); $serv->shutdown(); }); $serv->set(['worker_num' => 2, 'log_file' => '/dev/null']); @@ -25,42 +28,4 @@ $pm->childFunc = function () { $pm->childFirst(); $pm->run(); ?> ---EXPECTF-- -array(%d) { - ["start_time"]=> - int(%d) - ["connection_num"]=> - int(0) - ["accept_count"]=> - int(0) - ["close_count"]=> - int(0) - ["worker_num"]=> - int(2) - ["idle_worker_num"]=> - int(2) - ["task_worker_num"]=> - int(0) - ["tasking_num"]=> - int(0) - ["request_count"]=> - int(0) - ["dispatch_count"]=> - int(0) - ["pipe_packet_msg_id"]=> - int(%d) - ["session_round"]=> - int(0) - ["min_fd"]=> - int(%d) - ["max_fd"]=> - int(%d) - ["worker_request_count"]=> - int(0) - ["worker_dispatch_count"]=> - int(0) - ["coroutine_num"]=> - int(0) - ["coroutine_peek_num"]=> - int(0) -} +--EXPECT-- diff --git a/tests/swoole_server/stats_file.phpt b/tests/swoole_server/stats_file.phpt index 9c08d692b5b..22741a68687 100644 --- a/tests/swoole_server/stats_file.phpt +++ b/tests/swoole_server/stats_file.phpt @@ -16,15 +16,20 @@ if (is_file(STATS_FILE)) { $pm = new ProcessManager; $pm->initFreePorts(1); -$pm->parentFunc = function ($pid) use ($pm) -{ - run(function() use ($pm, $pid) { +$pm->parentFunc = function ($pid) use ($pm) { + run(function () use ($pm, $pid) { httpRequest('http://127.0.0.1:' . $pm->getFreePort(0)); for ($i = 0; $i < 4; ++$i) { Co::sleep(0.5); $content = @file_get_contents(STATS_FILE); if ('' != $content) { - echo $content; + $stats = []; + swoole_string($content)->split("\n")->each(function ($value, $key) use (&$stats) { + [$k, $v] = swoole_string($value)->split(":"); + $stats[$k] = trim($v); + }); + Assert::keyExists($stats, 'connection_num'); + Assert::keyExists($stats, 'request_count'); break; } } @@ -33,11 +38,10 @@ $pm->parentFunc = function ($pid) use ($pm) $pm->kill(); }; -$pm->childFunc = function () use ($pm) -{ +$pm->childFunc = function () use ($pm) { $mode = SERVER_MODE_RANDOM; $worker_num = rand(1, 4); - echo "mode: $mode\nworker_num: $worker_num\n"; + phpt_var_dump("mode: $mode\nworker_num: $worker_num\n"); $server = new Swoole\Http\Server('127.0.0.1', $pm->getFreePort(0), $mode); $server->set([ 'stats_file' => STATS_FILE, @@ -48,7 +52,7 @@ $pm->childFunc = function () use ($pm) $pm->wakeup(); }); $server->on('request', function ($request, $response) { - $response->end("

Hello Swoole. #".rand(1000, 9999)."

"); + $response->end("

Hello Swoole. #" . rand(1000, 9999) . "

"); }); $server->start(); }; @@ -56,24 +60,4 @@ $pm->childFunc = function () use ($pm) $pm->childFirst(); $pm->run(); ?> ---EXPECTF-- -mode: %d -worker_num: %d -start_time: %d -connection_num: %d -accept_count: %d -close_count: %d -worker_num: %d -idle_worker_num: %d -task_worker_num: %d -tasking_num: %d -request_count: %d -dispatch_count: %d -pipe_packet_msg_id: %d -session_round: %d -min_fd: %d -max_fd: %d -worker_request_count: %d -worker_dispatch_count: %d -coroutine_num: %d -coroutine_peek_num: %d +--EXPECT-- From 41dced30b35ad3a1d5b1638be776e387ca44f1f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Mon, 27 Sep 2021 10:53:24 +0800 Subject: [PATCH 250/936] Add Server::onBeforeShutdown callback (#4415) * Added onBeforeShutdown callback * Fix tests * Fix tests [2] * declare property --- .github/workflows/ext.yml | 2 +- ext-src/php_swoole_server.h | 49 +++++++------- ext-src/swoole_server.cc | 65 ++++++++++++------- include/swoole_server.h | 1 + src/server/master.cc | 3 + src/server/worker.cc | 3 + .../swoole_server/event/before_shutdown.phpt | 57 ++++++++++++++++ tests/swoole_server/event/worker_exit.phpt | 6 +- 8 files changed, 138 insertions(+), 48 deletions(-) create mode 100644 tests/swoole_server/event/before_shutdown.phpt diff --git a/.github/workflows/ext.yml b/.github/workflows/ext.yml index 2280cfc200c..eb1bd6f52f9 100644 --- a/.github/workflows/ext.yml +++ b/.github/workflows/ext.yml @@ -38,7 +38,7 @@ jobs: make clean && make -j$(sysctl -n hw.ncpu) build-ubuntu-old: - runs-on: ubuntu-16.04 + runs-on: ubuntu-18.04 steps: - uses: actions/checkout@v1 - name: install-deps diff --git a/ext-src/php_swoole_server.h b/ext-src/php_swoole_server.h index 3554f6bb558..97a8e7cce0c 100644 --- a/ext-src/php_swoole_server.h +++ b/ext-src/php_swoole_server.h @@ -27,33 +27,34 @@ //-------------------------------------------------------- enum php_swoole_server_callback_type { - SW_SERVER_CB_onStart, // master - SW_SERVER_CB_onShutdown, // master - SW_SERVER_CB_onWorkerStart, // worker(event & task) - SW_SERVER_CB_onWorkerStop, // worker(event & task) - SW_SERVER_CB_onBeforeReload, // manager - SW_SERVER_CB_onAfterReload, // manager - SW_SERVER_CB_onTask, // worker(task) - SW_SERVER_CB_onFinish, // worker(event & task) - SW_SERVER_CB_onWorkerExit, // worker(event) - SW_SERVER_CB_onWorkerError, // manager - SW_SERVER_CB_onManagerStart, // manager - SW_SERVER_CB_onManagerStop, // manager - SW_SERVER_CB_onPipeMessage, // worker(event & task) + SW_SERVER_CB_onStart, // master + SW_SERVER_CB_onBeforeShutdown, // master + SW_SERVER_CB_onShutdown, // master + SW_SERVER_CB_onWorkerStart, // worker(event & task) + SW_SERVER_CB_onWorkerStop, // worker(event & task) + SW_SERVER_CB_onBeforeReload, // manager + SW_SERVER_CB_onAfterReload, // manager + SW_SERVER_CB_onTask, // worker(task) + SW_SERVER_CB_onFinish, // worker(event & task) + SW_SERVER_CB_onWorkerExit, // worker(event) + SW_SERVER_CB_onWorkerError, // manager + SW_SERVER_CB_onManagerStart, // manager + SW_SERVER_CB_onManagerStop, // manager + SW_SERVER_CB_onPipeMessage, // worker(event & task) }; //-------------------------------------------------------- enum php_swoole_server_port_callback_type { - SW_SERVER_CB_onConnect, // stream, worker(event) - SW_SERVER_CB_onReceive, // stream, worker(event) - SW_SERVER_CB_onClose, // stream, worker(event) - SW_SERVER_CB_onPacket, // dgram, worker(event) - SW_SERVER_CB_onRequest, // http, worker(event) - SW_SERVER_CB_onHandShake, // websocket, worker(event) - SW_SERVER_CB_onOpen, // websocket, worker(event) - SW_SERVER_CB_onMessage, // websocket, worker(event) - SW_SERVER_CB_onDisconnect, // websocket (non websocket connection), worker(event) - SW_SERVER_CB_onBufferFull, // worker(event) - SW_SERVER_CB_onBufferEmpty, // worker(event) + SW_SERVER_CB_onConnect, // stream, worker(event) + SW_SERVER_CB_onReceive, // stream, worker(event) + SW_SERVER_CB_onClose, // stream, worker(event) + SW_SERVER_CB_onPacket, // dgram, worker(event) + SW_SERVER_CB_onRequest, // http, worker(event) + SW_SERVER_CB_onHandShake, // websocket, worker(event) + SW_SERVER_CB_onOpen, // websocket, worker(event) + SW_SERVER_CB_onMessage, // websocket, worker(event) + SW_SERVER_CB_onDisconnect, // websocket (non websocket connection), worker(event) + SW_SERVER_CB_onBufferFull, // worker(event) + SW_SERVER_CB_onBufferEmpty, // worker(event) }; #define PHP_SWOOLE_SERVER_CALLBACK_NUM (SW_SERVER_CB_onPipeMessage + 1) diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 6804eea3303..1972c2d4fb3 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -44,34 +44,36 @@ struct ServerEvent { // clang-format off static std::unordered_map server_event_map({ - { "start", ServerEvent(SW_SERVER_CB_onStart, "Start") }, - { "shutdown", ServerEvent(SW_SERVER_CB_onShutdown, "Shutdown") }, - { "workerstart", ServerEvent(SW_SERVER_CB_onWorkerStart, "WorkerStart") }, - { "workerstop", ServerEvent(SW_SERVER_CB_onWorkerStop, "WorkerStop") }, - { "beforereload", ServerEvent(SW_SERVER_CB_onBeforeReload, "BeforeReload") }, - { "afterreload", ServerEvent(SW_SERVER_CB_onAfterReload, "AfterReload") }, - { "task", ServerEvent(SW_SERVER_CB_onTask, "Task") }, - { "finish", ServerEvent(SW_SERVER_CB_onFinish, "Finish") }, - { "workerexit", ServerEvent(SW_SERVER_CB_onWorkerExit, "WorkerExit") }, - { "workererror", ServerEvent(SW_SERVER_CB_onWorkerError, "WorkerError") }, - { "managerstart", ServerEvent(SW_SERVER_CB_onManagerStart, "ManagerStart") }, - { "managerstop", ServerEvent(SW_SERVER_CB_onManagerStop, "ManagerStop") }, - { "pipemessage", ServerEvent(SW_SERVER_CB_onPipeMessage, "PipeMessage") }, + { "start", ServerEvent(SW_SERVER_CB_onStart, "Start") }, + { "beforeshutdown", ServerEvent(SW_SERVER_CB_onBeforeShutdown, "BeforeShutdown") }, + { "shutdown", ServerEvent(SW_SERVER_CB_onShutdown, "Shutdown") }, + { "workerstart", ServerEvent(SW_SERVER_CB_onWorkerStart, "WorkerStart") }, + { "workerstop", ServerEvent(SW_SERVER_CB_onWorkerStop, "WorkerStop") }, + { "beforereload", ServerEvent(SW_SERVER_CB_onBeforeReload, "BeforeReload") }, + { "afterreload", ServerEvent(SW_SERVER_CB_onAfterReload, "AfterReload") }, + { "task", ServerEvent(SW_SERVER_CB_onTask, "Task") }, + { "finish", ServerEvent(SW_SERVER_CB_onFinish, "Finish") }, + { "workerexit", ServerEvent(SW_SERVER_CB_onWorkerExit, "WorkerExit") }, + { "workererror", ServerEvent(SW_SERVER_CB_onWorkerError, "WorkerError") }, + { "managerstart", ServerEvent(SW_SERVER_CB_onManagerStart, "ManagerStart") }, + { "managerstop", ServerEvent(SW_SERVER_CB_onManagerStop, "ManagerStop") }, + { "pipemessage", ServerEvent(SW_SERVER_CB_onPipeMessage, "PipeMessage") }, }); // clang-format on // server event callback -static void php_swoole_onPipeMessage(Server *serv, EventData *req); static void php_swoole_server_onStart(Server *); -static void php_swoole_onShutdown(Server *); +static void php_swoole_server_onBeforeShutdown(Server *serv); +static void php_swoole_server_onShutdown(Server *); static void php_swoole_server_onWorkerStart(Server *, int worker_id); static void php_swoole_server_onBeforeReload(Server *serv); static void php_swoole_server_onAfterReload(Server *serv); static void php_swoole_server_onWorkerStop(Server *, int worker_id); static void php_swoole_server_onWorkerExit(Server *serv, int worker_id); -static void php_swoole_onUserWorkerStart(Server *serv, Worker *worker); +static void php_swoole_server_onUserWorkerStart(Server *serv, Worker *worker); static int php_swoole_server_onTask(Server *, EventData *task); static int php_swoole_server_onFinish(Server *, EventData *task); +static void php_swoole_server_onPipeMessage(Server *serv, EventData *req); static void php_swoole_server_onWorkerError(Server *serv, int worker_id, const ExitStatus &exit_status); static void php_swoole_server_onManagerStart(Server *serv); static void php_swoole_server_onManagerStop(Server *serv); @@ -720,6 +722,7 @@ void php_swoole_server_minit(int module_number) { #endif // ---------------------------------------Server Property------------------------------------- zend_declare_property_null(swoole_server_ce, ZEND_STRL("onStart"), ZEND_ACC_PRIVATE); + zend_declare_property_null(swoole_server_ce, ZEND_STRL("onBeforeShutdown"), ZEND_ACC_PRIVATE); zend_declare_property_null(swoole_server_ce, ZEND_STRL("onShutdown"), ZEND_ACC_PRIVATE); zend_declare_property_null(swoole_server_ce, ZEND_STRL("onWorkerStart"), ZEND_ACC_PRIVATE); zend_declare_property_null(swoole_server_ce, ZEND_STRL("onWorkerStop"), ZEND_ACC_PRIVATE); @@ -746,6 +749,7 @@ void php_swoole_server_minit(int module_number) { zend_declare_property_bool(swoole_server_ce, ZEND_STRL("taskworker"), 0, ZEND_ACC_PUBLIC); zend_declare_property_long(swoole_server_ce, ZEND_STRL("worker_pid"), 0, ZEND_ACC_PUBLIC); zend_declare_property_null(swoole_server_ce, ZEND_STRL("stats_timer"), ZEND_ACC_PUBLIC); + zend_declare_property_null(swoole_server_ce, ZEND_STRL("admin_server"), ZEND_ACC_PUBLIC); /** * mode type @@ -1158,7 +1162,8 @@ void ServerObject::on_before_start() { void ServerObject::register_callback() { // control plane serv->onStart = php_swoole_server_onStart; - serv->onShutdown = php_swoole_onShutdown; + serv->onBeforeShutdown = php_swoole_server_onBeforeShutdown; + serv->onShutdown = php_swoole_server_onShutdown; serv->onWorkerStart = php_swoole_server_onWorkerStart; serv->onWorkerStop = php_swoole_server_onWorkerStop; serv->onWorkerExit = php_swoole_server_onWorkerExit; @@ -1174,7 +1179,7 @@ void ServerObject::register_callback() { serv->onFinish = php_swoole_server_onFinish; } if (property->callbacks[SW_SERVER_CB_onPipeMessage] != nullptr) { - serv->onPipeMessage = php_swoole_onPipeMessage; + serv->onPipeMessage = php_swoole_server_onPipeMessage; } if (serv->send_yield && serv->is_support_unsafe_events()) { serv->onBufferEmpty = php_swoole_server_onBufferEmpty; @@ -1210,7 +1215,7 @@ static int php_swoole_task_finish(Server *serv, zval *zdata, EventData *current_ return ret; } -static void php_swoole_onPipeMessage(Server *serv, EventData *req) { +static void php_swoole_server_onPipeMessage(Server *serv, EventData *req) { ServerObject *server_object = server_fetch_object(Z_OBJ_P((zval *) serv->private_data_2)); zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onPipeMessage]; zval *zserv = (zval *) serv->private_data_2; @@ -1611,7 +1616,23 @@ static void php_swoole_server_onManagerStop(Server *serv) { } } -static void php_swoole_onShutdown(Server *serv) { +static void php_swoole_server_onBeforeShutdown(Server *serv) { + serv->lock(); + zval *zserv = (zval *) serv->private_data_2; + ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); + auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onBeforeShutdown]; + + if (SWOOLE_G(enable_library)) { + zend::function::call("\\Swoole\\Server\\Helper::onBeforeShutdown", 1, zserv); + } + + if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, serv->is_enable_coroutine()))) { + php_swoole_error(E_WARNING, "%s->onBeforeShutdown handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); + } + serv->unlock(); +} + +static void php_swoole_server_onShutdown(Server *serv) { serv->lock(); zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); @@ -1723,7 +1744,7 @@ static void php_swoole_server_onWorkerExit(Server *serv, int worker_id) { } } -static void php_swoole_onUserWorkerStart(Server *serv, Worker *worker) { +static void php_swoole_server_onUserWorkerStart(Server *serv, Worker *worker) { zval *object = (zval *) worker->ptr; zend_update_property_long(swoole_process_ce, SW_Z8_OBJ_P(object), ZEND_STRL("id"), SwooleG.process_id); @@ -2613,7 +2634,7 @@ static PHP_METHOD(swoole_server, addProcess) { } if (serv->onUserWorkerStart == nullptr) { - serv->onUserWorkerStart = php_swoole_onUserWorkerStart; + serv->onUserWorkerStart = php_swoole_server_onUserWorkerStart; } zval *tmp_process = (zval *) emalloc(sizeof(zval)); diff --git a/include/swoole_server.h b/include/swoole_server.h index b54b54f02cb..b5419144852 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -1015,6 +1015,7 @@ class Server { * Master Process */ std::function onStart; + std::function onBeforeShutdown; std::function onShutdown; /** * Manager Process diff --git a/src/server/master.cc b/src/server/master.cc index 4b5123e8a71..fbebd5d826e 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -885,6 +885,9 @@ void Server::shutdown() { kill(gs->master_pid, SIGTERM); return; } + if (is_process_mode() && onBeforeShutdown) { + onBeforeShutdown(this); + } running = false; // stop all thread if (SwooleTG.reactor) { diff --git a/src/server/worker.cc b/src/server/worker.cc index db86b05469b..17f9df0e84f 100644 --- a/src/server/worker.cc +++ b/src/server/worker.cc @@ -431,6 +431,9 @@ void Server::stop_async_worker(Worker *worker) { if (is_base_mode()) { if (is_worker()) { + if (worker->id == 0 && gs->event_workers.running == 0 && onBeforeShutdown) { + onBeforeShutdown(this); + } for (auto ls : ports) { reactor->del(ls->socket); } diff --git a/tests/swoole_server/event/before_shutdown.phpt b/tests/swoole_server/event/before_shutdown.phpt new file mode 100644 index 00000000000..8a823b1cb99 --- /dev/null +++ b/tests/swoole_server/event/before_shutdown.phpt @@ -0,0 +1,57 @@ +--TEST-- +swoole_server/event: onBeforeShutdown +--SKIPIF-- + +--FILE-- +setLogFile(FILE); + +$pm->parentFunc = function ($pid) use ($pm) { +}; + +$pm->childFunc = function () use ($pm) { + $serv = new Server('127.0.0.1', $pm->getFreePort()); + $serv->set([ + 'worker_num' => 1, + 'log_file' => '/dev/null', + ]); + $serv->on("start", function (Server $serv) use ($pm) { + $pm->writeLog('master start'); + Event::add(STDIN, function ($fp) { + echo fread($fp, 8192); + }); + $serv->shutdown(); + }); + $serv->on("BeforeShutdown", function (Server $serv) use ($pm) { + $pm->writeLog('before master shutdown'); + Event::del(STDIN); + }); + $serv->on("shutdown", function (Server $serv) use ($pm) { + $pm->writeLog('master shutdown'); + $pm->wakeup(); + }); + $serv->on("Receive", function (Server $serv, $fd, $reactorId, $data) { + }); + $serv->start(); +}; + +$pm->childFirst(); +$pm->run(); + +echo file_get_contents(FILE); +unlink(FILE); +?> +--EXPECT-- +master start +before master shutdown +master shutdown diff --git a/tests/swoole_server/event/worker_exit.phpt b/tests/swoole_server/event/worker_exit.phpt index ca46edefac7..ac8661859ae 100644 --- a/tests/swoole_server/event/worker_exit.phpt +++ b/tests/swoole_server/event/worker_exit.phpt @@ -32,7 +32,7 @@ $pm->childFunc = function () use ($pm, $atomic) { $serv = new Server('127.0.0.1', $pm->getFreePort()); $serv->set([ - "worker_num" => 1, + 'worker_num' => 1, 'log_file' => '/dev/null', ]); @@ -41,10 +41,14 @@ $pm->childFunc = function () use ($pm, $atomic) { }); $serv->on(Constant::EVENT_MANAGER_START, function (Server $serv) use ($atomic, $pm) { + usleep(1000); $pm->writeLog('manager start'); }); $serv->on(Constant::EVENT_WORKER_START, function (Server $serv) use ($atomic, $pm) { + if ($atomic->get() == 0) { + usleep(2000); + } $pm->writeLog('worker start, id=' . $serv->getWorkerId() . ', status=' . $serv->getWorkerStatus()); if ($atomic->add() == 2) { From 280fd497bc2af0e29687870adc1ea065f2ba80ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Mon, 27 Sep 2021 14:24:36 +0800 Subject: [PATCH 251/936] Added worker_response_count (#4417) --- include/swoole_process_pool.h | 1 + include/swoole_server.h | 2 +- src/server/master.cc | 3 +++ src/server/message_bus.cc | 2 +- src/server/reactor_thread.cc | 13 ++++++++----- src/server/worker.cc | 9 +++++++-- 6 files changed, 21 insertions(+), 9 deletions(-) diff --git a/include/swoole_process_pool.h b/include/swoole_process_pool.h index 18d538738fa..19c762c0455 100644 --- a/include/swoole_process_pool.h +++ b/include/swoole_process_pool.h @@ -139,6 +139,7 @@ struct Worker { sw_atomic_long_t dispatch_count; sw_atomic_long_t request_count; + sw_atomic_long_t response_count; size_t coroutine_num; /** diff --git a/include/swoole_server.h b/include/swoole_server.h index b5419144852..a95c833c549 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -280,7 +280,7 @@ class MessageBus { /** * The last chunk of data has been received, return address and length, start processing this packet. */ - PacketPtr get_packet(); + PacketPtr get_packet() const; PipeBuffer *get_buffer() { return buffer_; } diff --git a/src/server/master.cc b/src/server/master.cc index fbebd5d826e..cf739549fde 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -1165,6 +1165,9 @@ bool Server::send(SessionId session_id, const void *data, uint32_t length) { sw_atomic_fetch_add(&port->gs->response_count, 1); sw_atomic_fetch_add(&port->gs->total_send_bytes, length); } + if (SwooleWG.worker) { + SwooleWG.worker->response_count++; + } return true; } return false; diff --git a/src/server/message_bus.cc b/src/server/message_bus.cc index 408aa3fc90f..f059625df0c 100644 --- a/src/server/message_bus.cc +++ b/src/server/message_bus.cc @@ -7,7 +7,7 @@ using swoole::network::Socket; namespace swoole { -PacketPtr MessageBus::get_packet() { +PacketPtr MessageBus::get_packet() const { PacketPtr pkt; if (buffer_->info.flags & SW_EVENT_DATA_PTR) { memcpy(&pkt, buffer_->data, sizeof(pkt)); diff --git a/src/server/reactor_thread.cc b/src/server/reactor_thread.cc index 0607d8d3d4e..be828e93e97 100644 --- a/src/server/reactor_thread.cc +++ b/src/server/reactor_thread.cc @@ -962,13 +962,16 @@ int Server::dispatch_task(Protocol *proto, Socket *_socket, const char *data, ui task.info.fd = conn->fd; task.info.len = length; task.data = data; - if (!serv->factory->dispatch(&task)) { - return_code = SW_ERR; - goto _return; - } if (length > 0) { sw_atomic_fetch_add(&conn->recv_queued_bytes, length); - swoole_trace_log(SW_TRACE_SERVER, "[Master] len=%d, qb=%d\n", length, conn->recv_queued_bytes); + swoole_trace_log( + SW_TRACE_SERVER, "session_id=%ld, len=%d, qb=%d", conn->session_id, length, conn->recv_queued_bytes); + } + if (!serv->factory->dispatch(&task)) { + return_code = SW_ERR; + if (length > 0) { + sw_atomic_fetch_sub(&conn->recv_queued_bytes, length); + } } } diff --git a/src/server/worker.cc b/src/server/worker.cc index 17f9df0e84f..c9708d64319 100644 --- a/src/server/worker.cc +++ b/src/server/worker.cc @@ -222,8 +222,13 @@ void Server::worker_accept_event(DataHead *info) { Connection *conn = get_connection_verify(info->fd); if (conn) { if (info->len > 0) { - sw_atomic_fetch_sub(&conn->recv_queued_bytes, info->len); - swoole_trace_log(SW_TRACE_SERVER, "[Worker] len=%d, qb=%d\n", info->len, conn->recv_queued_bytes); + auto packet = message_bus.get_packet(); + sw_atomic_fetch_sub(&conn->recv_queued_bytes, packet.length); + swoole_trace_log(SW_TRACE_SERVER, + "[Worker] session_id=%ld, len=%d, qb=%d", + conn->session_id, + packet.length, + conn->recv_queued_bytes); } conn->last_dispatch_time = info->time; } From 773dbb21a9c414d9db33459e17f08522a83f3dfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Tue, 28 Sep 2021 21:45:49 +0800 Subject: [PATCH 252/936] Fix #4393 (#4418) * Fix #4393 * Optimize tests --- ext-src/swoole_curl.cc | 21 ++++++++++-- tests/swoole_curl/multi/bug4393.phpt | 51 ++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 tests/swoole_curl/multi/bug4393.phpt diff --git a/ext-src/swoole_curl.cc b/ext-src/swoole_curl.cc index fe3ecaea20a..49af3ce35a3 100644 --- a/ext-src/swoole_curl.cc +++ b/ext-src/swoole_curl.cc @@ -44,6 +44,7 @@ int Multi::cb_error(Reactor *reactor, Event *event) { int Multi::handle_socket(CURL *easy, curl_socket_t s, int action, void *userp, void *socketp) { Multi *multi = (Multi *) userp; + swoole_trace_log(SW_TRACE_CO_CURL, SW_ECHO_CYAN "action=%d, userp=%p, socketp=%p", "[HANDLE_SOCKET]", action, userp, socketp); switch (action) { case CURL_POLL_IN: case CURL_POLL_OUT: @@ -94,7 +95,7 @@ void Multi::del_event(CURL *cp, void *socket_ptr, curl_socket_t sockfd) { Handle *handle = get_handle(cp); handle->socket = nullptr; - swoole_trace_log(SW_TRACE_CO_CURL, SW_ECHO_RED " handle=%p, curl=%p, fd=%d", "[DEL]", handle, cp, sockfd); + swoole_trace_log(SW_TRACE_CO_CURL, SW_ECHO_RED " handle=%p, curl=%p, fd=%d", "[DEL_EVENT]", handle, cp, sockfd); } void Multi::set_event(CURL *cp, void *socket_ptr, curl_socket_t sockfd, int action) { @@ -119,7 +120,7 @@ void Multi::set_event(CURL *cp, void *socket_ptr, curl_socket_t sockfd, int acti handle->action = action; swoole_trace_log( - SW_TRACE_CO_CURL, SW_ECHO_GREEN " handle=%p, curl=%p, fd=%d, events=%d", "[ADD]", handle, cp, sockfd, events); + SW_TRACE_CO_CURL, SW_ECHO_GREEN " handle=%p, curl=%p, fd=%d, events=%d", "[ADD_EVENT]", handle, cp, sockfd, events); } CURLMcode Multi::add_handle(CURL *cp) { @@ -132,6 +133,8 @@ CURLMcode Multi::add_handle(CURL *cp) { curl_easy_setopt(cp, CURLOPT_PRIVATE, handle); } handle->multi = this; + swoole_trace_log( + SW_TRACE_CO_CURL, SW_ECHO_GREEN " handle=%p, curl=%p", "[ADD_HANDLE]", handle, cp); } return retval; } @@ -143,6 +146,8 @@ CURLMcode Multi::remove_handle(CURL *cp) { if (handle) { handle->multi = nullptr; } + swoole_trace_log( + SW_TRACE_CO_CURL, SW_ECHO_RED " handle=%p, curl=%p", "[REMOVE_HANDLE]", handle, cp); } return retval; } @@ -233,6 +238,7 @@ CURLcode Multi::read_info() { int Multi::handle_timeout(CURLM *mh, long timeout_ms, void *userp) { Multi *multi = (Multi *) userp; + swoole_trace_log(SW_TRACE_CO_CURL, SW_ECHO_BLUE "timeout_ms=%d", "[HANDLE_TIMEOUT]", timeout_ms); if (!swoole_event_is_available()) { return 0; } @@ -252,6 +258,10 @@ long Multi::select(php_curlm *mh, double timeout) { return 0; } + if (curl_multi_socket_all(multi_handle_, &running_handles_) != CURLM_OK) { + return CURLE_FAILED_INIT; + } + for (zend_llist_element *element = mh->easyh.head; element; element = element->next) { zval *z_ch = (zval *) element->data; php_curl *ch; @@ -259,6 +269,9 @@ long Multi::select(php_curlm *mh, double timeout) { continue; } Handle *handle = get_handle(ch->cp); + + swoole_trace_log(SW_TRACE_CO_CURL, "handle=%p, handle->socket=%p, handle->socket->removed=%d", handle, handle ? handle->socket :nullptr); + if (handle && handle->socket && handle->socket->removed) { if (swoole_event_add(handle->socket, get_event(handle->action)) == SW_OK) { event_count_++; @@ -278,6 +291,8 @@ long Multi::select(php_curlm *mh, double timeout) { co->yield_ex(timeout); co = nullptr; + swoole_trace_log(SW_TRACE_CO_CURL, "yield timeout, count=%d", zend_llist_count(&mh->easyh)); + auto count = selector->active_handles.size(); for (zend_llist_element *element = mh->easyh.head; element; element = element->next) { @@ -297,7 +312,7 @@ long Multi::select(php_curlm *mh, double timeout) { if (selector->timer_callback) { selector->timer_callback = false; - curl_multi_socket_action(multi_handle_, -1, 0, &running_handles_); + curl_multi_socket_action(multi_handle_, CURL_SOCKET_TIMEOUT, 0, &running_handles_); swoole_trace_log(SW_TRACE_CO_CURL, "socket_action[timer], running_handles=%d", running_handles_); } diff --git a/tests/swoole_curl/multi/bug4393.phpt b/tests/swoole_curl/multi/bug4393.phpt new file mode 100644 index 00000000000..d9819941caa --- /dev/null +++ b/tests/swoole_curl/multi/bug4393.phpt @@ -0,0 +1,51 @@ +--TEST-- +swoole_curl: guzzle +--SKIPIF-- + +--FILE-- + $guzzle->getAsync('https://www.qq.com/'), + 'baidu' => $guzzle->getAsync('http://www.baidu.com/'), + ]; + + $responses = []; + foreach (Promise\Utils::settle($promises)->wait() as $k => $v) { + $responses[$k] = $v['value']; + } + + Assert::contains($responses['baidu']->getBody(), '百度'); + Assert::contains(iconv('gbk', 'utf-8', $responses['qq']->getBody()), '腾讯'); + }; + + $n = 2; + while ($n--) { + $s = microtime(true); + $test(); + Assert::lessThan(microtime(true) - $s, 1.5); + } + + echo 'Done' . PHP_EOL; +}); +?> +--EXPECT-- +Done From 1f0ddedaf172b11a3184ee3034ff427df7576988 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Wed, 29 Sep 2021 11:08:57 +0800 Subject: [PATCH 253/936] Optimize code, fix Server::stats() --- ext-src/swoole_server.cc | 1 + include/swoole_server.h | 2 +- src/server/master.cc | 12 +++++++----- src/server/worker.cc | 9 +++++++-- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 1972c2d4fb3..eb820382523 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -2988,6 +2988,7 @@ static PHP_METHOD(swoole_server, stats) { if (SwooleWG.worker) { add_assoc_long_ex(return_value, ZEND_STRL("worker_request_count"), SwooleWG.worker->request_count); + add_assoc_long_ex(return_value, ZEND_STRL("worker_response_count"), SwooleWG.worker->response_count); add_assoc_long_ex(return_value, ZEND_STRL("worker_dispatch_count"), SwooleWG.worker->dispatch_count); } diff --git a/include/swoole_server.h b/include/swoole_server.h index a95c833c549..e6e2842e02a 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -263,7 +263,7 @@ class MessageBus { /** * Send data to socket. If the data sent is larger than Server::ipc_max_size, then it is sent in chunks. * Otherwise send it directly. - * @return: send success returns MsgId(must be greater than 0), send failure returns 0. + * @return: send success returns true, send failure returns false. */ bool write(network::Socket *sock, SendData *packet); /** diff --git a/src/server/master.cc b/src/server/master.cc index cf739549fde..59666944fdf 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -878,15 +878,17 @@ void Server::clear_timer() { void Server::shutdown() { swoole_trace_log(SW_TRACE_SERVER, "shutdown service"); - if (swoole_isset_hook(SW_GLOBAL_HOOK_BEFORE_SERVER_SHUTDOWN)) { - swoole_call_hook(SW_GLOBAL_HOOK_BEFORE_SERVER_SHUTDOWN, this); - } if (getpid() != gs->master_pid) { kill(gs->master_pid, SIGTERM); return; } - if (is_process_mode() && onBeforeShutdown) { - onBeforeShutdown(this); + if (is_process_mode()) { + if (swoole_isset_hook(SW_GLOBAL_HOOK_BEFORE_SERVER_SHUTDOWN)) { + swoole_call_hook(SW_GLOBAL_HOOK_BEFORE_SERVER_SHUTDOWN, this); + } + if (onBeforeShutdown) { + onBeforeShutdown(this); + } } running = false; // stop all thread diff --git a/src/server/worker.cc b/src/server/worker.cc index c9708d64319..ea7aef44018 100644 --- a/src/server/worker.cc +++ b/src/server/worker.cc @@ -436,8 +436,13 @@ void Server::stop_async_worker(Worker *worker) { if (is_base_mode()) { if (is_worker()) { - if (worker->id == 0 && gs->event_workers.running == 0 && onBeforeShutdown) { - onBeforeShutdown(this); + if (worker->id == 0 && gs->event_workers.running == 0) { + if (swoole_isset_hook(SW_GLOBAL_HOOK_BEFORE_SERVER_SHUTDOWN)) { + swoole_call_hook(SW_GLOBAL_HOOK_BEFORE_SERVER_SHUTDOWN, this); + } + if (onBeforeShutdown) { + onBeforeShutdown(this); + } } for (auto ls : ports) { reactor->del(ls->socket); From 11576952ea7415d8344e372d4108b4061768b122 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Wed, 29 Sep 2021 17:30:54 +0800 Subject: [PATCH 254/936] Optimize name --- core-tests/src/reactor/base.cpp | 18 +++++++++--------- include/swoole.h | 6 +++--- include/swoole_coroutine_socket.h | 6 +++--- src/coroutine/socket.cc | 6 +++--- src/coroutine/system.cc | 16 ++++++++-------- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/core-tests/src/reactor/base.cpp b/core-tests/src/reactor/base.cpp index d753c544253..b4e567021a5 100644 --- a/core-tests/src/reactor/base.cpp +++ b/core-tests/src/reactor/base.cpp @@ -38,20 +38,20 @@ TEST(reactor, create) { /** * coroutine socket reactor */ - ASSERT_NE(reactor->read_handler[Reactor::get_fd_type(SW_FD_CORO_SOCKET | SW_EVENT_READ)], nullptr); - ASSERT_NE(reactor->write_handler[Reactor::get_fd_type(SW_FD_CORO_SOCKET | SW_EVENT_WRITE)], nullptr); - ASSERT_NE(reactor->error_handler[Reactor::get_fd_type(SW_FD_CORO_SOCKET | SW_EVENT_ERROR)], nullptr); + ASSERT_NE(reactor->read_handler[Reactor::get_fd_type(SW_FD_CO_SOCKET | SW_EVENT_READ)], nullptr); + ASSERT_NE(reactor->write_handler[Reactor::get_fd_type(SW_FD_CO_SOCKET | SW_EVENT_WRITE)], nullptr); + ASSERT_NE(reactor->error_handler[Reactor::get_fd_type(SW_FD_CO_SOCKET | SW_EVENT_ERROR)], nullptr); /** * system reactor */ - ASSERT_NE(reactor->read_handler[Reactor::get_fd_type(SW_FD_CORO_POLL | SW_EVENT_READ)], nullptr); - ASSERT_NE(reactor->write_handler[Reactor::get_fd_type(SW_FD_CORO_POLL | SW_EVENT_WRITE)], nullptr); - ASSERT_NE(reactor->error_handler[Reactor::get_fd_type(SW_FD_CORO_POLL | SW_EVENT_ERROR)], nullptr); + ASSERT_NE(reactor->read_handler[Reactor::get_fd_type(SW_FD_CO_POLL | SW_EVENT_READ)], nullptr); + ASSERT_NE(reactor->write_handler[Reactor::get_fd_type(SW_FD_CO_POLL | SW_EVENT_WRITE)], nullptr); + ASSERT_NE(reactor->error_handler[Reactor::get_fd_type(SW_FD_CO_POLL | SW_EVENT_ERROR)], nullptr); - ASSERT_NE(reactor->read_handler[Reactor::get_fd_type(SW_FD_CORO_EVENT | SW_EVENT_READ)], nullptr); - ASSERT_NE(reactor->write_handler[Reactor::get_fd_type(SW_FD_CORO_EVENT | SW_EVENT_WRITE)], nullptr); - ASSERT_NE(reactor->error_handler[Reactor::get_fd_type(SW_FD_CORO_EVENT | SW_EVENT_ERROR)], nullptr); + ASSERT_NE(reactor->read_handler[Reactor::get_fd_type(SW_FD_CO_EVENT | SW_EVENT_READ)], nullptr); + ASSERT_NE(reactor->write_handler[Reactor::get_fd_type(SW_FD_CO_EVENT | SW_EVENT_WRITE)], nullptr); + ASSERT_NE(reactor->error_handler[Reactor::get_fd_type(SW_FD_CO_EVENT | SW_EVENT_ERROR)], nullptr); ASSERT_NE(reactor->read_handler[Reactor::get_fd_type(SW_FD_AIO | SW_EVENT_READ)], nullptr); diff --git a/include/swoole.h b/include/swoole.h index 9fc49307ca9..e1441164569 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -372,15 +372,15 @@ enum swFdType { /** * Coroutine Socket */ - SW_FD_CORO_SOCKET, + SW_FD_CO_SOCKET, /** * socket poll fd [coroutine::socket_poll] */ - SW_FD_CORO_POLL, + SW_FD_CO_POLL, /** * event waiter */ - SW_FD_CORO_EVENT, + SW_FD_CO_EVENT, /** * signalfd */ diff --git a/include/swoole_coroutine_socket.h b/include/swoole_coroutine_socket.h index 95b540686e7..b6c71695cb8 100644 --- a/include/swoole_coroutine_socket.h +++ b/include/swoole_coroutine_socket.h @@ -147,9 +147,9 @@ class Socket { #endif static inline void init_reactor(Reactor *reactor) { - reactor->set_handler(SW_FD_CORO_SOCKET | SW_EVENT_READ, readable_event_callback); - reactor->set_handler(SW_FD_CORO_SOCKET | SW_EVENT_WRITE, writable_event_callback); - reactor->set_handler(SW_FD_CORO_SOCKET | SW_EVENT_ERROR, error_event_callback); + reactor->set_handler(SW_FD_CO_SOCKET | SW_EVENT_READ, readable_event_callback); + reactor->set_handler(SW_FD_CO_SOCKET | SW_EVENT_WRITE, writable_event_callback); + reactor->set_handler(SW_FD_CO_SOCKET | SW_EVENT_ERROR, error_event_callback); } inline SocketType get_type() { diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index 567241a24fa..dca93e28e84 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -457,7 +457,7 @@ void Socket::init_sock_type(SocketType _sw_type) { } bool Socket::init_sock() { - socket = make_socket(type, SW_FD_CORO_SOCKET, SW_SOCK_CLOEXEC | SW_SOCK_NONBLOCK); + socket = make_socket(type, SW_FD_CO_SOCKET, SW_SOCK_CLOEXEC | SW_SOCK_NONBLOCK); if (socket == nullptr) { return false; } @@ -468,7 +468,7 @@ bool Socket::init_sock() { } bool Socket::init_reactor_socket(int _fd) { - socket = swoole::make_socket(_fd, SW_FD_CORO_SOCKET); + socket = swoole::make_socket(_fd, SW_FD_CO_SOCKET); sock_fd = _fd; socket->object = this; socket->socket_type = type; @@ -526,7 +526,7 @@ Socket::Socket(network::Socket *sock, Socket *server_sock) { socket = sock; socket->object = this; socket->socket_type = type; - socket->fd_type = SW_FD_CORO_SOCKET; + socket->fd_type = SW_FD_CO_SOCKET; init_options(); /* inherits server socket options */ dns_timeout = server_sock->dns_timeout; diff --git a/src/coroutine/system.cc b/src/coroutine/system.cc index a2336a1713e..f7a042873ac 100644 --- a/src/coroutine/system.cc +++ b/src/coroutine/system.cc @@ -455,7 +455,7 @@ bool System::socket_poll(std::unordered_map &fds, double timeou task.co = Coroutine::get_current_safe(); for (auto i = fds.begin(); i != fds.end(); i++) { - i->second.socket = swoole::make_socket(i->first, SW_FD_CORO_POLL); + i->second.socket = swoole::make_socket(i->first, SW_FD_CO_POLL); if (swoole_event_add(i->second.socket, i->second.events) < 0) { i->second.socket->free(); continue; @@ -486,7 +486,7 @@ struct EventWaiter { EventWaiter(int fd, int events, double timeout) { error_ = revents = 0; - socket = swoole::make_socket(fd, SW_FD_CORO_EVENT); + socket = swoole::make_socket(fd, SW_FD_CO_EVENT); socket->object = this; timer = nullptr; co = Coroutine::get_current_safe(); @@ -601,13 +601,13 @@ int System::wait_event(int fd, int events, double timeout) { } void System::init_reactor(Reactor *reactor) { - reactor->set_handler(SW_FD_CORO_POLL | SW_EVENT_READ, socket_poll_read_callback); - reactor->set_handler(SW_FD_CORO_POLL | SW_EVENT_WRITE, socket_poll_write_callback); - reactor->set_handler(SW_FD_CORO_POLL | SW_EVENT_ERROR, socket_poll_error_callback); + reactor->set_handler(SW_FD_CO_POLL | SW_EVENT_READ, socket_poll_read_callback); + reactor->set_handler(SW_FD_CO_POLL | SW_EVENT_WRITE, socket_poll_write_callback); + reactor->set_handler(SW_FD_CO_POLL | SW_EVENT_ERROR, socket_poll_error_callback); - reactor->set_handler(SW_FD_CORO_EVENT | SW_EVENT_READ, event_waiter_read_callback); - reactor->set_handler(SW_FD_CORO_EVENT | SW_EVENT_WRITE, event_waiter_write_callback); - reactor->set_handler(SW_FD_CORO_EVENT | SW_EVENT_ERROR, event_waiter_error_callback); + reactor->set_handler(SW_FD_CO_EVENT | SW_EVENT_READ, event_waiter_read_callback); + reactor->set_handler(SW_FD_CO_EVENT | SW_EVENT_WRITE, event_waiter_write_callback); + reactor->set_handler(SW_FD_CO_EVENT | SW_EVENT_ERROR, event_waiter_error_callback); reactor->set_handler(SW_FD_AIO | SW_EVENT_READ, AsyncThreads::callback); } From 09571b94a26ab15cd745d45cbfcfd97ac9aaa4e9 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Thu, 30 Sep 2021 12:03:24 +0800 Subject: [PATCH 255/936] Optimize code --- ext-src/swoole_server.cc | 10 +--------- include/swoole_server.h | 1 + src/server/master.cc | 9 +++++++++ src/server/port.cc | 3 +++ 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index eb820382523..0417c1bde83 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -2963,19 +2963,10 @@ static PHP_METHOD(swoole_server, stats) { add_assoc_long_ex(return_value, ZEND_STRL("abort_count"), serv->gs->abort_count); add_assoc_long_ex(return_value, ZEND_STRL("accept_count"), serv->gs->accept_count); add_assoc_long_ex(return_value, ZEND_STRL("close_count"), serv->gs->close_count); - /** - * reset - */ - int tasking_num = serv->gs->tasking_num; - if (tasking_num < 0) { - tasking_num = serv->gs->tasking_num = 0; - } - add_assoc_long_ex(return_value, ZEND_STRL("worker_num"), serv->worker_num); add_assoc_long_ex(return_value, ZEND_STRL("task_worker_num"), serv->task_worker_num); add_assoc_long_ex(return_value, ZEND_STRL("user_worker_num"), serv->get_user_worker_num()); add_assoc_long_ex(return_value, ZEND_STRL("idle_worker_num"), serv->get_idle_worker_num()); - add_assoc_long_ex(return_value, ZEND_STRL("tasking_num"), tasking_num); add_assoc_long_ex(return_value, ZEND_STRL("dispatch_count"), serv->gs->dispatch_count); add_assoc_long_ex(return_value, ZEND_STRL("request_count"), serv->gs->request_count); add_assoc_long_ex(return_value, ZEND_STRL("response_count"), serv->gs->response_count); @@ -3003,6 +2994,7 @@ static PHP_METHOD(swoole_server, stats) { if (serv->task_worker_num > 0) { add_assoc_long_ex(return_value, ZEND_STRL("task_idle_worker_num"), serv->get_idle_task_worker_num()); + add_assoc_long_ex(return_value, ZEND_STRL("tasking_num"), serv->get_task_count()); } add_assoc_long_ex(return_value, ZEND_STRL("coroutine_num"), Coroutine::count()); diff --git a/include/swoole_server.h b/include/swoole_server.h index e6e2842e02a..a6efb9b50f6 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -1092,6 +1092,7 @@ class Server { int get_idle_worker_num(); int get_idle_task_worker_num(); + int get_task_count(); inline int get_minfd() { return gs->min_fd; diff --git a/src/server/master.cc b/src/server/master.cc index 59666944fdf..dfc6131343c 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -2004,4 +2004,13 @@ int Server::get_idle_task_worker_num() { return idle_worker_num; } +int Server::get_task_count() { + // TODO Why need to reset ? + int tasking_num = gs->tasking_num; + if (tasking_num < 0) { + tasking_num = gs->tasking_num = 0; + } + return tasking_num; +} + } // namespace swoole diff --git a/src/server/port.cc b/src/server/port.cc index 8bf86645ba3..bd5b3d0325d 100644 --- a/src/server/port.cc +++ b/src/server/port.cc @@ -725,6 +725,9 @@ void ListenPort::close() { } const char *ListenPort::get_protocols() { + if (is_dgram()) { + return "dgram"; + } if (open_eof_check) { return "eof"; } else if (open_length_check) { From f9089997d15f04d2e6213738d1fd4e412558feeb Mon Sep 17 00:00:00 2001 From: matyhtf Date: Mon, 4 Oct 2021 10:46:47 +0800 Subject: [PATCH 256/936] add type_conv.phpt for Table --- tests/swoole_table/type_conv.phpt | 44 +++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 tests/swoole_table/type_conv.phpt diff --git a/tests/swoole_table/type_conv.phpt b/tests/swoole_table/type_conv.phpt new file mode 100644 index 00000000000..a29e1ce362e --- /dev/null +++ b/tests/swoole_table/type_conv.phpt @@ -0,0 +1,44 @@ +--TEST-- +swoole_table: type convert +--SKIPIF-- + +--FILE-- +column('id', swoole_table::TYPE_INT); +$table->column('name', swoole_table::TYPE_STRING, 128); +$table->column('num', swoole_table::TYPE_FLOAT); + +if (!$table->create()) { + echo __LINE__." error"; +} + +$table->set('test_key', array('id' => 1, 'name' => NAME, 'num' => PI)); +$table->set(1002, array('id' => '2', 'name' => 'hello', 'num' => PI + 9)); + +$r1 = ($table->get('test_key')); +$r2 = ($table->get(1002)); + +Assert::same($r1['id'], 1); +Assert::same($r2['id'], 2); + +$table->set('test_key', array('id' => '2348', 'name' => 1024, 'num' => '3.231')); +$r1 = ($table->get('test_key')); + +Assert::same($r1['id'], 2348); +Assert::same($r1['num'], 3.231); +Assert::same($r1['name'], '1024'); + +$table->set('test_key', array('id' => 'abc', 'name' => 1024, 'num' => '3.231')); +$r1 = ($table->get('test_key')); +Assert::same($r1['id'], 0); + +?> +--EXPECT-- +SUCCESS From 241737abd8a2791a0ba86cc50d5d9921477f4e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Fri, 8 Oct 2021 10:02:37 +0800 Subject: [PATCH 257/936] Optimize send_yield (#4422) * Optimize server send_yield * revert * fix tests, code formart --- ext-src/swoole_server.cc | 53 ++++++++++++++++--------------- src/server/worker.cc | 1 - tests/swoole_table/type_conv.phpt | 1 - 3 files changed, 27 insertions(+), 28 deletions(-) diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 0417c1bde83..0d7c0fec2ba 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -1839,17 +1839,17 @@ void php_swoole_server_onClose(Server *serv, DataHead *info) { SessionId session_id = info->fd; if (serv->enable_coroutine && serv->send_yield) { - auto _i_coros_list = server_object->property->send_coroutine_map.find(session_id); - if (_i_coros_list != server_object->property->send_coroutine_map.end()) { - auto coros_list = _i_coros_list->second; + auto _i_co_list = server_object->property->send_coroutine_map.find(session_id); + if (_i_co_list != server_object->property->send_coroutine_map.end()) { + auto co_list = _i_co_list->second; server_object->property->send_coroutine_map.erase(session_id); - while (!coros_list->empty()) { - Coroutine *co = coros_list->front(); - coros_list->pop_front(); + while (!co_list->empty()) { + Coroutine *co = co_list->front(); + co_list->pop_front(); swoole_set_last_error(ECONNRESET); co->resume(); } - delete coros_list; + delete co_list; } } @@ -1921,7 +1921,6 @@ void php_swoole_server_onBufferFull(Server *serv, DataHead *info) { void php_swoole_server_send_yield(Server *serv, SessionId session_id, zval *zdata, zval *return_value) { ServerObject *server_object = server_fetch_object(Z_OBJ_P((zval *) serv->private_data_2)); - std::list *coros_list; Coroutine *co = Coroutine::get_current_safe(); char *data; size_t length = php_swoole_get_send_data(zdata, &data); @@ -1930,17 +1929,19 @@ void php_swoole_server_send_yield(Server *serv, SessionId session_id, zval *zdat RETURN_FALSE; } - auto coroutine_iterator = server_object->property->send_coroutine_map.find(session_id); - if (coroutine_iterator == server_object->property->send_coroutine_map.end()) { - coros_list = new std::list; - server_object->property->send_coroutine_map[session_id] = coros_list; - } else { - coros_list = coroutine_iterator->second; - } - SW_LOOP { - coros_list->push_back(co); + auto coroutine_iterator = server_object->property->send_coroutine_map.find(session_id); + std::list *co_list; + if (coroutine_iterator == server_object->property->send_coroutine_map.end()) { + co_list = new std::list; + server_object->property->send_coroutine_map[session_id] = co_list; + } else { + co_list = coroutine_iterator->second; + } + co_list->push_back(co); + auto iter = std::prev(co_list->end()); if (!co->yield_ex(serv->send_timeout)) { + co_list->erase(iter); RETURN_FALSE; } bool ret = serv->send(session_id, data, length); @@ -1996,23 +1997,23 @@ static int php_swoole_server_dispatch_func(Server *serv, Connection *conn, SendD void php_swoole_server_onBufferEmpty(Server *serv, DataHead *info) { zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - zend_fcall_info_cache *fci_cache; if (serv->send_yield) { - auto _i_coros_list = server_object->property->send_coroutine_map.find(info->fd); - if (_i_coros_list != server_object->property->send_coroutine_map.end()) { - auto coros_list = _i_coros_list->second; + auto _i_co_list = server_object->property->send_coroutine_map.find(info->fd); + if (_i_co_list != server_object->property->send_coroutine_map.end()) { + auto co_list = _i_co_list->second; server_object->property->send_coroutine_map.erase(info->fd); - while (!coros_list->empty()) { - Coroutine *co = coros_list->front(); - coros_list->pop_front(); + while (!co_list->empty()) { + Coroutine *co = co_list->front(); + co_list->pop_front(); co->resume(); } - delete coros_list; + delete co_list; } } - fci_cache = php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onBufferEmpty); + zend_fcall_info_cache *fci_cache = + php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onBufferEmpty); if (fci_cache) { zval args[2]; diff --git a/src/server/worker.cc b/src/server/worker.cc index ea7aef44018..85055e6d457 100644 --- a/src/server/worker.cc +++ b/src/server/worker.cc @@ -110,7 +110,6 @@ static sw_inline bool Worker_discard_data(Server *serv, Connection *conn, DataHe "[2] ignore data[%u bytes] received from session#%ld", info->len, info->fd); - return true; } diff --git a/tests/swoole_table/type_conv.phpt b/tests/swoole_table/type_conv.phpt index a29e1ce362e..a692eb3c7a2 100644 --- a/tests/swoole_table/type_conv.phpt +++ b/tests/swoole_table/type_conv.phpt @@ -41,4 +41,3 @@ Assert::same($r1['id'], 0); ?> --EXPECT-- -SUCCESS From bf393fb625bfc61c3ed75eab3a996a1d04c78288 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Fri, 8 Oct 2021 10:27:03 +0800 Subject: [PATCH 258/936] Add defense code --- include/swoole_error.h | 2 +- src/core/error.cc | 2 +- src/memory/fixed_pool.cc | 10 ++++++++-- thirdparty/php/curl/multi.cc | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/include/swoole_error.h b/include/swoole_error.h index 78dac8f4f7e..6992edbeec6 100644 --- a/include/swoole_error.h +++ b/include/swoole_error.h @@ -187,6 +187,6 @@ class Exception { int code; const char *msg; - Exception(int code); + Exception(int code) throw(); }; } // namespace swoole diff --git a/src/core/error.cc b/src/core/error.cc index 34ffea50e77..68419450ce2 100644 --- a/src/core/error.cc +++ b/src/core/error.cc @@ -17,7 +17,7 @@ #include "swoole.h" namespace swoole { -Exception::Exception(int code) : code(code) { +Exception::Exception(int code) throw() : code(code) { msg = swoole_strerror(code); } } // namespace swoole diff --git a/src/memory/fixed_pool.cc b/src/memory/fixed_pool.cc index 0517e059642..2a598e280ec 100644 --- a/src/memory/fixed_pool.cc +++ b/src/memory/fixed_pool.cc @@ -51,6 +51,9 @@ struct FixedPoolImpl { * create new FixedPool, random alloc/free fixed size memory */ FixedPool::FixedPool(uint32_t slice_num, uint32_t slice_size, bool shared) { + if (slice_num < 2) { + throw Exception(SW_ERROR_INVALID_PARAMS); + } slice_size = SW_MEM_ALIGNED_SIZE(slice_size); size_t size = slice_num * (sizeof(FixedPoolSlice) + slice_size); size_t alloc_size = size + sizeof(*impl); @@ -79,11 +82,14 @@ FixedPool::FixedPool(uint32_t slice_size, void *memory, size_t size, bool shared impl = (FixedPoolImpl*) memory; memory = (char*) memory + sizeof(*impl); sw_memset_zero(impl, sizeof(*impl)); - + uint32_t slice_num = impl->size / (slice_size + sizeof(FixedPoolSlice)); + if (slice_num < 2) { + throw Exception(SW_ERROR_INVALID_PARAMS); + } impl->shared = shared; impl->slice_size = slice_size; impl->size = size - sizeof(*impl); - impl->slice_num = impl->size / (slice_size + sizeof(FixedPoolSlice)); + impl->slice_num = slice_num; impl->memory = memory; impl->allocated = false; impl->init(); diff --git a/thirdparty/php/curl/multi.cc b/thirdparty/php/curl/multi.cc index df587f1082c..06cf7f0ab3a 100644 --- a/thirdparty/php/curl/multi.cc +++ b/thirdparty/php/curl/multi.cc @@ -371,7 +371,7 @@ PHP_FUNCTION(swoole_native_curl_multi_close) { if (!ch) { continue; } - swoole_curl_verify_handlers(ch, 1); + swoole_curl_verify_handlers(ch, 0); mh->multi->remove_handle(ch->cp); } zend_llist_clean(&mh->easyh); From 7a419528cd8d2efa7725f367a7d099959acbaa29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Fri, 8 Oct 2021 15:41:09 +0800 Subject: [PATCH 259/936] Fix missing coroutine options (#4425) --- tools/constant-generator.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/constant-generator.php b/tools/constant-generator.php index 1eb9602931b..63dfd68d730 100755 --- a/tools/constant-generator.php +++ b/tools/constant-generator.php @@ -21,8 +21,16 @@ preg_match_all('/php_swoole_array_get_value\(.+?, "(.+?)", .+?\)/', $source_content, $matches); $matches = array_unique($matches[1]); + +$coroutineOptions = [ + 'exit_condition', + 'deadlock_check_disable_trace', + 'deadlock_check_limit', + 'deadlock_check_depth' +]; +$options = array_merge($matches, $coroutineOptions); $result = ''; -foreach ($matches as $option) { +foreach ($options as $option) { $result .= space(4) . sprintf("public const OPTION_%s = '%s';\n\n", strtoupper($option), $option); } From 73372ad07720f3f024d8b86b50d2e96dc9b6c1de Mon Sep 17 00:00:00 2001 From: matyhtf Date: Fri, 8 Oct 2021 18:18:17 +0800 Subject: [PATCH 260/936] Added tests, improved server stats_file, fix core-tests --- ext-src/php_swoole_library.h | 1094 +++++++++++++++++++++- src/memory/fixed_pool.cc | 6 +- tests/include/functions.php | 7 +- tests/swoole_server/stats_file.phpt | 10 +- tests/swoole_server/stats_file_json.phpt | 62 ++ tests/swoole_server/stats_file_php.phpt | 65 ++ tools/build-library.php | 1 + 7 files changed, 1194 insertions(+), 51 deletions(-) create mode 100644 tests/swoole_server/stats_file_json.phpt create mode 100644 tests/swoole_server/stats_file_php.phpt diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index 7f5f085e09f..dd3aa6b375e 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: 1b421d51331d70d14a1b971c1a20c31c14b523d7 */ +/* $Id: 3efc2e949a7125178561fb5c3f3ae5a4dd176dfa */ static const char* swoole_library_source_constants = "\n" @@ -170,6 +170,8 @@ static const char* swoole_library_source_core_constant = "\n" " public const OPTION_SOCKET_TIMEOUT = 'socket_timeout';\n" "\n" + " public const OPTION_MAX_CONCURRENCY = 'max_concurrency';\n" + "\n" " public const OPTION_AIO_CORE_WORKER_NUM = 'aio_core_worker_num';\n" "\n" " public const OPTION_AIO_WORKER_NUM = 'aio_worker_num';\n" @@ -595,15 +597,15 @@ static const char* swoole_library_source_core_string_object = " }\n" "\n" " /**\n" + " * @param mixed $characters\n" " * @return static\n" " */\n" " public function trim($characters = ''): self\n" " {\n" " if ($characters) {\n" " return new static(trim($this->string, $characters));\n" - " } else {\n" - " return new static(trim($this->string));\n" " }\n" + " return new static(trim($this->string));\n" " }\n" "\n" " /**\n" @@ -6790,7 +6792,7 @@ static const char* swoole_library_source_core_process_manager = " }\n" "}\n"; -static const char* swoole_library_source_core_server_helper = +static const char* swoole_library_source_core_server_admin = "\n" "/**\n" " * This file is part of Swoole.\n" @@ -6804,12 +6806,1028 @@ static const char* swoole_library_source_core_server_helper = "\n" "namespace Swoole\\Server;\n" "\n" + "use Reflection;\n" + "use ReflectionClass;\n" + "use ReflectionExtension;\n" "use Swoole\\Coroutine;\n" + "use Swoole\\Coroutine\\System;\n" + "use Swoole\\Http\\Request;\n" + "use Swoole\\Http\\Response;\n" "use Swoole\\Server;\n" "use Swoole\\Timer;\n" - "use Swoole\\Http\\Response;\n" - "use Swoole\\Http\\Request;\n" "\n" + "class Admin\n" + "{\n" + " /**\n" + " * gdb php\n" + " * (gdb) p sizeof(zval)\n" + " * $2 = 16\n" + " * (gdb) p sizeof(zend_array)\n" + " * $1 = 56\n" + " * (gdb) p sizeof(zend_string)\n" + " * $3 = 32\n" + " * (gdb) p sizeof(zend_object)\n" + " * $4 = 56\n" + " */\n" + " const SIZE_OF_ZVAL = 16;\n" + "\n" + " const SIZE_OF_ZEND_STRING = 32;\n" + "\n" + " const SIZE_OF_ZEND_OBJECT = 56;\n" + "\n" + " const SIZE_OF_ZEND_ARRAY = 56;\n" + "\n" + " const DASHBOARD_DIR = '/opt/swoole/dashboard';\n" + "\n" + " public static function init(Server $server)\n" + " {\n" + " $accepted_process_types = SWOOLE_SERVER_COMMAND_MASTER |\n" + " SWOOLE_SERVER_COMMAND_MANAGER |\n" + " SWOOLE_SERVER_COMMAND_EVENT_WORKER |\n" + " SWOOLE_SERVER_COMMAND_TASK_WORKER;\n" + "\n" + " $server->addCommand(\n" + " 'coroutine_stats',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json(Coroutine::stats());\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'coroutine_list',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json(iterator_to_array(Coroutine::list()));\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'coroutine_bt',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " $json = json_decode($msg);\n" + " $cid = empty($json->cid) ? 0 : intval($json->cid);\n" + " $bt = Coroutine::getBackTrace($cid);\n" + " if ($bt === false) {\n" + " return self::json(\"Coroutine#{$cid} not exists\", 4004);\n" + " }\n" + " return self::json($bt);\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'server_stats',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json($server->stats());\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'server_setting',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " /**\n" + " * @var Server $server\n" + " */\n" + " $setting = $server->setting;\n" + " $setting['mode'] = $server->mode;\n" + " $setting['host'] = $server->host;\n" + " $setting['port'] = $server->port;\n" + " $setting['master_pid'] = $server->master_pid;\n" + " $setting['manager_pid'] = $server->manager_pid;\n" + " return self::json($setting);\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'get_client_info',\n" + " $accepted_process_types,\n" + " function (Server $server, $msg) {\n" + " $json = json_decode($msg, true);\n" + " if (empty($json['session_id'])) {\n" + " return self::json('require session_id', 4003);\n" + " }\n" + " return self::json($server->getClientInfo(intval($json['session_id'])));\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'close_session',\n" + " $accepted_process_types,\n" + " function (Server $server, $msg) {\n" + " $json = json_decode($msg, true);\n" + " if (empty($json['session_id'])) {\n" + " return self::json('require session_id', 4003);\n" + " }\n" + " if ($server->close(intval($json['session_id']), !empty($json['force']))) {\n" + " return self::json([]);\n" + " }\n" + " return self::json(['error' => swoole_last_error()], 4004);\n" + " }\n" + " );\n" + "\n" + " $server->addCommand('get_version_info', $accepted_process_types, [__CLASS__, 'handlerGetVersionInfo']);\n" + " $server->addCommand('get_worker_info', $accepted_process_types, [__CLASS__, 'handlerGetWorkerInfo']);\n" + " $server->addCommand('get_timer_list', $accepted_process_types, [__CLASS__, 'handlerGetTimerList']);\n" + " $server->addCommand('get_coroutine_list', $accepted_process_types, [__CLASS__, 'handlerGetCoroutineList']);\n" + " $server->addCommand('get_objects', $accepted_process_types, [__CLASS__, 'handlerGetObjects']);\n" + " $server->addCommand('get_class_info', $accepted_process_types, [__CLASS__, 'handlerGetClassInfo']);\n" + " $server->addCommand('get_function_info', $accepted_process_types, [__CLASS__, 'handlerGetFunctionInfo']);\n" + " $server->addCommand('get_object_by_handle', $accepted_process_types, [__CLASS__, 'handlerGetObjectByHandle']);\n" + " $server->addCommand('get_server_cpu_usage', $accepted_process_types, [__CLASS__, 'handlerGetServerCpuUsage']);\n" + " $server->addCommand(\n" + " 'get_server_memory_usage',\n" + " $accepted_process_types,\n" + " [__CLASS__, 'handlerGetServerMemoryUsage']\n" + " );\n" + " $server->addCommand(\n" + " 'get_static_property_value',\n" + " $accepted_process_types,\n" + " [__CLASS__, 'handlerGetStaticPropertyValue']\n" + " );\n" + " $server->addCommand(\n" + " 'get_defined_functions',\n" + " $accepted_process_types,\n" + " [__CLASS__, 'handlerGetDefinedFunctions']\n" + " );\n" + " $server->addCommand('get_declared_classes', $accepted_process_types, [__CLASS__, 'handlerGetDeclaredClasses']);\n" + "\n" + " if (PHP_VERSION_ID > 70300) {\n" + " $server->addCommand(\n" + " 'gc_status',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json(gc_status());\n" + " }\n" + " );\n" + " }\n" + "\n" + " if (extension_loaded('opcache')) {\n" + " $server->addCommand(\n" + " 'opcache_status',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json(opcache_get_status(true));\n" + " }\n" + " );\n" + " }\n" + "\n" + " $server->addCommand(\n" + " 'getpid',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json(['pid' => posix_getpid()]);\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'memory_usage',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json([\n" + " 'usage' => memory_get_usage(),\n" + " 'real_usage' => memory_get_usage(true),\n" + " ]);\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'get_included_files',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json(['files' => get_included_files()]);\n" + " }\n" + " );\n" + "\n" + " $server->addCommand('get_resources', $accepted_process_types, [__CLASS__, 'handlerGetResources']);\n" + "\n" + " $server->addCommand(\n" + " 'get_defined_constants',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " $constants = get_defined_constants();\n" + " foreach ($constants as $k => $c) {\n" + " if (is_resource($c)) {\n" + " unset($constants[$k]);\n" + " }\n" + " }\n" + " unset($constants['NULL'], $constants['NAN'], $constants['INF']);\n" + " return self::json($constants);\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'get_loaded_extensions',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " $extensions = get_loaded_extensions();\n" + " $list = [];\n" + " foreach ($extensions as $key => $extension) {\n" + " $ext = new \\ReflectionExtension($extension);\n" + " $list[$key] = [\n" + " 'id' => ++$key,\n" + " 'name' => $extension,\n" + " 'version' => $ext->getVersion() ?? '',\n" + " ];\n" + " }\n" + " return self::json($list);\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'get_declared_interfaces',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json(get_declared_interfaces());\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'get_declared_traits',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json(get_declared_traits());\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'get_included_file_contents',\n" + " $accepted_process_types,\n" + " function (Server $server, $msg) {\n" + " $json = json_decode($msg, true);\n" + " if (empty($json['filename'])) {\n" + " return self::json('require filename', 4003);\n" + " }\n" + "\n" + " if (!file_exists($json['filename'])) {\n" + " return self::json(\"{$json['filename']} not exist\", 4004);\n" + " }\n" + "\n" + " if (!in_array($json['filename'], get_included_files())) {\n" + " return self::json('no permission', 4003);\n" + " }\n" + "\n" + " return self::json(file_get_contents($json['filename']));\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'get_globals',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " $globals = [];\n" + " foreach ($GLOBALS as $key => $item) {\n" + " if ($key === 'GLOBALS') {\n" + " continue;\n" + " }\n" + " $type = gettype($item);\n" + " $other = [];\n" + " if ($type === 'object') {\n" + " $other = [\n" + " 'class_name' => get_class($item),\n" + " 'object_id' => spl_object_id($item),\n" + " 'object_hash' => spl_object_hash($item),\n" + " ];\n" + " }\n" + " if ($type == 'resource' || $type == 'resource (closed)') {\n" + " $item = '';\n" + " }\n" + " $globals[] = [\n" + " 'key' => $key,\n" + " 'value' => $item,\n" + " 'type' => $type,\n" + " 'other' => $other,\n" + " ];\n" + " }\n" + " return self::json($globals);\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'get_extension_info',\n" + " $accepted_process_types,\n" + " function (Server $server, $msg) {\n" + " $json = json_decode($msg, true);\n" + "\n" + " if (empty($json['extension_name']) || !extension_loaded($json['extension_name'])) {\n" + " return self::json('require extension_name', 4004);\n" + " }\n" + "\n" + " $ext = new ReflectionExtension($json['extension_name']);\n" + "\n" + " ob_start();\n" + " $ext->info();\n" + " $info = ob_get_clean();\n" + "\n" + " $constants = $ext->getConstants();\n" + " foreach ($constants as $k => $c) {\n" + " if (is_resource($c)) {\n" + " unset($constants[$k]);\n" + " }\n" + " }\n" + "\n" + " unset($constants['NULL'], $constants['NAN'], $constants['INF']);\n" + "\n" + " return self::json([\n" + " 'classes' => $ext->getClassNames(),\n" + " 'version' => $ext->getVersion(),\n" + " 'constants' => $constants,\n" + " 'ini_entries' => $ext->getINIEntries(),\n" + " 'dependencies' => $ext->getDependencies(),\n" + " 'functions' => array_keys($ext->getFunctions()),\n" + " 'info' => trim($info),\n" + " ]);\n" + " }\n" + " );\n" + " }\n" + "\n" + " public static function start(Server $server)\n" + " {\n" + " $admin_server_uri = swoole_string($server->setting['admin_server']);\n" + " if ($admin_server_uri->startsWith('unix:/')) {\n" + " $admin_server = new Coroutine\\Http\\Server($admin_server_uri->toString());\n" + " } else {\n" + " [$host, $port] = $admin_server_uri->split(':', 2)->toArray();\n" + " $admin_server = new Coroutine\\Http\\Server($host, intval($port));\n" + " }\n" + " $admin_server->handle('/api', function (Request $req, Response $resp) use ($server) {\n" + " $path_array = swoole_string($req->server['request_uri'])->trim('/')->split('/');\n" + " if ($path_array->count() < 2 or $path_array->count() > 3) {\n" + " $resp->status(403);\n" + " $resp->end(self::json('Bad API path', 4003));\n" + " return;\n" + " }\n" + "\n" + " $cmd = $path_array->get(1)->toString();\n" + " if ($path_array->count() == 2) {\n" + " $process = swoole_string('master');\n" + " } else {\n" + " $process = $path_array->get(2);\n" + " }\n" + "\n" + " if ($process->startsWith('master')) {\n" + " $process_type = SWOOLE_SERVER_COMMAND_MASTER;\n" + " $process_id = 0;\n" + " } elseif ($process->startsWith('manager')) {\n" + " $process_type = SWOOLE_SERVER_COMMAND_MANAGER;\n" + " $process_id = 0;\n" + " } else {\n" + " $array = $process->split('-');\n" + " if ($array->count() != 2) {\n" + " _bad_process:\n" + " $resp->status(403);\n" + " $resp->end(self::json('Bad process', 4003));\n" + " return;\n" + " }\n" + "\n" + " static $map = [\n" + " 'reactor' => SWOOLE_SERVER_COMMAND_REACTOR_THREAD,\n" + " 'reactor_thread' => SWOOLE_SERVER_COMMAND_REACTOR_THREAD,\n" + " 'worker' => SWOOLE_SERVER_COMMAND_EVENT_WORKER,\n" + " 'event_worker' => SWOOLE_SERVER_COMMAND_EVENT_WORKER,\n" + " 'task' => SWOOLE_SERVER_COMMAND_TASK_WORKER,\n" + " 'task_worker' => SWOOLE_SERVER_COMMAND_TASK_WORKER,\n" + " ];\n" + "\n" + " if (!isset($map[$array->get(0)->toString()])) {\n" + " goto _bad_process;\n" + " }\n" + "\n" + " $process_type = $map[$array->get(0)->toString()];\n" + " $process_id = intval($array->get(1)->toString());\n" + " }\n" + "\n" + " if ($req->getMethod() == 'GET') {\n" + " $data = $req->get;\n" + " } else {\n" + " $data = $req->post;\n" + " }\n" + "\n" + " $resp->header('Access-Control-Allow-Origin', '*');\n" + " $resp->header('Access-Control-Allow-Methods', 'GET, OPTIONS');\n" + " $resp->header('Access-Control-Allow-Headers', 'X-ACCESS-TOKEN');\n" + "\n" + " $result = $server->command($cmd, intval($process_id), intval($process_type), $data, false);\n" + " if (!$result) {\n" + " $resp->end(json_encode([\n" + " 'code' => swoole_last_error(),\n" + " 'data' => swoole_strerror(swoole_last_error()),\n" + " ]));\n" + " } else {\n" + " $resp->end($result);\n" + " }\n" + " });\n" + " $admin_server->handle('/', function (Request $req, Response $resp) use ($server) {\n" + " if ($req->server['request_uri'] == '/' or $req->server['request_uri'] == '/index.html') {\n" + " $dir = self::DASHBOARD_DIR . '/' . SWOOLE_VERSION;\n" + " $index_file = $dir . '/dist/index.html';\n" + " if (!is_file($index_file)) {\n" + " $url = 'https://business.swoole.com/static/swoole_dashboard/' . SWOOLE_VERSION . '.tar.gz';\n" + " $download_request = Coroutine\\Http\\get($url);\n" + " if (!$download_request or $download_request->getStatusCode() != '200') {\n" + " $resp->end(\"download [{$url}] failed\");\n" + " return;\n" + " }\n" + " $tmp_file = '/tmp/swoole_dashborad.' . SWOOLE_VERSION . '.tar.gz';\n" + " file_put_contents($tmp_file, $download_request->getBody());\n" + " if (is_file($tmp_file) or filesize($tmp_file) == 0) {\n" + " $resp->end(\"write [{$tmp_file}] failed\");\n" + " return;\n" + " }\n" + " if (!is_dir($dir)) {\n" + " mkdir($dir, 0777, true);\n" + " }\n" + " $sh = 'tar zxvf ' . $tmp_file . ' -C ' . $dir;\n" + " System::exec($sh);\n" + " }\n" + " }\n" + "\n" + " $file = self::DASHBOARD_DIR . '/' . SWOOLE_VERSION . '/dist/' . ($req->server['request_uri'] == '/' ? 'index.html' : $req->server['request_uri']);\n" + " if (!is_file($file)) {\n" + " $resp->status(404);\n" + " $resp->end('file ' . $file . ' not found');\n" + " } else {\n" + " $resp->sendfile($file);\n" + " }\n" + " });\n" + " $server->admin_server = $admin_server;\n" + " $admin_server->start();\n" + " }\n" + "\n" + " /**\n" + " * @param $server Server\n" + " * @param $msg\n" + " * @return false|string\n" + " */\n" + " public static function handlerGetResources($server, $msg)\n" + " {\n" + " $resources = get_resources();\n" + " $list = [];\n" + " foreach ($resources as $r) {\n" + " $info = [\n" + " 'id' => function_exists('get_resource_id') ? get_resource_id($r) : intval($r),\n" + " 'type' => get_resource_type($r),\n" + " ];\n" + " if ($info['type'] == 'stream') {\n" + " $info['info'] = stream_get_meta_data($r);\n" + " }\n" + " $list[] = $info;\n" + " }\n" + " return self::json($list);\n" + " }\n" + "\n" + " /**\n" + " * @param $server Server\n" + " * @param $msg\n" + " * @return false|string\n" + " */\n" + " public static function handlerGetWorkerInfo($server, $msg)\n" + " {\n" + " $info = [\n" + " 'id' => $server->getWorkerId(),\n" + " 'pid' => $server->getWorkerPid(),\n" + " 'gc_status' => gc_status(),\n" + " 'memory_usage' => memory_get_usage(),\n" + " 'memory_real_usage' => memory_get_usage(true),\n" + " 'process_status' => self::getProcessStatus(),\n" + " 'coroutine_stats' => Coroutine::stats(),\n" + " 'timer_stats' => Timer::stats(),\n" + " ];\n" + " if (function_exists('swoole_get_vm_status')) {\n" + " $info['vm_status'] = swoole_get_vm_status();\n" + " }\n" + " return self::json($info);\n" + " }\n" + "\n" + " /**\n" + " * @param $server\n" + " * @param $msg\n" + " * @return false|string\n" + " */\n" + " public static function handlerGetTimerList($server, $msg)\n" + " {\n" + " $list = [];\n" + " foreach (Timer::list() as $timer_id) {\n" + " $list[] = [\n" + " 'id' => $timer_id,\n" + " 'info' => Timer::info($timer_id),\n" + " ];\n" + " }\n" + "\n" + " return self::json($list);\n" + " }\n" + "\n" + " /**\n" + " * @param $server\n" + " * @param $msg\n" + " * @return false|string\n" + " */\n" + " public static function handlerGetCoroutineList($server, $msg)\n" + " {\n" + " $list = [];\n" + " foreach (Coroutine::list() as $cid) {\n" + " $list[] = [\n" + " 'id' => $cid,\n" + " 'elapsed' => Coroutine::getElapsed($cid),\n" + " 'stack_usage' => Coroutine::getStackUsage($cid),\n" + " 'backTrace' => Coroutine::getBackTrace($cid, DEBUG_BACKTRACE_IGNORE_ARGS, 1),\n" + " ];\n" + " }\n" + "\n" + " return self::json($list);\n" + " }\n" + "\n" + " public static function handlerGetObjects($server, $msg)\n" + " {\n" + " if (!function_exists('swoole_get_objects')) {\n" + " return self::json(['require ext-swoole_plus'], 5000);\n" + " }\n" + " $list = [];\n" + " $objects = swoole_get_objects();\n" + " foreach ($objects as $o) {\n" + " $class_name = get_class($o);\n" + " $class = new ReflectionClass($class_name);\n" + " $filename = $class->getFileName();\n" + " $line = $class->getStartLine();\n" + " $list[] = [\n" + " 'id' => spl_object_id($o),\n" + " 'hash' => spl_object_hash($o),\n" + " 'class' => $class_name,\n" + " 'filename' => $filename ?: '',\n" + " 'line' => $line ?: '',\n" + " 'memory_size' => self::getObjectMemorySize($o),\n" + " ];\n" + " }\n" + "\n" + " return self::json($list);\n" + " }\n" + "\n" + " public static function handlerGetClassInfo($server, $msg)\n" + " {\n" + " $json = json_decode($msg, true);\n" + " if (empty($json['class_name'])) {\n" + " return self::json(['error' => 'require class_name'], 4004);\n" + " }\n" + "\n" + " if (!class_exists($json['class_name'], false)) {\n" + " return self::json(\"{$json['class_name']} not exists\", 4003);\n" + " }\n" + "\n" + " $class = new ReflectionClass($json['class_name']);\n" + "\n" + " $filename = $class->getFileName();\n" + "\n" + " $getTmpConstants = function ($data) {\n" + " $tmp = [];\n" + " foreach ($data as $k => $v) {\n" + " $tmp[] = [\n" + " 'name' => $k,\n" + " 'value' => is_array($v) ? var_export($v, true) : $v,\n" + " 'type' => is_array($v) ? 'detail' : 'default',\n" + " ];\n" + " }\n" + " return $tmp;\n" + " };\n" + "\n" + " $tmpConstants = $class->getConstants();\n" + " $constants = $tmpConstants ? $getTmpConstants($tmpConstants) : [];\n" + "\n" + " $staticProperties = [];\n" + " $properties = [];\n" + " $tmpProperties = $class->getProperties();\n" + "\n" + " $getTmpProperties = function ($class, $data) {\n" + " $static = [];\n" + " $no_static = [];\n" + " $reflProp = $class->getDefaultProperties();\n" + " foreach ($data as $k => $v) {\n" + " $name = $v->getName();\n" + " $modifiers = Reflection::getModifierNames($v->getModifiers());\n" + " if ($v->isStatic()) {\n" + " $static[] = [\n" + " 'name' => $name,\n" + " 'value' => $reflProp[$name],\n" + " 'modifiers' => implode(' ', $modifiers),\n" + " ];\n" + " } else {\n" + " $no_static[] = [\n" + " 'name' => $name,\n" + " 'value' => $reflProp[$name],\n" + " 'modifiers' => implode(' ', $modifiers),\n" + " ];\n" + " }\n" + " }\n" + " return ['static' => $static, 'no_static' => $no_static];\n" + " };\n" + "\n" + " if ($tmpProperties) {\n" + " $tmpProperties = $getTmpProperties($class, $tmpProperties);\n" + " $staticProperties = $tmpProperties['static'];\n" + " $properties = $tmpProperties['no_static'];\n" + " }\n" + "\n" + " $staticMethods = [];\n" + " $methods = [];\n" + " $tmpStaticMethods = $class->getMethods();\n" + "\n" + " $getTmpMethods = function ($data) {\n" + " $static = [];\n" + " $no_static = [];\n" + " foreach ($data as $k => $v) {\n" + " $name = $v->getName();\n" + " $line = $v->getStartLine();\n" + " $modifiers = \\Reflection::getModifierNames($v->getModifiers());\n" + " if ($v->isStatic()) {\n" + " $static[] = [\n" + " 'name' => $name,\n" + " 'line' => $line ?: '',\n" + " 'modifiers' => implode(' ', $modifiers),\n" + " ];\n" + " } else {\n" + " $no_static[] = [\n" + " 'name' => $name,\n" + " 'line' => $line ?: '',\n" + " 'modifiers' => implode(' ', $modifiers),\n" + " ];\n" + " }\n" + " }\n" + " return ['static' => $static, 'no_static' => $no_static];\n" + " };\n" + "\n" + " if ($tmpStaticMethods) {\n" + " $tmpStaticMethods = $getTmpMethods($tmpStaticMethods);\n" + " $staticMethods = $tmpStaticMethods['static'];\n" + " $methods = $tmpStaticMethods['no_static'];\n" + " }\n" + "\n" + " $tmpParentClass = $class->getParentClass();\n" + " $parentClass = $tmpParentClass ? $tmpParentClass->getName() : '';\n" + "\n" + " $tmpInterface = $class->getInterfaceNames();\n" + " $interface = $tmpInterface ? $tmpInterface : [];\n" + "\n" + " $data = [\n" + " 'filename' => $filename,\n" + " 'constants' => $constants,\n" + " 'staticProperties' => $staticProperties,\n" + " 'properties' => $properties,\n" + " 'staticMethods' => $staticMethods,\n" + " 'methods' => $methods,\n" + " 'parentClass' => $parentClass,\n" + " 'interface' => $interface,\n" + " ];\n" + " return self::json($data);\n" + " }\n" + "\n" + " public static function handlerGetFunctionInfo($server, $msg)\n" + " {\n" + " $json = json_decode($msg, true);\n" + " if (!$json || empty($json['function_name'])) {\n" + " return self::json('require function_name', 4004);\n" + " }\n" + " if (!function_exists($json['function_name'])) {\n" + " return self::json(\"{$json['function_name']} not exists\", 4004);\n" + " }\n" + " $function = new \\ReflectionFunction($json['function_name']);\n" + "\n" + " $result = [\n" + " 'filename' => $function->getFileName(),\n" + " 'line' => $function->getStartLine() ?? '',\n" + " 'num' => $function->getNumberOfParameters(),\n" + " 'user_defined' => $function->isUserDefined(),\n" + " 'extension' => $function->getExtensionName(),\n" + " ];\n" + "\n" + " $params = $function->getParameters();\n" + "\n" + " $list = [];\n" + " foreach ($params as $param) {\n" + " $type = $param->hasType() ? $param->getType()->getName() : '';\n" + "\n" + " $optional = $default = '';\n" + " if ($param->isOptional() && !$param->isVariadic() && PHP_VERSION_ID >= 80000) {\n" + " $optional = '?';\n" + " $value = $param->getDefaultValue();\n" + " if (in_array($value, [true, false, null])) {\n" + " if ($value === null) {\n" + " $value = 'null';\n" + " }\n" + " if ($value === true) {\n" + " $value = 'true';\n" + " }\n" + " if ($value === false) {\n" + " $value = 'false';\n" + " }\n" + " }\n" + " $default = \" = {$value}\";\n" + " }\n" + "\n" + " $isPassedByReference = $param->isPassedByReference() ? '&' : '';\n" + " $isVariadic = $param->isVariadic() ? '...' : '';\n" + "\n" + " $param_value = \"{$optional}{$type} {$isPassedByReference}{$isVariadic}{$param->getName()}{$default}\";\n" + "\n" + " $list[] = $param_value;\n" + " }\n" + " $result['params'] = $list;\n" + "\n" + " return self::json($result);\n" + " }\n" + "\n" + " public static function handlerGetObjectByHandle($server, $msg)\n" + " {\n" + " if (!function_exists('swoole_get_object_by_handle')) {\n" + " return self::json(['require ext-swoole_plus'], 5000);\n" + " }\n" + "\n" + " $json = json_decode($msg, true);\n" + " if (!$json || !isset($json['object_id']) || empty($json['object_id']) || !isset($json['object_hash']) || empty($json['object_hash'])) {\n" + " return self::json(['error' => 'Params Error!'], 4004);\n" + " }\n" + "\n" + " $object = swoole_get_object_by_handle((int) $json['object_id']);\n" + " if (!$object) {\n" + " return self::json(['error' => 'Object destroyed!'], 4004);\n" + " }\n" + "\n" + " $object_hash = spl_object_hash($object);\n" + " if ($object_hash != $json['object_hash']) {\n" + " return self::json(['error' => 'Object destroyed!'], 4004);\n" + " }\n" + "\n" + " return self::json(var_export($object, true));\n" + " }\n" + "\n" + " public static function handlerGetVersionInfo($server, $msg)\n" + " {\n" + " $ip_arr = swoole_get_local_ip();\n" + " $host = [];\n" + " $local = [];\n" + " foreach ($ip_arr as $k => $ip) {\n" + " if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {\n" + " $host[] = $ip;\n" + " } else {\n" + " $local[] = $ip;\n" + " }\n" + " }\n" + " $data = [\n" + " 'os' => php_uname('s') . '-' . php_uname('r'),\n" + " 'swoole' => swoole_version(),\n" + " 'php' => phpversion(),\n" + " 'ip' => $host ? $host[0] : $local[0],\n" + " ];\n" + " return self::json($data);\n" + " }\n" + "\n" + " public static function handlerGetDefinedFunctions($server, $msg)\n" + " {\n" + " $functions = get_defined_functions();\n" + " $arr = [];\n" + " if ($functions) {\n" + " $arr['internal'] = $functions['internal'];\n" + "\n" + " foreach ($functions['user'] as $function_name) {\n" + " $function = new \\ReflectionFunction($function_name);\n" + " $filename = $function->getFileName();\n" + " $line = $function->getStartLine();\n" + " $arr['user'][] = [\n" + " 'function' => $function_name,\n" + " 'filename' => $filename,\n" + " 'line' => $line,\n" + " ];\n" + " }\n" + " }\n" + " return self::json($arr);\n" + " }\n" + "\n" + " public static function handlerGetDeclaredClasses($server, $msg)\n" + " {\n" + " $classes = get_declared_classes();\n" + " $arr = [];\n" + " if ($classes) {\n" + " foreach ($classes as $classes_name) {\n" + " $function = new \\ReflectionClass($classes_name);\n" + " $filename = $function->getFileName();\n" + " $line = $function->getStartLine();\n" + " $arr[] = [\n" + " 'class' => $classes_name,\n" + " 'filename' => $filename ?: '',\n" + " 'line' => $line ?: '',\n" + " ];\n" + " }\n" + " }\n" + " return self::json($arr);\n" + " }\n" + "\n" + " public static function handlerGetServerMemoryUsage($server, $msg)\n" + " {\n" + " $total = 0;\n" + "\n" + " $result['master'] = self::getProcessMemoryRealUsage($server->master_pid);\n" + " $total += $result['master'];\n" + "\n" + " $result['manager'] = self::getProcessMemoryRealUsage($server->manager_pid);\n" + " $total += $result['manager'];\n" + "\n" + " $n = $server->setting['worker_num'] + $server->setting['task_worker_num'];\n" + " for ($i = 0; $i < $n; $i++) {\n" + " $key = 'worker-' . $i;\n" + " $result[$key] = self::getProcessMemoryRealUsage($server->getWorkerPid($i));\n" + " $total += $result[$key];\n" + " }\n" + "\n" + " $result['total'] = $total;\n" + "\n" + " $result['memory_size'] = 0;\n" + " // TODO: Support other OS\n" + " if (PHP_OS_FAMILY === 'Linux') {\n" + " preg_match('#MemTotal:\\s+(\\d+) kB#i', file_get_contents('/proc/meminfo'), $match);\n" + " $result['memory_size'] = $match[1] * 1024;\n" + " }\n" + "\n" + " return self::json($result);\n" + " }\n" + "\n" + " public static function handlerGetServerCpuUsage($server, $msg)\n" + " {\n" + " $total = 0;\n" + "\n" + " $result['master'] = self::getProcessCpuUsage($server->master_pid);\n" + " $total += $result['master'][1] ?? 0;\n" + "\n" + " $result['manager'] = self::getProcessCpuUsage($server->manager_pid);\n" + " $total += $result['manager'][1] ?? 0;\n" + "\n" + " $n = $server->setting['worker_num'] + $server->setting['task_worker_num'];\n" + " for ($i = 0; $i < $n; $i++) {\n" + " $key = 'worker-' . $i;\n" + " $result[$key] = self::getProcessCpuUsage($server->getWorkerPid($i))[1] ?? 0;\n" + " $total += $result[$key];\n" + " }\n" + "\n" + " $result['total'] = $total;\n" + " $result['cpu_num'] = swoole_cpu_num();\n" + "\n" + " return self::json($result);\n" + " }\n" + "\n" + " public static function handlerGetStaticPropertyValue($server, $msg)\n" + " {\n" + " $json = json_decode($msg, true);\n" + " if (empty($json['class_name'])) {\n" + " return self::json(['error' => 'require class_name!'], 4004);\n" + " }\n" + " if (empty($json['property_name'])) {\n" + " return self::json(['error' => 'require property_name!'], 4004);\n" + " }\n" + "\n" + " $class_name = $json['class_name'];\n" + " $property_name = $json['property_name'];\n" + "\n" + " $refClass = new ReflectionClass($class_name);\n" + " if (!$refClass) {\n" + " return self::json(\"class[{$class_name}] not exists\", 4004);\n" + " }\n" + "\n" + " $property = $refClass->getProperty($property_name);\n" + " if (!$property) {\n" + " return self::json(\"property[{$property_name}] not exists\", 4004);\n" + " }\n" + "\n" + " $property->setAccessible(true);\n" + " $value = $property->getValue($property_name);\n" + "\n" + " $result = [\n" + " 'value' => var_export($value, true),\n" + " ];\n" + " return self::json($result);\n" + " }\n" + "\n" + " private static function getProcessCpuUsage($pid)\n" + " {\n" + " // TODO: Support other OS\n" + " if (PHP_OS_FAMILY !== 'Linux') {\n" + " return [0];\n" + " }\n" + "\n" + " $statAll = file_get_contents('/proc/stat');\n" + " $statProc = file_get_contents(\"/proc/{$pid}/stat\");\n" + "\n" + " $dataAll = preg_split(\"/[ \\t]+/\", $statAll, 6);\n" + " assert($dataAll[0] === 'cpu', '/proc/stat malformed');\n" + " $dataProc = preg_split(\"/[ \\t]+/\", $statProc, 15);\n" + "\n" + " if (isset($dataProc[13]) and isset($dataProc[14])) {\n" + " return [\n" + " (int) $dataAll[1] + (int) $dataAll[2] + (int) $dataAll[3] + (int) $dataAll[4],\n" + " (int) $dataProc[13] + (int) $dataProc[14],\n" + " ];\n" + " }\n" + " return [(int) $dataAll[1] + (int) $dataAll[2] + (int) $dataAll[3] + (int) $dataAll[4]];\n" + " }\n" + "\n" + " private static function getProcessMemoryRealUsage($pid = 'self')\n" + " {\n" + " $status = self::getProcessStatus($pid);\n" + " if (!is_array($status) || !isset($status['VmRSS'])) {\n" + " return 0;\n" + " }\n" + " return intval($status['VmRSS']) * 1024;\n" + " }\n" + "\n" + " private static function getProcessStatus($pid = 'self')\n" + " {\n" + " $array = [];\n" + " // TODO: Support other OS\n" + " if (PHP_OS_FAMILY !== 'Linux') {\n" + " return $array;\n" + " }\n" + " $status = swoole_string(trim(file_get_contents('/proc/' . $pid . '/status')));\n" + " $lines = $status->split(\"\\n\");\n" + " foreach ($lines as $l) {\n" + " if (empty($l)) {\n" + " continue;\n" + " }\n" + " [$k, $v] = swoole_string($l)->split(':');\n" + " $array[$k] = trim($v);\n" + " }\n" + " return $array;\n" + " }\n" + "\n" + " private static function getArrayMemorySize(array $a): int\n" + " {\n" + " $size = self::SIZE_OF_ZVAL + self::SIZE_OF_ZEND_ARRAY;\n" + " foreach ($a as $k => $v) {\n" + " if (is_string($k)) {\n" + " $size += self::getStringMemorySize($k);\n" + " } else {\n" + " $size += self::SIZE_OF_ZVAL;\n" + " }\n" + " if (is_string($v)) {\n" + " $size += self::getStringMemorySize($v);\n" + " } elseif (is_array($v)) {\n" + " $size += self::getArrayMemorySize($v);\n" + " } else {\n" + " $size += self::SIZE_OF_ZVAL;\n" + " }\n" + " }\n" + " return $size;\n" + " }\n" + "\n" + " private static function getStringMemorySize(string $s): int\n" + " {\n" + " return self::SIZE_OF_ZVAL + self::SIZE_OF_ZEND_STRING + strlen($s);\n" + " }\n" + "\n" + " private static function getObjectMemorySize(object $o): int\n" + " {\n" + " $vars = get_object_vars($o);\n" + " $size = self::SIZE_OF_ZEND_OBJECT;\n" + "\n" + " foreach ($vars as $v) {\n" + " if (is_array($v)) {\n" + " $size += self::getArrayMemorySize($v);\n" + " } elseif (is_string($v)) {\n" + " $size += self::getStringMemorySize($v);\n" + " } else {\n" + " $size += self::SIZE_OF_ZVAL;\n" + " }\n" + " }\n" + "\n" + " return $size;\n" + " }\n" + "\n" + " private static function json($data, $code = 0)\n" + " {\n" + " $result = json_encode(['code' => $code, 'data' => $data], JSON_INVALID_UTF8_IGNORE);\n" + " if (empty($result)) {\n" + " return json_encode([\n" + " 'code' => 5010,\n" + " 'data' => ['message' => json_last_error_msg(), 'code' => json_last_error()],\n" + " ]);\n" + " }\n" + " return $result;\n" + " }\n" + "}\n"; + +static const char* swoole_library_source_core_server_helper = + "\n" + "/**\n" + " * This file is part of Swoole.\n" + " *\n" + " * @link https://www.swoole.com\n" + " * @contact team@swoole.com\n" + " * @license https://github.com/swoole/library/blob/master/LICENSE\n" + " */\n" + "\n" + "declare(strict_types=1);\n" + "\n" + "namespace Swoole\\Server;\n" + "\n" + "use Swoole\\Server;\n" + "use Swoole\\Timer;\n" "use function Swoole\\Coroutine\\go;\n" "\n" "class Helper\n" @@ -6951,6 +7969,7 @@ static const char* swoole_library_source_core_server_helper = "\n" " const HELPER_OPTIONS = [\n" " 'stats_file' => true,\n" + " 'stats_timer_interval' => true,\n" " 'admin_server' => true,\n" " ];\n" "\n" @@ -6970,26 +7989,37 @@ static const char* swoole_library_source_core_server_helper = " public static function onBeforeStart(Server $server)\n" " {\n" " if (!empty($server->setting['admin_server'])) {\n" - " $server->addCommand('coroutine_stats',\n" - " 'Get the statistical data of the coroutine scheduler, PATH: /api/coroutine_stats/{$workerId}, GET: [], POST: []',\n" - " SWOOLE_SERVER_COMMAND_EVENT_WORKER | SWOOLE_SERVER_COMMAND_TASK_WORKER,\n" - " function ($server, $msg) {\n" - " return json_encode(Coroutine::stats());\n" - " }\n" - " );\n" + " Admin::init($server);\n" + " }\n" + " }\n" + "\n" + " public static function onBeforeShutdown(Server $server)\n" + " {\n" + " if ($server->admin_server) {\n" + " $server->admin_server->shutdown();\n" + " $server->admin_server = null;\n" " }\n" " }\n" "\n" " public static function onWorkerStart(Server $server, int $workerId)\n" " {\n" " if (!empty($server->setting['stats_file']) and $workerId == 0) {\n" - " $server->stats_timer = Timer::tick(self::STATS_TIMER_INTERVAL_TIME, function () use ($server) {\n" + " $interval_ms = empty($server->setting['stats_timer_interval']) ? self::STATS_TIMER_INTERVAL_TIME : intval($server->setting['stats_timer_interval']);\n" + "\n" + " $server->stats_timer = Timer::tick($interval_ms, function () use ($server) {\n" " $stats = $server->stats();\n" - " $lines = [];\n" - " foreach ($stats as $k => $v) {\n" - " $lines[] = \"{$k}: {$v}\";\n" + " $stats_file = swoole_string($server->setting['stats_file']);\n" + " if ($stats_file->endsWith('.json')) {\n" + " $out = json_encode($stats);\n" + " } elseif ($stats_file->endsWith('.php')) {\n" + " $out = \" $v) {\n" + " $lines[] = \"{$k}: {$v}\";\n" + " }\n" + " $out = implode(\"\\n\", $lines);\n" " }\n" - " $out = implode(\"\\n\", $lines);\n" " file_put_contents($server->setting['stats_file'], $out);\n" " });\n" " }\n" @@ -7011,32 +8041,7 @@ static const char* swoole_library_source_core_server_helper = " {\n" " if (!empty($server->setting['admin_server'])) {\n" " go(function () use ($server) {\n" - " $admin_server_uri = swoole_string($server->setting['admin_server']);\n" - " if ($admin_server_uri->startsWith('unix:/')) {\n" - " $admin_server = new Coroutine\\Http\\Server($admin_server_uri->toString());\n" - " } else {\n" - " list($host, $port) = $admin_server_uri->split(':', 2)->toArray();\n" - " $admin_server = new Coroutine\\Http\\Server($host, intval($port));\n" - " }\n" - " $admin_server->handle('/api', function (Request $req, Response $resp) use ($server) {\n" - " $path_array = swoole_string($req->server['request_uri'])->trim('/')->split('/');\n" - " $cmd = $path_array->get(1)->toString();\n" - " $worker_id = $path_array->get(2)->toString();\n" - " if ($req->getMethod() == 'GET') {\n" - " var_dump($cmd, intval($worker_id), $req->get);\n" - " $result = $server->command($cmd, intval($worker_id), $req->get);\n" - " } else {\n" - " $result = $server->command($cmd, intval($worker_id), $req->post);\n" - " }\n" - " if (!$result) {\n" - " $resp->end(json_encode(['code' => swoole_last_error(),]));\n" - " } else {\n" - " $resp->end(json_encode(['code' => 0, $result]));\n" - " }\n" - " });\n" - " $admin_server->handle('/app', function (Request $req, Response $resp) use ($server) {\n" - " });\n" - " $admin_server->start();\n" + " Admin::start($server);\n" " });\n" " }\n" " }\n" @@ -7730,6 +8735,7 @@ void php_swoole_load_library() zend::eval(swoole_library_source_core_coroutine_fast_cgi_client_exception, "@swoole-src/library/core/Coroutine/FastCGI/Client/Exception.php"); zend::eval(swoole_library_source_core_coroutine_fast_cgi_proxy, "@swoole-src/library/core/Coroutine/FastCGI/Proxy.php"); zend::eval(swoole_library_source_core_process_manager, "@swoole-src/library/core/Process/Manager.php"); + zend::eval(swoole_library_source_core_server_admin, "@swoole-src/library/core/Server/Admin.php"); zend::eval(swoole_library_source_core_server_helper, "@swoole-src/library/core/Server/Helper.php"); zend::eval(swoole_library_source_core_coroutine_functions, "@swoole-src/library/core/Coroutine/functions.php"); zend::eval(swoole_library_source_ext_curl, "@swoole-src/library/ext/curl.php"); diff --git a/src/memory/fixed_pool.cc b/src/memory/fixed_pool.cc index 2a598e280ec..fdb89aef055 100644 --- a/src/memory/fixed_pool.cc +++ b/src/memory/fixed_pool.cc @@ -82,13 +82,13 @@ FixedPool::FixedPool(uint32_t slice_size, void *memory, size_t size, bool shared impl = (FixedPoolImpl*) memory; memory = (char*) memory + sizeof(*impl); sw_memset_zero(impl, sizeof(*impl)); + impl->shared = shared; + impl->slice_size = slice_size; + impl->size = size - sizeof(*impl); uint32_t slice_num = impl->size / (slice_size + sizeof(FixedPoolSlice)); if (slice_num < 2) { throw Exception(SW_ERROR_INVALID_PARAMS); } - impl->shared = shared; - impl->slice_size = slice_size; - impl->size = size - sizeof(*impl); impl->slice_num = slice_num; impl->memory = memory; impl->allocated = false; diff --git a/tests/include/functions.php b/tests/include/functions.php index 98c954b799e..a57b77d59d5 100644 --- a/tests/include/functions.php +++ b/tests/include/functions.php @@ -798,4 +798,9 @@ function swoole_get_variance($avg, $array, $is_swatch = false) function swoole_get_average($array) { return array_sum($array) / count($array); -} \ No newline at end of file +} + +function assert_server_stats($stats) { + Assert::keyExists($stats, 'connection_num'); + Assert::keyExists($stats, 'request_count'); +} diff --git a/tests/swoole_server/stats_file.phpt b/tests/swoole_server/stats_file.phpt index 22741a68687..62a438c7ae4 100644 --- a/tests/swoole_server/stats_file.phpt +++ b/tests/swoole_server/stats_file.phpt @@ -9,9 +9,12 @@ require __DIR__ . '/../include/bootstrap.php'; use function Swoole\Coroutine\run; const STATS_FILE = __DIR__ . '/stats.log'; -if (is_file(STATS_FILE)) { - unlink(STATS_FILE); -} +$rm_fn = function () { + if (is_file(STATS_FILE)) { + unlink(STATS_FILE); + } +}; +$rm_fn(); $pm = new ProcessManager; $pm->initFreePorts(1); @@ -59,5 +62,6 @@ $pm->childFunc = function () use ($pm) { $pm->childFirst(); $pm->run(); +$rm_fn(); ?> --EXPECT-- diff --git a/tests/swoole_server/stats_file_json.phpt b/tests/swoole_server/stats_file_json.phpt new file mode 100644 index 00000000000..47dc6717f5c --- /dev/null +++ b/tests/swoole_server/stats_file_json.phpt @@ -0,0 +1,62 @@ +--TEST-- +swoole_server: stats_file [json] +--SKIPIF-- + +--FILE-- +initFreePorts(1); + +$pm->parentFunc = function ($pid) use ($pm) { + run(function () use ($pm, $pid) { + httpRequest('http://127.0.0.1:' . $pm->getFreePort(0)); + for ($i = 0; $i < 4; ++$i) { + Co::sleep(0.5); + $content = @file_get_contents(STATS_FILE); + if ('' != $content) { + $stats = json_decode($content, true); + assert_server_stats($stats); + break; + } + } + }); + echo "\n"; + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm) { + $mode = SERVER_MODE_RANDOM; + $worker_num = rand(1, 4); + phpt_var_dump("mode: $mode\nworker_num: $worker_num\n"); + $server = new Swoole\Http\Server('127.0.0.1', $pm->getFreePort(0), $mode); + $server->set([ + 'stats_file' => STATS_FILE, + 'log_file' => DEV_NULL, + 'worker_num' => $worker_num, + ]); + $server->on('ManagerStart', function ($serv) use ($pm) { + $pm->wakeup(); + }); + $server->on('request', function ($request, $response) { + $response->end("

Hello Swoole. #" . rand(1000, 9999) . "

"); + }); + $server->start(); +}; + +$pm->childFirst(); +$pm->run(); +$rm_fn(); +?> +--EXPECT-- diff --git a/tests/swoole_server/stats_file_php.phpt b/tests/swoole_server/stats_file_php.phpt new file mode 100644 index 00000000000..6f95430bd0e --- /dev/null +++ b/tests/swoole_server/stats_file_php.phpt @@ -0,0 +1,65 @@ +--TEST-- +swoole_server: stats_file [php] +--SKIPIF-- + +--FILE-- +initFreePorts(1); + +$pm->parentFunc = function ($pid) use ($pm) { + run(function () use ($pm, $pid) { + httpRequest('http://127.0.0.1:' . $pm->getFreePort(0)); + for ($i = 0; $i < 4; ++$i) { + Co::sleep(0.5); + if (!is_file(STATS_FILE)) { + continue; + } + $stats = include STATS_FILE; + if (empty($stats)) { + assert_server_stats($stats); + break; + } + } + }); + echo "\n"; + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm) { + $mode = SERVER_MODE_RANDOM; + $worker_num = rand(1, 4); + phpt_var_dump("mode: $mode\nworker_num: $worker_num\n"); + $server = new Swoole\Http\Server('127.0.0.1', $pm->getFreePort(0), $mode); + $server->set([ + 'stats_file' => STATS_FILE, + 'log_file' => DEV_NULL, + 'worker_num' => $worker_num, + ]); + $server->on('ManagerStart', function ($serv) use ($pm) { + $pm->wakeup(); + }); + $server->on('request', function ($request, $response) { + $response->end("

Hello Swoole. #" . rand(1000, 9999) . "

"); + }); + $server->start(); +}; + +$pm->childFirst(); +$pm->run(); + +$rm_fn(); +?> +--EXPECT-- diff --git a/tools/build-library.php b/tools/build-library.php index 9a77ac5b979..4055ed71f53 100755 --- a/tools/build-library.php +++ b/tools/build-library.php @@ -85,6 +85,7 @@ # # 'core/Process/Manager.php', # # + 'core/Server/Admin.php', 'core/Server/Helper.php', # # 'core/Coroutine/functions.php', From 2198378d8a4e71ff53a0e895d83d7bdc5f795054 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Sat, 9 Oct 2021 13:25:14 +0800 Subject: [PATCH 261/936] Fix connection cannot be forcibly closed --- src/server/process.cc | 3 ++- src/server/reactor_thread.cc | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/server/process.cc b/src/server/process.cc index 605007244c9..df38a959aeb 100644 --- a/src/server/process.cc +++ b/src/server/process.cc @@ -205,7 +205,8 @@ bool ProcessFactory::finish(SendData *resp) { resp->info.len, session_id); return false; - } else if (conn->overflow) { + } else if (conn->overflow && + (resp->info.type == SW_SERVER_EVENT_SEND_DATA && resp->info.type == SW_SERVER_EVENT_SEND_FILE)) { if (server_->send_yield && process_is_supported_send_yield(server_, conn)) { swoole_set_last_error(SW_ERROR_OUTPUT_SEND_YIELD); } else { diff --git a/src/server/reactor_thread.cc b/src/server/reactor_thread.cc index be828e93e97..d00d1f44cc4 100644 --- a/src/server/reactor_thread.cc +++ b/src/server/reactor_thread.cc @@ -1055,8 +1055,7 @@ void Server::start_heartbeat_thread() { ev.type = SW_SERVER_EVENT_CLOSE_FORCE; // convert fd to session_id, in order to verify the connection before the force close connection ev.fd = session_id; - Socket *_pipe_sock = get_reactor_pipe_socket(session_id, conn->reactor_id); - _pipe_sock->send_blocking((void *) &ev, sizeof(ev)); + get_reactor_pipe_socket(session_id, conn->reactor_id)->send_blocking(&ev, sizeof(ev)); }); sleep(heartbeat_check_interval); } From f018c8981205927ae0137487ec13e438ba43b2a7 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 12 Oct 2021 11:04:38 +0800 Subject: [PATCH 262/936] Update library and README --- README-CN.md | 2 +- README.md | 2 +- ext-src/php_swoole_library.h | 169 +++++++++++++++++++++++++---------- swoole-logo.svg | 15 ++++ 4 files changed, 138 insertions(+), 50 deletions(-) create mode 100644 swoole-logo.svg diff --git a/README-CN.md b/README-CN.md index a418d8decd6..d742a3af669 100644 --- a/README-CN.md +++ b/README-CN.md @@ -1,7 +1,7 @@ [English](./README.md) | 中文

-Swoole Logo +Swoole Logo

[![lib-swoole](https://github.com/swoole/swoole-src/workflows/lib-swoole/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Alib-swoole) diff --git a/README.md b/README.md index 145143df500..06a7f30c7b7 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ English | [中文](./README-CN.md)

-Swoole Logo +Swoole Logo

[![lib-swoole](https://github.com/swoole/swoole-src/workflows/lib-swoole/badge.svg)](https://github.com/swoole/swoole-src/actions?query=workflow%3Alib-swoole) diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index dd3aa6b375e..eba4d805df4 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: 3efc2e949a7125178561fb5c3f3ae5a4dd176dfa */ +/* $Id: a6b2a575a3a0ae9d66b8140650d1a98b00bd4097 */ static const char* swoole_library_source_constants = "\n" @@ -20,7 +20,8 @@ static const char* swoole_library_source_constants = "\n" "!defined('CURLOPT_HEADEROPT') && define('CURLOPT_HEADEROPT', 229);\n" "!defined('CURLOPT_PROXYHEADER') && define('CURLOPT_PROXYHEADER', 10228);\n" - "!defined('CURLOPT_RESOLVE') && define('CURLOPT_RESOLVE', 10203);\n"; + "!defined('CURLOPT_RESOLVE') && define('CURLOPT_RESOLVE', 10203);\n" + "!defined('CURLOPT_UNIX_SOCKET_PATH') && define('CURLOPT_UNIX_SOCKET_PATH', 10231);\n"; static const char* swoole_library_source_std_exec = "\n" @@ -3597,6 +3598,8 @@ static const char* swoole_library_source_core_curl_handler = "\n" " private $resolve = [];\n" "\n" + " private $unix_socket_path = '';\n" + "\n" " public function __construct(string $url = '')\n" " {\n" " if ($url) {\n" @@ -3691,6 +3694,13 @@ static const char* swoole_library_source_core_curl_handler = " }\n" " $this->urlInfo['host'] = $host = $this->resolve[$host][$port] ?? null ?: $host;\n" " }\n" + " if ($this->unix_socket_path) {\n" + " $host = $this->unix_socket_path;\n" + " $port = 0;\n" + " if (stripos($host, 'unix:/') !== 0) {\n" + " $host = \"unix:/{$host}\";\n" + " }\n" + " }\n" " $this->client = new Client($host, $port, $urlInfo['scheme'] === 'https');\n" " }\n" "\n" @@ -3716,11 +3726,19 @@ static const char* swoole_library_source_core_curl_handler = " $this->setError(CURLE_URL_MALFORMAT, 'No URL set!');\n" " return false;\n" " }\n" - " if (strpos($url, '://') === false) {\n" + " if (strpos($url, '://') === false && $this->unix_socket_path === '') {\n" " $url = 'http://' . $url;\n" " }\n" " if ($setInfo) {\n" " $urlInfo = parse_url($url);\n" + " if ($this->unix_socket_path) {\n" + " if (empty($urlInfo['host']) && !empty($urlInfo['path'])) {\n" + " $urlInfo['host'] = explode('/', $urlInfo['path'])[1] ?? null;\n" + " }\n" + " if (!$this->hasHeader('Host') && !empty($urlInfo['host'])) {\n" + " $this->setHeader('Host', $urlInfo['host']);\n" + " }\n" + " }\n" " if (!is_array($urlInfo)) {\n" " $this->setError(CURLE_URL_MALFORMAT, \"URL[{$url}] using bad/illegal format\");\n" " return false;\n" @@ -3884,6 +3902,14 @@ static const char* swoole_library_source_core_curl_handler = " case CURLOPT_PROXYAUTH:\n" " /* ignored temporarily */\n" " break;\n" + " case CURLOPT_UNIX_SOCKET_PATH:\n" + " $realpath = realpath((string) $value);\n" + " if ($realpath) {\n" + " $this->unix_socket_path = $realpath;\n" + " } else {\n" + " $this->setError(CURLE_COULDNT_CONNECT);\n" + " }\n" + " break;\n" " case CURLOPT_NOBODY:\n" " $this->nobody = boolval($value);\n" " $this->method = 'HEAD';\n" @@ -4140,7 +4166,7 @@ static const char* swoole_library_source_core_curl_handler = " if (!$this->client) {\n" " $this->create();\n" " }\n" - " do {\n" + " while (true) {\n" " $client = $this->client;\n" " /*\n" " * Http Proxy\n" @@ -4290,7 +4316,7 @@ static const char* swoole_library_source_core_curl_handler = " } else {\n" " break;\n" " }\n" - " } while (true);\n" + " }\n" " $this->info['total_time'] = microtime(true) - $timeBegin;\n" " $this->info['http_code'] = $client->statusCode;\n" " $this->info['content_type'] = $client->headers['content-type'] ?? '';\n" @@ -4304,6 +4330,11 @@ static const char* swoole_library_source_core_curl_handler = " $this->info['primary_ip'] = $this->urlInfo['host'];\n" " }\n" "\n" + " if ($this->unix_socket_path) {\n" + " $this->info['primary_ip'] = $this->unix_socket_path;\n" + " $this->info['primary_port'] = $this->urlInfo['port'];\n" + " }\n" + "\n" " $headerContent = '';\n" " if ($client->headers) {\n" " $cb = $this->headerFunction;\n" @@ -4840,8 +4871,8 @@ static const char* swoole_library_source_core_fast_cgi_record_params = " [$nameLength, $valueLength] = array_values(unpack($format, $data));\n" "\n" " // Clear top bit for long record\n" - " $nameLength &= ($isLongName ? 0x7fffffff : 0x7f);\n" - " $valueLength &= ($isLongValue ? 0x7fffffff : 0x7f);\n" + " $nameLength &= ($isLongName ? 0x7FFFFFFF : 0x7F);\n" + " $valueLength &= ($isLongValue ? 0x7FFFFFFF : 0x7F);\n" "\n" " [$nameData, $valueData] = array_values(\n" " unpack(\n" @@ -6829,15 +6860,15 @@ static const char* swoole_library_source_core_server_admin = " * (gdb) p sizeof(zend_object)\n" " * $4 = 56\n" " */\n" - " const SIZE_OF_ZVAL = 16;\n" + " public const SIZE_OF_ZVAL = 16;\n" "\n" - " const SIZE_OF_ZEND_STRING = 32;\n" + " public const SIZE_OF_ZEND_STRING = 32;\n" "\n" - " const SIZE_OF_ZEND_OBJECT = 56;\n" + " public const SIZE_OF_ZEND_OBJECT = 56;\n" "\n" - " const SIZE_OF_ZEND_ARRAY = 56;\n" + " public const SIZE_OF_ZEND_ARRAY = 56;\n" "\n" - " const DASHBOARD_DIR = '/opt/swoole/dashboard';\n" + " public const DASHBOARD_DIR = '/opt/swoole/dashboard';\n" "\n" " public static function init(Server $server)\n" " {\n" @@ -6847,6 +6878,23 @@ static const char* swoole_library_source_core_server_admin = " SWOOLE_SERVER_COMMAND_TASK_WORKER;\n" "\n" " $server->addCommand(\n" + " 'server_reload',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " $server->reload();\n" + " return self::json('Operation succeeded');\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'server_shutdown',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " $server->shutdown();\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" " 'coroutine_stats',\n" " $accepted_process_types,\n" " function ($server, $msg) {\n" @@ -6913,21 +6961,7 @@ static const char* swoole_library_source_core_server_admin = " }\n" " );\n" "\n" - " $server->addCommand(\n" - " 'close_session',\n" - " $accepted_process_types,\n" - " function (Server $server, $msg) {\n" - " $json = json_decode($msg, true);\n" - " if (empty($json['session_id'])) {\n" - " return self::json('require session_id', 4003);\n" - " }\n" - " if ($server->close(intval($json['session_id']), !empty($json['force']))) {\n" - " return self::json([]);\n" - " }\n" - " return self::json(['error' => swoole_last_error()], 4004);\n" - " }\n" - " );\n" - "\n" + " $server->addCommand('close_session', $accepted_process_types, [__CLASS__, 'handlerCloseSession']);\n" " $server->addCommand('get_version_info', $accepted_process_types, [__CLASS__, 'handlerGetVersionInfo']);\n" " $server->addCommand('get_worker_info', $accepted_process_types, [__CLASS__, 'handlerGetWorkerInfo']);\n" " $server->addCommand('get_timer_list', $accepted_process_types, [__CLASS__, 'handlerGetTimerList']);\n" @@ -7306,6 +7340,23 @@ static const char* swoole_library_source_core_server_admin = " * @param $msg\n" " * @return false|string\n" " */\n" + " public static function handlerCloseSession($server, $msg)\n" + " {\n" + " $json = json_decode($msg, true);\n" + " if (empty($json['session_id'])) {\n" + " return self::json('require session_id', 4003);\n" + " }\n" + " if ($server->close(intval($json['session_id']), !empty($json['force']))) {\n" + " return self::json([]);\n" + " }\n" + " return self::json(['error' => swoole_last_error()], 4004);\n" + " }\n" + "\n" + " /**\n" + " * @param $server\n" + " * @param $msg\n" + " * @return false|string\n" + " */\n" " public static function handlerGetTimerList($server, $msg)\n" " {\n" " $list = [];\n" @@ -7504,31 +7555,53 @@ static const char* swoole_library_source_core_server_admin = "\n" " $list = [];\n" " foreach ($params as $param) {\n" - " $type = $param->hasType() ? $param->getType()->getName() : '';\n" + " $type = $optional = $default = '';\n" + "\n" + " if ($param->hasType()) {\n" + " /** @var \\ReflectionNamedType|\\ReflectionUnionType $getType */\n" + " $getType = $param->getType();\n" + " if ($getType instanceof \\ReflectionUnionType) {\n" + " $unionType = [];\n" + " foreach ($getType->getTypes() as $objType) {\n" + " $unionType[] = $objType->getName();\n" + " }\n" + " $type = implode('|', $unionType);\n" + " } else {\n" + " $type = $getType->getName();\n" + " }\n" + " }\n" "\n" - " $optional = $default = '';\n" - " if ($param->isOptional() && !$param->isVariadic() && PHP_VERSION_ID >= 80000) {\n" + " if ($param->isOptional() && !$param->isVariadic()) {\n" + " if (!$result['user_defined'] && PHP_VERSION_ID < 80000) {\n" + " continue;\n" + " }\n" " $optional = '?';\n" - " $value = $param->getDefaultValue();\n" - " if (in_array($value, [true, false, null])) {\n" - " if ($value === null) {\n" - " $value = 'null';\n" - " }\n" - " if ($value === true) {\n" - " $value = 'true';\n" - " }\n" - " if ($value === false) {\n" - " $value = 'false';\n" + " if ($param->isDefaultValueAvailable()) {\n" + " $value = $param->getDefaultValue();\n" + " if (in_array($value, [true, false, null, ''])) {\n" + " if ($value === null) {\n" + " $value = 'null';\n" + " }\n" + " if ($value === true) {\n" + " $value = 'true';\n" + " }\n" + " if ($value === false) {\n" + " $value = 'false';\n" + " }\n" + " if ($value === '') {\n" + " $value = \"''\";\n" + " }\n" " }\n" + " $default = \" = {$value}\";\n" " }\n" - " $default = \" = {$value}\";\n" " }\n" "\n" " $isPassedByReference = $param->isPassedByReference() ? '&' : '';\n" " $isVariadic = $param->isVariadic() ? '...' : '';\n" "\n" - " $param_value = \"{$optional}{$type} {$isPassedByReference}{$isVariadic}{$param->getName()}{$default}\";\n" - "\n" + " $option = \"{$optional}{$type} {$isPassedByReference}{$isVariadic}\";\n" + " $param = \"\\${$param->getName()}{$default}\";\n" + " $param_value = $option !== ' ' ? \"{$option}{$param}\" : $param;\n" " $list[] = $param_value;\n" " }\n" " $result['params'] = $list;\n" @@ -7832,9 +7905,9 @@ static const char* swoole_library_source_core_server_helper = "\n" "class Helper\n" "{\n" - " const STATS_TIMER_INTERVAL_TIME = 1000;\n" + " public const STATS_TIMER_INTERVAL_TIME = 1000;\n" "\n" - " const GLOBAL_OPTIONS = [\n" + " public const GLOBAL_OPTIONS = [\n" " 'debug_mode' => true,\n" " 'trace_flags' => true,\n" " 'log_file' => true,\n" @@ -7854,7 +7927,7 @@ static const char* swoole_library_source_core_server_helper = " 'socket_timeout' => true,\n" " ];\n" "\n" - " const SERVER_OPTIONS = [\n" + " public const SERVER_OPTIONS = [\n" " 'chroot' => true,\n" " 'user' => true,\n" " 'group' => true,\n" @@ -7917,7 +7990,7 @@ static const char* swoole_library_source_core_server_helper = " 'message_queue_key' => true,\n" " ];\n" "\n" - " const PORT_OPTIONS = [\n" + " public const PORT_OPTIONS = [\n" " 'ssl_cert_file' => true,\n" " 'ssl_key_file' => true,\n" " 'backlog' => true,\n" @@ -7967,7 +8040,7 @@ static const char* swoole_library_source_core_server_helper = " 'ssl_sni_certs' => true,\n" " ];\n" "\n" - " const HELPER_OPTIONS = [\n" + " public const HELPER_OPTIONS = [\n" " 'stats_file' => true,\n" " 'stats_timer_interval' => true,\n" " 'admin_server' => true,\n" diff --git a/swoole-logo.svg b/swoole-logo.svg new file mode 100644 index 00000000000..6297cc67437 --- /dev/null +++ b/swoole-logo.svg @@ -0,0 +1,15 @@ + + + + Transfon SWOOLE - Registered + + + + \ No newline at end of file From 09e04274e6526cfdbccb7c2affa21007f80c0ffd Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 12 Oct 2021 11:44:56 +0800 Subject: [PATCH 263/936] Optimize code --- ext-src/swoole_http_response.cc | 1 + ext-src/swoole_redis_coro.cc | 2 +- src/coroutine/socket.cc | 7 +++++-- src/protocol/redis.cc | 21 ++++++++++++--------- src/server/process.cc | 2 +- 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/ext-src/swoole_http_response.cc b/ext-src/swoole_http_response.cc index e1543046670..71961971349 100644 --- a/ext-src/swoole_http_response.cc +++ b/ext-src/swoole_http_response.cc @@ -1345,6 +1345,7 @@ static PHP_METHOD(swoole_http_response, create) { ctx->parser.data = ctx; swoole_http_parser_init(&ctx->parser, PHP_HTTP_REQUEST); } else { + delete ctx; assert(0); RETURN_FALSE; } diff --git a/ext-src/swoole_redis_coro.cc b/ext-src/swoole_redis_coro.cc index 02ac7643191..f86e8be2875 100644 --- a/ext-src/swoole_redis_coro.cc +++ b/ext-src/swoole_redis_coro.cc @@ -4824,7 +4824,7 @@ static PHP_METHOD(swoole_redis_coro, xTrim) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|a", &key, &key_len, &z_options) == FAILURE) { RETURN_FALSE; } - if (zend_hash_num_elements(Z_ARRVAL_P(z_options)) < 1) { + if (php_swoole_array_length_safe(z_options) < 1) { RETURN_FALSE; } diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index dca93e28e84..f26810be35b 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -1146,11 +1146,14 @@ bool Socket::listen(int backlog) { return false; } this->backlog = backlog <= 0 ? SW_BACKLOG : backlog; - if (socket->listen(this->backlog) != 0) { + if (socket->listen(this->backlog) < 0) { + set_err(errno); + return false; + } + if (socket->get_name(&socket->info) < 0) { set_err(errno); return false; } - socket->get_name(&socket->info); #ifdef SW_USE_OPENSSL ssl_is_server = true; #endif diff --git a/src/protocol/redis.cc b/src/protocol/redis.cc index 184ffa0602e..424319a849b 100644 --- a/src/protocol/redis.cc +++ b/src/protocol/redis.cc @@ -102,18 +102,21 @@ int recv_packet(Protocol *protocol, Connection *conn, String *buffer) { do { switch (request->state) { case STATE_RECEIVE_TOTAL_LINE: - if (*p == '*' && (p = get_number(p, &ret))) { + if (*p == '*') { + if ((p = get_number(p, &ret)) == nullptr) { + goto _failed; + } request->n_lines_total = ret; request->state = STATE_RECEIVE_LENGTH; break; } - if (p == nullptr) { - goto _failed; - } /* no break */ case STATE_RECEIVE_LENGTH: - if (*p == '$' && (p = get_number(p, &ret))) { + if (*p == '$') { + if ((p = get_number(p, &ret)) == nullptr) { + goto _failed; + } if (ret < 0) { break; } @@ -125,12 +128,12 @@ int recv_packet(Protocol *protocol, Connection *conn, String *buffer) { break; } // integer - else if (*p == ':' && (p = get_number(p, &ret))) { + else if (*p == ':') { + if ((p = get_number(p, &ret)) == nullptr) { + goto _failed; + } break; } - if (p == nullptr) { - goto _failed; - } /* no break */ case STATE_RECEIVE_STRING: diff --git a/src/server/process.cc b/src/server/process.cc index df38a959aeb..9468322052c 100644 --- a/src/server/process.cc +++ b/src/server/process.cc @@ -206,7 +206,7 @@ bool ProcessFactory::finish(SendData *resp) { session_id); return false; } else if (conn->overflow && - (resp->info.type == SW_SERVER_EVENT_SEND_DATA && resp->info.type == SW_SERVER_EVENT_SEND_FILE)) { + (resp->info.type == SW_SERVER_EVENT_SEND_DATA || resp->info.type == SW_SERVER_EVENT_SEND_FILE)) { if (server_->send_yield && process_is_supported_send_yield(server_, conn)) { swoole_set_last_error(SW_ERROR_OUTPUT_SEND_YIELD); } else { From 372fdb824a91173bfe4892b3a75e4662473b64d3 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Tue, 12 Oct 2021 18:04:34 +0800 Subject: [PATCH 264/936] Update library, remove CREDITS --- CREDITS | 3 --- ext-src/php_swoole_library.h | 19 ++++++++++++------- 2 files changed, 12 insertions(+), 10 deletions(-) delete mode 100644 CREDITS diff --git a/CREDITS b/CREDITS deleted file mode 100644 index 7f55d94500b..00000000000 --- a/CREDITS +++ /dev/null @@ -1,3 +0,0 @@ -Tianfeng Han(mikan.tenny@gmail.com) -Swoole Inc. -QQ: 350749960 diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index eba4d805df4..a7acb858726 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: a6b2a575a3a0ae9d66b8140650d1a98b00bd4097 */ +/* $Id: 34a3bb25db6d0dfd46128628ed753f8ad84a5ab8 */ static const char* swoole_library_source_constants = "\n" @@ -7181,11 +7181,11 @@ static const char* swoole_library_source_core_server_admin = " {\n" " $admin_server_uri = swoole_string($server->setting['admin_server']);\n" " if ($admin_server_uri->startsWith('unix:/')) {\n" - " $admin_server = new Coroutine\\Http\\Server($admin_server_uri->toString());\n" - " } else {\n" - " [$host, $port] = $admin_server_uri->split(':', 2)->toArray();\n" - " $admin_server = new Coroutine\\Http\\Server($host, intval($port));\n" + " return swoole_error_log(SWOOLE_LOG_ERROR, \"admin_server[{$server->setting['admin_server']}] is not supported\");\n" " }\n" + " [$host, $port] = $admin_server_uri->split(':', 2)->toArray();\n" + " $admin_server = new Coroutine\\Http\\Server($host, intval($port));\n" + "\n" " $admin_server->handle('/api', function (Request $req, Response $resp) use ($server) {\n" " $path_array = swoole_string($req->server['request_uri'])->trim('/')->split('/');\n" " if ($path_array->count() < 2 or $path_array->count() > 3) {\n" @@ -7240,7 +7240,7 @@ static const char* swoole_library_source_core_server_admin = " }\n" "\n" " $resp->header('Access-Control-Allow-Origin', '*');\n" - " $resp->header('Access-Control-Allow-Methods', 'GET, OPTIONS');\n" + " $resp->header('Access-Control-Allow-Methods', 'GET, OPTIONS');\n" " $resp->header('Access-Control-Allow-Headers', 'X-ACCESS-TOKEN');\n" "\n" " $result = $server->command($cmd, intval($process_id), intval($process_type), $data, false);\n" @@ -7266,7 +7266,7 @@ static const char* swoole_library_source_core_server_admin = " }\n" " $tmp_file = '/tmp/swoole_dashborad.' . SWOOLE_VERSION . '.tar.gz';\n" " file_put_contents($tmp_file, $download_request->getBody());\n" - " if (is_file($tmp_file) or filesize($tmp_file) == 0) {\n" + " if (!is_file($tmp_file) or filesize($tmp_file) === 0) {\n" " $resp->end(\"write [{$tmp_file}] failed\");\n" " return;\n" " }\n" @@ -7275,6 +7275,11 @@ static const char* swoole_library_source_core_server_admin = " }\n" " $sh = 'tar zxvf ' . $tmp_file . ' -C ' . $dir;\n" " System::exec($sh);\n" + " $remote_addr = $req->server['remote_addr'];\n" + " $server_port = $req->server['server_port'];\n" + " $f = $dir . '/dist/js/app.js';\n" + " $baseURL = 'baseURL:\"http://' . $remote_addr . ':' . $server_port . '/\"';\n" + " file_put_contents($f, str_replace('baseURL:\"http://127.0.0.1:9502/\"', $baseURL, file_get_contents($f)));\n" " }\n" " }\n" "\n" From 1bc39175acb7d339a9d2d046e031dd9561adb1eb Mon Sep 17 00:00:00 2001 From: albert Date: Wed, 13 Oct 2021 18:43:50 +0800 Subject: [PATCH 265/936] client support ssl_ciphers config (#4432) --- ext-src/swoole_client.cc | 4 ++++ ext-src/swoole_client_coro.cc | 3 +++ 2 files changed, 7 insertions(+) diff --git a/ext-src/swoole_client.cc b/ext-src/swoole_client.cc index 5ca6650f5f3..b01301d3505 100644 --- a/ext-src/swoole_client.cc +++ b/ext-src/swoole_client.cc @@ -324,6 +324,10 @@ void php_swoole_client_check_ssl_setting(Client *cli, zval *zset) { zend_long v = zval_get_long(ztmp); cli->ssl_context->verify_depth = SW_MAX(0, SW_MIN(v, UINT8_MAX)); } + if (php_swoole_array_get_value(vht, "ssl_ciphers", ztmp)) { + zend::String str_v(ztmp); + cli->ssl_context->ciphers = str_v.to_std_string(); + } if (!cli->ssl_context->cert_file.empty() && cli->ssl_context->key_file.empty()) { php_swoole_fatal_error(E_ERROR, "ssl require key file"); return; diff --git a/ext-src/swoole_client_coro.cc b/ext-src/swoole_client_coro.cc index 86049b89f6d..49dd4d2eda7 100644 --- a/ext-src/swoole_client_coro.cc +++ b/ext-src/swoole_client_coro.cc @@ -457,6 +457,9 @@ bool php_swoole_socket_set_ssl(Socket *sock, zval *zset) { zend_long v = zval_get_long(ztmp); sock->get_ssl_context()->verify_depth = SW_MAX(0, SW_MIN(v, UINT8_MAX)); } + if (php_swoole_array_get_value(vht, "ssl_ciphers", ztmp)) { + sock->get_ssl_context()->ciphers = zend::String(ztmp).to_std_string(); + } if (!sock->ssl_check_context()) { ret = false; } From 0a869854fc71146d15a6e1b17386baa12d05ca78 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Thu, 14 Oct 2021 01:40:38 +0800 Subject: [PATCH 266/936] No longer include swoole dashboard --- ext-src/php_swoole_library.h | 39 ++---------------------------------- 1 file changed, 2 insertions(+), 37 deletions(-) diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index a7acb858726..a1f9ecd6f4f 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: 34a3bb25db6d0dfd46128628ed753f8ad84a5ab8 */ +/* $Id: 47fac979e2420ba0a43cadb1faacce5d75fe0462 */ static const char* swoole_library_source_constants = "\n" @@ -7254,42 +7254,7 @@ static const char* swoole_library_source_core_server_admin = " }\n" " });\n" " $admin_server->handle('/', function (Request $req, Response $resp) use ($server) {\n" - " if ($req->server['request_uri'] == '/' or $req->server['request_uri'] == '/index.html') {\n" - " $dir = self::DASHBOARD_DIR . '/' . SWOOLE_VERSION;\n" - " $index_file = $dir . '/dist/index.html';\n" - " if (!is_file($index_file)) {\n" - " $url = 'https://business.swoole.com/static/swoole_dashboard/' . SWOOLE_VERSION . '.tar.gz';\n" - " $download_request = Coroutine\\Http\\get($url);\n" - " if (!$download_request or $download_request->getStatusCode() != '200') {\n" - " $resp->end(\"download [{$url}] failed\");\n" - " return;\n" - " }\n" - " $tmp_file = '/tmp/swoole_dashborad.' . SWOOLE_VERSION . '.tar.gz';\n" - " file_put_contents($tmp_file, $download_request->getBody());\n" - " if (!is_file($tmp_file) or filesize($tmp_file) === 0) {\n" - " $resp->end(\"write [{$tmp_file}] failed\");\n" - " return;\n" - " }\n" - " if (!is_dir($dir)) {\n" - " mkdir($dir, 0777, true);\n" - " }\n" - " $sh = 'tar zxvf ' . $tmp_file . ' -C ' . $dir;\n" - " System::exec($sh);\n" - " $remote_addr = $req->server['remote_addr'];\n" - " $server_port = $req->server['server_port'];\n" - " $f = $dir . '/dist/js/app.js';\n" - " $baseURL = 'baseURL:\"http://' . $remote_addr . ':' . $server_port . '/\"';\n" - " file_put_contents($f, str_replace('baseURL:\"http://127.0.0.1:9502/\"', $baseURL, file_get_contents($f)));\n" - " }\n" - " }\n" - "\n" - " $file = self::DASHBOARD_DIR . '/' . SWOOLE_VERSION . '/dist/' . ($req->server['request_uri'] == '/' ? 'index.html' : $req->server['request_uri']);\n" - " if (!is_file($file)) {\n" - " $resp->status(404);\n" - " $resp->end('file ' . $file . ' not found');\n" - " } else {\n" - " $resp->sendfile($file);\n" - " }\n" + " $resp->status(404);\n" " });\n" " $server->admin_server = $admin_server;\n" " $admin_server->start();\n" From ffdb510da3cf2e671b7ea9c9b29d791cda908cfa Mon Sep 17 00:00:00 2001 From: codinghuang Date: Thu, 14 Oct 2021 13:08:37 +0800 Subject: [PATCH 267/936] Update version for Swoole 4.8.0 (#4431) * Update version for Swoole 4.8.0 * Added release permission * Update package.xml * Added release permission * Revert "Added release permission" This reverts commit 7b62768fc91806f8a66b9fc964a89cfc24ae3e7f. * client support ssl_ciphers config (#4432) * Update version for Swoole 4.8.0 Co-authored-by: Bruce Dou Co-authored-by: matyhtf Co-authored-by: albert --- CMakeLists.txt | 2 +- config.m4 | 2 +- ext-src/php_swoole_library.h | 10 ++ include/swoole_version.h | 12 +-- package.xml | 91 +++++++++++++------ tests/swoole_curl/multi/bug4393.phpt | 2 +- .../file_hook/open_basedir.phpt | 4 +- tests/swoole_server/bug_2308.phpt | 1 - 8 files changed, 84 insertions(+), 40 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index db511c86491..014d06a0961 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ PROJECT(libswoole) ENABLE_LANGUAGE(ASM) -set(SWOOLE_VERSION 4.7.2-dev) +set(SWOOLE_VERSION 4.8.0) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g") diff --git a/config.m4 b/config.m4 index 692d85bac3a..d5e465933c1 100644 --- a/config.m4 +++ b/config.m4 @@ -623,6 +623,7 @@ if test "$PHP_SWOOLE" != "no"; then src/server/base.cc \ src/server/manager.cc \ src/server/master.cc \ + src/server/message_bus.cc \ src/server/port.cc \ src/server/process.cc \ src/server/reactor_process.cc \ @@ -630,7 +631,6 @@ if test "$PHP_SWOOLE" != "no"; then src/server/static_handler.cc \ src/server/task_worker.cc \ src/server/worker.cc \ - src/server/message_bus.cc \ src/wrapper/event.cc \ src/wrapper/timer.cc" diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index a1f9ecd6f4f..e06ebfc14e1 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -86,6 +86,8 @@ static const char* swoole_library_source_core_constant = " /* {{{ EVENT */\n" " public const EVENT_START = 'start';\n" "\n" + " public const EVENT_BEFORE_SHUTDOWN = 'beforeShutdown';\n" + "\n" " public const EVENT_SHUTDOWN = 'shutdown';\n" "\n" " public const EVENT_WORKER_START = 'workerStart';\n" @@ -499,6 +501,14 @@ static const char* swoole_library_source_core_constant = "\n" " public const OPTION_OPEN_FASTCGI_PROTOCOL = 'open_fastcgi_protocol';\n" "\n" + " public const OPTION_EXIT_CONDITION = 'exit_condition';\n" + "\n" + " public const OPTION_DEADLOCK_CHECK_DISABLE_TRACE = 'deadlock_check_disable_trace';\n" + "\n" + " public const OPTION_DEADLOCK_CHECK_LIMIT = 'deadlock_check_limit';\n" + "\n" + " public const OPTION_DEADLOCK_CHECK_DEPTH = 'deadlock_check_depth';\n" + "\n" " /* }}} OPTION */\n" "}\n"; diff --git a/include/swoole_version.h b/include/swoole_version.h index 30ffe704e68..6e6ca19bd73 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -19,12 +19,12 @@ #define SWOOLE_VERSION_H_ #define SWOOLE_MAJOR_VERSION 4 -#define SWOOLE_MINOR_VERSION 7 -#define SWOOLE_RELEASE_VERSION 2 -#define SWOOLE_EXTRA_VERSION "dev" -#define SWOOLE_VERSION "4.7.2-dev" -#define SWOOLE_VERSION_ID 40702 -#define SWOOLE_API_VERSION_ID 0x202109a +#define SWOOLE_MINOR_VERSION 8 +#define SWOOLE_RELEASE_VERSION 0 +#define SWOOLE_EXTRA_VERSION "" +#define SWOOLE_VERSION "4.8.0" +#define SWOOLE_VERSION_ID 40800 +#define SWOOLE_API_VERSION_ID 0x202012a #define SWOOLE_BUG_REPORT \ "A bug occurred in Swoole-v" SWOOLE_VERSION ", please report it.\n" \ diff --git a/package.xml b/package.xml index a5138e4b7fb..69856a2c600 100644 --- a/package.xml +++ b/package.xml @@ -1,8 +1,5 @@ - + swoole pecl.php.net Event-driven asynchronous and concurrent networking engine with high performance for PHP. @@ -27,20 +24,20 @@ Tianfeng Han tianfenghan - mikan.tenny@gmail.com + rango@swoole.com yes Twosee twosee - twose@qq.com + twosee@php.net yes Shen Zhe shenzhe shenzhe163@gmail.com - yes + no Lu Fei @@ -48,10 +45,16 @@ lufei@php.net yes - 2021-08-13 - + + Bruce Dou + doubaokun + doubaokun@php.net + yes + + 2021-10-12 + - 4.7.1 + 4.8.0 4.0 @@ -60,32 +63,40 @@ Apache2.0 + New APIs + --- + * Added Co::getStackUsage() (#4398) (@matyhtf) (@twose) + * Added Coroutine\Redis some api (#4390) (@chrysanthemum) + * Added Table::stats() (#4405) (@matyhtf) + * Added Coroutine::join() (#4406) (@matyhtf) + New feature --- - * Introduce a new concurrency mode (#4330) (@doubaokun) + * Supported server command (#4389) (@matyhtf) + * Supported Server::onBeforeShutdown callback (#4415) (@matyhtf) Enhancement --- - * Supported query /etc/hosts for System::dnsLookup (#4341) (#4349) (@zmyWL) (@NathanFreeman) - * Supported boost context support for mips64 (#4358) (@dixyes) - * Supported CURLOPT_RESOLVE option for SWOOLE_HOOK_CURL (swoole/library#107) (@sy-records) - * Supported CURLOPT_NOPROGRESS for SWOOLE_HOOK_CURL (swoole/library#117) (@sy-records) - * Supported boost context support for riscv64 (#4375) (@dixyes) + * Set error code when websocket pack fails (swoole/swoole-src@d27c5a5) (@matyhtf) + * Added Timer::exec_count field (#4402) (@matyhtf) + * Supported for hooked mkdir using open_basedir ini config (#4407) (@NathanFreeman) + * Added vendor_init.php (swoole/library@6c40b02) (@matyhtf) + * Supported CURLOPT_UNIX_SOCKET_PATH for SWOOLE_HOOK_CURL (swoole/library#121) (@sy-records) + * Supported ssl_ciphers config for client (#4432) (@amuluowin) Fixed --- - * Fixed memory error on shutdown (PHP-8.1) (#4325) (@twose) - * Fixed not serializable classes for 8.1.0beta1 (#4335) (@remicollet) - * Fixed multiple coroutines recursively creating directories (#4337) (@NathanFreeman) - * Fixed native curl bugs (#4360) (@matyhtf) - * Fixed PDOStatement::bindParam() expects parameter 1 to be string (swoole/library#116) (@sy-records) + * Fixed unnecessary URL decode of file names when uploading files (swoole/swoole-src@a73780e) (@matyhtf) + * Fixed HTTP2 max_frame_size error (#4394) (@twose) + * Fixed curl_multi_select bug #4393 (#4418) (@matyhtf) + * Fixed missing coroutine options (#4425) (@sy-records) + * Fixed connection cannot be forcibly closed when the send buffer is full (swoole/swoole-src@2198378) (@matyhtf) - @@ -158,6 +169,7 @@ + @@ -222,6 +234,7 @@ + @@ -671,6 +684,7 @@ + @@ -680,6 +694,7 @@ + @@ -975,6 +990,10 @@ + + + + @@ -1091,6 +1110,7 @@ + @@ -1136,6 +1156,7 @@ + @@ -1362,6 +1383,7 @@ + @@ -1555,6 +1577,7 @@ + @@ -1591,6 +1614,7 @@ + @@ -1685,6 +1709,8 @@ + + @@ -1702,6 +1728,7 @@ + @@ -1736,6 +1763,7 @@ + @@ -1807,6 +1835,8 @@ + + @@ -1836,6 +1866,7 @@ + @@ -1929,6 +1960,8 @@ + + @@ -2001,6 +2034,7 @@ + @@ -2027,6 +2061,7 @@ + @@ -2128,11 +2163,11 @@ swoole - - - - - - + + + + + + diff --git a/tests/swoole_curl/multi/bug4393.phpt b/tests/swoole_curl/multi/bug4393.phpt index d9819941caa..4e734b7f89c 100644 --- a/tests/swoole_curl/multi/bug4393.phpt +++ b/tests/swoole_curl/multi/bug4393.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_curl: guzzle +swoole_curl/multi: guzzle --SKIPIF-- childFirst(); $pm->run(); ?> --EXPECTF-- - From 92deb01f5f69901cf54d465591cde89698691400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E5=94=81?= <52o@qq52o.cn> Date: Sat, 16 Oct 2021 10:24:34 +0800 Subject: [PATCH 268/936] Fix missing helper options (#4436) --- tools/constant-generator.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/constant-generator.php b/tools/constant-generator.php index 63dfd68d730..3d3af35633a 100755 --- a/tools/constant-generator.php +++ b/tools/constant-generator.php @@ -28,7 +28,12 @@ 'deadlock_check_limit', 'deadlock_check_depth' ]; -$options = array_merge($matches, $coroutineOptions); +$helperOptions = [ + 'stats_file', + 'stats_timer_interval', + 'admin_server', +]; +$options = array_merge($matches, $coroutineOptions, $helperOptions); $result = ''; foreach ($options as $option) { $result .= space(4) . sprintf("public const OPTION_%s = '%s';\n\n", strtoupper($option), $option); From af1359c1befd8572d50c08f1745b5f61bc785327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Mon, 18 Oct 2021 13:42:14 +0800 Subject: [PATCH 269/936] Support ignore error (#4440) * Support ignore error, Improved swoole_error_log * added swoole_error_log_ex --- core-tests/src/core/log.cpp | 22 ++++++++++++ ext-src/php_swoole.cc | 40 ++++++++++++++++++++- include/swoole.h | 2 ++ include/swoole_log.h | 2 +- src/core/error.cc | 17 +++++++-- tests/swoole_function/swoole_error_log.phpt | 31 ++++++++++++++++ 6 files changed, 109 insertions(+), 5 deletions(-) create mode 100644 tests/swoole_function/swoole_error_log.phpt diff --git a/core-tests/src/core/log.cpp b/core-tests/src/core/log.cpp index 06c93351a44..202e31a5498 100644 --- a/core-tests/src/core/log.cpp +++ b/core-tests/src/core/log.cpp @@ -171,3 +171,25 @@ TEST(log, pretty_name_lambda) { TestA::test_pretty_name_lambda(false, "TestA::test_pretty_name_lambda"); test_pretty_name_lambda(false, "test_pretty_name_lambda"); } + +TEST(log, ignore_error) { + sw_logger()->reset(); + sw_logger()->set_level(SW_LOG_NOTICE); + sw_logger()->open(file); + + const int ignored_errcode = 999999; + const int errcode = 888888; + + swoole_ignore_error(ignored_errcode); + + swoole_error_log(SW_LOG_WARNING, ignored_errcode, "error 1"); + swoole_error_log(SW_LOG_WARNING, errcode, "error 2"); + + auto content = file_get_contents(file); + + sw_logger()->close(); + unlink(file); + + ASSERT_FALSE(content->contains(SW_STRL("error 1"))); + ASSERT_TRUE(content->contains(SW_STRL("error 2"))); +} diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index 89d1a4b7879..6eda040ef91 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -70,6 +70,8 @@ static PHP_FUNCTION(swoole_strerror); static PHP_FUNCTION(swoole_clear_error); static PHP_FUNCTION(swoole_errno); static PHP_FUNCTION(swoole_error_log); +static PHP_FUNCTION(swoole_error_log_ex); +static PHP_FUNCTION(swoole_ignore_error); static PHP_FUNCTION(swoole_get_local_ip); static PHP_FUNCTION(swoole_get_local_mac); static PHP_FUNCTION(swoole_hashcode); @@ -160,6 +162,16 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_error_log, 0, 0, 2) ZEND_ARG_INFO(0, msg) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_error_log_ex, 0, 0, 3) + ZEND_ARG_INFO(0, level) + ZEND_ARG_INFO(0, error) + ZEND_ARG_INFO(0, msg) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_ignore_error, 0, 0, 1) + ZEND_ARG_INFO(0, error) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_hashcode, 0, 0, 1) ZEND_ARG_INFO(0, data) ZEND_ARG_INFO(0, type) @@ -202,6 +214,8 @@ const zend_function_entry swoole_functions[] = { PHP_FE(swoole_errno, arginfo_swoole_void) PHP_FE(swoole_clear_error, arginfo_swoole_void) PHP_FE(swoole_error_log, arginfo_swoole_error_log) + PHP_FE(swoole_error_log_ex, arginfo_swoole_error_log_ex) + PHP_FE(swoole_ignore_error, arginfo_swoole_ignore_error) PHP_FE(swoole_hashcode, arginfo_swoole_hashcode) PHP_FE(swoole_mime_type_add, arginfo_swoole_mime_type_write) PHP_FE(swoole_mime_type_set, arginfo_swoole_mime_type_write) @@ -1154,7 +1168,7 @@ static PHP_FUNCTION(swoole_strerror) { static PHP_FUNCTION(swoole_error_log) { char *msg; size_t l_msg; - zend_long level = 0; + zend_long level; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_LONG(level) @@ -1164,6 +1178,30 @@ static PHP_FUNCTION(swoole_error_log) { sw_logger()->put(level, msg, l_msg); } +static PHP_FUNCTION(swoole_error_log_ex) { + char *msg; + size_t l_msg; + zend_long level, error; + + ZEND_PARSE_PARAMETERS_START(3, 3) + Z_PARAM_LONG(level) + Z_PARAM_LONG(error) + Z_PARAM_STRING(msg, l_msg) + ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + + swoole_error_log(level, (int) error, "%.*s", (int) l_msg, msg); +} + +static PHP_FUNCTION(swoole_ignore_error) { + zend_long error; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_LONG(error) + ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + + swoole_ignore_error(error); +} + static PHP_FUNCTION(swoole_mime_type_add) { zend_string *suffix; zend_string *mime_type; diff --git a/include/swoole.h b/include/swoole.h index e1441164569..1e795af4168 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -709,6 +709,8 @@ static inline int swoole_get_process_id() { SW_API const char *swoole_strerror(int code); SW_API void swoole_throw_error(int code); +SW_API void swoole_ignore_error(int code); +SW_API bool swoole_is_ignored_error(int code); SW_API void swoole_set_log_level(int level); SW_API void swoole_set_trace_flags(int flags); SW_API void swoole_set_dns_server(const std::string &server); diff --git a/include/swoole_log.h b/include/swoole_log.h index 62317967cbf..235594c6af5 100644 --- a/include/swoole_log.h +++ b/include/swoole_log.h @@ -167,7 +167,7 @@ swoole::Logger *sw_logger(); #define swoole_error_log(level, error, str, ...) \ do { \ swoole_set_last_error(error); \ - if (level >= sw_logger()->get_level()) { \ + if (level >= sw_logger()->get_level() && !swoole_is_ignored_error(error)) { \ size_t _sw_error_len = \ sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s() (ERRNO %d): " str, __SW_FUNC__, error, ##__VA_ARGS__); \ sw_logger()->put(level, sw_error, _sw_error_len); \ diff --git a/src/core/error.cc b/src/core/error.cc index 68419450ce2..288600a6948 100644 --- a/src/core/error.cc +++ b/src/core/error.cc @@ -16,6 +16,10 @@ #include "swoole.h" +#include + +static std::unordered_set ignored_errors; + namespace swoole { Exception::Exception(int code) throw() : code(code) { msg = swoole_strerror(code); @@ -27,8 +31,7 @@ const char *swoole_strerror(int code) { return strerror(code); } /* swstrerror {{{*/ - switch(code) - { + switch (code) { case SW_ERROR_MALLOC_FAIL: return "Malloc fail"; case SW_ERROR_SYSTEM_CALL_FAIL: @@ -240,9 +243,17 @@ const char *swoole_strerror(int code) { #endif return buffer; } -/*}}}*/ + /*}}}*/ } void swoole_throw_error(int code) { throw swoole::Exception(code); } + +void swoole_ignore_error(int code) { + ignored_errors.insert(code); +} + +bool swoole_is_ignored_error(int code) { + return ignored_errors.find(code) != ignored_errors.end(); +} diff --git a/tests/swoole_function/swoole_error_log.phpt b/tests/swoole_function/swoole_error_log.phpt new file mode 100644 index 00000000000..c47ce1b0921 --- /dev/null +++ b/tests/swoole_function/swoole_error_log.phpt @@ -0,0 +1,31 @@ +--TEST-- +swoole_function: swoole_error_log +--SKIPIF-- + +--FILE-- + LOG_FILE]); +swoole_error_log(SWOOLE_LOG_NOTICE, "hello 1"); +swoole_error_log_ex(SWOOLE_LOG_NOTICE, ERROR_1, "hello 2"); + +swoole_ignore_error(ERROR_2); +swoole_error_log_ex(SWOOLE_LOG_NOTICE, ERROR_2, "hello 3"); + +$content = file_get_contents(LOG_FILE); +Assert::contains($content, 'hello 1'); +Assert::contains($content, 'hello 2'); +Assert::contains($content, '(ERRNO ' . ERROR_1 . ')'); +Assert::notContains($content, 'hello 3'); +unlink(LOG_FILE); +?> +--EXPECT-- From 0395148585cceba25b754fafd40e57096492c110 Mon Sep 17 00:00:00 2001 From: matyhtf Date: Mon, 18 Oct 2021 17:26:02 +0800 Subject: [PATCH 270/936] Fix warning that the constant is already defined --- tools/bootstrap.php | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tools/bootstrap.php b/tools/bootstrap.php index 7e8710461fa..639d7ba50ba 100755 --- a/tools/bootstrap.php +++ b/tools/bootstrap.php @@ -11,10 +11,19 @@ define('LIBRARY_DIR', ROOT_DIR . '/library'); define('LIBRARY_SRC_DIR', LIBRARY_DIR . '/src'); -define('EMOJI_OK', '✅'); -define('EMOJI_SUCCESS', '🚀'); -define('EMOJI_ERROR', '❌'); -define('EMOJI_WARN', '⚠️'); +if (!defined('EMOJI_OK')) { + define('EMOJI_OK', '✅'); +} +if (!defined('EMOJI_SUCCESS')) { + define('EMOJI_SUCCESS', '🚀'); +} +if (!defined('EMOJI_ERROR')) { + define('EMOJI_ERROR', '❌'); +} +if (!defined('EMOJI_WARN')) { + define('EMOJI_WARN', '⚠️'); +} + define('SWOOLE_SOURCE_ROOT', dirname(__DIR__) . '/'); if (!defined('SWOOLE_COLOR_RED')) { From a89e3abd3ecd64e881c6ae9bb3930adadafd7911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9F=A9=E5=A4=A9=E5=B3=B0-Rango?= Date: Tue, 19 Oct 2021 10:30:52 +0800 Subject: [PATCH 271/936] Migrate admin api from ext-swoole_plus to swoole-src (#4441) * Migration admin api from ext-swoole_plus to swoole-src * Optimize code --- CMakeLists.txt | 2 +- config.m4 | 2 + ext-src/php_swoole.cc | 6 + ext-src/php_swoole.stub.php | 16 + ext-src/php_swoole_arginfo.h | 24 + ext-src/php_swoole_cxx.h | 33 +- ext-src/php_swoole_legacy_arginfo.h | 24 + ext-src/php_swoole_server.h | 24 +- ext-src/php_swoole_x_arginfo.h | 7 + ext-src/swoole_admin_server.cc | 481 + ext-src/swoole_server.cc | 4 + thirdparty/nlohmann/adl_serializer.hpp | 49 + .../nlohmann/detail/conversions/from_json.hpp | 389 + .../nlohmann/detail/conversions/to_chars.hpp | 1106 +++ .../nlohmann/detail/conversions/to_json.hpp | 347 + thirdparty/nlohmann/detail/exceptions.hpp | 356 + .../nlohmann/detail/input/binary_reader.hpp | 1983 ++++ .../nlohmann/detail/input/input_adapters.hpp | 442 + thirdparty/nlohmann/detail/input/json_sax.hpp | 701 ++ thirdparty/nlohmann/detail/input/lexer.hpp | 1512 +++ thirdparty/nlohmann/detail/input/parser.hpp | 498 + .../nlohmann/detail/input/position_t.hpp | 27 + .../detail/iterators/internal_iterator.hpp | 25 + .../nlohmann/detail/iterators/iter_impl.hpp | 638 ++ .../detail/iterators/iteration_proxy.hpp | 176 + .../detail/iterators/iterator_traits.hpp | 51 + .../iterators/json_reverse_iterator.hpp | 119 + .../detail/iterators/primitive_iterator.hpp | 120 + thirdparty/nlohmann/detail/json_pointer.hpp | 1011 ++ thirdparty/nlohmann/detail/json_ref.hpp | 69 + thirdparty/nlohmann/detail/macro_scope.hpp | 121 + thirdparty/nlohmann/detail/macro_unscope.hpp | 21 + .../nlohmann/detail/meta/cpp_future.hpp | 63 + thirdparty/nlohmann/detail/meta/detected.hpp | 58 + thirdparty/nlohmann/detail/meta/is_sax.hpp | 142 + .../nlohmann/detail/meta/type_traits.hpp | 374 + thirdparty/nlohmann/detail/meta/void_t.hpp | 13 + .../nlohmann/detail/output/binary_writer.hpp | 1335 +++ .../detail/output/output_adapters.hpp | 123 + .../nlohmann/detail/output/serializer.hpp | 866 ++ thirdparty/nlohmann/detail/value_t.hpp | 77 + thirdparty/nlohmann/json.hpp | 8181 +++++++++++++++++ thirdparty/nlohmann/json_fwd.hpp | 64 + .../nlohmann/thirdparty/hedley/hedley.hpp | 1595 ++++ .../thirdparty/hedley/hedley_undef.hpp | 128 + 45 files changed, 23377 insertions(+), 26 deletions(-) create mode 100644 ext-src/php_swoole.stub.php create mode 100644 ext-src/php_swoole_arginfo.h create mode 100644 ext-src/php_swoole_legacy_arginfo.h create mode 100644 ext-src/php_swoole_x_arginfo.h create mode 100644 ext-src/swoole_admin_server.cc create mode 100644 thirdparty/nlohmann/adl_serializer.hpp create mode 100644 thirdparty/nlohmann/detail/conversions/from_json.hpp create mode 100644 thirdparty/nlohmann/detail/conversions/to_chars.hpp create mode 100644 thirdparty/nlohmann/detail/conversions/to_json.hpp create mode 100644 thirdparty/nlohmann/detail/exceptions.hpp create mode 100644 thirdparty/nlohmann/detail/input/binary_reader.hpp create mode 100644 thirdparty/nlohmann/detail/input/input_adapters.hpp create mode 100644 thirdparty/nlohmann/detail/input/json_sax.hpp create mode 100644 thirdparty/nlohmann/detail/input/lexer.hpp create mode 100644 thirdparty/nlohmann/detail/input/parser.hpp create mode 100644 thirdparty/nlohmann/detail/input/position_t.hpp create mode 100644 thirdparty/nlohmann/detail/iterators/internal_iterator.hpp create mode 100644 thirdparty/nlohmann/detail/iterators/iter_impl.hpp create mode 100644 thirdparty/nlohmann/detail/iterators/iteration_proxy.hpp create mode 100644 thirdparty/nlohmann/detail/iterators/iterator_traits.hpp create mode 100644 thirdparty/nlohmann/detail/iterators/json_reverse_iterator.hpp create mode 100644 thirdparty/nlohmann/detail/iterators/primitive_iterator.hpp create mode 100644 thirdparty/nlohmann/detail/json_pointer.hpp create mode 100644 thirdparty/nlohmann/detail/json_ref.hpp create mode 100644 thirdparty/nlohmann/detail/macro_scope.hpp create mode 100644 thirdparty/nlohmann/detail/macro_unscope.hpp create mode 100644 thirdparty/nlohmann/detail/meta/cpp_future.hpp create mode 100644 thirdparty/nlohmann/detail/meta/detected.hpp create mode 100644 thirdparty/nlohmann/detail/meta/is_sax.hpp create mode 100644 thirdparty/nlohmann/detail/meta/type_traits.hpp create mode 100644 thirdparty/nlohmann/detail/meta/void_t.hpp create mode 100644 thirdparty/nlohmann/detail/output/binary_writer.hpp create mode 100644 thirdparty/nlohmann/detail/output/output_adapters.hpp create mode 100644 thirdparty/nlohmann/detail/output/serializer.hpp create mode 100644 thirdparty/nlohmann/detail/value_t.hpp create mode 100644 thirdparty/nlohmann/json.hpp create mode 100644 thirdparty/nlohmann/json_fwd.hpp create mode 100644 thirdparty/nlohmann/thirdparty/hedley/hedley.hpp create mode 100644 thirdparty/nlohmann/thirdparty/hedley/hedley_undef.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 014d06a0961..44217ce992e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,7 +64,7 @@ add_definitions(-DHAVE_CONFIG_H) # test #add_definitions(-DSW_USE_THREAD_CONTEXT) -include_directories(BEFORE ./include ./include/wrapper ext-src/ ./) +include_directories(BEFORE ./include ./include/wrapper ext-src/ thirdparty/ ./) SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) # find OpenSSL diff --git a/config.m4 b/config.m4 index d5e465933c1..0f6db13adb2 100644 --- a/config.m4 +++ b/config.m4 @@ -563,6 +563,7 @@ if test "$PHP_SWOOLE" != "no"; then ext-src/swoole_table.cc \ ext-src/swoole_timer.cc \ ext-src/swoole_websocket_server.cc \ + ext-src/swoole_admin_server.cc \ src/core/base.cc \ src/core/channel.cc \ src/core/crc32.cc \ @@ -760,6 +761,7 @@ if test "$PHP_SWOOLE" != "no"; then PHP_ADD_INCLUDE([$ext_srcdir]) PHP_ADD_INCLUDE([$ext_srcdir/include]) PHP_ADD_INCLUDE([$ext_srcdir/ext-src]) + PHP_ADD_INCLUDE([$ext_srcdir/thirdparty]) PHP_ADD_INCLUDE([$ext_srcdir/thirdparty/hiredis]) AC_MSG_CHECKING([swoole coverage]) diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index 6eda040ef91..55fc5c8c48a 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -192,6 +192,8 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_mime_type_read, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() +#include "php_swoole_x_arginfo.h" + const zend_function_entry swoole_functions[] = { PHP_FE(swoole_version, arginfo_swoole_void) PHP_FE(swoole_cpu_num, arginfo_swoole_void) @@ -230,6 +232,10 @@ const zend_function_entry swoole_functions[] = { PHP_FE(swoole_substr_json_decode, arginfo_swoole_substr_json_decode) #endif PHP_FE(swoole_internal_call_user_shutdown_begin, arginfo_swoole_void) + // for admin server + ZEND_FE(swoole_get_objects, arginfo_swoole_get_objects) + ZEND_FE(swoole_get_vm_status, arginfo_swoole_get_vm_status) + ZEND_FE(swoole_get_object_by_handle, arginfo_swoole_get_object_by_handle) PHP_FE_END /* Must be the last line in swoole_functions[] */ }; diff --git a/ext-src/php_swoole.stub.php b/ext-src/php_swoole.stub.php new file mode 100644 index 00000000000..38fbcf4b978 --- /dev/null +++ b/ext-src/php_swoole.stub.php @@ -0,0 +1,16 @@ +create_object = [](zend_class_entry *ce) { return sw_zend_create_object(ce, &module##_handlers); } - SW_API bool php_swoole_is_enable_coroutine(); SW_API zend_object *php_swoole_create_socket_from_fd(int fd, enum swSocketType type); SW_API bool php_swoole_export_socket(zval *zobject, swoole::coroutine::Socket *_socket); @@ -91,7 +90,10 @@ SW_API bool php_swoole_socket_set_ssl(swoole::coroutine::Socket *sock, zval *zse #endif SW_API bool php_swoole_socket_set_protocol(swoole::coroutine::Socket *sock, zval *zset); SW_API bool php_swoole_client_set(swoole::coroutine::Socket *cli, zval *zset); -SW_API php_stream *php_swoole_create_stream_from_socket(php_socket_t _fd, int domain, int type, int protocol STREAMS_DC); +SW_API php_stream *php_swoole_create_stream_from_socket(php_socket_t _fd, + int domain, + int type, + int protocol STREAMS_DC); SW_API php_stream_ops *php_swoole_get_ori_php_stream_stdio_ops(); SW_API void php_swoole_register_rshutdown_callback(swoole::Callback cb, void *private_data); @@ -114,24 +116,31 @@ static inline bool php_swoole_is_fatal_error() { return false; } -ssize_t php_swoole_length_func(swoole::Protocol *protocol, swoole::network::Socket *_socket, const char *data, uint32_t length); +ssize_t php_swoole_length_func(swoole::Protocol *protocol, + swoole::network::Socket *_socket, + const char *data, + uint32_t length); #ifdef SW_HAVE_ZLIB -#define php_swoole_websocket_frame_pack php_swoole_websocket_frame_pack_ex +#define php_swoole_websocket_frame_pack php_swoole_websocket_frame_pack_ex #define php_swoole_websocket_frame_object_pack php_swoole_websocket_frame_object_pack_ex #else -#define php_swoole_websocket_frame_pack(buffer, zdata, opcode, flags, mask, allow_compress) \ - php_swoole_websocket_frame_pack_ex(buffer, zdata, opcode, flags, mask, 0) -#define php_swoole_websocket_frame_object_pack(buffer, zdata, mask, allow_compress) \ - php_swoole_websocket_frame_object_pack_ex(buffer, zdata, mask, 0) +#define php_swoole_websocket_frame_pack(buffer, zdata, opcode, flags, mask, allow_compress) \ + php_swoole_websocket_frame_pack_ex(buffer, zdata, opcode, flags, mask, 0) +#define php_swoole_websocket_frame_object_pack(buffer, zdata, mask, allow_compress) \ + php_swoole_websocket_frame_object_pack_ex(buffer, zdata, mask, 0) #endif -int php_swoole_websocket_frame_pack_ex(swoole::String *buffer, zval *zdata, zend_long opcode, uint8_t flags, zend_bool mask, zend_bool allow_compress); -int php_swoole_websocket_frame_object_pack_ex(swoole::String *buffer, zval *zdata, zend_bool mask, zend_bool allow_compress); +int php_swoole_websocket_frame_pack_ex( + swoole::String *buffer, zval *zdata, zend_long opcode, uint8_t flags, zend_bool mask, zend_bool allow_compress); +int php_swoole_websocket_frame_object_pack_ex(swoole::String *buffer, + zval *zdata, + zend_bool mask, + zend_bool allow_compress); void php_swoole_websocket_frame_unpack(swoole::String *data, zval *zframe); void php_swoole_websocket_frame_unpack_ex(swoole::String *data, zval *zframe, uchar allow_uncompress); swoole::TaskId php_swoole_task_pack(swoole::EventData *task, zval *data); -zval* php_swoole_task_unpack(swoole::EventData *task_result); +zval *php_swoole_task_unpack(swoole::EventData *task_result); #ifdef SW_HAVE_ZLIB int php_swoole_zlib_decompress(z_stream *stream, swoole::String *buffer, char *body, int length); @@ -444,5 +453,3 @@ static inline void assign_zend_string_by_val(zval *zdata, char *addr, size_t len //-----------------------------------namespace end-------------------------------------------- } // namespace zend - - diff --git a/ext-src/php_swoole_legacy_arginfo.h b/ext-src/php_swoole_legacy_arginfo.h new file mode 100644 index 00000000000..9a00b171de4 --- /dev/null +++ b/ext-src/php_swoole_legacy_arginfo.h @@ -0,0 +1,24 @@ +/* This is a generated file, edit the .stub.php file instead. + * Stub hash: 7d05091fc87828ebabc77c6c797984366e7afd4a */ + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_get_objects, 0, 0, 0) +ZEND_END_ARG_INFO() + +#define arginfo_swoole_get_vm_status arginfo_swoole_get_objects + +ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_get_object_by_handle, 0, 0, 1) + ZEND_ARG_INFO(0, handle) +ZEND_END_ARG_INFO() + + +ZEND_FUNCTION(swoole_get_objects); +ZEND_FUNCTION(swoole_get_vm_status); +ZEND_FUNCTION(swoole_get_object_by_handle); + + +static const zend_function_entry ext_functions[] = { + ZEND_FE(swoole_get_objects, arginfo_swoole_get_objects) + ZEND_FE(swoole_get_vm_status, arginfo_swoole_get_vm_status) + ZEND_FE(swoole_get_object_by_handle, arginfo_swoole_get_object_by_handle) + ZEND_FE_END +}; diff --git a/ext-src/php_swoole_server.h b/ext-src/php_swoole_server.h index 97a8e7cce0c..7b485a3ba0c 100644 --- a/ext-src/php_swoole_server.h +++ b/ext-src/php_swoole_server.h @@ -44,17 +44,17 @@ enum php_swoole_server_callback_type { }; //-------------------------------------------------------- enum php_swoole_server_port_callback_type { - SW_SERVER_CB_onConnect, // stream, worker(event) - SW_SERVER_CB_onReceive, // stream, worker(event) - SW_SERVER_CB_onClose, // stream, worker(event) - SW_SERVER_CB_onPacket, // dgram, worker(event) - SW_SERVER_CB_onRequest, // http, worker(event) - SW_SERVER_CB_onHandShake, // websocket, worker(event) - SW_SERVER_CB_onOpen, // websocket, worker(event) - SW_SERVER_CB_onMessage, // websocket, worker(event) - SW_SERVER_CB_onDisconnect, // websocket (non websocket connection), worker(event) - SW_SERVER_CB_onBufferFull, // worker(event) - SW_SERVER_CB_onBufferEmpty, // worker(event) + SW_SERVER_CB_onConnect, // stream, worker(event) + SW_SERVER_CB_onReceive, // stream, worker(event) + SW_SERVER_CB_onClose, // stream, worker(event) + SW_SERVER_CB_onPacket, // dgram, worker(event) + SW_SERVER_CB_onRequest, // http, worker(event) + SW_SERVER_CB_onHandShake, // websocket, worker(event) + SW_SERVER_CB_onOpen, // websocket, worker(event) + SW_SERVER_CB_onMessage, // websocket, worker(event) + SW_SERVER_CB_onDisconnect, // websocket (non websocket connection), worker(event) + SW_SERVER_CB_onBufferFull, // worker(event) + SW_SERVER_CB_onBufferEmpty, // worker(event) }; #define PHP_SWOOLE_SERVER_CALLBACK_NUM (SW_SERVER_CB_onPipeMessage + 1) @@ -123,7 +123,7 @@ struct TaskCo { uint32_t count; zval *result; }; - +void register_admin_server_commands(Server *serv); } // namespace swoole void php_swoole_server_register_callbacks(swServer *serv); diff --git a/ext-src/php_swoole_x_arginfo.h b/ext-src/php_swoole_x_arginfo.h new file mode 100644 index 00000000000..ec395780c1f --- /dev/null +++ b/ext-src/php_swoole_x_arginfo.h @@ -0,0 +1,7 @@ +BEGIN_EXTERN_C() +#if PHP_VERSION_ID < 80000 +#include "php_swoole_legacy_arginfo.h" +#else +#include "php_swoole_arginfo.h" +#endif +END_EXTERN_C() diff --git a/ext-src/swoole_admin_server.cc b/ext-src/swoole_admin_server.cc new file mode 100644 index 00000000000..673c41c731d --- /dev/null +++ b/ext-src/swoole_admin_server.cc @@ -0,0 +1,481 @@ +/* + +----------------------------------------------------------------------+ + | 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 | + +----------------------------------------------------------------------+ + */ + +#include "php_swoole_server.h" +#include "swoole_process_pool.h" +#include "php_swoole_http.h" +#include "php_swoole_x_arginfo.h" + +#include "nlohmann/json.hpp" + +namespace swoole { + +using json = nlohmann::json; + +#ifdef TCP_INFO +static json get_socket_info(int fd); +#endif + +static std::string handle_get_all_unix_sockets(Server *_server, const std::string &msg) { + auto _result = json::parse(msg); + if (!_result.is_object() || _result.find("type") == _result.end()) { + json return_value{ + {"data", "require parameter type"}, + {"code", 4003}, + }; + return return_value.dump(); + } + + std::string _type = _result["type"]; + Worker *workers; + uint32_t worker_num; + + if (_type == "event") { + workers = _server->gs->event_workers.workers; + worker_num = _server->worker_num; + } else { + workers = _server->gs->task_workers.workers; + worker_num = _server->task_worker_num; + } + + json sockets = json::array(); + + SW_LOOP_N(worker_num) { + auto master_socket = workers[i].pipe_object->get_socket(true); + json master_socket_info = json::object({ + {"fd", master_socket->fd}, + {"events", master_socket->events}, + {"total_recv_bytes", master_socket->total_recv_bytes}, + {"total_send_bytes", master_socket->total_send_bytes}, + {"out_buffer_size", master_socket->out_buffer ? master_socket->out_buffer->length() : 0}, + }); + sockets.push_back(master_socket_info); + + auto worker_socket = workers[i].pipe_object->get_socket(false); + json worker_socket_info = json::object({ + {"fd", worker_socket->fd}, + {"events", worker_socket->events}, + {"total_recv_bytes", worker_socket->total_recv_bytes}, + {"total_send_bytes", worker_socket->total_send_bytes}, + {"out_buffer_size", worker_socket->out_buffer ? worker_socket->out_buffer->length() : 0}, + }); + sockets.push_back(worker_socket_info); + } + + json return_value{ + {"data", sockets}, + {"code", 0}, + }; + return return_value.dump(); +} + +static std::string handle_get_all_sockets(Server *, const std::string &msg) { + if (sw_reactor() == nullptr) { + json return_value{ + {"data", "No event loop created"}, + {"code", 4004}, + }; + return return_value.dump(); + } + + json sockets = json::array(); + sw_reactor()->foreach_socket([&sockets](int fd, network::Socket *socket) { + network::Address addr{}; + if (socket->socket_type > SW_SOCK_UNIX_DGRAM || socket->socket_type < SW_SOCK_TCP) { +#ifdef SO_DOMAIN + struct stat fdstat; + if (fstat(fd, &fdstat) == -1) { + return; + } + mode_t type = fdstat.st_mode & S_IFMT; + if (type == S_IFSOCK) { + int domain; + if (socket->get_option(SOL_SOCKET, SO_DOMAIN, &domain) < 0) { + return; + } + int type; + if (socket->get_option(SOL_SOCKET, SO_TYPE, &type) < 0) { + return; + } + addr.type = network::Socket::convert_to_type(domain, type); + socket->get_name(&addr); + } +#else + return; +#endif + } else { + addr = socket->info; + } + json info = json::object({ + {"fd", socket->fd}, + {"address", addr.get_ip()}, + {"port", addr.get_port()}, + {"events", socket->events}, + {"socket_type", socket->socket_type}, + {"fd_type", socket->fd_type}, + {"total_recv_bytes", socket->total_recv_bytes}, + {"total_send_bytes", socket->total_send_bytes}, + {"out_buffer_size", socket->out_buffer ? socket->out_buffer->length() : 0}, + }); + sockets.push_back(info); + }); + + json return_value{ + {"data", sockets}, + {"code", 0}, + }; + return return_value.dump(); +} + +static std::string handle_get_all_commands(Server *serv, const std::string &msg) { + json command_list = json::array(); + for (auto kv : serv->commands) { + json info = json::object({ + {"id", kv.second.id}, + {"name", kv.second.name}, + {"accepted_process_types", kv.second.accepted_process_types}, + }); + command_list.push_back(info); + }; + json return_value{ + {"data", command_list}, + {"code", 0}, + }; + return return_value.dump(); +} + +#ifdef TCP_INFO +static json get_socket_info(int fd) { + struct tcp_info info; + socklen_t len = sizeof(info); + if (getsockopt(fd, IPPROTO_TCP, TCP_INFO, &info, &len) < 0) { + json return_value{ + {"data", "failed to getsockopt(TCP_INFO) for socket"}, + {"code", 5001}, + }; + return return_value.dump(); + } + json jinfo{ + {"state", info.tcpi_state}, + {"ca_state", info.tcpi_ca_state}, + {"retransmits", info.tcpi_retransmits}, + {"probes", info.tcpi_probes}, + {"backoff", info.tcpi_backoff}, + {"options", info.tcpi_options}, + {"snd_wscale", uint8_t(info.tcpi_snd_wscale)}, + {"rcv_wscale", uint8_t(info.tcpi_rcv_wscale)}, + {"rto", info.tcpi_rto}, + {"ato", info.tcpi_ato}, + {"snd_mss", info.tcpi_snd_mss}, + {"rcv_mss", info.tcpi_rcv_mss}, + {"unacked", info.tcpi_unacked}, + {"sacked", info.tcpi_sacked}, + {"lost", info.tcpi_lost}, + {"retrans", info.tcpi_retrans}, + {"fackets", info.tcpi_fackets}, + {"last_data_sent", info.tcpi_last_data_sent}, + {"last_ack_sent", info.tcpi_last_ack_sent}, + {"last_data_recv", info.tcpi_last_data_recv}, + {"last_ack_recv", info.tcpi_last_ack_recv}, + {"pmtu", info.tcpi_pmtu}, + {"rcv_ssthresh", info.tcpi_rcv_ssthresh}, + {"rtt", info.tcpi_rtt}, + {"rttvar", info.tcpi_rttvar}, + {"snd_ssthresh", info.tcpi_snd_ssthresh}, + {"snd_cwnd", info.tcpi_snd_cwnd}, + {"advmss", info.tcpi_advmss}, + {"reordering", info.tcpi_reordering}, + {"rcv_rtt", info.tcpi_rcv_rtt}, + {"rcv_space", info.tcpi_rcv_space}, + {"total_retrans", info.tcpi_total_retrans}, + }; + return jinfo; +} +#endif + +static json get_connection_info(Server *serv, Connection *conn) { + auto server_socket = serv->get_port_by_server_fd(conn->server_fd)->socket; + json info = json::object({ + {"session_id", conn->session_id}, + {"reactor_id", conn->reactor_id}, + {"fd", conn->fd}, + {"server_port", + std::string(server_socket->info.get_ip()) + ":" + std::to_string(server_socket->info.get_port())}, + {"address", conn->info.get_ip()}, + {"port", conn->info.get_port()}, + {"overflow", conn->overflow}, + {"connect_time", conn->connect_time}, + {"last_recv_time", conn->last_recv_time}, + {"last_send_time", conn->last_send_time}, + {"last_dispatch_time", conn->last_dispatch_time}, + {"recv_queued_bytes", conn->recv_queued_bytes}, + {"send_queued_bytes", conn->send_queued_bytes}, + {"total_recv_bytes", conn->socket->total_recv_bytes}, + {"total_send_bytes", conn->socket->total_send_bytes}, + {"uid", conn->uid}, + }); + return info; +} + +static std::string handle_get_socket_info(Server *serv, const std::string &msg) { + auto _result = json::parse(msg); + if (!_result.is_object() || _result.find("fd") == _result.end()) { + json return_value{ + {"data", "require parameter fd"}, + {"code", 4003}, + }; + return return_value.dump(); + } + +#ifndef TCP_INFO + json return_value{ + {"data", "platform unsupported"}, + {"code", 5001}, + }; +#else + std::string _fd = _result["fd"]; + int fd = std::atoi(_fd.c_str()); + json return_value{ + {"data", get_socket_info(fd)}, + {"code", 0}, + }; + return return_value.dump(); +#endif +} + +static std::string handle_get_thread_info(Server *serv, const std::string &msg) { + ReactorThread *thread = serv->get_thread(SwooleTG.id); + json jinfo{ + {"tid", pthread_self()}, + {"id", thread->id}, + {"dispatch_count", thread->dispatch_count}, + {"event_num", SwooleTG.reactor->get_event_num()}, + {"timer_num", SwooleTG.timer ? SwooleTG.timer->count() : 0}, + }; + json return_value{ + {"data", jinfo}, + {"code", 0}, + }; + return return_value.dump(); +} + +static std::string handle_get_manager_info(Server *serv, const std::string &msg) { + ProcessPool *pool = (ProcessPool *) &serv->gs->event_workers; + json jinfo{ + {"pid", getpid()}, + {"reload_count", pool->reload_count}, + {"reload_last_time", pool->reload_last_time}, + }; + json return_value{ + {"data", jinfo}, + {"code", 0}, + }; + return return_value.dump(); +} + +static size_t get_socket_out_buffer_total_size() { + if (!sw_reactor()) { + return 0; + } + size_t size = 0; + for (auto s : sw_reactor()->get_sockets()) { + if (s.second->out_buffer) { + size += s.second->out_buffer->length(); + } + } + return size; +} + +static std::string handle_get_memory_info(Server *serv, const std::string &msg) { + bool is_thread = serv->is_reactor_thread(); + + json jinfo{ + {"server", sizeof(Server)}, + {"workers", serv->get_all_worker_num() * sizeof(Worker)}, + {"connection_list", serv->get_max_connection() * sizeof(Connection)}, + {"session_list", SW_SESSION_LIST_SIZE * sizeof(Session)}, + {"global_memory", dynamic_cast(sw_mem_pool())->get_memory_size()}, + {"thread_global_memory", sw_tg_buffer()->size}, + {"message_bus", + is_thread ? serv->get_thread(SwooleTG.id)->message_bus.get_memory_size() + : serv->message_bus.get_memory_size()}, + {"socket_list", sw_reactor() ? sw_reactor()->get_sockets().size() * sizeof(network::Socket) : 0}, + {"socket_out_buffer", get_socket_out_buffer_total_size()}, + {"php_memory", is_thread ? 0 : zend_memory_usage(true)}, + {"http_buffer", swoole_http_buffer ? swoole_http_buffer->size : 0}, + {"http_form_data_buffer", swoole_http_form_data_buffer ? swoole_http_form_data_buffer->size : 0}, +#ifdef SW_HAVE_COMPRESSION + {"zlib_buffer", swoole_zlib_buffer ? swoole_zlib_buffer->size : 0}, +#else + {"zlib_buffer", 0}, +#endif + }; + json return_value{ + {"data", jinfo}, + {"code", 0}, + }; + return return_value.dump(); +} + +static std::string handle_get_connections(Server *serv, const std::string &msg) { + json list = json::array(); + serv->foreach_connection([serv, &list](Connection *conn) { + if (serv->is_process_mode() && conn->reactor_id != SwooleTG.id) { + return; + } + if (serv->is_base_mode() && SwooleWG.worker && conn->reactor_id != SwooleWG.worker->id) { + return; + } + list.push_back(get_connection_info(serv, conn)); + }); + json return_value{ + {"data", list}, + {"code", 0}, + }; + return return_value.dump(); +} + +static std::string handle_get_connection_info(Server *serv, const std::string &msg) { + auto _result = json::parse(msg); + if (!_result.is_object() || _result.find("session_id") == _result.end()) { + json return_value{ + {"data", "require parameter session_id"}, + {"code", 4003}, + }; + return return_value.dump(); + } + + std::string _session_id = _result["session_id"]; + int session_id = std::atoi(_session_id.c_str()); + Connection *conn = serv->get_connection_verify(session_id); + if (!conn) { + json return_value{ + {"data", "connection not exists"}, + {"code", 4004}, + }; + return return_value.dump(); + } + + json return_value{ + {"data", get_connection_info(serv, conn)}, + {"code", 0}, + }; + return return_value.dump(); +} + +static std::string handle_get_all_ports(Server *serv, const std::string &msg) { + json _list = json::array(); + for (auto port : serv->ports) { + json info = json::object({ + {"host", port->host}, + {"port", port->port}, + {"backlog", port->backlog}, + {"type", port->type}, + {"ssl", port->ssl}, + {"protocols", port->get_protocols()}, + {"connection_num", (long) port->gs->connection_num}, + }); + _list.push_back(info); + }; + json return_value{ + {"data", _list}, + {"code", 0}, + }; + return return_value.dump(); +} + +void register_admin_server_commands(Server *serv) { + serv->add_command("get_all_sockets", Server::Command::ALL_PROCESS, handle_get_all_sockets); + serv->add_command("get_all_commands", Server::Command::ALL_PROCESS, handle_get_all_commands); + serv->add_command("get_socket_info", Server::Command::ALL_PROCESS, handle_get_socket_info); + serv->add_command("get_thread_info", Server::Command::ALL_PROCESS, handle_get_thread_info); + serv->add_command("get_manager_info", Server::Command::MANAGER, handle_get_manager_info); + serv->add_command("get_thread_info", Server::Command::ALL_PROCESS, handle_get_thread_info); + serv->add_command("get_memory_info", Server::Command::ALL_PROCESS, handle_get_memory_info); + serv->add_command("get_all_unix_sockets", Server::Command::ALL_PROCESS, handle_get_all_unix_sockets); + serv->add_command("get_all_ports", Server::Command::MASTER, handle_get_all_ports); + + int accepted_process_types; + if (serv->is_base_mode() || serv->single_thread) { + accepted_process_types = Server::Command::EVENT_WORKER | Server::Command::MASTER; + } else { + accepted_process_types = Server::Command::REACTOR_THREAD; + } + serv->add_command("get_connections", accepted_process_types, handle_get_connections); + serv->add_command("get_connection_info", accepted_process_types, handle_get_connection_info); +} +} // namespace swoole + +typedef std::function objects_store_iterator; + +static inline bool object_valid(zend_object *obj) { + return obj && IS_OBJ_VALID(obj) && obj->handlers && obj->handlers->get_class_name; +} + +static void objects_store_foreach(const objects_store_iterator &fn) { + for (uint32_t i = 0; i < EG(objects_store).top; i++) { + zend_object *obj = EG(objects_store).object_buckets[i]; + if (object_valid(obj)) { + fn(obj); + } + } +} + +static uint32_t object_store_count() { + uint32_t count = 0; + objects_store_foreach([&count](zend_object *obj) { count++; }); + return count; +} + +ZEND_FUNCTION(swoole_get_vm_status) { + array_init(return_value); + add_assoc_long_ex(return_value, ZEND_STRL("object_num"), object_store_count()); + add_assoc_long_ex(return_value, ZEND_STRL("resource_num"), zend_array_count(&EG(regular_list))); +} + +ZEND_FUNCTION(swoole_get_objects) { + zend_objects_store *objects = &EG(objects_store); + if (objects->top <= 1) { + RETURN_FALSE; + } + + array_init(return_value); + objects_store_foreach([return_value](zend_object *obj) { + zval zobject; + ZVAL_OBJ(&zobject, obj); + zval_addref_p(&zobject); + add_next_index_zval(return_value, &zobject); + }); +} + +ZEND_FUNCTION(swoole_get_object_by_handle) { + long handle; + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_LONG(handle) + ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + + zend_objects_store *objects = &EG(objects_store); + if (objects->top <= 1 || handle >= objects->top) { + RETURN_FALSE; + } + + zend_object *obj = objects->object_buckets[handle]; + if (!object_valid(obj)) { + RETURN_FALSE; + } + GC_ADDREF(obj); + RETURN_OBJ(obj); +} diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 0d7c0fec2ba..5a4fa48c1eb 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -1029,6 +1029,10 @@ void ServerObject::on_before_start() { if (!zend_hash_str_exists(Z_ARRVAL_P(zsetting), ZEND_STRL("max_connection"))) { add_assoc_long(zsetting, "max_connection", serv->get_max_connection()); } + // for admin_server + if (zend_hash_str_exists(Z_ARRVAL_P(zsetting), ZEND_STRL("admin_server"))) { + swoole::register_admin_server_commands(serv); + } bool find_http_port = false; if (is_redis_server()) { diff --git a/thirdparty/nlohmann/adl_serializer.hpp b/thirdparty/nlohmann/adl_serializer.hpp new file mode 100644 index 00000000000..eeaa1425740 --- /dev/null +++ b/thirdparty/nlohmann/adl_serializer.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include + +#include +#include + +namespace nlohmann +{ + +template +struct adl_serializer +{ + /*! + @brief convert a JSON value to any value type + + This function is usually called by the `get()` function of the + @ref basic_json class (either explicit or via conversion operators). + + @param[in] j JSON value to read from + @param[in,out] val value to write to + */ + template + static auto from_json(BasicJsonType&& j, ValueType& val) noexcept( + noexcept(::nlohmann::from_json(std::forward(j), val))) + -> decltype(::nlohmann::from_json(std::forward(j), val), void()) + { + ::nlohmann::from_json(std::forward(j), val); + } + + /*! + @brief convert any value type to a JSON value + + This function is usually called by the constructors of the @ref basic_json + class. + + @param[in,out] j JSON value to write to + @param[in] val value to read from + */ + template + static auto to_json(BasicJsonType& j, ValueType&& val) noexcept( + noexcept(::nlohmann::to_json(j, std::forward(val)))) + -> decltype(::nlohmann::to_json(j, std::forward(val)), void()) + { + ::nlohmann::to_json(j, std::forward(val)); + } +}; + +} // namespace nlohmann diff --git a/thirdparty/nlohmann/detail/conversions/from_json.hpp b/thirdparty/nlohmann/detail/conversions/from_json.hpp new file mode 100644 index 00000000000..c389dca7ad3 --- /dev/null +++ b/thirdparty/nlohmann/detail/conversions/from_json.hpp @@ -0,0 +1,389 @@ +#pragma once + +#include // transform +#include // array +#include // and, not +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +#include +#include +#include +#include +#include + +namespace nlohmann +{ +namespace detail +{ +template +void from_json(const BasicJsonType& j, typename std::nullptr_t& n) +{ + if (JSON_HEDLEY_UNLIKELY(not j.is_null())) + { + JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()))); + } + n = nullptr; +} + +// overloads for basic_json template parameters +template::value and + not std::is_same::value, + int> = 0> +void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) +{ + switch (static_cast(j)) + { + case value_t::number_unsigned: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_integer: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_float: + { + val = static_cast(*j.template get_ptr()); + break; + } + + default: + JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); + } +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) +{ + if (JSON_HEDLEY_UNLIKELY(not j.is_boolean())) + { + JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()))); + } + b = *j.template get_ptr(); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) +{ + if (JSON_HEDLEY_UNLIKELY(not j.is_string())) + { + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); + } + s = *j.template get_ptr(); +} + +template < + typename BasicJsonType, typename ConstructibleStringType, + enable_if_t < + is_constructible_string_type::value and + not std::is_same::value, + int > = 0 > +void from_json(const BasicJsonType& j, ConstructibleStringType& s) +{ + if (JSON_HEDLEY_UNLIKELY(not j.is_string())) + { + JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); + } + + s = *j.template get_ptr(); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) +{ + get_arithmetic_value(j, val); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) +{ + get_arithmetic_value(j, val); +} + +template +void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) +{ + get_arithmetic_value(j, val); +} + +template::value, int> = 0> +void from_json(const BasicJsonType& j, EnumType& e) +{ + typename std::underlying_type::type val; + get_arithmetic_value(j, val); + e = static_cast(val); +} + +// forward_list doesn't have an insert method +template::value, int> = 0> +void from_json(const BasicJsonType& j, std::forward_list& l) +{ + if (JSON_HEDLEY_UNLIKELY(not j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + l.clear(); + std::transform(j.rbegin(), j.rend(), + std::front_inserter(l), [](const BasicJsonType & i) + { + return i.template get(); + }); +} + +// valarray doesn't have an insert method +template::value, int> = 0> +void from_json(const BasicJsonType& j, std::valarray& l) +{ + if (JSON_HEDLEY_UNLIKELY(not j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + l.resize(j.size()); + std::copy(j.begin(), j.end(), std::begin(l)); +} + +template +auto from_json(const BasicJsonType& j, T (&arr)[N]) +-> decltype(j.template get(), void()) +{ + for (std::size_t i = 0; i < N; ++i) + { + arr[i] = j.at(i).template get(); + } +} + +template +void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) +{ + arr = *j.template get_ptr(); +} + +template +auto from_json_array_impl(const BasicJsonType& j, std::array& arr, + priority_tag<2> /*unused*/) +-> decltype(j.template get(), void()) +{ + for (std::size_t i = 0; i < N; ++i) + { + arr[i] = j.at(i).template get(); + } +} + +template +auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/) +-> decltype( + arr.reserve(std::declval()), + j.template get(), + void()) +{ + using std::end; + + ConstructibleArrayType ret; + ret.reserve(j.size()); + std::transform(j.begin(), j.end(), + std::inserter(ret, end(ret)), [](const BasicJsonType & i) + { + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); + arr = std::move(ret); +} + +template +void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, + priority_tag<0> /*unused*/) +{ + using std::end; + + ConstructibleArrayType ret; + std::transform( + j.begin(), j.end(), std::inserter(ret, end(ret)), + [](const BasicJsonType & i) + { + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); + arr = std::move(ret); +} + +template ::value and + not is_constructible_object_type::value and + not is_constructible_string_type::value and + not is_basic_json::value, + int > = 0 > + +auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr) +-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), +j.template get(), +void()) +{ + if (JSON_HEDLEY_UNLIKELY(not j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + + std::string(j.type_name()))); + } + + from_json_array_impl(j, arr, priority_tag<3> {}); +} + +template::value, int> = 0> +void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) +{ + if (JSON_HEDLEY_UNLIKELY(not j.is_object())) + { + JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()))); + } + + ConstructibleObjectType ret; + auto inner_object = j.template get_ptr(); + using value_type = typename ConstructibleObjectType::value_type; + std::transform( + inner_object->begin(), inner_object->end(), + std::inserter(ret, ret.begin()), + [](typename BasicJsonType::object_t::value_type const & p) + { + return value_type(p.first, p.second.template get()); + }); + obj = std::move(ret); +} + +// overload for arithmetic types, not chosen for basic_json template arguments +// (BooleanType, etc..); note: Is it really necessary to provide explicit +// overloads for boolean_t etc. in case of a custom BooleanType which is not +// an arithmetic type? +template::value and + not std::is_same::value and + not std::is_same::value and + not std::is_same::value and + not std::is_same::value, + int> = 0> +void from_json(const BasicJsonType& j, ArithmeticType& val) +{ + switch (static_cast(j)) + { + case value_t::number_unsigned: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_integer: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::number_float: + { + val = static_cast(*j.template get_ptr()); + break; + } + case value_t::boolean: + { + val = static_cast(*j.template get_ptr()); + break; + } + + default: + JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); + } +} + +template +void from_json(const BasicJsonType& j, std::pair& p) +{ + p = {j.at(0).template get(), j.at(1).template get()}; +} + +template +void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence /*unused*/) +{ + t = std::make_tuple(j.at(Idx).template get::type>()...); +} + +template +void from_json(const BasicJsonType& j, std::tuple& t) +{ + from_json_tuple_impl(j, t, index_sequence_for {}); +} + +template ::value>> +void from_json(const BasicJsonType& j, std::map& m) +{ + if (JSON_HEDLEY_UNLIKELY(not j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + m.clear(); + for (const auto& p : j) + { + if (JSON_HEDLEY_UNLIKELY(not p.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()))); + } + m.emplace(p.at(0).template get(), p.at(1).template get()); + } +} + +template ::value>> +void from_json(const BasicJsonType& j, std::unordered_map& m) +{ + if (JSON_HEDLEY_UNLIKELY(not j.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); + } + m.clear(); + for (const auto& p : j) + { + if (JSON_HEDLEY_UNLIKELY(not p.is_array())) + { + JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()))); + } + m.emplace(p.at(0).template get(), p.at(1).template get()); + } +} + +struct from_json_fn +{ + template + auto operator()(const BasicJsonType& j, T& val) const + noexcept(noexcept(from_json(j, val))) + -> decltype(from_json(j, val), void()) + { + return from_json(j, val); + } +}; +} // namespace detail + +/// namespace to hold default `from_json` function +/// to see why this is required: +/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html +namespace +{ +constexpr const auto& from_json = detail::static_const::value; +} // namespace +} // namespace nlohmann diff --git a/thirdparty/nlohmann/detail/conversions/to_chars.hpp b/thirdparty/nlohmann/detail/conversions/to_chars.hpp new file mode 100644 index 00000000000..d99703a54c1 --- /dev/null +++ b/thirdparty/nlohmann/detail/conversions/to_chars.hpp @@ -0,0 +1,1106 @@ +#pragma once + +#include // array +#include // assert +#include // or, and, not +#include // signbit, isfinite +#include // intN_t, uintN_t +#include // memcpy, memmove +#include // numeric_limits +#include // conditional +#include + +namespace nlohmann +{ +namespace detail +{ + +/*! +@brief implements the Grisu2 algorithm for binary to decimal floating-point +conversion. + +This implementation is a slightly modified version of the reference +implementation which may be obtained from +http://florian.loitsch.com/publications (bench.tar.gz). + +The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch. + +For a detailed description of the algorithm see: + +[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with + Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming + Language Design and Implementation, PLDI 2010 +[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately", + Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language + Design and Implementation, PLDI 1996 +*/ +namespace dtoa_impl +{ + +template +Target reinterpret_bits(const Source source) +{ + static_assert(sizeof(Target) == sizeof(Source), "size mismatch"); + + Target target; + std::memcpy(&target, &source, sizeof(Source)); + return target; +} + +struct diyfp // f * 2^e +{ + static constexpr int kPrecision = 64; // = q + + std::uint64_t f = 0; + int e = 0; + + constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {} + + /*! + @brief returns x - y + @pre x.e == y.e and x.f >= y.f + */ + static diyfp sub(const diyfp& x, const diyfp& y) noexcept + { + assert(x.e == y.e); + assert(x.f >= y.f); + + return {x.f - y.f, x.e}; + } + + /*! + @brief returns x * y + @note The result is rounded. (Only the upper q bits are returned.) + */ + static diyfp mul(const diyfp& x, const diyfp& y) noexcept + { + static_assert(kPrecision == 64, "internal error"); + + // Computes: + // f = round((x.f * y.f) / 2^q) + // e = x.e + y.e + q + + // Emulate the 64-bit * 64-bit multiplication: + // + // p = u * v + // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) + // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) + // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) + // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) + // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) + // = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) + // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) + // + // (Since Q might be larger than 2^32 - 1) + // + // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) + // + // (Q_hi + H does not overflow a 64-bit int) + // + // = p_lo + 2^64 p_hi + + const std::uint64_t u_lo = x.f & 0xFFFFFFFFu; + const std::uint64_t u_hi = x.f >> 32u; + const std::uint64_t v_lo = y.f & 0xFFFFFFFFu; + const std::uint64_t v_hi = y.f >> 32u; + + const std::uint64_t p0 = u_lo * v_lo; + const std::uint64_t p1 = u_lo * v_hi; + const std::uint64_t p2 = u_hi * v_lo; + const std::uint64_t p3 = u_hi * v_hi; + + const std::uint64_t p0_hi = p0 >> 32u; + const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu; + const std::uint64_t p1_hi = p1 >> 32u; + const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu; + const std::uint64_t p2_hi = p2 >> 32u; + + std::uint64_t Q = p0_hi + p1_lo + p2_lo; + + // The full product might now be computed as + // + // p_hi = p3 + p2_hi + p1_hi + (Q >> 32) + // p_lo = p0_lo + (Q << 32) + // + // But in this particular case here, the full p_lo is not required. + // Effectively we only need to add the highest bit in p_lo to p_hi (and + // Q_hi + 1 does not overflow). + + Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up + + const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u); + + return {h, x.e + y.e + 64}; + } + + /*! + @brief normalize x such that the significand is >= 2^(q-1) + @pre x.f != 0 + */ + static diyfp normalize(diyfp x) noexcept + { + assert(x.f != 0); + + while ((x.f >> 63u) == 0) + { + x.f <<= 1u; + x.e--; + } + + return x; + } + + /*! + @brief normalize x such that the result has the exponent E + @pre e >= x.e and the upper e - x.e bits of x.f must be zero. + */ + static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept + { + const int delta = x.e - target_exponent; + + assert(delta >= 0); + assert(((x.f << delta) >> delta) == x.f); + + return {x.f << delta, target_exponent}; + } +}; + +struct boundaries +{ + diyfp w; + diyfp minus; + diyfp plus; +}; + +/*! +Compute the (normalized) diyfp representing the input number 'value' and its +boundaries. + +@pre value must be finite and positive +*/ +template +boundaries compute_boundaries(FloatType value) +{ + assert(std::isfinite(value)); + assert(value > 0); + + // Convert the IEEE representation into a diyfp. + // + // If v is denormal: + // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) + // If v is normalized: + // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) + + static_assert(std::numeric_limits::is_iec559, + "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); + + constexpr int kPrecision = std::numeric_limits::digits; // = p (includes the hidden bit) + constexpr int kBias = std::numeric_limits::max_exponent - 1 + (kPrecision - 1); + constexpr int kMinExp = 1 - kBias; + constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1) + + using bits_type = typename std::conditional::type; + + const std::uint64_t bits = reinterpret_bits(value); + const std::uint64_t E = bits >> (kPrecision - 1); + const std::uint64_t F = bits & (kHiddenBit - 1); + + const bool is_denormal = E == 0; + const diyfp v = is_denormal + ? diyfp(F, kMinExp) + : diyfp(F + kHiddenBit, static_cast(E) - kBias); + + // Compute the boundaries m- and m+ of the floating-point value + // v = f * 2^e. + // + // Determine v- and v+, the floating-point predecessor and successor if v, + // respectively. + // + // v- = v - 2^e if f != 2^(p-1) or e == e_min (A) + // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) + // + // v+ = v + 2^e + // + // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ + // between m- and m+ round to v, regardless of how the input rounding + // algorithm breaks ties. + // + // ---+-------------+-------------+-------------+-------------+--- (A) + // v- m- v m+ v+ + // + // -----------------+------+------+-------------+-------------+--- (B) + // v- m- v m+ v+ + + const bool lower_boundary_is_closer = F == 0 and E > 1; + const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); + const diyfp m_minus = lower_boundary_is_closer + ? diyfp(4 * v.f - 1, v.e - 2) // (B) + : diyfp(2 * v.f - 1, v.e - 1); // (A) + + // Determine the normalized w+ = m+. + const diyfp w_plus = diyfp::normalize(m_plus); + + // Determine w- = m- such that e_(w-) = e_(w+). + const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e); + + return {diyfp::normalize(v), w_minus, w_plus}; +} + +// Given normalized diyfp w, Grisu needs to find a (normalized) cached +// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies +// within a certain range [alpha, gamma] (Definition 3.2 from [1]) +// +// alpha <= e = e_c + e_w + q <= gamma +// +// or +// +// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q +// <= f_c * f_w * 2^gamma +// +// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies +// +// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma +// +// or +// +// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma) +// +// The choice of (alpha,gamma) determines the size of the table and the form of +// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well +// in practice: +// +// The idea is to cut the number c * w = f * 2^e into two parts, which can be +// processed independently: An integral part p1, and a fractional part p2: +// +// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e +// = (f div 2^-e) + (f mod 2^-e) * 2^e +// = p1 + p2 * 2^e +// +// The conversion of p1 into decimal form requires a series of divisions and +// modulos by (a power of) 10. These operations are faster for 32-bit than for +// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be +// achieved by choosing +// +// -e >= 32 or e <= -32 := gamma +// +// In order to convert the fractional part +// +// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ... +// +// into decimal form, the fraction is repeatedly multiplied by 10 and the digits +// d[-i] are extracted in order: +// +// (10 * p2) div 2^-e = d[-1] +// (10 * p2) mod 2^-e = d[-2] / 10^1 + ... +// +// The multiplication by 10 must not overflow. It is sufficient to choose +// +// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64. +// +// Since p2 = f mod 2^-e < 2^-e, +// +// -e <= 60 or e >= -60 := alpha + +constexpr int kAlpha = -60; +constexpr int kGamma = -32; + +struct cached_power // c = f * 2^e ~= 10^k +{ + std::uint64_t f; + int e; + int k; +}; + +/*! +For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached +power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c +satisfies (Definition 3.2 from [1]) + + alpha <= e_c + e + q <= gamma. +*/ +inline cached_power get_cached_power_for_binary_exponent(int e) +{ + // Now + // + // alpha <= e_c + e + q <= gamma (1) + // ==> f_c * 2^alpha <= c * 2^e * 2^q + // + // and since the c's are normalized, 2^(q-1) <= f_c, + // + // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) + // ==> 2^(alpha - e - 1) <= c + // + // If c were an exact power of ten, i.e. c = 10^k, one may determine k as + // + // k = ceil( log_10( 2^(alpha - e - 1) ) ) + // = ceil( (alpha - e - 1) * log_10(2) ) + // + // From the paper: + // "In theory the result of the procedure could be wrong since c is rounded, + // and the computation itself is approximated [...]. In practice, however, + // this simple function is sufficient." + // + // For IEEE double precision floating-point numbers converted into + // normalized diyfp's w = f * 2^e, with q = 64, + // + // e >= -1022 (min IEEE exponent) + // -52 (p - 1) + // -52 (p - 1, possibly normalize denormal IEEE numbers) + // -11 (normalize the diyfp) + // = -1137 + // + // and + // + // e <= +1023 (max IEEE exponent) + // -52 (p - 1) + // -11 (normalize the diyfp) + // = 960 + // + // This binary exponent range [-1137,960] results in a decimal exponent + // range [-307,324]. One does not need to store a cached power for each + // k in this range. For each such k it suffices to find a cached power + // such that the exponent of the product lies in [alpha,gamma]. + // This implies that the difference of the decimal exponents of adjacent + // table entries must be less than or equal to + // + // floor( (gamma - alpha) * log_10(2) ) = 8. + // + // (A smaller distance gamma-alpha would require a larger table.) + + // NB: + // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. + + constexpr int kCachedPowersMinDecExp = -300; + constexpr int kCachedPowersDecStep = 8; + + static constexpr std::array kCachedPowers = + { + { + { 0xAB70FE17C79AC6CA, -1060, -300 }, + { 0xFF77B1FCBEBCDC4F, -1034, -292 }, + { 0xBE5691EF416BD60C, -1007, -284 }, + { 0x8DD01FAD907FFC3C, -980, -276 }, + { 0xD3515C2831559A83, -954, -268 }, + { 0x9D71AC8FADA6C9B5, -927, -260 }, + { 0xEA9C227723EE8BCB, -901, -252 }, + { 0xAECC49914078536D, -874, -244 }, + { 0x823C12795DB6CE57, -847, -236 }, + { 0xC21094364DFB5637, -821, -228 }, + { 0x9096EA6F3848984F, -794, -220 }, + { 0xD77485CB25823AC7, -768, -212 }, + { 0xA086CFCD97BF97F4, -741, -204 }, + { 0xEF340A98172AACE5, -715, -196 }, + { 0xB23867FB2A35B28E, -688, -188 }, + { 0x84C8D4DFD2C63F3B, -661, -180 }, + { 0xC5DD44271AD3CDBA, -635, -172 }, + { 0x936B9FCEBB25C996, -608, -164 }, + { 0xDBAC6C247D62A584, -582, -156 }, + { 0xA3AB66580D5FDAF6, -555, -148 }, + { 0xF3E2F893DEC3F126, -529, -140 }, + { 0xB5B5ADA8AAFF80B8, -502, -132 }, + { 0x87625F056C7C4A8B, -475, -124 }, + { 0xC9BCFF6034C13053, -449, -116 }, + { 0x964E858C91BA2655, -422, -108 }, + { 0xDFF9772470297EBD, -396, -100 }, + { 0xA6DFBD9FB8E5B88F, -369, -92 }, + { 0xF8A95FCF88747D94, -343, -84 }, + { 0xB94470938FA89BCF, -316, -76 }, + { 0x8A08F0F8BF0F156B, -289, -68 }, + { 0xCDB02555653131B6, -263, -60 }, + { 0x993FE2C6D07B7FAC, -236, -52 }, + { 0xE45C10C42A2B3B06, -210, -44 }, + { 0xAA242499697392D3, -183, -36 }, + { 0xFD87B5F28300CA0E, -157, -28 }, + { 0xBCE5086492111AEB, -130, -20 }, + { 0x8CBCCC096F5088CC, -103, -12 }, + { 0xD1B71758E219652C, -77, -4 }, + { 0x9C40000000000000, -50, 4 }, + { 0xE8D4A51000000000, -24, 12 }, + { 0xAD78EBC5AC620000, 3, 20 }, + { 0x813F3978F8940984, 30, 28 }, + { 0xC097CE7BC90715B3, 56, 36 }, + { 0x8F7E32CE7BEA5C70, 83, 44 }, + { 0xD5D238A4ABE98068, 109, 52 }, + { 0x9F4F2726179A2245, 136, 60 }, + { 0xED63A231D4C4FB27, 162, 68 }, + { 0xB0DE65388CC8ADA8, 189, 76 }, + { 0x83C7088E1AAB65DB, 216, 84 }, + { 0xC45D1DF942711D9A, 242, 92 }, + { 0x924D692CA61BE758, 269, 100 }, + { 0xDA01EE641A708DEA, 295, 108 }, + { 0xA26DA3999AEF774A, 322, 116 }, + { 0xF209787BB47D6B85, 348, 124 }, + { 0xB454E4A179DD1877, 375, 132 }, + { 0x865B86925B9BC5C2, 402, 140 }, + { 0xC83553C5C8965D3D, 428, 148 }, + { 0x952AB45CFA97A0B3, 455, 156 }, + { 0xDE469FBD99A05FE3, 481, 164 }, + { 0xA59BC234DB398C25, 508, 172 }, + { 0xF6C69A72A3989F5C, 534, 180 }, + { 0xB7DCBF5354E9BECE, 561, 188 }, + { 0x88FCF317F22241E2, 588, 196 }, + { 0xCC20CE9BD35C78A5, 614, 204 }, + { 0x98165AF37B2153DF, 641, 212 }, + { 0xE2A0B5DC971F303A, 667, 220 }, + { 0xA8D9D1535CE3B396, 694, 228 }, + { 0xFB9B7CD9A4A7443C, 720, 236 }, + { 0xBB764C4CA7A44410, 747, 244 }, + { 0x8BAB8EEFB6409C1A, 774, 252 }, + { 0xD01FEF10A657842C, 800, 260 }, + { 0x9B10A4E5E9913129, 827, 268 }, + { 0xE7109BFBA19C0C9D, 853, 276 }, + { 0xAC2820D9623BF429, 880, 284 }, + { 0x80444B5E7AA7CF85, 907, 292 }, + { 0xBF21E44003ACDD2D, 933, 300 }, + { 0x8E679C2F5E44FF8F, 960, 308 }, + { 0xD433179D9C8CB841, 986, 316 }, + { 0x9E19DB92B4E31BA9, 1013, 324 }, + } + }; + + // This computation gives exactly the same results for k as + // k = ceil((kAlpha - e - 1) * 0.30102999566398114) + // for |e| <= 1500, but doesn't require floating-point operations. + // NB: log_10(2) ~= 78913 / 2^18 + assert(e >= -1500); + assert(e <= 1500); + const int f = kAlpha - e - 1; + const int k = (f * 78913) / (1 << 18) + static_cast(f > 0); + + const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; + assert(index >= 0); + assert(static_cast(index) < kCachedPowers.size()); + + const cached_power cached = kCachedPowers[static_cast(index)]; + assert(kAlpha <= cached.e + e + 64); + assert(kGamma >= cached.e + e + 64); + + return cached; +} + +/*! +For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. +For n == 0, returns 1 and sets pow10 := 1. +*/ +inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10) +{ + // LCOV_EXCL_START + if (n >= 1000000000) + { + pow10 = 1000000000; + return 10; + } + // LCOV_EXCL_STOP + else if (n >= 100000000) + { + pow10 = 100000000; + return 9; + } + else if (n >= 10000000) + { + pow10 = 10000000; + return 8; + } + else if (n >= 1000000) + { + pow10 = 1000000; + return 7; + } + else if (n >= 100000) + { + pow10 = 100000; + return 6; + } + else if (n >= 10000) + { + pow10 = 10000; + return 5; + } + else if (n >= 1000) + { + pow10 = 1000; + return 4; + } + else if (n >= 100) + { + pow10 = 100; + return 3; + } + else if (n >= 10) + { + pow10 = 10; + return 2; + } + else + { + pow10 = 1; + return 1; + } +} + +inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta, + std::uint64_t rest, std::uint64_t ten_k) +{ + assert(len >= 1); + assert(dist <= delta); + assert(rest <= delta); + assert(ten_k > 0); + + // <--------------------------- delta ----> + // <---- dist ---------> + // --------------[------------------+-------------------]-------------- + // M- w M+ + // + // ten_k + // <------> + // <---- rest ----> + // --------------[------------------+----+--------------]-------------- + // w V + // = buf * 10^k + // + // ten_k represents a unit-in-the-last-place in the decimal representation + // stored in buf. + // Decrement buf by ten_k while this takes buf closer to w. + + // The tests are written in this order to avoid overflow in unsigned + // integer arithmetic. + + while (rest < dist + and delta - rest >= ten_k + and (rest + ten_k < dist or dist - rest > rest + ten_k - dist)) + { + assert(buf[len - 1] != '0'); + buf[len - 1]--; + rest += ten_k; + } +} + +/*! +Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. +M- and M+ must be normalized and share the same exponent -60 <= e <= -32. +*/ +inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, + diyfp M_minus, diyfp w, diyfp M_plus) +{ + static_assert(kAlpha >= -60, "internal error"); + static_assert(kGamma <= -32, "internal error"); + + // Generates the digits (and the exponent) of a decimal floating-point + // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's + // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. + // + // <--------------------------- delta ----> + // <---- dist ---------> + // --------------[------------------+-------------------]-------------- + // M- w M+ + // + // Grisu2 generates the digits of M+ from left to right and stops as soon as + // V is in [M-,M+]. + + assert(M_plus.e >= kAlpha); + assert(M_plus.e <= kGamma); + + std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e) + std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e) + + // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): + // + // M+ = f * 2^e + // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e + // = ((p1 ) * 2^-e + (p2 )) * 2^e + // = p1 + p2 * 2^e + + const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e); + + auto p1 = static_cast(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.) + std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e + + // 1) + // + // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] + + assert(p1 > 0); + + std::uint32_t pow10; + const int k = find_largest_pow10(p1, pow10); + + // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) + // + // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) + // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) + // + // M+ = p1 + p2 * 2^e + // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e + // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e + // = d[k-1] * 10^(k-1) + ( rest) * 2^e + // + // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) + // + // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] + // + // but stop as soon as + // + // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e + + int n = k; + while (n > 0) + { + // Invariants: + // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) + // pow10 = 10^(n-1) <= p1 < 10^n + // + const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) + const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) + // + // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e + // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) + // + assert(d <= 9); + buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d + // + // M+ = buffer * 10^(n-1) + (r + p2 * 2^e) + // + p1 = r; + n--; + // + // M+ = buffer * 10^n + (p1 + p2 * 2^e) + // pow10 = 10^n + // + + // Now check if enough digits have been generated. + // Compute + // + // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e + // + // Note: + // Since rest and delta share the same exponent e, it suffices to + // compare the significands. + const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2; + if (rest <= delta) + { + // V = buffer * 10^n, with M- <= V <= M+. + + decimal_exponent += n; + + // We may now just stop. But instead look if the buffer could be + // decremented to bring V closer to w. + // + // pow10 = 10^n is now 1 ulp in the decimal representation V. + // The rounding procedure works with diyfp's with an implicit + // exponent of e. + // + // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e + // + const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e; + grisu2_round(buffer, length, dist, delta, rest, ten_n); + + return; + } + + pow10 /= 10; + // + // pow10 = 10^(n-1) <= p1 < 10^n + // Invariants restored. + } + + // 2) + // + // The digits of the integral part have been generated: + // + // M+ = d[k-1]...d[1]d[0] + p2 * 2^e + // = buffer + p2 * 2^e + // + // Now generate the digits of the fractional part p2 * 2^e. + // + // Note: + // No decimal point is generated: the exponent is adjusted instead. + // + // p2 actually represents the fraction + // + // p2 * 2^e + // = p2 / 2^-e + // = d[-1] / 10^1 + d[-2] / 10^2 + ... + // + // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) + // + // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m + // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) + // + // using + // + // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) + // = ( d) * 2^-e + ( r) + // + // or + // 10^m * p2 * 2^e = d + r * 2^e + // + // i.e. + // + // M+ = buffer + p2 * 2^e + // = buffer + 10^-m * (d + r * 2^e) + // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e + // + // and stop as soon as 10^-m * r * 2^e <= delta * 2^e + + assert(p2 > delta); + + int m = 0; + for (;;) + { + // Invariant: + // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e + // = buffer * 10^-m + 10^-m * (p2 ) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e + // + assert(p2 <= (std::numeric_limits::max)() / 10); + p2 *= 10; + const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e + const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e + // + // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e + // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) + // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e + // + assert(d <= 9); + buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d + // + // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e + // + p2 = r; + m++; + // + // M+ = buffer * 10^-m + 10^-m * p2 * 2^e + // Invariant restored. + + // Check if enough digits have been generated. + // + // 10^-m * p2 * 2^e <= delta * 2^e + // p2 * 2^e <= 10^m * delta * 2^e + // p2 <= 10^m * delta + delta *= 10; + dist *= 10; + if (p2 <= delta) + { + break; + } + } + + // V = buffer * 10^-m, with M- <= V <= M+. + + decimal_exponent -= m; + + // 1 ulp in the decimal representation is now 10^-m. + // Since delta and dist are now scaled by 10^m, we need to do the + // same with ulp in order to keep the units in sync. + // + // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e + // + const std::uint64_t ten_m = one.f; + grisu2_round(buffer, length, dist, delta, p2, ten_m); + + // By construction this algorithm generates the shortest possible decimal + // number (Loitsch, Theorem 6.2) which rounds back to w. + // For an input number of precision p, at least + // + // N = 1 + ceil(p * log_10(2)) + // + // decimal digits are sufficient to identify all binary floating-point + // numbers (Matula, "In-and-Out conversions"). + // This implies that the algorithm does not produce more than N decimal + // digits. + // + // N = 17 for p = 53 (IEEE double precision) + // N = 9 for p = 24 (IEEE single precision) +} + +/*! +v = buf * 10^decimal_exponent +len is the length of the buffer (number of decimal digits) +The buffer must be large enough, i.e. >= max_digits10. +*/ +JSON_HEDLEY_NON_NULL(1) +inline void grisu2(char* buf, int& len, int& decimal_exponent, + diyfp m_minus, diyfp v, diyfp m_plus) +{ + assert(m_plus.e == m_minus.e); + assert(m_plus.e == v.e); + + // --------(-----------------------+-----------------------)-------- (A) + // m- v m+ + // + // --------------------(-----------+-----------------------)-------- (B) + // m- v m+ + // + // First scale v (and m- and m+) such that the exponent is in the range + // [alpha, gamma]. + + const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e); + + const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k + + // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] + const diyfp w = diyfp::mul(v, c_minus_k); + const diyfp w_minus = diyfp::mul(m_minus, c_minus_k); + const diyfp w_plus = diyfp::mul(m_plus, c_minus_k); + + // ----(---+---)---------------(---+---)---------------(---+---)---- + // w- w w+ + // = c*m- = c*v = c*m+ + // + // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and + // w+ are now off by a small amount. + // In fact: + // + // w - v * 10^k < 1 ulp + // + // To account for this inaccuracy, add resp. subtract 1 ulp. + // + // --------+---[---------------(---+---)---------------]---+-------- + // w- M- w M+ w+ + // + // Now any number in [M-, M+] (bounds included) will round to w when input, + // regardless of how the input rounding algorithm breaks ties. + // + // And digit_gen generates the shortest possible such number in [M-, M+]. + // Note that this does not mean that Grisu2 always generates the shortest + // possible number in the interval (m-, m+). + const diyfp M_minus(w_minus.f + 1, w_minus.e); + const diyfp M_plus (w_plus.f - 1, w_plus.e ); + + decimal_exponent = -cached.k; // = -(-k) = k + + grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus); +} + +/*! +v = buf * 10^decimal_exponent +len is the length of the buffer (number of decimal digits) +The buffer must be large enough, i.e. >= max_digits10. +*/ +template +JSON_HEDLEY_NON_NULL(1) +void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) +{ + static_assert(diyfp::kPrecision >= std::numeric_limits::digits + 3, + "internal error: not enough precision"); + + assert(std::isfinite(value)); + assert(value > 0); + + // If the neighbors (and boundaries) of 'value' are always computed for double-precision + // numbers, all float's can be recovered using strtod (and strtof). However, the resulting + // decimal representations are not exactly "short". + // + // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars) + // says "value is converted to a string as if by std::sprintf in the default ("C") locale" + // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars' + // does. + // On the other hand, the documentation for 'std::to_chars' requires that "parsing the + // representation using the corresponding std::from_chars function recovers value exactly". That + // indicates that single precision floating-point numbers should be recovered using + // 'std::strtof'. + // + // NB: If the neighbors are computed for single-precision numbers, there is a single float + // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision + // value is off by 1 ulp. +#if 0 + const boundaries w = compute_boundaries(static_cast(value)); +#else + const boundaries w = compute_boundaries(value); +#endif + + grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus); +} + +/*! +@brief appends a decimal representation of e to buf +@return a pointer to the element following the exponent. +@pre -1000 < e < 1000 +*/ +JSON_HEDLEY_NON_NULL(1) +JSON_HEDLEY_RETURNS_NON_NULL +inline char* append_exponent(char* buf, int e) +{ + assert(e > -1000); + assert(e < 1000); + + if (e < 0) + { + e = -e; + *buf++ = '-'; + } + else + { + *buf++ = '+'; + } + + auto k = static_cast(e); + if (k < 10) + { + // Always print at least two digits in the exponent. + // This is for compatibility with printf("%g"). + *buf++ = '0'; + *buf++ = static_cast('0' + k); + } + else if (k < 100) + { + *buf++ = static_cast('0' + k / 10); + k %= 10; + *buf++ = static_cast('0' + k); + } + else + { + *buf++ = static_cast('0' + k / 100); + k %= 100; + *buf++ = static_cast('0' + k / 10); + k %= 10; + *buf++ = static_cast('0' + k); + } + + return buf; +} + +/*! +@brief prettify v = buf * 10^decimal_exponent + +If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point +notation. Otherwise it will be printed in exponential notation. + +@pre min_exp < 0 +@pre max_exp > 0 +*/ +JSON_HEDLEY_NON_NULL(1) +JSON_HEDLEY_RETURNS_NON_NULL +inline char* format_buffer(char* buf, int len, int decimal_exponent, + int min_exp, int max_exp) +{ + assert(min_exp < 0); + assert(max_exp > 0); + + const int k = len; + const int n = len + decimal_exponent; + + // v = buf * 10^(n-k) + // k is the length of the buffer (number of decimal digits) + // n is the position of the decimal point relative to the start of the buffer. + + if (k <= n and n <= max_exp) + { + // digits[000] + // len <= max_exp + 2 + + std::memset(buf + k, '0', static_cast(n - k)); + // Make it look like a floating-point number (#362, #378) + buf[n + 0] = '.'; + buf[n + 1] = '0'; + return buf + (n + 2); + } + + if (0 < n and n <= max_exp) + { + // dig.its + // len <= max_digits10 + 1 + + assert(k > n); + + std::memmove(buf + (n + 1), buf + n, static_cast(k - n)); + buf[n] = '.'; + return buf + (k + 1); + } + + if (min_exp < n and n <= 0) + { + // 0.[000]digits + // len <= 2 + (-min_exp - 1) + max_digits10 + + std::memmove(buf + (2 + -n), buf, static_cast(k)); + buf[0] = '0'; + buf[1] = '.'; + std::memset(buf + 2, '0', static_cast(-n)); + return buf + (2 + (-n) + k); + } + + if (k == 1) + { + // dE+123 + // len <= 1 + 5 + + buf += 1; + } + else + { + // d.igitsE+123 + // len <= max_digits10 + 1 + 5 + + std::memmove(buf + 2, buf + 1, static_cast(k - 1)); + buf[1] = '.'; + buf += 1 + k; + } + + *buf++ = 'e'; + return append_exponent(buf, n - 1); +} + +} // namespace dtoa_impl + +/*! +@brief generates a decimal representation of the floating-point number value in [first, last). + +The format of the resulting decimal representation is similar to printf's %g +format. Returns an iterator pointing past-the-end of the decimal representation. + +@note The input number must be finite, i.e. NaN's and Inf's are not supported. +@note The buffer must be large enough. +@note The result is NOT null-terminated. +*/ +template +JSON_HEDLEY_NON_NULL(1, 2) +JSON_HEDLEY_RETURNS_NON_NULL +char* to_chars(char* first, const char* last, FloatType value) +{ + static_cast(last); // maybe unused - fix warning + assert(std::isfinite(value)); + + // Use signbit(value) instead of (value < 0) since signbit works for -0. + if (std::signbit(value)) + { + value = -value; + *first++ = '-'; + } + + if (value == 0) // +-0 + { + *first++ = '0'; + // Make it look like a floating-point number (#362, #378) + *first++ = '.'; + *first++ = '0'; + return first; + } + + assert(last - first >= std::numeric_limits::max_digits10); + + // Compute v = buffer * 10^decimal_exponent. + // The decimal digits are stored in the buffer, which needs to be interpreted + // as an unsigned decimal integer. + // len is the length of the buffer, i.e. the number of decimal digits. + int len = 0; + int decimal_exponent = 0; + dtoa_impl::grisu2(first, len, decimal_exponent, value); + + assert(len <= std::numeric_limits::max_digits10); + + // Format the buffer like printf("%.*g", prec, value) + constexpr int kMinExp = -4; + // Use digits10 here to increase compatibility with version 2. + constexpr int kMaxExp = std::numeric_limits::digits10; + + assert(last - first >= kMaxExp + 2); + assert(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits::max_digits10); + assert(last - first >= std::numeric_limits::max_digits10 + 6); + + return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); +} + +} // namespace detail +} // namespace nlohmann diff --git a/thirdparty/nlohmann/detail/conversions/to_json.hpp b/thirdparty/nlohmann/detail/conversions/to_json.hpp new file mode 100644 index 00000000000..a1def699fd7 --- /dev/null +++ b/thirdparty/nlohmann/detail/conversions/to_json.hpp @@ -0,0 +1,347 @@ +#pragma once + +#include // copy +#include // or, and, not +#include // begin, end +#include // string +#include // tuple, get +#include // is_same, is_constructible, is_floating_point, is_enum, underlying_type +#include // move, forward, declval, pair +#include // valarray +#include // vector + +#include +#include +#include +#include + +namespace nlohmann +{ +namespace detail +{ +////////////////// +// constructors // +////////////////// + +template struct external_constructor; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept + { + j.m_type = value_t::boolean; + j.m_value = b; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) + { + j.m_type = value_t::string; + j.m_value = s; + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) + { + j.m_type = value_t::string; + j.m_value = std::move(s); + j.assert_invariant(); + } + + template::value, + int> = 0> + static void construct(BasicJsonType& j, const CompatibleStringType& str) + { + j.m_type = value_t::string; + j.m_value.string = j.template create(str); + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept + { + j.m_type = value_t::number_float; + j.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept + { + j.m_type = value_t::number_unsigned; + j.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept + { + j.m_type = value_t::number_integer; + j.m_value = val; + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) + { + j.m_type = value_t::array; + j.m_value = arr; + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) + { + j.m_type = value_t::array; + j.m_value = std::move(arr); + j.assert_invariant(); + } + + template::value, + int> = 0> + static void construct(BasicJsonType& j, const CompatibleArrayType& arr) + { + using std::begin; + using std::end; + j.m_type = value_t::array; + j.m_value.array = j.template create(begin(arr), end(arr)); + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, const std::vector& arr) + { + j.m_type = value_t::array; + j.m_value = value_t::array; + j.m_value.array->reserve(arr.size()); + for (const bool x : arr) + { + j.m_value.array->push_back(x); + } + j.assert_invariant(); + } + + template::value, int> = 0> + static void construct(BasicJsonType& j, const std::valarray& arr) + { + j.m_type = value_t::array; + j.m_value = value_t::array; + j.m_value.array->resize(arr.size()); + if (arr.size() > 0) + { + std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); + } + j.assert_invariant(); + } +}; + +template<> +struct external_constructor +{ + template + static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) + { + j.m_type = value_t::object; + j.m_value = obj; + j.assert_invariant(); + } + + template + static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) + { + j.m_type = value_t::object; + j.m_value = std::move(obj); + j.assert_invariant(); + } + + template::value, int> = 0> + static void construct(BasicJsonType& j, const CompatibleObjectType& obj) + { + using std::begin; + using std::end; + + j.m_type = value_t::object; + j.m_value.object = j.template create(begin(obj), end(obj)); + j.assert_invariant(); + } +}; + +///////////// +// to_json // +///////////// + +template::value, int> = 0> +void to_json(BasicJsonType& j, T b) noexcept +{ + external_constructor::construct(j, b); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, const CompatibleString& s) +{ + external_constructor::construct(j, s); +} + +template +void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) +{ + external_constructor::construct(j, std::move(s)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, FloatType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept +{ + external_constructor::construct(j, static_cast(val)); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, EnumType e) noexcept +{ + using underlying_type = typename std::underlying_type::type; + external_constructor::construct(j, static_cast(e)); +} + +template +void to_json(BasicJsonType& j, const std::vector& e) +{ + external_constructor::construct(j, e); +} + +template ::value and + not is_compatible_object_type< + BasicJsonType, CompatibleArrayType>::value and + not is_compatible_string_type::value and + not is_basic_json::value, + int> = 0> +void to_json(BasicJsonType& j, const CompatibleArrayType& arr) +{ + external_constructor::construct(j, arr); +} + +template::value, int> = 0> +void to_json(BasicJsonType& j, const std::valarray& arr) +{ + external_constructor::construct(j, std::move(arr)); +} + +template +void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) +{ + external_constructor::construct(j, std::move(arr)); +} + +template::value and not is_basic_json::value, int> = 0> +void to_json(BasicJsonType& j, const CompatibleObjectType& obj) +{ + external_constructor::construct(j, obj); +} + +template +void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) +{ + external_constructor::construct(j, std::move(obj)); +} + +template < + typename BasicJsonType, typename T, std::size_t N, + enable_if_t::value, + int> = 0 > +void to_json(BasicJsonType& j, const T(&arr)[N]) +{ + external_constructor::construct(j, arr); +} + +template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible::value&& std::is_constructible::value, int > = 0 > +void to_json(BasicJsonType& j, const std::pair& p) +{ + j = { p.first, p.second }; +} + +// for https://github.com/nlohmann/json/pull/1134 +template < typename BasicJsonType, typename T, + enable_if_t>::value, int> = 0> +void to_json(BasicJsonType& j, const T& b) +{ + j = { {b.key(), b.value()} }; +} + +template +void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence /*unused*/) +{ + j = { std::get(t)... }; +} + +template::value, int > = 0> +void to_json(BasicJsonType& j, const T& t) +{ + to_json_tuple_impl(j, t, make_index_sequence::value> {}); +} + +struct to_json_fn +{ + template + auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward(val)))) + -> decltype(to_json(j, std::forward(val)), void()) + { + return to_json(j, std::forward(val)); + } +}; +} // namespace detail + +/// namespace to hold default `to_json` function +namespace +{ +constexpr const auto& to_json = detail::static_const::value; +} // namespace +} // namespace nlohmann diff --git a/thirdparty/nlohmann/detail/exceptions.hpp b/thirdparty/nlohmann/detail/exceptions.hpp new file mode 100644 index 00000000000..ed836188ccc --- /dev/null +++ b/thirdparty/nlohmann/detail/exceptions.hpp @@ -0,0 +1,356 @@ +#pragma once + +#include // exception +#include // runtime_error +#include // to_string + +#include +#include + +namespace nlohmann +{ +namespace detail +{ +//////////////// +// exceptions // +//////////////// + +/*! +@brief general exception of the @ref basic_json class + +This class is an extension of `std::exception` objects with a member @a id for +exception ids. It is used as the base class for all exceptions thrown by the +@ref basic_json class. This class can hence be used as "wildcard" to catch +exceptions. + +Subclasses: +- @ref parse_error for exceptions indicating a parse error +- @ref invalid_iterator for exceptions indicating errors with iterators +- @ref type_error for exceptions indicating executing a member function with + a wrong type +- @ref out_of_range for exceptions indicating access out of the defined range +- @ref other_error for exceptions indicating other library errors + +@internal +@note To have nothrow-copy-constructible exceptions, we internally use + `std::runtime_error` which can cope with arbitrary-length error messages. + Intermediate strings are built with static functions and then passed to + the actual constructor. +@endinternal + +@liveexample{The following code shows how arbitrary library exceptions can be +caught.,exception} + +@since version 3.0.0 +*/ +class exception : public std::exception +{ + public: + /// returns the explanatory string + JSON_HEDLEY_RETURNS_NON_NULL + const char* what() const noexcept override + { + return m.what(); + } + + /// the id of the exception + const int id; + + protected: + JSON_HEDLEY_NON_NULL(3) + exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} + + static std::string name(const std::string& ename, int id_) + { + return "[json.exception." + ename + "." + std::to_string(id_) + "] "; + } + + private: + /// an exception object as storage for error messages + std::runtime_error m; +}; + +/*! +@brief exception indicating a parse error + +This exception is thrown by the library when a parse error occurs. Parse errors +can occur during the deserialization of JSON text, CBOR, MessagePack, as well +as when using JSON Patch. + +Member @a byte holds the byte index of the last read character in the input +file. + +Exceptions have ids 1xx. + +name / id | example message | description +------------------------------ | --------------- | ------------------------- +json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. +json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. +json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. +json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. +json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. +json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`. +json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. +json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. +json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. +json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. +json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. +json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. +json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet). + +@note For an input with n bytes, 1 is the index of the first character and n+1 + is the index of the terminating null byte or the end of file. This also + holds true when reading a byte vector (CBOR or MessagePack). + +@liveexample{The following code shows how a `parse_error` exception can be +caught.,parse_error} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class parse_error : public exception +{ + public: + /*! + @brief create a parse error exception + @param[in] id_ the id of the exception + @param[in] pos the position where the error occurred (or with + chars_read_total=0 if the position cannot be + determined) + @param[in] what_arg the explanatory string + @return parse_error object + */ + static parse_error create(int id_, const position_t& pos, const std::string& what_arg) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + position_string(pos) + ": " + what_arg; + return parse_error(id_, pos.chars_read_total, w.c_str()); + } + + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + + ": " + what_arg; + return parse_error(id_, byte_, w.c_str()); + } + + /*! + @brief byte index of the parse error + + The byte index of the last read character in the input file. + + @note For an input with n bytes, 1 is the index of the first character and + n+1 is the index of the terminating null byte or the end of file. + This also holds true when reading a byte vector (CBOR or MessagePack). + */ + const std::size_t byte; + + private: + parse_error(int id_, std::size_t byte_, const char* what_arg) + : exception(id_, what_arg), byte(byte_) {} + + static std::string position_string(const position_t& pos) + { + return " at line " + std::to_string(pos.lines_read + 1) + + ", column " + std::to_string(pos.chars_read_current_line); + } +}; + +/*! +@brief exception indicating errors with iterators + +This exception is thrown if iterators passed to a library function do not match +the expected semantics. + +Exceptions have ids 2xx. + +name / id | example message | description +----------------------------------- | --------------- | ------------------------- +json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. +json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. +json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. +json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid. +json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. +json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. +json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. +json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. +json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. +json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. +json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. +json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. +json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered. +json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin(). + +@liveexample{The following code shows how an `invalid_iterator` exception can be +caught.,invalid_iterator} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class invalid_iterator : public exception +{ + public: + static invalid_iterator create(int id_, const std::string& what_arg) + { + std::string w = exception::name("invalid_iterator", id_) + what_arg; + return invalid_iterator(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + invalid_iterator(int id_, const char* what_arg) + : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating executing a member function with a wrong type + +This exception is thrown in case of a type error; that is, a library function is +executed on a JSON value whose type does not match the expected semantics. + +Exceptions have ids 3xx. + +name / id | example message | description +----------------------------- | --------------- | ------------------------- +json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. +json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. +json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &. +json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types. +json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types. +json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types. +json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types. +json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types. +json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types. +json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types. +json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types. +json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types. +json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. +json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers. +json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive. +json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. | +json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) | + +@liveexample{The following code shows how a `type_error` exception can be +caught.,type_error} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref out_of_range for exceptions indicating access out of the defined range +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class type_error : public exception +{ + public: + static type_error create(int id_, const std::string& what_arg) + { + std::string w = exception::name("type_error", id_) + what_arg; + return type_error(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating access out of the defined range + +This exception is thrown in case a library function is called on an input +parameter that exceeds the expected range, for instance in case of array +indices or nonexisting object keys. + +Exceptions have ids 4xx. + +name / id | example message | description +------------------------------- | --------------- | ------------------------- +json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. +json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. +json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object. +json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. +json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. +json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. +json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. | +json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. | +json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string | + +@liveexample{The following code shows how an `out_of_range` exception can be +caught.,out_of_range} + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref other_error for exceptions indicating other library errors + +@since version 3.0.0 +*/ +class out_of_range : public exception +{ + public: + static out_of_range create(int id_, const std::string& what_arg) + { + std::string w = exception::name("out_of_range", id_) + what_arg; + return out_of_range(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; + +/*! +@brief exception indicating other library errors + +This exception is thrown in case of errors that cannot be classified with the +other exception types. + +Exceptions have ids 5xx. + +name / id | example message | description +------------------------------ | --------------- | ------------------------- +json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/https/github.com/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. + +@sa - @ref exception for the base class of the library exceptions +@sa - @ref parse_error for exceptions indicating a parse error +@sa - @ref invalid_iterator for exceptions indicating errors with iterators +@sa - @ref type_error for exceptions indicating executing a member function with + a wrong type +@sa - @ref out_of_range for exceptions indicating access out of the defined range + +@liveexample{The following code shows how an `other_error` exception can be +caught.,other_error} + +@since version 3.0.0 +*/ +class other_error : public exception +{ + public: + static other_error create(int id_, const std::string& what_arg) + { + std::string w = exception::name("other_error", id_) + what_arg; + return other_error(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} +}; +} // namespace detail +} // namespace nlohmann diff --git a/thirdparty/nlohmann/detail/input/binary_reader.hpp b/thirdparty/nlohmann/detail/input/binary_reader.hpp new file mode 100644 index 00000000000..1b6e0f9b7b3 --- /dev/null +++ b/thirdparty/nlohmann/detail/input/binary_reader.hpp @@ -0,0 +1,1983 @@ +#pragma once + +#include // generate_n +#include // array +#include // assert +#include // ldexp +#include // size_t +#include // uint8_t, uint16_t, uint32_t, uint64_t +#include // snprintf +#include // memcpy +#include // back_inserter +#include // numeric_limits +#include // char_traits, string +#include // make_pair, move + +#include +#include +#include +#include +#include +#include + +namespace nlohmann +{ +namespace detail +{ +/////////////////// +// binary reader // +/////////////////// + +/*! +@brief deserialization of CBOR, MessagePack, and UBJSON values +*/ +template> +class binary_reader +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using json_sax_t = SAX; + + public: + /*! + @brief create a binary reader + + @param[in] adapter input adapter to read from + */ + explicit binary_reader(input_adapter_t adapter) : ia(std::move(adapter)) + { + (void)detail::is_sax_static_asserts {}; + assert(ia); + } + + // make class move-only + binary_reader(const binary_reader&) = delete; + binary_reader(binary_reader&&) = default; + binary_reader& operator=(const binary_reader&) = delete; + binary_reader& operator=(binary_reader&&) = default; + ~binary_reader() = default; + + /*! + @param[in] format the binary format to parse + @param[in] sax_ a SAX event processor + @param[in] strict whether to expect the input to be consumed completed + + @return + */ + JSON_HEDLEY_NON_NULL(3) + bool sax_parse(const input_format_t format, + json_sax_t* sax_, + const bool strict = true) + { + sax = sax_; + bool result = false; + + switch (format) + { + case input_format_t::bson: + result = parse_bson_internal(); + break; + + case input_format_t::cbor: + result = parse_cbor_internal(); + break; + + case input_format_t::msgpack: + result = parse_msgpack_internal(); + break; + + case input_format_t::ubjson: + result = parse_ubjson_internal(); + break; + + default: // LCOV_EXCL_LINE + assert(false); // LCOV_EXCL_LINE + } + + // strict mode: next byte must be EOF + if (result and strict) + { + if (format == input_format_t::ubjson) + { + get_ignore_noop(); + } + else + { + get(); + } + + if (JSON_HEDLEY_UNLIKELY(current != std::char_traits::eof())) + { + return sax->parse_error(chars_read, get_token_string(), + parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"))); + } + } + + return result; + } + + /*! + @brief determine system byte order + + @return true if and only if system's byte order is little endian + + @note from http://stackoverflow.com/a/1001328/266378 + */ + static constexpr bool little_endianess(int num = 1) noexcept + { + return *reinterpret_cast(&num) == 1; + } + + private: + ////////// + // BSON // + ////////// + + /*! + @brief Reads in a BSON-object and passes it to the SAX-parser. + @return whether a valid BSON-value was passed to the SAX parser + */ + bool parse_bson_internal() + { + std::int32_t document_size; + get_number(input_format_t::bson, document_size); + + if (JSON_HEDLEY_UNLIKELY(not sax->start_object(std::size_t(-1)))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(not parse_bson_element_list(/*is_array*/false))) + { + return false; + } + + return sax->end_object(); + } + + /*! + @brief Parses a C-style string from the BSON input. + @param[in, out] result A reference to the string variable where the read + string is to be stored. + @return `true` if the \x00-byte indicating the end of the string was + encountered before the EOF; false` indicates an unexpected EOF. + */ + bool get_bson_cstr(string_t& result) + { + auto out = std::back_inserter(result); + while (true) + { + get(); + if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::bson, "cstring"))) + { + return false; + } + if (current == 0x00) + { + return true; + } + *out++ = static_cast(current); + } + + return true; + } + + /*! + @brief Parses a zero-terminated string of length @a len from the BSON + input. + @param[in] len The length (including the zero-byte at the end) of the + string to be read. + @param[in, out] result A reference to the string variable where the read + string is to be stored. + @tparam NumberType The type of the length @a len + @pre len >= 1 + @return `true` if the string was successfully parsed + */ + template + bool get_bson_string(const NumberType len, string_t& result) + { + if (JSON_HEDLEY_UNLIKELY(len < 1)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"))); + } + + return get_string(input_format_t::bson, len - static_cast(1), result) and get() != std::char_traits::eof(); + } + + /*! + @brief Read a BSON document element of the given @a element_type. + @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html + @param[in] element_type_parse_position The position in the input stream, + where the `element_type` was read. + @warning Not all BSON element types are supported yet. An unsupported + @a element_type will give rise to a parse_error.114: + Unsupported BSON record type 0x... + @return whether a valid BSON-object/array was passed to the SAX parser + */ + bool parse_bson_element_internal(const int element_type, + const std::size_t element_type_parse_position) + { + switch (element_type) + { + case 0x01: // double + { + double number; + return get_number(input_format_t::bson, number) and sax->number_float(static_cast(number), ""); + } + + case 0x02: // string + { + std::int32_t len; + string_t value; + return get_number(input_format_t::bson, len) and get_bson_string(len, value) and sax->string(value); + } + + case 0x03: // object + { + return parse_bson_internal(); + } + + case 0x04: // array + { + return parse_bson_array(); + } + + case 0x08: // boolean + { + return sax->boolean(get() != 0); + } + + case 0x0A: // null + { + return sax->null(); + } + + case 0x10: // int32 + { + std::int32_t value; + return get_number(input_format_t::bson, value) and sax->number_integer(value); + } + + case 0x12: // int64 + { + std::int64_t value; + return get_number(input_format_t::bson, value) and sax->number_integer(value); + } + + default: // anything else not supported (yet) + { + std::array cr{{}}; + (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(element_type)); + return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()))); + } + } + } + + /*! + @brief Read a BSON element list (as specified in the BSON-spec) + + The same binary layout is used for objects and arrays, hence it must be + indicated with the argument @a is_array which one is expected + (true --> array, false --> object). + + @param[in] is_array Determines if the element list being read is to be + treated as an object (@a is_array == false), or as an + array (@a is_array == true). + @return whether a valid BSON-object/array was passed to the SAX parser + */ + bool parse_bson_element_list(const bool is_array) + { + string_t key; + while (int element_type = get()) + { + if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::bson, "element list"))) + { + return false; + } + + const std::size_t element_type_parse_position = chars_read; + if (JSON_HEDLEY_UNLIKELY(not get_bson_cstr(key))) + { + return false; + } + + if (not is_array and not sax->key(key)) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(not parse_bson_element_internal(element_type, element_type_parse_position))) + { + return false; + } + + // get_bson_cstr only appends + key.clear(); + } + + return true; + } + + /*! + @brief Reads an array from the BSON input and passes it to the SAX-parser. + @return whether a valid BSON-array was passed to the SAX parser + */ + bool parse_bson_array() + { + std::int32_t document_size; + get_number(input_format_t::bson, document_size); + + if (JSON_HEDLEY_UNLIKELY(not sax->start_array(std::size_t(-1)))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(not parse_bson_element_list(/*is_array*/true))) + { + return false; + } + + return sax->end_array(); + } + + ////////// + // CBOR // + ////////// + + /*! + @param[in] get_char whether a new character should be retrieved from the + input (true, default) or whether the last read + character should be considered instead + + @return whether a valid CBOR value was passed to the SAX parser + */ + bool parse_cbor_internal(const bool get_char = true) + { + switch (get_char ? get() : current) + { + // EOF + case std::char_traits::eof(): + return unexpect_eof(input_format_t::cbor, "value"); + + // Integer 0x00..0x17 (0..23) + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + return sax->number_unsigned(static_cast(current)); + + case 0x18: // Unsigned integer (one-byte uint8_t follows) + { + std::uint8_t number; + return get_number(input_format_t::cbor, number) and sax->number_unsigned(number); + } + + case 0x19: // Unsigned integer (two-byte uint16_t follows) + { + std::uint16_t number; + return get_number(input_format_t::cbor, number) and sax->number_unsigned(number); + } + + case 0x1A: // Unsigned integer (four-byte uint32_t follows) + { + std::uint32_t number; + return get_number(input_format_t::cbor, number) and sax->number_unsigned(number); + } + + case 0x1B: // Unsigned integer (eight-byte uint64_t follows) + { + std::uint64_t number; + return get_number(input_format_t::cbor, number) and sax->number_unsigned(number); + } + + // Negative integer -1-0x00..-1-0x17 (-1..-24) + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + return sax->number_integer(static_cast(0x20 - 1 - current)); + + case 0x38: // Negative integer (one-byte uint8_t follows) + { + std::uint8_t number; + return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast(-1) - number); + } + + case 0x39: // Negative integer -1-n (two-byte uint16_t follows) + { + std::uint16_t number; + return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast(-1) - number); + } + + case 0x3A: // Negative integer -1-n (four-byte uint32_t follows) + { + std::uint32_t number; + return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast(-1) - number); + } + + case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows) + { + std::uint64_t number; + return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast(-1) + - static_cast(number)); + } + + // UTF-8 string (0x00..0x17 bytes follow) + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: // UTF-8 string (one-byte uint8_t for n follows) + case 0x79: // UTF-8 string (two-byte uint16_t for n follow) + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) + case 0x7F: // UTF-8 string (indefinite length) + { + string_t s; + return get_cbor_string(s) and sax->string(s); + } + + // array (0x00..0x17 data items follow) + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + return get_cbor_array(static_cast(static_cast(current) & 0x1Fu)); + + case 0x98: // array (one-byte uint8_t for n follows) + { + std::uint8_t len; + return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast(len)); + } + + case 0x99: // array (two-byte uint16_t for n follow) + { + std::uint16_t len; + return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast(len)); + } + + case 0x9A: // array (four-byte uint32_t for n follow) + { + std::uint32_t len; + return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast(len)); + } + + case 0x9B: // array (eight-byte uint64_t for n follow) + { + std::uint64_t len; + return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast(len)); + } + + case 0x9F: // array (indefinite length) + return get_cbor_array(std::size_t(-1)); + + // map (0x00..0x17 pairs of data items follow) + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + return get_cbor_object(static_cast(static_cast(current) & 0x1Fu)); + + case 0xB8: // map (one-byte uint8_t for n follows) + { + std::uint8_t len; + return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast(len)); + } + + case 0xB9: // map (two-byte uint16_t for n follow) + { + std::uint16_t len; + return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast(len)); + } + + case 0xBA: // map (four-byte uint32_t for n follow) + { + std::uint32_t len; + return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast(len)); + } + + case 0xBB: // map (eight-byte uint64_t for n follow) + { + std::uint64_t len; + return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast(len)); + } + + case 0xBF: // map (indefinite length) + return get_cbor_object(std::size_t(-1)); + + case 0xF4: // false + return sax->boolean(false); + + case 0xF5: // true + return sax->boolean(true); + + case 0xF6: // null + return sax->null(); + + case 0xF9: // Half-Precision Float (two-byte IEEE 754) + { + const int byte1_raw = get(); + if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number"))) + { + return false; + } + const int byte2_raw = get(); + if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::cbor, "number"))) + { + return false; + } + + const auto byte1 = static_cast(byte1_raw); + const auto byte2 = static_cast(byte2_raw); + + // code from RFC 7049, Appendix D, Figure 3: + // As half-precision floating-point numbers were only added + // to IEEE 754 in 2008, today's programming platforms often + // still only have limited support for them. It is very + // easy to include at least decoding support for them even + // without such support. An example of a small decoder for + // half-precision floating-point numbers in the C language + // is shown in Fig. 3. + const auto half = static_cast((byte1 << 8u) + byte2); + const double val = [&half] + { + const int exp = (half >> 10u) & 0x1Fu; + const unsigned int mant = half & 0x3FFu; + assert(0 <= exp and exp <= 32); + assert(mant <= 1024); + switch (exp) + { + case 0: + return std::ldexp(mant, -24); + case 31: + return (mant == 0) + ? std::numeric_limits::infinity() + : std::numeric_limits::quiet_NaN(); + default: + return std::ldexp(mant + 1024, exp - 25); + } + }(); + return sax->number_float((half & 0x8000u) != 0 + ? static_cast(-val) + : static_cast(val), ""); + } + + case 0xFA: // Single-Precision Float (four-byte IEEE 754) + { + float number; + return get_number(input_format_t::cbor, number) and sax->number_float(static_cast(number), ""); + } + + case 0xFB: // Double-Precision Float (eight-byte IEEE 754) + { + double number; + return get_number(input_format_t::cbor, number) and sax->number_float(static_cast(number), ""); + } + + default: // anything else (0xFF is handled inside the other types) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"))); + } + } + } + + /*! + @brief reads a CBOR string + + This function first reads starting bytes to determine the expected + string length and then copies this number of bytes into a string. + Additionally, CBOR's strings with indefinite lengths are supported. + + @param[out] result created string + + @return whether string creation completed + */ + bool get_cbor_string(string_t& result) + { + if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::cbor, "string"))) + { + return false; + } + + switch (current) + { + // UTF-8 string (0x00..0x17 bytes follow) + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + { + return get_string(input_format_t::cbor, static_cast(current) & 0x1Fu, result); + } + + case 0x78: // UTF-8 string (one-byte uint8_t for n follows) + { + std::uint8_t len; + return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result); + } + + case 0x79: // UTF-8 string (two-byte uint16_t for n follow) + { + std::uint16_t len; + return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result); + } + + case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) + { + std::uint32_t len; + return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result); + } + + case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) + { + std::uint64_t len; + return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result); + } + + case 0x7F: // UTF-8 string (indefinite length) + { + while (get() != 0xFF) + { + string_t chunk; + if (not get_cbor_string(chunk)) + { + return false; + } + result.append(chunk); + } + return true; + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"))); + } + } + } + + /*! + @param[in] len the length of the array or std::size_t(-1) for an + array of indefinite size + @return whether array creation completed + */ + bool get_cbor_array(const std::size_t len) + { + if (JSON_HEDLEY_UNLIKELY(not sax->start_array(len))) + { + return false; + } + + if (len != std::size_t(-1)) + { + for (std::size_t i = 0; i < len; ++i) + { + if (JSON_HEDLEY_UNLIKELY(not parse_cbor_internal())) + { + return false; + } + } + } + else + { + while (get() != 0xFF) + { + if (JSON_HEDLEY_UNLIKELY(not parse_cbor_internal(false))) + { + return false; + } + } + } + + return sax->end_array(); + } + + /*! + @param[in] len the length of the object or std::size_t(-1) for an + object of indefinite size + @return whether object creation completed + */ + bool get_cbor_object(const std::size_t len) + { + if (JSON_HEDLEY_UNLIKELY(not sax->start_object(len))) + { + return false; + } + + string_t key; + if (len != std::size_t(-1)) + { + for (std::size_t i = 0; i < len; ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(not get_cbor_string(key) or not sax->key(key))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(not parse_cbor_internal())) + { + return false; + } + key.clear(); + } + } + else + { + while (get() != 0xFF) + { + if (JSON_HEDLEY_UNLIKELY(not get_cbor_string(key) or not sax->key(key))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(not parse_cbor_internal())) + { + return false; + } + key.clear(); + } + } + + return sax->end_object(); + } + + ///////////// + // MsgPack // + ///////////// + + /*! + @return whether a valid MessagePack value was passed to the SAX parser + */ + bool parse_msgpack_internal() + { + switch (get()) + { + // EOF + case std::char_traits::eof(): + return unexpect_eof(input_format_t::msgpack, "value"); + + // positive fixint + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + case 0x07: + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + case 0x16: + case 0x17: + case 0x18: + case 0x19: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x1F: + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5C: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: + return sax->number_unsigned(static_cast(current)); + + // fixmap + case 0x80: + case 0x81: + case 0x82: + case 0x83: + case 0x84: + case 0x85: + case 0x86: + case 0x87: + case 0x88: + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + case 0x8F: + return get_msgpack_object(static_cast(static_cast(current) & 0x0Fu)); + + // fixarray + case 0x90: + case 0x91: + case 0x92: + case 0x93: + case 0x94: + case 0x95: + case 0x96: + case 0x97: + case 0x98: + case 0x99: + case 0x9A: + case 0x9B: + case 0x9C: + case 0x9D: + case 0x9E: + case 0x9F: + return get_msgpack_array(static_cast(static_cast(current) & 0x0Fu)); + + // fixstr + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + case 0xD9: // str 8 + case 0xDA: // str 16 + case 0xDB: // str 32 + { + string_t s; + return get_msgpack_string(s) and sax->string(s); + } + + case 0xC0: // nil + return sax->null(); + + case 0xC2: // false + return sax->boolean(false); + + case 0xC3: // true + return sax->boolean(true); + + case 0xCA: // float 32 + { + float number; + return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast(number), ""); + } + + case 0xCB: // float 64 + { + double number; + return get_number(input_format_t::msgpack, number) and sax->number_float(static_cast(number), ""); + } + + case 0xCC: // uint 8 + { + std::uint8_t number; + return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number); + } + + case 0xCD: // uint 16 + { + std::uint16_t number; + return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number); + } + + case 0xCE: // uint 32 + { + std::uint32_t number; + return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number); + } + + case 0xCF: // uint 64 + { + std::uint64_t number; + return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number); + } + + case 0xD0: // int 8 + { + std::int8_t number; + return get_number(input_format_t::msgpack, number) and sax->number_integer(number); + } + + case 0xD1: // int 16 + { + std::int16_t number; + return get_number(input_format_t::msgpack, number) and sax->number_integer(number); + } + + case 0xD2: // int 32 + { + std::int32_t number; + return get_number(input_format_t::msgpack, number) and sax->number_integer(number); + } + + case 0xD3: // int 64 + { + std::int64_t number; + return get_number(input_format_t::msgpack, number) and sax->number_integer(number); + } + + case 0xDC: // array 16 + { + std::uint16_t len; + return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast(len)); + } + + case 0xDD: // array 32 + { + std::uint32_t len; + return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast(len)); + } + + case 0xDE: // map 16 + { + std::uint16_t len; + return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast(len)); + } + + case 0xDF: // map 32 + { + std::uint32_t len; + return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast(len)); + } + + // negative fixint + case 0xE0: + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xED: + case 0xEE: + case 0xEF: + case 0xF0: + case 0xF1: + case 0xF2: + case 0xF3: + case 0xF4: + case 0xF5: + case 0xF6: + case 0xF7: + case 0xF8: + case 0xF9: + case 0xFA: + case 0xFB: + case 0xFC: + case 0xFD: + case 0xFE: + case 0xFF: + return sax->number_integer(static_cast(current)); + + default: // anything else + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"))); + } + } + } + + /*! + @brief reads a MessagePack string + + This function first reads starting bytes to determine the expected + string length and then copies this number of bytes into a string. + + @param[out] result created string + + @return whether string creation completed + */ + bool get_msgpack_string(string_t& result) + { + if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::msgpack, "string"))) + { + return false; + } + + switch (current) + { + // fixstr + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + case 0xA8: + case 0xA9: + case 0xAA: + case 0xAB: + case 0xAC: + case 0xAD: + case 0xAE: + case 0xAF: + case 0xB0: + case 0xB1: + case 0xB2: + case 0xB3: + case 0xB4: + case 0xB5: + case 0xB6: + case 0xB7: + case 0xB8: + case 0xB9: + case 0xBA: + case 0xBB: + case 0xBC: + case 0xBD: + case 0xBE: + case 0xBF: + { + return get_string(input_format_t::msgpack, static_cast(current) & 0x1Fu, result); + } + + case 0xD9: // str 8 + { + std::uint8_t len; + return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result); + } + + case 0xDA: // str 16 + { + std::uint16_t len; + return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result); + } + + case 0xDB: // str 32 + { + std::uint32_t len; + return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result); + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"))); + } + } + } + + /*! + @param[in] len the length of the array + @return whether array creation completed + */ + bool get_msgpack_array(const std::size_t len) + { + if (JSON_HEDLEY_UNLIKELY(not sax->start_array(len))) + { + return false; + } + + for (std::size_t i = 0; i < len; ++i) + { + if (JSON_HEDLEY_UNLIKELY(not parse_msgpack_internal())) + { + return false; + } + } + + return sax->end_array(); + } + + /*! + @param[in] len the length of the object + @return whether object creation completed + */ + bool get_msgpack_object(const std::size_t len) + { + if (JSON_HEDLEY_UNLIKELY(not sax->start_object(len))) + { + return false; + } + + string_t key; + for (std::size_t i = 0; i < len; ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(not get_msgpack_string(key) or not sax->key(key))) + { + return false; + } + + if (JSON_HEDLEY_UNLIKELY(not parse_msgpack_internal())) + { + return false; + } + key.clear(); + } + + return sax->end_object(); + } + + //////////// + // UBJSON // + //////////// + + /*! + @param[in] get_char whether a new character should be retrieved from the + input (true, default) or whether the last read + character should be considered instead + + @return whether a valid UBJSON value was passed to the SAX parser + */ + bool parse_ubjson_internal(const bool get_char = true) + { + return get_ubjson_value(get_char ? get_ignore_noop() : current); + } + + /*! + @brief reads a UBJSON string + + This function is either called after reading the 'S' byte explicitly + indicating a string, or in case of an object key where the 'S' byte can be + left out. + + @param[out] result created string + @param[in] get_char whether a new character should be retrieved from the + input (true, default) or whether the last read + character should be considered instead + + @return whether string creation completed + */ + bool get_ubjson_string(string_t& result, const bool get_char = true) + { + if (get_char) + { + get(); // TODO(niels): may we ignore N here? + } + + if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value"))) + { + return false; + } + + switch (current) + { + case 'U': + { + std::uint8_t len; + return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result); + } + + case 'i': + { + std::int8_t len; + return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result); + } + + case 'I': + { + std::int16_t len; + return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result); + } + + case 'l': + { + std::int32_t len; + return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result); + } + + case 'L': + { + std::int64_t len; + return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result); + } + + default: + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"))); + } + } + + /*! + @param[out] result determined size + @return whether size determination completed + */ + bool get_ubjson_size_value(std::size_t& result) + { + switch (get_ignore_noop()) + { + case 'U': + { + std::uint8_t number; + if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + case 'i': + { + std::int8_t number; + if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + case 'I': + { + std::int16_t number; + if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + case 'l': + { + std::int32_t number; + if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + case 'L': + { + std::int64_t number; + if (JSON_HEDLEY_UNLIKELY(not get_number(input_format_t::ubjson, number))) + { + return false; + } + result = static_cast(number); + return true; + } + + default: + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"))); + } + } + } + + /*! + @brief determine the type and size for a container + + In the optimized UBJSON format, a type and a size can be provided to allow + for a more compact representation. + + @param[out] result pair of the size and the type + + @return whether pair creation completed + */ + bool get_ubjson_size_type(std::pair& result) + { + result.first = string_t::npos; // size + result.second = 0; // type + + get_ignore_noop(); + + if (current == '$') + { + result.second = get(); // must not ignore 'N', because 'N' maybe the type + if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "type"))) + { + return false; + } + + get_ignore_noop(); + if (JSON_HEDLEY_UNLIKELY(current != '#')) + { + if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value"))) + { + return false; + } + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"))); + } + + return get_ubjson_size_value(result.first); + } + + if (current == '#') + { + return get_ubjson_size_value(result.first); + } + + return true; + } + + /*! + @param prefix the previously read or set type prefix + @return whether value creation completed + */ + bool get_ubjson_value(const int prefix) + { + switch (prefix) + { + case std::char_traits::eof(): // EOF + return unexpect_eof(input_format_t::ubjson, "value"); + + case 'T': // true + return sax->boolean(true); + case 'F': // false + return sax->boolean(false); + + case 'Z': // null + return sax->null(); + + case 'U': + { + std::uint8_t number; + return get_number(input_format_t::ubjson, number) and sax->number_unsigned(number); + } + + case 'i': + { + std::int8_t number; + return get_number(input_format_t::ubjson, number) and sax->number_integer(number); + } + + case 'I': + { + std::int16_t number; + return get_number(input_format_t::ubjson, number) and sax->number_integer(number); + } + + case 'l': + { + std::int32_t number; + return get_number(input_format_t::ubjson, number) and sax->number_integer(number); + } + + case 'L': + { + std::int64_t number; + return get_number(input_format_t::ubjson, number) and sax->number_integer(number); + } + + case 'd': + { + float number; + return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast(number), ""); + } + + case 'D': + { + double number; + return get_number(input_format_t::ubjson, number) and sax->number_float(static_cast(number), ""); + } + + case 'C': // char + { + get(); + if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "char"))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(current > 127)) + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"))); + } + string_t s(1, static_cast(current)); + return sax->string(s); + } + + case 'S': // string + { + string_t s; + return get_ubjson_string(s) and sax->string(s); + } + + case '[': // array + return get_ubjson_array(); + + case '{': // object + return get_ubjson_object(); + + default: // anything else + { + auto last_token = get_token_string(); + return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"))); + } + } + } + + /*! + @return whether array creation completed + */ + bool get_ubjson_array() + { + std::pair size_and_type; + if (JSON_HEDLEY_UNLIKELY(not get_ubjson_size_type(size_and_type))) + { + return false; + } + + if (size_and_type.first != string_t::npos) + { + if (JSON_HEDLEY_UNLIKELY(not sax->start_array(size_and_type.first))) + { + return false; + } + + if (size_and_type.second != 0) + { + if (size_and_type.second != 'N') + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(not get_ubjson_value(size_and_type.second))) + { + return false; + } + } + } + } + else + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(not parse_ubjson_internal())) + { + return false; + } + } + } + } + else + { + if (JSON_HEDLEY_UNLIKELY(not sax->start_array(std::size_t(-1)))) + { + return false; + } + + while (current != ']') + { + if (JSON_HEDLEY_UNLIKELY(not parse_ubjson_internal(false))) + { + return false; + } + get_ignore_noop(); + } + } + + return sax->end_array(); + } + + /*! + @return whether object creation completed + */ + bool get_ubjson_object() + { + std::pair size_and_type; + if (JSON_HEDLEY_UNLIKELY(not get_ubjson_size_type(size_and_type))) + { + return false; + } + + string_t key; + if (size_and_type.first != string_t::npos) + { + if (JSON_HEDLEY_UNLIKELY(not sax->start_object(size_and_type.first))) + { + return false; + } + + if (size_and_type.second != 0) + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(not get_ubjson_string(key) or not sax->key(key))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(not get_ubjson_value(size_and_type.second))) + { + return false; + } + key.clear(); + } + } + else + { + for (std::size_t i = 0; i < size_and_type.first; ++i) + { + if (JSON_HEDLEY_UNLIKELY(not get_ubjson_string(key) or not sax->key(key))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(not parse_ubjson_internal())) + { + return false; + } + key.clear(); + } + } + } + else + { + if (JSON_HEDLEY_UNLIKELY(not sax->start_object(std::size_t(-1)))) + { + return false; + } + + while (current != '}') + { + if (JSON_HEDLEY_UNLIKELY(not get_ubjson_string(key, false) or not sax->key(key))) + { + return false; + } + if (JSON_HEDLEY_UNLIKELY(not parse_ubjson_internal())) + { + return false; + } + get_ignore_noop(); + key.clear(); + } + } + + return sax->end_object(); + } + + /////////////////////// + // Utility functions // + /////////////////////// + + /*! + @brief get next character from the input + + This function provides the interface to the used input adapter. It does + not throw in case the input reached EOF, but returns a -'ve valued + `std::char_traits::eof()` in that case. + + @return character read from the input + */ + int get() + { + ++chars_read; + return current = ia->get_character(); + } + + /*! + @return character read from the input after ignoring all 'N' entries + */ + int get_ignore_noop() + { + do + { + get(); + } + while (current == 'N'); + + return current; + } + + /* + @brief read a number from the input + + @tparam NumberType the type of the number + @param[in] format the current format (for diagnostics) + @param[out] result number of type @a NumberType + + @return whether conversion completed + + @note This function needs to respect the system's endianess, because + bytes in CBOR, MessagePack, and UBJSON are stored in network order + (big endian) and therefore need reordering on little endian systems. + */ + template + bool get_number(const input_format_t format, NumberType& result) + { + // step 1: read input into array with system's byte order + std::array vec; + for (std::size_t i = 0; i < sizeof(NumberType); ++i) + { + get(); + if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(format, "number"))) + { + return false; + } + + // reverse byte order prior to conversion if necessary + if (is_little_endian != InputIsLittleEndian) + { + vec[sizeof(NumberType) - i - 1] = static_cast(current); + } + else + { + vec[i] = static_cast(current); // LCOV_EXCL_LINE + } + } + + // step 2: convert array into number of type T and return + std::memcpy(&result, vec.data(), sizeof(NumberType)); + return true; + } + + /*! + @brief create a string by reading characters from the input + + @tparam NumberType the type of the number + @param[in] format the current format (for diagnostics) + @param[in] len number of characters to read + @param[out] result string created by reading @a len bytes + + @return whether string creation completed + + @note We can not reserve @a len bytes for the result, because @a len + may be too large. Usually, @ref unexpect_eof() detects the end of + the input before we run out of string memory. + */ + template + bool get_string(const input_format_t format, + const NumberType len, + string_t& result) + { + bool success = true; + std::generate_n(std::back_inserter(result), len, [this, &success, &format]() + { + get(); + if (JSON_HEDLEY_UNLIKELY(not unexpect_eof(format, "string"))) + { + success = false; + } + return static_cast(current); + }); + return success; + } + + /*! + @param[in] format the current format (for diagnostics) + @param[in] context further context information (for diagnostics) + @return whether the last read character is not EOF + */ + JSON_HEDLEY_NON_NULL(3) + bool unexpect_eof(const input_format_t format, const char* context) const + { + if (JSON_HEDLEY_UNLIKELY(current == std::char_traits::eof())) + { + return sax->parse_error(chars_read, "", + parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context))); + } + return true; + } + + /*! + @return a string representation of the last read byte + */ + std::string get_token_string() const + { + std::array cr{{}}; + (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(current)); + return std::string{cr.data()}; + } + + /*! + @param[in] format the current format + @param[in] detail a detailed error message + @param[in] context further context information + @return a message string to use in the parse_error exceptions + */ + std::string exception_message(const input_format_t format, + const std::string& detail, + const std::string& context) const + { + std::string error_msg = "syntax error while parsing "; + + switch (format) + { + case input_format_t::cbor: + error_msg += "CBOR"; + break; + + case input_format_t::msgpack: + error_msg += "MessagePack"; + break; + + case input_format_t::ubjson: + error_msg += "UBJSON"; + break; + + case input_format_t::bson: + error_msg += "BSON"; + break; + + default: // LCOV_EXCL_LINE + assert(false); // LCOV_EXCL_LINE + } + + return error_msg + " " + context + ": " + detail; + } + + private: + /// input adapter + input_adapter_t ia = nullptr; + + /// the current character + int current = std::char_traits::eof(); + + /// the number of characters read + std::size_t chars_read = 0; + + /// whether we can assume little endianess + const bool is_little_endian = little_endianess(); + + /// the SAX parser + json_sax_t* sax = nullptr; +}; +} // namespace detail +} // namespace nlohmann diff --git a/thirdparty/nlohmann/detail/input/input_adapters.hpp b/thirdparty/nlohmann/detail/input/input_adapters.hpp new file mode 100644 index 00000000000..9512a771eef --- /dev/null +++ b/thirdparty/nlohmann/detail/input/input_adapters.hpp @@ -0,0 +1,442 @@ +#pragma once + +#include // array +#include // assert +#include // size_t +#include //FILE * +#include // strlen +#include // istream +#include // begin, end, iterator_traits, random_access_iterator_tag, distance, next +#include // shared_ptr, make_shared, addressof +#include // accumulate +#include // string, char_traits +#include // enable_if, is_base_of, is_pointer, is_integral, remove_pointer +#include // pair, declval + +#include +#include + +namespace nlohmann +{ +namespace detail +{ +/// the supported input formats +enum class input_format_t { json, cbor, msgpack, ubjson, bson }; + +//////////////////// +// input adapters // +//////////////////// + +/*! +@brief abstract input adapter interface + +Produces a stream of std::char_traits::int_type characters from a +std::istream, a buffer, or some other input type. Accepts the return of +exactly one non-EOF character for future input. The int_type characters +returned consist of all valid char values as positive values (typically +unsigned char), plus an EOF value outside that range, specified by the value +of the function std::char_traits::eof(). This value is typically -1, but +could be any arbitrary value which is not a valid char value. +*/ +struct input_adapter_protocol +{ + /// get a character [0,255] or std::char_traits::eof(). + virtual std::char_traits::int_type get_character() = 0; + virtual ~input_adapter_protocol() = default; +}; + +/// a type to simplify interfaces +using input_adapter_t = std::shared_ptr; + +/*! +Input adapter for stdio file access. This adapter read only 1 byte and do not use any + buffer. This adapter is a very low level adapter. +*/ +class file_input_adapter : public input_adapter_protocol +{ + public: + JSON_HEDLEY_NON_NULL(2) + explicit file_input_adapter(std::FILE* f) noexcept + : m_file(f) + {} + + // make class move-only + file_input_adapter(const file_input_adapter&) = delete; + file_input_adapter(file_input_adapter&&) = default; + file_input_adapter& operator=(const file_input_adapter&) = delete; + file_input_adapter& operator=(file_input_adapter&&) = default; + ~file_input_adapter() override = default; + + std::char_traits::int_type get_character() noexcept override + { + return std::fgetc(m_file); + } + + private: + /// the file pointer to read from + std::FILE* m_file; +}; + + +/*! +Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at +beginning of input. Does not support changing the underlying std::streambuf +in mid-input. Maintains underlying std::istream and std::streambuf to support +subsequent use of standard std::istream operations to process any input +characters following those used in parsing the JSON input. Clears the +std::istream flags; any input errors (e.g., EOF) will be detected by the first +subsequent call for input from the std::istream. +*/ +class input_stream_adapter : public input_adapter_protocol +{ + public: + ~input_stream_adapter() override + { + // clear stream flags; we use underlying streambuf I/O, do not + // maintain ifstream flags, except eof + is.clear(is.rdstate() & std::ios::eofbit); + } + + explicit input_stream_adapter(std::istream& i) + : is(i), sb(*i.rdbuf()) + {} + + // delete because of pointer members + input_stream_adapter(const input_stream_adapter&) = delete; + input_stream_adapter& operator=(input_stream_adapter&) = delete; + input_stream_adapter(input_stream_adapter&&) = delete; + input_stream_adapter& operator=(input_stream_adapter&&) = delete; + + // std::istream/std::streambuf use std::char_traits::to_int_type, to + // ensure that std::char_traits::eof() and the character 0xFF do not + // end up as the same value, eg. 0xFFFFFFFF. + std::char_traits::int_type get_character() override + { + auto res = sb.sbumpc(); + // set eof manually, as we don't use the istream interface. + if (res == EOF) + { + is.clear(is.rdstate() | std::ios::eofbit); + } + return res; + } + + private: + /// the associated input stream + std::istream& is; + std::streambuf& sb; +}; + +/// input adapter for buffer input +class input_buffer_adapter : public input_adapter_protocol +{ + public: + input_buffer_adapter(const char* b, const std::size_t l) noexcept + : cursor(b), limit(b == nullptr ? nullptr : (b + l)) + {} + + // delete because of pointer members + input_buffer_adapter(const input_buffer_adapter&) = delete; + input_buffer_adapter& operator=(input_buffer_adapter&) = delete; + input_buffer_adapter(input_buffer_adapter&&) = delete; + input_buffer_adapter& operator=(input_buffer_adapter&&) = delete; + ~input_buffer_adapter() override = default; + + std::char_traits::int_type get_character() noexcept override + { + if (JSON_HEDLEY_LIKELY(cursor < limit)) + { + assert(cursor != nullptr and limit != nullptr); + return std::char_traits::to_int_type(*(cursor++)); + } + + return std::char_traits::eof(); + } + + private: + /// pointer to the current character + const char* cursor; + /// pointer past the last character + const char* const limit; +}; + +template +struct wide_string_input_helper +{ + // UTF-32 + static void fill_buffer(const WideStringType& str, + size_t& current_wchar, + std::array::int_type, 4>& utf8_bytes, + size_t& utf8_bytes_index, + size_t& utf8_bytes_filled) + { + utf8_bytes_index = 0; + + if (current_wchar == str.size()) + { + utf8_bytes[0] = std::char_traits::eof(); + utf8_bytes_filled = 1; + } + else + { + // get the current character + const auto wc = static_cast(str[current_wchar++]); + + // UTF-32 to UTF-8 encoding + if (wc < 0x80) + { + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + else if (wc <= 0x7FF) + { + utf8_bytes[0] = static_cast::int_type>(0xC0u | ((wc >> 6u) & 0x1Fu)); + utf8_bytes[1] = static_cast::int_type>(0x80u | (wc & 0x3Fu)); + utf8_bytes_filled = 2; + } + else if (wc <= 0xFFFF) + { + utf8_bytes[0] = static_cast::int_type>(0xE0u | ((wc >> 12u) & 0x0Fu)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((wc >> 6u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | (wc & 0x3Fu)); + utf8_bytes_filled = 3; + } + else if (wc <= 0x10FFFF) + { + utf8_bytes[0] = static_cast::int_type>(0xF0u | ((wc >> 18u) & 0x07u)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((wc >> 12u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | ((wc >> 6u) & 0x3Fu)); + utf8_bytes[3] = static_cast::int_type>(0x80u | (wc & 0x3Fu)); + utf8_bytes_filled = 4; + } + else + { + // unknown character + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + } + } +}; + +template +struct wide_string_input_helper +{ + // UTF-16 + static void fill_buffer(const WideStringType& str, + size_t& current_wchar, + std::array::int_type, 4>& utf8_bytes, + size_t& utf8_bytes_index, + size_t& utf8_bytes_filled) + { + utf8_bytes_index = 0; + + if (current_wchar == str.size()) + { + utf8_bytes[0] = std::char_traits::eof(); + utf8_bytes_filled = 1; + } + else + { + // get the current character + const auto wc = static_cast(str[current_wchar++]); + + // UTF-16 to UTF-8 encoding + if (wc < 0x80) + { + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + else if (wc <= 0x7FF) + { + utf8_bytes[0] = static_cast::int_type>(0xC0u | ((wc >> 6u))); + utf8_bytes[1] = static_cast::int_type>(0x80u | (wc & 0x3Fu)); + utf8_bytes_filled = 2; + } + else if (0xD800 > wc or wc >= 0xE000) + { + utf8_bytes[0] = static_cast::int_type>(0xE0u | ((wc >> 12u))); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((wc >> 6u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | (wc & 0x3Fu)); + utf8_bytes_filled = 3; + } + else + { + if (current_wchar < str.size()) + { + const auto wc2 = static_cast(str[current_wchar++]); + const auto charcode = 0x10000u + (((wc & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); + utf8_bytes[0] = static_cast::int_type>(0xF0u | (charcode >> 18u)); + utf8_bytes[1] = static_cast::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu)); + utf8_bytes[2] = static_cast::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu)); + utf8_bytes[3] = static_cast::int_type>(0x80u | (charcode & 0x3Fu)); + utf8_bytes_filled = 4; + } + else + { + // unknown character + ++current_wchar; + utf8_bytes[0] = static_cast::int_type>(wc); + utf8_bytes_filled = 1; + } + } + } + } +}; + +template +class wide_string_input_adapter : public input_adapter_protocol +{ + public: + explicit wide_string_input_adapter(const WideStringType& w) noexcept + : str(w) + {} + + std::char_traits::int_type get_character() noexcept override + { + // check if buffer needs to be filled + if (utf8_bytes_index == utf8_bytes_filled) + { + fill_buffer(); + + assert(utf8_bytes_filled > 0); + assert(utf8_bytes_index == 0); + } + + // use buffer + assert(utf8_bytes_filled > 0); + assert(utf8_bytes_index < utf8_bytes_filled); + return utf8_bytes[utf8_bytes_index++]; + } + + private: + template + void fill_buffer() + { + wide_string_input_helper::fill_buffer(str, current_wchar, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); + } + + /// the wstring to process + const WideStringType& str; + + /// index of the current wchar in str + std::size_t current_wchar = 0; + + /// a buffer for UTF-8 bytes + std::array::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; + + /// index to the utf8_codes array for the next valid byte + std::size_t utf8_bytes_index = 0; + /// number of valid bytes in the utf8_codes array + std::size_t utf8_bytes_filled = 0; +}; + +class input_adapter +{ + public: + // native support + JSON_HEDLEY_NON_NULL(2) + input_adapter(std::FILE* file) + : ia(std::make_shared(file)) {} + /// input adapter for input stream + input_adapter(std::istream& i) + : ia(std::make_shared(i)) {} + + /// input adapter for input stream + input_adapter(std::istream&& i) + : ia(std::make_shared(i)) {} + + input_adapter(const std::wstring& ws) + : ia(std::make_shared>(ws)) {} + + input_adapter(const std::u16string& ws) + : ia(std::make_shared>(ws)) {} + + input_adapter(const std::u32string& ws) + : ia(std::make_shared>(ws)) {} + + /// input adapter for buffer + template::value and + std::is_integral::type>::value and + sizeof(typename std::remove_pointer::type) == 1, + int>::type = 0> + input_adapter(CharT b, std::size_t l) + : ia(std::make_shared(reinterpret_cast(b), l)) {} + + // derived support + + /// input adapter for string literal + template::value and + std::is_integral::type>::value and + sizeof(typename std::remove_pointer::type) == 1, + int>::type = 0> + input_adapter(CharT b) + : input_adapter(reinterpret_cast(b), + std::strlen(reinterpret_cast(b))) {} + + /// input adapter for iterator range with contiguous storage + template::iterator_category, std::random_access_iterator_tag>::value, + int>::type = 0> + input_adapter(IteratorType first, IteratorType last) + { +#ifndef NDEBUG + // assertion to check that the iterator range is indeed contiguous, + // see http://stackoverflow.com/a/35008842/266378 for more discussion + const auto is_contiguous = std::accumulate( + first, last, std::pair(true, 0), + [&first](std::pair res, decltype(*first) val) + { + res.first &= (val == *(std::next(std::addressof(*first), res.second++))); + return res; + }).first; + assert(is_contiguous); +#endif + + // assertion to check that each element is 1 byte long + static_assert( + sizeof(typename iterator_traits::value_type) == 1, + "each element in the iterator range must have the size of 1 byte"); + + const auto len = static_cast(std::distance(first, last)); + if (JSON_HEDLEY_LIKELY(len > 0)) + { + // there is at least one element: use the address of first + ia = std::make_shared(reinterpret_cast(&(*first)), len); + } + else + { + // the address of first cannot be used: use nullptr + ia = std::make_shared(nullptr, len); + } + } + + /// input adapter for array + template + input_adapter(T (&array)[N]) + : input_adapter(std::begin(array), std::end(array)) {} + + /// input adapter for contiguous container + template::value and + std::is_base_of()))>::iterator_category>::value, + int>::type = 0> + input_adapter(const ContiguousContainer& c) + : input_adapter(std::begin(c), std::end(c)) {} + + operator input_adapter_t() + { + return ia; + } + + private: + /// the actual adapter + input_adapter_t ia = nullptr; +}; +} // namespace detail +} // namespace nlohmann diff --git a/thirdparty/nlohmann/detail/input/json_sax.hpp b/thirdparty/nlohmann/detail/input/json_sax.hpp new file mode 100644 index 00000000000..606b7862ebd --- /dev/null +++ b/thirdparty/nlohmann/detail/input/json_sax.hpp @@ -0,0 +1,701 @@ +#pragma once + +#include // assert +#include +#include // string +#include // move +#include // vector + +#include +#include + +namespace nlohmann +{ + +/*! +@brief SAX interface + +This class describes the SAX interface used by @ref nlohmann::json::sax_parse. +Each function is called in different situations while the input is parsed. The +boolean return value informs the parser whether to continue processing the +input. +*/ +template +struct json_sax +{ + /// type for (signed) integers + using number_integer_t = typename BasicJsonType::number_integer_t; + /// type for unsigned integers + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + /// type for floating-point numbers + using number_float_t = typename BasicJsonType::number_float_t; + /// type for strings + using string_t = typename BasicJsonType::string_t; + + /*! + @brief a null value was read + @return whether parsing should proceed + */ + virtual bool null() = 0; + + /*! + @brief a boolean value was read + @param[in] val boolean value + @return whether parsing should proceed + */ + virtual bool boolean(bool val) = 0; + + /*! + @brief an integer number was read + @param[in] val integer value + @return whether parsing should proceed + */ + virtual bool number_integer(number_integer_t val) = 0; + + /*! + @brief an unsigned integer number was read + @param[in] val unsigned integer value + @return whether parsing should proceed + */ + virtual bool number_unsigned(number_unsigned_t val) = 0; + + /*! + @brief an floating-point number was read + @param[in] val floating-point value + @param[in] s raw token value + @return whether parsing should proceed + */ + virtual bool number_float(number_float_t val, const string_t& s) = 0; + + /*! + @brief a string was read + @param[in] val string value + @return whether parsing should proceed + @note It is safe to move the passed string. + */ + virtual bool string(string_t& val) = 0; + + /*! + @brief the beginning of an object was read + @param[in] elements number of object elements or -1 if unknown + @return whether parsing should proceed + @note binary formats may report the number of elements + */ + virtual bool start_object(std::size_t elements) = 0; + + /*! + @brief an object key was read + @param[in] val object key + @return whether parsing should proceed + @note It is safe to move the passed string. + */ + virtual bool key(string_t& val) = 0; + + /*! + @brief the end of an object was read + @return whether parsing should proceed + */ + virtual bool end_object() = 0; + + /*! + @brief the beginning of an array was read + @param[in] elements number of array elements or -1 if unknown + @return whether parsing should proceed + @note binary formats may report the number of elements + */ + virtual bool start_array(std::size_t elements) = 0; + + /*! + @brief the end of an array was read + @return whether parsing should proceed + */ + virtual bool end_array() = 0; + + /*! + @brief a parse error occurred + @param[in] position the position in the input where the error occurs + @param[in] last_token the last read token + @param[in] ex an exception object describing the error + @return whether parsing should proceed (must return false) + */ + virtual bool parse_error(std::size_t position, + const std::string& last_token, + const detail::exception& ex) = 0; + + virtual ~json_sax() = default; +}; + + +namespace detail +{ +/*! +@brief SAX implementation to create a JSON value from SAX events + +This class implements the @ref json_sax interface and processes the SAX events +to create a JSON value which makes it basically a DOM parser. The structure or +hierarchy of the JSON value is managed by the stack `ref_stack` which contains +a pointer to the respective array or object for each recursion depth. + +After successful parsing, the value that is passed by reference to the +constructor contains the parsed value. + +@tparam BasicJsonType the JSON type +*/ +template +class json_sax_dom_parser +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + + /*! + @param[in, out] r reference to a JSON value that is manipulated while + parsing + @param[in] allow_exceptions_ whether parse errors yield exceptions + */ + explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) + : root(r), allow_exceptions(allow_exceptions_) + {} + + // make class move-only + json_sax_dom_parser(const json_sax_dom_parser&) = delete; + json_sax_dom_parser(json_sax_dom_parser&&) = default; + json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete; + json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; + ~json_sax_dom_parser() = default; + + bool null() + { + handle_value(nullptr); + return true; + } + + bool boolean(bool val) + { + handle_value(val); + return true; + } + + bool number_integer(number_integer_t val) + { + handle_value(val); + return true; + } + + bool number_unsigned(number_unsigned_t val) + { + handle_value(val); + return true; + } + + bool number_float(number_float_t val, const string_t& /*unused*/) + { + handle_value(val); + return true; + } + + bool string(string_t& val) + { + handle_value(val); + return true; + } + + bool start_object(std::size_t len) + { + ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); + + if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, + "excessive object size: " + std::to_string(len))); + } + + return true; + } + + bool key(string_t& val) + { + // add null at given key and store the reference for later + object_element = &(ref_stack.back()->m_value.object->operator[](val)); + return true; + } + + bool end_object() + { + ref_stack.pop_back(); + return true; + } + + bool start_array(std::size_t len) + { + ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); + + if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, + "excessive array size: " + std::to_string(len))); + } + + return true; + } + + bool end_array() + { + ref_stack.pop_back(); + return true; + } + + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, + const detail::exception& ex) + { + errored = true; + if (allow_exceptions) + { + // determine the proper exception type from the id + switch ((ex.id / 100) % 100) + { + case 1: + JSON_THROW(*static_cast(&ex)); + case 4: + JSON_THROW(*static_cast(&ex)); + // LCOV_EXCL_START + case 2: + JSON_THROW(*static_cast(&ex)); + case 3: + JSON_THROW(*static_cast(&ex)); + case 5: + JSON_THROW(*static_cast(&ex)); + default: + assert(false); + // LCOV_EXCL_STOP + } + } + return false; + } + + constexpr bool is_errored() const + { + return errored; + } + + private: + /*! + @invariant If the ref stack is empty, then the passed value will be the new + root. + @invariant If the ref stack contains a value, then it is an array or an + object to which we can add elements + */ + template + JSON_HEDLEY_RETURNS_NON_NULL + BasicJsonType* handle_value(Value&& v) + { + if (ref_stack.empty()) + { + root = BasicJsonType(std::forward(v)); + return &root; + } + + assert(ref_stack.back()->is_array() or ref_stack.back()->is_object()); + + if (ref_stack.back()->is_array()) + { + ref_stack.back()->m_value.array->emplace_back(std::forward(v)); + return &(ref_stack.back()->m_value.array->back()); + } + + assert(ref_stack.back()->is_object()); + assert(object_element); + *object_element = BasicJsonType(std::forward(v)); + return object_element; + } + + /// the parsed JSON value + BasicJsonType& root; + /// stack to model hierarchy of values + std::vector ref_stack {}; + /// helper to hold the reference for the next object element + BasicJsonType* object_element = nullptr; + /// whether a syntax error occurred + bool errored = false; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; +}; + +template +class json_sax_dom_callback_parser +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using parser_callback_t = typename BasicJsonType::parser_callback_t; + using parse_event_t = typename BasicJsonType::parse_event_t; + + json_sax_dom_callback_parser(BasicJsonType& r, + const parser_callback_t cb, + const bool allow_exceptions_ = true) + : root(r), callback(cb), allow_exceptions(allow_exceptions_) + { + keep_stack.push_back(true); + } + + // make class move-only + json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete; + json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; + json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete; + json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; + ~json_sax_dom_callback_parser() = default; + + bool null() + { + handle_value(nullptr); + return true; + } + + bool boolean(bool val) + { + handle_value(val); + return true; + } + + bool number_integer(number_integer_t val) + { + handle_value(val); + return true; + } + + bool number_unsigned(number_unsigned_t val) + { + handle_value(val); + return true; + } + + bool number_float(number_float_t val, const string_t& /*unused*/) + { + handle_value(val); + return true; + } + + bool string(string_t& val) + { + handle_value(val); + return true; + } + + bool start_object(std::size_t len) + { + // check callback for object start + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::object_start, discarded); + keep_stack.push_back(keep); + + auto val = handle_value(BasicJsonType::value_t::object, true); + ref_stack.push_back(val.second); + + // check object limit + if (ref_stack.back() and JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len))); + } + + return true; + } + + bool key(string_t& val) + { + BasicJsonType k = BasicJsonType(val); + + // check callback for key + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::key, k); + key_keep_stack.push_back(keep); + + // add discarded value at given key and store the reference for later + if (keep and ref_stack.back()) + { + object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded); + } + + return true; + } + + bool end_object() + { + if (ref_stack.back() and not callback(static_cast(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) + { + // discard object + *ref_stack.back() = discarded; + } + + assert(not ref_stack.empty()); + assert(not keep_stack.empty()); + ref_stack.pop_back(); + keep_stack.pop_back(); + + if (not ref_stack.empty() and ref_stack.back() and ref_stack.back()->is_object()) + { + // remove discarded value + for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) + { + if (it->is_discarded()) + { + ref_stack.back()->erase(it); + break; + } + } + } + + return true; + } + + bool start_array(std::size_t len) + { + const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::array_start, discarded); + keep_stack.push_back(keep); + + auto val = handle_value(BasicJsonType::value_t::array, true); + ref_stack.push_back(val.second); + + // check array limit + if (ref_stack.back() and JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size())) + { + JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len))); + } + + return true; + } + + bool end_array() + { + bool keep = true; + + if (ref_stack.back()) + { + keep = callback(static_cast(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); + if (not keep) + { + // discard array + *ref_stack.back() = discarded; + } + } + + assert(not ref_stack.empty()); + assert(not keep_stack.empty()); + ref_stack.pop_back(); + keep_stack.pop_back(); + + // remove discarded value + if (not keep and not ref_stack.empty() and ref_stack.back()->is_array()) + { + ref_stack.back()->m_value.array->pop_back(); + } + + return true; + } + + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, + const detail::exception& ex) + { + errored = true; + if (allow_exceptions) + { + // determine the proper exception type from the id + switch ((ex.id / 100) % 100) + { + case 1: + JSON_THROW(*static_cast(&ex)); + case 4: + JSON_THROW(*static_cast(&ex)); + // LCOV_EXCL_START + case 2: + JSON_THROW(*static_cast(&ex)); + case 3: + JSON_THROW(*static_cast(&ex)); + case 5: + JSON_THROW(*static_cast(&ex)); + default: + assert(false); + // LCOV_EXCL_STOP + } + } + return false; + } + + constexpr bool is_errored() const + { + return errored; + } + + private: + /*! + @param[in] v value to add to the JSON value we build during parsing + @param[in] skip_callback whether we should skip calling the callback + function; this is required after start_array() and + start_object() SAX events, because otherwise we would call the + callback function with an empty array or object, respectively. + + @invariant If the ref stack is empty, then the passed value will be the new + root. + @invariant If the ref stack contains a value, then it is an array or an + object to which we can add elements + + @return pair of boolean (whether value should be kept) and pointer (to the + passed value in the ref_stack hierarchy; nullptr if not kept) + */ + template + std::pair handle_value(Value&& v, const bool skip_callback = false) + { + assert(not keep_stack.empty()); + + // do not handle this value if we know it would be added to a discarded + // container + if (not keep_stack.back()) + { + return {false, nullptr}; + } + + // create value + auto value = BasicJsonType(std::forward(v)); + + // check callback + const bool keep = skip_callback or callback(static_cast(ref_stack.size()), parse_event_t::value, value); + + // do not handle this value if we just learnt it shall be discarded + if (not keep) + { + return {false, nullptr}; + } + + if (ref_stack.empty()) + { + root = std::move(value); + return {true, &root}; + } + + // skip this value if we already decided to skip the parent + // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) + if (not ref_stack.back()) + { + return {false, nullptr}; + } + + // we now only expect arrays and objects + assert(ref_stack.back()->is_array() or ref_stack.back()->is_object()); + + // array + if (ref_stack.back()->is_array()) + { + ref_stack.back()->m_value.array->push_back(std::move(value)); + return {true, &(ref_stack.back()->m_value.array->back())}; + } + + // object + assert(ref_stack.back()->is_object()); + // check if we should store an element for the current key + assert(not key_keep_stack.empty()); + const bool store_element = key_keep_stack.back(); + key_keep_stack.pop_back(); + + if (not store_element) + { + return {false, nullptr}; + } + + assert(object_element); + *object_element = std::move(value); + return {true, object_element}; + } + + /// the parsed JSON value + BasicJsonType& root; + /// stack to model hierarchy of values + std::vector ref_stack {}; + /// stack to manage which values to keep + std::vector keep_stack {}; + /// stack to manage which object keys to keep + std::vector key_keep_stack {}; + /// helper to hold the reference for the next object element + BasicJsonType* object_element = nullptr; + /// whether a syntax error occurred + bool errored = false; + /// callback function + const parser_callback_t callback = nullptr; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; + /// a discarded value for the callback + BasicJsonType discarded = BasicJsonType::value_t::discarded; +}; + +template +class json_sax_acceptor +{ + public: + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + + bool null() + { + return true; + } + + bool boolean(bool /*unused*/) + { + return true; + } + + bool number_integer(number_integer_t /*unused*/) + { + return true; + } + + bool number_unsigned(number_unsigned_t /*unused*/) + { + return true; + } + + bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) + { + return true; + } + + bool string(string_t& /*unused*/) + { + return true; + } + + bool start_object(std::size_t /*unused*/ = std::size_t(-1)) + { + return true; + } + + bool key(string_t& /*unused*/) + { + return true; + } + + bool end_object() + { + return true; + } + + bool start_array(std::size_t /*unused*/ = std::size_t(-1)) + { + return true; + } + + bool end_array() + { + return true; + } + + bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) + { + return false; + } +}; +} // namespace detail + +} // namespace nlohmann diff --git a/thirdparty/nlohmann/detail/input/lexer.hpp b/thirdparty/nlohmann/detail/input/lexer.hpp new file mode 100644 index 00000000000..0843d749d6a --- /dev/null +++ b/thirdparty/nlohmann/detail/input/lexer.hpp @@ -0,0 +1,1512 @@ +#pragma once + +#include // array +#include // localeconv +#include // size_t +#include // snprintf +#include // strtof, strtod, strtold, strtoll, strtoull +#include // initializer_list +#include // char_traits, string +#include // move +#include // vector + +#include +#include +#include + +namespace nlohmann +{ +namespace detail +{ +/////////// +// lexer // +/////////// + +/*! +@brief lexical analysis + +This class organizes the lexical analysis during JSON deserialization. +*/ +template +class lexer +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + + public: + /// token types for the parser + enum class token_type + { + uninitialized, ///< indicating the scanner is uninitialized + literal_true, ///< the `true` literal + literal_false, ///< the `false` literal + literal_null, ///< the `null` literal + value_string, ///< a string -- use get_string() for actual value + value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value + value_integer, ///< a signed integer -- use get_number_integer() for actual value + value_float, ///< an floating point number -- use get_number_float() for actual value + begin_array, ///< the character for array begin `[` + begin_object, ///< the character for object begin `{` + end_array, ///< the character for array end `]` + end_object, ///< the character for object end `}` + name_separator, ///< the name separator `:` + value_separator, ///< the value separator `,` + parse_error, ///< indicating a parse error + end_of_input, ///< indicating the end of the input buffer + literal_or_value ///< a literal or the begin of a value (only for diagnostics) + }; + + /// return name of values of type token_type (only used for errors) + JSON_HEDLEY_RETURNS_NON_NULL + JSON_HEDLEY_CONST + static const char* token_type_name(const token_type t) noexcept + { + switch (t) + { + case token_type::uninitialized: + return ""; + case token_type::literal_true: + return "true literal"; + case token_type::literal_false: + return "false literal"; + case token_type::literal_null: + return "null literal"; + case token_type::value_string: + return "string literal"; + case lexer::token_type::value_unsigned: + case lexer::token_type::value_integer: + case lexer::token_type::value_float: + return "number literal"; + case token_type::begin_array: + return "'['"; + case token_type::begin_object: + return "'{'"; + case token_type::end_array: + return "']'"; + case token_type::end_object: + return "'}'"; + case token_type::name_separator: + return "':'"; + case token_type::value_separator: + return "','"; + case token_type::parse_error: + return ""; + case token_type::end_of_input: + return "end of input"; + case token_type::literal_or_value: + return "'[', '{', or a literal"; + // LCOV_EXCL_START + default: // catch non-enum values + return "unknown token"; + // LCOV_EXCL_STOP + } + } + + explicit lexer(detail::input_adapter_t&& adapter) + : ia(std::move(adapter)), decimal_point_char(get_decimal_point()) {} + + // delete because of pointer members + lexer(const lexer&) = delete; + lexer(lexer&&) = delete; + lexer& operator=(lexer&) = delete; + lexer& operator=(lexer&&) = delete; + ~lexer() = default; + + private: + ///////////////////// + // locales + ///////////////////// + + /// return the locale-dependent decimal point + JSON_HEDLEY_PURE + static char get_decimal_point() noexcept + { + const auto loc = localeconv(); + assert(loc != nullptr); + return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point); + } + + ///////////////////// + // scan functions + ///////////////////// + + /*! + @brief get codepoint from 4 hex characters following `\u` + + For input "\u c1 c2 c3 c4" the codepoint is: + (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4 + = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0) + + Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f' + must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The + conversion is done by subtracting the offset (0x30, 0x37, and 0x57) + between the ASCII value of the character and the desired integer value. + + @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or + non-hex character) + */ + int get_codepoint() + { + // this function only makes sense after reading `\u` + assert(current == 'u'); + int codepoint = 0; + + const auto factors = { 12u, 8u, 4u, 0u }; + for (const auto factor : factors) + { + get(); + + if (current >= '0' and current <= '9') + { + codepoint += static_cast((static_cast(current) - 0x30u) << factor); + } + else if (current >= 'A' and current <= 'F') + { + codepoint += static_cast((static_cast(current) - 0x37u) << factor); + } + else if (current >= 'a' and current <= 'f') + { + codepoint += static_cast((static_cast(current) - 0x57u) << factor); + } + else + { + return -1; + } + } + + assert(0x0000 <= codepoint and codepoint <= 0xFFFF); + return codepoint; + } + + /*! + @brief check if the next byte(s) are inside a given range + + Adds the current byte and, for each passed range, reads a new byte and + checks if it is inside the range. If a violation was detected, set up an + error message and return false. Otherwise, return true. + + @param[in] ranges list of integers; interpreted as list of pairs of + inclusive lower and upper bound, respectively + + @pre The passed list @a ranges must have 2, 4, or 6 elements; that is, + 1, 2, or 3 pairs. This precondition is enforced by an assertion. + + @return true if and only if no range violation was detected + */ + bool next_byte_in_range(std::initializer_list ranges) + { + assert(ranges.size() == 2 or ranges.size() == 4 or ranges.size() == 6); + add(current); + + for (auto range = ranges.begin(); range != ranges.end(); ++range) + { + get(); + if (JSON_HEDLEY_LIKELY(*range <= current and current <= *(++range))) + { + add(current); + } + else + { + error_message = "invalid string: ill-formed UTF-8 byte"; + return false; + } + } + + return true; + } + + /*! + @brief scan a string literal + + This function scans a string according to Sect. 7 of RFC 7159. While + scanning, bytes are escaped and copied into buffer token_buffer. Then the + function returns successfully, token_buffer is *not* null-terminated (as it + may contain \0 bytes), and token_buffer.size() is the number of bytes in the + string. + + @return token_type::value_string if string could be successfully scanned, + token_type::parse_error otherwise + + @note In case of errors, variable error_message contains a textual + description. + */ + token_type scan_string() + { + // reset token_buffer (ignore opening quote) + reset(); + + // we entered the function by reading an open quote + assert(current == '\"'); + + while (true) + { + // get next character + switch (get()) + { + // end of file while parsing string + case std::char_traits::eof(): + { + error_message = "invalid string: missing closing quote"; + return token_type::parse_error; + } + + // closing quote + case '\"': + { + return token_type::value_string; + } + + // escapes + case '\\': + { + switch (get()) + { + // quotation mark + case '\"': + add('\"'); + break; + // reverse solidus + case '\\': + add('\\'); + break; + // solidus + case '/': + add('/'); + break; + // backspace + case 'b': + add('\b'); + break; + // form feed + case 'f': + add('\f'); + break; + // line feed + case 'n': + add('\n'); + break; + // carriage return + case 'r': + add('\r'); + break; + // tab + case 't': + add('\t'); + break; + + // unicode escapes + case 'u': + { + const int codepoint1 = get_codepoint(); + int codepoint = codepoint1; // start with codepoint1 + + if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1)) + { + error_message = "invalid string: '\\u' must be followed by 4 hex digits"; + return token_type::parse_error; + } + + // check if code point is a high surrogate + if (0xD800 <= codepoint1 and codepoint1 <= 0xDBFF) + { + // expect next \uxxxx entry + if (JSON_HEDLEY_LIKELY(get() == '\\' and get() == 'u')) + { + const int codepoint2 = get_codepoint(); + + if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1)) + { + error_message = "invalid string: '\\u' must be followed by 4 hex digits"; + return token_type::parse_error; + } + + // check if codepoint2 is a low surrogate + if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF)) + { + // overwrite codepoint + codepoint = static_cast( + // high surrogate occupies the most significant 22 bits + (static_cast(codepoint1) << 10u) + // low surrogate occupies the least significant 15 bits + + static_cast(codepoint2) + // there is still the 0xD800, 0xDC00 and 0x10000 noise + // in the result so we have to subtract with: + // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 + - 0x35FDC00u); + } + else + { + error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF"; + return token_type::parse_error; + } + } + else + { + error_message = "invalid string: surrogate U+DC00..U+DFFF must be followed by U+DC00..U+DFFF"; + return token_type::parse_error; + } + } + else + { + if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 and codepoint1 <= 0xDFFF)) + { + error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF"; + return token_type::parse_error; + } + } + + // result of the above calculation yields a proper codepoint + assert(0x00 <= codepoint and codepoint <= 0x10FFFF); + + // translate codepoint into bytes + if (codepoint < 0x80) + { + // 1-byte characters: 0xxxxxxx (ASCII) + add(codepoint); + } + else if (codepoint <= 0x7FF) + { + // 2-byte characters: 110xxxxx 10xxxxxx + add(static_cast(0xC0u | (static_cast(codepoint) >> 6u))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } + else if (codepoint <= 0xFFFF) + { + // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx + add(static_cast(0xE0u | (static_cast(codepoint) >> 12u))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } + else + { + // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + add(static_cast(0xF0u | (static_cast(codepoint) >> 18u))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 12u) & 0x3Fu))); + add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); + add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); + } + + break; + } + + // other characters after escape + default: + error_message = "invalid string: forbidden character after backslash"; + return token_type::parse_error; + } + + break; + } + + // invalid control characters + case 0x00: + { + error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000"; + return token_type::parse_error; + } + + case 0x01: + { + error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001"; + return token_type::parse_error; + } + + case 0x02: + { + error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002"; + return token_type::parse_error; + } + + case 0x03: + { + error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003"; + return token_type::parse_error; + } + + case 0x04: + { + error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004"; + return token_type::parse_error; + } + + case 0x05: + { + error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005"; + return token_type::parse_error; + } + + case 0x06: + { + error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006"; + return token_type::parse_error; + } + + case 0x07: + { + error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007"; + return token_type::parse_error; + } + + case 0x08: + { + error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b"; + return token_type::parse_error; + } + + case 0x09: + { + error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t"; + return token_type::parse_error; + } + + case 0x0A: + { + error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n"; + return token_type::parse_error; + } + + case 0x0B: + { + error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B"; + return token_type::parse_error; + } + + case 0x0C: + { + error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f"; + return token_type::parse_error; + } + + case 0x0D: + { + error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r"; + return token_type::parse_error; + } + + case 0x0E: + { + error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E"; + return token_type::parse_error; + } + + case 0x0F: + { + error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F"; + return token_type::parse_error; + } + + case 0x10: + { + error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010"; + return token_type::parse_error; + } + + case 0x11: + { + error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011"; + return token_type::parse_error; + } + + case 0x12: + { + error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012"; + return token_type::parse_error; + } + + case 0x13: + { + error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013"; + return token_type::parse_error; + } + + case 0x14: + { + error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014"; + return token_type::parse_error; + } + + case 0x15: + { + error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015"; + return token_type::parse_error; + } + + case 0x16: + { + error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016"; + return token_type::parse_error; + } + + case 0x17: + { + error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017"; + return token_type::parse_error; + } + + case 0x18: + { + error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018"; + return token_type::parse_error; + } + + case 0x19: + { + error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019"; + return token_type::parse_error; + } + + case 0x1A: + { + error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A"; + return token_type::parse_error; + } + + case 0x1B: + { + error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B"; + return token_type::parse_error; + } + + case 0x1C: + { + error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C"; + return token_type::parse_error; + } + + case 0x1D: + { + error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D"; + return token_type::parse_error; + } + + case 0x1E: + { + error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E"; + return token_type::parse_error; + } + + case 0x1F: + { + error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F"; + return token_type::parse_error; + } + + // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace)) + case 0x20: + case 0x21: + case 0x23: + case 0x24: + case 0x25: + case 0x26: + case 0x27: + case 0x28: + case 0x29: + case 0x2A: + case 0x2B: + case 0x2C: + case 0x2D: + case 0x2E: + case 0x2F: + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + case 0x38: + case 0x39: + case 0x3A: + case 0x3B: + case 0x3C: + case 0x3D: + case 0x3E: + case 0x3F: + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + case 0x78: + case 0x79: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: + { + add(current); + break; + } + + // U+0080..U+07FF: bytes C2..DF 80..BF + case 0xC2: + case 0xC3: + case 0xC4: + case 0xC5: + case 0xC6: + case 0xC7: + case 0xC8: + case 0xC9: + case 0xCA: + case 0xCB: + case 0xCC: + case 0xCD: + case 0xCE: + case 0xCF: + case 0xD0: + case 0xD1: + case 0xD2: + case 0xD3: + case 0xD4: + case 0xD5: + case 0xD6: + case 0xD7: + case 0xD8: + case 0xD9: + case 0xDA: + case 0xDB: + case 0xDC: + case 0xDD: + case 0xDE: + case 0xDF: + { + if (JSON_HEDLEY_UNLIKELY(not next_byte_in_range({0x80, 0xBF}))) + { + return token_type::parse_error; + } + break; + } + + // U+0800..U+0FFF: bytes E0 A0..BF 80..BF + case 0xE0: + { + if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF + // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF + case 0xE1: + case 0xE2: + case 0xE3: + case 0xE4: + case 0xE5: + case 0xE6: + case 0xE7: + case 0xE8: + case 0xE9: + case 0xEA: + case 0xEB: + case 0xEC: + case 0xEE: + case 0xEF: + { + if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+D000..U+D7FF: bytes ED 80..9F 80..BF + case 0xED: + { + if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF + case 0xF0: + { + if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF + case 0xF1: + case 0xF2: + case 0xF3: + { + if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF + case 0xF4: + { + if (JSON_HEDLEY_UNLIKELY(not (next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) + { + return token_type::parse_error; + } + break; + } + + // remaining bytes (80..C1 and F5..FF) are ill-formed + default: + { + error_message = "invalid string: ill-formed UTF-8 byte"; + return token_type::parse_error; + } + } + } + } + + JSON_HEDLEY_NON_NULL(2) + static void strtof(float& f, const char* str, char** endptr) noexcept + { + f = std::strtof(str, endptr); + } + + JSON_HEDLEY_NON_NULL(2) + static void strtof(double& f, const char* str, char** endptr) noexcept + { + f = std::strtod(str, endptr); + } + + JSON_HEDLEY_NON_NULL(2) + static void strtof(long double& f, const char* str, char** endptr) noexcept + { + f = std::strtold(str, endptr); + } + + /*! + @brief scan a number literal + + This function scans a string according to Sect. 6 of RFC 7159. + + The function is realized with a deterministic finite state machine derived + from the grammar described in RFC 7159. Starting in state "init", the + input is read and used to determined the next state. Only state "done" + accepts the number. State "error" is a trap state to model errors. In the + table below, "anything" means any character but the ones listed before. + + state | 0 | 1-9 | e E | + | - | . | anything + ---------|----------|----------|----------|---------|---------|----------|----------- + init | zero | any1 | [error] | [error] | minus | [error] | [error] + minus | zero | any1 | [error] | [error] | [error] | [error] | [error] + zero | done | done | exponent | done | done | decimal1 | done + any1 | any1 | any1 | exponent | done | done | decimal1 | done + decimal1 | decimal2 | [error] | [error] | [error] | [error] | [error] | [error] + decimal2 | decimal2 | decimal2 | exponent | done | done | done | done + exponent | any2 | any2 | [error] | sign | sign | [error] | [error] + sign | any2 | any2 | [error] | [error] | [error] | [error] | [error] + any2 | any2 | any2 | done | done | done | done | done + + The state machine is realized with one label per state (prefixed with + "scan_number_") and `goto` statements between them. The state machine + contains cycles, but any cycle can be left when EOF is read. Therefore, + the function is guaranteed to terminate. + + During scanning, the read bytes are stored in token_buffer. This string is + then converted to a signed integer, an unsigned integer, or a + floating-point number. + + @return token_type::value_unsigned, token_type::value_integer, or + token_type::value_float if number could be successfully scanned, + token_type::parse_error otherwise + + @note The scanner is independent of the current locale. Internally, the + locale's decimal point is used instead of `.` to work with the + locale-dependent converters. + */ + token_type scan_number() // lgtm [cpp/use-of-goto] + { + // reset token_buffer to store the number's bytes + reset(); + + // the type of the parsed number; initially set to unsigned; will be + // changed if minus sign, decimal point or exponent is read + token_type number_type = token_type::value_unsigned; + + // state (init): we just found out we need to scan a number + switch (current) + { + case '-': + { + add(current); + goto scan_number_minus; + } + + case '0': + { + add(current); + goto scan_number_zero; + } + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + // all other characters are rejected outside scan_number() + default: // LCOV_EXCL_LINE + assert(false); // LCOV_EXCL_LINE + } + +scan_number_minus: + // state: we just parsed a leading minus sign + number_type = token_type::value_integer; + switch (get()) + { + case '0': + { + add(current); + goto scan_number_zero; + } + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + default: + { + error_message = "invalid number; expected digit after '-'"; + return token_type::parse_error; + } + } + +scan_number_zero: + // state: we just parse a zero (maybe with a leading minus sign) + switch (get()) + { + case '.': + { + add(decimal_point_char); + goto scan_number_decimal1; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_any1: + // state: we just parsed a number 0-9 (maybe with a leading minus sign) + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any1; + } + + case '.': + { + add(decimal_point_char); + goto scan_number_decimal1; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_decimal1: + // state: we just parsed a decimal point + number_type = token_type::value_float; + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_decimal2; + } + + default: + { + error_message = "invalid number; expected digit after '.'"; + return token_type::parse_error; + } + } + +scan_number_decimal2: + // we just parsed at least one number after a decimal point + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_decimal2; + } + + case 'e': + case 'E': + { + add(current); + goto scan_number_exponent; + } + + default: + goto scan_number_done; + } + +scan_number_exponent: + // we just parsed an exponent + number_type = token_type::value_float; + switch (get()) + { + case '+': + case '-': + { + add(current); + goto scan_number_sign; + } + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + { + error_message = + "invalid number; expected '+', '-', or digit after exponent"; + return token_type::parse_error; + } + } + +scan_number_sign: + // we just parsed an exponent sign + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + { + error_message = "invalid number; expected digit after exponent sign"; + return token_type::parse_error; + } + } + +scan_number_any2: + // we just parsed a number after the exponent or exponent sign + switch (get()) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + add(current); + goto scan_number_any2; + } + + default: + goto scan_number_done; + } + +scan_number_done: + // unget the character after the number (we only read it to know that + // we are done scanning a number) + unget(); + + char* endptr = nullptr; + errno = 0; + + // try to parse integers first and fall back to floats + if (number_type == token_type::value_unsigned) + { + const auto x = std::strtoull(token_buffer.data(), &endptr, 10); + + // we checked the number format before + assert(endptr == token_buffer.data() + token_buffer.size()); + + if (errno == 0) + { + value_unsigned = static_cast(x); + if (value_unsigned == x) + { + return token_type::value_unsigned; + } + } + } + else if (number_type == token_type::value_integer) + { + const auto x = std::strtoll(token_buffer.data(), &endptr, 10); + + // we checked the number format before + assert(endptr == token_buffer.data() + token_buffer.size()); + + if (errno == 0) + { + value_integer = static_cast(x); + if (value_integer == x) + { + return token_type::value_integer; + } + } + } + + // this code is reached if we parse a floating-point number or if an + // integer conversion above failed + strtof(value_float, token_buffer.data(), &endptr); + + // we checked the number format before + assert(endptr == token_buffer.data() + token_buffer.size()); + + return token_type::value_float; + } + + /*! + @param[in] literal_text the literal text to expect + @param[in] length the length of the passed literal text + @param[in] return_type the token type to return on success + */ + JSON_HEDLEY_NON_NULL(2) + token_type scan_literal(const char* literal_text, const std::size_t length, + token_type return_type) + { + assert(current == literal_text[0]); + for (std::size_t i = 1; i < length; ++i) + { + if (JSON_HEDLEY_UNLIKELY(get() != literal_text[i])) + { + error_message = "invalid literal"; + return token_type::parse_error; + } + } + return return_type; + } + + ///////////////////// + // input management + ///////////////////// + + /// reset token_buffer; current character is beginning of token + void reset() noexcept + { + token_buffer.clear(); + token_string.clear(); + token_string.push_back(std::char_traits::to_char_type(current)); + } + + /* + @brief get next character from the input + + This function provides the interface to the used input adapter. It does + not throw in case the input reached EOF, but returns a + `std::char_traits::eof()` in that case. Stores the scanned characters + for use in error messages. + + @return character read from the input + */ + std::char_traits::int_type get() + { + ++position.chars_read_total; + ++position.chars_read_current_line; + + if (next_unget) + { + // just reset the next_unget variable and work with current + next_unget = false; + } + else + { + current = ia->get_character(); + } + + if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) + { + token_string.push_back(std::char_traits::to_char_type(current)); + } + + if (current == '\n') + { + ++position.lines_read; + position.chars_read_current_line = 0; + } + + return current; + } + + /*! + @brief unget current character (read it again on next get) + + We implement unget by setting variable next_unget to true. The input is not + changed - we just simulate ungetting by modifying chars_read_total, + chars_read_current_line, and token_string. The next call to get() will + behave as if the unget character is read again. + */ + void unget() + { + next_unget = true; + + --position.chars_read_total; + + // in case we "unget" a newline, we have to also decrement the lines_read + if (position.chars_read_current_line == 0) + { + if (position.lines_read > 0) + { + --position.lines_read; + } + } + else + { + --position.chars_read_current_line; + } + + if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) + { + assert(not token_string.empty()); + token_string.pop_back(); + } + } + + /// add a character to token_buffer + void add(int c) + { + token_buffer.push_back(std::char_traits::to_char_type(c)); + } + + public: + ///////////////////// + // value getters + ///////////////////// + + /// return integer value + constexpr number_integer_t get_number_integer() const noexcept + { + return value_integer; + } + + /// return unsigned integer value + constexpr number_unsigned_t get_number_unsigned() const noexcept + { + return value_unsigned; + } + + /// return floating-point value + constexpr number_float_t get_number_float() const noexcept + { + return value_float; + } + + /// return current string value (implicitly resets the token; useful only once) + string_t& get_string() + { + return token_buffer; + } + + ///////////////////// + // diagnostics + ///////////////////// + + /// return position of last read token + constexpr position_t get_position() const noexcept + { + return position; + } + + /// return the last read token (for errors only). Will never contain EOF + /// (an arbitrary value that is not a valid char value, often -1), because + /// 255 may legitimately occur. May contain NUL, which should be escaped. + std::string get_token_string() const + { + // escape control characters + std::string result; + for (const auto c : token_string) + { + if ('\x00' <= c and c <= '\x1F') + { + // escape control characters + std::array cs{{}}; + (std::snprintf)(cs.data(), cs.size(), "", static_cast(c)); + result += cs.data(); + } + else + { + // add character as is + result.push_back(c); + } + } + + return result; + } + + /// return syntax error message + JSON_HEDLEY_RETURNS_NON_NULL + constexpr const char* get_error_message() const noexcept + { + return error_message; + } + + ///////////////////// + // actual scanner + ///////////////////// + + /*! + @brief skip the UTF-8 byte order mark + @return true iff there is no BOM or the correct BOM has been skipped + */ + bool skip_bom() + { + if (get() == 0xEF) + { + // check if we completely parse the BOM + return get() == 0xBB and get() == 0xBF; + } + + // the first character is not the beginning of the BOM; unget it to + // process is later + unget(); + return true; + } + + token_type scan() + { + // initially, skip the BOM + if (position.chars_read_total == 0 and not skip_bom()) + { + error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; + return token_type::parse_error; + } + + // read next character and ignore whitespace + do + { + get(); + } + while (current == ' ' or current == '\t' or current == '\n' or current == '\r'); + + switch (current) + { + // structural characters + case '[': + return token_type::begin_array; + case ']': + return token_type::end_array; + case '{': + return token_type::begin_object; + case '}': + return token_type::end_object; + case ':': + return token_type::name_separator; + case ',': + return token_type::value_separator; + + // literals + case 't': + return scan_literal("true", 4, token_type::literal_true); + case 'f': + return scan_literal("false", 5, token_type::literal_false); + case 'n': + return scan_literal("null", 4, token_type::literal_null); + + // string + case '\"': + return scan_string(); + + // number + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return scan_number(); + + // end of input (the null byte is needed when parsing from + // string literals) + case '\0': + case std::char_traits::eof(): + return token_type::end_of_input; + + // error + default: + error_message = "invalid literal"; + return token_type::parse_error; + } + } + + private: + /// input adapter + detail::input_adapter_t ia = nullptr; + + /// the current character + std::char_traits::int_type current = std::char_traits::eof(); + + /// whether the next get() call should just return current + bool next_unget = false; + + /// the start position of the current token + position_t position {}; + + /// raw input token string (for error messages) + std::vector token_string {}; + + /// buffer for variable-length tokens (numbers, strings) + string_t token_buffer {}; + + /// a description of occurred lexer errors + const char* error_message = ""; + + // number values + number_integer_t value_integer = 0; + number_unsigned_t value_unsigned = 0; + number_float_t value_float = 0; + + /// the decimal point + const char decimal_point_char = '.'; +}; +} // namespace detail +} // namespace nlohmann diff --git a/thirdparty/nlohmann/detail/input/parser.hpp b/thirdparty/nlohmann/detail/input/parser.hpp new file mode 100644 index 00000000000..8d4febcbfab --- /dev/null +++ b/thirdparty/nlohmann/detail/input/parser.hpp @@ -0,0 +1,498 @@ +#pragma once + +#include // assert +#include // isfinite +#include // uint8_t +#include // function +#include // string +#include // move +#include // vector + +#include +#include +#include +#include +#include +#include +#include + +namespace nlohmann +{ +namespace detail +{ +//////////// +// parser // +//////////// + +/*! +@brief syntax analysis + +This class implements a recursive decent parser. +*/ +template +class parser +{ + using number_integer_t = typename BasicJsonType::number_integer_t; + using number_unsigned_t = typename BasicJsonType::number_unsigned_t; + using number_float_t = typename BasicJsonType::number_float_t; + using string_t = typename BasicJsonType::string_t; + using lexer_t = lexer; + using token_type = typename lexer_t::token_type; + + public: + enum class parse_event_t : uint8_t + { + /// the parser read `{` and started to process a JSON object + object_start, + /// the parser read `}` and finished processing a JSON object + object_end, + /// the parser read `[` and started to process a JSON array + array_start, + /// the parser read `]` and finished processing a JSON array + array_end, + /// the parser read a key of a value in an object + key, + /// the parser finished reading a JSON value + value + }; + + using parser_callback_t = + std::function; + + /// a parser reading from an input adapter + explicit parser(detail::input_adapter_t&& adapter, + const parser_callback_t cb = nullptr, + const bool allow_exceptions_ = true) + : callback(cb), m_lexer(std::move(adapter)), allow_exceptions(allow_exceptions_) + { + // read first token + get_token(); + } + + /*! + @brief public parser interface + + @param[in] strict whether to expect the last token to be EOF + @param[in,out] result parsed JSON value + + @throw parse_error.101 in case of an unexpected token + @throw parse_error.102 if to_unicode fails or surrogate error + @throw parse_error.103 if to_unicode fails + */ + void parse(const bool strict, BasicJsonType& result) + { + if (callback) + { + json_sax_dom_callback_parser sdp(result, callback, allow_exceptions); + sax_parse_internal(&sdp); + result.assert_invariant(); + + // in strict mode, input must be completely read + if (strict and (get_token() != token_type::end_of_input)) + { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"))); + } + + // in case of an error, return discarded value + if (sdp.is_errored()) + { + result = value_t::discarded; + return; + } + + // set top-level value to null if it was discarded by the callback + // function + if (result.is_discarded()) + { + result = nullptr; + } + } + else + { + json_sax_dom_parser sdp(result, allow_exceptions); + sax_parse_internal(&sdp); + result.assert_invariant(); + + // in strict mode, input must be completely read + if (strict and (get_token() != token_type::end_of_input)) + { + sdp.parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"))); + } + + // in case of an error, return discarded value + if (sdp.is_errored()) + { + result = value_t::discarded; + return; + } + } + } + + /*! + @brief public accept interface + + @param[in] strict whether to expect the last token to be EOF + @return whether the input is a proper JSON text + */ + bool accept(const bool strict = true) + { + json_sax_acceptor sax_acceptor; + return sax_parse(&sax_acceptor, strict); + } + + template + JSON_HEDLEY_NON_NULL(2) + bool sax_parse(SAX* sax, const bool strict = true) + { + (void)detail::is_sax_static_asserts {}; + const bool result = sax_parse_internal(sax); + + // strict mode: next byte must be EOF + if (result and strict and (get_token() != token_type::end_of_input)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_of_input, "value"))); + } + + return result; + } + + private: + template + JSON_HEDLEY_NON_NULL(2) + bool sax_parse_internal(SAX* sax) + { + // stack to remember the hierarchy of structured values we are parsing + // true = array; false = object + std::vector states; + // value to avoid a goto (see comment where set to true) + bool skip_to_state_evaluation = false; + + while (true) + { + if (not skip_to_state_evaluation) + { + // invariant: get_token() was called before each iteration + switch (last_token) + { + case token_type::begin_object: + { + if (JSON_HEDLEY_UNLIKELY(not sax->start_object(std::size_t(-1)))) + { + return false; + } + + // closing } -> we are done + if (get_token() == token_type::end_object) + { + if (JSON_HEDLEY_UNLIKELY(not sax->end_object())) + { + return false; + } + break; + } + + // parse key + if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::value_string, "object key"))); + } + if (JSON_HEDLEY_UNLIKELY(not sax->key(m_lexer.get_string()))) + { + return false; + } + + // parse separator (:) + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::name_separator, "object separator"))); + } + + // remember we are now inside an object + states.push_back(false); + + // parse values + get_token(); + continue; + } + + case token_type::begin_array: + { + if (JSON_HEDLEY_UNLIKELY(not sax->start_array(std::size_t(-1)))) + { + return false; + } + + // closing ] -> we are done + if (get_token() == token_type::end_array) + { + if (JSON_HEDLEY_UNLIKELY(not sax->end_array())) + { + return false; + } + break; + } + + // remember we are now inside an array + states.push_back(true); + + // parse values (no need to call get_token) + continue; + } + + case token_type::value_float: + { + const auto res = m_lexer.get_number_float(); + + if (JSON_HEDLEY_UNLIKELY(not std::isfinite(res))) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'")); + } + + if (JSON_HEDLEY_UNLIKELY(not sax->number_float(res, m_lexer.get_string()))) + { + return false; + } + + break; + } + + case token_type::literal_false: + { + if (JSON_HEDLEY_UNLIKELY(not sax->boolean(false))) + { + return false; + } + break; + } + + case token_type::literal_null: + { + if (JSON_HEDLEY_UNLIKELY(not sax->null())) + { + return false; + } + break; + } + + case token_type::literal_true: + { + if (JSON_HEDLEY_UNLIKELY(not sax->boolean(true))) + { + return false; + } + break; + } + + case token_type::value_integer: + { + if (JSON_HEDLEY_UNLIKELY(not sax->number_integer(m_lexer.get_number_integer()))) + { + return false; + } + break; + } + + case token_type::value_string: + { + if (JSON_HEDLEY_UNLIKELY(not sax->string(m_lexer.get_string()))) + { + return false; + } + break; + } + + case token_type::value_unsigned: + { + if (JSON_HEDLEY_UNLIKELY(not sax->number_unsigned(m_lexer.get_number_unsigned()))) + { + return false; + } + break; + } + + case token_type::parse_error: + { + // using "uninitialized" to avoid "expected" message + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::uninitialized, "value"))); + } + + default: // the last token was unexpected + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::literal_or_value, "value"))); + } + } + } + else + { + skip_to_state_evaluation = false; + } + + // we reached this line after we successfully parsed a value + if (states.empty()) + { + // empty stack: we reached the end of the hierarchy: done + return true; + } + + if (states.back()) // array + { + // comma -> next value + if (get_token() == token_type::value_separator) + { + // parse a new value + get_token(); + continue; + } + + // closing ] + if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) + { + if (JSON_HEDLEY_UNLIKELY(not sax->end_array())) + { + return false; + } + + // We are done with this array. Before we can parse a + // new value, we need to evaluate the new state first. + // By setting skip_to_state_evaluation to false, we + // are effectively jumping to the beginning of this if. + assert(not states.empty()); + states.pop_back(); + skip_to_state_evaluation = true; + continue; + } + + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_array, "array"))); + } + else // object + { + // comma -> next value + if (get_token() == token_type::value_separator) + { + // parse key + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::value_string, "object key"))); + } + + if (JSON_HEDLEY_UNLIKELY(not sax->key(m_lexer.get_string()))) + { + return false; + } + + // parse separator (:) + if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) + { + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::name_separator, "object separator"))); + } + + // parse values + get_token(); + continue; + } + + // closing } + if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) + { + if (JSON_HEDLEY_UNLIKELY(not sax->end_object())) + { + return false; + } + + // We are done with this object. Before we can parse a + // new value, we need to evaluate the new state first. + // By setting skip_to_state_evaluation to false, we + // are effectively jumping to the beginning of this if. + assert(not states.empty()); + states.pop_back(); + skip_to_state_evaluation = true; + continue; + } + + return sax->parse_error(m_lexer.get_position(), + m_lexer.get_token_string(), + parse_error::create(101, m_lexer.get_position(), + exception_message(token_type::end_object, "object"))); + } + } + } + + /// get next token from lexer + token_type get_token() + { + return last_token = m_lexer.scan(); + } + + std::string exception_message(const token_type expected, const std::string& context) + { + std::string error_msg = "syntax error "; + + if (not context.empty()) + { + error_msg += "while parsing " + context + " "; + } + + error_msg += "- "; + + if (last_token == token_type::parse_error) + { + error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" + + m_lexer.get_token_string() + "'"; + } + else + { + error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token)); + } + + if (expected != token_type::uninitialized) + { + error_msg += "; expected " + std::string(lexer_t::token_type_name(expected)); + } + + return error_msg; + } + + private: + /// callback function + const parser_callback_t callback = nullptr; + /// the type of the last read token + token_type last_token = token_type::uninitialized; + /// the lexer + lexer_t m_lexer; + /// whether to throw exceptions in case of errors + const bool allow_exceptions = true; +}; +} // namespace detail +} // namespace nlohmann diff --git a/thirdparty/nlohmann/detail/input/position_t.hpp b/thirdparty/nlohmann/detail/input/position_t.hpp new file mode 100644 index 00000000000..14e9649fb29 --- /dev/null +++ b/thirdparty/nlohmann/detail/input/position_t.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include // size_t + +namespace nlohmann +{ +namespace detail +{ +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +} // namespace nlohmann diff --git a/thirdparty/nlohmann/detail/iterators/internal_iterator.hpp b/thirdparty/nlohmann/detail/iterators/internal_iterator.hpp new file mode 100644 index 00000000000..2c81f723fd2 --- /dev/null +++ b/thirdparty/nlohmann/detail/iterators/internal_iterator.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include + +namespace nlohmann +{ +namespace detail +{ +/*! +@brief an iterator value + +@note This structure could easily be a union, but MSVC currently does not allow +unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. +*/ +template struct internal_iterator +{ + /// iterator for JSON objects + typename BasicJsonType::object_t::iterator object_iterator {}; + /// iterator for JSON arrays + typename BasicJsonType::array_t::iterator array_iterator {}; + /// generic iterator for all other types + primitive_iterator_t primitive_iterator {}; +}; +} // namespace detail +} // namespace nlohmann diff --git a/thirdparty/nlohmann/detail/iterators/iter_impl.hpp b/thirdparty/nlohmann/detail/iterators/iter_impl.hpp new file mode 100644 index 00000000000..3a362971909 --- /dev/null +++ b/thirdparty/nlohmann/detail/iterators/iter_impl.hpp @@ -0,0 +1,638 @@ +#pragma once + +#include // not +#include // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next +#include // conditional, is_const, remove_const + +#include +#include +#include +#include +#include +#include +#include + +namespace nlohmann +{ +namespace detail +{ +// forward declare, to be able to friend it later on +template class iteration_proxy; +template class iteration_proxy_value; + +/*! +@brief a template for a bidirectional iterator for the @ref basic_json class +This class implements a both iterators (iterator and const_iterator) for the +@ref basic_json class. +@note An iterator is called *initialized* when a pointer to a JSON value has + been set (e.g., by a constructor or a copy assignment). If the iterator is + default-constructed, it is *uninitialized* and most methods are undefined. + **The library uses assertions to detect calls on uninitialized iterators.** +@requirement The class satisfies the following concept requirements: +- +[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): + The iterator that can be moved can be moved in both directions (i.e. + incremented and decremented). +@since version 1.0.0, simplified in version 2.0.9, change to bidirectional + iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593) +*/ +template +class iter_impl +{ + /// allow basic_json to access private members + friend iter_impl::value, typename std::remove_const::type, const BasicJsonType>::type>; + friend BasicJsonType; + friend iteration_proxy; + friend iteration_proxy_value; + + using object_t = typename BasicJsonType::object_t; + using array_t = typename BasicJsonType::array_t; + // make sure BasicJsonType is basic_json or const basic_json + static_assert(is_basic_json::type>::value, + "iter_impl only accepts (const) basic_json"); + + public: + + /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. + /// The C++ Standard has never required user-defined iterators to derive from std::iterator. + /// A user-defined iterator should provide publicly accessible typedefs named + /// iterator_category, value_type, difference_type, pointer, and reference. + /// Note that value_type is required to be non-const, even for constant iterators. + using iterator_category = std::bidirectional_iterator_tag; + + /// the type of the values when the iterator is dereferenced + using value_type = typename BasicJsonType::value_type; + /// a type to represent differences between iterators + using difference_type = typename BasicJsonType::difference_type; + /// defines a pointer to the type iterated over (value_type) + using pointer = typename std::conditional::value, + typename BasicJsonType::const_pointer, + typename BasicJsonType::pointer>::type; + /// defines a reference to the type iterated over (value_type) + using reference = + typename std::conditional::value, + typename BasicJsonType::const_reference, + typename BasicJsonType::reference>::type; + + /// default constructor + iter_impl() = default; + + /*! + @brief constructor for a given JSON instance + @param[in] object pointer to a JSON object for this iterator + @pre object != nullptr + @post The iterator is initialized; i.e. `m_object != nullptr`. + */ + explicit iter_impl(pointer object) noexcept : m_object(object) + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + m_it.object_iterator = typename object_t::iterator(); + break; + } + + case value_t::array: + { + m_it.array_iterator = typename array_t::iterator(); + break; + } + + default: + { + m_it.primitive_iterator = primitive_iterator_t(); + break; + } + } + } + + /*! + @note The conventional copy constructor and copy assignment are implicitly + defined. Combined with the following converting constructor and + assignment, they support: (1) copy from iterator to iterator, (2) + copy from const iterator to const iterator, and (3) conversion from + iterator to const iterator. However conversion from const iterator + to iterator is not defined. + */ + + /*! + @brief const copy constructor + @param[in] other const iterator to copy from + @note This copy constructor had to be defined explicitly to circumvent a bug + occurring on msvc v19.0 compiler (VS 2015) debug build. For more + information refer to: https://github.com/nlohmann/json/issues/1608 + */ + iter_impl(const iter_impl& other) noexcept + : m_object(other.m_object), m_it(other.m_it) + {} + + /*! + @brief converting assignment + @param[in] other const iterator to copy from + @return const/non-const iterator + @note It is not checked whether @a other is initialized. + */ + iter_impl& operator=(const iter_impl& other) noexcept + { + m_object = other.m_object; + m_it = other.m_it; + return *this; + } + + /*! + @brief converting constructor + @param[in] other non-const iterator to copy from + @note It is not checked whether @a other is initialized. + */ + iter_impl(const iter_impl::type>& other) noexcept + : m_object(other.m_object), m_it(other.m_it) + {} + + /*! + @brief converting assignment + @param[in] other non-const iterator to copy from + @return const/non-const iterator + @note It is not checked whether @a other is initialized. + */ + iter_impl& operator=(const iter_impl::type>& other) noexcept + { + m_object = other.m_object; + m_it = other.m_it; + return *this; + } + + private: + /*! + @brief set the iterator to the first value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + void set_begin() noexcept + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + m_it.object_iterator = m_object->m_value.object->begin(); + break; + } + + case value_t::array: + { + m_it.array_iterator = m_object->m_value.array->begin(); + break; + } + + case value_t::null: + { + // set to end so begin()==end() is true: null is empty + m_it.primitive_iterator.set_end(); + break; + } + + default: + { + m_it.primitive_iterator.set_begin(); + break; + } + } + } + + /*! + @brief set the iterator past the last value + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + void set_end() noexcept + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + m_it.object_iterator = m_object->m_value.object->end(); + break; + } + + case value_t::array: + { + m_it.array_iterator = m_object->m_value.array->end(); + break; + } + + default: + { + m_it.primitive_iterator.set_end(); + break; + } + } + } + + public: + /*! + @brief return a reference to the value pointed to by the iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference operator*() const + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + assert(m_it.object_iterator != m_object->m_value.object->end()); + return m_it.object_iterator->second; + } + + case value_t::array: + { + assert(m_it.array_iterator != m_object->m_value.array->end()); + return *m_it.array_iterator; + } + + case value_t::null: + JSON_THROW(invalid_iterator::create(214, "cannot get value")); + + default: + { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) + { + return *m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value")); + } + } + } + + /*! + @brief dereference the iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + pointer operator->() const + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + assert(m_it.object_iterator != m_object->m_value.object->end()); + return &(m_it.object_iterator->second); + } + + case value_t::array: + { + assert(m_it.array_iterator != m_object->m_value.array->end()); + return &*m_it.array_iterator; + } + + default: + { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) + { + return m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value")); + } + } + } + + /*! + @brief post-increment (it++) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl const operator++(int) + { + auto result = *this; + ++(*this); + return result; + } + + /*! + @brief pre-increment (++it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator++() + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + std::advance(m_it.object_iterator, 1); + break; + } + + case value_t::array: + { + std::advance(m_it.array_iterator, 1); + break; + } + + default: + { + ++m_it.primitive_iterator; + break; + } + } + + return *this; + } + + /*! + @brief post-decrement (it--) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl const operator--(int) + { + auto result = *this; + --(*this); + return result; + } + + /*! + @brief pre-decrement (--it) + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator--() + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + { + std::advance(m_it.object_iterator, -1); + break; + } + + case value_t::array: + { + std::advance(m_it.array_iterator, -1); + break; + } + + default: + { + --m_it.primitive_iterator; + break; + } + } + + return *this; + } + + /*! + @brief comparison: equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator==(const iter_impl& other) const + { + // if objects are not the same, the comparison is undefined + if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) + { + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); + } + + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + return (m_it.object_iterator == other.m_it.object_iterator); + + case value_t::array: + return (m_it.array_iterator == other.m_it.array_iterator); + + default: + return (m_it.primitive_iterator == other.m_it.primitive_iterator); + } + } + + /*! + @brief comparison: not equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator!=(const iter_impl& other) const + { + return not operator==(other); + } + + /*! + @brief comparison: smaller + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator<(const iter_impl& other) const + { + // if objects are not the same, the comparison is undefined + if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) + { + JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); + } + + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators")); + + case value_t::array: + return (m_it.array_iterator < other.m_it.array_iterator); + + default: + return (m_it.primitive_iterator < other.m_it.primitive_iterator); + } + } + + /*! + @brief comparison: less than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator<=(const iter_impl& other) const + { + return not other.operator < (*this); + } + + /*! + @brief comparison: greater than + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator>(const iter_impl& other) const + { + return not operator<=(other); + } + + /*! + @brief comparison: greater than or equal + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + bool operator>=(const iter_impl& other) const + { + return not operator<(other); + } + + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator+=(difference_type i) + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); + + case value_t::array: + { + std::advance(m_it.array_iterator, i); + break; + } + + default: + { + m_it.primitive_iterator += i; + break; + } + } + + return *this; + } + + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl& operator-=(difference_type i) + { + return operator+=(-i); + } + + /*! + @brief add to iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator+(difference_type i) const + { + auto result = *this; + result += i; + return result; + } + + /*! + @brief addition of distance and iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + friend iter_impl operator+(difference_type i, const iter_impl& it) + { + auto result = it; + result += i; + return result; + } + + /*! + @brief subtract from iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + iter_impl operator-(difference_type i) const + { + auto result = *this; + result -= i; + return result; + } + + /*! + @brief return difference + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + difference_type operator-(const iter_impl& other) const + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); + + case value_t::array: + return m_it.array_iterator - other.m_it.array_iterator; + + default: + return m_it.primitive_iterator - other.m_it.primitive_iterator; + } + } + + /*! + @brief access to successor + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference operator[](difference_type n) const + { + assert(m_object != nullptr); + + switch (m_object->m_type) + { + case value_t::object: + JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators")); + + case value_t::array: + return *std::next(m_it.array_iterator, n); + + case value_t::null: + JSON_THROW(invalid_iterator::create(214, "cannot get value")); + + default: + { + if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) + { + return *m_object; + } + + JSON_THROW(invalid_iterator::create(214, "cannot get value")); + } + } + } + + /*! + @brief return the key of an object iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + const typename object_t::key_type& key() const + { + assert(m_object != nullptr); + + if (JSON_HEDLEY_LIKELY(m_object->is_object())) + { + return m_it.object_iterator->first; + } + + JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators")); + } + + /*! + @brief return the value of an iterator + @pre The iterator is initialized; i.e. `m_object != nullptr`. + */ + reference value() const + { + return operator*(); + } + + private: + /// associated JSON instance + pointer m_object = nullptr; + /// the actual iterator of the associated instance + internal_iterator::type> m_it {}; +}; +} // namespace detail +} // namespace nlohmann diff --git a/thirdparty/nlohmann/detail/iterators/iteration_proxy.hpp b/thirdparty/nlohmann/detail/iterators/iteration_proxy.hpp new file mode 100644 index 00000000000..c61d96296ce --- /dev/null +++ b/thirdparty/nlohmann/detail/iterators/iteration_proxy.hpp @@ -0,0 +1,176 @@ +#pragma once + +#include // size_t +#include // input_iterator_tag +#include // string, to_string +#include // tuple_size, get, tuple_element + +#include +#include + +namespace nlohmann +{ +namespace detail +{ +template +void int_to_string( string_type& target, std::size_t value ) +{ + target = std::to_string(value); +} +template class iteration_proxy_value +{ + public: + using difference_type = std::ptrdiff_t; + using value_type = iteration_proxy_value; + using pointer = value_type * ; + using reference = value_type & ; + using iterator_category = std::input_iterator_tag; + using string_type = typename std::remove_cv< typename std::remove_reference().key() ) >::type >::type; + + private: + /// the iterator + IteratorType anchor; + /// an index for arrays (used to create key names) + std::size_t array_index = 0; + /// last stringified array index + mutable std::size_t array_index_last = 0; + /// a string representation of the array index + mutable string_type array_index_str = "0"; + /// an empty string (to return a reference for primitive values) + const string_type empty_str = ""; + + public: + explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {} + + /// dereference operator (needed for range-based for) + iteration_proxy_value& operator*() + { + return *this; + } + + /// increment operator (needed for range-based for) + iteration_proxy_value& operator++() + { + ++anchor; + ++array_index; + + return *this; + } + + /// equality operator (needed for InputIterator) + bool operator==(const iteration_proxy_value& o) const + { + return anchor == o.anchor; + } + + /// inequality operator (needed for range-based for) + bool operator!=(const iteration_proxy_value& o) const + { + return anchor != o.anchor; + } + + /// return key of the iterator + const string_type& key() const + { + assert(anchor.m_object != nullptr); + + switch (anchor.m_object->type()) + { + // use integer array index as key + case value_t::array: + { + if (array_index != array_index_last) + { + int_to_string( array_index_str, array_index ); + array_index_last = array_index; + } + return array_index_str; + } + + // use key from the object + case value_t::object: + return anchor.key(); + + // use an empty key for all primitive types + default: + return empty_str; + } + } + + /// return value of the iterator + typename IteratorType::reference value() const + { + return anchor.value(); + } +}; + +/// proxy class for the items() function +template class iteration_proxy +{ + private: + /// the container to iterate + typename IteratorType::reference container; + + public: + /// construct iteration proxy from a container + explicit iteration_proxy(typename IteratorType::reference cont) noexcept + : container(cont) {} + + /// return iterator begin (needed for range-based for) + iteration_proxy_value begin() noexcept + { + return iteration_proxy_value(container.begin()); + } + + /// return iterator end (needed for range-based for) + iteration_proxy_value end() noexcept + { + return iteration_proxy_value(container.end()); + } +}; +// Structured Bindings Support +// For further reference see https://blog.tartanllama.xyz/structured-bindings/ +// And see https://github.com/nlohmann/json/pull/1391 +template = 0> +auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.key()) +{ + return i.key(); +} +// Structured Bindings Support +// For further reference see https://blog.tartanllama.xyz/structured-bindings/ +// And see https://github.com/nlohmann/json/pull/1391 +template = 0> +auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.value()) +{ + return i.value(); +} +} // namespace detail +} // namespace nlohmann + +// The Addition to the STD Namespace is required to add +// Structured Bindings Support to the iteration_proxy_value class +// For further reference see https://blog.tartanllama.xyz/structured-bindings/ +// And see https://github.com/nlohmann/json/pull/1391 +namespace std +{ +#if defined(__clang__) + // Fix: https://github.com/nlohmann/json/issues/1401 + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wmismatched-tags" +#endif +template +class tuple_size<::nlohmann::detail::iteration_proxy_value> + : public std::integral_constant {}; + +template +class tuple_element> +{ + public: + using type = decltype( + get(std::declval < + ::nlohmann::detail::iteration_proxy_value> ())); +}; +#if defined(__clang__) + #pragma clang diagnostic pop +#endif +} // namespace std diff --git a/thirdparty/nlohmann/detail/iterators/iterator_traits.hpp b/thirdparty/nlohmann/detail/iterators/iterator_traits.hpp new file mode 100644 index 00000000000..4cced80caf4 --- /dev/null +++ b/thirdparty/nlohmann/detail/iterators/iterator_traits.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include // random_access_iterator_tag + +#include +#include + +namespace nlohmann +{ +namespace detail +{ +template +struct iterator_types {}; + +template +struct iterator_types < + It, + void_t> +{ + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// This is required as some compilers implement std::iterator_traits in a way that +// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. +template +struct iterator_traits +{ +}; + +template +struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> +{ + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; +} // namespace detail +} // namespace nlohmann diff --git a/thirdparty/nlohmann/detail/iterators/json_reverse_iterator.hpp b/thirdparty/nlohmann/detail/iterators/json_reverse_iterator.hpp new file mode 100644 index 00000000000..f3b5b5db6b8 --- /dev/null +++ b/thirdparty/nlohmann/detail/iterators/json_reverse_iterator.hpp @@ -0,0 +1,119 @@ +#pragma once + +#include // ptrdiff_t +#include // reverse_iterator +#include // declval + +namespace nlohmann +{ +namespace detail +{ +////////////////////// +// reverse_iterator // +////////////////////// + +/*! +@brief a template for a reverse iterator class + +@tparam Base the base iterator type to reverse. Valid types are @ref +iterator (to create @ref reverse_iterator) and @ref const_iterator (to +create @ref const_reverse_iterator). + +@requirement The class satisfies the following concept requirements: +- +[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): + The iterator that can be moved can be moved in both directions (i.e. + incremented and decremented). +- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator): + It is possible to write to the pointed-to element (only if @a Base is + @ref iterator). + +@since version 1.0.0 +*/ +template +class json_reverse_iterator : public std::reverse_iterator +{ + public: + using difference_type = std::ptrdiff_t; + /// shortcut to the reverse iterator adapter + using base_iterator = std::reverse_iterator; + /// the reference type for the pointed-to element + using reference = typename Base::reference; + + /// create reverse iterator from iterator + explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept + : base_iterator(it) {} + + /// create reverse iterator from base class + explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} + + /// post-increment (it++) + json_reverse_iterator const operator++(int) + { + return static_cast(base_iterator::operator++(1)); + } + + /// pre-increment (++it) + json_reverse_iterator& operator++() + { + return static_cast(base_iterator::operator++()); + } + + /// post-decrement (it--) + json_reverse_iterator const operator--(int) + { + return static_cast(base_iterator::operator--(1)); + } + + /// pre-decrement (--it) + json_reverse_iterator& operator--() + { + return static_cast(base_iterator::operator--()); + } + + /// add to iterator + json_reverse_iterator& operator+=(difference_type i) + { + return static_cast(base_iterator::operator+=(i)); + } + + /// add to iterator + json_reverse_iterator operator+(difference_type i) const + { + return static_cast(base_iterator::operator+(i)); + } + + /// subtract from iterator + json_reverse_iterator operator-(difference_type i) const + { + return static_cast(base_iterator::operator-(i)); + } + + /// return difference + difference_type operator-(const json_reverse_iterator& other) const + { + return base_iterator(*this) - base_iterator(other); + } + + /// access to successor + reference operator[](difference_type n) const + { + return *(this->operator+(n)); + } + + /// return the key of an object iterator + auto key() const -> decltype(std::declval().key()) + { + auto it = --this->base(); + return it.key(); + } + + /// return the value of an iterator + reference value() const + { + auto it = --this->base(); + return it.operator * (); + } +}; +} // namespace detail +} // namespace nlohmann diff --git a/thirdparty/nlohmann/detail/iterators/primitive_iterator.hpp b/thirdparty/nlohmann/detail/iterators/primitive_iterator.hpp new file mode 100644 index 00000000000..28d6f1a65df --- /dev/null +++ b/thirdparty/nlohmann/detail/iterators/primitive_iterator.hpp @@ -0,0 +1,120 @@ +#pragma once + +#include // ptrdiff_t +#include // numeric_limits + +namespace nlohmann +{ +namespace detail +{ +/* +@brief an iterator for primitive JSON types + +This class models an iterator for primitive JSON types (boolean, number, +string). It's only purpose is to allow the iterator/const_iterator classes +to "iterate" over primitive values. Internally, the iterator is modeled by +a `difference_type` variable. Value begin_value (`0`) models the begin, +end_value (`1`) models past the end. +*/ +class primitive_iterator_t +{ + private: + using difference_type = std::ptrdiff_t; + static constexpr difference_type begin_value = 0; + static constexpr difference_type end_value = begin_value + 1; + + /// iterator as signed integer type + difference_type m_it = (std::numeric_limits::min)(); + + public: + constexpr difference_type get_value() const noexcept + { + return m_it; + } + + /// set iterator to a defined beginning + void set_begin() noexcept + { + m_it = begin_value; + } + + /// set iterator to a defined past the end + void set_end() noexcept + { + m_it = end_value; + } + + /// return whether the iterator can be dereferenced + constexpr bool is_begin() const noexcept + { + return m_it == begin_value; + } + + /// return whether the iterator is at end + constexpr bool is_end() const noexcept + { + return m_it == end_value; + } + + friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it == rhs.m_it; + } + + friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it < rhs.m_it; + } + + primitive_iterator_t operator+(difference_type n) noexcept + { + auto result = *this; + result += n; + return result; + } + + friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept + { + return lhs.m_it - rhs.m_it; + } + + primitive_iterator_t& operator++() noexcept + { + ++m_it; + return *this; + } + + primitive_iterator_t const operator++(int) noexcept + { + auto result = *this; + ++m_it; + return result; + } + + primitive_iterator_t& operator--() noexcept + { + --m_it; + return *this; + } + + primitive_iterator_t const operator--(int) noexcept + { + auto result = *this; + --m_it; + return result; + } + + primitive_iterator_t& operator+=(difference_type n) noexcept + { + m_it += n; + return *this; + } + + primitive_iterator_t& operator-=(difference_type n) noexcept + { + m_it -= n; + return *this; + } +}; +} // namespace detail +} // namespace nlohmann diff --git a/thirdparty/nlohmann/detail/json_pointer.hpp b/thirdparty/nlohmann/detail/json_pointer.hpp new file mode 100644 index 00000000000..87af3423315 --- /dev/null +++ b/thirdparty/nlohmann/detail/json_pointer.hpp @@ -0,0 +1,1011 @@ +#pragma once + +#include // all_of +#include // assert +#include // isdigit +#include // accumulate +#include // string +#include // move +#include // vector + +#include +#include +#include + +namespace nlohmann +{ +template +class json_pointer +{ + // allow basic_json to access private members + NLOHMANN_BASIC_JSON_TPL_DECLARATION + friend class basic_json; + + public: + /*! + @brief create JSON pointer + + Create a JSON pointer according to the syntax described in + [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3). + + @param[in] s string representing the JSON pointer; if omitted, the empty + string is assumed which references the whole JSON value + + @throw parse_error.107 if the given JSON pointer @a s is nonempty and does + not begin with a slash (`/`); see example below + + @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is + not followed by `0` (representing `~`) or `1` (representing `/`); see + example below + + @liveexample{The example shows the construction several valid JSON pointers + as well as the exceptional behavior.,json_pointer} + + @since version 2.0.0 + */ + explicit json_pointer(const std::string& s = "") + : reference_tokens(split(s)) + {} + + /*! + @brief return a string representation of the JSON pointer + + @invariant For each JSON pointer `ptr`, it holds: + @code {.cpp} + ptr == json_pointer(ptr.to_string()); + @endcode + + @return a string representation of the JSON pointer + + @liveexample{The example shows the result of `to_string`.,json_pointer__to_string} + + @since version 2.0.0 + */ + std::string to_string() const + { + return std::accumulate(reference_tokens.begin(), reference_tokens.end(), + std::string{}, + [](const std::string & a, const std::string & b) + { + return a + "/" + escape(b); + }); + } + + /// @copydoc to_string() + operator std::string() const + { + return to_string(); + } + + /*! + @brief append another JSON pointer at the end of this JSON pointer + + @param[in] ptr JSON pointer to append + @return JSON pointer with @a ptr appended + + @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} + + @complexity Linear in the length of @a ptr. + + @sa @ref operator/=(std::string) to append a reference token + @sa @ref operator/=(std::size_t) to append an array index + @sa @ref operator/(const json_pointer&, const json_pointer&) for a binary operator + + @since version 3.6.0 + */ + json_pointer& operator/=(const json_pointer& ptr) + { + reference_tokens.insert(reference_tokens.end(), + ptr.reference_tokens.begin(), + ptr.reference_tokens.end()); + return *this; + } + + /*! + @brief append an unescaped reference token at the end of this JSON pointer + + @param[in] token reference token to append + @return JSON pointer with @a token appended without escaping @a token + + @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} + + @complexity Amortized constant. + + @sa @ref operator/=(const json_pointer&) to append a JSON pointer + @sa @ref operator/=(std::size_t) to append an array index + @sa @ref operator/(const json_pointer&, std::size_t) for a binary operator + + @since version 3.6.0 + */ + json_pointer& operator/=(std::string token) + { + push_back(std::move(token)); + return *this; + } + + /*! + @brief append an array index at the end of this JSON pointer + + @param[in] array_index array index to append + @return JSON pointer with @a array_index appended + + @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} + + @complexity Amortized constant. + + @sa @ref operator/=(const json_pointer&) to append a JSON pointer + @sa @ref operator/=(std::string) to append a reference token + @sa @ref operator/(const json_pointer&, std::string) for a binary operator + + @since version 3.6.0 + */ + json_pointer& operator/=(std::size_t array_index) + { + return *this /= std::to_string(array_index); + } + + /*! + @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer + + @param[in] lhs JSON pointer + @param[in] rhs JSON pointer + @return a new JSON pointer with @a rhs appended to @a lhs + + @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary} + + @complexity Linear in the length of @a lhs and @a rhs. + + @sa @ref operator/=(const json_pointer&) to append a JSON pointer + + @since version 3.6.0 + */ + friend json_pointer operator/(const json_pointer& lhs, + const json_pointer& rhs) + { + return json_pointer(lhs) /= rhs; + } + + /*! + @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer + + @param[in] ptr JSON pointer + @param[in] token reference token + @return a new JSON pointer with unescaped @a token appended to @a ptr + + @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary} + + @complexity Linear in the length of @a ptr. + + @sa @ref operator/=(std::string) to append a reference token + + @since version 3.6.0 + */ + friend json_pointer operator/(const json_pointer& ptr, std::string token) + { + return json_pointer(ptr) /= std::move(token); + } + + /*! + @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer + + @param[in] ptr JSON pointer + @param[in] array_index array index + @return a new JSON pointer with @a array_index appended to @a ptr + + @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary} + + @complexity Linear in the length of @a ptr. + + @sa @ref operator/=(std::size_t) to append an array index + + @since version 3.6.0 + */ + friend json_pointer operator/(const json_pointer& ptr, std::size_t array_index) + { + return json_pointer(ptr) /= array_index; + } + + /*! + @brief returns the parent of this JSON pointer + + @return parent of this JSON pointer; in case this JSON pointer is the root, + the root itself is returned + + @complexity Linear in the length of the JSON pointer. + + @liveexample{The example shows the result of `parent_pointer` for different + JSON Pointers.,json_pointer__parent_pointer} + + @since version 3.6.0 + */ + json_pointer parent_pointer() const + { + if (empty()) + { + return *this; + } + + json_pointer res = *this; + res.pop_back(); + return res; + } + + /*! + @brief remove last reference token + + @pre not `empty()` + + @liveexample{The example shows the usage of `pop_back`.,json_pointer__pop_back} + + @complexity Constant. + + @throw out_of_range.405 if JSON pointer has no parent + + @since version 3.6.0 + */ + void pop_back() + { + if (JSON_HEDLEY_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); + } + + reference_tokens.pop_back(); + } + + /*! + @brief return last reference token + + @pre not `empty()` + @return last reference token + + @liveexample{The example shows the usage of `back`.,json_pointer__back} + + @complexity Constant. + + @throw out_of_range.405 if JSON pointer has no parent + + @since version 3.6.0 + */ + const std::string& back() const + { + if (JSON_HEDLEY_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); + } + + return reference_tokens.back(); + } + + /*! + @brief append an unescaped token at the end of the reference pointer + + @param[in] token token to add + + @complexity Amortized constant. + + @liveexample{The example shows the result of `push_back` for different + JSON Pointers.,json_pointer__push_back} + + @since version 3.6.0 + */ + void push_back(const std::string& token) + { + reference_tokens.push_back(token); + } + + /// @copydoc push_back(const std::string&) + void push_back(std::string&& token) + { + reference_tokens.push_back(std::move(token)); + } + + /*! + @brief return whether pointer points to the root document + + @return true iff the JSON pointer points to the root document + + @complexity Constant. + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + + @liveexample{The example shows the result of `empty` for different JSON + Pointers.,json_pointer__empty} + + @since version 3.6.0 + */ + bool empty() const noexcept + { + return reference_tokens.empty(); + } + + private: + /*! + @param[in] s reference token to be converted into an array index + + @return integer representation of @a s + + @throw out_of_range.404 if string @a s could not be converted to an integer + */ + static int array_index(const std::string& s) + { + std::size_t processed_chars = 0; + const int res = std::stoi(s, &processed_chars); + + // check if the string was completely read + if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size())) + { + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'")); + } + + return res; + } + + json_pointer top() const + { + if (JSON_HEDLEY_UNLIKELY(empty())) + { + JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); + } + + json_pointer result = *this; + result.reference_tokens = {reference_tokens[0]}; + return result; + } + + /*! + @brief create and return a reference to the pointed to value + + @complexity Linear in the number of reference tokens. + + @throw parse_error.109 if array index is not a number + @throw type_error.313 if value cannot be unflattened + */ + BasicJsonType& get_and_create(BasicJsonType& j) const + { + using size_type = typename BasicJsonType::size_type; + auto result = &j; + + // in case no reference tokens exist, return a reference to the JSON value + // j which will be overwritten by a primitive value + for (const auto& reference_token : reference_tokens) + { + switch (result->type()) + { + case detail::value_t::null: + { + if (reference_token == "0") + { + // start a new array if reference token is 0 + result = &result->operator[](0); + } + else + { + // start a new object otherwise + result = &result->operator[](reference_token); + } + break; + } + + case detail::value_t::object: + { + // create an entry in the object + result = &result->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + // create an entry in the array + JSON_TRY + { + result = &result->operator[](static_cast(array_index(reference_token))); + } + JSON_CATCH(std::invalid_argument&) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } + break; + } + + /* + The following code is only reached if there exists a reference + token _and_ the current value is primitive. In this case, we have + an error situation, because primitive values may only occur as + single value; that is, with an empty list of reference tokens. + */ + default: + JSON_THROW(detail::type_error::create(313, "invalid value to unflatten")); + } + } + + return *result; + } + + /*! + @brief return a reference to the pointed to value + + @note This version does not throw if a value is not present, but tries to + create nested values instead. For instance, calling this function + with pointer `"/this/that"` on a null value is equivalent to calling + `operator[]("this").operator[]("that")` on that value, effectively + changing the null value to an object. + + @param[in] ptr a JSON value + + @return reference to the JSON value pointed to by the JSON pointer + + @complexity Linear in the length of the JSON pointer. + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + BasicJsonType& get_unchecked(BasicJsonType* ptr) const + { + using size_type = typename BasicJsonType::size_type; + for (const auto& reference_token : reference_tokens) + { + // convert null values to arrays or objects before continuing + if (ptr->is_null()) + { + // check if reference token is a number + const bool nums = + std::all_of(reference_token.begin(), reference_token.end(), + [](const unsigned char x) + { + return std::isdigit(x); + }); + + // change value to array for numbers or "-" or to object otherwise + *ptr = (nums or reference_token == "-") + ? detail::value_t::array + : detail::value_t::object; + } + + switch (ptr->type()) + { + case detail::value_t::object: + { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0')) + { + JSON_THROW(detail::parse_error::create(106, 0, + "array index '" + reference_token + + "' must not begin with '0'")); + } + + if (reference_token == "-") + { + // explicitly treat "-" as index beyond the end + ptr = &ptr->operator[](ptr->m_value.array->size()); + } + else + { + // convert array index to number; unchecked access + JSON_TRY + { + ptr = &ptr->operator[]( + static_cast(array_index(reference_token))); + } + JSON_CATCH(std::invalid_argument&) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } + } + break; + } + + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + } + } + + return *ptr; + } + + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + BasicJsonType& get_checked(BasicJsonType* ptr) const + { + using size_type = typename BasicJsonType::size_type; + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + JSON_THROW(detail::out_of_range::create(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); + } + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0')) + { + JSON_THROW(detail::parse_error::create(106, 0, + "array index '" + reference_token + + "' must not begin with '0'")); + } + + // note: at performs range check + JSON_TRY + { + ptr = &ptr->at(static_cast(array_index(reference_token))); + } + JSON_CATCH(std::invalid_argument&) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } + break; + } + + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + } + } + + return *ptr; + } + + /*! + @brief return a const reference to the pointed to value + + @param[in] ptr a JSON value + + @return const reference to the JSON value pointed to by the JSON + pointer + + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const + { + using size_type = typename BasicJsonType::size_type; + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + // use unchecked object access + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" cannot be used for const access + JSON_THROW(detail::out_of_range::create(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); + } + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0')) + { + JSON_THROW(detail::parse_error::create(106, 0, + "array index '" + reference_token + + "' must not begin with '0'")); + } + + // use unchecked array access + JSON_TRY + { + ptr = &ptr->operator[]( + static_cast(array_index(reference_token))); + } + JSON_CATCH(std::invalid_argument&) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } + break; + } + + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + } + } + + return *ptr; + } + + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + @throw out_of_range.402 if the array index '-' is used + @throw out_of_range.404 if the JSON pointer can not be resolved + */ + const BasicJsonType& get_checked(const BasicJsonType* ptr) const + { + using size_type = typename BasicJsonType::size_type; + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + // note: at performs range check + ptr = &ptr->at(reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + JSON_THROW(detail::out_of_range::create(402, + "array index '-' (" + std::to_string(ptr->m_value.array->size()) + + ") is out of range")); + } + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0')) + { + JSON_THROW(detail::parse_error::create(106, 0, + "array index '" + reference_token + + "' must not begin with '0'")); + } + + // note: at performs range check + JSON_TRY + { + ptr = &ptr->at(static_cast(array_index(reference_token))); + } + JSON_CATCH(std::invalid_argument&) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } + break; + } + + default: + JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); + } + } + + return *ptr; + } + + /*! + @throw parse_error.106 if an array index begins with '0' + @throw parse_error.109 if an array index was not a number + */ + bool contains(const BasicJsonType* ptr) const + { + using size_type = typename BasicJsonType::size_type; + for (const auto& reference_token : reference_tokens) + { + switch (ptr->type()) + { + case detail::value_t::object: + { + if (not ptr->contains(reference_token)) + { + // we did not find the key in the object + return false; + } + + ptr = &ptr->operator[](reference_token); + break; + } + + case detail::value_t::array: + { + if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) + { + // "-" always fails the range check + return false; + } + + // error condition (cf. RFC 6901, Sect. 4) + if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1 and reference_token[0] == '0')) + { + JSON_THROW(detail::parse_error::create(106, 0, + "array index '" + reference_token + + "' must not begin with '0'")); + } + + JSON_TRY + { + const auto idx = static_cast(array_index(reference_token)); + if (idx >= ptr->size()) + { + // index out of range + return false; + } + + ptr = &ptr->operator[](idx); + break; + } + JSON_CATCH(std::invalid_argument&) + { + JSON_THROW(detail::parse_error::create(109, 0, "array index '" + reference_token + "' is not a number")); + } + break; + } + + default: + { + // we do not expect primitive values if there is still a + // reference token to process + return false; + } + } + } + + // no reference token left means we found a primitive value + return true; + } + + /*! + @brief split the string input to reference tokens + + @note This function is only called by the json_pointer constructor. + All exceptions below are documented there. + + @throw parse_error.107 if the pointer is not empty or begins with '/' + @throw parse_error.108 if character '~' is not followed by '0' or '1' + */ + static std::vector split(const std::string& reference_string) + { + std::vector result; + + // special case: empty reference string -> no reference tokens + if (reference_string.empty()) + { + return result; + } + + // check if nonempty reference string begins with slash + if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) + { + JSON_THROW(detail::parse_error::create(107, 1, + "JSON pointer must be empty or begin with '/' - was: '" + + reference_string + "'")); + } + + // extract the reference tokens: + // - slash: position of the last read slash (or end of string) + // - start: position after the previous slash + for ( + // search for the first slash after the first character + std::size_t slash = reference_string.find_first_of('/', 1), + // set the beginning of the first reference token + start = 1; + // we can stop if start == 0 (if slash == std::string::npos) + start != 0; + // set the beginning of the next reference token + // (will eventually be 0 if slash == std::string::npos) + start = (slash == std::string::npos) ? 0 : slash + 1, + // find next slash + slash = reference_string.find_first_of('/', start)) + { + // use the text between the beginning of the reference token + // (start) and the last slash (slash). + auto reference_token = reference_string.substr(start, slash - start); + + // check reference tokens are properly escaped + for (std::size_t pos = reference_token.find_first_of('~'); + pos != std::string::npos; + pos = reference_token.find_first_of('~', pos + 1)) + { + assert(reference_token[pos] == '~'); + + // ~ must be followed by 0 or 1 + if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 or + (reference_token[pos + 1] != '0' and + reference_token[pos + 1] != '1'))) + { + JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'")); + } + } + + // finally, store the reference token + unescape(reference_token); + result.push_back(reference_token); + } + + return result; + } + + /*! + @brief replace all occurrences of a substring by another string + + @param[in,out] s the string to manipulate; changed so that all + occurrences of @a f are replaced with @a t + @param[in] f the substring to replace with @a t + @param[in] t the string to replace @a f + + @pre The search string @a f must not be empty. **This precondition is + enforced with an assertion.** + + @since version 2.0.0 + */ + static void replace_substring(std::string& s, const std::string& f, + const std::string& t) + { + assert(not f.empty()); + for (auto pos = s.find(f); // find first occurrence of f + pos != std::string::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find next occurrence of f + {} + } + + /// escape "~" to "~0" and "/" to "~1" + static std::string escape(std::string s) + { + replace_substring(s, "~", "~0"); + replace_substring(s, "/", "~1"); + return s; + } + + /// unescape "~1" to tilde and "~0" to slash (order is important!) + static void unescape(std::string& s) + { + replace_substring(s, "~1", "/"); + replace_substring(s, "~0", "~"); + } + + /*! + @param[in] reference_string the reference string to the current value + @param[in] value the value to consider + @param[in,out] result the result object to insert values to + + @note Empty objects or arrays are flattened to `null`. + */ + static void flatten(const std::string& reference_string, + const BasicJsonType& value, + BasicJsonType& result) + { + switch (value.type()) + { + case detail::value_t::array: + { + if (value.m_value.array->empty()) + { + // flatten empty array as null + result[reference_string] = nullptr; + } + else + { + // iterate array and use index as reference string + for (std::size_t i = 0; i < value.m_value.array->size(); ++i) + { + flatten(reference_string + "/" + std::to_string(i), + value.m_value.array->operator[](i), result); + } + } + break; + } + + case detail::value_t::object: + { + if (value.m_value.object->empty()) + { + // flatten empty object as null + result[reference_string] = nullptr; + } + else + { + // iterate object and use keys as reference string + for (const auto& element : *value.m_value.object) + { + flatten(reference_string + "/" + escape(element.first), element.second, result); + } + } + break; + } + + default: + { + // add primitive value with its reference string + result[reference_string] = value; + break; + } + } + } + + /*! + @param[in] value flattened JSON + + @return unflattened JSON + + @throw parse_error.109 if array index is not a number + @throw type_error.314 if value is not an object + @throw type_error.315 if object values are not primitive + @throw type_error.313 if value cannot be unflattened + */ + static BasicJsonType + unflatten(const BasicJsonType& value) + { + if (JSON_HEDLEY_UNLIKELY(not value.is_object())) + { + JSON_THROW(detail::type_error::create(314, "only objects can be unflattened")); + } + + BasicJsonType result; + + // iterate the JSON object values + for (const auto& element : *value.m_value.object) + { + if (JSON_HEDLEY_UNLIKELY(not element.second.is_primitive())) + { + JSON_THROW(detail::type_error::create(315, "values in object must be primitive")); + } + + // assign value to reference pointed to by JSON pointer; Note that if + // the JSON pointer is "" (i.e., points to the whole value), function + // get_and_create returns a reference to result itself. An assignment + // will then create a primitive value. + json_pointer(element.first).get_and_create(result) = element.second; + } + + return result; + } + + /*! + @brief compares two JSON pointers for equality + + @param[in] lhs JSON pointer to compare + @param[in] rhs JSON pointer to compare + @return whether @a lhs is equal to @a rhs + + @complexity Linear in the length of the JSON pointer + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + */ + friend bool operator==(json_pointer const& lhs, + json_pointer const& rhs) noexcept + { + return lhs.reference_tokens == rhs.reference_tokens; + } + + /*! + @brief compares two JSON pointers for inequality + + @param[in] lhs JSON pointer to compare + @param[in] rhs JSON pointer to compare + @return whether @a lhs is not equal @a rhs + + @complexity Linear in the length of the JSON pointer + + @exceptionsafety No-throw guarantee: this function never throws exceptions. + */ + friend bool operator!=(json_pointer const& lhs, + json_pointer const& rhs) noexcept + { + return not (lhs == rhs); + } + + /// the reference tokens + std::vector reference_tokens; +}; +} // namespace nlohmann diff --git a/thirdparty/nlohmann/detail/json_ref.hpp b/thirdparty/nlohmann/detail/json_ref.hpp new file mode 100644 index 00000000000..c8dec7330f2 --- /dev/null +++ b/thirdparty/nlohmann/detail/json_ref.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include +#include + +#include + +namespace nlohmann +{ +namespace detail +{ +template +class json_ref +{ + public: + using value_type = BasicJsonType; + + json_ref(value_type&& value) + : owned_value(std::move(value)), value_ref(&owned_value), is_rvalue(true) + {} + + json_ref(const value_type& value) + : value_ref(const_cast(&value)), is_rvalue(false) + {} + + json_ref(std::initializer_list init) + : owned_value(init), value_ref(&owned_value), is_rvalue(true) + {} + + template < + class... Args, + enable_if_t::value, int> = 0 > + json_ref(Args && ... args) + : owned_value(std::forward(args)...), value_ref(&owned_value), + is_rvalue(true) {} + + // class should be movable only + json_ref(json_ref&&) = default; + json_ref(const json_ref&) = delete; + json_ref& operator=(const json_ref&) = delete; + json_ref& operator=(json_ref&&) = delete; + ~json_ref() = default; + + value_type moved_or_copied() const + { + if (is_rvalue) + { + return std::move(*value_ref); + } + return *value_ref; + } + + value_type const& operator*() const + { + return *static_cast(value_ref); + } + + value_type const* operator->() const + { + return static_cast(value_ref); + } + + private: + mutable value_type owned_value = nullptr; + value_type* value_ref = nullptr; + const bool is_rvalue; +}; +} // namespace detail +} // namespace nlohmann diff --git a/thirdparty/nlohmann/detail/macro_scope.hpp b/thirdparty/nlohmann/detail/macro_scope.hpp new file mode 100644 index 00000000000..27dddc6be76 --- /dev/null +++ b/thirdparty/nlohmann/detail/macro_scope.hpp @@ -0,0 +1,121 @@ +#pragma once + +#include // pair +#include + +// This file contains all internal macro definitions +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// C++ language standard detection +#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 +#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 +#endif + +// disable float-equal warnings on GCC/clang +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdocumentation" +#endif + +// allow to disable exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #include + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json diff --git a/thirdparty/nlohmann/detail/macro_unscope.hpp b/thirdparty/nlohmann/detail/macro_unscope.hpp new file mode 100644 index 00000000000..80b293e7d59 --- /dev/null +++ b/thirdparty/nlohmann/detail/macro_unscope.hpp @@ -0,0 +1,21 @@ +#pragma once + +// restore GCC/clang diagnostic settings +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #pragma GCC diagnostic pop +#endif +#if defined(__clang__) + #pragma GCC diagnostic pop +#endif + +// clean up +#undef JSON_INTERNAL_CATCH +#undef JSON_CATCH +#undef JSON_THROW +#undef JSON_TRY +#undef JSON_HAS_CPP_14 +#undef JSON_HAS_CPP_17 +#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION +#undef NLOHMANN_BASIC_JSON_TPL + +#include diff --git a/thirdparty/nlohmann/detail/meta/cpp_future.hpp b/thirdparty/nlohmann/detail/meta/cpp_future.hpp new file mode 100644 index 00000000000..948cd4fb0cb --- /dev/null +++ b/thirdparty/nlohmann/detail/meta/cpp_future.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include // not +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type + +namespace nlohmann +{ +namespace detail +{ +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +template +using uncvref_t = typename std::remove_cv::type>::type; + +// implementation of C++14 index_sequence and affiliates +// source: https://stackoverflow.com/a/32223343 +template +struct index_sequence +{ + using type = index_sequence; + using value_type = std::size_t; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +template +struct merge_and_renumber; + +template +struct merge_and_renumber, index_sequence> + : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; + +template +struct make_index_sequence + : merge_and_renumber < typename make_index_sequence < N / 2 >::type, + typename make_index_sequence < N - N / 2 >::type > {}; + +template<> struct make_index_sequence<0> : index_sequence<> {}; +template<> struct make_index_sequence<1> : index_sequence<0> {}; + +template +using index_sequence_for = make_index_sequence; + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static constexpr T value{}; +}; + +template +constexpr T static_const::value; +} // namespace detail +} // namespace nlohmann diff --git a/thirdparty/nlohmann/detail/meta/detected.hpp b/thirdparty/nlohmann/detail/meta/detected.hpp new file mode 100644 index 00000000000..5b52460acf6 --- /dev/null +++ b/thirdparty/nlohmann/detail/meta/detected.hpp @@ -0,0 +1,58 @@ +#pragma once + +#include + +#include + +// http://en.cppreference.com/w/cpp/experimental/is_detected +namespace nlohmann +{ +namespace detail +{ +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template