ruby-lsapi 1.3

Sign up to get free protection for your applications and to get access to all the features.
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
+