bossan 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ZjFiOTYwNTUwMTUwNGFkYmJjOWQwYzdiMjA3NzVlOGI0NDhkNjMxNg==
5
- data.tar.gz: !binary |-
6
- ODU1NGExMjUxYzVmOTQ2NDE3Y2U3ZDg1YzMwNzY0OTliYjE4ZjU1OA==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- OTUxMWUwMGIxYmM0ZWUwODNjYzNlMTVlYjk5MmE2YTJjMmQ0YzMxMmQ1N2Uz
10
- NjM5ZjA3MmE4NTAzM2JmNjNmZWQxYjY5MTdiYWMxZjUzYzE5NGNkODRhODlm
11
- NzhlZjVkNDAwYjhkMDE2MTRiNzdiMzJmMWRkMGVhMjY1YzMwMDM=
12
- data.tar.gz: !binary |-
13
- ZjNhZjE4ZDgxZmNmOWQ5M2UyMWVjOTI3OGZiNWU1ZmUyYzg1ZGMxMzQ4OWRk
14
- ODg4OGE1YWQ1YzU0YmE3Y2FhOTkxZWNhY2YxYzcxYTAzYjFiNTA1NTMwNDYw
15
- MTU5YTk5MWQ3Y2ZiNzUwOGFlMzRjM2I5NzgyY2FlYjBjMmVmZDg=
2
+ SHA1:
3
+ metadata.gz: a6c9a88db061e6810d579b2bbd96d1883353e0dc
4
+ data.tar.gz: 2b24f8d88a989cf4f6bb388297f7aca5d79d93bf
5
+ SHA512:
6
+ metadata.gz: dbe2c03e817dae7af733fbd451e211a5ec04288a4a472c4cc3782844145f344640c9f6752ca594c5be7aa285fe96c5072c37818c3dabc62c04f59e2975fec600
7
+ data.tar.gz: 825ce88118370976ef9ca6c3f1161ee402a3c3fcf2e5faa6d2b513285f84f35da6bf708a49e4b433abaf954d2209049351a2393ee42a06f3a9a494ebdb8c164f
@@ -1,4 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 1.9.2
4
- - 1.9.3
4
+ - 1.9.3
5
+ - 2.0.0
@@ -1,5 +1,21 @@
1
1
  # CHANGELOG
2
2
 
3
+ ### v0.4.0
4
+
5
+ (New Feature release. release 2013-0X-XX)
6
+
7
+ * Support RFC2616(HTTP/1.1)
8
+
9
+ * fix reason phrase
10
+
11
+ ### v0.3.0
12
+
13
+ (New Feature release. release 2013-06-28)
14
+
15
+ * Add Bossan.listen method, for supporting pre-fork server
16
+
17
+ * change API Bossan.run
18
+
3
19
  ### v0.2.0
4
20
 
5
21
  (New Feature release. release 2013-05-22)
data/README.md CHANGED
@@ -31,14 +31,16 @@ simple rack app:
31
31
  ``` ruby
32
32
  require 'bossan'
33
33
 
34
- Bossan.run('127.0.0.1', 8000, proc {|env|
34
+ Bossan.listen('127.0.0.1', 8000)
35
+ Bossan.run(proc {|env|
36
+ body = ['hello, world!'] # Response body
35
37
  [
36
38
  200, # Status code
37
39
  { # Response headers
38
40
  'Content-Type' => 'text/html',
39
- 'Content-Length' => '13',
41
+ 'Content-Length' => body.join.size.to_s,
40
42
  },
41
- ['hello, world!'] # Response body
43
+ body
42
44
  ]
43
45
  })
44
46
  ```
@@ -13,6 +13,6 @@ app = ->(env){
13
13
 
14
14
  Bossan.set_keepalive(10)
15
15
  Bossan.listen('localhost', 8000)
16
- workers = Parallel.each([0,1,2,3]) {|i|
16
+ Parallel.each([0,1,2,3]) {
17
17
  Bossan.run(app)
18
18
  }
@@ -1,14 +1,14 @@
1
1
  require_relative '../lib/bossan'
2
2
 
3
3
  Bossan.listen('127.0.0.1', 8000)
4
- Bossn.run(proc {|env|
5
- body = 'hello, world!'
6
- [
7
- 200, # Status code
8
- { # Response headers
9
- 'Content-Type' => 'text/html',
10
- 'Content-Length' => body.size.to_s,
11
- },
12
- [body] # Response body
13
- ]
14
- })
4
+ Bossan.run(proc {|env|
5
+ body = ['hello, world!']
6
+ [
7
+ 200, # Status code
8
+ { # Response headers
9
+ 'Content-Type' => 'text/html',
10
+ 'Content-Length' => body.join.size.to_s,
11
+ },
12
+ body # Response body
13
+ ]
14
+ })
@@ -4,9 +4,6 @@ require 'tempfile'
4
4
 
5
5
 
6
6
  def view_file req
7
- # p req
8
- # p req.env['rack.input']
9
-
10
7
  tempfile = Tempfile.new('raw-upload.')
11
8
  req.env['rack.input'].each do |chunk|
12
9
  if chunk.respond_to?(:force_encoding)
@@ -21,11 +18,10 @@ def view_file req
21
18
  tempfile.flush
22
19
  tempfile.rewind
23
20
 
24
- # return Rack::File.new(tempfile)
25
- return Rack::Multipart::UploadedFile.new(tempfile, req.content_type, true)
26
- # return Rack::Response.new(req.env["rack.input"],
27
- # 200,
28
- # {"Content-Type" => req.content_type})
21
+ return Rack::Response.new(tempfile,
22
+ 200,
23
+ { "Content-Length" => req.env["CONTENT_LENGTH"],
24
+ "Content-Type" => 'image/jpeg'})
29
25
  end
30
26
 
31
27
 
@@ -38,7 +34,7 @@ def upload_file req
38
34
  EOF
39
35
  ],
40
36
  200,
41
- ).to_a
37
+ )
42
38
  end
43
39
 
44
40
 
@@ -55,5 +51,5 @@ app = ->(env) {
55
51
 
56
52
 
57
53
  Bossan.set_max_content_length(1024 * 1024 * 1024)
58
- Bossan.run('localhost', 8000)
59
- Bossan.listen(app)
54
+ Bossan.listen('localhost', 8000)
55
+ Bossan.run(app)
@@ -3,8 +3,9 @@
3
3
 
4
4
  #include "ruby.h"
5
5
  #include <assert.h>
6
- #include <fcntl.h>
7
- #include <stddef.h>
6
+ #include <fcntl.h>
7
+ #include <stddef.h>
8
+ #include <stdlib.h>
8
9
  #include <unistd.h>
9
10
  #include <errno.h>
10
11
  #include <arpa/inet.h>
@@ -26,36 +27,36 @@
26
27
  /* #define DEVELOP */
27
28
 
28
29
  #ifdef DEVELOP
29
- #define DEBUG(...) \
30
- do { \
31
- printf("%-40s %-26s%4u: ", __FILE__, __func__, __LINE__); \
32
- printf(__VA_ARGS__); \
33
- printf("\n"); \
34
- } while(0)
35
- #define RDEBUG(...) \
36
- do { \
37
- printf("\x1B[31m%-40s %-26s%4u: ", __FILE__, __func__, __LINE__); \
38
- printf(__VA_ARGS__); \
39
- printf("\x1B[0m\n"); \
40
- } while(0)
41
- #define GDEBUG(...) \
42
- do { \
43
- printf("\x1B[32m%-40s %-26s%4u: ", __FILE__, __func__, __LINE__); \
44
- printf(__VA_ARGS__); \
45
- printf("\x1B[0m\n"); \
46
- } while(0)
47
- #define BDEBUG(...) \
48
- do { \
49
- printf("\x1B[1;34m%-40s %-26s%4u: ", __FILE__, __func__, __LINE__); \
50
- printf(__VA_ARGS__); \
51
- printf("\x1B[0m\n"); \
52
- } while(0)
53
- #define YDEBUG(...) \
54
- do { \
55
- printf("\x1B[1;33m%-40s %-26s%4u: ", __FILE__, __func__, __LINE__); \
56
- printf(__VA_ARGS__); \
57
- printf("\x1B[0m\n"); \
58
- } while(0)
30
+ #define DEBUG(...) \
31
+ do { \
32
+ printf("%-40s %-26s%4u: ", __FILE__, __func__, __LINE__); \
33
+ printf(__VA_ARGS__); \
34
+ printf("\n"); \
35
+ } while(0)
36
+ #define RDEBUG(...) \
37
+ do { \
38
+ printf("\x1B[31m%-40s %-26s%4u: ", __FILE__, __func__, __LINE__); \
39
+ printf(__VA_ARGS__); \
40
+ printf("\x1B[0m\n"); \
41
+ } while(0)
42
+ #define GDEBUG(...) \
43
+ do { \
44
+ printf("\x1B[32m%-40s %-26s%4u: ", __FILE__, __func__, __LINE__); \
45
+ printf(__VA_ARGS__); \
46
+ printf("\x1B[0m\n"); \
47
+ } while(0)
48
+ #define BDEBUG(...) \
49
+ do { \
50
+ printf("\x1B[1;34m%-40s %-26s%4u: ", __FILE__, __func__, __LINE__); \
51
+ printf(__VA_ARGS__); \
52
+ printf("\x1B[0m\n"); \
53
+ } while(0)
54
+ #define YDEBUG(...) \
55
+ do { \
56
+ printf("\x1B[1;33m%-40s %-26s%4u: ", __FILE__, __func__, __LINE__); \
57
+ printf(__VA_ARGS__); \
58
+ printf("\x1B[0m\n"); \
59
+ } while(0)
59
60
  #else
60
61
  #define DEBUG(...) do{}while(0)
61
62
  #define RDEBUG(...) do{}while(0)
@@ -6,6 +6,7 @@
6
6
  #include "buffer.h"
7
7
  #include "client.h"
8
8
 
9
+
9
10
  #define ACCEPT_TIMEOUT_SECS 1
10
11
  #define SHORT_TIMEOUT_SECS 2
11
12
  #define WRITE_TIMEOUT_SECS 5
@@ -16,18 +17,42 @@
16
17
 
17
18
  #define LIMIT_SIZE 1024 * 512
18
19
 
20
+ #define READ_TIMEOUT_SECS 30
21
+ #define READ_BUF_SIZE 1024 * 64
22
+
19
23
  #define CRLF "\r\n"
20
24
  #define DELIM ": "
21
25
 
22
- #define MSG_500 ("HTTP/1.0 500 Internal Server Error\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n<html><head><title>500 Internal Server Error</title></head><h1>Internal Server Error</h1><p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p></html>\n")
26
+ #define SERVER "bossan/0.4.0"
27
+
28
+ #define H_MSG_500 "HTTP/1.0 500 Internal Server Error\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n"
29
+
30
+ #define H_MSG_503 "HTTP/1.0 503 Service Unavailable\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n"
31
+
32
+ #define H_MSG_400 "HTTP/1.0 400 Bad Request\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n"
33
+
34
+ #define H_MSG_408 "HTTP/1.0 408 Request Timeout\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n"
35
+
36
+ #define H_MSG_411 "HTTP/1.0 411 Length Required\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n"
37
+
38
+ #define H_MSG_413 "HTTP/1.0 413 Request Entity Too Large\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n"
39
+
40
+ #define H_MSG_417 "HTTP/1.1 417 Expectation Failed\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n"
41
+
42
+
43
+ #define MSG_500 H_MSG_500 "<html><head><title>500 Internal Server Error</title></head><body><h1>Internal Server Error</h1><p>The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.</p></body></html>"
23
44
 
24
- #define MSG_400 ("HTTP/1.0 400 Bad Request\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n<html><head><title>Bad Request</title></head><body><p>Bad Request.</p></body></html>")
45
+ #define MSG_503 H_MSG_503 "<html><head><title>Service Unavailable</title></head><body><p>Service Unavailable.</p></body></html>"
25
46
 
26
- #define MSG_411 ("HTTP/1.0 411 Length Required\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n<html><head><title>Length Required</title></head><body><p>Length Required.</p></body></html>")
47
+ #define MSG_400 H_MSG_400 "<html><head><title>Bad Request</title></head><body><p>Bad Request.</p></body></html>"
27
48
 
28
- #define MSG_413 ("HTTP/1.0 413 Request Entity Too Large\r\nContent-Type: text/html\r\nServer: " SERVER "\r\n\r\n<html><head><title>Request Entity Too Large</title></head><body><p>Request Entity Too Large.</p></body></html>")
49
+ #define MSG_408 H_MSG_408 "<html><head><title>Request Timeout</title></head><body><p>Request Timeout.</p></body></html>"
29
50
 
30
- #define SERVER "bossan/0.3.0"
51
+ #define MSG_411 H_MSG_411 "<html><head><title>Length Required</title></head><body><p>Length Required.</p></body></html>"
52
+
53
+ #define MSG_413 H_MSG_413 "<html><head><title>Request Entity Too Large</title></head><body><p>Request Entity Too Large.</p></body></html>"
54
+
55
+ #define MSG_417 H_MSG_417 "<html><head><title>Expectation Failed</title></head><body><p>Expectation Failed.</p></body></html>"
31
56
 
32
57
  VALUE server; // Bossan
33
58
 
@@ -62,23 +87,60 @@ static VALUE rb_remote_port;
62
87
  static VALUE rack_input;
63
88
  static VALUE http_connection;
64
89
 
90
+ static VALUE content_type;
91
+ static VALUE content_length;
92
+
93
+ static VALUE h_content_type;
94
+ static VALUE h_content_length;
95
+
65
96
  static VALUE empty_string;
66
97
 
98
+ static VALUE http_10;
99
+ static VALUE http_11;
100
+
101
+ static VALUE http_delete;
102
+ static VALUE http_get;
103
+ static VALUE http_head;
104
+ static VALUE http_post;
105
+ static VALUE http_put;
106
+ static VALUE http_connect;
107
+ static VALUE http_options;
108
+ static VALUE http_trace;
109
+ static VALUE http_copy;
110
+ static VALUE http_lock;
111
+ static VALUE http_mkcol;
112
+ static VALUE http_move;
113
+ static VALUE http_propfind;
114
+ static VALUE http_proppatch;
115
+ static VALUE http_unlock;
116
+ static VALUE http_report;
117
+ static VALUE http_mkactivity;
118
+ static VALUE http_checkout;
119
+ static VALUE http_merge;
120
+
67
121
  static VALUE http_user_agent;
68
122
  static VALUE http_referer;
69
123
 
70
- static VALUE i_keys;
71
- static VALUE i_call;
72
- static VALUE i_new;
73
- static VALUE i_key;
74
- static VALUE i_each;
75
- static VALUE i_close;
76
- static VALUE i_write;
77
- static VALUE i_seek;
124
+ static VALUE http_expect;
125
+
126
+ static ID i_keys;
127
+ static ID i_call;
128
+ static ID i_new;
129
+ static ID i_each;
130
+ static ID i_toenum;
131
+ static ID i_close;
132
+ static ID i_write;
133
+ static ID i_seek;
134
+ static ID i_toa;
135
+ static ID i_next;
136
+
137
+ static VALUE default_path_string;
78
138
 
79
139
  static const char *server_name = "127.0.0.1";
80
140
  static short server_port = 8000;
81
141
 
142
+ static int prefix_len = 0;
143
+
82
144
  static int listen_sock; // listen socket
83
145
 
84
146
  static char *unix_sock_name = NULL;
@@ -89,8 +151,6 @@ static VALUE rack_app; //rack app
89
151
 
90
152
  static char *log_path = NULL; //access log path
91
153
  static int log_fd = -1; //access log
92
- /* static char *error_log_path = NULL; //error log path */
93
- /* static int err_log_fd = -1; //error log */
94
154
 
95
155
  static int is_keep_alive = 0; //keep alive support
96
156
  static int keep_alive_timeout = 5;
@@ -110,15 +170,30 @@ typedef struct {
110
170
  uint32_t iov_size;
111
171
  uint32_t total;
112
172
  uint32_t total_size;
173
+ uint8_t sended;
174
+ VALUE temp1; //keep origin pointer
175
+ VALUE chunk_data; //keep chunk_data origin pointer
113
176
  } write_bucket;
114
177
 
115
178
 
179
+ typedef enum {
180
+ STATUS_OK = 0,
181
+ STATUS_SUSPEND,
182
+ STATUS_ERROR
183
+ } response_status;
184
+
185
+
116
186
  static void
117
187
  r_callback(picoev_loop* loop, int fd, int events, void* cb_arg);
118
188
 
119
189
  static void
120
190
  w_callback(picoev_loop* loop, int fd, int events, void* cb_arg);
121
191
 
192
+ static void
193
+ call_rack_app(client_t *client);
194
+
195
+ static void
196
+ prepare_call_rack(client_t *client);
122
197
 
123
198
  int
124
199
  open_log_file(const char *path)
@@ -176,43 +251,45 @@ write_log(const char *new_path, int fd, const char *data, size_t len)
176
251
  }
