eventmachine 0.12.10 → 1.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- 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);
|