Return to lsapilib.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / sapi / litespeed |
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: