bossan 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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);