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.
Files changed (51) hide show
  1. data/README.md +157 -7
  2. data/ext/noderb_extension/extconf.rb +1 -3
  3. data/ext/noderb_extension/libuv/BSDmakefile +2 -0
  4. data/ext/noderb_extension/libuv/all.gyp +326 -0
  5. data/ext/noderb_extension/libuv/config-mingw.mk +0 -1
  6. data/ext/noderb_extension/libuv/config-unix.mk +7 -1
  7. data/ext/noderb_extension/libuv/create-msvs-files.bat +13 -6
  8. data/ext/noderb_extension/libuv/{build/gyp_uv → gyp_uv} +1 -2
  9. data/ext/noderb_extension/libuv/include/uv.h +5 -0
  10. data/ext/noderb_extension/libuv/src/eio/config_cygwin.h +3 -0
  11. data/ext/noderb_extension/libuv/src/eio/config_freebsd.h +3 -0
  12. data/ext/noderb_extension/libuv/src/eio/config_sunos.h +3 -0
  13. data/ext/noderb_extension/libuv/src/eio/ecb.h +1 -1
  14. data/ext/noderb_extension/libuv/src/eio/eio.c +8 -1
  15. data/ext/noderb_extension/libuv/src/uv-common.c +1 -0
  16. data/ext/noderb_extension/libuv/src/uv-sunos.c +1 -1
  17. data/ext/noderb_extension/libuv/src/uv-unix.c +72 -59
  18. data/ext/noderb_extension/libuv/src/win/core.c +3 -0
  19. data/ext/noderb_extension/libuv/src/win/internal.h +11 -0
  20. data/ext/noderb_extension/libuv/src/win/ntdll.h +130 -0
  21. data/ext/noderb_extension/libuv/src/win/pipe.c +105 -27
  22. data/ext/noderb_extension/libuv/src/win/process.c +76 -5
  23. data/ext/noderb_extension/libuv/src/win/req.c +7 -0
  24. data/ext/noderb_extension/libuv/src/win/winapi.c +52 -0
  25. data/ext/noderb_extension/libuv/test/benchmark-pound.c +50 -48
  26. data/ext/noderb_extension/libuv/test/echo-server.c +2 -2
  27. data/ext/noderb_extension/libuv/test/test-list.h +2 -0
  28. data/ext/noderb_extension/libuv/test/test-spawn.c +48 -1
  29. data/ext/noderb_extension/noderb.c +38 -339
  30. data/ext/noderb_extension/noderb.h +18 -2
  31. data/ext/noderb_extension/noderb_common.h +13 -0
  32. data/ext/noderb_extension/noderb_dns.c +37 -0
  33. data/ext/noderb_extension/noderb_dns.h +15 -0
  34. data/ext/noderb_extension/noderb_process.c +126 -0
  35. data/ext/noderb_extension/noderb_process.h +17 -0
  36. data/ext/noderb_extension/noderb_tcp.c +127 -0
  37. data/ext/noderb_extension/noderb_tcp.h +19 -0
  38. data/ext/noderb_extension/noderb_timers.c +58 -0
  39. data/ext/noderb_extension/noderb_timers.h +16 -0
  40. data/ext/noderb_extension/noderb_tools.c +127 -0
  41. data/ext/noderb_extension/noderb_tools.h +33 -0
  42. data/lib/noderb/dns.rb +11 -0
  43. data/lib/noderb/next_tick.rb +2 -1
  44. data/lib/noderb/tcp.rb +27 -0
  45. data/lib/noderb/timers.rb +24 -0
  46. data/lib/noderb/version.rb +1 -1
  47. data/lib/noderb.rb +6 -1
  48. metadata +23 -7
  49. data/ext/noderb_extension/libuv/build/all.gyp +0 -254
  50. data/ext/noderb_extension/libuv/doc/desired-api.md +0 -159
  51. /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
- void nodeRb_on_shutdown(uv_shutdown_t* req, int status) {
118
- uv_close((uv_handle_t*) req->handle, nodeRb_on_close);
119
- free(req);
15
+ // Core module of NodeRb
16
+ VALUE nodeRb_get_nodeRb_module(){
17
+ return nodeRb;
120
18
  }
121
19
 
122
- VALUE nodeRb_close_connection(VALUE self) {
123
- uv_shutdown_t* req = malloc(sizeof (uv_shutdown_t));
124
- VALUE rhandler = rb_iv_get(self, "@_handle");
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
- nodeRbPointer = rb_define_class_under(nodeRb, "Pointer", rb_cObject);
340
- nodeRbConnection = rb_define_module_under(nodeRb, "Connection");
341
- nodeRbProcess = rb_define_module_under(nodeRb, "Process");
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, "write", nodeRb_send_data, 1);
344
- rb_define_method(nodeRbConnection, "close_connection", nodeRb_close_connection, 0);
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, "write", nodeRb_process_write, 1);
347
- rb_define_method(nodeRbProcess, "kill", nodeRb_process_kill, 1);
348
- // Run code on next tick
349
- rb_define_singleton_method(nodeRb, "native_next_tick", nodeRb_nextTick, 0);
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, "start_server", nodeRb_startServer, 3);
353
- rb_define_singleton_method(nodeRb, "start_client", nodeRb_startClient, 3);
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", nodeRb_register_instance, 1);
358
- rb_define_singleton_method(nodeRb, "unregister_instance", nodeRb_unregister_instance, 1);
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
- #include <libuv/include/uv.h>
2
- #include <ruby.h>
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,13 @@
1
+ #include <libuv/include/uv.h>
2
+ #include <ruby.h>
3
+
4
+ #define NODERB_BASIC_HANDLE \
5
+ long target; \
6
+ char* target_callback; \
7
+ void* proxy;
8
+
9
+ typedef struct {
10
+ NODERB_BASIC_HANDLE
11
+ } nodeRb_basic_handle;
12
+
13
+ #define rb_num2int(x) NUM2LONG(x)
@@ -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,15 @@
1
+ #ifndef NODERB_DNS_H
2
+ #define NODERB_DNS_H
3
+
4
+ #ifdef __cplusplus
5
+ extern "C" {
6
+ #endif
7
+
8
+ VALUE nodeRb_dns_resolve(VALUE self, VALUE host, VALUE callback);
9
+
10
+ #ifdef __cplusplus
11
+ }
12
+ #endif
13
+
14
+ #endif /* NODERB_DNS_H */
15
+
@@ -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
+