eventmachine 0.12.10 → 1.0.0.beta.1
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/.gitignore +2 -0
- data/Gemfile +1 -0
- data/README +1 -2
- data/Rakefile +4 -76
- data/docs/DEFERRABLES +183 -70
- data/docs/KEYBOARD +15 -11
- data/docs/LIGHTWEIGHT_CONCURRENCY +84 -24
- data/docs/SMTP +3 -1
- data/docs/SPAWNED_PROCESSES +84 -25
- data/eventmachine.gemspec +19 -26
- data/examples/ex_tick_loop_array.rb +15 -0
- data/examples/ex_tick_loop_counter.rb +32 -0
- data/ext/binder.cpp +0 -1
- data/ext/cmain.cpp +36 -11
- data/ext/cplusplus.cpp +1 -1
- data/ext/ed.cpp +104 -113
- data/ext/ed.h +24 -30
- data/ext/em.cpp +347 -248
- data/ext/em.h +23 -16
- data/ext/eventmachine.h +5 -3
- data/ext/extconf.rb +5 -3
- data/ext/fastfilereader/extconf.rb +5 -3
- data/ext/fastfilereader/mapper.cpp +1 -1
- data/ext/kb.cpp +1 -3
- data/ext/pipe.cpp +9 -11
- data/ext/project.h +12 -4
- data/ext/rubymain.cpp +138 -89
- data/java/src/com/rubyeventmachine/EmReactor.java +1 -0
- data/lib/em/channel.rb +1 -1
- data/lib/em/connection.rb +6 -1
- data/lib/em/deferrable.rb +16 -2
- data/lib/em/iterator.rb +270 -0
- data/lib/em/protocols.rb +1 -1
- data/lib/em/protocols/httpclient.rb +5 -0
- data/lib/em/protocols/line_protocol.rb +28 -0
- data/lib/em/protocols/smtpserver.rb +101 -8
- data/lib/em/protocols/stomp.rb +1 -1
- data/lib/{pr_eventmachine.rb → em/pure_ruby.rb} +1 -11
- data/lib/em/queue.rb +1 -0
- data/lib/em/streamer.rb +1 -1
- data/lib/em/tick_loop.rb +85 -0
- data/lib/em/timers.rb +2 -1
- data/lib/em/version.rb +1 -1
- data/lib/eventmachine.rb +38 -84
- data/lib/jeventmachine.rb +1 -0
- data/tests/test_attach.rb +13 -3
- data/tests/test_basic.rb +60 -95
- data/tests/test_channel.rb +3 -2
- data/tests/test_defer.rb +14 -12
- data/tests/test_deferrable.rb +35 -0
- data/tests/test_file_watch.rb +1 -1
- data/tests/test_futures.rb +1 -1
- data/tests/test_hc.rb +40 -68
- data/tests/test_httpclient.rb +15 -6
- data/tests/test_httpclient2.rb +3 -2
- data/tests/test_inactivity_timeout.rb +3 -3
- data/tests/test_ltp.rb +13 -5
- data/tests/test_next_tick.rb +1 -1
- data/tests/test_pending_connect_timeout.rb +2 -2
- data/tests/test_process_watch.rb +36 -34
- data/tests/test_proxy_connection.rb +52 -0
- data/tests/test_pure.rb +10 -1
- data/tests/test_sasl.rb +1 -1
- data/tests/test_send_file.rb +16 -7
- data/tests/test_servers.rb +1 -1
- data/tests/test_tick_loop.rb +59 -0
- data/tests/test_timers.rb +13 -15
- metadata +45 -17
- data/web/whatis +0 -7
data/ext/em.h
CHANGED
@@ -57,16 +57,6 @@ See the file COPYING for complete licensing information.
|
|
57
57
|
#define EmSelect select
|
58
58
|
#endif
|
59
59
|
|
60
|
-
|
61
|
-
#ifdef OS_UNIX
|
62
|
-
typedef long long Int64;
|
63
|
-
#endif
|
64
|
-
#ifdef OS_WIN32
|
65
|
-
typedef __int64 Int64;
|
66
|
-
#endif
|
67
|
-
|
68
|
-
extern Int64 gCurrentLoopTime;
|
69
|
-
|
70
60
|
class EventableDescriptor;
|
71
61
|
class InotifyDescriptor;
|
72
62
|
|
@@ -82,7 +72,7 @@ class EventMachine_t
|
|
82
72
|
static void SetMaxTimerCount (int);
|
83
73
|
|
84
74
|
public:
|
85
|
-
EventMachine_t (
|
75
|
+
EventMachine_t (EMCallback);
|
86
76
|
virtual ~EventMachine_t();
|
87
77
|
|
88
78
|
void Run();
|
@@ -137,6 +127,8 @@ class EventMachine_t
|
|
137
127
|
void _HandleKqueuePidEvent (struct kevent*);
|
138
128
|
#endif
|
139
129
|
|
130
|
+
uint64_t GetCurrentLoopTime() { return MyCurrentLoopTime; }
|
131
|
+
|
140
132
|
// Temporary:
|
141
133
|
void _UseEpoll();
|
142
134
|
void _UseKqueue();
|
@@ -144,6 +136,11 @@ class EventMachine_t
|
|
144
136
|
bool UsingKqueue() { return bKqueue; }
|
145
137
|
bool UsingEpoll() { return bEpoll; }
|
146
138
|
|
139
|
+
void QueueHeartbeat(EventableDescriptor*);
|
140
|
+
void ClearHeartbeat(uint64_t);
|
141
|
+
|
142
|
+
uint64_t GetRealTime();
|
143
|
+
|
147
144
|
private:
|
148
145
|
bool _RunOnce();
|
149
146
|
bool _RunTimers();
|
@@ -151,12 +148,16 @@ class EventMachine_t
|
|
151
148
|
void _AddNewDescriptors();
|
152
149
|
void _ModifyDescriptors();
|
153
150
|
void _InitializeLoopBreaker();
|
151
|
+
void _CleanupSockets();
|
154
152
|
|
155
153
|
bool _RunSelectOnce();
|
156
154
|
bool _RunEpollOnce();
|
157
155
|
bool _RunKqueueOnce();
|
158
156
|
|
159
157
|
void _ModifyEpollEvent (EventableDescriptor*);
|
158
|
+
void _DispatchHeartbeats();
|
159
|
+
timeval _TimeTilNextEvent();
|
160
|
+
void _CleanBadDescriptors();
|
160
161
|
|
161
162
|
public:
|
162
163
|
void _ReadLoopBreaker();
|
@@ -168,19 +169,20 @@ class EventMachine_t
|
|
168
169
|
MaxEvents = 4096
|
169
170
|
};
|
170
171
|
int HeartbeatInterval;
|
171
|
-
|
172
|
+
EMCallback EventCallback;
|
172
173
|
|
173
174
|
class Timer_t: public Bindable_t {
|
174
175
|
};
|
175
176
|
|
176
|
-
multimap<
|
177
|
+
multimap<uint64_t, Timer_t> Timers;
|
178
|
+
multimap<uint64_t, EventableDescriptor*> Heartbeats;
|
177
179
|
map<int, Bindable_t*> Files;
|
178
180
|
map<int, Bindable_t*> Pids;
|
179
181
|
vector<EventableDescriptor*> Descriptors;
|
180
182
|
vector<EventableDescriptor*> NewDescriptors;
|
181
183
|
set<EventableDescriptor*> ModifiedDescriptors;
|
182
184
|
|
183
|
-
|
185
|
+
uint64_t NextHeartbeatTime;
|
184
186
|
|
185
187
|
int LoopBreakerReader;
|
186
188
|
int LoopBreakerWriter;
|
@@ -190,6 +192,13 @@ class EventMachine_t
|
|
190
192
|
|
191
193
|
timeval Quantum;
|
192
194
|
|
195
|
+
uint64_t MyCurrentLoopTime;
|
196
|
+
|
197
|
+
#ifdef OS_WIN32
|
198
|
+
unsigned TickCountTickover;
|
199
|
+
unsigned LastTickCount;
|
200
|
+
#endif
|
201
|
+
|
193
202
|
private:
|
194
203
|
bool bEpoll;
|
195
204
|
int epfd; // Epoll file-descriptor
|
@@ -225,8 +234,6 @@ struct SelectData_t
|
|
225
234
|
int nSockets;
|
226
235
|
};
|
227
236
|
|
228
|
-
|
229
|
-
|
230
237
|
#endif // __EventMachine__H_
|
231
238
|
|
232
239
|
//#endif // OS_UNIX
|
data/ext/eventmachine.h
CHANGED
@@ -35,11 +35,12 @@ extern "C" {
|
|
35
35
|
EM_CONNECTION_NOTIFY_WRITABLE = 107,
|
36
36
|
EM_SSL_HANDSHAKE_COMPLETED = 108,
|
37
37
|
EM_SSL_VERIFY = 109,
|
38
|
-
EM_PROXY_TARGET_UNBOUND = 110
|
38
|
+
EM_PROXY_TARGET_UNBOUND = 110,
|
39
|
+
EM_PROXY_COMPLETED = 111
|
39
40
|
|
40
41
|
};
|
41
42
|
|
42
|
-
void evma_initialize_library (
|
43
|
+
void evma_initialize_library (EMCallback);
|
43
44
|
void evma_run_machine();
|
44
45
|
void evma_release_library();
|
45
46
|
const unsigned long evma_install_oneshot_timer (int seconds);
|
@@ -105,7 +106,7 @@ extern "C" {
|
|
105
106
|
const unsigned long evma_watch_pid (int);
|
106
107
|
void evma_unwatch_pid (const unsigned long);
|
107
108
|
|
108
|
-
void evma_start_proxy(const unsigned long, const unsigned long, const unsigned long);
|
109
|
+
void evma_start_proxy(const unsigned long, const unsigned long, const unsigned long, const unsigned long);
|
109
110
|
void evma_stop_proxy(const unsigned long);
|
110
111
|
|
111
112
|
int evma_set_rlimit_nofile (int n_files);
|
@@ -113,6 +114,7 @@ extern "C" {
|
|
113
114
|
void evma_set_epoll (int use);
|
114
115
|
void evma_set_kqueue (int use);
|
115
116
|
|
117
|
+
uint64_t evma_get_current_loop_time();
|
116
118
|
#if __cplusplus
|
117
119
|
}
|
118
120
|
#endif
|
data/ext/extconf.rb
CHANGED
@@ -53,11 +53,13 @@ when /solaris/
|
|
53
53
|
add_define 'OS_SOLARIS8'
|
54
54
|
check_libs(%w[nsl socket], true)
|
55
55
|
|
56
|
-
|
57
|
-
if CONFIG['CC'] == 'cc'
|
56
|
+
if CONFIG['CC'] == 'cc' and `cc -flags 2>&1` =~ /Sun/ # detect SUNWspro compiler
|
58
57
|
# SUN CHAIN
|
59
|
-
|
58
|
+
add_define 'CC_SUNWspro'
|
59
|
+
$preload = ["\nCXX = CC"] # hack a CXX= line into the makefile
|
60
|
+
$CFLAGS = CONFIG['CFLAGS'] = "-KPIC"
|
60
61
|
CONFIG['CCDLFLAGS'] = "-KPIC"
|
62
|
+
CONFIG['LDSHARED'] = "$(CXX) -G -KPIC -lCstd"
|
61
63
|
else
|
62
64
|
# GNU CHAIN
|
63
65
|
# on Unix we need a g++ link, not gcc.
|
@@ -44,11 +44,13 @@ when /solaris/
|
|
44
44
|
add_define 'OS_SOLARIS8'
|
45
45
|
check_libs(%w[nsl socket], true)
|
46
46
|
|
47
|
-
|
48
|
-
if CONFIG['CC'] == 'cc'
|
47
|
+
if CONFIG['CC'] == 'cc' and `cc -flags 2>&1` =~ /Sun/ # detect SUNWspro compiler
|
49
48
|
# SUN CHAIN
|
50
|
-
|
49
|
+
add_define 'CC_SUNWspro'
|
50
|
+
$preload = ["\nCXX = CC"] # hack a CXX= line into the makefile
|
51
|
+
$CFLAGS = CONFIG['CFLAGS'] = "-KPIC"
|
51
52
|
CONFIG['CCDLFLAGS'] = "-KPIC"
|
53
|
+
CONFIG['LDSHARED'] = "$(CXX) -G -KPIC -lCstd"
|
52
54
|
else
|
53
55
|
# GNU CHAIN
|
54
56
|
# on Unix we need a g++ link, not gcc.
|
@@ -88,7 +88,7 @@ void Mapper_t::Close()
|
|
88
88
|
// Can be called multiple times.
|
89
89
|
// Calls to GetChunk are invalid after a call to Close.
|
90
90
|
if (MapPoint) {
|
91
|
-
#ifdef
|
91
|
+
#ifdef CC_SUNWspro
|
92
92
|
munmap ((char*)MapPoint, FileSize);
|
93
93
|
#else
|
94
94
|
munmap ((void*)MapPoint, FileSize);
|
data/ext/kb.cpp
CHANGED
@@ -26,9 +26,7 @@ KeyboardDescriptor::KeyboardDescriptor
|
|
26
26
|
|
27
27
|
KeyboardDescriptor::KeyboardDescriptor (EventMachine_t *parent_em):
|
28
28
|
EventableDescriptor (0, parent_em),
|
29
|
-
bReadAttemptedAfterClose (false)
|
30
|
-
LastIo (gCurrentLoopTime),
|
31
|
-
InactivityTimeout (0)
|
29
|
+
bReadAttemptedAfterClose (false)
|
32
30
|
{
|
33
31
|
#ifdef HAVE_EPOLL
|
34
32
|
EpollEvent.events = EPOLLIN;
|
data/ext/pipe.cpp
CHANGED
@@ -30,8 +30,6 @@ PipeDescriptor::PipeDescriptor
|
|
30
30
|
PipeDescriptor::PipeDescriptor (int fd, pid_t subpid, EventMachine_t *parent_em):
|
31
31
|
EventableDescriptor (fd, parent_em),
|
32
32
|
bReadAttemptedAfterClose (false),
|
33
|
-
LastIo (gCurrentLoopTime),
|
34
|
-
InactivityTimeout (0),
|
35
33
|
OutboundDataSize (0),
|
36
34
|
SubprocessPid (subpid)
|
37
35
|
{
|
@@ -104,22 +102,22 @@ PipeDescriptor::~PipeDescriptor()
|
|
104
102
|
struct timespec req = {0, 50000000}; // 0.05s
|
105
103
|
int n;
|
106
104
|
|
107
|
-
// wait 0.
|
108
|
-
for (n=0; n<
|
105
|
+
// wait 0.5s for the process to die
|
106
|
+
for (n=0; n<10; n++) {
|
109
107
|
if (waitpid (SubprocessPid, &(MyEventMachine->SubprocessExitStatus), WNOHANG) != 0) return;
|
110
108
|
nanosleep (&req, NULL);
|
111
109
|
}
|
112
110
|
|
113
|
-
// send SIGTERM and wait another
|
111
|
+
// send SIGTERM and wait another 1s
|
114
112
|
kill (SubprocessPid, SIGTERM);
|
115
|
-
for (n=0; n<
|
113
|
+
for (n=0; n<20; n++) {
|
116
114
|
nanosleep (&req, NULL);
|
117
115
|
if (waitpid (SubprocessPid, &(MyEventMachine->SubprocessExitStatus), WNOHANG) != 0) return;
|
118
116
|
}
|
119
117
|
|
120
|
-
// send SIGKILL and wait another
|
118
|
+
// send SIGKILL and wait another 5s
|
121
119
|
kill (SubprocessPid, SIGKILL);
|
122
|
-
for (n=0; n<
|
120
|
+
for (n=0; n<100; n++) {
|
123
121
|
nanosleep (&req, NULL);
|
124
122
|
if (waitpid (SubprocessPid, &(MyEventMachine->SubprocessExitStatus), WNOHANG) != 0) return;
|
125
123
|
}
|
@@ -143,7 +141,7 @@ void PipeDescriptor::Read()
|
|
143
141
|
return;
|
144
142
|
}
|
145
143
|
|
146
|
-
|
144
|
+
LastActivity = MyEventMachine->GetCurrentLoopTime();
|
147
145
|
|
148
146
|
int total_bytes_read = 0;
|
149
147
|
char readbuffer [16 * 1024];
|
@@ -203,7 +201,7 @@ void PipeDescriptor::Write()
|
|
203
201
|
int sd = GetSocket();
|
204
202
|
assert (sd != INVALID_SOCKET);
|
205
203
|
|
206
|
-
|
204
|
+
LastActivity = MyEventMachine->GetCurrentLoopTime();
|
207
205
|
char output_buffer [16 * 1024];
|
208
206
|
size_t nbytes = 0;
|
209
207
|
|
@@ -268,7 +266,7 @@ PipeDescriptor::Heartbeat
|
|
268
266
|
void PipeDescriptor::Heartbeat()
|
269
267
|
{
|
270
268
|
// If an inactivity timeout is defined, then check for it.
|
271
|
-
if (InactivityTimeout && ((
|
269
|
+
if (InactivityTimeout && ((MyEventMachine->GetCurrentLoopTime() - LastActivity) >= InactivityTimeout))
|
272
270
|
ScheduleClose (false);
|
273
271
|
//bCloseNow = true;
|
274
272
|
}
|
data/ext/project.h
CHANGED
@@ -55,8 +55,8 @@ See the file COPYING for complete licensing information.
|
|
55
55
|
#include <netinet/tcp.h>
|
56
56
|
#include <arpa/inet.h>
|
57
57
|
#include <pwd.h>
|
58
|
+
#include <string.h>
|
58
59
|
typedef int SOCKET;
|
59
|
-
#define closesocket close
|
60
60
|
#define INVALID_SOCKET -1
|
61
61
|
#define SOCKET_ERROR -1
|
62
62
|
#ifdef OS_SOLARIS8
|
@@ -96,6 +96,9 @@ typedef int socklen_t;
|
|
96
96
|
typedef int pid_t;
|
97
97
|
#endif
|
98
98
|
|
99
|
+
#if !defined(_MSC_VER) || _MSC_VER > 1400
|
100
|
+
#include <stdint.h>
|
101
|
+
#endif
|
99
102
|
|
100
103
|
using namespace std;
|
101
104
|
|
@@ -134,6 +137,14 @@ static inline int inotify_rm_watch (int fd, __u32 wd) { return syscall (__NR_ino
|
|
134
137
|
#include <sys/uio.h>
|
135
138
|
#endif
|
136
139
|
|
140
|
+
#if __cplusplus
|
141
|
+
extern "C" {
|
142
|
+
#endif
|
143
|
+
typedef void (*EMCallback)(const unsigned long, int, const char*, const unsigned long);
|
144
|
+
#if __cplusplus
|
145
|
+
}
|
146
|
+
#endif
|
147
|
+
|
137
148
|
#include "binder.h"
|
138
149
|
#include "em.h"
|
139
150
|
#include "epoll.h"
|
@@ -145,7 +156,4 @@ static inline int inotify_rm_watch (int fd, __u32 wd) { return syscall (__NR_ino
|
|
145
156
|
#include "eventmachine.h"
|
146
157
|
#include "eventmachine_cpp.h"
|
147
158
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
159
|
#endif // __Project__H_
|
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,117 @@ 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
|
+
case EM_CONNECTION_UNBOUND:
|
99
|
+
{
|
100
|
+
rb_funcall (EmModule, Intern_event_callback, 3, ULONG2NUM(signature), INT2FIX(event), data_str ? rb_str_new(data_str,data_num) : ULONG2NUM(data_num));
|
101
|
+
return;
|
102
|
+
}
|
103
|
+
case EM_CONNECTION_COMPLETED:
|
104
|
+
{
|
105
|
+
VALUE conn = ensure_conn(signature);
|
106
|
+
rb_funcall (conn, Intern_connection_completed, 0);
|
107
|
+
return;
|
108
|
+
}
|
109
|
+
case EM_CONNECTION_NOTIFY_READABLE:
|
110
|
+
{
|
111
|
+
VALUE conn = ensure_conn(signature);
|
112
|
+
rb_funcall (conn, Intern_notify_readable, 0);
|
113
|
+
return;
|
114
|
+
}
|
115
|
+
case EM_CONNECTION_NOTIFY_WRITABLE:
|
116
|
+
{
|
117
|
+
VALUE conn = ensure_conn(signature);
|
118
|
+
rb_funcall (conn, Intern_notify_writable, 0);
|
119
|
+
return;
|
120
|
+
}
|
121
|
+
case EM_LOOPBREAK_SIGNAL:
|
122
|
+
{
|
123
|
+
rb_funcall (EmModule, Intern_run_deferred_callbacks, 0);
|
124
|
+
return;
|
125
|
+
}
|
126
|
+
case EM_TIMER_FIRED:
|
127
|
+
{
|
128
|
+
VALUE timer = rb_funcall (EmTimersHash, Intern_delete, 1, ULONG2NUM (data_num));
|
129
|
+
if (timer == Qnil) {
|
130
|
+
rb_raise (EM_eUnknownTimerFired, "no such timer: %lu", data_num);
|
131
|
+
} else if (timer == Qfalse) {
|
132
|
+
/* Timer Canceled */
|
133
|
+
} else {
|
134
|
+
rb_funcall (timer, Intern_call, 0);
|
135
|
+
}
|
136
|
+
return;
|
137
|
+
}
|
138
|
+
#ifdef WITH_SSL
|
139
|
+
case EM_SSL_HANDSHAKE_COMPLETED:
|
140
|
+
{
|
141
|
+
VALUE conn = ensure_conn(signature);
|
142
|
+
rb_funcall (conn, Intern_ssl_handshake_completed, 0);
|
143
|
+
return;
|
144
|
+
}
|
145
|
+
case EM_SSL_VERIFY:
|
146
|
+
{
|
147
|
+
VALUE conn = ensure_conn(signature);
|
148
|
+
VALUE should_accept = rb_funcall (conn, Intern_ssl_verify_peer, 1, rb_str_new(data_str, data_num));
|
149
|
+
if (RTEST(should_accept))
|
150
|
+
evma_accept_ssl_peer (signature);
|
151
|
+
return;
|
152
|
+
}
|
153
|
+
#endif
|
154
|
+
case EM_PROXY_TARGET_UNBOUND:
|
155
|
+
{
|
156
|
+
VALUE conn = ensure_conn(signature);
|
157
|
+
rb_funcall (conn, Intern_proxy_target_unbound, 0);
|
158
|
+
return;
|
159
|
+
}
|
160
|
+
case EM_PROXY_COMPLETED:
|
161
|
+
{
|
162
|
+
VALUE conn = ensure_conn(signature);
|
163
|
+
rb_funcall (conn, Intern_proxy_completed, 0);
|
164
|
+
return;
|
108
165
|
}
|
109
166
|
}
|
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
167
|
}
|
138
168
|
|
139
169
|
/*******************
|
@@ -150,13 +180,13 @@ static void event_error_handler(VALUE unused, VALUE err)
|
|
150
180
|
event_callback_wrapper
|
151
181
|
**********************/
|
152
182
|
|
153
|
-
static void event_callback_wrapper (const unsigned long
|
183
|
+
static void event_callback_wrapper (const unsigned long signature, int event, const char *data_str, const unsigned long data_num)
|
154
184
|
{
|
155
185
|
struct em_event e;
|
156
|
-
e.
|
157
|
-
e.
|
158
|
-
e.
|
159
|
-
e.
|
186
|
+
e.signature = signature;
|
187
|
+
e.event = event;
|
188
|
+
e.data_str = data_str;
|
189
|
+
e.data_num = data_num;
|
160
190
|
|
161
191
|
if (!rb_ivar_defined(EmModule, Intern_at_error_handler))
|
162
192
|
event_callback(&e);
|
@@ -170,7 +200,11 @@ t_initialize_event_machine
|
|
170
200
|
|
171
201
|
static VALUE t_initialize_event_machine (VALUE self)
|
172
202
|
{
|
173
|
-
|
203
|
+
EmConnsHash = rb_ivar_get (EmModule, Intern_at_conns);
|
204
|
+
EmTimersHash = rb_ivar_get (EmModule, Intern_at_timers);
|
205
|
+
assert(EmConnsHash != Qnil);
|
206
|
+
assert(EmTimersHash != Qnil);
|
207
|
+
evma_initialize_library ((EMCallback)event_callback_wrapper);
|
174
208
|
return Qnil;
|
175
209
|
}
|
176
210
|
|
@@ -208,7 +242,7 @@ static VALUE t_start_server (VALUE self, VALUE server, VALUE port)
|
|
208
242
|
{
|
209
243
|
const unsigned long f = evma_create_tcp_server (StringValuePtr(server), FIX2INT(port));
|
210
244
|
if (!f)
|
211
|
-
rb_raise (rb_eRuntimeError, "no acceptor");
|
245
|
+
rb_raise (rb_eRuntimeError, "no acceptor (port is in use or requires root privileges)");
|
212
246
|
return ULONG2NUM (f);
|
213
247
|
}
|
214
248
|
|
@@ -467,6 +501,7 @@ static VALUE t_connect_server (VALUE self, VALUE server, VALUE port)
|
|
467
501
|
} catch (std::runtime_error e) {
|
468
502
|
rb_raise (EM_eConnectionError, e.what());
|
469
503
|
}
|
504
|
+
return Qnil;
|
470
505
|
}
|
471
506
|
|
472
507
|
/*********************
|
@@ -487,6 +522,7 @@ static VALUE t_bind_connect_server (VALUE self, VALUE bind_addr, VALUE bind_port
|
|
487
522
|
} catch (std::runtime_error e) {
|
488
523
|
rb_raise (EM_eConnectionError, e.what());
|
489
524
|
}
|
525
|
+
return Qnil;
|
490
526
|
}
|
491
527
|
|
492
528
|
/*********************
|
@@ -725,9 +761,9 @@ static VALUE t_invoke_popen (VALUE self, VALUE cmd)
|
|
725
761
|
#else
|
726
762
|
int len = RARRAY (cmd)->len;
|
727
763
|
#endif
|
728
|
-
if (len
|
764
|
+
if (len >= 2048)
|
729
765
|
rb_raise (rb_eRuntimeError, "too many arguments to popen");
|
730
|
-
char *strings [
|
766
|
+
char *strings [2048];
|
731
767
|
for (int i=0; i < len; i++) {
|
732
768
|
VALUE ix = INT2FIX (i);
|
733
769
|
VALUE s = rb_ary_aref (1, &ix, cmd);
|
@@ -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);
|