bossan 0.1.8 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NTI5NjNkNTJkYmMwYmY0NDk5OGFkZDIyYzU1NzQxYWU1NGM3ODcxYw==
5
+ data.tar.gz: !binary |-
6
+ NjBmZmUxYjczNTM0YzllYjRmMmI4MzM3Mzc0MjkyZmQ1MDU2MmI4Ng==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NjJjMzk1YTlhMjM4OTgxYjU4MWUwODY1ZmZhNWQzY2M3YzU4ZjA0N2U0ODIx
10
+ MzUzODU0MDYxZmM2YTBhMzlkZjVjNGMyOTU0YjY2MGJiYzlmYTI1YWZlZTZh
11
+ M2ZjNjBiZWMxZmRlZjE0YzNlNjNlNjE2ODhkZjMxMzM4MjE1MGE=
12
+ data.tar.gz: !binary |-
13
+ NWQ4YTdkNmNjODVkZTgyZGQxNzdhMjk5NjViYzk1ZjliYjQwODY2OGI1MTI0
14
+ MTgxMjlkNDA2MzRkNzJlNDY4MDNmMTViODJmM2ZmNDY4MTFiNjYyNzIyYzlk
15
+ MThmNWY4Mjg4NGI5YzgyOWY1OGFhMDlhOGEzYTE2OTRkNzA1ZGE=
data/.gitignore CHANGED
@@ -20,4 +20,5 @@ tmp
20
20
  Makefile
21
21
  *.log
22
22
  *.db
23
+ *.pid
23
24
  TAGS
data/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # CHANGELOG
2
+
3
+ ### v0.2.0
4
+
5
+ (New Feature release. rerelease 2013-05-22)
6
+
7
+ * support keep-alive (use Bossan.set_keepalive)
8
+
9
+ * use TCP_DEFER_ACCEPT
10
+
11
+ * add set_backlog (default:1024)
12
+
13
+ * add set_picoev_max_fd (default:1024)
data/README.md CHANGED
@@ -8,7 +8,7 @@ Bossan is a high performance asynchronous ruby's rack-compliant web server.
8
8
 
9
9
  Bossan requires Ruby 1.9.2 or later.
10
10
 
11
- Bossan supports Linux, FreeBSD and Mac OS X(need gcc>=4.2).
11
+ Bossan supports Linux, FreeBSD and MacOSX(need gcc>=4.2).
12
12
 
13
13
  ## Installation
14
14
 
@@ -16,7 +16,7 @@ from rubygems
16
16
 
17
17
  `gem install bossan`
18
18
 
19
- or from source:
19
+ from source(github)
20
20
 
