ebb 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/benchmark/application.rb +8 -1
- data/libev/ev.c +612 -135
- data/libev/ev.h +76 -42
- data/libev/ev_epoll.c +1 -1
- data/libev/ev_kqueue.c +1 -1
- data/libev/ev_poll.c +18 -15
- data/libev/ev_port.c +1 -1
- data/libev/ev_select.c +25 -8
- data/libev/ev_vars.h +5 -2
- data/libev/ev_win32.c +1 -1
- data/libev/ev_wrap.h +2 -0
- data/ruby_lib/ebb.rb +37 -24
- data/src/ebb.c +15 -15
- data/src/ebb.h +3 -3
- data/src/ebb_ruby.c +20 -18
- metadata +13 -13
data/libev/ev.h
CHANGED
@@ -100,6 +100,8 @@ struct ev_loop;
|
|
100
100
|
# define EV_P_ EV_P,
|
101
101
|
# define EV_A loop
|
102
102
|
# define EV_A_ EV_A,
|
103
|
+
# define EV_DEFAULT_UC ev_default_loop_uc ()
|
104
|
+
# define EV_DEFAULT_UC_ EV_DEFAULT_UC,
|
103
105
|
# define EV_DEFAULT ev_default_loop (0)
|
104
106
|
# define EV_DEFAULT_ EV_DEFAULT,
|
105
107
|
#else
|
@@ -109,28 +111,37 @@ struct ev_loop;
|
|
109
111
|
# define EV_A_
|
110
112
|
# define EV_DEFAULT
|
111
113
|
# define EV_DEFAULT_
|
112
|
-
|
114
|
+
# define EV_DEFAULT_UC
|
115
|
+
# define EV_DEFAULT_UC_
|
113
116
|
# undef EV_EMBED_ENABLE
|
114
117
|
#endif
|
115
118
|
|
119
|
+
#if __STDC_VERSION__ >= 199901L || __GNUC__ >= 3
|
120
|
+
# define EV_INLINE static inline
|
121
|
+
#else
|
122
|
+
# define EV_INLINE static
|
123
|
+
#endif
|
124
|
+
|
125
|
+
/*****************************************************************************/
|
126
|
+
|
116
127
|
/* eventmask, revents, events... */
|
117
|
-
#define EV_UNDEF -
|
118
|
-
#define EV_NONE
|
119
|
-
#define EV_READ
|
120
|
-
#define EV_WRITE
|
121
|
-
#define EV_IOFDSET
|
122
|
-
#define EV_TIMEOUT
|
123
|
-
#define EV_PERIODIC
|
124
|
-
#define EV_SIGNAL
|
125
|
-
#define EV_CHILD
|
126
|
-
#define EV_STAT
|
127
|
-
#define EV_IDLE
|
128
|
-
#define EV_PREPARE
|
129
|
-
#define EV_CHECK
|
130
|
-
#define EV_EMBED
|
131
|
-
#define EV_FORK
|
132
|
-
#define EV_ASYNC
|
133
|
-
#define EV_ERROR
|
128
|
+
#define EV_UNDEF -1 /* guaranteed to be invalid */
|
129
|
+
#define EV_NONE 0x00 /* no events */
|
130
|
+
#define EV_READ 0x01 /* ev_io detected read will not block */
|
131
|
+
#define EV_WRITE 0x02 /* ev_io detected write will not block */
|
132
|
+
#define EV_IOFDSET 0x80 /* internal use only */
|
133
|
+
#define EV_TIMEOUT 0x00000100 /* timer timed out */
|
134
|
+
#define EV_PERIODIC 0x00000200 /* periodic timer timed out */
|
135
|
+
#define EV_SIGNAL 0x00000400 /* signal was received */
|
136
|
+
#define EV_CHILD 0x00000800 /* child/pid had status change */
|
137
|
+
#define EV_STAT 0x00001000 /* stat data changed */
|
138
|
+
#define EV_IDLE 0x00002000 /* event loop is idling */
|
139
|
+
#define EV_PREPARE 0x00004000 /* event loop about to poll */
|
140
|
+
#define EV_CHECK 0x00008000 /* event loop finished poll */
|
141
|
+
#define EV_EMBED 0x00010000 /* embedded event loop needs sweep */
|
142
|
+
#define EV_FORK 0x00020000 /* event loop resumed in child */
|
143
|
+
#define EV_ASYNC 0x00040000 /* async intra-loop signal */
|
144
|
+
#define EV_ERROR 0x80000000 /* sent when an error occurs */
|
134
145
|
|
135
146
|
/* can be used to add custom fields to all watchers, while losing binary compatibility */
|
136
147
|
#ifndef EV_COMMON
|
@@ -155,6 +166,15 @@ struct ev_loop;
|
|
155
166
|
* private: you can look at them, but not change them, and they might not mean anything to you.
|
156
167
|
* ro: can be read anytime, but only changed when the watcher isn't active
|
157
168
|
* rw: can be read and modified anytime, even when the watcher is active
|
169
|
+
*
|
170
|
+
* some internal details that might be helpful for debugging:
|
171
|
+
*
|
172
|
+
* active is either 0, which means the watcher is not active,
|
173
|
+
* or the array index of the watcher (periodics, timers)
|
174
|
+
* or the array index + 1 (most other watchers)
|
175
|
+
* or simply 1 for watchers that aren't in some array.
|
176
|
+
* pending is either 0, in which case the watcher isn't,
|
177
|
+
* or the array index + 1 in the pendings array.
|
158
178
|
*/
|
159
179
|
|
160
180
|
/* shared by all watchers */
|
@@ -327,7 +347,7 @@ typedef struct ev_async
|
|
327
347
|
EV_ATOMIC_T sent; /* private */
|
328
348
|
} ev_async;
|
329
349
|
|
330
|
-
# define ev_async_pending(w) ((
|
350
|
+
# define ev_async_pending(w) ((w)->sent + 0)
|
331
351
|
#endif
|
332
352
|
|
333
353
|
/* the presence of this union forces similar struct layout */
|
@@ -355,24 +375,24 @@ union ev_any_watcher
|
|
355
375
|
#if EV_EMBED_ENABLE
|
356
376
|
struct ev_embed embed;
|
357
377
|
#endif
|
358
|
-
#if
|
378
|
+
#if EV_ASYNC_ENABLE
|
359
379
|
struct ev_async async;
|
360
380
|
#endif
|
361
381
|
};
|
362
382
|
|
363
383
|
/* bits for ev_default_loop and ev_loop_new */
|
364
384
|
/* the default */
|
365
|
-
#define EVFLAG_AUTO
|
385
|
+
#define EVFLAG_AUTO 0x00000000U /* not quite a mask */
|
366
386
|
/* flag bits */
|
367
|
-
#define EVFLAG_NOENV
|
368
|
-
#define EVFLAG_FORKCHECK
|
387
|
+
#define EVFLAG_NOENV 0x01000000U /* do NOT consult environment */
|
388
|
+
#define EVFLAG_FORKCHECK 0x02000000U /* check for a fork in each iteration */
|
369
389
|
/* method bits to be ored together */
|
370
|
-
#define EVBACKEND_SELECT
|
371
|
-
#define EVBACKEND_POLL
|
372
|
-
#define EVBACKEND_EPOLL
|
373
|
-
#define EVBACKEND_KQUEUE
|
374
|
-
#define EVBACKEND_DEVPOLL
|
375
|
-
#define EVBACKEND_PORT
|
390
|
+
#define EVBACKEND_SELECT 0x00000001U /* about anywhere */
|
391
|
+
#define EVBACKEND_POLL 0x00000002U /* !win */
|
392
|
+
#define EVBACKEND_EPOLL 0x00000004U /* linux */
|
393
|
+
#define EVBACKEND_KQUEUE 0x00000008U /* bsd */
|
394
|
+
#define EVBACKEND_DEVPOLL 0x00000010U /* solaris 8 */ /* NYI */
|
395
|
+
#define EVBACKEND_PORT 0x00000020U /* solaris 10 */
|
376
396
|
|
377
397
|
#if EV_PROTOTYPES
|
378
398
|
int ev_version_major (void);
|
@@ -399,42 +419,54 @@ void ev_set_allocator (void *(*cb)(void *ptr, long size));
|
|
399
419
|
*/
|
400
420
|
void ev_set_syserr_cb (void (*cb)(const char *msg));
|
401
421
|
|
402
|
-
#
|
422
|
+
#if EV_MULTIPLICITY
|
423
|
+
EV_INLINE struct ev_loop *
|
424
|
+
ev_default_loop_uc (void)
|
425
|
+
{
|
426
|
+
extern struct ev_loop *ev_default_loop_ptr;
|
427
|
+
|
428
|
+
return ev_default_loop_ptr;
|
429
|
+
}
|
430
|
+
|
403
431
|
/* the default loop is the only one that handles signals and child watchers */
|
404
432
|
/* you can call this as often as you like */
|
405
|
-
|
433
|
+
EV_INLINE struct ev_loop *
|
406
434
|
ev_default_loop (unsigned int flags)
|
407
435
|
{
|
408
|
-
|
409
|
-
extern struct ev_loop *ev_default_loop_init (unsigned int flags);
|
436
|
+
struct ev_loop *loop = ev_default_loop_uc ();
|
410
437
|
|
411
|
-
if (!
|
412
|
-
|
438
|
+
if (!loop)
|
439
|
+
{
|
440
|
+
extern struct ev_loop *ev_default_loop_init (unsigned int flags);
|
413
441
|
|
414
|
-
|
442
|
+
loop = ev_default_loop_init (flags);
|
443
|
+
}
|
444
|
+
|
445
|
+
return loop;
|
415
446
|
}
|
416
447
|
|
417
448
|
/* create and destroy alternative loops that don't handle signals */
|
418
449
|
struct ev_loop *ev_loop_new (unsigned int flags);
|
419
450
|
void ev_loop_destroy (EV_P);
|
420
451
|
void ev_loop_fork (EV_P);
|
452
|
+
void ev_loop_verify (EV_P);
|
421
453
|
|
422
454
|
ev_tstamp ev_now (EV_P); /* time w.r.t. timers and the eventloop, updated after each poll */
|
423
455
|
|
424
|
-
#
|
456
|
+
#else
|
425
457
|
|
426
458
|
int ev_default_loop (unsigned int flags); /* returns true when successful */
|
427
459
|
|
428
|
-
|
460
|
+
EV_INLINE ev_tstamp
|
429
461
|
ev_now (void)
|
430
462
|
{
|
431
463
|
extern ev_tstamp ev_rt_now;
|
432
464
|
|
433
465
|
return ev_rt_now;
|
434
466
|
}
|
435
|
-
#
|
467
|
+
#endif /* multiplicity */
|
436
468
|
|
437
|
-
|
469
|
+
EV_INLINE int
|
438
470
|
ev_is_default_loop (EV_P)
|
439
471
|
{
|
440
472
|
#if EV_MULTIPLICITY
|
@@ -455,7 +487,7 @@ void ev_default_fork (void);
|
|
455
487
|
|
456
488
|
unsigned int ev_backend (EV_P); /* backend in use by loop */
|
457
489
|
unsigned int ev_loop_count (EV_P); /* number of loop iterations */
|
458
|
-
#endif
|
490
|
+
#endif /* prototypes */
|
459
491
|
|
460
492
|
#define EVLOOP_NONBLOCK 1 /* do not block/wait */
|
461
493
|
#define EVLOOP_ONESHOT 2 /* block *once* only */
|
@@ -493,7 +525,7 @@ void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revent
|
|
493
525
|
} while (0)
|
494
526
|
|
495
527
|
#define ev_io_set(ev,fd_,events_) do { (ev)->fd = (fd_); (ev)->events = (events_) | EV_IOFDSET; } while (0)
|
496
|
-
#define ev_timer_set(ev,after_,repeat_) do { (ev)->at = (after_); (ev)->repeat = (repeat_); } while (0)
|
528
|
+
#define ev_timer_set(ev,after_,repeat_) do { ((ev_watcher_time *)(ev))->at = (after_); (ev)->repeat = (repeat_); } while (0)
|
497
529
|
#define ev_periodic_set(ev,ofs_,ival_,res_) do { (ev)->offset = (ofs_); (ev)->interval = (ival_); (ev)->reschedule_cb= (res_); } while (0)
|
498
530
|
#define ev_signal_set(ev,signum_) do { (ev)->signum = (signum_); } while (0)
|
499
531
|
#define ev_child_set(ev,pid_,trace_) do { (ev)->pid = (pid_); (ev)->flags = !!(trace_); } while (0)
|
@@ -525,6 +557,8 @@ void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revent
|
|
525
557
|
#define ev_cb(ev) (ev)->cb /* rw */
|
526
558
|
#define ev_set_priority(ev,pri) ((ev_watcher *)(void *)(ev))->priority = (pri)
|
527
559
|
|
560
|
+
#define ev_periodic_at(ev) (((ev_watcher_time *)(ev))->at + 0.)
|
561
|
+
|
528
562
|
#ifndef ev_set_cb
|
529
563
|
# define ev_set_cb(ev,cb_) ev_cb (ev) = (cb_)
|
530
564
|
#endif
|
data/libev/ev_epoll.c
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* libev epoll fd activity backend
|
3
3
|
*
|
4
|
-
* Copyright (c) 2007 Marc Alexander Lehmann <libev@schmorp.de>
|
4
|
+
* Copyright (c) 2007,2008 Marc Alexander Lehmann <libev@schmorp.de>
|
5
5
|
* All rights reserved.
|
6
6
|
*
|
7
7
|
* Redistribution and use in source and binary forms, with or without modifica-
|
data/libev/ev_kqueue.c
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* libev kqueue backend
|
3
3
|
*
|
4
|
-
* Copyright (c) 2007 Marc Alexander Lehmann <libev@schmorp.de>
|
4
|
+
* Copyright (c) 2007,2008 Marc Alexander Lehmann <libev@schmorp.de>
|
5
5
|
* All rights reserved.
|
6
6
|
*
|
7
7
|
* Redistribution and use in source and binary forms, with or without modifica-
|
data/libev/ev_poll.c
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* libev poll fd activity backend
|
3
3
|
*
|
4
|
-
* Copyright (c) 2007 Marc Alexander Lehmann <libev@schmorp.de>
|
4
|
+
* Copyright (c) 2007,2008 Marc Alexander Lehmann <libev@schmorp.de>
|
5
5
|
* All rights reserved.
|
6
6
|
*
|
7
7
|
* Redistribution and use in source and binary forms, with or without modifica-
|
@@ -86,7 +86,7 @@ poll_modify (EV_P_ int fd, int oev, int nev)
|
|
86
86
|
static void
|
87
87
|
poll_poll (EV_P_ ev_tstamp timeout)
|
88
88
|
{
|
89
|
-
|
89
|
+
struct pollfd *p;
|
90
90
|
int res = poll (polls, pollcnt, (int)ceil (timeout * 1000.));
|
91
91
|
|
92
92
|
if (expect_false (res < 0))
|
@@ -97,20 +97,23 @@ poll_poll (EV_P_ ev_tstamp timeout)
|
|
97
97
|
fd_enomem (EV_A);
|
98
98
|
else if (errno != EINTR)
|
99
99
|
syserr ("(libev) poll");
|
100
|
-
|
101
|
-
return;
|
102
100
|
}
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
101
|
+
else
|
102
|
+
for (p = polls; res; ++p)
|
103
|
+
if (expect_false (p->revents)) /* this expect is debatable */
|
104
|
+
{
|
105
|
+
--res;
|
106
|
+
|
107
|
+
if (expect_false (p->revents & POLLNVAL))
|
108
|
+
fd_kill (EV_A_ p->fd);
|
109
|
+
else
|
110
|
+
fd_event (
|
111
|
+
EV_A_
|
112
|
+
p->fd,
|
113
|
+
(p->revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0)
|
114
|
+
| (p->revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0)
|
115
|
+
);
|
116
|
+
}
|
114
117
|
}
|
115
118
|
|
116
119
|
int inline_size
|
data/libev/ev_port.c
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* libev solaris event port backend
|
3
3
|
*
|
4
|
-
* Copyright (c) 2007 Marc Alexander Lehmann <libev@schmorp.de>
|
4
|
+
* Copyright (c) 2007,2008 Marc Alexander Lehmann <libev@schmorp.de>
|
5
5
|
* All rights reserved.
|
6
6
|
*
|
7
7
|
* Redistribution and use in source and binary forms, with or without modifica-
|
data/libev/ev_select.c
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* libev select fd activity backend
|
3
3
|
*
|
4
|
-
* Copyright (c) 2007 Marc Alexander Lehmann <libev@schmorp.de>
|
4
|
+
* Copyright (c) 2007,2008 Marc Alexander Lehmann <libev@schmorp.de>
|
5
5
|
* All rights reserved.
|
6
6
|
*
|
7
7
|
* Redistribution and use in source and binary forms, with or without modifica-
|
@@ -54,12 +54,6 @@
|
|
54
54
|
#if EV_SELECT_IS_WINSOCKET
|
55
55
|
# undef EV_SELECT_USE_FD_SET
|
56
56
|
# define EV_SELECT_USE_FD_SET 1
|
57
|
-
# undef EINTR
|
58
|
-
# define EINTR WSAEINTR
|
59
|
-
# undef EBADF
|
60
|
-
# define EBADF WSAENOTSOCK
|
61
|
-
# undef ENOMEM
|
62
|
-
# define ENOMEM (errno + 1)
|
63
57
|
#endif
|
64
58
|
|
65
59
|
#if !EV_SELECT_USE_FD_SET
|
@@ -98,7 +92,7 @@ select_modify (EV_P_ int fd, int oev, int nev)
|
|
98
92
|
int word = fd / NFDBITS;
|
99
93
|
fd_mask mask = 1UL << (fd % NFDBITS);
|
100
94
|
|
101
|
-
if (expect_false (vec_max
|
95
|
+
if (expect_false (vec_max <= word))
|
102
96
|
{
|
103
97
|
int new_max = word + 1;
|
104
98
|
|
@@ -147,6 +141,29 @@ select_poll (EV_P_ ev_tstamp timeout)
|
|
147
141
|
#if EV_SELECT_IS_WINSOCKET
|
148
142
|
errno = WSAGetLastError ();
|
149
143
|
#endif
|
144
|
+
#ifdef WSABASEERR
|
145
|
+
/* on windows, select returns incompatible error codes, fix this */
|
146
|
+
if (errno >= WSABASEERR && errno < WSABASEERR + 1000)
|
147
|
+
if (errno == WSAENOTSOCK)
|
148
|
+
errno = EBADF;
|
149
|
+
else
|
150
|
+
errno -= WSABASEERR;
|
151
|
+
#endif
|
152
|
+
|
153
|
+
#ifdef _WIN32
|
154
|
+
/* select on windows errornously returns EINVAL when no fd sets have been
|
155
|
+
* provided (this is documented). what microsoft doesn't tell you that this bug
|
156
|
+
* exists even when the fd sets are provided, so we have to check for this bug
|
157
|
+
* here and emulate by sleeping manually.
|
158
|
+
* we also get EINVAL when the timeout is invalid, but we ignore this case here
|
159
|
+
* and assume that EINVAL always means: you have to wait manually.
|
160
|
+
*/
|
161
|
+
if (errno == EINVAL)
|
162
|
+
{
|
163
|
+
ev_sleep (timeout);
|
164
|
+
return;
|
165
|
+
}
|
166
|
+
#endif
|
150
167
|
|
151
168
|
if (errno == EBADF)
|
152
169
|
fd_ebadf (EV_A);
|
data/libev/ev_vars.h
CHANGED
@@ -55,6 +55,9 @@ VARx(ev_tstamp, backend_fudge) /* assumed typical timer resolution */
|
|
55
55
|
VAR (backend_modify, void (*backend_modify)(EV_P_ int fd, int oev, int nev))
|
56
56
|
VAR (backend_poll , void (*backend_poll)(EV_P_ ev_tstamp timeout))
|
57
57
|
|
58
|
+
#if EV_USE_EVENTFD || EV_GENWRAP
|
59
|
+
VARx(int, evfd)
|
60
|
+
#endif
|
58
61
|
VAR (evpipe, int evpipe [2])
|
59
62
|
VARx(ev_io, pipeev)
|
60
63
|
|
@@ -109,12 +112,12 @@ VARx(int *, fdchanges)
|
|
109
112
|
VARx(int, fdchangemax)
|
110
113
|
VARx(int, fdchangecnt)
|
111
114
|
|
112
|
-
VARx(
|
115
|
+
VARx(ANHE *, timers)
|
113
116
|
VARx(int, timermax)
|
114
117
|
VARx(int, timercnt)
|
115
118
|
|
116
119
|
#if EV_PERIODIC_ENABLE || EV_GENWRAP
|
117
|
-
VARx(
|
120
|
+
VARx(ANHE *, periodics)
|
118
121
|
VARx(int, periodicmax)
|
119
122
|
VARx(int, periodiccnt)
|
120
123
|
#endif
|
data/libev/ev_win32.c
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
/*
|
2
2
|
* libev win32 compatibility cruft (_not_ a backend)
|
3
3
|
*
|
4
|
-
* Copyright (c) 2007 Marc Alexander Lehmann <libev@schmorp.de>
|
4
|
+
* Copyright (c) 2007,2008 Marc Alexander Lehmann <libev@schmorp.de>
|
5
5
|
* All rights reserved.
|
6
6
|
*
|
7
7
|
* Redistribution and use in source and binary forms, with or without modifica-
|
data/libev/ev_wrap.h
CHANGED
@@ -13,6 +13,7 @@
|
|
13
13
|
#define backend_fudge ((loop)->backend_fudge)
|
14
14
|
#define backend_modify ((loop)->backend_modify)
|
15
15
|
#define backend_poll ((loop)->backend_poll)
|
16
|
+
#define evfd ((loop)->evfd)
|
16
17
|
#define evpipe ((loop)->evpipe)
|
17
18
|
#define pipeev ((loop)->pipeev)
|
18
19
|
#define curpid ((loop)->curpid)
|
@@ -84,6 +85,7 @@
|
|
84
85
|
#undef backend_fudge
|
85
86
|
#undef backend_modify
|
86
87
|
#undef backend_poll
|
88
|
+
#undef evfd
|
87
89
|
#undef evpipe
|
88
90
|
#undef pipeev
|
89
91
|
#undef curpid
|
data/ruby_lib/ebb.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# See README file for details.
|
4
4
|
require 'stringio'
|
5
5
|
module Ebb
|
6
|
-
VERSION = "0.2.
|
6
|
+
VERSION = "0.2.1"
|
7
7
|
LIBDIR = File.dirname(__FILE__)
|
8
8
|
autoload :Runner, LIBDIR + '/ebb/runner'
|
9
9
|
autoload :FFI, LIBDIR + '/../src/ebb_ext'
|
@@ -18,7 +18,7 @@ module Ebb
|
|
18
18
|
FFI::server_listen_on_unix_socket(socketfile)
|
19
19
|
log.puts "Ebb is listening on unix socket #{socketfile}"
|
20
20
|
else
|
21
|
-
port = (options[:port] || 4001).to_i
|
21
|
+
port = (options[:Port] || options[:port] || 4001).to_i
|
22
22
|
FFI::server_listen_on_port(port)
|
23
23
|
log.puts "Ebb is listening at http://0.0.0.0:#{port}/"
|
24
24
|
end
|
@@ -30,10 +30,10 @@ module Ebb
|
|
30
30
|
while @running
|
31
31
|
FFI::server_process_connections()
|
32
32
|
while client = FFI::server_waiting_clients.shift
|
33
|
-
if app.respond_to?(:deferred?) and
|
34
|
-
process(app, client)
|
35
|
-
else
|
33
|
+
if app.respond_to?(:deferred?) and app.deferred?(client.env)
|
36
34
|
Thread.new(client) { |c| process(app, c) }
|
35
|
+
else
|
36
|
+
process(app, client)
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
@@ -51,22 +51,34 @@ module Ebb
|
|
51
51
|
def self.process(app, client)
|
52
52
|
#p client.env
|
53
53
|
status, headers, body = app.call(client.env)
|
54
|
+
status = status.to_i
|
54
55
|
|
55
56
|
# Write the status
|
56
57
|
client.write_status(status)
|
57
58
|
|
58
59
|
# Add Content-Length to the headers.
|
59
|
-
if headers
|
60
|
-
headers.respond_to?(:[]=) and
|
61
|
-
body.respond_to?(:length) and
|
60
|
+
if !headers.has_key?('Content-Length') and
|
61
|
+
headers.respond_to?(:[]=) and
|
62
62
|
status != 304
|
63
63
|
then
|
64
|
-
|
64
|
+
# for String just use "length" method
|
65
|
+
if body.kind_of?(String)
|
66
|
+
headers['Content-Length'] = body.length.to_s
|
67
|
+
else
|
68
|
+
# for non-Array object call "each" and transform to Array
|
69
|
+
unless body.kind_of?(Array)
|
70
|
+
parts = []
|
71
|
+
body.each {|p| parts << p}
|
72
|
+
body = parts
|
73
|
+
end
|
74
|
+
# body is Array so calculate Content-Length as sum of length each part
|
75
|
+
headers['Content-Length'] = body.inject(0) {|s, p| s + p.length }.to_s
|
76
|
+
end
|
65
77
|
end
|
66
78
|
|
67
79
|
# Decide if we should keep the connection alive or not
|
68
|
-
|
69
|
-
if headers
|
80
|
+
unless headers.has_key?('Connection')
|
81
|
+
if headers.has_key?('Content-Length') and client.should_keep_alive?
|
70
82
|
headers['Connection'] = 'Keep-Alive'
|
71
83
|
else
|
72
84
|
headers['Connection'] = 'close'
|
@@ -103,6 +115,7 @@ module Ebb
|
|
103
115
|
BASE_ENV = {
|
104
116
|
'SERVER_NAME' => '0.0.0.0',
|
105
117
|
'SCRIPT_NAME' => '',
|
118
|
+
'QUERY_STRING' => '',
|
106
119
|
'SERVER_SOFTWARE' => "Ebb-Ruby #{Ebb::VERSION}",
|
107
120
|
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
108
121
|
'rack.version' => [0, 1],
|
@@ -121,8 +134,7 @@ module Ebb
|
|
121
134
|
end
|
122
135
|
|
123
136
|
def write_status(status)
|
124
|
-
|
125
|
-
FFI::client_write_status(self, s, HTTP_STATUS_CODES[s])
|
137
|
+
FFI::client_write_status(self, status, HTTP_STATUS_CODES[status])
|
126
138
|
end
|
127
139
|
|
128
140
|
def write_body(data)
|
@@ -130,9 +142,7 @@ module Ebb
|
|
130
142
|
end
|
131
143
|
|
132
144
|
def write_header(field, value)
|
133
|
-
|
134
|
-
FFI::client_write_header(self, field, v.chomp)
|
135
|
-
end
|
145
|
+
FFI::client_write_header(self, field, value)
|
136
146
|
end
|
137
147
|
|
138
148
|
def release
|
@@ -144,12 +154,11 @@ module Ebb
|
|
144
154
|
end
|
145
155
|
|
146
156
|
def should_keep_alive?
|
147
|
-
if env['HTTP_VERSION'] == 'HTTP/1.0'
|
148
|
-
return
|
157
|
+
if env['HTTP_VERSION'] == 'HTTP/1.0'
|
158
|
+
return env['HTTP_CONNECTION'] =~ /Keep-Alive/i
|
149
159
|
else
|
150
|
-
return
|
160
|
+
return env['HTTP_CONNECTION'] !~ /close/i
|
151
161
|
end
|
152
|
-
false
|
153
162
|
end
|
154
163
|
end
|
155
164
|
|
@@ -183,6 +192,14 @@ module Ebb
|
|
183
192
|
def each(&block)
|
184
193
|
raise NotImplemented
|
185
194
|
end
|
195
|
+
|
196
|
+
private
|
197
|
+
|
198
|
+
# cause i don't want to create an array
|
199
|
+
def min(a,b)
|
200
|
+
a > b ? b : a
|
201
|
+
end
|
202
|
+
|
186
203
|
end
|
187
204
|
|
188
205
|
|
@@ -238,7 +255,3 @@ module Rack
|
|
238
255
|
end
|
239
256
|
end
|
240
257
|
|
241
|
-
# cause i don't want to create an array
|
242
|
-
def min(a,b)
|
243
|
-
a > b ? b : a
|
244
|
-
end
|