Annotation of embedaddon/php/sapi/litespeed/lsapilib.c, revision 1.1.1.3
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
1.1.1.3 ! misho 5: | Copyright (c) 1997-2013 The PHP Group |
1.1 misho 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:
1.1.1.2 misho 19: /* $Id$ */
1.1 misho 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>