bossan 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- 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