From e3df0c5f60da9922c939649f0149f36c3c14e3c6 Mon Sep 17 00:00:00 2001 From: George Wang Date: Tue, 5 Nov 2013 16:14:49 -0500 Subject: [PATCH] Update LiteSpeed SAPI code to V6.4 Conflicts: sapi/litespeed/lsapi_main.c sapi/litespeed/lsapidef.h sapi/litespeed/lsapilib.c sapi/litespeed/lsapilib.h --- sapi/litespeed/lsapi_main.c | 132 +- sapi/litespeed/lsapidef.h | 8 +- sapi/litespeed/lsapilib.c | 2459 ++++++++++++++++++++++++++--------- sapi/litespeed/lsapilib.h | 77 +- 4 files changed, 2007 insertions(+), 669 deletions(-) diff --git a/sapi/litespeed/lsapi_main.c b/sapi/litespeed/lsapi_main.c index 84e870d628..bc236bafab 100644 --- a/sapi/litespeed/lsapi_main.c +++ b/sapi/litespeed/lsapi_main.c @@ -16,8 +16,6 @@ +----------------------------------------------------------------------+ */ -/* $Id$ */ - #include "php.h" #include "SAPI.h" #include "php_main.h" @@ -75,6 +73,7 @@ static int lsapi_mode = 1; static char *php_self = ""; static char *script_filename = ""; static int source_highlight = 0; +static int ignore_php_ini = 0; static char * argv0 = NULL; static int engine = 1; #ifdef ZTS @@ -289,7 +288,7 @@ static void sapi_lsapi_register_variables(zval *track_vars_array TSRMLS_DC) static int sapi_lsapi_read_post(char *buffer, uint count_bytes TSRMLS_DC) { if ( lsapi_mode ) { - return LSAPI_ReadReqBody( buffer, count_bytes ); + return LSAPI_ReadReqBody( buffer, (unsigned long long)count_bytes ); } else { return 0; } @@ -353,7 +352,14 @@ static int sapi_lsapi_send_headers(sapi_headers_struct *sapi_headers TSRMLS_DC) */ static void sapi_lsapi_log_message(char *message TSRMLS_DC) { + char buf[8192]; int len = strlen( message ); + if ( *(message + len - 1 ) != '\n' ) + { + snprintf( buf, 8191, "%s\n", message ); + message = buf; + ++len; + } LSAPI_Write_Stderr( message, len); } /* }}} */ @@ -364,7 +370,7 @@ static void sapi_lsapi_log_message(char *message TSRMLS_DC) static sapi_module_struct lsapi_sapi_module = { "litespeed", - "LiteSpeed V5.5", + "LiteSpeed V6.4", php_lsapi_startup, /* startup */ php_module_shutdown_wrapper, /* shutdown */ @@ -520,7 +526,7 @@ static int lsapi_module_main(int show_source TSRMLS_DC) } zend_try { php_request_shutdown(NULL); - *argv0 = 0; + memset( argv0, 0, 46 ); } zend_end_try(); return 0; } @@ -558,10 +564,12 @@ static void override_ini() } + static int processReq( TSRMLS_D ) { int ret = 0; zend_first_try { + /* avoid server_context==NULL checks */ SG(server_context) = (void *) 1; @@ -587,14 +595,16 @@ static void cli_usage( TSRMLS_D ) { static const char * usage = "Usage: php\n" - " php -[b|c|h|i|q|s|v|?] [] [args...]\n" + " php -[b|c|n|h|i|q|s|v|?] [] [args...]\n" " Run in LSAPI mode, only '-b', '-s' and '-c' are effective\n" " Run in Command Line Interpreter mode when parameters are specified\n" "\n" " -b | Bind Path for external LSAPI Server mode\n" " -c | Look for php.ini file in this directory\n" + " -n No php.ini file will be used\n" " -h This help\n" " -i PHP information\n" + " -l Syntax check\n" " -q Quiet-mode. Suppress HTTP Header output.\n" " -s Display colour syntax highlighted source.\n" " -v Version number\n" @@ -626,7 +636,7 @@ static int parse_opt( int argc, char * argv[], int *climode, fprintf( stderr, "TCP or socket address must be specified following '-b' option.\n"); return -1; } - *php_bind = *p++; + *php_bind = strdup(*p++); break; case 'c': @@ -635,16 +645,22 @@ static int parse_opt( int argc, char * argv[], int *climode, return -1; } - *php_ini_path = *p++; + *php_ini_path = strdup( *p++ ); break; case 's': source_highlight = 1; - break; + break; + case 'n': + ignore_php_ini = 1; + break; + case '?': + if ( *((*(p-1))+2) == 's' ) + exit( 99 ); case 'h': case 'i': + case 'l': case 'q': case 'v': - case '?': default: *climode = 1; break; @@ -674,7 +690,7 @@ static int cli_main( int argc, char * argv[] ) const char ** ini; char ** p = &argv[1]; char ** argend= &argv[argc]; - int ret = 0; + int ret = -1; int c; lsapi_mode = 0; /* enter CLI mode */ @@ -713,8 +729,8 @@ static int cli_main( int argc, char * argv[] ) php_end_ob_buffers(1 TSRMLS_CC); #endif php_request_shutdown( NULL ); + ret = 0; } - ret = 1; break; case 'v': if (php_request_startup(TSRMLS_C) != FAILURE) { @@ -729,25 +745,27 @@ static int cli_main( int argc, char * argv[] ) php_end_ob_buffers(1 TSRMLS_CC); #endif php_request_shutdown( NULL ); + ret = 0; } - ret = 1; break; case 'c': ++p; /* fall through */ case 's': break; - + case 'l': + source_highlight = 2; + break; case 'h': case '?': default: cli_usage(TSRMLS_C); - ret = 1; + ret = 0; break; } } - if ( !ret ) { + if ( ret == -1 ) { if ( *p ) { zend_file_handle file_handle = {0}; @@ -766,18 +784,30 @@ static int cli_main( int argc, char * argv[] ) fclose( file_handle.handle.fp ); ret = 2; } else { - if (source_highlight) { + if (source_highlight == 1) { zend_syntax_highlighter_ini syntax_highlighter_ini; php_get_highlight_struct(&syntax_highlighter_ini); highlight_file(SG(request_info).path_translated, &syntax_highlighter_ini TSRMLS_CC); + } else if (source_highlight == 2) { + file_handle.filename = *p; + file_handle.free_filename = 0; + file_handle.opened_path = NULL; + ret = php_lint_script(&file_handle TSRMLS_CC); + if (ret==SUCCESS) { + zend_printf("No syntax errors detected in %s\n", file_handle.filename); + } else { + zend_printf("Errors parsing %s\n", file_handle.filename); + } + } else { file_handle.filename = *p; file_handle.free_filename = 0; file_handle.opened_path = NULL; php_execute_script(&file_handle TSRMLS_CC); - } + ret = EG(exit_status); + } php_request_shutdown( NULL ); } @@ -858,7 +888,25 @@ void start_children( int children ) exit( 0 ); } - +void setArgv0( int argc, char * argv[] ) +{ + char * p; + int i; + argv0 = argv[0] + strlen( argv[0] ); + p = argv0; + while(( p > argv[0] )&&( p[-1] != '/')) + --p; + if ( p > argv[0] ) + { + memmove( argv[0], p, argv0 - p ); + memset( argv[0] + ( argv0 - p ), 0, p - argv[0] ); + argv0 = argv[0] + (argv0 - p); + } + for( i = 1; i < argc; ++i ) + { + memset( argv[i], 0, strlen( argv[i] ) ); + } +} #include int main( int argc, char * argv[] ) @@ -868,7 +916,6 @@ int main( int argc, char * argv[] ) char * php_ini_path = NULL; char * php_bind = NULL; - char * p; int n; int climode = 0; struct timeval tv_req_begin; @@ -894,8 +941,10 @@ int main( int argc, char * argv[] ) } if ( climode ) { lsapi_sapi_module.phpinfo_as_text = 1; + } else { + setArgv0(argc, argv ); } - argv0 = argv[0] + strlen( argv[0] ); + sapi_startup(&lsapi_sapi_module); #ifdef ZTS @@ -909,6 +958,9 @@ int main( int argc, char * argv[] ) #endif lsapi_sapi_module.executable_location = argv[0]; + + if ( ignore_php_ini ) + lsapi_sapi_module.php_ini_ignore = 1; if ( php_ini_path ) { lsapi_sapi_module.php_ini_path_override = php_ini_path; @@ -949,6 +1001,8 @@ int main( int argc, char * argv[] ) if ( php_bind ) { LSAPI_No_Check_ppid(); + free( php_bind ); + php_bind = NULL; } while( LSAPI_Prefork_Accept_r( &g_req ) >= 0 ) { @@ -986,27 +1040,23 @@ int main( int argc, char * argv[] ) /* LiteSpeed PHP module starts here */ -#if PHP_MAJOR_VERSION > 4 - /* {{{ arginfo */ ZEND_BEGIN_ARG_INFO(arginfo_litespeed__void, 0) ZEND_END_ARG_INFO() /* }}} */ -#else -#define arginfo_litespeed__void NULL -#endif - PHP_FUNCTION(litespeed_request_headers); PHP_FUNCTION(litespeed_response_headers); +PHP_FUNCTION(apache_get_modules); PHP_MINFO_FUNCTION(litespeed); zend_function_entry litespeed_functions[] = { - PHP_FE(litespeed_request_headers, arginfo_litespeed__void) - PHP_FE(litespeed_response_headers, arginfo_litespeed__void) - PHP_FALIAS(getallheaders, litespeed_request_headers, arginfo_litespeed__void) - PHP_FALIAS(apache_request_headers, litespeed_request_headers, arginfo_litespeed__void) + PHP_FE(litespeed_request_headers, arginfo_litespeed__void) + PHP_FE(litespeed_response_headers, arginfo_litespeed__void) + PHP_FE(apache_get_modules, arginfo_litespeed__void) + PHP_FALIAS(getallheaders, litespeed_request_headers, arginfo_litespeed__void) + PHP_FALIAS(apache_request_headers, litespeed_request_headers, arginfo_litespeed__void) PHP_FALIAS(apache_response_headers, litespeed_response_headers, arginfo_litespeed__void) {NULL, NULL, NULL} }; @@ -1055,8 +1105,7 @@ PHP_FUNCTION(litespeed_request_headers) } array_init(return_value); - if ( lsapi_mode ) - LSAPI_ForeachOrgHeader( add_associate_array, return_value ); + LSAPI_ForeachOrgHeader( add_associate_array, return_value ); } /* }}} */ @@ -1106,6 +1155,23 @@ PHP_FUNCTION(litespeed_response_headers) /* }}} */ +/* {{{ proto array apache_get_modules(void) + Fetch all loaded module names */ +PHP_FUNCTION(apache_get_modules) +{ + /* TODO: */ + if (ZEND_NUM_ARGS() > 0) { + WRONG_PARAM_COUNT; + } + array_init(return_value); + add_next_index_string(return_value, "mod_rewrite", 1); + add_next_index_string(return_value, "mod_mime", 1); + add_next_index_string(return_value, "mod_headers", 1); + add_next_index_string(return_value, "mod_expires", 1); +} +/* }}} */ + + /* * Local variables: * tab-width: 4 diff --git a/sapi/litespeed/lsapidef.h b/sapi/litespeed/lsapidef.h index 3bdadac1d1..fb75d01a17 100644 --- a/sapi/litespeed/lsapidef.h +++ b/sapi/litespeed/lsapidef.h @@ -1,4 +1,3 @@ - /* +----------------------------------------------------------------------+ | PHP Version 5 | @@ -17,9 +16,8 @@ +----------------------------------------------------------------------+ */ - /* -Copyright (c) 2007, Lite Speed Technologies Inc. +Copyright (c) 2002-2014, Lite Speed Technologies Inc. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -113,12 +111,14 @@ enum #define LSAPI_RESP_END 5 #define LSAPI_STDERR_STREAM 6 #define LSAPI_REQ_RECEIVED 7 +#define LSAPI_CONN_CLOSE 8 +#define LSAPI_INTERNAL_ERROR 9 #define LSAPI_MAX_HEADER_LEN 65535 #define LSAPI_MAX_DATA_PACKET_LEN 16384 -#define LSAPI_RESP_HTTP_HEADER_MAX 4096 +#define LSAPI_RESP_HTTP_HEADER_MAX 32768 #define LSAPI_PACKET_HEADER_LEN 8 diff --git a/sapi/litespeed/lsapilib.c b/sapi/litespeed/lsapilib.c index 1bb16b3268..8a10ac62cd 100644 --- a/sapi/litespeed/lsapilib.c +++ b/sapi/litespeed/lsapilib.c @@ -16,10 +16,8 @@ +----------------------------------------------------------------------+ */ -/* $Id$ */ - /* -Copyright (c) 2007, Lite Speed Technologies Inc. +Copyright (c) 2002-2014, Lite Speed Technologies Inc. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -50,17 +48,21 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +/*************************************************************************** + lsapilib.c - description + ------------------- + begin : Mon Feb 21 2005 + copyright : (C) 2005 by George Wang + email : gwang@litespeedtech.com + ***************************************************************************/ + #include +#include #include #include -#include -#include -#include -#include -#include +#include #include #include #include @@ -71,8 +73,48 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include +#include #include #include +#include +#include +#include +#include +#include + +#include "lsapilib.h" + +#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) +#include +#endif + +#if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \ + || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) +#include +#endif + +#include +#ifndef uint32 +#define uint32 uint32_t +#endif + +struct lsapi_MD5Context { + uint32 buf[4]; + uint32 bits[2]; + unsigned char in[64]; +}; + +void lsapi_MD5Init(struct lsapi_MD5Context *context); +void lsapi_MD5Update(struct lsapi_MD5Context *context, unsigned char const *buf, + unsigned len); +void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *context); + +/* + * This is needed to make RSAREF happy on some MS-DOS compilers. + */ +typedef struct lsapi_MD5Context lsapi_MD5_CTX; + #define LSAPI_ST_REQ_HEADER 1 #define LSAPI_ST_REQ_BODY 2 @@ -83,12 +125,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define LSAPI_INIT_RESP_HEADER_LEN 4096 + static int g_inited = 0; static int g_running = 1; static int s_ppid; static int s_slow_req_msecs = 0; +static int s_keepListener = 0; +static int s_dump_debug_info = 0; +static int s_pid_dump_debug_info = 0; + LSAPI_Request g_req = { -1, -1 }; +static char s_pSecret[24]; + + void Flush_RespBuf_r( LSAPI_Request * pReq ); static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] = @@ -112,13 +162,13 @@ static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] = "HTTP_TRANSFER_ENCODING" }; -static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] = { - 11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 18, - 22, 13, 18, 13, 24, 15, 10, 20, 8, 22 -}; +static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] = +{ 11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 18, + 22, 13, 18, 13, 24, 15, 10, 20, 8, 22 }; -static const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] = { +static const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] = +{ "Accept", "Accept-Charset", "Accept-Encoding", "Accept-Language", "Authorization", @@ -138,8 +188,8 @@ static const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] = { "Transfer-Encoding" }; -static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] = { - 6, 14, 15, 15, 13, 10, 12, 14, 6, 7, 4, 6, 7, 10, /* user-agent */ +static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] = +{ 6, 14, 15, 15, 13, 10, 12, 14, 6, 7, 4, 6, 7, 10, //user-agent 13,17, 8, 13, 8, 19, 10, 5, 15, 3, 17 }; @@ -161,7 +211,8 @@ static void lsapi_signal(int signo, sighandler_t handler) sigaction(signo, NULL, &sa); - if (sa.sa_handler == SIG_DFL) { + if (sa.sa_handler == SIG_DFL) + { sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = handler; @@ -170,6 +221,34 @@ static void lsapi_signal(int signo, sighandler_t handler) } +static int s_enable_core_dump = 0; +static void lsapi_enable_core_dump() +{ +#if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \ + || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) + int mib[2]; + size_t len; + + len = 2; + if ( sysctlnametomib("kern.sugid_coredump", mib, &len) == 0 ) + { + len = sizeof(s_enable_core_dump); + if (sysctl(mib, 2, NULL, 0, &s_enable_core_dump, len) == -1) + perror( "sysctl: Failed to set 'kern.sugid_coredump', " + "core dump may not be available!"); + } + + +#endif + +#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) + if (prctl(PR_SET_DUMPABLE, s_enable_core_dump,0,0,0) == -1) + perror( "prctl: Failed to set dumpable, " + "core dump may not be available!"); +#endif +} + + static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader, char type, int len ) { @@ -200,75 +279,115 @@ static int lsapi_set_nblock( int fd, int nonblock ) return 0; } - static int lsapi_close( int fd ) { int ret; - while( 1 ) { + while( 1 ) + { ret = close( fd ); - if (( ret == -1 )&&( errno == EINTR )&&(g_running)) { + if (( ret == -1 )&&( errno == EINTR )&&(g_running)) continue; - } return ret; } } -static inline int lsapi_read( int fd, void * pBuf, int len ) +static inline ssize_t lsapi_read( int fd, void * pBuf, size_t len ) { - int ret; - while( 1 ) { + ssize_t ret; + while( 1 ) + { ret = read( fd, (char *)pBuf, len ); - if (( ret == -1 )&&( errno == EINTR )&&(g_running)) { + if (( ret == -1 )&&( errno == EINTR )&&(g_running)) continue; - } return ret; } } +/* +static int lsapi_write( int fd, const void * pBuf, int len ) +{ + int ret; + const char * pCur; + const char * pEnd; + if ( len == 0 ) + return 0; + pCur = (const char *)pBuf; + pEnd = pCur + len; + while( g_running && (pCur < pEnd) ) + { + ret = write( fd, pCur, pEnd - pCur ); + if ( ret >= 0) + pCur += ret; + else if (( ret == -1 )&&( errno != EINTR )) + return ret; + } + return pCur - (const char *)pBuf; +} +*/ static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen ) { int ret; int left = totalLen; int n = count; - while(( left > 0 )&&g_running ) { + while(( left > 0 )&&g_running ) + { ret = writev( fd, *pVec, n ); - if ( ret > 0 ) { + if ( ret > 0 ) + { left -= ret; - if (( left <= 0)||( !g_running )) { + if (( left <= 0)||( !g_running )) return totalLen - left; - } - while( ret > 0 ) { - if ( (*pVec)->iov_len <= ret ) { + while( ret > 0 ) + { + if ( (*pVec)->iov_len <= (unsigned int )ret ) + { ret -= (*pVec)->iov_len; ++(*pVec); - } else { + } + else + { (*pVec)->iov_base = (char *)(*pVec)->iov_base + ret; (*pVec)->iov_len -= ret; break; } } - } else if ( ret == -1 ) { - if ( errno == EAGAIN ) { - if ( totalLen - left > 0 ) { + } + else if ( ret == -1 ) + { + if ( errno == EAGAIN ) + { + if ( totalLen - left > 0 ) return totalLen - left; - } else { + else return -1; - } - } else { - if ( errno != EINTR ) { - return ret; - } } + else if ( errno != EINTR ) + return ret; } } return totalLen - left; } +/* +static int getTotalLen( struct iovec * pVec, int count ) +{ + struct iovec * pEnd = pVec + count; + int total = 0; + while( pVec < pEnd ) + { + total += pVec->iov_len; + ++pVec; + } + return total; +} +*/ + static inline int allocateBuf( LSAPI_Request * pReq, int size ) { char * pBuf = (char *)realloc( pReq->m_pReqBuf, size ); - if ( pBuf ) { + if ( pBuf ) + { pReq->m_pReqBuf = pBuf; pReq->m_reqBufSize = size; pReq->m_pHeader = (struct lsapi_req_header *)pReq->m_pReqBuf; @@ -282,9 +401,8 @@ static int allocateIovec( LSAPI_Request * pReq, int n ) { struct iovec * p = (struct iovec *)realloc( pReq->m_pIovec, sizeof(struct iovec) * n ); - if ( !p ) { + if ( !p ) return -1; - } pReq->m_pIovecToWrite = p + ( pReq->m_pIovecToWrite - pReq->m_pIovec ); pReq->m_pIovecCur = p + ( pReq->m_pIovecCur - pReq->m_pIovec ); pReq->m_pIovec = p; @@ -295,9 +413,8 @@ static int allocateIovec( LSAPI_Request * pReq, int n ) static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size ) { char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size ); - if ( !p ) { + if ( !p ) return -1; - } pReq->m_pRespHeaderBufPos = p + ( pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf ); pReq->m_pRespHeaderBuf = p; pReq->m_pRespHeaderBufEnd = p + size; @@ -309,10 +426,10 @@ static inline int verifyHeader( struct lsapi_packet_header * pHeader, char pktTy { if (( LSAPI_VERSION_B0 != pHeader->m_versionB0 )|| ( LSAPI_VERSION_B1 != pHeader->m_versionB1 )|| - ( pktType != pHeader->m_type )) { + ( pktType != pHeader->m_type )) return -1; - } - if ( LSAPI_ENDIAN != (pHeader->m_flag & LSAPI_ENDIAN_BIT )) { + if ( LSAPI_ENDIAN != (pHeader->m_flag & LSAPI_ENDIAN_BIT )) + { register char b; b = pHeader->m_packetLen.m_bytes[0]; pHeader->m_packetLen.m_bytes[0] = pHeader->m_packetLen.m_bytes[3]; @@ -328,21 +445,20 @@ static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList, int *curSize, int newSize ) { struct LSAPI_key_value_pair * pBuf; - if ( *curSize >= newSize ) { + if ( *curSize >= newSize ) return 0; - } - if ( newSize > 8192 ) { + if ( newSize > 8192 ) return -1; - } pBuf = (struct LSAPI_key_value_pair *)realloc( *pEnvList, newSize * sizeof(struct LSAPI_key_value_pair) ); - if ( pBuf ) { + if ( pBuf ) + { *pEnvList = pBuf; *curSize = newSize; return 0; - } else { - return -1; } + else + return -1; } @@ -351,36 +467,32 @@ static inline int isPipe( int fd ) char achPeer[128]; socklen_t len = 128; if (( getpeername( fd, (struct sockaddr *)achPeer, &len ) != 0 )&& - ( errno == ENOTCONN )) { + ( errno == ENOTCONN )) return 0; - } else { + else return 1; - } } static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count, char **pBegin, char * pEnd ) { struct LSAPI_key_value_pair * pEnvEnd; - int keyLen = 0, valLen = 0; - if ( count > 8192 ) { + int keyLen = 0, valLen = 0; + if ( count > 8192 ) return -1; - } pEnvEnd = pEnvList + count; - while( pEnvList != pEnvEnd ) { - if ( pEnd - *pBegin < 4 ) { + while( pEnvList != pEnvEnd ) + { + if ( pEnd - *pBegin < 4 ) return -1; - } keyLen = *((unsigned char *)((*pBegin)++)); keyLen = (keyLen << 8) + *((unsigned char *)((*pBegin)++)); valLen = *((unsigned char *)((*pBegin)++)); valLen = (valLen << 8) + *((unsigned char *)((*pBegin)++)); - if ( *pBegin + keyLen + valLen > pEnd ) { + if ( *pBegin + keyLen + valLen > pEnd ) return -1; - } - if (( !keyLen )||( !valLen )) { + if (( !keyLen )||( !valLen )) return -1; - } pEnvList->pKey = *pBegin; *pBegin += keyLen; @@ -391,9 +503,8 @@ static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count, pEnvList->valLen = valLen - 1; ++pEnvList; } - if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 ) { + if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 ) return -1; - } *pBegin += 4; return 0; } @@ -428,8 +539,10 @@ static inline void fixEndian( LSAPI_Request * pReq ) static void fixHeaderIndexEndian( LSAPI_Request * pReq ) { int i; - for( i = 0; i < H_TRANSFER_ENCODING; ++i ) { - if ( pReq->m_pHeaderIndex->m_headerOff[i] ) { + for( i = 0; i < H_TRANSFER_ENCODING; ++i ) + { + if ( pReq->m_pHeaderIndex->m_headerOff[i] ) + { register char b; char * p = (char *)(&pReq->m_pHeaderIndex->m_headerLen[i]); b = p[0]; @@ -438,20 +551,434 @@ static void fixHeaderIndexEndian( LSAPI_Request * pReq ) swapIntEndian( &pReq->m_pHeaderIndex->m_headerOff[i] ); } } - if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) { + if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) + { struct lsapi_header_offset * pCur, *pEnd; pCur = pReq->m_pUnknownHeader; pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders; - while( pCur < pEnd ) { + while( pCur < pEnd ) + { swapIntEndian( &pCur->nameOff ); swapIntEndian( &pCur->nameLen ); swapIntEndian( &pCur->valueOff ); swapIntEndian( &pCur->valueLen ); ++pCur; } - } + } +} + +static uid_t s_uid = 0; +static uid_t s_defaultUid; //web server need set this +static gid_t s_defaultGid; + +#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) + +#define LSAPI_LVE_DISABLED 0 +#define LSAPI_LVE_ENABLED 1 +#define LSAPI_CAGEFS_ENABLED 2 +#define LSAPI_CAGEFS_NO_SUEXEC 3 +struct liblve; +static int s_enable_lve = LSAPI_LVE_DISABLED; +static struct liblve * s_lve = NULL; + +static void *s_liblve; +static int (*fp_lve_is_available)(void) = NULL; +static int (*fp_lve_instance_init)(struct liblve *) = NULL; +static int (*fp_lve_destroy)(struct liblve *) = NULL; +static int (*fp_lve_enter)(struct liblve *, uint32_t, int32_t, int32_t, uint32_t *) = NULL; +static int (*fp_lve_leave)(struct liblve *, uint32_t *) = NULL; +static int (*fp_lve_jail)( struct passwd *, char *) = NULL; +static int lsapi_load_lve_lib() +{ + s_liblve = dlopen("liblve.so.0", RTLD_LAZY); + if (s_liblve) + { + fp_lve_is_available = dlsym(s_liblve, "lve_is_available"); + if (dlerror() == NULL) + { + if ( !(*fp_lve_is_available)() ) + { + int uid = getuid(); + if ( uid ) + { + setreuid( s_uid, uid ); + if ( !(*fp_lve_is_available)() ) + s_enable_lve = 0; + setreuid( uid, s_uid ); + } + } + } + } + else + { + s_enable_lve = LSAPI_LVE_DISABLED; + } + return (s_liblve)? 0 : -1; +} + +static int init_lve_ex() +{ + int rc; + if ( !s_liblve ) + return -1; + fp_lve_instance_init = dlsym(s_liblve, "lve_instance_init"); + fp_lve_destroy = dlsym(s_liblve, "lve_destroy"); + fp_lve_enter = dlsym(s_liblve, "lve_enter"); + fp_lve_leave = dlsym(s_liblve, "lve_leave"); + if ( s_enable_lve >= LSAPI_CAGEFS_ENABLED ) + fp_lve_jail = dlsym(s_liblve, "jail" ); + + if ( s_lve == NULL ) + { + rc = (*fp_lve_instance_init)(NULL); + s_lve = malloc(rc); + } + rc = (*fp_lve_instance_init)(s_lve); + if (rc != 0) + { + perror( "LSAPI: Unable to initialize LVE" ); + free( s_lve ); + s_lve = NULL; + return -1; + } + return 0; + +} + +#endif + + + +static int readSecret( const char * pSecretFile ) +{ + struct stat st; + int fd = open( pSecretFile, O_RDONLY , 0600 ); + if ( fd == -1 ) + { + fprintf( stderr, "LSAPI: failed to open secret file: %s!\n", pSecretFile ); + return -1; + } + if ( fstat( fd, &st ) == -1 ) + { + fprintf( stderr, "LSAPI: failed to check state of file: %s!\n", pSecretFile ); + close( fd ); + return -1; + } +/* + if ( st.st_uid != s_uid ) + { + fprintf( stderr, "LSAPI: file owner check failure: %s!\n", pSecretFile ); + close( fd ); + return -1; + } +*/ + if ( st.st_mode & 0077 ) + { + fprintf( stderr, "LSAPI: file permission check failure: %s\n", pSecretFile ); + close( fd ); + return -1; + } + if ( read( fd, s_pSecret, 16 ) < 16 ) + { + fprintf( stderr, "LSAPI: failed to read secret from secret file: %s\n", pSecretFile ); + close( fd ); + return -1; + } + close( fd ); + return 0; +} + +int LSAPI_is_suEXEC_Daemon() +{ + if (( !s_uid )&&( s_pSecret[0] )) + return 1; + else + return 0; +} + +static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char *pErr2 ) +{ + char achError[1024]; + int n = snprintf(achError, 1024, "%s:%s: %s\n", pErr1, (pErr2)?pErr2:"", strerror( errno ) ); + if ( pReq ) + LSAPI_Write_Stderr_r( pReq, achError, n ); + else + write( STDERR_FILENO, achError, n ); + return 0; +} + +static int lsapi_lve_error( LSAPI_Request * pReq ) +{ + static const char * headers[] = + { + "Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0", + "Pragma: no-cache", + "Retry-After: 60", + "Content-Type: text/html", + NULL + }; + static const char achBody[] = + "\n" + "\n508 Resource Limit Is Reached\n" + "\n" "

