diff --git a/configure b/configure index 649ad635..35a55a29 100755 --- a/configure +++ b/configure @@ -1070,6 +1070,7 @@ enable_GSDS enable_HCRS enable_HPRS enable_SSE +enable_websocket_parallelization enable_http2 enable_check_time enable_classic @@ -1807,7 +1808,8 @@ Optional Features: --enable-GSDS enable GDB Stack Dump Support [default=no] --enable-HCRS enable Cache Request Support [default=no] --enable-HPRS enable Homogeneous Pipeline Request Support [default=no] - --enable-SSE enable Server-Sent Events Support [default=no] + --enable-SSE enable Server-Sent Events support [default=no] + --enable-websocket-parallelization enable Websocket parallelization support [default=yes] --enable-http2 enable HTTP/2 support [default=no] --enable-check-time enable server check time between request for parallelization [default=no] --enable-classic enable server classic model support [default=no] @@ -28185,6 +28187,24 @@ $as_echo "#define U_SSE_ENABLE 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_SSE" >&5 $as_echo "$enable_SSE" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if you want to enable Websocket parallelization support" >&5 +$as_echo_n "checking if you want to enable Websocket parallelization support... " >&6; } + # Check whether --enable-websocket-parallelization was given. +if test "${enable_websocket_parallelization+set}" = set; then : + enableval=$enable_websocket_parallelization; +fi + + if test -z "$enable_websocket_parallelization"; then + enable_websocket_parallelization="yes" + fi + if test "$enable_websocket_parallelization" = "yes"; then + +$as_echo "#define U_WEBSOCKET_PARALLELIZATION 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_websocket_parallelization" >&5 +$as_echo "$enable_websocket_parallelization" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if you want to enable HTTP/2 support" >&5 $as_echo_n "checking if you want to enable HTTP/2 support... " >&6; } # Check whether --enable-http2 was given. diff --git a/include/ulib/internal/config.h.in b/include/ulib/internal/config.h.in index 530913e2..0d55e413 100644 --- a/include/ulib/internal/config.h.in +++ b/include/ulib/internal/config.h.in @@ -952,6 +952,9 @@ /* enable server bandwidth throttling support */ #undef U_THROTTLING_SUPPORT +/* enable Websocket parallelization support */ +#undef U_WEBSOCKET_PARALLELIZATION + /* enable welcome message support */ #undef U_WELCOME_SUPPORT diff --git a/include/ulib/notifier.h b/include/ulib/notifier.h index 32f061d1..4637f9ba 100644 --- a/include/ulib/notifier.h +++ b/include/ulib/notifier.h @@ -51,6 +51,8 @@ #include #include +#define U_NOTIFY_DELETE 0x010 + class USocket; class UTimeStat; class USocketExt; diff --git a/ltmain.sh b/ltmain.sh index b2549eeb..e774ddfe 100644 --- a/ltmain.sh +++ b/ltmain.sh @@ -7127,6 +7127,16 @@ func_mode_link () *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac + + # As we are forced to pass -nostdlib to g++ during linking, the option + # -pthread{,s} is not in effect; add the -lpthread to $deplist + # explicitly to link correctly. + if test "$tagname" = CXX -a x"$with_gcc" = xyes; then + case "$arg" in + -pthread*) func_append deplibs " -lpthread" ;; + esac + fi + continue ;; diff --git a/m4/ac_compilation_options.m4 b/m4/ac_compilation_options.m4 index f98d52ec..009e134c 100644 --- a/m4/ac_compilation_options.m4 +++ b/m4/ac_compilation_options.m4 @@ -211,7 +211,7 @@ AC_DEFUN([AC_COMPILATION_OPTIONS],[ AC_MSG_CHECKING(if you want to enable Server-Sent Events support) AC_ARG_ENABLE(SSE, - [ --enable-SSE enable Server-Sent Events Support [[default=no]]]) + [ --enable-SSE enable Server-Sent Events support [[default=no]]]) if test -z "$enable_SSE"; then enable_SSE="no" fi @@ -220,6 +220,17 @@ AC_DEFUN([AC_COMPILATION_OPTIONS],[ fi AC_MSG_RESULT([$enable_SSE]) + AC_MSG_CHECKING(if you want to enable Websocket parallelization support) + AC_ARG_ENABLE(websocket-parallelization, + [ --enable-websocket-parallelization enable Websocket parallelization support [[default=yes]]]) + if test -z "$enable_websocket_parallelization"; then + enable_websocket_parallelization="yes" + fi + if test "$enable_websocket_parallelization" = "yes"; then + AC_DEFINE(U_WEBSOCKET_PARALLELIZATION, 1, [enable Websocket parallelization support]) + fi + AC_MSG_RESULT([$enable_websocket_parallelization]) + AC_MSG_CHECKING(if you want to enable HTTP/2 support) AC_ARG_ENABLE(http2, [ --enable-http2 enable HTTP/2 support [[default=no]]]) diff --git a/src/ulib/net/server/client_image.cpp b/src/ulib/net/server/client_image.cpp index d7638673..99d2720e 100644 --- a/src/ulib/net/server/client_image.cpp +++ b/src/ulib/net/server/client_image.cpp @@ -473,6 +473,18 @@ void UClientImage_Base::handlerDelete() U_INTERNAL_ASSERT_DIFFERS(U_ClientImage_parallelization, U_PARALLELIZATION_CHILD) + bool bdelete = (U_ClientImage_state == U_NOTIFY_DELETE); + + U_INTERNAL_DUMP("U_ClientImage_state = %d %B bdelete = %b bsocket_open = %b", U_ClientImage_state, U_ClientImage_state, bdelete, bsocket_open) + + if (bdelete && + bsocket_open) + { + socket->close(); + + bsocket_open = false; + } + #ifndef U_LOG_DISABLE if (UServer_Base::isLog()) { @@ -482,7 +494,7 @@ void UClientImage_Base::handlerDelete() char buffer[32]; uint32_t len = UServer_Base::setNumConnection(buffer); - const char* agent = (bsocket_open == false || UServer_Base::isParallelizationParent() ? "Server" : "Client"); + const char* agent = (bdelete || bsocket_open ? "Client" : "Server"); UServer_Base::log->log(U_CONSTANT_TO_PARAM("%.6s close connection from %v, %.*s clients still connected"), agent, logbuf->rep, len, buffer); @@ -514,12 +526,21 @@ void UClientImage_Base::handlerDelete() if (UServer_Base::isClassic()) U_EXIT(0); #endif -#ifndef U_HTTP2_DISABLE U_INTERNAL_DUMP("U_ClientImage_http = %C U_http_version = %C", U_ClientImage_http(this), U_http_version) +#ifndef U_HTTP2_DISABLE if (U_ClientImage_http(this) == '2') UHTTP2::handlerDelete(this, bsocket_open); #endif +#ifndef U_WEBSOCKET_PARALLELIZATION + if (U_ClientImage_http(this) == '0') + { + if (bsocket_open) (void) UWebSocket::sendClose(socket); + + UWebSocket::on_message_param(U_DPAGE_CLOSE); + } +#endif + if (bsocket_open) socket->close(); --UNotifier::num_connection; @@ -1297,11 +1318,29 @@ data_missing: if (U_ClientImage_parallelization == U_PARALLELIZATION_PARENT) U_RETURN(U_NOTIFIER_DELETE); #endif + U_INTERNAL_ASSERT_EQUALS(UServer_Base::csocket, UServer_Base::pClientImage->socket) + resetBuffer(); - size_request = 0; +#ifndef U_WEBSOCKET_PARALLELIZATION + U_INTERNAL_DUMP("U_ClientImage_http = %C U_http_version = %C", U_ClientImage_http(this), U_http_version) - U_INTERNAL_ASSERT_EQUALS(UServer_Base::csocket, UServer_Base::pClientImage->socket) + if (U_ClientImage_http(this) == '0') + { + if (UWebSocket::handleDataFraming(socket) == U_WS_STATUS_CODE_OK) + { + UWebSocket::on_message(); + + UWebSocket::rbuffer->setEmpty(); + + if (U_http_info.nResponseCode == HTTP_INTERNAL_ERROR) U_RETURN(U_NOTIFIER_DELETE); + } + + U_RETURN(U_NOTIFIER_OK); + } +#endif + + size_request = 0; U_ClientImage_state = callerHandlerRead(); @@ -1450,9 +1489,24 @@ check: U_INTERNAL_DUMP("nrequest = %u resto = %u", nrequest, resto) if (isRequestNeedProcessing()) { - U_INTERNAL_ASSERT_DIFFERS(U_ClientImage_parallelization, U_PARALLELIZATION_PARENT) U_INTERNAL_ASSERT_EQUALS(U_ClientImage_state & (U_PLUGIN_HANDLER_AGAIN | U_PLUGIN_HANDLER_ERROR), 0) +# ifdef U_WEBSOCKET_PARALLELIZATION + U_INTERNAL_ASSERT_DIFFERS(U_ClientImage_parallelization, U_PARALLELIZATION_PARENT) +# else + if (U_ClientImage_parallelization == U_PARALLELIZATION_PARENT) + { + U_ASSERT(wbuffer->empty()) + U_INTERNAL_ASSERT_EQUALS(U_ClientImage_data_missing, false) + + endRequest(); + + U_ClientImage_parallelization = 0; + + U_RETURN(U_NOTIFIER_OK); + } +# endif + callerHandlerRequest(); if (UNLIKELY(socket->isClosed())) goto cls; diff --git a/src/ulib/notifier.cpp b/src/ulib/notifier.cpp index 15ba7430..1ccaa60a 100644 --- a/src/ulib/notifier.cpp +++ b/src/ulib/notifier.cpp @@ -568,6 +568,8 @@ loop0: if (bdelete) { + U_ClientImage_state = U_NOTIFY_DELETE; + handlerDelete(handler_event); # if defined(U_EPOLLET_POSTPONE_STRATEGY) diff --git a/src/ulib/utility/uhttp.cpp b/src/ulib/utility/uhttp.cpp index 125c2611..0461dcd3 100644 --- a/src/ulib/utility/uhttp.cpp +++ b/src/ulib/utility/uhttp.cpp @@ -4641,9 +4641,19 @@ from_cache: } else { +# ifdef U_WEBSOCKET_PARALLELIZATION UClientImage_Base::setRequestNoCache(); if (UServer_Base::startParallelization() == false) UWebSocket::handlerRequest(); // child +# else + UWebSocket::checkForInitialData(); // check if we have read more data than necessary... + + UWebSocket::on_message_param(U_DPAGE_OPEN); + + U_ClientImage_http(UServer_Base::pClientImage) = '0'; + + U_ClientImage_parallelization = U_PARALLELIZATION_PARENT; +# endif } U_RETURN(U_PLUGIN_HANDLER_OK); diff --git a/src/ulib/utility/websocket.cpp b/src/ulib/utility/websocket.cpp index 533b2d13..66889a41 100644 --- a/src/ulib/utility/websocket.cpp +++ b/src/ulib/utility/websocket.cpp @@ -708,9 +708,12 @@ bool UWebSocket::sendControlFrame(USocket* socket, int opcode, const unsigned ch header[6+i] = (payload[i] ^ masking_key[i % 4]) & 0xff; } - U_SRV_LOG_WITH_ADDR("send control frame(%d) (6+%u bytes) %.*S to", opcode, payload_length, payload_length, payload) + if (USocketExt::write(socket, (const char*)header, ncount, UServer_Base::timeoutMS) == ncount) + { + U_SRV_LOG_WITH_ADDR("send control frame(%d) (6+%u bytes) %.*S to", opcode, payload_length, payload_length, payload) - if (USocketExt::write(socket, (const char*)header, ncount, UServer_Base::timeoutMS) == ncount) U_RETURN(true); + U_RETURN(true); + } U_RETURN(false); } diff --git a/tests/examples/TSA/tsaserial b/tests/examples/TSA/tsaserial index c7aa18a2..c635f61f 100644 --- a/tests/examples/TSA/tsaserial +++ b/tests/examples/TSA/tsaserial @@ -1 +1 @@ -0469 +0470