177
252
 
178
253
 
179
- int
254
+ static int
180
255
  write_access_log(client_t *cli, int log_fd, const char *log_path)
181
256
  {
257
+ request *req = (cli);
258
+
182
259
  char buf[1024*4];
183
260
  if(log_fd > 0){
184
261
  VALUE obj;
185
262
  char *method, *path, *version, *ua, *referer;
186
263
 
187
- obj = rb_hash_aref(cli->environ, request_method);
264
+ obj = rb_hash_aref(req->environ, request_method);
188
265
  if(obj != Qnil){
189
266
  method = StringValuePtr(obj);
190
267
  }else{
191
268
  method = "-";
192
269
  }
193
270
 
194
- obj = rb_hash_aref(cli->environ, path_info);
271
+ obj = rb_hash_aref(req->environ, path_info);
195
272
  if(obj != Qnil){
196
273
  path = StringValuePtr(obj);
197
274
  }else{
198
275
  path = "-";
199
276
  }
200
277
 
201
- obj = rb_hash_aref(cli->environ, server_protocol);
278
+ obj = rb_hash_aref(req->environ, server_protocol);
202
279
  if(obj != Qnil){
203
280
  version = StringValuePtr(obj);
204
281
  }else{
205
282
  version = "-";
206
283
  }
207
284
 
208
- obj = rb_hash_aref(cli->environ, http_user_agent);
285
+ obj = rb_hash_aref(req->environ, http_user_agent);
209
286
  if(obj != Qnil){
210
287
  ua = StringValuePtr(obj);
211
288
  }else{
212
289
  ua = "-";
213
290
  }
214
291
 
215
- obj = rb_hash_aref(cli->environ, http_referer);
292
+ obj = rb_hash_aref(req->environ, http_referer);
216
293
  if(obj != Qnil){
217
294
  referer = StringValuePtr(obj);
218
295
  }else{
@@ -278,38 +355,52 @@ blocking_write(client_t *client, char *data, size_t len)
278
355
  default:
279
356
  data += (int)r;
280
357
  len -= r;
281
- client->content_length += r;
358
+ client->write_bytes += r;
282
359
  }
283
360
  }
284
361
  return 1;
285
362
  }
286
363
 
287
364
 
288
- void
365
+ static void
289
366
  send_error_page(client_t *client)
