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