Resource Limit Is Reached

\n" + "The website is temporarily unable to service your request as it exceeded resource limit.\n" + "Please try again later.\n" + "
\n" + "\n"; + + LSAPI_ErrResponse_r( pReq, 508, headers, achBody, sizeof( achBody ) - 1 ); + return 0; +} + +static int lsapi_enterLVE( LSAPI_Request * pReq, uid_t uid ) +{ +#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) + if ( s_lve && uid ) //root user should not do that + { + uint32_t cookie; + int ret = -1; + ret = (*fp_lve_enter)(s_lve, uid, -1, -1, &cookie); + if ( ret < 0 ) + { + fprintf( stderr, "Pid (%d): enter LVE (%d) : ressult: %d !\n", getpid(), uid, ret ); + LSAPI_perror_r(pReq, "LSAPI: lve_enter() failure, reached resource limit.", NULL ); + lsapi_lve_error( pReq ); + return -1; + } + } +#endif + + return 0; +} + +static int lsapi_jailLVE( LSAPI_Request * pReq, uid_t uid, struct passwd * pw ) +{ + int ret = 0; +#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) + char error_msg[1024] = ""; + ret = (*fp_lve_jail)( pw, error_msg ); + if ( ret < 0 ) + { + fprintf( stderr, "LSAPI (%d): LVE jail(%d) ressult: %d, error: %s !\n", + getpid(), uid, ret, error_msg ); + LSAPI_perror_r( pReq, "LSAPI: jail() failure.", NULL ); + return -1; + } +#endif + return ret; +} + + +#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) +static int lsapi_initLVE() +{ + const char * pEnv; + if ( (pEnv = getenv( "LSAPI_LVE_ENABLE" ))!= NULL ) + { + s_enable_lve = atol( pEnv ); + pEnv = NULL; + } + else if ( (pEnv = getenv( "LVE_ENABLE" ))!= NULL ) + { + s_enable_lve = atol( pEnv ); + pEnv = NULL; + } + if ( s_enable_lve && !s_uid ) + { + lsapi_load_lve_lib(); + if ( s_enable_lve ) + { + return init_lve_ex(); + } + + } + return 0; +} +#endif + + +static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * pChroot) +{ + int rv; + struct passwd * pw; + pw = getpwuid( uid ); +#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) + if ( s_lve ) + { + if( lsapi_enterLVE( pReq, uid ) == -1 ) + return -1; + if ( pw && fp_lve_jail) + { + rv = lsapi_jailLVE( pReq, uid, pw ); + if ( rv == -1 ) + return -1; + if (( rv == 1 )&&(s_enable_lve == LSAPI_CAGEFS_NO_SUEXEC )) //this mode only use cageFS, does not use suEXEC + { + uid = s_defaultUid; + gid = s_defaultGid; + pw = getpwuid( uid ); + } + } + } +#endif + //if ( !uid || !gid ) //do not allow root + //{ + // return -1; + //} + +#if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \ + || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) + if ( s_enable_core_dump ) + lsapi_enable_core_dump(); +#endif + + rv = setgid(gid); + if (rv == -1) + { + LSAPI_perror_r(pReq, "LSAPI: setgid()", NULL); + return -1; + } + if ( pw && (pw->pw_gid == gid )) + { + rv = initgroups( pw->pw_name, gid ); + if (rv == -1) + { + LSAPI_perror_r(pReq, "LSAPI: initgroups()", NULL); + return -1; + } + } + else + { + rv = setgroups(1, &gid); + if (rv == -1) + { + LSAPI_perror_r(pReq, "LSAPI: setgroups()", NULL); + } + } + if ( pChroot ) + { + rv = chroot( pChroot ); + if ( rv == -1 ) + { + LSAPI_perror_r(pReq, "LSAPI: chroot()", NULL); + return -1; + } + } + rv = setuid(uid); + if (rv == -1) + { + LSAPI_perror_r(pReq, "LSAPI: setuid()", NULL); + return -1; + } +#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) + if ( s_enable_core_dump ) + lsapi_enable_core_dump(); +#endif + return 0; +} + +static int lsapi_suexec_auth( LSAPI_Request *pReq, + char * pAuth, int len, char * pUgid, int ugidLen ) +{ + lsapi_MD5_CTX md5ctx; + unsigned char achMD5[16]; + if ( len < 32 ) + return -1; + memmove( achMD5, pAuth + 16, 16 ); + memmove( pAuth + 16, s_pSecret, 16 ); + lsapi_MD5Init( &md5ctx ); + lsapi_MD5Update( &md5ctx, (unsigned char *)pAuth, 32 ); + lsapi_MD5Update( &md5ctx, (unsigned char *)pUgid, 8 ); + lsapi_MD5Final( (unsigned char *)pAuth + 16, &md5ctx); + if ( memcmp( achMD5, pAuth + 16, 16 ) == 0 ) + return 0; + return 1; +} + + +static int lsapi_changeUGid( LSAPI_Request * pReq ) +{ + int uid = s_defaultUid; + int gid = s_defaultGid; + const char * pChroot = NULL; + struct LSAPI_key_value_pair * pEnv; + struct LSAPI_key_value_pair * pAuth; + int i; + if ( s_uid ) + return 0; + //with special ID 0x00 + //authenticate the suEXEC request; + //first one should be MD5( nonce + lscgid secret ) + //remember to clear the secret after verification + //it should be set at the end of special env + i = pReq->m_pHeader->m_cntSpecialEnv - 1; + if ( i >= 0 ) + { + pEnv = pReq->m_pSpecialEnvList + i; + if (( *pEnv->pKey == '\000' )&& + ( strcmp( pEnv->pKey+1, "SUEXEC_AUTH" ) == 0 )) + { + --pReq->m_pHeader->m_cntSpecialEnv; + pAuth = pEnv--; + if (( *pEnv->pKey == '\000' )&& + ( strcmp( pEnv->pKey+1, "SUEXEC_UGID" ) == 0 )) + { + --pReq->m_pHeader->m_cntSpecialEnv; + uid = *(uint32_t *)pEnv->pValue; + gid = *(((uint32_t *)pEnv->pValue) + 1 ); + //fprintf( stderr, "LSAPI: SUEXEC_UGID set UID: %d, GID: %d\n", uid, gid ); + } + else + { + fprintf( stderr, "LSAPI: missing SUEXEC_UGID env, use default user!\n" ); + pEnv = NULL; + } + if ( pEnv&& lsapi_suexec_auth( pReq, pAuth->pValue, pAuth->valLen, pEnv->pValue, pEnv->valLen ) == 0 ) + { + //read UID, GID from specialEnv + + } + else + { + //authentication error + fprintf( stderr, "LSAPI: SUEXEC_AUTH authentication failed, use default user!\n" ); + uid = 0; + } + } + else + { + //fprintf( stderr, "LSAPI: no SUEXEC_AUTH env, use default user!\n" ); + } + } + + + if ( !uid ) + { + uid = s_defaultUid; + gid = s_defaultGid; + } + + //change uid + if ( setUID_LVE( pReq, uid, gid, pChroot ) == -1 ) + { + return -1; + } + + s_uid = uid; + + return 0; + +} + +static int parseContentLenFromHeader(LSAPI_Request * pReq) +{ + const char * pContentLen = LSAPI_GetHeader_r( pReq, H_CONTENT_LENGTH ); + if ( pContentLen ) + pReq->m_reqBodyLen = strtoll( pContentLen, NULL, 10 ); + return 0; } + static int parseRequest( LSAPI_Request * pReq, int totalLen ) { int shouldFixEndian; @@ -459,29 +986,28 @@ static int parseRequest( LSAPI_Request * pReq, int totalLen ) char * pEnd = pReq->m_pReqBuf + totalLen; shouldFixEndian = ( LSAPI_ENDIAN != ( pReq->m_pHeader->m_pktHeader.m_flag & LSAPI_ENDIAN_BIT ) ); - if ( shouldFixEndian ) { + if ( shouldFixEndian ) + { fixEndian( pReq ); } if ( (pReq->m_specialEnvListSize < pReq->m_pHeader->m_cntSpecialEnv )&& allocateEnvList( &pReq->m_pSpecialEnvList, - &pReq->m_specialEnvListSize, - pReq->m_pHeader->m_cntSpecialEnv ) == -1 ) { + &pReq->m_specialEnvListSize, + pReq->m_pHeader->m_cntSpecialEnv ) == -1 ) return -1; - } if ( (pReq->m_envListSize < pReq->m_pHeader->m_cntEnv )&& allocateEnvList( &pReq->m_pEnvList, &pReq->m_envListSize, - pReq->m_pHeader->m_cntEnv ) == -1 ) { + pReq->m_pHeader->m_cntEnv ) == -1 ) return -1; - } + if ( parseEnv( pReq->m_pSpecialEnvList, - pReq->m_pHeader->m_cntSpecialEnv, - &pBegin, pEnd ) == -1 ) { + pReq->m_pHeader->m_cntSpecialEnv, + &pBegin, pEnd ) == -1 ) return -1; - } if ( parseEnv( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv, - &pBegin, pEnd ) == -1 ) { + &pBegin, pEnd ) == -1 ) return -1; - } + pReq->m_pScriptFile = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptFileOff; pReq->m_pScriptName = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptNameOff; pReq->m_pQueryString = pReq->m_pReqBuf + pReq->m_pHeader->m_queryStringOff; @@ -497,90 +1023,183 @@ static int parseRequest( LSAPI_Request * pReq, int totalLen ) pReq->m_pHttpHeader = pBegin; pBegin += pReq->m_pHeader->m_httpHeaderLen; - if ( pBegin != pEnd ) { + if ( pBegin != pEnd ) + { + fprintf( stderr, "%d: request header does match total size, total: %d, real: %ld\n", getpid(), totalLen, + pBegin - pReq->m_pReqBuf ); return -1; } - - if ( shouldFixEndian ) { + if ( shouldFixEndian ) + { fixHeaderIndexEndian( pReq ); } - + pReq->m_reqBodyLen = pReq->m_pHeader->m_reqBodyLen; + if ( pReq->m_reqBodyLen == -2 ) + { + parseContentLenFromHeader(pReq); + } + return 0; } -static int s_accept_notify = 0; +//OPTIMIZATION +static char s_accept_notify = 0; +static char s_schedule_notify = 0; +static char s_notify_scheduled = 0; +static char s_notified_pid = 0; -static struct lsapi_packet_header ack = {'L', 'S', +static struct lsapi_packet_header s_ack = {'L', 'S', LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} }; -static inline int notify_req_received( int fd ) + + +static inline int write_req_received_notification( int fd ) { - if ( write( fd, &ack, LSAPI_PACKET_HEADER_LEN ) - < LSAPI_PACKET_HEADER_LEN ) { + if ( write( fd, &s_ack, LSAPI_PACKET_HEADER_LEN ) + < LSAPI_PACKET_HEADER_LEN ) return -1; + return 0; +} + +static void lsapi_sigalarm( int sig ) +{ + if ( s_notify_scheduled ) + { + s_notify_scheduled = 0; + if ( g_req.m_fd != -1 ) + write_req_received_notification( g_req.m_fd ); + } +} + +static inline int lsapi_schedule_notify() +{ + if ( !s_notify_scheduled ) + { + alarm( 2 ); + s_notify_scheduled = 1; } return 0; } +static inline int notify_req_received( int fd ) +{ + if ( s_schedule_notify ) + return lsapi_schedule_notify(); + return write_req_received_notification( fd ); + +} + + +static inline int lsapi_notify_pid( int fd ) +{ + char achBuf[16]; + lsapi_buildPacketHeader( (struct lsapi_packet_header *)achBuf, LSAPI_STDERR_STREAM, + 8 + LSAPI_PACKET_HEADER_LEN ); + memmove( &achBuf[8], "\0PID", 4 ); + *((int *)&achBuf[12]) = getpid(); + + if ( write( fd, achBuf, 16 ) < 16 ) + return -1; + return 0; +} + +static char s_conn_key_packet[16]; +static inline int init_conn_key( int fd ) +{ + struct lsapi_packet_header * pHeader = (struct lsapi_packet_header *)s_conn_key_packet; + struct timeval tv; + int i; + gettimeofday( &tv, NULL ); + srand( (tv.tv_sec % 0x1000 + tv.tv_usec) ^ rand() ); + for( i = 8; i < 16; ++i ) + { + s_conn_key_packet[i]=(int) (256.0*rand()/(RAND_MAX+1.0)); + } + lsapi_buildPacketHeader( pHeader, LSAPI_REQ_RECEIVED, + 8 + LSAPI_PACKET_HEADER_LEN ); + if ( write( fd, s_conn_key_packet, LSAPI_PACKET_HEADER_LEN+8 ) + < LSAPI_PACKET_HEADER_LEN+8 ) + return -1; + return 0; + + +} static int readReq( LSAPI_Request * pReq ) { int len; int packetLen; - if ( !pReq ) { + if ( !pReq ) return -1; - } - if ( pReq->m_reqBufSize < 8192 ) { - if ( allocateBuf( pReq, 8192 ) == -1 ) { + if ( pReq->m_reqBufSize < 8192 ) + { + if ( allocateBuf( pReq, 8192 ) == -1 ) return -1; - } } - while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN ) { + while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN ) + { len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf, pReq->m_reqBufSize ); - if ( len <= 0 ) { + if ( len <= 0 ) return -1; - } pReq->m_bufRead += len; } pReq->m_reqState = LSAPI_ST_REQ_HEADER; packetLen = verifyHeader( &pReq->m_pHeader->m_pktHeader, LSAPI_BEGIN_REQUEST ); - if ( packetLen < 0 ) { + if ( packetLen < 0 ) + { + fprintf( stderr, "%d: packetLen < 0\n", getpid() ); return -1; } - if ( packetLen > LSAPI_MAX_HEADER_LEN ) { + if ( packetLen > LSAPI_MAX_HEADER_LEN ) + { + fprintf( stderr, "%d: packetLen > %d\n", getpid(), LSAPI_MAX_HEADER_LEN ); return -1; } - if ( packetLen + 1024 > pReq->m_reqBufSize ) { - if ( allocateBuf( pReq, packetLen + 1024 ) == -1 ) { + if ( packetLen + 1024 > pReq->m_reqBufSize ) + { + if ( allocateBuf( pReq, packetLen + 1024 ) == -1 ) return -1; - } } - while( packetLen > pReq->m_bufRead ) { + while( packetLen > pReq->m_bufRead ) + { len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, packetLen - pReq->m_bufRead ); - if ( len <= 0 ) { + if ( len <= 0 ) return -1; - } pReq->m_bufRead += len; } - if ( parseRequest( pReq, packetLen ) < 0 ) { + if ( parseRequest( pReq, packetLen ) < 0 ) + { + fprintf( stderr, "%d: parseRequest error\n", getpid() ); return -1; } - pReq->m_bufProcessed = packetLen; + pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER; - if ( !s_accept_notify ) + if ( !s_uid ) + if ( lsapi_changeUGid( pReq ) ) + return -1; + pReq->m_bufProcessed = packetLen; + + //OPTIMIZATION + if ( !s_accept_notify && !s_notified_pid ) return notify_req_received( pReq->m_fd ); else + { + s_notified_pid = 0; return 0; + } } int LSAPI_Init(void) { - if ( !g_inited ) { + if ( !g_inited ) + { + s_uid = geteuid(); + s_pSecret[0] = 0; lsapi_signal(SIGPIPE, lsapi_sigpipe); lsapi_signal(SIGUSR1, lsapi_siguser1); @@ -589,11 +1208,9 @@ int LSAPI_Init(void) #endif /* let STDOUT function as STDERR, just in case writing to STDOUT directly */ - dup2( 2, 1 ); - - if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 ) { + dup2( 2, 1 ); + if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 ) return -1; - } g_inited = 1; s_ppid = getppid(); } @@ -612,28 +1229,27 @@ int LSAPI_IsRunning(void) int LSAPI_InitRequest( LSAPI_Request * pReq, int fd ) { - if ( !pReq ) { + if ( !pReq ) return -1; - } memset( pReq, 0, sizeof( LSAPI_Request ) ); - if ( allocateIovec( pReq, 16 ) == -1 ) { + if ( allocateIovec( pReq, 16 ) == -1 ) return -1; - } pReq->m_pRespBuf = pReq->m_pRespBufPos = (char *)malloc( LSAPI_RESP_BUF_SIZE ); - if ( !pReq->m_pRespBuf ) { + if ( !pReq->m_pRespBuf ) return -1; - } pReq->m_pRespBufEnd = pReq->m_pRespBuf + LSAPI_RESP_BUF_SIZE; pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1; pReq->m_respPktHeaderEnd = &pReq->m_respPktHeader[5]; - if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 ) { + if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 ) return -1; - } - if ( isPipe( fd ) ) { + if ( isPipe( fd ) ) + { pReq->m_fdListen = -1; pReq->m_fd = fd; - } else { + } + else + { pReq->m_fdListen = fd; pReq->m_fd = -1; lsapi_set_nblock( fd, 1 ); @@ -659,42 +1275,48 @@ int LSAPI_Accept_r( LSAPI_Request * pReq ) socklen_t len; int nodelay = 1; - if ( !pReq ) { + if ( !pReq ) return -1; - } - if ( LSAPI_Finish_r( pReq ) == -1 ) { + if ( LSAPI_Finish_r( pReq ) == -1 ) return -1; - } - while( g_running ) { - if ( pReq->m_fd == -1 ) { - if ( pReq->m_fdListen != -1) { + lsapi_set_nblock( pReq->m_fdListen , 0 ); + while( g_running ) + { + if ( pReq->m_fd == -1 ) + { + if ( pReq->m_fdListen != -1) + { len = sizeof( achPeer ); pReq->m_fd = accept( pReq->m_fdListen, (struct sockaddr *)&achPeer, &len ); - if ( pReq->m_fd == -1 ) { - if (( errno == EINTR )||( errno == EAGAIN)) { + if ( pReq->m_fd == -1 ) + { + if (( errno == EINTR )||( errno == EAGAIN)) continue; - } else { + else return -1; - } - } else { + } + else + { lsapi_set_nblock( pReq->m_fd , 0 ); - if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) { + if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) + { setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY, - (char *)&nodelay, sizeof(nodelay)); + (char *)&nodelay, sizeof(nodelay)); } - + //init_conn_key( pReq->m_fd ); + //OPTIMIZATION if ( s_accept_notify ) - return notify_req_received( pReq->m_fd ); - + if ( notify_req_received( pReq->m_fd ) == -1 ) + return -1; } - } else { - return -1; } + else + return -1; } - if ( !readReq( pReq ) ) { + if ( !readReq( pReq ) ) break; - } + //abort(); lsapi_close( pReq->m_fd ); pReq->m_fd = -1; LSAPI_Reset_r( pReq ); @@ -708,15 +1330,18 @@ static struct lsapi_packet_header finish = {'L', 'S', int LSAPI_Finish_r( LSAPI_Request * pReq ) { /* finish req body */ - if ( !pReq ) { + if ( !pReq ) return -1; - } - if (pReq->m_reqState) { - if ( pReq->m_fd != -1 ) { - if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) { + if (pReq->m_reqState) + { + if ( pReq->m_fd != -1 ) + { + if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) + { LSAPI_FinalizeRespHeaders_r( pReq ); } - if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) { + if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) + { Flush_RespBuf_r( pReq ); } @@ -745,18 +1370,14 @@ void LSAPI_Reset_r( LSAPI_Request * pReq ) int LSAPI_Release_r( LSAPI_Request * pReq ) { - if ( pReq->m_pReqBuf ) { + if ( pReq->m_pReqBuf ) free( pReq->m_pReqBuf ); - } - if ( pReq->m_pSpecialEnvList ) { + if ( pReq->m_pSpecialEnvList ) free( pReq->m_pSpecialEnvList ); - } - if ( pReq->m_pEnvList ) { + if ( pReq->m_pEnvList ) free( pReq->m_pEnvList ); - } - if ( pReq->m_pRespHeaderBuf ) { + if ( pReq->m_pRespHeaderBuf ) free( pReq->m_pRespHeaderBuf ); - } return 0; } @@ -764,55 +1385,48 @@ int LSAPI_Release_r( LSAPI_Request * pReq ) char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex ) { int off; - if ( !pReq || ((unsigned int)headerIndex > H_TRANSFER_ENCODING) ) { + if ( !pReq || ((unsigned int)headerIndex > H_TRANSFER_ENCODING) ) return NULL; - } off = pReq->m_pHeaderIndex->m_headerOff[ headerIndex ]; - if ( !off ) { + if ( !off ) return NULL; - } - if ( *(pReq->m_pHttpHeader + off + - pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) ) { - *( pReq->m_pHttpHeader + off + - pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0; - } + if ( *(pReq->m_pHttpHeader + off + + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) ) + *( pReq->m_pHttpHeader + off + + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0; return pReq->m_pHttpHeader + off; } static int readBodyToReqBuf( LSAPI_Request * pReq ) { - int bodyLeft; - int len = pReq->m_bufRead - pReq->m_bufProcessed; - if ( len > 0 ) { + off_t bodyLeft; + ssize_t len = pReq->m_bufRead - pReq->m_bufProcessed; + if ( len > 0 ) return len; - } pReq->m_bufRead = pReq->m_bufProcessed = pReq->m_pHeader->m_pktHeader.m_packetLen.m_iLen; - bodyLeft = pReq->m_pHeader->m_reqBodyLen - pReq->m_reqBodyRead; + bodyLeft = pReq->m_reqBodyLen - pReq->m_reqBodyRead; len = pReq->m_reqBufSize - pReq->m_bufRead; - if ( len < 0 ) { + if ( len < 0 ) return -1; - } - if ( len > bodyLeft ) { + if ( len > bodyLeft ) len = bodyLeft; - } + len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, len ); - if ( len > 0 ) { + if ( len > 0 ) pReq->m_bufRead += len; - } return len; } int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq ) { - if (!pReq || (pReq->m_fd ==-1) ) { + if (!pReq || (pReq->m_fd ==-1) ) return EOF; - } - if ( pReq->m_bufProcessed >= pReq->m_bufRead ) { - if ( readBodyToReqBuf( pReq ) <= 0 ) { + if ( pReq->m_bufProcessed >= pReq->m_bufRead ) + { + if ( readBodyToReqBuf( pReq ) <= 0 ) return EOF; - } } ++pReq->m_reqBodyRead; return (unsigned char)*(pReq->m_pReqBuf + pReq->m_bufProcessed++); @@ -820,42 +1434,43 @@ int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq ) -int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, int bufLen, int *getLF ) +int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF ) { - int len; - int left; + ssize_t len; + ssize_t left; char * pBufEnd = pBuf + bufLen - 1; char * pBufCur = pBuf; char * pCur; char * p; - if (!pReq || (pReq->m_fd ==-1) ||( !pBuf )||(bufLen < 0 )|| !getLF ) { + if (!pReq || (pReq->m_fd ==-1) ||( !pBuf )||(bufLen < 0 )|| !getLF ) return -1; - } *getLF = 0; - while( (left = pBufEnd - pBufCur ) > 0 ) { + while( (left = pBufEnd - pBufCur ) > 0 ) + { len = pReq->m_bufRead - pReq->m_bufProcessed; - if ( len <= 0 ) { - if ( (len = readBodyToReqBuf( pReq )) <= 0 ) { + if ( len <= 0 ) + { + if ( (len = readBodyToReqBuf( pReq )) <= 0 ) + { *getLF = 1; break; } } - if ( len > left ) { + if ( len > left ) len = left; - } pCur = pReq->m_pReqBuf + pReq->m_bufProcessed; p = memchr( pCur, '\n', len ); - if ( p ) { + if ( p ) len = p - pCur + 1; - } memmove( pBufCur, pCur, len ); pBufCur += len; pReq->m_bufProcessed += len; pReq->m_reqBodyRead += len; - if ( p ) { + if ( p ) + { *getLF = 1; break; } @@ -866,48 +1481,47 @@ int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, int bufLen, int * } -int LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, int bufLen ) +ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen ) { - int len; - int total; + ssize_t len; + off_t total; /* char *pOldBuf = pBuf; */ - if (!pReq || (pReq->m_fd ==-1) || ( !pBuf )||(bufLen < 0 )) { + if (!pReq || (pReq->m_fd ==-1) || ( !pBuf )||(bufLen < 0 )) return -1; - } - total = pReq->m_pHeader->m_reqBodyLen - pReq->m_reqBodyRead; + + total = pReq->m_reqBodyLen - pReq->m_reqBodyRead; - if ( total <= 0 ) { + if ( total <= 0 ) return 0; - } - if ( total < bufLen ) { + if ( total < bufLen ) bufLen = total; - } total = 0; len = pReq->m_bufRead - pReq->m_bufProcessed; - if ( len > 0 ) { - if ( len > bufLen ) { + if ( len > 0 ) + { + if ( len > bufLen ) len = bufLen; - } memmove( pBuf, pReq->m_pReqBuf + pReq->m_bufProcessed, len ); pReq->m_bufProcessed += len; total += len; pBuf += len; bufLen -= len; } - while( bufLen > 0 ) { + while( bufLen > 0 ) + { len = lsapi_read( pReq->m_fd, pBuf, bufLen ); - if ( len > 0 ) { + if ( len > 0 ) + { total += len; pBuf += len; bufLen -= len; - } else { - if ( len <= 0 ) { - if ( !total) { - return -1; - } - break; - } + } + else if ( len <= 0 ) + { + if ( !total) + return -1; + break; } } pReq->m_reqBodyRead += total; @@ -916,37 +1530,52 @@ int LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, int bufLen ) } -int LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, int len ) +ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len ) { struct lsapi_packet_header * pHeader; const char * pEnd; const char * p; - int bufLen; - int toWrite; - int packetLen; + ssize_t bufLen; + ssize_t toWrite; + ssize_t packetLen; + int skip = 0; - if ( !pReq || !pBuf || (pReq->m_fd == -1) ) { + if ( !pReq || !pBuf || (pReq->m_fd == -1) ) return -1; + if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) + { + LSAPI_FinalizeRespHeaders_r( pReq ); +/* + if ( *pBuf == '\r' ) + { + ++skip; + } + if ( *pBuf == '\n' ) + { + ++skip; + } +*/ } - if ( len < pReq->m_pRespBufEnd - pReq->m_pRespBufPos ) { - memmove( pReq->m_pRespBufPos, pBuf, len ); - pReq->m_pRespBufPos += len; + pReq->m_reqState |= LSAPI_ST_RESP_BODY; + + if ( (len - skip) < pReq->m_pRespBufEnd - pReq->m_pRespBufPos ) + { + memmove( pReq->m_pRespBufPos, pBuf + skip, len - skip ); + pReq->m_pRespBufPos += len - skip; return len; } - if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) { - LSAPI_FinalizeRespHeaders_r( pReq ); - } - pReq->m_reqState |= LSAPI_ST_RESP_BODY; pHeader = pReq->m_respPktHeader; - p = pBuf; + p = pBuf + skip; pEnd = pBuf + len; bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf; - while( ( toWrite = pEnd - p ) > 0 ) { + while( ( toWrite = pEnd - p ) > 0 ) + { packetLen = toWrite + bufLen; - if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen) { + if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen) + { packetLen = LSAPI_MAX_DATA_PACKET_LEN; toWrite = packetLen - bufLen; } @@ -959,7 +1588,8 @@ int LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, int len ) pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN; ++pReq->m_pIovecCur; ++pHeader; - if ( bufLen > 0 ) { + if ( bufLen > 0 ) + { pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf; pReq->m_pIovecCur->iov_len = bufLen; pReq->m_pRespBufPos = pReq->m_pRespBuf; @@ -972,21 +1602,108 @@ int LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, int len ) ++pReq->m_pIovecCur; p += toWrite; - if ( pHeader >= pReq->m_respPktHeaderEnd - 1) { - if ( LSAPI_Flush_r( pReq ) == -1 ) { + if ( pHeader >= pReq->m_respPktHeaderEnd - 1) + { + if ( LSAPI_Flush_r( pReq ) == -1 ) return -1; - } pHeader = pReq->m_respPktHeader; } } - if ( pHeader != pReq->m_respPktHeader ) { - if ( LSAPI_Flush_r( pReq ) == -1 ) { + if ( pHeader != pReq->m_respPktHeader ) + if ( LSAPI_Flush_r( pReq ) == -1 ) return -1; - } - } return p - pBuf; } +#if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) +ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size ) +{ + ssize_t ret; + off_t written; + ret = sendfile( fdIn, fdOut, *off, size, NULL, &written, 0 ); + if ( written > 0 ) + { + ret = written; + *off += ret; + } + return ret; +} +#endif + +#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) +ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size ) +{ + ssize_t ret; + off_t len = size; + ret = sendfile( fdIn, fdOut, *off, &len, NULL, 0 ); + if (( ret == 0 )&&( len > 0 )) + { + ret = len; + *off += len; + } + return ret; +} +#endif + +#if defined(sun) || defined(__sun) +#include +ssize_t gsendfile( int fdOut, int fdIn, off_t *off, size_t size ) +{ + int n = 0 ; + sendfilevec_t vec[1]; + + vec[n].sfv_fd = fdIn; + vec[n].sfv_flag = 0; + vec[n].sfv_off = *off; + vec[n].sfv_len = size; + ++n; + + size_t written; + ssize_t ret = sendfilev( fdOut, vec, n, &written ); + if (( !ret )||( errno == EAGAIN )) + ret = written; + if ( ret > 0 ) + *off += ret; + return ret; +} +#endif + +#if defined(linux) || defined(__linux) || defined(__linux__) || \ + defined(__gnu_linux__) +#include +#define gsendfile sendfile +#endif +#if defined(HPUX) +ssize_t gsendfile( int fdOut, int fdIn, off_t * off, size_t size ) +{ + return sendfile( fdOut, fdIn, off, size, NULL, 0 ); +} +#endif + +ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size ) +{ + struct lsapi_packet_header * pHeader = pReq->m_respPktHeader; + if ( !pReq || (pReq->m_fd == -1) || fdIn == -1 ) + return -1; + if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) + { + LSAPI_FinalizeRespHeaders_r( pReq ); + } + pReq->m_reqState |= LSAPI_ST_RESP_BODY; + + LSAPI_Flush_r(pReq); + + lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM, + size + LSAPI_PACKET_HEADER_LEN ); + + + if (write(pReq->m_fd, (const char *) pHeader, LSAPI_PACKET_HEADER_LEN ) != LSAPI_PACKET_HEADER_LEN) + return -1; + + return gsendfile( pReq->m_fd, fdIn, off, size ); +} + + void Flush_RespBuf_r( LSAPI_Request * pReq ) { struct lsapi_packet_header * pHeader = pReq->m_respPktHeader; @@ -1000,7 +1717,8 @@ void Flush_RespBuf_r( LSAPI_Request * pReq ) pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN; ++pReq->m_pIovecCur; ++pHeader; - if ( bufLen > 0 ) { + if ( bufLen > 0 ) + { pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf; pReq->m_pIovecCur->iov_len = bufLen; pReq->m_pRespBufPos = pReq->m_pRespBuf; @@ -1016,32 +1734,35 @@ int LSAPI_Flush_r( LSAPI_Request * pReq ) { int ret = 0; int n; - if ( !pReq ) { + if ( !pReq ) return -1; - } n = pReq->m_pIovecCur - pReq->m_pIovecToWrite; - if (( 0 == n )&&( pReq->m_pRespBufPos == pReq->m_pRespBuf )) { + if (( 0 == n )&&( pReq->m_pRespBufPos == pReq->m_pRespBuf )) return 0; - } - if ( pReq->m_fd == -1 ) { + if ( pReq->m_fd == -1 ) + { pReq->m_pRespBufPos = pReq->m_pRespBuf; pReq->m_totalLen = 0; pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec; return -1; } - if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) { + if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) + { LSAPI_FinalizeRespHeaders_r( pReq ); } - if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) { + if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) + { Flush_RespBuf_r( pReq ); } n = pReq->m_pIovecCur - pReq->m_pIovecToWrite; - if ( n > 0 ) { + if ( n > 0 ) + { ret = lsapi_writev( pReq->m_fd, &pReq->m_pIovecToWrite, n, pReq->m_totalLen ); - if ( ret < pReq->m_totalLen ) { + if ( ret < pReq->m_totalLen ) + { lsapi_close( pReq->m_fd ); pReq->m_fd = -1; ret = -1; @@ -1053,32 +1774,33 @@ int LSAPI_Flush_r( LSAPI_Request * pReq ) } -int LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, int len ) +ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t len ) { struct lsapi_packet_header header; const char * pEnd; const char * p; - int packetLen; - int totalLen; + ssize_t packetLen; + ssize_t totalLen; int ret; struct iovec iov[2]; struct iovec *pIov; - if ( !pReq ) { + if ( !pReq ) return -1; - } - if (( pReq->m_fd == -1 )||(pReq->m_fd == pReq->m_fdListen )) { + if (( pReq->m_fd == -1 )||(pReq->m_fd == pReq->m_fdListen )) return write( 2, pBuf, len ); - } - if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) { + if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) + { LSAPI_Flush_r( pReq ); } p = pBuf; pEnd = pBuf + len; - while( ( packetLen = pEnd - p ) > 0 ) { - if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen) { + while( ( packetLen = pEnd - p ) > 0 ) + { + if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen) + { packetLen = LSAPI_MAX_DATA_PACKET_LEN; } @@ -1095,7 +1817,8 @@ int LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, int len ) pIov = iov; ret = lsapi_writev( pReq->m_fd, &pIov, 2, totalLen ); - if ( ret < totalLen ) { + if ( ret < totalLen ) + { lsapi_close( pReq->m_fd ); pReq->m_fd = -1; ret = -1; @@ -1107,14 +1830,16 @@ int LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, int len ) static char * GetHeaderVar( LSAPI_Request * pReq, const char * name ) { int i; - for( i = 0; i < H_TRANSFER_ENCODING; ++i ) { - if ( pReq->m_pHeaderIndex->m_headerOff[i] ) { - if ( strcmp( name, CGI_HEADERS[i] ) == 0 ) { + for( i = 0; i < H_TRANSFER_ENCODING; ++i ) + { + if ( pReq->m_pHeaderIndex->m_headerOff[i] ) + { + if ( strcmp( name, CGI_HEADERS[i] ) == 0 ) return pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i]; - } } } - if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) { + if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) + { const char *p; char *pKey; char *pKeyEnd; @@ -1122,22 +1847,22 @@ static char * GetHeaderVar( LSAPI_Request * pReq, const char * name ) struct lsapi_header_offset * pCur, *pEnd; pCur = pReq->m_pUnknownHeader; pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders; - while( pCur < pEnd ) { + while( pCur < pEnd ) + { pKey = pReq->m_pHttpHeader + pCur->nameOff; keyLen = pCur->nameLen; pKeyEnd = pKey + keyLen; p = &name[5]; - while(( pKey < pKeyEnd )&&( *p )) { + while(( pKey < pKeyEnd )&&( *p )) + { char ch = toupper( *pKey ); - if ((ch != *p )||(( *p == '_' )&&( ch != '-'))) { + if ((ch != *p )||(( *p == '_' )&&( ch != '-'))) break; - } ++p; ++pKey; } - if (( pKey == pKeyEnd )&& (!*p )) { + if (( pKey == pKeyEnd )&& (!*p )) return pReq->m_pHttpHeader + pCur->valueOff; - } ++pCur; } } @@ -1149,21 +1874,35 @@ char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name ) { struct LSAPI_key_value_pair * pBegin = pReq->m_pEnvList; struct LSAPI_key_value_pair * pEnd = pBegin + pReq->m_pHeader->m_cntEnv; - if ( !pReq || !name ) { + if ( !pReq || !name ) return NULL; - } - if ( strncmp( name, "HTTP_", 5 ) == 0 ) { + if ( strncmp( name, "HTTP_", 5 ) == 0 ) + { return GetHeaderVar( pReq, name ); } - while( pBegin < pEnd ) { - if ( strcmp( name, pBegin->pKey ) == 0 ) { + while( pBegin < pEnd ) + { + if ( strcmp( name, pBegin->pKey ) == 0 ) return pBegin->pValue; - } ++pBegin; } return NULL; } +struct _headerInfo +{ + const char * _name; + int _nameLen; + const char * _value; + int _valueLen; +}; + +int compareValueLocation(const void * v1, const void *v2 ) +{ + return ((const struct _headerInfo *)v1)->_value - + ((const struct _headerInfo *)v2)->_value; +} + int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ) { @@ -1172,43 +1911,66 @@ int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq, char * pValue; int ret; int count = 0; - if ( !pReq || !fn ) { + struct _headerInfo headers[512]; + if ( !pReq || !fn ) return -1; - } - for( i = 0; i < H_TRANSFER_ENCODING; ++i ) { - if ( pReq->m_pHeaderIndex->m_headerOff[i] ) { + + for( i = 0; i < H_TRANSFER_ENCODING; ++i ) + { + if ( pReq->m_pHeaderIndex->m_headerOff[i] ) + { len = pReq->m_pHeaderIndex->m_headerLen[i]; pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i]; *(pValue + len ) = 0; - ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i], - pValue, len, arg ); + headers[count]._name = HTTP_HEADERS[i]; + headers[count]._nameLen = HTTP_HEADER_LEN[i]; + headers[count]._value = pValue; + headers[count]._valueLen = len; ++count; - if ( ret <= 0 ) { - return ret; - } + + //ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i], + // pValue, len, arg ); + //if ( ret <= 0 ) + // return ret; } } - if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) { + if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) + { char *pKey; int keyLen; struct lsapi_header_offset * pCur, *pEnd; pCur = pReq->m_pUnknownHeader; pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders; - while( pCur < pEnd ) { + while( pCur < pEnd ) + { pKey = pReq->m_pHttpHeader + pCur->nameOff; keyLen = pCur->nameLen; pValue = pReq->m_pHttpHeader + pCur->valueOff; *(pValue + pCur->valueLen ) = 0; - ret = (*fn)( pKey, keyLen, - pValue, pCur->valueLen, arg ); - if ( ret <= 0 ) { - return ret; - } + headers[count]._name = pKey; + headers[count]._nameLen = keyLen; + headers[count]._value = pValue; + headers[count]._valueLen = pCur->valueLen; + ++count; + if ( count == 512 ) + break; + //ret = (*fn)( pKey, keyLen, + // pValue, pCur->valueLen, arg ); + //if ( ret <= 0 ) + // return ret; ++pCur; } } - return count + pReq->m_pHeader->m_cntUnknownHeaders; + qsort( headers, count, sizeof( struct _headerInfo ), compareValueLocation ); + for( i = 0; i < count; ++i ) + { + ret = (*fn)( headers[i]._name, headers[i]._nameLen, + headers[i]._value, headers[i]._valueLen, arg ); + if ( ret <= 0 ) + return ret; + } + return count; } @@ -1221,23 +1983,24 @@ int LSAPI_ForeachHeader_r( LSAPI_Request * pReq, char * pValue; int ret; int count = 0; - if ( !pReq || !fn ) { + if ( !pReq || !fn ) return -1; - } - for( i = 0; i < H_TRANSFER_ENCODING; ++i ) { - if ( pReq->m_pHeaderIndex->m_headerOff[i] ) { + for( i = 0; i < H_TRANSFER_ENCODING; ++i ) + { + if ( pReq->m_pHeaderIndex->m_headerOff[i] ) + { len = pReq->m_pHeaderIndex->m_headerLen[i]; pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i]; *(pValue + len ) = 0; ret = (*fn)( CGI_HEADERS[i], CGI_HEADER_LEN[i], pValue, len, arg ); ++count; - if ( ret <= 0 ) { + if ( ret <= 0 ) return ret; - } } } - if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) { + if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) + { char achHeaderName[256]; char *p; char *pKey; @@ -1246,24 +2009,23 @@ int LSAPI_ForeachHeader_r( LSAPI_Request * pReq, struct lsapi_header_offset * pCur, *pEnd; pCur = pReq->m_pUnknownHeader; pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders; - while( pCur < pEnd ) { + while( pCur < pEnd ) + { pKey = pReq->m_pHttpHeader + pCur->nameOff; keyLen = pCur->nameLen; - if ( keyLen > 250 ) { + if ( keyLen > 250 ) keyLen = 250; - } - pKeyEnd = pKey + keyLen; memcpy( achHeaderName, "HTTP_", 5 ); p = &achHeaderName[5]; - while( pKey < pKeyEnd ) { + while( pKey < pKeyEnd ) + { char ch = *pKey++; - if ( ch == '-' ) { + if ( ch == '-' ) *p++ = '_'; - } else { + else *p++ = toupper( ch ); - } } *p = 0; keyLen += 5; @@ -1272,9 +2034,8 @@ int LSAPI_ForeachHeader_r( LSAPI_Request * pReq, *(pValue + pCur->valueLen ) = 0; ret = (*fn)( achHeaderName, keyLen, pValue, pCur->valueLen, arg ); - if ( ret <= 0 ) { + if ( ret <= 0 ) return ret; - } ++pCur; } } @@ -1287,15 +2048,14 @@ static int EnvForeach( struct LSAPI_key_value_pair * pEnv, { struct LSAPI_key_value_pair * pEnd = pEnv + n; int ret; - if ( !pEnv || !fn ) { + if ( !pEnv || !fn ) return -1; - } - while( pEnv < pEnd ) { + while( pEnv < pEnd ) + { ret = (*fn)( pEnv->pKey, pEnv->keyLen, pEnv->pValue, pEnv->valLen, arg ); - if ( ret <= 0 ) { + if ( ret <= 0 ) return ret; - } ++pEnv; } return n; @@ -1306,10 +2066,10 @@ static int EnvForeach( struct LSAPI_key_value_pair * pEnv, int LSAPI_ForeachEnv_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ) { - if ( !pReq || !fn ) { + if ( !pReq || !fn ) return -1; - } - if ( pReq->m_pHeader->m_cntEnv > 0 ) { + if ( pReq->m_pHeader->m_cntEnv > 0 ) + { return EnvForeach( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv, fn, arg ); } @@ -1321,10 +2081,10 @@ int LSAPI_ForeachEnv_r( LSAPI_Request * pReq, int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ) { - if ( !pReq || !fn ) { + if ( !pReq || !fn ) return -1; - } - if ( pReq->m_pHeader->m_cntSpecialEnv > 0 ) { + if ( pReq->m_pHeader->m_cntSpecialEnv > 0 ) + { return EnvForeach( pReq->m_pSpecialEnvList, pReq->m_pHeader->m_cntSpecialEnv, fn, arg ); @@ -1337,14 +2097,13 @@ int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq, int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq ) { - if ( !pReq || !pReq->m_pIovec ) { + if ( !pReq || !pReq->m_pIovec ) return -1; - } - if ( !( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) ) { + if ( !( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) ) return 0; - } pReq->m_reqState &= ~LSAPI_ST_RESP_HEADER; - if ( pReq->m_pRespHeaderBufPos > pReq->m_pRespHeaderBuf ) { + if ( pReq->m_pRespHeaderBufPos > pReq->m_pRespHeaderBuf ) + { pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespHeaderBuf; pReq->m_pIovecCur->iov_len = pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf; pReq->m_totalLen += pReq->m_pIovecCur->iov_len; @@ -1363,25 +2122,87 @@ int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq ) } - - -int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, char * pBuf, int len ) +int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName, + const char * pHeaderValue ) { - if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX ) { + int nameLen, valLen, len; + if ( !pReq || !pHeaderName || !pHeaderValue ) + return -1; + if ( pReq->m_reqState & LSAPI_ST_RESP_BODY ) return -1; + if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS ) + return -1; + nameLen = strlen( pHeaderName ); + valLen = strlen( pHeaderValue ); + if ( nameLen == 0 ) + return -1; + while( nameLen > 0 ) + { + char ch = *(pHeaderName + nameLen - 1 ); + if (( ch == '\n' )||( ch == '\r' )) + --nameLen; + else + break; } - if ( pReq->m_reqState & LSAPI_ST_RESP_BODY ) { + if ( nameLen <= 0 ) + return 0; + while( valLen > 0 ) + { + char ch = *(pHeaderValue + valLen - 1 ); + if (( ch == '\n' )||( ch == '\r' )) + --valLen; + else + break; + } + len = nameLen + valLen + 1; + if ( len > LSAPI_RESP_HTTP_HEADER_MAX ) return -1; + + if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd ) + { + int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf; + newlen -= newlen % 4096; + if ( allocateRespHeaderBuf( pReq, newlen ) == -1 ) + return -1; } - if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS ) { + memmove( pReq->m_pRespHeaderBufPos, pHeaderName, nameLen ); + pReq->m_pRespHeaderBufPos += nameLen; + *pReq->m_pRespHeaderBufPos++ = ':'; + memmove( pReq->m_pRespHeaderBufPos, pHeaderValue, valLen ); + pReq->m_pRespHeaderBufPos += valLen; + *pReq->m_pRespHeaderBufPos++ = 0; + ++len; /* add one byte padding for \0 */ + pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len; + ++pReq->m_respHeader.m_respInfo.m_cntHeaders; + return 0; +} + + + +int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len ) +{ + if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX ) + return -1; + if ( pReq->m_reqState & LSAPI_ST_RESP_BODY ) return -1; + if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS ) + return -1; + while( len > 0 ) + { + char ch = *(pBuf + len - 1 ); + if (( ch == '\n' )||( ch == '\r' )) + --len; + else + break; } - if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd ) { + if ( len <= 0 ) + return 0; + if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd ) + { int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf; newlen -= newlen % 4096; - if ( allocateRespHeaderBuf( pReq, newlen ) == -1 ) { + if ( allocateRespHeaderBuf( pReq, newlen ) == -1 ) return -1; - } } memmove( pReq->m_pRespHeaderBufPos, pBuf, len ); pReq->m_pRespHeaderBufPos += len; @@ -1400,7 +2221,8 @@ int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog ) int flag = 1; int addr_len; - switch( pServerAddr->sa_family ) { + switch( pServerAddr->sa_family ) + { case AF_INET: addr_len = 16; break; @@ -1416,20 +2238,20 @@ int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog ) } fd = socket( pServerAddr->sa_family, SOCK_STREAM, 0 ); - if ( fd == -1 ) { + if ( fd == -1 ) return -1; - } fcntl( fd, F_SETFD, FD_CLOEXEC ); if(setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, - (char *)( &flag ), sizeof(flag)) == 0) { + (char *)( &flag ), sizeof(flag)) == 0) + { ret = bind( fd, pServerAddr, addr_len ); - if ( !ret ) { + if ( !ret ) + { ret = listen( fd, backlog ); - if ( !ret ) { + if ( !ret ) return fd; - } } } @@ -1449,17 +2271,16 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr ) int doAddrInfo = 0; int port; - if ( !pBind ) { + if ( !pBind ) return -1; - } - while( isspace( *pBind ) ) { + while( isspace( *pBind ) ) ++pBind; - } strncpy( achAddr, pBind, 256 ); - switch( *p ) { + switch( *p ) + { case '/': pAddr->sa_family = AF_UNIX; strncpy( ((struct sockaddr_un *)pAddr)->sun_path, p, @@ -1474,7 +2295,8 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr ) return -1; *pEnd++ = 0; - if ( *p == '*' ) { + if ( *p == '*' ) + { strcpy( achAddr, "::" ); p = achAddr; } @@ -1484,35 +2306,35 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr ) default: pAddr->sa_family = AF_INET; pEnd = strchr( p, ':' ); - if ( !pEnd ) { + if ( !pEnd ) return -1; - } *pEnd++ = 0; doAddrInfo = 0; - if ( *p == '*' ) { + if ( *p == '*' ) + { ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl(INADDR_ANY); - } else { - if (!strcasecmp( p, "localhost" ) ) { - ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl( INADDR_LOOPBACK ); - } else { - ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = inet_addr( p ); - if ( ((struct sockaddr_in *)pAddr)->sin_addr.s_addr == INADDR_BROADCAST) { - doAddrInfo = 1; - } + } + else if (!strcasecmp( p, "localhost" ) ) + ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl( INADDR_LOOPBACK ); + else + { + ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = inet_addr( p ); + if ( ((struct sockaddr_in *)pAddr)->sin_addr.s_addr == INADDR_BROADCAST) + { + doAddrInfo = 1; } } break; } - if ( *pEnd == ':' ) { + if ( *pEnd == ':' ) ++pEnd; - } port = atoi( pEnd ); - if (( port <= 0 )||( port > 65535 )) { + if (( port <= 0 )||( port > 65535 )) return -1; - } - if ( doAddrInfo ) { + if ( doAddrInfo ) + { memset(&hints, 0, sizeof(hints)); @@ -1520,7 +2342,8 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr ) hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; - if ( getaddrinfo(p, NULL, &hints, &res) ) { + if ( getaddrinfo(p, NULL, &hints, &res) ) + { return -1; } @@ -1528,11 +2351,10 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr ) freeaddrinfo(res); } - if ( pAddr->sa_family == AF_INET ) { + if ( pAddr->sa_family == AF_INET ) ((struct sockaddr_in *)pAddr)->sin_port = htons( port ); - } else { + else ((struct sockaddr_in6 *)pAddr)->sin6_port = htons( port ); - } return 0; } @@ -1543,7 +2365,8 @@ int LSAPI_CreateListenSock( const char * pBind, int backlog ) int ret; int fd = -1; ret = LSAPI_ParseSockAddr( pBind, (struct sockaddr *)serverAddr ); - if ( !ret ) { + if ( !ret ) + { fd = LSAPI_CreateListenSock2( (struct sockaddr *)serverAddr, backlog ); } return fd; @@ -1554,9 +2377,11 @@ static fn_select_t g_fnSelect = select; typedef struct _lsapi_child_status { int m_pid; + long m_tmStart; volatile short m_iKillSent; volatile short m_inProcess; + volatile int m_iReqCounter; volatile long m_tmWaitBegin; volatile long m_tmReqBegin; @@ -1586,43 +2411,42 @@ static lsapi_prefork_server * g_prefork_server = NULL; int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork ) { - if ( g_prefork_server ) { + int pid; + if ( g_prefork_server ) return 0; - } - if ( max_children <= 1 ) { + if ( max_children <= 1 ) return -1; - } - if ( max_children >= 10000) { + if ( max_children >= 10000) max_children = 10000; - } g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) ); - if ( !g_prefork_server ) { + if ( !g_prefork_server ) return -1; - } memset( g_prefork_server, 0, sizeof( lsapi_prefork_server ) ); - if ( fp != NULL ) { + if ( fp != NULL ) g_fnSelect = fp; - } s_ppid = getppid(); + pid = getpid(); + setpgid( pid, pid ); g_prefork_server->m_iAvoidFork = avoidFork; g_prefork_server->m_iMaxChildren = max_children; g_prefork_server->m_iExtraChildren = ( avoidFork ) ? 0 : (max_children / 3) ; g_prefork_server->m_iMaxIdleChildren = ( avoidFork ) ? (max_children + 1) : (max_children / 3); + if ( g_prefork_server->m_iMaxIdleChildren == 0 ) + g_prefork_server->m_iMaxIdleChildren = 1; g_prefork_server->m_iChildrenMaxIdleTime = 300; - g_prefork_server->m_iMaxReqProcessTime = 300; + g_prefork_server->m_iMaxReqProcessTime = 3600; return 0; } void LSAPI_Set_Server_fd( int fd ) { - if( g_prefork_server ) { + if( g_prefork_server ) g_prefork_server->m_fd = fd; - } } @@ -1635,14 +2459,17 @@ static int lsapi_accept( int fdListen ) len = sizeof( achPeer ); fd = accept( fdListen, (struct sockaddr *)&achPeer, &len ); - if ( fd != -1 ) { - if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) { + if ( fd != -1 ) + { + if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) + { setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay)); } - if ( s_accept_notify ) - notify_req_received( fd ); + //OPTIMIZATION + //if ( s_accept_notify ) + // notify_req_received( fd ); } return fd; @@ -1666,10 +2493,10 @@ static lsapi_child_status * find_child_status( int pid ) { lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus; lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatus + g_prefork_server->m_iMaxChildren * 2; - while( pStatus < pEnd ) { - if ( pStatus->m_pid == pid ) { + while( pStatus < pEnd ) + { + if ( pStatus->m_pid == pid ) return pStatus; - } ++pStatus; } return NULL; @@ -1681,16 +2508,30 @@ static void lsapi_sigchild( int signal ) { int status, pid; lsapi_child_status * child_status; - while( 1 ) { + while( 1 ) + { pid = waitpid( -1, &status, WNOHANG|WUNTRACED ); - if ( pid <= 0 ) { + if ( pid <= 0 ) + { break; } + if ( WIFSIGNALED( status )) + { + int sig_num = WTERMSIG( status ); + int dump = WCOREDUMP( status ); + fprintf( stderr, "Child process with pid: %d was killed by signal: %d, core dump: %d\n", pid, sig_num, dump ); + } + if ( pid == s_pid_dump_debug_info ) + { + pid = 0; + continue; + } child_status = find_child_status( pid ); - if ( child_status ) { + if ( child_status ) + { child_status->m_pid = 0; + --g_prefork_server->m_iCurChildren; } - --g_prefork_server->m_iCurChildren; } } @@ -1704,76 +2545,108 @@ static int lsapi_init_children_status() size = (size + 4095 ) / 4096 * 4096; pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0 ); - if ( pBuf == MAP_FAILED ) { + if ( pBuf == MAP_FAILED ) + { perror( "Anonymous mmap() failed" ); return -1; } memset( pBuf, 0, size ); - g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf; + g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf; return 0; } +static void dump_debug_info( lsapi_child_status * pStatus, long tmCur ) +{ + char achCmd[1024]; + if ( s_pid_dump_debug_info ) + { + if ( kill( s_pid_dump_debug_info, 0 ) == 0 ) + return; + } + s_pid_dump_debug_info = fork(); + + fprintf( stderr, "[%s] Possible runaway process, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld\n", + ctime(&tmCur), getpid(), pStatus->m_pid, pStatus->m_iReqCounter, + tmCur - pStatus->m_tmReqBegin, tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart ); + snprintf( achCmd, 1024, "gdb --batch -ex \"attach %d\" -ex \"set height 0\" -ex \"bt\" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2", pStatus->m_pid, pStatus->m_pid ); + if ( system( achCmd ) == -1 ) + perror( "system()" ); + exit( 0 ); +} + static void lsapi_check_child_status( long tmCur ) { int idle = 0; int tobekilled; int dying = 0; + int count = 0; lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus; lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatus + g_prefork_server->m_iMaxChildren * 2; - while( pStatus < pEnd ) { - tobekilled = pStatus->m_iKillSent; - if ( pStatus->m_pid != 0 ) { - if ( !tobekilled ) { - if ( !pStatus->m_inProcess ) { - - if (( g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren)|| - ( idle >= g_prefork_server->m_iMaxIdleChildren )) { - - tobekilled = 1; - } else { - if (( s_max_idle_secs> 0)&&(tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5 )) { - tobekilled = 1; - } - } - if ( !tobekilled ) { - ++idle; - } - } else { - if ( tmCur - pStatus->m_tmReqBegin > - g_prefork_server->m_iMaxReqProcessTime ) { - tobekilled = 1; - } + while( pStatus < pEnd ) + { + tobekilled = 0; + if ( pStatus->m_pid != 0 ) + { + ++count; + if ( !pStatus->m_inProcess ) + { + + if (( g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren)|| + ( idle > g_prefork_server->m_iMaxIdleChildren )) + { + tobekilled = SIGUSR1; } - } else { - if ( pStatus->m_inProcess ) { - tobekilled = pStatus->m_iKillSent = 0; + else + { + if (( s_max_idle_secs> 0)&&(tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5 )) + { + tobekilled = SIGUSR1; + } } + if ( !tobekilled ) + ++idle; } - if ( tobekilled ) { - tobekilled = 0; - if ( pStatus->m_iKillSent > 5 ) { - tobekilled = SIGKILL; - } else { - if ( pStatus->m_iKillSent == 3 ) { + else + { + if ( tmCur - pStatus->m_tmReqBegin > + g_prefork_server->m_iMaxReqProcessTime ) + { + if (( ( pStatus->m_iKillSent % 5 ) == 0 )&&( s_dump_debug_info )) + dump_debug_info( pStatus, tmCur ); + if ( pStatus->m_iKillSent > 5 ) + { + tobekilled = SIGKILL; + fprintf( stderr, "Force killing runaway process PID: %d with SIGKILL\n", pStatus->m_pid ); + } + else + { tobekilled = SIGTERM; - } else { - if ( pStatus->m_iKillSent == 1 ) { - tobekilled = SIGUSR1; - } + fprintf( stderr, "Killing runaway process PID: %d with SIGTERM\n", pStatus->m_pid ); } } - if ( tobekilled ) { - kill( pStatus->m_pid, tobekilled ); + } + if ( tobekilled ) + { + if (( kill( pStatus->m_pid, tobekilled ) == -1 )&&( errno == ESRCH )) + { + pStatus->m_pid = 0; + --count; + } + else + { + ++pStatus->m_iKillSent; + ++dying; } - ++pStatus->m_iKillSent; - ++dying; } - - } else { - ++dying; } ++pStatus; } + if ( abs( g_prefork_server->m_iCurChildren - count ) > 1 ) + { + fprintf( stderr, "Children tracking is wrong: PID: %d, Cur Childen: %d, count: %d, idle: %d, dying: %d\n", getpid(), + g_prefork_server->m_iCurChildren, count, idle, dying ); + + } } static int lsapi_all_children_must_die() @@ -1784,14 +2657,14 @@ static int lsapi_all_children_must_die() g_prefork_server->m_iMaxIdleChildren = -1; maxWait = 15; - while( g_prefork_server->m_iCurChildren && (sec < maxWait) ) { + while( g_prefork_server->m_iCurChildren && (sec < maxWait) ) + { lsapi_check_child_status(time(NULL)); sleep( 1 ); sec++; } - if ( g_prefork_server->m_iCurChildren != 0 ) { + if ( g_prefork_server->m_iCurChildren != 0 ) kill( -getpgrp(), SIGKILL ); - } return 0; } @@ -1810,13 +2683,17 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re fd_set readfds; struct timeval timeout; + sigset_t mask; + sigset_t orig_mask; + lsapi_init_children_status(); setsid(); act.sa_flags = 0; act.sa_handler = lsapi_sigchild; - if( sigaction( SIGCHLD, &act, &old_child ) ) { + if( sigaction( SIGCHLD, &act, &old_child ) ) + { perror( "Can't set signal handler for SIGCHILD" ); return -1; } @@ -1827,36 +2704,36 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re if( sigaction( SIGTERM, &act, &old_term ) || sigaction( SIGINT, &act, &old_int ) || sigaction( SIGUSR1, &act, &old_usr1 ) || - sigaction( SIGQUIT, &act, &old_quit )) { + sigaction( SIGQUIT, &act, &old_quit )) + { perror( "Can't set signals" ); return -1; } s_stop = 0; - while( !s_stop ) { - if ( ret ) { - curTime = time( NULL ); - } else { - ++curTime; - } - if (curTime != lastTime ) { + while( !s_stop ) + { + curTime = time( NULL ); + if (curTime != lastTime ) + { lastTime = curTime; - if (s_ppid && (getppid() != s_ppid )) { + if (s_ppid && (getppid() != s_ppid )) break; - } lsapi_check_child_status(curTime ); - if (pServer->m_iServerMaxIdle) { - if ( pServer->m_iCurChildren <= 0 ) { + if (pServer->m_iServerMaxIdle) + { + if ( pServer->m_iCurChildren <= 0 ) + { ++wait_secs; - if ( wait_secs > pServer->m_iServerMaxIdle ) { + if ( wait_secs > pServer->m_iServerMaxIdle ) return -1; - } - } else { - wait_secs = 0; } + else + wait_secs = 0; } } - if ( pServer->m_iCurChildren >= (pServer->m_iMaxChildren + pServer->m_iExtraChildren ) ) { + if ( pServer->m_iCurChildren >= (pServer->m_iMaxChildren + pServer->m_iExtraChildren ) ) + { usleep( 100000 ); continue; } @@ -1864,66 +2741,100 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re FD_ZERO( &readfds ); FD_SET( pServer->m_fd, &readfds ); timeout.tv_sec = 1; timeout.tv_usec = 0; - if ((ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout)) == 1 ) { - if ( pServer->m_iCurChildren >= 0 ) { + if ((ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout)) == 1 ) + { + /* + if ( pServer->m_iCurChildren >= 0 ) + { usleep( 10 ); FD_ZERO( &readfds ); FD_SET( pServer->m_fd, &readfds ); timeout.tv_sec = 0; timeout.tv_usec = 0; - if ( (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout) == 0 ) { - continue; - } - } - } else { - if ( ret == -1 ) { - if ( errno == EINTR ) { + if ( (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout) == 0 ) continue; - } - /* perror( "select()" ); */ - break; - } else { + }*/ + } + else if ( ret == -1 ) + { + if ( errno == EINTR ) continue; - } + /* perror( "select()" ); */ + break; + } + else + { + continue; } pReq->m_fd = lsapi_accept( pServer->m_fd ); - if ( pReq->m_fd != -1 ) { + if ( pReq->m_fd != -1 ) + { child_status = find_child_status( 0 ); + if ( child_status ) + memset( child_status, 0, sizeof( *child_status ) ); + + sigemptyset( &mask ); + sigaddset( &mask, SIGCHLD ); + + if ( sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0 ) + { + perror( "sigprocmask(SIG_BLOCK) to block SIGCHLD" ); + } + pid = fork(); - if ( !pid ) { + + if ( !pid ) + { + if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0) + perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK in child" ); g_prefork_server = NULL; s_ppid = getppid(); s_req_processed = 0; s_pChildStatus = child_status; - child_status->m_iKillSent = 0; lsapi_set_nblock( pReq->m_fd, 0 ); - + if ( pReq->m_fdListen != -1 ) + { + close( pReq->m_fdListen ); + pReq->m_fdListen = -1; + } /* don't catch our signals */ sigaction( SIGCHLD, &old_child, 0 ); sigaction( SIGTERM, &old_term, 0 ); sigaction( SIGQUIT, &old_quit, 0 ); sigaction( SIGINT, &old_int, 0 ); sigaction( SIGUSR1, &old_usr1, 0 ); + //init_conn_key( pReq->m_fd ); + lsapi_notify_pid( pReq->m_fd ); + s_notified_pid = 1; + //if ( s_accept_notify ) + // return notify_req_received( pReq->m_fd ); return 0; - } else { - if ( pid == -1 ) { - perror( "fork() failed, please increase process limit" ); - } else { - ++pServer->m_iCurChildren; - if ( child_status ) { - child_status->m_pid = pid; - child_status->m_iKillSent = 0; - child_status->m_tmWaitBegin = time(NULL); - } + } + else if ( pid == -1 ) + { + perror( "fork() failed, please increase process limit" ); + } + else + { + ++pServer->m_iCurChildren; + if ( child_status ) + { + child_status->m_pid = pid; + child_status->m_tmWaitBegin = curTime; + child_status->m_tmStart = curTime; } } close( pReq->m_fd ); pReq->m_fd = -1; - } else { - if (( errno == EINTR )||( errno == EAGAIN)) { + if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0) + perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK" ); + + } + else + { + if (( errno == EINTR )||( errno == EAGAIN)) continue; - } perror( "accept() failed" ); return -1; } @@ -1935,6 +2846,11 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re } +void lsapi_error( const char * pMessage, int err_no ) +{ + fprintf( stderr, "%d: %s, errno: %d (%s)\n", getpid(), pMessage, err_no, strerror( err_no ) ); +} + int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq ) { int fd; @@ -1946,88 +2862,105 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq ) LSAPI_Finish_r( pReq ); - if ( g_prefork_server ) { - if ( g_prefork_server->m_fd != -1 ) { - if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 ) { + if ( g_prefork_server ) + { + if ( g_prefork_server->m_fd != -1 ) + if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 ) return -1; - } - } } - if ( s_req_processed >= s_max_reqs ) { + if ( s_req_processed >= s_max_reqs ) return -1; - } - if ( s_pChildStatus ) { + if ( s_pChildStatus ) + { s_pChildStatus->m_tmWaitBegin = time( NULL ); } + - while( g_running ) { - if ( pReq->m_fd != -1 ) { + while( g_running ) + { + if ( pReq->m_fd != -1 ) + { fd = pReq->m_fd; - } else { - if ( pReq->m_fdListen != -1 ) { - fd = pReq->m_fdListen; - } else { - return -1; - } + } + else if ( pReq->m_fdListen != -1 ) + fd = pReq->m_fdListen; + else + { + break; } wait_secs = 0; - while( 1 ) { - if ( !g_running ) { + while( 1 ) + { + if ( !g_running ) return -1; - } - if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent )) { + if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent )) return -1; - } FD_ZERO( &readfds ); FD_SET( fd, &readfds ); timeout.tv_sec = 1; timeout.tv_usec = 0; ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout); - if ( ret == 0 ) { - if ( s_pChildStatus ) { + if ( ret == 0 ) + { + if ( s_pChildStatus ) + { s_pChildStatus->m_inProcess = 0; } ++wait_secs; - if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs )) { + if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs )) return -1; - } - if ( s_ppid &&( getppid() != s_ppid)) { + if ( s_ppid &&( getppid() != s_ppid)) return -1; - } - } else { - if ( ret == -1 ) { - if ( errno == EINTR ) { - continue; - } else { - return -1; - } - } else { - if ( ret >= 1 ) { - if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent )) { - return -1; + } + else if ( ret == -1 ) + { + if ( errno == EINTR ) + continue; + else + return -1; + } + else if ( ret >= 1 ) + { + if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent )) + return -1; + if ( fd == pReq->m_fdListen ) + { + pReq->m_fd = lsapi_accept( pReq->m_fdListen ); + if ( pReq->m_fd != -1 ) + { + fd = pReq->m_fd; + lsapi_set_nblock( fd, 0 ); + //init_conn_key( pReq->m_fd ); + if ( !s_keepListener ) + { + close( pReq->m_fdListen ); + pReq->m_fdListen = -1; } - if ( fd == pReq->m_fdListen ) { - pReq->m_fd = lsapi_accept( pReq->m_fdListen ); - if ( pReq->m_fd != -1 ) { - fd = pReq->m_fd; - lsapi_set_nblock( fd, 0 ); - } else { - if (( errno == EINTR )||( errno == EAGAIN)) { - continue; - } + if ( s_accept_notify ) + if ( notify_req_received( pReq->m_fd ) == -1 ) return -1; - } - } else { - break; - } + } + else + { + if (( errno == EINTR )||( errno == EAGAIN)) + continue; + lsapi_error( "lsapi_accept() error", errno ); + return -1; } } + else + break; } } - if ( !readReq( pReq ) ) { - if ( s_pChildStatus ) { + + if ( !readReq( pReq ) ) + { + if ( s_pChildStatus ) + { + s_pChildStatus->m_iKillSent = 0; s_pChildStatus->m_inProcess = 1; + ++s_pChildStatus->m_iReqCounter; s_pChildStatus->m_tmReqBegin = s_pChildStatus->m_tmLastCheckPoint = time(NULL); } ++s_req_processed; @@ -2042,61 +2975,53 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq ) } void LSAPI_Set_Max_Reqs( int reqs ) -{ - s_max_reqs = reqs; -} +{ s_max_reqs = reqs; } void LSAPI_Set_Max_Idle( int secs ) -{ - s_max_idle_secs = secs; -} +{ s_max_idle_secs = secs; } void LSAPI_Set_Max_Children( int maxChildren ) { - if ( g_prefork_server ) { + if ( g_prefork_server ) g_prefork_server->m_iMaxChildren = maxChildren; - } } void LSAPI_Set_Extra_Children( int extraChildren ) { - if (( g_prefork_server )&&( extraChildren >= 0 )) { + if (( g_prefork_server )&&( extraChildren >= 0 )) g_prefork_server->m_iExtraChildren = extraChildren; - } } void LSAPI_Set_Max_Process_Time( int secs ) { - if (( g_prefork_server )&&( secs > 0 )) { + if (( g_prefork_server )&&( secs > 0 )) g_prefork_server->m_iMaxReqProcessTime = secs; - } } void LSAPI_Set_Max_Idle_Children( int maxIdleChld ) { - if (( g_prefork_server )&&( maxIdleChld > 0 )) { + if (( g_prefork_server )&&( maxIdleChld > 0 )) g_prefork_server->m_iMaxIdleChildren = maxIdleChld; - } } void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle ) { - if ( g_prefork_server ) { + if ( g_prefork_server ) g_prefork_server->m_iServerMaxIdle = serverMaxIdle; - } } void LSAPI_Set_Slow_Req_Msecs( int msecs ) { - s_slow_req_msecs = msecs; + s_slow_req_msecs = msecs; } int LSAPI_Get_Slow_Req_Msecs() { - return s_slow_req_msecs; + return s_slow_req_msecs; } + void LSAPI_No_Check_ppid() { s_ppid = 0; @@ -2115,113 +3040,419 @@ static void unset_lsapi_envs() #else env = environ; #endif - while( env != NULL && *env != NULL ) { - if ( !strncmp(*env, "LSAPI_", 6) || - !strncmp( *env, "PHP_LSAPI_", 10 ) ) { + while( env != NULL && *env != NULL ) + { + if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 ) + || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid))) + { char ** del = env; - do { + do *del = del[1]; - } while( *del++ ); - } else { - ++env; + while( *del++ ); } + else + ++env; } } -void LSAPI_Init_Env_Parameters( fn_select_t fp ) +static int lsapi_initSuEXEC() +{ + int i; + struct passwd * pw; + s_defaultUid = 0; + s_defaultGid = 0; + if ( s_uid == 0 ) + { + const char * p = getenv( "LSAPI_DEFAULT_UID" ); + if ( p ) + { + i = atoi( p ); + if ( i > 0 ) + s_defaultUid = i; + } + p = getenv( "LSAPI_DEFAULT_GID" ); + if ( p ) + { + i = atoi( p ); + if ( i > 0 ) + s_defaultGid = i; + } + p = getenv( "LSAPI_SECRET" ); + if (( !p )||( readSecret(p) == -1 )) + return -1; + if ( g_prefork_server ) + { + if ( g_prefork_server->m_iMaxChildren < 100 ) + g_prefork_server->m_iMaxChildren = 100; + } + } + if ( !s_defaultUid || !s_defaultGid ) + { + pw = getpwnam( "nobody" ); + if ( !s_defaultUid ) + s_defaultUid = pw->pw_uid; + if ( !s_defaultGid ) + s_defaultGid = pw->pw_gid; + } + return 0; +} + + +int LSAPI_Init_Env_Parameters( fn_select_t fp ) { const char *p; int n; int avoidFork = 0; p = getenv( "PHP_LSAPI_MAX_REQUESTS" ); - if ( !p ) { + if ( !p ) p = getenv( "LSAPI_MAX_REQS" ); - } - if ( p ) { + if ( p ) + { n = atoi( p ); - if ( n > 0 ) { + if ( n > 0 ) LSAPI_Set_Max_Reqs( n ); - } } p = getenv( "LSAPI_AVOID_FORK" ); - if ( p ) { + if ( p ) + { avoidFork = atoi( p ); } p = getenv( "LSAPI_ACCEPT_NOTIFY" ); - if ( p ) { + if ( p ) + { s_accept_notify = atoi( p ); - } + } p = getenv( "LSAPI_SLOW_REQ_MSECS" ); - if ( p ) { + if ( p ) + { n = atoi( p ); LSAPI_Set_Slow_Req_Msecs( n ); - } - + } #if defined( RLIMIT_CORE ) p = getenv( "LSAPI_ALLOW_CORE_DUMP" ); - if ( !p ) { + if ( !p ) + { struct rlimit limit = { 0, 0 }; setrlimit( RLIMIT_CORE, &limit ); } -#endif + else + s_enable_core_dump = 1; + +#endif p = getenv( "LSAPI_MAX_IDLE" ); - if ( p ) { + if ( p ) + { n = atoi( p ); LSAPI_Set_Max_Idle( n ); } - if ( LSAPI_Is_Listen() ) { + p = getenv( "LSAPI_KEEP_LISTEN" ); + if ( p ) + { + n = atoi( p ); + s_keepListener = n; + } + + + if ( LSAPI_Is_Listen() ) + { n = 0; p = getenv( "PHP_LSAPI_CHILDREN" ); - if ( !p ) { + if ( !p ) p = getenv( "LSAPI_CHILDREN" ); - } - if ( p ) { + if ( p ) n = atoi( p ); - } - if ( n > 1 ) { + if ( n > 1 ) + { LSAPI_Init_Prefork_Server( n, fp, avoidFork ); LSAPI_Set_Server_fd( g_req.m_fdListen ); } p = getenv( "LSAPI_EXTRA_CHILDREN" ); - if ( p ) { + if ( p ) LSAPI_Set_Extra_Children( atoi( p ) ); - } p = getenv( "LSAPI_MAX_IDLE_CHILDREN" ); - if ( p ) { + if ( p ) LSAPI_Set_Max_Idle_Children( atoi( p ) ); - } + p = getenv( "LSAPI_PGRP_MAX_IDLE" ); - if ( p ) { + if ( p ) + { LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) ); } p = getenv( "LSAPI_MAX_PROCESS_TIME" ); - if ( p ) { + if ( p ) LSAPI_Set_Max_Process_Time( atoi( p ) ); - } - if ( getenv( "LSAPI_PPID_NO_CHECK" ) ) { + + if ( getenv( "LSAPI_PPID_NO_CHECK" ) ) + { LSAPI_No_Check_ppid(); } + + p = getenv( "LSAPI_DUMP_DEBUG_INFO" ); + if ( p ) + s_dump_debug_info = atoi( p ); + + if ( lsapi_initSuEXEC() == -1 ) + return -1; +#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) + lsapi_initLVE(); +#endif } unset_lsapi_envs(); + return 0; +} + + +int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders, + const char * pBody, int bodyLen ) +{ + LSAPI_SetRespStatus_r( pReq, code ); + if ( pRespHeaders ) + { + while( *pRespHeaders ) + { + LSAPI_AppendRespHeader_r( pReq, *pRespHeaders, strlen( *pRespHeaders ) ); + ++pRespHeaders; + } + } + if ( pBody &&( bodyLen > 0 )) + { + LSAPI_Write_r( pReq, pBody, bodyLen ); + } + LSAPI_Finish_r( pReq ); + return 0; +} + + +static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]); + +/* + * Note: this code is harmless on little-endian machines. + */ +static void byteReverse(unsigned char *buf, unsigned longs) +{ + uint32 t; + do { + t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32 *) buf = t; + buf += 4; + } while (--longs); +} + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void lsapi_MD5Init(struct lsapi_MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; } +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void lsapi_MD5Update(struct lsapi_MD5Context *ctx, unsigned char const *buf, unsigned len) +{ + register uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memmove(p, buf, len); + return; + } + memmove(p, buf, t); + byteReverse(ctx->in, 16); + lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memmove(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memmove(ctx->in, buf, len); +} /* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) */ +void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *ctx) +{ + unsigned int count; + unsigned char *p; + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(ctx->in, 16); + lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((uint32 *) ctx->in)[14] = ctx->bits[0]; + ((uint32 *) ctx->in)[15] = ctx->bits[1]; + + lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memmove(digest, ctx->buf, 16); + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]) +{ + register uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} diff --git a/sapi/litespeed/lsapilib.h b/sapi/litespeed/lsapilib.h index 45934ad464..efa1f53dcc 100644 --- a/sapi/litespeed/lsapilib.h +++ b/sapi/litespeed/lsapilib.h @@ -1,4 +1,3 @@ - /* +----------------------------------------------------------------------+ | PHP Version 5 | @@ -18,7 +17,7 @@ */ /* -Copyright (c) 2007, Lite Speed Technologies Inc. +Copyright (c) 2002-2014, Lite Speed Technologies Inc. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -49,6 +48,13 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/*************************************************************************** + lsapilib.h - description + ------------------- + begin : Mon Feb 21 2005 + copyright : (C) 2005 by George Wang + email : gwang@litespeedtech.com + ***************************************************************************/ #ifndef _LSAPILIB_H_ @@ -118,7 +124,8 @@ typedef struct lsapi_request char * m_pRequestMethod; int m_totalLen; int m_reqState; - int m_reqBodyRead; + off_t m_reqBodyLen; + off_t m_reqBodyRead; int m_bufProcessed; int m_bufRead; @@ -126,6 +133,7 @@ typedef struct lsapi_request struct lsapi_resp_header m_respHeader; short m_respHeaderLen[LSAPI_MAX_RESP_HEADERS]; + void * m_pAppData; }LSAPI_Request; @@ -170,22 +178,30 @@ int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq, char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name ); -int LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, int len ); +ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t len ); int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq ); -int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, int bufLen, int *getLF ); +int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF ); int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq ); -int LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, int len ); +ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len ); + +ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size ); -int LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, int len ); +ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t len ); int LSAPI_Flush_r( LSAPI_Request * pReq ); -int LSAPI_AppendRespHeader_r( LSAPI_Request * pHeader, char * pBuf, int len ); +int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len ); + +int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName, + const char * pHeaderValue ); + +int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders, + const char * pBody, int bodyLen ); static inline int LSAPI_SetRespStatus_r( LSAPI_Request * pReq, int code ) { @@ -195,6 +211,21 @@ static inline int LSAPI_SetRespStatus_r( LSAPI_Request * pReq, int code ) return 0; } +static inline int LSAPI_SetAppData_r( LSAPI_Request * pReq, void * data ) +{ + if ( !pReq ) + return -1; + pReq->m_pAppData = data; + return 0; +} + +static inline void * LSAPI_GetAppData_r( LSAPI_Request * pReq ) +{ + if ( !pReq ) + return NULL; + return pReq->m_pAppData; +} + static inline char * LSAPI_GetQueryString_r( LSAPI_Request * pReq ) { if ( pReq ) @@ -228,21 +259,22 @@ static inline char * LSAPI_GetRequestMethod_r( LSAPI_Request * pReq) -static inline int LSAPI_GetReqBodyLen_r( LSAPI_Request * pReq ) +static inline off_t LSAPI_GetReqBodyLen_r( LSAPI_Request * pReq ) { if ( pReq ) - return pReq->m_pHeader->m_reqBodyLen; + return pReq->m_reqBodyLen; return -1; } -static inline int LSAPI_GetReqBodyRemain_r( LSAPI_Request * pReq ) +static inline off_t LSAPI_GetReqBodyRemain_r( LSAPI_Request * pReq ) { if ( pReq ) - return pReq->m_pHeader->m_reqBodyLen - pReq->m_reqBodyRead; + return pReq->m_reqBodyLen - pReq->m_reqBodyRead; return -1; } + int LSAPI_Is_Listen(void); static inline int LSAPI_Accept( void ) @@ -282,13 +314,13 @@ static inline char * LSAPI_GetScriptName() static inline char * LSAPI_GetRequestMethod() { return LSAPI_GetRequestMethod_r( &g_req ); } -static inline int LSAPI_GetReqBodyLen() +static inline off_t LSAPI_GetReqBodyLen() { return LSAPI_GetReqBodyLen_r( &g_req ); } -static inline int LSAPI_GetReqBodyRemain() +static inline off_t LSAPI_GetReqBodyRemain() { return LSAPI_GetReqBodyRemain_r( &g_req ); } -static inline int LSAPI_ReadReqBody( char * pBuf, int len ) +static inline ssize_t LSAPI_ReadReqBody( char * pBuf, size_t len ) { return LSAPI_ReadReqBody_r( &g_req, pBuf, len ); } static inline int LSAPI_ReqBodyGetChar() @@ -302,10 +334,15 @@ static inline int LSAPI_ReqBodyGetLine( char * pBuf, int len, int *getLF ) static inline int LSAPI_FinalizeRespHeaders(void) { return LSAPI_FinalizeRespHeaders_r( &g_req ); } -static inline int LSAPI_Write( const char * pBuf, int len ) +static inline ssize_t LSAPI_Write( const char * pBuf, ssize_t len ) { return LSAPI_Write_r( &g_req, pBuf, len ); } -static inline int LSAPI_Write_Stderr( const char * pBuf, int len ) +static inline ssize_t LSAPI_sendfile( int fdIn, off_t* off, size_t size ) +{ + return LSAPI_sendfile_r(&g_req, fdIn, off, size ); +} + +static inline ssize_t LSAPI_Write_Stderr( const char * pBuf, ssize_t len ) { return LSAPI_Write_Stderr_r( &g_req, pBuf, len ); } static inline int LSAPI_Flush() @@ -317,6 +354,9 @@ static inline int LSAPI_AppendRespHeader( char * pBuf, int len ) static inline int LSAPI_SetRespStatus( int code ) { return LSAPI_SetRespStatus_r( &g_req, code ); } +static inline int LSAPI_ErrResponse( int code, const char ** pRespHeaders, const char * pBody, int bodyLen ) +{ return LSAPI_ErrResponse_r( &g_req, code, pRespHeaders, pBody, bodyLen ); } + int LSAPI_IsRunning(void); int LSAPI_CreateListenSock( const char * pBind, int backlog ); @@ -341,12 +381,13 @@ void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle ); void LSAPI_Set_Max_Process_Time( int secs ); -void LSAPI_Init_Env_Parameters( fn_select_t fp ); +int LSAPI_Init_Env_Parameters( fn_select_t fp ); void LSAPI_Set_Slow_Req_Msecs( int msecs ); int LSAPI_Get_Slow_Req_Msecs( ); +int LSAPI_is_suEXEC_Daemon(); #if defined (c_plusplus) || defined (__cplusplus) } -- 2.40.0