eventmachine-maglev- 0.12.10 → 1.0.0.beta.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +7 -0
- data/.yardopts +7 -0
- data/Gemfile +3 -0
- data/README.md +109 -0
- data/Rakefile +14 -368
- data/docs/DocumentationGuidesIndex.md +27 -0
- data/docs/GettingStarted.md +521 -0
- data/docs/old/DEFERRABLES +246 -0
- data/docs/{KEYBOARD → old/KEYBOARD} +15 -11
- data/docs/old/LIGHTWEIGHT_CONCURRENCY +130 -0
- data/docs/old/SMTP +4 -0
- data/docs/old/SPAWNED_PROCESSES +148 -0
- data/eventmachine.gemspec +20 -26
- data/examples/guides/getting_started/01_eventmachine_echo_server.rb +18 -0
- data/examples/guides/getting_started/02_eventmachine_echo_server_that_recognizes_exit_command.rb +22 -0
- data/examples/guides/getting_started/03_simple_chat_server.rb +149 -0
- data/examples/guides/getting_started/04_simple_chat_server_step_one.rb +27 -0
- data/examples/guides/getting_started/05_simple_chat_server_step_two.rb +43 -0
- data/examples/guides/getting_started/06_simple_chat_server_step_three.rb +98 -0
- data/examples/guides/getting_started/07_simple_chat_server_step_four.rb +121 -0
- data/examples/guides/getting_started/08_simple_chat_server_step_five.rb +141 -0
- data/examples/{ex_channel.rb → old/ex_channel.rb} +3 -3
- data/examples/old/ex_tick_loop_array.rb +15 -0
- data/examples/old/ex_tick_loop_counter.rb +32 -0
- data/ext/binder.cpp +0 -1
- data/ext/cmain.cpp +40 -29
- data/ext/ed.cpp +189 -134
- data/ext/ed.h +34 -40
- data/ext/em.cpp +388 -340
- data/ext/em.h +29 -32
- data/ext/eventmachine.h +7 -6
- data/ext/extconf.rb +57 -48
- data/ext/fastfilereader/extconf.rb +5 -3
- data/ext/fastfilereader/mapper.cpp +1 -1
- data/ext/fastfilereader/rubymain.cpp +0 -1
- data/ext/kb.cpp +1 -3
- data/ext/pipe.cpp +9 -11
- data/ext/project.h +12 -8
- data/ext/rubymain.cpp +158 -112
- data/java/src/com/rubyeventmachine/EmReactor.java +3 -2
- data/lib/em/buftok.rb +35 -63
- data/lib/em/callback.rb +43 -11
- data/lib/em/channel.rb +22 -15
- data/lib/em/completion.rb +303 -0
- data/lib/em/connection.rb +341 -208
- data/lib/em/deferrable/pool.rb +2 -0
- data/lib/em/deferrable.rb +20 -2
- data/lib/em/file_watch.rb +37 -18
- data/lib/em/iterator.rb +270 -0
- data/lib/em/pool.rb +146 -0
- data/lib/em/process_watch.rb +5 -4
- data/lib/em/processes.rb +8 -4
- data/lib/em/protocols/httpclient.rb +27 -11
- data/lib/em/protocols/httpclient2.rb +15 -5
- data/lib/em/protocols/line_protocol.rb +29 -0
- data/lib/em/protocols/memcache.rb +17 -9
- data/lib/em/protocols/object_protocol.rb +2 -1
- data/lib/em/protocols/postgres3.rb +2 -1
- data/lib/em/protocols/smtpclient.rb +19 -11
- data/lib/em/protocols/smtpserver.rb +101 -8
- data/lib/em/protocols/stomp.rb +9 -7
- data/lib/em/protocols/tcptest.rb +3 -2
- data/lib/em/protocols.rb +1 -1
- data/lib/{pr_eventmachine.rb → em/pure_ruby.rb} +188 -205
- data/lib/em/queue.rb +23 -13
- data/lib/em/resolver.rb +192 -0
- data/lib/em/spawnable.rb +9 -10
- data/lib/em/streamer.rb +34 -46
- data/lib/em/threaded_resource.rb +90 -0
- data/lib/em/tick_loop.rb +85 -0
- data/lib/em/timers.rb +8 -3
- data/lib/em/version.rb +1 -1
- data/lib/eventmachine.rb +582 -686
- data/lib/jeventmachine.rb +25 -3
- data/tasks/package.rake +98 -0
- data/tasks/test.rake +8 -0
- data/tests/em_test_helper.rb +64 -0
- data/tests/test_attach.rb +56 -56
- data/tests/test_basic.rb +111 -168
- data/tests/test_channel.rb +5 -6
- data/tests/test_completion.rb +177 -0
- data/tests/test_connection_count.rb +1 -3
- data/tests/test_defer.rb +3 -32
- data/tests/test_deferrable.rb +35 -0
- data/tests/test_epoll.rb +27 -57
- data/tests/test_error_handler.rb +10 -7
- data/tests/test_exc.rb +6 -33
- data/tests/test_file_watch.rb +51 -35
- data/tests/test_futures.rb +10 -38
- data/tests/test_get_sock_opt.rb +27 -20
- data/tests/test_handler_check.rb +1 -3
- data/tests/test_hc.rb +49 -112
- data/tests/test_httpclient.rb +34 -62
- data/tests/test_httpclient2.rb +14 -39
- data/tests/test_inactivity_timeout.rb +44 -40
- data/tests/test_kb.rb +26 -52
- data/tests/test_ltp.rb +27 -71
- data/tests/test_ltp2.rb +1 -30
- data/tests/test_next_tick.rb +2 -31
- data/tests/test_object_protocol.rb +8 -9
- data/tests/test_pause.rb +45 -37
- data/tests/test_pending_connect_timeout.rb +42 -38
- data/tests/test_pool.rb +128 -0
- data/tests/test_process_watch.rb +37 -37
- data/tests/test_processes.rb +92 -110
- data/tests/test_proxy_connection.rb +137 -61
- data/tests/test_pure.rb +30 -67
- data/tests/test_queue.rb +10 -4
- data/tests/test_resolver.rb +55 -0
- data/tests/test_running.rb +1 -29
- data/tests/test_sasl.rb +8 -33
- data/tests/test_send_file.rb +163 -188
- data/tests/test_servers.rb +12 -55
- data/tests/test_shutdown_hooks.rb +23 -0
- data/tests/test_smtpclient.rb +1 -29
- data/tests/test_smtpserver.rb +1 -29
- data/tests/test_spawn.rb +2 -31
- data/tests/test_ssl_args.rb +9 -10
- data/tests/test_ssl_methods.rb +1 -3
- data/tests/test_ssl_verify.rb +63 -63
- data/tests/test_threaded_resource.rb +53 -0
- data/tests/test_tick_loop.rb +59 -0
- data/tests/test_timers.rb +52 -91
- data/tests/test_ud.rb +1 -29
- data/tests/test_unbind_reason.rb +31 -0
- metadata +113 -70
- data/README +0 -82
- data/docs/DEFERRABLES +0 -133
- data/docs/LIGHTWEIGHT_CONCURRENCY +0 -70
- data/docs/SMTP +0 -2
- data/docs/SPAWNED_PROCESSES +0 -89
- data/ext/cplusplus.cpp +0 -202
- data/ext/emwin.cpp +0 -300
- data/ext/emwin.h +0 -94
- data/ext/epoll.cpp +0 -26
- data/ext/epoll.h +0 -25
- data/ext/eventmachine_cpp.h +0 -96
- data/ext/files.cpp +0 -94
- data/ext/files.h +0 -65
- data/ext/sigs.cpp +0 -89
- data/ext/sigs.h +0 -32
- data/java/src/com/rubyeventmachine/application/Application.java +0 -194
- data/java/src/com/rubyeventmachine/application/Connection.java +0 -74
- data/java/src/com/rubyeventmachine/application/ConnectionFactory.java +0 -37
- data/java/src/com/rubyeventmachine/application/DefaultConnectionFactory.java +0 -46
- data/java/src/com/rubyeventmachine/application/PeriodicTimer.java +0 -38
- data/java/src/com/rubyeventmachine/application/Timer.java +0 -54
- data/java/src/com/rubyeventmachine/tests/ApplicationTest.java +0 -109
- data/java/src/com/rubyeventmachine/tests/ConnectTest.java +0 -148
- data/java/src/com/rubyeventmachine/tests/EMTest.java +0 -80
- data/java/src/com/rubyeventmachine/tests/TestDatagrams.java +0 -53
- data/java/src/com/rubyeventmachine/tests/TestServers.java +0 -75
- data/java/src/com/rubyeventmachine/tests/TestTimers.java +0 -90
- data/lib/evma/callback.rb +0 -32
- data/lib/evma/container.rb +0 -75
- data/lib/evma/factory.rb +0 -77
- data/lib/evma/protocol.rb +0 -87
- data/lib/evma/reactor.rb +0 -48
- data/lib/evma.rb +0 -32
- data/setup.rb +0 -1585
- data/tests/test_errors.rb +0 -82
- data/tests/testem.rb +0 -31
- data/web/whatis +0 -7
- /data/{docs/GNU → GNU} +0 -0
- /data/{docs/COPYING → LICENSE} +0 -0
- /data/docs/{ChangeLog → old/ChangeLog} +0 -0
- /data/docs/{EPOLL → old/EPOLL} +0 -0
- /data/docs/{INSTALL → old/INSTALL} +0 -0
- /data/docs/{LEGAL → old/LEGAL} +0 -0
- /data/docs/{PURE_RUBY → old/PURE_RUBY} +0 -0
- /data/docs/{RELEASE_NOTES → old/RELEASE_NOTES} +0 -0
- /data/docs/{TODO → old/TODO} +0 -0
- /data/examples/{ex_queue.rb → old/ex_queue.rb} +0 -0
- /data/examples/{helper.rb → old/helper.rb} +0 -0
data/ext/rubymain.cpp
CHANGED
@@ -31,6 +31,8 @@ Statics
|
|
31
31
|
|
32
32
|
static VALUE EmModule;
|
33
33
|
static VALUE EmConnection;
|
34
|
+
static VALUE EmConnsHash;
|
35
|
+
static VALUE EmTimersHash;
|
34
36
|
|
35
37
|
static VALUE EM_eConnectionError;
|
36
38
|
static VALUE EM_eUnknownTimerFired;
|
@@ -51,89 +53,121 @@ static VALUE Intern_ssl_verify_peer;
|
|
51
53
|
static VALUE Intern_notify_readable;
|
52
54
|
static VALUE Intern_notify_writable;
|
53
55
|
static VALUE Intern_proxy_target_unbound;
|
56
|
+
static VALUE Intern_proxy_completed;
|
57
|
+
static VALUE Intern_connection_completed;
|
54
58
|
|
55
59
|
static VALUE rb_cProcStatus;
|
56
60
|
|
57
61
|
struct em_event {
|
58
|
-
unsigned long
|
59
|
-
int
|
60
|
-
const char *
|
61
|
-
unsigned long
|
62
|
+
unsigned long signature;
|
63
|
+
int event;
|
64
|
+
const char *data_str;
|
65
|
+
unsigned long data_num;
|
62
66
|
};
|
63
67
|
|
68
|
+
static inline VALUE ensure_conn(const unsigned long signature)
|
69
|
+
{
|
70
|
+
VALUE conn = rb_hash_aref (EmConnsHash, ULONG2NUM (signature));
|
71
|
+
if (conn == Qnil)
|
72
|
+
rb_raise (EM_eConnectionNotBound, "unknown connection: %lu", signature);
|
73
|
+
return conn;
|
74
|
+
}
|
75
|
+
|
76
|
+
|
64
77
|
/****************
|
65
78
|
t_event_callback
|
66
79
|
****************/
|
67
80
|
|
68
|
-
static void event_callback (struct em_event* e)
|
69
|
-
{
|
70
|
-
const unsigned long
|
71
|
-
int
|
72
|
-
const char *
|
73
|
-
const unsigned long
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
81
|
+
static inline void event_callback (struct em_event* e)
|
82
|
+
{
|
83
|
+
const unsigned long signature = e->signature;
|
84
|
+
int event = e->event;
|
85
|
+
const char *data_str = e->data_str;
|
86
|
+
const unsigned long data_num = e->data_num;
|
87
|
+
|
88
|
+
switch (event) {
|
89
|
+
case EM_CONNECTION_READ:
|
90
|
+
{
|
91
|
+
VALUE conn = rb_hash_aref (EmConnsHash, ULONG2NUM (signature));
|
92
|
+
if (conn == Qnil)
|
93
|
+
rb_raise (EM_eConnectionNotBound, "received %lu bytes of data for unknown signature: %lu", data_num, signature);
|
94
|
+
rb_funcall (conn, Intern_receive_data, 1, rb_str_new (data_str, data_num));
|
95
|
+
return;
|
96
|
+
}
|
97
|
+
case EM_CONNECTION_ACCEPTED:
|
98
|
+
{
|
99
|
+
rb_funcall (EmModule, Intern_event_callback, 3, ULONG2NUM(signature), INT2FIX(event), ULONG2NUM(data_num));
|
100
|
+
return;
|
101
|
+
}
|
102
|
+
case EM_CONNECTION_UNBOUND:
|
103
|
+
{
|
104
|
+
rb_funcall (EmModule, Intern_event_callback, 3, ULONG2NUM(signature), INT2FIX(event), ULONG2NUM(data_num));
|
105
|
+
return;
|
106
|
+
}
|
107
|
+
case EM_CONNECTION_COMPLETED:
|
108
|
+
{
|
109
|
+
VALUE conn = ensure_conn(signature);
|
110
|
+
rb_funcall (conn, Intern_connection_completed, 0);
|
111
|
+
return;
|
112
|
+
}
|
113
|
+
case EM_CONNECTION_NOTIFY_READABLE:
|
114
|
+
{
|
115
|
+
VALUE conn = ensure_conn(signature);
|
116
|
+
rb_funcall (conn, Intern_notify_readable, 0);
|
117
|
+
return;
|
118
|
+
}
|
119
|
+
case EM_CONNECTION_NOTIFY_WRITABLE:
|
120
|
+
{
|
121
|
+
VALUE conn = ensure_conn(signature);
|
122
|
+
rb_funcall (conn, Intern_notify_writable, 0);
|
123
|
+
return;
|
124
|
+
}
|
125
|
+
case EM_LOOPBREAK_SIGNAL:
|
126
|
+
{
|
127
|
+
rb_funcall (EmModule, Intern_run_deferred_callbacks, 0);
|
128
|
+
return;
|
129
|
+
}
|
130
|
+
case EM_TIMER_FIRED:
|
131
|
+
{
|
132
|
+
VALUE timer = rb_funcall (EmTimersHash, Intern_delete, 1, ULONG2NUM (data_num));
|
133
|
+
if (timer == Qnil) {
|
134
|
+
rb_raise (EM_eUnknownTimerFired, "no such timer: %lu", data_num);
|
135
|
+
} else if (timer == Qfalse) {
|
136
|
+
/* Timer Canceled */
|
137
|
+
} else {
|
138
|
+
rb_funcall (timer, Intern_call, 0);
|
139
|
+
}
|
140
|
+
return;
|
141
|
+
}
|
142
|
+
#ifdef WITH_SSL
|
143
|
+
case EM_SSL_HANDSHAKE_COMPLETED:
|
144
|
+
{
|
145
|
+
VALUE conn = ensure_conn(signature);
|
146
|
+
rb_funcall (conn, Intern_ssl_handshake_completed, 0);
|
147
|
+
return;
|
148
|
+
}
|
149
|
+
case EM_SSL_VERIFY:
|
150
|
+
{
|
151
|
+
VALUE conn = ensure_conn(signature);
|
152
|
+
VALUE should_accept = rb_funcall (conn, Intern_ssl_verify_peer, 1, rb_str_new(data_str, data_num));
|
153
|
+
if (RTEST(should_accept))
|
154
|
+
evma_accept_ssl_peer (signature);
|
155
|
+
return;
|
156
|
+
}
|
157
|
+
#endif
|
158
|
+
case EM_PROXY_TARGET_UNBOUND:
|
159
|
+
{
|
160
|
+
VALUE conn = ensure_conn(signature);
|
161
|
+
rb_funcall (conn, Intern_proxy_target_unbound, 0);
|
162
|
+
return;
|
163
|
+
}
|
164
|
+
case EM_PROXY_COMPLETED:
|
165
|
+
{
|
166
|
+
VALUE conn = ensure_conn(signature);
|
167
|
+
rb_funcall (conn, Intern_proxy_completed, 0);
|
168
|
+
return;
|
108
169
|
}
|
109
170
|
}
|
110
|
-
#ifdef WITH_SSL
|
111
|
-
else if (a2 == EM_SSL_HANDSHAKE_COMPLETED) {
|
112
|
-
VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
|
113
|
-
VALUE q = rb_hash_aref (t, ULONG2NUM (a1));
|
114
|
-
if (q == Qnil)
|
115
|
-
rb_raise (EM_eConnectionNotBound, "unknown connection: %lu", a1);
|
116
|
-
rb_funcall (q, Intern_ssl_handshake_completed, 0);
|
117
|
-
}
|
118
|
-
else if (a2 == EM_SSL_VERIFY) {
|
119
|
-
VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
|
120
|
-
VALUE q = rb_hash_aref (t, ULONG2NUM (a1));
|
121
|
-
if (q == Qnil)
|
122
|
-
rb_raise (EM_eConnectionNotBound, "unknown connection: %lu", a1);
|
123
|
-
VALUE r = rb_funcall (q, Intern_ssl_verify_peer, 1, rb_str_new(a3, a4));
|
124
|
-
if (RTEST(r))
|
125
|
-
evma_accept_ssl_peer (a1);
|
126
|
-
}
|
127
|
-
#endif
|
128
|
-
else if (a2 == EM_PROXY_TARGET_UNBOUND) {
|
129
|
-
VALUE t = rb_ivar_get (EmModule, Intern_at_conns);
|
130
|
-
VALUE q = rb_hash_aref (t, ULONG2NUM (a1));
|
131
|
-
if (q == Qnil)
|
132
|
-
rb_raise (EM_eConnectionNotBound, "unknown connection: %lu", a1);
|
133
|
-
rb_funcall (q, Intern_proxy_target_unbound, 0);
|
134
|
-
}
|
135
|
-
else
|
136
|
-
rb_funcall (EmModule, Intern_event_callback, 3, ULONG2NUM(a1), INT2FIX(a2), a3 ? rb_str_new(a3,a4) : ULONG2NUM(a4));
|
137
171
|
}
|
138
172
|
|
139
173
|
/*******************
|
@@ -150,13 +184,13 @@ static void event_error_handler(VALUE unused, VALUE err)
|
|
150
184
|
event_callback_wrapper
|
151
185
|
**********************/
|
152
186
|
|
153
|
-
static void event_callback_wrapper (const unsigned long
|
187
|
+
static void event_callback_wrapper (const unsigned long signature, int event, const char *data_str, const unsigned long data_num)
|
154
188
|
{
|
155
189
|
struct em_event e;
|
156
|
-
e.
|
157
|
-
e.
|
158
|
-
e.
|
159
|
-
e.
|
190
|
+
e.signature = signature;
|
191
|
+
e.event = event;
|
192
|
+
e.data_str = data_str;
|
193
|
+
e.data_num = data_num;
|
160
194
|
|
161
195
|
if (!rb_ivar_defined(EmModule, Intern_at_error_handler))
|
162
196
|
event_callback(&e);
|
@@ -170,7 +204,11 @@ t_initialize_event_machine
|
|
170
204
|
|
171
205
|
static VALUE t_initialize_event_machine (VALUE self)
|
172
206
|
{
|
173
|
-
|
207
|
+
EmConnsHash = rb_ivar_get (EmModule, Intern_at_conns);
|
208
|
+
EmTimersHash = rb_ivar_get (EmModule, Intern_at_timers);
|
209
|
+
assert(EmConnsHash != Qnil);
|
210
|
+
assert(EmTimersHash != Qnil);
|
211
|
+
evma_initialize_library ((EMCallback)event_callback_wrapper);
|
174
212
|
return Qnil;
|
175
213
|
}
|
176
214
|
|
@@ -208,7 +246,7 @@ static VALUE t_start_server (VALUE self, VALUE server, VALUE port)
|
|
208
246
|
{
|
209
247
|
const unsigned long f = evma_create_tcp_server (StringValuePtr(server), FIX2INT(port));
|
210
248
|
if (!f)
|
211
|
-
rb_raise (rb_eRuntimeError, "no acceptor");
|
249
|
+
rb_raise (rb_eRuntimeError, "no acceptor (port is in use or requires root privileges)");
|
212
250
|
return ULONG2NUM (f);
|
213
251
|
}
|
214
252
|
|
@@ -307,9 +345,10 @@ t_get_peername
|
|
307
345
|
|
308
346
|
static VALUE t_get_peername (VALUE self, VALUE signature)
|
309
347
|
{
|
310
|
-
|
311
|
-
|
312
|
-
|
348
|
+
char buf[1024];
|
349
|
+
socklen_t len = sizeof buf;
|
350
|
+
if (evma_get_peername (NUM2ULONG (signature), (struct sockaddr*)buf, &len)) {
|
351
|
+
return rb_str_new (buf, len);
|
313
352
|
}
|
314
353
|
|
315
354
|
return Qnil;
|
@@ -321,9 +360,10 @@ t_get_sockname
|
|
321
360
|
|
322
361
|
static VALUE t_get_sockname (VALUE self, VALUE signature)
|
323
362
|
{
|
324
|
-
|
325
|
-
|
326
|
-
|
363
|
+
char buf[1024];
|
364
|
+
socklen_t len = sizeof buf;
|
365
|
+
if (evma_get_sockname (NUM2ULONG (signature), (struct sockaddr*)buf, &len)) {
|
366
|
+
return rb_str_new (buf, len);
|
327
367
|
}
|
328
368
|
|
329
369
|
return Qnil;
|
@@ -390,8 +430,9 @@ t_set_comm_inactivity_timeout
|
|
390
430
|
static VALUE t_set_comm_inactivity_timeout (VALUE self, VALUE signature, VALUE timeout)
|
391
431
|
{
|
392
432
|
float ti = RFLOAT_VALUE(timeout);
|
393
|
-
if (evma_set_comm_inactivity_timeout
|
433
|
+
if (evma_set_comm_inactivity_timeout(NUM2ULONG(signature), ti)) {
|
394
434
|
return Qtrue;
|
435
|
+
}
|
395
436
|
return Qfalse;
|
396
437
|
}
|
397
438
|
|
@@ -411,8 +452,9 @@ t_set_pending_connect_timeout
|
|
411
452
|
static VALUE t_set_pending_connect_timeout (VALUE self, VALUE signature, VALUE timeout)
|
412
453
|
{
|
413
454
|
float ti = RFLOAT_VALUE(timeout);
|
414
|
-
if (evma_set_pending_connect_timeout
|
455
|
+
if (evma_set_pending_connect_timeout(NUM2ULONG(signature), ti)) {
|
415
456
|
return Qtrue;
|
457
|
+
}
|
416
458
|
return Qfalse;
|
417
459
|
}
|
418
460
|
|
@@ -467,6 +509,7 @@ static VALUE t_connect_server (VALUE self, VALUE server, VALUE port)
|
|
467
509
|
} catch (std::runtime_error e) {
|
468
510
|
rb_raise (EM_eConnectionError, e.what());
|
469
511
|
}
|
512
|
+
return Qnil;
|
470
513
|
}
|
471
514
|
|
472
515
|
/*********************
|
@@ -487,6 +530,7 @@ static VALUE t_bind_connect_server (VALUE self, VALUE bind_addr, VALUE bind_port
|
|
487
530
|
} catch (std::runtime_error e) {
|
488
531
|
rb_raise (EM_eConnectionError, e.what());
|
489
532
|
}
|
533
|
+
return Qnil;
|
490
534
|
}
|
491
535
|
|
492
536
|
/*********************
|
@@ -701,18 +745,6 @@ static VALUE t_setuid_string (VALUE self, VALUE username)
|
|
701
745
|
|
702
746
|
|
703
747
|
|
704
|
-
/*************
|
705
|
-
t__write_file
|
706
|
-
*************/
|
707
|
-
|
708
|
-
static VALUE t__write_file (VALUE self, VALUE filename)
|
709
|
-
{
|
710
|
-
const unsigned long f = evma__write_file (StringValuePtr (filename));
|
711
|
-
if (!f)
|
712
|
-
rb_raise (rb_eRuntimeError, "file not opened");
|
713
|
-
return ULONG2NUM (f);
|
714
|
-
}
|
715
|
-
|
716
748
|
/**************
|
717
749
|
t_invoke_popen
|
718
750
|
**************/
|
@@ -725,13 +757,17 @@ static VALUE t_invoke_popen (VALUE self, VALUE cmd)
|
|
725
757
|
#else
|
726
758
|
int len = RARRAY (cmd)->len;
|
727
759
|
#endif
|
728
|
-
if (len
|
760
|
+
if (len >= 2048)
|
729
761
|
rb_raise (rb_eRuntimeError, "too many arguments to popen");
|
730
|
-
char *strings [
|
762
|
+
char *strings [2048];
|
731
763
|
for (int i=0; i < len; i++) {
|
732
764
|
VALUE ix = INT2FIX (i);
|
733
765
|
VALUE s = rb_ary_aref (1, &ix, cmd);
|
766
|
+
#ifdef BUILD_FOR_MAGLEV
|
734
767
|
strings[i] = (char*)StringValuePtr (s);
|
768
|
+
#else
|
769
|
+
strings[i] = StringValuePtr (s);
|
770
|
+
#endif
|
735
771
|
}
|
736
772
|
strings[len] = NULL;
|
737
773
|
|
@@ -769,8 +805,9 @@ static VALUE t_watch_filename (VALUE self, VALUE fname)
|
|
769
805
|
try {
|
770
806
|
return ULONG2NUM(evma_watch_filename(StringValuePtr(fname)));
|
771
807
|
} catch (std::runtime_error e) {
|
772
|
-
|
808
|
+
rb_raise (EM_eUnsupported, e.what());
|
773
809
|
}
|
810
|
+
return Qnil;
|
774
811
|
}
|
775
812
|
|
776
813
|
|
@@ -794,8 +831,9 @@ static VALUE t_watch_pid (VALUE self, VALUE pid)
|
|
794
831
|
try {
|
795
832
|
return ULONG2NUM(evma_watch_pid(NUM2INT(pid)));
|
796
833
|
} catch (std::runtime_error e) {
|
797
|
-
|
834
|
+
rb_raise (EM_eUnsupported, e.what());
|
798
835
|
}
|
836
|
+
return Qnil;
|
799
837
|
}
|
800
838
|
|
801
839
|
|
@@ -972,11 +1010,12 @@ static VALUE t_get_loop_time (VALUE self)
|
|
972
1010
|
static ID at = rb_intern("at");
|
973
1011
|
#endif
|
974
1012
|
|
975
|
-
|
1013
|
+
uint64_t current_time = evma_get_current_loop_time();
|
1014
|
+
if (current_time != 0) {
|
976
1015
|
#ifndef HAVE_RB_TIME_NEW
|
977
|
-
return rb_funcall(cTime, at, 2, INT2NUM(
|
1016
|
+
return rb_funcall(cTime, at, 2, INT2NUM(current_time / 1000000), INT2NUM(current_time % 1000000));
|
978
1017
|
#else
|
979
|
-
return rb_time_new(
|
1018
|
+
return rb_time_new(current_time / 1000000, current_time % 1000000);
|
980
1019
|
#endif
|
981
1020
|
}
|
982
1021
|
return Qnil;
|
@@ -987,9 +1026,13 @@ static VALUE t_get_loop_time (VALUE self)
|
|
987
1026
|
t_start_proxy
|
988
1027
|
**************/
|
989
1028
|
|
990
|
-
static VALUE t_start_proxy (VALUE self, VALUE from, VALUE to, VALUE bufsize)
|
1029
|
+
static VALUE t_start_proxy (VALUE self, VALUE from, VALUE to, VALUE bufsize, VALUE length)
|
991
1030
|
{
|
992
|
-
|
1031
|
+
try {
|
1032
|
+
evma_start_proxy(NUM2ULONG (from), NUM2ULONG (to), NUM2ULONG(bufsize), NUM2ULONG(length));
|
1033
|
+
} catch (std::runtime_error e) {
|
1034
|
+
rb_raise (EM_eConnectionError, e.what());
|
1035
|
+
}
|
993
1036
|
return Qnil;
|
994
1037
|
}
|
995
1038
|
|
@@ -1000,7 +1043,11 @@ t_stop_proxy
|
|
1000
1043
|
|
1001
1044
|
static VALUE t_stop_proxy (VALUE self, VALUE from)
|
1002
1045
|
{
|
1003
|
-
|
1046
|
+
try{
|
1047
|
+
evma_stop_proxy(NUM2ULONG (from));
|
1048
|
+
} catch (std::runtime_error e) {
|
1049
|
+
rb_raise (EM_eConnectionError, e.what());
|
1050
|
+
}
|
1004
1051
|
return Qnil;
|
1005
1052
|
}
|
1006
1053
|
|
@@ -1054,6 +1101,8 @@ extern "C" void Init_rubyeventmachine()
|
|
1054
1101
|
Intern_notify_readable = rb_intern ("notify_readable");
|
1055
1102
|
Intern_notify_writable = rb_intern ("notify_writable");
|
1056
1103
|
Intern_proxy_target_unbound = rb_intern ("proxy_target_unbound");
|
1104
|
+
Intern_proxy_completed = rb_intern ("proxy_completed");
|
1105
|
+
Intern_connection_completed = rb_intern ("connection_completed");
|
1057
1106
|
|
1058
1107
|
// INCOMPLETE, we need to define class Connections inside module EventMachine
|
1059
1108
|
// run_machine and run_machine_without_threads are now identical.
|
@@ -1097,7 +1146,7 @@ extern "C" void Init_rubyeventmachine()
|
|
1097
1146
|
rb_define_module_function (EmModule, "resume_connection", (VALUE (*)(...))t_resume, 1);
|
1098
1147
|
rb_define_module_function (EmModule, "connection_paused?", (VALUE (*)(...))t_paused_p, 1);
|
1099
1148
|
|
1100
|
-
rb_define_module_function (EmModule, "start_proxy", (VALUE (*)(...))t_start_proxy,
|
1149
|
+
rb_define_module_function (EmModule, "start_proxy", (VALUE (*)(...))t_start_proxy, 4);
|
1101
1150
|
rb_define_module_function (EmModule, "stop_proxy", (VALUE (*)(...))t_stop_proxy, 1);
|
1102
1151
|
|
1103
1152
|
rb_define_module_function (EmModule, "watch_filename", (VALUE (*)(...))t_watch_filename, 1);
|
@@ -1123,9 +1172,6 @@ extern "C" void Init_rubyeventmachine()
|
|
1123
1172
|
rb_define_module_function (EmModule, "get_heartbeat_interval", (VALUE(*)(...))t_get_heartbeat_interval, 0);
|
1124
1173
|
rb_define_module_function (EmModule, "set_heartbeat_interval", (VALUE(*)(...))t_set_heartbeat_interval, 1);
|
1125
1174
|
|
1126
|
-
// Provisional:
|
1127
|
-
rb_define_module_function (EmModule, "_write_file", (VALUE(*)(...))t__write_file, 1);
|
1128
|
-
|
1129
1175
|
rb_define_module_function (EmModule, "get_peername", (VALUE(*)(...))t_get_peername, 1);
|
1130
1176
|
rb_define_module_function (EmModule, "get_sockname", (VALUE(*)(...))t_get_sockname, 1);
|
1131
1177
|
rb_define_module_function (EmModule, "get_subprocess_pid", (VALUE(*)(...))t_get_subprocess_pid, 1);
|
@@ -48,6 +48,7 @@ public class EmReactor {
|
|
48
48
|
public final int EM_SSL_HANDSHAKE_COMPLETED = 108;
|
49
49
|
public final int EM_SSL_VERIFY = 109;
|
50
50
|
public final int EM_PROXY_TARGET_UNBOUND = 110;
|
51
|
+
public final int EM_PROXY_COMPLETED = 111;
|
51
52
|
|
52
53
|
private Selector mySelector;
|
53
54
|
private TreeMap<Long, ArrayList<Long>> Timers;
|
@@ -441,8 +442,8 @@ public class EmReactor {
|
|
441
442
|
Connections.get(sig).setCommInactivityTimeout (mills);
|
442
443
|
}
|
443
444
|
|
444
|
-
public void sendDatagram (long sig,
|
445
|
-
sendDatagram (sig, ByteBuffer.wrap(data
|
445
|
+
public void sendDatagram (long sig, byte[] data, int length, String recipAddress, int recipPort) {
|
446
|
+
sendDatagram (sig, ByteBuffer.wrap(data), recipAddress, recipPort);
|
446
447
|
}
|
447
448
|
|
448
449
|
public void sendDatagram (long sig, ByteBuffer bb, String recipAddress, int recipPort) {
|
data/lib/em/buftok.rb
CHANGED
@@ -1,43 +1,29 @@
|
|
1
|
-
# BufferedTokenizer - Statefully split input data by a specifiable token
|
2
|
-
#
|
3
|
-
# Authors:: Tony Arcieri, Martin Emde
|
4
|
-
#
|
5
|
-
#----------------------------------------------------------------------------
|
6
|
-
#
|
7
|
-
# Copyright (C) 2006-07 by Tony Arcieri and Martin Emde
|
8
|
-
#
|
9
|
-
# Distributed under the Ruby license (http://www.ruby-lang.org/en/LICENSE.txt)
|
10
|
-
#
|
11
|
-
#---------------------------------------------------------------------------
|
12
|
-
#
|
13
|
-
|
14
|
-
# (C)2006 Tony Arcieri, Martin Emde
|
15
|
-
# Distributed under the Ruby license (http://www.ruby-lang.org/en/LICENSE.txt)
|
16
|
-
|
17
1
|
# BufferedTokenizer takes a delimiter upon instantiation, or acts line-based
|
18
2
|
# by default. It allows input to be spoon-fed from some outside source which
|
19
3
|
# receives arbitrary length datagrams which may-or-may-not contain the token
|
20
4
|
# by which entities are delimited.
|
21
5
|
#
|
22
|
-
#
|
6
|
+
# By default, new BufferedTokenizers will operate on lines delimited by "\n" by default
|
7
|
+
# or allow you to specify any delimiter token you so choose, which will then
|
8
|
+
# be used by String#split to tokenize the input data
|
23
9
|
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
|
10
|
+
# @example Using BufferedTokernizer to parse lines out of incoming data
|
11
|
+
#
|
12
|
+
# module LineBufferedConnection
|
13
|
+
# def receive_data(data)
|
14
|
+
# (@buffer ||= BufferedTokenizer.new).extract(data).each do |line|
|
15
|
+
# receive_line(line)
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# @author Tony Arcieri
|
21
|
+
# @author Martin Emde
|
32
22
|
class BufferedTokenizer
|
33
|
-
#
|
34
|
-
#
|
35
|
-
# be used by String#split to tokenize the input data
|
23
|
+
# @param [String] delimiter
|
24
|
+
# @param [Integer] size_limit
|
36
25
|
def initialize(delimiter = "\n", size_limit = nil)
|
37
|
-
|
38
|
-
@delimiter = delimiter
|
39
|
-
|
40
|
-
# Store the specified size limitation
|
26
|
+
@delimiter = delimiter
|
41
27
|
@size_limit = size_limit
|
42
28
|
|
43
29
|
# The input buffer is stored as an array. This is by far the most efficient
|
@@ -52,14 +38,18 @@ class BufferedTokenizer
|
|
52
38
|
end
|
53
39
|
|
54
40
|
# Extract takes an arbitrary string of input data and returns an array of
|
55
|
-
# tokenized entities, provided there were any available to extract.
|
56
|
-
# makes for easy processing of datagrams using a pattern like:
|
41
|
+
# tokenized entities, provided there were any available to extract.
|
57
42
|
#
|
58
|
-
#
|
43
|
+
# @example
|
44
|
+
#
|
45
|
+
# tokenizer.extract(data).
|
46
|
+
# map { |entity| Decode(entity) }.each { ... }
|
47
|
+
#
|
48
|
+
# @param [String] data
|
59
49
|
def extract(data)
|
60
50
|
# Extract token-delimited entities from the input string with the split command.
|
61
51
|
# There's a bit of craftiness here with the -1 parameter. Normally split would
|
62
|
-
# behave no differently regardless of if the token lies at the very end of the
|
52
|
+
# behave no differently regardless of if the token lies at the very end of the
|
63
53
|
# input buffer or not (i.e. a literal edge case) Specifying -1 forces split to
|
64
54
|
# return "" in this case, meaning that the last entry in the list represents a
|
65
55
|
# new segment of data where the token has not been encountered
|
@@ -70,7 +60,7 @@ class BufferedTokenizer
|
|
70
60
|
raise 'input buffer full' if @input_size + entities.first.size > @size_limit
|
71
61
|
@input_size += entities.first.size
|
72
62
|
end
|
73
|
-
|
63
|
+
|
74
64
|
# Move the first entry in the resulting array into the input buffer. It represents
|
75
65
|
# the last segment of a token-delimited entity unless it's the only entry in the list.
|
76
66
|
@input << entities.shift
|
@@ -85,36 +75,16 @@ class BufferedTokenizer
|
|
85
75
|
# and add it to our list of discovered entities.
|
86
76
|
entities.unshift @input.join
|
87
77
|
|
88
|
-
=begin
|
89
|
-
# Note added by FC, 10Jul07. This paragraph contains a regression. It breaks
|
90
|
-
# empty tokens. Think of the empty line that delimits an HTTP header. It will have
|
91
|
-
# two "\n" delimiters in a row, and this code mishandles the resulting empty token.
|
92
|
-
# It someone figures out how to fix the problem, we can re-enable this code branch.
|
93
|
-
# Multi-character token support.
|
94
|
-
# Split any tokens that were incomplete on the last iteration buf complete now.
|
95
|
-
entities.map! do |e|
|
96
|
-
e.split @delimiter, -1
|
97
|
-
end
|
98
|
-
# Flatten the resulting array. This has the side effect of removing the empty
|
99
|
-
# entry at the end that was produced by passing -1 to split. Add it again if
|
100
|
-
# necessary.
|
101
|
-
if (entities[-1] == [])
|
102
|
-
entities.flatten! << []
|
103
|
-
else
|
104
|
-
entities.flatten!
|
105
|
-
end
|
106
|
-
=end
|
107
|
-
|
108
78
|
# Now that we've hit a token, joined the input buffer and added it to the entities
|
109
79
|
# list, we can go ahead and clear the input buffer. All of the segments that were
|
110
80
|
# stored before the join can now be garbage collected.
|
111
81
|
@input.clear
|
112
|
-
|
82
|
+
|
113
83
|
# The last entity in the list is not token delimited, however, thanks to the -1
|
114
|
-
# passed to split. It represents the beginning of a new list of as-yet-untokenized
|
84
|
+
# passed to split. It represents the beginning of a new list of as-yet-untokenized
|
115
85
|
# data, so we add it to the start of the list.
|
116
86
|
@input << entities.pop
|
117
|
-
|
87
|
+
|
118
88
|
# Set the new input buffer size, provided we're keeping track
|
119
89
|
@input_size = @input.first.size if @size_limit
|
120
90
|
|
@@ -122,16 +92,18 @@ class BufferedTokenizer
|
|
122
92
|
# in the first place. Hooray!
|
123
93
|
entities
|
124
94
|
end
|
125
|
-
|
95
|
+
|
126
96
|
# Flush the contents of the input buffer, i.e. return the input buffer even though
|
127
|
-
# a token has not yet been encountered
|
97
|
+
# a token has not yet been encountered.
|
98
|
+
#
|
99
|
+
# @return [String]
|
128
100
|
def flush
|
129
101
|
buffer = @input.join
|
130
102
|
@input.clear
|
131
103
|
buffer
|
132
104
|
end
|
133
105
|
|
134
|
-
#
|
106
|
+
# @return [Boolean]
|
135
107
|
def empty?
|
136
108
|
@input.empty?
|
137
109
|
end
|
data/lib/em/callback.rb
CHANGED
@@ -1,26 +1,58 @@
|
|
1
1
|
module EventMachine
|
2
|
-
# Utility method for coercing arguments to an object that responds to
|
2
|
+
# Utility method for coercing arguments to an object that responds to :call.
|
3
3
|
# Accepts an object and a method name to send to, or a block, or an object
|
4
|
-
# that responds to call.
|
4
|
+
# that responds to :call.
|
5
5
|
#
|
6
|
-
#
|
6
|
+
# @example EventMachine.Callback used with a block. Returns that block.
|
7
|
+
#
|
8
|
+
# cb = EventMachine.Callback do |msg|
|
9
|
+
# puts(msg)
|
10
|
+
# end
|
11
|
+
# # returned object is a callable
|
7
12
|
# cb.call('hello world')
|
8
13
|
#
|
9
|
-
#
|
14
|
+
#
|
15
|
+
# @example EventMachine.Callback used with an object (to be more specific, class object) and a method name, returns an object that responds to #call
|
16
|
+
#
|
17
|
+
# cb = EventMachine.Callback(Object, :puts)
|
18
|
+
# # returned object is a callable that delegates to Kernel#puts (in this case Object.puts)
|
10
19
|
# cb.call('hello world')
|
11
20
|
#
|
12
|
-
#
|
21
|
+
#
|
22
|
+
# @example EventMachine.Callback used with an object that responds to #call. Returns the argument.
|
23
|
+
#
|
24
|
+
# cb = EventMachine.Callback(proc{ |msg| puts(msg) })
|
25
|
+
# # returned object is a callable
|
13
26
|
# cb.call('hello world')
|
14
27
|
#
|
28
|
+
#
|
29
|
+
# @overload Callback(object, method)
|
30
|
+
# Wraps `method` invocation on `object` into an object that responds to #call that proxies all the arguments to that method
|
31
|
+
# @param [Object] Object to invoke method on
|
32
|
+
# @param [Symbol] Method name
|
33
|
+
# @return [<#call>] An object that responds to #call that takes any number of arguments and invokes method on object with those arguments
|
34
|
+
#
|
35
|
+
# @overload Callback(object)
|
36
|
+
# Returns callable object as is, without any coercion
|
37
|
+
# @param [<#call>] An object that responds to #call
|
38
|
+
# @return [<#call>] Its argument
|
39
|
+
#
|
40
|
+
# @overload Callback(&block)
|
41
|
+
# Returns block passed to it without any coercion
|
42
|
+
# @return [<#call>] Block passed to this method
|
43
|
+
#
|
44
|
+
# @raise [ArgumentError] When argument doesn't respond to #call, method name is missing or when invoked without arguments and block isn't given
|
45
|
+
#
|
46
|
+
# @return [<#call>]
|
15
47
|
def self.Callback(object = nil, method = nil, &blk)
|
16
48
|
if object && method
|
17
|
-
lambda { |*args| object.
|
49
|
+
lambda { |*args| object.__send__ method, *args }
|
18
50
|
else
|
19
51
|
if object.respond_to? :call
|
20
52
|
object
|
21
|
-
else
|
53
|
+
else
|
22
54
|
blk || raise(ArgumentError)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
55
|
+
end # if
|
56
|
+
end # if
|
57
|
+
end # self.Callback
|
58
|
+
end # EventMachine
|