xbintsc 0.2.9 → 0.3.1

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 (311) hide show
  1. package/README.md +17 -2
  2. package/README.zh-CN.md +16 -2
  3. package/bin/xbintsc.js +49 -10
  4. package/dist/src/ast/expressions.d.ts +2 -0
  5. package/dist/src/binder/binder.d.ts +24 -98
  6. package/dist/src/binder/binder.js +13 -559
  7. package/dist/src/binder/binder.js.map +1 -1
  8. package/dist/src/binder/declarations.d.ts +16 -0
  9. package/dist/src/binder/declarations.js +168 -0
  10. package/dist/src/binder/declarations.js.map +1 -0
  11. package/dist/src/binder/helpers.d.ts +11 -0
  12. package/dist/src/binder/helpers.js +46 -0
  13. package/dist/src/binder/helpers.js.map +1 -0
  14. package/dist/src/binder/references.d.ts +21 -0
  15. package/dist/src/binder/references.js +349 -0
  16. package/dist/src/binder/references.js.map +1 -0
  17. package/dist/src/binder/types.d.ts +114 -0
  18. package/dist/src/binder/types.js +27 -0
  19. package/dist/src/binder/types.js.map +1 -0
  20. package/dist/src/cli/main.d.ts +1 -0
  21. package/dist/src/cli/main.js +40 -0
  22. package/dist/src/cli/main.js.map +1 -1
  23. package/dist/src/codegen/generator/calls/access.d.ts +13 -0
  24. package/dist/src/codegen/generator/calls/access.js +115 -0
  25. package/dist/src/codegen/generator/calls/access.js.map +1 -0
  26. package/dist/src/codegen/generator/calls/closures.d.ts +11 -0
  27. package/dist/src/codegen/generator/calls/closures.js +50 -0
  28. package/dist/src/codegen/generator/calls/closures.js.map +1 -0
  29. package/dist/src/codegen/generator/calls/invocation.d.ts +18 -0
  30. package/dist/src/codegen/generator/calls/invocation.js +242 -0
  31. package/dist/src/codegen/generator/calls/invocation.js.map +1 -0
  32. package/dist/src/codegen/generator/calls/literals.d.ts +10 -0
  33. package/dist/src/codegen/generator/calls/literals.js +69 -0
  34. package/dist/src/codegen/generator/calls/literals.js.map +1 -0
  35. package/dist/src/codegen/generator/calls/super.d.ts +10 -0
  36. package/dist/src/codegen/generator/calls/super.js +47 -0
  37. package/dist/src/codegen/generator/calls/super.js.map +1 -0
  38. package/dist/src/codegen/generator/calls.d.ts +15 -24
  39. package/dist/src/codegen/generator/calls.js +15 -482
  40. package/dist/src/codegen/generator/calls.js.map +1 -1
  41. package/dist/src/codegen/generator/context.d.ts +1 -1
  42. package/dist/src/codegen/generator/context.js +2 -2
  43. package/dist/src/codegen/generator/context.js.map +1 -1
  44. package/dist/src/codegen/generator/expressions/assignment.d.ts +13 -0
  45. package/dist/src/codegen/generator/expressions/assignment.js +203 -0
  46. package/dist/src/codegen/generator/expressions/assignment.js.map +1 -0
  47. package/dist/src/codegen/generator/expressions/operators.d.ts +14 -0
  48. package/dist/src/codegen/generator/expressions/operators.js +163 -0
  49. package/dist/src/codegen/generator/expressions/operators.js.map +1 -0
  50. package/dist/src/codegen/generator/expressions/primary.d.ts +17 -0
  51. package/dist/src/codegen/generator/expressions/primary.js +260 -0
  52. package/dist/src/codegen/generator/expressions/primary.js.map +1 -0
  53. package/dist/src/codegen/generator/expressions.d.ts +11 -21
  54. package/dist/src/codegen/generator/expressions.js +11 -494
  55. package/dist/src/codegen/generator/expressions.js.map +1 -1
  56. package/dist/src/codegen/generator/module.js +16 -4
  57. package/dist/src/codegen/generator/module.js.map +1 -1
  58. package/dist/src/codegen/generator/state.js +8 -0
  59. package/dist/src/codegen/generator/state.js.map +1 -1
  60. package/dist/src/codegen/generator/statements/control-flow.d.ts +14 -0
  61. package/dist/src/codegen/generator/statements/control-flow.js +199 -0
  62. package/dist/src/codegen/generator/statements/control-flow.js.map +1 -0
  63. package/dist/src/codegen/generator/statements/dispatch.d.ts +12 -0
  64. package/dist/src/codegen/generator/statements/dispatch.js +100 -0
  65. package/dist/src/codegen/generator/statements/dispatch.js.map +1 -0
  66. package/dist/src/codegen/generator/statements/loops.d.ts +13 -0
  67. package/dist/src/codegen/generator/statements/loops.js +152 -0
  68. package/dist/src/codegen/generator/statements/loops.js.map +1 -0
  69. package/dist/src/codegen/generator/statements/variables.d.ts +13 -0
  70. package/dist/src/codegen/generator/statements/variables.js +146 -0
  71. package/dist/src/codegen/generator/statements/variables.js.map +1 -0
  72. package/dist/src/codegen/generator/statements.d.ts +13 -21
  73. package/dist/src/codegen/generator/statements.js +13 -568
  74. package/dist/src/codegen/generator/statements.js.map +1 -1
  75. package/dist/src/codegen/generator/tables.js +7 -0
  76. package/dist/src/codegen/generator/tables.js.map +1 -1
  77. package/dist/src/codegen/values.d.ts +17 -17
  78. package/dist/src/codegen/values.js +21 -57
  79. package/dist/src/codegen/values.js.map +1 -1
  80. package/dist/src/diagnostics/diagnostic.d.ts +1 -0
  81. package/dist/src/diagnostics/diagnostic.js +1 -0
  82. package/dist/src/diagnostics/diagnostic.js.map +1 -1
  83. package/dist/src/diagnostics/source.d.ts +1 -1
  84. package/dist/src/diagnostics/source.js +7 -12
  85. package/dist/src/diagnostics/source.js.map +1 -1
  86. package/dist/src/driver/compiler.d.ts +4 -0
  87. package/dist/src/driver/compiler.js +51 -16
  88. package/dist/src/driver/compiler.js.map +1 -1
  89. package/dist/src/driver/index.d.ts +5 -2
  90. package/dist/src/driver/index.js +5 -2
  91. package/dist/src/driver/index.js.map +1 -1
  92. package/dist/src/driver/paths.d.ts +20 -0
  93. package/dist/src/driver/paths.js +49 -0
  94. package/dist/src/driver/paths.js.map +1 -1
  95. package/dist/src/driver/runtime-lib.d.ts +18 -0
  96. package/dist/src/driver/runtime-lib.js +31 -0
  97. package/dist/src/driver/runtime-lib.js.map +1 -0
  98. package/dist/src/driver/toolchain-download.d.ts +50 -0
  99. package/dist/src/driver/toolchain-download.js +76 -0
  100. package/dist/src/driver/toolchain-download.js.map +1 -0
  101. package/dist/src/driver/toolchain-provider.d.ts +33 -0
  102. package/dist/src/driver/toolchain-provider.js +71 -0
  103. package/dist/src/driver/toolchain-provider.js.map +1 -0
  104. package/dist/src/driver/toolchain.d.ts +9 -4
  105. package/dist/src/driver/toolchain.js +6 -10
  106. package/dist/src/driver/toolchain.js.map +1 -1
  107. package/dist/src/extensions/node/child_process/index.d.ts +4 -2
  108. package/dist/src/extensions/node/child_process/index.js +4 -2
  109. package/dist/src/extensions/node/child_process/index.js.map +1 -1
  110. package/dist/src/extensions/node/events/index.d.ts +10 -0
  111. package/dist/src/extensions/node/events/index.js +22 -0
  112. package/dist/src/extensions/node/events/index.js.map +1 -0
  113. package/dist/src/extensions/node/index.js +6 -0
  114. package/dist/src/extensions/node/index.js.map +1 -1
  115. package/dist/src/extensions/node/querystring/index.d.ts +10 -0
  116. package/dist/src/extensions/node/querystring/index.js +25 -0
  117. package/dist/src/extensions/node/querystring/index.js.map +1 -0
  118. package/dist/src/extensions/node/util/index.d.ts +11 -0
  119. package/dist/src/extensions/node/util/index.js +41 -0
  120. package/dist/src/extensions/node/util/index.js.map +1 -0
  121. package/dist/src/extensions/registry.d.ts +6 -0
  122. package/dist/src/extensions/registry.js.map +1 -1
  123. package/dist/src/index.d.ts +1 -1
  124. package/dist/src/index.js +1 -1
  125. package/dist/src/index.js.map +1 -1
  126. package/dist/src/lexer/scanner/identifiers.d.ts +9 -0
  127. package/dist/src/lexer/scanner/identifiers.js +33 -0
  128. package/dist/src/lexer/scanner/identifiers.js.map +1 -0
  129. package/dist/src/lexer/scanner/numbers.d.ts +10 -0
  130. package/dist/src/lexer/scanner/numbers.js +89 -0
  131. package/dist/src/lexer/scanner/numbers.js.map +1 -0
  132. package/dist/src/lexer/scanner/punctuation.d.ts +9 -0
  133. package/dist/src/lexer/scanner/punctuation.js +151 -0
  134. package/dist/src/lexer/scanner/punctuation.js.map +1 -0
  135. package/dist/src/lexer/scanner/regex.d.ts +11 -0
  136. package/dist/src/lexer/scanner/regex.js +69 -0
  137. package/dist/src/lexer/scanner/regex.js.map +1 -0
  138. package/dist/src/lexer/scanner/strings.d.ts +13 -0
  139. package/dist/src/lexer/scanner/strings.js +118 -0
  140. package/dist/src/lexer/scanner/strings.js.map +1 -0
  141. package/dist/src/lexer/scanner.d.ts +20 -27
  142. package/dist/src/lexer/scanner.js +11 -415
  143. package/dist/src/lexer/scanner.js.map +1 -1
  144. package/dist/src/parser/declarations/classes.d.ts +14 -0
  145. package/dist/src/parser/declarations/classes.js +191 -0
  146. package/dist/src/parser/declarations/classes.js.map +1 -0
  147. package/dist/src/parser/declarations/functions.d.ts +17 -0
  148. package/dist/src/parser/declarations/functions.js +241 -0
  149. package/dist/src/parser/declarations/functions.js.map +1 -0
  150. package/dist/src/parser/declarations/type-members.d.ts +16 -0
  151. package/dist/src/parser/declarations/type-members.js +156 -0
  152. package/dist/src/parser/declarations/type-members.js.map +1 -0
  153. package/dist/src/parser/declarations.d.ts +13 -24
  154. package/dist/src/parser/declarations.js +13 -571
  155. package/dist/src/parser/declarations.js.map +1 -1
  156. package/dist/src/parser/helpers.js +13 -4
  157. package/dist/src/parser/helpers.js.map +1 -1
  158. package/dist/src/parser/literals.js +10 -1
  159. package/dist/src/parser/literals.js.map +1 -1
  160. package/dist/tests/codegen/llvm.test.js +24 -0
  161. package/dist/tests/codegen/llvm.test.js.map +1 -1
  162. package/dist/tests/driver/compiler.test.js +3 -0
  163. package/dist/tests/driver/compiler.test.js.map +1 -1
  164. package/dist/tests/driver/paths.test.d.ts +1 -0
  165. package/dist/tests/driver/paths.test.js +26 -0
  166. package/dist/tests/driver/paths.test.js.map +1 -0
  167. package/dist/tests/driver/toolchain-download.test.d.ts +1 -0
  168. package/dist/tests/driver/toolchain-download.test.js +38 -0
  169. package/dist/tests/driver/toolchain-download.test.js.map +1 -0
  170. package/dist/tests/driver/toolchain-provider.test.d.ts +1 -0
  171. package/dist/tests/driver/toolchain-provider.test.js +37 -0
  172. package/dist/tests/driver/toolchain-provider.test.js.map +1 -0
  173. package/dist/tests/e2e/compile-node.test.d.ts +7 -0
  174. package/dist/tests/e2e/compile-node.test.js +123 -0
  175. package/dist/tests/e2e/compile-node.test.js.map +1 -0
  176. package/dist/tests/e2e/compile.test.d.ts +4 -1
  177. package/dist/tests/e2e/compile.test.js +78 -130
  178. package/dist/tests/e2e/compile.test.js.map +1 -1
  179. package/dist/tests/e2e/harness.d.ts +36 -0
  180. package/dist/tests/e2e/harness.js +64 -0
  181. package/dist/tests/e2e/harness.js.map +1 -0
  182. package/dist/tests/e2e/node-modules.test.js +60 -0
  183. package/dist/tests/e2e/node-modules.test.js.map +1 -1
  184. package/dist/tests/extensions/registry.test.js +4 -0
  185. package/dist/tests/extensions/registry.test.js.map +1 -1
  186. package/package.json +5 -3
  187. package/runtime/ext_node/buffer/buffer.c +12 -552
  188. package/runtime/ext_node/buffer/parts/byte-access.inc +35 -0
  189. package/runtime/ext_node/buffer/parts/construction.inc +60 -0
  190. package/runtime/ext_node/buffer/parts/integer-io.inc +119 -0
  191. package/runtime/ext_node/buffer/parts/methods.inc +135 -0
  192. package/runtime/ext_node/buffer/parts/prototype.inc +54 -0
  193. package/runtime/ext_node/buffer/parts/search.inc +86 -0
  194. package/runtime/ext_node/buffer/parts/static-api.inc +58 -0
  195. package/runtime/ext_node/child_process/child_process.c +37 -3
  196. package/runtime/ext_node/events/events.c +285 -0
  197. package/runtime/ext_node/http/http.c +11 -736
  198. package/runtime/ext_node/http/parts/client.inc +290 -0
  199. package/runtime/ext_node/http/parts/helpers.inc +45 -0
  200. package/runtime/ext_node/http/parts/prototypes.inc +57 -0
  201. package/runtime/ext_node/http/parts/response.inc +149 -0
  202. package/runtime/ext_node/http/parts/server.inc +133 -0
  203. package/runtime/ext_node/http/parts/string-builder.inc +58 -0
  204. package/runtime/ext_node/net/net.c +12 -504
  205. package/runtime/ext_node/net/parts/construction.inc +22 -0
  206. package/runtime/ext_node/net/parts/platform.inc +60 -0
  207. package/runtime/ext_node/net/parts/prototypes.inc +35 -0
  208. package/runtime/ext_node/net/parts/read-loop.inc +58 -0
  209. package/runtime/ext_node/net/parts/server.inc +131 -0
  210. package/runtime/ext_node/net/parts/socket-methods.inc +100 -0
  211. package/runtime/ext_node/net/parts/static-api.inc +93 -0
  212. package/runtime/ext_node/querystring/querystring.c +251 -0
  213. package/runtime/ext_node/util/util.c +456 -0
  214. package/runtime/rt.h +8 -2
  215. package/runtime/rt_internal.h +34 -0
  216. package/runtime/xt_bigint/arithmetic.inc +135 -0
  217. package/runtime/xt_bigint/bits.inc +98 -0
  218. package/runtime/xt_bigint/bitwise.inc +103 -0
  219. package/runtime/xt_bigint/compare.inc +30 -0
  220. package/runtime/xt_bigint/conversions.inc +51 -0
  221. package/runtime/xt_bigint/division.inc +85 -0
  222. package/runtime/xt_bigint/format.inc +145 -0
  223. package/runtime/xt_bigint/helpers.inc +92 -0
  224. package/runtime/xt_bigint/magnitude.inc +88 -0
  225. package/runtime/xt_bigint/public.inc +59 -0
  226. package/runtime/xt_bigint/small-arithmetic.inc +58 -0
  227. package/runtime/xt_bigint.c +42 -0
  228. package/runtime/xt_builtins.c +1 -0
  229. package/runtime/xt_io.c +7 -0
  230. package/runtime/xt_stdlib/arrays.inc +161 -0
  231. package/runtime/xt_stdlib/dispatch.inc +116 -0
  232. package/runtime/xt_stdlib/helpers.inc +23 -0
  233. package/runtime/xt_stdlib/math.inc +72 -0
  234. package/runtime/xt_stdlib/strings.inc +178 -0
  235. package/runtime/xt_stdlib.c +10 -549
  236. package/runtime/xt_stdlib2/array-statics.inc +37 -0
  237. package/runtime/xt_stdlib2/arrays.inc +189 -0
  238. package/runtime/xt_stdlib2/container.inc +23 -0
  239. package/runtime/xt_stdlib2/date.inc +72 -0
  240. package/runtime/xt_stdlib2/error.inc +22 -0
  241. package/runtime/xt_stdlib2/helpers.inc +43 -0
  242. package/runtime/xt_stdlib2/json.inc +213 -0
  243. package/runtime/xt_stdlib2/map.inc +95 -0
  244. package/runtime/xt_stdlib2/number-string-statics.inc +73 -0
  245. package/runtime/xt_stdlib2/numbers.inc +38 -0
  246. package/runtime/xt_stdlib2/objects.inc +41 -0
  247. package/runtime/xt_stdlib2/regexp-match.inc +204 -0
  248. package/runtime/xt_stdlib2/regexp.inc +20 -0
  249. package/runtime/xt_stdlib2/set.inc +105 -0
  250. package/runtime/xt_stdlib2/strings.inc +94 -0
  251. package/runtime/xt_stdlib2.c +19 -1278
  252. package/runtime/xt_values.c +155 -12
  253. package/scripts/build-runtime.ts +109 -0
  254. package/scripts/fetch-toolchain.ts +101 -0
  255. package/scripts/package-release.ts +192 -0
  256. package/src/ast/expressions.ts +2 -0
  257. package/src/binder/binder.ts +40 -725
  258. package/src/binder/declarations.ts +203 -0
  259. package/src/binder/helpers.ts +47 -0
  260. package/src/binder/references.ts +410 -0
  261. package/src/binder/types.ts +134 -0
  262. package/src/cli/main.ts +43 -0
  263. package/src/codegen/generator/calls/access.ts +139 -0
  264. package/src/codegen/generator/calls/closures.ts +60 -0
  265. package/src/codegen/generator/calls/invocation.ts +282 -0
  266. package/src/codegen/generator/calls/literals.ts +77 -0
  267. package/src/codegen/generator/calls/super.ts +61 -0
  268. package/src/codegen/generator/calls.ts +30 -552
  269. package/src/codegen/generator/context.ts +2 -2
  270. package/src/codegen/generator/expressions/assignment.ts +226 -0
  271. package/src/codegen/generator/expressions/operators.ts +182 -0
  272. package/src/codegen/generator/expressions/primary.ts +304 -0
  273. package/src/codegen/generator/expressions.ts +22 -553
  274. package/src/codegen/generator/module.ts +14 -4
  275. package/src/codegen/generator/state.ts +8 -0
  276. package/src/codegen/generator/statements/control-flow.ts +225 -0
  277. package/src/codegen/generator/statements/dispatch.ts +122 -0
  278. package/src/codegen/generator/statements/loops.ts +173 -0
  279. package/src/codegen/generator/statements/variables.ts +152 -0
  280. package/src/codegen/generator/statements.ts +26 -612
  281. package/src/codegen/generator/tables.ts +7 -0
  282. package/src/codegen/values.ts +22 -57
  283. package/src/diagnostics/diagnostic.ts +1 -0
  284. package/src/diagnostics/source.ts +7 -12
  285. package/src/driver/compiler.ts +61 -18
  286. package/src/driver/index.ts +17 -2
  287. package/src/driver/paths.ts +54 -0
  288. package/src/driver/runtime-lib.ts +32 -0
  289. package/src/driver/toolchain-download.ts +108 -0
  290. package/src/driver/toolchain-provider.ts +91 -0
  291. package/src/driver/toolchain.ts +29 -11
  292. package/src/extensions/node/child_process/index.ts +4 -2
  293. package/src/extensions/node/events/index.ts +27 -0
  294. package/src/extensions/node/index.ts +6 -0
  295. package/src/extensions/node/querystring/index.ts +29 -0
  296. package/src/extensions/node/util/index.ts +48 -0
  297. package/src/extensions/registry.ts +6 -0
  298. package/src/index.ts +1 -0
  299. package/src/lexer/scanner/identifiers.ts +37 -0
  300. package/src/lexer/scanner/numbers.ts +84 -0
  301. package/src/lexer/scanner/punctuation.ts +132 -0
  302. package/src/lexer/scanner/regex.ts +79 -0
  303. package/src/lexer/scanner/strings.ts +128 -0
  304. package/src/lexer/scanner.ts +35 -401
  305. package/src/parser/declarations/classes.ts +215 -0
  306. package/src/parser/declarations/functions.ts +254 -0
  307. package/src/parser/declarations/type-members.ts +181 -0
  308. package/src/parser/declarations.ts +32 -609
  309. package/src/parser/helpers.ts +13 -6
  310. package/src/parser/literals.ts +10 -1
  311. package/scripts/build-runtime.mjs +0 -55
