1 /*
2    +----------------------------------------------------------------------+
3    | Copyright (c) The PHP Group                                          |
4    +----------------------------------------------------------------------+
5    | This source file is subject to version 3.01 of the PHP license,      |
6    | that is bundled with this package in the file LICENSE, and is        |
7    | available through the world-wide-web at the following url:           |
8    | https://www.php.net/license/3_01.txt                                 |
9    | If you did not receive a copy of the PHP license and are unable to   |
10    | obtain it through the world-wide-web, please send a note to          |
11    | license@php.net so we can mail you a copy immediately.               |
12    +----------------------------------------------------------------------+
13    | Author: George Wang <gwang@litespeedtech.com>                        |
14    +----------------------------------------------------------------------+
15 */
16 
17 /*
18 Copyright (c) 2002-2018, Lite Speed Technologies Inc.
19 All rights reserved.
20 
21 Redistribution and use in source and binary forms, with or without
22 modification, are permitted provided that the following conditions are
23 met:
24 
25     * Redistributions of source code must retain the above copyright
26       notice, this list of conditions and the following disclaimer.
27     * Redistributions in binary form must reproduce the above
28       copyright notice, this list of conditions and the following
29       disclaimer in the documentation and/or other materials provided
30       with the distribution.
31     * Neither the name of the Lite Speed Technologies Inc nor the
32       names of its contributors may be used to endorse or promote
33       products derived from this software without specific prior
34       written permission.
35 
36 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
37 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
38 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
39 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
40 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
43 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47 */
48 
49 
50 #include <ctype.h>
51 #include <dlfcn.h>
52 #include <errno.h>
53 #include <fcntl.h>
54 #include <limits.h>
55 #include <sys/stat.h>
56 #include <sched.h>
57 #include <signal.h>
58 #include <stdlib.h>
59 #include <stdio.h>
60 #include <stdarg.h>
61 #include <string.h>
62 #include <sys/mman.h>
63 #include <sys/resource.h>
64 #include <sys/socket.h>
65 #include <sys/time.h>
66 #include <sys/uio.h>
67 #include <sys/wait.h>
68 #include <grp.h>
69 #include <pwd.h>
70 #include <time.h>
71 #include <unistd.h>
72 #include <arpa/inet.h>
73 #include <netdb.h>
74 #include <netinet/in.h>
75 #include <netinet/tcp.h>
76 #include <sys/un.h>
77 
78 #include "lsapilib.h"
79 
80 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
81 #include <sys/prctl.h>
82 #endif
83 
84 #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
85     || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
86 #include <sys/sysctl.h>
87 #endif
88 
89 #include <inttypes.h>
90 #ifndef uint32
91 #define uint32 uint32_t
92 #endif
93 
94 #include <Zend/zend_portability.h>
95 
96 struct lsapi_MD5Context {
97     uint32 buf[4];
98     uint32 bits[2];
99     unsigned char in[64];
100 };
101 
102 void lsapi_MD5Init(struct lsapi_MD5Context *context);
103 void lsapi_MD5Update(struct lsapi_MD5Context *context, unsigned char const *buf,
104            unsigned len);
105 void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *context);
106 
107 /*
108  * This is needed to make RSAREF happy on some MS-DOS compilers.
109  */
110 typedef struct lsapi_MD5Context lsapi_MD5_CTX;
111 
112 
113 #define LSAPI_ST_REQ_HEADER     1
114 #define LSAPI_ST_REQ_BODY       2
115 #define LSAPI_ST_RESP_HEADER    4
116 #define LSAPI_ST_RESP_BODY      8
117 #define LSAPI_ST_BACKGROUND     16
118 
119 #define LSAPI_RESP_BUF_SIZE     8192
120 #define LSAPI_INIT_RESP_HEADER_LEN 4096
121 
122 enum
123 {
124     LSAPI_STATE_IDLE,
125     LSAPI_STATE_CONNECTED,
126     LSAPI_STATE_ACCEPTING,
127 };
128 
129 typedef struct lsapi_child_status
130 {
131     int     m_pid;
132     long    m_tmStart;
133 
134     volatile short   m_iKillSent;
135     volatile char    m_inProcess;
136     volatile char    m_state;
137     volatile int     m_iReqCounter;
138 
139     volatile long    m_tmWaitBegin;
140     volatile long    m_tmReqBegin;
141     volatile long    m_tmLastCheckPoint;
142 }
143 lsapi_child_status;
144 
145 static lsapi_child_status * s_worker_status = NULL;
146 
147 static int g_inited = 0;
148 static int g_running = 1;
149 static int s_ppid;
150 static int s_restored_ppid = 0;
151 static int s_pid = 0;
152 static int s_slow_req_msecs = 0;
153 static int s_keep_listener = 1;
154 static int s_dump_debug_info = 0;
155 static int s_pid_dump_debug_info = 0;
156 static int s_req_processed = 0;
157 static int s_skip_write = 0;
158 static int (*pthread_atfork_func)(void (*prepare)(void), void (*parent)(void),
159                                   void (*child)(void)) = NULL;
160 
161 static int *s_busy_workers = NULL;
162 static int *s_accepting_workers = NULL;
163 static int *s_global_counter = &s_req_processed;
164 static int s_max_busy_workers = -1;
165 static char *s_stderr_log_path = NULL;
166 static int s_stderr_is_pipe = 0;
167 static int s_ignore_pid = -1;
168 static size_t s_total_pages = 1;
169 static size_t s_min_avail_pages = 256 * 1024;
170 static size_t *s_avail_pages = &s_total_pages;
171 
172 LSAPI_Request g_req =
173 { .m_fdListen = -1, .m_fd = -1 };
174 
175 static char         s_secret[24];
176 
177 static LSAPI_On_Timer_pf s_proc_group_timer_cb = NULL;
178 
179 void Flush_RespBuf_r( LSAPI_Request * pReq );
180 static int lsapi_reopen_stderr(const char *p);
181 
182 static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] =
183 {
184     "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET",
185     "HTTP_ACCEPT_ENCODING",
186     "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHORIZATION",
187     "HTTP_CONNECTION", "CONTENT_TYPE",
188     "CONTENT_LENGTH", "HTTP_COOKIE", "HTTP_COOKIE2",
189     "HTTP_HOST", "HTTP_PRAGMA",
190     "HTTP_REFERER", "HTTP_USER_AGENT",
191     "HTTP_CACHE_CONTROL",
192     "HTTP_IF_MODIFIED_SINCE", "HTTP_IF_MATCH",
193     "HTTP_IF_NONE_MATCH",
194     "HTTP_IF_RANGE",
195     "HTTP_IF_UNMODIFIED_SINCE",
196     "HTTP_KEEP_ALIVE",
197     "HTTP_RANGE",
198     "HTTP_X_FORWARDED_FOR",
199     "HTTP_VIA",
200     "HTTP_TRANSFER_ENCODING"
201 };
202 
203 static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] =
204 {    11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 18,
205      22, 13, 18, 13, 24, 15, 10, 20, 8, 22 };
206 
207 
208 static const char *HTTP_HEADERS[H_TRANSFER_ENCODING+1] =
209 {
210     "Accept", "Accept-Charset",
211     "Accept-Encoding",
212     "Accept-Language", "Authorization",
213     "Connection", "Content-Type",
214     "Content-Length", "Cookie", "Cookie2",
215     "Host", "Pragma",
216     "Referer", "User-Agent",
217     "Cache-Control",
218     "If-Modified-Since", "If-Match",
219     "If-None-Match",
220     "If-Range",
221     "If-Unmodified-Since",
222     "Keep-Alive",
223     "Range",
224     "X-Forwarded-For",
225     "Via",
226     "Transfer-Encoding"
227 };
228 
229 static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] =
230 {   6, 14, 15, 15, 13, 10, 12, 14, 6, 7, 4, 6, 7, 10, //user-agent
231     13,17, 8, 13, 8, 19, 10, 5, 15, 3, 17
232 };
233 
234 
235 static const char *s_log_level_names[8] =
236 {
237     "", "DEBUG","INFO", "NOTICE", "WARN", "ERROR", "CRIT", "FATAL"
238 };
239 
240 
LSAPI_Log(int flag,const char * fmt,...)241 void LSAPI_Log(int flag, const char * fmt, ...)
242 {
243     char buf[1024];
244     char *p = buf;
245     if ((flag & LSAPI_LOG_TIMESTAMP_BITS)
246         && !(s_stderr_is_pipe))
247     {
248         struct timeval  tv;
249         struct tm       tm;
250         gettimeofday(&tv, NULL);
251         localtime_r(&tv.tv_sec, &tm);
252         if (flag & LSAPI_LOG_TIMESTAMP_FULL)
253         {
254             p += snprintf(p, 1024, "%04d-%02d-%02d %02d:%02d:%02d.%06d ",
255                 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
256                 tm.tm_hour, tm.tm_min, tm.tm_sec, (int)tv.tv_usec);
257         }
258         else if (flag & LSAPI_LOG_TIMESTAMP_HMS)
259         {
260             p += snprintf(p, 1024, "%02d:%02d:%02d ",
261                 tm.tm_hour, tm.tm_min, tm.tm_sec);
262         }
263     }
264 
265     int level = flag & LSAPI_LOG_LEVEL_BITS;
266     if (level && level <= LSAPI_LOG_FLAG_FATAL)
267     {
268         p += snprintf(p, 100, "[%s] ", s_log_level_names[level]);
269     }
270 
271     if (flag & LSAPI_LOG_PID)
272     {
273         p += snprintf(p, 100, "[UID:%d][%d] ", getuid(), s_pid);
274     }
275 
276     if (p > buf)
277         fprintf(stderr, "%.*s", (int)(p - buf), buf);
278     va_list ap;
279     va_start(ap, fmt);
280     vfprintf(stderr, fmt, ap);
281     va_end(ap);
282 }
283 
284 #ifdef LSAPI_DEBUG
285 
286 #define DBGLOG_FLAG (LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_FLAG_DEBUG|LSAPI_LOG_PID)
287 #define lsapi_dbg(...)   LSAPI_Log(DBGLOG_FLAG, __VA_ARGS__)
288 
289 #else
290 
291 #define lsapi_dbg(...)
292 
293 #endif
294 
295 #define lsapi_log(...)  LSAPI_Log(LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_PID, __VA_ARGS__)
296 
297 
lsapi_perror(const char * pMessage,int err_no)298 void lsapi_perror(const char * pMessage, int err_no)
299 {
300     lsapi_log("%s, errno: %d (%s)\n", pMessage, err_no, strerror(err_no));
301 }
302 
303 
lsapi_parent_dead()304 static int lsapi_parent_dead()
305 {
306     // Return non-zero if the parent is dead.  0 if still alive.
307     if (!s_ppid) {
308         // not checking, so not dead
309         return(0);
310     }
311     if (s_restored_ppid) {
312         if (kill(s_restored_ppid,0) == -1) {
313             if (errno == EPERM) {
314                 return(0); // no permission, but it's still there.
315             }
316             return(1); // Dead
317         }
318         return(0); // it worked, so it's not dead
319     }
320     return(s_ppid != getppid());
321 }
322 
323 
lsapi_sigpipe(int sig)324 static void lsapi_sigpipe( int sig )
325 {
326 }
327 
328 
lsapi_siguser1(int sig)329 static void lsapi_siguser1( int sig )
330 {
331     g_running = 0;
332 }
333 
334 #ifndef sighandler_t
335 typedef void (*sighandler_t)(int);
336 #endif
337 
lsapi_signal(int signo,sighandler_t handler)338 static void lsapi_signal(int signo, sighandler_t handler)
339 {
340     struct sigaction sa;
341 
342     sigaction(signo, NULL, &sa);
343 
344     if (sa.sa_handler == SIG_DFL)
345     {
346         sigemptyset(&sa.sa_mask);
347         sa.sa_flags = 0;
348         sa.sa_handler = handler;
349         sigaction(signo, &sa, NULL);
350     }
351 }
352 
353 
354 static int s_enable_core_dump = 0;
lsapi_enable_core_dump(void)355 static void lsapi_enable_core_dump(void)
356 {
357 #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
358     || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
359     int  mib[2];
360     size_t len;
361 
362 #if !defined(__OpenBSD__)
363     len = 2;
364     if ( sysctlnametomib("kern.sugid_coredump", mib, &len) == 0 )
365     {
366         len = sizeof(s_enable_core_dump);
367         if (sysctl(mib, 2, NULL, 0, &s_enable_core_dump, len) == -1)
368             perror( "sysctl: Failed to set 'kern.sugid_coredump', "
369                     "core dump may not be available!");
370     }
371 #else
372     int set = 3;
373     len = sizeof(set);
374     mib[0] = CTL_KERN;
375     mib[1] = KERN_NOSUIDCOREDUMP;
376     if (sysctl(mib, 2, NULL, 0, &set, len) == 0) {
377 	    s_enable_core_dump = 1;
378     }
379 #endif
380 
381 
382 #endif
383 
384 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
385     if (prctl(PR_SET_DUMPABLE, s_enable_core_dump,0,0,0) == -1)
386         perror( "prctl: Failed to set dumpable, "
387                     "core dump may not be available!");
388 #endif
389 }
390 
391 
lsapi_buildPacketHeader(struct lsapi_packet_header * pHeader,char type,int len)392 static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader,
393                                 char type, int len )
394 {
395     pHeader->m_versionB0 = LSAPI_VERSION_B0;  /* LSAPI protocol version */
396     pHeader->m_versionB1 = LSAPI_VERSION_B1;
397     pHeader->m_type      = type;
398     pHeader->m_flag      = LSAPI_ENDIAN;
399     pHeader->m_packetLen.m_iLen = len;
400 }
401 
402 
lsapi_set_nblock(int fd,int nonblock)403 static  int lsapi_set_nblock( int fd, int nonblock )
404 {
405     int val = fcntl( fd, F_GETFL, 0 );
406     if ( nonblock )
407     {
408         if (!( val & O_NONBLOCK ))
409         {
410             return fcntl( fd, F_SETFL, val | O_NONBLOCK );
411         }
412     }
413     else
414     {
415         if ( val & O_NONBLOCK )
416         {
417             return fcntl( fd, F_SETFL, val &(~O_NONBLOCK) );
418         }
419     }
420     return 0;
421 }
422 
423 
lsapi_close(int fd)424 static int lsapi_close( int fd )
425 {
426     int ret;
427     while( 1 )
428     {
429         ret = close( fd );
430         if (( ret == -1 )&&( errno == EINTR )&&(g_running))
431             continue;
432         return ret;
433     }
434 }
435 
436 
lsapi_close_connection(LSAPI_Request * pReq)437 static void lsapi_close_connection(LSAPI_Request *pReq)
438 {
439     if (pReq->m_fd == -1)
440         return;
441     lsapi_close(pReq->m_fd);
442     pReq->m_fd = -1;
443     if (s_busy_workers)
444         __sync_fetch_and_sub(s_busy_workers, 1);
445     if (s_worker_status)
446         __sync_lock_test_and_set(&s_worker_status->m_state, LSAPI_STATE_IDLE);
447 }
448 
449 
lsapi_read(int fd,void * pBuf,size_t len)450 static inline ssize_t lsapi_read( int fd, void * pBuf, size_t len )
451 {
452     ssize_t ret;
453     while( 1 )
454     {
455         ret = read( fd, (char *)pBuf, len );
456         if (( ret == -1 )&&( errno == EINTR )&&(g_running))
457             continue;
458         return ret;
459     }
460 }
461 
462 
463 /*
464 static int lsapi_write( int fd, const void * pBuf, int len )
465 {
466    int ret;
467    const char * pCur;
468    const char * pEnd;
469    if ( len == 0 )
470        return 0;
471    pCur = (const char *)pBuf;
472    pEnd = pCur + len;
473    while( g_running && (pCur < pEnd) )
474    {
475        ret = write( fd, pCur, pEnd - pCur );
476        if ( ret >= 0)
477            pCur += ret;
478        else if (( ret == -1 )&&( errno != EINTR ))
479            return ret;
480    }
481    return pCur - (const char *)pBuf;
482 }
483 */
484 
485 
lsapi_writev(int fd,struct iovec ** pVec,int count,int totalLen)486 static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen )
487 {
488     int ret;
489     int left = totalLen;
490     int n = count;
491 
492     if (s_skip_write)
493         return totalLen;
494 
495     while(( left > 0 )&&g_running )
496     {
497         ret = writev( fd, *pVec, n );
498         if ( ret > 0 )
499         {
500             left -= ret;
501             if (( left <= 0)||( !g_running ))
502                 return totalLen - left;
503             while( ret > 0 )
504             {
505                 if ( (*pVec)->iov_len <= (unsigned int )ret )
506                 {
507                     ret -= (*pVec)->iov_len;
508                     ++(*pVec);
509                 }
510                 else
511                 {
512                     (*pVec)->iov_base = (char *)(*pVec)->iov_base + ret;
513                     (*pVec)->iov_len -= ret;
514                     break;
515                 }
516             }
517         }
518         else if ( ret == -1 )
519         {
520             if ( errno == EAGAIN )
521             {
522                 if ( totalLen - left > 0 )
523                     return totalLen - left;
524                 else
525                     return -1;
526             }
527             else if ( errno != EINTR )
528                 return ret;
529         }
530     }
531     return totalLen - left;
532 }
533 
534 
535 /*
536 static int getTotalLen( struct iovec * pVec, int count )
537 {
538    struct iovec * pEnd = pVec + count;
539    int total = 0;
540    while( pVec < pEnd )
541    {
542        total += pVec->iov_len;
543        ++pVec;
544    }
545    return total;
546 }
547 */
548 
549 
allocateBuf(LSAPI_Request * pReq,int size)550 static inline int allocateBuf( LSAPI_Request * pReq, int size )
551 {
552     char * pBuf = (char *)realloc( pReq->m_pReqBuf, size );
553     if ( pBuf )
554     {
555         pReq->m_pReqBuf = pBuf;
556         pReq->m_reqBufSize = size;
557         pReq->m_pHeader = (struct lsapi_req_header *)pReq->m_pReqBuf;
558         return 0;
559     }
560     return -1;
561 }
562 
563 
allocateIovec(LSAPI_Request * pReq,int n)564 static int allocateIovec( LSAPI_Request * pReq, int n )
565 {
566     struct iovec * p = (struct iovec *)realloc(
567                 pReq->m_pIovec, sizeof(struct iovec) * n );
568     if ( !p )
569         return -1;
570     pReq->m_pIovecToWrite = p + ( pReq->m_pIovecToWrite - pReq->m_pIovec );
571     pReq->m_pIovecCur = p + ( pReq->m_pIovecCur - pReq->m_pIovec );
572     pReq->m_pIovec = p;
573     pReq->m_pIovecEnd = p + n;
574     return 0;
575 }
576 
577 
allocateRespHeaderBuf(LSAPI_Request * pReq,int size)578 static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size )
579 {
580     char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size );
581     if ( !p )
582         return -1;
583     pReq->m_pRespHeaderBufPos   = p + ( pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf );
584     pReq->m_pRespHeaderBuf      = p;
585     pReq->m_pRespHeaderBufEnd   = p + size;
586     return 0;
587 }
588 
589 
verifyHeader(struct lsapi_packet_header * pHeader,char pktType)590 static inline int verifyHeader( struct lsapi_packet_header * pHeader, char pktType )
591 {
592     if (( LSAPI_VERSION_B0 != pHeader->m_versionB0 )||
593         ( LSAPI_VERSION_B1 != pHeader->m_versionB1 )||
594         ( pktType != pHeader->m_type ))
595         return -1;
596     if ( LSAPI_ENDIAN != (pHeader->m_flag & LSAPI_ENDIAN_BIT ))
597     {
598         register char b;
599         b = pHeader->m_packetLen.m_bytes[0];
600         pHeader->m_packetLen.m_bytes[0] = pHeader->m_packetLen.m_bytes[3];
601         pHeader->m_packetLen.m_bytes[3] = b;
602         b = pHeader->m_packetLen.m_bytes[1];
603         pHeader->m_packetLen.m_bytes[1] = pHeader->m_packetLen.m_bytes[2];
604         pHeader->m_packetLen.m_bytes[2] = b;
605     }
606     return pHeader->m_packetLen.m_iLen;
607 }
608 
609 
allocateEnvList(struct LSAPI_key_value_pair ** pEnvList,int * curSize,int newSize)610 static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList,
611                         int *curSize, int newSize )
612 {
613     struct LSAPI_key_value_pair * pBuf;
614     if ( *curSize >= newSize )
615         return 0;
616     if ( newSize > 8192 )
617         return -1;
618     pBuf = (struct LSAPI_key_value_pair *)realloc( *pEnvList, newSize *
619                     sizeof(struct LSAPI_key_value_pair) );
620     if ( pBuf )
621     {
622         *pEnvList = pBuf;
623         *curSize  = newSize;
624         return 0;
625     }
626     else
627         return -1;
628 
629 }
630 
631 
isPipe(int fd)632 static inline int isPipe( int fd )
633 {
634     char        achPeer[128];
635     socklen_t   len = 128;
636     if (( getpeername( fd, (struct sockaddr *)achPeer, &len ) != 0 )&&
637         ( errno == ENOTCONN ))
638         return 0;
639     else
640         return 1;
641 }
642 
643 
parseEnv(struct LSAPI_key_value_pair * pEnvList,int count,char ** pBegin,char * pEnd)644 static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count,
645             char **pBegin, char * pEnd )
646 {
647     struct LSAPI_key_value_pair * pEnvEnd;
648         int keyLen = 0, valLen = 0;
649     if ( count > 8192 )
650         return -1;
651     pEnvEnd = pEnvList + count;
652     while( pEnvList != pEnvEnd )
653     {
654         if ( pEnd - *pBegin < 4 )
655             return -1;
656         keyLen = *((unsigned char *)((*pBegin)++));
657         keyLen = (keyLen << 8) + *((unsigned char *)((*pBegin)++));
658         valLen = *((unsigned char *)((*pBegin)++));
659         valLen = (valLen << 8) + *((unsigned char *)((*pBegin)++));
660         if ( *pBegin + keyLen + valLen > pEnd )
661             return -1;
662         if (( !keyLen )||( !valLen ))
663             return -1;
664 
665         pEnvList->pKey = *pBegin;
666         *pBegin += keyLen;
667         pEnvList->pValue = *pBegin;
668         *pBegin += valLen;
669 
670         pEnvList->keyLen = keyLen - 1;
671         pEnvList->valLen = valLen - 1;
672         ++pEnvList;
673     }
674     if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 )
675         return -1;
676     *pBegin += 4;
677     return 0;
678 }
679 
680 
swapIntEndian(int * pInteger)681 static inline void swapIntEndian( int * pInteger )
682 {
683     char * p = (char *)pInteger;
684     register char b;
685     b = p[0];
686     p[0] = p[3];
687     p[3] = b;
688     b = p[1];
689     p[1] = p[2];
690     p[2] = b;
691 
692 }
693 
694 
fixEndian(LSAPI_Request * pReq)695 static inline void fixEndian( LSAPI_Request * pReq )
696 {
697     struct lsapi_req_header *p= pReq->m_pHeader;
698     swapIntEndian( &p->m_httpHeaderLen );
699     swapIntEndian( &p->m_reqBodyLen );
700     swapIntEndian( &p->m_scriptFileOff );
701     swapIntEndian( &p->m_scriptNameOff );
702     swapIntEndian( &p->m_queryStringOff );
703     swapIntEndian( &p->m_requestMethodOff );
704     swapIntEndian( &p->m_cntUnknownHeaders );
705     swapIntEndian( &p->m_cntEnv );
706     swapIntEndian( &p->m_cntSpecialEnv );
707 }
708 
709 
fixHeaderIndexEndian(LSAPI_Request * pReq)710 static void fixHeaderIndexEndian( LSAPI_Request * pReq )
711 {
712     int i;
713     for( i = 0; i < H_TRANSFER_ENCODING; ++i )
714     {
715         if ( pReq->m_pHeaderIndex->m_headerOff[i] )
716         {
717             register char b;
718             char * p = (char *)(&pReq->m_pHeaderIndex->m_headerLen[i]);
719             b = p[0];
720             p[0] = p[1];
721             p[1] = b;
722             swapIntEndian( &pReq->m_pHeaderIndex->m_headerOff[i] );
723         }
724     }
725     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
726     {
727         struct lsapi_header_offset * pCur, *pEnd;
728         pCur = pReq->m_pUnknownHeader;
729         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
730         while( pCur < pEnd )
731         {
732             swapIntEndian( &pCur->nameOff );
733             swapIntEndian( &pCur->nameLen );
734             swapIntEndian( &pCur->valueOff );
735             swapIntEndian( &pCur->valueLen );
736             ++pCur;
737         }
738     }
739 }
740 
741 
validateHeaders(LSAPI_Request * pReq)742 static int validateHeaders( LSAPI_Request * pReq )
743 {
744     int totalLen = pReq->m_pHeader->m_httpHeaderLen;
745     int i;
746     for(i = 0; i < H_TRANSFER_ENCODING; ++i)
747     {
748         if ( pReq->m_pHeaderIndex->m_headerOff[i] )
749         {
750             if (pReq->m_pHeaderIndex->m_headerOff[i] > totalLen
751                 || pReq->m_pHeaderIndex->m_headerLen[i]
752                     + pReq->m_pHeaderIndex->m_headerOff[i] > totalLen)
753                 return -1;
754         }
755     }
756     if (pReq->m_pHeader->m_cntUnknownHeaders > 0)
757     {
758         struct lsapi_header_offset * pCur, *pEnd;
759         pCur = pReq->m_pUnknownHeader;
760         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
761         while( pCur < pEnd )
762         {
763             if (pCur->nameOff > totalLen
764                 || pCur->nameOff + pCur->nameLen > totalLen
765                 || pCur->valueOff > totalLen
766                 || pCur->valueOff + pCur->valueLen > totalLen)
767                 return -1;
768             ++pCur;
769         }
770     }
771     return 0;
772 }
773 
774 
775 static uid_t s_uid = 0;
776 static uid_t s_defaultUid;  //web server need set this
777 static gid_t s_defaultGid;
778 
779 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
780 
781 #define LSAPI_LVE_DISABLED  0
782 #define LSAPI_LVE_ENABLED   1
783 #define LSAPI_CAGEFS_ENABLED 2
784 #define LSAPI_CAGEFS_NO_SUEXEC 3
785 struct liblve;
786 static int s_enable_lve = LSAPI_LVE_DISABLED;
787 static struct liblve * s_lve = NULL;
788 
789 static void *s_liblve;
790 static int (*fp_lve_is_available)(void) = NULL;
791 static int (*fp_lve_instance_init)(struct liblve *) = NULL;
792 static int (*fp_lve_destroy)(struct liblve *) = NULL;
793 static int (*fp_lve_enter)(struct liblve *, uint32_t, int32_t, int32_t, uint32_t *) = NULL;
794 static int (*fp_lve_leave)(struct liblve *, uint32_t *) = NULL;
795 static int (*fp_lve_jail)( struct passwd *, char *) = NULL;
lsapi_load_lve_lib(void)796 static int lsapi_load_lve_lib(void)
797 {
798     s_liblve = DL_LOAD("liblve.so.0");
799     if (s_liblve)
800     {
801         fp_lve_is_available = dlsym(s_liblve, "lve_is_available");
802         if (dlerror() == NULL)
803         {
804             if ( !(*fp_lve_is_available)() )
805             {
806                 int uid = getuid();
807                 if ( uid )
808                 {
809                     if (setreuid( s_uid, uid )) {};
810                     if ( !(*fp_lve_is_available)() )
811                         s_enable_lve = 0;
812                     if (setreuid( uid, s_uid )) {};
813                 }
814             }
815         }
816     }
817     else
818     {
819         s_enable_lve = LSAPI_LVE_DISABLED;
820     }
821     return (s_liblve)? 0 : -1;
822 }
823 
824 
init_lve_ex(void)825 static int init_lve_ex(void)
826 {
827     int rc;
828     if ( !s_liblve )
829         return -1;
830     fp_lve_instance_init = dlsym(s_liblve, "lve_instance_init");
831     fp_lve_destroy = dlsym(s_liblve, "lve_destroy");
832     fp_lve_enter = dlsym(s_liblve, "lve_enter");
833     fp_lve_leave = dlsym(s_liblve, "lve_leave");
834     if ( s_enable_lve >= LSAPI_CAGEFS_ENABLED )
835         fp_lve_jail = dlsym(s_liblve, "jail" );
836 
837     if ( s_lve == NULL )
838     {
839         rc = (*fp_lve_instance_init)(NULL);
840         s_lve = malloc(rc);
841     }
842     rc = (*fp_lve_instance_init)(s_lve);
843     if (rc != 0)
844     {
845         perror( "LSAPI: Unable to initialize LVE" );
846         free( s_lve );
847         s_lve = NULL;
848         return -1;
849     }
850     return 0;
851 
852 }
853 
854 #endif
855 
856 
857 
readSecret(const char * pSecretFile)858 static int readSecret( const char * pSecretFile )
859 {
860     struct stat st;
861     int fd = open( pSecretFile, O_RDONLY , 0600 );
862     if ( fd == -1 )
863     {
864         lsapi_log("LSAPI: failed to open secret file: %s!\n", pSecretFile );
865         return -1;
866     }
867     if ( fstat( fd, &st ) == -1 )
868     {
869         lsapi_log("LSAPI: failed to check state of file: %s!\n", pSecretFile );
870         close( fd );
871         return -1;
872     }
873 /*
874     if ( st.st_uid != s_uid )
875     {
876         lsapi_log("LSAPI: file owner check failure: %s!\n", pSecretFile );
877         close( fd );
878         return -1;
879     }
880 */
881     if ( st.st_mode & 0077 )
882     {
883         lsapi_log("LSAPI: file permission check failure: %s\n", pSecretFile );
884         close( fd );
885         return -1;
886     }
887     if ( read( fd, s_secret, 16 ) < 16 )
888     {
889         lsapi_log("LSAPI: failed to read secret from secret file: %s\n", pSecretFile );
890         close( fd );
891         return -1;
892     }
893     close( fd );
894     return 0;
895 }
896 
897 
LSAPI_is_suEXEC_Daemon(void)898 int LSAPI_is_suEXEC_Daemon(void)
899 {
900     if (( !s_uid )&&( s_secret[0] ))
901         return 1;
902     else
903         return 0;
904 }
905 
906 
LSAPI_perror_r(LSAPI_Request * pReq,const char * pErr1,const char * pErr2)907 static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char *pErr2 )
908 {
909     char achError[4096];
910     int n = snprintf(achError, sizeof(achError), "[UID:%d][%d] %s:%s: %s\n",
911                      getuid(), getpid(),
912                      pErr1, (pErr2)?pErr2:"", strerror(errno));
913     if (n > (int)sizeof(achError))
914         n = sizeof(achError);
915     if ( pReq )
916         LSAPI_Write_Stderr_r( pReq, achError, n );
917     else
918         if (write( STDERR_FILENO, achError, n )) {};
919     return 0;
920 }
921 
922 
lsapi_lve_error(LSAPI_Request * pReq)923 static int lsapi_lve_error( LSAPI_Request * pReq )
924 {
925     static const char * headers[] =
926     {
927         "Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0",
928         "Pragma: no-cache",
929         "Retry-After: 60",
930         "Content-Type: text/html",
931         NULL
932     };
933     static const char achBody[] =
934         "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"
935         "<HTML><HEAD>\n<TITLE>508 Resource Limit Is Reached</TITLE>\n"
936         "</HEAD><BODY>\n" "<H1>Resource Limit Is Reached</H1>\n"
937         "The website is temporarily unable to service your request as it exceeded resource limit.\n"
938         "Please try again later.\n"
939         "<HR>\n"
940         "</BODY></HTML>\n";
941 
942     LSAPI_ErrResponse_r( pReq, 508, headers, achBody, sizeof( achBody ) - 1 );
943     return 0;
944 }
945 
946 
lsapi_enterLVE(LSAPI_Request * pReq,uid_t uid)947 static int lsapi_enterLVE( LSAPI_Request * pReq, uid_t uid )
948 {
949 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
950     if ( s_lve && uid ) //root user should not do that
951     {
952         uint32_t cookie;
953         int ret = -1;
954         ret = (*fp_lve_enter)(s_lve, uid, -1, -1, &cookie);
955         if ( ret < 0 )
956         {
957             //lsapi_log("enter LVE (%d) : result: %d !\n", uid, ret );
958             LSAPI_perror_r(pReq, "LSAPI: lve_enter() failure, reached resource limit.", NULL );
959             lsapi_lve_error( pReq );
960             return -1;
961         }
962     }
963 #endif
964 
965     return 0;
966 }
967 
968 
lsapi_jailLVE(LSAPI_Request * pReq,uid_t uid,struct passwd * pw)969 static int lsapi_jailLVE( LSAPI_Request * pReq, uid_t uid, struct passwd * pw )
970 {
971     int ret = 0;
972 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
973     char  error_msg[1024] = "";
974     ret = (*fp_lve_jail)( pw, error_msg );
975     if ( ret < 0 )
976     {
977         lsapi_log("LSAPI: LVE jail(%d) result: %d, error: %s !\n",
978                   uid, ret, error_msg );
979         LSAPI_perror_r( pReq, "LSAPI: jail() failure.", NULL );
980         return -1;
981     }
982 #endif
983     return ret;
984 }
985 
986 
987 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
lsapi_initLVE(void)988 static int lsapi_initLVE(void)
989 {
990     const char * pEnv;
991     if ( (pEnv = getenv( "LSAPI_LVE_ENABLE" ))!= NULL )
992     {
993         s_enable_lve = atol( pEnv );
994         pEnv = NULL;
995     }
996     else if ( (pEnv = getenv( "LVE_ENABLE" ))!= NULL )
997     {
998         s_enable_lve = atol( pEnv );
999         pEnv = NULL;
1000     }
1001     if ( s_enable_lve && !s_uid )
1002     {
1003         lsapi_load_lve_lib();
1004         if ( s_enable_lve )
1005         {
1006             return init_lve_ex();
1007         }
1008 
1009     }
1010     return 0;
1011 }
1012 #endif
1013 
1014 
setUID_LVE(LSAPI_Request * pReq,uid_t uid,gid_t gid,const char * pChroot)1015 static int setUID_LVE(LSAPI_Request * pReq, uid_t uid, gid_t gid, const char * pChroot)
1016 {
1017     int rv;
1018     struct passwd * pw;
1019     pw = getpwuid( uid );
1020 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
1021     if ( s_lve )
1022     {
1023         if( lsapi_enterLVE( pReq, uid ) == -1 )
1024             return -1;
1025         if ( pw && fp_lve_jail)
1026         {
1027             rv = lsapi_jailLVE( pReq, uid, pw );
1028             if ( rv == -1 )
1029                 return -1;
1030             if (( rv == 1 )&&(s_enable_lve == LSAPI_CAGEFS_NO_SUEXEC ))    //this mode only use cageFS, does not use suEXEC
1031             {
1032                 uid = s_defaultUid;
1033                 gid = s_defaultGid;
1034                 pw = getpwuid( uid );
1035             }
1036         }
1037     }
1038 #endif
1039     //if ( !uid || !gid )  //do not allow root
1040     //{
1041     //    return -1;
1042     //}
1043 
1044 #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) \
1045     || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
1046     if ( s_enable_core_dump )
1047         lsapi_enable_core_dump();
1048 #endif
1049 
1050     rv = setgid(gid);
1051     if (rv == -1)
1052     {
1053         LSAPI_perror_r(pReq, "LSAPI: setgid()", NULL);
1054         return -1;
1055     }
1056     if ( pw && (pw->pw_gid == gid ))
1057     {
1058         rv = initgroups( pw->pw_name, gid );
1059         if (rv == -1)
1060         {
1061             LSAPI_perror_r(pReq, "LSAPI: initgroups()", NULL);
1062             return -1;
1063         }
1064     }
1065     else
1066     {
1067         rv = setgroups(1, &gid);
1068         if (rv == -1)
1069         {
1070             LSAPI_perror_r(pReq, "LSAPI: setgroups()", NULL);
1071         }
1072     }
1073     if ( pChroot )
1074     {
1075         rv = chroot( pChroot );
1076         if ( rv == -1 )
1077         {
1078             LSAPI_perror_r(pReq, "LSAPI: chroot()", NULL);
1079             return -1;
1080         }
1081     }
1082     rv = setuid(uid);
1083     if (rv == -1)
1084     {
1085         LSAPI_perror_r(pReq, "LSAPI: setuid()", NULL);
1086         return -1;
1087     }
1088 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
1089     if ( s_enable_core_dump )
1090         lsapi_enable_core_dump();
1091 #endif
1092     return 0;
1093 }
1094 
lsapi_suexec_auth(LSAPI_Request * pReq,char * pAuth,int len,char * pUgid,int ugidLen)1095 static int lsapi_suexec_auth( LSAPI_Request *pReq,
1096             char * pAuth, int len, char * pUgid, int ugidLen )
1097 {
1098     lsapi_MD5_CTX md5ctx;
1099     unsigned char achMD5[16];
1100     if ( len < 32 )
1101         return -1;
1102     memmove( achMD5, pAuth + 16, 16 );
1103     memmove( pAuth + 16, s_secret, 16 );
1104     lsapi_MD5Init( &md5ctx );
1105     lsapi_MD5Update( &md5ctx, (unsigned char *)pAuth, 32 );
1106     lsapi_MD5Update( &md5ctx, (unsigned char *)pUgid, 8 );
1107     lsapi_MD5Final( (unsigned char *)pAuth + 16, &md5ctx);
1108     if ( memcmp( achMD5, pAuth + 16, 16 ) == 0 )
1109         return 0;
1110     return 1;
1111 }
1112 
1113 
lsapi_changeUGid(LSAPI_Request * pReq)1114 static int lsapi_changeUGid( LSAPI_Request * pReq )
1115 {
1116     int uid = s_defaultUid;
1117     int gid = s_defaultGid;
1118     const char *pStderrLog;
1119     const char *pChroot = NULL;
1120     struct LSAPI_key_value_pair * pEnv;
1121     struct LSAPI_key_value_pair * pAuth;
1122     int i;
1123     if ( s_uid )
1124         return 0;
1125     //with special ID  0x00
1126     //authenticate the suEXEC request;
1127     //first one should be MD5( nonce + lscgid secret )
1128     //remember to clear the secret after verification
1129     //it should be set at the end of special env
1130     i = pReq->m_pHeader->m_cntSpecialEnv - 1;
1131     if ( i >= 0 )
1132     {
1133         pEnv = pReq->m_pSpecialEnvList + i;
1134         if (( *pEnv->pKey == '\000' )&&
1135             ( strcmp( pEnv->pKey+1, "SUEXEC_AUTH" ) == 0 ))
1136         {
1137             --pReq->m_pHeader->m_cntSpecialEnv;
1138             pAuth = pEnv--;
1139             if (( *pEnv->pKey == '\000' )&&
1140                 ( strcmp( pEnv->pKey+1, "SUEXEC_UGID" ) == 0 ))
1141             {
1142                 --pReq->m_pHeader->m_cntSpecialEnv;
1143                 uid = *(uint32_t *)pEnv->pValue;
1144                 gid = *(((uint32_t *)pEnv->pValue) + 1 );
1145                 //lsapi_log("LSAPI: SUEXEC_UGID set UID: %d, GID: %d\n", uid, gid );
1146             }
1147             else
1148             {
1149                 lsapi_log("LSAPI: missing SUEXEC_UGID env, use default user!\n" );
1150                 pEnv = NULL;
1151             }
1152             if ( pEnv&& lsapi_suexec_auth( pReq, pAuth->pValue, pAuth->valLen, pEnv->pValue, pEnv->valLen ) == 0 )
1153             {
1154                 //read UID, GID from specialEnv
1155 
1156             }
1157             else
1158             {
1159                 //authentication error
1160                 lsapi_log("LSAPI: SUEXEC_AUTH authentication failed, use default user!\n" );
1161                 uid = 0;
1162             }
1163         }
1164         else
1165         {
1166             //lsapi_log("LSAPI: no SUEXEC_AUTH env, use default user!\n" );
1167         }
1168     }
1169 
1170 
1171     if ( !uid )
1172     {
1173         uid = s_defaultUid;
1174         gid = s_defaultGid;
1175     }
1176 
1177     //change uid
1178     if ( setUID_LVE( pReq, uid, gid, pChroot ) == -1 )
1179     {
1180         return -1;
1181     }
1182 
1183     s_uid = uid;
1184 
1185     if ( pReq->m_fdListen != -1 )
1186     {
1187         close( pReq->m_fdListen );
1188         pReq->m_fdListen = -1;
1189     }
1190 
1191     pStderrLog = LSAPI_GetEnv_r( pReq, "LSAPI_STDERR_LOG");
1192     if (pStderrLog)
1193         lsapi_reopen_stderr(pStderrLog);
1194 
1195     return 0;
1196 
1197 }
1198 
1199 
parseContentLenFromHeader(LSAPI_Request * pReq)1200 static int parseContentLenFromHeader(LSAPI_Request * pReq)
1201 {
1202     const char * pContentLen = LSAPI_GetHeader_r( pReq, H_CONTENT_LENGTH );
1203     if ( pContentLen )
1204         pReq->m_reqBodyLen = strtoll( pContentLen, NULL, 10 );
1205     return 0;
1206 }
1207 
1208 
parseRequest(LSAPI_Request * pReq,int totalLen)1209 static int parseRequest( LSAPI_Request * pReq, int totalLen )
1210 {
1211     int shouldFixEndian;
1212     char * pBegin = pReq->m_pReqBuf + sizeof( struct lsapi_req_header );
1213     char * pEnd = pReq->m_pReqBuf + totalLen;
1214     shouldFixEndian = ( LSAPI_ENDIAN != (
1215                 pReq->m_pHeader->m_pktHeader.m_flag & LSAPI_ENDIAN_BIT ) );
1216     if ( shouldFixEndian )
1217     {
1218         fixEndian( pReq );
1219     }
1220     if ( (pReq->m_specialEnvListSize < pReq->m_pHeader->m_cntSpecialEnv )&&
1221             allocateEnvList( &pReq->m_pSpecialEnvList,
1222                 &pReq->m_specialEnvListSize,
1223                 pReq->m_pHeader->m_cntSpecialEnv ) == -1 )
1224         return -1;
1225     if ( (pReq->m_envListSize < pReq->m_pHeader->m_cntEnv )&&
1226             allocateEnvList( &pReq->m_pEnvList, &pReq->m_envListSize,
1227                 pReq->m_pHeader->m_cntEnv ) == -1 )
1228         return -1;
1229 
1230     if ( parseEnv( pReq->m_pSpecialEnvList,
1231                 pReq->m_pHeader->m_cntSpecialEnv,
1232                 &pBegin, pEnd ) == -1 )
1233         return -1;
1234     if ( parseEnv( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
1235                 &pBegin, pEnd ) == -1 )
1236         return -1;
1237     if (pReq->m_pHeader->m_scriptFileOff < 0
1238         || pReq->m_pHeader->m_scriptFileOff >= totalLen
1239         || pReq->m_pHeader->m_scriptNameOff < 0
1240         || pReq->m_pHeader->m_scriptNameOff >= totalLen
1241         || pReq->m_pHeader->m_queryStringOff < 0
1242         || pReq->m_pHeader->m_queryStringOff >= totalLen
1243         || pReq->m_pHeader->m_requestMethodOff < 0
1244         || pReq->m_pHeader->m_requestMethodOff >= totalLen)
1245     {
1246         lsapi_log("Bad request header - ERROR#1\n");
1247         return -1;
1248     }
1249     pReq->m_pScriptFile     = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptFileOff;
1250     pReq->m_pScriptName     = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptNameOff;
1251     pReq->m_pQueryString    = pReq->m_pReqBuf + pReq->m_pHeader->m_queryStringOff;
1252     pReq->m_pRequestMethod  = pReq->m_pReqBuf + pReq->m_pHeader->m_requestMethodOff;
1253 
1254     pBegin = pReq->m_pReqBuf + (( pBegin - pReq->m_pReqBuf + 7 ) & (~0x7));
1255     pReq->m_pHeaderIndex = ( struct lsapi_http_header_index * )pBegin;
1256     pBegin += sizeof( struct lsapi_http_header_index );
1257 
1258     pReq->m_pUnknownHeader = (struct lsapi_header_offset *)pBegin;
1259     pBegin += sizeof( struct lsapi_header_offset) *
1260                     pReq->m_pHeader->m_cntUnknownHeaders;
1261 
1262     pReq->m_pHttpHeader = pBegin;
1263     pBegin += pReq->m_pHeader->m_httpHeaderLen;
1264     if ( pBegin != pEnd )
1265     {
1266         lsapi_log("Request header does match total size, total: %d, "
1267                  "real: %ld\n", totalLen, pBegin - pReq->m_pReqBuf );
1268         return -1;
1269     }
1270     if ( shouldFixEndian )
1271     {
1272         fixHeaderIndexEndian( pReq );
1273     }
1274 
1275     if (validateHeaders(pReq) == -1)
1276     {
1277         lsapi_log("Bad request header - ERROR#2\n");
1278         return -1;
1279     }
1280 
1281     pReq->m_reqBodyLen = pReq->m_pHeader->m_reqBodyLen;
1282     if ( pReq->m_reqBodyLen == -2 )
1283     {
1284         parseContentLenFromHeader(pReq);
1285     }
1286 
1287     return 0;
1288 }
1289 
1290 
1291 //OPTIMIZATION
1292 static char s_accept_notify = 0;
1293 static char s_schedule_notify = 0;
1294 static char s_notify_scheduled = 0;
1295 static char s_notified_pid = 0;
1296 
1297 static struct lsapi_packet_header s_ack = {'L', 'S',
1298                 LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
1299 static struct lsapi_packet_header s_conn_close_pkt = {'L', 'S',
1300                 LSAPI_CONN_CLOSE, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
1301 
1302 
send_notification_pkt(int fd,struct lsapi_packet_header * pkt)1303 static inline int send_notification_pkt( int fd, struct lsapi_packet_header *pkt )
1304 {
1305     if ( write( fd, pkt, LSAPI_PACKET_HEADER_LEN ) < LSAPI_PACKET_HEADER_LEN )
1306         return -1;
1307     return 0;
1308 }
1309 
1310 
send_req_received_notification(int fd)1311 static inline int send_req_received_notification( int fd )
1312 {
1313     return send_notification_pkt(fd, &s_ack);
1314 }
1315 
1316 
send_conn_close_notification(int fd)1317 static inline int send_conn_close_notification( int fd )
1318 {
1319     return send_notification_pkt(fd, &s_conn_close_pkt);
1320 }
1321 
1322 
1323 //static void lsapi_sigalarm( int sig )
1324 //{
1325 //    if ( s_notify_scheduled )
1326 //    {
1327 //        s_notify_scheduled = 0;
1328 //        if ( g_req.m_fd != -1 )
1329 //            write_req_received_notification( g_req.m_fd );
1330 //    }
1331 //}
1332 
1333 
lsapi_schedule_notify(void)1334 static inline int lsapi_schedule_notify(void)
1335 {
1336     if ( !s_notify_scheduled )
1337     {
1338         alarm( 2 );
1339         s_notify_scheduled = 1;
1340     }
1341     return 0;
1342 }
1343 
1344 
notify_req_received(int fd)1345 static inline int notify_req_received( int fd )
1346 {
1347     if ( s_schedule_notify )
1348         return lsapi_schedule_notify();
1349     return send_req_received_notification( fd );
1350 
1351 }
1352 
1353 
lsapi_notify_pid(int fd)1354 static inline int lsapi_notify_pid( int fd )
1355 {
1356     char achBuf[16];
1357     lsapi_buildPacketHeader( (struct lsapi_packet_header *)achBuf, LSAPI_STDERR_STREAM,
1358                         8 + LSAPI_PACKET_HEADER_LEN );
1359     memmove( &achBuf[8], "\0PID", 4 );
1360     *((int *)&achBuf[12]) = getpid();
1361 
1362     if ( write( fd, achBuf, 16 ) < 16 )
1363         return -1;
1364     return 0;
1365 }
1366 
1367 
1368 static char s_conn_key_packet[16];
init_conn_key(int fd)1369 static inline int init_conn_key( int fd )
1370 {
1371     struct lsapi_packet_header * pHeader = (struct lsapi_packet_header *)s_conn_key_packet;
1372     struct timeval tv;
1373     int i;
1374     gettimeofday( &tv, NULL );
1375     srand( (tv.tv_sec % 0x1000 + tv.tv_usec) ^ rand() );
1376     for( i = 8; i < 16; ++i )
1377     {
1378         s_conn_key_packet[i]=(int) (256.0*rand()/(RAND_MAX+1.0));
1379     }
1380     lsapi_buildPacketHeader( pHeader, LSAPI_REQ_RECEIVED,
1381                         8 + LSAPI_PACKET_HEADER_LEN );
1382     if ( write( fd, s_conn_key_packet, LSAPI_PACKET_HEADER_LEN+8 )
1383                 < LSAPI_PACKET_HEADER_LEN+8 )
1384         return -1;
1385     return 0;
1386 
1387 
1388 }
1389 
1390 
readReq(LSAPI_Request * pReq)1391 static int readReq( LSAPI_Request * pReq )
1392 {
1393     int len;
1394     int packetLen;
1395     if ( !pReq )
1396         return -1;
1397     if ( pReq->m_reqBufSize < 8192 )
1398     {
1399         if ( allocateBuf( pReq, 8192 ) == -1 )
1400             return -1;
1401     }
1402 
1403     while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN )
1404     {
1405         len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf, pReq->m_reqBufSize );
1406         if ( len <= 0 )
1407             return -1;
1408         pReq->m_bufRead += len;
1409     }
1410     pReq->m_reqState = LSAPI_ST_REQ_HEADER;
1411 
1412     packetLen = verifyHeader( &pReq->m_pHeader->m_pktHeader, LSAPI_BEGIN_REQUEST );
1413     if ( packetLen < 0 )
1414     {
1415         lsapi_log("packetLen < 0\n");
1416         return -1;
1417     }
1418     if ( packetLen > LSAPI_MAX_HEADER_LEN )
1419     {
1420         lsapi_log("packetLen > %d\n", LSAPI_MAX_HEADER_LEN );
1421         return -1;
1422     }
1423 
1424     if ( packetLen + 1024 > pReq->m_reqBufSize )
1425     {
1426         if ( allocateBuf( pReq, packetLen + 1024 ) == -1 )
1427             return -1;
1428     }
1429     while( packetLen > pReq->m_bufRead )
1430     {
1431         len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, packetLen - pReq->m_bufRead );
1432         if ( len <= 0 )
1433             return -1;
1434         pReq->m_bufRead += len;
1435     }
1436     if ( parseRequest( pReq, packetLen ) < 0 )
1437     {
1438         lsapi_log("ParseRequest error\n");
1439         return -1;
1440     }
1441 
1442     pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER;
1443 
1444     if ( !s_uid )
1445     {
1446         if ( lsapi_changeUGid( pReq ) )
1447             return -1;
1448         memset(s_secret, 0, sizeof(s_secret));
1449     }
1450     pReq->m_bufProcessed = packetLen;
1451 
1452     //OPTIMIZATION
1453     if ( !s_accept_notify && !s_notified_pid )
1454         return notify_req_received( pReq->m_fd );
1455     else
1456     {
1457         s_notified_pid = 0;
1458         return 0;
1459     }
1460 }
1461 
1462 
LSAPI_Init(void)1463 int LSAPI_Init(void)
1464 {
1465     if ( !g_inited )
1466     {
1467         s_uid = geteuid();
1468         s_secret[0] = 0;
1469         lsapi_signal(SIGPIPE, lsapi_sigpipe);
1470         lsapi_signal(SIGUSR1, lsapi_siguser1);
1471 
1472 #if defined(SIGXFSZ) && defined(SIG_IGN)
1473         signal(SIGXFSZ, SIG_IGN);
1474 #endif
1475         /* let STDOUT function as STDERR,
1476            just in case writing to STDOUT directly */
1477         dup2( 2, 1 );
1478         if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 )
1479             return -1;
1480         g_inited = 1;
1481         s_ppid = getppid();
1482         void *pthread_lib = dlopen("libpthread.so", RTLD_LAZY);
1483         if (pthread_lib)
1484             pthread_atfork_func = dlsym(pthread_lib, "pthread_atfork");
1485 
1486     }
1487     return 0;
1488 }
1489 
1490 
LSAPI_Stop(void)1491 void LSAPI_Stop(void)
1492 {
1493     g_running = 0;
1494 }
1495 
1496 
LSAPI_IsRunning(void)1497 int LSAPI_IsRunning(void)
1498 {
1499     return g_running;
1500 }
1501 
1502 
LSAPI_Register_Pgrp_Timer_Callback(LSAPI_On_Timer_pf cb)1503 void LSAPI_Register_Pgrp_Timer_Callback(LSAPI_On_Timer_pf cb)
1504 {
1505     s_proc_group_timer_cb = cb;
1506 }
1507 
1508 
LSAPI_InitRequest(LSAPI_Request * pReq,int fd)1509 int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
1510 {
1511     int newfd;
1512     if ( !pReq )
1513         return -1;
1514     memset( pReq, 0, sizeof( LSAPI_Request ) );
1515     if ( allocateIovec( pReq, 16 ) == -1 )
1516         return -1;
1517     pReq->m_pRespBuf = pReq->m_pRespBufPos = (char *)malloc( LSAPI_RESP_BUF_SIZE );
1518     if ( !pReq->m_pRespBuf )
1519         return -1;
1520     pReq->m_pRespBufEnd = pReq->m_pRespBuf + LSAPI_RESP_BUF_SIZE;
1521     pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
1522     pReq->m_respPktHeaderEnd = &pReq->m_respPktHeader[5];
1523     if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 )
1524         return -1;
1525 
1526     if ( fd == STDIN_FILENO )
1527     {
1528         fd = dup( fd );
1529         newfd = open( "/dev/null", O_RDWR );
1530         dup2( newfd, STDIN_FILENO );
1531     }
1532 
1533     if ( isPipe( fd ) )
1534     {
1535         pReq->m_fdListen = -1;
1536         pReq->m_fd = fd;
1537     }
1538     else
1539     {
1540         pReq->m_fdListen = fd;
1541         pReq->m_fd = -1;
1542         lsapi_set_nblock( fd, 1 );
1543     }
1544     return 0;
1545 }
1546 
1547 
LSAPI_Is_Listen(void)1548 int LSAPI_Is_Listen( void )
1549 {
1550     return LSAPI_Is_Listen_r( &g_req );
1551 }
1552 
1553 
LSAPI_Is_Listen_r(LSAPI_Request * pReq)1554 int LSAPI_Is_Listen_r( LSAPI_Request * pReq)
1555 {
1556     return pReq->m_fdListen != -1;
1557 }
1558 
1559 
LSAPI_Accept_r(LSAPI_Request * pReq)1560 int LSAPI_Accept_r( LSAPI_Request * pReq )
1561 {
1562     char        achPeer[128];
1563     socklen_t   len;
1564     int         nodelay = 1;
1565 
1566     if ( !pReq )
1567         return -1;
1568     if ( LSAPI_Finish_r( pReq ) == -1 )
1569         return -1;
1570     lsapi_set_nblock( pReq->m_fdListen , 0 );
1571     while( g_running )
1572     {
1573         if ( pReq->m_fd == -1 )
1574         {
1575             if ( pReq->m_fdListen != -1)
1576             {
1577                 len = sizeof( achPeer );
1578                 pReq->m_fd = accept( pReq->m_fdListen,
1579                             (struct sockaddr *)&achPeer, &len );
1580                 if ( pReq->m_fd == -1 )
1581                 {
1582                     if (( errno == EINTR )||( errno == EAGAIN))
1583                         continue;
1584                     else
1585                         return -1;
1586                 }
1587                 else
1588                 {
1589                     if (s_worker_status)
1590                         __sync_lock_test_and_set(&s_worker_status->m_state,
1591                                                  LSAPI_STATE_CONNECTED);
1592                     if (s_busy_workers)
1593                         __sync_fetch_and_add(s_busy_workers, 1);
1594                     lsapi_set_nblock( pReq->m_fd , 0 );
1595                     if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
1596                     {
1597                         setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY,
1598                                    (char *)&nodelay, sizeof(nodelay));
1599                     }
1600                     //init_conn_key( pReq->m_fd );
1601                     //OPTIMIZATION
1602                     if ( s_accept_notify )
1603                         if ( notify_req_received( pReq->m_fd ) == -1 )
1604                                 return -1;
1605                 }
1606             }
1607             else
1608                 return -1;
1609         }
1610         if ( !readReq( pReq ) )
1611             break;
1612         //abort();
1613         lsapi_close_connection(pReq);
1614         LSAPI_Reset_r( pReq );
1615     }
1616     return 0;
1617 }
1618 
1619 
1620 static struct lsapi_packet_header   finish_close[2] =
1621 {
1622     {'L', 'S', LSAPI_RESP_END, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} },
1623     {'L', 'S', LSAPI_CONN_CLOSE, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} }
1624 };
1625 
1626 
LSAPI_Finish_r(LSAPI_Request * pReq)1627 int LSAPI_Finish_r( LSAPI_Request * pReq )
1628 {
1629     /* finish req body */
1630     if ( !pReq )
1631         return -1;
1632     if (pReq->m_reqState)
1633     {
1634         if ( pReq->m_fd != -1 )
1635         {
1636             if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1637             {
1638                 LSAPI_FinalizeRespHeaders_r( pReq );
1639             }
1640             if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
1641             {
1642                 Flush_RespBuf_r( pReq );
1643             }
1644 
1645             pReq->m_pIovecCur->iov_base = (void *)finish_close;
1646             pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
1647             pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN;
1648             ++pReq->m_pIovecCur;
1649             LSAPI_Flush_r( pReq );
1650         }
1651         LSAPI_Reset_r( pReq );
1652     }
1653     return 0;
1654 }
1655 
1656 
LSAPI_End_Response_r(LSAPI_Request * pReq)1657 int LSAPI_End_Response_r(LSAPI_Request * pReq)
1658 {
1659     if (!pReq)
1660         return -1;
1661     if (pReq->m_reqState & LSAPI_ST_BACKGROUND)
1662         return 0;
1663     if (pReq->m_reqState)
1664     {
1665         if ( pReq->m_fd != -1 )
1666         {
1667             if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1668             {
1669                 if ( pReq->m_pRespHeaderBufPos <= pReq->m_pRespHeaderBuf )
1670                     return 0;
1671 
1672                 LSAPI_FinalizeRespHeaders_r( pReq );
1673             }
1674             if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
1675             {
1676                 Flush_RespBuf_r( pReq );
1677             }
1678 
1679             pReq->m_pIovecCur->iov_base = (void *)finish_close;
1680             pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN << 1;
1681             pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN << 1;
1682             ++pReq->m_pIovecCur;
1683             LSAPI_Flush_r( pReq );
1684             lsapi_close_connection(pReq);
1685         }
1686         pReq->m_reqState |= LSAPI_ST_BACKGROUND;
1687     }
1688     return 0;
1689 }
1690 
1691 
LSAPI_Reset_r(LSAPI_Request * pReq)1692 void LSAPI_Reset_r( LSAPI_Request * pReq )
1693 {
1694     pReq->m_pRespBufPos         = pReq->m_pRespBuf;
1695     pReq->m_pIovecCur           = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
1696     pReq->m_pRespHeaderBufPos   = pReq->m_pRespHeaderBuf;
1697 
1698     memset( &pReq->m_pHeaderIndex, 0,
1699             (char *)(pReq->m_respHeaderLen) - (char *)&pReq->m_pHeaderIndex );
1700 }
1701 
1702 
LSAPI_Release_r(LSAPI_Request * pReq)1703 int LSAPI_Release_r( LSAPI_Request * pReq )
1704 {
1705     if ( pReq->m_pReqBuf )
1706         free( pReq->m_pReqBuf );
1707     if ( pReq->m_pSpecialEnvList )
1708         free( pReq->m_pSpecialEnvList );
1709     if ( pReq->m_pEnvList )
1710         free( pReq->m_pEnvList );
1711     if ( pReq->m_pRespHeaderBuf )
1712         free( pReq->m_pRespHeaderBuf );
1713     return 0;
1714 }
1715 
1716 
LSAPI_GetHeader_r(LSAPI_Request * pReq,int headerIndex)1717 char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex )
1718 {
1719     int off;
1720     if ( !pReq || ((unsigned int)headerIndex > H_TRANSFER_ENCODING) )
1721         return NULL;
1722     off = pReq->m_pHeaderIndex->m_headerOff[ headerIndex ];
1723     if ( !off )
1724         return NULL;
1725     if ( *(pReq->m_pHttpHeader + off
1726         + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) )
1727     {
1728         *( pReq->m_pHttpHeader + off
1729             + pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0;
1730     }
1731     return pReq->m_pHttpHeader + off;
1732 }
1733 
1734 
readBodyToReqBuf(LSAPI_Request * pReq)1735 static int readBodyToReqBuf( LSAPI_Request * pReq )
1736 {
1737     off_t bodyLeft;
1738     ssize_t len = pReq->m_bufRead - pReq->m_bufProcessed;
1739     if ( len > 0 )
1740         return len;
1741     pReq->m_bufRead = pReq->m_bufProcessed = pReq->m_pHeader->m_pktHeader.m_packetLen.m_iLen;
1742 
1743     bodyLeft = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
1744     len = pReq->m_reqBufSize - pReq->m_bufRead;
1745     if ( len < 0 )
1746         return -1;
1747     if ( len > bodyLeft )
1748         len = bodyLeft;
1749 
1750     len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, len );
1751     if ( len > 0 )
1752         pReq->m_bufRead += len;
1753     return len;
1754 }
1755 
1756 
LSAPI_ReqBodyGetChar_r(LSAPI_Request * pReq)1757 int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq )
1758 {
1759     if (!pReq || (pReq->m_fd ==-1) )
1760         return EOF;
1761     if ( pReq->m_bufProcessed >= pReq->m_bufRead )
1762     {
1763         if ( readBodyToReqBuf( pReq ) <= 0 )
1764             return EOF;
1765     }
1766     ++pReq->m_reqBodyRead;
1767     return (unsigned char)*(pReq->m_pReqBuf + pReq->m_bufProcessed++);
1768 }
1769 
1770 
LSAPI_ReqBodyGetLine_r(LSAPI_Request * pReq,char * pBuf,size_t bufLen,int * getLF)1771 int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF )
1772 {
1773     ssize_t len;
1774     ssize_t left;
1775     char * pBufEnd = pBuf + bufLen - 1;
1776     char * pBufCur = pBuf;
1777     char * pCur;
1778     char * p;
1779     if (!pReq || pReq->m_fd == -1 || !pBuf || !getLF)
1780         return -1;
1781     *getLF = 0;
1782     while( (left = pBufEnd - pBufCur ) > 0 )
1783     {
1784 
1785         len = pReq->m_bufRead - pReq->m_bufProcessed;
1786         if ( len <= 0 )
1787         {
1788             if ( (len = readBodyToReqBuf( pReq )) <= 0 )
1789             {
1790                 *getLF = 1;
1791                 break;
1792             }
1793         }
1794         if ( len > left )
1795             len = left;
1796         pCur = pReq->m_pReqBuf + pReq->m_bufProcessed;
1797         p = memchr( pCur, '\n', len );
1798         if ( p )
1799             len = p - pCur + 1;
1800         memmove( pBufCur, pCur, len );
1801         pBufCur += len;
1802         pReq->m_bufProcessed += len;
1803 
1804         pReq->m_reqBodyRead += len;
1805 
1806         if ( p )
1807         {
1808             *getLF = 1;
1809             break;
1810         }
1811     }
1812     *pBufCur = 0;
1813 
1814     return pBufCur - pBuf;
1815 }
1816 
1817 
LSAPI_ReadReqBody_r(LSAPI_Request * pReq,char * pBuf,size_t bufLen)1818 ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen )
1819 {
1820     ssize_t len;
1821     off_t total;
1822     /* char *pOldBuf = pBuf; */
1823     if (!pReq || pReq->m_fd == -1 || !pBuf || (ssize_t)bufLen < 0)
1824         return -1;
1825 
1826     total = pReq->m_reqBodyLen - pReq->m_reqBodyRead;
1827 
1828     if ( total <= 0 )
1829         return 0;
1830     if ( total < (ssize_t)bufLen )
1831         bufLen = total;
1832 
1833     total = 0;
1834     len = pReq->m_bufRead - pReq->m_bufProcessed;
1835     if ( len > 0 )
1836     {
1837         if ( len > (ssize_t)bufLen )
1838             len = bufLen;
1839         memmove( pBuf, pReq->m_pReqBuf + pReq->m_bufProcessed, len );
1840         pReq->m_bufProcessed += len;
1841         total += len;
1842         pBuf += len;
1843         bufLen -= len;
1844     }
1845     while( bufLen > 0 )
1846     {
1847         len = lsapi_read( pReq->m_fd, pBuf, bufLen );
1848         if ( len > 0 )
1849         {
1850             total += len;
1851             pBuf += len;
1852             bufLen -= len;
1853         }
1854         else if ( len <= 0 )
1855         {
1856             if ( !total)
1857                 return -1;
1858             break;
1859         }
1860     }
1861     pReq->m_reqBodyRead += total;
1862     return total;
1863 
1864 }
1865 
1866 
LSAPI_Write_r(LSAPI_Request * pReq,const char * pBuf,size_t len)1867 ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
1868 {
1869     struct lsapi_packet_header * pHeader;
1870     const char * pEnd;
1871     const char * p;
1872     ssize_t bufLen;
1873     ssize_t toWrite;
1874     ssize_t packetLen;
1875     int skip = 0;
1876 
1877     if (!pReq || !pBuf)
1878         return -1;
1879     if (pReq->m_reqState & LSAPI_ST_BACKGROUND)
1880         return len;
1881     if (pReq->m_fd == -1)
1882         return -1;
1883     if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1884     {
1885         LSAPI_FinalizeRespHeaders_r( pReq );
1886 /*
1887         if ( *pBuf == '\r' )
1888         {
1889             ++skip;
1890         }
1891         if ( *pBuf == '\n' )
1892         {
1893             ++skip;
1894         }
1895 */
1896     }
1897     pReq->m_reqState |= LSAPI_ST_RESP_BODY;
1898 
1899     if ( ((ssize_t)len - skip) < pReq->m_pRespBufEnd - pReq->m_pRespBufPos )
1900     {
1901         memmove( pReq->m_pRespBufPos, pBuf + skip, len - skip );
1902         pReq->m_pRespBufPos += len - skip;
1903         return len;
1904     }
1905 
1906 
1907     pHeader = pReq->m_respPktHeader;
1908     p       = pBuf + skip;
1909     pEnd    = pBuf + len;
1910     bufLen  = pReq->m_pRespBufPos - pReq->m_pRespBuf;
1911 
1912     while( ( toWrite = pEnd - p ) > 0 )
1913     {
1914         packetLen = toWrite + bufLen;
1915         if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen)
1916         {
1917             packetLen = LSAPI_MAX_DATA_PACKET_LEN;
1918             toWrite = packetLen - bufLen;
1919         }
1920 
1921         lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
1922                             packetLen + LSAPI_PACKET_HEADER_LEN );
1923         pReq->m_totalLen += packetLen + LSAPI_PACKET_HEADER_LEN;
1924 
1925         pReq->m_pIovecCur->iov_base = (void *)pHeader;
1926         pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
1927         ++pReq->m_pIovecCur;
1928         ++pHeader;
1929         if ( bufLen > 0 )
1930         {
1931             pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
1932             pReq->m_pIovecCur->iov_len  = bufLen;
1933             pReq->m_pRespBufPos = pReq->m_pRespBuf;
1934             ++pReq->m_pIovecCur;
1935             bufLen = 0;
1936         }
1937 
1938         pReq->m_pIovecCur->iov_base = (void *)p;
1939         pReq->m_pIovecCur->iov_len  = toWrite;
1940         ++pReq->m_pIovecCur;
1941         p += toWrite;
1942 
1943         if ( pHeader >= pReq->m_respPktHeaderEnd - 1)
1944         {
1945             if ( LSAPI_Flush_r( pReq ) == -1 )
1946                 return -1;
1947             pHeader = pReq->m_respPktHeader;
1948         }
1949     }
1950     if ( pHeader != pReq->m_respPktHeader )
1951         if ( LSAPI_Flush_r( pReq ) == -1 )
1952             return -1;
1953     return p - pBuf;
1954 }
1955 
1956 
1957 #if defined(__FreeBSD__ ) || defined(__DragonFly__)
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)1958 ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1959 {
1960     ssize_t ret;
1961     off_t written;
1962     ret = sendfile( fdIn, fdOut, *off, size, NULL, &written, 0 );
1963     if ( written > 0 )
1964     {
1965         ret = written;
1966         *off += ret;
1967     }
1968     return ret;
1969 }
1970 #endif
1971 
1972 #if defined(__OpenBSD__) || defined(__NetBSD__)
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)1973 ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
1974 {
1975     ssize_t ret;
1976     off_t written = 0;
1977     const size_t bufsiz = 16384;
1978     unsigned char in[bufsiz] = {0};
1979 
1980     if (lseek(fdIn, *off, SEEK_SET) == -1) {
1981         return -1;
1982     }
1983 
1984     while (size > 0) {
1985 	    size_t tor = size > sizeof(in) ? sizeof(in) : size;
1986 	    ssize_t c = read(fdIn, in, tor);
1987 	    if (c <= 0) {
1988 		    goto end;
1989 	    }
1990 
1991 	    ssize_t w = write(fdOut, in, c);
1992 	    if (w != c) {
1993 		    goto end;
1994 	    }
1995 
1996 	    written += w;
1997 	    size -= c;
1998     }
1999 
2000 end:
2001     *off += written;
2002     return 0;
2003 }
2004 #endif
2005 
2006 
2007 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)2008 ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size )
2009 {
2010     ssize_t ret;
2011     off_t len = size;
2012     ret = sendfile( fdIn, fdOut, *off, &len, NULL, 0 );
2013     if (( ret == 0 )&&( len > 0 ))
2014     {
2015         ret = len;
2016         *off += len;
2017     }
2018     return ret;
2019 }
2020 #endif
2021 
2022 
2023 #if defined(sun) || defined(__sun)
2024 #include <sys/sendfile.h>
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)2025 ssize_t gsendfile( int fdOut, int fdIn, off_t *off, size_t size )
2026 {
2027     int n = 0 ;
2028     sendfilevec_t vec[1];
2029 
2030     vec[n].sfv_fd   = fdIn;
2031     vec[n].sfv_flag = 0;
2032     vec[n].sfv_off  = *off;
2033     vec[n].sfv_len  = size;
2034     ++n;
2035 
2036     size_t written;
2037     ssize_t ret = sendfilev( fdOut, vec, n, &written );
2038     if (( !ret )||( errno == EAGAIN ))
2039         ret = written;
2040     if ( ret > 0 )
2041         *off += ret;
2042     return ret;
2043 }
2044 #endif
2045 
2046 
2047 #if defined(linux) || defined(__linux) || defined(__linux__) || \
2048     defined(__gnu_linux__)
2049 #include <sys/sendfile.h>
2050 #define gsendfile sendfile
2051 #endif
2052 
2053 
2054 #if defined(HPUX)
gsendfile(int fdOut,int fdIn,off_t * off,size_t size)2055 ssize_t gsendfile( int fdOut, int fdIn, off_t * off, size_t size )
2056 {
2057     return sendfile( fdOut, fdIn, off, size, NULL, 0 );
2058 }
2059 #endif
2060 
2061 
LSAPI_sendfile_r(LSAPI_Request * pReq,int fdIn,off_t * off,size_t size)2062 ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size )
2063 {
2064     struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
2065     if ( !pReq || (pReq->m_fd == -1) || fdIn == -1 )
2066         return -1;
2067     if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
2068     {
2069         LSAPI_FinalizeRespHeaders_r( pReq );
2070     }
2071     pReq->m_reqState |= LSAPI_ST_RESP_BODY;
2072 
2073     LSAPI_Flush_r(pReq);
2074 
2075     lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
2076                             size + LSAPI_PACKET_HEADER_LEN );
2077 
2078 
2079     if (write(pReq->m_fd,  (const char *) pHeader, LSAPI_PACKET_HEADER_LEN ) != LSAPI_PACKET_HEADER_LEN)
2080         return -1;
2081 
2082     return gsendfile( pReq->m_fd, fdIn, off, size );
2083 }
2084 
2085 
Flush_RespBuf_r(LSAPI_Request * pReq)2086 void Flush_RespBuf_r( LSAPI_Request * pReq )
2087 {
2088     struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
2089     int bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf;
2090     pReq->m_reqState |= LSAPI_ST_RESP_BODY;
2091     lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
2092                         bufLen + LSAPI_PACKET_HEADER_LEN );
2093     pReq->m_totalLen += bufLen + LSAPI_PACKET_HEADER_LEN;
2094 
2095     pReq->m_pIovecCur->iov_base = (void *)pHeader;
2096     pReq->m_pIovecCur->iov_len  = LSAPI_PACKET_HEADER_LEN;
2097     ++pReq->m_pIovecCur;
2098     ++pHeader;
2099     if ( bufLen > 0 )
2100     {
2101         pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
2102         pReq->m_pIovecCur->iov_len  = bufLen;
2103         pReq->m_pRespBufPos = pReq->m_pRespBuf;
2104         ++pReq->m_pIovecCur;
2105         bufLen = 0;
2106     }
2107 }
2108 
2109 
LSAPI_Flush_r(LSAPI_Request * pReq)2110 int LSAPI_Flush_r( LSAPI_Request * pReq )
2111 {
2112     int ret = 0;
2113     int n;
2114     if ( !pReq )
2115         return -1;
2116     n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
2117     if (( 0 == n )&&( pReq->m_pRespBufPos == pReq->m_pRespBuf ))
2118         return 0;
2119     if ( pReq->m_fd == -1 )
2120     {
2121         pReq->m_pRespBufPos = pReq->m_pRespBuf;
2122         pReq->m_totalLen = 0;
2123         pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
2124         return -1;
2125     }
2126     if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
2127     {
2128         LSAPI_FinalizeRespHeaders_r( pReq );
2129     }
2130     if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
2131     {
2132         Flush_RespBuf_r( pReq );
2133     }
2134 
2135     n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
2136     if ( n > 0 )
2137     {
2138 
2139         ret = lsapi_writev( pReq->m_fd, &pReq->m_pIovecToWrite,
2140                   n, pReq->m_totalLen );
2141         if ( ret < pReq->m_totalLen )
2142         {
2143             lsapi_close_connection(pReq);
2144             ret = -1;
2145         }
2146         pReq->m_totalLen = 0;
2147         pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
2148     }
2149     return ret;
2150 }
2151 
2152 
LSAPI_Write_Stderr_r(LSAPI_Request * pReq,const char * pBuf,size_t len)2153 ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
2154 {
2155     struct lsapi_packet_header header;
2156     const char * pEnd;
2157     const char * p;
2158     ssize_t packetLen;
2159     ssize_t totalLen;
2160     int ret;
2161     struct iovec iov[2];
2162     struct iovec *pIov;
2163 
2164     if ( !pReq )
2165         return -1;
2166     if (s_stderr_log_path || pReq->m_fd == -1 || pReq->m_fd == pReq->m_fdListen)
2167         return write( 2, pBuf, len );
2168     if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
2169     {
2170         LSAPI_Flush_r( pReq );
2171     }
2172 
2173     p       = pBuf;
2174     pEnd    = pBuf + len;
2175 
2176     while( ( packetLen = pEnd - p ) > 0 )
2177     {
2178         if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen)
2179         {
2180             packetLen = LSAPI_MAX_DATA_PACKET_LEN;
2181         }
2182 
2183         lsapi_buildPacketHeader( &header, LSAPI_STDERR_STREAM,
2184                             packetLen + LSAPI_PACKET_HEADER_LEN );
2185         totalLen = packetLen + LSAPI_PACKET_HEADER_LEN;
2186 
2187         iov[0].iov_base = (void *)&header;
2188         iov[0].iov_len  = LSAPI_PACKET_HEADER_LEN;
2189 
2190         iov[1].iov_base = (void *)p;
2191         iov[1].iov_len  = packetLen;
2192         p += packetLen;
2193         pIov = iov;
2194         ret = lsapi_writev( pReq->m_fd, &pIov,
2195                   2, totalLen );
2196         if ( ret < totalLen )
2197         {
2198             lsapi_close_connection(pReq);
2199             ret = -1;
2200         }
2201     }
2202     return p - pBuf;
2203 }
2204 
2205 
GetHeaderVar(LSAPI_Request * pReq,const char * name)2206 static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
2207 {
2208     int i;
2209     char * pValue;
2210     for( i = 0; i < H_TRANSFER_ENCODING; ++i )
2211     {
2212         if ( pReq->m_pHeaderIndex->m_headerOff[i] )
2213         {
2214             if ( strcmp( name, CGI_HEADERS[i] ) == 0 )
2215             {
2216                 pValue = pReq->m_pHttpHeader
2217                          + pReq->m_pHeaderIndex->m_headerOff[i];
2218                 if ( *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) != '\0')
2219                 {
2220                     *(pValue + pReq->m_pHeaderIndex->m_headerLen[i]) = '\0';
2221                 }
2222                 return pValue;
2223             }
2224         }
2225     }
2226     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
2227     {
2228         const char *p;
2229         char *pKey;
2230         char *pKeyEnd;
2231         int  keyLen;
2232         struct lsapi_header_offset * pCur, *pEnd;
2233         pCur = pReq->m_pUnknownHeader;
2234         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
2235         while( pCur < pEnd )
2236         {
2237             pKey = pReq->m_pHttpHeader + pCur->nameOff;
2238             keyLen = pCur->nameLen;
2239             pKeyEnd = pKey + keyLen;
2240             p = &name[5];
2241 
2242             while(( pKey < pKeyEnd )&&( *p ))
2243             {
2244                 char ch = toupper( *pKey );
2245                 if ((ch != *p )||(( *p == '_' )&&( ch != '-')))
2246                     break;
2247                 ++p; ++pKey;
2248             }
2249             if (( pKey == pKeyEnd )&& (!*p ))
2250             {
2251                 pValue = pReq->m_pHttpHeader + pCur->valueOff;
2252 
2253                 if ( *(pValue + pCur->valueLen) != '\0')
2254                 {
2255                     *(pValue + pCur->valueLen) = '\0';
2256                 }
2257                 return pValue;
2258             }
2259             ++pCur;
2260         }
2261     }
2262     return NULL;
2263 }
2264 
2265 
LSAPI_GetEnv_r(LSAPI_Request * pReq,const char * name)2266 char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name )
2267 {
2268     struct LSAPI_key_value_pair * pBegin = pReq->m_pEnvList;
2269     struct LSAPI_key_value_pair * pEnd = pBegin + pReq->m_pHeader->m_cntEnv;
2270     if ( !pReq || !name )
2271         return NULL;
2272     if ( strncmp( name, "HTTP_", 5 ) == 0 )
2273     {
2274         return GetHeaderVar( pReq, name );
2275     }
2276     while( pBegin < pEnd )
2277     {
2278         if ( strcmp( name, pBegin->pKey ) == 0 )
2279             return pBegin->pValue;
2280         ++pBegin;
2281     }
2282     return NULL;
2283 }
2284 
2285 
2286 struct _headerInfo
2287 {
2288     const char * _name;
2289     int          _nameLen;
2290     const char * _value;
2291     int          _valueLen;
2292 };
2293 
2294 
compareValueLocation(const void * v1,const void * v2)2295 int compareValueLocation(const void * v1, const void *v2 )
2296 {
2297     return ((const struct _headerInfo *)v1)->_value -
2298            ((const struct _headerInfo *)v2)->_value;
2299 }
2300 
2301 
LSAPI_ForeachOrgHeader_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)2302 int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq,
2303             LSAPI_CB_EnvHandler fn, void * arg )
2304 {
2305     int i;
2306     int len = 0;
2307     char * pValue;
2308     int ret;
2309     int count = 0;
2310     struct _headerInfo headers[512];
2311 
2312     if ( !pReq || !fn )
2313         return -1;
2314 
2315     if ( !pReq->m_pHeaderIndex )
2316         return 0;
2317 
2318     for( i = 0; i < H_TRANSFER_ENCODING; ++i )
2319     {
2320         if ( pReq->m_pHeaderIndex->m_headerOff[i] )
2321         {
2322             len = pReq->m_pHeaderIndex->m_headerLen[i];
2323             pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
2324             *(pValue + len ) = 0;
2325             headers[count]._name = HTTP_HEADERS[i];
2326             headers[count]._nameLen = HTTP_HEADER_LEN[i];
2327             headers[count]._value = pValue;
2328             headers[count]._valueLen = len;
2329             ++count;
2330 
2331             //ret = (*fn)( HTTP_HEADERS[i], HTTP_HEADER_LEN[i],
2332             //            pValue, len, arg );
2333             //if ( ret <= 0 )
2334             //    return ret;
2335         }
2336     }
2337     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
2338     {
2339         char *pKey;
2340         int  keyLen;
2341         struct lsapi_header_offset * pCur, *pEnd;
2342         pCur = pReq->m_pUnknownHeader;
2343         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
2344         while( pCur < pEnd )
2345         {
2346             pKey = pReq->m_pHttpHeader + pCur->nameOff;
2347             keyLen = pCur->nameLen;
2348             *(pKey + keyLen ) = 0;
2349 
2350             pValue = pReq->m_pHttpHeader + pCur->valueOff;
2351             *(pValue + pCur->valueLen ) = 0;
2352             headers[count]._name = pKey;
2353             headers[count]._nameLen = keyLen;
2354             headers[count]._value = pValue;
2355             headers[count]._valueLen = pCur->valueLen;
2356             ++count;
2357             if ( count == 512 )
2358                 break;
2359             //ret = (*fn)( pKey, keyLen,
2360             //            pValue, pCur->valueLen, arg );
2361             //if ( ret <= 0 )
2362             //    return ret;
2363             ++pCur;
2364         }
2365     }
2366     qsort( headers, count, sizeof( struct _headerInfo ), compareValueLocation );
2367     for( i = 0; i < count; ++i )
2368     {
2369         ret = (*fn)( headers[i]._name, headers[i]._nameLen,
2370                     headers[i]._value, headers[i]._valueLen, arg );
2371         if ( ret <= 0 )
2372             return ret;
2373     }
2374     return count;
2375 }
2376 
2377 
LSAPI_ForeachHeader_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)2378 int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
2379             LSAPI_CB_EnvHandler fn, void * arg )
2380 {
2381     int i;
2382     int len = 0;
2383     char * pValue;
2384     int ret;
2385     int count = 0;
2386     if ( !pReq || !fn )
2387         return -1;
2388     for( i = 0; i < H_TRANSFER_ENCODING; ++i )
2389     {
2390         if ( pReq->m_pHeaderIndex->m_headerOff[i] )
2391         {
2392             len = pReq->m_pHeaderIndex->m_headerLen[i];
2393             pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
2394             *(pValue + len ) = 0;
2395             ret = (*fn)( CGI_HEADERS[i], CGI_HEADER_LEN[i],
2396                         pValue, len, arg );
2397             ++count;
2398             if ( ret <= 0 )
2399                 return ret;
2400         }
2401     }
2402     if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
2403     {
2404         char achHeaderName[256];
2405         char *p;
2406         char *pKey;
2407         char *pKeyEnd ;
2408         int  keyLen;
2409         struct lsapi_header_offset * pCur, *pEnd;
2410         pCur = pReq->m_pUnknownHeader;
2411         pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
2412         while( pCur < pEnd )
2413         {
2414             pKey = pReq->m_pHttpHeader + pCur->nameOff;
2415             keyLen = pCur->nameLen;
2416             if ( keyLen > 250 )
2417                 keyLen = 250;
2418             pKeyEnd = pKey + keyLen;
2419             memcpy( achHeaderName, "HTTP_", 5 );
2420             p = &achHeaderName[5];
2421 
2422             while( pKey < pKeyEnd )
2423             {
2424                 char ch = *pKey++;
2425                 if ( ch == '-' )
2426                     *p++ = '_';
2427                 else
2428                     *p++ = toupper( ch );
2429             }
2430             *p = 0;
2431             keyLen += 5;
2432 
2433             pValue = pReq->m_pHttpHeader + pCur->valueOff;
2434             *(pValue + pCur->valueLen ) = 0;
2435             ret = (*fn)( achHeaderName, keyLen,
2436                         pValue, pCur->valueLen, arg );
2437             if ( ret <= 0 )
2438                 return ret;
2439             ++pCur;
2440         }
2441     }
2442     return count + pReq->m_pHeader->m_cntUnknownHeaders;
2443 }
2444 
2445 
EnvForeach(struct LSAPI_key_value_pair * pEnv,int n,LSAPI_CB_EnvHandler fn,void * arg)2446 static int EnvForeach( struct LSAPI_key_value_pair * pEnv,
2447             int n, LSAPI_CB_EnvHandler fn, void * arg )
2448 {
2449     struct LSAPI_key_value_pair * pEnd = pEnv + n;
2450     int ret;
2451     if ( !pEnv || !fn )
2452         return -1;
2453     while( pEnv < pEnd )
2454     {
2455         ret = (*fn)( pEnv->pKey, pEnv->keyLen,
2456                     pEnv->pValue, pEnv->valLen, arg );
2457         if ( ret <= 0 )
2458             return ret;
2459         ++pEnv;
2460     }
2461     return n;
2462 }
2463 
2464 
LSAPI_ForeachEnv_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)2465 int LSAPI_ForeachEnv_r( LSAPI_Request * pReq,
2466             LSAPI_CB_EnvHandler fn, void * arg )
2467 {
2468     if ( !pReq || !fn )
2469         return -1;
2470     if ( pReq->m_pHeader->m_cntEnv > 0 )
2471     {
2472         return EnvForeach( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
2473                     fn, arg );
2474     }
2475     return 0;
2476 }
2477 
2478 
LSAPI_ForeachSpecialEnv_r(LSAPI_Request * pReq,LSAPI_CB_EnvHandler fn,void * arg)2479 int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq,
2480             LSAPI_CB_EnvHandler fn, void * arg )
2481 {
2482     if ( !pReq || !fn )
2483         return -1;
2484     if ( pReq->m_pHeader->m_cntSpecialEnv > 0 )
2485     {
2486         return EnvForeach( pReq->m_pSpecialEnvList,
2487                 pReq->m_pHeader->m_cntSpecialEnv,
2488                     fn, arg );
2489     }
2490     return 0;
2491 
2492 }
2493 
2494 
LSAPI_FinalizeRespHeaders_r(LSAPI_Request * pReq)2495 int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq )
2496 {
2497     if ( !pReq || !pReq->m_pIovec )
2498         return -1;
2499     if ( !( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) )
2500         return 0;
2501     pReq->m_reqState &= ~LSAPI_ST_RESP_HEADER;
2502     if ( pReq->m_pRespHeaderBufPos > pReq->m_pRespHeaderBuf )
2503     {
2504         pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespHeaderBuf;
2505         pReq->m_pIovecCur->iov_len  = pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf;
2506         pReq->m_totalLen += pReq->m_pIovecCur->iov_len;
2507         ++pReq->m_pIovecCur;
2508     }
2509 
2510     pReq->m_pIovec->iov_len  = sizeof( struct lsapi_resp_header)
2511             + pReq->m_respHeader.m_respInfo.m_cntHeaders * sizeof( short );
2512     pReq->m_totalLen += pReq->m_pIovec->iov_len;
2513 
2514     lsapi_buildPacketHeader( &pReq->m_respHeader.m_pktHeader,
2515                     LSAPI_RESP_HEADER, pReq->m_totalLen  );
2516     pReq->m_pIovec->iov_base = (void *)&pReq->m_respHeader;
2517     pReq->m_pIovecToWrite = pReq->m_pIovec;
2518     return 0;
2519 }
2520 
2521 
LSAPI_AppendRespHeader2_r(LSAPI_Request * pReq,const char * pHeaderName,const char * pHeaderValue)2522 int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName,
2523                               const char * pHeaderValue )
2524 {
2525     int nameLen, valLen, len;
2526     if ( !pReq || !pHeaderName || !pHeaderValue )
2527         return -1;
2528     if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
2529         return -1;
2530     if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS )
2531         return -1;
2532     nameLen = strlen( pHeaderName );
2533     valLen = strlen( pHeaderValue );
2534     if ( nameLen == 0 )
2535         return -1;
2536     while( nameLen > 0 )
2537     {
2538         char ch = *(pHeaderName + nameLen - 1 );
2539         if (( ch == '\n' )||( ch == '\r' ))
2540             --nameLen;
2541         else
2542             break;
2543     }
2544     if ( nameLen <= 0 )
2545         return 0;
2546     while( valLen > 0 )
2547     {
2548         char ch = *(pHeaderValue + valLen - 1 );
2549         if (( ch == '\n' )||( ch == '\r' ))
2550             --valLen;
2551         else
2552             break;
2553     }
2554     len = nameLen + valLen + 1;
2555     if ( len > LSAPI_RESP_HTTP_HEADER_MAX )
2556         return -1;
2557 
2558     if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
2559     {
2560         int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
2561         newlen -= newlen % 4096;
2562         if ( allocateRespHeaderBuf( pReq, newlen ) == -1 )
2563             return -1;
2564     }
2565     memmove( pReq->m_pRespHeaderBufPos, pHeaderName, nameLen );
2566     pReq->m_pRespHeaderBufPos += nameLen;
2567     *pReq->m_pRespHeaderBufPos++ = ':';
2568     memmove( pReq->m_pRespHeaderBufPos, pHeaderValue, valLen );
2569     pReq->m_pRespHeaderBufPos += valLen;
2570     *pReq->m_pRespHeaderBufPos++ = 0;
2571     ++len;  /* add one byte padding for \0 */
2572     pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
2573     ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
2574     return 0;
2575 }
2576 
2577 
LSAPI_AppendRespHeader_r(LSAPI_Request * pReq,const char * pBuf,int len)2578 int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len )
2579 {
2580     if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX )
2581         return -1;
2582     if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
2583         return -1;
2584     if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS )
2585         return -1;
2586     while( len > 0 )
2587     {
2588         char ch = *(pBuf + len - 1 );
2589         if (( ch == '\n' )||( ch == '\r' ))
2590             --len;
2591         else
2592             break;
2593     }
2594     if ( len <= 0 )
2595         return 0;
2596     if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
2597     {
2598         int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
2599         newlen -= newlen % 4096;
2600         if ( allocateRespHeaderBuf( pReq, newlen ) == -1 )
2601             return -1;
2602     }
2603     memmove( pReq->m_pRespHeaderBufPos, pBuf, len );
2604     pReq->m_pRespHeaderBufPos += len;
2605     *pReq->m_pRespHeaderBufPos++ = 0;
2606     ++len;  /* add one byte padding for \0 */
2607     pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
2608     ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
2609     return 0;
2610 }
2611 
2612 
LSAPI_CreateListenSock2(const struct sockaddr * pServerAddr,int backlog)2613 int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog )
2614 {
2615     int ret;
2616     int fd;
2617     int flag = 1;
2618     int addr_len;
2619 
2620     switch( pServerAddr->sa_family )
2621     {
2622     case AF_INET:
2623         addr_len = 16;
2624         break;
2625     case AF_INET6:
2626         addr_len = sizeof( struct sockaddr_in6 );
2627         break;
2628     case AF_UNIX:
2629         addr_len = sizeof( struct sockaddr_un );
2630         unlink( ((struct sockaddr_un *)pServerAddr)->sun_path );
2631         break;
2632     default:
2633         return -1;
2634     }
2635 
2636     fd = socket( pServerAddr->sa_family, SOCK_STREAM, 0 );
2637     if ( fd == -1 )
2638         return -1;
2639 
2640     fcntl( fd, F_SETFD, FD_CLOEXEC );
2641 
2642     if(setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
2643                 (char *)( &flag ), sizeof(flag)) == 0)
2644     {
2645         ret = bind( fd, pServerAddr, addr_len );
2646         if ( !ret )
2647         {
2648             ret = listen( fd, backlog );
2649             if ( !ret )
2650                 return fd;
2651         }
2652     }
2653 
2654     ret = errno;
2655     close(fd);
2656     errno = ret;
2657     return -1;
2658 }
2659 
2660 
LSAPI_ParseSockAddr(const char * pBind,struct sockaddr * pAddr)2661 int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr )
2662 {
2663     char achAddr[256];
2664     char * p = achAddr;
2665     char * pEnd;
2666     struct addrinfo *res, hints;
2667     int  doAddrInfo = 0;
2668     int port;
2669 
2670     if ( !pBind )
2671         return -1;
2672 
2673     while( isspace( *pBind ) )
2674         ++pBind;
2675 
2676     strncpy(achAddr, pBind, 255);
2677     achAddr[255] = 0;
2678 
2679     switch( *p )
2680     {
2681     case '/':
2682         pAddr->sa_family = AF_UNIX;
2683         strncpy( ((struct sockaddr_un *)pAddr)->sun_path, p,
2684                 sizeof(((struct sockaddr_un *)pAddr)->sun_path) );
2685         return 0;
2686 
2687     case '[':
2688         pAddr->sa_family = AF_INET6;
2689         ++p;
2690         pEnd = strchr( p, ']' );
2691         if ( !pEnd )
2692             return -1;
2693         *pEnd++ = 0;
2694 
2695         if ( *p == '*' )
2696         {
2697             strcpy( achAddr, "::" );
2698             p = achAddr;
2699         }
2700         doAddrInfo = 1;
2701         break;
2702 
2703     default:
2704         pAddr->sa_family = AF_INET;
2705         pEnd = strchr( p, ':' );
2706         if ( !pEnd )
2707             return -1;
2708         *pEnd++ = 0;
2709 
2710         doAddrInfo = 0;
2711         if ( *p == '*' )
2712         {
2713             ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl(INADDR_ANY);
2714         }
2715         else if (!strcasecmp( p, "localhost" ) )
2716             ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = htonl( INADDR_LOOPBACK );
2717         else
2718         {
2719 #ifdef HAVE_INET_PTON
2720             if (!inet_pton(AF_INET, p, &((struct sockaddr_in *)pAddr)->sin_addr))
2721 #else
2722             ((struct sockaddr_in *)pAddr)->sin_addr.s_addr = inet_addr( p );
2723             if ( ((struct sockaddr_in *)pAddr)->sin_addr.s_addr == INADDR_BROADCAST)
2724 #endif
2725             {
2726                 doAddrInfo = 1;
2727             }
2728         }
2729         break;
2730     }
2731     if ( *pEnd == ':' )
2732         ++pEnd;
2733 
2734     port = atoi( pEnd );
2735     if (( port <= 0 )||( port > 65535 ))
2736         return -1;
2737     if ( doAddrInfo )
2738     {
2739 
2740         memset(&hints, 0, sizeof(hints));
2741 
2742         hints.ai_family   = pAddr->sa_family;
2743         hints.ai_socktype = SOCK_STREAM;
2744         hints.ai_protocol = IPPROTO_TCP;
2745 
2746         if ( getaddrinfo(p, NULL, &hints, &res) )
2747         {
2748             return -1;
2749         }
2750 
2751         memcpy(pAddr, res->ai_addr, res->ai_addrlen);
2752         freeaddrinfo(res);
2753     }
2754 
2755     if ( pAddr->sa_family == AF_INET )
2756         ((struct sockaddr_in *)pAddr)->sin_port = htons( port );
2757     else
2758         ((struct sockaddr_in6 *)pAddr)->sin6_port = htons( port );
2759     return 0;
2760 
2761 }
2762 
2763 
LSAPI_CreateListenSock(const char * pBind,int backlog)2764 int LSAPI_CreateListenSock( const char * pBind, int backlog )
2765 {
2766     char serverAddr[128];
2767     int ret;
2768     int fd = -1;
2769     ret = LSAPI_ParseSockAddr( pBind, (struct sockaddr *)serverAddr );
2770     if ( !ret )
2771     {
2772         fd = LSAPI_CreateListenSock2( (struct sockaddr *)serverAddr, backlog );
2773     }
2774     return fd;
2775 }
2776 
2777 
2778 static fn_select_t g_fnSelect = select;
2779 typedef struct _lsapi_prefork_server
2780 {
2781     int m_fd;
2782     int m_iMaxChildren;
2783     int m_iExtraChildren;
2784     int m_iCurChildren;
2785     int m_iMaxIdleChildren;
2786     int m_iServerMaxIdle;
2787     int m_iChildrenMaxIdleTime;
2788     int m_iMaxReqProcessTime;
2789     int m_iAvoidFork;
2790 
2791     lsapi_child_status * m_pChildrenStatus;
2792     lsapi_child_status * m_pChildrenStatusCur;
2793     lsapi_child_status * m_pChildrenStatusEnd;
2794 
2795 }lsapi_prefork_server;
2796 static lsapi_prefork_server * g_prefork_server = NULL;
2797 
2798 
LSAPI_Init_Prefork_Server(int max_children,fn_select_t fp,int avoidFork)2799 int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
2800 {
2801     if ( g_prefork_server )
2802         return 0;
2803     if ( max_children <= 1 )
2804         return -1;
2805     if ( max_children >= 10000)
2806         max_children = 10000;
2807 
2808     if (s_max_busy_workers == 0)
2809         s_max_busy_workers = max_children / 2 + 1;
2810 
2811     g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) );
2812     if ( !g_prefork_server )
2813         return -1;
2814     memset( g_prefork_server, 0, sizeof( lsapi_prefork_server ) );
2815 
2816     if ( fp != NULL )
2817         g_fnSelect = fp;
2818 
2819     s_ppid = getppid();
2820     s_pid = getpid();
2821     setpgid( s_pid, s_pid );
2822 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
2823     s_total_pages = sysconf(_SC_PHYS_PAGES);
2824 #endif
2825     g_prefork_server->m_iAvoidFork = avoidFork;
2826     g_prefork_server->m_iMaxChildren = max_children;
2827 
2828     g_prefork_server->m_iExtraChildren = ( avoidFork ) ? 0 : (max_children / 3) ;
2829     g_prefork_server->m_iMaxIdleChildren = ( avoidFork ) ? (max_children + 1) : (max_children / 3);
2830     if ( g_prefork_server->m_iMaxIdleChildren == 0 )
2831         g_prefork_server->m_iMaxIdleChildren = 1;
2832     g_prefork_server->m_iChildrenMaxIdleTime = 300;
2833     g_prefork_server->m_iMaxReqProcessTime = 3600;
2834 
2835     setsid();
2836 
2837     return 0;
2838 }
2839 
2840 
LSAPI_Set_Server_fd(int fd)2841 void LSAPI_Set_Server_fd( int fd )
2842 {
2843     if( g_prefork_server )
2844         g_prefork_server->m_fd = fd;
2845 }
2846 
2847 
lsapi_accept(int fdListen)2848 static int lsapi_accept( int fdListen )
2849 {
2850     int         fd;
2851     int         nodelay = 1;
2852     socklen_t   len;
2853     char        achPeer[128];
2854 
2855     len = sizeof( achPeer );
2856     fd = accept( fdListen, (struct sockaddr *)&achPeer, &len );
2857     if ( fd != -1 )
2858     {
2859         if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
2860         {
2861             setsockopt( fd, IPPROTO_TCP, TCP_NODELAY,
2862                     (char *)&nodelay, sizeof(nodelay));
2863         }
2864 
2865         //OPTIMIZATION
2866         //if ( s_accept_notify )
2867         //    notify_req_received( fd );
2868     }
2869     return fd;
2870 
2871 }
2872 
2873 
2874 static unsigned int s_max_reqs = UINT_MAX;
2875 static int s_max_idle_secs = 300;
2876 static int s_stop;
2877 
lsapi_cleanup(int signal)2878 static void lsapi_cleanup(int signal)
2879 {
2880     s_stop = signal;
2881 }
2882 
2883 
find_child_status(int pid)2884 static lsapi_child_status * find_child_status( int pid )
2885 {
2886     lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
2887     lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd;
2888     while( pStatus < pEnd )
2889     {
2890         if ( pStatus->m_pid == pid )
2891         {
2892             if (pid == 0)
2893             {
2894                 memset(pStatus, 0, sizeof( *pStatus ) );
2895                 pStatus->m_pid = -1;
2896             }
2897             if ( pStatus + 1 > g_prefork_server->m_pChildrenStatusCur )
2898                 g_prefork_server->m_pChildrenStatusCur = pStatus + 1;
2899             return pStatus;
2900         }
2901         ++pStatus;
2902     }
2903     return NULL;
2904 }
2905 
2906 
LSAPI_reset_server_state(void)2907 void LSAPI_reset_server_state( void )
2908 {
2909     /*
2910        Reset child status
2911     */
2912     g_prefork_server->m_iCurChildren = 0;
2913     lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
2914     lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd;
2915     while( pStatus < pEnd )
2916     {
2917         pStatus->m_pid = 0;
2918         ++pStatus;
2919     }
2920     if (s_busy_workers)
2921         __sync_lock_release(s_busy_workers);
2922     if (s_accepting_workers)
2923         __sync_lock_release(s_accepting_workers);
2924 
2925 }
2926 
2927 
lsapi_sigchild(int signal)2928 static void lsapi_sigchild( int signal )
2929 {
2930     int status, pid;
2931     lsapi_child_status * child_status;
2932     if (g_prefork_server == NULL)
2933         return;
2934     while( 1 )
2935     {
2936         pid = waitpid( -1, &status, WNOHANG|WUNTRACED );
2937         if ( pid <= 0 )
2938         {
2939             break;
2940         }
2941         if ( WIFSIGNALED( status ))
2942         {
2943             int sig_num = WTERMSIG( status );
2944 
2945 #ifdef WCOREDUMP
2946             const char * dump = WCOREDUMP( status ) ? "yes" : "no";
2947 #else
2948             const char * dump = "unknown";
2949 #endif
2950             lsapi_log("Child process with pid: %d was killed by signal: "
2951                      "%d, core dumped: %s\n", pid, sig_num, dump );
2952         }
2953         if ( pid == s_pid_dump_debug_info )
2954         {
2955             pid = 0;
2956             continue;
2957         }
2958         if ( pid == s_ignore_pid )
2959         {
2960             pid = 0;
2961             s_ignore_pid = -1;
2962             continue;
2963         }
2964         child_status = find_child_status( pid );
2965         if ( child_status )
2966         {
2967             if (__sync_bool_compare_and_swap(&child_status->m_state,
2968                                              LSAPI_STATE_CONNECTED,
2969                                              LSAPI_STATE_IDLE))
2970             {
2971                 if (s_busy_workers)
2972                     __sync_fetch_and_sub(s_busy_workers, 1);
2973             }
2974             else if (__sync_bool_compare_and_swap(&child_status->m_state,
2975                                                   LSAPI_STATE_ACCEPTING,
2976                                                   LSAPI_STATE_IDLE))
2977             {
2978                 if (s_accepting_workers)
2979                     __sync_fetch_and_sub(s_accepting_workers, 1);
2980             }
2981             child_status->m_pid = 0;
2982             --g_prefork_server->m_iCurChildren;
2983         }
2984     }
2985     while(( g_prefork_server->m_pChildrenStatusCur > g_prefork_server->m_pChildrenStatus )
2986             &&( g_prefork_server->m_pChildrenStatusCur[-1].m_pid == 0 ))
2987         --g_prefork_server->m_pChildrenStatusCur;
2988 
2989 }
2990 
2991 
lsapi_init_children_status(void)2992 static int lsapi_init_children_status(void)
2993 {
2994     char * pBuf;
2995     int size = 4096;
2996     int max_children;
2997     if (g_prefork_server->m_pChildrenStatus)
2998         return 0;
2999     max_children = g_prefork_server->m_iMaxChildren
3000                         + g_prefork_server->m_iExtraChildren;
3001 
3002     size = max_children * sizeof( lsapi_child_status ) * 2 + 3 * sizeof(int);
3003     size = (size + 4095) / 4096 * 4096;
3004     pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE,
3005         MAP_ANON | MAP_SHARED, -1, 0 );
3006     if ( pBuf == MAP_FAILED )
3007     {
3008         perror( "Anonymous mmap() failed" );
3009         return -1;
3010     }
3011     memset( pBuf, 0, size );
3012     g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf;
3013     g_prefork_server->m_pChildrenStatusCur = (lsapi_child_status *)pBuf;
3014     g_prefork_server->m_pChildrenStatusEnd = (lsapi_child_status *)pBuf + max_children;
3015     s_busy_workers = (int *)g_prefork_server->m_pChildrenStatusEnd;
3016     s_accepting_workers = s_busy_workers + 1;
3017     s_global_counter = s_accepting_workers + 1;
3018     s_avail_pages = (size_t *)(s_global_counter + 1);
3019 
3020     setsid();
3021     return 0;
3022 }
3023 
3024 
dump_debug_info(lsapi_child_status * pStatus,long tmCur)3025 static void dump_debug_info( lsapi_child_status * pStatus, long tmCur )
3026 {
3027     char achCmd[1024];
3028     if ( s_pid_dump_debug_info )
3029     {
3030         if ( kill( s_pid_dump_debug_info, 0 ) == 0 )
3031             return;
3032     }
3033 
3034     lsapi_log("Possible runaway process, UID: %d, PPID: %d, PID: %d, "
3035              "reqCount: %d, process time: %ld, checkpoint time: %ld, start "
3036              "time: %ld\n", getuid(), getppid(), pStatus->m_pid,
3037              pStatus->m_iReqCounter, tmCur - pStatus->m_tmReqBegin,
3038              tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart );
3039 
3040     s_pid_dump_debug_info = fork();
3041     if (s_pid_dump_debug_info == 0)
3042     {
3043         snprintf( achCmd, 1024, "gdb --batch -ex \"attach %d\" -ex \"set height 0\" "
3044                 "-ex \"bt\" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2",
3045                 pStatus->m_pid, pStatus->m_pid );
3046         if ( system( achCmd ) == -1 )
3047             perror( "system()" );
3048         exit( 0 );
3049     }
3050 }
3051 
3052 
lsapi_check_child_status(long tmCur)3053 static void lsapi_check_child_status( long tmCur )
3054 {
3055     int idle = 0;
3056     int tobekilled;
3057     int dying = 0;
3058     int count = 0;
3059     lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus;
3060     lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusCur;
3061     while( pStatus < pEnd )
3062     {
3063         tobekilled = 0;
3064         if ( pStatus->m_pid != 0 && pStatus->m_pid != -1)
3065         {
3066             ++count;
3067             if ( !pStatus->m_inProcess )
3068             {
3069                 if (g_prefork_server->m_iCurChildren - dying
3070                         > g_prefork_server->m_iMaxChildren
3071                     || idle > g_prefork_server->m_iMaxIdleChildren)
3072                 {
3073                     ++pStatus->m_iKillSent;
3074                     //tobekilled = SIGUSR1;
3075                 }
3076                 else
3077                 {
3078                     if (s_max_idle_secs> 0
3079                         && tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5)
3080                     {
3081                         ++pStatus->m_iKillSent;
3082                         //tobekilled = SIGUSR1;
3083                     }
3084                 }
3085                 if (!pStatus->m_iKillSent)
3086                     ++idle;
3087             }
3088             else
3089             {
3090                 if (tmCur - pStatus->m_tmReqBegin >
3091                         g_prefork_server->m_iMaxReqProcessTime)
3092                 {
3093                     if ((pStatus->m_iKillSent % 5) == 0 && s_dump_debug_info)
3094                         dump_debug_info( pStatus, tmCur );
3095                     if ( pStatus->m_iKillSent > 5 )
3096                     {
3097                         tobekilled = SIGKILL;
3098                         lsapi_log("Force killing runaway process PID: %d"
3099                                  " with SIGKILL\n", pStatus->m_pid );
3100                     }
3101                     else
3102                     {
3103                         tobekilled = SIGTERM;
3104                         lsapi_log("Killing runaway process PID: %d with "
3105                                  "SIGTERM\n", pStatus->m_pid );
3106                     }
3107                 }
3108             }
3109             if ( tobekilled )
3110             {
3111                 if (( kill( pStatus->m_pid, tobekilled ) == -1 ) &&
3112                     ( errno == ESRCH ))
3113                 {
3114                     pStatus->m_pid = 0;
3115                     --count;
3116                 }
3117                 else
3118                 {
3119                     ++pStatus->m_iKillSent;
3120                     ++dying;
3121                 }
3122             }
3123         }
3124         ++pStatus;
3125     }
3126     if ( abs( g_prefork_server->m_iCurChildren - count ) > 1 )
3127     {
3128         lsapi_log("Children tracking is wrong: Cur Children: %d,"
3129                   " count: %d, idle: %d, dying: %d\n",
3130                   g_prefork_server->m_iCurChildren, count, idle, dying );
3131     }
3132 }
3133 
3134 
3135 //static int lsapi_all_children_must_die(void)
3136 //{
3137 //    int maxWait;
3138 //    int sec =0;
3139 //    g_prefork_server->m_iMaxReqProcessTime = 10;
3140 //    g_prefork_server->m_iMaxIdleChildren = -1;
3141 //    maxWait = 15;
3142 //
3143 //    while( g_prefork_server->m_iCurChildren && (sec < maxWait) )
3144 //    {
3145 //        lsapi_check_child_status(time(NULL));
3146 //        sleep( 1 );
3147 //        sec++;
3148 //    }
3149 //    if ( g_prefork_server->m_iCurChildren != 0 )
3150 //        kill( -getpgrp(), SIGKILL );
3151 //    return 0;
3152 //}
3153 
3154 
set_skip_write()3155 void set_skip_write()
3156 {   s_skip_write = 1;   }
3157 
3158 
is_enough_free_mem()3159 int is_enough_free_mem()
3160 {
3161 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3162     //minimum 1GB or 10% available free memory
3163     return (*s_avail_pages > s_min_avail_pages
3164             || (*s_avail_pages * 10) / s_total_pages > 0);
3165 #endif
3166     return 1;
3167 }
3168 
3169 
lsapi_prefork_server_accept(lsapi_prefork_server * pServer,LSAPI_Request * pReq)3170 static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
3171                                         LSAPI_Request * pReq )
3172 {
3173     struct sigaction act, old_term, old_quit, old_int,
3174                     old_usr1, old_child;
3175     lsapi_child_status * child_status;
3176     int             wait_secs = 0;
3177     int             ret = 0;
3178     int             pid;
3179     time_t          lastTime = 0;
3180     time_t          curTime = 0;
3181     fd_set          readfds;
3182     struct timeval  timeout;
3183 
3184     sigset_t mask;
3185     sigset_t orig_mask;
3186 
3187     lsapi_init_children_status();
3188 
3189     act.sa_flags = 0;
3190     act.sa_handler = lsapi_sigchild;
3191     sigemptyset(&(act.sa_mask));
3192     if( sigaction( SIGCHLD, &act, &old_child ) )
3193     {
3194         perror( "Can't set signal handler for SIGCHILD" );
3195         return -1;
3196     }
3197 
3198     /* Set up handler to kill children upon exit */
3199     act.sa_flags = 0;
3200     act.sa_handler = lsapi_cleanup;
3201     sigemptyset(&(act.sa_mask));
3202     if( sigaction( SIGTERM, &act, &old_term ) ||
3203         sigaction( SIGINT,  &act, &old_int  ) ||
3204         sigaction( SIGUSR1, &act, &old_usr1 ) ||
3205         sigaction( SIGQUIT, &act, &old_quit ))
3206     {
3207         perror( "Can't set signals" );
3208         return -1;
3209     }
3210 
3211     while( !s_stop )
3212     {
3213         if (s_proc_group_timer_cb != NULL) {
3214             s_proc_group_timer_cb(&s_ignore_pid);
3215         }
3216 
3217         curTime = time( NULL );
3218         if (curTime != lastTime )
3219         {
3220             lastTime = curTime;
3221             if (lsapi_parent_dead())
3222                 break;
3223             lsapi_check_child_status(curTime );
3224             if (pServer->m_iServerMaxIdle)
3225             {
3226                 if ( pServer->m_iCurChildren <= 0 )
3227                 {
3228                     ++wait_secs;
3229                     if ( wait_secs > pServer->m_iServerMaxIdle )
3230                         return -1;
3231                 }
3232                 else
3233                     wait_secs = 0;
3234             }
3235         }
3236 
3237 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3238         *s_avail_pages = sysconf(_SC_AVPHYS_PAGES);
3239 //        lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n",
3240 //                  s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages);
3241 
3242 #endif
3243         FD_ZERO( &readfds );
3244         FD_SET( pServer->m_fd, &readfds );
3245         timeout.tv_sec = 1;
3246         timeout.tv_usec = 0;
3247         ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout);
3248         if (ret == 1 )
3249         {
3250             int accepting = 0;
3251             if (s_accepting_workers)
3252                 accepting = __sync_add_and_fetch(s_accepting_workers, 0);
3253 
3254             if (pServer->m_iCurChildren > 0
3255                 && accepting > 0)
3256             {
3257                 usleep(400);
3258                 while(accepting-- > 0)
3259                     sched_yield();
3260                 continue;
3261             }
3262         }
3263         else if ( ret == -1 )
3264         {
3265             if ( errno == EINTR )
3266                 continue;
3267             /* perror( "select()" ); */
3268             break;
3269         }
3270         else
3271         {
3272             continue;
3273         }
3274 
3275         if (pServer->m_iCurChildren >=
3276             pServer->m_iMaxChildren + pServer->m_iExtraChildren)
3277         {
3278             lsapi_log("Reached max children process limit: %d, extra: %d,"
3279                      " current: %d, busy: %d, please increase LSAPI_CHILDREN.\n",
3280                      pServer->m_iMaxChildren, pServer->m_iExtraChildren,
3281                      pServer->m_iCurChildren,
3282                      s_busy_workers ? *s_busy_workers : -1 );
3283             usleep( 100000 );
3284             continue;
3285         }
3286 
3287         pReq->m_fd = lsapi_accept( pServer->m_fd );
3288         if ( pReq->m_fd != -1 )
3289         {
3290             wait_secs = 0;
3291             child_status = find_child_status( 0 );
3292 
3293             sigemptyset( &mask );
3294             sigaddset( &mask, SIGCHLD );
3295 
3296             if ( sigprocmask(SIG_BLOCK, &mask, &orig_mask) < 0 )
3297             {
3298                 perror( "sigprocmask(SIG_BLOCK) to block SIGCHLD" );
3299             }
3300 
3301             pid = fork();
3302 
3303             if ( !pid )
3304             {
3305                 setsid();
3306                 if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
3307                     perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK in child" );
3308                 g_prefork_server = NULL;
3309                 s_ppid = getppid();
3310                 s_pid = getpid();
3311                 s_req_processed = 0;
3312                 s_proc_group_timer_cb = NULL;
3313                 s_worker_status = child_status;
3314 
3315                 if (pthread_atfork_func)
3316                     (*pthread_atfork_func)(NULL, NULL, set_skip_write);
3317 
3318                 __sync_lock_test_and_set(&s_worker_status->m_state,
3319                                          LSAPI_STATE_CONNECTED);
3320                 if (s_busy_workers)
3321                     __sync_add_and_fetch(s_busy_workers, 1);
3322                 lsapi_set_nblock( pReq->m_fd, 0 );
3323                 //keep it open if busy_count is used.
3324                 if (!s_keep_listener && s_busy_workers
3325                     && *s_busy_workers > (pServer->m_iMaxChildren >> 1))
3326                     s_keep_listener = 1;
3327                 if ((s_uid == 0 || !s_keep_listener || !is_enough_free_mem())
3328                     && pReq->m_fdListen != -1 )
3329                 {
3330                     close( pReq->m_fdListen );
3331                     pReq->m_fdListen = -1;
3332                 }
3333                 /* don't catch our signals */
3334                 sigaction( SIGCHLD, &old_child, 0 );
3335                 sigaction( SIGTERM, &old_term, 0 );
3336                 sigaction( SIGQUIT, &old_quit, 0 );
3337                 sigaction( SIGINT,  &old_int,  0 );
3338                 sigaction( SIGUSR1, &old_usr1, 0 );
3339                 //init_conn_key( pReq->m_fd );
3340                 lsapi_notify_pid( pReq->m_fd );
3341                 s_notified_pid = 1;
3342                 //if ( s_accept_notify )
3343                 //    return notify_req_received( pReq->m_fd );
3344                 return 0;
3345             }
3346             else if ( pid == -1 )
3347             {
3348                 lsapi_perror("fork() failed, please increase process limit", errno);
3349                 if (child_status)
3350                     child_status->m_pid = 0;
3351             }
3352             else
3353             {
3354                 ++pServer->m_iCurChildren;
3355                 if ( child_status )
3356                 {
3357                     child_status->m_pid = pid;
3358                     child_status->m_tmWaitBegin = curTime;
3359                     child_status->m_tmStart = curTime;
3360                 }
3361             }
3362             close( pReq->m_fd );
3363             pReq->m_fd = -1;
3364 
3365             if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0)
3366                 perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK" );
3367 
3368         }
3369         else
3370         {
3371             if (( errno == EINTR )||( errno == EAGAIN))
3372                 continue;
3373             lsapi_perror("accept() failed", errno);
3374             return -1;
3375         }
3376     }
3377     sigaction( SIGUSR1, &old_usr1, 0 );
3378     //kill( -getpgrp(), SIGUSR1 );
3379     //lsapi_all_children_must_die();  /* Sorry, children ;-) */
3380     return -1;
3381 
3382 }
3383 
3384 
3385 static struct sigaction old_term, old_quit, old_int,
3386                     old_usr1, old_child;
3387 
3388 
LSAPI_Postfork_Child(LSAPI_Request * pReq)3389 int LSAPI_Postfork_Child(LSAPI_Request * pReq)
3390 {
3391     int max_children = g_prefork_server->m_iMaxChildren;
3392     s_pid = getpid();
3393     __sync_lock_test_and_set(&pReq->child_status->m_pid, s_pid);
3394     s_worker_status = pReq->child_status;
3395 
3396     setsid();
3397     g_prefork_server = NULL;
3398     s_ppid = getppid();
3399     s_req_processed = 0;
3400     s_proc_group_timer_cb = NULL;
3401 
3402     if (pthread_atfork_func)
3403         (*pthread_atfork_func)(NULL, NULL, set_skip_write);
3404 
3405     __sync_lock_test_and_set(&s_worker_status->m_state,
3406                                 LSAPI_STATE_CONNECTED);
3407     if (s_busy_workers)
3408         __sync_add_and_fetch(s_busy_workers, 1);
3409     lsapi_set_nblock( pReq->m_fd, 0 );
3410     //keep it open if busy_count is used.
3411     if (!s_keep_listener && s_busy_workers
3412         && *s_busy_workers > (max_children >> 1))
3413         s_keep_listener = 1;
3414     if ((s_uid == 0 || !s_keep_listener || !is_enough_free_mem())
3415         && pReq->m_fdListen != -1 )
3416     {
3417         close(pReq->m_fdListen);
3418         pReq->m_fdListen = -1;
3419     }
3420 
3421     //init_conn_key( pReq->m_fd );
3422     lsapi_notify_pid(pReq->m_fd);
3423     s_notified_pid = 1;
3424     //if ( s_accept_notify )
3425     //    return notify_req_received( pReq->m_fd );
3426     return 0;
3427 }
3428 
3429 
LSAPI_Postfork_Parent(LSAPI_Request * pReq)3430 int LSAPI_Postfork_Parent(LSAPI_Request * pReq)
3431 {
3432     ++g_prefork_server->m_iCurChildren;
3433     if (pReq->child_status)
3434     {
3435         time_t curTime = time( NULL );
3436         pReq->child_status->m_tmWaitBegin = curTime;
3437         pReq->child_status->m_tmStart = curTime;
3438     }
3439     close(pReq->m_fd);
3440     pReq->m_fd = -1;
3441     return 0;
3442 }
3443 
3444 
LSAPI_Accept_Before_Fork(LSAPI_Request * pReq)3445 int LSAPI_Accept_Before_Fork(LSAPI_Request * pReq)
3446 {
3447     time_t          lastTime = 0;
3448     time_t          curTime = 0;
3449     fd_set          readfds;
3450     struct timeval  timeout;
3451     int             wait_secs = 0;
3452     int             ret = 0;
3453 
3454     lsapi_prefork_server * pServer = g_prefork_server;
3455 
3456     struct sigaction act;
3457 
3458     lsapi_init_children_status();
3459 
3460     act.sa_flags = 0;
3461     act.sa_handler = lsapi_sigchild;
3462     sigemptyset(&(act.sa_mask));
3463     if (sigaction(SIGCHLD, &act, &old_child))
3464     {
3465         perror( "Can't set signal handler for SIGCHILD" );
3466         return -1;
3467     }
3468 
3469     /* Set up handler to kill children upon exit */
3470     act.sa_flags = 0;
3471     act.sa_handler = lsapi_cleanup;
3472     sigemptyset(&(act.sa_mask));
3473     if (sigaction(SIGTERM, &act, &old_term) ||
3474         sigaction(SIGINT,  &act, &old_int ) ||
3475         sigaction(SIGUSR1, &act, &old_usr1) ||
3476         sigaction(SIGQUIT, &act, &old_quit))
3477     {
3478         perror( "Can't set signals" );
3479         return -1;
3480     }
3481     s_stop = 0;
3482     pReq->m_reqState = 0;
3483 
3484     while(!s_stop)
3485     {
3486         if (s_proc_group_timer_cb != NULL) {
3487             s_proc_group_timer_cb(&s_ignore_pid);
3488         }
3489 
3490         curTime = time(NULL);
3491         if (curTime != lastTime)
3492         {
3493             lastTime = curTime;
3494             if (lsapi_parent_dead())
3495                 break;
3496             lsapi_check_child_status(curTime);
3497             if (pServer->m_iServerMaxIdle)
3498             {
3499                 if (pServer->m_iCurChildren <= 0)
3500                 {
3501                     ++wait_secs;
3502                     if ( wait_secs > pServer->m_iServerMaxIdle )
3503                         return -1;
3504                 }
3505                 else
3506                     wait_secs = 0;
3507             }
3508         }
3509 
3510 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3511         *s_avail_pages = sysconf(_SC_AVPHYS_PAGES);
3512 //        lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n",
3513 //                  s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages);
3514 
3515 #endif
3516         FD_ZERO(&readfds);
3517         FD_SET(pServer->m_fd, &readfds);
3518         timeout.tv_sec = 1;
3519         timeout.tv_usec = 0;
3520         ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout);
3521         if (ret == 1 )
3522         {
3523             int accepting = 0;
3524             if (s_accepting_workers)
3525                 accepting = __sync_add_and_fetch(s_accepting_workers, 0);
3526 
3527             if (pServer->m_iCurChildren > 0
3528                 && accepting > 0)
3529             {
3530                 usleep( 400);
3531                 while(accepting-- > 0)
3532                     sched_yield();
3533                 continue;
3534             }
3535         }
3536         else if (ret == -1)
3537         {
3538             if (errno == EINTR)
3539                 continue;
3540             /* perror( "select()" ); */
3541             break;
3542         }
3543         else
3544         {
3545             continue;
3546         }
3547 
3548         if (pServer->m_iCurChildren >=
3549             pServer->m_iMaxChildren + pServer->m_iExtraChildren)
3550         {
3551             lsapi_log("Reached max children process limit: %d, extra: %d,"
3552                      " current: %d, busy: %d, please increase LSAPI_CHILDREN.\n",
3553                      pServer->m_iMaxChildren, pServer->m_iExtraChildren,
3554                      pServer->m_iCurChildren,
3555                      s_busy_workers ? *s_busy_workers : -1);
3556             usleep(100000);
3557             continue;
3558         }
3559 
3560         pReq->m_fd = lsapi_accept(pServer->m_fd);
3561         if (pReq->m_fd != -1)
3562         {
3563             wait_secs = 0;
3564             pReq->child_status = find_child_status(0);
3565 
3566             ret = 0;
3567             break;
3568         }
3569         else
3570         {
3571             if ((errno == EINTR) || (errno == EAGAIN))
3572                 continue;
3573             lsapi_perror("accept() failed", errno);
3574             ret = -1;
3575             break;
3576         }
3577     }
3578 
3579     sigaction(SIGCHLD, &old_child, 0);
3580     sigaction(SIGTERM, &old_term, 0);
3581     sigaction(SIGQUIT, &old_quit, 0);
3582     sigaction(SIGINT,  &old_int,  0);
3583     sigaction(SIGUSR1, &old_usr1, 0);
3584 
3585     return ret;
3586 }
3587 
3588 
LSAPI_Prefork_Accept_r(LSAPI_Request * pReq)3589 int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
3590 {
3591     int             fd;
3592     int             ret;
3593     int             wait_secs;
3594     fd_set          readfds;
3595     struct timeval  timeout;
3596 
3597     if (s_skip_write)
3598         return -1;
3599 
3600     LSAPI_Finish_r( pReq );
3601 
3602     if ( g_prefork_server )
3603     {
3604         if ( g_prefork_server->m_fd != -1 )
3605             if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 )
3606                 return -1;
3607     }
3608     else if (s_req_processed > 0 && s_max_busy_workers > 0 && s_busy_workers)
3609     {
3610         ret = __sync_fetch_and_add(s_busy_workers, 0);
3611         if (ret >= s_max_busy_workers)
3612         {
3613             send_conn_close_notification(pReq->m_fd);
3614             lsapi_close_connection(pReq);
3615         }
3616     }
3617 
3618     if ( (unsigned int)s_req_processed > s_max_reqs )
3619         return -1;
3620 
3621     if ( s_worker_status )
3622     {
3623         s_worker_status->m_tmWaitBegin = time( NULL );
3624     }
3625 
3626 
3627     while( g_running )
3628     {
3629         if ( pReq->m_fd != -1 )
3630         {
3631             fd = pReq->m_fd;
3632         }
3633         else if ( pReq->m_fdListen != -1 )
3634             fd = pReq->m_fdListen;
3635         else
3636         {
3637             break;
3638         }
3639         wait_secs = 0;
3640         while( 1 )
3641         {
3642             if ( !g_running )
3643                 return -1;
3644             if (s_req_processed && s_worker_status
3645                 && s_worker_status->m_iKillSent)
3646                 return -1;
3647             FD_ZERO( &readfds );
3648             FD_SET( fd, &readfds );
3649             timeout.tv_sec = 1;
3650             timeout.tv_usec = 0;
3651             if (fd == pReq->m_fdListen)
3652             {
3653                 if (s_worker_status)
3654                     __sync_lock_test_and_set(&s_worker_status->m_state,
3655                                              LSAPI_STATE_ACCEPTING);
3656                 if (s_accepting_workers)
3657                     __sync_fetch_and_add(s_accepting_workers, 1);
3658             }
3659             ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout);
3660             if (fd == pReq->m_fdListen)
3661             {
3662                 if (s_accepting_workers)
3663                     __sync_fetch_and_sub(s_accepting_workers, 1);
3664                 if (s_worker_status)
3665                     __sync_lock_test_and_set(&s_worker_status->m_state,
3666                                              LSAPI_STATE_IDLE);
3667             }
3668 
3669             if ( ret == 0 )
3670             {
3671                 if ( s_worker_status )
3672                 {
3673                     s_worker_status->m_inProcess = 0;
3674                     if (fd == pReq->m_fdListen)
3675                     {
3676                         if (s_keep_listener == 0 || !is_enough_free_mem())
3677                             return -1;
3678                         if (s_keep_listener == 1)
3679                         {
3680                             int wait_time = 10;
3681                             if (s_busy_workers)
3682                                 wait_time += *s_busy_workers * 10;
3683                             if (s_accepting_workers)
3684                                 wait_time >>= (*s_accepting_workers);
3685                             if (wait_secs >= wait_time)
3686                                 return -1;
3687                         }
3688                     }
3689                 }
3690                 ++wait_secs;
3691                 if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs ))
3692                     return -1;
3693                 if ( lsapi_parent_dead() )
3694                     return -1;
3695             }
3696             else if ( ret == -1 )
3697             {
3698                 if ( errno == EINTR )
3699                     continue;
3700                 else
3701                     return -1;
3702             }
3703             else if ( ret >= 1 )
3704             {
3705                 if (s_req_processed && s_worker_status
3706                     && s_worker_status->m_iKillSent)
3707                     return -1;
3708                 if ( fd == pReq->m_fdListen )
3709                 {
3710                     pReq->m_fd = lsapi_accept( pReq->m_fdListen );
3711                     if ( pReq->m_fd != -1 )
3712                     {
3713                         if (s_worker_status)
3714                             __sync_lock_test_and_set(&s_worker_status->m_state,
3715                                                      LSAPI_STATE_CONNECTED);
3716                         if (s_busy_workers)
3717                             __sync_fetch_and_add(s_busy_workers, 1);
3718 
3719                         fd = pReq->m_fd;
3720 
3721                         lsapi_set_nblock( fd, 0 );
3722                         //init_conn_key( pReq->m_fd );
3723                         if (!s_keep_listener)
3724                         {
3725                             close( pReq->m_fdListen );
3726                             pReq->m_fdListen = -1;
3727                         }
3728                         if ( s_accept_notify )
3729                             if ( notify_req_received( pReq->m_fd ) == -1 )
3730                                 return -1;
3731                     }
3732                     else
3733                     {
3734                         if (( errno == EINTR )||( errno == EAGAIN))
3735                             continue;
3736                         lsapi_perror( "lsapi_accept() error", errno );
3737                         return -1;
3738                     }
3739                 }
3740                 else
3741                     break;
3742             }
3743         }
3744 
3745         if ( !readReq( pReq ) )
3746         {
3747             if ( s_worker_status )
3748             {
3749                 s_worker_status->m_iKillSent = 0;
3750                 s_worker_status->m_inProcess = 1;
3751                 ++s_worker_status->m_iReqCounter;
3752                 s_worker_status->m_tmReqBegin =
3753                 s_worker_status->m_tmLastCheckPoint = time(NULL);
3754             }
3755             ++s_req_processed;
3756             return 0;
3757         }
3758         lsapi_close_connection(pReq);
3759         LSAPI_Reset_r( pReq );
3760     }
3761     return -1;
3762 
3763 }
3764 
3765 
LSAPI_Set_Max_Reqs(int reqs)3766 void LSAPI_Set_Max_Reqs( int reqs )
3767 {   s_max_reqs = reqs - 1;      }
3768 
LSAPI_Set_Max_Idle(int secs)3769 void LSAPI_Set_Max_Idle( int secs )
3770 {   s_max_idle_secs = secs;     }
3771 
3772 
LSAPI_Set_Max_Children(int maxChildren)3773 void LSAPI_Set_Max_Children( int maxChildren )
3774 {
3775     if ( g_prefork_server )
3776         g_prefork_server->m_iMaxChildren = maxChildren;
3777 }
3778 
3779 
LSAPI_Set_Extra_Children(int extraChildren)3780 void LSAPI_Set_Extra_Children( int extraChildren )
3781 {
3782     if (( g_prefork_server )&&( extraChildren >= 0 ))
3783         g_prefork_server->m_iExtraChildren = extraChildren;
3784 }
3785 
3786 
LSAPI_Set_Max_Process_Time(int secs)3787 void LSAPI_Set_Max_Process_Time( int secs )
3788 {
3789     if (( g_prefork_server )&&( secs > 0 ))
3790         g_prefork_server->m_iMaxReqProcessTime = secs;
3791 }
3792 
3793 
LSAPI_Set_Max_Idle_Children(int maxIdleChld)3794 void LSAPI_Set_Max_Idle_Children( int maxIdleChld )
3795 {
3796     if (( g_prefork_server )&&( maxIdleChld > 0 ))
3797         g_prefork_server->m_iMaxIdleChildren = maxIdleChld;
3798 }
3799 
3800 
LSAPI_Set_Server_Max_Idle_Secs(int serverMaxIdle)3801 void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle )
3802 {
3803     if ( g_prefork_server )
3804         g_prefork_server->m_iServerMaxIdle = serverMaxIdle;
3805 }
3806 
3807 
LSAPI_Set_Slow_Req_Msecs(int msecs)3808 void LSAPI_Set_Slow_Req_Msecs( int msecs )
3809 {
3810     s_slow_req_msecs = msecs;
3811 }
3812 
3813 
LSAPI_Get_Slow_Req_Msecs(void)3814 int  LSAPI_Get_Slow_Req_Msecs(void)
3815 {
3816     return s_slow_req_msecs;
3817 }
3818 
3819 
LSAPI_No_Check_ppid(void)3820 void LSAPI_No_Check_ppid(void)
3821 {
3822     s_ppid = 0;
3823 }
3824 
3825 
LSAPI_Get_ppid()3826 int LSAPI_Get_ppid()
3827 {
3828     return(s_ppid);
3829 }
3830 
3831 
3832 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
3833 #include <crt_externs.h>
3834 #else
3835 extern char ** environ;
3836 #endif
unset_lsapi_envs(void)3837 static void unset_lsapi_envs(void)
3838 {
3839     char **env;
3840 #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
3841     env = *_NSGetEnviron();
3842 #else
3843     env = environ;
3844 #endif
3845     while( env != NULL && *env != NULL )
3846     {
3847         if (!strncmp(*env, "LSAPI_", 6) || !strncmp( *env, "PHP_LSAPI_", 10 )
3848             || (!strncmp( *env, "PHPRC=", 6 )&&(!s_uid)))
3849         {
3850             char ** del = env;
3851             do
3852                 *del = del[1];
3853             while( *del++ );
3854         }
3855         else
3856             ++env;
3857     }
3858 }
3859 
3860 
lsapi_initSuEXEC(void)3861 static int lsapi_initSuEXEC(void)
3862 {
3863     int i;
3864     struct passwd * pw;
3865     s_defaultUid = 0;
3866     s_defaultGid = 0;
3867     if ( s_uid == 0 )
3868     {
3869         const char * p = getenv( "LSAPI_DEFAULT_UID" );
3870         if ( p )
3871         {
3872             i = atoi( p );
3873             if ( i > 0 )
3874                 s_defaultUid = i;
3875         }
3876         p = getenv( "LSAPI_DEFAULT_GID" );
3877         if ( p )
3878         {
3879             i = atoi( p );
3880             if ( i > 0 )
3881                 s_defaultGid = i;
3882         }
3883         p = getenv( "LSAPI_SECRET" );
3884         if (( !p )||( readSecret(p) == -1 ))
3885                 return -1;
3886         if ( g_prefork_server )
3887         {
3888             if ( g_prefork_server->m_iMaxChildren < 100 )
3889                 g_prefork_server->m_iMaxChildren = 100;
3890             if ( g_prefork_server->m_iExtraChildren < 1000 )
3891                 g_prefork_server->m_iExtraChildren = 1000;
3892         }
3893     }
3894     if ( !s_defaultUid || !s_defaultGid )
3895     {
3896         pw = getpwnam( "nobody" );
3897         if ( pw )
3898         {
3899             if ( !s_defaultUid )
3900                 s_defaultUid = pw->pw_uid;
3901             if ( !s_defaultGid )
3902                 s_defaultGid = pw->pw_gid;
3903         }
3904         else
3905         {
3906             if ( !s_defaultUid )
3907                 s_defaultUid = 10000;
3908             if ( !s_defaultGid )
3909                 s_defaultGid = 10000;
3910         }
3911     }
3912     return 0;
3913 }
3914 
3915 
lsapi_check_path(const char * p,char * final,int max_len)3916 static int lsapi_check_path(const char *p, char *final, int max_len)
3917 {
3918     char resolved_path[PATH_MAX+1];
3919     int len = 0;
3920     char *end;
3921     if (*p != '/')
3922     {
3923         if (getcwd(final, max_len) == NULL)
3924             return -1;
3925         len = strlen(final);
3926         *(final + len) = '/';
3927         ++len;
3928     }
3929     end = memccpy(&final[len], p, '\0', PATH_MAX - len);
3930     if (!end)
3931     {
3932         errno = EINVAL;
3933         return -1;
3934     }
3935     p = final;
3936     if (realpath(p, resolved_path) == NULL
3937         && errno != ENOENT && errno != EACCES)
3938         return -1;
3939     if (strncmp(resolved_path, "/etc/", 5) == 0)
3940     {
3941         errno = EPERM;
3942         return -1;
3943     }
3944     return 0;
3945 }
3946 
3947 
lsapi_reopen_stderr2(const char * full_path)3948 static int lsapi_reopen_stderr2(const char *full_path)
3949 {
3950     int newfd = open(full_path, O_WRONLY | O_CREAT | O_APPEND, 0644);
3951     if (newfd == -1)
3952     {
3953         LSAPI_perror_r(NULL, "Failed to open custom stderr log", full_path);
3954         return -1;
3955     }
3956     if (newfd != 2)
3957     {
3958         dup2(newfd, 2);
3959         close(newfd);
3960         dup2(2, 1);
3961     }
3962     if (s_stderr_log_path && full_path != s_stderr_log_path)
3963     {
3964         free(s_stderr_log_path);
3965         s_stderr_log_path = NULL;
3966     }
3967     s_stderr_log_path = strdup(full_path);
3968     return 0;
3969 }
3970 
3971 
lsapi_reopen_stderr(const char * p)3972 static int lsapi_reopen_stderr(const char *p)
3973 {
3974     char full_path[PATH_MAX];
3975     if (s_uid == 0)
3976         return -1;
3977     if (lsapi_check_path(p, full_path, PATH_MAX) == -1)
3978     {
3979         LSAPI_perror_r(NULL, "Invalid custom stderr log path", p);
3980         return -1;
3981     }
3982     return lsapi_reopen_stderr2(full_path);
3983 }
3984 
3985 
LSAPI_Init_Env_Parameters(fn_select_t fp)3986 int LSAPI_Init_Env_Parameters( fn_select_t fp )
3987 {
3988     const char *p;
3989     char ch;
3990     int n;
3991     int avoidFork = 0;
3992 
3993     p = getenv("LSAPI_STDERR_LOG");
3994     if (p)
3995     {
3996         lsapi_reopen_stderr(p);
3997     }
3998     if (!s_stderr_log_path)
3999         s_stderr_is_pipe = isPipe(STDERR_FILENO);
4000 
4001     p = getenv( "PHP_LSAPI_MAX_REQUESTS" );
4002     if ( !p )
4003         p = getenv( "LSAPI_MAX_REQS" );
4004     if ( p )
4005     {
4006         n = atoi( p );
4007         if ( n > 0 )
4008             LSAPI_Set_Max_Reqs( n );
4009     }
4010 
4011     p = getenv( "LSAPI_KEEP_LISTEN" );
4012     if ( p )
4013     {
4014         n = atoi( p );
4015         s_keep_listener = n;
4016     }
4017 
4018     p = getenv( "LSAPI_AVOID_FORK" );
4019     if ( p )
4020     {
4021         avoidFork = atoi( p );
4022         if (avoidFork)
4023         {
4024             s_keep_listener = 2;
4025             ch = *(p + strlen(p) - 1);
4026             if (  ch == 'G' || ch == 'g' )
4027                 avoidFork *= 1024 * 1024 * 1024;
4028             else if (  ch == 'M' || ch == 'm' )
4029                 avoidFork *= 1024 * 1024;
4030             if (avoidFork >= 1024 * 10240)
4031                 s_min_avail_pages = avoidFork / 4096;
4032         }
4033     }
4034 
4035     p = getenv( "LSAPI_ACCEPT_NOTIFY" );
4036     if ( p )
4037     {
4038         s_accept_notify = atoi( p );
4039     }
4040 
4041     p = getenv( "LSAPI_SLOW_REQ_MSECS" );
4042     if ( p )
4043     {
4044         n = atoi( p );
4045         LSAPI_Set_Slow_Req_Msecs( n );
4046     }
4047 
4048 #if defined( RLIMIT_CORE )
4049     p = getenv( "LSAPI_ALLOW_CORE_DUMP" );
4050     if ( !p )
4051     {
4052         struct rlimit limit = { 0, 0 };
4053         setrlimit( RLIMIT_CORE, &limit );
4054     }
4055     else
4056         s_enable_core_dump = 1;
4057 
4058 #endif
4059 
4060     p = getenv( "LSAPI_MAX_IDLE" );
4061     if ( p )
4062     {
4063         n = atoi( p );
4064         LSAPI_Set_Max_Idle( n );
4065     }
4066 
4067     if ( LSAPI_Is_Listen() )
4068     {
4069         n = 0;
4070         p = getenv( "PHP_LSAPI_CHILDREN" );
4071         if ( !p )
4072             p = getenv( "LSAPI_CHILDREN" );
4073         if ( p )
4074             n = atoi( p );
4075         if ( n > 1 )
4076         {
4077             LSAPI_Init_Prefork_Server( n, fp, avoidFork != 0 );
4078             LSAPI_Set_Server_fd( g_req.m_fdListen );
4079         }
4080 
4081         p = getenv( "LSAPI_EXTRA_CHILDREN" );
4082         if ( p )
4083             LSAPI_Set_Extra_Children( atoi( p ) );
4084 
4085         p = getenv( "LSAPI_MAX_IDLE_CHILDREN" );
4086         if ( p )
4087             LSAPI_Set_Max_Idle_Children( atoi( p ) );
4088 
4089         p = getenv( "LSAPI_PGRP_MAX_IDLE" );
4090         if ( p )
4091         {
4092             LSAPI_Set_Server_Max_Idle_Secs( atoi( p ) );
4093         }
4094 
4095         p = getenv( "LSAPI_MAX_PROCESS_TIME" );
4096         if ( p )
4097             LSAPI_Set_Max_Process_Time( atoi( p ) );
4098 
4099         if ( getenv( "LSAPI_PPID_NO_CHECK" ) )
4100         {
4101             LSAPI_No_Check_ppid();
4102         }
4103 
4104         p = getenv("LSAPI_MAX_BUSY_WORKER");
4105         if (p)
4106         {
4107             n = atoi(p);
4108             s_max_busy_workers = n;
4109             if (n >= 0)
4110                 LSAPI_No_Check_ppid();
4111         }
4112 
4113 
4114         p = getenv( "LSAPI_DUMP_DEBUG_INFO" );
4115         if ( p )
4116             s_dump_debug_info = atoi( p );
4117 
4118         if ( lsapi_initSuEXEC() == -1 )
4119             return -1;
4120 #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
4121         lsapi_initLVE();
4122 #endif
4123     }
4124     unset_lsapi_envs();
4125     return 0;
4126 }
4127 
4128 
LSAPI_ErrResponse_r(LSAPI_Request * pReq,int code,const char ** pRespHeaders,const char * pBody,int bodyLen)4129 int LSAPI_ErrResponse_r( LSAPI_Request * pReq, int code, const char ** pRespHeaders,
4130                          const char * pBody, int bodyLen )
4131 {
4132     LSAPI_SetRespStatus_r( pReq, code );
4133     if ( pRespHeaders )
4134     {
4135         while( *pRespHeaders )
4136         {
4137             LSAPI_AppendRespHeader_r( pReq, *pRespHeaders, strlen( *pRespHeaders ) );
4138             ++pRespHeaders;
4139         }
4140     }
4141     if ( pBody &&( bodyLen > 0 ))
4142     {
4143         LSAPI_Write_r( pReq, pBody, bodyLen );
4144     }
4145     LSAPI_Finish_r( pReq );
4146     return 0;
4147 }
4148 
4149 
4150 static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]);
4151 
4152 /*
4153  * Note: this code is harmless on little-endian machines.
4154  */
byteReverse(unsigned char * buf,unsigned longs)4155 static void byteReverse(unsigned char *buf, unsigned longs)
4156 {
4157     uint32 t;
4158     do {
4159         t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
4160             ((unsigned) buf[1] << 8 | buf[0]);
4161         *(uint32 *) buf = t;
4162         buf += 4;
4163     } while (--longs);
4164 }
4165 
4166 
4167 /*
4168  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
4169  * initialization constants.
4170  */
lsapi_MD5Init(struct lsapi_MD5Context * ctx)4171 void lsapi_MD5Init(struct lsapi_MD5Context *ctx)
4172 {
4173     ctx->buf[0] = 0x67452301;
4174     ctx->buf[1] = 0xefcdab89;
4175     ctx->buf[2] = 0x98badcfe;
4176     ctx->buf[3] = 0x10325476;
4177 
4178     ctx->bits[0] = 0;
4179     ctx->bits[1] = 0;
4180 }
4181 
4182 /*
4183  * Update context to reflect the concatenation of another buffer full
4184  * of bytes.
4185  */
lsapi_MD5Update(struct lsapi_MD5Context * ctx,unsigned char const * buf,unsigned len)4186 void lsapi_MD5Update(struct lsapi_MD5Context *ctx, unsigned char const *buf, unsigned len)
4187 {
4188     register uint32 t;
4189 
4190     /* Update bitcount */
4191 
4192     t = ctx->bits[0];
4193     if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
4194         ctx->bits[1]++;                /* Carry from low to high */
4195     ctx->bits[1] += len >> 29;
4196 
4197     t = (t >> 3) & 0x3f;        /* Bytes already in shsInfo->data */
4198 
4199     /* Handle any leading odd-sized chunks */
4200 
4201     if (t) {
4202         unsigned char *p = (unsigned char *) ctx->in + t;
4203 
4204         t = 64 - t;
4205         if (len < t) {
4206             memmove(p, buf, len);
4207             return;
4208         }
4209         memmove(p, buf, t);
4210         byteReverse(ctx->in, 16);
4211         lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
4212         buf += t;
4213         len -= t;
4214     }
4215     /* Process data in 64-byte chunks */
4216 
4217     while (len >= 64) {
4218         memmove(ctx->in, buf, 64);
4219         byteReverse(ctx->in, 16);
4220         lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
4221         buf += 64;
4222         len -= 64;
4223     }
4224 
4225     /* Handle any remaining bytes of data. */
4226 
4227     memmove(ctx->in, buf, len);
4228 }
4229 
4230 
4231 /*
4232  * Final wrap-up - pad to 64-byte boundary with the bit pattern
4233  * 1 0* (64-bit count of bits processed, MSB-first)
4234  */
lsapi_MD5Final(unsigned char digest[16],struct lsapi_MD5Context * ctx)4235 void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *ctx)
4236 {
4237     unsigned int count;
4238     unsigned char *p;
4239 
4240     /* Compute number of bytes mod 64 */
4241     count = (ctx->bits[0] >> 3) & 0x3F;
4242 
4243     /* Set the first char of padding to 0x80.  This is safe since there is
4244        always at least one byte free */
4245     p = ctx->in + count;
4246     *p++ = 0x80;
4247 
4248     /* Bytes of padding needed to make 64 bytes */
4249     count = 64 - 1 - count;
4250 
4251     /* Pad out to 56 mod 64 */
4252     if (count < 8) {
4253         /* Two lots of padding:  Pad the first block to 64 bytes */
4254         memset(p, 0, count);
4255         byteReverse(ctx->in, 16);
4256         lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
4257 
4258         /* Now fill the next block with 56 bytes */
4259         memset(ctx->in, 0, 56);
4260     } else {
4261         /* Pad block to 56 bytes */
4262         memset(p, 0, count - 8);
4263     }
4264     byteReverse(ctx->in, 14);
4265 
4266     /* Append length in bits and transform */
4267     ((uint32 *) ctx->in)[14] = ctx->bits[0];
4268     ((uint32 *) ctx->in)[15] = ctx->bits[1];
4269 
4270     lsapi_MD5Transform(ctx->buf, (uint32 *) ctx->in);
4271     byteReverse((unsigned char *) ctx->buf, 4);
4272     memmove(digest, ctx->buf, 16);
4273     memset(ctx, 0, sizeof(*ctx));        /* In case it's sensitive */
4274 }
4275 
4276 
4277 /* The four core functions - F1 is optimized somewhat */
4278 
4279 /* #define F1(x, y, z) (x & y | ~x & z) */
4280 #define F1(x, y, z) (z ^ (x & (y ^ z)))
4281 #define F2(x, y, z) F1(z, x, y)
4282 #define F3(x, y, z) (x ^ y ^ z)
4283 #define F4(x, y, z) (y ^ (x | ~z))
4284 
4285 /* This is the central step in the MD5 algorithm. */
4286 #define MD5STEP(f, w, x, y, z, data, s) \
4287         ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
4288 
4289 /*
4290  * The core of the MD5 algorithm, this alters an existing MD5 hash to
4291  * reflect the addition of 16 longwords of new data.  MD5Update blocks
4292  * the data and converts bytes into longwords for this routine.
4293  */
lsapi_MD5Transform(uint32 buf[4],uint32 const in[16])4294 static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16])
4295 {
4296     register uint32 a, b, c, d;
4297 
4298     a = buf[0];
4299     b = buf[1];
4300     c = buf[2];
4301     d = buf[3];
4302 
4303     MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
4304     MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
4305     MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
4306     MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
4307     MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
4308     MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
4309     MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
4310     MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
4311     MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
4312     MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
4313     MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
4314     MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
4315     MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
4316     MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
4317     MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
4318     MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
4319 
4320     MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
4321     MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
4322     MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
4323     MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
4324     MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
4325     MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
4326     MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
4327     MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
4328     MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
4329     MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
4330     MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
4331     MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
4332     MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
4333     MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
4334     MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
4335     MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
4336 
4337     MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
4338     MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
4339     MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
4340     MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
4341     MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
4342     MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
4343     MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
4344     MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
4345     MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
4346     MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
4347     MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
4348     MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
4349     MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
4350     MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
4351     MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
4352     MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
4353 
4354     MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
4355     MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
4356     MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
4357     MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
4358     MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
4359     MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
4360     MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
4361     MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
4362     MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
4363     MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
4364     MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
4365     MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
4366     MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
4367     MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
4368     MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
4369     MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
4370 
4371     buf[0] += a;
4372     buf[1] += b;
4373     buf[2] += c;
4374     buf[3] += d;
4375 }
4376 
4377 
LSAPI_Set_Restored_Parent_Pid(int pid)4378 int LSAPI_Set_Restored_Parent_Pid(int pid)
4379 {
4380     int old_ppid = s_ppid;
4381     s_restored_ppid = pid;
4382     return old_ppid;
4383 }
4384 
4385 
LSAPI_Inc_Req_Processed(int cnt)4386 int LSAPI_Inc_Req_Processed(int cnt)
4387 {
4388     return __sync_add_and_fetch(s_global_counter, cnt);
4389 }
4390