290
367
  {
291
368
  shutdown(client->fd, SHUT_RD);
292
- if(client->header_done){
369
+ if(client->header_done || client->response_closed){
293
370
  //already sended response data
294
371
  //close connection
295
372
  return;
296
373
  }
297
- int status = client->bad_request_code;
298
- int r = status < 0 ? status * -1 : status;
299
- client->status_code = r;
300
- switch(r){
374
+
375
+ switch(client->status_code){
301
376
  case 400:
302
377
  blocking_write(client, MSG_400, sizeof(MSG_400) -1);
378
+ client->write_bytes -= sizeof(H_MSG_400) -1;
379
+ break;
380
+ case 408:
381
+ blocking_write(client, MSG_408, sizeof(MSG_408) -1);
382
+ client->write_bytes -= sizeof(H_MSG_408) -1;
303
383
  break;
304
384
  case 411:
305
385
  blocking_write(client, MSG_411, sizeof(MSG_411) -1);
386
+ client->write_bytes -= sizeof(H_MSG_411) -1;
306
387
  break;
307
388
  case 413:
308
389
  blocking_write(client, MSG_413, sizeof(MSG_413) -1);
390
+ client->write_bytes -= sizeof(H_MSG_413) -1;
391
+ break;
392
+ case 417:
393
+ blocking_write(client, MSG_417, sizeof(MSG_417) -1);
394
+ client->write_bytes -= sizeof(H_MSG_417) -1;
395
+ break;
396
+ case 503:
397
+ blocking_write(client, MSG_503, sizeof(MSG_503) -1);
398
+ client->write_bytes -= sizeof(H_MSG_503) -1;
309
399
  break;
310
400
  default:
311
401
  //Internal Server Error
312
402
  blocking_write(client, MSG_500, sizeof(MSG_500) -1);
403
+ client->write_bytes -= sizeof(H_MSG_500) -1;
313
404
  break;
314
405
  }
315
406
  client->keep_alive = 0;
@@ -318,29 +409,21 @@ send_error_page(client_t *client)
318
409
  }
319
410
 
320
411
 
321
- static void
322
- enable_cork(client_t *client)
323
- {
324
- int on = 1, r;
325
- #ifdef linux
326
- r = setsockopt(client->fd, IPPROTO_TCP, TCP_CORK, &on, sizeof(on));
327
- #elif defined(__APPLE__) || defined(__FreeBSD__)
328
- r = setsockopt(client->fd, IPPROTO_TCP, TCP_NOPUSH, &on, sizeof(on));
329
- #endif
330
- assert(r == 0);
331
- }
332
-
333
-
334
412
  static write_bucket *
335
413
  new_write_bucket(int fd, int cnt)
336
414
  {
337
415
  write_bucket *bucket;
416
+ iovec_t *iov;
417
+
338
418
  bucket = ruby_xmalloc(sizeof(write_bucket));
339
419
  memset(bucket, 0, sizeof(write_bucket));
340
420
 
341
421
  bucket->fd = fd;
342
- bucket->iov = (iovec_t *)ruby_xmalloc(sizeof(iovec_t) * cnt);
422
+ iov = (iovec_t *)ruby_xmalloc(sizeof(iovec_t) * cnt);
423
+ memset(iov, 0, sizeof(iovec_t));
424
+ bucket->iov = iov;
343
425
  bucket->iov_size = cnt;
426
+ GDEBUG("allocate %p", bucket);
344
427
  return bucket;
345
428
  }
346
429
 
@@ -348,6 +431,7 @@ new_write_bucket(int fd, int cnt)
348
431
  static void
349
432
  free_write_bucket(write_bucket *bucket)
350
433
  {
434
+ GDEBUG("free %p", bucket);
351
435
  ruby_xfree(bucket->iov);
352
436
  ruby_xfree(bucket);
353
437
  }
@@ -364,6 +448,25 @@ set2bucket(write_bucket *bucket, char *buf, size_t len)
364
448
  }
365
449
 
366
450
 
451
+ static void
452
+ set_chunked_data(write_bucket *bucket, char *lendata, size_t lenlen, char *data, size_t datalen)
453
+ {
454
+ set2bucket(bucket, lendata, lenlen);
455
+ set2bucket(bucket, CRLF, 2);
456
+ set2bucket(bucket, data, datalen);
457
+ set2bucket(bucket, CRLF, 2);
458
+ }
459
+
460
+
461
+ static void
462
+ set_last_chunked_data(write_bucket *bucket)
463
+ {
464
+ set2bucket(bucket, "0", 1);
465
+ set2bucket(bucket, CRLF, 2);
466
+ set2bucket(bucket, CRLF, 2);
467
+ }
468
+
469
+
367
470
  static void
368
471
  add_header(write_bucket *bucket, char *key, size_t keylen, char *val, size_t vallen)
369
472
  {
@@ -374,28 +477,50 @@ add_header(write_bucket *bucket, char *key, size_t keylen, char *val, size_t val
374
477
  }
375
478
 
376
479
 
377
- static int
480
+ #ifdef DEVELOP
481
+ static void
482
+ writev_log(write_bucket *data)
483
+ {
484
+ int i = 0;
485
+ char *c;
486
+ size_t len;
487
+ for(; i < data->iov_cnt; i++){
488
+ c = data->iov[i].iov_base;
489
+ len = data->iov[i].iov_len;
490
+ printf("%.*s", (int)len, c);
491
+ }
492
+ }
493
+ #endif
494
+
495
+
496
+ static response_status
378
497
  writev_bucket(write_bucket *data)
379
498
  {
380
- ssize_t w;
499
+ size_t w;
381
500
  int i = 0;
501
+ #ifdef DEVELOP
502
+ BDEBUG("\nwritev_bucket fd:%d", data->fd);
503
+ printf("\x1B[34m");
504
+ writev_log(data);
505
+ printf("\x1B[0m\n");
506
+ #endif
382
507
  w = writev(data->fd, data->iov, data->iov_cnt);
508
+ BDEBUG("writev fd:%d ret:%d total_size:%d", data->fd, (int)w, data->total);
383
509
  if(w == -1){
384
510
  //error
385
511
  if (errno == EAGAIN || errno == EWOULDBLOCK) {
386
512
  // try again later
387
- return 0;
513
+ return STATUS_SUSPEND;
388
514
  }else{
389
515
  //ERROR
390
516
 
391
517
  // TODO:
392
- // raise exception from errno
393
- /* rb_raise(rb_eIOError); */
394
- write_error_log(__FILE__, __LINE__);
395
- return -1;
518
+ /* write_error_log(__FILE__, __LINE__); */
519
+ return STATUS_ERROR;
396
520
  }
397
521
  }if(w == 0){
398
- return 1;
522
+ data->sended = 1;
523
+ return STATUS_OK;
399
524
  }else{
400
525
  if(data->total > w){
401
526
  for(; i < data->iov_cnt;i++){
@@ -409,23 +534,54 @@ writev_bucket(write_bucket *data)
409
534
  break;
410
535
  }
411
536
  }
412
- data->total = data->total -w;
537
+ data->total = data->total - w;
413
538
  DEBUG("writev_bucket write %d progeress %d/%d \n", w, data->total, data->total_size);
414
539
  //resume
415
540
  // again later
416
541
  return writev_bucket(data);
417
542
  }
418
543
  }
419
- return 1;
544
+ data->sended = 1;
545
+ return STATUS_OK;
420
546
  }
421
547
 
422
548
 
423
- static int
424
- write_headers(client_t *client)
549
+ static VALUE
550
+ get_chunk_data(size_t datalen)
425
551
  {
426
- if(client->header_done){
427
- return 1;
552
+ char lendata[32];
553
+ int i = 0;
554
+ i = snprintf(lendata, 32, "%zx", datalen);
555
+ DEBUG("Transfer-Encoding chunk_size %s", lendata);
556
+ return rb_str_new(lendata, i);
557
+ }
558
+
559
+
560
+ static void
561
+ set_first_body_data(client_t *client, char *data, size_t datalen)
562
+ {
563
+ write_bucket *bucket = client->bucket;
564
+ if(data){
565
+ if(client->chunked_response){
566
+ char *lendata = NULL;
567
+ ssize_t len = 0;
568
+
569
+ VALUE chunk_data = get_chunk_data(datalen);
570
+ //TODO CHECK ERROR
571
+ lendata = StringValuePtr(chunk_data);
572
+ len = RSTRING_LEN(chunk_data);
573
+ set_chunked_data(bucket, lendata, len, data, datalen);
574
+ bucket->chunk_data = chunk_data;
575
+ }else{
576
+ set2bucket(bucket, data, datalen);
577
+ }
428
578
  }
579
+ }
580
+
581
+
582
+ static response_status
583
+ write_headers(client_t *client, char *data, size_t datalen)
584
+ {
429
585
  write_bucket *bucket;
430
586
  uint32_t i = 0, hlen = 0;
431
587
 
@@ -435,22 +591,24 @@ write_headers(client_t *client)
435
591
  ssize_t namelen;
436
592
  char *value = NULL;
437
593
  long valuelen;
594
+ response_status ret;
438
595
 
439
- if(client->headers){
440
- if (TYPE(client->headers) != T_HASH) {
441
- return -1;
442
- }
443
- arr = rb_funcall(client->headers, i_keys, 0);
444
- hlen = RARRAY_LEN(arr);
596
+ DEBUG("header write? %d", client->header_done);
597
+ if(client->header_done){
598
+ return STATUS_OK;
445
599
  }
600
+
601
+ if (TYPE(client->headers) != T_HASH) {
602
+ return STATUS_ERROR;
603
+ }
604
+
605
+ arr = rb_funcall(client->headers, i_keys, 0);
606
+ hlen = RARRAY_LEN(arr);
607
+
446
608
  bucket = new_write_bucket(client->fd, ( hlen * 4 * 2) + 32 );
447
609
 
448
610
  object = client->http_status;
449
611
 
450
- if(TYPE(object) != T_STRING){
451
- return -1;
452
- }
453
-
454
612
  if(object){
455
613
  value = StringValuePtr(object);
456
614
  valuelen = RSTRING_LEN(object);
@@ -458,71 +616,77 @@ write_headers(client_t *client)
458
616
  set2bucket(bucket, value, valuelen);
459
617
 
460
618
  add_header(bucket, "Server", 6, SERVER, sizeof(SERVER) -1);
461
- cache_time_update();
462
619
  add_header(bucket, "Date", 4, (char *)http_time, 29);
463
- if(client->keep_alive == 1){
464
- // Keep-Alive
465
- add_header(bucket, "Connection", 10, "Keep-Alive", 10);
466
- } else {
467
- add_header(bucket, "Connection", 10, "close", 5);
468
- }
469
620
  }
470
621
 
471
622
  VALUE object1, object2;
472
623
 
473
624
  //write header
474
- if(client->headers){
475
- for(i=0; i < hlen; i++){
476
- object1 = rb_ary_entry(arr, i);
477
- Check_Type(object1, T_STRING);
478
-
479
- if (TYPE(client->headers)!=T_HASH){
480
- goto error;
481
- }
482
- VALUE tmp = rb_funcall(client->headers, i_key, 1, object1);
483
- if (tmp == Qfalse){
484
- goto error;
485
- }
486
- object2 = rb_hash_aref(client->headers, object1);
625
+ for(i=0; i < hlen; i++){
626
+ object1 = rb_ary_entry(arr, i);
627
+ /* Check_Type(object1, T_STRING); */
487
628
 
488
- Check_Type(object2, T_STRING);
629
+ object2 = rb_hash_aref(client->headers, object1);
630
+ /* Check_Type(object2, T_STRING); */
489
631
 
490
- name = StringValuePtr(object1);
491
- namelen = RSTRING_LEN(object1);
632
+ name = StringValuePtr(object1);
633
+ namelen = RSTRING_LEN(object1);
492
634
 
493
- value = StringValuePtr(object2);
494
- valuelen = RSTRING_LEN(object2);
635
+ value = StringValuePtr(object2);
636
+ valuelen = RSTRING_LEN(object2);
495
637
 
496
- if (strchr(name, '\n') != 0 || strchr(value, '\n') != 0) {
497
- rb_raise(rb_eArgError, "embedded newline in response header and value");
498
- }
638
+ if (strchr(name, ':') != 0) {
639
+ goto error;
640
+ }
641
+
642
+ if (strchr(name, '\n') != 0 || strchr(value, '\n') != 0) {
643
+ goto error;
644
+ }
499
645
 
500
- if (!strcasecmp(name, "Server") || !strcasecmp(name, "Date")) {
501
- continue;
502
- }
646
+ if (!strcasecmp(name, "Server") || !strcasecmp(name, "Date")) {
647
+ continue;
648
+ }
503
649
 
504
- if (!strcasecmp(name, "Content-Length")) {
505
- char *v = value;
506
- long l = 0;
650
+ if (client->content_length_set != 1 && !strcasecmp(name, "Content-Length")) {
651
+ char *v = value;
652
+ long l = 0;
507
653
 
508
- errno = 0;
509
- l = strtol(v, &v, 10);
510
- if (*v || errno == ERANGE || l < 0) {
511
- rb_raise(rb_eArgError, "invalid content length");
512
- goto error;
513
- }
514
- client->content_length_set = 1;
515
- client->content_length = l;
654
+ errno = 0;
655
+ l = strtol(v, &v, 10);
656
+ if (*v || errno == ERANGE || l < 0) {
657
+ goto error;
516
658
  }
517
- add_header(bucket, name, namelen, value, valuelen);
659
+ client->content_length_set = 1;
660
+ client->content_length = l;
518
661
  }
662
+ add_header(bucket, name, namelen, value, valuelen);
663
+ }
664
+
665
+ // check content_length_set
666
+ if(data && !client->content_length_set && client->http_parser->http_minor == 1){
667
+ //Transfer-Encoding chunked
668
+ add_header(bucket, "Transfer-Encoding", 17, "chunked", 7);
669
+ client->chunked_response = 1;
670
+ }
671
+
672
+ if(client->keep_alive == 1){
673
+ // Keep-Alive
674
+ add_header(bucket, "Connection", 10, "Keep-Alive", 10);
675
+ } else {
676
+ add_header(bucket, "Connection", 10, "close", 5);
519
677
  }
520
678
  set2bucket(bucket, CRLF, 2);
521
679
 
680
+ // write_body
522
681
  client->bucket = bucket;
523
- int ret = writev_bucket(bucket);
524
- if(ret != 0){
682
+ set_first_body_data(client, data, datalen);
683
+
684
+ ret = writev_bucket(bucket);
685
+ if(ret != STATUS_SUSPEND){
525
686
  client->header_done = 1;
687
+ if(ret == STATUS_OK && data){
688
+ client->write_bytes += datalen;
689
+ }
526
690
  // clear
527
691
  free_write_bucket(bucket);
528
692
  client->bucket = NULL;
@@ -534,9 +698,9 @@ write_headers(client_t *client)
534
698
  free_write_bucket(bucket);
535
699
  client->bucket = NULL;
536
700
  }
537
- return -1;
701
+ return STATUS_ERROR;
538
702
  }
539
-
703
+
540
704
 
541
705
  static void
542
706
  close_response(client_t *client)
@@ -548,21 +712,23 @@ close_response(client_t *client)
548
712
 
549
713
 
550
714
  static VALUE
551
- collect_body(VALUE i, VALUE str, int argc, VALUE *argv)
715
+ rb_body_iterator(VALUE iterator)
716
+ {
717
+ return rb_funcall(iterator, i_next, 0);
718
+ }
719
+
720
+
721
+ static VALUE
722
+ ret_qnil(void)
552
723
  {
553
- if(argc < 1) {
554
- return Qnil;
555
- }
556
- rb_str_concat(str, argv[0]);
557
724
  return Qnil;
558
725
  }
559
726
 
560
727
 
561
- static int
728
+ static response_status
562
729
  processs_write(client_t *client)
563
730
  {
564
731
  VALUE iterator;
565
- VALUE v_body;
566
732
  VALUE item;
567
733
  char *buf;
568
734
  size_t buflen;
@@ -570,112 +736,132 @@ processs_write(client_t *client)
570
736
  int ret;
571
737
 
572
738
  // body
739
+ DEBUG("process_write start");
573
740
  iterator = client->response_iter;
574
741
 
575
- if(iterator != Qnil){
576
- if (TYPE(iterator) != T_ARRAY || RARRAY_LEN(iterator) != 3){
577
- return -1;
578
- }
742
+ while ( (item = rb_rescue(rb_body_iterator, iterator, ret_qnil, NULL)) != Qnil ) {
579
743
 
580
- v_body = rb_ary_entry(iterator, 2);
744
+ buf = StringValuePtr(item);
745
+ buflen = RSTRING_LEN(item);
581
746
 
582
- if(!rb_respond_to(v_body, i_each)){
583
- return -1;
584
- }
747
+ //write
748
+ if(client->chunked_response){
749
+ bucket = new_write_bucket(client->fd, 4);
750
+ if(bucket == NULL){
751
+ return STATUS_ERROR;
752
+ }
753
+ char *lendata = NULL;
754
+ ssize_t len = 0;
585
755
 
586
- VALUE v_body_str = rb_str_new2("");
587
- rb_block_call(v_body, i_each, 0, NULL, collect_body, v_body_str);
588
- if(rb_respond_to(v_body, i_close)) {
589
- rb_funcall(v_body, i_close, 0);
590
- }
756
+ VALUE chunk_data = get_chunk_data(buflen);
757
+ //TODO CHECK ERROR
758
+ lendata = StringValuePtr(chunk_data);
759
+ len = RSTRING_LEN(chunk_data);
591
760
 
592
- buf = StringValuePtr(v_body_str);
593
- buflen = RSTRING_LEN(v_body_str);
761
+ set_chunked_data(bucket, lendata, len, buf, buflen);
762
+ bucket->chunk_data = chunk_data;
763
+ } else {
764
+ bucket = new_write_bucket(client->fd, 1);
765
+ if(bucket == NULL){
766
+ return STATUS_ERROR;
767
+ }
768
+ set2bucket(bucket, buf, buflen);
769
+ }
770
+ bucket->temp1 = item;
594
771
 
595
- bucket = new_write_bucket(client->fd, 1);
596
- set2bucket(bucket, buf, buflen);
597
772
  ret = writev_bucket(bucket);
598
- if(ret <= 0){
773
+ if(ret != STATUS_OK){
774
+ client->bucket = bucket;
599
775
  return ret;
600
776
  }
777
+
778
+ free_write_bucket(bucket);
601
779
  //mark
602
780
  client->write_bytes += buflen;
603
781
  //check write_bytes/content_length
604
782
  if(client->content_length_set){
605
783
  if(client->content_length <= client->write_bytes){
606
784
  // all done
607
- /* break; */
785
+ break;
608
786
  }
609
787
  }
788
+
789
+ if(client->chunked_response){
790
+ DEBUG("write last chunk");
791
+ //last packet
792
+ bucket = new_write_bucket(client->fd, 3);
793
+ if(bucket == NULL){
794
+ return STATUS_ERROR;
795
+ }
796
+ set_last_chunked_data(bucket);
797
+ writev_bucket(bucket);
798
+ free_write_bucket(bucket);
799
+ }
610
800
  close_response(client);
611
801
  }
612
- return 1;
802
+ return STATUS_OK;
613
803
  }
614
804
 
615
805
 
616
- int
806
+ static response_status
617
807
  process_body(client_t *client)
618
808
  {
619
- int ret;
809
+ response_status ret;
620
810
  write_bucket *bucket;
621
811
  if(client->bucket){
622
812
  bucket = (write_bucket *)client->bucket;
623
813
  //retry send
624
814
  ret = writev_bucket(bucket);
625
815
 
626
- if(ret != 0){
816
+ if(ret == STATUS_OK){
627
817
  client->write_bytes += bucket->total_size;
628
818
  //free
629
819
  free_write_bucket(bucket);
630
820
  client->bucket = NULL;
821
+ }else if(ret == STATUS_ERROR){
822
+ free_write_bucket(bucket);
823
+ client->bucket = NULL;
824
+ return ret;
631
825
  }else{
632
- return 0;
826
+ return ret;
633
827
  }
634
828
  }
635
- ret = processs_write(client);
636
- return ret;
829
+ return processs_write(client);
637
830
  }
638
831
 
639
832
 
640
- static int
833
+ static response_status
641
834
  start_response_write(client_t *client)
642
835
  {
643
- VALUE iterator;
644
- VALUE dict;
645
836
  VALUE item;
646
837
  char *buf;
647
838
  ssize_t buflen;
648
839
 
649
- iterator = client->response;
650
- client->response_iter = iterator;
651
-
652
- if (TYPE(iterator) != T_ARRAY){
653
- return -1;
654
- }
655
- assert(3 == RARRAY_LEN(iterator));
840
+ item = rb_funcall(client->response_iter, i_next, 0);
841
+ /* Check_Type(item, T_STRING); */
842
+ DEBUG("client %p :fd %d", client, client->fd);
656
843
 
657
- dict = rb_ary_entry(iterator, 1);
844
+ //write string only
845
+ buf = StringValuePtr(item);
846
+ buflen = RSTRING_LEN(item);
658
847
 
659
- if (TYPE(dict) != T_HASH){
660
- return -1;
661
- }
662
-
663
- /* DEBUG("start_response_write buflen %d \n", buflen); */
664
- return write_headers(client);
848
+ /* DEBUG("status_code %d body:%.*s", client->status_code, (int)buflen, buf); */
849
+ return write_headers(client, buf, buflen);
665
850
  }
666
851
 
667
852
 
668
- int
853
+ response_status
669
854
  response_start(client_t *client)
670
855
  {
671
- int ret;
672
- enable_cork(client);
856
+ response_status ret;
857
+
673
858
  if(client->status_code == 304){
674
- return write_headers(client);
859
+ return write_headers(client, NULL, 0);
675
860
  }
676
861
  ret = start_response_write(client);
677
- DEBUG("start_response_write ret = %d \n", ret);
678
- if(ret > 0){
862
+ DEBUG("start_response_write ret = %d :fd = %d\n", ret, client->fd);
863
+
864
+ if(ret == STATUS_OK){
679
865
  // sended header
680
866
  ret = processs_write(client);
681
867
  }
@@ -704,259 +890,342 @@ key_upper(char *s, const char *key, size_t len)
704
890
 
705
891
 
706
892
  static int
707
- write_body2mem(client_t *client, const char *buffer, size_t buffer_len)
893
+ write_body2mem(request *req, const char *buffer, size_t buf_len)
708
894
  {
709
- VALUE obj;
710
-
711
- rb_funcall((VALUE)client->body, i_write, 1, rb_str_new(buffer, buffer_len));
712
- client->body_readed += buffer_len;
713
- DEBUG("write_body2mem %d bytes \n", buffer_len);
714
- return client->body_readed;
895
+ rb_funcall((VALUE)req->body, i_write, 1, rb_str_new(buffer, buf_len));
896
+ req->body_readed += buf_len;
897
+ DEBUG("write_body2mem %d bytes \n", buf_len);
898
+ return req->body_readed;
715
899
  }
716
900
 
717
901
 
718
902
  static int
719
- write_body(client_t *cli, const char *buffer, size_t buffer_len)
903
+ write_body(request *req, const char *buffer, size_t buffer_len)
720
904
  {
721
- return write_body2mem(cli, buffer, buffer_len);
905
+ return write_body2mem(req, buffer, buffer_len);
722
906
  }
723
907
 
724
908
 
725
- typedef enum{
726
- CONTENT_TYPE,
727
- CONTENT_LENGTH,
728
- OTHER
729
- } rack_header_type;
909
+ static client_t *
910
+ get_client(http_parser *p)
911
+ {
912
+ return (client_t *)p->data;
913
+ }
730
914
 
731
915
 
732
- static rack_header_type
733
- check_header_type(const char *buf)
916
+ static request *
917
+ get_current_request(http_parser *p)
734
918
  {
735
- if(*buf++ != 'C'){
736
- return OTHER;
737
- }
738
- if(*buf++ != 'O'){
739
- return OTHER;
740
- }
741
- if(*buf++ != 'N'){
742
- return OTHER;
743
- }
744
- if(*buf++ != 'T'){
745
- return OTHER;
746
- }
747
- if(*buf++ != 'E'){
748
- return OTHER;
749
- }
750
- if(*buf++ != 'N'){
751
- return OTHER;
752
- }
753
- if(*buf++ != 'T'){
754
- return OTHER;
755
- }
756
- if(*buf++ != '_'){
757
- return OTHER;
919
+ client_t *client = (client_t *)p->data;
920
+ return client->current_req;
921
+ }
922
+
923
+
924
+ static VALUE
925
+ new_environ(client_t *client)
926
+ {
927
+ VALUE object, environ;
928
+ char r_port[7];
929
+
930
+ environ = rb_hash_new();
931
+
932
+ rb_hash_aset(environ, version_key, version_val);
933
+ rb_hash_aset(environ, scheme_key, scheme_val);
934
+ rb_hash_aset(environ, errors_key, errors_val);
935
+ rb_hash_aset(environ, multithread_key, multithread_val);
936
+ rb_hash_aset(environ, multiprocess_key, multiprocess_val);
937
+ rb_hash_aset(environ, run_once_key, run_once_val);
938
+ rb_hash_aset(environ, script_key, empty_string);
939
+ rb_hash_aset(environ, server_name_key, server_name_val);
940
+ rb_hash_aset(environ, server_port_key, server_port_val);
941
+
942
+ object = rb_str_new2(client->remote_addr);
943
+ rb_hash_aset(environ, rb_remote_addr, object);
944
+
945
+ sprintf(r_port, "%d", client->remote_port);
946
+ object = rb_str_new2(r_port);
947
+ rb_hash_aset(environ, rb_remote_port, object);
948
+ return environ;
949
+ }
950
+
951
+
952
+ static int
953
+ hex2int(int i)
954
+ {
955
+ i = toupper(i);
956
+ i = i - '0';
957
+ if(i > 9){
958
+ i = i - 'A' + '9' + 1;
758
959
  }
759
- char c = *buf++;
760
- if(c == 'L'){
761
- return CONTENT_LENGTH;
762
- }else if(c == 'T'){
763
- return CONTENT_TYPE;
960
+ return i;
961
+ }
962
+
963
+
964
+ static int
965
+ urldecode(char *buf, int len)
966
+ {
967
+ int c, c1;
968
+ char *s0, *t;
969
+ t = s0 = buf;
970
+ while(len >0){
971
+ c = *buf++;
972
+ if(c == '%' && len > 2){
973
+ c = *buf++;
974
+ c1 = c;
975
+ c = *buf++;
976
+ c = hex2int(c1) * 16 + hex2int(c);
977
+ len -= 2;
978
+ }
979
+ *t++ = c;
980
+ len--;
764
981
  }
765
- return OTHER;
982
+ *t = 0;
983
+ return t - s0;
766
984
  }
767
985
 
768
986
 
769
- static client_t *
770
- get_client(http_parser *p)
987
+ static VALUE
988
+ concat_string(VALUE o, const char *buf, size_t len)
771
989
  {
772
- return (client_t *)p->data;
990
+ VALUE ret;
991
+ size_t l;
992
+ char *dest, *origin;
993
+
994
+ l = RSTRING_LEN(o);
995
+
996
+ ret = rb_str_new((char*)0, l + len);
997
+ if(ret == NULL){
998
+ return ret;
999
+ }
1000
+ dest = StringValuePtr(ret);
1001
+ origin = StringValuePtr(o);
1002
+ memcpy(dest, origin, l);
1003
+ memcpy(dest + l, buf, len);
1004
+ return ret;
773
1005
  }
774
1006
 
775
1007
 
776
- int
777
- message_begin_cb(http_parser *p)
1008
+ static int
1009
+ replace_env_key(VALUE dict, VALUE old_key, VALUE new_key)
778
1010
  {
779
- return 0;
1011
+ int ret = 1;
1012
+
1013
+ VALUE value = rb_hash_aref(dict, old_key);
1014
+ if(value != Qnil) {
1015
+ rb_hash_aset(dict, old_key, Qnil);
1016
+ ret = rb_hash_aset(dict, new_key, value);
1017
+ }
1018
+ return ret;
780
1019
  }
781
1020
 
782
1021
 
783
- int
784
- header_field_cb (http_parser *p, const char *buf, size_t len, char partial)
1022
+ static int
1023
+ set_query(VALUE env, char *buf, int len)
785
1024
  {
786
- uint32_t i;
787
- header *h;
788
- client_t *client = get_client(p);
789
- request *req = client->req;
790
- char temp[len];
791
-
792
- buffer_result ret = MEMORY_ERROR;
793
- if (req->last_header_element != FIELD){
794
- if(LIMIT_REQUEST_FIELDS <= req->num_headers){
795
- client->bad_request_code = 400;
796
- return -1;
1025
+ int c, slen = 0;
1026
+ char *s0;
1027
+ VALUE obj;
1028
+
1029
+ s0 = buf;
1030
+ while(len > 0){
1031
+ c = *buf++;
1032
+ if(c == '#'){
1033
+ slen++;
1034
+ break;
797
1035
  }
798
- req->num_headers++;
1036
+ len--;
1037
+ slen++;
799
1038
  }
800
- i = req->num_headers;
801
- h = req->headers[i];
802
-
803
- key_upper(temp, buf, len);
804
- if(h){
805
- ret = write2buf(h->field, temp, len);
806
- }else{
807
- req->headers[i] = h = new_header(128, LIMIT_REQUEST_FIELD_SIZE, 1024, LIMIT_REQUEST_FIELD_SIZE);
808
- rack_header_type type = check_header_type(temp);
809
- if(type == OTHER){
810
- ret = write2buf(h->field, "HTTP_", 5);
1039
+
1040
+ if(slen > 1){
1041
+ obj = rb_str_new(s0, slen-1);
1042
+ rb_hash_aset(env, query_string, obj);
1043
+ }
1044
+ return 1;
1045
+ }
1046
+
1047
+
1048
+ static int
1049
+ set_path(VALUE env, char *buf, int len)
1050
+ {
1051
+ int c, c1, slen;
1052
+ char *s0, *t;
1053
+ VALUE obj;
1054
+
1055
+ t = s0 = buf;
1056
+ while(len > 0){
1057
+ c = *buf++;
1058
+ if(c == '%' && len > 2){
1059
+ c = *buf++;
1060
+ c1 = c;
1061
+ c = *buf++;
1062
+ c = hex2int(c1) * 16 + hex2int(c);
1063
+ len -= 2;
1064
+ }else if(c == '?'){
1065
+ //stop
1066
+ if(set_query(env, buf, len) == -1){
1067
+ //Error
1068
+ return -1;
1069
+ }
1070
+ break;
1071
+ }else if(c == '#'){
1072
+ //stop
1073
+ //ignore fragment
1074
+ break;
811
1075
  }
812
- ret = write2buf(h->field, temp, len);
813
- //printf("%s \n", getString(h->field));
1076
+ *t++ = c;
1077
+ len--;
814
1078
  }
815
- switch(ret){
816
- case MEMORY_ERROR:
817
- client->bad_request_code = 500;
818
- return -1;
819
- case LIMIT_OVER:
820
- client->bad_request_code = 400;
821
- return -1;
822
- default:
823
- break;
1079
+ slen = t - s0;
1080
+ slen = urldecode(s0, slen);
1081
+
1082
+ obj = rb_str_new(s0, slen);
1083
+
1084
+ rb_hash_aset(env, path_info, obj);
1085
+
1086
+ if (rb_hash_aref(env, query_string) == Qnil) {
1087
+ rb_hash_aset(env, query_string, empty_string);
824
1088
  }
825
- req->last_header_element = FIELD;
826
- return 0;
1089
+ return slen;
827
1090
  }
828
1091
 
829
1092
 
830
- int
831
- header_value_cb (http_parser *p, const char *buf, size_t len, char partial)
1093
+ static VALUE
1094
+ get_http_header_key(const char *s, int len)
832
1095
  {
833
- uint32_t i;
834
- header *h;
835
- client_t *client = get_client(p);
836
- request *req = client->req;
837
-
838
- buffer_result ret = MEMORY_ERROR;
839
- i = req->num_headers;
840
- h = req->headers[i];
841
-
842
- if(h){
843
- ret = write2buf(h->value, buf, len);
844
- }
845
- switch(ret){
846
- case MEMORY_ERROR:
847
- client->bad_request_code = 500;
848
- return -1;
849
- case LIMIT_OVER:
850
- client->bad_request_code = 400;
851
- return -1;
852
- default:
853
- break;
1096
+ VALUE obj;
1097
+ char *dest;
1098
+ char c;
1099
+
1100
+ obj = rb_str_new("", len + prefix_len);
1101
+ dest = (char*)StringValuePtr(obj);
1102
+
1103
+ *dest++ = 'H';
1104
+ *dest++ = 'T';
1105
+ *dest++ = 'T';
1106
+ *dest++ = 'P';
1107
+ *dest++ = '_';
1108
+
1109
+ while(len--) {
1110
+ c = *s++;
1111
+ if(c == '-'){
1112
+ *dest++ = '_';
1113
+ }else if(c >= 'a' && c <= 'z'){
1114
+ *dest++ = c - ('a'-'A');
1115
+ }else{
1116
+ *dest++ = c;
1117
+ }
854
1118
  }
855
- req->last_header_element = VAL;
856
- return 0;
1119
+ return obj;
857
1120
  }
858
1121
 
859
1122
 
860
- int
861
- request_path_cb (http_parser *p, const char *buf, size_t len, char partial)
1123
+ static int
1124
+ message_begin_cb(http_parser *p)
862
1125
  {
1126
+ request *req;
1127
+
1128
+ DEBUG("message_begin_cb");
1129
+
863
1130
  client_t *client = get_client(p);
864
- request *req = client->req;
865
- buffer_result ret = MEMORY_ERROR;
866
-
867
- if(req->path){
868
- ret = write2buf(req->path, buf, len);
869
- }else{
870
- req->path = new_buffer(1024, LIMIT_PATH);
871
- ret = write2buf(req->path, buf, len);
872
- }
873
- switch(ret){
874
- case MEMORY_ERROR:
875
- client->bad_request_code = 500;
876
- return -1;
877
- case LIMIT_OVER:
878
- client->bad_request_code = 400;
879
- return -1;
880
- default:
881
- break;
882
- }
1131
+
1132
+ req = new_request();
1133
+ req->start_msec = current_msec;
1134
+ client->current_req = req;
1135
+ client->complete = 0;
1136
+ req->environ = new_environ(client);
1137
+ rb_gc_register_address(&req->environ);
1138
+ push_request(client->request_queue, client->current_req);
883
1139
  return 0;
884
1140
  }
885
1141
 
886
1142
 
887
- int
888
- request_uri_cb (http_parser *p, const char *buf, size_t len, char partial)
1143
+ static int
1144
+ header_field_cb(http_parser *p, const char *buf, size_t len)
889
1145
  {
890
- client_t *client = get_client(p);
891
- request *req = client->req;
892
- buffer_result ret = MEMORY_ERROR;
893
-
894
- if(req->uri){
895
- ret = write2buf(req->uri, buf, len);
1146
+ VALUE env, obj;
1147
+ request *req = get_current_request(p);
1148
+
1149
+ if (req->last_header_element != FIELD){
1150
+ env = req->environ;
1151
+ if(LIMIT_REQUEST_FIELDS <= req->num_headers){
1152
+ req->bad_request_code = 400;
1153
+ return -1;
1154
+ }
1155
+ rb_hash_aset(env, req->field, req->value);
1156
+ req->field = NULL;
1157
+ req->value = NULL;
1158
+ req->num_headers++;
1159
+ }
1160
+
1161
+ if(likely(req->field == NULL)){
1162
+ obj = get_http_header_key(buf, len);
896
1163
  }else{
897
- req->uri = new_buffer(1024, LIMIT_URI);
898
- ret = write2buf(req->uri, buf, len);
1164
+ char temp[len];
1165
+ key_upper(temp, buf, len);
1166
+ obj = concat_string(req->field, temp, len);
899
1167
  }
900
- switch(ret){
901
- case MEMORY_ERROR:
902
- client->bad_request_code = 500;
1168
+
1169
+ if(unlikely(obj == NULL)){
1170
+ req->bad_request_code = 500;
903
1171
  return -1;
904
- case LIMIT_OVER:
905
- client->bad_request_code = 400;
1172
+ }
1173
+
1174
+ if(unlikely(RSTRING_LEN(obj) > LIMIT_REQUEST_FIELD_SIZE)){
1175
+ req->bad_request_code = 400;
906
1176
  return -1;
907
- default:
908
- break;
909
1177
  }
1178
+
1179
+ req->field = obj;
1180
+ req->last_header_element = FIELD;
910
1181
  return 0;
911
1182
  }
912
1183
 
913
-
914
- int
915
- query_string_cb (http_parser *p, const char *buf, size_t len, char partial)
916
- {
917
- client_t *client = get_client(p);
918
- request *req = client->req;
919
- buffer_result ret = MEMORY_ERROR;
920
-
921
- if(req->query_string){
922
- ret = write2buf(req->query_string, buf, len);
1184
+
1185
+ static int
1186
+ header_value_cb(http_parser *p, const char *buf, size_t len)
1187
+ {
1188
+ request *req = get_current_request(p);
1189
+ VALUE obj;
1190
+
1191
+ if(likely(req->value == NULL)){
1192
+ obj = rb_str_new(buf, len);
923
1193
  }else{
924
- req->query_string = new_buffer(1024*2, LIMIT_QUERY_STRING);
925
- ret = write2buf(req->query_string, buf, len);
1194
+ obj = concat_string(req->value, buf, len);
926
1195
  }
927
- switch(ret){
928
- case MEMORY_ERROR:
929
- client->bad_request_code = 500;
930
- return -1;
931
- case LIMIT_OVER:
932
- client->bad_request_code = 400;
1196
+
1197
+ if(unlikely(obj == NULL)){
1198
+ req->bad_request_code = 500;
1199
+ return -1;
1200
+ }
1201
+ if(unlikely(RSTRING_LEN(obj) > LIMIT_REQUEST_FIELD_SIZE)){
1202
+ req->bad_request_code = 400;
933
1203
  return -1;
934
- default:
935
- break;
936
1204
  }
1205
+ req->value = obj;
1206
+ req->last_header_element = VAL;
937
1207
  return 0;
938
1208
  }
939
1209
 
940
1210
 
941
- int
942
- fragment_cb (http_parser *p, const char *buf, size_t len, char partial)
1211
+ static int
1212
+ request_uri_cb(http_parser *p, const char *buf, size_t len)
943
1213
  {
944
- client_t *client = get_client(p);
945
- request *req = client->req;
1214
+ request *req = get_current_request(p);
946
1215
  buffer_result ret = MEMORY_ERROR;
947
-
948
- if(req->fragment){
949
- ret = write2buf(req->fragment, buf, len);
1216
+
1217
+ if(req->path){
1218
+ ret = write2buf(req->path, buf, len);
950
1219
  }else{
951
- req->fragment = new_buffer(1024, LIMIT_FRAGMENT);
952
- ret = write2buf(req->fragment, buf, len);
1220
+ req->path = new_buffer(1024, LIMIT_URI);
1221
+ ret = write2buf(req->path, buf, len);
953
1222
  }
954
1223
  switch(ret){
955
1224
  case MEMORY_ERROR:
956
- client->bad_request_code = 500;
1225
+ req->bad_request_code = 500;
957
1226
  return -1;
958
1227
  case LIMIT_OVER:
959
- client->bad_request_code = 400;
1228
+ req->bad_request_code = 400;
960
1229
  return -1;
961
1230
  default:
962
1231
  break;
@@ -965,27 +1234,28 @@ fragment_cb (http_parser *p, const char *buf, size_t len, char partial)
965
1234
  }
966
1235
 
967
1236
 
968
- int
969
- body_cb (http_parser *p, const char *buf, size_t len, char partial)
1237
+ static int
1238
+ body_cb(http_parser *p, const char *buf, size_t len)
970
1239
  {
971
- client_t *client = get_client(p);
972
- if(max_content_length <= client->body_readed + len){
973
- client->bad_request_code = 413;
1240
+ request *req = get_current_request(p);
1241
+
1242
+ if(max_content_length <= req->body_readed + len){
1243
+ req->bad_request_code = 413;
974
1244
  return -1;
975
1245
  }
976
- if(client->body_type == BODY_TYPE_NONE){
977
- if(client->body_length == 0){
1246
+ if(req->body_type == BODY_TYPE_NONE){
1247
+ if(req->body_length == 0){
978
1248
  //Length Required
979
- client->bad_request_code = 411;
1249
+ req->bad_request_code = 411;
980
1250
  return -1;
981
1251
  }
982
1252
  //default memory stream
983
- DEBUG("client->body_length %d \n", client->body_length);
984
- client->body = rb_funcall(StringIO, i_new, 1, rb_str_new2(""));
985
- client->body_type = BODY_TYPE_BUFFER;
1253
+ DEBUG("client->body_length %d \n", req->body_length);
1254
+ req->body = rb_funcall(StringIO, i_new, 1, rb_str_new2(""));
1255
+ req->body_type = BODY_TYPE_BUFFER;
986
1256
  DEBUG("BODY_TYPE_BUFFER \n");
987
1257
  }
988
- write_body(client, buf, len);
1258
+ write_body(req, buf, len);
989
1259
  return 0;
990
1260
  }
991
1261
 
@@ -993,129 +1263,134 @@ body_cb (http_parser *p, const char *buf, size_t len, char partial)
993
1263
  int
994
1264
  headers_complete_cb(http_parser *p)
995
1265
  {
996
- VALUE obj, key;
1266
+ VALUE obj = NULL;
997
1267
  client_t *client = get_client(p);
998
- request *req = client->req;
999
- VALUE env = client->environ;
1000
- uint32_t i = 0;
1001
- header *h;
1002
-
1003
- if(max_content_length < p->content_length){
1004
- client->bad_request_code = 413;
1005
- return -1;
1268
+ request *req = client->current_req;
1269
+ VALUE env = req->environ;
1270
+ int ret;
1271
+ uint64_t content_length = 0;
1272
+
1273
+ DEBUG("should keep alive %d", http_should_keep_alive(p));
1274
+ client->keep_alive = http_should_keep_alive(p);
1275
+
1276
+ if(p->content_length != ULLONG_MAX){
1277
+ content_length = p->content_length;
1278
+ if(max_content_length < p->content_length){
1279
+ RDEBUG("max_content_length over %d/%d", (int)content_length, (int)max_content_length);
1280
+ DEBUG("set request code %d", 413);
1281
+ req->bad_request_code = 413;
1282
+ return -1;
1283
+ }
1006
1284
  }
1007
1285
 
1008
1286
  if (p->http_minor == 1) {
1009
- obj = rb_str_new2("HTTP/1.1");
1287
+ obj = http_11;
1010
1288
  } else {
1011
- obj = rb_str_new2("HTTP/1.0");
1012
- }
1289
+ obj = http_10;
1290
+ }
1013
1291
  rb_hash_aset(env, server_protocol, obj);
1014
-
1015
- if(req->path){
1016
- obj = getRbString(req->path);
1017
- rb_hash_aset(env, path_info, obj);
1018
- req->path = NULL;
1292
+
1293
+ if(likely(req->path)){
1294
+ ret = set_path(env, req->path->buf, req->path->len);
1295
+ free_buffer(req->path);
1296
+ if(unlikely(ret == -1)){
1297
+ //TODO Error
1298
+ return -1;
1299
+ }
1300
+ }else{
1301
+ rb_hash_aset(env, path_info, default_path_string);
1019
1302
  }
1020
- if(req->uri){
1021
- obj = getRbString(req->uri);
1022
- rb_hash_aset(env, request_uri, obj);
1023
- req->uri = NULL;
1303
+ req->path = NULL;
1304
+
1305
+ //Last header
1306
+ if(likely(req->field && req->value)){
1307
+ rb_hash_aset(env, req->field, req->value);
1308
+
1309
+ req->field = NULL;
1310
+ req->value = NULL;
1024
1311
  }
1025
- if(req->query_string){
1026
- obj = getRbString(req->query_string);
1027
- rb_hash_aset(env, query_string, obj);
1028
- req->query_string = NULL;
1029
- }
1030
- if(req->fragment){
1031
- obj = getRbString(req->fragment);
1032
- rb_hash_aset(env, http_fragment, obj);
1033
- req->fragment = NULL;
1034
- }
1035
- for(i = 0; i < req->num_headers+1; i++){
1036
- h = req->headers[i];
1037
- if(h){
1038
- key = getRbString(h->field);
1039
- obj = getRbString(h->value);
1040
- rb_hash_aset(env, key, obj);
1041
- free_header(h);
1042
- req->headers[i] = NULL;
1043
- }
1312
+
1313
+ ret = replace_env_key(env, h_content_type, content_type);
1314
+ if(unlikely(ret == -1)){
1315
+ return -1;
1316
+ }
1317
+ ret = replace_env_key(env, h_content_length, content_length);
1318
+ if(unlikely(ret == -1)){
1319
+ return -1;
1044
1320
  }
1045
1321
 
1046
1322
  switch(p->method){
1047
1323
  case HTTP_DELETE:
1048
- obj = rb_str_new("DELETE", 6);
1324
+ obj = http_delete;
1049
1325
  break;
1050
1326
  case HTTP_GET:
1051
- obj = rb_str_new("GET", 3);
1327
+ obj = http_get;
1052
1328
  break;
1053
1329
  case HTTP_HEAD:
1054
- obj = rb_str_new("HEAD", 4);
1330
+ obj = http_head;
1055
1331
  break;
1056
1332
  case HTTP_POST:
1057
- obj = rb_str_new("POST", 4);
1333
+ obj = http_post;
1058
1334
  break;
1059
1335
  case HTTP_PUT:
1060
- obj = rb_str_new("PUT", 3);
1336
+ obj = http_put;
1061
1337
  break;
1062
1338
  case HTTP_CONNECT:
1063
- obj = rb_str_new("CONNECT", 7);
1339
+ obj = http_connect;
1064
1340
  break;
1065
1341
  case HTTP_OPTIONS:
1066
- obj = rb_str_new("OPTIONS", 7);
1342
+ obj = http_options;
1067
1343
  break;
1068
1344
  case HTTP_TRACE:
1069
- obj = rb_str_new("TRACE", 5);
1345
+ obj = http_trace;
1070
1346
  break;
1071
1347
  case HTTP_COPY:
1072
- obj = rb_str_new("COPY", 4);
1348
+ obj = http_copy;
1073
1349
  break;
1074
1350
  case HTTP_LOCK:
1075
- obj = rb_str_new("LOCK", 4);
1351
+ obj = http_lock;
1076
1352
  break;
1077
1353
  case HTTP_MKCOL:
1078
- obj = rb_str_new("MKCOL", 5);
1354
+ obj = http_mkcol;
1079
1355
  break;
1080
1356
  case HTTP_MOVE:
1081
- obj = rb_str_new("MOVE", 4);
1357
+ obj = http_move;
1082
1358
  break;
1083
1359
  case HTTP_PROPFIND:
1084
- obj = rb_str_new("PROPFIND", 8);
1360
+ obj = http_propfind;
1085
1361
  break;
1086
1362
  case HTTP_PROPPATCH:
1087
- obj = rb_str_new("PROPPATCH", 9);
1363
+ obj = http_proppatch;
1088
1364
  break;
1089
1365
  case HTTP_UNLOCK:
1090
- obj = rb_str_new("UNLOCK", 6);
1366
+ obj = http_unlock;
1091
1367
  break;
1092
1368
  case HTTP_REPORT:
1093
- obj = rb_str_new("REPORT", 6);
1369
+ obj = http_report;
1094
1370
  break;
1095
1371
  case HTTP_MKACTIVITY:
1096
- obj = rb_str_new("MKACTIVITY", 10);
1372
+ obj = http_mkactivity;
1097
1373
  break;
1098
1374
  case HTTP_CHECKOUT:
1099
- obj = rb_str_new("CHECKOUT", 8);
1375
+ obj = http_checkout;
1100
1376
  break;
1101
1377
  case HTTP_MERGE:
1102
- obj = rb_str_new("MERGE", 5);
1378
+ obj = http_merge;
1103
1379
  break;
1104
1380
  default:
1105
- obj = rb_str_new("GET", 3);
1381
+ obj = http_get;
1106
1382
  break;
1107
1383
  }
1108
1384
 
1109
1385
  rb_hash_aset(env, request_method, obj);
1386
+ req->body_length = p->content_length;
1110
1387
 
1111
- ruby_xfree(req);
1112
- client->req = NULL;
1113
- client->body_length = p->content_length;
1388
+ DEBUG("fin headers_complete_cb");
1114
1389
  return 0;
1115
1390
  }
1116
1391
 
1117
1392
 
1118
- int
1393
+ static int
1119
1394
  message_complete_cb (http_parser *p)
1120
1395
  {
1121
1396
  client_t *client = get_client(p);
@@ -1128,73 +1403,46 @@ static http_parser_settings settings =
1128
1403
  {.on_message_begin = message_begin_cb
1129
1404
  ,.on_header_field = header_field_cb
1130
1405
  ,.on_header_value = header_value_cb
1131
- ,.on_path = request_path_cb
1132
1406
  ,.on_url = request_uri_cb
1133
- ,.on_fragment = fragment_cb
1134
- ,.on_query_string = query_string_cb
1135
1407
  ,.on_body = body_cb
1136
1408
  ,.on_headers_complete = headers_complete_cb
1137
1409
  ,.on_message_complete = message_complete_cb
1138
1410
  };
1139
1411
 
1140
1412
 
1141
- int
1413
+ static int
1142
1414
  init_parser(client_t *cli, const char *name, const short port)
1143
1415
  {
1144
- VALUE object;
1145
- char r_port[7];
1146
-
1147
- cli->http = (http_parser*)ruby_xmalloc(sizeof(http_parser));
1148
- memset(cli->http, 0, sizeof(http_parser));
1149
-
1150
- cli->environ = rb_hash_new();
1151
-
1152
- rb_hash_aset(cli->environ, version_key, version_val);
1153
- rb_hash_aset(cli->environ, scheme_key, scheme_val);
1154
- rb_hash_aset(cli->environ, errors_key, errors_val);
1155
- rb_hash_aset(cli->environ, multithread_key, multithread_val);
1156
- rb_hash_aset(cli->environ, multiprocess_key, multiprocess_val);
1157
- rb_hash_aset(cli->environ, run_once_key, run_once_val);
1158
- rb_hash_aset(cli->environ, script_key, script_val);
1159
- rb_hash_aset(cli->environ, server_name_key, server_name_val);
1160
- rb_hash_aset(cli->environ, server_port_key, server_port_val);
1161
-
1162
- // query_string
1163
- rb_hash_aset(cli->environ, query_string, empty_string);
1164
-
1165
- object = rb_str_new2(cli->remote_addr);
1166
- rb_hash_aset(cli->environ, rb_remote_addr, object);
1167
-
1168
- sprintf(r_port, "%d", cli->remote_port);
1169
- object = rb_str_new2(r_port);
1170
- rb_hash_aset(cli->environ, rb_remote_port, object);
1171
-
1172
- http_parser_init(cli->http, HTTP_REQUEST);
1173
- cli->http->data = cli;
1416
+ cli->http_parser = (http_parser*)ruby_xmalloc(sizeof(http_parser));
1417
+ memset(cli->http_parser, 0, sizeof(http_parser));
1418
+ http_parser_init(cli->http_parser, HTTP_REQUEST);
1419
+ cli->http_parser->data = cli;
1174
1420
 
1175
1421
  return 0;
1176
1422
  }
1177
1423
 
1178
1424
 
1179
- size_t
1425
+ static size_t
1180
1426
  execute_parse(client_t *cli, const char *data, size_t len)
1181
1427
  {
1182
- return http_parser_execute(cli->http, &settings, data, len);
1428
+ return http_parser_execute(cli->http_parser, &settings, data, len);
1183
1429
  }
1184
1430
 
1185
1431
 
1186
- int
1432
+ static int
1187
1433
  parser_finish(client_t *cli)
1188
1434
  {
1189
1435
  return cli->complete;
1190
1436
  }
1191
1437
 
1192
1438
 
1193
- void
1439
+ static void
1194
1440
  setup_static_env(char *name, int port)
1195
1441
  {
1196
1442
  char vport[7];
1197
1443
 
1444
+ prefix_len = strlen("HTTP_");
1445
+
1198
1446
  version_val = rb_obj_freeze(rb_ary_new3(2, INT2FIX(1), INT2FIX(1)));
1199
1447
  version_key = rb_obj_freeze(rb_str_new2("rack.version"));
1200
1448
 
@@ -1234,8 +1482,39 @@ setup_static_env(char *name, int port)
1234
1482
  rack_input = rb_obj_freeze(rb_str_new2("rack.input"));
1235
1483
  http_connection = rb_obj_freeze(rb_str_new2("HTTP_CONNECTION"));
1236
1484
 
1485
+ content_type = rb_obj_freeze(rb_str_new2("CONTENT_TYPE"));
1486
+ content_length = rb_obj_freeze(rb_str_new2("CONTENT_LENGTH"));
1487
+
1488
+ h_content_type = rb_obj_freeze(rb_str_new2("HTTP_CONTENT_TYPE"));
1489
+ h_content_length = rb_obj_freeze(rb_str_new2("HTTP_CONTENT_LENGTH"));
1490
+
1491
+ http_10 = rb_obj_freeze(rb_str_new2("HTTP/1.0"));
1492
+ http_11 = rb_obj_freeze(rb_str_new2("HTTP/1.1"));
1493
+
1494
+ http_delete = rb_obj_freeze(rb_str_new2("DELETE"));
1495
+ http_get = rb_obj_freeze(rb_str_new2("GET"));
1496
+ http_head = rb_obj_freeze(rb_str_new2("HEAD"));
1497
+ http_post = rb_obj_freeze(rb_str_new2("POST"));
1498
+ http_put = rb_obj_freeze(rb_str_new2("PUT"));
1499
+ http_connect = rb_obj_freeze(rb_str_new2("CONNECT"));
1500
+ http_options = rb_obj_freeze(rb_str_new2("OPTIONS"));
1501
+ http_trace = rb_obj_freeze(rb_str_new2("TRACE"));
1502
+ http_copy = rb_obj_freeze(rb_str_new2("COPY"));
1503
+ http_lock = rb_obj_freeze(rb_str_new2("LOCK"));
1504
+ http_mkcol = rb_obj_freeze(rb_str_new2("MKCOL"));
1505
+ http_move = rb_obj_freeze(rb_str_new2("MOVE"));
1506
+ http_propfind= rb_obj_freeze(rb_str_new2("PROPFIND"));
1507
+ http_proppatch = rb_obj_freeze(rb_str_new2("PROPPATCH"));
1508
+ http_unlock = rb_obj_freeze(rb_str_new2("UNLOCK"));
1509
+ http_report = rb_obj_freeze(rb_str_new2("REPORT"));
1510
+ http_mkactivity = rb_obj_freeze(rb_str_new2("MKACTIVITY"));
1511
+ http_checkout = rb_obj_freeze(rb_str_new2("CHECKOUT"));
1512
+ http_merge = rb_obj_freeze(rb_str_new2("MERGE"));
1513
+
1237
1514
  http_user_agent = rb_obj_freeze(rb_str_new2("HTTP_USER_AGENT"));
1238
1515
  http_referer = rb_obj_freeze(rb_str_new2("HTTP_REFERER"));
1516
+
1517
+ http_expect = rb_obj_freeze(rb_str_new2("HTTP_EXPECT"));
1239
1518
  }
1240
1519
 
1241
1520
 
@@ -1250,10 +1529,10 @@ setsig(int sig, void* handler)
1250
1529
  }
1251
1530
 
1252
1531
 
1253
- void
1532
+ static void
1254
1533
  setup_listen_sock(int fd)
1255
1534
  {
1256
- int on = 1, r;
1535
+ int on = 1, r = -1;
1257
1536
  r = setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &on, sizeof(on));
1258
1537
  assert(r == 0);
1259
1538
  r = fcntl(fd, F_SETFL, O_NONBLOCK);
@@ -1261,42 +1540,30 @@ setup_listen_sock(int fd)
1261
1540
  }
1262
1541
 
1263
1542
 
1264
- static void
1543
+ static int
1265
1544
  setup_sock(int fd)
1266
1545
  {
1267
- int on = 1, r;
1546
+ int r;
1547
+ int on = 1;
1268
1548
  r = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
1269
- assert(r == 0);
1270
1549
 
1271
1550
  // 60 + 30 * 4
1272
- on = 300;
1273
- r = setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &on, sizeof(on));
1274
- assert(r == 0);
1275
- on = 30;
1276
- r = setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &on, sizeof(on));
1277
- assert(r == 0);
1278
- on = 4;
1279
- r = setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &on, sizeof(on));
1280
- assert(r == 0);
1281
-
1551
+ /* on = 300; */
1552
+ /* r = setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &on, sizeof(on)); */
1553
+ /* assert(r == 0); */
1554
+ /* on = 30; */
1555
+ /* r = setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &on, sizeof(on)); */
1556
+ /* assert(r == 0); */
1557
+ /* on = 4; */
1558
+ /* r = setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &on, sizeof(on)); */
1559
+ /* assert(r == 0); */
1560
+ #if linux
1561
+ r = 0; // Use accept4() on Linux
1562
+ #else
1282
1563
  r = fcntl(fd, F_SETFL, O_NONBLOCK);
1283
1564
  assert(r == 0);
1284
- }
1285
-
1286
-
1287
- static void
1288
- disable_cork(client_t *client)
1289
- {
1290
- int off = 0;
1291
- int on = 1, r;
1292
- #ifdef linux
1293
- r = setsockopt(client->fd, IPPROTO_TCP, TCP_CORK, &off, sizeof(off));
1294
- #elif defined(__APPLE__) || defined(__FreeBSD__)
1295
- r = setsockopt(client->fd, IPPROTO_TCP, TCP_NOPUSH, &off, sizeof(off));
1296
1565
  #endif
1297
- assert(r == 0);
1298
- r = setsockopt(client->fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
1299
- assert(r == 0);
1566
+ return r;
1300
1567
  }
1301
1568
 
1302
1569
 
@@ -1311,98 +1578,255 @@ new_client_t(int client_fd, char *remote_addr, uint32_t remote_port)
1311
1578
  client->fd = client_fd;
1312
1579
  client->remote_addr = remote_addr;
1313
1580
  client->remote_port = remote_port;
1314
- client->req = new_request();
1315
- client->body_type = BODY_TYPE_NONE;
1581
+ client->request_queue = new_request_queue();
1316
1582
  return client;
1317
1583
  }
1318
1584
 
1319
1585
 
1320
1586
  static void
1321
- clean_cli(client_t *client)
1587
+ clean_client(client_t *client)
1322
1588
  {
1323
- write_access_log(client, log_fd, log_path);
1324
- if(client->req){
1325
- free_request(client->req);
1326
- client->req = NULL;
1589
+ VALUE environ;
1590
+ uintptr_t end, delta_msec = 0;
1591
+
1592
+ request *req = client->current_req;
1593
+
1594
+ if(log_fd) {
1595
+ write_access_log(client, log_fd, log_path);
1596
+ if(req){
1597
+ environ = req->environ;
1598
+ end = current_msec;
1599
+ if (req->start_msec > 0){
1600
+ delta_msec = end - req->start_msec;
1601
+ }
1602
+ } else {
1603
+ if (client->status_code != 408) {
1604
+ environ = new_environ(client);
1605
+ }
1606
+ }
1327
1607
  }
1328
- DEBUG("close environ %p \n", client->environ);
1329
1608
 
1330
- // force clear
1331
- client->environ = rb_hash_new();
1609
+ if (req == NULL) {
1610
+ goto init;
1611
+ }
1332
1612
 
1333
- if(client->http != NULL){
1334
- ruby_xfree(client->http);
1335
- client->http = NULL;
1613
+ DEBUG("status_code:%d env:%p", client->status_code, req->environ);
1614
+ if (req->body) {
1615
+ req->body = NULL;
1336
1616
  }
1617
+ free_request(req);
1618
+ init:
1619
+ client->current_req = NULL;
1620
+ client->header_done = 0;
1621
+ client->response_closed = 0;
1622
+ client->chunked_response = 0;
1623
+ client->content_length_set = 0;
1624
+ client->content_length = 0;
1625
+ client->write_bytes = 0;
1337
1626
  }
1338
1627
 
1339
1628
 
1340
1629
  static void
1341
- close_conn(client_t *cli, picoev_loop* loop)
1630
+ close_client(client_t *client)
1342
1631
  {
1343
- client_t *new_client;
1344
- if(!cli->response_closed){
1345
- close_response(cli);
1632
+ client_t *new_client = NULL;
1633
+
1634
+ if (!client->response_closed) {
1635
+ close_response(client);
1346
1636
  }
1347
- picoev_del(loop, cli->fd);
1637
+ DEBUG("start close client:%p fd:%d status_code %d", client, client->fd, client->status_code);
1348
1638
 
1349
- DEBUG("picoev_del client:%p fd:%d \n", cli, cli->fd);
1350
- clean_cli(cli);
1351
- if(!cli->keep_alive){
1352
- close(cli->fd);
1353
- DEBUG("close client:%p fd:%d \n", cli, cli->fd);
1354
- }else{
1355
- disable_cork(cli);
1356
- new_client = new_client_t(cli->fd, cli->remote_addr, cli->remote_port);
1357
- rb_gc_register_address(&new_client->environ);
1639
+ if (picoev_is_active(main_loop, client->fd)) {
1640
+ picoev_del(main_loop, client->fd);
1641
+ DEBUG("picoev_del client:%p fd:%d", client, client->fd);
1642
+ }
1643
+
1644
+ clean_client(client);
1645
+
1646
+ DEBUG("remain http pipeline size :%d", client->request_queue->size);
1647
+ if (client->request_queue->size > 0) {
1648
+ /* if (check_status_code(client) > 0) { */
1649
+ //process pipeline
1650
+ prepare_call_rack(client);
1651
+ call_rack_app(client);
1652
+ /* } */
1653
+ return;
1654
+ }
1655
+
1656
+ if (client->http_parser != NULL) {
1657
+ ruby_xfree(client->http_parser);
1658
+ }
1659
+
1660
+ free_request_queue(client->request_queue);
1661
+ if (!client->keep_alive) {
1662
+ close(client->fd);
1663
+ BDEBUG("close client:%p fd:%d", client, client->fd);
1664
+ } else {
1665
+ BDEBUG("keep alive client:%p fd:%d", client, client->fd);
1666
+ new_client = new_client_t(client->fd, client->remote_addr, client->remote_port);
1358
1667
  new_client->keep_alive = 1;
1359
1668
  init_parser(new_client, server_name, server_port);
1360
1669
  picoev_add(main_loop, new_client->fd, PICOEV_READ, keep_alive_timeout, r_callback, (void *)new_client);
1361
1670
  }
1362
- ruby_xfree(cli);
1671
+ //clear old client
1672
+ ruby_xfree(client);
1673
+ }
1674
+
1675
+
1676
+ static void
1677
+ init_main_loop(void)
1678
+ {
1679
+ if (main_loop == NULL) {
1680
+ /* init picoev */
1681
+ picoev_init(max_fd);
1682
+ /* create loop */
1683
+ main_loop = picoev_create_loop(60);
1684
+ }
1685
+ }
1686
+
1687
+ static char*
1688
+ get_reason_phrase(int status_code)
1689
+ {
1690
+ if (status_code == 200) {
1691
+ return "OK";
1692
+ } else if (status_code == 201) {
1693
+ return "Created";
1694
+ } else if (status_code == 202) {
1695
+ return "Accepted";
1696
+ } else if (status_code == 203) {
1697
+ return "Non-Authoritative Information";
1698
+ } else if (status_code == 204) {
1699
+ return "No Content";
1700
+ } else if (status_code == 205) {
1701
+ return "Reset Content";
1702
+ } else if (status_code == 206) {
1703
+ return "Partial Content";
1704
+ } else if (status_code == 300) {
1705
+ return "Multiple Choices";
1706
+ } else if (status_code == 301) {
1707
+ return "Moved Permanently";
1708
+ } else if (status_code == 302) {
1709
+ return "Found";
1710
+ } else if (status_code == 303) {
1711
+ return "See Other";
1712
+ } else if (status_code == 304) {
1713
+ return "Not Modified";
1714
+ } else if (status_code == 305) {
1715
+ return "Use Proxy";
1716
+ } else if (status_code == 307) {
1717
+ return "Temporary Redirect";
1718
+ } else if (status_code == 400) {
1719
+ return "Bad Request";
1720
+ } else if (status_code == 401) {
1721
+ return "Unauthorized";
1722
+ } else if (status_code == 402) {
1723
+ return "Payment Required";
1724
+ } else if (status_code == 403) {
1725
+ return "Forbidden";
1726
+ } else if (status_code == 404) {
1727
+ return "Not Found";
1728
+ } else if (status_code == 405) {
1729
+ return "Method Not Allowed";
1730
+ } else if (status_code == 406) {
1731
+ return "Not Acceptable";
1732
+ } else if (status_code == 407) {
1733
+ return "Proxy Authentication Required";
1734
+ } else if (status_code == 408) {
1735
+ return "Request Time-out";
1736
+ } else if (status_code == 409) {
1737
+ return "Conflict";
1738
+ } else if (status_code == 410) {
1739
+ return "Gone";
1740
+ } else if (status_code == 411) {
1741
+ return "Length Required";
1742
+ } else if (status_code == 412) {
1743
+ return "Precondition Failed";
1744
+ } else if (status_code == 413) {
1745
+ return " Request Entity Too Large";
1746
+ } else if (status_code == 414) {
1747
+ return "Request-URI Too Large";
1748
+ } else if (status_code == 415) {
1749
+ return "Unsupported Media Type";
1750
+ } else if (status_code == 416) {
1751
+ return "Requested range not satisfiable";
1752
+ } else if (status_code == 417) {
1753
+ return "Expectation Failed";
1754
+ } else if (status_code == 500) {
1755
+ return "Internal Server Error";
1756
+ } else if (status_code == 501) {
1757
+ return "Not Implemented";
1758
+ } else if (status_code == 502) {
1759
+ return "Bad Gateway";
1760
+ } else if (status_code == 503) {
1761
+ return "Service Unavailable";
1762
+ } else if (status_code == 504) {
1763
+ return "Gateway Time-out";
1764
+ } else if (status_code == 505) {
1765
+ return "HTTP Version not supported";
1766
+ } else {
1767
+ return "Unknown";
1768
+ }
1363
1769
  }
1364
1770
 
1365
1771
 
1366
1772
  static int
1367
1773
  process_rack_app(client_t *cli)
1368
1774
  {
1369
- VALUE args;
1370
- char *status;
1775
+ VALUE env, response_arr, status_code, headers, response_body;
1776
+ request *req = cli->current_req;
1371
1777
 
1372
- args = cli->environ;
1778
+ env = req->environ;
1373
1779
 
1374
1780
  // cli->response = [200, {}, []]
1375
- cli->response = rb_funcall(rack_app, i_call, 1, args);
1781
+ response_arr = rb_funcall(rack_app, i_call, 1, env);
1782
+
1783
+ // to_arr
1784
+ if (TYPE(response_arr) != T_ARRAY) {
1785
+ response_arr = rb_funcall(response_arr, i_toa, 0);
1786
+ }
1376
1787
 
1377
- if(TYPE(cli->response) != T_ARRAY || RARRAY_LEN(cli->response) < 3) {
1788
+ if(RARRAY_LEN(response_arr) < 3) {
1378
1789
  return 0;
1379
1790
  }
1380
1791
 
1381
- VALUE* response_ary = RARRAY_PTR(cli->response);
1382
-
1383
- /* rb_p(cli->response); */
1792
+ status_code = rb_ary_entry(response_arr, 0);
1793
+ headers = rb_ary_entry(response_arr, 1);
1794
+ response_body = rb_ary_entry(response_arr, 2);
1384
1795
 
1385
- if (TYPE(response_ary[0]) != T_FIXNUM ||
1386
- TYPE(response_ary[1]) != T_HASH) {
1796
+ if (TYPE(status_code) != T_FIXNUM ||
1797
+ TYPE(headers) != T_HASH ||
1798
+ rb_respond_to(response_body, i_each) == 0) {
1387
1799
  return 0;
1388
1800
  }
1389
1801
 
1390
- cli->status_code = NUM2INT(response_ary[0]);
1391
- cli->headers = response_ary[1];
1802
+ cli->status_code = NUM2INT(status_code);
1803
+ cli->headers = headers;
1804
+ cli->response_iter = rb_funcall(response_body, i_toenum, 0);
1805
+
1806
+ rb_gc_register_address(&cli->headers);
1807
+ rb_gc_register_address(&cli->response_iter);
1808
+
1809
+ if (cli->response_closed) {
1810
+ //closed
1811
+ close_client(cli);
1812
+ return 1;
1813
+ }
1392
1814
 
1393
1815
  errno = 0;
1394
1816
  /* printf("status code: %d\n", cli->status_code); */
1395
1817
 
1818
+ char* reason_phrase;
1819
+ reason_phrase = get_reason_phrase(cli->status_code);
1820
+
1396
1821
  char buff[256];
1397
- sprintf(buff, "HTTP/1.1 %d\r\n", cli->status_code);
1822
+ sprintf(buff, "HTTP/1.%d %d %s\r\n", cli->http_parser->http_minor, cli->status_code, reason_phrase);
1398
1823
  cli->http_status = rb_str_new(buff, strlen(buff));
1399
1824
 
1400
1825
  //check response
1401
1826
  if(cli->response && cli->response == Qnil){
1402
1827
  write_error_log(__FILE__, __LINE__);
1403
- rb_raise(rb_eException, "response must be a iter or sequence object");
1828
+ return 0;
1404
1829
  }
1405
-
1406
1830
  return 1;
1407
1831
  }
1408
1832
 
@@ -1417,85 +1841,256 @@ w_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
1417
1841
  YDEBUG("** w_callback timeout ** \n");
1418
1842
  //timeout
1419
1843
  client->keep_alive = 0;
1420
- close_conn(client, loop);
1844
+ close_client(client);
1421
1845
 
1422
1846
  } else if ((events & PICOEV_WRITE) != 0) {
1423
1847
  ret = process_body(client);
1424
- picoev_set_timeout(loop, client->fd, WRITE_TIMEOUT_SECS);
1848
+ /* picoev_set_timeout(loop, client->fd, WRITE_TIMEOUT_SECS); */
1425
1849
  DEBUG("process_body ret %d \n", ret);
1426
1850
  if(ret != 0){
1427
1851
  //ok or die
1428
- close_conn(client, loop);
1852
+ close_client(client);
1429
1853
  }
1430
1854
  }
1431
1855
  }
1432
1856
 
1433
1857
 
1434
- static void
1435
- call_rack_app(client_t *client, picoev_loop* loop)
1858
+ static int
1859
+ check_http_expect(client_t *client)
1436
1860
  {
1861
+ VALUE c;
1862
+ char *val = NULL;
1437
1863
  int ret;
1864
+ request *req = client->current_req;
1865
+
1866
+ if (client->http_parser->http_minor == 1) {
1867
+ ///TODO CHECK
1868
+ c = rb_hash_aref(req->environ, http_expect);
1869
+ if (c != Qnil) {
1870
+ val = StringValuePtr(c);
1871
+ if (!strncasecmp(val, "100-continue", 12)) {
1872
+ ret = write(client->fd, "HTTP/1.1 100 Continue\r\n\r\n", 25);
1873
+ if (ret < 0) {
1874
+ //fail
1875
+ client->keep_alive = 0;
1876
+ client->status_code = 500;
1877
+ send_error_page(client);
1878
+ close_client(client);
1879
+ return -1;
1880
+ }
1881
+ } else {
1882
+ //417
1883
+ client->keep_alive = 0;
1884
+ client->status_code = 417;
1885
+ send_error_page(client);
1886
+ close_client(client);
1887
+ return -1;
1888
+ }
1889
+ }
1890
+ return 1;
1891
+ }
1892
+ return 0;
1893
+ }
1894
+
1895
+
1896
+ static void
1897
+ call_rack_app(client_t *client)
1898
+ {
1899
+ response_status ret;
1900
+ request *req = client->current_req;
1901
+
1438
1902
  if(!process_rack_app(client)){
1439
1903
  //Internal Server Error
1440
- client->bad_request_code = 500;
1904
+ req->bad_request_code = 500;
1441
1905
  send_error_page(client);
1442
- close_conn(client, loop);
1906
+ close_client(client);
1443
1907
  return;
1444
1908
  }
1445
1909
 
1446
1910
  ret = response_start(client);
1447
1911
  switch(ret){
1448
- case -1:
1912
+ case STATUS_ERROR:
1449
1913
  // Internal Server Error
1450
- client->bad_request_code = 500;
1914
+ client->status_code = 500;
1451
1915
  send_error_page(client);
1452
- close_conn(client, loop);
1916
+ close_client(client);
1453
1917
  return;
1454
- case 0:
1918
+ case STATUS_SUSPEND:
1455
1919
  // continue
1456
1920
  // set callback
1457
1921
  DEBUG("set write callback %d \n", ret);
1458
1922
  //clear event
1459
- picoev_del(loop, client->fd);
1460
- picoev_add(loop, client->fd, PICOEV_WRITE, WRITE_TIMEOUT_SECS, w_callback, (void *)client);
1923
+ picoev_del(main_loop, client->fd);
1924
+ picoev_add(main_loop, client->fd, PICOEV_WRITE, WRITE_TIMEOUT_SECS, w_callback, (void *)client);
1461
1925
  return;
1462
1926
  default:
1463
1927
  // send OK
1464
- close_conn(client, loop);
1928
+ close_client(client);
1465
1929
  }
1466
1930
  }
1467
1931
 
1468
1932
 
1933
+ static inline void
1934
+ set_current_request(client_t *client)
1935
+ {
1936
+ request *req;
1937
+ req = shift_request(client->request_queue);
1938
+ client->current_req = req;
1939
+ }
1940
+
1941
+
1469
1942
  static void
1470
1943
  prepare_call_rack(client_t *client)
1471
1944
  {
1472
- VALUE input, object, c;
1473
- char *val;
1945
+ request *req = NULL;
1946
+ VALUE input, object;
1947
+
1948
+ set_current_request(client);
1949
+ req = client->current_req;
1950
+
1951
+ //check Expect
1952
+ if (check_http_expect(client) < 0) {
1953
+ return;
1954
+ }
1474
1955
 
1475
- if(client->body_type == BODY_TYPE_BUFFER) {
1476
- rb_funcall((VALUE)client->body, i_seek, 1, INT2NUM(0));
1477
- rb_hash_aset(client->environ, rack_input, (VALUE)client->body);
1956
+ if(req->body_type == BODY_TYPE_BUFFER) {
1957
+ rb_funcall((VALUE)req->body, i_seek, 1, INT2NUM(0));
1958
+ rb_hash_aset(req->environ, rack_input, (VALUE)req->body);
1478
1959
  } else {
1479
1960
  object = rb_str_new2("");
1480
1961
  input = rb_funcall(StringIO, i_new, 1, object);
1481
1962
  rb_gc_register_address(&input);
1482
- rb_hash_aset(client->environ, rack_input, input);
1483
- client->body = input;
1963
+ rb_hash_aset(req->environ, rack_input, input);
1964
+ req->body = input;
1484
1965
  }
1485
1966
 
1486
- if(is_keep_alive){
1487
- //support keep-alive
1488
- c = rb_hash_aref(client->environ, http_connection);
1489
- if(c != Qnil){
1490
- val = StringValuePtr(c);
1491
- if(!strcasecmp(val, "keep-alive")){
1492
- client->keep_alive = 1;
1493
- }else{
1494
- client->keep_alive = 0;
1495
- }
1496
- }else{
1967
+ if(!is_keep_alive){
1968
+ client->keep_alive = 0;
1969
+ }
1970
+ }
1971
+
1972
+
1973
+ static void
1974
+ set_bad_request_code(client_t *client, int status_code)
1975
+ {
1976
+ request *req;
1977
+ req = client->request_queue->tail;
1978
+ req->bad_request_code = status_code;
1979
+ DEBUG("set bad request code %d", status_code);
1980
+ }
1981
+
1982
+
1983
+ static int
1984
+ check_status_code(client_t *client)
1985
+ {
1986
+ request *req;
1987
+ req = client->request_queue->head;
1988
+ if (req && req->bad_request_code > 200) {
1989
+ //error
1990
+ //shift
1991
+ DEBUG("bad status code %d", req->bad_request_code);
1992
+ set_current_request(client);
1993
+ client->status_code = req->bad_request_code;
1994
+ send_error_page(client);
1995
+ close_client(client);
1996
+ return -1;
1997
+ }
1998
+ return 1;
1999
+ }
2000
+
2001
+
2002
+ static int
2003
+ set_read_error(client_t *client, int status_code)
2004
+ {
2005
+ client->keep_alive = 0;
2006
+ if (status_code == 0) {
2007
+ // bad request
2008
+ status_code = 400;
2009
+ }
2010
+ if (client->request_queue->size > 0) {
2011
+ //piplining
2012
+ set_bad_request_code(client, status_code);
2013
+ return 1;
2014
+ } else {
2015
+ client->status_code = status_code;
2016
+ send_error_page(client);
2017
+ close_client(client);
2018
+ return -1;
2019
+ }
2020
+ }
2021
+
2022
+
2023
+ static int
2024
+ read_timeout(int fd, client_t *client)
2025
+ {
2026
+ RDEBUG("** read timeout fd:%d", fd);
2027
+ //timeout
2028
+ return set_read_error(client, 408);
2029
+ }
2030
+
2031
+
2032
+ static int
2033
+ parse_http_request(int fd, client_t *client, char *buf, ssize_t r)
2034
+ {
2035
+ int nread = 0;
2036
+ request *req = NULL;
2037
+
2038
+ BDEBUG("fd:%d \n%.*s", fd, (int)r, buf);
2039
+ nread = execute_parse(client, buf, r);
2040
+ BDEBUG("read request fd %d readed %d nread %d", fd, (int)r, nread);
2041
+
2042
+ req = client->current_req;
2043
+
2044
+ if (nread != r || req->bad_request_code > 0) {
2045
+ if (req == NULL) {
2046
+ DEBUG("fd %d bad_request code 400", fd);
2047
+ return set_read_error(client, 400);
2048
+ } else {
2049
+ DEBUG("fd %d bad_request code %d", fd, req->bad_request_code);
2050
+ return set_read_error(client, req->bad_request_code);
2051
+ }
2052
+ }
2053
+
2054
+ if (parser_finish(client) > 0) {
2055
+ return 1;
2056
+ }
2057
+ return 0;
2058
+ }
2059
+
2060
+
2061
+ static int
2062
+ read_request(picoev_loop *loop, int fd, client_t *client, char call_time_update)
2063
+ {
2064
+ char buf[READ_BUF_SIZE];
2065
+ ssize_t r;
2066
+
2067
+ if (!client->keep_alive) {
2068
+ picoev_set_timeout(loop, fd, READ_TIMEOUT_SECS);
2069
+ }
2070
+
2071
+ r = read(client->fd, buf, sizeof(buf));
2072
+ switch (r) {
2073
+ case 0:
2074
+ return set_read_error(client, 503);
2075
+ case -1:
2076
+ // Error
2077
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
2078
+ // try again later
2079
+ return 0;
2080
+ } else {
2081
+ // Fatal error
1497
2082
  client->keep_alive = 0;
2083
+ if (errno == ECONNRESET) {
2084
+ client->header_done = 1;
2085
+ client->response_closed = 1;
2086
+ }
2087
+ return set_read_error(client, 500);
2088
+ }
2089
+ default:
2090
+ if (call_time_update) {
2091
+ cache_time_update();
1498
2092
  }
2093
+ return parse_http_request(fd, client, buf, r);
1499
2094
  }
1500
2095
  }
1501
2096
 
@@ -1504,85 +2099,22 @@ static void
1504
2099
  r_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
1505
2100
  {
1506
2101
  client_t *cli = ( client_t *)(cb_arg);
2102
+ int finish = 0;
2103
+
1507
2104
  if ((events & PICOEV_TIMEOUT) != 0) {
1508
- YDEBUG("** r_callback timeout ** \n");
1509
- //timeout
1510
- cli->keep_alive = 0;
1511
- close_conn(cli, loop);
1512
- } else if ((events & PICOEV_READ) != 0) {
1513
- RDEBUG("ready read \n");
1514
- /* update timeout, and read */
1515
- int finish = 0, nread;
1516
- char buf[INPUT_BUF_SIZE];
1517
- ssize_t r;
1518
- if(!cli->keep_alive){
1519
- picoev_set_timeout(loop, cli->fd, SHORT_TIMEOUT_SECS);
1520
- }
1521
- r = read(cli->fd, buf, sizeof(buf));
1522
- switch (r) {
1523
- case 0:
1524
- cli->keep_alive = 0;
1525
- cli->status_code = 500; // ??? 503 ??
1526
- send_error_page(cli);
1527
- close_conn(cli, loop);
1528
- return;
1529
- case -1: /* error */
1530
- if (errno == EAGAIN || errno == EWOULDBLOCK) { /* try again later */
1531
- break;
1532
- } else { /* fatal error */
1533
- if (cli->keep_alive && errno == ECONNRESET) {
1534
- cli->keep_alive = 0;
1535
- cli->status_code = 500;
1536
- cli->header_done = 1;
1537
- cli->response_closed = 1;
1538
- } else {
1539
- /* rb_raise(rb_eException, "fatal error"); */
1540
- write_error_log(__FILE__, __LINE__);
1541
- cli->keep_alive = 0;
1542
- cli->status_code = 500;
1543
- if(errno != ECONNRESET){
1544
- send_error_page(cli);
1545
- }else{
1546
- cli->header_done = 1;
1547
- cli->response_closed = 1;
1548
- }
1549
- }
1550
- close_conn(cli, loop);
1551
- return;
1552
- }
1553
- break;
1554
- default:
1555
- RDEBUG("read request fd %d bufsize %d \n", cli->fd, r);
1556
- nread = execute_parse(cli, buf, r);
1557
-
1558
- if(cli->bad_request_code > 0){
1559
- RDEBUG("fd %d bad_request code %d \n", cli->fd, cli->bad_request_code);
1560
- send_error_page(cli);
1561
- close_conn(cli, loop);
1562
- return;
1563
- }
1564
- if( nread != r ){
1565
- // parse error
1566
- DEBUG("fd %d parse error %d \n", cli->fd, cli->bad_request_code);
1567
- cli->bad_request_code = 400;
1568
- send_error_page(cli);
1569
- close_conn(cli, loop);
1570
- return;
1571
- }
1572
- RDEBUG("parse ok, fd %d %d nread \n", cli->fd, nread);
2105
+ finish = read_timeout(fd, cli);
1573
2106
 
1574
- if(parser_finish(cli) > 0){
1575
- finish = 1;
1576
- }
1577
- break;
1578
- }
1579
-
1580
- if(finish == 1){
1581
- /* picoev_del(loop, cli->fd); */
2107
+ } else if ((events & PICOEV_READ) != 0) {
2108
+ finish = read_request(loop, fd, cli, 0);
2109
+ }
2110
+ if(finish == 1){
2111
+ picoev_del(loop, cli->fd);
2112
+ RDEBUG("del fd: %d", cli->fd);
2113
+ if (check_status_code(cli) > 0) {
1582
2114
  prepare_call_rack(cli);
1583
- call_rack_app(cli, loop);
1584
- return;
2115
+ call_rack_app(cli);
1585
2116
  }
2117
+ return;
1586
2118
  }
1587
2119
  }
1588
2120
 
@@ -1595,6 +2127,7 @@ accept_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
1595
2127
  struct sockaddr_in client_addr;
1596
2128
  char *remote_addr;
1597
2129
  uint32_t remote_port;
2130
+ int finish = 0;
1598
2131
 
1599
2132
  if ((events & PICOEV_TIMEOUT) != 0) {
1600
2133
  // time out
@@ -1602,25 +2135,44 @@ accept_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
1602
2135
  return;
1603
2136
  }else if ((events & PICOEV_READ) != 0) {
1604
2137
  socklen_t client_len = sizeof(client_addr);
2138
+ for(;;) {
1605
2139
  #ifdef linux
1606
- client_fd = accept4(fd, (struct sockaddr *)&client_addr, &client_len, SOCK_NONBLOCK | SOCK_CLOEXEC);
2140
+ client_fd = accept4(fd, (struct sockaddr *)&client_addr, &client_len, SOCK_NONBLOCK | SOCK_CLOEXEC);
1607
2141
  #else
1608
- client_fd = accept(fd, (struct sockaddr *)&client_addr, &client_len);
2142
+ client_fd = accept(fd, (struct sockaddr *)&client_addr, &client_len);
1609
2143
  #endif
1610
- if (client_fd != -1) {
1611
- DEBUG("accept fd %d \n", client_fd);
1612
- setup_sock(client_fd);
1613
- remote_addr = inet_ntoa(client_addr.sin_addr);
1614
- remote_port = ntohs(client_addr.sin_port);
1615
- client = new_client_t(client_fd, remote_addr, remote_port);
1616
- rb_gc_register_address(&client->environ);
1617
- init_parser(client, server_name, server_port);
1618
- picoev_add(loop, client_fd, PICOEV_READ, keep_alive_timeout, r_callback, (void *)client);
1619
- }else{
1620
- if (errno != EAGAIN && errno != EWOULDBLOCK) {
1621
- write_error_log(__FILE__, __LINE__);
1622
- // die
1623
- loop_done = 0;
2144
+ if (client_fd != -1) {
2145
+ DEBUG("accept fd %d \n", client_fd);
2146
+
2147
+ if (setup_sock(client_fd) == -1) {
2148
+ write_error_log(__FILE__, __LINE__);
2149
+ // die
2150
+ loop_done = 0;
2151
+ return;
2152
+ }
2153
+
2154
+ remote_addr = inet_ntoa(client_addr.sin_addr);
2155
+ remote_port = ntohs(client_addr.sin_port);
2156
+ client = new_client_t(client_fd, remote_addr, remote_port);
2157
+ init_parser(client, server_name, server_port);
2158
+
2159
+ finish = read_request(loop, fd, client, 1);
2160
+ if (finish == 1) {
2161
+ if (check_status_code(client) > 0) {
2162
+ //current request ok
2163
+ prepare_call_rack(client);
2164
+ call_rack_app(client);
2165
+ }
2166
+ } else if (finish == 0) {
2167
+ picoev_add(loop, client_fd, PICOEV_READ, keep_alive_timeout, r_callback, (void *)client);
2168
+ }
2169
+ } else {
2170
+ if (errno != EAGAIN && errno != EWOULDBLOCK) {
2171
+ write_error_log(__FILE__, __LINE__);
2172
+ // die
2173
+ loop_done = 0;
2174
+ }
2175
+ break;
1624
2176
  }
1625
2177
  }
1626
2178
  }
@@ -1660,7 +2212,6 @@ inet_listen(void)
1660
2212
  for(p = servinfo; p != NULL; p = p->ai_next) {
1661
2213
  if ((listen_sock = socket(p->ai_family, p->ai_socktype,
1662
2214
  p->ai_protocol)) == -1) {
1663
- //perror("server: socket");
1664
2215
  continue;
1665
2216
  }
1666
2217
 
@@ -1677,10 +2228,9 @@ inet_listen(void)
1677
2228
  break;
1678
2229
  }
1679
2230
 
1680
- if (p == NULL) {
2231
+ if (p == NULL) {
1681
2232
  close(listen_sock);
1682
2233
  rb_raise(rb_eIOError, "server: failed to bind\n");
1683
- return -1;
1684
2234
  }
1685
2235
 
1686
2236
  freeaddrinfo(servinfo); // all done with this structure
@@ -1848,9 +2398,7 @@ bossan_run_loop(VALUE self, VALUE args)
1848
2398
  rack_app = args;
1849
2399
 
1850
2400
  /* init picoev */
1851
- picoev_init(max_fd);
1852
- /* create loop */
1853
- main_loop = picoev_create_loop(60);
2401
+ init_main_loop();
1854
2402
  loop_done = 1;
1855
2403
 
1856
2404
  setsig(SIGPIPE, sigpipe_cb);
@@ -1863,6 +2411,7 @@ bossan_run_loop(VALUE self, VALUE args)
1863
2411
  while (loop_done) {
1864
2412
  picoev_loop_once(main_loop, 10);
1865
2413
  }
2414
+
1866
2415
  picoev_destroy_loop(main_loop);
1867
2416
  picoev_deinit();
1868
2417
 
@@ -1874,7 +2423,7 @@ bossan_run_loop(VALUE self, VALUE args)
1874
2423
  }
1875
2424
 
1876
2425
 
1877
- VALUE
2426
+ static VALUE
1878
2427
  bossan_set_max_content_length(VALUE self, VALUE args)
1879
2428
  {
1880
2429
  max_content_length = NUM2INT(args);
@@ -1882,21 +2431,21 @@ bossan_set_max_content_length(VALUE self, VALUE args)
1882
2431
  }
1883
2432
 
1884
2433
 
1885
- VALUE
2434
+ static VALUE
1886
2435
  bossan_get_max_content_length(VALUE self)
1887
2436
  {
1888
2437
  return INT2NUM(max_content_length);
1889
2438
  }
1890
2439
 
1891
2440
 
1892
- VALUE
2441
+ static VALUE
1893
2442
  bossan_set_keepalive(VALUE self, VALUE args)
1894
2443
  {
1895
2444
  int on;
1896
2445
 
1897
2446
  on = NUM2INT(args);
1898
2447
  if(on < 0){
1899
- rb_p("keep alive value out of range.\n");
2448
+ printf("keep alive value out of range.\n");
1900
2449
  return Qfalse;
1901
2450
  }
1902
2451
 
@@ -1911,14 +2460,14 @@ bossan_set_keepalive(VALUE self, VALUE args)
1911
2460
  }
1912
2461
 
1913
2462
 
1914
- VALUE
2463
+ static VALUE
1915
2464
  bossan_get_keepalive(VALUE self)
1916
2465
  {
1917
2466
  return INT2NUM(is_keep_alive);
1918
2467
  }
1919
2468
 
1920
2469
 
1921
- VALUE
2470
+ static VALUE
1922
2471
  bossan_set_picoev_max_fd(VALUE self, VALUE args)
1923
2472
  {
1924
2473
  int temp;
@@ -1931,14 +2480,14 @@ bossan_set_picoev_max_fd(VALUE self, VALUE args)
1931
2480
  }
1932
2481
 
1933
2482
 
1934
- VALUE
2483
+ static VALUE
1935
2484
  bossan_get_picoev_max_fd(VALUE self)
1936
2485
  {
1937
2486
  return INT2NUM(max_fd);
1938
2487
  }
1939
2488
 
1940
2489
 
1941
- VALUE
2490
+ static VALUE
1942
2491
  bossan_set_backlog(VALUE self, VALUE args)
1943
2492
  {
1944
2493
  int temp;
@@ -1951,7 +2500,7 @@ bossan_set_backlog(VALUE self, VALUE args)
1951
2500
  }
1952
2501
 
1953
2502
 
1954
- VALUE
2503
+ static VALUE
1955
2504
  bossan_get_backlog(VALUE self)
1956
2505
  {
1957
2506
  return INT2NUM(backlog);
@@ -1992,17 +2541,47 @@ Init_bossan_ext(void)
1992
2541
  rb_gc_register_address(&rack_input);
1993
2542
  rb_gc_register_address(&http_connection);
1994
2543
 
2544
+ rb_gc_register_address(&h_content_type);
2545
+ rb_gc_register_address(&h_content_length);
2546
+ rb_gc_register_address(&content_type);
2547
+ rb_gc_register_address(&content_length);
2548
+
2549
+ rb_gc_register_address(&http_10);
2550
+ rb_gc_register_address(&http_11);
2551
+
2552
+ rb_gc_register_address(&http_delete);
2553
+ rb_gc_register_address(&http_get);
2554
+ rb_gc_register_address(&http_head);
2555
+ rb_gc_register_address(&http_post);
2556
+ rb_gc_register_address(&http_put);
2557
+ rb_gc_register_address(&http_connect);
2558
+ rb_gc_register_address(&http_options);
2559
+ rb_gc_register_address(&http_trace);
2560
+ rb_gc_register_address(&http_copy);
2561
+ rb_gc_register_address(&http_lock);
2562
+ rb_gc_register_address(&http_mkcol);
2563
+ rb_gc_register_address(&http_move);
2564
+ rb_gc_register_address(&http_propfind);
2565
+ rb_gc_register_address(&http_proppatch);
2566
+ rb_gc_register_address(&http_unlock);
2567
+ rb_gc_register_address(&http_report);
2568
+ rb_gc_register_address(&http_mkactivity);
2569
+ rb_gc_register_address(&http_checkout);
2570
+ rb_gc_register_address(&http_merge);
2571
+
1995
2572
  rb_gc_register_address(&http_user_agent);
1996
2573
  rb_gc_register_address(&http_referer);
1997
2574
 
2575
+ rb_gc_register_address(&http_expect);
2576
+
1998
2577
  empty_string = rb_obj_freeze(rb_str_new2(""));
1999
2578
  rb_gc_register_address(&empty_string);
2000
2579
 
2001
2580
  rb_gc_register_address(&i_keys);
2002
2581
  rb_gc_register_address(&i_call);
2003
2582
  rb_gc_register_address(&i_new);
2004
- rb_gc_register_address(&i_key);
2005
2583
  rb_gc_register_address(&i_each);
2584
+ rb_gc_register_address(&i_toenum);
2006
2585
  rb_gc_register_address(&i_close);
2007
2586
  rb_gc_register_address(&i_write);
2008
2587
  rb_gc_register_address(&i_seek);
@@ -2012,11 +2591,13 @@ Init_bossan_ext(void)
2012
2591
  i_new = rb_intern("new");
2013
2592
  i_call = rb_intern("call");
2014
2593
  i_keys = rb_intern("keys");
2015
- i_key = rb_intern("key?");
2016
2594
  i_each = rb_intern("each");
2595
+ i_toenum = rb_intern("to_enum");
2017
2596
  i_close = rb_intern("close");
2018
2597
  i_write = rb_intern("write");
2019
2598
  i_seek = rb_intern("seek");
2599
+ i_toa = rb_intern("to_a");
2600
+ i_next = rb_intern("next");
2020
2601
 
2021
2602
  server = rb_define_module("Bossan");
2022
2603
  rb_gc_register_address(&server);