noderb 0.0.3 → 0.0.4
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/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
|
+
|