2
0

uv.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. #define HL_NAME(n) uv_##n
  2. #ifdef _WIN32
  3. # include <uv.h>
  4. # include <hl.h>
  5. #else
  6. # include <hl.h>
  7. # include <uv.h>
  8. #endif
  9. #if (UV_VERSION_MAJOR <= 0)
  10. # error "libuv1-dev required, uv version 0.x found"
  11. #endif
  12. typedef struct sockaddr uv_sockaddr;
  13. #define EVT_CLOSE 1
  14. #define EVT_READ 0 // stream
  15. #define EVT_LISTEN 2 // stream
  16. #define EVT_WRITE 0 // write_t
  17. #define EVT_CONNECT 0 // connect_t
  18. #define EVT_FS 0
  19. #define EVT_MAX 2
  20. typedef struct {
  21. vclosure *events[EVT_MAX + 1];
  22. void *write_data;
  23. } events_data;
  24. #define UV_DATA(h) ((events_data*)((h)->data))
  25. #define _LOOP _ABSTRACT(uv_loop)
  26. #define _HANDLE _ABSTRACT(uv_handle)
  27. #define _CALLB _FUN(_VOID,_NO_ARG)
  28. #define UV_ALLOC(t) ((t*)malloc(sizeof(t)))
  29. // HANDLE
  30. static events_data *init_hl_data( uv_handle_t *h ) {
  31. events_data *d = hl_gc_alloc_raw(sizeof(events_data));
  32. memset(d,0,sizeof(events_data));
  33. hl_add_root(&h->data);
  34. h->data = d;
  35. return d;
  36. }
  37. static void register_callb( uv_handle_t *h, vclosure *c, int event_kind ) {
  38. if( !h || !h->data ) return;
  39. UV_DATA(h)->events[event_kind] = c;
  40. }
  41. static void clear_callb( uv_handle_t *h, int event_kind ) {
  42. register_callb(h,NULL,event_kind);
  43. }
  44. static void trigger_callb( uv_handle_t *h, int event_kind, vdynamic **args, int nargs, bool repeat ) {
  45. events_data *ev = UV_DATA(h);
  46. vclosure *c = ev ? ev->events[event_kind] : NULL;
  47. if( !c ) return;
  48. if( !repeat ) ev->events[event_kind] = NULL;
  49. hl_dyn_call(c, args, nargs);
  50. }
  51. static void on_close( uv_handle_t *h ) {
  52. events_data *ev = UV_DATA(h);
  53. if( !ev ) return;
  54. trigger_callb(h, EVT_CLOSE, NULL, 0, false);
  55. free(ev->write_data);
  56. hl_remove_root(&h->data);
  57. h->data = NULL;
  58. free(h);
  59. }
  60. static void free_handle( void *h ) {
  61. if( h ) uv_close((uv_handle_t*)h, on_close);
  62. }
  63. HL_PRIM void HL_NAME(close_handle)( uv_handle_t *h, vclosure *c ) {
  64. register_callb(h, c, EVT_CLOSE);
  65. free_handle(h);
  66. }
  67. DEFINE_PRIM(_VOID, close_handle, _HANDLE _CALLB);
  68. // STREAM
  69. static void on_write( uv_write_t *wr, int status ) {
  70. vdynamic b;
  71. vdynamic *args = &b;
  72. b.t = &hlt_bool;
  73. b.v.b = status == 0;
  74. trigger_callb((uv_handle_t*)wr,EVT_WRITE,&args,1,false);
  75. on_close((uv_handle_t*)wr);
  76. }
  77. HL_PRIM bool HL_NAME(stream_write)( uv_stream_t *s, vbyte *b, int size, vclosure *c ) {
  78. uv_write_t *wr = UV_ALLOC(uv_write_t);
  79. events_data *d = init_hl_data((uv_handle_t*)wr);
  80. // keep a copy of the data
  81. uv_buf_t buf;
  82. d->write_data = malloc(size);
  83. memcpy(d->write_data,b,size);
  84. buf.base = d->write_data;
  85. buf.len = size;
  86. register_callb((uv_handle_t*)wr,c,EVT_WRITE);
  87. if( uv_write(wr,s,&buf,1,on_write) < 0 ) {
  88. on_close((uv_handle_t*)wr);
  89. return false;
  90. }
  91. return true;
  92. }
  93. static void on_alloc( uv_handle_t* h, size_t size, uv_buf_t *buf ) {
  94. *buf = uv_buf_init(malloc(size), (int)size);
  95. }
  96. static void on_read( uv_stream_t *s, ssize_t nread, const uv_buf_t *buf ) {
  97. vdynamic bytes;
  98. vdynamic len;
  99. vdynamic *args[2];
  100. bytes.t = &hlt_bytes;
  101. bytes.v.ptr = buf->base;
  102. len.t = &hlt_i32;
  103. len.v.i = (int)nread;
  104. args[0] = &bytes;
  105. args[1] = &len;
  106. trigger_callb((uv_handle_t*)s,EVT_READ,args,2,true);
  107. free(buf->base);
  108. }
  109. HL_PRIM bool HL_NAME(stream_read_start)( uv_stream_t *s, vclosure *c ) {
  110. register_callb((uv_handle_t*)s,c,EVT_READ);
  111. return uv_read_start(s,on_alloc,on_read) >= 0;
  112. }
  113. HL_PRIM void HL_NAME(stream_read_stop)( uv_stream_t *s ) {
  114. uv_read_stop(s);
  115. clear_callb((uv_handle_t*)s,EVT_READ); // clear callback
  116. }
  117. static void on_listen( uv_stream_t *s, int status ) {
  118. trigger_callb((uv_handle_t*)s, EVT_LISTEN, NULL, 0, true);
  119. }
  120. HL_PRIM bool HL_NAME(stream_listen)( uv_stream_t *s, int count, vclosure *c ) {
  121. register_callb((uv_handle_t*)s,c,EVT_LISTEN);
  122. return uv_listen(s,count,on_listen) >= 0;
  123. }
  124. DEFINE_PRIM(_BOOL, stream_write, _HANDLE _BYTES _I32 _FUN(_VOID,_BOOL));
  125. DEFINE_PRIM(_BOOL, stream_read_start, _HANDLE _FUN(_VOID,_BYTES _I32));
  126. DEFINE_PRIM(_VOID, stream_read_stop, _HANDLE);
  127. DEFINE_PRIM(_BOOL, stream_listen, _HANDLE _I32 _CALLB);
  128. // TCP
  129. #define _TCP _HANDLE
  130. HL_PRIM uv_tcp_t *HL_NAME(tcp_init_wrap)( uv_loop_t *loop ) {
  131. uv_tcp_t *t = UV_ALLOC(uv_tcp_t);
  132. if( uv_tcp_init(loop,t) < 0 ) {
  133. free(t);
  134. return NULL;
  135. }
  136. init_hl_data((uv_handle_t*)t);
  137. return t;
  138. }
  139. static void on_connect( uv_connect_t *cnx, int status ) {
  140. vdynamic b;
  141. vdynamic *args = &b;
  142. b.t = &hlt_bool;
  143. b.v.b = status == 0;
  144. trigger_callb((uv_handle_t*)cnx,EVT_CONNECT,&args,1,false);
  145. on_close((uv_handle_t*)cnx);
  146. }
  147. HL_PRIM uv_connect_t *HL_NAME(tcp_connect_wrap)( uv_tcp_t *t, int host, int port, vclosure *c ) {
  148. uv_connect_t *cnx = UV_ALLOC(uv_connect_t);
  149. struct sockaddr_in addr;
  150. memset(&addr,0,sizeof(addr));
  151. addr.sin_family = AF_INET;
  152. addr.sin_port = htons((unsigned short)port);
  153. *(int*)&addr.sin_addr.s_addr = host;
  154. if( !t || uv_tcp_connect(cnx,t,(uv_sockaddr *)&addr,on_connect) < 0 ) {
  155. free(cnx);
  156. return NULL;
  157. }
  158. memset(&addr,0,sizeof(addr));
  159. init_hl_data((uv_handle_t*)cnx);
  160. register_callb((uv_handle_t*)cnx, c, EVT_CONNECT);
  161. return cnx;
  162. }
  163. HL_PRIM bool HL_NAME(tcp_bind_wrap)( uv_tcp_t *t, int host, int port ) {
  164. struct sockaddr_in addr;
  165. memset(&addr,0,sizeof(addr));
  166. addr.sin_family = AF_INET;
  167. addr.sin_port = htons((unsigned short)port);
  168. *(int*)&addr.sin_addr.s_addr = host;
  169. return uv_tcp_bind(t,(uv_sockaddr *)&addr,0) >= 0;
  170. }
  171. HL_PRIM uv_tcp_t *HL_NAME(tcp_accept_wrap)( uv_tcp_t *t ) {
  172. uv_tcp_t *client = UV_ALLOC(uv_tcp_t);
  173. if( uv_tcp_init(t->loop, client) < 0 ) {
  174. free(client);
  175. return NULL;
  176. }
  177. if( uv_accept((uv_stream_t*)t,(uv_stream_t*)client) < 0 ) {
  178. uv_close((uv_handle_t*)client, NULL);
  179. return NULL;
  180. }
  181. init_hl_data((uv_handle_t*)client);
  182. return client;
  183. }
  184. HL_PRIM void HL_NAME(tcp_nodelay_wrap)( uv_tcp_t *t, bool enable ) {
  185. uv_tcp_nodelay(t,enable?1:0);
  186. }
  187. #define _FS _HANDLE
  188. static void on_fs_event(uv_fs_event_t* handle, const char* filename, int events, int status) {
  189. vdynamic ev;
  190. ev.t = &hlt_i32;
  191. ev.v.i = events;
  192. vdynamic* args[1];
  193. args[0] = &ev;
  194. trigger_callb((uv_handle_t*)handle, EVT_FS, args, 1, true);
  195. }
  196. HL_PRIM uv_fs_event_t* HL_NAME(fs_start_wrap)(uv_loop_t* loop, vclosure* cb, char* path) {
  197. uv_fs_event_t* handle = UV_ALLOC(uv_fs_event_t);
  198. if (uv_fs_event_init(loop, handle) < 0) {
  199. free(handle);
  200. return NULL;
  201. }
  202. init_hl_data((uv_handle_t*) handle);
  203. register_callb((uv_handle_t*)handle, cb, EVT_FS);
  204. if (uv_fs_event_start(handle, on_fs_event, path, 0) < 0) {
  205. free_handle(handle);
  206. return NULL;
  207. }
  208. return handle;
  209. }
  210. HL_PRIM bool HL_NAME(fs_stop_wrap)(uv_fs_event_t* handle) {
  211. clear_callb((uv_handle_t*)handle, EVT_FS);
  212. return uv_fs_event_stop(handle);
  213. }
  214. DEFINE_PRIM(_TCP, tcp_init_wrap, _LOOP);
  215. DEFINE_PRIM(_HANDLE, tcp_connect_wrap, _TCP _I32 _I32 _FUN(_VOID,_BOOL));
  216. DEFINE_PRIM(_BOOL, tcp_bind_wrap, _TCP _I32 _I32);
  217. DEFINE_PRIM(_HANDLE, tcp_accept_wrap, _HANDLE);
  218. DEFINE_PRIM(_VOID, tcp_nodelay_wrap, _TCP _BOOL);
  219. // handle FS
  220. DEFINE_PRIM(_FS, fs_start_wrap, _LOOP _FUN(_VOID, _I32) _BYTES);
  221. DEFINE_PRIM(_BOOL, fs_stop_wrap, _FS);
  222. // loop
  223. HL_PRIM uv_loop_t *HL_NAME(create_loop)() {
  224. uv_loop_t *l = (uv_loop_t*)hl_gc_alloc_noptr(sizeof(uv_loop_t));
  225. uv_loop_init(l);
  226. return l;
  227. }
  228. DEFINE_PRIM(_LOOP, create_loop, _NO_ARG);
  229. DEFINE_PRIM(_LOOP, default_loop, _NO_ARG);
  230. DEFINE_PRIM(_I32, loop_close, _LOOP);
  231. DEFINE_PRIM(_I32, run, _LOOP _I32);
  232. DEFINE_PRIM(_I32, loop_alive, _LOOP);
  233. DEFINE_PRIM(_VOID, stop, _LOOP);
  234. HL_PRIM uv_loop_t* HL_NAME(default_loop_wrap)() {
  235. return uv_default_loop();
  236. }
  237. HL_PRIM int HL_NAME(loop_close_wrap)(uv_loop_t* loop) {
  238. return uv_loop_close(loop);
  239. }
  240. HL_PRIM int HL_NAME(run_wrap)(uv_loop_t* loop, int mode) {
  241. return uv_run(loop, (uv_run_mode)mode);
  242. }
  243. HL_PRIM int HL_NAME(loop_alive_wrap)(uv_loop_t* loop) {
  244. return uv_loop_alive(loop);
  245. }
  246. HL_PRIM void HL_NAME(stop_wrap)(uv_loop_t* loop) {
  247. uv_stop(loop);
  248. }
  249. DEFINE_PRIM(_LOOP, default_loop_wrap, _NO_ARG);
  250. DEFINE_PRIM(_I32, loop_close_wrap, _LOOP);
  251. DEFINE_PRIM(_I32, run_wrap, _LOOP _I32);
  252. DEFINE_PRIM(_I32, loop_alive_wrap, _LOOP);
  253. DEFINE_PRIM(_VOID, stop_wrap, _LOOP);
  254. DEFINE_PRIM(_BYTES, strerror, _I32);