xref: /PHP-5.3/sapi/litespeed/lsapilib.c (revision a2045ff3)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 5                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2013 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$ */
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 
lsapi_sigpipe(int sig)146 static void lsapi_sigpipe( int sig )
147 {
148 }
lsapi_siguser1(int sig)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 
lsapi_signal(int signo,sighandler_t handler)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 
lsapi_buildPacketHeader(struct lsapi_packet_header * pHeader,char type,int len)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 
lsapi_set_nblock(int fd,int nonblock)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 
lsapi_close(int fd)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 
lsapi_read(int fd,void * pBuf,int len)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 
lsapi_writev(int fd,struct iovec ** pVec,int count,int totalLen)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 
allocateBuf(LSAPI_Request * pReq,int size)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 
allocateIovec(LSAPI_Request * pReq,int n)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 
allocateRespHeaderBuf(LSAPI_Request * pReq,int size)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 
verifyHeader(struct lsapi_packet_header * pHeader,char pktType)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 
allocateEnvList(struct LSAPI_key_value_pair ** pEnvList,int * curSize,int newSize)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 
isPipe(int fd)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 
parseEnv(struct LSAPI_key_value_pair * pEnvList,int count,char ** pBegin,char * pEnd)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 
swapIntEndian(int * pInteger)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 
fixEndian(LSAPI_Request * pReq)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 
fixHeaderIndexEndian(LSAPI_Request * pReq)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 
parseRequest(LSAPI_Request * pReq,int totalLen)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} };
notify_req_received(int fd)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 
readReq(LSAPI_Request * pReq)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 
LSAPI_Init(void)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 
LSAPI_Stop(void)603 void LSAPI_Stop(void)
604 {
605     g_running = 0;
606 }
607 
LSAPI_IsRunning(void)608 int LSAPI_IsRunning(void)
609 {
610     return g_running;
611 }
612 
LSAPI_InitRequest(LSAPI_Request * pReq,int fd)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 
LSAPI_Is_Listen(void)644 int LSAPI_Is_Listen( void )
645 {
646     return LSAPI_Is_Listen_r( &g_req );
647 }
648 
LSAPI_Is_Listen_r(LSAPI_Request * pReq)649 int LSAPI_Is_Listen_r( LSAPI_Request * pReq)
650 {
651     return pReq->m_fdListen != -1;
652 }
653 
654 
655 
LSAPI_Accept_r(LSAPI_Request * pReq)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 
LSAPI_Finish_r(LSAPI_Request * pReq)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 
LSAPI_Reset_r(LSAPI_Request * pReq)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 
LSAPI_Release_r(LSAPI_Request * pReq)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 
LSAPI_GetHeader_r(LSAPI_Request * pReq,int headerIndex)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 
readBodyToReqBuf(LSAPI_Request * pReq)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 
LSAPI_ReqBodyGetChar_r(LSAPI_Request * pReq)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 
LSAPI_ReqBodyGetLine_r(LSAPI_Request * pReq,char * pBuf,int bufLen,int * getLF)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 
LSAPI_ReadReqBody_r(LSAPI_Request * pReq,char * pBuf,int bufLen)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 
LSAPI_Write_r(LSAPI_Request * pReq,const char * pBuf,int len)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 
Flush_RespBuf_r(LSAPI_Request * pReq)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 
LSAPI_Flush_r(LSAPI_Request * pReq)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 
LSAPI_Write_Stderr_r(LSAPI_Request * pReq,const char * pBuf,int len)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 
GetHeaderVar(LSAPI_Request * pReq,const char * name)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 
LSAPI_GetEnv_r(LSAPI_Request * pReq,const char * name)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 
LSAPI_ForeachOrgHeader_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)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 
LSAPI_ForeachHeader_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)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 
EnvForeach(struct LSAPI_key_value_pair * pEnv,int n,LSAPI_CB_EnvHandler fn,void * arg)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 
LSAPI_ForeachEnv_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)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 
LSAPI_ForeachSpecialEnv_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)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 
LSAPI_FinalizeRespHeaders_r(LSAPI_Request * pReq)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 
LSAPI_AppendRespHeader_r(LSAPI_Request * pReq,char * pBuf,int len)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 
LSAPI_CreateListenSock2(const struct sockaddr * pServerAddr,int backlog)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 
LSAPI_ParseSockAddr(const char * pBind,struct sockaddr * pAddr)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 
LSAPI_CreateListenSock(const char * pBind,int backlog)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 
LSAPI_Init_Prefork_Server(int max_children,fn_select_t fp,int avoidFork)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 
LSAPI_Set_Server_fd(int fd)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 
lsapi_accept(int fdListen)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 
lsapi_cleanup(int signal)1660 static void lsapi_cleanup(int signal)
1661 {
1662     s_stop = signal;
1663 }
1664 
find_child_status(int pid)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 
lsapi_sigchild(int signal)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 
lsapi_init_children_status()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 
lsapi_check_child_status(long tmCur)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 
lsapi_all_children_must_die()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 
lsapi_prefork_server_accept(lsapi_prefork_server * pServer,LSAPI_Request * pReq)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 
LSAPI_Prefork_Accept_r(LSAPI_Request * pReq)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 
LSAPI_Set_Max_Reqs(int reqs)2044 void LSAPI_Set_Max_Reqs( int reqs )
2045 {
2046     s_max_reqs = reqs;
2047 }
2048 
LSAPI_Set_Max_Idle(int secs)2049 void LSAPI_Set_Max_Idle( int secs )
2050 {
2051     s_max_idle_secs = secs;
2052 }
2053 
LSAPI_Set_Max_Children(int maxChildren)2054 void LSAPI_Set_Max_Children( int maxChildren )
2055 {
2056     if ( g_prefork_server ) {
2057         g_prefork_server->m_iMaxChildren = maxChildren;
2058     }
2059 }
2060 
LSAPI_Set_Extra_Children(int extraChildren)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 
LSAPI_Set_Max_Process_Time(int secs)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 
LSAPI_Set_Max_Idle_Children(int maxIdleChld)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 
LSAPI_Set_Server_Max_Idle_Secs(int serverMaxIdle)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 
LSAPI_Set_Slow_Req_Msecs(int msecs)2090 void LSAPI_Set_Slow_Req_Msecs( int msecs )
2091 {
2092 	s_slow_req_msecs = msecs;
2093 }
2094 
LSAPI_Get_Slow_Req_Msecs()2095 int  LSAPI_Get_Slow_Req_Msecs()
2096 {
2097 	return s_slow_req_msecs;
2098 }
2099 
LSAPI_No_Check_ppid()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
unset_lsapi_envs()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 
LSAPI_Init_Env_Parameters(fn_select_t fp)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 
2228