@@ -0,0 +1,58 @@
1
+ /* -- tiny string builder -------------------------------------------------- */
2
+
3
+ typedef struct {
4
+ char *data;
5
+ size_t length;
6
+ size_t capacity;
7
+ } xt_http_buffer;
8
+
9
+ static void xt_http_buffer_init(xt_http_buffer *buffer) {
10
+ buffer->capacity = 256;
11
+ buffer->length = 0;
12
+ buffer->data = (char *)malloc(buffer->capacity);
13
+ buffer->data[0] = '\0';
14
+ }
15
+
16
+ static void xt_http_buffer_append(xt_http_buffer *buffer, const char *data, size_t length) {
17
+ if (buffer->length + length + 1 > buffer->capacity) {
18
+ while (buffer->length + length + 1 > buffer->capacity) buffer->capacity *= 2;
19
+ buffer->data = (char *)realloc(buffer->data, buffer->capacity);
20
+ }
21
+ memcpy(buffer->data + buffer->length, data, length);
22
+ buffer->length += length;
23
+ buffer->data[buffer->length] = '\0';
24
+ }
25
+
26
+ static void xt_http_buffer_free(xt_http_buffer *buffer) { free(buffer->data); }
27
+
28
+ /* Parse `name: value` header lines into an object with lower-cased keys. */
29
+ static xt_value xt_http_parse_headers(const char *headers, size_t length) {
30
+ xt_value object = xt_object_new();
31
+ size_t i = 0;
32
+ while (i < length) {
33
+ size_t lineEnd = i;
34
+ while (lineEnd < length && headers[lineEnd] != '\n') lineEnd++;
35
+ size_t lineLength = lineEnd - i;
36
+ while (lineLength > 0 && (headers[i + lineLength - 1] == '\r' || headers[i + lineLength - 1] == ' ')) lineLength--;
37
+ const char *colon = memchr(headers + i, ':', lineLength);
38
+ if (colon) {
39
+ size_t nameLength = (size_t)(colon - (headers + i));
40
+ const char *value = colon + 1;
41
+ size_t valueLength = lineLength - nameLength - 1;
42
+ while (valueLength > 0 && *value == ' ') {
43
+ value++;
44
+ valueLength--;
45
+ }
46
+ char *name = (char *)malloc(nameLength + 1);
47
+ for (size_t j = 0; j < nameLength; j++) {
48
+ char c = headers[i + j];
49
+ name[j] = (c >= 'A' && c <= 'Z') ? (char)(c + 32) : c;
50
+ }
51
+ name[nameLength] = '\0';
52
+ xt_object_set(object, xt_string_from_cstr(name), xt_string_new(value, valueLength));
53
+ free(name);
54
+ }
55
+ i = lineEnd + 1;
56
+ }
57
+ return object;
58
+ }
@@ -46,508 +46,16 @@ unsigned char *xt_node_buffer_bytes(xt_value value, size_t *outLength);
46
46
  static xt_value xt_net_socket_proto(void);
