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