bossan 0.1.4 → 0.1.5
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.
- data/ext/bossan/bossan_ext.c +64 -54
- data/ext/bossan/http_parser.c +82 -45
- data/ext/bossan/http_parser.h +3 -4
- data/ext/bossan/picoev_epoll.c +2 -1
- data/lib/bossan/version.rb +1 -1
- metadata +27 -21
- data/.gitignore +0 -19
- data/Gemfile +0 -4
- data/README.md +0 -50
- data/Rakefile +0 -15
- data/bossan.gemspec +0 -16
- data/examples/config.ru +0 -19
- data/examples/hello.rb +0 -12
- data/examples/sinatra_app.rb +0 -11
- data/examples/views/index.haml +0 -10
- data/examples/views_sample.rb +0 -11
data/ext/bossan/bossan_ext.c
CHANGED
@@ -10,18 +10,20 @@
|
|
10
10
|
#include <inttypes.h>
|
11
11
|
#include <arpa/inet.h>
|
12
12
|
#include <signal.h>
|
13
|
-
#include <sys/sendfile.h>
|
14
13
|
#include <sys/socket.h>
|
15
14
|
#include <sys/types.h>
|
15
|
+
#ifdef linux
|
16
|
+
#include <sys/sendfile.h>
|
16
17
|
#include <sys/prctl.h>
|
18
|
+
#elif defined(__APPLE__) || defined(__FreeBSD__)
|
19
|
+
#include <sys/uio.h>
|
20
|
+
#endif
|
17
21
|
#include <sys/un.h>
|
18
22
|
#include <sys/stat.h>
|
19
23
|
#include <sys/file.h>
|
20
|
-
#include <sys/uio.h>
|
21
24
|
#include <netinet/in.h>
|
22
25
|
#include <netinet/tcp.h>
|
23
26
|
#include <netdb.h>
|
24
|
-
|
25
27
|
#include "time_cache.h"
|
26
28
|
#include "http_parser.h"
|
27
29
|
#include "picoev.h"
|
@@ -59,7 +61,7 @@
|
|
59
61
|
|
60
62
|
#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>")
|
61
63
|
|
62
|
-
#define SERVER "bossan/0.1.
|
64
|
+
#define SERVER "bossan/0.1.5"
|
63
65
|
|
64
66
|
VALUE server; // Bossan
|
65
67
|
|
@@ -205,7 +207,7 @@ typedef struct {
|
|
205
207
|
uint32_t total_size;
|
206
208
|
} write_bucket;
|
207
209
|
|
208
|
-
|
210
|
+
buffer *
|
209
211
|
new_buffer(size_t buf_size, size_t limit)
|
210
212
|
{
|
211
213
|
buffer *buf;
|
@@ -221,7 +223,7 @@ new_buffer(size_t buf_size, size_t limit)
|
|
221
223
|
return buf;
|
222
224
|
}
|
223
225
|
|
224
|
-
|
226
|
+
buffer_result
|
225
227
|
write2buf(buffer *buf, const char *c, size_t l) {
|
226
228
|
size_t newl;
|
227
229
|
char *newbuf;
|
@@ -248,14 +250,14 @@ write2buf(buffer *buf, const char *c, size_t l) {
|
|
248
250
|
return ret;
|
249
251
|
}
|
250
252
|
|
251
|
-
|
253
|
+
void
|
252
254
|
free_buffer(buffer *buf)
|
253
255
|
{
|
254
256
|
ruby_xfree(buf->buf);
|
255
257
|
ruby_xfree(buf);
|
256
258
|
}
|
257
259
|
|
258
|
-
|
260
|
+
VALUE
|
259
261
|
getRbString(buffer *buf)
|
260
262
|
{
|
261
263
|
VALUE o;
|
@@ -264,7 +266,7 @@ getRbString(buffer *buf)
|
|
264
266
|
return o;
|
265
267
|
}
|
266
268
|
|
267
|
-
|
269
|
+
char *
|
268
270
|
getString(buffer *buf)
|
269
271
|
{
|
270
272
|
buf->buf[buf->len] = '\0';
|
@@ -277,7 +279,7 @@ open_log_file(const char *path)
|
|
277
279
|
return open(path, O_CREAT|O_APPEND|O_WRONLY, 0744);
|
278
280
|
}
|
279
281
|
|
280
|
-
static
|
282
|
+
static int
|
281
283
|
write_log(const char *new_path, int fd, const char *data, size_t len)
|
282
284
|
{
|
283
285
|
int openfd;
|
@@ -356,7 +358,7 @@ write_access_log(client_t *cli, int log_fd, const char *log_path)
|
|
356
358
|
return 0;
|
357
359
|
}
|
358
360
|
|
359
|
-
static
|
361
|
+
static int
|
360
362
|
blocking_write(client_t *client, char *data, size_t len)
|
361
363
|
{
|
362
364
|
size_t r = 0, send_len = len;
|
@@ -425,7 +427,7 @@ send_error_page(client_t *client)
|
|
425
427
|
client->keep_alive = 0;
|
426
428
|
}
|
427
429
|
|
428
|
-
static
|
430
|
+
static void
|
429
431
|
extent_sndbuf(client_t *client)
|
430
432
|
{
|
431
433
|
int bufsize = 1024 * 1024 * 2, r;
|
@@ -433,15 +435,19 @@ extent_sndbuf(client_t *client)
|
|
433
435
|
assert(r == 0);
|
434
436
|
}
|
435
437
|
|
436
|
-
static
|
438
|
+
static void
|
437
439
|
enable_cork(client_t *client)
|
438
440
|
{
|
439
441
|
int on = 1, r;
|
442
|
+
#ifdef linux
|
440
443
|
r = setsockopt(client->fd, IPPROTO_TCP, TCP_CORK, &on, sizeof(on));
|
444
|
+
#elif defined(__APPLE__) || defined(__FreeBSD__)
|
445
|
+
r = setsockopt(client->fd, IPPROTO_TCP, TCP_NOPUSH, &on, sizeof(on));
|
446
|
+
#endif
|
441
447
|
assert(r == 0);
|
442
448
|
}
|
443
449
|
|
444
|
-
static
|
450
|
+
static write_bucket *
|
445
451
|
new_write_bucket(int fd, int cnt)
|
446
452
|
{
|
447
453
|
write_bucket *bucket;
|
@@ -454,14 +460,14 @@ new_write_bucket(int fd, int cnt)
|
|
454
460
|
return bucket;
|
455
461
|
}
|
456
462
|
|
457
|
-
static
|
463
|
+
static void
|
458
464
|
free_write_bucket(write_bucket *bucket)
|
459
465
|
{
|
460
466
|
ruby_xfree(bucket->iov);
|
461
467
|
ruby_xfree(bucket);
|
462
468
|
}
|
463
469
|
|
464
|
-
static
|
470
|
+
static void
|
465
471
|
set2bucket(write_bucket *bucket, char *buf, size_t len)
|
466
472
|
{
|
467
473
|
bucket->iov[bucket->iov_cnt].iov_base = buf;
|
@@ -471,7 +477,7 @@ set2bucket(write_bucket *bucket, char *buf, size_t len)
|
|
471
477
|
bucket->total_size += len;
|
472
478
|
}
|
473
479
|
|
474
|
-
static
|
480
|
+
static void
|
475
481
|
add_header(write_bucket *bucket, char *key, size_t keylen, char *val, size_t vallen)
|
476
482
|
{
|
477
483
|
set2bucket(bucket, key, keylen);
|
@@ -480,7 +486,7 @@ add_header(write_bucket *bucket, char *key, size_t keylen, char *val, size_t val
|
|
480
486
|
set2bucket(bucket, CRLF, 2);
|
481
487
|
}
|
482
488
|
|
483
|
-
static
|
489
|
+
static int
|
484
490
|
writev_bucket(write_bucket *data)
|
485
491
|
{
|
486
492
|
size_t w;
|
@@ -528,7 +534,7 @@ writev_bucket(write_bucket *data)
|
|
528
534
|
return 1;
|
529
535
|
}
|
530
536
|
|
531
|
-
static
|
537
|
+
static int
|
532
538
|
write_headers(client_t *client)
|
533
539
|
{
|
534
540
|
if(client->header_done){
|
@@ -645,7 +651,7 @@ write_headers(client_t *client)
|
|
645
651
|
return -1;
|
646
652
|
}
|
647
653
|
|
648
|
-
/* static
|
654
|
+
/* static int */
|
649
655
|
/* write_sendfile(int out_fd, int in_fd, size_t count) */
|
650
656
|
/* { */
|
651
657
|
/* int size = (int)count; */
|
@@ -664,7 +670,7 @@ write_headers(client_t *client)
|
|
664
670
|
/* return sendfile(out_fd, in_fd, NULL, count); */
|
665
671
|
/* } */
|
666
672
|
|
667
|
-
static
|
673
|
+
static void
|
668
674
|
close_response(client_t *client)
|
669
675
|
{
|
670
676
|
//send all response
|
@@ -682,7 +688,7 @@ collect_body(VALUE i, VALUE str, int argc, VALUE *argv)
|
|
682
688
|
return Qnil;
|
683
689
|
}
|
684
690
|
|
685
|
-
static
|
691
|
+
static int
|
686
692
|
processs_write(client_t *client)
|
687
693
|
{
|
688
694
|
VALUE iterator = NULL;
|
@@ -736,7 +742,7 @@ processs_write(client_t *client)
|
|
736
742
|
return 1;
|
737
743
|
}
|
738
744
|
|
739
|
-
|
745
|
+
int
|
740
746
|
process_body(client_t *client)
|
741
747
|
{
|
742
748
|
int ret;
|
@@ -759,7 +765,7 @@ process_body(client_t *client)
|
|
759
765
|
return ret;
|
760
766
|
}
|
761
767
|
|
762
|
-
static
|
768
|
+
static int
|
763
769
|
start_response_write(client_t *client)
|
764
770
|
{
|
765
771
|
VALUE iterator;
|
@@ -788,7 +794,7 @@ start_response_write(client_t *client)
|
|
788
794
|
return write_headers(client);
|
789
795
|
}
|
790
796
|
|
791
|
-
|
797
|
+
int
|
792
798
|
response_start(client_t *client)
|
793
799
|
{
|
794
800
|
int ret;
|
@@ -807,7 +813,7 @@ response_start(client_t *client)
|
|
807
813
|
return ret;
|
808
814
|
}
|
809
815
|
|
810
|
-
|
816
|
+
request *
|
811
817
|
new_request(void)
|
812
818
|
{
|
813
819
|
request *req = (request *)ruby_xmalloc(sizeof(request));
|
@@ -815,7 +821,7 @@ new_request(void)
|
|
815
821
|
return req;
|
816
822
|
}
|
817
823
|
|
818
|
-
|
824
|
+
header *
|
819
825
|
new_header(size_t fsize, size_t flimit, size_t vsize, size_t vlimit)
|
820
826
|
{
|
821
827
|
header *h;
|
@@ -825,13 +831,13 @@ new_header(size_t fsize, size_t flimit, size_t vsize, size_t vlimit)
|
|
825
831
|
return h;
|
826
832
|
}
|
827
833
|
|
828
|
-
|
834
|
+
void
|
829
835
|
free_header(header *h)
|
830
836
|
{
|
831
837
|
ruby_xfree(h);
|
832
838
|
}
|
833
839
|
|
834
|
-
|
840
|
+
void
|
835
841
|
free_request(request *req)
|
836
842
|
{
|
837
843
|
uint32_t i;
|
@@ -864,7 +870,7 @@ free_request(request *req)
|
|
864
870
|
ruby_xfree(req);
|
865
871
|
}
|
866
872
|
|
867
|
-
static
|
873
|
+
static void
|
868
874
|
key_upper(char *s, const char *key, size_t len)
|
869
875
|
{
|
870
876
|
int i = 0;
|
@@ -883,7 +889,7 @@ key_upper(char *s, const char *key, size_t len)
|
|
883
889
|
}
|
884
890
|
}
|
885
891
|
|
886
|
-
static
|
892
|
+
static int
|
887
893
|
write_body2file(client_t *client, const char *buffer, size_t buffer_len)
|
888
894
|
{
|
889
895
|
FILE *tmp = (FILE *)client->body;
|
@@ -895,7 +901,7 @@ write_body2file(client_t *client, const char *buffer, size_t buffer_len)
|
|
895
901
|
return client->body_readed;
|
896
902
|
}
|
897
903
|
|
898
|
-
static
|
904
|
+
static int
|
899
905
|
write_body2mem(client_t *client, const char *buffer, size_t buffer_len)
|
900
906
|
{
|
901
907
|
printf("body2mem called\n");
|
@@ -908,7 +914,7 @@ write_body2mem(client_t *client, const char *buffer, size_t buffer_len)
|
|
908
914
|
return client->body_readed;
|
909
915
|
}
|
910
916
|
|
911
|
-
static
|
917
|
+
static int
|
912
918
|
write_body(client_t *cli, const char *buffer, size_t buffer_len)
|
913
919
|
{
|
914
920
|
return write_body2mem(cli, buffer, buffer_len);
|
@@ -920,7 +926,7 @@ typedef enum{
|
|
920
926
|
OTHER
|
921
927
|
} rack_header_type;
|
922
928
|
|
923
|
-
static
|
929
|
+
static rack_header_type
|
924
930
|
check_header_type(const char *buf)
|
925
931
|
{
|
926
932
|
if(*buf++ != 'C'){
|
@@ -956,7 +962,7 @@ check_header_type(const char *buf)
|
|
956
962
|
return OTHER;
|
957
963
|
}
|
958
964
|
|
959
|
-
static
|
965
|
+
static client_t *
|
960
966
|
get_client(http_parser *p)
|
961
967
|
{
|
962
968
|
return (client_t *)p->data;
|
@@ -1319,7 +1325,7 @@ static http_parser_settings settings =
|
|
1319
1325
|
,.on_message_complete = message_complete_cb
|
1320
1326
|
};
|
1321
1327
|
|
1322
|
-
|
1328
|
+
int
|
1323
1329
|
init_parser(client_t *cli, const char *name, const short port)
|
1324
1330
|
{
|
1325
1331
|
register VALUE object;
|
@@ -1360,19 +1366,19 @@ init_parser(client_t *cli, const char *name, const short port)
|
|
1360
1366
|
return 0;
|
1361
1367
|
}
|
1362
1368
|
|
1363
|
-
|
1369
|
+
size_t
|
1364
1370
|
execute_parse(client_t *cli, const char *data, size_t len)
|
1365
1371
|
{
|
1366
1372
|
return http_parser_execute(cli->http, &settings, data, len);
|
1367
1373
|
}
|
1368
1374
|
|
1369
|
-
|
1375
|
+
int
|
1370
1376
|
parser_finish(client_t *cli)
|
1371
1377
|
{
|
1372
1378
|
return cli->complete;
|
1373
1379
|
}
|
1374
1380
|
|
1375
|
-
|
1381
|
+
void
|
1376
1382
|
setup_static_env(char *name, int port)
|
1377
1383
|
{
|
1378
1384
|
version_val = rb_obj_freeze(rb_ary_new3(2, INT2FIX(1), INT2FIX(1)));
|
@@ -1418,7 +1424,7 @@ setup_static_env(char *name, int port)
|
|
1418
1424
|
http_user_agent = rb_obj_freeze(rb_str_new2("HTTP_USER_AGENT"));
|
1419
1425
|
}
|
1420
1426
|
|
1421
|
-
static
|
1427
|
+
static int
|
1422
1428
|
setsig(int sig, void* handler)
|
1423
1429
|
{
|
1424
1430
|
struct sigaction context, ocontext;
|
@@ -1428,7 +1434,7 @@ setsig(int sig, void* handler)
|
|
1428
1434
|
return sigaction(sig, &context, &ocontext);
|
1429
1435
|
}
|
1430
1436
|
|
1431
|
-
static
|
1437
|
+
static void
|
1432
1438
|
setup_sock(int fd)
|
1433
1439
|
{
|
1434
1440
|
int on = 1, r;
|
@@ -1438,19 +1444,22 @@ setup_sock(int fd)
|
|
1438
1444
|
assert(r == 0);
|
1439
1445
|
}
|
1440
1446
|
|
1441
|
-
static
|
1447
|
+
static void
|
1442
1448
|
disable_cork(client_t *client)
|
1443
1449
|
{
|
1444
1450
|
int off = 0;
|
1445
1451
|
int on = 1, r;
|
1452
|
+
#ifdef linux
|
1446
1453
|
r = setsockopt(client->fd, IPPROTO_TCP, TCP_CORK, &off, sizeof(off));
|
1454
|
+
#elif defined(__APPLE__) || defined(__FreeBSD__)
|
1455
|
+
r = setsockopt(client->fd, IPPROTO_TCP, TCP_NOPUSH, &off, sizeof(off));
|
1456
|
+
#endif
|
1447
1457
|
assert(r == 0);
|
1448
|
-
|
1449
1458
|
r = setsockopt(client->fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
|
1450
1459
|
assert(r == 0);
|
1451
1460
|
}
|
1452
1461
|
|
1453
|
-
static
|
1462
|
+
static client_t *
|
1454
1463
|
new_client_t(int client_fd, struct sockaddr_in client_addr){
|
1455
1464
|
client_t *client;
|
1456
1465
|
|
@@ -1469,7 +1478,7 @@ new_client_t(int client_fd, struct sockaddr_in client_addr){
|
|
1469
1478
|
return client;
|
1470
1479
|
}
|
1471
1480
|
|
1472
|
-
static
|
1481
|
+
static void
|
1473
1482
|
clean_cli(client_t *client)
|
1474
1483
|
{
|
1475
1484
|
write_access_log(client, log_fd, log_path);
|
@@ -1484,7 +1493,7 @@ clean_cli(client_t *client)
|
|
1484
1493
|
}
|
1485
1494
|
}
|
1486
1495
|
|
1487
|
-
static
|
1496
|
+
static void
|
1488
1497
|
close_conn(client_t *cli, picoev_loop* loop)
|
1489
1498
|
{
|
1490
1499
|
if(!cli->keep_alive){
|
@@ -1515,7 +1524,7 @@ close_conn(client_t *cli, picoev_loop* loop)
|
|
1515
1524
|
}
|
1516
1525
|
}
|
1517
1526
|
|
1518
|
-
static
|
1527
|
+
static int
|
1519
1528
|
process_rack_app(client_t *cli)
|
1520
1529
|
{
|
1521
1530
|
VALUE args = NULL;
|
@@ -1587,7 +1596,7 @@ w_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
|
|
1587
1596
|
}
|
1588
1597
|
}
|
1589
1598
|
|
1590
|
-
static
|
1599
|
+
static void
|
1591
1600
|
call_rack_app(client_t *client, picoev_loop* loop)
|
1592
1601
|
{
|
1593
1602
|
int ret;
|
@@ -1622,7 +1631,7 @@ call_rack_app(client_t *client, picoev_loop* loop)
|
|
1622
1631
|
}
|
1623
1632
|
}
|
1624
1633
|
|
1625
|
-
static
|
1634
|
+
static void
|
1626
1635
|
prepare_call_rack(client_t *client)
|
1627
1636
|
{
|
1628
1637
|
VALUE input = NULL, object = NULL, c = NULL;
|
@@ -1744,7 +1753,8 @@ accept_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
|
|
1744
1753
|
return;
|
1745
1754
|
}else if ((events & PICOEV_READ) != 0) {
|
1746
1755
|
socklen_t client_len = sizeof(client_addr);
|
1747
|
-
client_fd = accept4(fd, (struct sockaddr *)&client_addr, &client_len, SOCK_NONBLOCK | SOCK_CLOEXEC);
|
1756
|
+
//client_fd = accept4(fd, (struct sockaddr *)&client_addr, &client_len, SOCK_NONBLOCK | SOCK_CLOEXEC);
|
1757
|
+
client_fd = accept(fd, (struct sockaddr *)&client_addr, &client_len);
|
1748
1758
|
if (client_fd != -1) {
|
1749
1759
|
#ifdef DEBUG
|
1750
1760
|
printf("accept fd %d \n", client_fd);
|
@@ -1771,7 +1781,7 @@ accept_callback(picoev_loop* loop, int fd, int events, void* cb_arg)
|
|
1771
1781
|
}
|
1772
1782
|
}
|
1773
1783
|
|
1774
|
-
static
|
1784
|
+
static void
|
1775
1785
|
setup_server_env(void)
|
1776
1786
|
{
|
1777
1787
|
setup_sock(listen_sock);
|
@@ -1780,7 +1790,7 @@ setup_server_env(void)
|
|
1780
1790
|
setup_static_env(server_name, server_port);
|
1781
1791
|
}
|
1782
1792
|
|
1783
|
-
static
|
1793
|
+
static int
|
1784
1794
|
inet_listen(void)
|
1785
1795
|
{
|
1786
1796
|
struct addrinfo hints, *servinfo, *p;
|
@@ -1849,7 +1859,7 @@ inet_listen(void)
|
|
1849
1859
|
return 1;
|
1850
1860
|
}
|
1851
1861
|
|
1852
|
-
static
|
1862
|
+
static int
|
1853
1863
|
check_unix_sockpath(char *sock_name)
|
1854
1864
|
{
|
1855
1865
|
if(!access(sock_name, F_OK)){
|
@@ -1860,7 +1870,7 @@ check_unix_sockpath(char *sock_name)
|
|
1860
1870
|
return 1;
|
1861
1871
|
}
|
1862
1872
|
|
1863
|
-
static
|
1873
|
+
static int
|
1864
1874
|
unix_listen(char *sock_name)
|
1865
1875
|
{
|
1866
1876
|
int flag = 1;
|
data/ext/bossan/http_parser.c
CHANGED
@@ -1,7 +1,4 @@
|
|
1
1
|
/* Copyright 2009,2010 Ryan Dahl <ry@tinyclouds.org>
|
2
|
-
*
|
3
|
-
* Some parts of this source file were taken from NGINX
|
4
|
-
* (src/http/ngx_http_parser.c) copyright (C) 2002-2009 Igor Sysoev.
|
5
2
|
*
|
6
3
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
4
|
* of this software and associated documentation files (the "Software"), to
|
@@ -122,18 +119,44 @@ static const char *method_strings[] =
|
|
122
119
|
};
|
123
120
|
|
124
121
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
122
|
+
/* ' ', '_', '-' and all alpha-numeric ascii characters are accepted by acceptable_header.
|
123
|
+
The 'A'-'Z' are lower-cased. */
|
124
|
+
static const char acceptable_header[256] = {
|
125
|
+
/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
|
126
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
127
|
+
/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
|
128
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
129
|
+
/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
|
130
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
131
|
+
/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
|
132
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
133
|
+
/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
|
134
|
+
' ', 0, 0, 0, 0, 0, 0, 0,
|
135
|
+
/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
|
136
|
+
0, 0, 0, 0, 0, '-', 0, 0,
|
137
|
+
/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
|
138
|
+
'0', '1', '2', '3', '4', '5', '6', '7',
|
139
|
+
/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
|
140
|
+
'8', '9', 0, 0, 0, 0, 0, 0,
|
141
|
+
/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
|
142
|
+
0, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
|
143
|
+
/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
|
144
|
+
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
145
|
+
/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
|
146
|
+
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
|
147
|
+
/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
|
148
|
+
'x', 'y', 'z', 0, 0, 0, 0, '_',
|
149
|
+
/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
|
150
|
+
0, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
|
151
|
+
/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
|
152
|
+
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
|
153
|
+
/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
|
154
|
+
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
|
155
|
+
/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
|
156
|
+
'x', 'y', 'z', 0, 0, 0, 0, 0 };
|
157
|
+
|
158
|
+
|
159
|
+
static const int8_t unhex[256] =
|
137
160
|
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
138
161
|
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
139
162
|
,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
|
@@ -145,26 +168,39 @@ static const int unhex[] =
|
|
145
168
|
};
|
146
169
|
|
147
170
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
171
|
+
static const uint8_t normal_url_char[256] = {
|
172
|
+
/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
|
173
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
174
|
+
/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
|
175
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
176
|
+
/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
|
177
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
178
|
+
/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
|
179
|
+
0, 0, 0, 0, 0, 0, 0, 0,
|
180
|
+
/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
|
181
|
+
0, 1, 1, 0, 1, 1, 1, 1,
|
182
|
+
/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
|
183
|
+
1, 1, 1, 1, 1, 1, 1, 1,
|
184
|
+
/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
|
185
|
+
1, 1, 1, 1, 1, 1, 1, 1,
|
186
|
+
/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
|
187
|
+
1, 1, 1, 1, 1, 1, 1, 0,
|
188
|
+
/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
|
189
|
+
1, 1, 1, 1, 1, 1, 1, 1,
|
190
|
+
/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
|
191
|
+
1, 1, 1, 1, 1, 1, 1, 1,
|
192
|
+
/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
|
193
|
+
1, 1, 1, 1, 1, 1, 1, 1,
|
194
|
+
/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
|
195
|
+
1, 1, 1, 1, 1, 1, 1, 1,
|
196
|
+
/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
|
197
|
+
1, 1, 1, 1, 1, 1, 1, 1,
|
198
|
+
/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
|
199
|
+
1, 1, 1, 1, 1, 1, 1, 1,
|
200
|
+
/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
|
201
|
+
1, 1, 1, 1, 1, 1, 1, 1,
|
202
|
+
/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
|
203
|
+
1, 1, 1, 1, 1, 1, 1, 0 };
|
168
204
|
|
169
205
|
|
170
206
|
enum state
|
@@ -705,7 +741,7 @@ size_t http_parser_execute (http_parser *parser,
|
|
705
741
|
|
706
742
|
case s_req_path:
|
707
743
|
{
|
708
|
-
if (
|
744
|
+
if (normal_url_char[(unsigned char)ch]) break;
|
709
745
|
|
710
746
|
switch (ch) {
|
711
747
|
case ' ':
|
@@ -741,7 +777,7 @@ size_t http_parser_execute (http_parser *parser,
|
|
741
777
|
|
742
778
|
case s_req_query_string_start:
|
743
779
|
{
|
744
|
-
if (
|
780
|
+
if (normal_url_char[(unsigned char)ch]) {
|
745
781
|
MARK(query_string);
|
746
782
|
state = s_req_query_string;
|
747
783
|
break;
|
@@ -775,7 +811,7 @@ size_t http_parser_execute (http_parser *parser,
|
|
775
811
|
|
776
812
|
case s_req_query_string:
|
777
813
|
{
|
778
|
-
if (
|
814
|
+
if (normal_url_char[(unsigned char)ch]) break;
|
779
815
|
|
780
816
|
switch (ch) {
|
781
817
|
case '?':
|
@@ -810,7 +846,7 @@ size_t http_parser_execute (http_parser *parser,
|
|
810
846
|
|
811
847
|
case s_req_fragment_start:
|
812
848
|
{
|
813
|
-
if (
|
849
|
+
if (normal_url_char[(unsigned char)ch]) {
|
814
850
|
MARK(fragment);
|
815
851
|
state = s_req_fragment;
|
816
852
|
break;
|
@@ -845,7 +881,7 @@ size_t http_parser_execute (http_parser *parser,
|
|
845
881
|
|
846
882
|
case s_req_fragment:
|
847
883
|
{
|
848
|
-
if (
|
884
|
+
if (normal_url_char[(unsigned char)ch]) break;
|
849
885
|
|
850
886
|
switch (ch) {
|
851
887
|
case ' ':
|
@@ -1021,7 +1057,7 @@ size_t http_parser_execute (http_parser *parser,
|
|
1021
1057
|
|
1022
1058
|
case s_header_field:
|
1023
1059
|
{
|
1024
|
-
c =
|
1060
|
+
c = acceptable_header[(unsigned char)ch];
|
1025
1061
|
|
1026
1062
|
if (c) {
|
1027
1063
|
switch (header_state) {
|
@@ -1158,7 +1194,7 @@ size_t http_parser_execute (http_parser *parser,
|
|
1158
1194
|
state = s_header_value;
|
1159
1195
|
index = 0;
|
1160
1196
|
|
1161
|
-
c =
|
1197
|
+
c = acceptable_header[(unsigned char)ch];
|
1162
1198
|
|
1163
1199
|
if (!c) {
|
1164
1200
|
if (ch == CR) {
|
@@ -1221,7 +1257,7 @@ size_t http_parser_execute (http_parser *parser,
|
|
1221
1257
|
|
1222
1258
|
case s_header_value:
|
1223
1259
|
{
|
1224
|
-
c =
|
1260
|
+
c = acceptable_header[(unsigned char)ch];
|
1225
1261
|
|
1226
1262
|
if (!c) {
|
1227
1263
|
if (ch == CR) {
|
@@ -1428,7 +1464,7 @@ size_t http_parser_execute (http_parser *parser,
|
|
1428
1464
|
{
|
1429
1465
|
assert(parser->flags & F_CHUNKED);
|
1430
1466
|
|
1431
|
-
c = unhex[(
|
1467
|
+
c = unhex[(unsigned char)ch];
|
1432
1468
|
if (c == -1) goto error;
|
1433
1469
|
parser->content_length = c;
|
1434
1470
|
state = s_chunk_size;
|
@@ -1444,7 +1480,7 @@ size_t http_parser_execute (http_parser *parser,
|
|
1444
1480
|
break;
|
1445
1481
|
}
|
1446
1482
|
|
1447
|
-
c = unhex[(
|
1483
|
+
c = unhex[(unsigned char)ch];
|
1448
1484
|
|
1449
1485
|
if (c == -1) {
|
1450
1486
|
if (ch == ';' || ch == ' ') {
|
@@ -1575,4 +1611,5 @@ http_parser_init (http_parser *parser, enum http_parser_type t)
|
|
1575
1611
|
parser->nread = 0;
|
1576
1612
|
parser->upgrade = 0;
|
1577
1613
|
parser->flags = 0;
|
1614
|
+
parser->method = 0;
|
1578
1615
|
}
|
data/ext/bossan/http_parser.h
CHANGED
@@ -100,15 +100,14 @@ enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };
|
|
100
100
|
|
101
101
|
struct http_parser {
|
102
102
|
/** PRIVATE **/
|
103
|
-
unsigned char type;
|
103
|
+
unsigned char type : 2;
|
104
|
+
unsigned char flags : 6;
|
104
105
|
unsigned char state;
|
105
106
|
unsigned char header_state;
|
106
107
|
unsigned char index;
|
107
108
|
char maybe_ml;
|
108
109
|
|
109
|
-
|
110
|
-
|
111
|
-
uint64_t nread;
|
110
|
+
uint32_t nread;
|
112
111
|
int64_t content_length;
|
113
112
|
|
114
113
|
/** READ-ONLY **/
|
data/ext/bossan/picoev_epoll.c
CHANGED
data/lib/bossan/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bossan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,24 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
13
|
-
dependencies:
|
12
|
+
date: 2013-01-27 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rack
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.2'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.2'
|
14
30
|
description: high performance asynchronous rack web server
|
15
31
|
email:
|
16
32
|
- kubo39@gmail.com
|
@@ -19,28 +35,18 @@ extensions:
|
|
19
35
|
- ext/bossan/extconf.rb
|
20
36
|
extra_rdoc_files: []
|
21
37
|
files:
|
22
|
-
- .gitignore
|
23
|
-
- Gemfile
|
24
38
|
- LICENSE.txt
|
25
|
-
-
|
26
|
-
-
|
27
|
-
- bossan.
|
28
|
-
- examples/config.ru
|
29
|
-
- examples/hello.rb
|
30
|
-
- examples/sinatra_app.rb
|
31
|
-
- examples/views/index.haml
|
32
|
-
- examples/views_sample.rb
|
33
|
-
- ext/bossan/bossan_ext.c
|
34
|
-
- ext/bossan/extconf.rb
|
35
|
-
- ext/bossan/http_parser.c
|
39
|
+
- lib/bossan/version.rb
|
40
|
+
- lib/rack/handler/bossan.rb
|
41
|
+
- lib/bossan.rb
|
36
42
|
- ext/bossan/http_parser.h
|
37
|
-
- ext/bossan/picoev.h
|
38
43
|
- ext/bossan/picoev_epoll.c
|
39
44
|
- ext/bossan/time_cache.c
|
45
|
+
- ext/bossan/picoev.h
|
40
46
|
- ext/bossan/time_cache.h
|
41
|
-
-
|
42
|
-
-
|
43
|
-
-
|
47
|
+
- ext/bossan/bossan_ext.c
|
48
|
+
- ext/bossan/extconf.rb
|
49
|
+
- ext/bossan/http_parser.c
|
44
50
|
homepage: https://github.com/kubo39/bossan
|
45
51
|
licenses: []
|
46
52
|
post_install_message:
|
@@ -53,7 +59,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
53
59
|
requirements:
|
54
60
|
- - ! '>='
|
55
61
|
- !ruby/object:Gem::Version
|
56
|
-
version:
|
62
|
+
version: 1.9.2
|
57
63
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
64
|
none: false
|
59
65
|
requirements:
|
data/.gitignore
DELETED
data/Gemfile
DELETED
data/README.md
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
# Bossan
|
2
|
-
|
3
|
-
Bossan is a high performance asynchronous rack web server.
|
4
|
-
|
5
|
-
## Requirements
|
6
|
-
|
7
|
-
Bossan requires Ruby 1.9.2 or later.
|
8
|
-
|
9
|
-
Bossan supports Linux only.
|
10
|
-
|
11
|
-
## Installation
|
12
|
-
|
13
|
-
Add this line to your application's Gemfile:
|
14
|
-
|
15
|
-
gem 'bossan'
|
16
|
-
|
17
|
-
And then execute:
|
18
|
-
|
19
|
-
$ bundle
|
20
|
-
|
21
|
-
Or install it yourself as:
|
22
|
-
|
23
|
-
$ gem install bossan
|
24
|
-
|
25
|
-
## Usage
|
26
|
-
|
27
|
-
simple rack app:
|
28
|
-
|
29
|
-
``` ruby
|
30
|
-
require 'bossan'
|
31
|
-
|
32
|
-
Bossan.run('127.0.0.1', 8000, proc {|env|
|
33
|
-
[
|
34
|
-
200, # Status code
|
35
|
-
{ # Response headers
|
36
|
-
'Content-Type' => 'text/html',
|
37
|
-
'Content-Length' => '13',
|
38
|
-
},
|
39
|
-
['hello, world!'] # Response body
|
40
|
-
]
|
41
|
-
})
|
42
|
-
```
|
43
|
-
|
44
|
-
## Contributing
|
45
|
-
|
46
|
-
1. Fork it
|
47
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
48
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
49
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
50
|
-
5. Create new Pull Request
|
data/Rakefile
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
#!/usr/bin/env rake
|
2
|
-
require "bundler/gem_tasks"
|
3
|
-
|
4
|
-
task :default => [:compile, :clean]
|
5
|
-
|
6
|
-
task :compile do
|
7
|
-
Dir.chdir File.expand_path("../ext/bossan", __FILE__)
|
8
|
-
system "ruby extconf.rb"
|
9
|
-
system "make"
|
10
|
-
end
|
11
|
-
|
12
|
-
task :clean do
|
13
|
-
Dir.chdir File.expand_path("../ext/bossan", __FILE__)
|
14
|
-
system "rm -f *.o Makefile"
|
15
|
-
end
|
data/bossan.gemspec
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
require File.expand_path('../lib/bossan/version', __FILE__)
|
3
|
-
|
4
|
-
Gem::Specification.new do |gem|
|
5
|
-
gem.name = "bossan"
|
6
|
-
gem.version = Bossan::VERSION
|
7
|
-
gem.authors = ["Hiroki Noda"]
|
8
|
-
gem.email = ["kubo39@gmail.com"]
|
9
|
-
gem.description = %q{high performance asynchronous rack web server}
|
10
|
-
gem.summary = gem.description
|
11
|
-
gem.homepage = "https://github.com/kubo39/bossan"
|
12
|
-
|
13
|
-
gem.files = `git ls-files`.split($/)
|
14
|
-
gem.extensions = ["ext/bossan/extconf.rb"]
|
15
|
-
gem.require_paths = ["lib", "ext"]
|
16
|
-
end
|
data/examples/config.ru
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
require 'bossan'
|
2
|
-
require 'pp'
|
3
|
-
|
4
|
-
class MyApp
|
5
|
-
def call env
|
6
|
-
body = ['hi!']
|
7
|
-
# pp env
|
8
|
-
[
|
9
|
-
200, # Status code
|
10
|
-
{ 'Content-Type' => 'text/html',
|
11
|
-
'Content-Length' => body.join.size.to_s,
|
12
|
-
}, # Reponse headers
|
13
|
-
body # Body of the response
|
14
|
-
]
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
# Rack::Handler::Bossan.run MyApp.new
|
19
|
-
run MyApp.new
|
data/examples/hello.rb
DELETED
data/examples/sinatra_app.rb
DELETED
data/examples/views/index.haml
DELETED