47
47
  static xt_value xt_net_server_proto(void);
48
48
 
49
- /* -- platform helpers ----------------------------------------------------- */
50
-
51
- static void xt_net_set_nonblocking(int fd) {
52
- #if defined(_WIN32)
53
- u_long mode = 1;
54
- ioctlsocket(fd, FIONBIO, &mode);
55
- #else
56
- int flags = fcntl(fd, F_GETFL, 0);
57
- if (flags >= 0) fcntl(fd, F_SETFL, flags | O_NONBLOCK);
58
- #endif
59
- }
60
-
61
- static xt_value *xt_net_box(xt_value value) {
62
- xt_value *handle = (xt_value *)malloc(sizeof(xt_value));
63
- *handle = value;
64
- return handle;
65
- }
66
-
67
- static int xt_net_fd(xt_value object) {
68
- return (int)xt_to_number(xt_object_get_cstr(object, "__fd"));
69
- }
70
-
71
- static unsigned char *xt_net_bytes(xt_value data, size_t *outLength) {
72
- if (xt_node_is_buffer(data)) return xt_node_buffer_bytes(data, outLength);
73
- xt_value text = xt_to_string(data);
74
- const char *string = xt_string_data(text);
75
- size_t length = string ? (size_t)xt_string_length(xt_as_string(text)) : 0;
76
- unsigned char *bytes = (unsigned char *)malloc(length + 1);
77
- if (length > 0 && string) memcpy(bytes, string, length);
78
- bytes[length] = '\0';
79
- *outLength = length;
80
- return bytes;
81
- }
82
-
83
- static int xt_net_send_all(int fd, const unsigned char *data, size_t length) {
84
- size_t sent = 0;
85
- while (sent < length) {
86
- #if defined(_WIN32)
87
- int written = send(fd, (const char *)data + sent, (int)(length - sent), 0);
88
- #else
89
- ssize_t written = send(fd, data + sent, length - sent, 0);
90
- #endif
91
- if (written > 0) {
92
- sent += (size_t)written;
93
- continue;
94
- }
95
- if (written < 0 && xt_net_would_block()) {
96
- fd_set writeSet;
97
- FD_ZERO(&writeSet);
98
- FD_SET(fd, &writeSet);
99
- struct timeval timeout;
100
- timeout.tv_sec = 2;
101
- timeout.tv_usec = 0;
102
- if (select(fd + 1, NULL, &writeSet, NULL, &timeout) <= 0) return -1;
103
- continue;
104
- }
105
- return -1;
106
- }
107
- return 0;
108
- }
109
-
110
- /* -- socket read loop ----------------------------------------------------- */
111
-
112
- static void xt_net_socket_read(void *userdata, int events) {
113
- (void)events;
114
- xt_value socket = *(xt_value *)userdata;
115
- int fd = xt_net_fd(socket);
116
- if (fd < 0) return;
117
-
118
- unsigned char buffer[65536];
119
- #if defined(_WIN32)
120
- int count = recv(fd, (char *)buffer, (int)sizeof(buffer), 0);
121
- #else
122
- ssize_t count = recv(fd, buffer, sizeof(buffer), 0);
123
- #endif
124
- if (count > 0) {
125
- const char *encoding = xt_node_encoding(xt_object_get_cstr(socket, "__encoding"));
126
- xt_value chunk = xt_node_encode(buffer, (size_t)count, encoding);
127
- xt_node_emit1(socket, "data", chunk);
128
- return;
129
- }
130
- if (count == 0) {
131
- xt_loop_remove(fd);
132
- xt_close_socket(fd);
133
- xt_node_set(socket, "__fd", xt_number(-1));
134
- xt_node_set(socket, "__closed", xt_bool(1));
135
- xt_node_emit0(socket, "end");
136
- xt_node_emit0(socket, "close");
137
- return;
138
- }
139
- if (xt_net_would_block()) return;
140
- xt_loop_remove(fd);
141
- xt_close_socket(fd);
142
- xt_node_set(socket, "__fd", xt_number(-1));
143
- xt_node_set(socket, "__closed", xt_bool(1));
144
- xt_value error = xt_string_from_cstr("ECONNRESET");
145
- xt_node_emit1(socket, "error", error);
146
- xt_node_emit0(socket, "close");
147
- }
148
-
149
- static xt_value xt_net_socket_from_fd(int fd, const struct sockaddr *peer, xt_socklen_t peerLength) {
150
- xt_value socket = xt_object_new_with_proto(xt_net_socket_proto());
151
- xt_node_set(socket, "__fd", xt_number((double)fd));
152
- xt_node_set(socket, "__connected", xt_bool(1));
153
- xt_node_set(socket, "__readable", xt_array_new(0, NULL));
154
-
155
- char host[NI_MAXHOST];
156
- char service[NI_MAXSERV];
157
- if (peer && getnameinfo(peer, peerLength, host, sizeof(host), service, sizeof(service),
158
- NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
159
- xt_node_set(socket, "remoteAddress", xt_string_from_cstr(host));
160
- xt_node_set(socket, "remotePort", xt_number((double)atoi(service)));
161
- xt_node_set(socket, "remoteFamily", xt_string_from_cstr(strchr(host, ':') ? "IPv6" : "IPv4"));
162
- }
163
-
164
- xt_net_set_nonblocking(fd);
165
- xt_loop_add(fd, XT_IO_READ, xt_net_socket_read, xt_net_box(socket));
166
- return socket;
167
- }
168
-
169
- /* -- socket methods ------------------------------------------------------- */
170
-
171
- static xt_value xt_net_socket_write(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
172
- (void)env;
173
- int fd = xt_net_fd(thisValue);
174
- if (fd < 0) {
175
- xt_value callback = xt_arg(argc, argv, argc > 1 ? 2 : 1);
176
- xt_value error = xt_string_from_cstr("ERR_SOCKET_CLOSED");
177
- if (XT_IS_FUNCTION(callback)) xt_call_with_this(callback, xt_undefined(), 1, &error);
178
- return xt_bool(0);
179
- }
180
- size_t length = 0;
181
- unsigned char *bytes = xt_net_bytes(xt_arg(argc, argv, 0), &length);
182
- xt_net_send_all(fd, bytes, length);
183
- free(bytes);
184
- xt_value callback = XT_IS_FUNCTION(xt_arg(argc, argv, 1)) ? xt_arg(argc, argv, 1) : xt_arg(argc, argv, 2);
185
- if (XT_IS_FUNCTION(callback)) xt_call_with_this(callback, xt_undefined(), 0, NULL);
186
- return xt_bool(1);
187
- }
188
-
189
- static xt_value xt_net_socket_end(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
190
- (void)env;
191
- int fd = xt_net_fd(thisValue);
192
- if (fd < 0) return thisValue;
193
- if (argc > 0 && !xt_truthy(xt_is_nullish(argv[0]))) {
194
- xt_value writeFn = xt_object_get_cstr(thisValue, "write");
195
- if (XT_IS_FUNCTION(writeFn)) xt_call_with_this(writeFn, thisValue, 1, &argv[0]);
196
- }
197
- #if defined(_WIN32)
198
- shutdown(fd, SD_SEND);
199
- #else
200
- shutdown(fd, SHUT_WR);
201
- #endif
202
- return thisValue;
203
- }
204
-
205
- static xt_value xt_net_socket_destroy(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
206
- (void)env;
207
- (void)argc;
208
- (void)argv;
209
- int fd = xt_net_fd(thisValue);
210
- if (fd >= 0) {
211
- xt_loop_remove(fd);
212
- xt_close_socket(fd);
213
- }
214
- xt_node_set(thisValue, "__fd", xt_number(-1));
215
- if (!xt_truthy(xt_object_get_cstr(thisValue, "__closed"))) {
216
- xt_node_set(thisValue, "__closed", xt_bool(1));
217
- xt_node_emit0(thisValue, "close");
218
- }
219
- return thisValue;
220
- }
221
-
222
- static xt_value xt_net_socket_set_encoding(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
223
- (void)env;
224
- xt_node_set(thisValue, "__encoding", xt_arg(argc, argv, 0));
225
- return thisValue;
226
- }
227
-
228
- static xt_value xt_net_socket_pause(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
229
- (void)env;
230
- (void)argc;
231
- (void)argv;
232
- return thisValue;
233
- }
234
-
235
- static xt_value xt_net_socket_resume(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
236
- (void)env;
237
- (void)argc;
238
- (void)argv;
239
- return thisValue;
240
- }
241
-
242
- static xt_value xt_net_socket_noop(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
243
- (void)env;
244
- (void)argc;
245
- (void)argv;
246
- return thisValue;
247
- }
248
-
249
- static xt_value xt_net_socket_address(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
250
- (void)env;
251
- (void)argc;
252
- (void)argv;
253
- int fd = xt_net_fd(thisValue);
254
- if (fd < 0) return xt_null();
255
- struct sockaddr_storage storage;
256
- xt_socklen_t length = sizeof(storage);
257
- if (getsockname(fd, (struct sockaddr *)&storage, &length) != 0) return xt_null();
258
- char host[NI_MAXHOST];
259
- char service[NI_MAXSERV];
260
- if (getnameinfo((struct sockaddr *)&storage, length, host, sizeof(host), service, sizeof(service),
261
- NI_NUMERICHOST | NI_NUMERICSERV) != 0)
262
- return xt_null();
263
- xt_value object = xt_object_new();
264
- xt_node_set(object, "address", xt_string_from_cstr(host));
265
- xt_node_set(object, "port", xt_number((double)atoi(service)));
266
- xt_node_set(object, "family", xt_string_from_cstr(strchr(host, ':') ? "IPv6" : "IPv4"));
267
- return object;
268
- }
269
-
270
- /* -- server --------------------------------------------------------------- */
271
-
272
- static void xt_net_server_accept(void *userdata, int events) {
273
- (void)events;
274
- xt_value server = *(xt_value *)userdata;
275
- int listenFd = xt_net_fd(server);
276
- if (listenFd < 0) return;
277
- for (;;) {
278
- struct sockaddr_storage storage;
279
- xt_socklen_t length = sizeof(storage);
280
- int fd = accept(listenFd, (struct sockaddr *)&storage, &length);
281
- if (fd < 0) break;
282
- xt_value socket = xt_net_socket_from_fd(fd, (struct sockaddr *)&storage, length);
283
- xt_node_emit1(server, "connection", socket);
284
- }
285
- }
286
-
287
- /* Parse the many listen() signatures into a port + host. */
288
- static void xt_net_parse_listen(int32_t argc, xt_value *argv, int *port, const char **host, xt_value *callback) {
289
- *port = 0;
290
- *host = "0.0.0.0";
291
- *callback = XT_UNDEFINED;
292
- int index = 0;
293
- if (argc > 0 && XT_IS_OBJECT(argv[0])) {
294
- xt_value portValue = xt_object_get_cstr(argv[0], "port");
295
- if (!xt_truthy(xt_is_nullish(portValue))) *port = (int)xt_to_number(portValue);
296
- xt_value hostValue = xt_object_get_cstr(argv[0], "host");
297
- if (XT_IS_STRING(hostValue)) *host = xt_string_data(hostValue);
298
- index = 1;
299
- } else if (argc > 0 && XT_IS_NUMBER(argv[0])) {
300
- *port = (int)xt_to_number(argv[0]);
301
- index = 1;
302
- if (argc > 1 && XT_IS_STRING(argv[1])) {
303
- *host = xt_string_data(argv[1]);
304
- index = 2;
305
- }
306
- }
307
- for (int32_t i = index; i < argc; i++) {
308
- if (XT_IS_FUNCTION(argv[i])) *callback = argv[i];
309
- }
310
- }
311
-
312
- static xt_value xt_net_server_listen(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
313
- (void)env;
314
- int port = 0;
315
- const char *host = "0.0.0.0";
316
- xt_value callback = XT_UNDEFINED;
317
- xt_net_parse_listen(argc, argv, &port, &host, &callback);
318
-
319
- char service[16];
320
- snprintf(service, sizeof(service), "%d", port);
321
- struct addrinfo hints;
322
- memset(&hints, 0, sizeof(hints));
323
- hints.ai_family = AF_UNSPEC;
324
- hints.ai_socktype = SOCK_STREAM;
325
- hints.ai_flags = AI_PASSIVE;
326
- struct addrinfo *result = NULL;
327
- if (getaddrinfo(host, service, &hints, &result) != 0) {
328
- if (XT_IS_FUNCTION(callback)) {
329
- xt_value error = xt_string_from_cstr("EADDRNOTAVAIL");
330
- xt_call_with_this(callback, xt_undefined(), 1, &error);
331
- }
332
- return thisValue;
333
- }
334
-
335
- int listenFd = -1;
336
- for (struct addrinfo *info = result; info; info = info->ai_next) {
337
- int fd = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
338
- if (fd < 0) continue;
339
- int yes = 1;
340
- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&yes, sizeof(yes));
341
- if (bind(fd, info->ai_addr, info->ai_addrlen) == 0 && listen(fd, 511) == 0) {
342
- listenFd = fd;
343
- break;
344
- }
345
- xt_close_socket(fd);
346
- }
347
- freeaddrinfo(result);
348
-
349
- if (listenFd < 0) {
350
- if (XT_IS_FUNCTION(callback)) {
351
- xt_value error = xt_string_from_cstr("EADDRINUSE");
352
- xt_call_with_this(callback, xt_undefined(), 1, &error);
353
- }
354
- return thisValue;
355
- }
356
-
357
- xt_net_set_nonblocking(listenFd);
358
- xt_node_set(thisValue, "__fd", xt_number((double)listenFd));
359
- xt_node_set(thisValue, "__listening", xt_bool(1));
360
- xt_loop_add(listenFd, XT_IO_READ, xt_net_server_accept, xt_net_box(thisValue));
361
-
362
- xt_node_emit0(thisValue, "listening");
363
- if (XT_IS_FUNCTION(callback)) xt_call_with_this(callback, xt_undefined(), 0, NULL);
364
- return thisValue;
365
- }
366
-
367
- static xt_value xt_net_server_close(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
368
- (void)env;
369
- int fd = xt_net_fd(thisValue);
370
- if (fd >= 0) {
371
- xt_loop_remove(fd);
372
- xt_close_socket(fd);
373
- }
374
- xt_node_set(thisValue, "__fd", xt_number(-1));
375
- xt_node_set(thisValue, "__listening", xt_bool(0));
376
- xt_value callback = XT_IS_FUNCTION(xt_arg(argc, argv, 0)) ? xt_arg(argc, argv, 0) : XT_UNDEFINED;
377
- xt_node_emit0(thisValue, "close");
378
- if (XT_IS_FUNCTION(callback)) xt_call_with_this(callback, xt_undefined(), 0, NULL);
379
- return thisValue;
380
- }
381
-
382
- static xt_value xt_net_server_address(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
383
- return xt_net_socket_address(thisValue, env, argc, argv);
384
- }
385
-
386
- static xt_value xt_net_server_get_connections(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
387
- (void)thisValue;
388
- (void)env;
389
- (void)argc;
390
- (void)argv;
391
- xt_value callback = xt_arg(argc, argv, 0);
392
- if (XT_IS_FUNCTION(callback)) {
393
- xt_value count = xt_number(0);
394
- xt_value args[2];
395
- args[0] = xt_null();
396
- args[1] = count;
397
- xt_call_with_this(callback, xt_undefined(), 2, args);
398
- }
399
- return xt_undefined();
400
- }
401
-
402
- /* -- construction --------------------------------------------------------- */
403
-
404
- xt_value xt_net_socket_ctor(int32_t argc, xt_value *argv) {
405
- (void)argc;
406
- (void)argv;
407
- xt_value socket = xt_object_new_with_proto(xt_net_socket_proto());
408
- xt_node_set(socket, "__fd", xt_number(-1));
409
- xt_node_set(socket, "__readable", xt_array_new(0, NULL));
410
- return socket;
411
- }
412
-
413
- xt_value xt_net_server_ctor(int32_t argc, xt_value *argv) {
414
- xt_value server = xt_object_new_with_proto(xt_net_server_proto());
415
- xt_node_set(server, "__fd", xt_number(-1));
416
- for (int32_t i = 0; i < argc; i++) {
417
- if (XT_IS_FUNCTION(argv[i])) {
418
- xt_array_push(xt_node_listeners(server, "connection", 1), argv[i]);
419
- break;
420
- }
421
- }
422
- return server;
423
- }
424
-
425
- /* -- connect / static API ------------------------------------------------- */
426
-
427
- static int xt_net_connect_fd(const char *host, int port) {
428
- char service[16];
429
- snprintf(service, sizeof(service), "%d", port);
430
- struct addrinfo hints;
431
- memset(&hints, 0, sizeof(hints));
432
- hints.ai_family = AF_UNSPEC;
433
- hints.ai_socktype = SOCK_STREAM;
434
- struct addrinfo *result = NULL;
435
- if (getaddrinfo(host, service, &hints, &result) != 0) return -1;
436
- int fd = -1;
437
- for (struct addrinfo *info = result; info; info = info->ai_next) {
438
- int candidate = socket(info->ai_family, info->ai_socktype, info->ai_protocol);
439
- if (candidate < 0) continue;
440
- if (connect(candidate, info->ai_addr, info->ai_addrlen) == 0) {
441
- fd = candidate;
442
- break;
443
- }
444
- xt_close_socket(candidate);
445
- }
446
- freeaddrinfo(result);
447
- return fd;
448
- }
449
-
450
- xt_value xt_node_net_connect(int32_t argc, xt_value *argv) {
451
- int port = 0;
452
- const char *host = "127.0.0.1";
453
- xt_value callback = XT_UNDEFINED;
454
- int index = 0;
455
- if (argc > 0 && XT_IS_OBJECT(argv[0])) {
456
- xt_value portValue = xt_object_get_cstr(argv[0], "port");
457
- if (!xt_truthy(xt_is_nullish(portValue))) port = (int)xt_to_number(portValue);
458
- xt_value hostValue = xt_object_get_cstr(argv[0], "host");
459
- if (XT_IS_STRING(hostValue)) host = xt_string_data(hostValue);
460
- index = 1;
461
- } else if (argc > 0 && XT_IS_NUMBER(argv[0])) {
462
- port = (int)xt_to_number(argv[0]);
463
- index = 1;
464
- if (argc > 1 && XT_IS_STRING(argv[1])) {
465
- host = xt_string_data(argv[1]);
466
- index = 2;
467
- }
468
- }
469
- for (int32_t i = index; i < argc; i++) {
470
- if (XT_IS_FUNCTION(argv[i])) callback = argv[i];
471
- }
472
-
473
- int fd = xt_net_connect_fd(host, port);
474
- if (fd < 0) {
475
- xt_value socket = xt_net_socket_ctor(0, NULL);
476
- xt_value error = xt_string_from_cstr("ECONNREFUSED");
477
- if (XT_IS_FUNCTION(callback)) xt_call_with_this(callback, xt_undefined(), 1, &error);
478
- else xt_node_emit1(socket, "error", error);
479
- return socket;
480
- }
481
-
482
- struct sockaddr_storage storage;
483
- xt_socklen_t length = sizeof(storage);
484
- getpeername(fd, (struct sockaddr *)&storage, &length);
485
- xt_value socket = xt_net_socket_from_fd(fd, (struct sockaddr *)&storage, length);
486
- xt_node_set(socket, "__connecting", xt_bool(0));
487
- xt_node_emit0(socket, "connect");
488
- xt_node_emit0(socket, "ready");
489
- if (XT_IS_FUNCTION(callback)) xt_call_with_this(callback, xt_undefined(), 0, NULL);
490
- return socket;
491
- }
492
-
493
- xt_value xt_net_static(xt_value name, int32_t argc, xt_value *argv) {
494
- const char *fn = xt_string_data(name);
495
- if (!fn) return xt_undefined();
496
- if (strcmp(fn, "createServer") == 0) {
497
- xt_value server = xt_net_server_ctor(0, NULL);
498
- for (int32_t i = 0; i < argc; i++) {
499
- if (XT_IS_FUNCTION(argv[i])) {
500
- xt_array_push(xt_node_listeners(server, "connection", 1), argv[i]);
501
- break;
502
- }
503
- }
504
- return server;
505
- }
506
- if (strcmp(fn, "connect") == 0 || strcmp(fn, "createConnection") == 0) return xt_node_net_connect(argc, argv);
507
- if (strcmp(fn, "isIP") == 0 || strcmp(fn, "isIPv4") == 0 || strcmp(fn, "isIPv6") == 0) {
508
- const char *input = xt_string_data(xt_to_string(xt_arg(argc, argv, 0)));
509
- if (!input) return xt_number(0);
510
- if (strcmp(fn, "isIPv4") == 0) return xt_bool(strchr(input, '.') && !strchr(input, ':'));
511
- if (strcmp(fn, "isIPv6") == 0) return xt_bool(strchr(input, ':') != NULL);
512
- if (strchr(input, ':')) return xt_number(6);
513
- if (strchr(input, '.')) return xt_number(4);
514
- return xt_number(0);
515
- }
516
- return xt_undefined();
517
- }
518
-
519
- /* -- prototypes ----------------------------------------------------------- */
520
-
521
- static xt_value xt_net_socket_proto(void) {
522
- static xt_value proto = 0;
523
- if (proto) return proto;
524
- proto = xt_object_new();
525
- xt_node_install_emitter(proto);
526
- xt_node_define_method(proto, "write", (void *)xt_net_socket_write);
527
- xt_node_define_method(proto, "end", (void *)xt_net_socket_end);
528
- xt_node_define_method(proto, "destroy", (void *)xt_net_socket_destroy);
529
- xt_node_define_method(proto, "setEncoding", (void *)xt_net_socket_set_encoding);
530
- xt_node_define_method(proto, "pause", (void *)xt_net_socket_pause);
531
- xt_node_define_method(proto, "resume", (void *)xt_net_socket_resume);
532
- xt_node_define_method(proto, "setNoDelay", (void *)xt_net_socket_noop);
533
- xt_node_define_method(proto, "setKeepAlive", (void *)xt_net_socket_noop);
534
- xt_node_define_method(proto, "setTimeout", (void *)xt_net_socket_noop);
535
- xt_node_define_method(proto, "ref", (void *)xt_net_socket_noop);
536
- xt_node_define_method(proto, "unref", (void *)xt_net_socket_noop);
537
- xt_node_define_method(proto, "address", (void *)xt_net_socket_address);
538
- return proto;
539
- }
49
+ /*
50
+ * The implementation is grouped by functional area under `net/parts/` and
51
+ * `#include`d here as a single translation unit so the section helpers stay
52
+ * `static` while each file stays focused on one area.
53
+ */
540
54
 
