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