diff --git a/examples/IR/ir_web.cpp b/examples/IR/ir_web.cpp index 4b825e8b..e7db3c35 100644 --- a/examples/IR/ir_web.cpp +++ b/examples/IR/ir_web.cpp @@ -53,7 +53,7 @@ extern U_EXPORT void runDynamicPage_ir_web(int param); { if (param == U_DPAGE_INIT) { usp_init_ir_web(); return; } if (param == U_DPAGE_DESTROY) { usp_end_ir_web(); return; } - if (param >= U_DPAGE_FORK) return; + return; } UHTTP::mime_index = U_html; diff --git a/examples/WiAuth/v2/wi_auth2.cpp b/examples/WiAuth/v2/wi_auth2.cpp index a22df832..4d8b3301 100644 --- a/examples/WiAuth/v2/wi_auth2.cpp +++ b/examples/WiAuth/v2/wi_auth2.cpp @@ -19,7 +19,7 @@ extern U_EXPORT void runDynamicPage_wi_auth2(int param); if (param == U_DPAGE_INIT) { usp_init_wi_auth2(); return; } if (param == U_DPAGE_DESTROY) { usp_end_wi_auth2(); return; } if (param == U_DPAGE_FORK) { usp_fork_wi_auth2(); return; } - if (param > U_DPAGE_FORK) return; + return; } U_http_info.endHeader = 0; diff --git a/examples/WiAuth/v2/wi_auth_declaration2.h b/examples/WiAuth/v2/wi_auth_declaration2.h index 4368ee64..2f06fe70 100644 --- a/examples/WiAuth/v2/wi_auth_declaration2.h +++ b/examples/WiAuth/v2/wi_auth_declaration2.h @@ -94,10 +94,10 @@ loop: U_INTERNAL_ASSERT(lnetmask) U_ASSERT(vnetmask.empty()) - U_INTERNAL_DUMP("tok.current() = %C", tok.current()) + U_INTERNAL_DUMP("tok.previous() = %C tok.current() = %C", tok.previous(), tok.current()) - if (u__isdigit(tok.current())) name.clear(); - else (void) tok.next(name, (bool*)U_NULLPTR); + if (tok.previous() != ',') name.clear(); + else (void) tok.next(name, (bool*)U_NULLPTR); vnetmask.push_back(lnetmask); @@ -613,7 +613,7 @@ static void deleteSession() (void) rc->zrem(U_CONSTANT_TO_PARAM("SESSION:byCaptiveIdAndApId deviceId:%v;ip:%v"), mac->rep, ip->rep); (void) rc->zrem(U_CONSTANT_TO_PARAM("SESSION:byLastUpdate %v"), key_session->rep); - U_LOGGER("*** SESSION(%V) deleted at deleteSession() ***", key_session->rep); +// U_LOGGER("*** SESSION(%V) deleted at deleteSession() ***", key_session->rep); } static void resetDeviceDailyCounter() @@ -1111,7 +1111,7 @@ static void POST_login() (void) rc->hmset(U_CONSTANT_TO_PARAM("SESSION:%v captiveId %u apId %v deviceId %v ip %v created %u pId %v notify %c consume %c counter 0 lastUpdate %u"), key_session->rep, addr, ap_label->rep, mac->rep, ip->rep, u_now->tv_sec, policySessionId->rep, buffer[1], '0'+ap_consume, u_now->tv_sec); - U_LOGGER("*** SESSION(%V) created at POST_login() ***", key_session->rep); + // U_LOGGER("*** SESSION(%V) created at POST_login() ***", key_session->rep); (void) rc->zadd(U_CONSTANT_TO_PARAM("SESSION:byCaptiveIdAndApId %u%06u deviceId:%v;ip:%v"), addr, ap_label->strtoul(), mac->rep, ip->rep); (void) rc->zadd(U_CONSTANT_TO_PARAM("SESSION:byLastUpdate %u %v"), u_now->tv_sec, key_session->rep); diff --git a/examples/WiAuth/wi_auth.cpp b/examples/WiAuth/wi_auth.cpp index d0d038bd..b2efa32a 100644 --- a/examples/WiAuth/wi_auth.cpp +++ b/examples/WiAuth/wi_auth.cpp @@ -19,7 +19,7 @@ extern U_EXPORT void runDynamicPage_wi_auth(int param); if (param == U_DPAGE_INIT) { usp_init_wi_auth(); return; } if (param == U_DPAGE_DESTROY) { usp_end_wi_auth(); return; } if (param == U_DPAGE_SIGHUP) { usp_sighup_wi_auth(); return; } - if (param >= U_DPAGE_FORK) return; + return; } U_http_info.endHeader = 0; diff --git a/examples/userver/userver.cfg.default b/examples/userver/userver.cfg.default index 0651732c..d033fd83 100644 --- a/examples/userver/userver.cfg.default +++ b/examples/userver/userver.cfg.default @@ -416,8 +416,8 @@ http { # ------------------------------------------------------------------------------------------------------------------------------------------------ # socket - plugin parameters # ------------------------------------------------------------------------------------------------------------------------------------------------ -# COMMAND command (alternative to USP websocket) to execute -# ENVIRONMENT environment for command (alternative to USP websocket) to execute +# COMMAND command (alternative to USP modsocket) to execute +# ENVIRONMENT environment for command (alternative to USP modsocket) to execute # # MAX_MESSAGE_SIZE Maximum size (in bytes) of a message to accept; default is approximately 4GB # ------------------------------------------------------------------------------------------------------------------------------------------------ diff --git a/include/ulib/all.h b/include/ulib/all.h index 306b88b2..1f310662 100644 --- a/include/ulib/all.h +++ b/include/ulib/all.h @@ -53,6 +53,7 @@ # include # include # include +# include # include # include # ifdef HAVE_SSL_TS diff --git a/include/ulib/dynamic/dynamic.h b/include/ulib/dynamic/dynamic.h index 6ed2c75c..cbb5880d 100644 --- a/include/ulib/dynamic/dynamic.h +++ b/include/ulib/dynamic/dynamic.h @@ -41,7 +41,9 @@ enum DynamicPageType { U_DPAGE_RESET = -2, U_DPAGE_DESTROY = -3, U_DPAGE_SIGHUP = -4, - U_DPAGE_FORK = -5 + U_DPAGE_FORK = -5, + U_DPAGE_OPEN = -6, + U_DPAGE_CLOSE = -7 }; /** diff --git a/include/ulib/examples/wi_auth_declaration.h b/include/ulib/examples/wi_auth_declaration.h index 3d37217d..65ea0c9d 100644 --- a/include/ulib/examples/wi_auth_declaration.h +++ b/include/ulib/examples/wi_auth_declaration.h @@ -4163,7 +4163,9 @@ static bool runAuthCmd(const char* password, const char* prealm) *output = UCommand::outputCommand(cmd, U_NULLPTR, -1, fd_stderr); +#ifdef U_LOG_DISABLE UServer_Base::logCommandMsgError(cmd.data(), true); +#endif if (UCommand::exit_value || output->empty()) diff --git a/include/ulib/mime/header.h b/include/ulib/mime/header.h index a9c7d61e..1e081db6 100644 --- a/include/ulib/mime/header.h +++ b/include/ulib/mime/header.h @@ -178,9 +178,8 @@ public: U_ASSERT(empty() == false) - if (getHeader(U_CONSTANT_TO_PARAM("Connection")).equal(U_CONSTANT_TO_PARAM("close"))) + if (getHeader(U_CONSTANT_TO_PARAM("Connection")).equal(U_CONSTANT_TO_PARAM("close"))) U_RETURN(true); - U_RETURN(true); U_RETURN(false); } diff --git a/include/ulib/net/client/client.h b/include/ulib/net/client/client.h index d6c05eab..47848f0d 100644 --- a/include/ulib/net/client/client.h +++ b/include/ulib/net/client/client.h @@ -16,6 +16,7 @@ #include #include +#include #include #ifdef USE_LIBSSL @@ -39,6 +40,7 @@ class USCGIPlugIn; class UProxyPlugIn; class UNoCatPlugIn; class UServer_Base; +class UWebSocketClient; class UHttpClient_Base; class UClientImage_Base; class UREDISClient_Base; @@ -297,6 +299,8 @@ protected: bool sendRequestAndReadResponse() { return sendRequest(true); } + bool processHeader(UMimeHeader* responseHeader) { return responseHeader->readHeader(socket, response); } + #ifdef USE_LIBSSL void setSSLContext(); @@ -329,6 +333,7 @@ private: friend class UProxyPlugIn; friend class UNoCatPlugIn; friend class UServer_Base; + friend class UWebSocketClient; friend class UHttpClient_Base; friend class UClientImage_Base; friend class UREDISClient_Base; diff --git a/include/ulib/net/client/http.h b/include/ulib/net/client/http.h index 4820b1c1..1076e732 100644 --- a/include/ulib/net/client/http.h +++ b/include/ulib/net/client/http.h @@ -33,7 +33,6 @@ */ class UHTTP; -class UMimeHeader; class Application; class WiAuthNodog; class UServer_Base; diff --git a/include/ulib/net/client/websocket.h b/include/ulib/net/client/websocket.h new file mode 100644 index 00000000..bb131a5a --- /dev/null +++ b/include/ulib/net/client/websocket.h @@ -0,0 +1,104 @@ +// ============================================================================ +// +// = LIBRARY +// ULib - c++ library +// +// = FILENAME +// websocket.h - simple websocket client +// +// = AUTHOR +// Stefano Casazza +// +// ============================================================================ + +#ifndef ULIB_WEBSOCKET_CLIENT_H +#define ULIB_WEBSOCKET_CLIENT_H 1 + +#include +#include +#include + +/** + * @class UWebSocketClient + */ + +class U_EXPORT UWebSocketClient { +public: + + // Check for memory error + U_MEMORY_TEST + + // Allocator e Deallocator + U_MEMORY_ALLOCATOR + U_MEMORY_DEALLOCATOR + + /** + * Constructor + */ + + UWebSocketClient() + { + U_TRACE_CTOR(0, UWebSocketClient, "", 0) + + U_NEW(UClient, client, UClient(U_NULLPTR)); + } + + ~UWebSocketClient() + { + U_TRACE_DTOR(0, UWebSocketClient) + + U_INTERNAL_ASSERT_POINTER(client) + + U_DELETE(client) + } + + // SERVICES + + bool readMessage() + { + U_TRACE_NO_PARAM(0, "UWebSocketClient::readMessage()") + + U_INTERNAL_ASSERT_POINTER(client) + + UWebSocket::rbuffer->setEmpty(); + + if (UWebSocket::handleDataFraming(client->UClient_Base::socket) == U_WS_STATUS_CODE_OK) U_RETURN(true); + + U_RETURN(false); + } + + bool sendMessage(const UString& msg, int type = U_WS_MESSAGE_TYPE_TEXT) + { + U_TRACE(0, "UWebSocketClient::sendMessage(%V,%d)", msg.rep, type) + + U_INTERNAL_ASSERT_POINTER(client) + + return UWebSocket::sendData(client->UClient_Base::socket, type, msg); + } + + void close() + { + U_TRACE_NO_PARAM(0, "UWebSocketClient::close()") + + U_INTERNAL_ASSERT_POINTER(client) + + (void) UWebSocket::sendClose(client->UClient_Base::socket); + + client->UClient_Base::close(); + } + + bool connectServer(const UString& url); + + UClient* getClient() const { return client; } + +#if defined(U_STDCPP_ENABLE) && defined(DEBUG) + const char* dump(bool reset) const; +#endif + +protected: + UClient* client; + +private: + U_DISALLOW_COPY_AND_ASSIGN(UWebSocketClient) +}; +#endif diff --git a/include/ulib/net/server/plugin/mod_nocat.h b/include/ulib/net/server/plugin/mod_nocat.h index 6e1608b4..93953b18 100644 --- a/include/ulib/net/server/plugin/mod_nocat.h +++ b/include/ulib/net/server/plugin/mod_nocat.h @@ -300,9 +300,7 @@ protected: (void) peer->fw.executeAndWait(U_NULLPTR, -1, fd_stderr); -# ifndef U_LOG_DISABLE - UServer_Base::logCommandMsgError(peer->fw.getCommand(), false); -# endif + U_SRV_LOG_CMD_MSG_ERR(peer->fw, false); U_peer_status = type; } diff --git a/include/ulib/net/server/plugin/mod_nodog.h b/include/ulib/net/server/plugin/mod_nodog.h index bfd4dbfd..1912c74c 100644 --- a/include/ulib/net/server/plugin/mod_nodog.h +++ b/include/ulib/net/server/plugin/mod_nodog.h @@ -266,7 +266,7 @@ protected: { U_TRACE(0, "UNoDogPlugIn::setRedirect(%p,%u)", buffer, bufsize) - return u__snprintf(buffer, bufsize, U_CONSTANT_TO_PARAM("http://%.*s/%.*s"), U_HTTP_HOST_TO_TRACE, U_HTTP_URI_QUERY_TO_TRACE); + return u__snprintf(buffer, bufsize, U_CONSTANT_TO_PARAM("http://%.*s%.*s"), U_HTTP_HOST_TO_TRACE, U_HTTP_URI_QUERY_TO_TRACE); } static uint32_t getApInfo(char* buffer, uint32_t bufsize, const UString& lbl) diff --git a/include/ulib/net/server/plugin/mod_socket.h b/include/ulib/net/server/plugin/mod_socket.h index 2cec8a33..2e312d26 100644 --- a/include/ulib/net/server/plugin/mod_socket.h +++ b/include/ulib/net/server/plugin/mod_socket.h @@ -45,8 +45,10 @@ public: #endif protected: + static int fd_stderr; static vPFi on_message; static UCommand* command; + static UString* penvironment; static RETSIGTYPE handlerForSigTERM(int signo); diff --git a/include/ulib/net/server/server.h b/include/ulib/net/server/server.h index dd401382..50f6043b 100644 --- a/include/ulib/net/server/server.h +++ b/include/ulib/net/server/server.h @@ -86,7 +86,11 @@ vClientImage = new client_type[UNotifier::max_connection]; } } # define U_SRV_LOG( fmt,args...) {} # define U_SRV_LOG_WITH_ADDR(fmt,args...) {} + +# define U_SRV_LOG_CMD_MSG_ERR(cmd,balways) {} #else +# define U_SRV_LOG_CMD_MSG_ERR(cmd,balways) { if (UServer_Base::isLog()) UServer_Base::logCommandMsgError((cmd).getCommand(),balways); } + # define U_RESET_MODULE_NAME { if (UServer_Base::isLog()) (void) strcpy(UServer_Base::mod_name[0], UServer_Base::mod_name[1]); } # define U_SET_MODULE_NAME(name) { if (UServer_Base::isLog()) { (void) strcpy(UServer_Base::mod_name[1], UServer_Base::mod_name[0]); \ (void) strcpy(UServer_Base::mod_name[0], "["#name"] "); } } @@ -94,6 +98,7 @@ vClientImage = new client_type[UNotifier::max_connection]; } } # define U_SRV_LOG( fmt,args...) { if (UServer_Base::isLog()) UServer_Base::log->log(U_CONSTANT_TO_PARAM("%s" fmt), UServer_Base::mod_name[0] , ##args); } # define U_SRV_LOG_WITH_ADDR(fmt,args...) { if (UServer_Base::isLog()) UServer_Base::log->log(U_CONSTANT_TO_PARAM("%s" fmt " %v"), UServer_Base::mod_name[0] , ##args, \ UServer_Base::pClientImage->logbuf->rep); } + #endif class UHTTP; @@ -617,13 +622,12 @@ public: U_TRACE(0, "UServer_Base::logCommandMsgError(%S,%b)", cmd, balways) # ifndef U_LOG_DISABLE - if (isLog()) - { - if (UCommand::setMsgError(cmd, !balways) || balways) log->log(U_CONSTANT_TO_PARAM("%s%.*s"), mod_name[0], u_buffer_len, u_buffer); + U_INTERNAL_ASSERT_POINTER(log) - errno = 0; - u_buffer_len = 0; - } + if (UCommand::setMsgError(cmd, !balways) || balways) log->log(U_CONSTANT_TO_PARAM("%s%.*s"), mod_name[0], u_buffer_len, u_buffer); + + errno = 0; + u_buffer_len = 0; # endif } diff --git a/include/ulib/tokenizer.h b/include/ulib/tokenizer.h index aa77b7d7..fa131baf 100644 --- a/include/ulib/tokenizer.h +++ b/include/ulib/tokenizer.h @@ -158,6 +158,17 @@ public: --s; } + // get previous char + + char previous() + { + U_TRACE_NO_PARAM(0, "UTokenizer::previous()") + + U_INTERNAL_ASSERT(s <= end) + + U_RETURN(*(s-1)); + } + // get current char char current() diff --git a/include/ulib/url.h b/include/ulib/url.h index 33d95628..cb53a40f 100644 --- a/include/ulib/url.h +++ b/include/ulib/url.h @@ -232,12 +232,34 @@ public: U_RETURN_STRING(srv); } + bool isLDAP() const + { + U_TRACE_NO_PARAM(0, "Url::isLDAP()") + + if (u_get_unalignedp32(url.data()) == U_MULTICHAR_CONSTANT32('l','d','a','p')) U_RETURN(true); + + U_RETURN(false); + } + bool isHTTP() const { U_TRACE_NO_PARAM(0, "Url::isHTTP()") if (service_end == 4 && - UString::str_http->equal(url.data(), (uint32_t)service_end)) + u_get_unalignedp32(url.data()) == U_MULTICHAR_CONSTANT32('h','t','t','p')) + { + U_RETURN(true); + } + + U_RETURN(false); + } + + bool isWS() const + { + U_TRACE_NO_PARAM(0, "Url::isWS()") + + if (service_end == 2 && + u_get_unalignedp16(url.data()) == U_MULTICHAR_CONSTANT16('w','s')) { U_RETURN(true); } @@ -251,7 +273,7 @@ public: if (service_end == 5 && url.c_char(4) == 's' && - UString::str_http->equal(url.data(), 4)) + u_get_unalignedp32(url.data()) == U_MULTICHAR_CONSTANT32('h','t','t','p')) { U_RETURN(true); } @@ -259,11 +281,16 @@ public: U_RETURN(false); } - bool isLDAP() const + bool isWSS() const { - U_TRACE_NO_PARAM(0, "Url::isLDAP()") + U_TRACE_NO_PARAM(0, "Url::isWSS()") - if (getService().equal(U_CONSTANT_TO_PARAM("ldap"))) U_RETURN(true); + if (service_end == 3 && + url.c_char(2) == 's' && + u_get_unalignedp16(url.data()) == U_MULTICHAR_CONSTANT16('w','s')) + { + U_RETURN(true); + } U_RETURN(false); } @@ -272,7 +299,12 @@ public: { U_TRACE_NO_PARAM(0, "Url::isLDAPS()") - if (getService().equal(U_CONSTANT_TO_PARAM("ldaps"))) U_RETURN(true); + if (service_end == 5 && + url.c_char(4) == 's' && + u_get_unalignedp32(url.data()) == U_MULTICHAR_CONSTANT32('l','d','a','p')) + { + U_RETURN(true); + } U_RETURN(false); } diff --git a/include/ulib/utility/websocket.h b/include/ulib/utility/websocket.h index fe06d1e6..3d2417a2 100644 --- a/include/ulib/utility/websocket.h +++ b/include/ulib/utility/websocket.h @@ -16,26 +16,33 @@ #include -#define MESSAGE_TYPE_INVALID -1 -#define MESSAGE_TYPE_TEXT 0 -#define MESSAGE_TYPE_BINARY 128 -#define MESSAGE_TYPE_CLOSE 255 -#define MESSAGE_TYPE_PING 256 -#define MESSAGE_TYPE_PONG 257 +#define U_WS_MESSAGE_TYPE_INVALID -1 +#define U_WS_MESSAGE_TYPE_TEXT 0 +#define U_WS_MESSAGE_TYPE_BINARY 128 +#define U_WS_MESSAGE_TYPE_CLOSE 255 +#define U_WS_MESSAGE_TYPE_PING 256 +#define U_WS_MESSAGE_TYPE_PONG 257 -#define STATUS_CODE_OK 1000 -#define STATUS_CODE_GOING_AWAY 1001 -#define STATUS_CODE_PROTOCOL_ERROR 1002 -#define STATUS_CODE_INVALID_TYPE 1003 -#define STATUS_CODE_RESERVED1 1004 /* Protocol 8: frame too large */ -#define STATUS_CODE_RESERVED2 1005 -#define STATUS_CODE_RESERVED3 1006 -#define STATUS_CODE_INVALID_UTF8 1007 -#define STATUS_CODE_POLICY_VIOLATION 1008 -#define STATUS_CODE_MESSAGE_TOO_LARGE 1009 -#define STATUS_CODE_EXTENSION_ERROR 1010 -#define STATUS_CODE_INTERNAL_ERROR 1011 -#define STATUS_CODE_RESERVED4 1015 +#define U_WS_OPCODE_CONTINUATION 0x0 +#define U_WS_OPCODE_TEXT 0x1 +#define U_WS_OPCODE_BINARY 0x2 +#define U_WS_OPCODE_CLOSE 0x8 +#define U_WS_OPCODE_PING 0x9 +#define U_WS_OPCODE_PONG 0xA + +#define U_WS_STATUS_CODE_OK 1000 +#define U_WS_STATUS_CODE_GOING_AWAY 1001 +#define U_WS_STATUS_CODE_PROTOCOL_ERROR 1002 +#define U_WS_STATUS_CODE_INVALID_TYPE 1003 +#define U_WS_STATUS_CODE_RESERVED1 1004 /* Protocol 8: frame too large */ +#define U_WS_STATUS_CODE_RESERVED2 1005 +#define U_WS_STATUS_CODE_RESERVED3 1006 +#define U_WS_STATUS_CODE_INVALID_UTF8 1007 +#define U_WS_STATUS_CODE_POLICY_VIOLATION 1008 +#define U_WS_STATUS_CODE_MESSAGE_TOO_LARGE 1009 +#define U_WS_STATUS_CODE_EXTENSION_ERROR 1010 +#define U_WS_STATUS_CODE_INTERNAL_ERROR 1011 +#define U_WS_STATUS_CODE_RESERVED4 1015 class USocket; @@ -44,11 +51,6 @@ public: // SERVICES - static UString* rbuffer; - static uint32_t max_message_size; - static const char* upgrade_settings; - static int message_type, status_code; - typedef struct _WebSocketFrameData { unsigned char* application_data; uint32_t application_data_offset; @@ -57,17 +59,24 @@ public: unsigned int utf8_state; } WebSocketFrameData; + static UString* rbuffer; + static UString* message; + static uint32_t max_message_size; + static const char* upgrade_settings; + static int message_type, status_code; static WebSocketFrameData control_frame; static WebSocketFrameData message_frame; - static bool sendAccept(); static void checkForInitialData(); + static bool sendAccept(USocket* socket); static int handleDataFraming(USocket* socket); - static bool sendData(int type, const unsigned char* buffer, uint32_t buffer_size); + static bool sendData(USocket* socket, int type, const char* data, uint32_t len); - static bool sendClose() + static bool sendData(USocket* socket, int type, const UString& data) { return sendData(socket, type, U_STRING_TO_PARAM(data)); } + + static bool sendClose(USocket* socket) { - U_TRACE_NO_PARAM(0, "UWebSocket::sendClose()") + U_TRACE(0, "UWebSocket::sendClose(%p)", socket) // Send server-side closing handshake @@ -76,12 +85,14 @@ public: unsigned char status_code_buffer[2] = { (unsigned char)((status_code >> 8) & 0xFF), (unsigned char)( status_code & 0xFF) }; - if (sendData(MESSAGE_TYPE_CLOSE, status_code_buffer, sizeof(status_code_buffer))) U_RETURN(true); + if (sendControlFrame(socket, U_WS_OPCODE_CLOSE, status_code_buffer, sizeof(status_code_buffer))) U_RETURN(true); U_RETURN(false); } private: + static bool sendControlFrame(USocket* socket, int opcode, const unsigned char* payload, uint32_t payload_length); + U_DISALLOW_COPY_AND_ASSIGN(UWebSocket) }; diff --git a/nativejson-benchmark/travis-ci.log b/nativejson-benchmark/travis-ci.log new file mode 100644 index 00000000..b06c60ac --- /dev/null +++ b/nativejson-benchmark/travis-ci.log @@ -0,0 +1,1905 @@ +@see: https://travis-ci.org/miloyip/nativejson-benchmark/jobs/214711212 + +Read 'canada.json' (2251051 bytes) +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 + +Read 'citm_catalog.json' (1727204 bytes) +objectCount: 10937 +arrayCount: 10451 +numberCount: 14392 +stringCount: 26604 +trueCount: 0 +falseCount: 0 +nullCount: 1263 +memberCount: 25869 +elementCount: 11908 +stringLength: 221379 + +Read 'twitter.json' (631514 bytes) +objectCount: 1264 +arrayCount: 1050 +numberCount: 2109 +stringCount: 18099 +trueCount: 345 +falseCount: 2446 +nullCount: 1946 +memberCount: 13345 +elementCount: 568 +stringLength: 367917 + + +Verifying ULib (C++) ... OK +Verifying ArduinoJson (C++) ... OK +Verifying CAJUN (C++) ... OK +Verifying ccan/json (C) ... OK +Verifying cJSON (C) ... OK +Verifying Configuru (C++11) ... OK +Verifying dropbox/json11 (C++11) ... +Warning: potential memory leak (3 allocations for 136 bytes) +OK +Verifying mikeando/FastJson (C++) ... OK +Verifying gason (C++11) ... OK +Verifying Jansson (C) ... OK +Verifying JeayeSON (C++14) ... OK +Verifying jsmn (C) ... +Statistics of 'citm_catalog.json' is different from reference. + +Reference +--------- +objectCount: 10937 +arrayCount: 10451 +numberCount: 14392 +stringCount: 26604 +trueCount: 0 +falseCount: 0 +nullCount: 1263 +memberCount: 25869 +elementCount: 11908 +stringLength: 221379 + +Stat 1 +-------- +objectCount: 10937 +arrayCount: 10451 +numberCount: 14392 +stringCount: 26604 +trueCount: 0 +falseCount: 0 +nullCount: 1263 +memberCount: 25869 +elementCount: 11908 +stringLength: 221381 + + +Statistics of 'twitter.json' is different from reference. + +Reference +--------- +objectCount: 1264 +arrayCount: 1050 +numberCount: 2109 +stringCount: 18099 +trueCount: 345 +falseCount: 2446 +nullCount: 1946 +memberCount: 13345 +elementCount: 568 +stringLength: 367917 + +Stat 1 +-------- +objectCount: 1264 +arrayCount: 1050 +numberCount: 2109 +stringCount: 18099 +trueCount: 345 +falseCount: 2446 +nullCount: 1946 +memberCount: 13345 +elementCount: 568 +stringLength: 369145 + +Failed +Verifying JsonBox (C++) ... OK +Verifying jsoncons (C++) ... OK +Verifying JsonCpp (C++) ... OK +Verifying json-c (C) ... OK +Verifying JSON Spirit (C++) ... +Warning: potential memory leak (4 allocations for 128 bytes) +OK +Verifying hjiang/JSON++ (C++) ... +Warning: potential memory leak (256 allocations for 10240 bytes) +OK +Verifying juson (C) ... OK +Verifying JVar (C++) ... +Failed to parse 'citm_catalog.json' 2nd time +Failed to parse 'twitter.json' 2nd time +Failed +Verifying Jzon (C++) ... OK +Verifying nbsdx_SimpleJSON (C++11) ... +Statistics of 'canada.json' is different from reference. + +Reference +--------- +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 + +Stat #1 +-------- +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 0 +elementCount: 167178 +stringLength: 90 + + +Statistics of 'citm_catalog.json' is different from reference. + +Reference +--------- +objectCount: 10937 +arrayCount: 10451 +numberCount: 14392 +stringCount: 26604 +trueCount: 0 +falseCount: 0 +nullCount: 1263 +memberCount: 25869 +elementCount: 11908 +stringLength: 221379 + +Stat #1 +-------- +objectCount: 10937 +arrayCount: 10451 +numberCount: 14392 +stringCount: 26604 +trueCount: 0 +falseCount: 0 +nullCount: 1263 +memberCount: 0 +elementCount: 37777 +stringLength: 221381 + + +Statistics of 'twitter.json' is different from reference. + +Reference +--------- +objectCount: 1264 +arrayCount: 1050 +numberCount: 2109 +stringCount: 18099 +trueCount: 345 +falseCount: 2446 +nullCount: 1946 +memberCount: 13345 +elementCount: 568 +stringLength: 367917 + +Stat #1 +-------- +objectCount: 1264 +arrayCount: 1050 +numberCount: 2109 +stringCount: 18099 +trueCount: 345 +falseCount: 2446 +nullCount: 1946 +memberCount: 0 +elementCount: 13913 +stringLength: 369145 + +Failed +Verifying Nlohmann (C++11) ... OK +Verifying Parson (C) ... OK +Verifying PicoJSON (C++) ... OK +Verifying pjson (C) ... +Failed to parse 'canada.json' + +Failed to parse 'citm_catalog.json' + +Failed to parse 'twitter.json' +Failed +Verifying RapidJSON_AutoUTF (C++) ... OK +Verifying RapidJSON_FullPrec (C++) ... OK +Verifying RapidJSON_Insitu (C++) ... OK +Verifying RapidJSON_Iterative (C++) ... OK +Verifying RapidJSON (C++) ... OK +Verifying sajson (C++) ... OK +Verifying Sheredom json.h (C) ... OK +Verifying SimpleJSON (C++) ... +Statistics of 'twitter.json' is different from reference. + +Reference +--------- +objectCount: 1264 +arrayCount: 1050 +numberCount: 2109 +stringCount: 18099 +trueCount: 345 +falseCount: 2446 +nullCount: 1946 +memberCount: 13345 +elementCount: 568 +stringLength: 367917 + +Stat #1 +-------- +objectCount: 1264 +arrayCount: 1050 +numberCount: 2109 +stringCount: 18099 +trueCount: 345 +falseCount: 2446 +nullCount: 1946 +memberCount: 13345 +elementCount: 568 +stringLength: 304319 + +Failed +Verifying strdup (C) ... Not support Statistics +Not support Statistics +Not support Statistics +OK +Verifying taocpp/json & Nlohmann (C++11) ... OK +Verifying taocpp/json (C++11) ... OK +Verifying tunnuz/JSON++ (C++) ... +Warning: potential memory leak (1 allocations for 72 bytes) + +error: syntax error + +Failed to parse 'citm_catalog.json' 2nd time +error: syntax error + +Failed to parse 'twitter.json' 2nd time +Failed +Verifying ujson4c (C) ... +Statistics of 'twitter.json' is different from reference. + +Reference +--------- +objectCount: 1264 +arrayCount: 1050 +numberCount: 2109 +stringCount: 18099 +trueCount: 345 +falseCount: 2446 +nullCount: 1946 +memberCount: 13345 +elementCount: 568 +stringLength: 367917 + +Stat 1 +-------- +objectCount: 1264 +arrayCount: 1050 +numberCount: 2109 +stringCount: 18099 +trueCount: 345 +falseCount: 2446 +nullCount: 1946 +memberCount: 13345 +elementCount: 568 +stringLength: 304319 + +Failed +Verifying ujson (C++) ... OK +Verifying Vinenthz/libjson (C) ... OK +Verifying JSON Voorhees (C++) ... +Warning: potential memory leak (47 allocations for 11864 bytes) +OK +Verifying YAJL (C) ... OK + +Benchmarking Performance of ULib (C++) + Parse canada.json ... 5.997 ms 357.974 MB/s + Parse citm_catalog.json ... 4.168 ms 395.199 MB/s + Parse twitter.json ... 1.473 ms 408.865 MB/s + Stringify canada.json ... 7.679 ms 279.564 MB/s + Stringify citm_catalog.json ... 0.619 ms 2661.050 MB/s + Stringify twitter.json ... 0.624 ms 965.158 MB/s + Prettify canada.json ... 8.072 ms 265.953 MB/s + Prettify citm_catalog.json ... 0.794 ms 2074.547 MB/s + Prettify twitter.json ... 0.712 ms 845.869 MB/s + Statistics canada.json ... 0.496 ms 4328.164 MB/s + Statistics citm_catalog.json ... 0.381 ms 4323.334 MB/s + Statistics twitter.json ... 0.243 ms 2478.431 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 116560 + +Benchmarking Performance of ArduinoJson (C++) + Parse canada.json ... 750.417 ms 2.861 MB/s + Parse citm_catalog.json ... 4.063 ms 405.412 MB/s + Parse twitter.json ... 3.542 ms 170.034 MB/s + Stringify canada.json ... 43.471 ms 49.384 MB/s + Stringify citm_catalog.json ... 10.858 ms 151.703 MB/s + Stringify twitter.json ... 10.538 ms 57.151 MB/s + Prettify canada.json ... 122.200 ms 17.568 MB/s + Prettify citm_catalog.json ... 27.439 ms 60.031 MB/s + Prettify twitter.json ... 16.004 ms 37.632 MB/s + Statistics canada.json ... 30.232 ms 71.010 MB/s + Statistics citm_catalog.json ... 1.195 ms 1378.402 MB/s + Statistics twitter.json ... 0.722 ms 834.153 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 18824 + +Benchmarking Performance of CAJUN (C++) + Parse canada.json ... 626.339 ms 3.427 MB/s + Parse citm_catalog.json ... 130.574 ms 12.615 MB/s + Parse twitter.json ... 45.863 ms 13.132 MB/s + Stringify canada.json ... 173.782 ms 12.353 MB/s + Stringify citm_catalog.json ... 23.749 ms 69.358 MB/s + Stringify twitter.json ... 11.628 ms 51.794 MB/s + Prettify canada.json ... Not support + Prettify citm_catalog.json ... Not support + Prettify twitter.json ... Not support + Statistics canada.json ... 3.744 ms 573.389 MB/s + Statistics citm_catalog.json ... 0.476 ms 3460.483 MB/s + Statistics twitter.json ... 0.161 ms 3740.737 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 72408 + +Benchmarking Performance of ccan/json (C) + Parse canada.json ... 29.637 ms 72.435 MB/s + Parse citm_catalog.json ... 5.412 ms 304.359 MB/s + Parse twitter.json ... 3.012 ms 199.953 MB/s + Stringify canada.json ... 103.115 ms 20.819 MB/s + Stringify citm_catalog.json ... 10.668 ms 154.405 MB/s + Stringify twitter.json ... 3.529 ms 170.660 MB/s + Prettify canada.json ... 117.128 ms 18.328 MB/s + Prettify citm_catalog.json ... 13.170 ms 125.071 MB/s + Prettify twitter.json ... 4.075 ms 147.794 MB/s + Statistics canada.json ... 0.569 ms 3772.881 MB/s + Statistics citm_catalog.json ... 0.371 ms 4439.865 MB/s + Statistics twitter.json ... 0.147 ms 4096.998 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 31136 + +Benchmarking Performance of cJSON (C) + Parse canada.json ... 25.980 ms 82.632 MB/s + Parse citm_catalog.json ... 5.796 ms 284.194 MB/s + Parse twitter.json ... 3.092 ms 194.780 MB/s + Stringify canada.json ... 73.583 ms 29.175 MB/s + Stringify citm_catalog.json ... 3.574 ms 460.881 MB/s + Stringify twitter.json ... 2.394 ms 251.570 MB/s + Prettify canada.json ... 72.713 ms 29.524 MB/s + Prettify citm_catalog.json ... 3.814 ms 431.880 MB/s + Prettify twitter.json ... 2.599 ms 231.727 MB/s + Statistics canada.json ... 0.656 ms 3272.515 MB/s + Statistics citm_catalog.json ... 0.267 ms 6169.251 MB/s + Statistics twitter.json ... 0.170 ms 3542.698 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 47512 + +Benchmarking Performance of Configuru (C++11) + Parse canada.json ... 42.585 ms 50.411 MB/s + Parse citm_catalog.json ... 16.664 ms 98.847 MB/s + Parse twitter.json ... 7.321 ms 82.265 MB/s + Stringify canada.json ... 268.136 ms 8.006 MB/s + Stringify citm_catalog.json ... 5.192 ms 317.255 MB/s + Stringify twitter.json ... 2.398 ms 251.150 MB/s + Prettify canada.json ... 274.004 ms 7.835 MB/s + Prettify citm_catalog.json ... 7.830 ms 210.369 MB/s + Prettify twitter.json ... 3.789 ms 158.949 MB/s + Statistics canada.json ... 0.901 ms 2382.652 MB/s + Statistics citm_catalog.json ... 0.584 ms 2820.531 MB/s + Statistics twitter.json ... 0.274 ms 2198.024 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 105272 + +Benchmarking Performance of dropbox/json11 (C++11) + Parse canada.json ... 39.691 ms 54.087 MB/s + Parse citm_catalog.json ... 15.839 ms 103.996 MB/s + Parse twitter.json ... 10.583 ms 56.908 MB/s + Stringify canada.json ... 112.624 ms 19.061 MB/s + Stringify citm_catalog.json ... 4.411 ms 373.428 MB/s + Stringify twitter.json ... 3.060 ms 196.817 MB/s + Prettify canada.json ... Not support + Prettify citm_catalog.json ... Not support + Prettify twitter.json ... Not support + Statistics canada.json ... 1.020 ms 2104.676 MB/s + Statistics citm_catalog.json ... 0.570 ms 2889.807 MB/s + Statistics twitter.json ... 0.266 ms 2264.130 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 105112 + +Benchmarking Performance of mikeando/FastJson (C++) + Parse canada.json ... 16.735 ms 128.280 MB/s + Parse citm_catalog.json ... 6.876 ms 239.556 MB/s + Parse twitter.json ... 3.105 ms 193.964 MB/s + Stringify canada.json ... 92.373 ms 23.240 MB/s + Stringify citm_catalog.json ... 10.308 ms 159.797 MB/s + Stringify twitter.json ... 2.476 ms 243.239 MB/s + Prettify canada.json ... Not support + Prettify citm_catalog.json ... Not support + Prettify twitter.json ... Not support + Statistics canada.json ... 0.742 ms 2893.220 MB/s + Statistics citm_catalog.json ... 0.158 ms 10425.254 MB/s + Statistics twitter.json ... 0.072 ms 8364.704 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 76280 + +Benchmarking Performance of gason (C++11) + Parse canada.json ... 4.031 ms 532.565 MB/s + Parse citm_catalog.json ... 2.240 ms 735.353 MB/s + Parse twitter.json ... 1.037 ms 580.770 MB/s + Stringify canada.json ... 77.532 ms 27.689 MB/s + Stringify citm_catalog.json ... 15.620 ms 105.454 MB/s + Stringify twitter.json ... 6.157 ms 97.817 MB/s + Prettify canada.json ... 100.443 ms 21.373 MB/s + Prettify citm_catalog.json ... 20.131 ms 81.824 MB/s + Prettify twitter.json ... 7.244 ms 83.139 MB/s + Statistics canada.json ... 0.640 ms 3354.327 MB/s + Statistics citm_catalog.json ... 0.285 ms 5779.614 MB/s + Statistics twitter.json ... 0.209 ms 2881.620 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 18776 + +Benchmarking Performance of Jansson (C) + Parse canada.json ... 62.454 ms 34.374 MB/s + Parse citm_catalog.json ... 19.629 ms 83.916 MB/s + Parse twitter.json ... 9.949 ms 60.535 MB/s + Stringify canada.json ... 112.966 ms 19.004 MB/s + Stringify citm_catalog.json ... 4.673 ms 352.491 MB/s + Stringify twitter.json ... 2.831 ms 212.737 MB/s + Prettify canada.json ... 118.850 ms 18.063 MB/s + Prettify citm_catalog.json ... 5.819 ms 283.071 MB/s + Prettify twitter.json ... 3.223 ms 186.863 MB/s + Statistics canada.json ... 0.981 ms 2188.348 MB/s + Statistics citm_catalog.json ... 0.699 ms 2356.495 MB/s + Statistics twitter.json ... 0.317 ms 1899.870 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 76344 + +Benchmarking Performance of JeayeSON (C++14) + Parse canada.json ... 51.139 ms 41.979 MB/s + Parse citm_catalog.json ... 32.074 ms 51.356 MB/s + Parse twitter.json ... 17.301 ms 34.811 MB/s + Stringify canada.json ... 82.428 ms 26.044 MB/s + Stringify citm_catalog.json ... 8.346 ms 197.363 MB/s + Stringify twitter.json ... 5.052 ms 119.212 MB/s + Prettify canada.json ... Not support + Prettify citm_catalog.json ... Not support + Prettify twitter.json ... Not support + Statistics canada.json ... 0.616 ms 3485.015 MB/s + Statistics citm_catalog.json ... 0.346 ms 4760.665 MB/s + Statistics twitter.json ... 0.196 ms 3072.748 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 96928 + +Benchmarking Performance of jsmn (C) + Parse canada.json ... 449.918 ms 4.771 MB/s + Parse citm_catalog.json ... 14.829 ms 111.079 MB/s + Parse twitter.json ... 4.246 ms 141.841 MB/s + Stringify canada.json ... Not support + Stringify citm_catalog.json ... Not support + Stringify twitter.json ... Not support + Prettify canada.json ... Not support + Prettify citm_catalog.json ... Not support + Prettify twitter.json ... Not support + Statistics canada.json ... 0.277 ms 7750.070 MB/s + Statistics citm_catalog.json ... 0.130 ms 12670.693 MB/s + Statistics twitter.json ... 0.057 ms 10565.942 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 14680 + +Benchmarking Performance of JsonBox (C++) + Parse canada.json ... 231.900 ms 9.257 MB/s + Parse citm_catalog.json ... 84.496 ms 19.494 MB/s + Parse twitter.json ... 42.321 ms 14.231 MB/s + Stringify canada.json ... 210.738 ms 10.187 MB/s + Stringify citm_catalog.json ... 44.971 ms 36.628 MB/s + Stringify twitter.json ... 30.826 ms 19.537 MB/s + Prettify canada.json ... 197.909 ms 10.847 MB/s + Prettify citm_catalog.json ... 40.981 ms 40.194 MB/s + Prettify twitter.json ... 28.738 ms 20.957 MB/s + Statistics canada.json ... 0.748 ms 2870.013 MB/s + Statistics citm_catalog.json ... 0.381 ms 4323.334 MB/s + Statistics twitter.json ... 0.212 ms 2840.843 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 93128 + +Benchmarking Performance of jsoncons (C++) + Parse canada.json ... 58.148 ms 36.919 MB/s + Parse citm_catalog.json ... 9.153 ms 179.962 MB/s + Parse twitter.json ... 4.830 ms 124.691 MB/s + Stringify canada.json ... 124.034 ms 17.308 MB/s + Stringify citm_catalog.json ... 2.488 ms 662.054 MB/s + Stringify twitter.json ... 2.503 ms 240.615 MB/s + Prettify canada.json ... 124.056 ms 17.305 MB/s + Prettify citm_catalog.json ... 2.489 ms 661.788 MB/s + Prettify twitter.json ... 2.504 ms 240.519 MB/s + Statistics canada.json ... 1.393 ms 1541.112 MB/s + Statistics citm_catalog.json ... 0.578 ms 2849.810 MB/s + Statistics twitter.json ... 0.512 ms 1176.286 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 125936 + +Benchmarking Performance of JsonCpp (C++) + Parse canada.json ... 72.169 ms 29.746 MB/s + Parse citm_catalog.json ... 15.019 ms 109.674 MB/s + Parse twitter.json ... 10.293 ms 58.511 MB/s + Stringify canada.json ... 155.721 ms 13.786 MB/s + Stringify citm_catalog.json ... 17.528 ms 93.975 MB/s + Stringify twitter.json ... 11.738 ms 51.308 MB/s + Prettify canada.json ... Not support + Prettify citm_catalog.json ... Not support + Prettify twitter.json ... Not support + Statistics canada.json ... 2.272 ms 944.881 MB/s + Statistics citm_catalog.json ... 0.617 ms 2669.676 MB/s + Statistics twitter.json ... 0.589 ms 1022.510 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 203704 + +Benchmarking Performance of json-c (C) + Parse canada.json ... 79.288 ms 27.076 MB/s + Parse citm_catalog.json ... 16.277 ms 101.197 MB/s + Parse twitter.json ... 7.993 ms 75.348 MB/s + Stringify canada.json ... 15.741 ms 136.381 MB/s + Stringify citm_catalog.json ... 8.879 ms 185.515 MB/s + Stringify twitter.json ... 4.933 ms 122.088 MB/s + Prettify canada.json ... 27.362 ms 78.458 MB/s + Prettify citm_catalog.json ... 12.217 ms 134.828 MB/s + Prettify twitter.json ... 5.623 ms 107.106 MB/s + Statistics canada.json ... 3.403 ms 630.846 MB/s + Statistics citm_catalog.json ... 0.649 ms 2538.043 MB/s + Statistics twitter.json ... 0.227 ms 2653.122 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 55888 + +Benchmarking Performance of JSON Spirit (C++) + Parse canada.json ... 54.744 ms 39.215 MB/s + Parse citm_catalog.json ... 44.186 ms 37.279 MB/s + Parse twitter.json ... 12.845 ms 46.887 MB/s + Stringify canada.json ... 125.009 ms 17.173 MB/s + Stringify citm_catalog.json ... 12.899 ms 127.699 MB/s + Stringify twitter.json ... 16.039 ms 37.550 MB/s + Prettify canada.json ... 160.222 ms 13.399 MB/s + Prettify citm_catalog.json ... 21.829 ms 75.459 MB/s + Prettify twitter.json ... 18.138 ms 33.204 MB/s + Statistics canada.json ... 0.850 ms 2525.611 MB/s + Statistics citm_catalog.json ... 0.294 ms 5602.687 MB/s + Statistics twitter.json ... 0.125 ms 4818.069 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 113368 + +Benchmarking Performance of hjiang/JSON++ (C++) + Parse canada.json ... 139.530 ms 15.386 MB/s + Parse citm_catalog.json ... 44.772 ms 36.791 MB/s + Parse twitter.json ... 20.322 ms 29.636 MB/s + Stringify canada.json ... 296.907 ms 7.230 MB/s + Stringify citm_catalog.json ... 57.010 ms 28.893 MB/s + Stringify twitter.json ... 22.574 ms 26.679 MB/s + Prettify canada.json ... Not support + Prettify citm_catalog.json ... Not support + Prettify twitter.json ... Not support + Statistics canada.json ... 0.767 ms 2798.917 MB/s + Statistics citm_catalog.json ... 0.485 ms 3396.268 MB/s + Statistics twitter.json ... 0.247 ms 2438.294 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 88856 + +Benchmarking Performance of juson (C) + Parse canada.json ... 32.277 ms 66.511 MB/s + Parse citm_catalog.json ... 5.747 ms 286.617 MB/s + Parse twitter.json ... 1.815 ms 331.823 MB/s + Stringify canada.json ... Not support + Stringify citm_catalog.json ... Not support + Stringify twitter.json ... Not support + Prettify canada.json ... Not support + Prettify citm_catalog.json ... Not support + Prettify twitter.json ... Not support + Statistics canada.json ... 0.764 ms 2809.908 MB/s + Statistics citm_catalog.json ... 0.371 ms 4439.865 MB/s + Statistics twitter.json ... 0.180 ms 3345.882 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 22928 + +Benchmarking Performance of JVar (C++) + Parse canada.json ... 67.610 ms 31.752 MB/s + Parse citm_catalog.json ... 16.838 ms 97.826 MB/s + Parse twitter.json ... 8.261 ms 72.904 MB/s + Stringify canada.json ... 70.717 ms 30.357 MB/s + Stringify citm_catalog.json ... 5.152 ms 319.719 MB/s + Stringify twitter.json ... 2.197 ms 274.128 MB/s + Prettify canada.json ... Not support + Prettify citm_catalog.json ... Not support + Prettify twitter.json ... Not support + Statistics canada.json ... 0.942 ms 2278.949 MB/s + Statistics citm_catalog.json ... 0.470 ms 3504.660 MB/s + Statistics twitter.json ... 0.224 ms 2688.655 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 84704 + +Benchmarking Performance of Jzon (C++) + Parse canada.json ... 147.979 ms 14.507 MB/s + Parse citm_catalog.json ... 51.278 ms 32.123 MB/s + Parse twitter.json ... 24.314 ms 24.770 MB/s + Stringify canada.json ... 18.681 ms 114.917 MB/s + Stringify citm_catalog.json ... 7.140 ms 230.699 MB/s + Stringify twitter.json ... 4.492 ms 134.074 MB/s + Prettify canada.json ... 34.808 ms 61.675 MB/s + Prettify citm_catalog.json ... 11.196 ms 147.123 MB/s + Prettify twitter.json ... 5.690 ms 105.845 MB/s + Statistics canada.json ... 1.118 ms 1920.187 MB/s + Statistics citm_catalog.json ... 0.372 ms 4427.930 MB/s + Statistics twitter.json ... 0.215 ms 2801.203 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 80656 + +Benchmarking Performance of nbsdx_SimpleJSON (C++11) + Parse canada.json ... 151.309 ms 14.188 MB/s + Parse citm_catalog.json ... 47.413 ms 34.741 MB/s + Parse twitter.json ... 24.783 ms 24.301 MB/s + Stringify canada.json ... 152.319 ms 14.094 MB/s + Stringify citm_catalog.json ... 37.047 ms 44.462 MB/s + Stringify twitter.json ... 16.030 ms 37.571 MB/s + Prettify canada.json ... 153.677 ms 13.969 MB/s + Prettify citm_catalog.json ... 37.512 ms 43.911 MB/s + Prettify twitter.json ... 15.745 ms 38.251 MB/s + Statistics canada.json ... 1.714 ms 1252.491 MB/s + Statistics citm_catalog.json ... 0.810 ms 2033.568 MB/s + Statistics twitter.json ... 2.434 ms 247.436 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 0 +elementCount: 167178 +stringLength: 90 +jsonstat file size = 72312 + +Benchmarking Performance of Nlohmann (C++11) + Parse canada.json ... 39.755 ms 54.000 MB/s + Parse citm_catalog.json ... 9.888 ms 166.585 MB/s + Parse twitter.json ... 5.880 ms 102.425 MB/s + Stringify canada.json ... 113.745 ms 18.874 MB/s + Stringify citm_catalog.json ... 6.952 ms 236.938 MB/s + Stringify twitter.json ... 4.522 ms 133.184 MB/s + Prettify canada.json ... 134.119 ms 16.006 MB/s + Prettify citm_catalog.json ... 11.144 ms 147.810 MB/s + Prettify twitter.json ... 5.973 ms 100.830 MB/s + Statistics canada.json ... 0.731 ms 2936.757 MB/s + Statistics citm_catalog.json ... 0.777 ms 2119.936 MB/s + Statistics twitter.json ... 0.483 ms 1246.912 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 68304 + +Benchmarking Performance of Parson (C) + Parse canada.json ... 47.780 ms 44.930 MB/s + Parse citm_catalog.json ... 11.760 ms 140.067 MB/s + Parse twitter.json ... 5.963 ms 100.999 MB/s + Stringify canada.json ... 206.665 ms 10.388 MB/s + Stringify citm_catalog.json ... 9.956 ms 165.447 MB/s + Stringify twitter.json ... 8.718 ms 69.082 MB/s + Prettify canada.json ... 205.552 ms 10.444 MB/s + Prettify citm_catalog.json ... 10.043 ms 164.014 MB/s + Prettify twitter.json ... 8.833 ms 68.183 MB/s + Statistics canada.json ... 1.135 ms 1891.427 MB/s + Statistics citm_catalog.json ... 1.014 ms 1624.448 MB/s + Statistics twitter.json ... 1.262 ms 477.226 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 59864 + +Benchmarking Performance of PicoJSON (C++) + Parse canada.json ... 97.705 ms 21.972 MB/s + Parse citm_catalog.json ... 28.257 ms 58.293 MB/s + Parse twitter.json ... 12.714 ms 47.370 MB/s + Stringify canada.json ... 125.060 ms 17.166 MB/s + Stringify citm_catalog.json ... 12.354 ms 133.333 MB/s + Stringify twitter.json ... 4.128 ms 145.896 MB/s + Prettify canada.json ... Not support + Prettify citm_catalog.json ... Not support + Prettify twitter.json ... Not support + Statistics canada.json ... 0.642 ms 3343.878 MB/s + Statistics citm_catalog.json ... 0.333 ms 4946.517 MB/s + Statistics twitter.json ... 0.239 ms 2519.911 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 59976 + +Benchmarking Performance of pjson (C) + Parse canada.json ... Not support + Parse citm_catalog.json ... Not support + Parse twitter.json ... Not support + Stringify canada.json ... Not support + Stringify citm_catalog.json ... Not support + Stringify twitter.json ... Not support + Prettify canada.json ... Not support + Prettify citm_catalog.json ... Not support + Prettify twitter.json ... Not support + Statistics canada.json ... Not support + Statistics citm_catalog.json ... Not support + Statistics twitter.json ... Not support + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... 4.761 ms 450.907 MB/s + Sax Statistics citm_catalog.json ... 2.731 ms 603.145 MB/s + Sax Statistics twitter.json ... 1.358 ms 443.489 MB/s +Not support Statistics +jsonstat file size = 10576 + +Benchmarking Performance of RapidJSON_AutoUTF (C++) + Parse canada.json ... 9.671 ms 221.980 MB/s + Parse citm_catalog.json ... 7.879 ms 209.061 MB/s + Parse twitter.json ... 4.650 ms 129.518 MB/s + Stringify canada.json ... 16.961 ms 126.571 MB/s + Stringify citm_catalog.json ... 2.173 ms 758.026 MB/s + Stringify twitter.json ... 1.917 ms 314.167 MB/s + Prettify canada.json ... 32.052 ms 66.978 MB/s + Prettify citm_catalog.json ... 5.784 ms 284.784 MB/s + Prettify twitter.json ... 2.993 ms 201.222 MB/s + Statistics canada.json ... 0.646 ms 3323.173 MB/s + Statistics citm_catalog.json ... 0.209 ms 7881.292 MB/s + Statistics twitter.json ... 0.078 ms 7721.265 MB/s + SaxRoundtrip canada.json ... 23.674 ms 90.680 MB/s + SaxRoundtrip citm_catalog.json ... 9.034 ms 182.332 MB/s + SaxRoundtrip twitter.json ... 5.963 ms 100.999 MB/s + Sax Statistics canada.json ... 7.797 ms 275.333 MB/s + Sax Statistics citm_catalog.json ... 7.206 ms 228.586 MB/s + Sax Statistics twitter.json ... 4.221 ms 142.682 MB/s +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 35168 + +Benchmarking Performance of RapidJSON_FullPrec (C++) + Parse canada.json ... 12.431 ms 172.695 MB/s + Parse citm_catalog.json ... 2.919 ms 564.299 MB/s + Parse twitter.json ... 1.852 ms 325.194 MB/s + Stringify canada.json ... 8.581 ms 250.177 MB/s + Stringify citm_catalog.json ... 1.222 ms 1347.946 MB/s + Stringify twitter.json ... 0.857 ms 702.752 MB/s + Prettify canada.json ... 9.766 ms 219.821 MB/s + Prettify citm_catalog.json ... 1.591 ms 1035.317 MB/s + Prettify twitter.json ... 1.140 ms 528.297 MB/s + Statistics canada.json ... 0.635 ms 3380.739 MB/s + Statistics citm_catalog.json ... 0.204 ms 8074.461 MB/s + Statistics twitter.json ... 0.077 ms 7821.541 MB/s + SaxRoundtrip canada.json ... 19.961 ms 107.548 MB/s + SaxRoundtrip citm_catalog.json ... 3.488 ms 472.245 MB/s + SaxRoundtrip twitter.json ... 2.316 ms 260.043 MB/s + Sax Statistics canada.json ... 12.428 ms 172.737 MB/s + Sax Statistics citm_catalog.json ... 2.217 ms 742.982 MB/s + Sax Statistics twitter.json ... 1.422 ms 423.529 MB/s +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 31072 + +Benchmarking Performance of RapidJSON_Insitu (C++) + Parse canada.json ... 5.665 ms 378.953 MB/s + Parse citm_catalog.json ... 2.244 ms 734.042 MB/s + Parse twitter.json ... 1.261 ms 477.604 MB/s + Stringify canada.json ... 8.397 ms 255.659 MB/s + Stringify citm_catalog.json ... 1.264 ms 1303.157 MB/s + Stringify twitter.json ... 0.996 ms 604.677 MB/s + Prettify canada.json ... 9.706 ms 221.180 MB/s + Prettify citm_catalog.json ... 1.613 ms 1021.197 MB/s + Prettify twitter.json ... 1.243 ms 484.520 MB/s + Statistics canada.json ... 0.638 ms 3364.843 MB/s + Statistics citm_catalog.json ... 0.201 ms 8194.976 MB/s + Statistics twitter.json ... 0.088 ms 6843.849 MB/s + SaxRoundtrip canada.json ... 13.494 ms 159.091 MB/s + SaxRoundtrip citm_catalog.json ... 2.982 ms 552.378 MB/s + SaxRoundtrip twitter.json ... 2.106 ms 285.973 MB/s + Sax Statistics canada.json ... 4.472 ms 480.047 MB/s + Sax Statistics citm_catalog.json ... 1.795 ms 917.655 MB/s + Sax Statistics twitter.json ... 1.171 ms 514.311 MB/s +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 31072 + +Benchmarking Performance of RapidJSON_Iterative (C++) + Parse canada.json ... 6.238 ms 344.144 MB/s + Parse citm_catalog.json ... 3.186 ms 517.009 MB/s + Parse twitter.json ... 1.894 ms 317.982 MB/s + Stringify canada.json ... 8.533 ms 251.584 MB/s + Stringify citm_catalog.json ... 1.223 ms 1346.844 MB/s + Stringify twitter.json ... 0.856 ms 703.573 MB/s + Prettify canada.json ... 9.890 ms 217.065 MB/s + Prettify citm_catalog.json ... 1.600 ms 1029.494 MB/s + Prettify twitter.json ... 1.163 ms 517.849 MB/s + Statistics canada.json ... 0.635 ms 3380.739 MB/s + Statistics citm_catalog.json ... 0.204 ms 8074.461 MB/s + Statistics twitter.json ... 0.080 ms 7528.234 MB/s + SaxRoundtrip canada.json ... 14.365 ms 149.444 MB/s + SaxRoundtrip citm_catalog.json ... 3.683 ms 447.241 MB/s + SaxRoundtrip twitter.json ... 2.497 ms 241.193 MB/s + Sax Statistics canada.json ... 5.183 ms 414.194 MB/s + Sax Statistics citm_catalog.json ... 2.333 ms 706.039 MB/s + Sax Statistics twitter.json ... 1.509 ms 399.111 MB/s +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 31072 + +Benchmarking Performance of RapidJSON (C++) + Parse canada.json ... 5.377 ms 399.250 MB/s + Parse citm_catalog.json ... 2.569 ms 641.179 MB/s + Parse twitter.json ... 1.769 ms 340.451 MB/s + Stringify canada.json ... 8.552 ms 251.025 MB/s + Stringify citm_catalog.json ... 1.224 ms 1345.744 MB/s + Stringify twitter.json ... 0.852 ms 706.876 MB/s + Prettify canada.json ... 9.892 ms 217.021 MB/s + Prettify citm_catalog.json ... 1.594 ms 1033.369 MB/s + Prettify twitter.json ... 1.105 ms 545.030 MB/s + Statistics canada.json ... 0.641 ms 3349.094 MB/s + Statistics citm_catalog.json ... 0.204 ms 8074.461 MB/s + Statistics twitter.json ... 0.079 ms 7623.528 MB/s + SaxRoundtrip canada.json ... 13.008 ms 165.035 MB/s + SaxRoundtrip citm_catalog.json ... 3.115 ms 528.793 MB/s + SaxRoundtrip twitter.json ... 2.328 ms 258.702 MB/s + Sax Statistics canada.json ... 4.245 ms 505.717 MB/s + Sax Statistics citm_catalog.json ... 1.899 ms 867.399 MB/s + Sax Statistics twitter.json ... 1.387 ms 434.217 MB/s +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 31072 + +Benchmarking Performance of sajson (C++) + Parse canada.json ... 4.845 ms 443.090 MB/s + Parse citm_catalog.json ... 2.534 ms 650.036 MB/s + Parse twitter.json ... 1.179 ms 510.822 MB/s + Stringify canada.json ... Not support + Stringify citm_catalog.json ... Not support + Stringify twitter.json ... Not support + Prettify canada.json ... Not support + Prettify citm_catalog.json ... Not support + Prettify twitter.json ... Not support + Statistics canada.json ... 0.904 ms 2374.745 MB/s + Statistics citm_catalog.json ... 0.233 ms 7069.485 MB/s + Statistics twitter.json ... 0.069 ms 8728.387 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 35256 + +Benchmarking Performance of Sheredom json.h (C) + Parse canada.json ... 11.502 ms 186.643 MB/s + Parse citm_catalog.json ... 4.674 ms 352.416 MB/s + Parse twitter.json ... 2.537 ms 237.390 MB/s + Stringify canada.json ... 69.411 ms 30.928 MB/s + Stringify citm_catalog.json ... 9.776 ms 168.493 MB/s + Stringify twitter.json ... 2.594 ms 232.174 MB/s + Prettify canada.json ... 75.012 ms 28.619 MB/s + Prettify citm_catalog.json ... 10.900 ms 151.118 MB/s + Prettify twitter.json ... 2.927 ms 205.760 MB/s + Statistics canada.json ... 0.486 ms 4417.221 MB/s + Statistics citm_catalog.json ... 0.219 ms 7521.416 MB/s + Statistics twitter.json ... 0.099 ms 6083.421 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 31064 + +Benchmarking Performance of SimpleJSON (C++) + Parse canada.json ... 26.579 ms 80.769 MB/s + Parse citm_catalog.json ... 21.227 ms 77.599 MB/s + Parse twitter.json ... 16.495 ms 36.512 MB/s + Stringify canada.json ... 235.647 ms 9.110 MB/s + Stringify citm_catalog.json ... 47.634 ms 34.580 MB/s + Stringify twitter.json ... 18.953 ms 31.776 MB/s + Prettify canada.json ... Not support + Prettify citm_catalog.json ... Not support + Prettify twitter.json ... Not support + Statistics canada.json ... 0.581 ms 3694.956 MB/s + Statistics citm_catalog.json ... 0.484 ms 3403.285 MB/s + Statistics twitter.json ... 0.233 ms 2584.801 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 43656 + +Benchmarking Performance of strdup (C) + Parse canada.json ... 0.187 ms 11480.051 MB/s + Parse citm_catalog.json ... 0.147 ms 11205.375 MB/s + Parse twitter.json ... 0.052 ms 11581.898 MB/s + Stringify canada.json ... 0.192 ms 11181.091 MB/s + Stringify citm_catalog.json ... 0.146 ms 11282.124 MB/s + Stringify twitter.json ... 0.052 ms 11581.898 MB/s + Prettify canada.json ... Not support + Prettify citm_catalog.json ... Not support + Prettify twitter.json ... Not support + Statistics canada.json ... Not support + Statistics citm_catalog.json ... Not support + Statistics twitter.json ... Not support + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +Not support Statistics +jsonstat file size = 10584 + +Benchmarking Performance of taocpp/json & Nlohmann (C++11) + Parse canada.json ... 41.324 ms 51.950 MB/s + Parse citm_catalog.json ... 20.303 ms 81.130 MB/s + Parse twitter.json ... 9.541 ms 63.123 MB/s + Stringify canada.json ... 23.453 ms 91.535 MB/s + Stringify citm_catalog.json ... 3.864 ms 426.291 MB/s + Stringify twitter.json ... 2.489 ms 241.968 MB/s + Prettify canada.json ... 31.876 ms 67.348 MB/s + Prettify citm_catalog.json ... 6.150 ms 267.836 MB/s + Prettify twitter.json ... 3.206 ms 187.854 MB/s + Statistics canada.json ... 1.604 ms 1338.385 MB/s + Statistics citm_catalog.json ... 0.968 ms 1701.643 MB/s + Statistics twitter.json ... 0.576 ms 1045.588 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 72448 + +Benchmarking Performance of taocpp/json (C++11) + Parse canada.json ... 23.937 ms 89.684 MB/s + Parse citm_catalog.json ... 12.030 ms 136.924 MB/s + Parse twitter.json ... 5.307 ms 113.484 MB/s + Stringify canada.json ... 22.099 ms 97.143 MB/s + Stringify citm_catalog.json ... 3.109 ms 529.813 MB/s + Stringify twitter.json ... 2.242 ms 268.626 MB/s + Prettify canada.json ... 30.258 ms 70.949 MB/s + Prettify citm_catalog.json ... 5.413 ms 304.303 MB/s + Prettify twitter.json ... 3.034 ms 198.503 MB/s + Statistics canada.json ... 0.669 ms 3208.923 MB/s + Statistics citm_catalog.json ... 0.343 ms 4802.303 MB/s + Statistics twitter.json ... 0.243 ms 2478.431 MB/s + SaxRoundtrip canada.json ... 37.599 ms 57.096 MB/s + SaxRoundtrip citm_catalog.json ... 12.116 ms 135.952 MB/s + SaxRoundtrip twitter.json ... 6.197 ms 97.186 MB/s + Sax Statistics canada.json ... 12.684 ms 169.250 MB/s + Sax Statistics citm_catalog.json ... 7.968 ms 206.726 MB/s + Sax Statistics twitter.json ... 3.751 ms 160.559 MB/s +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 64176 + +Benchmarking Performance of tunnuz/JSON++ (C++) + Parse canada.json ... 145.362 ms 14.768 MB/s + Parse citm_catalog.json ... 68.999 ms 23.873 MB/s + Parse twitter.json ... 34.307 ms 17.555 MB/s + Stringify canada.json ... 199.031 ms 10.786 MB/s + Stringify citm_catalog.json ... 29.755 ms 55.358 MB/s + Stringify twitter.json ... 9.840 ms 61.205 MB/s + Prettify canada.json ... Not support + Prettify citm_catalog.json ... Not support + Prettify twitter.json ... Not support + Statistics canada.json ... 69.066 ms 31.083 MB/s + Statistics citm_catalog.json ... 16.651 ms 98.924 MB/s + Statistics twitter.json ... 5.696 ms 105.734 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 68360 + +Benchmarking Performance of ujson4c (C) + Parse canada.json ... 4.951 ms 433.603 MB/s + Parse citm_catalog.json ... 2.461 ms 669.317 MB/s + Parse twitter.json ... 1.494 ms 403.118 MB/s + Stringify canada.json ... Not support + Stringify citm_catalog.json ... Not support + Stringify twitter.json ... Not support + Prettify canada.json ... Not support + Prettify citm_catalog.json ... Not support + Prettify twitter.json ... Not support + Statistics canada.json ... 1.280 ms 1677.164 MB/s + Statistics citm_catalog.json ... 0.466 ms 3534.743 MB/s + Statistics twitter.json ... 0.216 ms 2788.235 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 27008 + +Benchmarking Performance of ujson (C++) + Parse canada.json ... 25.838 ms 83.086 MB/s + Parse citm_catalog.json ... 9.200 ms 179.042 MB/s + Parse twitter.json ... 5.423 ms 111.056 MB/s + Stringify canada.json ... 22.349 ms 96.057 MB/s + Stringify citm_catalog.json ... 4.034 ms 408.327 MB/s + Stringify twitter.json ... 2.027 ms 297.118 MB/s + Prettify canada.json ... 26.366 ms 81.422 MB/s + Prettify citm_catalog.json ... 5.144 ms 320.216 MB/s + Prettify twitter.json ... 2.450 ms 245.820 MB/s + Statistics canada.json ... 1.214 ms 1768.344 MB/s + Statistics citm_catalog.json ... 0.578 ms 2849.810 MB/s + Statistics twitter.json ... 0.263 ms 2289.957 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 96912 + +Benchmarking Performance of Vinenthz/libjson (C) + Parse canada.json ... 50.267 ms 42.707 MB/s + Parse citm_catalog.json ... 16.192 ms 101.729 MB/s + Parse twitter.json ... 7.504 ms 80.258 MB/s + Stringify canada.json ... 109.105 ms 19.676 MB/s + Stringify citm_catalog.json ... 5.432 ms 303.238 MB/s + Stringify twitter.json ... 4.354 ms 138.323 MB/s + Prettify canada.json ... 109.421 ms 19.619 MB/s + Prettify citm_catalog.json ... 5.417 ms 304.078 MB/s + Prettify twitter.json ... 4.342 ms 138.705 MB/s + Statistics canada.json ... 0.684 ms 3138.552 MB/s + Statistics citm_catalog.json ... 0.350 ms 4706.257 MB/s + Statistics twitter.json ... 0.153 ms 3936.331 MB/s + SaxRoundtrip canada.json ... 14.119 ms 152.048 MB/s + SaxRoundtrip citm_catalog.json ... 11.729 ms 140.437 MB/s + SaxRoundtrip twitter.json ... 7.008 ms 85.939 MB/s + Sax Statistics canada.json ... 11.463 ms 187.278 MB/s + Sax Statistics citm_catalog.json ... 8.546 ms 192.744 MB/s + Sax Statistics twitter.json ... 3.314 ms 181.732 MB/s +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 31096 + +Benchmarking Performance of JSON Voorhees (C++) + Parse canada.json ... 248.772 ms 8.629 MB/s + Parse citm_catalog.json ... 48.753 ms 33.786 MB/s + Parse twitter.json ... 17.957 ms 33.539 MB/s + Stringify canada.json ... 85.937 ms 24.981 MB/s + Stringify citm_catalog.json ... 10.478 ms 157.205 MB/s + Stringify twitter.json ... 12.564 ms 47.935 MB/s + Prettify canada.json ... 188.738 ms 11.374 MB/s + Prettify citm_catalog.json ... 32.949 ms 49.992 MB/s + Prettify twitter.json ... 17.679 ms 34.066 MB/s + Statistics canada.json ... 5.082 ms 422.426 MB/s + Statistics citm_catalog.json ... 0.904 ms 1822.113 MB/s + Statistics twitter.json ... 0.402 ms 1498.156 MB/s + SaxRoundtrip canada.json ... Not support + SaxRoundtrip citm_catalog.json ... Not support + SaxRoundtrip twitter.json ... Not support + Sax Statistics canada.json ... Not support + Sax Statistics citm_catalog.json ... Not support + Sax Statistics twitter.json ... Not support +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 369256 + +Benchmarking Performance of YAJL (C) + Parse canada.json ... 55.202 ms 38.889 MB/s + Parse citm_catalog.json ... 15.281 ms 107.793 MB/s + Parse twitter.json ... 6.051 ms 99.530 MB/s + Stringify canada.json ... 128.608 ms 16.692 MB/s + Stringify citm_catalog.json ... 4.628 ms 355.918 MB/s + Stringify twitter.json ... 2.609 ms 230.839 MB/s + Prettify canada.json ... 147.799 ms 14.525 MB/s + Prettify citm_catalog.json ... 9.244 ms 178.190 MB/s + Prettify twitter.json ... 3.865 ms 155.824 MB/s + Statistics canada.json ... 0.766 ms 2802.571 MB/s + Statistics citm_catalog.json ... 0.355 ms 4639.972 MB/s + Statistics twitter.json ... 0.169 ms 3563.661 MB/s + SaxRoundtrip canada.json ... 160.616 ms 13.366 MB/s + SaxRoundtrip citm_catalog.json ... 10.740 ms 153.370 MB/s + SaxRoundtrip twitter.json ... 4.419 ms 136.288 MB/s + Sax Statistics canada.json ... 31.220 ms 68.763 MB/s + Sax Statistics citm_catalog.json ... 6.041 ms 272.668 MB/s + Sax Statistics twitter.json ... 1.991 ms 302.491 MB/s +objectCount: 4 +arrayCount: 56045 +numberCount: 111126 +stringCount: 12 +trueCount: 0 +falseCount: 0 +nullCount: 0 +memberCount: 8 +elementCount: 167170 +stringLength: 90 +jsonstat file size = 47576 + +Benchmarking Conformance of ULib (C++) + +Benchmarking Conformance of ArduinoJson (C++) + +Benchmarking Conformance of CAJUN (C++) + +Benchmarking Conformance of ccan/json (C) + +Benchmarking Conformance of cJSON (C) + +Benchmarking Conformance of Configuru (C++11) + +Benchmarking Conformance of dropbox/json11 (C++11) + +Benchmarking Conformance of mikeando/FastJson (C++) +fastjson : an error occured [6001] : Input ended while in non-root state +It seems to have happened here... +sed array" + ^ +fastjson : an error occured [5002] : Unexpected character while parsing dict start +It seems to have happened here... +unquoted_k +^ +fastjson : an error occured [2002] : Invalid data found +It seems to have happened here... +] +^ +fastjson : an error occured [2002] : Invalid data found +It seems to have happened here... +,] +^ +fastjson : an error occured [2002] : Invalid data found +It seems to have happened here... +, "<-- mis +^ +fastjson : an error occured [2002] : Invalid data found +It seems to have happened here... +, +^ +fastjson : an error occured [2002] : Invalid data found +It seems to have happened here... +] +^ +fastjson : an error occured [5008] : Unexpected character when looking for dict key +It seems to have happened here... +,} + ^ +fastjson : an error occured [5006] : Unexpected character when looking for comma in dict +It seems to have happened here... ++ 2} +^ +fastjson : an error occured [2002] : Invalid data found +It seems to have happened here... + alert()} + ^ +fastjson : an error occured [5006] : Unexpected character when looking for comma in dict +It seems to have happened here... +13} +^ +fastjson : an error occured [5006] : Unexpected character when looking for comma in dict +It seems to have happened here... +x14} +^ +fastjson : an error occured [3006] : Invalid escape +It seems to have happened here... + escape: \x15"] + ^ +fastjson : an error occured [2002] : Invalid data found +It seems to have happened here... +\naked] +^ +fastjson : an error occured [3006] : Invalid escape +It seems to have happened here... + escape: \017"] + ^ +fastjson : an error occured [5004] : Unexpected character while looking for dict seperator +It seems to have happened here... +null} +^ +fastjson : an error occured [2002] : Invalid data found +It seems to have happened here... +: null} +^ +fastjson : an error occured [5004] : Unexpected character while looking for dict seperator +It seems to have happened here... +, null} +^ +fastjson : an error occured [4003] : Unexpected character while parsing array +It seems to have happened here... +: false] +^ +fastjson : an error occured [2001] : Invalid litteral found when expecting object +It seems to have happened here... + truth] + ^ +fastjson : an error occured [2002] : Invalid data found +It seems to have happened here... +'single qu +^ +fastjson : an error occured [3006] : Invalid escape +It seems to have happened here... +tab\ charact + ^ +fastjson : an error occured [3006] : Invalid escape +It seems to have happened here... +line\ +break"] + ^ +fastjson : an error occured [4003] : Unexpected character while parsing array +It seems to have happened here... +e] +^ +fastjson : an error occured [4003] : Unexpected character while parsing array +It seems to have happened here... +e+] +^ +fastjson : an error occured [4003] : Unexpected character while parsing array +It seems to have happened here... +e+-1] +^ +fastjson : an error occured [5007] : Unexpected end of input when looking for dict key +It seems to have happened here... +, + ^ +fastjson : an error occured [4003] : Unexpected character while parsing array +It seems to have happened here... +} +^ + +Benchmarking Conformance of gason (C++11) + +Benchmarking Conformance of Jansson (C) + +Benchmarking Conformance of JeayeSON (C++14) + +Benchmarking Conformance of jsmn (C) +Error -3 +Error -2 +Error -2 +Error -2 +Error -2 +Error -2 +Error -2 +Error -2 +Error -2 +Error -2 +Error -2 +Error -2 +Error -2 +Error -3 +Error -2 + +Benchmarking Conformance of JsonBox (C++) +Expected '"', got 'u', ignoring it. +Expected '"', got 'n', ignoring it. +Expected '"', got 'q', ignoring it. +Expected '"', got 'u', ignoring it. +Expected '"', got 'o', ignoring it. +Expected '"', got 't', ignoring it. +Expected '"', got 'e', ignoring it. +Expected '"', got 'd', ignoring it. +Expected '"', got '_', ignoring it. +Expected '"', got 'k', ignoring it. +Expected '"', got 'e', ignoring it. +Expected '"', got 'y', ignoring it. +Expected '"', got ':', ignoring it. +Expected '"', got 'u', ignoring it. +Expected '"', got 'l', ignoring it. +Expected '"', got 'l', ignoring it. +Expected '"', got 'n', ignoring it. +Expected '"', got 'u', ignoring it. +Expected '"', got 'l', ignoring it. +Expected '"', got 'l', ignoring it. +Expected a digit, '.', 'e' or 'E', got '-' instead, ignoring it. + +Benchmarking Conformance of jsoncons (C++) + +Benchmarking Conformance of JsonCpp (C++) + +Benchmarking Conformance of json-c (C) + +Benchmarking Conformance of JSON Spirit (C++) + +Benchmarking Conformance of hjiang/JSON++ (C++) + +Benchmarking Conformance of juson (C) +Benchmarking Conformance of JVar (C++) + +Benchmarking Conformance of Jzon (C++) + +Benchmarking Conformance of nbsdx_SimpleJSON (C++11) +ERROR: Array: Expected ',' or ']', found '' +ERROR: Parse: Unknown starting character 'u' +Error: Object: Expected colon, found 'u' +ERROR: Parse: Unknown starting character ']' +ERROR: Parse: Unknown starting character ',' +ERROR: Parse: Unknown starting character ']' +ERROR: Parse: Unknown starting character ',' +ERROR: Parse: Unknown starting character '}' +Error: Object: Expected colon, found '}' +ERROR: Object: Expected comma, found '+' +ERROR: Parse: Unknown starting character 'a' +ERROR: Object: Expected comma, found 'a' +ERROR: Number: unexpected character 'x' +ERROR: Object: Expected comma, found '1' +ERROR: Parse: Unknown starting character '\' +ERROR: Array: Expected ',' or ']', found '\' +Error: Object: Expected colon, found 'n' +ERROR: Parse: Unknown starting character ':' +ERROR: Object: Expected comma, found ':' +Error: Object: Expected colon, found ',' +ERROR: Array: Expected ',' or ']', found ':' +ERROR: Bool: Expected 'true' or 'false', found 'truth' +ERROR: Array: Expected ',' or ']', found 't' +ERROR: Parse: Unknown starting character ''' +ERROR: Array: Expected ',' or ']', found ''' +ERROR: Number: Expected a number for exponent, found '' +ERROR: Array: Expected ',' or ']', found 'e' +ERROR: Number: Expected a number for exponent, found '-' +ERROR: Array: Expected ',' or ']', found '1' +ERROR: Parse: Unknown starting character '' +Error: Object: Expected colon, found '' +ERROR: Array: Expected ',' or ']', found '}' + +Benchmarking Conformance of Nlohmann (C++11) + +Benchmarking Conformance of Parson (C) + +Warning: potential memory leak (1 allocations for 24 bytes) +... + +Benchmarking Conformance of PicoJSON (C++) + +Benchmarking Conformance of RapidJSON_AutoUTF (C++) + +Benchmarking Conformance of RapidJSON_FullPrec (C++) + +Benchmarking Conformance of RapidJSON_Insitu (C++) + +Benchmarking Conformance of RapidJSON_Iterative (C++) + +Benchmarking Conformance of RapidJSON (C++) + +Benchmarking Conformance of sajson (C++) + +Benchmarking Conformance of Sheredom json.h (C) + +Benchmarking Conformance of SimpleJSON (C++) + +Benchmarking Conformance of taocpp/json & Nlohmann (C++11) + +Benchmarking Conformance of taocpp/json (C++11) + +Benchmarking Conformance of tunnuz/JSON++ (C++) +error: syntax error + +Warning: potential memory leak (5 allocations for 296 bytes) +... + +error: syntax error + +Benchmarking Conformance of ujson4c (C) + +Benchmarking Conformance of ujson (C++) + +Benchmarking Conformance of Vinenthz/libjson (C) + +Warning: potential memory leak (4 allocations for 96 bytes) +... +Benchmarking Conformance of JSON Voorhees (C++) + +Benchmarking Conformance of YAJL (C) + +Warning: potential memory leak (5 allocations for 152 bytes) +... diff --git a/src/ulib/Makefile.am b/src/ulib/Makefile.am index cd737f46..f38c4395 100644 --- a/src/ulib/Makefile.am +++ b/src/ulib/Makefile.am @@ -174,7 +174,7 @@ endif if SSL SRC_C += base/ssl/cdes3.c base/ssl/dgst.c -SRC_CPP += ssl/certificate.cpp ssl/pkcs7.cpp ssl/crl.cpp ssl/pkcs10.cpp net/client/twilio.cpp \ +SRC_CPP += ssl/certificate.cpp ssl/pkcs7.cpp ssl/crl.cpp ssl/pkcs10.cpp net/client/twilio.cpp net/client/uwebsocket.cpp \ ssl/mime/mime_pkcs7.cpp ssl/net/sslsocket.cpp ssl/net/ssl_session.cpp utility/des3.cpp if SSL_TS SRC_CPP += ssl/timestamp.cpp diff --git a/src/ulib/Makefile.in b/src/ulib/Makefile.in index 80300069..c318d802 100644 --- a/src/ulib/Makefile.in +++ b/src/ulib/Makefile.in @@ -115,7 +115,7 @@ target_triplet = @target@ @USE_PARSER_TRUE@am__append_33 = flex/flexer.cpp flex/bison.cpp @PCRE_TRUE@am__append_34 = pcre/pcre.cpp @SSL_TRUE@am__append_35 = base/ssl/cdes3.c base/ssl/dgst.c -@SSL_TRUE@am__append_36 = ssl/certificate.cpp ssl/pkcs7.cpp ssl/crl.cpp ssl/pkcs10.cpp net/client/twilio.cpp \ +@SSL_TRUE@am__append_36 = ssl/certificate.cpp ssl/pkcs7.cpp ssl/crl.cpp ssl/pkcs10.cpp net/client/twilio.cpp net/client/uwebsocket.cpp \ @SSL_TRUE@ ssl/mime/mime_pkcs7.cpp ssl/net/sslsocket.cpp ssl/net/ssl_session.cpp utility/des3.cpp @SSL_TRUE@@SSL_TS_TRUE@am__append_37 = ssl/timestamp.cpp @@ -267,10 +267,11 @@ am__lib@ULIB@_la_SOURCES_DIST = base/base.c base/base_error.c \ debug/objectDB.cpp internal/memory_pool.cpp zip/zip.cpp \ flex/flexer.cpp flex/bison.cpp pcre/pcre.cpp \ ssl/certificate.cpp ssl/pkcs7.cpp ssl/crl.cpp ssl/pkcs10.cpp \ - net/client/twilio.cpp ssl/mime/mime_pkcs7.cpp \ - ssl/net/sslsocket.cpp ssl/net/ssl_session.cpp utility/des3.cpp \ - ssl/timestamp.cpp ssh/net/sshsocket.cpp ldap/ldap.cpp \ - curl/curl.cpp xml/expat/attribute.cpp xml/expat/element.cpp \ + net/client/twilio.cpp net/client/uwebsocket.cpp \ + ssl/mime/mime_pkcs7.cpp ssl/net/sslsocket.cpp \ + ssl/net/ssl_session.cpp utility/des3.cpp ssl/timestamp.cpp \ + ssh/net/sshsocket.cpp ldap/ldap.cpp curl/curl.cpp \ + xml/expat/attribute.cpp xml/expat/element.cpp \ xml/expat/xml_parser.cpp xml/expat/xml2txt.cpp \ xml/soap/soap_fault.cpp xml/soap/soap_gen_method.cpp \ xml/soap/soap_parser.cpp xml/soap/soap_encoder.cpp \ @@ -347,8 +348,9 @@ am__objects_26 = base/base.lo base/base_error.lo base/hash.lo \ @PCRE_TRUE@am__objects_37 = pcre/pcre.lo @SSL_TRUE@am__objects_38 = ssl/certificate.lo ssl/pkcs7.lo ssl/crl.lo \ @SSL_TRUE@ ssl/pkcs10.lo net/client/twilio.lo \ -@SSL_TRUE@ ssl/mime/mime_pkcs7.lo ssl/net/sslsocket.lo \ -@SSL_TRUE@ ssl/net/ssl_session.lo utility/des3.lo +@SSL_TRUE@ net/client/uwebsocket.lo ssl/mime/mime_pkcs7.lo \ +@SSL_TRUE@ ssl/net/sslsocket.lo ssl/net/ssl_session.lo \ +@SSL_TRUE@ utility/des3.lo @SSL_TRUE@@SSL_TS_TRUE@am__objects_39 = ssl/timestamp.lo @SSH_TRUE@am__objects_40 = ssh/net/sshsocket.lo @LDAP_TRUE@am__objects_41 = ldap/ldap.lo @@ -1256,6 +1258,8 @@ ssl/crl.lo: ssl/$(am__dirstamp) ssl/$(DEPDIR)/$(am__dirstamp) ssl/pkcs10.lo: ssl/$(am__dirstamp) ssl/$(DEPDIR)/$(am__dirstamp) net/client/twilio.lo: net/client/$(am__dirstamp) \ net/client/$(DEPDIR)/$(am__dirstamp) +net/client/uwebsocket.lo: net/client/$(am__dirstamp) \ + net/client/$(DEPDIR)/$(am__dirstamp) ssl/mime/$(am__dirstamp): @$(MKDIR_P) ssl/mime @: > ssl/mime/$(am__dirstamp) @@ -1608,6 +1612,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@net/client/$(DEPDIR)/redis.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@net/client/$(DEPDIR)/smtp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@net/client/$(DEPDIR)/twilio.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@net/client/$(DEPDIR)/uwebsocket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@net/rpc/$(DEPDIR)/rpc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@net/rpc/$(DEPDIR)/rpc_client.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@net/rpc/$(DEPDIR)/rpc_encoder.Plo@am__quote@ diff --git a/src/ulib/all_cpp.cpp b/src/ulib/all_cpp.cpp index b9f495f9..9b72b497 100644 --- a/src/ulib/all_cpp.cpp +++ b/src/ulib/all_cpp.cpp @@ -119,6 +119,7 @@ # include "ssl/crl.cpp" # include "ssl/pkcs10.cpp" # include "net/client/twilio.cpp" +# include "net/client/uwebsocket.cpp" # include "ssl/mime/mime_pkcs7.cpp" # include "ssl/net/sslsocket.cpp" # include "ssl/net/ssl_session.cpp" diff --git a/src/ulib/file_config.cpp b/src/ulib/file_config.cpp index 94d61737..08e180b4 100644 --- a/src/ulib/file_config.cpp +++ b/src/ulib/file_config.cpp @@ -104,9 +104,7 @@ bool UFileConfig::processData(bool bload) (void) cmd.execute(&data, &output, -1, fd_stderr); -# ifndef U_LOG_DISABLE - UServer_Base::logCommandMsgError(cmd.getCommand(), true); -# endif + U_SRV_LOG_CMD_MSG_ERR(cmd, true); # ifdef HAVE_MCPP if (data.empty()) @@ -117,9 +115,7 @@ bool UFileConfig::processData(bool bload) (void) _cmd.execute(&data, &output, -1, fd_stderr); -# ifndef U_LOG_DISABLE - UServer_Base::logCommandMsgError(_cmd.getCommand(), true); -# endif + U_SRV_LOG_CMD_MSG_ERR(_cmd, true); } # endif diff --git a/src/ulib/net/client/client.cpp b/src/ulib/net/client/client.cpp index 5b5d3f58..dfd37fc9 100644 --- a/src/ulib/net/client/client.cpp +++ b/src/ulib/net/client/client.cpp @@ -378,7 +378,7 @@ bool UClient_Base::setUrl(const char* str, uint32_t len) url.set(str, len); - if (socket->isSSL()) socket->setSSLActive(url.isHTTPS()); + if (socket->isSSL()) socket->setSSLActive(url.isHTTPS() | url.isWSS()); uri = url.getPathAndQuery(); diff --git a/src/ulib/net/client/http.cpp b/src/ulib/net/client/http.cpp index 3933164d..56b6e7f4 100644 --- a/src/ulib/net/client/http.cpp +++ b/src/ulib/net/client/http.cpp @@ -882,7 +882,7 @@ bool UHttpClient_Base::sendRequestEngine() responseHeader->clear(); result = (UClient_Base::sendRequestAndReadResponse() && - responseHeader->readHeader(UClient_Base::socket, UClient_Base::response) // read the HTTP response header + UClient_Base::processHeader(responseHeader) ? checkResponse(redirectCount, _uri) : -1); diff --git a/src/ulib/net/client/uwebsocket.cpp b/src/ulib/net/client/uwebsocket.cpp new file mode 100644 index 00000000..909b206c --- /dev/null +++ b/src/ulib/net/client/uwebsocket.cpp @@ -0,0 +1,77 @@ +// ============================================================================ +// +// = LIBRARY +// ULib - c++ library +// +// = FILENAME +// uwebsocket.cpp +// +// = AUTHOR +// Stefano Casazza +// +// ============================================================================ + +#include + +bool UWebSocketClient::connectServer(const UString& url) +{ + U_TRACE(0, "UWebSocketClient::connectServer(%V)", url.rep) + + U_INTERNAL_ASSERT_POINTER(client) + + if (client->UClient_Base::connectServer(url)) + { + UMimeHeader responseHeader; + UString buffer(U_CAPACITY); + + buffer.snprintf(U_CONSTANT_TO_PARAM( + "GET %v HTTP/1.1\r\n" + "Host: %v:%u\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n" + "Sec-WebSocket-Version: 13\r\n" + "\r\n"), + client->UClient_Base::uri.rep, client->UClient_Base::server.rep, client->UClient_Base::port); + + client->UClient_Base::prepareRequest(buffer); + + if (client->UClient_Base::sendRequestAndReadResponse() && + (responseHeader.setIgnoreCase(true), client->UClient_Base::processHeader(&responseHeader))) + { + /** + * HTTP/1.1 101 Switching Protocols\r\n + * Upgrade: websocket\r\n + * Connection: Upgrade\r\n + * Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n\r\n + */ + + if (U_http_info.nResponseCode != 101) U_RETURN(false); // invalid HTTP status response code + + if (responseHeader.getHeader(U_CONSTANT_TO_PARAM("Upgrade")).equalnocase(U_CONSTANT_TO_PARAM("websocket")) == false) U_RETURN(false); // invalid HTTP upgrade header + if (responseHeader.getHeader(U_CONSTANT_TO_PARAM("Connection")).equalnocase(U_CONSTANT_TO_PARAM("Upgrade")) == false) U_RETURN(false); // invalid HTTP connection header + + if (responseHeader.getHeader(U_CONSTANT_TO_PARAM("Sec-WebSocket-Accept")).equal(U_CONSTANT_TO_PARAM("s3pPLMBiTxaQ9kYGzzhZRbK+xOo="))) U_RETURN(true); + } + } + + U_RETURN(false); +} + +// DEBUG + +#if defined(U_STDCPP_ENABLE) && defined(DEBUG) +const char* UWebSocketClient::dump(bool _reset) const +{ + *UObjectIO::os << "client (UClient " << (void*)client << ')'; + + if (_reset) + { + UObjectIO::output(); + + return UObjectIO::buffer_output; + } + + return U_NULLPTR; +} +#endif diff --git a/src/ulib/net/server/client_image.cpp b/src/ulib/net/server/client_image.cpp index 3f490242..0695d779 100644 --- a/src/ulib/net/server/client_image.cpp +++ b/src/ulib/net/server/client_image.cpp @@ -923,7 +923,9 @@ void UClientImage_Base::manageReadBufferResize(uint32_t n) if (U_http_info.user_agent_len) U_http_info.user_agent += diff; if (U_http_accept_language_len) U_http_info.accept_language += diff; +# if defined(USE_LIBSSL) && !defined(U_SERVER_CAPTIVE_PORTAL) if (U_http_websocket_len) UWebSocket::upgrade_settings += diff; +# endif U_INTERNAL_DUMP("host = %.*S", U_HTTP_HOST_TO_TRACE) U_INTERNAL_DUMP("vhost = %.*S", U_HTTP_VHOST_TO_TRACE) diff --git a/src/ulib/net/server/plugin/mod_nocat.cpp b/src/ulib/net/server/plugin/mod_nocat.cpp index 581edfc8..6300a663 100644 --- a/src/ulib/net/server/plugin/mod_nocat.cpp +++ b/src/ulib/net/server/plugin/mod_nocat.cpp @@ -657,9 +657,7 @@ loop: ok = fw->execute(U_NULLPTR, &output, -1, fd_stderr); -#ifndef U_LOG_DISABLE - UServer_Base::logCommandMsgError(fw->getCommand(), false); -#endif + U_SRV_LOG_CMD_MSG_ERR(*fw, false); if (ok == false) { @@ -771,9 +769,7 @@ bool UNoCatPlugIn::checkFirewall() (void) _fw.executeAndWait(U_NULLPTR, -1, fd_stderr); -# ifndef U_LOG_DISABLE - UServer_Base::logCommandMsgError(_fw.getCommand(), false); -# endif + U_SRV_LOG_CMD_MSG_ERR(_fw, false); } } @@ -1057,9 +1053,7 @@ UString UNoCatPlugIn::getSignedData(const char* ptr, uint32_t len) (void) pgp.execute(&input, &output, -1, fd_stderr); -# ifndef U_LOG_DISABLE - UServer_Base::logCommandMsgError(pgp.getCommand(), false); -# endif + U_SRV_LOG_CMD_MSG_ERR(pgp, false); } */ @@ -2337,9 +2331,7 @@ int UNoCatPlugIn::handlerFork() (void) fw->executeAndWait(U_NULLPTR, -1, fd_stderr); -#ifndef U_LOG_DISABLE - UServer_Base::logCommandMsgError(fw->getCommand(), false); -#endif + U_SRV_LOG_CMD_MSG_ERR(*fw, false); fw->delArgument(); fw->setLastArgument("openlist"); diff --git a/src/ulib/net/server/plugin/mod_nodog.cpp b/src/ulib/net/server/plugin/mod_nodog.cpp index 05068787..c49f5ce2 100644 --- a/src/ulib/net/server/plugin/mod_nodog.cpp +++ b/src/ulib/net/server/plugin/mod_nodog.cpp @@ -360,9 +360,7 @@ void UNoDogPlugIn::executeCommand(const char* type, uint32_t len) (void) cmd.executeAndWait(U_NULLPTR, -1, fd_stderr); -#ifndef U_LOG_DISABLE - UServer_Base::logCommandMsgError(cmd.getCommand(), false); -#endif + U_SRV_LOG_CMD_MSG_ERR(cmd, false); } U_NO_EXPORT void UNoDogPlugIn::setMAC() @@ -989,9 +987,7 @@ end: (void) fw->executeAndWait(U_NULLPTR, -1, fd_stderr); -#ifndef U_LOG_DISABLE - UServer_Base::logCommandMsgError(fw->getCommand(), false); -#endif + U_SRV_LOG_CMD_MSG_ERR(*fw, false); fw->delArgument(); fw->setLastArgument("openlist"); @@ -1277,7 +1273,7 @@ next1: eraseTimer(); goto end; } - if (U_HTTP_URI_STREQ("/nodog_peer_delay.sh")) + if (U_HTTP_URI_MEMEQ("/nodog_peer_delay.sh")) { if (U_peer_delay_disable == false) { diff --git a/src/ulib/net/server/plugin/mod_proxy.cpp b/src/ulib/net/server/plugin/mod_proxy.cpp index 0570d2c2..4ba35319 100644 --- a/src/ulib/net/server/plugin/mod_proxy.cpp +++ b/src/ulib/net/server/plugin/mod_proxy.cpp @@ -146,6 +146,7 @@ int UProxyPlugIn::handlerRequest() client_http->UClient_Base::close(); } +# if defined(USE_LIBSSL) && !defined(U_SERVER_CAPTIVE_PORTAL) // -------------------------------------------------------------------------------------------------------------------- // A WebSocket is a long-lived connection, lasting hours or days. If each WebSocket proxy holds the original thread, // won't that consume all of the workers very quickly? It looks as if my server, with 16 workers, will be unable to @@ -158,9 +159,9 @@ int UProxyPlugIn::handlerRequest() { UWebSocket::checkForInitialData(); // check if we have read more data than necessary... - while (UWebSocket::handleDataFraming(UServer_Base::csocket) == STATUS_CODE_OK && + while (UWebSocket::handleDataFraming(UServer_Base::csocket) == U_WS_STATUS_CODE_OK && (client_http->UClient_Base::prepareRequest(*UClientImage_Base::wbuffer), client_http->UClient_Base::sendRequestAndReadResponse()) && - UWebSocket::sendData(UWebSocket::message_type, (const unsigned char*)U_STRING_TO_PARAM(client_http->UClient_Base::response))) + UWebSocket::sendData(UServer_Base::csocket, UWebSocket::message_type, client_http->UClient_Base::response)) { client_http->UClient_Base::clearData(); @@ -169,6 +170,7 @@ int UProxyPlugIn::handlerRequest() U_RETURN(U_PLUGIN_HANDLER_ERROR); } +# endif client_http->setFollowRedirects(UHTTP::service->isFollowRedirects(), true); if (UHTTP::service->isAuthorization()) client_http->setRequestPasswordAuthentication(UHTTP::service->getUser(), UHTTP::service->getPassword()); diff --git a/src/ulib/net/server/plugin/mod_socket.cpp b/src/ulib/net/server/plugin/mod_socket.cpp index 66a4a129..1f67c7a0 100644 --- a/src/ulib/net/server/plugin/mod_socket.cpp +++ b/src/ulib/net/server/plugin/mod_socket.cpp @@ -21,7 +21,9 @@ U_CREAT_FUNC(server_plugin_socket, UWebSocketPlugIn) +int UWebSocketPlugIn::fd_stderr; vPFi UWebSocketPlugIn::on_message; +UString* UWebSocketPlugIn::penvironment; UCommand* UWebSocketPlugIn::command; UWebSocketPlugIn::UWebSocketPlugIn() @@ -33,8 +35,17 @@ UWebSocketPlugIn::~UWebSocketPlugIn() { U_TRACE_DTOR(0, UWebSocketPlugIn) - if (command) U_DELETE(command) - if (UWebSocket::rbuffer) U_DELETE(UWebSocket::rbuffer) + if (command) + { + U_DELETE(command) + U_DELETE(penvironment) + } + + if (UWebSocket::rbuffer) + { + U_DELETE(UWebSocket::rbuffer) + U_DELETE(UWebSocket::message) + } } RETSIGTYPE UWebSocketPlugIn::handlerForSigTERM(int signo) @@ -50,10 +61,11 @@ int UWebSocketPlugIn::handlerConfig(UFileConfig& cfg) { U_TRACE(0, "UWebSocketPlugIn::handlerConfig(%p)", &cfg) + // ---------------------------------------------------------------------------------------------- // Perform registration of web socket method // ---------------------------------------------------------------------------------------------- - // COMMAND command (alternative to USP websocket) to execute - // ENVIRONMENT environment for command (alternative to USP websocket) to execute + // COMMAND command (alternative to USP modsocket) to execute + // ENVIRONMENT environment for command (alternative to USP modsocket) to execute // // MAX_MESSAGE_SIZE Maximum size (in bytes) of a message to accept; default is approximately 4GB // ---------------------------------------------------------------------------------------------- @@ -62,8 +74,12 @@ int UWebSocketPlugIn::handlerConfig(UFileConfig& cfg) { command = UServer_Base::loadConfigCommand(); + U_NEW_STRING(penvironment, UString(U_CAPACITY)); + UWebSocket::max_message_size = cfg.readLong(U_CONSTANT_TO_PARAM("MAX_MESSAGE_SIZE"), U_STRING_MAX_SIZE); + fd_stderr = UServices::getDevNull("/tmp/UWebSocketPlugIn.err"); + U_RETURN(U_PLUGIN_HANDLER_PROCESSED); } @@ -75,21 +91,21 @@ int UWebSocketPlugIn::handlerRun() U_TRACE_NO_PARAM(0, "UWebSocketPlugIn::handlerRun()") U_INTERNAL_ASSERT_EQUALS(UWebSocket::rbuffer, U_NULLPTR) + U_INTERNAL_ASSERT_EQUALS(UWebSocket::message, U_NULLPTR) U_NEW_STRING(UWebSocket::rbuffer, UString(U_CAPACITY)); + U_NEW_STRING(UWebSocket::message, UString(U_CAPACITY)); - if (UHTTP::getUSP(U_CONSTANT_TO_PARAM("modsocket"))) + if (command == U_NULLPTR) { + if (UHTTP::getUSP(U_CONSTANT_TO_PARAM("modsocket")) == false) U_RETURN(U_PLUGIN_HANDLER_ERROR); + U_INTERNAL_DUMP("modsocket->runDynamicPage = %p", UHTTP::usp->runDynamicPage) U_INTERNAL_ASSERT_POINTER(UHTTP::usp->runDynamicPage) on_message = UHTTP::usp->runDynamicPage; } - else - { - if (command == U_NULLPTR) U_RETURN(U_PLUGIN_HANDLER_ERROR); - } U_RETURN(U_PLUGIN_HANDLER_OK); } @@ -102,45 +118,40 @@ int UWebSocketPlugIn::handlerRequest() if (U_http_websocket_len) { - int fdmax = 0; + int fdmax = 0; // NB: to avoid 'warning: fdmax may be used uninitialized in this function'... fd_set fd_set_read, read_set; - bool bcommand = (command && on_message == U_NULLPTR); - - if (bcommand) - { - // Set environment for the command application server - - static int fd_stderr; - - if (fd_stderr == 0) fd_stderr = UServices::getDevNull("/tmp/UWebSocketPlugIn.err"); - - UString environment(U_CAPACITY); - - (void) environment.append(command->getStringEnvironment()); - - if (UHTTP::getCGIEnvironment(environment, U_GENERIC) == false) U_RETURN(U_PLUGIN_HANDLER_ERROR); - - command->setEnvironment(&environment); - - if (command->execute((UString*)-1, (UString*)-1, -1, fd_stderr)) - { -# ifndef U_LOG_DISABLE - UServer_Base::logCommandMsgError(command->getCommand(), true); -# endif - - UInterrupt::setHandlerForSignal(SIGTERM, (sighandler_t)UWebSocketPlugIn::handlerForSigTERM); // sync signal - } - - FD_ZERO(&fd_set_read); - FD_SET(UProcess::filedes[2], &fd_set_read); - FD_SET(UServer_Base::csocket->iSockDesc, &fd_set_read); - - fdmax = U_max(UServer_Base::csocket->iSockDesc, UProcess::filedes[2]) + 1; - } UWebSocket::checkForInitialData(); // check if we have read more data than necessary... - if (bcommand == false) goto handle_data; + if (command == U_NULLPTR) + { + on_message(U_DPAGE_OPEN); + + goto data; + } + + // Set environment for the command application server + + penvironment->setBuffer(U_CAPACITY); + + (void) penvironment->append(command->getStringEnvironment()); + + if (UHTTP::getCGIEnvironment(*penvironment, U_GENERIC) == false) U_RETURN(U_PLUGIN_HANDLER_ERROR); + + command->setEnvironment(penvironment); + + if (command->execute((UString*)-1, (UString*)-1, -1, fd_stderr)) + { + U_SRV_LOG_CMD_MSG_ERR(*command, true); + + UInterrupt::setHandlerForSignal(SIGTERM, (sighandler_t)UWebSocketPlugIn::handlerForSigTERM); // sync signal + } + + FD_ZERO(&fd_set_read); + FD_SET(UProcess::filedes[2], &fd_set_read); + FD_SET(UServer_Base::csocket->iSockDesc, &fd_set_read); + + fdmax = U_max(UServer_Base::csocket->iSockDesc, UProcess::filedes[2]) + 1; loop: read_set = fd_set_read; @@ -151,7 +162,7 @@ loop: read_set = fd_set_read; UWebSocket::rbuffer->setEmpty(); if (UServices::read(UProcess::filedes[2], *UWebSocket::rbuffer) && - UWebSocket::sendData(UWebSocket::message_type, (const unsigned char*)U_STRING_TO_PARAM(*UWebSocket::rbuffer))) + UWebSocket::sendData(UServer_Base::csocket, UWebSocket::message_type, *UWebSocket::rbuffer)) { UWebSocket::rbuffer->setEmpty(); @@ -160,16 +171,25 @@ loop: read_set = fd_set_read; } else if (FD_ISSET(UServer_Base::csocket->iSockDesc, &read_set)) { -handle_data: - if (UWebSocket::handleDataFraming(UServer_Base::csocket) == STATUS_CODE_OK && - (bcommand == false ? (on_message(0), U_http_info.nResponseCode != HTTP_INTERNAL_ERROR) - : UNotifier::write(UProcess::filedes[1], U_STRING_TO_PARAM(*UClientImage_Base::wbuffer)))) +data: if (UWebSocket::handleDataFraming(UServer_Base::csocket) == U_WS_STATUS_CODE_OK) { - UWebSocket::rbuffer->setEmpty(); + if (command == U_NULLPTR) + { + on_message(0); - if (bcommand == false) goto handle_data; + if (U_http_info.nResponseCode != HTTP_INTERNAL_ERROR) + { + UWebSocket::rbuffer->setEmpty(); - goto loop; + goto data; + } + } + else if (UNotifier::write(UProcess::filedes[1], U_STRING_TO_PARAM(*UClientImage_Base::wbuffer))) + { + UWebSocket::rbuffer->setEmpty(); + + goto loop; + } } } } @@ -177,7 +197,7 @@ handle_data: // Send server-side closing handshake if (UServer_Base::csocket->isOpen() && - UWebSocket::sendClose()) + UWebSocket::sendClose(UServer_Base::csocket)) { UClientImage_Base::close(); } @@ -186,6 +206,8 @@ handle_data: UClientImage_Base::setRequestProcessed(); } + if (command == U_NULLPTR) on_message(U_DPAGE_CLOSE); + U_RETURN(U_PLUGIN_HANDLER_PROCESSED); } @@ -197,8 +219,10 @@ handle_data: #if defined(U_STDCPP_ENABLE) && defined(DEBUG) const char* UWebSocketPlugIn::dump(bool reset) const { - *UObjectIO::os << "on_message " << (void*)on_message << '\n' - << "command (UCommand " << (void*)command << ')'; + *UObjectIO::os << "fd_stderr " << fd_stderr << '\n' + << "on_message " << (void*)on_message << '\n' + << "command (UCommand " << (void*)command << ")\n" + << "penvironment (UString " << (void*)penvironment << ')'; if (reset) { diff --git a/src/ulib/net/server/plugin/mod_stream.cpp b/src/ulib/net/server/plugin/mod_stream.cpp index 7ac7f9e2..d913e215 100644 --- a/src/ulib/net/server/plugin/mod_stream.cpp +++ b/src/ulib/net/server/plugin/mod_stream.cpp @@ -111,9 +111,7 @@ int UStreamPlugIn::handlerInit() bool result = command->execute(U_NULLPTR, (UString*)-1, -1, fd_stderr); -#ifndef U_LOG_DISABLE - UServer_Base::logCommandMsgError(command->getCommand(), true); -#endif + U_SRV_LOG_CMD_MSG_ERR(*command, false); if (result == false) { diff --git a/src/ulib/net/server/plugin/mod_tsa.cpp b/src/ulib/net/server/plugin/mod_tsa.cpp index 3edc3fa0..4111d2d7 100644 --- a/src/ulib/net/server/plugin/mod_tsa.cpp +++ b/src/ulib/net/server/plugin/mod_tsa.cpp @@ -100,9 +100,7 @@ int UTsaPlugIn::handlerRequest() UHTTP::setResponse(*UString::str_ctype_tsa, &body); } -# ifndef U_LOG_DISABLE - UServer_Base::logCommandMsgError(command->getCommand(), true); -# endif + U_SRV_LOG_CMD_MSG_ERR(*command, true); U_RETURN(U_PLUGIN_HANDLER_PROCESSED); } diff --git a/src/ulib/net/server/plugin/usp/modsocket.usp b/src/ulib/net/server/plugin/usp/modsocket.usp index b7a0379d..5af57b42 100644 --- a/src/ulib/net/server/plugin/usp/modsocket.usp +++ b/src/ulib/net/server/plugin/usp/modsocket.usp @@ -1,3 +1,87 @@ - + + + diff --git a/src/ulib/net/server/plugin/usp/usp_translator.cpp b/src/ulib/net/server/plugin/usp/usp_translator.cpp index 035cc847..3f1c6b7c 100644 --- a/src/ulib/net/server/plugin/usp/usp_translator.cpp +++ b/src/ulib/net/server/plugin/usp/usp_translator.cpp @@ -712,37 +712,56 @@ loop: distance = t.getDistance(); U_INTERNAL_DUMP("declaration = %V", declaration.rep) - bool binit, // usp_init (Server-wide hooks)... + /** + * Server-wide hooks + * + * enum DynamicPageType { + * U_DPAGE_INIT = -1, + * U_DPAGE_RESET = -2, + * U_DPAGE_DESTROY = -3, + * U_DPAGE_SIGHUP = -4, + * U_DPAGE_FORK = -5, + * U_DPAGE_OPEN = -6, + * U_DPAGE_CLOSE = -7 }; + */ + + bool binit, // usp_init + breset, // usp_reset bend, // usp_end bsighup, // usp_sighup - bfork; // usp_fork + bfork, // usp_fork + bopen, // usp_open + bclose; // usp_close char ptr1[100] = { '\0' }; char ptr2[100] = { '\0' }; char ptr3[100] = { '\0' }; char ptr4[100] = { '\0' }; char ptr5[100] = { '\0' }; - const char* ptr6 = ""; - const char* ptr7 = ""; + char ptr6[100] = { '\0' }; + char ptr7[100] = { '\0' }; + const char* ptr8 = ""; # ifndef U_CACHE_REQUEST_DISABLE if (usp.c_char(4) == '#' && u__isspace(usp.c_char(5)) && u_get_unalignedp32(usp.data()) == U_MULTICHAR_CONSTANT32('<','!','-','-')) // (comment) { - ptr7 = "\n\tUClientImage_Base::setRequestNoCache();\n\t\n"; + ptr8 = "\n\tUClientImage_Base::setRequestNoCache();\n\t\n"; } # endif if (declaration) { binit = (U_STRING_FIND(declaration, 0, "static void usp_init_") != U_NOT_FOUND); + breset = (U_STRING_FIND(declaration, 0, "static void usp_reset_") != U_NOT_FOUND); bend = (U_STRING_FIND(declaration, 0, "static void usp_end_") != U_NOT_FOUND); bsighup = (U_STRING_FIND(declaration, 0, "static void usp_sighup_") != U_NOT_FOUND); bfork = (U_STRING_FIND(declaration, 0, "static void usp_fork_") != U_NOT_FOUND); + bopen = (U_STRING_FIND(declaration, 0, "static void usp_open_") != U_NOT_FOUND); + bclose = (U_STRING_FIND(declaration, 0, "static void usp_close_") != U_NOT_FOUND); - if (bfork) (void) u__snprintf(ptr5, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_FORK) { usp_fork_%.*s(); return; }\n"), basename_sz, basename_ptr); - if (bsighup) (void) u__snprintf(ptr4, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_SIGHUP) { usp_sighup_%.*s(); return; }\n"), basename_sz, basename_ptr); + if (breset) (void) u__snprintf(ptr2, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_RESET) { usp_reset_%.*s(); return; }\n"), basename_sz, basename_ptr); if (bend) { @@ -752,16 +771,24 @@ loop: distance = t.getDistance(); # endif (void) u__snprintf(ptr3, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_DESTROY) { usp_end_%.*s(); return; }\n"), basename_sz, basename_ptr); } + + if (bsighup) (void) u__snprintf(ptr4, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_SIGHUP) { usp_sighup_%.*s(); return; }\n"), basename_sz, basename_ptr); + if (bfork) (void) u__snprintf(ptr5, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_FORK) { usp_fork_%.*s(); return; }\n"), basename_sz, basename_ptr); + if (bopen) (void) u__snprintf(ptr6, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_OPEN) { usp_open_%.*s(); return; }\n"), basename_sz, basename_ptr); + if (bclose) (void) u__snprintf(ptr7, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_CLOSE) { usp_close_%.*s(); return; }\n"), basename_sz, basename_ptr); } else { binit = + breset = bend = bsighup = - bfork = false; + bfork = + bopen = + bclose = false; } - U_INTERNAL_DUMP("binit = %b bend = %b bsighup = %b bfork = %b", binit, bend, bsighup, bfork) + U_INTERNAL_DUMP("binit = %b breset = %b bend = %b bsighup = %b bfork = %b bopen = %b bclose = %b", binit, breset, bend, bsighup, bfork, bopen, bclose) if (binit == false && (bsession || bstorage)) @@ -787,15 +814,6 @@ loop: distance = t.getDistance(); if (binit) (void) u__snprintf(ptr1, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_INIT) { usp_init_%.*s(); return; }\n"), basename_sz, basename_ptr); - if (binit == false || - bend == false || - bsighup == false || - bfork == false) - { - ptr6 = (bfork ? "\n\t\tif (param > U_DPAGE_FORK) return;\n" - : "\n\t\tif (param >= U_DPAGE_FORK) return;\n"); - } - if (bvar) { (void) vars.append(U_CONSTANT_TO_PARAM("\n\tuint32_t usp_sz = 0;" @@ -837,6 +855,8 @@ loop: distance = t.getDistance(); "%s" "%s" "%s" + "%s" + "\t\treturn;\n" "\t\t}\n" "\t\n" "%v" @@ -863,12 +883,13 @@ loop: distance = t.getDistance(); ptr4, ptr5, ptr6, + ptr7, vcode.rep, http_header.rep, output0.rep, output1.rep, output2.rep, - ptr7); + ptr8); UString name(200U); diff --git a/src/ulib/net/server/server.cpp b/src/ulib/net/server/server.cpp index af4d5439..197f42ae 100644 --- a/src/ulib/net/server/server.cpp +++ b/src/ulib/net/server/server.cpp @@ -3676,7 +3676,9 @@ U_NO_EXPORT void UServer_Base::manageCommand(const char* format, uint32_t fmt_si UString output = UCommand::outputCommand(cmd, U_NULLPTR, -1, fd_stderr); - logCommandMsgError(cmd.data(), true); +#ifdef U_LOG_DISABLE + UServer_Base::logCommandMsgError(cmd.data(), true); +#endif if (UCommand::exit_value) U_WARNING("command failed: EXIT_VALUE=%d OUTPUT=%V", UCommand::exit_value, output.rep); diff --git a/src/ulib/utility/services.cpp b/src/ulib/utility/services.cpp index 3e2e2ce4..e5b065c8 100644 --- a/src/ulib/utility/services.cpp +++ b/src/ulib/utility/services.cpp @@ -198,9 +198,7 @@ int UServices::askToLDAP(UString* pinput, UHashMap* ptable, const char* bool result = cmd.execute(pinput, &output, -1, _fd_stderr); -#ifndef U_LOG_DISABLE - UServer_Base::logCommandMsgError(cmd.getCommand(), false); -#endif + U_SRV_LOG_CMD_MSG_ERR(cmd, false); if (pinput == U_NULLPTR) ptable->clear(); diff --git a/src/ulib/utility/uhttp.cpp b/src/ulib/utility/uhttp.cpp index 3d776403..67ec9c78 100644 --- a/src/ulib/utility/uhttp.cpp +++ b/src/ulib/utility/uhttp.cpp @@ -3101,6 +3101,7 @@ U_NO_EXPORT bool UHTTP::checkRequestForHeader() } # endif } +# if defined(USE_LIBSSL) && !defined(U_SERVER_CAPTIVE_PORTAL) else if (pn[17] == ':') // "If-Modified-Since|Sec-WebSocket-Key:" { pn += 17; @@ -3127,6 +3128,7 @@ U_NO_EXPORT bool UHTTP::checkRequestForHeader() goto next; } } +# endif # ifndef U_LOG_DISABLE else if (pn[22] == ':') // "X-Http-X-Forwarded-For:" { @@ -4622,12 +4624,12 @@ from_cache: } #endif -#ifndef U_SERVER_CAPTIVE_PORTAL +#if defined(USE_LIBSSL) && !defined(U_SERVER_CAPTIVE_PORTAL) U_INTERNAL_DUMP("U_http_websocket_len = %u", U_http_websocket_len) if (U_http_websocket_len) { - if (UWebSocket::sendAccept() == false) + if (UWebSocket::sendAccept(UServer_Base::csocket) == false) { setBadRequest(); @@ -4635,6 +4637,8 @@ from_cache: } UClientImage_Base::setRequestNoCache(); + + if (UServer_Base::startParallelization()) U_RETURN(U_PLUGIN_HANDLER_OK); // parent } #endif @@ -10630,9 +10634,7 @@ bool UHTTP::processCGIRequest(UCommand* cmd, UHTTP::ucgi* cgi) if (cgi) (void) UFile::chdir(U_NULLPTR, true); -#ifndef U_LOG_DISABLE - UServer_Base::logCommandMsgError(cmd->getCommand(), false); -#endif + U_SRV_LOG_CMD_MSG_ERR(*cmd, false); cmd->reset(UClientImage_Base::environment); diff --git a/src/ulib/utility/websocket.cpp b/src/ulib/utility/websocket.cpp index 6e8c870e..0cc3b6ff 100644 --- a/src/ulib/utility/websocket.cpp +++ b/src/ulib/utility/websocket.cpp @@ -16,88 +16,40 @@ #include #include -#define OPCODE_CONTINUATION 0x0 -#define OPCODE_TEXT 0x1 -#define OPCODE_BINARY 0x2 -#define OPCODE_CLOSE 0x8 -#define OPCODE_PING 0x9 -#define OPCODE_PONG 0xA +#define U_WS_DATA_FRAMING_MASK 0 +#define U_WS_DATA_FRAMING_START 1 +#define U_WS_DATA_FRAMING_PAYLOAD_LENGTH 2 +#define U_WS_DATA_FRAMING_PAYLOAD_LENGTH_EXT 3 +#define U_WS_DATA_FRAMING_EXTENSION_DATA 4 +#define U_WS_DATA_FRAMING_APPLICATION_DATA 5 +#define U_WS_DATA_FRAMING_CLOSE 6 -#define DATA_FRAMING_MASK 0 -#define DATA_FRAMING_START 1 -#define DATA_FRAMING_PAYLOAD_LENGTH 2 -#define DATA_FRAMING_PAYLOAD_LENGTH_EXT 3 -#define DATA_FRAMING_EXTENSION_DATA 4 -#define DATA_FRAMING_APPLICATION_DATA 5 -#define DATA_FRAMING_CLOSE 6 +#define U_WS_FRAME_GET_FIN(BYTE) (((BYTE) >> 7) & 0x01) +#define U_WS_FRAME_GET_RSV1(BYTE) (((BYTE) >> 6) & 0x01) +#define U_WS_FRAME_GET_RSV2(BYTE) (((BYTE) >> 5) & 0x01) +#define U_WS_FRAME_GET_RSV3(BYTE) (((BYTE) >> 4) & 0x01) +#define U_WS_FRAME_GET_OPCODE(BYTE) ( (BYTE) & 0x0F) +#define U_WS_FRAME_GET_MASK(BYTE) (((BYTE) >> 7) & 0x01) +#define U_WS_FRAME_GET_PAYLOAD_LEN(BYTE) ( (BYTE) & 0x7F) -#define FRAME_GET_FIN(BYTE) (((BYTE) >> 7) & 0x01) -#define FRAME_GET_RSV1(BYTE) (((BYTE) >> 6) & 0x01) -#define FRAME_GET_RSV2(BYTE) (((BYTE) >> 5) & 0x01) -#define FRAME_GET_RSV3(BYTE) (((BYTE) >> 4) & 0x01) -#define FRAME_GET_OPCODE(BYTE) ( (BYTE) & 0x0F) -#define FRAME_GET_MASK(BYTE) (((BYTE) >> 7) & 0x01) -#define FRAME_GET_PAYLOAD_LEN(BYTE) ( (BYTE) & 0x7F) +#define U_WS_FRAME_SET_FIN(BYTE) (((BYTE) & 0x01) << 7) +#define U_WS_FRAME_SET_OPCODE(BYTE) ((BYTE) & 0x0F) +#define U_WS_FRAME_SET_MASK(BYTE) (((BYTE) & 0x01) << 7) +#define U_WS_FRAME_SET_LENGTH(X64, IDX) (unsigned char)(((uint64_t)(X64) >> ((IDX)*8)) & 0xFF) -#define FRAME_SET_FIN(BYTE) (((BYTE) & 0x01) << 7) -#define FRAME_SET_OPCODE(BYTE) ((BYTE) & 0x0F) -#define FRAME_SET_MASK(BYTE) (((BYTE) & 0x01) << 7) -#define FRAME_SET_LENGTH(X64, IDX) (unsigned char)(((uint64_t)(X64) >> ((IDX)*8)) & 0xFF) - -#define WEBSOCKET_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" -#define WEBSOCKET_GUID_LEN 36 +#define U_WS_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" +#define U_WS_GUID_LEN 36 int UWebSocket::status_code; int UWebSocket::message_type; UString* UWebSocket::rbuffer; +UString* UWebSocket::message; uint32_t UWebSocket::max_message_size; const char* UWebSocket::upgrade_settings; UWebSocket::WebSocketFrameData UWebSocket::control_frame = { U_NULLPTR, 0, 1, 8, 0 }; UWebSocket::WebSocketFrameData UWebSocket::message_frame = { U_NULLPTR, 0, 1, 0, 0 }; -bool UWebSocket::sendAccept() -{ - U_TRACE_NO_PARAM(0, "UWebSocket::sendAccept()") - - U_INTERNAL_ASSERT_MAJOR(U_http_websocket_len, 0) - - // In order to establish a websocket connection, a client (a web browser) sends a HTTP GET request with a number of HTTP headers. Among those - // headers there is the Sec-WebSocket-Key header, which contains a handshake key. According to the WebSocket protocol, the server should: - // - // 1) Concatenate the handshake key with the magic guid {258EAFA5-E914-47DA-95CA-C5AB0DC85B11} - // 2) Take the SHA1 hash of the concatenation result - // 3) Send the base64 equivalent of the hash in HTTP response to the client - - unsigned char challenge[128]; - - U_MEMCPY(challenge, upgrade_settings, U_http_websocket_len); - U_MEMCPY(challenge+U_http_websocket_len, WEBSOCKET_GUID, WEBSOCKET_GUID_LEN); - - // SHA1(challenge) - - UString accept(U_CAPACITY); - - UServices::generateDigest(U_HASH_SHA1, 0, challenge, U_http_websocket_len + WEBSOCKET_GUID_LEN, accept, true); - - UClientImage_Base::wbuffer->snprintf(U_CONSTANT_TO_PARAM("HTTP/1.1 101 Switching Protocols\r\n" - "Upgrade: websocket\r\n" - "Connection: Upgrade\r\n" - "Sec-WebSocket-Accept: %v\r\n\r\n"), accept.rep); - - if (USocketExt::write(UServer_Base::csocket, *UClientImage_Base::wbuffer, UServer_Base::timeoutMS)) - { - status_code = STATUS_CODE_INTERNAL_ERROR; - message_type = MESSAGE_TYPE_INVALID; - - if (max_message_size == 0) max_message_size = U_STRING_MAX_SIZE; - - U_RETURN(true); - } - - U_RETURN(false); -} - void UWebSocket::checkForInitialData() { U_TRACE_NO_PARAM(0, "UWebSocket::checkForInitialData()") @@ -113,22 +65,62 @@ void UWebSocket::checkForInitialData() { // we have read more data than necessary... - const char* ptr = UClientImage_Base::rbuffer->c_pointer(UClientImage_Base::size_request); - - (void) rbuffer->append(ptr, sz - UClientImage_Base::size_request); + (void) rbuffer->append(UClientImage_Base::rbuffer->c_pointer(UClientImage_Base::size_request), sz - UClientImage_Base::size_request); U_INTERNAL_DUMP("rbuffer(%u) = %V", rbuffer->size(), rbuffer->rep) } } +bool UWebSocket::sendAccept(USocket* socket) +{ + U_TRACE(0, "UWebSocket::sendAccept(%p)", socket) + + U_INTERNAL_ASSERT_MAJOR(U_http_websocket_len, 0) + + // In order to establish a websocket connection, a client (a web browser) sends a HTTP GET request with a number of HTTP headers. Among those + // headers there is the Sec-WebSocket-Key header, which contains a handshake key. According to the WebSocket protocol, the server should: + // + // 1) Concatenate the handshake key with the magic guid {258EAFA5-E914-47DA-95CA-C5AB0DC85B11} + // 2) Take the SHA1 hash of the concatenation result + // 3) Send the base64 equivalent of the hash in HTTP response to the client + + unsigned char challenge[128]; + + U_MEMCPY(challenge, upgrade_settings, U_http_websocket_len); + U_MEMCPY(challenge+U_http_websocket_len, U_WS_GUID, U_WS_GUID_LEN); + + // SHA1(challenge) + + UString accept(U_CAPACITY), buffer(U_CAPACITY); + + UServices::generateDigest(U_HASH_SHA1, 0, challenge, U_http_websocket_len + U_WS_GUID_LEN, accept, true); + + buffer.snprintf(U_CONSTANT_TO_PARAM("HTTP/1.1 101 Switching Protocols\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Accept: %v\r\n\r\n"), accept.rep); + + if (USocketExt::write(socket, buffer, UServer_Base::timeoutMS)) + { + status_code = U_WS_STATUS_CODE_INTERNAL_ERROR; + message_type = U_WS_MESSAGE_TYPE_INVALID; + + if (max_message_size == 0) max_message_size = U_STRING_MAX_SIZE; + + U_RETURN(true); + } + + U_RETURN(false); +} + /** - * So, WebSockets presents a sequence of infinitely long byte streams - * with a termination indicator (the FIN bit in the frame header) and - * not a message based interface as you might initially believe. Given - * that a general purpose protocol handler can only work in terms of - * partial frames, we effectively have a stream based protocol with - * lots of added complexity to provide the illusion of a message based + * @see: http://tools.ietf.org/html/rfc6455#section-5.2 Base Framing Protocol + * + * So, WebSockets presents a sequence of infinitely long byte streams with a termination indicator (the FIN bit in the frame header) and + * not a message based interface as you might initially believe. Given that a general purpose protocol handler can only work in terms of + * partial frames, we effectively have a stream based protocol with lots of added complexity to provide the illusion of a message based * protocol that can actually only ever be dealt with as a stream of bytes + * * +-+-+-+-+-------+-+-------------+-------------------------------+ * 0 1 2 3 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | @@ -159,13 +151,13 @@ int UWebSocket::handleDataFraming(USocket* socket) WebSocketFrameData* frame = &UWebSocket::control_frame; unsigned char fin = 0, opcode = 0xFF, mask[4] = { 0, 0, 0, 0 }; int32_t extension_bytes_remaining = 0, payload_length = 0, mask_offset = 0; - int framing_state = DATA_FRAMING_START, payload_length_bytes_remaining = 0, mask_index = 0, masking = 0; + int framing_state = U_WS_DATA_FRAMING_START, payload_length_bytes_remaining = 0, mask_index = 0, masking = 0; loop: if (rbuffer->empty() && USocketExt::read(socket, *rbuffer, U_SINGLE_READ, UServer_Base::timeoutMS) == false) { - status_code = STATUS_CODE_INTERNAL_ERROR; + status_code = U_WS_STATUS_CODE_INTERNAL_ERROR; U_RETURN(status_code); } @@ -179,35 +171,35 @@ loop: switch (framing_state) { - case DATA_FRAMING_START: // 1 + case U_WS_DATA_FRAMING_START: // 1 { // Since we don't currently support any extensions, the reserve bits must be 0 - if ((FRAME_GET_RSV1(block[block_offset]) != 0) || - (FRAME_GET_RSV2(block[block_offset]) != 0) || - (FRAME_GET_RSV3(block[block_offset]) != 0)) + if ((U_WS_FRAME_GET_RSV1(block[block_offset]) != 0) || + (U_WS_FRAME_GET_RSV2(block[block_offset]) != 0) || + (U_WS_FRAME_GET_RSV3(block[block_offset]) != 0)) { - // framing_state = DATA_FRAMING_CLOSE; // 6 + // framing_state = U_WS_DATA_FRAMING_CLOSE; // 6 - status_code = STATUS_CODE_PROTOCOL_ERROR; + status_code = U_WS_STATUS_CODE_PROTOCOL_ERROR; U_RETURN(status_code); } - fin = FRAME_GET_FIN( block[block_offset]); - opcode = FRAME_GET_OPCODE(block[block_offset++]); + fin = U_WS_FRAME_GET_FIN( block[block_offset]); + opcode = U_WS_FRAME_GET_OPCODE(block[block_offset++]); U_INTERNAL_DUMP("fin = %d opcode = %X", fin, opcode) - framing_state = DATA_FRAMING_PAYLOAD_LENGTH; // 2 + framing_state = U_WS_DATA_FRAMING_PAYLOAD_LENGTH; // 2 if (opcode >= 0x8) // Control frame { if (fin == 0) { - // framing_state = DATA_FRAMING_CLOSE; // 6 + // framing_state = U_WS_DATA_FRAMING_CLOSE; // 6 - status_code = STATUS_CODE_PROTOCOL_ERROR; + status_code = U_WS_STATUS_CODE_PROTOCOL_ERROR; U_RETURN(status_code); } @@ -224,9 +216,9 @@ loop: { if (frame->fin == 0) { - // framing_state = DATA_FRAMING_CLOSE; // 6 + // framing_state = U_WS_DATA_FRAMING_CLOSE; // 6 - status_code = STATUS_CODE_PROTOCOL_ERROR; + status_code = U_WS_STATUS_CODE_PROTOCOL_ERROR; U_RETURN(status_code); } @@ -237,9 +229,9 @@ loop: else if (frame->fin || ((opcode = frame->opcode) == 0)) { - // framing_state = DATA_FRAMING_CLOSE; // 6 + // framing_state = U_WS_DATA_FRAMING_CLOSE; // 6 - status_code = STATUS_CODE_PROTOCOL_ERROR; + status_code = U_WS_STATUS_CODE_PROTOCOL_ERROR; U_RETURN(status_code); } @@ -257,10 +249,10 @@ loop: /* FALLTHRU */ - case DATA_FRAMING_PAYLOAD_LENGTH: // 2 + case U_WS_DATA_FRAMING_PAYLOAD_LENGTH: // 2 { - payload_length = FRAME_GET_PAYLOAD_LEN(block[block_offset]); - masking = FRAME_GET_MASK( block[block_offset++]); + payload_length = U_WS_FRAME_GET_PAYLOAD_LEN(block[block_offset]); + masking = U_WS_FRAME_GET_MASK( block[block_offset++]); U_INTERNAL_DUMP("masking = %d payload_length = %d", masking, payload_length) @@ -283,14 +275,14 @@ loop: ((opcode >= 0x8) && // Control opcodes cannot have a payload larger than 125 bytes (payload_length_bytes_remaining != 0))) { - // framing_state = DATA_FRAMING_CLOSE; // 6 + // framing_state = U_WS_DATA_FRAMING_CLOSE; // 6 - status_code = STATUS_CODE_PROTOCOL_ERROR; + status_code = U_WS_STATUS_CODE_PROTOCOL_ERROR; U_RETURN(status_code); } - framing_state = DATA_FRAMING_PAYLOAD_LENGTH_EXT; // 3 + framing_state = U_WS_DATA_FRAMING_PAYLOAD_LENGTH_EXT; // 3 if (block_offset >= block_size) goto next; @@ -299,7 +291,7 @@ loop: /* FALLTHRU */ - case DATA_FRAMING_PAYLOAD_LENGTH_EXT: // 3 + case U_WS_DATA_FRAMING_PAYLOAD_LENGTH_EXT: // 3 { while ((payload_length_bytes_remaining > 0) && (block_offset < block_size)) @@ -317,21 +309,21 @@ loop: { U_SRV_LOG_WITH_ADDR("Got frame with payload greater than maximum frame buffer size: (%u > %u) from", payload_length, max_message_size); - // framing_state = DATA_FRAMING_CLOSE; // 6 + // framing_state = U_WS_DATA_FRAMING_CLOSE; // 6 - status_code = STATUS_CODE_MESSAGE_TOO_LARGE; // Invalid payload length + status_code = U_WS_STATUS_CODE_MESSAGE_TOO_LARGE; // Invalid payload length U_RETURN(status_code); } if (masking == 0) { - framing_state = DATA_FRAMING_EXTENSION_DATA; // 4 + framing_state = U_WS_DATA_FRAMING_EXTENSION_DATA; // 4 break; } - framing_state = DATA_FRAMING_MASK; // 0 + framing_state = U_WS_DATA_FRAMING_MASK; // 0 } if (block_offset >= block_size) goto next; @@ -341,7 +333,7 @@ loop: /* FALLTHRU */ - case DATA_FRAMING_MASK: // 0 + case U_WS_DATA_FRAMING_MASK: // 0 { U_INTERNAL_DUMP("mask_index = %d", mask_index) @@ -353,7 +345,7 @@ loop: mask_index = 0; mask_offset = 0; - framing_state = DATA_FRAMING_EXTENSION_DATA; // 4 + framing_state = U_WS_DATA_FRAMING_EXTENSION_DATA; // 4 if ((mask[0] == 0) && (mask[1] == 0) && @@ -368,7 +360,7 @@ loop: /* FALLTHRU */ - case DATA_FRAMING_EXTENSION_DATA: // 4 + case U_WS_DATA_FRAMING_EXTENSION_DATA: // 4 { // Deal with extension data when we support them -- FIXME @@ -378,12 +370,12 @@ loop: { if (payload_length > 0) { - (void) UClientImage_Base::wbuffer->reserve(frame->application_data_offset + payload_length); + (void) message->setBuffer(frame->application_data_offset + payload_length); - frame->application_data = (unsigned char*) UClientImage_Base::wbuffer->data(); + frame->application_data = (unsigned char*) message->data(); } - framing_state = DATA_FRAMING_APPLICATION_DATA; // 5 + framing_state = U_WS_DATA_FRAMING_APPLICATION_DATA; // 5 } U_INTERNAL_DUMP("framing_state = %d", framing_state) @@ -391,7 +383,7 @@ loop: /* FALLTHRU */ - case DATA_FRAMING_APPLICATION_DATA: // 5 + case U_WS_DATA_FRAMING_APPLICATION_DATA: // 5 { int32_t block_length = block_size - block_offset, block_data_length = (payload_length > block_length ? block_length @@ -404,7 +396,7 @@ loop: { int32_t i; - if (opcode == OPCODE_TEXT) + if (opcode == U_WS_OPCODE_TEXT) { unsigned int utf8_state = frame->utf8_state; @@ -440,7 +432,7 @@ loop: { U_MEMCPY(&application_data[application_data_offset], &block[block_offset], block_data_length); - if (opcode == OPCODE_TEXT) + if (opcode == U_WS_OPCODE_TEXT) { unsigned int utf8_state = frame->utf8_state; int32_t i, application_data_end = application_data_offset + block_data_length; @@ -468,51 +460,56 @@ loop: if (payload_length == 0) { - message_type = MESSAGE_TYPE_INVALID; + message_type = U_WS_MESSAGE_TYPE_INVALID; switch (opcode) { - case OPCODE_TEXT: + case U_WS_OPCODE_TEXT: { if ((fin && (frame->utf8_state != 0)) || (frame->utf8_state == 1)) { - // framing_state = DATA_FRAMING_CLOSE; // 6 + // framing_state = U_WS_DATA_FRAMING_CLOSE; // 6 - status_code = STATUS_CODE_INVALID_UTF8; + status_code = U_WS_STATUS_CODE_INVALID_UTF8; U_RETURN(status_code); } - message_type = MESSAGE_TYPE_TEXT; + message_type = U_WS_MESSAGE_TYPE_TEXT; } break; - case OPCODE_BINARY: message_type = MESSAGE_TYPE_BINARY; break; + case U_WS_OPCODE_BINARY: message_type = U_WS_MESSAGE_TYPE_BINARY; break; - case OPCODE_CLOSE: + case U_WS_OPCODE_CLOSE: { - // framing_state = DATA_FRAMING_CLOSE; // 6 + // framing_state = U_WS_DATA_FRAMING_CLOSE; // 6 - status_code = STATUS_CODE_OK; + status_code = U_WS_STATUS_CODE_OK; U_RETURN(status_code); } - case OPCODE_PING: + case U_WS_OPCODE_PING: { - (void) sendData(MESSAGE_TYPE_PONG, application_data, application_data_offset); + if (sendControlFrame(socket, U_WS_OPCODE_PONG, application_data, application_data_offset) == false) + { + status_code = U_WS_STATUS_CODE_PROTOCOL_ERROR; + + U_RETURN(status_code); + } } break; - case OPCODE_PONG: break; + case U_WS_OPCODE_PONG: break; default: { - // framing_state = DATA_FRAMING_CLOSE; // 6 + // framing_state = U_WS_DATA_FRAMING_CLOSE; // 6 - status_code = STATUS_CODE_PROTOCOL_ERROR; + status_code = U_WS_STATUS_CODE_PROTOCOL_ERROR; U_RETURN(status_code); } @@ -522,17 +519,17 @@ loop: { U_INTERNAL_DUMP("framing_state = %d message_type = %d status_code = %d", framing_state, message_type, status_code) - if (message_type != MESSAGE_TYPE_INVALID) + if (message_type != U_WS_MESSAGE_TYPE_INVALID) { - U_INTERNAL_ASSERT_EQUALS(framing_state, DATA_FRAMING_APPLICATION_DATA) + U_INTERNAL_ASSERT_EQUALS(framing_state, U_WS_DATA_FRAMING_APPLICATION_DATA) - UClientImage_Base::wbuffer->size_adjust_force(application_data_offset); + message->size_adjust_force(application_data_offset); U_SRV_LOG_WITH_ADDR("received websocket data (%u+%u bytes) %V from", - ncount - UClientImage_Base::wbuffer->size(), - UClientImage_Base::wbuffer->size(), UClientImage_Base::wbuffer->rep) + ncount - message->size(), + message->size(), message->rep) - status_code = STATUS_CODE_OK; + status_code = U_WS_STATUS_CODE_OK; U_RETURN(status_code); } @@ -541,20 +538,20 @@ loop: application_data_offset = 0; } - framing_state = DATA_FRAMING_START; // 1 + framing_state = U_WS_DATA_FRAMING_START; // 1 } frame->application_data_offset = application_data_offset; } break; - // case DATA_FRAMING_CLOSE: block_offset = block_size; break; + // case U_WS_DATA_FRAMING_CLOSE: block_offset = block_size; break; default: { - // framing_state = DATA_FRAMING_CLOSE; // 6 + // framing_state = U_WS_DATA_FRAMING_CLOSE; // 6 - status_code = STATUS_CODE_PROTOCOL_ERROR; + status_code = U_WS_STATUS_CODE_PROTOCOL_ERROR; U_RETURN(status_code); } @@ -564,69 +561,110 @@ loop: next: U_INTERNAL_ASSERT(block_offset >= block_size) - U_INTERNAL_ASSERT_DIFFERS(framing_state, DATA_FRAMING_CLOSE) // 6 + U_INTERNAL_ASSERT_DIFFERS(framing_state, U_WS_DATA_FRAMING_CLOSE) // 6 rbuffer->setEmpty(); goto loop; } -bool UWebSocket::sendData(int type, const unsigned char* buffer, uint32_t buffer_size) +bool UWebSocket::sendData(USocket* socket, int type, const char* data, uint32_t len) { - U_TRACE(0, "UWebSocket::sendData(%d,%p,%u)", type, buffer, buffer_size) + U_TRACE(0, "UWebSocket::sendData(%p,%d,%.*S,%u)", socket, type, len, data, len) - uint32_t pos = 0; - unsigned char opcode, header[32]; - uint32_t payload_length = (buffer ? buffer_size : 0); + uint8_t opcode, masking_key[4]; + uint32_t header_length = 6U + (len > 125U ? 2U : 0) + (len > 0xffff ? 8U : 0), ncount = header_length + len; + + UString tmp(ncount); + unsigned char* header = (unsigned char*)tmp.data(); + + *((uint32_t*)masking_key) = u_get_num_random(0); switch (type) { - case MESSAGE_TYPE_TEXT: - case MESSAGE_TYPE_INVALID: - opcode = OPCODE_TEXT; + case U_WS_MESSAGE_TYPE_TEXT: + case U_WS_MESSAGE_TYPE_INVALID: + opcode = U_WS_OPCODE_TEXT; break; - case MESSAGE_TYPE_PING: opcode = OPCODE_PING; break; - case MESSAGE_TYPE_PONG: opcode = OPCODE_PONG; break; - case MESSAGE_TYPE_BINARY: opcode = OPCODE_BINARY; break; + case U_WS_MESSAGE_TYPE_PING: opcode = U_WS_OPCODE_PING; break; + case U_WS_MESSAGE_TYPE_PONG: opcode = U_WS_OPCODE_PONG; break; + case U_WS_MESSAGE_TYPE_BINARY: opcode = U_WS_OPCODE_BINARY; break; - case MESSAGE_TYPE_CLOSE: + case U_WS_MESSAGE_TYPE_CLOSE: default: - opcode = OPCODE_CLOSE; + opcode = U_WS_OPCODE_CLOSE; break; } - header[pos++] = FRAME_SET_FIN(1) | FRAME_SET_OPCODE(opcode); + header[0] = (opcode | 0x80); - if (payload_length < 126) header[pos++] = FRAME_SET_MASK(0) | FRAME_SET_LENGTH(payload_length, 0); + if (len <= 125) + { + header[1] = (len | 0x80); + + u_put_unalignedp32(header+2, *((uint32_t*)masking_key)); + } + else if (len > 125 && + len <= 0xffff) // 125 && 65535 + { + header[1] = (126 | 0x80); + + u_put_unalignedp16(header+2, htons(len)); + u_put_unalignedp32(header+4, *((uint32_t*)masking_key)); + } + else if (len > 0xffff && + len <= 0xffffffff) + { + header[1] = (127 | 0x80); + + u_put_unalignedp64(header+2, htonl(len)); + u_put_unalignedp32(header+10, *((uint32_t*)masking_key)); + } else { - if (payload_length < 65536) header[pos++] = FRAME_SET_MASK(0) | 126; - else - { - header[pos++] = FRAME_SET_MASK(0) | 127; - header[pos++] = 0; // FRAME_SET_LENGTH(payload_length, 7); - header[pos++] = 0; // FRAME_SET_LENGTH(payload_length, 6); - header[pos++] = 0; // FRAME_SET_LENGTH(payload_length, 5); - header[pos++] = 0; // FRAME_SET_LENGTH(payload_length, 4); - header[pos++] = FRAME_SET_LENGTH(payload_length, 3); - header[pos++] = FRAME_SET_LENGTH(payload_length, 2); - } + status_code = U_WS_STATUS_CODE_MESSAGE_TOO_LARGE; - header[pos++] = FRAME_SET_LENGTH(payload_length, 1); - header[pos++] = FRAME_SET_LENGTH(payload_length, 0); + U_RETURN(false); } - U_SRV_LOG_WITH_ADDR("send websocket data (%u+%u bytes) %.*S to", pos, buffer_size, buffer_size, buffer) + for (uint32_t i = 0; i < len; ++i) + { + header[6+i] = (data[i] ^ masking_key[i % 4]) & 0xff; + } - struct iovec iov[2] = { { (caddr_t)header, pos }, - { (caddr_t)buffer, payload_length } }; + U_SRV_LOG_WITH_ADDR("send websocket data (%u+%u bytes) %.*S to", header_length, len, len, data) - int iBytesWrite = (payload_length - ? (pos += payload_length, USocketExt::writev(UServer_Base::csocket, iov, 2, pos, UServer_Base::timeoutMS)) - : USocketExt::write( UServer_Base::csocket, (const char*)header, pos, UServer_Base::timeoutMS)); - - if (iBytesWrite == (int)pos) U_RETURN(true); + if (USocketExt::write(socket, (const char*)header, ncount, UServer_Base::timeoutMS) == ncount) U_RETURN(true); + + U_RETURN(false); +} + +bool UWebSocket::sendControlFrame(USocket* socket, int opcode, const unsigned char* payload, uint32_t payload_length) +{ + U_TRACE(0, "UWebSocket::sendControlFrame(%p,%d,%.*S,%u)", socket, opcode, payload_length, payload, payload_length) + + uint8_t masking_key[4]; + uint32_t ncount = 6U + payload_length; + + UString tmp(ncount); + unsigned char* header = (unsigned char*)tmp.data(); + + *((uint32_t*)masking_key) = u_get_num_random(0); + + header[0] = ( opcode | 0x80); + header[1] = (payload_length | 0x80); + + u_put_unalignedp32(header+2, *((uint32_t*)masking_key)); + + for (uint32_t i = 0; i < payload_length; ++i) + { + 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_RETURN(true); U_RETURN(false); } diff --git a/tests/examples/web_server_proxy.test b/tests/examples/web_server_proxy.test index 87ae5467..90c420a9 100755 --- a/tests/examples/web_server_proxy.test +++ b/tests/examples/web_server_proxy.test @@ -91,7 +91,7 @@ kill_server userver_tcp $SLEEP pkill userver_tcp 2>/dev/null -cat err/userver_tcp.err >> err/webserver_proxy.err +cat err/userver_tcp.err > err/webserver_proxy.err rm err/userver_tcp.err # Test against expected output diff --git a/tests/examples/web_socket.sh b/tests/examples/web_socket.sh index fe9c7017..824d20fe 100755 --- a/tests/examples/web_socket.sh +++ b/tests/examples/web_socket.sh @@ -2,44 +2,49 @@ . ../.function -rm -f web_socket.log \ - /tmp/UWebSocketPlugIn.err \ - out/userver_tcp.out err/userver_tcp.err \ - trace.*userver_tcp*.[0-9]* object.*userver_tcp*.[0-9]* stack.*userver_tcp*.[0-9]* +rm -f /tmp/web_socket.log \ + /tmp/UWebSocketPlugIn.err \ + out/web_socket.out err/userver_tcp.err \ + /tmp/trace.*userver_tcp*.[0-9]* /tmp/object.*userver_tcp*.[0-9]* /tmp/stack.*userver_tcp*.[0-9]* UTRACE="0 50M 0" -#UOBJDUMP="0 1M 10" + UTRACE_SIGNAL="0 50M 0" + UTRACE_FOLDER=/tmp + TMPDIR=/tmp +#UOBJDUMP="0 10M 100" #USIMERR="error.sim" - export UTRACE UOBJDUMP USIMERR +#UMEMUSAGE=yes +export UTRACE UOBJDUMP USIMERR UTRACE_SIGNAL UMEMUSAGE UTRACE_FOLDER TMPDIR -cat <web_socket_sh.cfg +cat <inp/webserver.cfg userver { PORT 8787 - MAX_KEEP_ALIVE 6 - RUN_AS_USER apache - PID_FILE docroot/web_socket_sh.pid - LOG_FILE web_socket.log + PID_FILE /tmp/web_socket.pid + LOG_FILE /tmp/web_socket.log LOG_FILE_SZ 1M LOG_MSG_SIZE -1 PLUGIN "socket http" - DOCUMENT_ROOT docroot + DOCUMENT_ROOT websocket PLUGIN_DIR ../../../src/ulib/net/server/plugin/.libs ORM_DRIVER_DIR ../../../src/ulib/orm/driver/.libs - PREFORK_CHILD 1 -} -socket { - COMMAND ../my_websocket.sh } EOF +(cd websocket; ln -sf ../../../src/ulib/net/server/plugin/usp/.libs/modsocket.so) + DIR_CMD="../../examples/userver" +check_for_netcat + #STRACE=$TRUSS -start_prg_background userver_tcp -c web_socket_sh.cfg +start_prg_background userver_tcp -c inp/webserver.cfg -#$SLEEP -#kill_prg userver_tcp TERM +wait_server_ready localhost 8787 +$SLEEP +send_req $NCAT localhost 8787 inp/http/websocket.req web_socket 3 kill +$SLEEP +kill_prg userver_tcp TERM -mv err/userver_tcp.err err/web_socket.err +mv err/userver_tcp.err /tmp/web_socket.err -echo "PID = `cat docroot/web_socket_sh.pid`" +#echo "PID = `cat /tmp/web_socket.pid`" diff --git a/tests/examples/web_socket.test b/tests/examples/web_socket.test index 92638a0e..40147475 100755 --- a/tests/examples/web_socket.test +++ b/tests/examples/web_socket.test @@ -2,34 +2,52 @@ . ../.function +# set -x + +## web_socket.test -- Test web socket feature + start_msg web_socket DOC_ROOT=websocket -rm -f $DOC_ROOT/web_socket.log \ - /tmp/UWebSocketPlugIn.err \ - out/userver_tcp.out err/userver_tcp.err \ +rm -f /tmp/web_socket*.log /tmp/UWebSocketPlugIn.err out/userver_tcp.out err/userver_tcp.err \ trace.*userver_*.[0-9]* object.*userver_*.[0-9]* stack.*userver_*.[0-9]* mempool.*userver_*.[0-9]* \ + /tmp/trace.*userver_*.[0-9]* /tmp/object.*userver_*.[0-9]* /tmp/stack.*userver_*.[0-9]* /tmp/mempool.*userver_*.[0-9]* \ $DOC_ROOT/trace.*userver_*.[0-9]* $DOC_ROOT/object.*userver_*.[0-9]* $DOC_ROOT/stack.*userver_*.[0-9]* $DOC_ROOT/mempool.*userver_*.[0-9]* -#UTRACE="0 50M 0" -#UOBJDUMP="0 50M 1000" +#UTRACE="0 100M 0" + UTRACE_FOLDER=/tmp + TMPDIR=/tmp +#UOBJDUMP="0 10M 100" #USIMERR="error.sim" - export UTRACE UOBJDUMP USIMERR +#UMEMUSAGE=yes +export UTRACE UOBJDUMP USIMERR UTRACE_SIGNAL UMEMUSAGE UTRACE_FOLDER TMPDIR cat <inp/webserver.cfg userver { PORT 8787 - RUN_AS_USER apache - MAX_KEEP_ALIVE 6 - LOG_FILE web_socket.log + LOG_FILE /tmp/web_socket.log LOG_FILE_SZ 1M LOG_MSG_SIZE -1 + PID_FILE /tmp/userver_tcp.pid PLUGIN "socket http" DOCUMENT_ROOT websocket PLUGIN_DIR ../../../src/ulib/net/server/plugin/.libs ORM_DRIVER_DIR ../../../src/ulib/orm/driver/.libs - PREFORK_CHILD 1 +} +EOF + +cat <inp/webserver_proxy.cfg +userver { + PORT 8888 + LOG_FILE /tmp/webserver_proxy.log + LOG_FILE_SZ 10M + LOG_MSG_SIZE -1 + PID_FILE /tmp/userver_tcp_proxy.pid + PREFORK_CHILD 0 + DOCUMENT_ROOT python + PLUGIN "socket http" + PLUGIN_DIR ../../../src/ulib/net/server/plugin/.libs } socket { COMMAND ../my_websocket.sh @@ -42,14 +60,21 @@ check_for_netcat #STRACE=$TRUSS start_prg_background userver_tcp -c inp/webserver.cfg - wait_server_ready localhost 8787 +start_prg_background userver_tcp -c inp/webserver_proxy.cfg +wait_server_ready localhost 8888 + +sync +#echo "PID1 = `cat /tmp/userver_tcp.pid`" +#echo "PID2 = `cat /tmp/userver_tcp_proxy.pid`" send_req $NCAT localhost 8787 inp/http/websocket.req web_socket 3 kill -$SLEEP -kill_prg userver_tcp TERM -mv err/userver_tcp.err err/web_socket.err +kill_prg userver_tcp TERM +$SLEEP +pkill userver_tcp 2>/dev/null + +mv err/userver_tcp.err err/websocket.err # Test against expected output test_output_wc l web_socket