bossan 0.1.8 → 0.2.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 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: