Annotation of embedaddon/php/sapi/litespeed/lsapilib.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | PHP Version 5 |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 1997-2007 The PHP Group |
! 6: +----------------------------------------------------------------------+
! 7: | This source file is subject to version 3.01 of the PHP license, |
! 8: | that is bundled with this package in the file LICENSE, and is |
! 9: | available at through the world-wide-web at the following url: |
! 10: | http://www.php.net/license/3_01.txt. |
! 11: | If you did not receive a copy of the PHP license and are unable to |
! 12: | obtain it through the world-wide-web, please send a note to |
! 13: | license@php.net so we can mail you a copy immediately. |
! 14: +----------------------------------------------------------------------+
! 15: | Author: George Wang <gwang@litespeedtech.com> |
! 16: +----------------------------------------------------------------------+
! 17: */
! 18:
! 19: /* $Id: lsapilib.c 311935 2011-06-08 16:51:59Z gwang $ */
! 20:
! 21: /*
! 22: Copyright (c) 2007, Lite Speed Technologies Inc.
! 23: All rights reserved.
! 24:
! 25: Redistribution and use in source and binary forms, with or without
! 26: modification, are permitted provided that the following conditions are
! 27: met:
! 28:
! 29: * Redistributions of source code must retain the above copyright
! 30: notice, this list of conditions and the following disclaimer.
! 31: * Redistributions in binary form must reproduce the above
! 32: copyright notice, this list of conditions and the following
! 33: disclaimer in the documentation and/or other materials provided
! 34: with the distribution.
! 35: * Neither the name of the Lite Speed Technologies Inc nor the
! 36: names of its contributors may be used to endorse or promote
! 37: products derived from this software without specific prior
! 38: written permission.
! 39:
! 40: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
! 41: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
! 42: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
! 43: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
! 44: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
! 45: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
! 46: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 47: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 48: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 49: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
! 50: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 51: */
! 52:
! 53: #include <lsapilib.h>
! 54:
! 55: #include <ctype.h>
! 56: #include <errno.h>
! 57: #include <fcntl.h>
! 58:
! 59: #include <arpa/inet.h>
! 60: #include <netdb.h>
! 61: #include <netinet/in.h>
! 62: #include <netinet/tcp.h>
! 63: #include <sys/un.h>
! 64: #include <signal.h>
! 65: #include <stdlib.h>
! 66: #include <stdio.h>
! 67: #include <string.h>
! 68: #include <sys/mman.h>
! 69: #include <sys/resource.h>
! 70: #include <sys/socket.h>
! 71: #include <sys/time.h>
! 72: #include <sys/uio.h>
! 73: #include <sys/wait.h>
! 74: #include <time.h>
! 75: #include <unistd.h>
! 76:
! 77: #define LSAPI_ST_REQ_HEADER 1
! 78: #define LSAPI_ST_REQ_BODY 2
! 79: #define LSAPI_ST_RESP_HEADER 4
! 80: #define LSAPI_ST_RESP_BODY 8
! 81:
! 82: #define LSAPI_RESP_BUF_SIZE 8192
! 83: #define LSAPI_INIT_RESP_HEADER_LEN 4096
! 84:
! 85:
! 86: static int g_inited = 0;
! 87: static int g_running = 1;
! 88: static int s_ppid;
! 89: static int s_slow_req_msecs = 0;
! 90: LSAPI_Request g_req = { -1, -1 };
! 91:
! 92: void Flush_RespBuf_r( LSAPI_Request * pReq );
! 93:
! 94: static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] =
! 95: {
! 96: "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET",
! 97: "HTTP_ACCEPT_ENCODING",
! 98: "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHORIZATION",
! 99: "HTTP_CONNECTION", "CONTENT_TYPE",
! 100: "CONTENT_LENGTH", "HTTP_COOKIE", "HTTP_COOKIE2",
! 101: "HTTP_HOST", "HTTP_PRAGMA",
! 102: "HTTP_REFERER", "HTTP_USER_AGENT",
! 103: "HTTP_CACHE_CONTROL",
! 104: "HTTP_IF_MODIFIED_SINCE", "HTTP_IF_MATCH",
! 105: "HTTP_IF_NONE_MATCH",
! 106: "HTTP_IF_RANGE",
! 107: "HTTP_IF_UNMODIFIED_SINCE",
! 108: "HTTP_KEEP_ALIVE",
! 109: "HTTP_RANGE",
! 110: "HTTP_X_FORWARDED_FOR",
! 111: "HTTP_VIA",
! 112: "HTTP_TRANSFER_ENCODING"
! 113: };
! 114:
! 115: static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] = {
! 116: 11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 18,
! 117: 22, 13, 18, 13, 24, 15, 10, 20, 8, 22
! 118: };
! 119:
! 120:
! 121: static const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] = {
! 122: "Accept", "Accept-Charset",
! 123: "Accept-Encoding",
! 124: "Accept-Language", "Authorization",
! 125: "Connection", "Content-Type",
! 126: "Content-Length", "Cookie", "Cookie2",
! 127: "Host", "Pragma",
! 128: "Referer", "User-Agent",
! 129: "Cache-Control",
! 130: "If-Modified-Since", "If-Match",
! 131: "If-None-Match",
! 132: "If-Range",
! 133: "If-Unmodified-Since",
! 134: "Keep-Alive",
! 135: "Range",
! 136: "X-Forwarded-For",
! 137: "Via",
! 138: "Transfer-Encoding"
! 139: };
! 140:
! 141: static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] = {
! 142: 6, 14, 15, 15, 13, 10, 12, 14, 6, 7, 4, 6, 7, 10, /* user-agent */
! 143: 13,17, 8, 13, 8, 19, 10, 5, 15, 3, 17
! 144: };
! 145:
! 146: static void lsapi_sigpipe( int sig )
! 147: {
! 148: }
! 149: static void lsapi_siguser1( int sig )
! 150: {
! 151: g_running = 0;
! 152: }
! 153:
! 154: #ifndef sighandler_t
! 155: typedef void (*sighandler_t)(int);
! 156: #endif
! 157:
! 158: static void lsapi_signal(int signo, sighandler_t handler)
! 159: {
! 160: struct sigaction sa;
! 161:
! 162: sigaction(signo, NULL, &sa);
! 163:
! 164: if (sa.sa_handler == SIG_DFL) {
! 165: sigemptyset(&sa.sa_mask);
! 166: sa.sa_flags = 0;
! 167: sa.sa_handler = handler;
! 168: sigaction(signo, &sa, NULL);
! 169: }
! 170: }
! 171:
! 172:
! 173: static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader,
! 174: char type, int len )
! 175: {
! 176: pHeader->m_versionB0 = LSAPI_VERSION_B0; /* LSAPI protocol version */
! 177: pHeader->m_versionB1 = LSAPI_VERSION_B1;
! 178: pHeader->m_type = type;
! 179: pHeader->m_flag = LSAPI_ENDIAN;
! 180: pHeader->m_packetLen.m_iLen = len;
! 181: }
! 182:
! 183: static int lsapi_set_nblock( int fd, int nonblock )
! 184: {
! 185: int val = fcntl( fd, F_GETFL, 0 );
! 186: if ( nonblock )
! 187: {
! 188: if (!( val & O_NONBLOCK ))
! 189: {
! 190: return fcntl( fd, F_SETFL, val | O_NONBLOCK );
! 191: }
! 192: }
! 193: else
! 194: {
! 195: if ( val & O_NONBLOCK )
! 196: {
! 197: return fcntl( fd, F_SETFL, val &(~O_NONBLOCK) );
! 198: }
! 199: }
! 200: return 0;
! 201: }
! 202:
! 203:
! 204: static int lsapi_close( int fd )
! 205: {
! 206: int ret;
! 207: while( 1 ) {
! 208: ret = close( fd );
! 209: if (( ret == -1 )&&( errno == EINTR )&&(g_running)) {
! 210: continue;
! 211: }
! 212: return ret;
! 213: }
! 214: }
! 215:
! 216: static inline int lsapi_read( int fd, void * pBuf, int len )
! 217: {
! 218: int ret;
! 219: while( 1 ) {
! 220: ret = read( fd, (char *)pBuf, len );
! 221: if (( ret == -1 )&&( errno == EINTR )&&(g_running)) {
! 222: continue;
! 223: }
! 224: return ret;
! 225: }
! 226: }
! 227:
! 228:
! 229: static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen )
! 230: {
! 231: int ret;
! 232: int left = totalLen;
! 233: int n = count;
! 234: while(( left > 0 )&&g_running ) {
! 235: ret = writev( fd, *pVec, n );
! 236: if ( ret > 0 ) {
! 237: left -= ret;
! 238: if (( left <= 0)||( !g_running )) {
! 239: return totalLen - left;
! 240: }
! 241: while( ret > 0 ) {
! 242: if ( (*pVec)->iov_len <= ret ) {
! 243: ret -= (*pVec)->iov_len;
! 244: ++(*pVec);
! 245: } else {
! 246: (*pVec)->iov_base = (char *)(*pVec)->iov_base + ret;
! 247: (*pVec)->iov_len -= ret;
! 248: break;
! 249: }
! 250: }
! 251: } else if ( ret == -1 ) {
! 252: if ( errno == EAGAIN ) {
! 253: if ( totalLen - left > 0 ) {
! 254: return totalLen - left;
! 255: } else {
! 256: return -1;
! 257: }
! 258: } else {
! 259: if ( errno != EINTR ) {
! 260: return ret;
! 261: }
! 262: }
! 263: }
! 264: }
! 265: return totalLen - left;
! 266: }
! 267:
! 268: static inline int allocateBuf( LSAPI_Request * pReq, int size )
! 269: {
! 270: char * pBuf = (char *)realloc( pReq->m_pReqBuf, size );
! 271: if ( pBuf ) {
! 272: pReq->m_pReqBuf = pBuf;
! 273: pReq->m_reqBufSize = size;
! 274: pReq->m_pHeader = (struct lsapi_req_header *)pReq->m_pReqBuf;
! 275: return 0;
! 276: }
! 277: return -1;
! 278: }
! 279:
! 280:
! 281: static int allocateIovec( LSAPI_Request * pReq, int n )
! 282: {
! 283: struct iovec * p = (struct iovec *)realloc(
! 284: pReq->m_pIovec, sizeof(struct iovec) * n );
! 285: if ( !p ) {
! 286: return -1;
! 287: }
! 288: pReq->m_pIovecToWrite = p + ( pReq->m_pIovecToWrite - pReq->m_pIovec );
! 289: pReq->m_pIovecCur = p + ( pReq->m_pIovecCur - pReq->m_pIovec );
! 290: pReq->m_pIovec = p;
! 291: pReq->m_pIovecEnd = p + n;
! 292: return 0;
! 293: }
! 294:
! 295: static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size )
! 296: {
! 297: char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size );
! 298: if ( !p ) {
! 299: return -1;
! 300: }
! 301: pReq->m_pRespHeaderBufPos = p + ( pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf );
! 302: pReq->m_pRespHeaderBuf = p;
! 303: pReq->m_pRespHeaderBufEnd = p + size;
! 304: return 0;
! 305: }
! 306:
! 307:
! 308: static inline int verifyHeader( struct lsapi_packet_header * pHeader, char pktType )
! 309: {
! 310: if (( LSAPI_VERSION_B0 != pHeader->m_versionB0 )||
! 311: ( LSAPI_VERSION_B1 != pHeader->m_versionB1 )||
! 312: ( pktType != pHeader->m_type )) {
! 313: return -1;
! 314: }
! 315: if ( LSAPI_ENDIAN != (pHeader->m_flag & LSAPI_ENDIAN_BIT )) {
! 316: register char b;
! 317: b = pHeader->m_packetLen.m_bytes[0];
! 318: pHeader->m_packetLen.m_bytes[0] = pHeader->m_packetLen.m_bytes[3];
! 319: pHeader->m_packetLen.m_bytes[3] = b;
! 320: b = pHeader->m_packetLen.m_bytes[1];
! 321: pHeader->m_packetLen.m_bytes[1] = pHeader->m_packetLen.m_bytes[2];
! 322: pHeader->m_packetLen.m_bytes[2] = b;
! 323: }
! 324: return pHeader->m_packetLen.m_iLen;
! 325: }
! 326:
! 327: static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList,
! 328: int *curSize, int newSize )
! 329: {
! 330: struct LSAPI_key_value_pair * pBuf;
! 331: if ( *curSize >= newSize ) {
! 332: return 0;
! 333: }
! 334: if ( newSize > 8192 ) {
! 335: return -1;
! 336: }
! 337: pBuf = (struct LSAPI_key_value_pair *)realloc( *pEnvList, newSize *
! 338: sizeof(struct LSAPI_key_value_pair) );
! 339: if ( pBuf ) {
! 340: *pEnvList = pBuf;
! 341: *curSize = newSize;
! 342: return 0;
! 343: } else {
! 344: return -1;
! 345: }
! 346:
! 347: }
! 348:
! 349: static inline int isPipe( int fd )
! 350: {
! 351: char achPeer[128];
! 352: socklen_t len = 128;
! 353: if (( getpeername( fd, (struct sockaddr *)achPeer, &len ) != 0 )&&
! 354: ( errno == ENOTCONN )) {
! 355: return 0;
! 356: } else {
! 357: return 1;
! 358: }
! 359: }
! 360:
! 361: static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count,
! 362: char **pBegin, char * pEnd )
! 363: {
! 364: struct LSAPI_key_value_pair * pEnvEnd;
! 365: int keyLen = 0, valLen = 0;
! 366: if ( count > 8192 ) {
! 367: return -1;
! 368: }
! 369: pEnvEnd = pEnvList + count;
! 370: while( pEnvList != pEnvEnd ) {
! 371: if ( pEnd - *pBegin < 4 ) {
! 372: return -1;
! 373: }
! 374: keyLen = *((unsigned char *)((*pBegin)++));
! 375: keyLen = (keyLen << 8) + *((unsigned char *)((*pBegin)++));
! 376: valLen = *((unsigned char *)((*pBegin)++));
! 377: valLen = (valLen << 8) + *((unsigned char *)((*pBegin)++));
! 378: if ( *pBegin + keyLen + valLen > pEnd ) {
! 379: return -1;
! 380: }
! 381: if (( !keyLen )||( !valLen )) {
! 382: return -1;
! 383: }
! 384:
! 385: pEnvList->pKey = *pBegin;
! 386: *pBegin += keyLen;
! 387: pEnvList->pValue = *pBegin;
! 388: *pBegin += valLen;
! 389:
! 390: pEnvList->keyLen = keyLen - 1;
! 391: pEnvList->valLen = valLen - 1;
! 392: ++pEnvList;
! 393: }
! 394: if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 ) {
! 395: return -1;
! 396: }
! 397: *pBegin += 4;
! 398: return 0;
! 399: }
! 400:
! 401: static inline void swapIntEndian( int * pInteger )
! 402: {
! 403: char * p = (char *)pInteger;
! 404: register char b;
! 405: b = p[0];
! 406: p[0] = p[3];
! 407: p[3] = b;
! 408: b = p[1];
! 409: p[1] = p[2];
! 410: p[2] = b;
! 411:
! 412: }
! 413:
! 414: static inline void fixEndian( LSAPI_Request * pReq )
! 415: {
! 416: struct lsapi_req_header *p= pReq->m_pHeader;
! 417: swapIntEndian( &p->m_httpHeaderLen );
! 418: swapIntEndian( &p->m_reqBodyLen );
! 419: swapIntEndian( &p->m_scriptFileOff );
! 420: swapIntEndian( &p->m_scriptNameOff );
! 421: swapIntEndian( &p->m_queryStringOff );
! 422: swapIntEndian( &p->m_requestMethodOff );
! 423: swapIntEndian( &p->m_cntUnknownHeaders );
! 424: swapIntEndian( &p->m_cntEnv );
! 425: swapIntEndian( &p->m_cntSpecialEnv );
! 426: }
! 427:
! 428: static void fixHeaderIndexEndian( LSAPI_Request * pReq )
! 429: {
! 430: int i;
! 431: for( i = 0; i < H_TRANSFER_ENCODING; ++i ) {
! 432: if ( pReq->m_pHeaderIndex->m_headerOff[i] ) {
! 433: register char b;
! 434: char * p = (char *)(&pReq->m_pHeaderIndex->m_headerLen[i]);
! 435: b = p[0];
! 436: p[0] = p[1];
! 437: p[1] = b;
! 438: swapIntEndian( &pReq->m_pHeaderIndex->m_headerOff[i] );
! 439: }
! 440: }
! 441: if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) {
! 442: struct lsapi_header_offset * pCur, *pEnd;
! 443: pCur = pReq->m_pUnknownHeader;
! 444: pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
! 445: while( pCur < pEnd ) {
! 446: swapIntEndian( &pCur->nameOff );
! 447: swapIntEndian( &pCur->nameLen );
! 448: swapIntEndian( &pCur->valueOff );
! 449: swapIntEndian( &pCur->valueLen );
! 450: ++pCur;
! 451: }
! 452: }
! 453: }
! 454:
! 455: static int parseRequest( LSAPI_Request * pReq, int totalLen )
! 456: {
! 457: int shouldFixEndian;
! 458: char * pBegin = pReq->m_pReqBuf + sizeof( struct lsapi_req_header );
! 459: char * pEnd = pReq->m_pReqBuf + totalLen;
! 460: shouldFixEndian = ( LSAPI_ENDIAN != (
! 461: pReq->m_pHeader->m_pktHeader.m_flag & LSAPI_ENDIAN_BIT ) );
! 462: if ( shouldFixEndian ) {
! 463: fixEndian( pReq );
! 464: }
! 465: if ( (pReq->m_specialEnvListSize < pReq->m_pHeader->m_cntSpecialEnv )&&
! 466: allocateEnvList( &pReq->m_pSpecialEnvList,
! 467: &pReq->m_specialEnvListSize,
! 468: pReq->m_pHeader->m_cntSpecialEnv ) == -1 ) {
! 469: return -1;
! 470: }
! 471: if ( (pReq->m_envListSize < pReq->m_pHeader->m_cntEnv )&&
! 472: allocateEnvList( &pReq->m_pEnvList, &pReq->m_envListSize,
! 473: pReq->m_pHeader->m_cntEnv ) == -1 ) {
! 474: return -1;
! 475: }
! 476: if ( parseEnv( pReq->m_pSpecialEnvList,
! 477: pReq->m_pHeader->m_cntSpecialEnv,
! 478: &pBegin, pEnd ) == -1 ) {
! 479: return -1;
! 480: }
! 481: if ( parseEnv( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
! 482: &pBegin, pEnd ) == -1 ) {
! 483: return -1;
! 484: }
! 485: pReq->m_pScriptFile = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptFileOff;
! 486: pReq->m_pScriptName = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptNameOff;
! 487: pReq->m_pQueryString = pReq->m_pReqBuf + pReq->m_pHeader->m_queryStringOff;
! 488: pReq->m_pRequestMethod = pReq->m_pReqBuf + pReq->m_pHeader->m_requestMethodOff;
! 489:
! 490: pBegin = pReq->m_pReqBuf + (( pBegin - pReq->m_pReqBuf + 7 ) & (~0x7));
! 491: pReq->m_pHeaderIndex = ( struct lsapi_http_header_index * )pBegin;
! 492: pBegin += sizeof( struct lsapi_http_header_index );
! 493:
! 494: pReq->m_pUnknownHeader = (struct lsapi_header_offset *)pBegin;
! 495: pBegin += sizeof( struct lsapi_header_offset) *
! 496: pReq->m_pHeader->m_cntUnknownHeaders;
! 497:
! 498: pReq->m_pHttpHeader = pBegin;
! 499: pBegin += pReq->m_pHeader->m_httpHeaderLen;
! 500: if ( pBegin != pEnd ) {
! 501: return -1;
! 502: }
! 503:
! 504: if ( shouldFixEndian ) {
! 505: fixHeaderIndexEndian( pReq );
! 506: }
! 507:
! 508: return 0;
! 509: }
! 510:
! 511: static int s_accept_notify = 0;
! 512:
! 513: static struct lsapi_packet_header ack = {'L', 'S',
! 514: LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
! 515: static inline int notify_req_received( int fd )
! 516: {
! 517: if ( write( fd, &ack, LSAPI_PACKET_HEADER_LEN )
! 518: < LSAPI_PACKET_HEADER_LEN ) {
! 519: return -1;
! 520: }
! 521: return 0;
! 522: }
! 523:
! 524:
! 525: static int readReq( LSAPI_Request * pReq )
! 526: {
! 527: int len;
! 528: int packetLen;
! 529: if ( !pReq ) {
! 530: return -1;
! 531: }
! 532: if ( pReq->m_reqBufSize < 8192 ) {
! 533: if ( allocateBuf( pReq, 8192 ) == -1 ) {
! 534: return -1;
! 535: }
! 536: }
! 537:
! 538: while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN ) {
! 539: len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf, pReq->m_reqBufSize );
! 540: if ( len <= 0 ) {
! 541: return -1;
! 542: }
! 543: pReq->m_bufRead += len;
! 544: }
! 545: pReq->m_reqState = LSAPI_ST_REQ_HEADER;
! 546:
! 547: packetLen = verifyHeader( &pReq->m_pHeader->m_pktHeader, LSAPI_BEGIN_REQUEST );
! 548: if ( packetLen < 0 ) {
! 549: return -1;
! 550: }
! 551: if ( packetLen > LSAPI_MAX_HEADER_LEN ) {
! 552: return -1;
! 553: }
! 554:
! 555: if ( packetLen + 1024 > pReq->m_reqBufSize ) {
! 556: if ( allocateBuf( pReq, packetLen + 1024 ) == -1 ) {
! 557: return -1;
! 558: }
! 559: }
! 560: while( packetLen > pReq->m_bufRead ) {
! 561: len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, packetLen - pReq->m_bufRead );
! 562: if ( len <= 0 ) {
! 563: return -1;
! 564: }
! 565: pReq->m_bufRead += len;
! 566: }
! 567: if ( parseRequest( pReq, packetLen ) < 0 ) {
! 568: return -1;
! 569: }
! 570: pReq->m_bufProcessed = packetLen;
! 571: pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER;
! 572:
! 573: if ( !s_accept_notify )
! 574: return notify_req_received( pReq->m_fd );
! 575: else
! 576: return 0;
! 577: }
! 578:
! 579:
! 580:
! 581: int LSAPI_Init(void)
! 582: {
! 583: if ( !g_inited ) {
! 584: lsapi_signal(SIGPIPE, lsapi_sigpipe);
! 585: lsapi_signal(SIGUSR1, lsapi_siguser1);
! 586:
! 587: #if defined(SIGXFSZ) && defined(SIG_IGN)
! 588: signal(SIGXFSZ, SIG_IGN);
! 589: #endif
! 590: /* let STDOUT function as STDERR,
! 591: just in case writing to STDOUT directly */
! 592: dup2( 2, 1 );
! 593:
! 594: if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 ) {
! 595: return -1;
! 596: }
! 597: g_inited = 1;
! 598: s_ppid = getppid();
! 599: }
! 600: return 0;
! 601: }
! 602:
! 603: void LSAPI_Stop(void)
! 604: {
! 605: g_running = 0;
! 606: }
! 607:
! 608: int LSAPI_IsRunning(void)
! 609: {
! 610: return g_running;
! 611: }
! 612:
! 613: int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
! 614: {
! 615: if ( !pReq ) {
! 616: return -1;
! 617: }
! 618: memset( pReq, 0, sizeof( LSAPI_Request ) );
! 619: if ( allocateIovec( pReq, 16 ) == -1 ) {
! 620: return -1;
! 621: }
! 622: pReq->m_pRespBuf = pReq->m_pRespBufPos = (char *)malloc( LSAPI_RESP_BUF_SIZE );
! 623: if ( !pReq->m_pRespBuf ) {
! 624: return -1;
! 625: }
! 626: pReq->m_pRespBufEnd = pReq->m_pRespBuf + LSAPI_RESP_BUF_SIZE;
! 627: pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
! 628: pReq->m_respPktHeaderEnd = &pReq->m_respPktHeader[5];
! 629: if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 ) {
! 630: return -1;
! 631: }
! 632:
! 633: if ( isPipe( fd ) ) {
! 634: pReq->m_fdListen = -1;
! 635: pReq->m_fd = fd;
! 636: } else {
! 637: pReq->m_fdListen = fd;
! 638: pReq->m_fd = -1;
! 639: lsapi_set_nblock( fd, 1 );
! 640: }
! 641: return 0;
! 642: }
! 643:
! 644: int LSAPI_Is_Listen( void )
! 645: {
! 646: return LSAPI_Is_Listen_r( &g_req );
! 647: }
! 648:
! 649: int LSAPI_Is_Listen_r( LSAPI_Request * pReq)
! 650: {
! 651: return pReq->m_fdListen != -1;
! 652: }
! 653:
! 654:
! 655:
! 656: int LSAPI_Accept_r( LSAPI_Request * pReq )
! 657: {
! 658: char achPeer[128];
! 659: socklen_t len;
! 660: int nodelay = 1;
! 661:
! 662: if ( !pReq ) {
! 663: return -1;
! 664: }
! 665: if ( LSAPI_Finish_r( pReq ) == -1 ) {
! 666: return -1;
! 667: }
! 668: while( g_running ) {
! 669: if ( pReq->m_fd == -1 ) {
! 670: if ( pReq->m_fdListen != -1) {
! 671: len = sizeof( achPeer );
! 672: pReq->m_fd = accept( pReq->m_fdListen,
! 673: (struct sockaddr *)&achPeer, &len );
! 674: if ( pReq->m_fd == -1 ) {
! 675: if (( errno == EINTR )||( errno == EAGAIN)) {
! 676: continue;
! 677: } else {
! 678: return -1;
! 679: }
! 680: } else {
! 681: lsapi_set_nblock( pReq->m_fd , 0 );
! 682: if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) {
! 683: setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY,
! 684: (char *)&nodelay, sizeof(nodelay));
! 685: }
! 686:
! 687: if ( s_accept_notify )
! 688: return notify_req_received( pReq->m_fd );
! 689:
! 690: }
! 691: } else {
! 692: return -1;
! 693: }
! 694: }
! 695: if ( !readReq( pReq ) ) {
! 696: break;
! 697: }
! 698: lsapi_close( pReq->m_fd );
! 699: pReq->m_fd = -1;
! 700: LSAPI_Reset_r( pReq );
! 701: }
! 702: return 0;
! 703: }
! 704:
! 705: static struct lsapi_packet_header finish = {'L', 'S',
! 706: LSAPI_RESP_END, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
! 707:
! 708: int LSAPI_Finish_r( LSAPI_Request * pReq )
! 709: {
! 710: /* finish req body */
! 711: if ( !pReq ) {
! 712: return -1;
! 713: }
! 714: if (pReq->m_reqState) {
! 715: if ( pReq->m_fd != -1 ) {
! 716: if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) {
! 717: LSAPI_FinalizeRespHeaders_r( pReq );
! 718: }
! 719: if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) {
! 720: Flush_RespBuf_r( pReq );
! 721: }
! 722:
! 723: pReq->m_pIovecCur->iov_base = (void *)&finish;
! 724: pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN;
! 725: pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN;
! 726: ++pReq->m_pIovecCur;
! 727: LSAPI_Flush_r( pReq );
! 728: }
! 729: LSAPI_Reset_r( pReq );
! 730: }
! 731: return 0;
! 732: }
! 733:
! 734:
! 735: void LSAPI_Reset_r( LSAPI_Request * pReq )
! 736: {
! 737: pReq->m_pRespBufPos = pReq->m_pRespBuf;
! 738: pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
! 739: pReq->m_pRespHeaderBufPos = pReq->m_pRespHeaderBuf;
! 740:
! 741: memset( &pReq->m_pHeaderIndex, 0,
! 742: (char *)(pReq->m_respHeaderLen) - (char *)&pReq->m_pHeaderIndex );
! 743: }
! 744:
! 745:
! 746: int LSAPI_Release_r( LSAPI_Request * pReq )
! 747: {
! 748: if ( pReq->m_pReqBuf ) {
! 749: free( pReq->m_pReqBuf );
! 750: }
! 751: if ( pReq->m_pSpecialEnvList ) {
! 752: free( pReq->m_pSpecialEnvList );
! 753: }
! 754: if ( pReq->m_pEnvList ) {
! 755: free( pReq->m_pEnvList );
! 756: }
! 757: if ( pReq->m_pRespHeaderBuf ) {
! 758: free( pReq->m_pRespHeaderBuf );
! 759: }
! 760: return 0;
! 761: }
! 762:
! 763:
! 764: char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex )
! 765: {
! 766: int off;
! 767: if ( !pReq || ((unsigned int)headerIndex > H_TRANSFER_ENCODING) ) {
! 768: return NULL;
! 769: }
! 770: off = pReq->m_pHeaderIndex->m_headerOff[ headerIndex ];
! 771: if ( !off ) {
! 772: return NULL;
! 773: }
! 774: if ( *(pReq->m_pHttpHeader + off +
! 775: pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) ) {
! 776: *( pReq->m_pHttpHeader + off +
! 777: pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0;
! 778: }
! 779: return pReq->m_pHttpHeader + off;
! 780: }
! 781:
! 782: static int readBodyToReqBuf( LSAPI_Request * pReq )
! 783: {
! 784: int bodyLeft;
! 785: int len = pReq->m_bufRead - pReq->m_bufProcessed;
! 786: if ( len > 0 ) {
! 787: return len;
! 788: }
! 789: pReq->m_bufRead = pReq->m_bufProcessed = pReq->m_pHeader->m_pktHeader.m_packetLen.m_iLen;
! 790:
! 791: bodyLeft = pReq->m_pHeader->m_reqBodyLen - pReq->m_reqBodyRead;
! 792: len = pReq->m_reqBufSize - pReq->m_bufRead;
! 793: if ( len < 0 ) {
! 794: return -1;
! 795: }
! 796: if ( len > bodyLeft ) {
! 797: len = bodyLeft;
! 798: }
! 799: len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, len );
! 800: if ( len > 0 ) {
! 801: pReq->m_bufRead += len;
! 802: }
! 803: return len;
! 804: }
! 805:
! 806:
! 807: int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq )
! 808: {
! 809: if (!pReq || (pReq->m_fd ==-1) ) {
! 810: return EOF;
! 811: }
! 812: if ( pReq->m_bufProcessed >= pReq->m_bufRead ) {
! 813: if ( readBodyToReqBuf( pReq ) <= 0 ) {
! 814: return EOF;
! 815: }
! 816: }
! 817: ++pReq->m_reqBodyRead;
! 818: return (unsigned char)*(pReq->m_pReqBuf + pReq->m_bufProcessed++);
! 819: }
! 820:
! 821:
! 822:
! 823: int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, int bufLen, int *getLF )
! 824: {
! 825: int len;
! 826: int left;
! 827: char * pBufEnd = pBuf + bufLen - 1;
! 828: char * pBufCur = pBuf;
! 829: char * pCur;
! 830: char * p;
! 831: if (!pReq || (pReq->m_fd ==-1) ||( !pBuf )||(bufLen < 0 )|| !getLF ) {
! 832: return -1;
! 833: }
! 834: *getLF = 0;
! 835: while( (left = pBufEnd - pBufCur ) > 0 ) {
! 836:
! 837: len = pReq->m_bufRead - pReq->m_bufProcessed;
! 838: if ( len <= 0 ) {
! 839: if ( (len = readBodyToReqBuf( pReq )) <= 0 ) {
! 840: *getLF = 1;
! 841: break;
! 842: }
! 843: }
! 844: if ( len > left ) {
! 845: len = left;
! 846: }
! 847: pCur = pReq->m_pReqBuf + pReq->m_bufProcessed;
! 848: p = memchr( pCur, '\n', len );
! 849: if ( p ) {
! 850: len = p - pCur + 1;
! 851: }
! 852: memmove( pBufCur, pCur, len );
! 853: pBufCur += len;
! 854: pReq->m_bufProcessed += len;
! 855:
! 856: pReq->m_reqBodyRead += len;
! 857:
! 858: if ( p ) {
! 859: *getLF = 1;
! 860: break;
! 861: }
! 862: }
! 863: *pBufCur = 0;
! 864:
! 865: return pBufCur - pBuf;
! 866: }
! 867:
! 868:
! 869: int LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, int bufLen )
! 870: {
! 871: int len;
! 872: int total;
! 873: /* char *pOldBuf = pBuf; */
! 874: if (!pReq || (pReq->m_fd ==-1) || ( !pBuf )||(bufLen < 0 )) {
! 875: return -1;
! 876: }
! 877: total = pReq->m_pHeader->m_reqBodyLen - pReq->m_reqBodyRead;
! 878:
! 879: if ( total <= 0 ) {
! 880: return 0;
! 881: }
! 882: if ( total < bufLen ) {
! 883: bufLen = total;
! 884: }
! 885:
! 886: total = 0;
! 887: len = pReq->m_bufRead - pReq->m_bufProcessed;
! 888: if ( len > 0 ) {
! 889: if ( len > bufLen ) {
! 890: len = bufLen;
! 891: }
! 892: memmove( pBuf, pReq->m_pReqBuf + pReq->m_bufProcessed, len );
! 893: pReq->m_bufProcessed += len;
! 894: total += len;
! 895: pBuf += len;
! 896: bufLen -= len;
! 897: }
! 898: while( bufLen > 0 ) {
! 899: len = lsapi_read( pReq->m_fd, pBuf, bufLen );
! 900: if ( len > 0 ) {
! 901: total += len;
! 902: pBuf += len;
! 903: bufLen -= len;
! 904: } else {
! 905: if ( len <= 0 ) {
! 906: if ( !total) {
! 907: return -1;
! 908: }
! 909: break;
! 910: }
! 911: }
! 912: }
! 913: pReq->m_reqBodyRead += total;
! 914: return total;
! 915:
! 916: }
! 917:
! 918:
! 919: int LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, int len )
! 920: {
! 921: struct lsapi_packet_header * pHeader;
! 922: const char * pEnd;
! 923: const char * p;
! 924: int bufLen;
! 925: int toWrite;
! 926: int packetLen;
! 927:
! 928: if ( !pReq || !pBuf || (pReq->m_fd == -1) ) {
! 929: return -1;
! 930: }
! 931: if ( len < pReq->m_pRespBufEnd - pReq->m_pRespBufPos ) {
! 932: memmove( pReq->m_pRespBufPos, pBuf, len );
! 933: pReq->m_pRespBufPos += len;
! 934: return len;
! 935: }
! 936:
! 937: if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) {
! 938: LSAPI_FinalizeRespHeaders_r( pReq );
! 939: }
! 940: pReq->m_reqState |= LSAPI_ST_RESP_BODY;
! 941:
! 942: pHeader = pReq->m_respPktHeader;
! 943: p = pBuf;
! 944: pEnd = pBuf + len;
! 945: bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf;
! 946:
! 947: while( ( toWrite = pEnd - p ) > 0 ) {
! 948: packetLen = toWrite + bufLen;
! 949: if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen) {
! 950: packetLen = LSAPI_MAX_DATA_PACKET_LEN;
! 951: toWrite = packetLen - bufLen;
! 952: }
! 953:
! 954: lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
! 955: packetLen + LSAPI_PACKET_HEADER_LEN );
! 956: pReq->m_totalLen += packetLen + LSAPI_PACKET_HEADER_LEN;
! 957:
! 958: pReq->m_pIovecCur->iov_base = (void *)pHeader;
! 959: pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN;
! 960: ++pReq->m_pIovecCur;
! 961: ++pHeader;
! 962: if ( bufLen > 0 ) {
! 963: pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
! 964: pReq->m_pIovecCur->iov_len = bufLen;
! 965: pReq->m_pRespBufPos = pReq->m_pRespBuf;
! 966: ++pReq->m_pIovecCur;
! 967: bufLen = 0;
! 968: }
! 969:
! 970: pReq->m_pIovecCur->iov_base = (void *)p;
! 971: pReq->m_pIovecCur->iov_len = toWrite;
! 972: ++pReq->m_pIovecCur;
! 973: p += toWrite;
! 974:
! 975: if ( pHeader >= pReq->m_respPktHeaderEnd - 1) {
! 976: if ( LSAPI_Flush_r( pReq ) == -1 ) {
! 977: return -1;
! 978: }
! 979: pHeader = pReq->m_respPktHeader;
! 980: }
! 981: }
! 982: if ( pHeader != pReq->m_respPktHeader ) {
! 983: if ( LSAPI_Flush_r( pReq ) == -1 ) {
! 984: return -1;
! 985: }
! 986: }
! 987: return p - pBuf;
! 988: }
! 989:
! 990: void Flush_RespBuf_r( LSAPI_Request * pReq )
! 991: {
! 992: struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
! 993: int bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf;
! 994: pReq->m_reqState |= LSAPI_ST_RESP_BODY;
! 995: lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
! 996: bufLen + LSAPI_PACKET_HEADER_LEN );
! 997: pReq->m_totalLen += bufLen + LSAPI_PACKET_HEADER_LEN;
! 998:
! 999: pReq->m_pIovecCur->iov_base = (void *)pHeader;
! 1000: pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN;
! 1001: ++pReq->m_pIovecCur;
! 1002: ++pHeader;
! 1003: if ( bufLen > 0 ) {
! 1004: pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
! 1005: pReq->m_pIovecCur->iov_len = bufLen;
! 1006: pReq->m_pRespBufPos = pReq->m_pRespBuf;
! 1007: ++pReq->m_pIovecCur;
! 1008: bufLen = 0;
! 1009: }
! 1010: }
! 1011:
! 1012:
! 1013:
! 1014:
! 1015: int LSAPI_Flush_r( LSAPI_Request * pReq )
! 1016: {
! 1017: int ret = 0;
! 1018: int n;
! 1019: if ( !pReq ) {
! 1020: return -1;
! 1021: }
! 1022: n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
! 1023: if (( 0 == n )&&( pReq->m_pRespBufPos == pReq->m_pRespBuf )) {
! 1024: return 0;
! 1025: }
! 1026: if ( pReq->m_fd == -1 ) {
! 1027: pReq->m_pRespBufPos = pReq->m_pRespBuf;
! 1028: pReq->m_totalLen = 0;
! 1029: pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
! 1030: return -1;
! 1031: }
! 1032: if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) {
! 1033: LSAPI_FinalizeRespHeaders_r( pReq );
! 1034: }
! 1035: if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) {
! 1036: Flush_RespBuf_r( pReq );
! 1037: }
! 1038:
! 1039: n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
! 1040: if ( n > 0 ) {
! 1041:
! 1042: ret = lsapi_writev( pReq->m_fd, &pReq->m_pIovecToWrite,
! 1043: n, pReq->m_totalLen );
! 1044: if ( ret < pReq->m_totalLen ) {
! 1045: lsapi_close( pReq->m_fd );
! 1046: pReq->m_fd = -1;
! 1047: ret = -1;
! 1048: }
! 1049: pReq->m_totalLen = 0;
! 1050: pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
! 1051: }
! 1052: return ret;
! 1053: }
! 1054:
! 1055:
! 1056: int LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, int len )
! 1057: {
! 1058: struct lsapi_packet_header header;
! 1059: const char * pEnd;
! 1060: const char * p;
! 1061: int packetLen;
! 1062: int totalLen;
! 1063: int ret;
! 1064: struct iovec iov[2];
! 1065: struct iovec *pIov;
! 1066:
! 1067: if ( !pReq ) {
! 1068: return -1;
! 1069: }
! 1070: if (( pReq->m_fd == -1 )||(pReq->m_fd == pReq->m_fdListen )) {
! 1071: return write( 2, pBuf, len );
! 1072: }
! 1073: if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) {
! 1074: LSAPI_Flush_r( pReq );
! 1075: }
! 1076:
! 1077: p = pBuf;
! 1078: pEnd = pBuf + len;
! 1079:
! 1080: while( ( packetLen = pEnd - p ) > 0 ) {
! 1081: if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen) {
! 1082: packetLen = LSAPI_MAX_DATA_PACKET_LEN;
! 1083: }
! 1084:
! 1085: lsapi_buildPacketHeader( &header, LSAPI_STDERR_STREAM,
! 1086: packetLen + LSAPI_PACKET_HEADER_LEN );
! 1087: totalLen = packetLen + LSAPI_PACKET_HEADER_LEN;
! 1088:
! 1089: iov[0].iov_base = (void *)&header;
! 1090: iov[0].iov_len = LSAPI_PACKET_HEADER_LEN;
! 1091:
! 1092: iov[1].iov_base = (void *)p;
! 1093: iov[1].iov_len = packetLen;
! 1094: p += packetLen;
! 1095: pIov = iov;
! 1096: ret = lsapi_writev( pReq->m_fd, &pIov,
! 1097: 2, totalLen );
! 1098: if ( ret < totalLen ) {
! 1099: lsapi_close( pReq->m_fd );
! 1100: pReq->m_fd = -1;
! 1101: ret = -1;
! 1102: }
! 1103: }
! 1104: return p - pBuf;
! 1105: }
! 1106:
! 1107: static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
! 1108: {
! 1109: int i;
! 1110: for( i = 0; i < H_TRANSFER_ENCODING; ++i ) {
! 1111: if ( pReq->m_pHeaderIndex->m_headerOff[i] ) {
! 1112: if ( strcmp( name, CGI_HEADERS[i] ) == 0 ) {
! 1113: return pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
! 1114: }
! 1115: }
! 1116: }
! 1117: if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) {
! 1118: const char *p;
! 1119: char *pKey;
! 1120: char *pKeyEnd;
! 1121: int keyLen;
! 1122: struct lsapi_header_offset * pCur, *pEnd;
! 1123: pCur = pReq->m_pUnknownHeader;
! 1124: pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
! 1125: while( pCur < pEnd ) {
! 1126: pKey = pReq->m_pHttpHeader + pCur->nameOff;
! 1127: keyLen = pCur->nameLen;
! 1128: pKeyEnd = pKey + keyLen;
! 1129: p = &name[5];
! 1130:
! 1131: while(( pKey < pKeyEnd )&&( *p )) {
! 1132: char ch = toupper( *pKey );
! 1133: if ((ch != *p )||(( *p == '_' )&&( ch != '-'))) {
! 1134: break;
! 1135: }
! 1136: ++p; ++pKey;
! 1137: }
! 1138: if (( pKey == pKeyEnd )&& (!*p )) {
! 1139: return pReq->m_pHttpHeader + pCur->valueOff;
! 1140: }
! 1141: ++pCur;
! 1142: }
! 1143: }
! 1144: return NULL;
! 1145: }
! 1146:
! 1147:
! 1148: char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name )
! 1149: {
! 1150: struct LSAPI_key_value_pair * pBegin = pReq->m_pEnvList;
! 1151: struct LSAPI_key_value_pair * pEnd = pBegin + pReq->m_pHeader->m_cntEnv;
! 1152: if ( !pReq || !name ) {
! 1153: return NULL;
! 1154: }
! 1155: if ( strncmp( name, "HTTP_", 5 ) == 0 ) {
! 1156: return GetHeaderVar( pReq, name );
! 1157: }
! 1158: while( pBegin < pEnd ) {
! 1159: if ( strcmp( name, pBegin->pKey ) == 0 ) {
! 1160: return pBegin->pValue;
! 1161: }
! 1162: ++pBegin;
! 1163: }
! 1164: return NULL;
! 1165: }
! 1166:
! 1167: int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
! 1168: LSAPI_CB_EnvHandler fn, void * arg )
! 1169: {
! 1170: int i;
! 1171: int len = 0;
! 1172: char * pValue;
! 1173: int ret;
! 1174: int count = 0;
! 1175: if ( !pReq || !fn ) {
! 1176: return -1;
! 1177: }
! 1178: for( i = 0; i < H_TRANSFER_ENCODING; ++i ) {
! 1179: if ( pReq->m_pHeaderIndex->m_headerOff[i] ) {
! 1180: len = pReq->m_pHeaderIndex->m_headerLen[i];
! 1181: pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
! 1182: *(pValue + len ) = 0;
! 1183: ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i],
! 1184: pValue, len, arg );
! 1185: ++count;
! 1186: if ( ret <= 0 ) {
! 1187: return ret;
! 1188: }
! 1189: }
! 1190: }
! 1191: if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) {
! 1192: char *pKey;
! 1193: int keyLen;
! 1194: struct lsapi_header_offset * pCur, *pEnd;
! 1195: pCur = pReq->m_pUnknownHeader;
! 1196: pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
! 1197: while( pCur < pEnd ) {
! 1198: pKey = pReq->m_pHttpHeader + pCur->nameOff;
! 1199: keyLen = pCur->nameLen;
! 1200:
! 1201: pValue = pReq->m_pHttpHeader + pCur->valueOff;
! 1202: *(pValue + pCur->valueLen ) = 0;
! 1203: ret = (*fn)( pKey, keyLen,
! 1204: pValue, pCur->valueLen, arg );
! 1205: if ( ret <= 0 ) {
! 1206: return ret;
! 1207: }
! 1208: ++pCur;
! 1209: }
! 1210: }
! 1211: return count + pReq->m_pHeader->m_cntUnknownHeaders;
! 1212:
! 1213: }
! 1214:
! 1215:
! 1216: int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
! 1217: LSAPI_CB_EnvHandler fn, void * arg )
! 1218: {
! 1219: int i;
! 1220: int len = 0;
! 1221: char * pValue;
! 1222: int ret;
! 1223: int count = 0;
! 1224: if ( !pReq || !fn ) {
! 1225: return -1;
! 1226: }
! 1227: for( i = 0; i < H_TRANSFER_ENCODING; ++i ) {
! 1228: if ( pReq->m_pHeaderIndex->m_headerOff[i] ) {
! 1229: len = pReq->m_pHeaderIndex->m_headerLen[i];
! 1230: pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
! 1231: *(pValue + len ) = 0;
! 1232: ret = (*fn)( CGI_HEADERS[i], CGI_HEADER_LEN[i],
! 1233: pValue, len, arg );
! 1234: ++count;
! 1235: if ( ret <= 0 ) {
! 1236: return ret;
! 1237: }
! 1238: }
! 1239: }
! 1240: if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 ) {
! 1241: char achHeaderName[256];
! 1242: char *p;
! 1243: char *pKey;
! 1244: char *pKeyEnd ;
! 1245: int keyLen;
! 1246: struct lsapi_header_offset * pCur, *pEnd;
! 1247: pCur = pReq->m_pUnknownHeader;
! 1248: pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
! 1249: while( pCur < pEnd ) {
! 1250: pKey = pReq->m_pHttpHeader + pCur->nameOff;
! 1251: keyLen = pCur->nameLen;
! 1252: if ( keyLen > 250 ) {
! 1253: keyLen = 250;
! 1254: }
! 1255:
! 1256: pKeyEnd = pKey + keyLen;
! 1257: memcpy( achHeaderName, "HTTP_", 5 );
! 1258: p = &achHeaderName[5];
! 1259:
! 1260: while( pKey < pKeyEnd ) {
! 1261: char ch = *pKey++;
! 1262: if ( ch == '-' ) {
! 1263: *p++ = '_';
! 1264: } else {
! 1265: *p++ = toupper( ch );
! 1266: }
! 1267: }
! 1268: *p = 0;
! 1269: keyLen += 5;
! 1270:
! 1271: pValue = pReq->m_pHttpHeader + pCur->valueOff;
! 1272: *(pValue + pCur->valueLen ) = 0;
! 1273: ret = (*fn)( achHeaderName, keyLen,
! 1274: pValue, pCur->valueLen, arg );
! 1275: if ( ret <= 0 ) {
! 1276: return ret;
! 1277: }
! 1278: ++pCur;
! 1279: }
! 1280: }
! 1281: return count + pReq->m_pHeader->m_cntUnknownHeaders;
! 1282:
! 1283: }
! 1284:
! 1285: static int EnvForeach( struct LSAPI_key_value_pair * pEnv,
! 1286: int n, LSAPI_CB_EnvHandler fn, void * arg )
! 1287: {
! 1288: struct LSAPI_key_value_pair * pEnd = pEnv + n;
! 1289: int ret;
! 1290: if ( !pEnv || !fn ) {
! 1291: return -1;
! 1292: }
! 1293: while( pEnv < pEnd ) {
! 1294: ret = (*fn)( pEnv->pKey, pEnv->keyLen,
! 1295: pEnv->pValue, pEnv->valLen, arg );
! 1296: if ( ret <= 0 ) {
! 1297: return ret;
! 1298: }
! 1299: ++pEnv;
! 1300: }
! 1301: return n;
! 1302: }
! 1303:
! 1304:
! 1305:
! 1306: int LSAPI_ForeachEnv_r( LSAPI_Request * pReq,
! 1307: LSAPI_CB_EnvHandler fn, void * arg )
! 1308: {
! 1309: if ( !pReq || !fn ) {
! 1310: return -1;
! 1311: }
! 1312: if ( pReq->m_pHeader->m_cntEnv > 0 ) {
! 1313: return EnvForeach( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
! 1314: fn, arg );
! 1315: }
! 1316: return 0;
! 1317: }
! 1318:
! 1319:
! 1320:
! 1321: int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq,
! 1322: LSAPI_CB_EnvHandler fn, void * arg )
! 1323: {
! 1324: if ( !pReq || !fn ) {
! 1325: return -1;
! 1326: }
! 1327: if ( pReq->m_pHeader->m_cntSpecialEnv > 0 ) {
! 1328: return EnvForeach( pReq->m_pSpecialEnvList,
! 1329: pReq->m_pHeader->m_cntSpecialEnv,
! 1330: fn, arg );
! 1331: }
! 1332: return 0;
! 1333:
! 1334: }
! 1335:
! 1336:
! 1337:
! 1338: int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq )
! 1339: {
! 1340: if ( !pReq || !pReq->m_pIovec ) {
! 1341: return -1;
! 1342: }
! 1343: if ( !( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) ) {
! 1344: return 0;
! 1345: }
! 1346: pReq->m_reqState &= ~LSAPI_ST_RESP_HEADER;
! 1347: if ( pReq->m_pRespHeaderBufPos > pReq->m_pRespHeaderBuf ) {
! 1348: pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespHeaderBuf;
! 1349: pReq->m_pIovecCur->iov_len = pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf;
! 1350: pReq->m_totalLen += pReq->m_pIovecCur->iov_len;
! 1351: ++pReq->m_pIovecCur;
! 1352: }
! 1353:
! 1354: pReq->m_pIovec->iov_len = sizeof( struct lsapi_resp_header)
! 1355: + pReq->m_respHeader.m_respInfo.m_cntHeaders * sizeof( short );
! 1356: pReq->m_totalLen += pReq->m_pIovec->iov_len;
! 1357:
! 1358: lsapi_buildPacketHeader( &pReq->m_respHeader.m_pktHeader,
! 1359: LSAPI_RESP_HEADER, pReq->m_totalLen );
! 1360: pReq->m_pIovec->iov_base = (void *)&pReq->m_respHeader;
! 1361: pReq->m_pIovecToWrite = pReq->m_pIovec;
! 1362: return 0;
! 1363: }
! 1364:
! 1365:
! 1366:
! 1367:
! 1368: int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, char * pBuf, int len )
! 1369: {
! 1370: if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX ) {
! 1371: return -1;
! 1372: }
! 1373: if ( pReq->m_reqState & LSAPI_ST_RESP_BODY ) {
! 1374: return -1;
! 1375: }
! 1376: if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS ) {
! 1377: return -1;
! 1378: }
! 1379: if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd ) {
! 1380: int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
! 1381: newlen -= newlen % 4096;
! 1382: if ( allocateRespHeaderBuf( pReq, newlen ) == -1 ) {
! 1383: return -1;
! 1384: }
! 1385: }
! 1386: memmove( pReq->m_pRespHeaderBufPos, pBuf, len );
! 1387: pReq->m_pRespHeaderBufPos += len;
! 1388: *pReq->m_pRespHeaderBufPos++ = 0;
! 1389: ++len; /* add one byte padding for \0 */
! 1390: pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
! 1391: ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
! 1392: return 0;
! 1393: }
! 1394:
! 1395:
! 1396: int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog )
! 1397: {
! 1398: int ret;
! 1399: int fd;
! 1400: int flag = 1;
! 1401: int addr_len;
! 1402:
! 1403: switch( pServerAddr->sa_family ) {
! 1404: case AF_INET:
! 1405: addr_len = 16;
! 1406: break;
! 1407: case AF_INET6:
! 1408: addr_len = sizeof( struct sockaddr_in6 );
! 1409: break;
! 1410: case AF_UNIX:
! 1411: addr_len = sizeof( struct sockaddr_un );
! 1412: unlink( ((struct sockaddr_un *)pServerAddr)->sun_path );
! 1413: break;
! 1414: default:
! 1415: return -1;
! 1416: }
! 1417:
! 1418: fd = socket( pServerAddr->sa_family, SOCK_STREAM, 0 );
! 1419: if ( fd == -1 ) {
! 1420: return -1;
! 1421: }
! 1422:
! 1423: fcntl( fd, F_SETFD, FD_CLOEXEC );
! 1424:
! 1425: if(setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
! 1426: (char *)( &flag ), sizeof(flag)) == 0) {
! 1427: ret = bind( fd, pServerAddr, addr_len );
! 1428: if ( !ret ) {
! 1429: ret = listen( fd, backlog );
! 1430: if ( !ret ) {
! 1431: return fd;
! 1432: }
! 1433: }
! 1434: }
! 1435:
! 1436: ret = errno;
! 1437: close(fd);
! 1438: errno = ret;
! 1439: return -1;
! 1440:
! 1441: }
! 1442:
! 1443: int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
! 1444: {
! 1445: char achAddr[256];
! 1446: char * p = achAddr;
! 1447: char * pEnd;
! 1448: struct addrinfo *res, hints;
! 1449: int doAddrInfo = 0;
! 1450: int port;
! 1451:
! 1452: if ( !pBind ) {
! 1453: return -1;
! 1454: }
! 1455:
! 1456: while( isspace( *pBind ) ) {
! 1457: ++pBind;
! 1458: }
! 1459:
! 1460: strncpy( achAddr, pBind, 256 );
! 1461:
! 1462: switch( *p ) {
! 1463: case '/':
! 1464: pAddr->sa_family = AF_UNIX;
! 1465: strncpy( ((struct sockaddr_un *)pAddr)->sun_path, p,
! 1466: sizeof(((struct sockaddr_un *)pAddr)->sun_path) );
! 1467: return 0;
! 1468:
! 1469: case '[':
! 1470: pAddr->sa_family = AF_INET6;
! 1471: ++p;
! 1472: pEnd = strchr( p, ']' );
! 1473: if ( !pEnd )
! 1474: return -1;
! 1475: *pEnd++ = 0;
! 1476:
! 1477: if ( *p == '*' ) {
! 1478: strcpy( achAddr, "::" );
! 1479: p = achAddr;
! 1480: }
! 1481: doAddrInfo = 1;
! 1482: break;
! 1483:
! 1484: default:
! 1485: pAddr->sa_family = AF_INET;
! 1486: pEnd = strchr( p, ':' );
! 1487: if ( !pEnd ) {
! 1488: return -1;
! 1489: }
! 1490: *pEnd++ = 0;
! 1491:
! 1492: doAddrInfo = 0;
! 1493: if ( *p == '*' ) {
! 1494: ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl(INADDR_ANY);
! 1495: } else {
! 1496: if (!strcasecmp( p, "localhost" ) ) {
! 1497: ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl( INADDR_LOOPBACK );
! 1498: } else {
! 1499: ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = inet_addr( p );
! 1500: if ( ((struct sockaddr_in *)pAddr)->sin_addr.s_addr == INADDR_BROADCAST) {
! 1501: doAddrInfo = 1;
! 1502: }
! 1503: }
! 1504: }
! 1505: break;
! 1506: }
! 1507: if ( *pEnd == ':' ) {
! 1508: ++pEnd;
! 1509: }
! 1510:
! 1511: port = atoi( pEnd );
! 1512: if (( port <= 0 )||( port > 65535 )) {
! 1513: return -1;
! 1514: }
! 1515: if ( doAddrInfo ) {
! 1516:
! 1517: memset(&hints, 0, sizeof(hints));
! 1518:
! 1519: hints.ai_family = pAddr->sa_family;
! 1520: hints.ai_socktype = SOCK_STREAM;
! 1521: hints.ai_protocol = IPPROTO_TCP;
! 1522:
! 1523: if ( getaddrinfo(p, NULL, &hints, &res) ) {
! 1524: return -1;
! 1525: }
! 1526:
! 1527: memcpy(pAddr, res->ai_addr, res->ai_addrlen);
! 1528: freeaddrinfo(res);
! 1529: }
! 1530:
! 1531: if ( pAddr->sa_family == AF_INET ) {
! 1532: ((struct sockaddr_in *)pAddr)->sin_port = htons( port );
! 1533: } else {
! 1534: ((struct sockaddr_in6 *)pAddr)->sin6_port = htons( port );
! 1535: }
! 1536: return 0;
! 1537:
! 1538: }
! 1539:
! 1540: int LSAPI_CreateListenSock( const char * pBind, int backlog )
! 1541: {
! 1542: char serverAddr[128];
! 1543: int ret;
! 1544: int fd = -1;
! 1545: ret = LSAPI_ParseSockAddr( pBind, (struct sockaddr *)serverAddr );
! 1546: if ( !ret ) {
! 1547: fd = LSAPI_CreateListenSock2( (struct sockaddr *)serverAddr, backlog );
! 1548: }
! 1549: return fd;
! 1550: }
! 1551:
! 1552: static fn_select_t g_fnSelect = select;
! 1553:
! 1554: typedef struct _lsapi_child_status
! 1555: {
! 1556: int m_pid;
! 1557:
! 1558: volatile short m_iKillSent;
! 1559: volatile short m_inProcess;
! 1560:
! 1561: volatile long m_tmWaitBegin;
! 1562: volatile long m_tmReqBegin;
! 1563: volatile long m_tmLastCheckPoint;
! 1564: }
! 1565: lsapi_child_status;
! 1566:
! 1567: static lsapi_child_status * s_pChildStatus = NULL;
! 1568:
! 1569: typedef struct _lsapi_prefork_server
! 1570: {
! 1571: int m_fd;
! 1572: int m_iMaxChildren;
! 1573: int m_iExtraChildren;
! 1574: int m_iCurChildren;
! 1575: int m_iMaxIdleChildren;
! 1576: int m_iServerMaxIdle;
! 1577: int m_iChildrenMaxIdleTime;
! 1578: int m_iMaxReqProcessTime;
! 1579: int m_iAvoidFork;
! 1580:
! 1581: lsapi_child_status * m_pChildrenStatus;
! 1582:
! 1583: }lsapi_prefork_server;
! 1584:
! 1585: static lsapi_prefork_server * g_prefork_server = NULL;
! 1586:
! 1587: int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
! 1588: {
! 1589: if ( g_prefork_server ) {
! 1590: return 0;
! 1591: }
! 1592: if ( max_children <= 1 ) {
! 1593: return -1;
! 1594: }
! 1595: if ( max_children >= 10000) {
! 1596: max_children = 10000;
! 1597: }
! 1598:
! 1599:
! 1600: g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) );
! 1601: if ( !g_prefork_server ) {
! 1602: return -1;
! 1603: }
! 1604: memset( g_prefork_server, 0, sizeof( lsapi_prefork_server ) );
! 1605:
! 1606: if ( fp != NULL ) {
! 1607: g_fnSelect = fp;
! 1608: }
! 1609:
! 1610: s_ppid = getppid();
! 1611: g_prefork_server->m_iAvoidFork = avoidFork;
! 1612: g_prefork_server->m_iMaxChildren = max_children;
! 1613:
! 1614: g_prefork_server->m_iExtraChildren = ( avoidFork ) ? 0 : (max_children / 3) ;
! 1615: g_prefork_server->m_iMaxIdleChildren = ( avoidFork ) ? (max_children + 1) : (max_children / 3);
! 1616: g_prefork_server->m_iChildrenMaxIdleTime = 300;
! 1617: g_prefork_server->m_iMaxReqProcessTime = 300;
! 1618: return 0;
! 1619: }
! 1620:
! 1621: void LSAPI_Set_Server_fd( int fd )
! 1622: {
! 1623: if( g_prefork_server ) {
! 1624: g_prefork_server->m_fd = fd;
! 1625: }
! 1626: }
! 1627:
! 1628:
! 1629: static int lsapi_accept( int fdListen )
! 1630: {
! 1631: int fd;
! 1632: int nodelay = 1;
! 1633: socklen_t len;
! 1634: char achPeer[128];
! 1635:
! 1636: len = sizeof( achPeer );
! 1637: fd = accept( fdListen, (struct sockaddr *)&achPeer, &len );
! 1638: if ( fd != -1 ) {
! 1639: if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) {
! 1640: setsockopt( fd, IPPROTO_TCP, TCP_NODELAY,
! 1641: (char *)&nodelay, sizeof(nodelay));
! 1642: }
! 1643:
! 1644: if ( s_accept_notify )
! 1645: notify_req_received( fd );
! 1646: }
! 1647: return fd;
! 1648:
! 1649: }
! 1650:
! 1651:
! 1652:
! 1653:
! 1654: static int s_req_processed = 0;
! 1655: static int s_max_reqs = 10000;
! 1656: static int s_max_idle_secs = 300;
! 1657:
! 1658: static int s_stop;
! 1659:
! 1660: static void lsapi_cleanup(int signal)
! 1661: {
! 1662: s_stop = signal;
! 1663: }
! 1664:
! 1665: static lsapi_child_status * find_child_status( int pid )
! 1666: {
! 1667: lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
! 1668: lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatus + g_prefork_server->m_iMaxChildren * 2;
! 1669: while( pStatus < pEnd ) {
! 1670: if ( pStatus->m_pid == pid ) {
! 1671: return pStatus;
! 1672: }
! 1673: ++pStatus;
! 1674: }
! 1675: return NULL;
! 1676: }
! 1677:
! 1678:
! 1679:
! 1680: static void lsapi_sigchild( int signal )
! 1681: {
! 1682: int status, pid;
! 1683: lsapi_child_status * child_status;
! 1684: while( 1 ) {
! 1685: pid = waitpid( -1, &status, WNOHANG|WUNTRACED );
! 1686: if ( pid <= 0 ) {
! 1687: break;
! 1688: }
! 1689: child_status = find_child_status( pid );
! 1690: if ( child_status ) {
! 1691: child_status->m_pid = 0;
! 1692: }
! 1693: --g_prefork_server->m_iCurChildren;
! 1694: }
! 1695:
! 1696: }
! 1697:
! 1698: static int lsapi_init_children_status()
! 1699: {
! 1700: int size = 4096;
! 1701:
! 1702: char * pBuf;
! 1703: size = g_prefork_server->m_iMaxChildren * sizeof( lsapi_child_status ) * 2;
! 1704: size = (size + 4095 ) / 4096 * 4096;
! 1705: pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE,
! 1706: MAP_ANON | MAP_SHARED, -1, 0 );
! 1707: if ( pBuf == MAP_FAILED ) {
! 1708: perror( "Anonymous mmap() failed" );
! 1709: return -1;
! 1710: }
! 1711: memset( pBuf, 0, size );
! 1712: g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf;
! 1713: return 0;
! 1714: }
! 1715:
! 1716: static void lsapi_check_child_status( long tmCur )
! 1717: {
! 1718: int idle = 0;
! 1719: int tobekilled;
! 1720: int dying = 0;
! 1721: lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
! 1722: lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatus + g_prefork_server->m_iMaxChildren * 2;
! 1723: while( pStatus < pEnd ) {
! 1724: tobekilled = pStatus->m_iKillSent;
! 1725: if ( pStatus->m_pid != 0 ) {
! 1726: if ( !tobekilled ) {
! 1727: if ( !pStatus->m_inProcess ) {
! 1728:
! 1729: if (( g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren)||
! 1730: ( idle >= g_prefork_server->m_iMaxIdleChildren )) {
! 1731:
! 1732: tobekilled = 1;
! 1733: } else {
! 1734: if (( s_max_idle_secs> 0)&&(tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5 )) {
! 1735: tobekilled = 1;
! 1736: }
! 1737: }
! 1738: if ( !tobekilled ) {
! 1739: ++idle;
! 1740: }
! 1741: } else {
! 1742: if ( tmCur - pStatus->m_tmReqBegin >
! 1743: g_prefork_server->m_iMaxReqProcessTime ) {
! 1744: tobekilled = 1;
! 1745: }
! 1746: }
! 1747: } else {
! 1748: if ( pStatus->m_inProcess ) {
! 1749: tobekilled = pStatus->m_iKillSent = 0;
! 1750: }
! 1751: }
! 1752: if ( tobekilled ) {
! 1753: tobekilled = 0;
! 1754: if ( pStatus->m_iKillSent > 5 ) {
! 1755: tobekilled = SIGKILL;
! 1756: } else {
! 1757: if ( pStatus->m_iKillSent == 3 ) {
! 1758: tobekilled = SIGTERM;
! 1759: } else {
! 1760: if ( pStatus->m_iKillSent == 1 ) {
! 1761: tobekilled = SIGUSR1;
! 1762: }
! 1763: }
! 1764: }
! 1765: if ( tobekilled ) {
! 1766: kill( pStatus->m_pid, tobekilled );
! 1767: }
! 1768: ++pStatus->m_iKillSent;
! 1769: ++dying;
! 1770: }
! 1771:
! 1772: } else {
! 1773: ++dying;
! 1774: }
! 1775: ++pStatus;
! 1776: }
! 1777: }
! 1778:
! 1779: static int lsapi_all_children_must_die()
! 1780: {
! 1781: int maxWait;
! 1782: int sec =0;
! 1783: g_prefork_server->m_iMaxReqProcessTime = 10;
! 1784: g_prefork_server->m_iMaxIdleChildren = -1;
! 1785: maxWait = 15;
! 1786:
! 1787: while( g_prefork_server->m_iCurChildren && (sec < maxWait) ) {
! 1788: lsapi_check_child_status(time(NULL));
! 1789: sleep( 1 );
! 1790: sec++;
! 1791: }
! 1792: if ( g_prefork_server->m_iCurChildren != 0 ) {
! 1793: kill( -getpgrp(), SIGKILL );
! 1794: }
! 1795: return 0;
! 1796: }
! 1797:
! 1798:
! 1799:
! 1800: static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Request * pReq )
! 1801: {
! 1802: struct sigaction act, old_term, old_quit, old_int,
! 1803: old_usr1, old_child;
! 1804: lsapi_child_status * child_status;
! 1805: int wait_secs = 0;
! 1806: int ret = 0;
! 1807: int pid;
! 1808: time_t lastTime = 0;
! 1809: time_t curTime = 0;
! 1810: fd_set readfds;
! 1811: struct timeval timeout;
! 1812:
! 1813: lsapi_init_children_status();
! 1814:
! 1815: setsid();
! 1816:
! 1817: act.sa_flags = 0;
! 1818: act.sa_handler = lsapi_sigchild;
! 1819: if( sigaction( SIGCHLD, &act, &old_child ) ) {
! 1820: perror( "Can't set signal handler for SIGCHILD" );
! 1821: return -1;
! 1822: }
! 1823:
! 1824: /* Set up handler to kill children upon exit */
! 1825: act.sa_flags = 0;
! 1826: act.sa_handler = lsapi_cleanup;
! 1827: if( sigaction( SIGTERM, &act, &old_term ) ||
! 1828: sigaction( SIGINT, &act, &old_int ) ||
! 1829: sigaction( SIGUSR1, &act, &old_usr1 ) ||
! 1830: sigaction( SIGQUIT, &act, &old_quit )) {
! 1831: perror( "Can't set signals" );
! 1832: return -1;
! 1833: }
! 1834: s_stop = 0;
! 1835: while( !s_stop ) {
! 1836: if ( ret ) {
! 1837: curTime = time( NULL );
! 1838: } else {
! 1839: ++curTime;
! 1840: }
! 1841: if (curTime != lastTime ) {
! 1842: lastTime = curTime;
! 1843: if (s_ppid && (getppid() != s_ppid )) {
! 1844: break;
! 1845: }
! 1846: lsapi_check_child_status(curTime );
! 1847: if (pServer->m_iServerMaxIdle) {
! 1848: if ( pServer->m_iCurChildren <= 0 ) {
! 1849: ++wait_secs;
! 1850: if ( wait_secs > pServer->m_iServerMaxIdle ) {
! 1851: return -1;
! 1852: }
! 1853: } else {
! 1854: wait_secs = 0;
! 1855: }
! 1856: }
! 1857: }
! 1858:
! 1859: if ( pServer->m_iCurChildren >= (pServer->m_iMaxChildren + pServer->m_iExtraChildren ) ) {
! 1860: usleep( 100000 );
! 1861: continue;
! 1862: }
! 1863:
! 1864: FD_ZERO( &readfds );
! 1865: FD_SET( pServer->m_fd, &readfds );
! 1866: timeout.tv_sec = 1; timeout.tv_usec = 0;
! 1867: if ((ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout)) == 1 ) {
! 1868: if ( pServer->m_iCurChildren >= 0 ) {
! 1869: usleep( 10 );
! 1870: FD_ZERO( &readfds );
! 1871: FD_SET( pServer->m_fd, &readfds );
! 1872: timeout.tv_sec = 0; timeout.tv_usec = 0;
! 1873: if ( (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout) == 0 ) {
! 1874: continue;
! 1875: }
! 1876: }
! 1877: } else {
! 1878: if ( ret == -1 ) {
! 1879: if ( errno == EINTR ) {
! 1880: continue;
! 1881: }
! 1882: /* perror( "select()" ); */
! 1883: break;
! 1884: } else {
! 1885: continue;
! 1886: }
! 1887: }
! 1888:
! 1889: pReq->m_fd = lsapi_accept( pServer->m_fd );
! 1890: if ( pReq->m_fd != -1 ) {
! 1891: child_status = find_child_status( 0 );
! 1892: pid = fork();
! 1893: if ( !pid ) {
! 1894: g_prefork_server = NULL;
! 1895: s_ppid = getppid();
! 1896: s_req_processed = 0;
! 1897: s_pChildStatus = child_status;
! 1898: child_status->m_iKillSent = 0;
! 1899: lsapi_set_nblock( pReq->m_fd, 0 );
! 1900:
! 1901: /* don't catch our signals */
! 1902: sigaction( SIGCHLD, &old_child, 0 );
! 1903: sigaction( SIGTERM, &old_term, 0 );
! 1904: sigaction( SIGQUIT, &old_quit, 0 );
! 1905: sigaction( SIGINT, &old_int, 0 );
! 1906: sigaction( SIGUSR1, &old_usr1, 0 );
! 1907: return 0;
! 1908: } else {
! 1909: if ( pid == -1 ) {
! 1910: perror( "fork() failed, please increase process limit" );
! 1911: } else {
! 1912: ++pServer->m_iCurChildren;
! 1913: if ( child_status ) {
! 1914: child_status->m_pid = pid;
! 1915: child_status->m_iKillSent = 0;
! 1916: child_status->m_tmWaitBegin = time(NULL);
! 1917: }
! 1918: }
! 1919: }
! 1920: close( pReq->m_fd );
! 1921: pReq->m_fd = -1;
! 1922:
! 1923: } else {
! 1924: if (( errno == EINTR )||( errno == EAGAIN)) {
! 1925: continue;
! 1926: }
! 1927: perror( "accept() failed" );
! 1928: return -1;
! 1929: }
! 1930: }
! 1931: sigaction( SIGUSR1, &old_usr1, 0 );
! 1932: kill( -getpgrp(), SIGUSR1 );
! 1933: lsapi_all_children_must_die(); /* Sorry, children ;-) */
! 1934: return -1;
! 1935:
! 1936: }
! 1937:
! 1938: int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
! 1939: {
! 1940: int fd;
! 1941: int ret;
! 1942: int wait_secs;
! 1943: fd_set readfds;
! 1944: struct timeval timeout;
! 1945:
! 1946: LSAPI_Finish_r( pReq );
! 1947:
! 1948:
! 1949: if ( g_prefork_server ) {
! 1950: if ( g_prefork_server->m_fd != -1 ) {
! 1951: if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 ) {
! 1952: return -1;
! 1953: }
! 1954: }
! 1955: }
! 1956: if ( s_req_processed >= s_max_reqs ) {
! 1957: return -1;
! 1958: }
! 1959:
! 1960: if ( s_pChildStatus ) {
! 1961: s_pChildStatus->m_tmWaitBegin = time( NULL );
! 1962: }
! 1963:
! 1964: while( g_running ) {
! 1965: if ( pReq->m_fd != -1 ) {
! 1966: fd = pReq->m_fd;
! 1967: } else {
! 1968: if ( pReq->m_fdListen != -1 ) {
! 1969: fd = pReq->m_fdListen;
! 1970: } else {
! 1971: return -1;
! 1972: }
! 1973: }
! 1974: wait_secs = 0;
! 1975: while( 1 ) {
! 1976: if ( !g_running ) {
! 1977: return -1;
! 1978: }
! 1979: if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent )) {
! 1980: return -1;
! 1981: }
! 1982: FD_ZERO( &readfds );
! 1983: FD_SET( fd, &readfds );
! 1984: timeout.tv_sec = 1;
! 1985: timeout.tv_usec = 0;
! 1986: ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout);
! 1987: if ( ret == 0 ) {
! 1988: if ( s_pChildStatus ) {
! 1989: s_pChildStatus->m_inProcess = 0;
! 1990: }
! 1991: ++wait_secs;
! 1992: if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs )) {
! 1993: return -1;
! 1994: }
! 1995: if ( s_ppid &&( getppid() != s_ppid)) {
! 1996: return -1;
! 1997: }
! 1998: } else {
! 1999: if ( ret == -1 ) {
! 2000: if ( errno == EINTR ) {
! 2001: continue;
! 2002: } else {
! 2003: return -1;
! 2004: }
! 2005: } else {
! 2006: if ( ret >= 1 ) {
! 2007: if (( s_pChildStatus )&&( s_pChildStatus->m_iKillSent )) {
! 2008: return -1;
! 2009: }
! 2010: if ( fd == pReq->m_fdListen ) {
! 2011: pReq->m_fd = lsapi_accept( pReq->m_fdListen );
! 2012: if ( pReq->m_fd != -1 ) {
! 2013: fd = pReq->m_fd;
! 2014: lsapi_set_nblock( fd, 0 );
! 2015: } else {
! 2016: if (( errno == EINTR )||( errno == EAGAIN)) {
! 2017: continue;
! 2018: }
! 2019: return -1;
! 2020: }
! 2021: } else {
! 2022: break;
! 2023: }
! 2024: }
! 2025: }
! 2026: }
! 2027: }
! 2028: if ( !readReq( pReq ) ) {
! 2029: if ( s_pChildStatus ) {
! 2030: s_pChildStatus->m_inProcess = 1;
! 2031: s_pChildStatus->m_tmReqBegin = s_pChildStatus->m_tmLastCheckPoint = time(NULL);
! 2032: }
! 2033: ++s_req_processed;
! 2034: return 0;
! 2035: }
! 2036: lsapi_close( pReq->m_fd );
! 2037: pReq->m_fd = -1;
! 2038: LSAPI_Reset_r( pReq );
! 2039: }
! 2040: return -1;
! 2041:
! 2042: }
! 2043:
! 2044: void LSAPI_Set_Max_Reqs( int reqs )
! 2045: {
! 2046: s_max_reqs = reqs;
! 2047: }
! 2048:
! 2049: void LSAPI_Set_Max_Idle( int secs )
! 2050: {
! 2051: s_max_idle_secs = secs;
! 2052: }
! 2053:
! 2054: void LSAPI_Set_Max_Children( int maxChildren )
! 2055: {
! 2056: if ( g_prefork_server ) {
! 2057: g_prefork_server->m_iMaxChildren = maxChildren;
! 2058: }
! 2059: }
! 2060:
! 2061: void LSAPI_Set_Extra_Children( int extraChildren )
! 2062: {
! 2063: if (( g_prefork_server )&&( extraChildren >= 0 )) {
! 2064: g_prefork_server->m_iExtraChildren = extraChildren;
! 2065: }
! 2066: }
! 2067:
! 2068: void LSAPI_Set_Max_Process_Time( int secs )
! 2069: {
! 2070: if (( g_prefork_server )&&( secs > 0 )) {
! 2071: g_prefork_server->m_iMaxReqProcessTime = secs;
! 2072: }
! 2073: }
! 2074:
! 2075:
! 2076: void LSAPI_Set_Max_Idle_Children( int maxIdleChld )
! 2077: {
! 2078: if (( g_prefork_server )&&( maxIdleChld > 0 )) {
! 2079: g_prefork_server->m_iMaxIdleChildren = maxIdleChld;
! 2080: }
! 2081: }
! 2082:
! 2083: void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle )
! 2084: {
! 2085: if ( g_prefork_server ) {
! 2086: g_prefork_server->m_iServerMaxIdle = serverMaxIdle;
! 2087: }
! 2088: }
! 2089:
! 2090: void LSAPI_Set_Slow_Req_Msecs( int msecs )
! 2091: {
! 2092: s_slow_req_msecs = msecs;
! 2093: }
! 2094:
! 2095: int LSAPI_Get_Slow_Req_Msecs()
! 2096: {
! 2097: return s_slow_req_msecs;
! 2098: }
! 2099:
! 2100: void LSAPI_No_Check_ppid()
! 2101: {
! 2102: s_ppid = 0;
! 2103: }
! 2104:
! 2105: #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
! 2106: #include <crt_externs.h>
! 2107: #else
! 2108: extern char ** environ;
! 2109: #endif
! 2110: static void unset_lsapi_envs()
! 2111: {
! 2112: char **env;
! 2113: #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
! 2114: env = *_NSGetEnviron();
! 2115: #else
! 2116: env = environ;
! 2117: #endif
! 2118: while( env != NULL && *env != NULL ) {
! 2119: if ( !strncmp(*env, "LSAPI_", 6) ||
! 2120: !strncmp( *env, "PHP_LSAPI_", 10 ) ) {
! 2121: char ** del = env;
! 2122: do {
! 2123: *del = del[1];
! 2124: } while( *del++ );
! 2125: } else {
! 2126: ++env;
! 2127: }
! 2128: }
! 2129: }
! 2130:
! 2131: void LSAPI_Init_Env_Parameters( fn_select_t fp )
! 2132: {
! 2133: const char *p;
! 2134: int n;
! 2135: int avoidFork = 0;
! 2136: p = getenv( "PHP_LSAPI_MAX_REQUESTS" );
! 2137: if ( !p ) {
! 2138: p = getenv( "LSAPI_MAX_REQS" );
! 2139: }
! 2140: if ( p ) {
! 2141: n = atoi( p );
! 2142: if ( n > 0 ) {
! 2143: LSAPI_Set_Max_Reqs( n );
! 2144: }
! 2145: }
! 2146:
! 2147: p = getenv( "LSAPI_AVOID_FORK" );
! 2148: if ( p ) {
! 2149: avoidFork = atoi( p );
! 2150: }
! 2151:
! 2152: p = getenv( "LSAPI_ACCEPT_NOTIFY" );
! 2153: if ( p ) {
! 2154: s_accept_notify = atoi( p );
! 2155: }
! 2156:
! 2157: p = getenv( "LSAPI_SLOW_REQ_MSECS" );
! 2158: if ( p ) {
! 2159: n = atoi( p );
! 2160: LSAPI_Set_Slow_Req_Msecs( n );
! 2161: }
! 2162:
! 2163:
! 2164: #if defined( RLIMIT_CORE )
! 2165: p = getenv( "LSAPI_ALLOW_CORE_DUMP" );
! 2166: if ( !p ) {
! 2167: struct rlimit limit = { 0, 0 };
! 2168: setrlimit( RLIMIT_CORE, &limit );
! 2169: }
! 2170: #endif
! 2171:
! 2172: p = getenv( "LSAPI_MAX_IDLE" );
! 2173: if ( p ) {
! 2174: n = atoi( p );
! 2175: LSAPI_Set_Max_Idle( n );
! 2176: }
! 2177:
! 2178: if ( LSAPI_Is_Listen() ) {
! 2179: n = 0;
! 2180: p = getenv( "PHP_LSAPI_CHILDREN" );
! 2181: if ( !p ) {
! 2182: p = getenv( "LSAPI_CHILDREN" );
! 2183: }
! 2184: if ( p ) {
! 2185: n = atoi( p );
! 2186: }
! 2187: if ( n > 1 ) {
! 2188: LSAPI_Init_Prefork_Server( n, fp, avoidFork );
! 2189: LSAPI_Set_Server_fd( g_req.m_fdListen );
! 2190: }
! 2191:
! 2192: p = getenv( "LSAPI_EXTRA_CHILDREN" );
! 2193: if ( p ) {
! 2194: LSAPI_Set_Extra_Children( atoi( p ) );
! 2195: }
! 2196:
! 2197: p = getenv( "LSAPI_MAX_IDLE_CHILDREN" );
! 2198: if ( p ) {
! 2199: LSAPI_Set_Max_Idle_Children( atoi( p ) );
! 2200: }
! 2201: p = getenv( "LSAPI_PGRP_MAX_IDLE" );
! 2202: if ( p ) {
! 2203: LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) );
! 2204: }
! 2205:
! 2206: p = getenv( "LSAPI_MAX_PROCESS_TIME" );
! 2207: if ( p ) {
! 2208: LSAPI_Set_Max_Process_Time( atoi( p ) );
! 2209: }
! 2210: if ( getenv( "LSAPI_PPID_NO_CHECK" ) ) {
! 2211: LSAPI_No_Check_ppid();
! 2212: }
! 2213: }
! 2214: unset_lsapi_envs();
! 2215: }
! 2216:
! 2217:
! 2218: /*
! 2219: * Local variables:
! 2220: * tab-width: 4
! 2221: * c-basic-offset: 4
! 2222: * End:
! 2223: * vim600: sw=4 ts=4 fdm=marker
! 2224: * vim<600: sw=4 ts=4
! 2225: */
! 2226:
! 2227:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>