From b66e456d461d37e943603ea6ad1e70f8f66f4743 Mon Sep 17 00:00:00 2001 From: stefanocasazza Date: Tue, 10 Oct 2017 16:21:11 +0200 Subject: [PATCH] fix+sync --- examples/IR/ir_web.cpp | 5 +- examples/WiAuth/wi_auth.cpp | 2 - include/ulib/net/socket.h | 14 +- include/ulib/utility/string_ext.h | 6 +- src/ulib/container/vector.cpp | 28 +- src/ulib/log.cpp | 8 - src/ulib/net/server/client_image.cpp | 9 +- src/ulib/net/server/plugin/mod_http.cpp | 1 - src/ulib/net/server/plugin/usp/test.usp | 2 + .../net/server/plugin/usp/usp_translator.cpp | 1124 +++++++++-------- src/ulib/net/server/server.cpp | 65 +- src/ulib/net/socket.cpp | 43 +- src/ulib/utility/http2.cpp | 2 - src/ulib/utility/string_ext.cpp | 236 +++- src/ulib/utility/uhttp.cpp | 107 +- tests/examples/udp_server.sh | 2 +- tests/ulib/test_socket.cpp | 8 +- tests/ulib/test_string.cpp | 30 + 18 files changed, 1010 insertions(+), 682 deletions(-) create mode 100644 src/ulib/net/server/plugin/usp/test.usp diff --git a/examples/IR/ir_web.cpp b/examples/IR/ir_web.cpp index dd3e64e7..8ee8e4d7 100644 --- a/examples/IR/ir_web.cpp +++ b/examples/IR/ir_web.cpp @@ -219,8 +219,5 @@ extern U_EXPORT void runDynamicPage_ir_web(int param); ); UHTTP::putDataSession(); - - UClientImage_Base::setRequestNoCache(); - - + } } \ No newline at end of file diff --git a/examples/WiAuth/wi_auth.cpp b/examples/WiAuth/wi_auth.cpp index 796d2730..d9a1f20b 100644 --- a/examples/WiAuth/wi_auth.cpp +++ b/examples/WiAuth/wi_auth.cpp @@ -109,7 +109,5 @@ extern U_EXPORT void runDynamicPage_wi_auth(int param); if (U_http_info.nResponseCode == 0) (void) UClientImage_Base::environment->append(U_CONSTANT_TO_PARAM("HTTP_RESPONSE_CODE=0\n")); - UClientImage_Base::setRequestNoCache(); - } } \ No newline at end of file diff --git a/include/ulib/net/socket.h b/include/ulib/net/socket.h index 78214c6a..120fd171 100644 --- a/include/ulib/net/socket.h +++ b/include/ulib/net/socket.h @@ -749,7 +749,6 @@ protected: { U_TRACE_NO_PARAM(0, "USocket::setReusePort()") - U_ASSERT_EQUALS(isUDP(), false) U_ASSERT_EQUALS(isIPC(), false) /** @@ -768,6 +767,19 @@ protected: # endif } + bool listen() + { + U_TRACE_NO_PARAM(0, "USocket::listen()") + + if (isUDP() || + U_SYSCALL(listen, "%d,%d", iSockDesc, iBackLog) == 0) + { + U_RETURN(true); + } + + U_RETURN(false); + } + void close_socket(); void _close_socket(); diff --git a/include/ulib/utility/string_ext.h b/include/ulib/utility/string_ext.h index a9a1ebb5..a85e5a69 100644 --- a/include/ulib/utility/string_ext.h +++ b/include/ulib/utility/string_ext.h @@ -250,7 +250,11 @@ public: static UString substitute(const UString& s, const char* a, uint32_t n1, char b) { return substitute(U_STRING_TO_PARAM(s), a, n1, &b, 1); } static UString substitute(const UString& s, const char* a, uint32_t n1, const char* b, uint32_t n2) { return substitute(U_STRING_TO_PARAM(s), a, n1, b, n2); } - static UString substitute(const UString& s, const UString& a, const UString& b) { return substitute(U_STRING_TO_PARAM(s), U_STRING_TO_PARAM(a), U_STRING_TO_PARAM(b)); } + static UString substitute(const char* s, uint32_t n, const UString& a, const UString& b) { return substitute(s, n, U_STRING_TO_PARAM(a), U_STRING_TO_PARAM(b)); } + static UString substitute(const UString& s, const UString& a, const UString& b) { return substitute(U_STRING_TO_PARAM(s), U_STRING_TO_PARAM(a), U_STRING_TO_PARAM(b)); } + + static UString substitute(const char* s, uint32_t n, UVector& vec); + static UString substitute(const UString& s, UVector& vec) { return substitute(U_STRING_TO_PARAM(s), vec); } // ERASE diff --git a/src/ulib/container/vector.cpp b/src/ulib/container/vector.cpp index b4e926f1..cc3cd73a 100644 --- a/src/ulib/container/vector.cpp +++ b/src/ulib/container/vector.cpp @@ -86,7 +86,11 @@ void UVector::insert(uint32_t pos, const void* elem) // add elem before p U_INTERNAL_ASSERT(pos <= _length) U_INTERNAL_ASSERT(_length <= _capacity) - if (_length == _capacity) + if (_length != _capacity) + { + (void) U_SYSCALL(memmove, "%p,%p,%u", vec + pos + 1, vec + pos, (_length - pos) * sizeof(void*)); + } + else { const void** old_vec = vec; uint32_t old_capacity = _capacity; @@ -100,14 +104,6 @@ void UVector::insert(uint32_t pos, const void* elem) // add elem before p UMemoryPool::_free(old_vec, old_capacity, sizeof(void*)); } - else - { -# ifdef U_APEX_ENABLE - (void) U_SYSCALL(apex_memmove, "%p,%p,%u", vec + pos + 1, vec + pos, (_length - pos) * sizeof(void*)); -# else - (void) U_SYSCALL( memmove, "%p,%p,%u", vec + pos + 1, vec + pos, (_length - pos) * sizeof(void*)); -# endif - } vec[pos] = elem; @@ -126,7 +122,11 @@ void UVector::insert(uint32_t pos, uint32_t n, const void* elem) // add n uint32_t new_length = _length + n; - if (new_length > _capacity) + if (new_length <= _capacity) + { + (void) U_SYSCALL(memmove, "%p,%p,%u", vec + pos + n, vec + pos, (_length - pos) * sizeof(void*)); + } + else { const void** old_vec = vec; uint32_t old_capacity = _capacity; @@ -140,14 +140,6 @@ void UVector::insert(uint32_t pos, uint32_t n, const void* elem) // add n UMemoryPool::_free(old_vec, old_capacity, sizeof(void*)); } - else - { -# ifdef U_APEX_ENABLE - (void) U_SYSCALL(apex_memmove, "%p,%p,%u", vec + pos + n, vec + pos, (_length - pos) * sizeof(void*)); -# else - (void) U_SYSCALL( memmove, "%p,%p,%u", vec + pos + n, vec + pos, (_length - pos) * sizeof(void*)); -# endif - } for (uint32_t i = 0; i < n; ++i) vec[pos++] = elem; diff --git a/src/ulib/log.cpp b/src/ulib/log.cpp index ef08b383..04e4fdca 100644 --- a/src/ulib/log.cpp +++ b/src/ulib/log.cpp @@ -280,8 +280,6 @@ void ULog::updateDate2() */ #if defined(U_LINUX) && defined(ENABLE_THREAD) - U_INTERNAL_ASSERT_POINTER(u_pthread_time) - # ifndef U_SERVER_CAPTIVE_PORTAL (void) U_SYSCALL(pthread_rwlock_rdlock, "%p", prwlock); # endif @@ -314,8 +312,6 @@ void ULog::updateDate2() (void) U_SYSCALL(pthread_rwlock_unlock, "%p", prwlock); # endif #else - U_INTERNAL_ASSERT_EQUALS(u_pthread_time, U_NULLPTR) - u_gettimenow(); if (tv_sec_old_2 != u_now->tv_sec) @@ -354,8 +350,6 @@ void ULog::updateDate3(char* ptr_date) */ #if defined(U_LINUX) && defined(ENABLE_THREAD) - U_INTERNAL_ASSERT_POINTER(u_pthread_time) - # ifndef U_SERVER_CAPTIVE_PORTAL (void) U_SYSCALL(pthread_rwlock_rdlock, "%p", prwlock); # endif @@ -400,8 +394,6 @@ void ULog::updateDate3(char* ptr_date) (void) U_SYSCALL(pthread_rwlock_unlock, "%p", prwlock); # endif #else - U_INTERNAL_ASSERT_EQUALS(u_pthread_time, U_NULLPTR) - u_gettimenow(); if (tv_sec_old_3 != u_now->tv_sec) diff --git a/src/ulib/net/server/client_image.cpp b/src/ulib/net/server/client_image.cpp index 3b4152ec..5e045283 100644 --- a/src/ulib/net/server/client_image.cpp +++ b/src/ulib/net/server/client_image.cpp @@ -980,6 +980,10 @@ void UClientImage_Base::prepareForRead() u_clientimage_info.flag.u = 0; // NB: U_ClientImage_parallelization is reset by this... +#ifdef USERVER_UDP + if (UServer_Base::budp == false) +#endif + { #ifdef U_CLASSIC_SUPPORT if (UServer_Base::isClassic()) { @@ -1053,6 +1057,7 @@ void UClientImage_Base::prepareForRead() #ifdef U_THROTTLING_SUPPORT UServer_Base::initThrottlingClient(); #endif + } } bool UClientImage_Base::genericRead() @@ -1175,9 +1180,6 @@ int UClientImage_Base::handlerRead() // Connection-wide hooks int result; uint32_t sz; -# ifdef USERVER_UDP - if (UServer_Base::budp == false) -# endif prepareForRead(); start: @@ -1653,7 +1655,6 @@ bool UClientImage_Base::writeResponse() U_INTERNAL_ASSERT_MAJOR(iov_sav[0].iov_len, 0) # if defined(U_LINUX) && defined(ENABLE_THREAD) - U_INTERNAL_ASSERT_POINTER(u_pthread_time) U_INTERNAL_ASSERT_EQUALS(iov_vec[1].iov_base, ULog::ptr_shared_date->date3) # else U_INTERNAL_ASSERT_EQUALS(iov_vec[1].iov_base, ULog::date.date3) diff --git a/src/ulib/net/server/plugin/mod_http.cpp b/src/ulib/net/server/plugin/mod_http.cpp index 61a12e6e..47dac987 100644 --- a/src/ulib/net/server/plugin/mod_http.cpp +++ b/src/ulib/net/server/plugin/mod_http.cpp @@ -534,7 +534,6 @@ int UHttpPlugIn::handlerRun() // NB: we use this method instead of handlerInit() UClientImage_Base::iov_vec[1].iov_base = (caddr_t)ULog::date.date3; // Date: Wed, 20 Jun 2012 11:43:17 GMT\r\nServer: ULib\r\nConnection: close\r\n #if defined(U_LINUX) && defined(ENABLE_THREAD) - U_INTERNAL_ASSERT_POINTER(u_pthread_time) U_INTERNAL_ASSERT_POINTER(UServer_Base::ptr_shared_data) # ifndef U_SERVER_CAPTIVE_PORTAL diff --git a/src/ulib/net/server/plugin/usp/test.usp b/src/ulib/net/server/plugin/usp/test.usp new file mode 100644 index 00000000..a46d574b --- /dev/null +++ b/src/ulib/net/server/plugin/usp/test.usp @@ -0,0 +1,2 @@ + + diff --git a/src/ulib/net/server/plugin/usp/usp_translator.cpp b/src/ulib/net/server/plugin/usp/usp_translator.cpp index 92e5c5d3..f67aa775 100644 --- a/src/ulib/net/server/plugin/usp/usp_translator.cpp +++ b/src/ulib/net/server/plugin/usp/usp_translator.cpp @@ -4,7 +4,7 @@ // ULib - c++ library // // = FILENAME -// usp_translator.cpp - the translator .usp => .cpp for plugin dynamic page for UServer +// usp_translator.cpp - the translator .usp => .cpp for dynamic page for UServer // // = AUTHOR // Stefano Casazza @@ -22,7 +22,7 @@ #undef PACKAGE #define PACKAGE "usp_translator" #undef ARGS -#define ARGS "[filename]" +#define ARGS "[filename usp]" #define U_OPTIONS "" #define U_PURPOSE "program for dynamic page translation ([xxx].usp => [xxx].cpp)" @@ -88,22 +88,481 @@ public: U_TRACE_NO_PARAM(5, "Application::~Application()") } - void run(int argc, char* argv[], char* env[]) + void setDirectiveItem(const char* directive, uint32_t tag_len) { - U_TRACE(5, "Application::run(%d,%p,%p)", argc, argv, env) + U_TRACE(5, "Application::setDirectiveItem(%.10S,%u)", directive, tag_len) - UApplication::run(argc, argv, env); + uint32_t n = token.size() - tag_len - 2; - if (argv[1] == U_NULLPTR) U_ERROR("Filename not specified"); + token = UStringExt::trim(directive+tag_len, n); - UString filename(argv[1], strlen(argv[1])); + U_INTERNAL_DUMP("token = %V", token.rep) + } - UString usp = UFile::contentOf(filename); + void manageDirectiveSessionOrStorage(const char* name) + { + U_TRACE(5, "Application::manageDirectiveSessionOrStorage(%S)", name) - if (usp.empty()) U_ERROR(" %V not valid", filename.rep); + U_INTERNAL_ASSERT(token) + + UString id, tmp; + const char* ptr; + uint32_t pos, size; + UVector vec(token, "\t\n;"); + + bvar = true; + + (void) output0.reserve(20U + token.size()); + + output0.snprintf_add(U_CONSTANT_TO_PARAM("\n\t%v\n\t\n"), token.rep); + + for (uint32_t i = 0, n = vec.size(); i < n; ++i) + { + ptr = (tmp = UStringExt::trim(vec[i])).data(); + + do { ++ptr; } while (u__isspace(*ptr) == false); + do { ++ptr; } while (u__isspace(*ptr) == true); + + pos = (id = tmp.substr(tmp.distance(ptr))).find('('); + size = (pos == U_NOT_FOUND ? id.size() : pos); + + (void) output0.reserve(50U + size); + (void) output1.reserve(50U + size); + + output0.snprintf_add(U_CONSTANT_TO_PARAM("\n\tUSP_%s_VAR_GET(%u,%.*s);\n\t"), name, i, size, ptr); + output1.snprintf_add(U_CONSTANT_TO_PARAM("\n\tUSP_%s_VAR_PUT(%u,%.*s);\n\t"), name, i, size, ptr); + +# ifdef DEBUG + id.clear(); // NB: to avoid DEAD OF SOURCE STRING WITH CHILD ALIVE... +# endif + } + } + + void manageDirectiveArgsOrCpath(const char* name, bool binc) + { + U_TRACE(5, "Application::manageDirectiveArgsOrCpath(%S,%b)", name, binc) + + U_INTERNAL_ASSERT(token) + + uint32_t pos; + UString id, tmp; + UVector vec(token, "\t\n;"); + + (void) output0.reserve(200U + token.size()); + + for (uint32_t i = 0, n = vec.size(); i < n; ++i) + { + tmp = UStringExt::trim(vec[i]); + pos = tmp.find('('); + id = (pos == U_NOT_FOUND ? tmp : tmp.substr(0U, pos)); + + output0.snprintf_add(U_CONSTANT_TO_PARAM("\n\tUString %v = %s(%u);\n\t"), id.rep, name, i+binc); + + if (pos != U_NOT_FOUND) + { + output0.snprintf_add(U_CONSTANT_TO_PARAM("\n\tif (%v.empty()) %v = U_STRING_FROM_CONSTANT(%.*s);\n\t"), id.rep, id.rep, tmp.size()-pos-2, tmp.c_pointer(pos+1)); + } + +# ifdef DEBUG + id.clear(); // NB: to avoid DEAD OF SOURCE STRING WITH CHILD ALIVE... +# endif + } + } + + void processDirective() + { + U_TRACE_NO_PARAM(5, "Application::processDirective()") + + /** + * token list: + * + * (comment) + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + */ + + U_INTERNAL_DUMP("token = %V", token.rep) + + const char* directive = token.c_pointer(2); // "-#"... + + U_INTERNAL_DUMP("directive(10) = %.*S", 10, directive) + + if (bfirst_pass) + { + bool bdefine = (strncmp(directive, U_CONSTANT_TO_PARAM("define")) == 0), + binclude = (strncmp(directive, U_CONSTANT_TO_PARAM("include")) == 0); + + U_INTERNAL_DUMP("bdefine = %b binclude = %b", bdefine, binclude) + + if (bdefine || + binclude) + { + UString block(100U); + UVector vec; + + block.snprintf(U_CONSTANT_TO_PARAM(""), token.rep); + + for (const char* ptr = t.getPointer(); u__isspace(*ptr); ++ptr) block.push_back(*ptr); + + vec.push_back(block); + + if (binclude) + { + setDirectiveItem(directive, U_CONSTANT_SIZE("include")); + + UString content = UFile::contentOf(token); + + if (content) vec.push_back(vdefine.empty() ? content : UStringExt::substitute(content, vdefine)); + else + { + vec.push_back(UString::getStringNull()); + + U_WARNING("load of include usp %V failed", token.rep); + } + } + else + { + U_INTERNAL_ASSERT(bdefine) + + setDirectiveItem(directive, U_CONSTANT_SIZE("define")); + + vec.push_back(UString::getStringNull()); + + (void) vec.split(U_STRING_TO_PARAM(token)); + + U_ASSERT_EQUALS(vec.size(), 4) + + vdefine.push_back(vec[2]); + vdefine.push_back(vec[3]); + } + +# ifdef DEBUG + token.clear(); // NB: to avoid DEAD OF SOURCE STRING WITH CHILD ALIVE... +# endif + + t.setData((usp = UStringExt::substitute(usp, vec))); + } + + return; + } + + if (strncmp(directive, U_CONSTANT_TO_PARAM("declaration")) == 0) + { + U_ASSERT(vcode.empty()) + U_ASSERT(declaration.empty()) // NB: must be at the beginning and uniq... + U_INTERNAL_ASSERT_EQUALS(bfirst_pass, false) + + setDirectiveItem(directive, U_CONSTANT_SIZE("declaration")); + + declaration = UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t")); + } + else if (strncmp(directive, U_CONSTANT_TO_PARAM("session")) == 0) + { + U_ASSERT(vcode.empty()) + U_INTERNAL_ASSERT_EQUALS(bfirst_pass, false) + + bsession = true; + + setDirectiveItem(directive, U_CONSTANT_SIZE("session")); + + if (token) manageDirectiveSessionOrStorage("SESSION"); + else + { + (void) output0.append(U_CONSTANT_TO_PARAM("\n\tif (UHTTP::getDataSession() == false) UHTTP::setSessionCookie();\n\t")); + (void) output1.append(U_CONSTANT_TO_PARAM("\n\tUHTTP::putDataSession();\n\t")); + } + } + else if (strncmp(directive, U_CONSTANT_TO_PARAM("storage")) == 0) + { + U_ASSERT(vcode.empty()) + U_INTERNAL_ASSERT_EQUALS(bfirst_pass, false) + + bstorage = true; + + setDirectiveItem(directive, U_CONSTANT_SIZE("storage")); + + if (token) manageDirectiveSessionOrStorage("STORAGE"); + else + { + (void) output0.append(U_CONSTANT_TO_PARAM("\n\t(void) UHTTP::getDataStorage();\n\t")); + (void) output1.append(U_CONSTANT_TO_PARAM("\n\tUHTTP::putDataStorage();\n\t")); + } + } + else if (strncmp(directive, U_CONSTANT_TO_PARAM("args")) == 0) + { + U_ASSERT(vcode.empty()) + U_INTERNAL_ASSERT_EQUALS(bfirst_pass, false) + + setDirectiveItem(directive, U_CONSTANT_SIZE("args")); + + (void) output0.append(U_CONSTANT_TO_PARAM("\t\n\t\tif (UHTTP::isGETorPOST()) (void) UHTTP::processForm();\n")); + + if (token) manageDirectiveArgsOrCpath("USP_FORM_VALUE", false); + } + else if (strncmp(directive, U_CONSTANT_TO_PARAM("cpath")) == 0) + { + U_ASSERT(vcode.empty()) + U_INTERNAL_ASSERT_EQUALS(bfirst_pass, false) + + setDirectiveItem(directive, U_CONSTANT_SIZE("cpath")); + + manageDirectiveArgsOrCpath("UHTTP::getPathComponent", true); + } + else if (strncmp(directive, U_CONSTANT_TO_PARAM("header")) == 0) + { + U_ASSERT(vcode.empty()) + U_ASSERT(http_header.empty()) + U_INTERNAL_ASSERT_EQUALS(bfirst_pass, false) + + setDirectiveItem(directive, U_CONSTANT_SIZE("header")); + + http_header = token; + } + else if (strncmp(directive, U_CONSTANT_TO_PARAM("vcode")) == 0) // validation code + { + U_ASSERT(vcode.empty()) // NB: must be before other code and uniq... + U_INTERNAL_ASSERT_EQUALS(bfirst_pass, false) + + setDirectiveItem(directive, U_CONSTANT_SIZE("vcode")); + + token = UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t")); + + vcode.setBuffer(20U + token.size()); + + vcode.snprintf(U_CONSTANT_TO_PARAM("\n\t%v\n\t\n"), token.rep); + } + else if (strncmp(directive, U_CONSTANT_TO_PARAM("pcode")) == 0) // parallelization code (long running task) + { + U_INTERNAL_ASSERT_EQUALS(bfirst_pass, false) + + setDirectiveItem(directive, U_CONSTANT_SIZE("pcode")); + + token = UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t")); + + (void) output0.reserve(20U + token.size()); + + output0.snprintf_add(U_CONSTANT_TO_PARAM("\n\t%v\n\t\n"), token.rep); + + (void) vcode.append(U_CONSTANT_TO_PARAM("\tif (UServer_Base::startParallelization()) { U_http_info.nResponseCode = HTTP_CONTINUE; return; }\n\t\n")); + } + else if (strncmp(directive, U_CONSTANT_TO_PARAM("lcode")) == 0) // load balance code + { + U_INTERNAL_ASSERT_EQUALS(bfirst_pass, false) + + setDirectiveItem(directive, U_CONSTANT_SIZE("lcode")); + + token = UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t")); + + (void) output0.reserve(20U + token.size()); + + output0.snprintf_add(U_CONSTANT_TO_PARAM("\n\t%v\n\t\n"), token.rep); + + (void) vcode.append(U_CONSTANT_TO_PARAM("\tif (UServer_Base::startParallelization()) { U_http_info.nResponseCode = HTTP_CONTINUE; return; }\n\t\n")); + +# ifdef USE_LOAD_BALANCE + (void) vcode.append(U_CONSTANT_TO_PARAM("\tif (UHTTP::manageRequestOnRemoteServer()) return;\n\t\n")); +# endif + } + else if (strncmp(directive, U_CONSTANT_TO_PARAM("code")) == 0) // generic code + { + U_INTERNAL_ASSERT_EQUALS(bfirst_pass, false) + + setDirectiveItem(directive, U_CONSTANT_SIZE("code")); + + token = UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t")); + + (void) output0.reserve(20U + token.size()); + + output0.snprintf_add(U_CONSTANT_TO_PARAM("\n\t%v\n\t\n"), token.rep); + } + else if (strncmp(directive, U_CONSTANT_TO_PARAM("number")) == 0) + { + U_INTERNAL_ASSERT_EQUALS(bfirst_pass, false) + + setDirectiveItem(directive, U_CONSTANT_SIZE("number")); + + (void) output0.reserve(100U + token.size()); + + output0.snprintf_add(U_CONSTANT_TO_PARAM("\n\tUStringExt::appendNumber32(*UClientImage_Base::wbuffer, (%v));\n\t"), token.rep); + } + else if (strncmp(directive, U_CONSTANT_TO_PARAM("puts")) == 0) + { + U_INTERNAL_ASSERT_EQUALS(bfirst_pass, false) + + setDirectiveItem(directive, U_CONSTANT_SIZE("puts")); + + (void) output0.reserve(100U + token.size()); + + output0.snprintf_add(U_CONSTANT_TO_PARAM("\n\t(void) UClientImage_Base::wbuffer->append((%v));\n\t"), token.rep); + } + else if (strncmp(directive, U_CONSTANT_TO_PARAM("xmlputs")) == 0) + { + U_INTERNAL_ASSERT_EQUALS(bfirst_pass, false) + + setDirectiveItem(directive, U_CONSTANT_SIZE("xmlputs")); + + (void) output0.reserve(100U + token.size()); + + output0.snprintf_add(U_CONSTANT_TO_PARAM("\n\tUSP_XML_PUTS((%v));\n\t"), token.rep); + } + else if (strncmp(directive, U_CONSTANT_TO_PARAM("cout")) == 0) + { + U_INTERNAL_ASSERT_EQUALS(bfirst_pass, false) + + bvar = true; + + setDirectiveItem(directive, U_CONSTANT_SIZE("cout")); + + (void) output0.reserve(200U + token.size()); + + output0.snprintf_add(U_CONSTANT_TO_PARAM("\n\tusp_sz = UObject2String((%v), usp_buffer, sizeof(usp_buffer));" + "\n\t(void) UClientImage_Base::wbuffer->append(usp_buffer, usp_sz);\n\t"), token.rep); + } + else if (strncmp(directive, U_CONSTANT_TO_PARAM("print")) == 0) + { + U_INTERNAL_ASSERT_EQUALS(bfirst_pass, false) + + bvar = true; + + bool bfor = (strncmp(directive + U_CONSTANT_SIZE("print"), U_CONSTANT_TO_PARAM("for")) == 0); + + setDirectiveItem(directive, (bfor ? U_CONSTANT_SIZE("printfor") : U_CONSTANT_SIZE("print"))); + + (void) output0.reserve(200U + token.size()); + + UVector vec(token, ';'); + + if (bfor) + { + U_ASSERT_EQUALS(vec.size(), 5) + + output0.snprintf_add(U_CONSTANT_TO_PARAM("\n\tfor (%v; %v; %v) { usp_sz = u__snprintf(usp_buffer, sizeof(usp_buffer), %v, %v);" + "(void) UClientImage_Base::wbuffer->append(usp_buffer, usp_sz); }\n\t"), + vec[0].rep, vec[1].rep, vec[2].rep, vec[3].rep, vec[4].rep); + } + else + { + U_ASSERT_EQUALS(vec.size(), 2) + + output0.snprintf_add(U_CONSTANT_TO_PARAM("\n\tusp_sz = u__snprintf(usp_buffer, sizeof(usp_buffer), %v, %v);" + "(void) UClientImage_Base::wbuffer->append(usp_buffer, usp_sz);\n\t"), vec[0].rep, vec[1].rep); + } + } + } + + void processUSP() + { + U_TRACE_NO_PARAM(5, "Application::processUSP()") + + // NB: Anything that is not enclosed in tags is assumed to be HTML + + bool bgroup; + const char* ptr; + uint32_t distance, pos, size; + +# ifdef DEBUG + token.clear(); // NB: to avoid DEAD OF SOURCE STRING WITH CHILD ALIVE... +# endif + + t.setData(usp); + +loop: distance = t.getDistance(); + + pos = U_STRING_FIND(usp, distance, " and + + bfirst_pass = true; + + processUSP(); + } + + bool execPreProcessing() + { + U_TRACE_NO_PARAM(5, "Application::execPreProcessing()") # ifndef DEBUG - bool bpreprocessing_failed = false; + bpreprocessing_failed = false; # endif if (U_STRING_FIND(usp, 0, "\n#ifdef DEBUG") != U_NOT_FOUND) @@ -117,503 +576,57 @@ public: bpreprocessing_failed = true; # endif - U_WARNING("Preprocessing %V failed", filename.rep); + U_RETURN(false); } } - const char* ptr; - uint32_t i, n, size; - UString token, declaration, http_header(U_CAPACITY), buffer(U_CAPACITY), bufname(100U), vcode(U_CAPACITY), output(U_CAPACITY), output1(U_CAPACITY), output2(U_CAPACITY); - bool bgroup, binit = false, bend = false, bsighup = false, bfork = false, bcomment = false, bvar = false, test_if_html = false, is_html = false, bsession = false, - bstorage = false; + U_RETURN(true); + } - // Anything that is not enclosed in tags is assumed to be HTML + void secondPass() + { + U_TRACE_NO_PARAM(5, "Application::secondPass()") + + bvar = + bsession = + bstorage = + bfirst_pass = + is_html = + test_if_html = false; + + processUSP(); + } + + void run(int argc, char* argv[], char* env[]) + { + U_TRACE(5, "Application::run(%d,%p,%p)", argc, argv, env) + + UApplication::run(argc, argv, env); + + if (argv[1] == U_NULLPTR) U_ERROR("filename usp not specified"); + + UString filename(argv[1]); + + usp = UFile::contentOf(filename); + + if (usp.empty()) U_ERROR("load of %V failed", filename.rep); - UTokenizer t(usp); t.setGroup(U_CONSTANT_TO_PARAM("")); - while (true) - { - uint32_t distance = t.getDistance(), - pos = U_STRING_FIND(usp, distance, " (comment) - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - */ - - if (strncmp(directive, U_CONSTANT_TO_PARAM("declaration")) == 0) - { - U_ASSERT(vcode.empty()) - U_ASSERT(declaration.empty()) // NB: must be at the beginning and uniq... - - n = token.size() - U_CONSTANT_SIZE("declaration") - 2; - - declaration = UStringExt::trim(directive + U_CONSTANT_SIZE("declaration"), n); - - binit = (U_STRING_FIND(declaration, 0, "static void usp_init_") != U_NOT_FOUND); // usp_init (Server-wide hooks)... - bend = (U_STRING_FIND(declaration, 0, "static void usp_end_") != U_NOT_FOUND); // usp_end - bsighup = (U_STRING_FIND(declaration, 0, "static void usp_sighup_") != U_NOT_FOUND); // usp_sighup - bfork = (U_STRING_FIND(declaration, 0, "static void usp_fork_") != U_NOT_FOUND); // usp_fork - - declaration = UStringExt::substitute(declaration, '\n', U_CONSTANT_TO_PARAM("\n\t")); - } - else if (strncmp(directive, U_CONSTANT_TO_PARAM("session")) == 0) - { - U_ASSERT(vcode.empty()) - - bsession = true; - - n = token.size() - U_CONSTANT_SIZE("session") - 2; - - token = UStringExt::trim(directive + U_CONSTANT_SIZE("session"), n); - - if (token.empty()) - { - (void) output.append( U_CONSTANT_TO_PARAM("\n\tif (UHTTP::getDataSession() == false) UHTTP::setSessionCookie();\n\t")); - (void) output1.append(U_CONSTANT_TO_PARAM("\n\tUHTTP::putDataSession();\n\t")); - } - else - { - UString tmp, name; - UVector vec(token, "\t\n;"); - - bvar = true; - - (void) output.append(U_CONSTANT_TO_PARAM("\n\t")); - (void) output.append(token); - (void) output.append(U_CONSTANT_TO_PARAM("\n\t\n")); - - for (i = 0, n = vec.size(); i < n; ++i) - { -# ifdef DEBUG - name.clear(); // NB: to avoid DEAD OF SOURCE STRING WITH CHILD ALIVE... -# endif - tmp = UStringExt::trim(vec[i]); - ptr = tmp.data(); - - do { ++ptr; } while (u__isspace(*ptr) == false); - do { ++ptr; } while (u__isspace(*ptr) == true); - - name = tmp.substr(tmp.distance(ptr)); - pos = name.find('('); - - size = (pos == U_NOT_FOUND ? name.size() : pos); - - buffer.snprintf(U_CONSTANT_TO_PARAM("\n\tUSP_SESSION_VAR_GET(%u,%.*s);\n\t"), i, size, ptr); - - (void) output.append(buffer); - - output1.snprintf_add(U_CONSTANT_TO_PARAM("\n\tUSP_SESSION_VAR_PUT(%u,%.*s);\n\t"), i, size, ptr); - } - } - } - else if (strncmp(directive, U_CONSTANT_TO_PARAM("storage")) == 0) - { - U_ASSERT(vcode.empty()) - - bstorage = true; - - n = token.size() - U_CONSTANT_SIZE("storage") - 2; - - token = UStringExt::trim(directive + U_CONSTANT_SIZE("storage"), n); - - if (token.empty()) - { - (void) output.append( U_CONSTANT_TO_PARAM("\n\t(void) UHTTP::getDataStorage();\n\t")); - (void) output1.append(U_CONSTANT_TO_PARAM("\n\tUHTTP::putDataStorage();\n\t")); - } - else - { - UString tmp, name; - UVector vec(token, "\t\n;"); - - bvar = true; - - (void) output.append(U_CONSTANT_TO_PARAM("\n\t")); - (void) output.append(token); - (void) output.append(U_CONSTANT_TO_PARAM("\n\t\n")); - - for (i = 0, n = vec.size(); i < n; ++i) - { -# ifdef DEBUG - name.clear(); // NB: to avoid DEAD OF SOURCE STRING WITH CHILD ALIVE... -# endif - tmp = UStringExt::trim(vec[i]); - ptr = tmp.data(); - - do { ++ptr; } while (u__isspace(*ptr) == false); - do { ++ptr; } while (u__isspace(*ptr) == true); - - name = tmp.substr(tmp.distance(ptr)); - pos = name.find('('); - - size = (pos == U_NOT_FOUND ? name.size() : pos); - - buffer.snprintf(U_CONSTANT_TO_PARAM("\n\tUSP_STORAGE_VAR_GET(%u,%.*s);\n\t"), i, size, ptr); - - (void) output.append(buffer); - - output1.snprintf_add(U_CONSTANT_TO_PARAM("\n\tUSP_STORAGE_VAR_PUT(%u,%.*s);\n\t"), i, size, ptr); - } - } - } - else if (strncmp(directive, U_CONSTANT_TO_PARAM("args")) == 0) - { - U_ASSERT(vcode.empty()) - - n = token.size() - U_CONSTANT_SIZE("args") - 2; - - token = UStringExt::trim(directive + U_CONSTANT_SIZE("args"), n); - - (void) output.append(U_CONSTANT_TO_PARAM("\t\n\t\tif (UHTTP::isGETorPOST()) (void) UHTTP::processForm();\n")); - - UString tmp, name; - UVector vec(token, "\t\n;"); - - (void) buffer.reserve(token.size() * 100U); - - for (i = 0, n = vec.size(); i < n; ++i) - { -# ifdef DEBUG - name.clear(); // NB: to avoid DEAD OF SOURCE STRING WITH CHILD ALIVE... -# endif - tmp = UStringExt::trim(vec[i]); - pos = tmp.find('('); - name = (pos == U_NOT_FOUND ? tmp : tmp.substr(0U, pos)); - - buffer.snprintf(U_CONSTANT_TO_PARAM("\n\tUString %v = USP_FORM_VALUE(%u);\n\t"), name.rep, i); - - if (pos != U_NOT_FOUND) - { - buffer.snprintf_add(U_CONSTANT_TO_PARAM("\n\tif (%v.empty()) %v = U_STRING_FROM_CONSTANT(%.*s);\n\t"), - name.rep, name.rep, tmp.size() - pos - 2, tmp.c_pointer(pos + 1)); - } - - (void) output.append(buffer); - } - } - else if (strncmp(directive, U_CONSTANT_TO_PARAM("cpath")) == 0) - { - U_ASSERT(vcode.empty()) - - n = token.size() - U_CONSTANT_SIZE("cpath") - 2; - - token = UStringExt::trim(directive + U_CONSTANT_SIZE("cpath"), n); - - UString tmp, name; - UVector vec(token, "\t\n;"); - - (void) buffer.reserve(token.size() * 100U); - - for (i = 0, n = vec.size(); i < n; ++i) - { -# ifdef DEBUG - name.clear(); // NB: to avoid DEAD OF SOURCE STRING WITH CHILD ALIVE... -# endif - tmp = UStringExt::trim(vec[i]); - pos = tmp.find('('); - name = (pos == U_NOT_FOUND ? tmp : tmp.substr(0U, pos)); - - buffer.snprintf(U_CONSTANT_TO_PARAM("\n\tUString %v = UHTTP::getPathComponent(%u);\n\t"), name.rep, i+1); - - if (pos != U_NOT_FOUND) - { - buffer.snprintf_add(U_CONSTANT_TO_PARAM("\n\tif (%v.empty()) %v = U_STRING_FROM_CONSTANT(%.*s);\n\t"), - name.rep, name.rep, tmp.size() - pos - 2, tmp.c_pointer(pos + 1)); - } - - (void) output.append(buffer); - } - } - else if (strncmp(directive, U_CONSTANT_TO_PARAM("header")) == 0) - { - U_ASSERT(vcode.empty()) - U_ASSERT(http_header.empty()) - - n = token.size() - U_CONSTANT_SIZE("header") - 2; - - http_header = UStringExt::trim(directive + U_CONSTANT_SIZE("header"), n); - } - else if (strncmp(directive, U_CONSTANT_TO_PARAM("code")) == 0) // generic code - { - n = token.size() - U_CONSTANT_SIZE("code") - 2; - - token = UStringExt::trim(directive + U_CONSTANT_SIZE("code"), n); - - (void) output.append(U_CONSTANT_TO_PARAM("\n\t")); - (void) output.append(UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t"))); - (void) output.append(U_CONSTANT_TO_PARAM("\n\t\n")); - } - else if (strncmp(directive, U_CONSTANT_TO_PARAM("vcode")) == 0) // validation code - { - U_ASSERT(vcode.empty()) // NB: must be before other code and uniq... - - n = token.size() - U_CONSTANT_SIZE("vcode") - 2; - - token = UStringExt::trim(directive + U_CONSTANT_SIZE("vcode"), n); - - (void) vcode.append(U_CONSTANT_TO_PARAM("\n\t")); - (void) vcode.append(UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t"))); - (void) vcode.append(U_CONSTANT_TO_PARAM("\n\t\n")); - } - else if (strncmp(directive, U_CONSTANT_TO_PARAM("pcode")) == 0) // parallelization code (long running task) - { - n = token.size() - U_CONSTANT_SIZE("pcode") - 2; - - token = UStringExt::trim(directive + U_CONSTANT_SIZE("pcode"), n); - - (void) output.append(U_CONSTANT_TO_PARAM("\n\t")); - (void) output.append(UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t"))); - (void) output.append(U_CONSTANT_TO_PARAM("\n\t\n")); - - (void) vcode.append(U_CONSTANT_TO_PARAM("\tif (UServer_Base::startParallelization()) { U_http_info.nResponseCode = HTTP_CONTINUE; return; }\n\t\n")); - } - else if (strncmp(directive, U_CONSTANT_TO_PARAM("lcode")) == 0) // load balance code - { - n = token.size() - U_CONSTANT_SIZE("lcode") - 2; - - token = UStringExt::trim(directive + U_CONSTANT_SIZE("lcode"), n); - - (void) output.append(U_CONSTANT_TO_PARAM("\n\t")); - (void) output.append(UStringExt::substitute(token, '\n', U_CONSTANT_TO_PARAM("\n\t"))); - (void) output.append(U_CONSTANT_TO_PARAM("\n\t\n")); - - (void) vcode.append(U_CONSTANT_TO_PARAM("\tif (UServer_Base::startParallelization()) { U_http_info.nResponseCode = HTTP_CONTINUE; return; }\n\t\n")); -# ifdef USE_LOAD_BALANCE - (void) vcode.append(U_CONSTANT_TO_PARAM("\tif (UHTTP::manageRequestOnRemoteServer()) return;\n\t\n")); -# endif - } - else if (strncmp(directive, U_CONSTANT_TO_PARAM("number")) == 0) - { - n = token.size() - U_CONSTANT_SIZE("number") - 2; - - token = UStringExt::trim(directive + U_CONSTANT_SIZE("number"), n); - - (void) buffer.reserve(token.size() + 100U); - - buffer.snprintf(U_CONSTANT_TO_PARAM("\n\tUStringExt::appendNumber32(*UClientImage_Base::wbuffer, (%v));\n\t"), token.rep); - - (void) output.append(buffer); - } - else if (strncmp(directive, U_CONSTANT_TO_PARAM("puts")) == 0) - { - n = token.size() - U_CONSTANT_SIZE("puts") - 2; - - token = UStringExt::trim(directive + U_CONSTANT_SIZE("puts"), n); - - (void) buffer.reserve(token.size() + 100U); - - buffer.snprintf(U_CONSTANT_TO_PARAM("\n\t(void) UClientImage_Base::wbuffer->append((%v));\n\t"), token.rep); - - (void) output.append(buffer); - } - else if (strncmp(directive, U_CONSTANT_TO_PARAM("xmlputs")) == 0) - { - n = token.size() - U_CONSTANT_SIZE("xmlputs") - 2; - - token = UStringExt::trim(directive + U_CONSTANT_SIZE("xmlputs"), n); - - buffer.snprintf(U_CONSTANT_TO_PARAM("\n\tUSP_XML_PUTS((%v));\n\t"), token.rep); - - (void) output.append(buffer); - } - else if (strncmp(directive, U_CONSTANT_TO_PARAM("print")) == 0) - { - bvar = true; - - bool bfor = (strncmp(directive + U_CONSTANT_SIZE("print"), U_CONSTANT_TO_PARAM("for")) == 0); - - if (bfor) - { - n = token.size() - U_CONSTANT_SIZE("printfor") - 2; - - token = UStringExt::trim(directive + U_CONSTANT_SIZE("printfor"), n); - } - else - { - n = token.size() - U_CONSTANT_SIZE("print") - 2; - - token = UStringExt::trim(directive + U_CONSTANT_SIZE("print"), n); - } - - UVector vec(token, ';'); - - (void) buffer.reserve(token.size() + 200U); - - if (bfor) - { - buffer.snprintf(U_CONSTANT_TO_PARAM("\n\tfor (%v; %v; %v) { usp_sz = u__snprintf(usp_buffer, sizeof(usp_buffer), %v, %v);" - "(void) UClientImage_Base::wbuffer->append(usp_buffer, usp_sz); }\n\t"), vec[0].rep, vec[1].rep, vec[2].rep, vec[3].rep, vec[4].rep); - } - else - { - buffer.snprintf(U_CONSTANT_TO_PARAM("\n\tusp_sz = u__snprintf(usp_buffer, sizeof(usp_buffer), %v, %v);" - "(void) UClientImage_Base::wbuffer->append(usp_buffer, usp_sz);\n\t"), vec[0].rep, vec[1].rep); - } - - (void) output.append(buffer); - } - else if (strncmp(directive, U_CONSTANT_TO_PARAM("cout")) == 0) - { - bvar = true; - - n = token.size() - U_CONSTANT_SIZE("cout") - 2; - - token = UStringExt::trim(directive + U_CONSTANT_SIZE("cout"), n); - - (void) buffer.reserve(token.size() + 200U); - - buffer.snprintf(U_CONSTANT_TO_PARAM("\n\tusp_sz = UObject2String((%v), usp_buffer, sizeof(usp_buffer));" - "\n\t(void) UClientImage_Base::wbuffer->append(usp_buffer, usp_sz);\n\t"), token.rep); - - (void) output.append(buffer); - } - - // no trailing \n... - - for (ptr = t.getPointer(); u__islterm(*ptr); ++ptr) {} - - t.setPointer(ptr); - } - - UString basename = UStringExt::basename(filename); - - ptr = basename.data(); - size = basename.size() - U_CONSTANT_SIZE(".usp"); - - bufname.snprintf(U_CONSTANT_TO_PARAM("%.*s.cpp"), size, ptr); - - if (binit == false && - (bsession || bstorage)) - { - binit = true; - - (void) buffer.reserve(500U); - - buffer.snprintf(U_CONSTANT_TO_PARAM(USP_SESSION_INIT), - size, ptr, - size, ptr, - (bsession ? "\n\tif (UHTTP::data_session == U_NULLPTR) U_NEW(UDataSession, UHTTP::data_session, UDataSession);\n\t" : ""), - (bstorage ? "\n\tif (UHTTP::data_storage == U_NULLPTR) { U_NEW(UDataSession, UHTTP::data_storage, UDataSession(*UString::str_storage_keyid)); }\n\t" : "")); - - (void) declaration.append(buffer); - } - - // NB: we check for HTML without HTTP headers... - - UString x(U_CAPACITY); - - if (http_header.empty()) - { - if (is_html) (void) x.append(U_CONSTANT_TO_PARAM("\n\tUHTTP::mime_index = U_html;\n\t")); - - (void) x.append(U_CONSTANT_TO_PARAM("\n\tU_http_info.endHeader = 0;\n")); - } - else - { - // NB: we use insert because the possibility of UHTTP::callService() (see chat.usp)... - - if (U_STRING_FIND(http_header, 0, "Content-Type") != U_NOT_FOUND) (void) output2.append(U_CONSTANT_TO_PARAM("\n\t\tU_http_content_type_len = 1;\n\t")); - - UString header = UStringExt::dos2unix(http_header, true); - - (void) header.append(U_CONSTANT_TO_PARAM("\r\n\r\n")); - - n = header.size(); - - U_INTERNAL_DUMP("n = %u", size) - - UString encoded(n * 4); - - UEscape::encode(header, encoded); - - U_ASSERT(encoded.isQuoted()) - - UString tmp(encoded.size() + 200U); - - tmp.snprintf(U_CONSTANT_TO_PARAM("\n\tU_INTERNAL_ASSERT_EQUALS(UClientImage_Base::wbuffer->findEndHeader(),false)" - "\n\tU_http_info.endHeader = %u;" - "\n\t(void) UClientImage_Base::wbuffer->insert(0, U_CONSTANT_TO_PARAM(%v));\n\t\n"), n, encoded.rep); - - (void) x.append(tmp); - } - - http_header = x; + bool binit, // usp_init (Server-wide hooks)... + bend, // usp_end + bsighup, // usp_sighup + bfork; // usp_fork char ptr1[100] = { '\0' }; char ptr2[100] = { '\0' }; @@ -621,20 +634,59 @@ public: char ptr4[100] = { '\0' }; char ptr5[100] = { '\0' }; const char* ptr6 = ""; - const char* ptr7 = (bcomment ? "\n\tUClientImage_Base::setRequestNoCache();\n\t\n" : ""); + const char* ptr7 = (u_get_unalignedp32(usp.data()) == U_MULTICHAR_CONSTANT32('<','!','-','-') && usp.c_char(4) == '#' && u__isspace(usp.c_char(5)) // (comment) + ? "\n\tUClientImage_Base::setRequestNoCache();\n\t\n" + : ""); - if (binit) (void) u__snprintf(ptr1, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_INIT) { usp_init_%.*s(); return; }\n\t"), size, ptr); - if (bsighup) (void) u__snprintf(ptr4, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_SIGHUP) { usp_sighup_%.*s(); return; }\n\t"), size, ptr); - if (bfork) (void) u__snprintf(ptr5, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_FORK) { usp_fork_%.*s(); return; }\n\t"), size, ptr); + UString basename = UStringExt::basename(filename); - if (bend) + uint32_t basename_sz = basename.size() - U_CONSTANT_SIZE(".usp"); + const char* basename_ptr = basename.data(); + + if (declaration) { -# ifndef DEBUG - if (bpreprocessing_failed) bend = false; - else -# endif - (void) u__snprintf(ptr3, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_DESTROY) { usp_end_%.*s(); return; }\n\t"), size, ptr); + binit = (U_STRING_FIND(declaration, 0, "static void usp_init_") != 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); + + if (bfork) (void) u__snprintf(ptr5, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_FORK) { usp_fork_%.*s(); return; }\n\t"), 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\t"), basename_sz, basename_ptr); + + if (bend) + { +# ifndef DEBUG + if (bpreprocessing_failed) bend = false; + else +# endif + (void) u__snprintf(ptr3, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_DESTROY) { usp_end_%.*s(); return; }\n\t"), basename_sz, basename_ptr); + } } + else + { + binit = + bend = + bsighup = + bfork = false; + } + + U_INTERNAL_DUMP("binit = %b bend = %b bsighup = %b bfork = %b", binit, bend, bsighup, bfork) + + if (binit == false && + (bsession || bstorage)) + { + binit = true; + + (void) declaration.reserve(500U); + + declaration.snprintf_add(U_CONSTANT_TO_PARAM(USP_SESSION_INIT), + basename_sz, basename_ptr, + basename_sz, basename_ptr, + (bsession ? "\n\tif (UHTTP::data_session == U_NULLPTR) U_NEW(UDataSession, UHTTP::data_session, UDataSession);\n\t" : ""), + (bstorage ? "\n\tif (UHTTP::data_storage == U_NULLPTR) { U_NEW(UDataSession, UHTTP::data_storage, UDataSession(*UString::str_storage_keyid)); }\n\t" : "")); + } + + if (binit) (void) u__snprintf(ptr1, 100, U_CONSTANT_TO_PARAM("\n\t\tif (param == U_DPAGE_INIT) { usp_init_%.*s(); return; }\n\t"), basename_sz, basename_ptr); if (binit == false || bend == false || @@ -645,16 +697,51 @@ public: : "\n\t\tif (param >= U_DPAGE_FORK) return;\n"); } - UString result(1024U + sizeof(USP_TEMPLATE) + declaration.size() + http_header.size() + output.size() + output1.size() + output2.size()); + // NB: we check for HTML without HTTP headers... + + UString output2; + + if (http_header.empty()) + { + if (is_html) (void) http_header.append(U_CONSTANT_TO_PARAM("\n\tUHTTP::mime_index = U_html;\n\t")); + + (void) http_header.append(U_CONSTANT_TO_PARAM("\n\tU_http_info.endHeader = 0;\n")); + } + else + { + // NB: we use insert because the possibility of UHTTP::callService() (see chat.usp)... + + if (U_STRING_FIND(http_header, 0, "Content-Type") != U_NOT_FOUND) (void) output2.assign(U_CONSTANT_TO_PARAM("\n\t\tU_http_content_type_len = 1;\n\t")); + + http_header = UStringExt::dos2unix(http_header, true); + + (void) http_header.append(U_CONSTANT_TO_PARAM("\r\n\r\n")); + + uint32_t n = http_header.size(); + + UString encoded(n * 4); + + UEscape::encode(http_header, encoded); + + U_ASSERT(encoded.isQuoted()) + + (void) http_header.reserve(200U + encoded.size()); + + (void) http_header.snprintf(U_CONSTANT_TO_PARAM("\n\tU_INTERNAL_ASSERT_EQUALS(UClientImage_Base::wbuffer->findEndHeader(),false)" + "\n\tU_http_info.endHeader = %u;" + "\n\t(void) UClientImage_Base::wbuffer->insert(0, U_CONSTANT_TO_PARAM(%v));\n\t\n"), n, encoded.rep); + } + + UString result(1024U + sizeof(USP_TEMPLATE) + declaration.size() + http_header.size() + output0.size() + output1.size() + output2.size()); result.snprintf(U_CONSTANT_TO_PARAM(USP_TEMPLATE), - size, ptr, - size, ptr, - size, ptr, + basename_sz, basename_ptr, + basename_sz, basename_ptr, + basename_sz, basename_ptr, declaration.rep, - size, ptr, - size, ptr, - size, ptr, + basename_sz, basename_ptr, + basename_sz, basename_ptr, + basename_sz, basename_ptr, bvar ? "\n\tuint32_t usp_sz = 0;" "\n\tchar usp_buffer[10 * 4096];\n" : "", @@ -666,15 +753,24 @@ public: ptr6, vcode.rep, http_header.rep, - output.rep, + output0.rep, output1.rep, output2.rep, ptr7); - (void) UFile::writeTo(bufname, UStringExt::removeEmptyLine(result)); + UString name(200U); + + name.snprintf(U_CONSTANT_TO_PARAM("%.*s.cpp"), basename_sz, basename_ptr); + + (void) UFile::writeTo(name, UStringExt::removeEmptyLine(result)); } private: + UTokenizer t; + UVector vdefine; + UString usp, token, output0, output1, declaration, vcode, http_header; + bool test_if_html, is_html, bpreprocessing_failed, bfirst_pass, bvar, bsession, bstorage; + U_DISALLOW_COPY_AND_ASSIGN(Application) }; diff --git a/src/ulib/net/server/server.cpp b/src/ulib/net/server/server.cpp index 03431ad1..0993a727 100644 --- a/src/ulib/net/server/server.cpp +++ b/src/ulib/net/server/server.cpp @@ -640,7 +640,7 @@ void UServer_Base::initThrottlingServer() UString pattern, number; UVector vec(*throttling_mask); - U_SRV_LOG("db initialization of BandWidthThrottling success: size(%u)", db_throttling->size()); + U_SRV_LOG("db BandWidthThrottling initialization success: size(%u)", db_throttling->size()); db_throttling->reset(); // Initialize the db to contain no entries @@ -1116,22 +1116,27 @@ public: if (*UServer_Base::ifname) { - srv_addr.psaIP4Addr.sin_family = PF_INET; + udp_sock._socket(); + udp_sock.setReuseAddress(); + + fd_sock = udp_sock.getFd(); + + srv_addr.psaIP4Addr.sin_port = htons(UServer_Base::port); + srv_addr.psaIP4Addr.sin_family = PF_INET; srv_addr.psaIP4Addr.sin_addr.s_addr = htonl(INADDR_ANY); - if (udp_sock.setServer(UServer_Base::port, &srv_addr) == false) U_ERROR("Can't bind on udp socket"); + if (U_SYSCALL(bind, "%d,%p,%d", fd_sock, &(srv_addr.psaGeneric), sizeof(uusockaddr))) U_ERROR("bind on udp socket failed"); if (UIPAddress::setBroadcastAddress(srv_addr, *UServer_Base::ifname) == false) { - U_ERROR("Can't get broadcast address on interface %V", UServer_Base::ifname->rep); + U_ERROR("set broadcast address on interface %V failed", UServer_Base::ifname->rep); } - if (udp_sock.setSockOpt(SOL_SOCKET, SO_BROADCAST, (const int[]){ 1 }) == false) U_ERROR("Can't enable SO_BROADCAST on udp socket"); + if (udp_sock.setSockOpt(SOL_SOCKET, SO_BROADCAST, (const int[]){ 1 }) == false) U_ERROR("setting SO_BROADCAST on udp socket failed"); udp_sock.setNonBlocking(); - addr = UServer_Base::socket->cLocalAddress.get_addr(); - fd_sock = udp_sock.getFd(); + addr = UServer_Base::socket->cLocalAddress.get_addr(); U_DUMP("addr = %V", UIPAddress::toString(addr).rep) @@ -1196,8 +1201,10 @@ public: if (iBytesTransferred == 1) { - if ((cli_addr.psaIP4Addr.sin_addr.s_addr == addr && ntohs(cli_addr.psaIP4Addr.sin_port) == UServer_Base::port) || - (UServer_Base::vallow_cluster && UIPAllow::isAllowed(cli_addr.psaIP4Addr.sin_addr.s_addr, *UServer_Base::vallow_cluster) == false)) + if (( cli_addr.psaIP4Addr.sin_addr.s_addr == addr && + ntohs(cli_addr.psaIP4Addr.sin_port) == UServer_Base::port) || + (UServer_Base::vallow_cluster && + UIPAllow::isAllowed(cli_addr.psaIP4Addr.sin_addr.s_addr, *UServer_Base::vallow_cluster) == false)) { continue; } @@ -1421,11 +1428,12 @@ UServer_Base::~UServer_Base() # endif # ifdef U_LINUX - U_INTERNAL_ASSERT_POINTER(u_pthread_time) + if (u_pthread_time) + { + delete (UTimeThread*)u_pthread_time; - delete (UTimeThread*)u_pthread_time; - - (void) pthread_rwlock_destroy(ULog::prwlock); + (void) pthread_rwlock_destroy(ULog::prwlock); + } # if defined(USE_LIBSSL) && !defined(OPENSSL_NO_OCSP) && defined(SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB) if (bssl) @@ -2621,11 +2629,9 @@ void UServer_Base::init() #ifdef USERVER_UDP if (budp) { - uusockaddr srv_addr; - U_ASSERT(socket->isUDP()) - if (socket->setServer(port, &srv_addr) == false) + if (socket->setServer(port, U_NULLPTR) == false) { U_ERROR("Run as server UDP with port '%u' failed", port); } @@ -2916,11 +2922,17 @@ next: U_INTERNAL_ASSERT_EQUALS(ULog::prwlock, U_NULLPTR) U_INTERNAL_ASSERT_EQUALS(u_pthread_time, U_NULLPTR) +# ifdef USERVER_UDP + if (budp == false || + UServer_Base::update_date) +# endif + { U_NEW_ULIB_OBJECT(UTimeThread, u_pthread_time, UTimeThread); (void) UThread::initRwLock((ULog::prwlock = &(ptr_shared_data->rwlock))); ((UTimeThread*)u_pthread_time)->start(50); + } #endif #if !defined(U_LOG_DISABLE) && defined(USE_LIBZ) @@ -3130,9 +3142,7 @@ void UServer_Base::sendSignalToAllChildren(int signo, sighandler_t handler) U_INTERNAL_ASSERT(proc->parent()) #if defined(U_LINUX) && defined(ENABLE_THREAD) - U_INTERNAL_ASSERT_POINTER(u_pthread_time) - - ((UTimeThread*)u_pthread_time)->suspend(); + if (u_pthread_time) ((UTimeThread*)u_pthread_time)->suspend(); # if defined(USE_LIBSSL) && !defined(OPENSSL_NO_OCSP) && defined(SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB) if (pthread_ocsp) pthread_ocsp->suspend(); @@ -3154,9 +3164,7 @@ void UServer_Base::sendSignalToAllChildren(int signo, sighandler_t handler) #endif #if defined(U_LINUX) && defined(ENABLE_THREAD) - U_INTERNAL_ASSERT_POINTER(u_pthread_time) - - ((UTimeThread*)u_pthread_time)->resume(); + if (u_pthread_time) ((UTimeThread*)u_pthread_time)->resume(); # if defined(USE_LIBSSL) && !defined(OPENSSL_NO_OCSP) && defined(SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB) if (pthread_ocsp) pthread_ocsp->resume(); @@ -3244,9 +3252,7 @@ RETSIGTYPE UServer_Base::handlerForSigTERM(int signo) if (proc->parent()) { # if defined(U_LINUX) && defined(ENABLE_THREAD) - U_INTERNAL_ASSERT_POINTER(u_pthread_time) - - ((UTimeThread*)u_pthread_time)->suspend(); + if (u_pthread_time) ((UTimeThread*)u_pthread_time)->suspend(); # endif // NB: we can't use UInterrupt::erase() because it restore the old action (UInterrupt::init)... @@ -4057,6 +4063,15 @@ void UServer_Base::runLoop(const char* user) while (flag_loop) { if (pClientImage->handlerRead() == U_NOTIFIER_DELETE) break; + +# ifndef U_LOG_DISABLE + if (isLog()) + { + pClientImage->logbuf->setEmpty(); + + log->log(U_CONSTANT_TO_PARAM("Waiting for connection on port %u"), port); + } +# endif } if (runDynamicPage_udp) diff --git a/src/ulib/net/socket.cpp b/src/ulib/net/socket.cpp index ca177ad7..b4fdccd8 100644 --- a/src/ulib/net/socket.cpp +++ b/src/ulib/net/socket.cpp @@ -182,12 +182,12 @@ bool USocket::checkTime(long time_limit, long& timeout) U_RETURN(true); } -void USocket::setLocalInfo(USocket* p, SocketAddress* cLocal) +void USocket::setLocalInfo(USocket* p, SocketAddress* pLocal) { - U_TRACE(0, "USocket::setLocalInfo(%p,%p)", p, cLocal) + U_TRACE(0, "USocket::setLocalInfo(%p,%p)", p, pLocal) - p->iLocalPort = cLocal->getPortNumber(); - cLocal->getIPAddress(p->cLocalAddress); + p->iLocalPort = pLocal->getPortNumber(); + pLocal->getIPAddress(p->cLocalAddress); } void USocket::setRemoteInfo(USocket* p, SocketAddress* cRemote) @@ -204,12 +204,12 @@ void USocket::setLocal() U_CHECK_MEMORY - SocketAddress cLocal; - socklen_t slDummy = cLocal.sizeOf(); + SocketAddress local; + socklen_t slDummy = local.sizeOf(); - if (U_SYSCALL(getsockname, "%d,%p,%p", getFd(), (sockaddr*)cLocal, &slDummy) == 0) + if (U_SYSCALL(getsockname, "%d,%p,%p", getFd(), (sockaddr*)local, &slDummy) == 0) { - setLocalInfo(this, &cLocal); + setLocalInfo(this, &local); U_socket_LocalSet(this) = true; } @@ -305,7 +305,7 @@ bool USocket::bind() int result, counter = 0; loop: - result = U_SYSCALL(bind, "%d,%p,%d", getFd(), (sockaddr*)&(cLocal->addr.psaGeneric), cLocal->sizeOf()); + result = U_SYSCALL(bind, "%d,%p,%d", getFd(), (sockaddr*)(*cLocal), cLocal->sizeOf()); if (result == -1 && errno == EADDRINUSE && @@ -416,25 +416,6 @@ bool USocket::setServer(unsigned int port, void* localAddress) } #endif - if (isUDP()) - { - U_INTERNAL_ASSERT_POINTER(localAddress) - - ((uusockaddr*)localAddress)->psaIP4Addr.sin_port = htons(port); - - if (U_SYSCALL(bind, "%d,%p,%d", iSockDesc, &(((uusockaddr*)localAddress)->psaGeneric), sizeof(uusockaddr)) == 0) - { - iLocalPort = - iRemotePort = port; - - U_socket_LocalSet(this) = true; - - U_RETURN(true); - } - - U_RETURN(false); - } - setReusePort(); U_INTERNAL_DUMP("cLocal = %p", cLocal) @@ -504,8 +485,7 @@ bool USocket::setServer(unsigned int port, void* localAddress) U_INTERNAL_DUMP("breuseport = %b", breuseport) if (breuseport || - (bind() && - U_SYSCALL(listen, "%d,%d", iSockDesc, iBackLog) == 0)) + (bind() && listen())) { U_RETURN(true); } @@ -526,7 +506,6 @@ void USocket::reusePort(int _flags) if (breuseport) { - U_ASSERT_EQUALS(isUDP(), false) U_ASSERT_EQUALS(isIPC(), false) int old = iSockDesc, @@ -547,7 +526,7 @@ void USocket::reusePort(int _flags) if (isClosed() || (setReuseAddress(), setReusePort(), cLocal->setIPAddressWildCard(U_socket_IPv6(this)), bind()) == false || - U_SYSCALL(listen, "%d,%d", iSockDesc, iBackLog) != 0) + listen() == false) { U_ERROR("SO_REUSEPORT failed, port %d", iLocalPort); } diff --git a/src/ulib/utility/http2.cpp b/src/ulib/utility/http2.cpp index 10762d36..81194276 100644 --- a/src/ulib/utility/http2.cpp +++ b/src/ulib/utility/http2.cpp @@ -2679,7 +2679,6 @@ void UHTTP2::handlerResponse() if (dyntbl->num_entries == 0) { # if defined(U_LINUX) && defined(ENABLE_THREAD) - U_INTERNAL_ASSERT_POINTER(u_pthread_time) U_INTERNAL_ASSERT_EQUALS(UClientImage_Base::iov_vec[1].iov_base, ULog::ptr_shared_date->date3) # else U_INTERNAL_ASSERT_EQUALS(UClientImage_Base::iov_vec[1].iov_base, ULog::date.date3) @@ -2709,7 +2708,6 @@ void UHTTP2::handlerResponse() char* ptr_date = entry->value->data(); # if defined(U_LINUX) && defined(ENABLE_THREAD) - U_INTERNAL_ASSERT_POINTER(u_pthread_time) U_INTERNAL_ASSERT_EQUALS(UClientImage_Base::iov_vec[1].iov_base, ULog::ptr_shared_date->date3) # else U_INTERNAL_ASSERT_EQUALS(UClientImage_Base::iov_vec[1].iov_base, ULog::date.date3) diff --git a/src/ulib/utility/string_ext.cpp b/src/ulib/utility/string_ext.cpp index 52106476..3b6eed46 100644 --- a/src/ulib/utility/string_ext.cpp +++ b/src/ulib/utility/string_ext.cpp @@ -223,47 +223,237 @@ UString UStringExt::substitute(const char* s, uint32_t n, const char* a, uint32_ { U_TRACE(1, "UStringExt::substitute(%.*S,%u,%.*S,%u,%.*S,%u)", n, s, n, n1, a, n1, n2, b, n2) + U_INTERNAL_ASSERT_MAJOR(n, 0) U_INTERNAL_ASSERT_MAJOR(n1, 0) - void* p; - uint32_t start = 0, len, capacity = (n / n1); + uint32_t capacity; + bool breserve = false; - if (capacity == 0) capacity = 22U; - if (n2) capacity *= n2; - if (capacity > (256U * 1024U * 1024U)) capacity = (256U * 1024U * 1024U); // worst case... - - UString x(capacity); - - while ((p = u_find(s + start, n - start, a, n1))) + if (n2 <= n1) capacity = n; + else { - uint32_t _end = (const char*)p - s; + capacity = n2*((n+n1)/n1); - len = (_end > start ? _end - start : 0); + if (capacity > (256U * 1024U * 1024U)) capacity = (breserve = true, (256U * 1024U * 1024U)); // worst case... + } - U_INTERNAL_DUMP("start = %u _end = %u len = %u", start, _end, len) + uint32_t len1; + const char* p1; + UString x(capacity); + char* p2 = x.data(); - (void) x.reserve(len + n2); + while ((p1 = (const char*)u_find(s, n, a, n1))) + { + len1 = (p1-s); - if (len) + U_INTERNAL_DUMP("len1 = %u", len1) + + if (breserve) { - U_MEMCPY(x.pend(), s + start, len); + uint32_t len2 = len1 + n2; - x.rep->_length += len; + x.rep->_length = x.distance(p2); + + if (x.space() < len2) + { + UString::_reserve(x, len2); + + p2 = x.pend(); + } } + if (len1) + { + U_MEMCPY(p2, s, len1); + p2 += len1; + + s = p1; + n -= len1; + } + + n -= n1; + s += n1; + if (n2) { - U_MEMCPY(x.pend(), b, n2); - - x.rep->_length += n2; + U_MEMCPY(p2, b, n2); + p2 += n2; } - - start = _end + n1; } - len = n - start; + x.rep->_length = x.distance(p2); - if (len) (void) x.append(s + start, len); + U_INTERNAL_DUMP("n = %u", n) + + if (n) + { + if (breserve && + x.space() < n) + { + UString::_reserve(x, n); + + p2 = x.pend(); + } + + U_MEMCPY(p2, s, n); + + x.rep->_length += n; + } + + U_INTERNAL_ASSERT(x.invariant()) + + U_RETURN_STRING(x); +} + +UString UStringExt::substitute(const char* s, uint32_t len, UVector& vec) +{ + U_TRACE(1, "UStringExt::substitute(%.*S,%u,%p)", len, s, len, &vec) + + U_INTERNAL_ASSERT_MAJOR(len, 0) + + uint32_t n = vec.size(); + + if (n == 2) return substitute(s, len, U_STRING_TO_PARAM(vec[0]), U_STRING_TO_PARAM(vec[1])); + + char c; + int32_t i; + UString item; + bool breserve = false, bdigit = false, bspace = false; + uint32_t n1 = 0, n2 = 0, capacity, mask_lower = 0, mask_upper = 0; + + uint32_t maskFirstChar[] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, + 0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200, + 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000, + 0x00008000, 0x00010000, 0x00020000, 0x00040000, 0x00080000, + 0x00100000, 0x00200000, 0x00400000, 0x00800000, 0x01000000, + 0x02000000 }; + + for (i = 0; i < (int32_t)n; i += 2) + { + item = vec[i]; + + n1 += item.size(); + n2 += vec[i+1].size(); + + c = item.first_char(); + + if (u__islower(c)) mask_lower |= maskFirstChar[c-'a']; + else if (u__isupper(c)) mask_upper |= maskFirstChar[c-'A']; + else if (u__isdigit(c)) bdigit = true; + else if (u__isspace(c)) bspace = true; + } + + U_INTERNAL_DUMP("n1 = %u n2 = %u mask_lower = %B mask_upper = %B bdigit = %b bspace = %b", n1, n2, mask_lower, mask_upper, bdigit, bspace) + + if (n2 <= n1) capacity = len; + else + { + capacity = n2*((len+n1)/n1); + + if (capacity > (256U * 1024U * 1024U)) capacity = (breserve = true, (256U * 1024U * 1024U)); // worst case... + } + + uint32_t len1; + const char* p1; + UString x(capacity); + char* p2 = x.data(); + const char* end = s + len; + +loop: + for (p1 = s; p1 < end; ++p1) + { + c = *p1; + + if ((u__islower(c) && + (mask_lower & maskFirstChar[c-'a']) == 0) || + (u__isupper(c) && + (mask_upper & maskFirstChar[c-'A']) == 0) || + (u__isdigit(c) && + bdigit == false) || + (u__isspace(c) && + bspace == false)) + { + continue; + } + + for (i = 0; i < (int32_t)n; i += 2) + { + item = vec[i]; + + if (memcmp(p1, U_STRING_TO_PARAM(item)) == 0) + { + n1 = item.size(); + n2 = (item = vec[i+1]).size(); + + U_INTERNAL_DUMP("n1 = %u item(%u) = %V", n1, n2, item.rep) + + goto found; + } + } + } + + if (p1 < end) + { +found: + len1 = (p1-s); + + U_INTERNAL_DUMP("len1 = %u", len1) + + if (breserve) + { + uint32_t len2 = len1 + n2; + + x.rep->_length = x.distance(p2); + + if (x.space() < len2) + { + UString::_reserve(x, len2); + + p2 = x.pend(); + } + } + + if (len1) + { + U_MEMCPY(p2, s, len1); + p2 += len1; + + s = p1; + len -= len1; + } + + len -= n1; + s += n1; + + if (n2) + { + U_MEMCPY(p2, item.data(), n2); + p2 += n2; + } + + goto loop; + } + + x.rep->_length = x.distance(p2); + + U_INTERNAL_DUMP("len = %u", len) + + if (len) + { + if (breserve && + x.space() < len) + { + UString::_reserve(x, len); + + p2 = x.pend(); + } + + U_MEMCPY(p2, s, len); + + x.rep->_length += len; + } + + U_INTERNAL_ASSERT(x.invariant()) U_RETURN_STRING(x); } diff --git a/src/ulib/utility/uhttp.cpp b/src/ulib/utility/uhttp.cpp index 39a96b25..7360dda4 100644 --- a/src/ulib/utility/uhttp.cpp +++ b/src/ulib/utility/uhttp.cpp @@ -5537,14 +5537,14 @@ void UHTTP::initSession() if (db_session->open(8 * U_1M, false, true, true, U_SRV_LOCK_DATA_SESSION)) // NB: we don't want truncate (we have only the journal)... { - U_SRV_LOG("db initialization of HTTP session success"); + U_SRV_LOG("db HTTP session initialization success"); if (data_session) db_session->setPointerToDataStorage(data_session); else if (data_storage) db_session->setPointerToDataStorage(data_storage); } else { - U_SRV_LOG("WARNING: db initialization of HTTP session failed"); + U_SRV_LOG("WARNING: db HTTP session initialization failed"); delete db_session; db_session = U_NULLPTR; @@ -5580,7 +5580,7 @@ void UHTTP::initSessionSSL() if (db_session_ssl->open(8 * U_1M, false, true, true, U_SRV_LOCK_SSL_SESSION)) // NB: we don't want truncate (we have only the journal)... { - U_SRV_LOG("db initialization of SSL session success"); + U_SRV_LOG("db SSL session initialization success"); db_session_ssl->reset(); // Initialize the cache to contain no entries @@ -5623,7 +5623,7 @@ void UHTTP::initSessionSSL() } else { - U_SRV_LOG("WARNING: db initialization of SSL session failed"); + U_SRV_LOG("WARNING: db SSL session initialization failed"); delete db_session_ssl; db_session_ssl = U_NULLPTR; @@ -6612,6 +6612,8 @@ void UHTTP::handlerResponse() { UClientImage_Base::setHeaderForResponse(6+29+2+12+2); // Date: Wed, 20 Jun 2012 11:43:17 GMT\r\nServer: ULib\r\n + setStatusDescription(); + // NB: all other responses must include an entity body or a Content-Length header field defined with a value of zero (0) char* ptr; @@ -6619,32 +6621,7 @@ void UHTTP::handlerResponse() const char* ptr2; uint32_t sz1 = set_cookie->size(), sz2 = ext->size(); - if (sz2) ptr2 = ext->data(); - else - { - ptr2 = "Content-Length: 0\r\n\r\n"; - sz2 = U_CONSTANT_SIZE("Content-Length: 0\r\n\r\n"); - - if (U_http_info.nResponseCode == HTTP_OK) - { - if (isGETorHEAD()) U_http_info.nResponseCode = HTTP_NO_CONTENT; - - // A server implements an HSTS policy by supplying a header over an HTTPS connection (HSTS headers over HTTP are ignored) - -# if defined(USE_LIBSSL) && defined(U_HTTP_STRICT_TRANSPORT_SECURITY) - if (UServer_Base::bssl && - uri_strict_transport_security_mask == (void*)1L) - { - ptr2 = "Strict-Transport-Security: max-age=31536000; includeSubDomains; preload\r\nContent-Length: 0\r\n\r\n"; - sz2 = U_CONSTANT_SIZE("Strict-Transport-Security: max-age=31536000; includeSubDomains; preload\r\nContent-Length: 0\r\n\r\n"); - } -# endif - } - } - - setStatusDescription(); - - UClientImage_Base::wbuffer->setBuffer(200U + sz1 + sz2); + UClientImage_Base::wbuffer->setBuffer(300U + sz1 + sz2); ptr = base = UClientImage_Base::wbuffer->data(); @@ -6718,9 +6695,53 @@ void UHTTP::handlerResponse() } } + sz1 = ptr-base; + + U_INTERNAL_DUMP("sz1 = %u", sz1) + + if (sz2) + { + U_INTERNAL_DUMP("ext(%u) = %V", sz2, ext->rep) + + // U_INTERNAL_ASSERT(u_endsWith(U_STRING_TO_PARAM(*ext), U_CONSTANT_TO_PARAM(U_CRLF2))) + + if (sz1 == 0) + { + UClientImage_Base::wbuffer->swap(*ext); + + 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) + + return; + } + + ptr2 = ext->data(); + } + else + { + ptr2 = "Content-Length: 0\r\n\r\n"; + sz2 = U_CONSTANT_SIZE("Content-Length: 0\r\n\r\n"); + + if (U_http_info.nResponseCode == HTTP_OK) + { + if (isGETorHEAD()) U_http_info.nResponseCode = HTTP_NO_CONTENT; + + // A server implements an HSTS policy by supplying a header over an HTTPS connection (HSTS headers over HTTP are ignored) + +# if defined(USE_LIBSSL) && defined(U_HTTP_STRICT_TRANSPORT_SECURITY) + if (UServer_Base::bssl && + uri_strict_transport_security_mask == (void*)1L) + { + ptr2 = "Strict-Transport-Security: max-age=31536000; includeSubDomains; preload\r\nContent-Length: 0\r\n\r\n"; + sz2 = U_CONSTANT_SIZE("Strict-Transport-Security: max-age=31536000; includeSubDomains; preload\r\nContent-Length: 0\r\n\r\n"); + } +# endif + } + } + U_MEMCPY(ptr, ptr2, sz2); - UClientImage_Base::wbuffer->size_adjust((ptr - base) + sz2); + UClientImage_Base::wbuffer->size_adjust(sz1 + sz2); } U_INTERNAL_DUMP("UClientImage_Base::wbuffer(%u) = %#V", UClientImage_Base::wbuffer->size(), UClientImage_Base::wbuffer->rep) @@ -7194,12 +7215,7 @@ next: ptr = u_num2str32(clength, ptr + U_CONSTANT_SIZE("Content-Length: ")); - if (pEndHeader == U_NULLPTR) - { - u_put_unalignedp32(ptr, U_MULTICHAR_CONSTANT32('\r','\n','\r','\n')); - ptr += U_CONSTANT_SIZE(U_CRLF2); - } - else + if (pEndHeader) { u_put_unalignedp16(ptr, U_MULTICHAR_CONSTANT16('\r','\n')); ptr += U_CONSTANT_SIZE(U_CRLF); @@ -7209,6 +7225,11 @@ next: U_MEMCPY(ptr, pEndHeader, U_http_info.endHeader); ptr += U_http_info.endHeader; } + else + { + u_put_unalignedp32(ptr, U_MULTICHAR_CONSTANT32('\r','\n','\r','\n')); + ptr += U_CONSTANT_SIZE(U_CRLF2); + } ext->size_adjust(ptr); @@ -8113,7 +8134,9 @@ U_NO_EXPORT void UHTTP::putDataInCache(const UString& fmt, UString& content) U_INTERNAL_ASSERT_EQUALS(file_data->size, content.size()) +#ifndef U_LOG_DISABLE uint32_t ratio1 = 100, ratio2 = 100; +#endif if (u_is_img(mime_index)) { @@ -8214,7 +8237,9 @@ next: if (content1) { +# ifndef U_LOG_DISABLE ratio1 = UStringExt::ratio; +# endif setDataInCache(fmt, content1, U_CONSTANT_TO_PARAM("Content-Encoding: gzip\r\n")); } @@ -8225,7 +8250,9 @@ next: if (content2) { +# ifndef U_LOG_DISABLE ratio2 = UStringExt::ratio; +# endif checkArrayCompressData(file_data); @@ -11155,7 +11182,11 @@ U_NO_EXPORT bool UHTTP::UServletPage::load() // NB: dlopen() fail if the module name is not prefixed with "./"... char buffer[U_PATH_MAX]; +#ifndef U_LOG_DISABLE uint32_t sz = u__snprintf(buffer, sizeof(buffer), U_CONSTANT_TO_PARAM("./%v.%s"), path.rep, U_LIB_SUFFIX); +#else + (void) u__snprintf(buffer, sizeof(buffer), U_CONSTANT_TO_PARAM("./%v.%s"), path.rep, U_LIB_SUFFIX); +#endif if (UDynamic::load(buffer) == false) { @@ -11385,8 +11416,6 @@ next: if (*ptr1 == '?') setDynamicResponse(); - ext->clear(); - (void) UServer_Base::pClientImage->writeResponse(); U_RETURN(true); diff --git a/tests/examples/udp_server.sh b/tests/examples/udp_server.sh index 654299ce..84211adf 100755 --- a/tests/examples/udp_server.sh +++ b/tests/examples/udp_server.sh @@ -22,7 +22,7 @@ cat <inp/webserver.cfg userver { PORT 8080 RUN_AS_USER nobody - LOG_FILE /tmp/userver_udp.log +#LOG_FILE /tmp/userver_udp.log LOG_FILE_SZ 10M PID_FILE /var/run/userver_udp.pid PREFORK_CHILD 0 diff --git a/tests/ulib/test_socket.cpp b/tests/ulib/test_socket.cpp index 4d553100..52387527 100644 --- a/tests/ulib/test_socket.cpp +++ b/tests/ulib/test_socket.cpp @@ -263,7 +263,6 @@ static void UDPEchoServer(unsigned int iPortNumber, bool bIPv6) { U_TRACE(5, "::UDPEchoServer(%u,%b)", iPortNumber, bIPv6) - uusockaddr addr; char pcBuffer[65535]; UIPAddress cIPSource; int iBytesTransferred; @@ -271,12 +270,7 @@ static void UDPEchoServer(unsigned int iPortNumber, bool bIPv6) UUDPSocket cServerSocket(bIPv6); - (void) memset(&addr, 0, sizeof(addr)); - - addr.psaIP4Addr.sin_family = PF_INET; - addr.psaIP4Addr.sin_addr.s_addr = htonl(INADDR_ANY); - - cServerSocket.setServer(iPortNumber, &addr); + cServerSocket.setServer(iPortNumber, U_NULLPTR); cServerSocket.reusePort(O_RDWR | O_CLOEXEC); cServerSocket.setLocal(); diff --git a/tests/ulib/test_string.cpp b/tests/ulib/test_string.cpp index 6fdde6b0..f9b14d59 100644 --- a/tests/ulib/test_string.cpp +++ b/tests/ulib/test_string.cpp @@ -1956,6 +1956,36 @@ U_EXPORT main(int argc, char* argv[]) U_ASSERT( z == "############################################################################################################################ellllo") + y = U_STRING_FROM_CONSTANT(" uno due tre quattro cinque \n" + " uno due tre quattro cinque \n" + " uno due tre quattro cinque \n" + " uno due tre quattro cinque \n" + " uno due tre quattro cinque \n"); + + z = UStringExt::substitute(y, U_CONSTANT_TO_PARAM("uno"), U_CONSTANT_TO_PARAM("primo")); + + U_ASSERT( z == " primo due tre quattro cinque \n" + " primo due tre quattro cinque \n" + " primo due tre quattro cinque \n" + " primo due tre quattro cinque \n" + " primo due tre quattro cinque \n") + + z = U_STRING_FROM_CONSTANT("uno primo due secondo tre terzo quattro quarto cinque quinto"); + + vec.clear(); + + (void) vec.split(z); + + y = UStringExt::substitute(y, vec); + + vec.clear(); + + U_ASSERT( y == " primo secondo terzo quarto quinto \n" + " primo secondo terzo quarto quinto \n" + " primo secondo terzo quarto quinto \n" + " primo secondo terzo quarto quinto \n" + " primo secondo terzo quarto quinto \n") + y = U_STRING_FROM_CONSTANT("Hello\n\n"); z = UStringExt::dos2unix(y, true);