21
21
  ```
22
22
  git clone git://github.com/kubo39/bossan.git
data/Rakefile CHANGED
@@ -13,7 +13,7 @@ end
13
13
 
14
14
  task :clean do
15
15
  Dir.chdir File.expand_path("../ext/bossan", __FILE__)
16
- sh "rm -f *.o Makefile"
16
+ sh "rm -f *.o Makefile mkmf.log"
17
17
  end
18
18
 
19
19
  task :test do
data/TODO ADDED
@@ -0,0 +1,6 @@
1
+ * add picoev_max_fd setter, getter
2
+
3
+ * set rack.input File-type object, if over 512K
4
+ - avoid too much use memory
5
+
6
+ * or else...
data/examples/hello.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'bossan'
1
+ require_relative '../lib/bossan'
2
2
 
3
3
  Bossan.run('127.0.0.1', 8000, proc {|env|
4
4
  body = 'hello, world!'
@@ -1,4 +1,4 @@
1
- require 'bossan'
1
+ require_relative '../lib/bossan'
2
2
  require 'sinatra/base'
3
3
 
4
4
  class App < Sinatra::Base
@@ -1,4 +1,4 @@
1
- require 'bossan'
1
+ require_relative '../lib/bossan'
2
2
  require 'sinatra/base'
3
3
  require 'haml'
4
4
 
@@ -0,0 +1,75 @@
1
+ #ifndef BOSSAN_H
2
+ #define BOSSAN_H
3
+
4
+ #include "ruby.h"
5
+ #include <assert.h>
6
+ #include <fcntl.h>
7
+ #include <stddef.h>
8
+ #include <unistd.h>
9
+ #include <errno.h>
10
+ #include <arpa/inet.h>
11
+ #include <signal.h>
12
+ #include <sys/socket.h>
13
+ #include <sys/types.h>
14
+ #ifdef linux
15
+ #include <sys/prctl.h>
16
+ #elif defined(__APPLE__) || defined(__FreeBSD__)
17
+ #include <sys/uio.h>
18
+ #endif
19
+ #include <sys/un.h>
20
+ #include <sys/stat.h>
21
+ #include <sys/file.h>
22
+ #include <netinet/in.h>
23
+ #include <netinet/tcp.h>
24
+ #include <netdb.h>
25
+
26
+ /* #define DEVELOP */
27
+
28
+ #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)
59
+ #else
60
+ #define DEBUG(...) do{}while(0)
61
+ #define RDEBUG(...) do{}while(0)
62
+ #define GDEBUG(...) do{}while(0)
63
+ #define BDEBUG(...) do{}while(0)
64
+ #define YDEBUG(...) do{}while(0)
65
+ #endif
66
+
67
+ #if __GNUC__ >= 3
68
+ # define likely(x) __builtin_expect(!!(x), 1)
69
+ # define unlikely(x) __builtin_expect(!!(x), 0)
70
+ #else
71
+ # define likely(x) (x)
72
+ # define unlikely(x) (x)
73
+ #endif
74
+
75
+ #endif
@@ -1,25 +1,4 @@
1
- #include "ruby.h"
2
- #include <assert.h>
3
- #include <fcntl.h>
4
- #include <stddef.h>
5
- #include <unistd.h>
6
- #include <errno.h>
7
- #include <arpa/inet.h>
8
- #include <signal.h>
9
- #include <sys/socket.h>
10
- #include <sys/types.h>
11
- #ifdef linux
12
- #include <sys/sendfile.h>
13
- #include <sys/prctl.h>
14
- #elif defined(__APPLE__) || defined(__FreeBSD__)
15
- #include <sys/uio.h>
16
- #endif
17
- #include <sys/un.h>
18
- #include <sys/stat.h>
19
- #include <sys/file.h>
20
- #include <netinet/in.h>
21
- #include <netinet/tcp.h>
22
- #include <netdb.h>
1
+ #include "bossan.h"
23
2
 
24
3
  #include "time_cache.h"
25
4
  #include "http_parser.h"
@@ -27,13 +6,11 @@
27
6
  #include "buffer.h"
28
7
  #include "client.h"
29
8
 
30
- #define MAX_FDS 1024 * 8
31
9
  #define ACCEPT_TIMEOUT_SECS 1
32
10
  #define SHORT_TIMEOUT_SECS 2
33
11
  #define WRITE_TIMEOUT_SECS 5
34
12
  #define READ_LONG_TIMEOUT_SECS 5
35
13
 
36
- #define BACKLOG 1024
37
14
  #define MAX_BUFSIZE 1024 * 8
38
15
  #define INPUT_BUF_SIZE 1024 * 8
39
16
 
@@ -50,7 +27,7 @@
50
27
 
51
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>")
52
29
 
53
- #define SERVER "bossan/0.1.8"
30
+ #define SERVER "bossan/0.2.0"
54
31
 
55
32
  VALUE server; // Bossan
56
33
 
@@ -116,6 +93,10 @@ static int log_fd = -1; //access log
116
93
  /* static int err_log_fd = -1; //error log */
117
94
 
118
95
  static int is_keep_alive = 0; //keep alive support
96
+ static int keep_alive_timeout = 5;
97
+
98
+ static int max_fd = 1024 * 4; // picoev max_fd size
99
+ static int backlog = 1024; // backlog size
119
100
  int max_content_length = 1024 * 1024 * 16; //max_content_length
120
101
 
121
102
  static VALUE StringIO;
@@ -132,6 +113,13 @@ typedef struct {
132
113
  } write_bucket;
133
114
 
134
115
 
116
+ static void
117
+ r_callback(picoev_loop* loop, int fd, int events, void* cb_arg);
118
+
119
+ static void
120
+ w_callback(picoev_loop* loop, int fd, int events, void* cb_arg);
121
+
122
+
135
123
  int
136
124
  open_log_file(const char *path)
137
125
  {
@@ -139,6 +127,27 @@ open_log_file(const char *path)
139
127
  }
140
128
 
141
129
 
130
+ void
131
+ write_error_log(char *file_name, int line)
132
+ {
133
+ char buf[64];
134
+ FILE *fp = stderr;
135
+ int fd = fileno(fp);
136
+
137
+ flock(fd, LOCK_EX);
138
+
139
+ cache_time_update();
140
+ fputs((char *)err_log_time, fp);
141
+ fputs(" [error] ", fp);
142
+
143
+ sprintf(buf, "pid %d, File \"%s\", line %d :", getpid(), file_name, line);
144
+ fputs(buf, fp);
145
+ fflush(fp);
146
+
147
+ flock(fd, LOCK_UN);
148
+ }
149
+
150
+
142
151
  static int
143
152
  write_log(const char *new_path, int fd, const char *data, size_t len)
144
153
  {
@@ -261,7 +270,7 @@ blocking_write(client_t *client, char *data, size_t len)
261
270
  // TODO:
262
271
  // raise exception from errno
263
272
 
264
- /* write_error_log(__FILE__, __LINE__); */
273
+ write_error_log(__FILE__, __LINE__);
265
274
  client->keep_alive = 0;
266
275
  }
267
276
  return -1;
@@ -309,15 +318,6 @@ send_error_page(client_t *client)
309
318
  }
310
319
 
311
320
 
312
- static void
313
- extent_sndbuf(client_t *client)
314
- {
315
- int bufsize = 1024 * 1024 * 2, r;
316
- r = setsockopt(client->fd, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
317
- assert(r == 0);
318
- }
319
-
320
-
321
321
  static void
322
322
  enable_cork(client_t *client)
323
323
  {
@@ -391,7 +391,7 @@ writev_bucket(write_bucket *data)
391
391
  // TODO:
392
392
  // raise exception from errno
393
393
  /* rb_raise(rb_eIOError); */
394
- /* write_error_log(__FILE__, __LINE__); */
394
+ write_error_log(__FILE__, __LINE__);
395
395
  return -1;
396
396
  }
397
397
  }if(w == 0){
@@ -410,9 +410,7 @@ writev_bucket(write_bucket *data)
410
410
  }
411
411
  }
412
412
  data->total = data->total -w;
413
- #ifdef DEBUG
414
- printf("writev_bucket write %d progeress %d/%d \n", w, data->total, data->total_size);
415
- #endif
413
+ DEBUG("writev_bucket write %d progeress %d/%d \n", w, data->total, data->total_size);
416
414
  //resume
417
415
  // again later
418
416
  return writev_bucket(data);
@@ -531,7 +529,7 @@ write_headers(client_t *client)
531
529
  }
532
530
  return ret;
533
531
  error:
534
- /* write_error_log(__FILE__, __LINE__); */
532
+ write_error_log(__FILE__, __LINE__);
535
533
  if(bucket){
536
534
  free_write_bucket(bucket);
537
535
  client->bucket = NULL;
@@ -662,9 +660,7 @@ start_response_write(client_t *client)
662
660
  return -1;
663
661
  }
664
662
 
665
- #ifdef DEBUG
666
- printf("start_response_write buflen %d \n", buflen);
667
- #endif
663
+ /* DEBUG("start_response_write buflen %d \n", buflen); */
668
664
  return write_headers(client);
669
665
  }
670
666
 
@@ -678,9 +674,7 @@ response_start(client_t *client)
678
674
  return write_headers(client);
679
675
  }
680
676
  ret = start_response_write(client);
681
- #ifdef DEBUG
682
- printf("start_response_write ret = %d \n", ret);
683
- #endif
677
+ DEBUG("start_response_write ret = %d \n", ret);
684
678
  if(ret > 0){
685
679
  // sended header
686
680
  ret = processs_write(client);
@@ -693,7 +687,7 @@ static void
693
687
  key_upper(char *s, const char *key, size_t len)
694
688
  {
695
689
  int i = 0;
696
- register int c;
690
+ int c;
697
691
  for (i = 0; i < len; i++) {
698
692
  c = key[i];
699
693
  if(c == '-'){
@@ -709,30 +703,14 @@ key_upper(char *s, const char *key, size_t len)
709
703
  }
710
704
 
711
705
 
712
- static int
713
- write_body2file(client_t *client, const char *buffer, size_t buffer_len)
714
- {
715
- FILE *tmp = (FILE *)client->body;
716
- fwrite(buffer, 1, buffer_len, tmp);
717
- client->body_readed += buffer_len;
718
- #ifdef DEBUG
719
- printf("write_body2file %d bytes \n", buffer_len);
720
- #endif
721
- return client->body_readed;
722
- }
723
-
724
-
725
706
  static int
726
707
  write_body2mem(client_t *client, const char *buffer, size_t buffer_len)
727
708
  {
728
709
  VALUE obj;
729
- /* printf("body2mem called\n"); */
730
710
 
731
711
  rb_funcall((VALUE)client->body, i_write, 1, rb_str_new(buffer, buffer_len));
732
712
  client->body_readed += buffer_len;
733
- #ifdef DEBUG
734
- printf("write_body2mem %d bytes \n", buffer_len);
735
- #endif
713
+ DEBUG("write_body2mem %d bytes \n", buffer_len);
736
714
  return client->body_readed;
737
715
  }
738
716
 
@@ -910,7 +888,7 @@ int
910
888
  request_uri_cb (http_parser *p, const char *buf, size_t len, char partial)
911
889
  {
912
890
  client_t *client = get_client(p);
913
- register request *req = client->req;
891
+ request *req = client->req;
914
892
  buffer_result ret = MEMORY_ERROR;
915
893
 
916
894
  if(req->uri){
@@ -964,7 +942,7 @@ int
964
942
  fragment_cb (http_parser *p, const char *buf, size_t len, char partial)
965
943
  {
966
944
  client_t *client = get_client(p);
967
- register request *req = client->req;
945
+ request *req = client->req;
968
946
  buffer_result ret = MEMORY_ERROR;
969
947
 
970
948
  if(req->fragment){
@@ -1002,14 +980,10 @@ body_cb (http_parser *p, const char *buf, size_t len, char partial)
1002
980
  return -1;
1003
981
  }
1004
982
  //default memory stream
1005
- #ifdef DEBUG
1006
- printf("client->body_length %d \n", client->body_length);
1007
- #endif
983
+ DEBUG("client->body_length %d \n", client->body_length);
1008
984
  client->body = rb_funcall(StringIO, i_new, 1, rb_str_new2(""));
1009
985
  client->body_type = BODY_TYPE_BUFFER;
1010
- #ifdef DEBUG
1011
- printf("BODY_TYPE_BUFFER \n");
1012
- #endif
986
+ DEBUG("BODY_TYPE_BUFFER \n");
1013
987
  }
1014
988
  write_body(client, buf, len);
1015
989
  return 0;
@@ -1276,12 +1250,35 @@ setsig(int sig, void* handler)
1276
1250
  }
1277
1251
 
1278
1252
 
1253
+ void
1254
+ setup_listen_sock(int fd)
1255
+ {
1256
+ int on = 1, r;
1257
+ r = setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &on, sizeof(on));
1258
+ assert(r == 0);
1259
+ r = fcntl(fd, F_SETFL, O_NONBLOCK);
1260
+ assert(r == 0);
1261
+ }
1262
+
1263
+
1279
1264
  static void
1280
1265
  setup_sock(int fd)
1281
1266
  {
1282
1267
  int on = 1, r;
1283
1268
  r = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
1284
1269
  assert(r == 0);
1270
+
1271
+ // 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
+
1285
1282
  r = fcntl(fd, F_SETFL, O_NONBLOCK);
1286
1283
  assert(r == 0);
1287
1284
  }
@@ -1304,21 +1301,18 @@ disable_cork(client_t *client)
1304
1301
 
1305
1302
 
1306
1303
  static client_t *
1307
- new_client_t(int client_fd, struct sockaddr_in client_addr){
1304
+ new_client_t(int client_fd, char *remote_addr, uint32_t remote_port)
1305
+ {
1308
1306
  client_t *client;
1309
1307
 
1310
1308
  client = ruby_xmalloc(sizeof(client_t));
1311
1309
  memset(client, 0, sizeof(client_t));
1312
1310
 
1313
- /* printf("size %d\n", sizeof(client_t)); */
1314
-
1315
1311
  client->fd = client_fd;
1316
-
1317
- client->remote_addr = inet_ntoa(client_addr.sin_addr);
1318
- client->remote_port = ntohs(client_addr.sin_port);
1312
+ client->remote_addr = remote_addr;
1313
+ client->remote_port = remote_port;
1319
1314
  client->req = new_request();
1320
1315
  client->body_type = BODY_TYPE_NONE;
1321
- //printf("input_buf_size %d\n", client->input_buf_size);
1322
1316
  return client;
1323
1317
  }
1324
1318
 
@@ -1331,9 +1325,7 @@ clean_cli(client_t *client)
1331
1325
  free_request(client->req);
1332
1326
  client->req = NULL;
1333
1327
  }
1334
- #ifdef DEBUG
1335
- printf("close environ %p \n", client->environ);
1336
- #endif
1328
+ DEBUG("close environ %p \n", client->environ);
1337
1329
 
1338
1330
  // force clear
1339
1331
  client->environ = rb_hash_new();
@@ -1348,32 +1340,26 @@ clean_cli(client_t *client)
1348
1340
  static void
1349
1341
  close_conn(client_t *cli, picoev_loop* loop)
1350
1342
  {
1343
+ client_t *new_client;
1344
+ if(!cli->response_closed){
1345
+ close_response(cli);
1346
+ }
1347
+ picoev_del(loop, cli->fd);
1348
+
1349
+ DEBUG("picoev_del client:%p fd:%d \n", cli, cli->fd);
1350
+ clean_cli(cli);
1351
1351
  if(!cli->keep_alive){
1352
- picoev_del(loop, cli->fd);
1353
- clean_cli(cli);
1354
1352
  close(cli->fd);
1355
- #ifdef DEBUG
1356
- printf("close fd %d \n", cli->fd);
1357
- #endif
1358
- ruby_xfree(cli);
1353
+ DEBUG("close client:%p fd:%d \n", cli, cli->fd);
1359
1354
  }else{
1360
- clean_cli(cli);
1361
1355
  disable_cork(cli);
1362
- cli->keep_alive = 1;
1363
- cli->environ = Qnil;
1364
- cli->http_status = Qnil;
1365
- cli->headers = Qnil;
1366
- cli->header_done = 0;
1367
- cli->body_type = BODY_TYPE_NONE;
1368
- cli->status_code = 0;
1369
- cli->response = Qnil;
1370
- cli->content_length_set = 0;
1371
- cli->content_length = 0;
1372
- cli->write_bytes = 0;
1373
- cli->response_closed = 0;
1374
- cli->bad_request_code = 0;
1375
- init_parser(cli, server_name, server_port);
1356
+ new_client = new_client_t(cli->fd, cli->remote_addr, cli->remote_port);
1357
+ rb_gc_register_address(&new_client->environ);
1358
+ new_client->keep_alive = 1;
1359
+ init_parser(new_client, server_name, server_port);
1360
+ picoev_add(main_loop, new_client->fd, PICOEV_READ, keep_alive_timeout, r_callback, (void *)new_client);
1376
1361
  }
1362
+ ruby_xfree(cli);
1377
1363
  }
1378
1364
 
1379
1365
 
@@ -1413,7 +1399,7 @@ process_rack_app(client_t *cli)
1413
1399
 
1414
1400
  //check response
1415
1401
  if(cli->response && cli->response == Qnil){
1416
- /* write_error_log(__FILE__, __LINE__); */
1402
+ write_error_log(__FILE__, __LINE__);
1417
1403
  rb_raise(rb_eException, "response must be a iter or sequence object");
1418
1404
  }
1419
1405
 
@@ -1426,13 +1412,9 @@ w_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
1426
1412
  {
1427
1413
  client_t *client = ( client_t *)(cb_arg);
1428
1414
  int ret;
1429
- #ifdef DEBUG
1430
- printf("call w_callback \n");
1431
- #endif
1415
+ DEBUG("call w_callback \n");
1432
1416
  if ((events & PICOEV_TIMEOUT) != 0) {
1433
- #ifdef DEBUG
1434
- printf("** w_callback timeout ** \n");
1435
- #endif
1417
+ YDEBUG("** w_callback timeout ** \n");
1436
1418
  //timeout
1437
1419
  client->keep_alive = 0;
1438
1420
  close_conn(client, loop);
@@ -1440,9 +1422,7 @@ w_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
1440
1422
  } else if ((events & PICOEV_WRITE) != 0) {
1441
1423
  ret = process_body(client);
1442
1424
  picoev_set_timeout(loop, client->fd, WRITE_TIMEOUT_SECS);
1443
- #ifdef DEBUG
1444
- printf("process_body ret %d \n", ret);
1445
- #endif
1425
+ DEBUG("process_body ret %d \n", ret);
1446
1426
  if(ret != 0){
1447
1427
  //ok or die
1448
1428
  close_conn(client, loop);
@@ -1464,7 +1444,6 @@ call_rack_app(client_t *client, picoev_loop* loop)
1464
1444
  }
1465
1445
 
1466
1446
  ret = response_start(client);
1467
- /* printf("response_start done: %d\n", ret); */
1468
1447
  switch(ret){
1469
1448
  case -1:
1470
1449
  // Internal Server Error
@@ -1475,9 +1454,7 @@ call_rack_app(client_t *client, picoev_loop* loop)
1475
1454
  case 0:
1476
1455
  // continue
1477
1456
  // set callback
1478
- #ifdef DEBUG
1479
- printf("set write callback %d \n", ret);
1480
- #endif
1457
+ DEBUG("set write callback %d \n", ret);
1481
1458
  //clear event
1482
1459
  picoev_del(loop, client->fd);
1483
1460
  picoev_add(loop, client->fd, PICOEV_WRITE, WRITE_TIMEOUT_SECS, w_callback, (void *)client);
@@ -1528,16 +1505,12 @@ r_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
1528
1505
  {
1529
1506
  client_t *cli = ( client_t *)(cb_arg);
1530
1507
  if ((events & PICOEV_TIMEOUT) != 0) {
1531
- #ifdef DEBUG
1532
- printf("** r_callback timeout ** \n");
1533
- #endif
1508
+ YDEBUG("** r_callback timeout ** \n");
1534
1509
  //timeout
1535
1510
  cli->keep_alive = 0;
1536
1511
  close_conn(cli, loop);
1537
1512
  } else if ((events & PICOEV_READ) != 0) {
1538
- #ifdef DEBUG
1539
- printf("ready read \n");
1540
- #endif
1513
+ RDEBUG("ready read \n");
1541
1514
  /* update timeout, and read */
1542
1515
  int finish = 0, nread;
1543
1516
  char buf[INPUT_BUF_SIZE];
@@ -1548,50 +1521,56 @@ r_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
1548
1521
  r = read(cli->fd, buf, sizeof(buf));
1549
1522
  switch (r) {
1550
1523
  case 0:
1551
- finish = 1;
1552
- break;
1524
+ cli->keep_alive = 0;
1525
+ cli->status_code = 500; // ??? 503 ??
1526
+ send_error_page(cli);
1527
+ close_conn(cli, loop);
1528
+ return;
1553
1529
  case -1: /* error */
1554
1530
  if (errno == EAGAIN || errno == EWOULDBLOCK) { /* try again later */
1555
1531
  break;
1556
1532
  } else { /* fatal error */
1557
- rb_raise(rb_eException, "fatal error");
1558
- // TODO:
1559
- // raise exception from errno
1560
- /* rb_raise(); */
1561
- /* write_error_log(__FILE__, __LINE__); */
1562
- cli->keep_alive = 0;
1563
- cli->status_code = 500;
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
+ }
1564
1550
  close_conn(cli, loop);
1565
1551
  return;
1566
1552
  }
1567
1553
  break;
1568
1554
  default:
1569
- #ifdef DEBUG
1570
- printf("read request fd %d bufsize %d \n", cli->fd, r);
1571
- #endif
1555
+ RDEBUG("read request fd %d bufsize %d \n", cli->fd, r);
1572
1556
  nread = execute_parse(cli, buf, r);
1573
-
1557
+
1574
1558
  if(cli->bad_request_code > 0){
1575
- #ifdef DEBUG
1576
- printf("fd %d bad_request code %d \n", cli->fd, cli->bad_request_code);
1577
- #endif
1559
+ RDEBUG("fd %d bad_request code %d \n", cli->fd, cli->bad_request_code);
1578
1560
  send_error_page(cli);
1579
1561
  close_conn(cli, loop);
1580
1562
  return;
1581
1563
  }
1582
1564
  if( nread != r ){
1583
1565
  // parse error
1584
- #ifdef DEBUG
1585
- printf("fd %d parse error %d \n", cli->fd, cli->bad_request_code);
1586
- #endif
1566
+ DEBUG("fd %d parse error %d \n", cli->fd, cli->bad_request_code);
1587
1567
  cli->bad_request_code = 400;
1588
1568
  send_error_page(cli);
1589
1569
  close_conn(cli, loop);
1590
1570
  return;
1591
1571
  }
1592
- #ifdef DEBUG
1593
- printf("parse ok, fd %d %d nread \n", cli->fd, nread);
1594
- #endif
1572
+ RDEBUG("parse ok, fd %d %d nread \n", cli->fd, nread);
1573
+
1595
1574
  if(parser_finish(cli) > 0){
1596
1575
  finish = 1;
1597
1576
  }
@@ -1599,6 +1578,7 @@ r_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
1599
1578
  }
1600
1579
 
1601
1580
  if(finish == 1){
1581
+ /* picoev_del(loop, cli->fd); */
1602
1582
  prepare_call_rack(cli);
1603
1583
  call_rack_app(cli, loop);
1604
1584
  return;
@@ -1613,6 +1593,9 @@ accept_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
1613
1593
  int client_fd;
1614
1594
  client_t *client;
1615
1595
  struct sockaddr_in client_addr;
1596
+ char *remote_addr;
1597
+ uint32_t remote_port;
1598
+
1616
1599
  if ((events & PICOEV_TIMEOUT) != 0) {
1617
1600
  // time out
1618
1601
  // next turn or other process
@@ -1625,24 +1608,17 @@ accept_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
1625
1608
  client_fd = accept(fd, (struct sockaddr *)&client_addr, &client_len);
1626
1609
  #endif
1627
1610
  if (client_fd != -1) {
1628
- #ifdef DEBUG
1629
- printf("accept fd %d \n", client_fd);
1630
- #endif
1611
+ DEBUG("accept fd %d \n", client_fd);
1631
1612
  setup_sock(client_fd);
1632
- client = new_client_t(client_fd, client_addr);
1633
-
1634
- client->environ = Qnil;
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);
1635
1616
  rb_gc_register_address(&client->environ);
1636
-
1637
1617
  init_parser(client, server_name, server_port);
1638
-
1639
- picoev_add(loop, client_fd, PICOEV_READ, READ_LONG_TIMEOUT_SECS, r_callback, (void *)client);
1618
+ picoev_add(loop, client_fd, PICOEV_READ, keep_alive_timeout, r_callback, (void *)client);
1640
1619
  }else{
1641
1620
  if (errno != EAGAIN && errno != EWOULDBLOCK) {
1642
- // TODO:
1643
- // raise exception from errno
1644
- /* rb_raise(); */
1645
- /* write_error_log(__FILE__, __LINE__); */
1621
+ write_error_log(__FILE__, __LINE__);
1646
1622
  // die
1647
1623
  loop_done = 0;
1648
1624
  }
@@ -1654,9 +1630,9 @@ accept_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
1654
1630
  static void
1655
1631
  setup_server_env(void)
1656
1632
  {
1633
+ setup_listen_sock(listen_sock);
1657
1634
  setup_sock(listen_sock);
1658
1635
  cache_time_init();
1659
-
1660
1636
  setup_static_env(server_name, server_port);
1661
1637
  }
1662
1638
 
@@ -1677,9 +1653,6 @@ inet_listen(void)
1677
1653
  snprintf(strport, sizeof (strport), "%d", server_port);
1678
1654
 
1679
1655
  if ((rv = getaddrinfo(server_name, strport, &hints, &servinfo)) == -1) {
1680
- // TODO:
1681
- // raise exception from errno
1682
- /* rb_raise(); */
1683
1656
  return -1;
1684
1657
  }
1685
1658
 
@@ -1694,17 +1667,11 @@ inet_listen(void)
1694
1667
  if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &flag,
1695
1668
  sizeof(int)) == -1) {
1696
1669
  close(listen_sock);
1697
- // TODO:
1698
- // raise exception from errno
1699
- /* rb_raise(); */
1700
1670
  return -1;
1701
1671
  }
1702
1672
 
1703
1673
  if (bind(listen_sock, p->ai_addr, p->ai_addrlen) == -1) {
1704
1674
  close(listen_sock);
1705
- // TODO:
1706
- // raise exception from errno
1707
- /* rb_raise(); */
1708
1675
  return -1;
1709
1676
  }
1710
1677
  break;
@@ -1719,11 +1686,8 @@ inet_listen(void)
1719
1686
  freeaddrinfo(servinfo); // all done with this structure
1720
1687
 
1721
1688
  // BACKLOG 1024
1722
- if (listen(listen_sock, BACKLOG) == -1) {
1689
+ if (listen(listen_sock, backlog) == -1) {
1723
1690
  close(listen_sock);
1724
- // TODO:
1725
- // raise exception from errno
1726
- /* rb_raise(); */
1727
1691
  return -1;
1728
1692
  }
1729
1693
  setup_server_env();
@@ -1750,9 +1714,7 @@ unix_listen(char *sock_name)
1750
1714
  struct sockaddr_un saddr;
1751
1715
  mode_t old_umask;
1752
1716
 
1753
- #ifdef DEBUG
1754
- printf("unix domain socket %s\n", sock_name);
1755
- #endif
1717
+ DEBUG("unix domain socket %s\n", sock_name);
1756
1718
  memset(&saddr, 0, sizeof(saddr));
1757
1719
  check_unix_sockpath(sock_name);
1758
1720
 
@@ -1778,7 +1740,7 @@ unix_listen(char *sock_name)
1778
1740
  umask(old_umask);
1779
1741
 
1780
1742
  // BACKLOG 1024
1781
- if (listen(listen_sock, BACKLOG) == -1) {
1743
+ if (listen(listen_sock, backlog) == -1) {
1782
1744
  close(listen_sock);
1783
1745
  rb_raise(rb_eIOError, "server: failed to set backlog\n");
1784
1746
  }
@@ -1792,7 +1754,6 @@ static void
1792
1754
  sigint_cb(int signum)
1793
1755
  {
1794
1756
  loop_done = 0;
1795
- /* rb_interrupt(); */
1796
1757
  }
1797
1758
 
1798
1759
 
@@ -1881,7 +1842,7 @@ bossan_run_loop(int argc, VALUE *argv, VALUE self)
1881
1842
  }
1882
1843
 
1883
1844
  /* init picoev */
1884
- picoev_init(MAX_FDS);
1845
+ picoev_init(max_fd);
1885
1846
  /* create loop */
1886
1847
  main_loop = picoev_create_loop(60);
1887
1848
  loop_done = 1;
@@ -1899,6 +1860,9 @@ bossan_run_loop(int argc, VALUE *argv, VALUE self)
1899
1860
  picoev_destroy_loop(main_loop);
1900
1861
  picoev_deinit();
1901
1862
 
1863
+ if(unix_sock_name){
1864
+ unlink(unix_sock_name);
1865
+ }
1902
1866
  printf("Bye.\n");
1903
1867
  return Qnil;
1904
1868
  }
@@ -1919,6 +1883,75 @@ bossan_get_max_content_length(VALUE self)
1919
1883
  }
1920
1884
 
1921
1885
 
1886
+ VALUE
1887
+ bossan_set_keepalive(VALUE self, VALUE args)
1888
+ {
1889
+ int on;
1890
+
1891
+ on = NUM2INT(args);
1892
+ if(on < 0){
1893
+ rb_p("keep alive value out of range.\n");
1894
+ return Qfalse;
1895
+ }
1896
+
1897
+ is_keep_alive = on;
1898
+
1899
+ if(is_keep_alive){
1900
+ keep_alive_timeout = on;
1901
+ }else{
1902
+ keep_alive_timeout = 2;
1903
+ }
1904
+ return Qnil;
1905
+ }
1906
+
1907
+
1908
+ VALUE
1909
+ bossan_get_keepalive(VALUE self)
1910
+ {
1911
+ return INT2NUM(is_keep_alive);
1912
+ }
1913
+
1914
+
1915
+ VALUE
1916
+ bossan_set_picoev_max_fd(VALUE self, VALUE args)
1917
+ {
1918
+ int temp;
1919
+ temp = NUM2INT(args);
1920
+ if (temp <= 0) {
1921
+ rb_raise(rb_eException, "max_fd value out of range ");
1922
+ }
1923
+ max_fd = temp;
1924
+ return Qnil;
1925
+ }
1926
+
1927
+
1928
+ VALUE
1929
+ bossan_get_picoev_max_fd(VALUE self)
1930
+ {
1931
+ return INT2NUM(max_fd);
1932
+ }
1933
+
1934
+
1935
+ VALUE
1936
+ bossan_set_backlog(VALUE self, VALUE args)
1937
+ {
1938
+ int temp;
1939
+ temp = NUM2INT(args);
1940
+ if (temp <= 0) {
1941
+ rb_raise(rb_eException, "backlog value out of range ");
1942
+ }
1943
+ backlog = temp;
1944
+ return Qnil;
1945
+ }
1946
+
1947
+
1948
+ VALUE
1949
+ bossan_get_backlog(VALUE self)
1950
+ {
1951
+ return INT2NUM(backlog);
1952
+ }
1953
+
1954
+
1922
1955
  void
1923
1956
  Init_bossan_ext(void)
1924
1957
  {
@@ -1984,11 +2017,21 @@ Init_bossan_ext(void)
1984
2017
 
1985
2018
  rb_define_module_function(server, "run", bossan_run_loop, -1);
1986
2019
  rb_define_module_function(server, "stop", bossan_stop, 0);
2020
+ rb_define_module_function(server, "shutdown", bossan_stop, 0);
1987
2021
 
1988
2022
  rb_define_module_function(server, "access_log", bossan_access_log, 1);
1989
2023
  rb_define_module_function(server, "set_max_content_length", bossan_set_max_content_length, 1);
1990
2024
  rb_define_module_function(server, "get_max_content_length", bossan_get_max_content_length, 0);
1991
2025
 
2026
+ rb_define_module_function(server, "set_keepalive", bossan_set_keepalive, 1);
2027
+ rb_define_module_function(server, "get_keepalive", bossan_get_keepalive, 0);
2028
+
2029
+ rb_define_module_function(server, "set_picoev_max_fd", bossan_set_picoev_max_fd, 1);
2030
+ rb_define_module_function(server, "get_picoev_max_fd", bossan_get_picoev_max_fd, 0);
2031
+
2032
+ rb_define_module_function(server, "set_backlog", bossan_set_backlog, 1);
2033
+ rb_define_module_function(server, "get_backlog", bossan_get_backlog, 0);
2034
+
1992
2035
  rb_require("stringio");
1993
2036
  StringIO = rb_const_get(rb_cObject, rb_intern("StringIO"));
1994
2037
  }
@@ -64,8 +64,6 @@ picoev_loop* picoev_create_loop(int max_timeout)
64
64
  free(loop);
65
65
  return NULL;
66
66
  }
67
-
68
- loop->loop.now = time(NULL);
69
67
  return &loop->loop;
70
68
  }
71
69
 
@@ -1,3 +1,3 @@
1
1
  module Bossan
2
- VERSION = "0.1.8"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -29,7 +29,6 @@ class RackSpecTest < Test::Unit::TestCase
29
29
  rescue
30
30
  next
31
31
  end
32
- server_is_wake_up = true
33
32
  $stderr.puts "*** running success ***"
34
33
  return true
35
34
  }
@@ -39,6 +38,8 @@ class RackSpecTest < Test::Unit::TestCase
39
38
  private :server_is_wake_up?
40
39
 
41
40
  def setup
41
+ $stderr.puts RUBY_DESCRIPTION
42
+
42
43
  @pid = fork do
43
44
  trap(:INT) { Bossan.stop }
44
45
  Bossan.run(DEFAULT_HOST, DEFAULT_PORT, App.new)
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bossan
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
5
- prerelease:
4
+ version: 0.2.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Hiroki Noda
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-03-12 00:00:00.000000000 Z
11
+ date: 2013-05-22 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rack
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
@@ -37,10 +34,12 @@ extra_rdoc_files: []
37
34
  files:
38
35
  - .gitignore
39
36
  - .travis.yml
37
+ - CHANGELOG.md
40
38
  - Gemfile
41
39
  - LICENSE.txt
42
40
  - README.md
43
41
  - Rakefile
42
+ - TODO
44
43
  - bossan.gemspec
45
44
  - examples/blog/README.md
46
45
  - examples/blog/app.rb
@@ -53,6 +52,7 @@ files:
53
52
  - examples/sinatra_app.rb
54
53
  - examples/views/index.haml
55
54
  - examples/views_sample.rb
55
+ - ext/bossan/bossan.h
56
56
  - ext/bossan/bossan_ext.c
57
57
  - ext/bossan/buffer.c
58
58
  - ext/bossan/buffer.h
@@ -75,28 +75,27 @@ files:
75
75
  - test/test_rack_spec.rb
76
76
  homepage: https://github.com/kubo39/bossan
77
77
  licenses: []
78
+ metadata: {}
78
79
  post_install_message:
79
80
  rdoc_options: []
80
81
  require_paths:
81
82
  - lib
82
83
  - ext
83
84
  required_ruby_version: !ruby/object:Gem::Requirement
84
- none: false
85
85
  requirements:
86
86
  - - ! '>='
87
87
  - !ruby/object:Gem::Version
88
88
  version: 1.9.2
89
89
  required_rubygems_version: !ruby/object:Gem::Requirement
90
- none: false
91
90
  requirements:
92
91
  - - ! '>='
93
92
  - !ruby/object:Gem::Version
94
93
  version: '0'
95
94
  requirements: []
96
95
  rubyforge_project:
97
- rubygems_version: 1.8.24
96
+ rubygems_version: 2.0.3
98
97
  signing_key:
99
- specification_version: 3
98
+ specification_version: 4
100
99
  summary: high performance asynchronous rack web server
101
100
  test_files: []
102
101
  has_rdoc: