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