noderb 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +157 -7
- data/ext/noderb_extension/extconf.rb +1 -3
- data/ext/noderb_extension/libuv/BSDmakefile +2 -0
- data/ext/noderb_extension/libuv/all.gyp +326 -0
- data/ext/noderb_extension/libuv/config-mingw.mk +0 -1
- data/ext/noderb_extension/libuv/config-unix.mk +7 -1
- data/ext/noderb_extension/libuv/create-msvs-files.bat +13 -6
- data/ext/noderb_extension/libuv/{build/gyp_uv → gyp_uv} +1 -2
- data/ext/noderb_extension/libuv/include/uv.h +5 -0
- data/ext/noderb_extension/libuv/src/eio/config_cygwin.h +3 -0
- data/ext/noderb_extension/libuv/src/eio/config_freebsd.h +3 -0
- data/ext/noderb_extension/libuv/src/eio/config_sunos.h +3 -0
- data/ext/noderb_extension/libuv/src/eio/ecb.h +1 -1
- data/ext/noderb_extension/libuv/src/eio/eio.c +8 -1
- data/ext/noderb_extension/libuv/src/uv-common.c +1 -0
- data/ext/noderb_extension/libuv/src/uv-sunos.c +1 -1
- data/ext/noderb_extension/libuv/src/uv-unix.c +72 -59
- data/ext/noderb_extension/libuv/src/win/core.c +3 -0
- data/ext/noderb_extension/libuv/src/win/internal.h +11 -0
- data/ext/noderb_extension/libuv/src/win/ntdll.h +130 -0
- data/ext/noderb_extension/libuv/src/win/pipe.c +105 -27
- data/ext/noderb_extension/libuv/src/win/process.c +76 -5
- data/ext/noderb_extension/libuv/src/win/req.c +7 -0
- data/ext/noderb_extension/libuv/src/win/winapi.c +52 -0
- data/ext/noderb_extension/libuv/test/benchmark-pound.c +50 -48
- data/ext/noderb_extension/libuv/test/echo-server.c +2 -2
- data/ext/noderb_extension/libuv/test/test-list.h +2 -0
- data/ext/noderb_extension/libuv/test/test-spawn.c +48 -1
- data/ext/noderb_extension/noderb.c +38 -339
- data/ext/noderb_extension/noderb.h +18 -2
- data/ext/noderb_extension/noderb_common.h +13 -0
- data/ext/noderb_extension/noderb_dns.c +37 -0
- data/ext/noderb_extension/noderb_dns.h +15 -0
- data/ext/noderb_extension/noderb_process.c +126 -0
- data/ext/noderb_extension/noderb_process.h +17 -0
- data/ext/noderb_extension/noderb_tcp.c +127 -0
- data/ext/noderb_extension/noderb_tcp.h +19 -0
- data/ext/noderb_extension/noderb_timers.c +58 -0
- data/ext/noderb_extension/noderb_timers.h +16 -0
- data/ext/noderb_extension/noderb_tools.c +127 -0
- data/ext/noderb_extension/noderb_tools.h +33 -0
- data/lib/noderb/dns.rb +11 -0
- data/lib/noderb/next_tick.rb +2 -1
- data/lib/noderb/tcp.rb +27 -0
- data/lib/noderb/timers.rb +24 -0
- data/lib/noderb/version.rb +1 -1
- data/lib/noderb.rb +6 -1
- metadata +23 -7
- data/ext/noderb_extension/libuv/build/all.gyp +0 -254
- data/ext/noderb_extension/libuv/doc/desired-api.md +0 -159
- /data/ext/noderb_extension/libuv/{build/common.gypi → common.gypi} +0 -0
@@ -1,361 +1,60 @@
|
|
1
|
+
#include <noderb_common.h>
|
1
2
|
#include <noderb.h>
|
2
3
|
|
4
|
+
#include <noderb_process.h>
|
5
|
+
#include <noderb_tcp.h>
|
6
|
+
#include <noderb_dns.h>
|
7
|
+
#include <noderb_timers.h>
|
8
|
+
#include <noderb_tools.h>
|
9
|
+
|
10
|
+
// Core NodeRb module
|
3
11
|
VALUE nodeRb;
|
12
|
+
// Pointer for saving native data
|
4
13
|
VALUE nodeRbPointer;
|
5
|
-
VALUE nodeRbConnection;
|
6
|
-
VALUE nodeRbProcess;
|
7
|
-
|
8
|
-
VALUE nodeRbModules;
|
9
|
-
|
10
|
-
int nodeRbNextTickStatus = 0;
|
11
|
-
|
12
|
-
typedef struct {
|
13
|
-
|
14
|
-
} nodeRb_next_tick_handle;
|
15
|
-
|
16
|
-
typedef struct {
|
17
|
-
uv_write_t req;
|
18
|
-
uv_buf_t buf;
|
19
|
-
} write_req_t;
|
20
|
-
|
21
|
-
typedef struct {
|
22
|
-
long connection;
|
23
|
-
} nodeRb_client;
|
24
|
-
|
25
|
-
typedef struct {
|
26
|
-
long target;
|
27
|
-
uv_pipe_t* stdout;
|
28
|
-
uv_pipe_t* stdin;
|
29
|
-
uv_pipe_t* stderr;
|
30
|
-
} nodeRb_process_handle;
|
31
|
-
|
32
|
-
|
33
|
-
VALUE nodeRb_register_instance(VALUE self, VALUE instance) {
|
34
|
-
rb_ary_push(rb_iv_get(self, "@instances"), instance);
|
35
|
-
}
|
36
|
-
|
37
|
-
VALUE nodeRb_unregister_instance(VALUE self, VALUE instance) {
|
38
|
-
rb_ary_delete(rb_iv_get(self, "@instances"), instance);
|
39
|
-
}
|
40
|
-
|
41
|
-
VALUE nodeRb_get_class_from_id(long id) {
|
42
|
-
return rb_funcall(rb_const_get(rb_cObject, rb_intern("ObjectSpace")), rb_intern("_id2ref"), 1, rb_int2inum(id));
|
43
|
-
}
|
44
|
-
|
45
|
-
int nodeRb_handle_error(int e) {
|
46
|
-
if (e) {
|
47
|
-
uv_err_t error = uv_last_error();
|
48
|
-
fprintf(stderr, "%s\n", uv_strerror(error));
|
49
|
-
return 1;
|
50
|
-
} else {
|
51
|
-
return 0;
|
52
|
-
}
|
53
|
-
};
|
54
|
-
|
55
|
-
void nodeRb_next_tick(uv_idle_t* handle, int status) {
|
56
|
-
uv_idle_stop(handle);
|
57
|
-
free(handle);
|
58
|
-
nodeRbNextTickStatus = 0;
|
59
|
-
rb_funcall(nodeRb, rb_intern("next_tick_execute"), 0);
|
60
|
-
}
|
61
|
-
|
62
|
-
VALUE nodeRb_nextTick(VALUE self) {
|
63
|
-
if(nodeRbNextTickStatus == 0){
|
64
|
-
uv_idle_t* handle = malloc(sizeof(uv_idle_t));
|
65
|
-
uv_idle_init(handle);
|
66
|
-
nodeRbNextTickStatus = 1;
|
67
|
-
uv_idle_start(handle, nodeRb_next_tick);
|
68
|
-
}
|
69
|
-
}
|
70
|
-
|
71
|
-
VALUE nodeRb_start(VALUE self) {
|
72
|
-
// Let the loop run
|
73
|
-
uv_ref();
|
74
|
-
// Run Ruby
|
75
|
-
if (rb_block_given_p()) {
|
76
|
-
rb_yield(Qnil);
|
77
|
-
}
|
78
|
-
// Start loop
|
79
|
-
uv_run();
|
80
|
-
};
|
81
|
-
|
82
|
-
void nodeRb_after_write(uv_write_t* req, int status) {
|
83
|
-
write_req_t* wr;
|
84
|
-
|
85
|
-
if (status) {
|
86
|
-
uv_err_t err = uv_last_error();
|
87
|
-
fprintf(stderr, "uv_write error: %s\n", uv_strerror(err));
|
88
|
-
return;
|
89
|
-
}
|
90
|
-
|
91
|
-
wr = (write_req_t*) req;
|
92
|
-
free(wr);
|
93
|
-
|
94
|
-
}
|
95
|
-
|
96
|
-
VALUE nodeRb_send_data(VALUE self, VALUE data) {
|
97
|
-
write_req_t* wr = malloc(sizeof (write_req_t));
|
98
|
-
wr->buf.base = rb_string_value_cstr(&data);
|
99
|
-
wr->buf.len = RSTRING_LEN(data);
|
100
|
-
VALUE rhandler = rb_iv_get(self, "@_handle");
|
101
|
-
uv_stream_t *handle;
|
102
|
-
Data_Get_Struct(rhandler, uv_stream_t, handle);
|
103
|
-
uv_write(&wr->req, handle, &wr->buf, 1, nodeRb_after_write);
|
104
|
-
}
|
105
|
-
|
106
|
-
void nodeRb_on_close(uv_handle_t* client) {
|
107
|
-
nodeRb_client *client_data = client->data;
|
108
|
-
VALUE object = nodeRb_get_class_from_id(client_data->connection);
|
109
|
-
rb_funcall(object, rb_intern("on_close"), 0, 0);
|
110
|
-
nodeRb_unregister_instance(nodeRb, object);
|
111
|
-
rb_iv_set(object, "@_handle", Qnil);
|
112
|
-
free(client_data);
|
113
|
-
free(client);
|
114
|
-
client_data = NULL;
|
115
|
-
}
|
116
14
|
|
117
|
-
|
118
|
-
|
119
|
-
|
15
|
+
// Core module of NodeRb
|
16
|
+
VALUE nodeRb_get_nodeRb_module(){
|
17
|
+
return nodeRb;
|
120
18
|
}
|
121
19
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
uv_stream_t *handle;
|
126
|
-
Data_Get_Struct(rhandler, uv_stream_t, handle);
|
127
|
-
uv_shutdown(req, handle, nodeRb_on_shutdown);
|
20
|
+
// NodeRb pointer is used for wrapping native structs into Ruby
|
21
|
+
VALUE nodeRb_get_nodeRb_pointer(){
|
22
|
+
return nodeRbPointer;
|
128
23
|
}
|
129
24
|
|
130
|
-
void nodeRb_on_read(uv_stream_t* client, ssize_t nread, uv_buf_t buf) {
|
131
|
-
nodeRb_client *client_data = client->data;
|
132
|
-
if (nread < 0) {
|
133
|
-
if (buf.base) {
|
134
|
-
free(buf.base);
|
135
|
-
}
|
136
|
-
return;
|
137
|
-
}
|
138
|
-
|
139
|
-
if (nread == 0) {
|
140
|
-
free(buf.base);
|
141
|
-
return;
|
142
|
-
}
|
143
|
-
rb_funcall(nodeRb_get_class_from_id(client_data->connection), rb_intern("on_data"), 1, rb_str_new2(buf.base));
|
144
|
-
free(buf.base);
|
145
|
-
}
|
146
|
-
|
147
|
-
uv_buf_t nodeRb_read_alloc(uv_stream_t* handle, size_t suggested_size) {
|
148
|
-
uv_buf_t buf;
|
149
|
-
buf.base = (char*) malloc(suggested_size);
|
150
|
-
buf.len = suggested_size;
|
151
|
-
return buf;
|
152
|
-
}
|
153
|
-
|
154
|
-
void nodeRb_on_server_connect(uv_stream_t* server, int status) {
|
155
|
-
nodeRb_client *client_data = malloc(sizeof (nodeRb_client));
|
156
|
-
uv_stream_t *client = malloc(sizeof (uv_tcp_t));
|
157
|
-
uv_tcp_init((uv_tcp_t*) client);
|
158
|
-
int r = uv_accept(server, client);
|
159
|
-
if (nodeRb_handle_error(r)) return;
|
160
|
-
VALUE clazz = rb_path2class(server->data);
|
161
|
-
VALUE obj = rb_funcall(clazz, rb_intern("new"), 0, 0);
|
162
|
-
nodeRb_register_instance(nodeRb, obj);
|
163
|
-
rb_funcall(obj, rb_intern("on_connect"), 0, 0);
|
164
|
-
rb_iv_set(obj, "@_handle", Data_Wrap_Struct(nodeRbPointer, 0, NULL, client));
|
165
|
-
long id = rb_num2long(rb_obj_id(obj));
|
166
|
-
client_data->connection = id;
|
167
|
-
client->data = client_data;
|
168
|
-
uv_read_start(client, nodeRb_read_alloc, nodeRb_on_read);
|
169
|
-
}
|
170
|
-
|
171
|
-
VALUE nodeRb_startServer(VALUE self, VALUE address, VALUE port, VALUE clazz) {
|
172
|
-
uv_tcp_t *server = malloc(sizeof (uv_tcp_t));
|
173
|
-
uv_tcp_init(server);
|
174
|
-
struct sockaddr_in socket = uv_ip4_addr(rb_string_value_cstr(&address), (int) rb_num2long(port));
|
175
|
-
int r = uv_tcp_bind(server, socket);
|
176
|
-
if (nodeRb_handle_error(r)) return Qnil;
|
177
|
-
r = uv_listen((uv_stream_t*) server, 128, nodeRb_on_server_connect);
|
178
|
-
if (nodeRb_handle_error(r)) return Qnil;
|
179
|
-
VALUE name = rb_class_name(clazz);
|
180
|
-
server->data = rb_string_value_cstr(&name);
|
181
|
-
};
|
182
|
-
|
183
|
-
void nodeRb_on_client_connect(uv_connect_t* client, int status) {
|
184
|
-
nodeRb_client *client_data = client->handle->data;
|
185
|
-
VALUE obj = nodeRb_get_class_from_id(client_data->connection);
|
186
|
-
rb_iv_set(obj, "@_handle", Data_Wrap_Struct(nodeRbPointer, 0, NULL, client->handle));
|
187
|
-
rb_funcall(obj, rb_intern("on_connect"), 0, 0);
|
188
|
-
uv_read_start((uv_stream_t*) client->handle, nodeRb_read_alloc, nodeRb_on_read);
|
189
|
-
}
|
190
|
-
|
191
|
-
VALUE nodeRb_startClient(VALUE self, VALUE address, VALUE port, VALUE clazz) {
|
192
|
-
uv_tcp_t *handle = malloc(sizeof (uv_tcp_t));
|
193
|
-
uv_tcp_init(handle);
|
194
|
-
uv_connect_t *connect = malloc(sizeof (uv_connect_t));
|
195
|
-
struct sockaddr_in socket = uv_ip4_addr(rb_string_value_cstr(&address), (int) rb_num2long(port));
|
196
|
-
int r = uv_tcp_connect(connect, handle, socket, nodeRb_on_client_connect);
|
197
|
-
if (nodeRb_handle_error(r)) return Qnil;
|
198
|
-
nodeRb_client *client_data = malloc(sizeof (nodeRb_client));
|
199
|
-
VALUE obj = clazz;
|
200
|
-
long id = rb_num2long(rb_obj_id(obj));
|
201
|
-
client_data->connection = id;
|
202
|
-
handle->data = client_data;
|
203
|
-
};
|
204
|
-
|
205
|
-
void nodeRb_process_close(uv_handle_t* handle) {
|
206
|
-
|
207
|
-
}
|
208
|
-
|
209
|
-
void nodeRb_process_write_after(uv_write_t* req, int status) {
|
210
|
-
|
211
|
-
}
|
212
|
-
|
213
|
-
VALUE nodeRb_process_write(VALUE self, VALUE data) {
|
214
|
-
uv_process_t *handle;
|
215
|
-
Data_Get_Struct(rb_iv_get(self, "@_handle"), uv_process_t, handle);
|
216
|
-
uv_write_t write_req;
|
217
|
-
uv_buf_t buf;
|
218
|
-
char* buffer = rb_string_value_cstr(&data);
|
219
|
-
buf.base = buffer;
|
220
|
-
buf.len = sizeof (buffer);
|
221
|
-
nodeRb_process_handle* nhandle = (nodeRb_process_handle*) handle->data;
|
222
|
-
uv_write(&write_req, (uv_stream_t*) nhandle->stdin, &buf, 1, nodeRb_process_write_after);
|
223
|
-
}
|
224
|
-
|
225
|
-
void nodeRb_process_stdout_read(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) {
|
226
|
-
uv_err_t err = uv_last_error();
|
227
|
-
long id = ((nodeRb_process_handle*) handle->data)->target;
|
228
|
-
VALUE clazz = nodeRb_get_class_from_id(id);
|
229
|
-
if (nread > 0) {
|
230
|
-
rb_funcall(clazz, rb_intern("on_stdout"), 1, rb_str_new(buf.base, nread));
|
231
|
-
}
|
232
|
-
if (nread < 0) {
|
233
|
-
if (err.code == UV_EOF) {
|
234
|
-
//uv_close((uv_handle_t*) handle, nodeRb_process_close);
|
235
|
-
}
|
236
|
-
}
|
237
|
-
free(buf.base);
|
238
|
-
}
|
239
|
-
|
240
|
-
void nodeRb_process_stderr_read(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) {
|
241
|
-
uv_err_t err = uv_last_error();
|
242
|
-
long id = ((nodeRb_process_handle*) handle->data)->target;
|
243
|
-
VALUE clazz = nodeRb_get_class_from_id(id);
|
244
|
-
if (nread > 0) {
|
245
|
-
rb_funcall(clazz, rb_intern("on_stderr"), 1, rb_str_new(buf.base, nread));
|
246
|
-
}
|
247
|
-
if (nread < 0) {
|
248
|
-
if (err.code == UV_EOF) {
|
249
|
-
//uv_close((uv_handle_t*) handle, nodeRb_process_close);
|
250
|
-
}
|
251
|
-
}
|
252
|
-
free(buf.base);
|
253
|
-
}
|
254
|
-
|
255
|
-
VALUE nodeRb_process_kill(VALUE self, VALUE signal) {
|
256
|
-
uv_process_t *handle;
|
257
|
-
Data_Get_Struct(rb_iv_get(self, "@_handle"), uv_process_t, handle);
|
258
|
-
uv_process_kill(handle, (int) rb_num2int(signal));
|
259
|
-
}
|
260
|
-
|
261
|
-
void nodeRb_process_exit(uv_process_t* handle, int status, int signal) {
|
262
|
-
nodeRb_process_handle* nhandle = (nodeRb_process_handle*) handle->data;
|
263
|
-
VALUE clazz = nodeRb_get_class_from_id(nhandle->target);
|
264
|
-
rb_funcall(clazz, rb_intern("on_exit"), 2, rb_int2inum(status), rb_int2inum(signal));
|
265
|
-
}
|
266
|
-
|
267
|
-
VALUE nodeRb_startProcess(VALUE self, VALUE executable, VALUE arguments, VALUE environment, VALUE directory, VALUE clazz) {
|
268
|
-
uv_process_options_t options = {0};
|
269
|
-
// On process exit
|
270
|
-
options.exit_cb = nodeRb_process_exit;
|
271
|
-
// Executable
|
272
|
-
options.file = rb_string_value_cstr(&executable);
|
273
|
-
// Arguments
|
274
|
-
long len;
|
275
|
-
len = RARRAY_LEN(arguments);
|
276
|
-
char* args[len + 2];
|
277
|
-
args[0] = rb_string_value_cstr(&executable);
|
278
|
-
args[len + 1] = NULL;
|
279
|
-
options.args = args;
|
280
|
-
if (len > 0) {
|
281
|
-
long i;
|
282
|
-
VALUE *arr = RARRAY_PTR(arguments);
|
283
|
-
for (i = 0; i < len; i++) {
|
284
|
-
options.args[i + 1] = rb_string_value_cstr(&arr[i]);
|
285
|
-
}
|
286
|
-
}
|
287
|
-
// Environment
|
288
|
-
len = RARRAY_LEN(environment);
|
289
|
-
char* env[len+1];
|
290
|
-
options.env = env;
|
291
|
-
options.env[len] = NULL;
|
292
|
-
if (len > 0) {
|
293
|
-
long i;
|
294
|
-
VALUE *arr = RARRAY_PTR(environment);
|
295
|
-
for (i = 0; i < len; i++) {
|
296
|
-
options.env[i] = rb_string_value_cstr(&arr[i]);
|
297
|
-
}
|
298
|
-
}
|
299
|
-
|
300
|
-
// Working directory
|
301
|
-
options.cwd = rb_string_value_cstr(&directory);
|
302
|
-
// NodeRb helpers
|
303
|
-
nodeRb_process_handle* nhandle = malloc(sizeof(nodeRb_process_handle));
|
304
|
-
nhandle->target = rb_num2long(rb_obj_id(clazz));
|
305
|
-
// Be safe of GC
|
306
|
-
nodeRb_register_instance(nodeRb, clazz);
|
307
|
-
// stdin/out/err
|
308
|
-
uv_pipe_t* stdout = malloc(sizeof(uv_pipe_t));
|
309
|
-
uv_pipe_t* stdin = malloc(sizeof(uv_pipe_t));
|
310
|
-
uv_pipe_t* stderr = malloc(sizeof(uv_pipe_t));
|
311
|
-
uv_pipe_init(stdout);
|
312
|
-
uv_pipe_init(stdin);
|
313
|
-
uv_pipe_init(stderr);
|
314
|
-
options.stdout_stream = stdout;
|
315
|
-
options.stdin_stream = stdin;
|
316
|
-
options.stderr_stream = stderr;
|
317
|
-
stdout->data = nhandle;
|
318
|
-
stderr->data = nhandle;
|
319
|
-
nhandle->stdin = stdin;
|
320
|
-
// libuv handle
|
321
|
-
uv_process_t* handle = malloc(sizeof(uv_process_t));
|
322
|
-
handle->data = nhandle;
|
323
|
-
// Save reference into Ruby object
|
324
|
-
rb_iv_set(clazz, "@_handle", Data_Wrap_Struct(nodeRbPointer, 0, NULL, handle));
|
325
|
-
// spawn process
|
326
|
-
uv_spawn(handle, options);
|
327
|
-
// Listen to stdout/err
|
328
|
-
uv_read_start((uv_stream_t*) stdout, nodeRb_read_alloc, nodeRb_process_stdout_read);
|
329
|
-
uv_read_start((uv_stream_t*) stderr, nodeRb_read_alloc, nodeRb_process_stderr_read);
|
330
|
-
// call back ruby
|
331
|
-
rb_funcall(clazz, rb_intern("on_start"), 0);
|
332
|
-
};
|
333
|
-
|
334
25
|
void Init_noderb_extension() {
|
335
|
-
// Initialize
|
26
|
+
// Initialize event loop, but not start it
|
336
27
|
uv_init();
|
337
28
|
// Define module
|
338
29
|
nodeRb = rb_define_module("NodeRb");
|
339
|
-
|
340
|
-
|
341
|
-
|
30
|
+
// Define native pointer
|
31
|
+
nodeRbPointer = rb_define_class_under(nodeRb, "NativePointer", rb_cObject);
|
32
|
+
// Define handlers of events
|
33
|
+
VALUE nodeRbConnection = rb_define_module_under(nodeRb, "Connection");
|
34
|
+
VALUE nodeRbProcess = rb_define_module_under(nodeRb, "Process");
|
342
35
|
// Define connection methods
|
343
|
-
rb_define_method(nodeRbConnection, "
|
344
|
-
rb_define_method(nodeRbConnection, "close_connection",
|
36
|
+
rb_define_method(nodeRbConnection, "write_data", nodeRb_tcp_send_data, 1);
|
37
|
+
rb_define_method(nodeRbConnection, "close_connection", nodeRb_tcp_close_connection, 0);
|
345
38
|
// Define process methods
|
346
|
-
rb_define_method(nodeRbProcess, "
|
347
|
-
rb_define_method(nodeRbProcess, "
|
348
|
-
//
|
349
|
-
rb_define_singleton_method(nodeRb, "
|
39
|
+
rb_define_method(nodeRbProcess, "write_data", nodeRb_process_write, 1);
|
40
|
+
rb_define_method(nodeRbProcess, "kill_process", nodeRb_process_kill, 1);
|
41
|
+
// Define utility methods
|
42
|
+
rb_define_singleton_method(nodeRb, "next_tick_native", nodeRb_nextTick, 0);
|
43
|
+
// DNS related methods
|
44
|
+
rb_define_singleton_method(nodeRb, "resolve_native", nodeRb_dns_resolve, 2);
|
45
|
+
// Timer related functions
|
46
|
+
rb_define_singleton_method(nodeRb, "once_native", nodeRb_timers_once, 3);
|
47
|
+
VALUE timer = rb_define_module_under(nodeRb, "Timer");
|
48
|
+
rb_define_method(timer, "stop_timer", nodeRb_timers_stop, 0);
|
350
49
|
// Define starting methods
|
351
50
|
rb_define_singleton_method(nodeRb, "start", nodeRb_start, 0);
|
352
|
-
rb_define_singleton_method(nodeRb, "
|
353
|
-
rb_define_singleton_method(nodeRb, "
|
51
|
+
rb_define_singleton_method(nodeRb, "start_server_native", nodeRb_tcp_startServer, 3);
|
52
|
+
rb_define_singleton_method(nodeRb, "start_client_native", nodeRb_tcp_startClient, 3);
|
354
53
|
rb_define_singleton_method(nodeRb, "start_process", nodeRb_startProcess, 5);
|
355
54
|
// Memory management
|
356
55
|
rb_iv_set(nodeRb, "@instances", rb_ary_new());
|
357
|
-
rb_define_singleton_method(nodeRb, "register_instance",
|
358
|
-
rb_define_singleton_method(nodeRb, "unregister_instance",
|
56
|
+
rb_define_singleton_method(nodeRb, "register_instance", nodeRb_registerInstance, 1);
|
57
|
+
rb_define_singleton_method(nodeRb, "unregister_instance", nodeRb_unregisterInstance, 1);
|
359
58
|
// Modules
|
360
|
-
nodeRbModules = rb_define_module_under(nodeRb, "Modules");
|
59
|
+
VALUE nodeRbModules = rb_define_module_under(nodeRb, "Modules");
|
361
60
|
}
|
@@ -1,2 +1,18 @@
|
|
1
|
-
#
|
2
|
-
#
|
1
|
+
#ifndef NODERB_H
|
2
|
+
#define NODERB_H
|
3
|
+
|
4
|
+
#ifdef __cplusplus
|
5
|
+
extern "C" {
|
6
|
+
#endif
|
7
|
+
|
8
|
+
VALUE nodeRb_get_nodeRb_module();
|
9
|
+
VALUE nodeRb_get_nodeRb_pointer();
|
10
|
+
|
11
|
+
void Init_noderb_extension();
|
12
|
+
|
13
|
+
#ifdef __cplusplus
|
14
|
+
}
|
15
|
+
#endif
|
16
|
+
|
17
|
+
#endif /* NODERB_H */
|
18
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#include <noderb_common.h>
|
2
|
+
|
3
|
+
#include <noderb_dns.h>
|
4
|
+
#include <noderb_tools.h>
|
5
|
+
|
6
|
+
typedef struct {
|
7
|
+
long target;
|
8
|
+
} nodeRb_dns_handle;
|
9
|
+
|
10
|
+
void nodeRb_dns_resolved(uv_getaddrinfo_t* handle, int status, struct addrinfo* res){
|
11
|
+
// Load data
|
12
|
+
nodeRb_dns_handle* data = (nodeRb_dns_handle*) handle->data;
|
13
|
+
// Get resolved address
|
14
|
+
char address[INET_ADDRSTRLEN];
|
15
|
+
inet_ntop(AF_INET, &(((struct sockaddr_in*) res->ai_addr)->sin_addr), address, INET_ADDRSTRLEN);
|
16
|
+
// Call back
|
17
|
+
VALUE callback = nodeRb_get_class_from_id(data->target);
|
18
|
+
rb_funcall(callback, rb_intern("call"), 1, rb_str_new2(address));
|
19
|
+
// Let callback GC
|
20
|
+
nodeRb_unregister_instance(callback);
|
21
|
+
free(handle);
|
22
|
+
free(data);
|
23
|
+
};
|
24
|
+
|
25
|
+
VALUE nodeRb_dns_resolve(VALUE self, VALUE host, VALUE callback){
|
26
|
+
// Allocate memory
|
27
|
+
uv_getaddrinfo_t* handle = malloc(sizeof(uv_getaddrinfo_t));
|
28
|
+
nodeRb_dns_handle* data = malloc(sizeof(nodeRb_dns_handle));
|
29
|
+
// Save from GC
|
30
|
+
nodeRb_register_instance(callback);
|
31
|
+
// Save data
|
32
|
+
data->target = rb_num2long(rb_obj_id(callback));
|
33
|
+
// Resolve
|
34
|
+
uv_getaddrinfo(handle, nodeRb_dns_resolved, rb_string_value_cstr(&host), NULL, NULL);
|
35
|
+
// Save callback
|
36
|
+
handle->data = data;
|
37
|
+
}
|
@@ -0,0 +1,126 @@
|
|
1
|
+
#include <noderb_common.h>
|
2
|
+
#include <noderb_process.h>
|
3
|
+
#include <noderb.h>
|
4
|
+
#include <noderb_tools.h>
|
5
|
+
|
6
|
+
typedef struct {
|
7
|
+
NODERB_BASIC_HANDLE
|
8
|
+
uv_pipe_t* stdout;
|
9
|
+
uv_pipe_t* stdin;
|
10
|
+
uv_pipe_t* stderr;
|
11
|
+
} nodeRb_process_handle;
|
12
|
+
|
13
|
+
typedef struct {
|
14
|
+
NODERB_BASIC_HANDLE
|
15
|
+
} nodeRb_process_read_handle;
|
16
|
+
|
17
|
+
void nodeRb_process_close(uv_handle_t* handle) {
|
18
|
+
nodeRb_process_handle* process_handle = (nodeRb_process_handle*) handle->data;
|
19
|
+
free(process_handle->stdin);
|
20
|
+
free(process_handle->stdout);
|
21
|
+
free(process_handle->stderr);
|
22
|
+
free(process_handle);
|
23
|
+
free(handle);
|
24
|
+
}
|
25
|
+
|
26
|
+
VALUE nodeRb_process_write(VALUE self, VALUE data) {
|
27
|
+
// Read data from Ruby
|
28
|
+
uv_process_t *handle;
|
29
|
+
Data_Get_Struct(rb_iv_get(self, "@_handle"), uv_process_t, handle);
|
30
|
+
uv_write_t write_req;
|
31
|
+
uv_buf_t buf;
|
32
|
+
// Get data to write from Ruby
|
33
|
+
char* buffer = rb_string_value_cstr(&data);
|
34
|
+
// Get process handle
|
35
|
+
nodeRb_process_handle* process_handle = (nodeRb_process_handle*) handle->data;
|
36
|
+
// Write data to stream
|
37
|
+
nodeRb_write((uv_stream_t*) process_handle->stdin, buffer, sizeof(buffer));
|
38
|
+
}
|
39
|
+
|
40
|
+
VALUE nodeRb_process_kill(VALUE self, VALUE signal) {
|
41
|
+
uv_process_t *handle;
|
42
|
+
Data_Get_Struct(rb_iv_get(self, "@_handle"), uv_process_t, handle);
|
43
|
+
uv_process_kill(handle, (int) rb_num2int(signal));
|
44
|
+
}
|
45
|
+
|
46
|
+
void nodeRb_process_exit(uv_process_t* handle, int status, int signal) {
|
47
|
+
nodeRb_process_handle* process_handle = (nodeRb_process_handle*) handle->data;
|
48
|
+
VALUE clazz = nodeRb_get_class_from_id(process_handle->target);
|
49
|
+
rb_funcall(clazz, rb_intern("on_exit"), 2, rb_int2inum(status), rb_int2inum(signal));
|
50
|
+
}
|
51
|
+
|
52
|
+
VALUE nodeRb_startProcess(VALUE self, VALUE executable, VALUE arguments, VALUE environment, VALUE directory, VALUE clazz) {
|
53
|
+
uv_process_options_t options = {0};
|
54
|
+
// On process exit
|
55
|
+
options.exit_cb = nodeRb_process_exit;
|
56
|
+
// Executable
|
57
|
+
options.file = rb_string_value_cstr(&executable);
|
58
|
+
// Arguments
|
59
|
+
long len;
|
60
|
+
len = RARRAY_LEN(arguments);
|
61
|
+
char* args[len + 2];
|
62
|
+
args[0] = rb_string_value_cstr(&executable);
|
63
|
+
args[len + 1] = NULL;
|
64
|
+
options.args = args;
|
65
|
+
if (len > 0) {
|
66
|
+
long i;
|
67
|
+
VALUE *arr = RARRAY_PTR(arguments);
|
68
|
+
for (i = 0; i < len; i++) {
|
69
|
+
options.args[i + 1] = rb_string_value_cstr(&arr[i]);
|
70
|
+
}
|
71
|
+
}
|
72
|
+
// Environment
|
73
|
+
len = RARRAY_LEN(environment);
|
74
|
+
char* env[len+1];
|
75
|
+
options.env = env;
|
76
|
+
options.env[len] = NULL;
|
77
|
+
if (len > 0) {
|
78
|
+
long i;
|
79
|
+
VALUE *arr = RARRAY_PTR(environment);
|
80
|
+
for (i = 0; i < len; i++) {
|
81
|
+
options.env[i] = rb_string_value_cstr(&arr[i]);
|
82
|
+
}
|
83
|
+
}
|
84
|
+
// Working directory
|
85
|
+
options.cwd = rb_string_value_cstr(&directory);
|
86
|
+
// NodeRb helpers
|
87
|
+
nodeRb_process_handle* process_handle = malloc(sizeof(nodeRb_process_handle));
|
88
|
+
process_handle->target = rb_num2long(rb_obj_id(clazz));
|
89
|
+
// Be safe of GC
|
90
|
+
nodeRb_register_instance(clazz);
|
91
|
+
// stdin
|
92
|
+
uv_pipe_t* stdin = malloc(sizeof(uv_pipe_t));
|
93
|
+
uv_pipe_init(stdin);
|
94
|
+
options.stdin_stream = stdin;
|
95
|
+
process_handle->stdin = stdin;
|
96
|
+
// stdout
|
97
|
+
uv_pipe_t* stdout = malloc(sizeof(uv_pipe_t));
|
98
|
+
uv_pipe_init(stdout);
|
99
|
+
options.stdout_stream = stdout;
|
100
|
+
nodeRb_process_read_handle* stdout_handle = malloc(sizeof(nodeRb_process_read_handle));
|
101
|
+
stdout_handle->target = process_handle->target;
|
102
|
+
stdout_handle->target_callback = (char*) "on_stdout";
|
103
|
+
stdout->data = stdout_handle;
|
104
|
+
process_handle->stdout = stdout;
|
105
|
+
// stderr
|
106
|
+
uv_pipe_t* stderr = malloc(sizeof(uv_pipe_t));
|
107
|
+
uv_pipe_init(stderr);
|
108
|
+
options.stderr_stream = stderr;
|
109
|
+
nodeRb_process_read_handle* stderr_handle = malloc(sizeof(nodeRb_process_read_handle));
|
110
|
+
stderr_handle->target = process_handle->target;
|
111
|
+
stderr_handle->target_callback = (char*) "on_stderr";
|
112
|
+
stderr->data = stderr_handle;
|
113
|
+
process_handle->stderr = stderr;
|
114
|
+
// libuv handle
|
115
|
+
uv_process_t* handle = malloc(sizeof(uv_process_t));
|
116
|
+
handle->data = process_handle;
|
117
|
+
// Save reference into Ruby object
|
118
|
+
rb_iv_set(clazz, "@_handle", Data_Wrap_Struct(nodeRb_get_nodeRb_pointer(), 0, NULL, handle));
|
119
|
+
// spawn process
|
120
|
+
uv_spawn(handle, options);
|
121
|
+
// Listen to stdout/err
|
122
|
+
uv_read_start((uv_stream_t*) stdout, nodeRb_read_alloc, nodeRb_read);
|
123
|
+
uv_read_start((uv_stream_t*) stderr, nodeRb_read_alloc, nodeRb_read);
|
124
|
+
// call back ruby
|
125
|
+
rb_funcall(clazz, rb_intern("on_start"), 0);
|
126
|
+
};
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#ifndef NODERB_PROCESS_H
|
2
|
+
#define NODERB_PROCESS_H
|
3
|
+
|
4
|
+
#ifdef __cplusplus
|
5
|
+
extern "C" {
|
6
|
+
#endif
|
7
|
+
|
8
|
+
VALUE nodeRb_startProcess(VALUE self, VALUE executable, VALUE arguments, VALUE environment, VALUE directory, VALUE clazz);
|
9
|
+
VALUE nodeRb_process_write(VALUE self, VALUE data);
|
10
|
+
VALUE nodeRb_process_kill(VALUE self, VALUE signal);
|
11
|
+
|
12
|
+
#ifdef __cplusplus
|
13
|
+
}
|
14
|
+
#endif
|
15
|
+
|
16
|
+
#endif /* NODERB_PROCESS_H */
|
17
|
+
|