/sapi/litespeed/lsapilib.c
C | 4110 lines | 3365 code | 529 blank | 216 comment | 796 complexity | 41e936f77533c7a5e759089d70cf9b1b MD5 | raw file
Possible License(s): BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-2.1
Large files files are truncated, but you can click here to view the full file
- /*
- +----------------------------------------------------------------------+
- | Copyright (c) The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available at through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt. |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Author: George Wang <gwang@litespeedtech.com> |
- +----------------------------------------------------------------------+
- */
- /*
- Copyright (c) 2002-2018, Lite Speed Technologies Inc.
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are
- met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials provided
- with the distribution.
- * Neither the name of the Lite Speed Technologies Inc nor the
- names of its contributors may be used to endorse or promote
- products derived from this software without specific prior
- written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include <ctype.h>
- #include <dlfcn.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <limits.h>
- #include <sys/stat.h>
- #include <sched.h>
- #include <signal.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <stdarg.h>
- #include <string.h>
- #include <sys/mman.h>
- #include <sys/resource.h>
- #include <sys/socket.h>
- #include <sys/time.h>
- #include <sys/uio.h>
- #include <sys/wait.h>
- #include <grp.h>
- #include <pwd.h>
- #include <time.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #include <netdb.h>
- #include <netinet/in.h>
- #include <netinet/tcp.h>
- #include <sys/un.h>
- #include "lsapilib.h"
- #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
- #include <sys/prctl.h>
- #endif
- #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \
- || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
- #include <sys/sysctl.h>
- #endif
- #include <inttypes.h>
- #ifndef uint32
- #define uint32 uint32_t
- #endif
- #include <Zend/zend_portability.h>
- 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
- #define LSAPI_ST_RESP_HEADER 4
- #define LSAPI_ST_RESP_BODY 8
- #define LSAPI_ST_BACKGROUND 16
- #define LSAPI_RESP_BUF_SIZE 8192
- #define LSAPI_INIT_RESP_HEADER_LEN 4096
- enum
- {
- LSAPI_STATE_IDLE,
- LSAPI_STATE_CONNECTED,
- LSAPI_STATE_ACCEPTING,
- };
- typedef struct _lsapi_child_status
- {
- int m_pid;
- long m_tmStart;
- volatile short m_iKillSent;
- volatile char m_inProcess;
- volatile char m_state;
- volatile int m_iReqCounter;
- volatile long m_tmWaitBegin;
- volatile long m_tmReqBegin;
- volatile long m_tmLastCheckPoint;
- }
- lsapi_child_status;
- static lsapi_child_status * s_worker_status = NULL;
- static int g_inited = 0;
- static int g_running = 1;
- static int s_ppid;
- static int s_restored_ppid = 0;
- static int s_pid = 0;
- 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;
- static int s_req_processed = 0;
- static int s_skip_write = 0;
- static int (*pthread_atfork_func)(void (*prepare)(void), void (*parent)(void),
- void (*child)(void)) = NULL;
- static int *s_busy_workers = NULL;
- static int *s_accepting_workers = NULL;
- static int *s_global_counter = &s_req_processed;
- static int s_max_busy_workers = -1;
- static char *s_stderr_log_path = NULL;
- static int s_stderr_is_pipe = 0;
- static int s_ignore_pid = -1;
- static size_t s_total_pages = 1;
- static size_t s_min_avail_pages = 256 * 1024;
- static size_t *s_avail_pages = &s_total_pages;
- LSAPI_Request g_req =
- { .m_fdListen = -1, .m_fd = -1 };
- static char s_secret[24];
- static LSAPI_On_Timer_pf s_proc_group_timer_cb = NULL;
- void Flush_RespBuf_r( LSAPI_Request * pReq );
- static int lsapi_reopen_stderr(const char *p);
- static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] =
- {
- "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET",
- "HTTP_ACCEPT_ENCODING",
- "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHORIZATION",
- "HTTP_CONNECTION", "CONTENT_TYPE",
- "CONTENT_LENGTH", "HTTP_COOKIE", "HTTP_COOKIE2",
- "HTTP_HOST", "HTTP_PRAGMA",
- "HTTP_REFERER", "HTTP_USER_AGENT",
- "HTTP_CACHE_CONTROL",
- "HTTP_IF_MODIFIED_SINCE", "HTTP_IF_MATCH",
- "HTTP_IF_NONE_MATCH",
- "HTTP_IF_RANGE",
- "HTTP_IF_UNMODIFIED_SINCE",
- "HTTP_KEEP_ALIVE",
- "HTTP_RANGE",
- "HTTP_X_FORWARDED_FOR",
- "HTTP_VIA",
- "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 const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] =
- {
- "Accept", "Accept-Charset",
- "Accept-Encoding",
- "Accept-Language", "Authorization",
- "Connection", "Content-Type",
- "Content-Length", "Cookie", "Cookie2",
- "Host", "Pragma",
- "Referer", "User-Agent",
- "Cache-Control",
- "If-Modified-Since", "If-Match",
- "If-None-Match",
- "If-Range",
- "If-Unmodified-Since",
- "Keep-Alive",
- "Range",
- "X-Forwarded-For",
- "Via",
- "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
- 13,17, 8, 13, 8, 19, 10, 5, 15, 3, 17
- };
- static const char *s_log_level_names[8] =
- {
- "", "DEBUG","INFO", "NOTICE", "WARN", "ERROR", "CRIT", "FATAL"
- };
- void LSAPI_Log(int flag, const char * fmt, ...)
- {
- char buf[1024];
- char *p = buf;
- if ((flag & LSAPI_LOG_TIMESTAMP_BITS) &&
- !((flag & LSAPI_LOG_TIMESTAMP_STDERR) && s_stderr_is_pipe))
- {
- struct timeval tv;
- struct tm tm;
- gettimeofday(&tv, NULL);
- localtime_r(&tv.tv_sec, &tm);
- if (flag & LSAPI_LOG_TIMESTAMP_FULL)
- {
- p += snprintf(p, 1024, "%04d-%02d-%02d %02d:%02d:%02d.%06d ",
- tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec, (int)tv.tv_usec);
- }
- else if (flag & LSAPI_LOG_TIMESTAMP_HMS)
- {
- p += snprintf(p, 1024, "%02d:%02d:%02d ",
- tm.tm_hour, tm.tm_min, tm.tm_sec);
- }
- }
- int level = flag & LSAPI_LOG_LEVEL_BITS;
- if (level && level <= LSAPI_LOG_FLAG_FATAL)
- {
- p += snprintf(p, 100, "[%s] ", s_log_level_names[level]);
- }
- if (flag & LSAPI_LOG_PID)
- {
- p += snprintf(p, 100, "[%d] ", s_pid);
- }
- if (p > buf)
- fprintf(stderr, "%.*s", (int)(p - buf), buf);
- va_list ap;
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
- }
- #ifdef LSAPI_DEBUG
- #define DBGLOG_FLAG (LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_FLAG_DEBUG|LSAPI_LOG_PID)
- #define lsapi_dbg(...) LSAPI_Log(DBGLOG_FLAG, __VA_ARGS__)
- #else
- #define lsapi_dbg(...)
- #endif
- #define lsapi_log(...) LSAPI_Log(LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_TIMESTAMP_STDERR|LSAPI_LOG_PID, __VA_ARGS__)
- static int lsapi_parent_dead()
- {
- // Return non-zero if the parent is dead. 0 if still alive.
- if (!s_ppid) {
- // not checking, so not dead
- return(0);
- }
- if (s_restored_ppid) {
- if (kill(s_restored_ppid,0) == -1) {
- if (errno == EPERM) {
- return(0); // no permission, but it's still there.
- }
- return(1); // Dead
- }
- return(0); // it worked, so it's not dead
- }
- return(s_ppid != getppid());
- }
- static void lsapi_sigpipe( int sig )
- {
- }
- static void lsapi_siguser1( int sig )
- {
- g_running = 0;
- }
- #ifndef sighandler_t
- typedef void (*sighandler_t)(int);
- #endif
- static void lsapi_signal(int signo, sighandler_t handler)
- {
- struct sigaction sa;
- sigaction(signo, NULL, &sa);
- if (sa.sa_handler == SIG_DFL)
- {
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sa.sa_handler = handler;
- sigaction(signo, &sa, NULL);
- }
- }
- static int s_enable_core_dump = 0;
- static void lsapi_enable_core_dump(void)
- {
- #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 )
- {
- pHeader->m_versionB0 = LSAPI_VERSION_B0; /* LSAPI protocol version */
- pHeader->m_versionB1 = LSAPI_VERSION_B1;
- pHeader->m_type = type;
- pHeader->m_flag = LSAPI_ENDIAN;
- pHeader->m_packetLen.m_iLen = len;
- }
- static int lsapi_set_nblock( int fd, int nonblock )
- {
- int val = fcntl( fd, F_GETFL, 0 );
- if ( nonblock )
- {
- if (!( val & O_NONBLOCK ))
- {
- return fcntl( fd, F_SETFL, val | O_NONBLOCK );
- }
- }
- else
- {
- if ( val & O_NONBLOCK )
- {
- return fcntl( fd, F_SETFL, val &(~O_NONBLOCK) );
- }
- }
- return 0;
- }
- static int lsapi_close( int fd )
- {
- int ret;
- while( 1 )
- {
- ret = close( fd );
- if (( ret == -1 )&&( errno == EINTR )&&(g_running))
- continue;
- return ret;
- }
- }
- static void lsapi_close_connection(LSAPI_Request *pReq)
- {
- if (pReq->m_fd == -1)
- return;
- lsapi_close(pReq->m_fd);
- pReq->m_fd = -1;
- if (s_busy_workers)
- __sync_fetch_and_sub(s_busy_workers, 1);
- if (s_worker_status)
- __sync_lock_test_and_set(&s_worker_status->m_state, LSAPI_STATE_IDLE);
- }
- static inline ssize_t lsapi_read( int fd, void * pBuf, size_t len )
- {
- ssize_t ret;
- while( 1 )
- {
- ret = read( fd, (char *)pBuf, len );
- 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;
- if (s_skip_write)
- return totalLen;
- while(( left > 0 )&&g_running )
- {
- ret = writev( fd, *pVec, n );
- if ( ret > 0 )
- {
- left -= ret;
- if (( left <= 0)||( !g_running ))
- return totalLen - left;
- while( ret > 0 )
- {
- if ( (*pVec)->iov_len <= (unsigned int )ret )
- {
- ret -= (*pVec)->iov_len;
- ++(*pVec);
- }
- 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 )
- return totalLen - left;
- else
- return -1;
- }
- 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 )
- {
- pReq->m_pReqBuf = pBuf;
- pReq->m_reqBufSize = size;
- pReq->m_pHeader = (struct lsapi_req_header *)pReq->m_pReqBuf;
- return 0;
- }
- return -1;
- }
- static int allocateIovec( LSAPI_Request * pReq, int n )
- {
- struct iovec * p = (struct iovec *)realloc(
- pReq->m_pIovec, sizeof(struct iovec) * n );
- 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;
- pReq->m_pIovecEnd = p + n;
- return 0;
- }
- static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size )
- {
- char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size );
- if ( !p )
- return -1;
- pReq->m_pRespHeaderBufPos = p + ( pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf );
- pReq->m_pRespHeaderBuf = p;
- pReq->m_pRespHeaderBufEnd = p + size;
- return 0;
- }
- static inline int verifyHeader( struct lsapi_packet_header * pHeader, char pktType )
- {
- if (( LSAPI_VERSION_B0 != pHeader->m_versionB0 )||
- ( LSAPI_VERSION_B1 != pHeader->m_versionB1 )||
- ( pktType != pHeader->m_type ))
- return -1;
- 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];
- pHeader->m_packetLen.m_bytes[3] = b;
- b = pHeader->m_packetLen.m_bytes[1];
- pHeader->m_packetLen.m_bytes[1] = pHeader->m_packetLen.m_bytes[2];
- pHeader->m_packetLen.m_bytes[2] = b;
- }
- return pHeader->m_packetLen.m_iLen;
- }
- static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList,
- int *curSize, int newSize )
- {
- struct LSAPI_key_value_pair * pBuf;
- if ( *curSize >= newSize )
- return 0;
- if ( newSize > 8192 )
- return -1;
- pBuf = (struct LSAPI_key_value_pair *)realloc( *pEnvList, newSize *
- sizeof(struct LSAPI_key_value_pair) );
- if ( pBuf )
- {
- *pEnvList = pBuf;
- *curSize = newSize;
- return 0;
- }
- else
- return -1;
- }
- static inline int isPipe( int fd )
- {
- char achPeer[128];
- socklen_t len = 128;
- if (( getpeername( fd, (struct sockaddr *)achPeer, &len ) != 0 )&&
- ( errno == ENOTCONN ))
- return 0;
- 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 )
- return -1;
- pEnvEnd = pEnvList + count;
- 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 )
- return -1;
- if (( !keyLen )||( !valLen ))
- return -1;
- pEnvList->pKey = *pBegin;
- *pBegin += keyLen;
- pEnvList->pValue = *pBegin;
- *pBegin += valLen;
- pEnvList->keyLen = keyLen - 1;
- pEnvList->valLen = valLen - 1;
- ++pEnvList;
- }
- if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 )
- return -1;
- *pBegin += 4;
- return 0;
- }
- static inline void swapIntEndian( int * pInteger )
- {
- char * p = (char *)pInteger;
- register char b;
- b = p[0];
- p[0] = p[3];
- p[3] = b;
- b = p[1];
- p[1] = p[2];
- p[2] = b;
- }
- static inline void fixEndian( LSAPI_Request * pReq )
- {
- struct lsapi_req_header *p= pReq->m_pHeader;
- swapIntEndian( &p->m_httpHeaderLen );
- swapIntEndian( &p->m_reqBodyLen );
- swapIntEndian( &p->m_scriptFileOff );
- swapIntEndian( &p->m_scriptNameOff );
- swapIntEndian( &p->m_queryStringOff );
- swapIntEndian( &p->m_requestMethodOff );
- swapIntEndian( &p->m_cntUnknownHeaders );
- swapIntEndian( &p->m_cntEnv );
- swapIntEndian( &p->m_cntSpecialEnv );
- }
- static void fixHeaderIndexEndian( LSAPI_Request * pReq )
- {
- int 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];
- p[0] = p[1];
- p[1] = b;
- swapIntEndian( &pReq->m_pHeaderIndex->m_headerOff[i] );
- }
- }
- 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 )
- {
- swapIntEndian( &pCur->nameOff );
- swapIntEndian( &pCur->nameLen );
- swapIntEndian( &pCur->valueOff );
- swapIntEndian( &pCur->valueLen );
- ++pCur;
- }
- }
- }
- static int validateHeaders( LSAPI_Request * pReq )
- {
- int totalLen = pReq->m_pHeader->m_httpHeaderLen;
- int i;
- for(i = 0; i < H_TRANSFER_ENCODING; ++i)
- {
- if ( pReq->m_pHeaderIndex->m_headerOff[i] )
- {
- if (pReq->m_pHeaderIndex->m_headerOff[i] > totalLen
- || pReq->m_pHeaderIndex->m_headerLen[i]
- + pReq->m_pHeaderIndex->m_headerOff[i] > totalLen)
- return -1;
- }
- }
- 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 )
- {
- if (pCur->nameOff > totalLen
- || pCur->nameOff + pCur->nameLen > totalLen
- || pCur->valueOff > totalLen
- || pCur->valueOff + pCur->valueLen > totalLen)
- return -1;
- ++pCur;
- }
- }
- return 0;
- }
- 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(void)
- {
- s_liblve = DL_LOAD("liblve.so.0");
- 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(void)
- {
- 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 )
- {
- lsapi_log("LSAPI: failed to open secret file: %s!\n", pSecretFile );
- return -1;
- }
- if ( fstat( fd, &st ) == -1 )
- {
- lsapi_log("LSAPI: failed to check state of file: %s!\n", pSecretFile );
- close( fd );
- return -1;
- }
- /*
- if ( st.st_uid != s_uid )
- {
- lsapi_log("LSAPI: file owner check failure: %s!\n", pSecretFile );
- close( fd );
- return -1;
- }
- */
- if ( st.st_mode & 0077 )
- {
- lsapi_log("LSAPI: file permission check failure: %s\n", pSecretFile );
- close( fd );
- return -1;
- }
- if ( read( fd, s_secret, 16 ) < 16 )
- {
- lsapi_log("LSAPI: failed to read secret from secret file: %s\n", pSecretFile );
- close( fd );
- return -1;
- }
- close( fd );
- return 0;
- }
- int LSAPI_is_suEXEC_Daemon(void)
- {
- if (( !s_uid )&&( s_secret[0] ))
- return 1;
- else
- return 0;
- }
- static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char *pErr2 )
- {
- char achError[4096];
- int n = snprintf(achError, sizeof(achError), "[%d] %s:%s: %s\n", getpid(),
- pErr1, (pErr2)?pErr2:"", strerror(errno));
- if (n > (int)sizeof(achError))
- n = sizeof(achError);
- 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[] =
- "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"
- "<HTML><HEAD>\n<TITLE>508 Resource Limit Is Reached</TITLE>\n"
- "</HEAD><BODY>\n" "<H1>Resource Limit Is Reached</H1>\n"
- "The website is temporarily unable to service your request as it exceeded resource limit.\n"
- "Please try again later.\n"
- "<HR>\n"
- "</BODY></HTML>\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 )
- {
- lsapi_log("enter LVE (%d) : result: %d !\n", 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 )
- {
- lsapi_log("LSAPI: LVE jail(%d) result: %d, error: %s !\n",
- 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(void)
- {
- 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_secret, 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 *pStderrLog;
- 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 );
- //lsapi_log("LSAPI: SUEXEC_UGID set UID: %d, GID: %d\n", uid, gid );
- }
- else
- {
- lsapi_log("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
- lsapi_log("LSAPI: SUEXEC_AUTH authentication failed, use default user!\n" );
- uid = 0;
- }
- }
- else
- {
- //lsapi_log("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;
- if ( pReq->m_fdListen != -1 )
- {
- close( pReq->m_fdListen );
- pReq->m_fdListen = -1;
- }
- pStderrLog = LSAPI_GetEnv_r( pReq, "LSAPI_STDERR_LOG");
- if (pStderrLog)
- lsapi_reopen_stderr(pStderrLog);
- 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;
- char * pBegin = pReq->m_pReqBuf + sizeof( struct lsapi_req_header );
- char * pEnd = pReq->m_pReqBuf + totalLen;
- shouldFixEndian = ( LSAPI_ENDIAN != (
- pReq->m_pHeader->m_pktHeader.m_flag & LSAPI_ENDIAN_BIT ) );
- 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 )
- return -1;
- if ( (pReq->m_envListSize < pReq->m_pHeader->m_cntEnv )&&
- allocateEnvList( &pReq->m_pEnvList, &pReq->m_envListSize,
- pReq->m_pHeader->m_cntEnv ) == -1 )
- return -1;
- if ( parseEnv( pReq->m_pSpecialEnvList,
- pReq->m_pHeader->m_cntSpecialEnv,
- &pBegin, pEnd ) == -1 )
- return -1;
- if ( parseEnv( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
- &pBegin, pEnd ) == -1 )
- return -1;
- if (pReq->m_pHeader->m_scriptFileOff < 0
- || pReq->m_pHeader->m_scriptFileOff >= totalLen
- || pReq->m_pHeader->m_scriptNameOff < 0
- || pReq->m_pHeader->m_scriptNameOff >= totalLen
- || pReq->m_pHeader->m_queryStringOff < 0
- || pReq->m_pHeader->m_queryStringOff >= totalLen
- || pReq->m_pHeader->m_requestMethodOff < 0
- || pReq->m_pHeader->m_requestMethodOff >= totalLen)
- {
- lsapi_log("Bad request header - ERROR#1\n");
- 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;
- pReq->m_pRequestMethod = pReq->m_pReqBuf + pReq->m_pHeader->m_requestMethodOff;
- pBegin = pReq->m_pReqBuf + (( pBegin - pReq->m_pReqBuf + 7 ) & (~0x7));
- pReq->m_pHeaderIndex = ( struct lsapi_http_header_index * )pBegin;
- pBegin += sizeof( struct lsapi_http_header_index );
- pReq->m_pUnknownHeader = (struct lsapi_header_offset *)pBegin;
- pBegin += sizeof( struct lsapi_header_offset) *
- pReq->m_pHeader->m_cntUnknownHeaders;
- pReq->m_pHttpHeader = pBegin;
- pBegin += pReq->m_pHeader->m_httpHeaderLen;
- if ( pBegin != pEnd )
- {
- lsapi_log("Request header does match total size, total: %d, "
- "real: %ld\n", totalLen, pBegin - pReq->m_pReqBuf );
- return -1;
- }
- if ( shouldFixEndian )
- {
- fixHeaderIndexEndian( pReq );
- }
- if (validateHeaders(pReq) == -1)
- {
- lsapi_log("Bad request header - ERROR#2\n");
- return -1;
- }
- pReq->m_reqBodyLen = pReq->m_pHeader->m_reqBodyLen;
- if ( pReq->m_reqBodyLen == -2 )
- {
- parseContentLenFromHeader(pReq);
- }
- return 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 s_ack = {'L', 'S',
- LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
- static struct lsapi_packet_header s_conn_close_pkt = {'L', 'S',
- LSAPI_CONN_CLOSE, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
- static inline int send_notification_pkt( int fd, struct lsapi_packet_header *pkt )
- {
- if ( write( fd, pkt, LSAPI_PACKET_HEADER_LEN ) < LSAPI_PACKET_HEADER_LEN )
- return -1;
- return 0;
- }
- static inline int send_req_received_notification( int fd )
- {
- return send_notification_pkt(fd, &s_ack);
- }
- static inline int send_conn_close_notification( int fd )
- {
- return send_notification_pkt(fd, &s_conn_close_pkt);
- }
- //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(void)
- {
- 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 send_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 )
- return -1;
- if ( pReq->m_reqBufSize < 8192 )
- {
- if ( allocateBuf( pReq, 8192 ) == -1 )
- return -1;
- }
- while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN )
- {
- len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf, pReq->m_reqBufSize );
- 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 )
- {
- lsapi_log("packetLen < 0\n");
- return -1;
- }
- if ( packetLen > LSAPI_MAX_HEADER_LEN )
- {
- lsapi_log("packetLen > %d\n", LSAPI_MAX_HEADER_LEN );
- return -1;
- }
- if ( packetLen + 1024 > pReq->m_reqBufSize )
- {
- if ( allocateBuf( pReq, packetLen + 1024 ) == -1 )
- return -1;
- }
- while( packetLen > pReq->m_bufRead )
- {
- len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, packetLen - pReq->m_bufRead );
- if ( len <= 0 )
- return -1;
- pReq->m_bufRead += len;
- }
- if ( parseRequest( pReq, packetLen ) < 0 )
- {
- lsapi_log("ParseRequest error\n");
- return -1;
- }
- pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER;
- if ( !s_uid )
- {
- if ( lsapi_changeUGid( pReq ) )
- return -1;
- memset(s_secret, 0, sizeof(s_secret));
- }
- 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 )
- {
- s_uid = geteuid();
- s_secret[0] = 0;
- lsapi_signal(SIGPIPE, lsapi_sigpipe);
- lsapi_signal(SIGUSR1, lsapi_siguser1);
- #if defined(SIGXFSZ) && defined(SIG_IGN)
- signal(SIGXFSZ, SIG_IGN);
- #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 )
- return -1;
- g_inited = 1;
- s_ppid = getppid();
- void *pthread_lib = dlopen("libpthread.so", RTLD_LAZY);
- if (pthread_lib)
- pthread_atfork_func = dlsym(pthread_lib, "pthread_atfork");
- }
- return 0;
- }
- void LSAPI_Stop(void)
- {
- g_running = 0;
- }
- int LSAPI_IsRunning(void)
- {
- return g_running;
- }
- void LSAPI_Register_Pgrp_Timer_Callback(LSAPI_On_Timer_pf cb)
- {
- s_proc_group_timer_cb = cb;
- }
- int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
- {
- int newfd;
- if ( !pReq )
- return -1;
- memset( pReq, 0, sizeof( LSAPI_Request ) );
- if ( allocateIovec( pReq, 16 ) == -1 )
- return -1;
- pReq->m_pRespBuf = pReq->m_pRespBufPos = (char *)malloc( LSAPI_RESP_BUF_SIZE );
- 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 )
- return -1;
- if ( fd == STDIN_FILENO )
- {
- fd = dup( fd );
- newfd = open( "/dev/null", O_RDWR );
- dup2( newfd, STDIN_FILENO );
- }
- if ( isPipe( fd ) )
- {
- pReq->m_fdListen = -1;
- pReq->m_fd = fd;
- }
- else
- {
- pReq->m_fdListen = fd;
- pReq->m_fd = -1;
- lsapi_set_nblock( fd, 1 );
- }
- return 0;
- }
- int LSAPI_Is_Listen( void )
- {
- return LSAPI_Is_Listen_r( &g_req );
- }
- int LSAPI_Is_Listen_r( LSAPI_Request * pReq)
- {
- return pReq->m_fdListen != -1;
- }
- int LSAPI_Accept_r( LSAPI_Request * pReq )
- {
- char achPeer[128];
- socklen_t len;
- int nodelay = 1;
- if ( !pReq )
- return -1;
- if ( LSAPI_Finish_r( pReq ) == -1 )
- return -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))
- continue;
- else
- return -1;
- }
- else
- {
- if (s_worker_status)
- __sync_lock_test_and_set(&s_worker_status->m_state,
- LSAPI_STATE_CONNECTED);
- if (s_busy_workers)
- __sync_fetch_and_add(s_busy_workers, 1);
- lsapi_set_nblock( pReq->m_fd , 0 );
- if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
- {
- setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY,
- (char *)&nodelay, sizeof(nodelay));
- }
- //init_conn_key( pReq->m_fd );
- //OPTIMIZATION
- if ( s_accept_notify )
- if ( notify_req_received( pReq->m_fd ) == -1 )
- return -1;
- }
- }
- else
- return -1;
- }
- if ( !readReq( pReq ) )
- break;
- //abort();
- lsapi_close_connection(pReq);
- LSAPI_Reset_r( pReq );
- }
- return 0;
- }
- static struct lsapi_packet_header finish_close[2] =
- {
- {'L', 'S', LSAPI_RESP_END, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} },
- {'L', 'S', LSAPI_CONN_CLOSE, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} }
- };
- int LSAPI_Finish_r( LSAPI_Request * pReq )
- {
- /* finish req body */
- if ( !pReq )
- return -1;
- 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 )
- {
- Flush_RespBuf_r( pReq );
- }
- pReq->m_pIovecCur->iov_base = (void *)finish_close;
- pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN;
- pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN;
- ++pReq->m_pIovecCur;
- LSAPI_Flush_r( pReq );
- }
- LSAPI_Reset_r( pReq );
- }
- return 0;
- }
- int LSAPI_End_Response_r(LSAPI_Request * pReq)
- {
- if (!pReq)
- return -1;
- if (pReq->m_reqState & LSAPI_ST_BACKGROUND)
- return 0;
- if (pReq->m_reqState)
- {
- if ( pReq->m_fd != -1 )
- {
- if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
- {
- if ( pReq->m_pRespHeaderBufPos <= pReq->m_pRespHeaderBuf )
- return 0;
- LSAPI_FinalizeRespHeaders_r( pReq );
- }
- if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
- {
- Flush_RespBuf_r( pReq );
- }
- pReq->m_pIovecCur->iov_base = (void *)finish_close;
- pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN << 1;
- pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN << 1;
- ++pReq->m_pIovecCur;
- LSAPI_Flush_r( pReq );
- lsapi_close_connection(pReq);
- }
- pReq->m_reqState |= LSAPI_ST_BACKGROUND;
- }
- return 0;
- }
- void LSAPI_Reset_r( LSAPI_Request * pReq )
- {
- pReq->m_pRespBufPos = pReq->m_pRespBuf;
- pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
- pReq->m_pRespHeaderBufPos = pReq->m_pRespHeaderBuf;
- memset( &pReq->m_pHeaderIndex, 0,
- (char *)(pReq->m_respHeaderLen) - (char *)&pReq->m_pHeaderIndex );
- }
- int LSAPI_Release_r( LSAPI_Request * pReq )
- {
- if ( pReq->m_pReqBuf )
- free( pReq->m_pReqBuf );
- if ( pReq->m_pSpecialEnvList )
- free( pReq->m_pSpecialEnvList );
- if ( pReq->m_pEnvList )
- free( pReq->m_pEnvList );
- if ( pReq->m_pRespHeaderBuf )
- free( pReq->m_pRespHeaderBuf );
- return 0;
- }
- char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex )
- {
- int off;
- if ( !pReq || ((unsigned int)headerIndex > H_TRANSFER_ENCODING) )
- return NULL;
- off = pReq->m_pHeaderIndex->m_headerOff[ headerIndex ];
- 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;
- }
- return pReq->m_pHttpHeader + off;
- }
- static int readBodyToReqBuf( LSAPI_Request * pReq )
- {
- 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_reqBodyLen - pReq->m_reqBodyRead;
- len = pReq->m_reqBufSize - pReq->m_bufRead;
- if ( len < 0 )
- return -1;
- if ( len > bodyLeft )
- len = bodyLeft;
- len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, len );
- if ( len > 0 )
- pReq->m_bufRead += len;
- return len;
- }
- int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq )
- {
- if (!pReq || (pReq->m_fd ==-1) )
- return EOF;
- 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++);
- }
- int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF )
- {
- 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 || !getLF)
- return -1;
- *getLF = 0;
- while( (left = pBufEnd - pBufCur ) > 0 )
- {
- len = pReq->m_bufRead - pReq->m_bufProcessed;
- if ( len <= 0 )
- {
- if ( (len = readBodyToReqBuf( pReq )) <= 0 )
- {
- *getLF = 1;
- break;
- }
- }
- if ( len > left )
- len = left;
- pCur = pReq->m_pReqBuf + pReq->m_bufProcessed;
- p = memchr( pCur, '\n', len );
- if ( p )
- len = p - pCur + 1;
- memmove( pBufCur, pCur, len );
- pBufCur += len;
- pReq->m_bufProcessed += len;
- pReq->m_reqBodyRead += len;
- if ( p )
- {
- *getLF = 1;
- break;
- }
- }
- *pBufCur = 0;
- return pBufCur - pBuf;
- }
- ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen )
- {
- ssize_t len;
- off_t total;
- /* char *pOldBuf = pBuf; */
- if (!pReq || pReq->m_fd == -1 || !pBuf || (ssize_t)bufLen < 0)
- return -1;
- total = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
- if ( total <= 0 )
- return 0;
- if ( total < (ssize_t)bufLen )
- bufLen = total;
- total = 0;
- len = pReq->m_bufRead - pReq->m_bufProcessed;
- if ( len > 0 )
- {
- if ( len > (ssize_t)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 )
- {
- len = lsapi_read( pReq->m_fd, pBuf, bufLen );
- if ( len > 0 )
- {
- total += len;
- pBuf += len;
- bufLen -= len;
- }
- else if ( len <= 0 )
- {
- if ( !total)
- return -1;
- break;
- }
- }
- pReq->m_reqBodyRead += total;
- return total;
- }
- 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;
- ssize_t bufLen;
- ssize_t toWrite;
- ssize_t packetLen;
- int skip = 0;
- if (!pReq || !pBuf)
- return -1;
- if (pReq->m_reqState & LSAPI_ST_BACKGROUND)
- return len;
- if (pReq->m_fd == -1)
- return -1;
- if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
- {
- LSAPI_…
Large files files are truncated, but you can click here to view the full file