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