541
- static xt_value xt_net_server_proto(void) {
542
- static xt_value proto = 0;
543
- if (proto) return proto;
544
- proto = xt_object_new();
545
- xt_node_install_emitter(proto);
546
- xt_node_define_method(proto, "listen", (void *)xt_net_server_listen);
547
- xt_node_define_method(proto, "close", (void *)xt_net_server_close);
548
- xt_node_define_method(proto, "address", (void *)xt_net_server_address);
549
- xt_node_define_method(proto, "getConnections", (void *)xt_net_server_get_connections);
550
- xt_node_define_method(proto, "ref", (void *)xt_net_socket_noop);
551
- xt_node_define_method(proto, "unref", (void *)xt_net_socket_noop);
552
- return proto;
553
- }
55
+ #include "parts/platform.inc"
56
+ #include "parts/read-loop.inc"
57
+ #include "parts/socket-methods.inc"
58
+ #include "parts/server.inc"
59
+ #include "parts/construction.inc"
60
+ #include "parts/static-api.inc"
61
+ #include "parts/prototypes.inc"
@@ -0,0 +1,22 @@
1
+ /* -- construction --------------------------------------------------------- */
2
+
3
+ xt_value xt_net_socket_ctor(int32_t argc, xt_value *argv) {
4
+ (void)argc;
5
+ (void)argv;
6
+ xt_value socket = xt_object_new_with_proto(xt_net_socket_proto());
7
+ xt_node_set(socket, "__fd", xt_number(-1));
8
+ xt_node_set(socket, "__readable", xt_array_new(0, NULL));
9
+ return socket;
10
+ }
11
+
12
+ xt_value xt_net_server_ctor(int32_t argc, xt_value *argv) {
13
+ xt_value server = xt_object_new_with_proto(xt_net_server_proto());
14
+ xt_node_set(server, "__fd", xt_number(-1));
15
+ for (int32_t i = 0; i < argc; i++) {
16
+ if (XT_IS_FUNCTION(argv[i])) {
17
+ xt_array_push(xt_node_listeners(server, "connection", 1), argv[i]);
18
+ break;
19
+ }
20
+ }
21
+ return server;
22
+ }
@@ -0,0 +1,60 @@
1
+ /* -- platform helpers ----------------------------------------------------- */
2
+
3
+ static void xt_net_set_nonblocking(int fd) {
4
+ #if defined(_WIN32)
5
+ u_long mode = 1;
6
+ ioctlsocket(fd, FIONBIO, &mode);
7
+ #else
8
+ int flags = fcntl(fd, F_GETFL, 0);
9
+ if (flags >= 0) fcntl(fd, F_SETFL, flags | O_NONBLOCK);
10
+ #endif
11
+ }
12
+
13
+ static xt_value *xt_net_box(xt_value value) {
14
+ xt_value *handle = (xt_value *)malloc(sizeof(xt_value));
15
+ *handle = value;
16
+ return handle;
17
+ }
18
+
19
+ static int xt_net_fd(xt_value object) {
20
+ return (int)xt_to_number(xt_object_get_cstr(object, "__fd"));
21
+ }
22
+
23
+ static unsigned char *xt_net_bytes(xt_value data, size_t *outLength) {
24
+ if (xt_node_is_buffer(data)) return xt_node_buffer_bytes(data, outLength);
25
+ xt_value text = xt_to_string(data);
26
+ const char *string = xt_string_data(text);
27
+ size_t length = string ? (size_t)xt_string_length(xt_as_string(text)) : 0;
28
+ unsigned char *bytes = (unsigned char *)malloc(length + 1);
29
+ if (length > 0 && string) memcpy(bytes, string, length);
30
+ bytes[length] = '\0';
31
+ *outLength = length;
32
+ return bytes;
33
+ }
34
+
35
+ static int xt_net_send_all(int fd, const unsigned char *data, size_t length) {
36
+ size_t sent = 0;
37
+ while (sent < length) {
38
+ #if defined(_WIN32)
39
+ int written = send(fd, (const char *)data + sent, (int)(length - sent), 0);
40
+ #else
41
+ ssize_t written = send(fd, data + sent, length - sent, 0);
42
+ #endif
43
+ if (written > 0) {
44
+ sent += (size_t)written;
45
+ continue;
46
+ }
47
+ if (written < 0 && xt_net_would_block()) {
48
+ fd_set writeSet;
49
+ FD_ZERO(&writeSet);
50
+ FD_SET(fd, &writeSet);
51
+ struct timeval timeout;
52
+ timeout.tv_sec = 2;
53
+ timeout.tv_usec = 0;
54
+ if (select(fd + 1, NULL, &writeSet, NULL, &timeout) <= 0) return -1;
55
+ continue;
56
+ }
57
+ return -1;
58
+ }
59
+ return 0;
60
+ }
@@ -0,0 +1,35 @@
1
+ /* -- prototypes ----------------------------------------------------------- */
2
+
3
+ static xt_value xt_net_socket_proto(void) {
4
+ static xt_value proto = 0;
5
+ if (proto) return proto;
6
+ proto = xt_object_new();
7
+ xt_node_install_emitter(proto);
8
+ xt_node_define_method(proto, "write", (void *)xt_net_socket_write);
9
+ xt_node_define_method(proto, "end", (void *)xt_net_socket_end);
10
+ xt_node_define_method(proto, "destroy", (void *)xt_net_socket_destroy);
11
+ xt_node_define_method(proto, "setEncoding", (void *)xt_net_socket_set_encoding);
12
+ xt_node_define_method(proto, "pause", (void *)xt_net_socket_pause);
13
+ xt_node_define_method(proto, "resume", (void *)xt_net_socket_resume);
14
+ xt_node_define_method(proto, "setNoDelay", (void *)xt_net_socket_noop);
15
+ xt_node_define_method(proto, "setKeepAlive", (void *)xt_net_socket_noop);
16
+ xt_node_define_method(proto, "setTimeout", (void *)xt_net_socket_noop);
17
+ xt_node_define_method(proto, "ref", (void *)xt_net_socket_noop);
18
+ xt_node_define_method(proto, "unref", (void *)xt_net_socket_noop);
19
+ xt_node_define_method(proto, "address", (void *)xt_net_socket_address);
20
+ return proto;
21
+ }
22
+
23
+ static xt_value xt_net_server_proto(void) {
24
+ static xt_value proto = 0;
25
+ if (proto) return proto;
26
+ proto = xt_object_new();
27
+ xt_node_install_emitter(proto);
28
+ xt_node_define_method(proto, "listen", (void *)xt_net_server_listen);
29
+ xt_node_define_method(proto, "close", (void *)xt_net_server_close);
30
+ xt_node_define_method(proto, "address", (void *)xt_net_server_address);
31
+ xt_node_define_method(proto, "getConnections", (void *)xt_net_server_get_connections);
32
+ xt_node_define_method(proto, "ref", (void *)xt_net_socket_noop);
33
+ xt_node_define_method(proto, "unref", (void *)xt_net_socket_noop);
34
+ return proto;
35
+ }