diff --git a/include/ulib/mime/header.h b/include/ulib/mime/header.h index 0c09a57c..30a7fdf6 100644 --- a/include/ulib/mime/header.h +++ b/include/ulib/mime/header.h @@ -76,6 +76,7 @@ */ class UHTTP; +class UHTTP2; class U_EXPORT UMimeHeader { public: @@ -444,6 +445,7 @@ private: #endif friend class UHTTP; + friend class UHTTP2; }; #endif diff --git a/include/ulib/net/server/client_image.h b/include/ulib/net/server/client_image.h index 225723b0..5dcd9344 100644 --- a/include/ulib/net/server/client_image.h +++ b/include/ulib/net/server/client_image.h @@ -390,8 +390,6 @@ protected: #endif private: - static int handlerDataPending() U_NO_EXPORT; - static bool isValidMethod( const char* ptr) U_NO_EXPORT; static bool isValidRequest( const char* ptr, uint32_t sz) U_NO_EXPORT; static bool isValidRequestExt(const char* ptr, uint32_t sz) U_NO_EXPORT; diff --git a/include/ulib/utility/http2.h b/include/ulib/utility/http2.h index bb9aa52f..ee11229c 100644 --- a/include/ulib/utility/http2.h +++ b/include/ulib/utility/http2.h @@ -28,7 +28,6 @@ public: static void ctor(); static void dtor(); - static bool manageSetting(); protected: enum FrameTypesId { @@ -242,6 +241,7 @@ protected: static void sendError(); static void manageData(); static void manageHeaders(); + static int handlerRequest(); static void handlerResponse(); static bool readBodyRequest(); static bool updateSetting(const char* ptr, uint32_t len); @@ -306,6 +306,9 @@ protected: static uint32_t hpackDecodeInt( const unsigned char* src, const unsigned char* src_end, int32_t* pvalue, uint8_t prefix_max); private: + static unsigned char* pwbuffer; + static bool addHTTPHeader(UStringRep* key, void* value) U_NO_EXPORT; + friend class UHTTP; friend class UClientImage_Base; diff --git a/include/ulib/utility/uhttp.h b/include/ulib/utility/uhttp.h index 175bad5a..c6b4cee3 100644 --- a/include/ulib/utility/uhttp.h +++ b/include/ulib/utility/uhttp.h @@ -87,7 +87,6 @@ public: static void dtor(); static bool readRequest(); - static int handlerDataPending(); static void setStatusDescription(); static bool isValidMethod(const char* ptr) __pure; static bool scanfHeaderRequest(const char* ptr, uint32_t size); @@ -1002,7 +1001,7 @@ public: static UFileCacheData* getFileInCache(const char* path, uint32_t len); private: - static UString getHeaderForResponse(); + static void handlerResponse(); static UString getHTMLDirectoryList() U_NO_EXPORT; static void setMimeIndex() // NB: it is used by server_plugin_ssi... diff --git a/src/ulib/net/server/client_image.cpp b/src/ulib/net/server/client_image.cpp index 2c48cbde..fe3a7619 100644 --- a/src/ulib/net/server/client_image.cpp +++ b/src/ulib/net/server/client_image.cpp @@ -28,7 +28,6 @@ iPF UClientImage_Base::callerHandlerRequest; iPF UClientImage_Base::callerHandlerReset; bPF UClientImage_Base::callerHandlerCache; vPF UClientImage_Base::callerHandlerEndRequest; -iPF UClientImage_Base::callerHandlerDataPending; bool UClientImage_Base::bIPv6; bool UClientImage_Base::log_request_partial; char UClientImage_Base::cbuffer[128]; @@ -249,33 +248,6 @@ U_NO_EXPORT bool UClientImage_Base::isValidMethod( const char* ptr) U_NO_EXPORT bool UClientImage_Base::isValidRequest( const char* ptr, uint32_t sz) { return true; } U_NO_EXPORT bool UClientImage_Base::isValidRequestExt(const char* ptr, uint32_t sz) { return true; } -U_NO_EXPORT int UClientImage_Base::handlerDataPending() -{ - U_TRACE(0, "UClientImage_Base::handlerDataPending()") - - if (UServer_Base::startParallelization(UServer_Base::num_client_for_parallelization)) - { - // parent - - U_ClientImage_state = U_PLUGIN_HANDLER_ERROR; - - U_RETURN(-1); - } - - if (U_ClientImage_parallelization == 1) // 1 => child of parallelization - { - if (UNotifier::waitForRead(UServer_Base::csocket->iSockDesc, U_TIMEOUT_MS) != 1 || - (resetReadBuffer(), USocketExt::read(UServer_Base::csocket, *rbuffer, getCountToRead(), 0)) == false) - { - U_RETURN(-1); - } - - U_RETURN(1); - } - - U_RETURN(0); -} - void UClientImage_Base::init() { U_TRACE(0, "UClientImage_Base::init()") @@ -305,10 +277,9 @@ void UClientImage_Base::init() _buffer = U_NEW(UString(U_CAPACITY)); _encoded = U_NEW(UString(U_CAPACITY)); - callerIsValidMethod = isValidMethod; - callerIsValidRequest = isValidRequest; - callerIsValidRequestExt = isValidRequestExt; - callerHandlerDataPending = handlerDataPending; + callerIsValidMethod = isValidMethod; + callerIsValidRequest = isValidRequest; + callerIsValidRequestExt = isValidRequestExt; #ifdef DEBUG UError::callerDataDump = saveRequestResponse; @@ -989,12 +960,6 @@ bool UClientImage_Base::genericRead() U_RETURN(true); } -#ifdef U_HTTP2_DISABLE -#define U_CALL_DATA_PENDING handlerDataPending -#else -#define U_CALL_DATA_PENDING callerHandlerDataPending -#endif - int UClientImage_Base::handlerRead() // Connection-wide hooks { U_TRACE(0, "UClientImage_Base::handlerRead()") @@ -1063,34 +1028,47 @@ pipeline: } } - U_INTERNAL_DUMP("U_ClientImage_pipeline = %b U_ClientImage_data_missing = %b", U_ClientImage_pipeline, U_ClientImage_data_missing) - U_INTERNAL_ASSERT(request->invariant()) #ifdef U_LOG_ENABLE if (logbuf) logRequest(); #endif + U_INTERNAL_DUMP("U_ClientImage_pipeline = %b U_ClientImage_data_missing = %b", U_ClientImage_pipeline, U_ClientImage_data_missing) + if (U_ClientImage_data_missing) { dmiss: -# if defined(U_LOG_ENABLE) || !defined(U_CACHE_REQUEST_DISABLE) - result = U_CALL_DATA_PENDING(); + U_INTERNAL_DUMP("U_ClientImage_parallelization = %d", U_ClientImage_parallelization) - if (result) + if (U_ClientImage_parallelization == 1) // 1 => child of parallelization { - if (result == 1) goto loop; // child of parallelization - if (result == -1) // parent of parallelization + if (UNotifier::waitForRead(UServer_Base::csocket->iSockDesc, U_TIMEOUT_MS) != 1 || + (resetReadBuffer(), USocketExt::read(UServer_Base::csocket, *rbuffer, getCountToRead(), 0)) == false) { if ((U_ClientImage_state & U_PLUGIN_HANDLER_ERROR) != 0) U_RETURN(U_NOTIFIER_DELETE); goto death; } + + goto loop; } -# endif U_ClientImage_data_missing = false; +# ifndef U_HTTP2_DISABLE + U_INTERNAL_DUMP("U_http_version = %C", U_http_version) + + if (U_http_version == '2') + { + U_ClientImage_state = UHTTP2::handlerRequest(); + + if (UNLIKELY((U_ClientImage_state & U_PLUGIN_HANDLER_ERROR) != 0)) goto error; + + goto processing; + } +# endif + U_INTERNAL_ASSERT_EQUALS(data_pending, 0) data_pending = U_NEW(UString((void*)U_STRING_TO_PARAM(*request))); @@ -1271,6 +1249,9 @@ check: } } +#ifndef U_HTTP2_DISABLE +processing: +#endif U_INTERNAL_DUMP("U_ClientImage_pipeline = %b size_request = %u request->size() = %u", U_ClientImage_pipeline, size_request, request->size()) diff --git a/src/ulib/net/server/plugin/mod_http.cpp b/src/ulib/net/server/plugin/mod_http.cpp index a11670b5..1e367974 100644 --- a/src/ulib/net/server/plugin/mod_http.cpp +++ b/src/ulib/net/server/plugin/mod_http.cpp @@ -467,13 +467,12 @@ int UHttpPlugIn::handlerRun() // NB: we use this method because now we have the // NB: we can shortcut the http request processing... - UClientImage_Base::callerHandlerRead = UHTTP::handlerREAD; - UClientImage_Base::callerHandlerCache = UHTTP::handlerCache; - UClientImage_Base::callerIsValidMethod = UHTTP::isValidMethod; - UClientImage_Base::callerIsValidRequest = UHTTP::isValidRequest; - UClientImage_Base::callerIsValidRequestExt = UHTTP::isValidRequestExt; - UClientImage_Base::callerHandlerEndRequest = UHTTP::setEndRequestProcessing; - UClientImage_Base::callerHandlerDataPending = UHTTP::handlerDataPending; + UClientImage_Base::callerHandlerRead = UHTTP::handlerREAD; + UClientImage_Base::callerHandlerCache = UHTTP::handlerCache; + UClientImage_Base::callerIsValidMethod = UHTTP::isValidMethod; + UClientImage_Base::callerIsValidRequest = UHTTP::isValidRequest; + UClientImage_Base::callerIsValidRequestExt = UHTTP::isValidRequestExt; + UClientImage_Base::callerHandlerEndRequest = UHTTP::setEndRequestProcessing; } U_ASSERT(UHTTP::cache_file_check_memory()) diff --git a/src/ulib/net/server/plugin/mod_soap.cpp b/src/ulib/net/server/plugin/mod_soap.cpp index 89c2ab99..cc3d574c 100644 --- a/src/ulib/net/server/plugin/mod_soap.cpp +++ b/src/ulib/net/server/plugin/mod_soap.cpp @@ -101,7 +101,7 @@ int USoapPlugIn::handlerRequest() (void) UFile::writeToTmp(U_STRING_TO_PARAM(body), false, "soap.res", 0); # endif - U_http_info.nResponseCode = HTTP_OK; + U_http_info.nResponseCode = HTTP_OK; UHTTP::setResponse(UHTTP::str_ctype_soap, &body); } diff --git a/src/ulib/net/server/plugin/mod_ssi.cpp b/src/ulib/net/server/plugin/mod_ssi.cpp index bb0fcf09..8deb8e81 100644 --- a/src/ulib/net/server/plugin/mod_ssi.cpp +++ b/src/ulib/net/server/plugin/mod_ssi.cpp @@ -1055,8 +1055,9 @@ int USSIPlugIn::handlerRequest() U_http_info.nResponseCode = HTTP_OK; - *UClientImage_Base::body = output; - *UClientImage_Base::wbuffer = UHTTP::getHeaderForResponse(); + *UClientImage_Base::body = output; + + UHTTP::handlerResponse(); } else if (alternative_response > 1) { diff --git a/src/ulib/net/server/plugin/ruby/mod_ruby.cpp b/src/ulib/net/server/plugin/ruby/mod_ruby.cpp index 0a6b4aa4..ade34c50 100644 --- a/src/ulib/net/server/plugin/ruby/mod_ruby.cpp +++ b/src/ulib/net/server/plugin/ruby/mod_ruby.cpp @@ -329,15 +329,15 @@ extern U_EXPORT bool runRUBY(const char* libdir, const char* script); rbv = rb_ary_new(); env = rb_hash_new(); - /* - "rack.version"=>[1, 0], - "rack.run_once"=>false, - "rack.multithread"=>false, - "rack.multiprocess"=>false, - "rack.url_scheme"=>"http", - "rack.errors"=>#>, - "rack.input"=>#, - */ + /** + * "rack.version"=>[1, 0], + * "rack.run_once"=>false, + * "rack.multithread"=>false, + * "rack.multiprocess"=>false, + * "rack.url_scheme"=>"http", + * "rack.errors"=>#>, + * "rack.input"=>#, + */ (void) rb_ary_store(rbv, 0, INT2NUM(1)); (void) rb_ary_store(rbv, 1, INT2NUM(1)); diff --git a/src/ulib/utility/http2.cpp b/src/ulib/utility/http2.cpp index 8d3766ee..a0b94a08 100644 --- a/src/ulib/utility/http2.cpp +++ b/src/ulib/utility/http2.cpp @@ -11,6 +11,7 @@ // // ============================================================================ +#include #include #include #include @@ -25,6 +26,7 @@ bool UHTTP2::settings_ack; void* UHTTP2::pConnectionEnd; uint32_t UHTTP2::hash_static_table[61]; const char* UHTTP2::upgrade_settings; +unsigned char* UHTTP2::pwbuffer; UHTTP2::Stream* UHTTP2::pStream; UHTTP2::FrameHeader UHTTP2::frame; UHTTP2::Connection* UHTTP2::pConnection; @@ -517,9 +519,22 @@ uint32_t UHTTP2::hpackEncodeString(unsigned char* dst, const char* src, uint32_t U_INTERNAL_ASSERT_MAJOR(len, 0) + unsigned char* ptr; + + if (len < 29) + { + // encode as-is + +asis: *dst = '\0'; + ptr = hpackEncodeInt(dst, len, (1<<7)-1); + + u__memcpy(ptr, src, len, __PRETTY_FUNCTION__); + + U_RETURN(ptr - dst + len); + } + uint64_t bits = 0; int bits_left = 40; - unsigned char* ptr; const char* src_end = src + len; UString buffer(len + 1024U); @@ -528,45 +543,53 @@ uint32_t UHTTP2::hpackEncodeString(unsigned char* dst, const char* src, uint32_t unsigned char* _dst_end = _dst + len; unsigned char* _dst_start = _dst; + // try to encode in huffman + do { - const HuffSym* sym = huff_sym_table + *src++; + const HuffSym* sym = huff_sym_table + *(unsigned char*)src++; + + // U_INTERNAL_DUMP("sym->nbits = %u sym->code = %u bits_left = %d", sym->nbits, sym->code, bits_left) bits |= (uint64_t)sym->code << (bits_left - sym->nbits); bits_left -= sym->nbits; + // U_INTERNAL_DUMP("bits = %llu bits_left = %d", bits, bits_left) + while (bits_left <= 32) { *_dst++ = bits >> 32; + // U_INTERNAL_DUMP("_dst = %u bits >> 32 = %u", _dst[-1], bits >> 32) + bits <<= 8; bits_left += 8; + + U_INTERNAL_ASSERT_MINOR(_dst, _dst_end) } } while (src < src_end); +// U_INTERNAL_DUMP("bits = %llu bits_left = %d", bits, bits_left) + if (bits_left != 40) { bits |= (1UL << bits_left) - 1; *_dst++ = bits >> 32; + + // U_INTERNAL_DUMP("_dst = %u bits >> 32 = %u", _dst[-1], bits >> 32) } - if (_dst >= _dst_end) // encode as-is - { - *dst = '\0'; - ptr = hpackEncodeInt(dst, len, (1<<7)-1); + U_INTERNAL_DUMP("_dst_end = %p _dst = %p %#.*S", _dst_end, _dst, buffer.distance((const char*)_dst), _dst_start) - u__memcpy(ptr, src, len, __PRETTY_FUNCTION__); + if (_dst > _dst_end) goto asis; // encode as-is - U_RETURN(ptr - dst + len); - } - - len = _dst - _dst_start; *dst = '\x80'; + len = _dst - _dst_start; ptr = hpackEncodeInt(dst, len, (1<<7)-1); - u__memcpy(ptr, _dst, len, __PRETTY_FUNCTION__); + u__memcpy(ptr, _dst_start, len, __PRETTY_FUNCTION__); U_RETURN(ptr - dst + len); } @@ -588,7 +611,7 @@ err: pvalue->clear(); src += nmove; - U_INTERNAL_DUMP("is_huffman = %b", is_huffman) + U_INTERNAL_DUMP("is_huffman = %b len = %u src = %#.*S", is_huffman, len, len, src) if (is_huffman == false) { @@ -1505,110 +1528,6 @@ void UHTTP2::manageData() (void) UClientImage_Base::body->append(ptr, sz); } -bool UHTTP2::manageSetting() -{ - U_TRACE(0, "UHTTP2::manageSetting()") - - U_INTERNAL_ASSERT_EQUALS(U_http_version, '2') - - U_INTERNAL_DUMP("HTTP2-Settings: = %.*S U_http_method_type = %B", U_http2_settings_len, UHTTP2::upgrade_settings, U_http_method_type) - - if (U_http2_settings_len && - USocketExt::write(UServer_Base::csocket, U_CONSTANT_TO_PARAM(HTTP2_CONNECTION_UPGRADE_AND_SETTING_BIN), UServer_Base::timeoutMS) != - U_CONSTANT_SIZE(HTTP2_CONNECTION_UPGRADE_AND_SETTING_BIN)) - { - U_RETURN(false); - } - - U_INTERNAL_ASSERT(UClientImage_Base::request->same(*UClientImage_Base::rbuffer)) - - UClientImage_Base::request->clear(); - - // maybe we have read more data than necessary... - - uint32_t sz = UClientImage_Base::rbuffer->size(); - - U_INTERNAL_ASSERT_MAJOR(sz, 0) - - if (sz > U_http_info.endHeader) UClientImage_Base::rstart = U_http_info.endHeader; - else - { - // we wait for HTTP2_CONNECTION_PREFACE... - - UClientImage_Base::rbuffer->setEmptyForce(); - - if (UNotifier::waitForRead(UServer_Base::csocket->iSockDesc, U_TIMEOUT_MS) != 1 || - USocketExt::read(UServer_Base::csocket, *UClientImage_Base::rbuffer, U_SINGLE_READ, 0) == false) - { - U_RETURN(false); - } - - UClientImage_Base::rstart = 0; - - sz = UClientImage_Base::rbuffer->size(); - } - - const char* ptr = UClientImage_Base::rbuffer->c_pointer(UClientImage_Base::rstart); - - if (u_get_unalignedp64(ptr) != U_MULTICHAR_CONSTANT64( 'P', 'R','I',' ', '*', ' ', 'H', 'T') || - u_get_unalignedp64(ptr+8) != U_MULTICHAR_CONSTANT64( 'T', 'P','/','2', '.', '0','\r','\n') || - u_get_unalignedp64(ptr+16) != U_MULTICHAR_CONSTANT64('\r','\n','S','M','\r','\n','\r','\n')) - { - U_RETURN(false); - } - - pConnection = (Connection*)UServer_Base::pClientImage->connection; - pConnectionEnd = (char*)pConnection + sizeof(Connection); - - pConnection->state = CONN_STATE_OPEN; - pConnection->peer_settings = settings; - - pConnection->max_open_stream_id = - pConnection->num_responding_streams = - pConnection->max_processed_stream_id = 0; - - pStream = pConnection->streams; - - pStream->state = STREAM_STATE_IDLE; - - if (U_http2_settings_len == 0) - { - if (USocketExt::write(UServer_Base::csocket, U_CONSTANT_TO_PARAM(HTTP2_SETTINGS_BIN), UServer_Base::timeoutMS) != U_CONSTANT_SIZE(HTTP2_SETTINGS_BIN)) U_RETURN(false); - } - else - { - UString buffer(U_CAPACITY); - - UBase64::decodeUrl(upgrade_settings, U_http2_settings_len, buffer); - - if (buffer.empty() || - updateSetting(U_STRING_TO_PARAM(buffer)) == false) - { - U_RETURN(false); - } - } - - settings_ack = false; - - UClientImage_Base::rstart += U_CONSTANT_SIZE(HTTP2_CONNECTION_PREFACE); - -loop: - readFrame(); - - if (nerror == NO_ERROR) - { - U_INTERNAL_DUMP("settings_ack = %b", settings_ack) - - if (settings_ack == false) goto loop; // we wait for SETTINGS ack... - - U_RETURN(true); - } - - sendError(); - - U_RETURN(false); -} - void UHTTP2::sendError() { U_TRACE(0, "UHTTP2::sendError()") @@ -1647,60 +1566,140 @@ void UHTTP2::sendError() } } +U_NO_EXPORT bool UHTTP2::addHTTPHeader(UStringRep* key, void* value) +{ + U_TRACE(0+256, "UHTTP2::addHTTPHeader(%V,%V)", key, value) + + U_INTERNAL_ASSERT_POINTER(key) + U_INTERNAL_ASSERT_POINTER(value) + + uint32_t key_sz = key->size(), + value_sz = ((UStringRep*)value)->size(); + const char* key_ptr = key->data(); + const char* value_ptr = ((UStringRep*)value)->data(); + + U_INTERNAL_DUMP("key(%u) = %#V value(%u) = %#V", key_sz, key, value_sz, (UStringRep*)value) + + U_INTERNAL_ASSERT_EQUALS(u_isBinary((const unsigned char*)value_ptr, value_sz), false) + + uint32_t index = U_NOT_FOUND; + + if (hpack_static_table[30].name->equalnocase(key_ptr, key_sz)) index = 31; // content-type + else if (hpack_static_table[27].name->equalnocase(key_ptr, key_sz)) U_RETURN(true); // content-length + else if (hpack_static_table[35].name->equalnocase(key_ptr, key_sz)) index = 36; // expires + else if (hpack_static_table[43].name->equalnocase(key_ptr, key_sz)) index = 44; // last-modified + else if (hpack_static_table[45].name->equalnocase(key_ptr, key_sz)) index = 46; // location + else if (hpack_static_table[51].name->equalnocase(key_ptr, key_sz)) index = 52; // refresh + else if (hpack_static_table[60].name->equalnocase(key_ptr, key_sz)) index = 61; // www-authenticate + else if (hpack_static_table[29].name->equalnocase(key_ptr, key_sz)) index = 30; // content-range + else if (hpack_static_table[17].name->equalnocase(key_ptr, key_sz)) index = 18; // accept-ranges + else if (hpack_static_table[19].name->equalnocase(key_ptr, key_sz)) index = 20; // access-control-allow-origin + else if (hpack_static_table[20].name->equalnocase(key_ptr, key_sz)) index = 21; // age + else if (hpack_static_table[23].name->equalnocase(key_ptr, key_sz)) index = 24; // cache-control + else if (hpack_static_table[24].name->equalnocase(key_ptr, key_sz)) index = 25; // content-disposition + else if (hpack_static_table[25].name->equalnocase(key_ptr, key_sz)) index = 26; // content-encoding + else if (hpack_static_table[26].name->equalnocase(key_ptr, key_sz)) index = 27; // content-language + else if (hpack_static_table[28].name->equalnocase(key_ptr, key_sz)) index = 29; // content-location + else if (hpack_static_table[33].name->equalnocase(key_ptr, key_sz)) index = 34; // etag + else if (hpack_static_table[44].name->equalnocase(key_ptr, key_sz)) index = 45; // link + else if (hpack_static_table[47].name->equalnocase(key_ptr, key_sz)) index = 48; // proxy-authenticate + else if (hpack_static_table[52].name->equalnocase(key_ptr, key_sz)) index = 53; // retry-after + else if (hpack_static_table[55].name->equalnocase(key_ptr, key_sz)) index = 56; // strict-transport-security + else if (hpack_static_table[58].name->equalnocase(key_ptr, key_sz)) index = 59; // vary + else if (hpack_static_table[59].name->equalnocase(key_ptr, key_sz)) index = 60; // via + + if (index != U_NOT_FOUND) + { + *pwbuffer = 0x40; + pwbuffer = hpackEncodeInt(pwbuffer, index, (1<<6)-1); + pwbuffer += hpackEncodeString(pwbuffer, value_ptr, value_sz); + } + /* + else + { + } + */ + + U_RETURN(true); +} + void UHTTP2::handlerResponse() { U_TRACE(0, "UHTTP2::handlerResponse()") - unsigned char buffer[8192] = { 0, 0, 0, // frame size - HEADERS, // header frame - FLAG_END_HEADERS, // end header flags - 0, 0, 0, 0, // stream id - 8, 3, '0', '0', '0' }; // use literal header field without indexing - indexed name + U_ASSERT(UClientImage_Base::wbuffer->empty()) + U_ASSERT(UClientImage_Base::wbuffer->capacity()) - // \000\000# - // \001 - // \004 - // \000\000\000\001 - // \b\003403 - // v\004\000UHTa + U_INTERNAL_DUMP("ext(%u) = %#V", UHTTP::ext->size(), UHTTP::ext->rep) - char* ptr = (char*)buffer; - int32_t sz = HTTP2_FRAME_HEADER_SIZE+1; + char* ptr = (char*)UClientImage_Base::wbuffer->data(); + uint32_t sz = HTTP2_FRAME_HEADER_SIZE+1, sz1 = UHTTP::set_cookie->size(), sz2 = UHTTP::ext->size(); - switch (U_http_info.nResponseCode) + pwbuffer = (unsigned char*)ptr+HTTP2_FRAME_HEADER_SIZE+1; + + if (U_http_info.nResponseCode == HTTP_NOT_IMPLEMENTED || + U_http_info.nResponseCode == HTTP_OPTIONS_RESPONSE) { - case HTTP_OK: ptr[HTTP2_FRAME_HEADER_SIZE] = 0x80 | 8; break; - case HTTP_NO_CONTENT: ptr[HTTP2_FRAME_HEADER_SIZE] = 0x80 | 9; break; - case HTTP_PARTIAL: ptr[HTTP2_FRAME_HEADER_SIZE] = 0x80 | 10; break; - case HTTP_NOT_MODIFIED: ptr[HTTP2_FRAME_HEADER_SIZE] = 0x80 | 11; break; - case HTTP_BAD_REQUEST: ptr[HTTP2_FRAME_HEADER_SIZE] = 0x80 | 12; break; - case HTTP_NOT_FOUND: ptr[HTTP2_FRAME_HEADER_SIZE] = 0x80 | 13; break; - case HTTP_INTERNAL_ERROR: ptr[HTTP2_FRAME_HEADER_SIZE] = 0x80 | 14; break; + ptr[HTTP2_FRAME_HEADER_SIZE] = 0x80 | 8; - default: // use literal header field without indexing - indexed name + *pwbuffer = 0x40; + pwbuffer = hpackEncodeInt(pwbuffer, 22, (1<<6)-1); + pwbuffer += hpackEncodeString(pwbuffer, + U_CONSTANT_TO_PARAM("GET, HEAD, POST, PUT, DELETE, OPTIONS, " // request methods + "TRACE, CONNECT, " // pathological + "COPY, MOVE, LOCK, UNLOCK, MKCOL, PROPFIND, " // webdav + "PATCH, PURGE, " // rfc-5789 + "MERGE, REPORT, CHECKOUT, MKACTIVITY, " // subversion + "NOTIFY, MSEARCH, SUBSCRIBE, UNSUBSCRIBE")); // upnp + + UClientImage_Base::setCloseConnection(); + } + else + { + if (sz2 == 0 && + U_http_info.nResponseCode == HTTP_OK) { - sz += 4; + ptr[HTTP2_FRAME_HEADER_SIZE] = 0x80 | 9; // HTTP_NO_CONTENT + } + else + { + switch (U_http_info.nResponseCode) + { + case HTTP_OK: ptr[HTTP2_FRAME_HEADER_SIZE] = 0x80 | 8; break; + case HTTP_NO_CONTENT: ptr[HTTP2_FRAME_HEADER_SIZE] = 0x80 | 9; break; + case HTTP_PARTIAL: ptr[HTTP2_FRAME_HEADER_SIZE] = 0x80 | 10; break; + case HTTP_NOT_MODIFIED: ptr[HTTP2_FRAME_HEADER_SIZE] = 0x80 | 11; break; + case HTTP_BAD_REQUEST: ptr[HTTP2_FRAME_HEADER_SIZE] = 0x80 | 12; break; + case HTTP_NOT_FOUND: ptr[HTTP2_FRAME_HEADER_SIZE] = 0x80 | 13; break; + case HTTP_INTERNAL_ERROR: ptr[HTTP2_FRAME_HEADER_SIZE] = 0x80 | 14; break; - ptr[HTTP2_FRAME_HEADER_SIZE+2] = (U_http_info.nResponseCode / 100) + '0'; - U_NUM2STR16(ptr+HTTP2_FRAME_HEADER_SIZE+3, U_http_info.nResponseCode % 100); + default: // use literal header field without indexing - indexed name + { + u_put_unalignedp32(ptr+HTTP2_FRAME_HEADER_SIZE, U_MULTICHAR_CONSTANT32('\010','\003','0'+(U_http_info.nResponseCode / 100),'\0')); + U_NUM2STR16(ptr+HTTP2_FRAME_HEADER_SIZE+3, U_http_info.nResponseCode % 100); + + sz += 4; + pwbuffer += 4; + } + } } } + // ------------------------------------------------- // literal header field with indexing (indexed name) - - unsigned char* dst = buffer+sz; - + // ------------------------------------------------- // server: ULib // date: Wed, 20 Jun 2012 11:43:17 GMT - *dst = 0x40; - dst = hpackEncodeInt(dst, 54, (1<<6)-1); - dst += hpackEncodeString(dst, U_CONSTANT_TO_PARAM("ULib")); - *dst = 0x40; - dst = hpackEncodeInt(dst, 33, (1<<6)-1); + /** + * *pwbuffer = 0x40; + * pwbuffer = hpackEncodeInt(pwbuffer, 54, (1<<6)-1); + * pwbuffer += hpackEncodeString(pwbuffer, U_CONSTANT_TO_PARAM("ULib")); + * *pwbuffer = 0x40; + * pwbuffer = hpackEncodeInt(pwbuffer, 33, (1<<6)-1); + */ -// u__memcpy(dst, "v\004\000UHTa", U_CONSTANT_SIZE("v\004\000UHTa"), __PRETTY_FUNCTION__); -// dst += U_CONSTANT_SIZE("v\004\000UHTa"); + u_put_unalignedp64(pwbuffer, U_MULTICHAR_CONSTANT64('v','\004','U','L','i','b','a','\0')); #if defined(ENABLE_THREAD) && !defined(U_LOG_ENABLE) && !defined(USE_LIBZ) U_INTERNAL_ASSERT_POINTER(u_pthread_time) @@ -1711,18 +1710,164 @@ void UHTTP2::handlerResponse() ULog::updateDate3(); #endif - dst += hpackEncodeString(dst, ((char*)UClientImage_Base::iov_vec[1].iov_base)+6, 29); // Date: Wed, 20 Jun 2012 11:43:17 GMT\r\nServer: ULib\r\nConnection: close\r\n + pwbuffer += 7+hpackEncodeString(pwbuffer+7, ((char*)UClientImage_Base::iov_vec[1].iov_base)+6, 29); // Date: Wed, 20 Jun 2012 11:43:17 GMT\r\nServer: ULib\r\nConnection: close\r\n - sz = dst - buffer; + if (sz1) + { + UClientImage_Base::setRequestNoCache(); + + *pwbuffer = 0x40; + pwbuffer = hpackEncodeInt(pwbuffer, 55, (1<<6)-1); + pwbuffer += hpackEncodeString(pwbuffer, UHTTP::set_cookie->data(), sz1); + + UHTTP::set_cookie->setEmpty(); + } + + if (sz2 == 0) + { + *pwbuffer = 0x40; + pwbuffer = hpackEncodeInt(pwbuffer, 28, (1<<6)-1); + pwbuffer += hpackEncodeString(pwbuffer, U_CONSTANT_TO_PARAM("0")); + } + else + { + UMimeHeader header; + + if (header.parse(UHTTP::ext->data(), sz2)) header.table.callForAllEntry(addHTTPHeader); + } + + sz = pwbuffer-(unsigned char*)ptr; *(uint32_t*) ptr = htonl((sz-HTTP2_FRAME_HEADER_SIZE) << 8); ptr[3] = HEADERS; + ptr[4] = FLAG_END_HEADERS; *(uint32_t*)(ptr+5) = htonl(pStream->id); - U_DUMP("frame response { length = %d stream_id = %d type = (%d, %s) flags = %d } = %#.*S", ntohl(*(uint32_t*)ptr & 0x00ffffff) >> 8, + U_DUMP("frame header response { length = %d stream_id = %d type = (%d, %s) flags = %d } = %#.*S", ntohl(*(uint32_t*)ptr & 0x00ffffff) >> 8, ntohl(*(uint32_t*)(ptr+5) & 0x7fffffff), ptr[3], getFrameTypeDescription(ptr[3]), ptr[4], ntohl(*(uint32_t*)ptr & 0x00ffffff) >> 8, ptr + HTTP2_FRAME_HEADER_SIZE) - if (USocketExt::write(UServer_Base::csocket, ptr, sz, UServer_Base::timeoutMS) != sz) nerror = FLOW_CONTROL_ERROR; + sz2 = UClientImage_Base::body->size(); + + if (sz2) + { + *(uint32_t*) pwbuffer = htonl(sz2 << 8); + pwbuffer[3] = DATA; + pwbuffer[4] = FLAG_END_STREAM; + *(uint32_t*)(pwbuffer+5) = htonl(pStream->id); + + U_DUMP("frame data response { length = %d stream_id = %d type = (%d, %s) flags = %d }", ntohl(*(uint32_t*)pwbuffer & 0x00ffffff) >> 8, + ntohl(*(uint32_t*)(pwbuffer+5) & 0x7fffffff), pwbuffer[3], getFrameTypeDescription(pwbuffer[3]), pwbuffer[4]) + + sz += HTTP2_FRAME_HEADER_SIZE; + } + + UClientImage_Base::wbuffer->size_adjust(sz); + + UClientImage_Base::setNoHeaderForResponse(); +} + +int UHTTP2::handlerRequest() +{ + U_TRACE(0, "UHTTP2::handlerRequest()") + + U_INTERNAL_ASSERT_EQUALS(U_http_version, '2') + + U_INTERNAL_DUMP("HTTP2-Settings: = %.*S U_http_method_type = %B", U_http2_settings_len, UHTTP2::upgrade_settings, U_http_method_type) + + if (U_http2_settings_len && + USocketExt::write(UServer_Base::csocket, U_CONSTANT_TO_PARAM(HTTP2_CONNECTION_UPGRADE_AND_SETTING_BIN), UServer_Base::timeoutMS) != + U_CONSTANT_SIZE(HTTP2_CONNECTION_UPGRADE_AND_SETTING_BIN)) + { + U_RETURN(U_PLUGIN_HANDLER_ERROR); + } + + U_INTERNAL_ASSERT(UClientImage_Base::request->same(*UClientImage_Base::rbuffer)) + + UClientImage_Base::request->clear(); + + // maybe we have read more data than necessary... + + uint32_t sz = UClientImage_Base::rbuffer->size(); + + U_INTERNAL_ASSERT_MAJOR(sz, 0) + + if (sz > U_http_info.endHeader) UClientImage_Base::rstart = U_http_info.endHeader; + else + { + // we wait for HTTP2_CONNECTION_PREFACE... + + UClientImage_Base::rbuffer->setEmptyForce(); + + if (UNotifier::waitForRead(UServer_Base::csocket->iSockDesc, U_TIMEOUT_MS) != 1 || + USocketExt::read(UServer_Base::csocket, *UClientImage_Base::rbuffer, U_SINGLE_READ, 0) == false) + { + U_RETURN(U_PLUGIN_HANDLER_ERROR); + } + + UClientImage_Base::rstart = 0; + + sz = UClientImage_Base::rbuffer->size(); + } + + const char* ptr = UClientImage_Base::rbuffer->c_pointer(UClientImage_Base::rstart); + + if (u_get_unalignedp64(ptr) != U_MULTICHAR_CONSTANT64( 'P', 'R','I',' ', '*', ' ', 'H', 'T') || + u_get_unalignedp64(ptr+8) != U_MULTICHAR_CONSTANT64( 'T', 'P','/','2', '.', '0','\r','\n') || + u_get_unalignedp64(ptr+16) != U_MULTICHAR_CONSTANT64('\r','\n','S','M','\r','\n','\r','\n')) + { + U_RETURN(U_PLUGIN_HANDLER_ERROR); + } + + pConnection = (Connection*)UServer_Base::pClientImage->connection; + pConnectionEnd = (char*)pConnection + sizeof(Connection); + + pConnection->state = CONN_STATE_OPEN; + pConnection->peer_settings = settings; + + pConnection->max_open_stream_id = + pConnection->num_responding_streams = + pConnection->max_processed_stream_id = 0; + + pStream = pConnection->streams; + + pStream->state = STREAM_STATE_IDLE; + + if (U_http2_settings_len == 0) + { + if (USocketExt::write(UServer_Base::csocket, U_CONSTANT_TO_PARAM(HTTP2_SETTINGS_BIN), UServer_Base::timeoutMS) != U_CONSTANT_SIZE(HTTP2_SETTINGS_BIN)) U_RETURN(U_PLUGIN_HANDLER_ERROR); + } + else + { + UString buffer(U_CAPACITY); + + UBase64::decodeUrl(upgrade_settings, U_http2_settings_len, buffer); + + if (buffer.empty() || + updateSetting(U_STRING_TO_PARAM(buffer)) == false) + { + U_RETURN(U_PLUGIN_HANDLER_ERROR); + } + } + + settings_ack = false; + + UClientImage_Base::rstart += U_CONSTANT_SIZE(HTTP2_CONNECTION_PREFACE); + +loop: + readFrame(); + + if (nerror == NO_ERROR) + { + U_INTERNAL_DUMP("settings_ack = %b", settings_ack) + + if (settings_ack == false) goto loop; // we wait for SETTINGS ack... + + return UHTTP::manageRequest(); + } + + sendError(); + + U_RETURN(U_PLUGIN_HANDLER_ERROR); } #ifdef ENTRY diff --git a/src/ulib/utility/uhttp.cpp b/src/ulib/utility/uhttp.cpp index 8914feb6..a5213c43 100644 --- a/src/ulib/utility/uhttp.cpp +++ b/src/ulib/utility/uhttp.cpp @@ -1648,37 +1648,6 @@ __pure bool UHTTP::isValidRequestExt(const char* ptr, uint32_t sz) U_RETURN(false); } -int UHTTP::handlerDataPending() -{ - U_TRACE(0, "UHTTP::handlerDataPending()") - -#ifndef U_HTTP2_DISABLE - U_INTERNAL_DUMP("U_http_version = %C", U_http_version) - - if (U_http_version == '2') - { - if (UHTTP2::manageSetting() == false) - { - U_ClientImage_state = U_PLUGIN_HANDLER_ERROR; - - U_RETURN(-1); - } - - U_ClientImage_data_missing = false; - - UClientImage_Base::setRequestNeedProcessing(); - - (void) manageRequest(); - - U_ClientImage_state = U_PLUGIN_HANDLER_ERROR; - - U_RETURN(-1); - } -#endif - - return UClientImage_Base::handlerDataPending(); -} - bool UHTTP::scanfHeaderRequest(const char* ptr, uint32_t size) { U_TRACE(0, "UHTTP::scanfHeaderRequest(%.*S,%u)", size, ptr, size) @@ -1923,7 +1892,7 @@ error: U_SRV_LOG("WARNING: invalid character %C in URI %.*S", c, ptr - U } // NB: there are case of requests fragmented (maybe because of VPN tunnel) - // for example something like: GET /info?Mac=00%3A40%3A63%3Afb%3A42%3A1c&ip=172.16.93.235&gateway=172.16.93.254%3A5280&ap=ap%4010.8.0.9 + // for example something like: GET /info?Mac=00%3A40%3A63%3Afb%3A42%3A1c&ip=172.16.93.235&gateway=172.16.93.254%3A5280&ap=ap%4010.8.0.9 end: U_ClientImage_data_missing = true; @@ -3426,7 +3395,7 @@ int UHTTP::handlerREAD() if (readHeaderRequest() == false) { - if (U_ClientImage_data_missing) goto dmiss; + if (U_ClientImage_data_missing) U_RETURN(U_PLUGIN_HANDLER_FINISHED); if (UNLIKELY(UServer_Base::csocket->isClosed())) U_RETURN(U_PLUGIN_HANDLER_ERROR); @@ -3474,12 +3443,7 @@ int UHTTP::handlerREAD() { checkRequestForHeader(); - if (U_ClientImage_data_missing) - { -dmiss: UClientImage_Base::setRequestProcessed(); - - U_RETURN(U_PLUGIN_HANDLER_FINISHED); - } + if (U_ClientImage_data_missing) U_RETURN(U_PLUGIN_HANDLER_FINISHED); } U_INTERNAL_DUMP("U_http_host_len = %u U_HTTP_HOST = %.*S", U_http_host_len, U_HTTP_HOST_TO_TRACE) @@ -4092,7 +4056,7 @@ int UHTTP::processRequest() *UClientImage_Base::body = getBodyFromCache(); } - *UClientImage_Base::wbuffer = getHeaderForResponse(); + handlerResponse(); # endif U_RETURN(U_PLUGIN_HANDLER_FINISHED); @@ -4138,7 +4102,7 @@ int UHTTP::processRequest() (void) ext->append(getHeaderMimeType(0, sz, U_CTYPE_HTML)); - *UClientImage_Base::wbuffer = getHeaderForResponse(); // build response... + handlerResponse(); } U_RETURN(U_PLUGIN_HANDLER_FINISHED); @@ -4221,7 +4185,7 @@ empty_file: // NB: now we check for empty file... ext->clear(); - *UClientImage_Base::wbuffer = getHeaderForResponse(); + handlerResponse(); } } @@ -5515,9 +5479,9 @@ void UHTTP::setStatusDescription() U_INTERNAL_DUMP("UClientImage_Base::iov_vec[0] = %.*S", UClientImage_Base::iov_vec[0].iov_len, UClientImage_Base::iov_vec[0].iov_base) } -UString UHTTP::getHeaderForResponse() +void UHTTP::handlerResponse() { - U_TRACE(0, "UHTTP::getHeaderForResponse()") + U_TRACE(0, "UHTTP::handlerResponse()") U_INTERNAL_DUMP("U_http_info.nResponseCode = %d", U_http_info.nResponseCode) @@ -5535,27 +5499,23 @@ UString UHTTP::getHeaderForResponse() UClientImage_Base::setRequestProcessed(); #ifndef U_HTTP2_DISABLE - if (U_http_version == '2') - { - UHTTP2::handlerResponse(); - - return UString::getStringNull(); - } + if (U_http_version == '2') UHTTP2::handlerResponse(); + else #endif - + { UClientImage_Base::setHeaderForResponse(6+29+2+12+2); // Date: Wed, 20 Jun 2012 11:43:17 GMT\r\nServer: ULib\r\n if (U_http_info.nResponseCode == HTTP_NOT_IMPLEMENTED || U_http_info.nResponseCode == HTTP_OPTIONS_RESPONSE) { - UString result = U_STRING_FROM_CONSTANT("Allow: " + (void) UClientImage_Base::wbuffer->assign(U_CONSTANT_TO_PARAM("Allow: " "GET, HEAD, POST, PUT, DELETE, OPTIONS, " // request methods "TRACE, CONNECT, " // pathological "COPY, MOVE, LOCK, UNLOCK, MKCOL, PROPFIND, " // webdav "PATCH, PURGE, " // rfc-5789 "MERGE, REPORT, CHECKOUT, MKACTIVITY, " // subversion "NOTIFY, MSEARCH, SUBSCRIBE, UNSUBSCRIBE" // upnp - "\r\nContent-Length: 0\r\n\r\n"); + "\r\nContent-Length: 0\r\n\r\n")); UClientImage_Base::setRequestNoCache(); UClientImage_Base::setCloseConnection(); @@ -5564,7 +5524,7 @@ UString UHTTP::getHeaderForResponse() setStatusDescription(); - U_RETURN_STRING(result); + return; } // NB: all other responses must include an entity body or a Content-Length header field defined with a value of zero (0) @@ -5600,9 +5560,9 @@ UString UHTTP::getHeaderForResponse() setStatusDescription(); - UString result(200U + sz1 + sz2); + UClientImage_Base::wbuffer->setBuffer(200U + sz1 + sz2); - base = ptr = result.data(); + base = ptr = UClientImage_Base::wbuffer->data(); if (sz1) { @@ -5673,11 +5633,11 @@ UString UHTTP::getHeaderForResponse() u__memcpy(ptr, ptr2, sz2, __PRETTY_FUNCTION__); - result.size_adjust((ptr - base) + sz2); + UClientImage_Base::wbuffer->size_adjust((ptr - base) + sz2); + } - U_INTERNAL_DUMP("result(%u) = %V", result.size(), result.rep) - - U_RETURN_STRING(result); + U_INTERNAL_DUMP("UClientImage_Base::wbuffer(%u) = %#V", UClientImage_Base::wbuffer->size(), UClientImage_Base::wbuffer->rep) + U_INTERNAL_DUMP("UClientImage_Base::body(%u) = %V", UClientImage_Base::body->size(), UClientImage_Base::body->rep) } void UHTTP::setResponse(const UString* content_type, UString* pbody) @@ -5709,55 +5669,65 @@ void UHTTP::setResponse(const UString* content_type, UString* pbody) ptr += sz; +# ifndef U_HTTP2_DISABLE + if (U_http_version != '2') +# endif + { u_put_unalignedp64(ptr, U_MULTICHAR_CONSTANT64('C','o','n','t','e','n','t','-')); u_put_unalignedp64(ptr+8, U_MULTICHAR_CONSTANT64('L','e','n','g','t','h',':',' ')); ptr += U_CONSTANT_SIZE("Content-Length: "); + } - if (pbody == 0) *ptr++ = '0'; - else + if (pbody == 0) { - sz = pbody->size(); - -# ifdef USE_LIBZ - if (UStringExt::isGzip(*pbody)) - { - if (U_http_is_accept_gzip == false) - { - *pbody = UStringExt::gunzip(*pbody); - - sz = pbody->size(); - } - - ptr += u_num2str32(ptr, sz); - - if (U_http_is_accept_gzip) - { - u_put_unalignedp64(ptr, U_MULTICHAR_CONSTANT64('\r','\n','C','o','n','t','e','n')); - u_put_unalignedp64(ptr+8, U_MULTICHAR_CONSTANT64('t', '-','E','n','c','o','d','i')); - u_put_unalignedp64(ptr+16, U_MULTICHAR_CONSTANT64('n', 'g',':',' ','g','z','i','p')); - - ptr += U_CONSTANT_SIZE("\r\nContent-Encoding: gzip"); - } - } - else +# ifndef U_HTTP2_DISABLE + if (U_http_version != '2') # endif - ptr += u_num2str32(ptr, sz); + *ptr++ = '0'; + + UClientImage_Base::body->clear(); // clean body to avoid writev() in response... + + goto end; } - u_put_unalignedp32(ptr, U_MULTICHAR_CONSTANT32('\r','\n','\r','\n')); +# ifdef USE_LIBZ + if (UStringExt::isGzip(*pbody)) + { + if (U_http_is_accept_gzip) *pbody = UStringExt::gunzip(*pbody); + +# ifndef U_HTTP2_DISABLE + if (U_http_version != '2') +# endif + ptr += u_num2str32(ptr, pbody->size()); + + if (U_http_is_accept_gzip) + { + u_put_unalignedp64(ptr, U_MULTICHAR_CONSTANT64('\r','\n','C','o','n','t','e','n')); + u_put_unalignedp64(ptr+8, U_MULTICHAR_CONSTANT64('t', '-','E','n','c','o','d','i')); + u_put_unalignedp64(ptr+16, U_MULTICHAR_CONSTANT64('n', 'g',':',' ','g','z','i','p')); + + ptr += U_CONSTANT_SIZE("\r\nContent-Encoding: gzip"); + } + } + else +# endif + { +# ifndef U_HTTP2_DISABLE + if (U_http_version != '2') +# endif + ptr += u_num2str32(ptr, pbody->size()); + } + + *UClientImage_Base::body = *pbody; + +end: u_put_unalignedp32(ptr, U_MULTICHAR_CONSTANT32('\r','\n','\r','\n')); ptr += U_CONSTANT_SIZE(U_CRLF2); ext->size_adjust(ptr - start); } - if (pbody) *UClientImage_Base::body = *pbody; - else UClientImage_Base::body->clear(); // clean body to avoid writev() in response... - - *UClientImage_Base::wbuffer = getHeaderForResponse(); - - U_INTERNAL_DUMP("UClientImage_Base::wbuffer(%u) = %V", UClientImage_Base::wbuffer->size(), UClientImage_Base::wbuffer->rep) - U_INTERNAL_DUMP("UClientImage_Base::body(%u) = %V", UClientImage_Base::body->size(), UClientImage_Base::body->rep) + handlerResponse(); } #define U_STR_FMR_BODY "\r\n" \ @@ -6110,7 +6080,7 @@ end: ext->size_adjust(ptr1); - *UClientImage_Base::wbuffer = getHeaderForResponse(); + handlerResponse(); } U_NO_EXPORT bool UHTTP::processAuthorization() @@ -7680,8 +7650,9 @@ U_NO_EXPORT bool UHTTP::processFileCache() *ext = getHeaderCompressFromCache(); - *UClientImage_Base::wbuffer = getHeaderForResponse(); - *UClientImage_Base::body = getBodyCompressFromCache(); + *UClientImage_Base::body = getBodyCompressFromCache(); + + handlerResponse(); U_RETURN(true); } @@ -7722,7 +7693,7 @@ U_NO_EXPORT bool UHTTP::processFileCache() U_http_sendfile = true; } - *UClientImage_Base::wbuffer = getHeaderForResponse(); + handlerResponse(); U_RETURN(result); } @@ -8288,7 +8259,7 @@ bool UHTTP::getCGIEnvironment(UString& environment, int mask) if (requestHeader.parse(UClientImage_Base::request->c_pointer(U_http_info.startHeader), U_http_info.endHeader - U_CONSTANT_SIZE(U_CRLF2) - U_http_info.startHeader)) { - // The environment must not contain the keys HTTP_CONTENT_TYPE or HTTP_CONTENT_LENGTH (we use the versions without HTTP_). + // The environment must not contain the keys HTTP_CONTENT_TYPE or HTTP_CONTENT_LENGTH (we use the versions without HTTP_) requestHeader.removeHeader(*UString::str_content_type); requestHeader.removeHeader(*UString::str_content_length); @@ -8869,7 +8840,7 @@ loop: UClientImage_Base::body->clear(); - *UClientImage_Base::wbuffer = getHeaderForResponse(); + handlerResponse(); U_RETURN(true); } @@ -9083,11 +9054,11 @@ loop: ext->clear(); - UClientImage_Base::body->clear(); - (void) set_cookie->append(UClientImage_Base::wbuffer->data(), sz - U_CONSTANT_SIZE(U_CRLF)); // NB: opportunism... - *UClientImage_Base::wbuffer = getHeaderForResponse(); + UClientImage_Base::body->clear(); + + handlerResponse(); U_RETURN(true); } @@ -9224,7 +9195,7 @@ bool UHTTP::checkContentLength(uint32_t length, uint32_t pos) (void) ext->replace(pos, sz_len1, bp, sz_len2); - U_INTERNAL_DUMP("x(%u) = %#V", ext->size(), ext->rep) + U_INTERNAL_DUMP("ext(%u) = %#V", ext->size(), ext->rep) U_RETURN(true); } @@ -9522,8 +9493,9 @@ U_NO_EXPORT int UHTTP::checkGetRequestForRange(const UString& data) (void) UFile::writeToTmp(U_STRING_TO_PARAM(*ext), false, "byteranges.%P", 0); #endif - U_http_info.nResponseCode = HTTP_PARTIAL; - *UClientImage_Base::wbuffer = getHeaderForResponse(); + U_http_info.nResponseCode = HTTP_PARTIAL; + + handlerResponse(); U_RETURN(U_YES); } @@ -9695,7 +9667,7 @@ U_NO_EXPORT void UHTTP::processGetRequest() setResponseForRange(range_start, range_size-1, U_CONSTANT_SIZE(U_FLV_HEAD)); - *UClientImage_Base::wbuffer = getHeaderForResponse(); + handlerResponse(); (void) UClientImage_Base::wbuffer->append(U_CONSTANT_TO_PARAM(U_FLV_HEAD)); @@ -9704,7 +9676,7 @@ U_NO_EXPORT void UHTTP::processGetRequest() } build_response: - *UClientImage_Base::wbuffer = getHeaderForResponse(); + handlerResponse(); next: U_INTERNAL_DUMP("range_start = %u range_size = %u UServer_Base::min_size_for_sendfile = %u", range_start, range_size, UServer_Base::min_size_for_sendfile) diff --git a/tests/examples/FrameworkBenchmarks.sh b/tests/examples/FrameworkBenchmarks.sh index 18d72496..644d8395 100755 --- a/tests/examples/FrameworkBenchmarks.sh +++ b/tests/examples/FrameworkBenchmarks.sh @@ -22,9 +22,9 @@ export ORM_DRIVER ORM_OPTION UMEMPOOL # ---------------------------------------------------------------------------------------------------------------------------------------------------------- # PLAINTEXT # ---------------------------------------------------------------------------------------------------------------------------------------------------------- -#UMEMPOOL="982,0,0,36,9846,-24,-23,1727,1151" -#sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET 0|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg -#sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 16384|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg + UMEMPOOL="982,0,0,36,9846,-24,-23,1727,1151" + sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET 0|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg + sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 16384|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg #sed -i "s|CLIENT_THRESHOLD .*|CLIENT_THRESHOLD 4000|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg #sed -i "s|CLIENT_FOR_PARALLELIZATION .*|CLIENT_FOR_PARALLELIZATION 8000|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg # ---------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -58,9 +58,9 @@ export ORM_DRIVER ORM_OPTION UMEMPOOL # ---------------------------------------------------------------------------------------------------------------------------------------------------------- # JSON # ---------------------------------------------------------------------------------------------------------------------------------------------------------- - UMEMPOOL="56,0,0,40,150,-24,-13,-20,0" - sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET 0|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg - sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 256|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg +#UMEMPOOL="56,0,0,40,150,-24,-13,-20,0" +#sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET 0|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg +#sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 256|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg #sed -i "s|CLIENT_THRESHOLD .*|CLIENT_THRESHOLD 50|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg #sed -i "s|CLIENT_FOR_PARALLELIZATION .*|CLIENT_FOR_PARALLELIZATION 100|g" benchmark/FrameworkBenchmarks/fbenchmark.cfg # ----------------------------------------------------------------------------------------------------------------------------------------------------------