ruby-lsapi 1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README ADDED
@@ -0,0 +1,84 @@
1
+
2
+ lsapi - LSAPI extension for Ruby
3
+ ================================
4
+
5
+ Version 0.1.0
6
+
7
+ INSTALL
8
+ -------
9
+
10
+ $ ruby setup.rb config
11
+ $ ruby setup.rb setup
12
+ # ruby setup.rb install
13
+
14
+ USAGE
15
+ -----
16
+
17
+ General CGI scripts
18
+ ```````````````````
19
+ The most efficient way to use LSAPI interface is to modify your CGI script,
20
+ you need to add the following to your CGI script
21
+
22
+ require 'lsapi'
23
+
24
+ while LSAPI.accept != nil
25
+
26
+ <your CGI script>
27
+ ...
28
+
29
+ end
30
+
31
+ There is no need to change the way how CGI environment variables being
32
+ accessed in your script.
33
+
34
+ There are examples under examples/ folder.
35
+
36
+
37
+ Rails dispatcher
38
+ ````````````````
39
+ A LSAPI dispatcher is available under rails/ folder, just copy it over to
40
+ the public/ folder of your Rails application, then change the rewrite rule
41
+ in public/.htaccess from
42
+
43
+ RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]
44
+ to
45
+ RewriteRule ^(.*)$ dispatch.lsapi [QSA,L]
46
+
47
+ It is very expensive to start a fresh Rails application process, while on
48
+ the other hand, server hardware resources can be used more efficiently with
49
+ dynamic spawning. In order to solve this conflict, instead of spawning a
50
+ fresh Rails process, LSAPI dispatcher can dynamically fork children processes
51
+ off an initialized Rails process.
52
+
53
+ When you configure dispatch.lsapi as a LSAPI application, you should add
54
+ an extra environment variable
55
+
56
+ LSAPI_CHILDREN=n
57
+
58
+ n should match the "Max Conns" configuration entry of the LSAPI application.
59
+
60
+
61
+ Ruby Script Runner
62
+ ``````````````````
63
+ If you don't want to change your Ruby CGI code, you can use our Ruby script
64
+ runner under scripts/ folder. You need to configure lsruby_runner.rb as a
65
+ LSAPI application, then add a script handler for "rb" suffix.
66
+
67
+
68
+ License
69
+ -------
70
+
71
+ LSAPI library code is under BSD license
72
+
73
+ LSAPI ruby extension code is under Ruby license
74
+
75
+ * ((<URL:http://www.ruby-lang.org/ja/LICENSE.txt>)) (Japanese)
76
+ * ((<URL:http://www.ruby-lang.org/en/LICENSE.txt>)) (English)
77
+
78
+
79
+ Copyright
80
+ ---------
81
+
82
+ Copyright (C) 2006 Lite Speed Technologes Inc.
83
+
84
+
@@ -0,0 +1,14 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ require 'lsapi'
4
+ require 'cgi'
5
+
6
+
7
+ while LSAPI.accept != nil
8
+ cgi = CGI.new
9
+ name = cgi['name']
10
+ puts cgi.header
11
+ puts "Hello #{name}! <br> " if name
12
+ puts "You are from #{cgi.remote_addr}<br>"
13
+
14
+ end
@@ -0,0 +1,11 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ require 'lsapi'
4
+
5
+ $count = 0;
6
+
7
+ while LSAPI.accept != nil
8
+ print "HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\nHello World! \##{$count}<br>\r\n"
9
+ ENV.each_pair {|key, value| print "#{key} is #{value}<br>\r\n" }
10
+ $count = $count + 1
11
+ end
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+ dir_config( 'lsapi' )
3
+ create_makefile( "lsapi" )
@@ -0,0 +1,181 @@
1
+ /*
2
+ Copyright (c) 2005, Lite Speed Technologies Inc.
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are
7
+ met:
8
+
9
+ * Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+ * Redistributions in binary form must reproduce the above
12
+ copyright notice, this list of conditions and the following
13
+ disclaimer in the documentation and/or other materials provided
14
+ with the distribution.
15
+ * Neither the name of the Lite Speed Technologies Inc nor the
16
+ names of its contributors may be used to endorse or promote
17
+ products derived from this software without specific prior
18
+ written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ */
32
+
33
+ /***************************************************************************
34
+ $Id: lsapidef.h,v 1.14 2005/09/29 23:51:06 gwang Exp $
35
+ -------------------
36
+ begin : Thu Feb 10 2005
37
+ author : George Wang
38
+ email : gwang@litespeedtech.com
39
+ ***************************************************************************/
40
+
41
+ #ifndef _LSAPIDEF_H_
42
+ #define _LSAPIDEF_H_
43
+
44
+ #include <inttypes.h>
45
+
46
+ #if defined (c_plusplus) || defined (__cplusplus)
47
+ extern "C" {
48
+ #endif
49
+
50
+ enum
51
+ {
52
+ H_ACCEPT = 0,
53
+ H_ACC_CHARSET,
54
+ H_ACC_ENCODING,
55
+ H_ACC_LANG,
56
+ H_AUTHORIZATION,
57
+ H_CONNECTION,
58
+ H_CONTENT_TYPE,
59
+ H_CONTENT_LENGTH,
60
+ H_COOKIE,
61
+ H_COOKIE2,
62
+ H_HOST,
63
+ H_PRAGMA,
64
+ H_REFERER,
65
+ H_USERAGENT,
66
+ H_CACHE_CTRL,
67
+ H_IF_MODIFIED_SINCE,
68
+ H_IF_MATCH,
69
+ H_IF_NO_MATCH,
70
+ H_IF_RANGE,
71
+ H_IF_UNMOD_SINCE,
72
+ H_KEEP_ALIVE,
73
+ H_RANGE,
74
+ H_X_FORWARDED_FOR,
75
+ H_VIA,
76
+ H_TRANSFER_ENCODING
77
+
78
+ };
79
+ #define LSAPI_SOCK_FILENO 0
80
+
81
+ #define LSAPI_VERSION_B0 'L'
82
+ #define LSAPI_VERSION_B1 'S'
83
+
84
+ //Values for m_flag in lsapi_packet_header
85
+ #define LSAPI_ENDIAN_LITTLE 0
86
+ #define LSAPI_ENDIAN_BIG 1
87
+ #define LSAPI_ENDIAN_BIT 1
88
+
89
+ #if defined(__i386__)||defined( __x86_64 )||defined( __x86_64__ )
90
+ #define LSAPI_ENDIAN LSAPI_ENDIAN_LITTLE
91
+ #else
92
+ #define LSAPI_ENDIAN LSAPI_ENDIAN_BIG
93
+ #endif
94
+
95
+ //Values for m_type in lsapi_packet_header
96
+ #define LSAPI_BEGIN_REQUEST 1
97
+ #define LSAPI_ABORT_REQUEST 2
98
+ #define LSAPI_RESP_HEADER 3
99
+ #define LSAPI_RESP_STREAM 4
100
+ #define LSAPI_RESP_END 5
101
+ #define LSAPI_STDERR_STREAM 6
102
+ #define LSAPI_REQ_RECEIVED 7
103
+
104
+
105
+ #define LSAPI_MAX_HEADER_LEN 65535
106
+ #define LSAPI_MAX_DATA_PACKET_LEN 16384
107
+
108
+ #define LSAPI_RESP_HTTP_HEADER_MAX 4096
109
+ #define LSAPI_PACKET_HEADER_LEN 8
110
+
111
+
112
+ struct lsapi_packet_header
113
+ {
114
+ char m_versionB0; //LSAPI protocol version
115
+ char m_versionB1;
116
+ char m_type;
117
+ char m_flag;
118
+ union
119
+ {
120
+ int32_t m_iLen; //include this header
121
+ char m_bytes[4];
122
+ }m_packetLen;
123
+ };
124
+
125
+ // LSAPI request header packet
126
+ //
127
+ // 1. struct lsapi_req_header
128
+ // 2. struct lsapi_http_header_index
129
+ // 3. lsapi_header_offset * unknownHeaders
130
+ // 4. org http request header
131
+ // 5. request body if available
132
+
133
+ struct lsapi_req_header
134
+ {
135
+ struct lsapi_packet_header m_pktHeader;
136
+
137
+ int32_t m_httpHeaderLen;
138
+ int32_t m_reqBodyLen;
139
+ int32_t m_scriptFileOff; //path to the script file.
140
+ int32_t m_scriptNameOff; //decrypted URI, without pathinfo,
141
+ int32_t m_queryStringOff; //Query string inside env
142
+ int32_t m_requestMethodOff;
143
+ int32_t m_cntUnknownHeaders;
144
+ int32_t m_cntEnv;
145
+ int32_t m_cntSpecialEnv;
146
+ } ;
147
+
148
+
149
+ struct lsapi_http_header_index
150
+ {
151
+ int16_t m_headerLen[H_TRANSFER_ENCODING+1];
152
+ int32_t m_headerOff[H_TRANSFER_ENCODING+1];
153
+ } ;
154
+
155
+ struct lsapi_header_offset
156
+ {
157
+ int32_t nameOff;
158
+ int32_t nameLen;
159
+ int32_t valueOff;
160
+ int32_t valueLen;
161
+ } ;
162
+
163
+ struct lsapi_resp_info
164
+ {
165
+ int32_t m_cntHeaders;
166
+ int32_t m_status;
167
+ };
168
+
169
+ struct lsapi_resp_header
170
+ {
171
+ struct lsapi_packet_header m_pktHeader;
172
+ struct lsapi_resp_info m_respInfo;
173
+ };
174
+
175
+ #if defined (c_plusplus) || defined (__cplusplus)
176
+ }
177
+ #endif
178
+
179
+
180
+ #endif
181
+
@@ -0,0 +1,1181 @@
1
+ /*
2
+ Copyright (c) 2005, Lite Speed Technologies Inc.
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are
7
+ met:
8
+
9
+ * Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+ * Redistributions in binary form must reproduce the above
12
+ copyright notice, this list of conditions and the following
13
+ disclaimer in the documentation and/or other materials provided
14
+ with the distribution.
15
+ * Neither the name of the Lite Speed Technologies Inc nor the
16
+ names of its contributors may be used to endorse or promote
17
+ products derived from this software without specific prior
18
+ written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ */
32
+
33
+ /***************************************************************************
34
+ lsapilib.c - description
35
+ -------------------
36
+ begin : Mon Feb 21 2005
37
+ copyright : (C) 2005 by George Wang
38
+ email : gwang@litespeedtech.com
39
+ ***************************************************************************/
40
+
41
+
42
+ #include <lsapilib.h>
43
+
44
+ #include <ctype.h>
45
+ #include <errno.h>
46
+ #include <fcntl.h>
47
+
48
+ //#include <arpa/inet.h>
49
+ #include <sys/types.h>
50
+ #include <netinet/in.h>
51
+ #include <netinet/tcp.h>
52
+ #include <signal.h>
53
+ #include <stdlib.h>
54
+ #include <stdio.h>
55
+ #include <string.h>
56
+ #include <sys/socket.h>
57
+ #include <sys/uio.h>
58
+ #include <unistd.h>
59
+
60
+ #define LSAPI_ST_REQ_HEADER 1
61
+ #define LSAPI_ST_REQ_BODY 2
62
+ #define LSAPI_ST_RESP_HEADER 4
63
+ #define LSAPI_ST_RESP_BODY 8
64
+
65
+ #define LSAPI_RESP_BUF_SIZE 8192
66
+ #define LSAPI_INIT_RESP_HEADER_LEN 4096
67
+
68
+
69
+ static int g_inited = 0;
70
+ static int g_running = 1;
71
+ LSAPI_Request g_req;
72
+
73
+ void Flush_RespBuf_r( LSAPI_Request * pReq );
74
+
75
+ static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] =
76
+ {
77
+ "HTTP_ACCEPT", "HTTP_ACCEPT_CHARSET",
78
+ "HTTP_ACCEPT_ENCODING",
79
+ "HTTP_ACCEPT_LANGUAGE", "HTTP_AUTHORIZATION",
80
+ "HTTP_CONNECTION", "CONTENT_TYPE",
81
+ "CONTENT_LENGTH", "HTTP_COOKIE", "HTTP_COOKIE2",
82
+ "HTTP_HOST", "HTTP_PRAGMA",
83
+ "HTTP_REFERER", "HTTP_USER_AGENT",
84
+ "HTTP_CACHE_CTRL",
85
+ "HTTP_IF_MODIFIED_SINCE", "HTTP_IF_MATCH",
86
+ "HTTP_IF_NONE_MATCH",
87
+ "HTTP_IF_RANGE",
88
+ "HTTP_IF_UNMODIFIED_SINCE",
89
+ "HTTP_KEEPALIVE",
90
+ "HTTP_RANGE",
91
+ "HTTP_X_FORWARDED_FOR",
92
+ "HTTP_VIA",
93
+ "HTTP_TRANSFER_ENCODING"
94
+ };
95
+
96
+ static int CGI_HEADER_LEN[H_TRANSFER_ENCODING+1] =
97
+ { 11, 19, 20, 20, 18, 15, 12, 14, 11, 12, 9, 11, 12, 15, 15,
98
+ 22, 13, 18, 13, 24, 14, 10, 20, 8, 22 };
99
+
100
+ static void lsapi_sigpipe( int sig )
101
+ {
102
+ }
103
+ static void lsapi_siguser1( int sig )
104
+ {
105
+ g_running = 0;
106
+ }
107
+
108
+ #ifndef sighandler_t
109
+ typedef void (*sighandler_t)(int);
110
+ #endif
111
+
112
+ static void lsapi_signal(int signo, sighandler_t handler)
113
+ {
114
+ struct sigaction sa;
115
+
116
+ sigaction(signo, NULL, &sa);
117
+
118
+ if (sa.sa_handler == SIG_DFL)
119
+ {
120
+ sigemptyset(&sa.sa_mask);
121
+ sa.sa_flags = 0;
122
+ sa.sa_handler = handler;
123
+ sigaction(signo, &sa, NULL);
124
+ }
125
+ }
126
+
127
+
128
+ static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader,
129
+ char type, int len )
130
+ {
131
+ pHeader->m_versionB0 = LSAPI_VERSION_B0; //LSAPI protocol version
132
+ pHeader->m_versionB1 = LSAPI_VERSION_B1;
133
+ pHeader->m_type = type;
134
+ pHeader->m_flag = LSAPI_ENDIAN;
135
+ pHeader->m_packetLen.m_iLen = len;
136
+ }
137
+
138
+ static int lsapi_close( int fd )
139
+ {
140
+ int ret;
141
+ while( 1 )
142
+ {
143
+ ret = close( fd );
144
+ if (( ret == -1 )&&( errno == EINTR )&&(g_running))
145
+ continue;
146
+ return ret;
147
+ }
148
+ }
149
+
150
+ static inline int lsapi_read( int fd, void * pBuf, int len )
151
+ {
152
+ int ret;
153
+ while( 1 )
154
+ {
155
+ ret = read( fd, (char *)pBuf, len );
156
+ if (( ret == -1 )&&( errno == EINTR )&&(g_running))
157
+ continue;
158
+ return ret;
159
+ }
160
+ }
161
+
162
+ //static int lsapi_write( int fd, const void * pBuf, int len )
163
+ //{
164
+ // int ret;
165
+ // const char * pCur;
166
+ // const char * pEnd;
167
+ // if ( len == 0 )
168
+ // return 0;
169
+ // pCur = (const char *)pBuf;
170
+ // pEnd = pCur + len;
171
+ // while( g_running && (pCur < pEnd) )
172
+ // {
173
+ // ret = write( fd, pCur, pEnd - pCur );
174
+ // if ( ret >= 0)
175
+ // pCur += ret;
176
+ // else if (( ret == -1 )&&( errno != EINTR ))
177
+ // return ret;
178
+ // }
179
+ // return pCur - (const char *)pBuf;
180
+ //}
181
+
182
+ static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen )
183
+ {
184
+ int ret;
185
+ int left = totalLen;
186
+ int n = count;
187
+ while(( left > 0 )&&g_running )
188
+ {
189
+ ret = writev( fd, *pVec, n );
190
+ if ( ret > 0 )
191
+ {
192
+ left -= ret;
193
+ if (( left <= 0)||( !g_running ))
194
+ return totalLen - left;
195
+ while( ret > 0 )
196
+ {
197
+ if ( (*pVec)->iov_len <= ret )
198
+ {
199
+ ret -= (*pVec)->iov_len;
200
+ ++(*pVec);
201
+ }
202
+ else
203
+ {
204
+ (*pVec)->iov_base = (char *)(*pVec)->iov_base + ret;
205
+ (*pVec)->iov_len -= ret;
206
+ break;
207
+ }
208
+ }
209
+ }
210
+ else if (( ret == -1 )&&( errno != EINTR ))
211
+ return ret;
212
+ }
213
+ return totalLen - left;
214
+ }
215
+
216
+ //static int getTotalLen( struct iovec * pVec, int count )
217
+ //{
218
+ // struct iovec * pEnd = pVec + count;
219
+ // int total = 0;
220
+ // while( pVec < pEnd )
221
+ // {
222
+ // total += pVec->iov_len;
223
+ // ++pVec;
224
+ // }
225
+ // return total;
226
+ //}
227
+
228
+
229
+ static inline int allocateBuf( LSAPI_Request * pReq, int size )
230
+ {
231
+ char * pBuf = (char *)realloc( pReq->m_pReqBuf, size );
232
+ if ( pBuf )
233
+ {
234
+ pReq->m_pReqBuf = pBuf;
235
+ pReq->m_reqBufSize = size;
236
+ pReq->m_pHeader = (struct lsapi_req_header *)pReq->m_pReqBuf;
237
+ return 0;
238
+ }
239
+ return -1;
240
+ }
241
+
242
+
243
+ static int allocateIovec( LSAPI_Request * pReq, int n )
244
+ {
245
+ struct iovec * p = (struct iovec *)realloc(
246
+ pReq->m_pIovec, sizeof(struct iovec) * n );
247
+ if ( !p )
248
+ return -1;
249
+ pReq->m_pIovecToWrite = p + ( pReq->m_pIovecToWrite - pReq->m_pIovec );
250
+ pReq->m_pIovecCur = p + ( pReq->m_pIovecCur - pReq->m_pIovec );
251
+ pReq->m_pIovec = p;
252
+ pReq->m_pIovecEnd = p + n;
253
+ return 0;
254
+ }
255
+
256
+ static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size )
257
+ {
258
+ char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size );
259
+ if ( !p )
260
+ return -1;
261
+ pReq->m_pRespHeaderBufPos = p + ( pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf );
262
+ pReq->m_pRespHeaderBuf = p;
263
+ pReq->m_pRespHeaderBufEnd = p + size;
264
+ return 0;
265
+ }
266
+
267
+
268
+ static inline int verifyHeader( struct lsapi_packet_header * pHeader, char pktType )
269
+ {
270
+ if (( LSAPI_VERSION_B0 != pHeader->m_versionB0 )||
271
+ ( LSAPI_VERSION_B1 != pHeader->m_versionB1 )||
272
+ ( pktType != pHeader->m_type ))
273
+ return -1;
274
+ if ( LSAPI_ENDIAN != (pHeader->m_flag & LSAPI_ENDIAN_BIT ))
275
+ {
276
+ register char b;
277
+ b = pHeader->m_packetLen.m_bytes[0];
278
+ pHeader->m_packetLen.m_bytes[0] = pHeader->m_packetLen.m_bytes[3];
279
+ pHeader->m_packetLen.m_bytes[3] = b;
280
+ b = pHeader->m_packetLen.m_bytes[1];
281
+ pHeader->m_packetLen.m_bytes[1] = pHeader->m_packetLen.m_bytes[2];
282
+ pHeader->m_packetLen.m_bytes[2] = b;
283
+ }
284
+ return pHeader->m_packetLen.m_iLen;
285
+ }
286
+
287
+ static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList,
288
+ int *curSize, int newSize )
289
+ {
290
+ struct LSAPI_key_value_pair * pBuf;
291
+ if ( *curSize >= newSize )
292
+ return 0;
293
+ if ( newSize > 8192 )
294
+ return -1;
295
+ pBuf = (struct LSAPI_key_value_pair *)realloc( *pEnvList, newSize *
296
+ sizeof(struct LSAPI_key_value_pair) );
297
+ if ( pBuf )
298
+ {
299
+ *pEnvList = pBuf;
300
+ *curSize = newSize;
301
+ return 0;
302
+ }
303
+ else
304
+ return -1;
305
+
306
+ }
307
+
308
+ static inline int isPipe( int fd )
309
+ {
310
+ char achPeer[128];
311
+ socklen_t len = 128;
312
+ if (( getpeername( fd, (struct sockaddr *)achPeer, &len ) != 0 )&&
313
+ ( errno == ENOTCONN ))
314
+ return 0;
315
+ else
316
+ return 1;
317
+ }
318
+
319
+ static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count,
320
+ char **pBegin, char * pEnd )
321
+ {
322
+ struct LSAPI_key_value_pair * pEnvEnd;
323
+ int keyLen = 0, valLen = 0;
324
+ if ( count > 8192 )
325
+ return -1;
326
+ pEnvEnd = pEnvList + count;
327
+ while( pEnvList != pEnvEnd )
328
+ {
329
+ if ( pEnd - *pBegin < 4 )
330
+ return -1;
331
+ keyLen = *((unsigned char *)((*pBegin)++));
332
+ keyLen = (keyLen << 8) + *((unsigned char *)((*pBegin)++));
333
+ valLen = *((unsigned char *)((*pBegin)++));
334
+ valLen = (valLen << 8) + *((unsigned char *)((*pBegin)++));
335
+ if ( *pBegin + keyLen + valLen > pEnd )
336
+ return -1;
337
+ if (( !keyLen )||( !valLen ))
338
+ return -1;
339
+
340
+ pEnvList->pKey = *pBegin;
341
+ *pBegin += keyLen;
342
+ pEnvList->pValue = *pBegin;
343
+ *pBegin += valLen;
344
+
345
+ pEnvList->keyLen = keyLen - 1;
346
+ pEnvList->valLen = valLen - 1;
347
+ ++pEnvList;
348
+ }
349
+ if ( memcmp( *pBegin, "\0\0\0\0", 4 ) != 0 )
350
+ return -1;
351
+ *pBegin += 4;
352
+ return 0;
353
+ }
354
+
355
+ static inline void swapIntEndian( int * pInteger )
356
+ {
357
+ char * p = (char *)pInteger;
358
+ register char b;
359
+ b = p[0];
360
+ p[0] = p[3];
361
+ p[3] = b;
362
+ b = p[1];
363
+ p[1] = p[2];
364
+ p[2] = b;
365
+
366
+ }
367
+
368
+ static inline void fixEndian( LSAPI_Request * pReq )
369
+ {
370
+ struct lsapi_req_header *p= pReq->m_pHeader;
371
+ swapIntEndian( &p->m_httpHeaderLen );
372
+ swapIntEndian( &p->m_reqBodyLen );
373
+ swapIntEndian( &p->m_scriptFileOff );
374
+ swapIntEndian( &p->m_scriptNameOff );
375
+ swapIntEndian( &p->m_queryStringOff );
376
+ swapIntEndian( &p->m_requestMethodOff );
377
+ swapIntEndian( &p->m_cntUnknownHeaders );
378
+ swapIntEndian( &p->m_cntEnv );
379
+ swapIntEndian( &p->m_cntSpecialEnv );
380
+ }
381
+
382
+ static void fixHeaderIndexEndian( LSAPI_Request * pReq )
383
+ {
384
+ int i;
385
+ for( i = 0; i < H_TRANSFER_ENCODING; ++i )
386
+ {
387
+ if ( pReq->m_pHeaderIndex->m_headerOff[i] )
388
+ {
389
+ register char b;
390
+ char * p = (char *)(&pReq->m_pHeaderIndex->m_headerLen[i]);
391
+ b = p[0];
392
+ p[0] = p[1];
393
+ p[1] = b;
394
+ swapIntEndian( &pReq->m_pHeaderIndex->m_headerOff[i] );
395
+ }
396
+ }
397
+ if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
398
+ {
399
+ struct lsapi_header_offset * pCur, *pEnd;
400
+ pCur = pReq->m_pUnknownHeader;
401
+ pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
402
+ while( pCur < pEnd )
403
+ {
404
+ swapIntEndian( &pCur->nameOff );
405
+ swapIntEndian( &pCur->nameLen );
406
+ swapIntEndian( &pCur->valueOff );
407
+ swapIntEndian( &pCur->valueLen );
408
+ ++pCur;
409
+ }
410
+ }
411
+ }
412
+
413
+ static int parseRequest( LSAPI_Request * pReq, int totalLen )
414
+ {
415
+ int shouldFixEndian;
416
+ char * pBegin = pReq->m_pReqBuf + sizeof( struct lsapi_req_header );
417
+ char * pEnd = pReq->m_pReqBuf + totalLen;
418
+ shouldFixEndian = ( LSAPI_ENDIAN != (
419
+ pReq->m_pHeader->m_pktHeader.m_flag & LSAPI_ENDIAN_BIT ) );
420
+ if ( shouldFixEndian )
421
+ {
422
+ fixEndian( pReq );
423
+ }
424
+ if ( (pReq->m_specialEnvListSize < pReq->m_pHeader->m_cntSpecialEnv )&&
425
+ allocateEnvList( &pReq->m_pSpecialEnvList,
426
+ &pReq->m_specialEnvListSize,
427
+ pReq->m_pHeader->m_cntSpecialEnv ) == -1 )
428
+ return -1;
429
+ if ( (pReq->m_envListSize < pReq->m_pHeader->m_cntEnv )&&
430
+ allocateEnvList( &pReq->m_pEnvList, &pReq->m_envListSize,
431
+ pReq->m_pHeader->m_cntEnv ) == -1 )
432
+ return -1;
433
+
434
+ if ( parseEnv( pReq->m_pSpecialEnvList,
435
+ pReq->m_pHeader->m_cntSpecialEnv,
436
+ &pBegin, pEnd ) == -1 )
437
+ return -1;
438
+ if ( parseEnv( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
439
+ &pBegin, pEnd ) == -1 )
440
+ return -1;
441
+
442
+ pReq->m_pScriptFile = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptFileOff;
443
+ pReq->m_pScriptName = pReq->m_pReqBuf + pReq->m_pHeader->m_scriptNameOff;
444
+ pReq->m_pQueryString = pReq->m_pReqBuf + pReq->m_pHeader->m_queryStringOff;
445
+ pReq->m_pRequestMethod = pReq->m_pReqBuf + pReq->m_pHeader->m_requestMethodOff;
446
+
447
+ pBegin = pReq->m_pReqBuf + (( pBegin - pReq->m_pReqBuf + 7 ) & (~0x7));
448
+ pReq->m_pHeaderIndex = ( struct lsapi_http_header_index * )pBegin;
449
+ pBegin += sizeof( struct lsapi_http_header_index );
450
+
451
+ pReq->m_pUnknownHeader = (struct lsapi_header_offset *)pBegin;
452
+ pBegin += sizeof( struct lsapi_header_offset) *
453
+ pReq->m_pHeader->m_cntUnknownHeaders;
454
+
455
+ pReq->m_pHttpHeader = pBegin;
456
+ pBegin += pReq->m_pHeader->m_httpHeaderLen;
457
+ if ( pBegin != pEnd )
458
+ return -1;
459
+
460
+ if ( shouldFixEndian )
461
+ {
462
+ fixHeaderIndexEndian( pReq );
463
+ }
464
+
465
+ return 0;
466
+ }
467
+
468
+ static struct lsapi_packet_header ack = {'L', 'S',
469
+ LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
470
+ static inline int notify_req_received( LSAPI_Request * pReq )
471
+ {
472
+ if ( write( pReq->m_fd, &ack, LSAPI_PACKET_HEADER_LEN )
473
+ < LSAPI_PACKET_HEADER_LEN )
474
+ return -1;
475
+ return 0;
476
+ }
477
+
478
+
479
+ static int readReq( LSAPI_Request * pReq )
480
+ {
481
+ int len;
482
+ int packetLen;
483
+ if ( !pReq )
484
+ return -1;
485
+ if ( pReq->m_reqBufSize < 8192 )
486
+ {
487
+ if ( allocateBuf( pReq, 8192 ) == -1 )
488
+ return -1;
489
+ }
490
+
491
+ while ( pReq->m_bufRead < LSAPI_PACKET_HEADER_LEN )
492
+ {
493
+ len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf, pReq->m_reqBufSize );
494
+ if ( len <= 0 )
495
+ return -1;
496
+ pReq->m_bufRead += len;
497
+ }
498
+ pReq->m_reqState = LSAPI_ST_REQ_HEADER;
499
+
500
+ packetLen = verifyHeader( &pReq->m_pHeader->m_pktHeader, LSAPI_BEGIN_REQUEST );
501
+ if ( packetLen < 0 )
502
+ return -1;
503
+ if ( packetLen > LSAPI_MAX_HEADER_LEN )
504
+ return -1;
505
+
506
+ if ( packetLen > pReq->m_reqBufSize )
507
+ {
508
+ if ( allocateBuf( pReq, packetLen ) == -1 )
509
+ return -1;
510
+ }
511
+ while( packetLen > pReq->m_bufRead )
512
+ {
513
+ len = lsapi_read( pReq->m_fd, pReq->m_pReqBuf + pReq->m_bufRead, packetLen - pReq->m_bufRead );
514
+ if ( len <= 0 )
515
+ return -1;
516
+ pReq->m_bufRead += len;
517
+ }
518
+ if ( parseRequest( pReq, packetLen ) < 0 )
519
+ return -1;
520
+ pReq->m_bufProcessed = packetLen;
521
+ pReq->m_reqState = LSAPI_ST_REQ_BODY | LSAPI_ST_RESP_HEADER;
522
+
523
+ return notify_req_received( pReq );
524
+ }
525
+
526
+
527
+
528
+ int LSAPI_Init(void)
529
+ {
530
+ if ( !g_inited )
531
+ {
532
+ lsapi_signal(SIGPIPE, lsapi_sigpipe);
533
+ lsapi_signal(SIGUSR1, lsapi_siguser1);
534
+
535
+ if ( LSAPI_InitRequest( &g_req, LSAPI_SOCK_FILENO ) == -1 )
536
+ return -1;
537
+ g_inited = 1;
538
+ }
539
+ return 0;
540
+ }
541
+
542
+ void LSAPI_stop(void)
543
+ {
544
+ g_running = 0;
545
+ }
546
+
547
+ int LSAPI_InitRequest( LSAPI_Request * pReq, int fd )
548
+ {
549
+ if ( !pReq )
550
+ return -1;
551
+ memset( pReq, 0, sizeof( LSAPI_Request ) );
552
+ if ( allocateIovec( pReq, 16 ) == -1 )
553
+ return -1;
554
+ pReq->m_pRespBuf = pReq->m_pRespBufPos = (char *)malloc( LSAPI_RESP_BUF_SIZE );
555
+ if ( !pReq->m_pRespBuf )
556
+ return -1;
557
+ pReq->m_pRespBufEnd = pReq->m_pRespBuf + LSAPI_RESP_BUF_SIZE;
558
+ pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
559
+ pReq->m_respPktHeaderEnd = &pReq->m_respPktHeader[5];
560
+ if ( allocateRespHeaderBuf( pReq, LSAPI_INIT_RESP_HEADER_LEN ) == -1 )
561
+ return -1;
562
+
563
+ if ( isPipe( fd ) )
564
+ {
565
+ pReq->m_fdListen = -1;
566
+ pReq->m_fd = fd;
567
+ }
568
+ else
569
+ {
570
+ pReq->m_fdListen = fd;
571
+ pReq->m_fd = -1;
572
+ }
573
+ return 0;
574
+ }
575
+
576
+ int LSAPI_Is_Listen( void )
577
+ {
578
+ return LSAPI_Is_Listen_r( &g_req );
579
+ }
580
+
581
+ int LSAPI_Is_Listen_r( LSAPI_Request * pReq)
582
+ {
583
+ return pReq->m_fdListen != -1;
584
+ }
585
+
586
+
587
+
588
+ int LSAPI_Accept_r( LSAPI_Request * pReq )
589
+ {
590
+ char achPeer[128];
591
+ socklen_t len;
592
+ int nodelay = 1;
593
+
594
+ if ( !pReq )
595
+ return -1;
596
+ if ( LSAPI_Finish_r( pReq ) == -1 )
597
+ return -1;
598
+ while( g_running )
599
+ {
600
+ if ( pReq->m_fd == -1 )
601
+ {
602
+ if ( pReq->m_fdListen != -1)
603
+ {
604
+ len = sizeof( achPeer );
605
+ pReq->m_fd = accept( pReq->m_fdListen,
606
+ (struct sockaddr *)&achPeer, &len );
607
+ if ( pReq->m_fd == -1 )
608
+ {
609
+ if (( errno == EINTR )||( errno == EAGAIN))
610
+ continue;
611
+ else
612
+ return -1;
613
+ }
614
+ else if (((struct sockaddr *)&achPeer)->sa_family == AF_INET )
615
+ {
616
+ setsockopt(pReq->m_fd, IPPROTO_TCP, TCP_NODELAY,
617
+ (char *)&nodelay, sizeof(nodelay));
618
+ }
619
+ }
620
+ else
621
+ return -1;
622
+ }
623
+ if ( !readReq( pReq ) )
624
+ break;
625
+ lsapi_close( pReq->m_fd );
626
+ pReq->m_fd = -1;
627
+ LSAPI_Reset_r( pReq );
628
+ }
629
+ return 0;
630
+ }
631
+
632
+ static struct lsapi_packet_header finish = {'L', 'S',
633
+ LSAPI_RESP_END, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} };
634
+
635
+ int LSAPI_Finish_r( LSAPI_Request * pReq )
636
+ {
637
+ //finish req body
638
+ if ( !pReq )
639
+ return -1;
640
+ if (pReq->m_reqState)
641
+ {
642
+ if ( pReq->m_fd != -1 )
643
+ {
644
+ if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
645
+ {
646
+ LSAPI_FinalizeRespHeaders_r( pReq );
647
+ }
648
+ if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
649
+ {
650
+ Flush_RespBuf_r( pReq );
651
+ }
652
+
653
+ pReq->m_pIovecCur->iov_base = (void *)&finish;
654
+ pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN;
655
+ pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN;
656
+ ++pReq->m_pIovecCur;
657
+ LSAPI_Flush_r( pReq );
658
+ }
659
+ LSAPI_Reset_r( pReq );
660
+ }
661
+ return 0;
662
+ }
663
+
664
+
665
+ void LSAPI_Reset_r( LSAPI_Request * pReq )
666
+ {
667
+ pReq->m_pRespBufPos = pReq->m_pRespBuf;
668
+ pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec + 1;
669
+ pReq->m_pRespHeaderBufPos = pReq->m_pRespHeaderBuf;
670
+
671
+ memset( &pReq->m_pHeaderIndex, 0,
672
+ (char *)(pReq->m_respHeaderLen) - (char *)&pReq->m_pHeaderIndex );
673
+ }
674
+
675
+
676
+ int LSAPI_Release_r( LSAPI_Request * pReq )
677
+ {
678
+ if ( pReq->m_pReqBuf )
679
+ free( pReq->m_pReqBuf );
680
+ if ( pReq->m_pSpecialEnvList )
681
+ free( pReq->m_pSpecialEnvList );
682
+ if ( pReq->m_pEnvList )
683
+ free( pReq->m_pEnvList );
684
+ if ( pReq->m_pRespHeaderBuf )
685
+ free( pReq->m_pRespHeaderBuf );
686
+ return 0;
687
+ }
688
+
689
+
690
+ char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex )
691
+ {
692
+ int off;
693
+ if ( !pReq || ((unsigned int)headerIndex > H_TRANSFER_ENCODING) )
694
+ return NULL;
695
+ off = pReq->m_pHeaderIndex->m_headerOff[ headerIndex ];
696
+ if ( !off )
697
+ return NULL;
698
+ if ( *(pReq->m_pHttpHeader + off +
699
+ pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) )
700
+ *( pReq->m_pHttpHeader + off +
701
+ pReq->m_pHeaderIndex->m_headerLen[ headerIndex ]) = 0;
702
+ return pReq->m_pHttpHeader + off;
703
+ }
704
+
705
+
706
+ int LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, int bufLen )
707
+ {
708
+ int len;
709
+ int total;
710
+ //char *pOldBuf = pBuf;
711
+ if (!pReq || ( !pBuf )||(bufLen < 0 ))
712
+ return -1;
713
+
714
+ total = pReq->m_pHeader->m_reqBodyLen - pReq->m_reqBodyRead;
715
+
716
+ if ( total <= 0 )
717
+ return 0;
718
+ if ( total < bufLen )
719
+ bufLen = total;
720
+
721
+ total = 0;
722
+ len = pReq->m_bufRead - pReq->m_bufProcessed;
723
+ if ( len > 0 )
724
+ {
725
+ if ( len > bufLen )
726
+ len = bufLen;
727
+ memmove( pBuf, pReq->m_pReqBuf + pReq->m_bufProcessed, len );
728
+ pReq->m_bufProcessed += len;
729
+ total += len;
730
+ pBuf += len;
731
+ bufLen -= len;
732
+ }
733
+ while( bufLen > 0 )
734
+ {
735
+ len = lsapi_read( pReq->m_fd, pBuf, bufLen );
736
+ if ( len > 0 )
737
+ {
738
+ total += len;
739
+ pBuf += len;
740
+ bufLen -= len;
741
+ }
742
+ else if ( len < 0 )
743
+ return -1;
744
+ }
745
+ pReq->m_reqBodyRead += total;
746
+ return total;
747
+
748
+ }
749
+
750
+
751
+ //int LSAPI_Write( const char * pBuf, int len )
752
+ //{
753
+ // return LSAPI_Write_r( &g_req, pBuf, len );
754
+ //}
755
+
756
+ int LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, int len )
757
+ {
758
+ struct lsapi_packet_header * pHeader;
759
+ const char * pEnd;
760
+ const char * p;
761
+ int bufLen;
762
+ int toWrite;
763
+ int packetLen;
764
+
765
+ if ( !pReq || !pBuf )
766
+ return -1;
767
+ if ( len < pReq->m_pRespBufEnd - pReq->m_pRespBufPos )
768
+ {
769
+ memmove( pReq->m_pRespBufPos, pBuf, len );
770
+ pReq->m_pRespBufPos += len;
771
+ return len;
772
+ }
773
+
774
+ if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
775
+ {
776
+ LSAPI_FinalizeRespHeaders_r( pReq );
777
+ }
778
+ pReq->m_reqState |= LSAPI_ST_RESP_BODY;
779
+
780
+ pHeader = pReq->m_respPktHeader;
781
+ p = pBuf;
782
+ pEnd = pBuf + len;
783
+ bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf;
784
+
785
+ while( ( toWrite = pEnd - p ) > 0 )
786
+ {
787
+ packetLen = toWrite + bufLen;
788
+ if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen)
789
+ {
790
+ packetLen = LSAPI_MAX_DATA_PACKET_LEN;
791
+ toWrite = packetLen - bufLen;
792
+ }
793
+
794
+ lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
795
+ packetLen + LSAPI_PACKET_HEADER_LEN );
796
+ pReq->m_totalLen += packetLen + LSAPI_PACKET_HEADER_LEN;
797
+
798
+ pReq->m_pIovecCur->iov_base = (void *)pHeader;
799
+ pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN;
800
+ ++pReq->m_pIovecCur;
801
+ ++pHeader;
802
+ if ( bufLen > 0 )
803
+ {
804
+ pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
805
+ pReq->m_pIovecCur->iov_len = bufLen;
806
+ pReq->m_pRespBufPos = pReq->m_pRespBuf;
807
+ ++pReq->m_pIovecCur;
808
+ bufLen = 0;
809
+ }
810
+
811
+ pReq->m_pIovecCur->iov_base = (void *)p;
812
+ pReq->m_pIovecCur->iov_len = toWrite;
813
+ ++pReq->m_pIovecCur;
814
+ p += toWrite;
815
+
816
+ if ( pHeader >= pReq->m_respPktHeaderEnd - 1)
817
+ {
818
+ if ( LSAPI_Flush_r( pReq ) == -1 )
819
+ return -1;
820
+ pHeader = pReq->m_respPktHeader;
821
+ }
822
+ }
823
+ if ( pHeader != pReq->m_respPktHeader )
824
+ if ( LSAPI_Flush_r( pReq ) == -1 )
825
+ return -1;
826
+ return p - pBuf;
827
+ }
828
+
829
+ void Flush_RespBuf_r( LSAPI_Request * pReq )
830
+ {
831
+ struct lsapi_packet_header * pHeader = pReq->m_respPktHeader;
832
+ int bufLen = pReq->m_pRespBufPos - pReq->m_pRespBuf;
833
+ pReq->m_reqState |= LSAPI_ST_RESP_BODY;
834
+ lsapi_buildPacketHeader( pHeader, LSAPI_RESP_STREAM,
835
+ bufLen + LSAPI_PACKET_HEADER_LEN );
836
+ pReq->m_totalLen += bufLen + LSAPI_PACKET_HEADER_LEN;
837
+
838
+ pReq->m_pIovecCur->iov_base = (void *)pHeader;
839
+ pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN;
840
+ ++pReq->m_pIovecCur;
841
+ ++pHeader;
842
+ if ( bufLen > 0 )
843
+ {
844
+ pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespBuf;
845
+ pReq->m_pIovecCur->iov_len = bufLen;
846
+ pReq->m_pRespBufPos = pReq->m_pRespBuf;
847
+ ++pReq->m_pIovecCur;
848
+ bufLen = 0;
849
+ }
850
+ }
851
+
852
+
853
+
854
+
855
+ int LSAPI_Flush_r( LSAPI_Request * pReq )
856
+ {
857
+ int ret = 0;
858
+ int n;
859
+ if ( !pReq )
860
+ return -1;
861
+ n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
862
+ if (( 0 == n )&&( pReq->m_pRespBufPos == pReq->m_pRespBuf ))
863
+ return 0;
864
+ if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
865
+ {
866
+ LSAPI_FinalizeRespHeaders_r( pReq );
867
+ }
868
+ if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
869
+ {
870
+ Flush_RespBuf_r( pReq );
871
+ }
872
+
873
+ n = pReq->m_pIovecCur - pReq->m_pIovecToWrite;
874
+ if ( n > 0 )
875
+ {
876
+
877
+ ret = lsapi_writev( pReq->m_fd, &pReq->m_pIovecToWrite,
878
+ n, pReq->m_totalLen );
879
+ if ( ret < pReq->m_totalLen )
880
+ {
881
+ lsapi_close( pReq->m_fd );
882
+ pReq->m_fd = -1;
883
+ ret = -1;
884
+ }
885
+ pReq->m_totalLen = 0;
886
+ pReq->m_pIovecCur = pReq->m_pIovecToWrite = pReq->m_pIovec;
887
+ }
888
+ return ret;
889
+ }
890
+
891
+
892
+ int LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, int len )
893
+ {
894
+ struct lsapi_packet_header header;
895
+ const char * pEnd;
896
+ const char * p;
897
+ int packetLen;
898
+ int totalLen;
899
+ int ret;
900
+ struct iovec iov[2];
901
+ struct iovec *pIov;
902
+
903
+ if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
904
+ {
905
+ LSAPI_Flush_r( pReq );
906
+ }
907
+
908
+ p = pBuf;
909
+ pEnd = pBuf + len;
910
+
911
+ while( ( packetLen = pEnd - p ) > 0 )
912
+ {
913
+ if ( LSAPI_MAX_DATA_PACKET_LEN < packetLen)
914
+ {
915
+ packetLen = LSAPI_MAX_DATA_PACKET_LEN;
916
+ }
917
+
918
+ lsapi_buildPacketHeader( &header, LSAPI_STDERR_STREAM,
919
+ packetLen + LSAPI_PACKET_HEADER_LEN );
920
+ totalLen = packetLen + LSAPI_PACKET_HEADER_LEN;
921
+
922
+ iov[0].iov_base = (void *)&header;
923
+ iov[0].iov_len = LSAPI_PACKET_HEADER_LEN;
924
+
925
+ iov[1].iov_base = (void *)p;
926
+ iov[1].iov_len = packetLen;
927
+ p += packetLen;
928
+ pIov = iov;
929
+ ret = lsapi_writev( pReq->m_fd, &pIov,
930
+ 2, totalLen );
931
+ if ( ret < totalLen )
932
+ {
933
+ lsapi_close( pReq->m_fd );
934
+ pReq->m_fd = -1;
935
+ ret = -1;
936
+ }
937
+ }
938
+ return p - pBuf;
939
+ }
940
+
941
+ static char * GetHeaderVar( LSAPI_Request * pReq, const char * name )
942
+ {
943
+ int i;
944
+ for( i = 0; i < H_TRANSFER_ENCODING; ++i )
945
+ {
946
+ if ( pReq->m_pHeaderIndex->m_headerOff[i] )
947
+ {
948
+ if ( strcmp( name, CGI_HEADERS[i] ) == 0 )
949
+ return pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
950
+ }
951
+ }
952
+ if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
953
+ {
954
+ const char *p;
955
+ char *pKey;
956
+ char *pKeyEnd ;
957
+ int keyLen;
958
+ struct lsapi_header_offset * pCur, *pEnd;
959
+ pCur = pReq->m_pUnknownHeader;
960
+ pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
961
+ while( pCur < pEnd )
962
+ {
963
+ pKey = pReq->m_pHttpHeader + pCur->nameOff;
964
+ keyLen = pCur->nameLen;
965
+ pKeyEnd = pKey + keyLen;
966
+ p = &name[5];
967
+
968
+ while(( pKey < pKeyEnd )&&( *p ))
969
+ {
970
+ char ch = toupper( *pKey );
971
+ if ((ch != *p )||(( *p == '_' )&&( ch != '-')))
972
+ break;
973
+ ++p; ++pKey;
974
+ }
975
+ if (( pKey == pKeyEnd )&& (!*p ))
976
+ return pReq->m_pHttpHeader + pCur->valueOff;
977
+ ++pCur;
978
+ }
979
+ }
980
+ return NULL;
981
+ }
982
+
983
+
984
+ char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name )
985
+ {
986
+ struct LSAPI_key_value_pair * pBegin = pReq->m_pEnvList;
987
+ struct LSAPI_key_value_pair * pEnd = pBegin + pReq->m_pHeader->m_cntEnv;
988
+ if ( !pReq || !name )
989
+ return NULL;
990
+ if ( strncmp( name, "HTTP_", 5 ) == 0 )
991
+ {
992
+ return GetHeaderVar( pReq, name );
993
+ }
994
+ while( pBegin < pEnd )
995
+ {
996
+ if ( strcmp( name, pBegin->pKey ) == 0 )
997
+ return pBegin->pValue;
998
+ ++pBegin;
999
+ }
1000
+ return NULL;
1001
+ }
1002
+
1003
+
1004
+ int LSAPI_ForeachHeader_r( LSAPI_Request * pReq,
1005
+ LSAPI_CB_EnvHandler fn, void * arg )
1006
+ {
1007
+ int i;
1008
+ int len = 0;
1009
+ char * pValue;
1010
+ int ret;
1011
+ int count = 0;
1012
+ if ( !pReq || !fn )
1013
+ return -1;
1014
+ for( i = 0; i < H_TRANSFER_ENCODING; ++i )
1015
+ {
1016
+ if ( pReq->m_pHeaderIndex->m_headerOff[i] )
1017
+ {
1018
+ len = pReq->m_pHeaderIndex->m_headerLen[i];
1019
+ pValue = pReq->m_pHttpHeader + pReq->m_pHeaderIndex->m_headerOff[i];
1020
+ *(pValue + len ) = 0;
1021
+ ret = (*fn)( CGI_HEADERS[i], CGI_HEADER_LEN[i],
1022
+ pValue, len, arg );
1023
+ ++count;
1024
+ if ( ret <= 0 )
1025
+ return ret;
1026
+ }
1027
+ }
1028
+ if ( pReq->m_pHeader->m_cntUnknownHeaders > 0 )
1029
+ {
1030
+ char achHeaderName[256];
1031
+ char *p;
1032
+ char *pKey;
1033
+ char *pKeyEnd ;
1034
+ int keyLen;
1035
+ struct lsapi_header_offset * pCur, *pEnd;
1036
+ pCur = pReq->m_pUnknownHeader;
1037
+ pEnd = pCur + pReq->m_pHeader->m_cntUnknownHeaders;
1038
+ while( pCur < pEnd )
1039
+ {
1040
+ pKey = pReq->m_pHttpHeader + pCur->nameOff;
1041
+ keyLen = pCur->nameLen;
1042
+ pKeyEnd = pKey + keyLen;
1043
+ memcpy( achHeaderName, "HTTP_", 5 );
1044
+ p = &achHeaderName[5];
1045
+ if ( keyLen > 250 )
1046
+ keyLen = 250;
1047
+
1048
+ while( pKey < pKeyEnd )
1049
+ {
1050
+ char ch = *pKey++;
1051
+ if ( ch == '-' )
1052
+ *p++ = '_';
1053
+ else
1054
+ *p++ = toupper( ch );
1055
+ }
1056
+ *p = 0;
1057
+ keyLen += 5;
1058
+
1059
+ pValue = pReq->m_pHttpHeader + pCur->valueOff;
1060
+ *(pValue + pCur->valueLen ) = 0;
1061
+ ret = (*fn)( achHeaderName, pCur->valueLen,
1062
+ pValue, len, arg );
1063
+ if ( ret <= 0 )
1064
+ return ret;
1065
+ ++pCur;
1066
+ }
1067
+ }
1068
+ return count + pReq->m_pHeader->m_cntUnknownHeaders;
1069
+
1070
+ }
1071
+
1072
+ static int EnvForeach( struct LSAPI_key_value_pair * pEnv,
1073
+ int n, LSAPI_CB_EnvHandler fn, void * arg )
1074
+ {
1075
+ struct LSAPI_key_value_pair * pEnd = pEnv + n;
1076
+ int ret;
1077
+ if ( !pEnv || !fn )
1078
+ return -1;
1079
+ while( pEnv < pEnd )
1080
+ {
1081
+ ret = (*fn)( pEnv->pKey, pEnv->keyLen,
1082
+ pEnv->pValue, pEnv->valLen, arg );
1083
+ if ( ret <= 0 )
1084
+ return ret;
1085
+ ++pEnv;
1086
+ }
1087
+ return n;
1088
+ }
1089
+
1090
+
1091
+
1092
+ int LSAPI_ForeachEnv_r( LSAPI_Request * pReq,
1093
+ LSAPI_CB_EnvHandler fn, void * arg )
1094
+ {
1095
+ if ( !pReq || !fn )
1096
+ return -1;
1097
+ if ( pReq->m_pHeader->m_cntEnv > 0 )
1098
+ {
1099
+ return EnvForeach( pReq->m_pEnvList, pReq->m_pHeader->m_cntEnv,
1100
+ fn, arg );
1101
+ }
1102
+ return 0;
1103
+ }
1104
+
1105
+
1106
+
1107
+ int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq,
1108
+ LSAPI_CB_EnvHandler fn, void * arg )
1109
+ {
1110
+ if ( !pReq || !fn )
1111
+ return -1;
1112
+ if ( pReq->m_pHeader->m_cntSpecialEnv > 0 )
1113
+ {
1114
+ return EnvForeach( pReq->m_pSpecialEnvList,
1115
+ pReq->m_pHeader->m_cntSpecialEnv,
1116
+ fn, arg );
1117
+ }
1118
+ return 0;
1119
+
1120
+ }
1121
+
1122
+
1123
+
1124
+ int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq )
1125
+ {
1126
+ if ( !pReq || !pReq->m_pIovec )
1127
+ return -1;
1128
+ if ( !( pReq->m_reqState & LSAPI_ST_RESP_HEADER ) )
1129
+ return 0;
1130
+ pReq->m_reqState &= ~LSAPI_ST_RESP_HEADER;
1131
+ if ( pReq->m_pRespHeaderBufPos > pReq->m_pRespHeaderBuf )
1132
+ {
1133
+ pReq->m_pIovecCur->iov_base = (void *)pReq->m_pRespHeaderBuf;
1134
+ pReq->m_pIovecCur->iov_len = pReq->m_pRespHeaderBufPos - pReq->m_pRespHeaderBuf;
1135
+ pReq->m_totalLen += pReq->m_pIovecCur->iov_len;
1136
+ ++pReq->m_pIovecCur;
1137
+ }
1138
+
1139
+ pReq->m_pIovec->iov_len = sizeof( struct lsapi_resp_header)
1140
+ + pReq->m_respHeader.m_respInfo.m_cntHeaders * sizeof( short );
1141
+ pReq->m_totalLen += pReq->m_pIovec->iov_len;
1142
+
1143
+ lsapi_buildPacketHeader( &pReq->m_respHeader.m_pktHeader,
1144
+ LSAPI_RESP_HEADER, pReq->m_totalLen );
1145
+ pReq->m_pIovec->iov_base = (void *)&pReq->m_respHeader;
1146
+ pReq->m_pIovecToWrite = pReq->m_pIovec;
1147
+ return 0;
1148
+ }
1149
+
1150
+
1151
+
1152
+
1153
+ int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, char * pBuf, int len )
1154
+ {
1155
+ if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX )
1156
+ return -1;
1157
+ if ( pReq->m_reqState & LSAPI_ST_RESP_BODY )
1158
+ return -1;
1159
+ if ( pReq->m_respHeader.m_respInfo.m_cntHeaders >= LSAPI_MAX_RESP_HEADERS )
1160
+ return -1;
1161
+ if ( pReq->m_pRespHeaderBufPos + len + 1 > pReq->m_pRespHeaderBufEnd )
1162
+ {
1163
+ int newlen = pReq->m_pRespHeaderBufPos + len + 4096 - pReq->m_pRespHeaderBuf;
1164
+ newlen -= newlen % 4096;
1165
+ if ( allocateRespHeaderBuf( pReq, newlen ) == -1 )
1166
+ return -1;
1167
+ }
1168
+ memmove( pReq->m_pRespHeaderBufPos, pBuf, len );
1169
+ pReq->m_pRespHeaderBufPos += len;
1170
+ *pReq->m_pRespHeaderBufPos++ = 0;
1171
+ ++len; //add one byte padding for \0
1172
+ pReq->m_respHeaderLen[pReq->m_respHeader.m_respInfo.m_cntHeaders] = len;
1173
+ ++pReq->m_respHeader.m_respInfo.m_cntHeaders;
1174
+ return 0;
1175
+ }
1176
+
1177
+
1178
+
1179
+
1180
+
1181
+