react-native-nitro-net 0.1.5 → 0.3.0

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 (71) hide show
  1. package/README.md +122 -12
  2. package/android/libs/arm64-v8a/librust_c_net.so +0 -0
  3. package/android/libs/armeabi-v7a/librust_c_net.so +0 -0
  4. package/android/libs/x86/librust_c_net.so +0 -0
  5. package/android/libs/x86_64/librust_c_net.so +0 -0
  6. package/cpp/HybridHttpParser.hpp +67 -0
  7. package/cpp/HybridNetDriver.hpp +74 -0
  8. package/cpp/HybridNetServerDriver.hpp +16 -0
  9. package/cpp/HybridNetSocketDriver.hpp +176 -0
  10. package/cpp/NetBindings.hpp +67 -1
  11. package/ios/Frameworks/RustCNet.xcframework/ios-arm64/RustCNet.framework/RustCNet +0 -0
  12. package/ios/Frameworks/RustCNet.xcframework/ios-arm64_x86_64-simulator/RustCNet.framework/RustCNet +0 -0
  13. package/lib/Net.nitro.d.ts +46 -1
  14. package/lib/Net.nitro.js +3 -1
  15. package/lib/http.d.ts +203 -0
  16. package/lib/http.js +1138 -0
  17. package/lib/https.d.ts +24 -0
  18. package/lib/https.js +144 -0
  19. package/lib/index.d.ts +50 -11
  20. package/lib/index.js +179 -31
  21. package/lib/tls.d.ts +145 -0
  22. package/lib/tls.js +521 -0
  23. package/nitrogen/generated/android/RustCNet+autolinking.cmake +2 -0
  24. package/nitrogen/generated/android/RustCNetOnLoad.cpp +2 -0
  25. package/nitrogen/generated/android/c++/JHybridHttpParserSpec.cpp +54 -0
  26. package/nitrogen/generated/android/c++/JHybridHttpParserSpec.hpp +65 -0
  27. package/nitrogen/generated/android/c++/JHybridNetDriverSpec.cpp +47 -1
  28. package/nitrogen/generated/android/c++/JHybridNetDriverSpec.hpp +9 -0
  29. package/nitrogen/generated/android/c++/JHybridNetServerDriverSpec.cpp +8 -0
  30. package/nitrogen/generated/android/c++/JHybridNetServerDriverSpec.hpp +2 -0
  31. package/nitrogen/generated/android/c++/JHybridNetSocketDriverSpec.cpp +79 -0
  32. package/nitrogen/generated/android/c++/JHybridNetSocketDriverSpec.hpp +17 -0
  33. package/nitrogen/generated/android/c++/JNetConfig.hpp +7 -3
  34. package/nitrogen/generated/android/kotlin/com/margelo/nitro/net/HybridHttpParserSpec.kt +58 -0
  35. package/nitrogen/generated/android/kotlin/com/margelo/nitro/net/HybridNetDriverSpec.kt +37 -0
  36. package/nitrogen/generated/android/kotlin/com/margelo/nitro/net/HybridNetServerDriverSpec.kt +8 -0
  37. package/nitrogen/generated/android/kotlin/com/margelo/nitro/net/HybridNetSocketDriverSpec.kt +68 -0
  38. package/nitrogen/generated/android/kotlin/com/margelo/nitro/net/NetConfig.kt +6 -3
  39. package/nitrogen/generated/ios/RustCNet-Swift-Cxx-Bridge.cpp +17 -0
  40. package/nitrogen/generated/ios/RustCNet-Swift-Cxx-Bridge.hpp +118 -41
  41. package/nitrogen/generated/ios/RustCNet-Swift-Cxx-Umbrella.hpp +5 -0
  42. package/nitrogen/generated/ios/c++/HybridHttpParserSpecSwift.cpp +11 -0
  43. package/nitrogen/generated/ios/c++/HybridHttpParserSpecSwift.hpp +79 -0
  44. package/nitrogen/generated/ios/c++/HybridNetDriverSpecSwift.hpp +69 -0
  45. package/nitrogen/generated/ios/c++/HybridNetServerDriverSpecSwift.hpp +12 -0
  46. package/nitrogen/generated/ios/c++/HybridNetSocketDriverSpecSwift.hpp +123 -0
  47. package/nitrogen/generated/ios/swift/HybridHttpParserSpec.swift +56 -0
  48. package/nitrogen/generated/ios/swift/HybridHttpParserSpec_cxx.swift +131 -0
  49. package/nitrogen/generated/ios/swift/HybridNetDriverSpec.swift +9 -0
  50. package/nitrogen/generated/ios/swift/HybridNetDriverSpec_cxx.swift +133 -0
  51. package/nitrogen/generated/ios/swift/HybridNetServerDriverSpec.swift +2 -0
  52. package/nitrogen/generated/ios/swift/HybridNetServerDriverSpec_cxx.swift +36 -0
  53. package/nitrogen/generated/ios/swift/HybridNetSocketDriverSpec.swift +17 -0
  54. package/nitrogen/generated/ios/swift/HybridNetSocketDriverSpec_cxx.swift +314 -0
  55. package/nitrogen/generated/ios/swift/NetConfig.swift +19 -1
  56. package/nitrogen/generated/shared/c++/HybridHttpParserSpec.cpp +21 -0
  57. package/nitrogen/generated/shared/c++/HybridHttpParserSpec.hpp +63 -0
  58. package/nitrogen/generated/shared/c++/HybridNetDriverSpec.cpp +9 -0
  59. package/nitrogen/generated/shared/c++/HybridNetDriverSpec.hpp +13 -0
  60. package/nitrogen/generated/shared/c++/HybridNetServerDriverSpec.cpp +2 -0
  61. package/nitrogen/generated/shared/c++/HybridNetServerDriverSpec.hpp +2 -0
  62. package/nitrogen/generated/shared/c++/HybridNetSocketDriverSpec.cpp +17 -0
  63. package/nitrogen/generated/shared/c++/HybridNetSocketDriverSpec.hpp +18 -0
  64. package/nitrogen/generated/shared/c++/NetConfig.hpp +6 -2
  65. package/package.json +7 -5
  66. package/react-native-nitro-net.podspec +1 -3
  67. package/src/Net.nitro.ts +44 -1
  68. package/src/http.ts +1304 -0
  69. package/src/https.ts +127 -0
  70. package/src/index.ts +167 -27
  71. package/src/tls.ts +608 -0
package/src/https.ts ADDED
@@ -0,0 +1,127 @@
1
+ import * as http from './http'
2
+ import * as tls from './tls'
3
+ import { Driver } from './Driver'
4
+ import { Buffer } from 'react-native-nitro-buffer'
5
+ import { IncomingMessage } from './http'
6
+
7
+ // ========== Server ==========
8
+
9
+ export class Server extends tls.Server {
10
+ private _httpConnections = new Set<any>();
11
+ public maxHeaderSize: number = 16384;
12
+ public maxRequestsPerSocket: number = 0;
13
+ public headersTimeout: number = 60000;
14
+ public requestTimeout: number = 300000;
15
+ public keepAliveTimeout: number = 5000;
16
+
17
+ constructor(options?: any, requestListener?: (req: http.IncomingMessage, res: http.ServerResponse) => void) {
18
+ if (typeof options === 'function') {
19
+ requestListener = options;
20
+ options = {};
21
+ }
22
+ super(options);
23
+
24
+ if (requestListener) {
25
+ this.on('request', requestListener);
26
+ }
27
+
28
+ // Initialize HTTP connection setup for secure connections
29
+ this.on('secureConnection', (socket: any) => {
30
+ // @ts-ignore - access internal http logic
31
+ (http.Server.prototype as any)._setupHttpConnection.call(this, socket);
32
+ });
33
+ }
34
+
35
+ public setTimeout(ms: number, callback?: () => void): this {
36
+ // @ts-ignore - access netServer via super's internal or cast
37
+ (this as any)._netServer.setTimeout(ms, callback);
38
+ return this;
39
+ }
40
+ }
41
+
42
+ export function createServer(options?: any, requestListener?: (req: http.IncomingMessage, res: http.ServerResponse) => void): Server {
43
+ return new Server(options, requestListener);
44
+ }
45
+
46
+ // ========== ClientRequest ==========
47
+
48
+ export class ClientRequest extends http.ClientRequest {
49
+ constructor(options: any, callback?: (res: http.IncomingMessage) => void) {
50
+ if (typeof options === 'string') {
51
+ options = new URL(options);
52
+ }
53
+ if (options instanceof URL) {
54
+ options = {
55
+ protocol: options.protocol,
56
+ hostname: options.hostname,
57
+ path: options.pathname + options.search,
58
+ port: options.port ? parseInt(options.port) : 443
59
+ };
60
+ }
61
+ options.protocol = 'https:';
62
+ super(options, callback);
63
+ }
64
+ }
65
+
66
+ export function request(
67
+ urlOrOptions: string | URL | http.RequestOptions,
68
+ optionsOrCallback?: http.RequestOptions | ((res: http.IncomingMessage) => void),
69
+ callback?: (res: http.IncomingMessage) => void
70
+ ): ClientRequest {
71
+ let opts: http.RequestOptions = {};
72
+ let cb: ((res: http.IncomingMessage) => void) | undefined = callback;
73
+
74
+ if (typeof urlOrOptions === 'string') {
75
+ const url = new URL(urlOrOptions);
76
+ opts = {
77
+ protocol: url.protocol,
78
+ hostname: url.hostname,
79
+ path: url.pathname + url.search,
80
+ port: url.port ? parseInt(url.port) : 443
81
+ };
82
+ } else if (urlOrOptions instanceof URL) {
83
+ opts = {
84
+ protocol: urlOrOptions.protocol,
85
+ hostname: urlOrOptions.hostname,
86
+ path: urlOrOptions.pathname + urlOrOptions.search,
87
+ port: urlOrOptions.port ? parseInt(urlOrOptions.port) : 443
88
+ };
89
+ } else {
90
+ opts = { ...urlOrOptions };
91
+ }
92
+
93
+ if (typeof optionsOrCallback === 'function') {
94
+ cb = optionsOrCallback;
95
+ } else if (optionsOrCallback) {
96
+ opts = { ...opts, ...optionsOrCallback };
97
+ }
98
+
99
+ opts.protocol = 'https:';
100
+ return new ClientRequest(opts, cb);
101
+ }
102
+
103
+ export function get(
104
+ urlOrOptions: string | URL | http.RequestOptions,
105
+ optionsOrCallback?: http.RequestOptions | ((res: http.IncomingMessage) => void),
106
+ callback?: (res: http.IncomingMessage) => void
107
+ ): ClientRequest {
108
+ const req = request(urlOrOptions, optionsOrCallback, callback);
109
+ req.end();
110
+ return req;
111
+ }
112
+
113
+ // ========== Agent ==========
114
+
115
+ export class Agent extends http.Agent {
116
+ constructor(options?: any) {
117
+ super(options);
118
+ }
119
+ }
120
+
121
+ export const globalAgent = new Agent({
122
+ keepAlive: true,
123
+ scheduling: 'lifo',
124
+ timeout: 5000,
125
+ });
126
+
127
+ export { IncomingMessage };
package/src/index.ts CHANGED
@@ -33,16 +33,21 @@ let _autoSelectFamilyDefault = 4; // Node default is usually 4/6 independent, bu
33
33
  let _isVerbose = false;
34
34
  let _isInitialized = false;
35
35
 
36
- function debugLog(message: string) {
37
- if (_isVerbose) {
38
- console.log(`[NET DEBUG] ${message}`);
39
- }
36
+ function isVerbose(): boolean {
37
+ return _isVerbose;
40
38
  }
41
39
 
42
40
  function setVerbose(enabled: boolean): void {
43
41
  _isVerbose = enabled;
44
42
  }
45
43
 
44
+ function debugLog(message: string) {
45
+ if (_isVerbose) {
46
+ const timestamp = new Date().toISOString().split('T')[1].split('Z')[0];
47
+ console.log(`[NET DEBUG ${timestamp}] ${message}`);
48
+ }
49
+ }
50
+
46
51
  function getDefaultAutoSelectFamily(): number {
47
52
  return _autoSelectFamilyDefault;
48
53
  }
@@ -79,6 +84,9 @@ function ensureInitialized(): void {
79
84
  */
80
85
  function initWithConfig(config: NetConfig): void {
81
86
  _isInitialized = true;
87
+ if (config.debug !== undefined) {
88
+ setVerbose(config.debug);
89
+ }
82
90
  Driver.initWithConfig(config);
83
91
  }
84
92
 
@@ -89,17 +97,69 @@ function initWithConfig(config: NetConfig): void {
89
97
  // SocketAddress
90
98
  // -----------------------------------------------------------------------------
91
99
 
100
+ export interface SocketAddressOptions {
101
+ address?: string;
102
+ family?: 'ipv4' | 'ipv6';
103
+ port?: number;
104
+ flowlabel?: number;
105
+ }
106
+
92
107
  export class SocketAddress {
93
108
  readonly address: string;
94
109
  readonly family: 'ipv4' | 'ipv6';
95
110
  readonly port: number;
96
111
  readonly flowlabel: number;
97
112
 
98
- constructor(options: { address: string, family?: 'ipv4' | 'ipv6', port: number, flowlabel?: number }) {
99
- this.address = options.address;
100
- this.family = options.family || (isIPv6(options.address) ? 'ipv6' : 'ipv4');
101
- this.port = options.port;
102
- this.flowlabel = options.flowlabel || 0;
113
+ constructor(options: SocketAddressOptions = {}) {
114
+ this.address = options.address ?? (options.family === 'ipv6' ? '::' : '127.0.0.1');
115
+ this.family = options.family || (isIPv6(this.address) ? 'ipv6' : 'ipv4');
116
+ this.port = options.port ?? 0;
117
+ this.flowlabel = options.flowlabel ?? 0;
118
+ }
119
+
120
+ /**
121
+ * Attempts to parse a string containing a socket address.
122
+ * Returns a SocketAddress if successful, or undefined if not.
123
+ *
124
+ * Supported formats:
125
+ * - `ip:port` (e.g., `127.0.0.1:8080`, `[::1]:8080`)
126
+ * - `ip` only (port defaults to 0)
127
+ */
128
+ static parse(input: string): SocketAddress | undefined {
129
+ if (!input || typeof input !== 'string') return undefined;
130
+ let address: string;
131
+ let port = 0;
132
+
133
+ // Handle IPv6 bracket notation: [::1]:port
134
+ const ipv6Match = input.match(/^\[([^\]]+)\]:?(\d*)$/);
135
+ if (ipv6Match) {
136
+ address = ipv6Match[1];
137
+ port = ipv6Match[2] ? parseInt(ipv6Match[2], 10) : 0;
138
+ if (!isIPv6(address)) return undefined;
139
+ return new SocketAddress({ address, port, family: 'ipv6' });
140
+ }
141
+
142
+ // Handle IPv4 or IPv6 without brackets
143
+ const lastColon = input.lastIndexOf(':');
144
+ if (lastColon === -1) {
145
+ // No port, just IP
146
+ address = input;
147
+ } else {
148
+ // Determine if the colon is a port separator or part of IPv6
149
+ const potentialPort = input.slice(lastColon + 1);
150
+ const potentialAddr = input.slice(0, lastColon);
151
+ if (/^\d+$/.test(potentialPort) && (isIPv4(potentialAddr) || isIPv6(potentialAddr))) {
152
+ address = potentialAddr;
153
+ port = parseInt(potentialPort, 10);
154
+ } else {
155
+ // It's an IPv6 address without port
156
+ address = input;
157
+ }
158
+ }
159
+
160
+ const family = isIPv6(address) ? 'ipv6' : (isIPv4(address) ? 'ipv4' : undefined);
161
+ if (!family) return undefined;
162
+ return new SocketAddress({ address, port, family });
103
163
  }
104
164
  }
105
165
 
@@ -107,9 +167,31 @@ export class SocketAddress {
107
167
  // BlockList
108
168
  // -----------------------------------------------------------------------------
109
169
 
170
+ export interface BlockListRule {
171
+ type: 'address' | 'range' | 'subnet';
172
+ address?: string;
173
+ start?: string;
174
+ end?: string;
175
+ prefix?: number;
176
+ family: 'ipv4' | 'ipv6';
177
+ }
178
+
110
179
  export class BlockList {
111
180
  private _rules: Array<{ type: 'address' | 'range' | 'subnet', data: any }> = [];
112
181
 
182
+ /** Returns an array of rules added to the blocklist. */
183
+ get rules(): BlockListRule[] {
184
+ return this._rules.map(r => {
185
+ if (r.type === 'address') {
186
+ return { type: 'address' as const, address: r.data.address, family: r.data.family };
187
+ } else if (r.type === 'range') {
188
+ return { type: 'range' as const, start: r.data.start, end: r.data.end, family: r.data.family };
189
+ } else {
190
+ return { type: 'subnet' as const, address: r.data.net, prefix: r.data.prefix, family: r.data.family };
191
+ }
192
+ });
193
+ }
194
+
113
195
  addAddress(address: string, family?: 'ipv4' | 'ipv6'): void {
114
196
  this._rules.push({ type: 'address', data: { address, family: family || (isIPv6(address) ? 'ipv6' : 'ipv4') } });
115
197
  }
@@ -143,6 +225,37 @@ export class BlockList {
143
225
  }
144
226
  return false;
145
227
  }
228
+
229
+ /**
230
+ * Serializes the BlockList to a JSON-compatible format.
231
+ */
232
+ toJSON(): BlockListRule[] {
233
+ return this.rules;
234
+ }
235
+
236
+ /**
237
+ * Creates a BlockList from a JSON array of rules.
238
+ */
239
+ static fromJSON(json: BlockListRule[]): BlockList {
240
+ const list = new BlockList();
241
+ for (const rule of json) {
242
+ if (rule.type === 'address' && rule.address) {
243
+ list.addAddress(rule.address, rule.family);
244
+ } else if (rule.type === 'range' && rule.start && rule.end) {
245
+ list.addRange(rule.start, rule.end, rule.family);
246
+ } else if (rule.type === 'subnet' && rule.address && rule.prefix !== undefined) {
247
+ list.addSubnet(rule.address, rule.prefix, rule.family);
248
+ }
249
+ }
250
+ return list;
251
+ }
252
+
253
+ /**
254
+ * Checks if a given value is a BlockList instance.
255
+ */
256
+ static isBlockList(value: unknown): value is BlockList {
257
+ return value instanceof BlockList;
258
+ }
146
259
  }
147
260
 
148
261
  function ipv4ToLong(ip: string): number {
@@ -165,10 +278,10 @@ export interface SocketOptions extends DuplexOptions {
165
278
  }
166
279
 
167
280
  export class Socket extends Duplex {
168
- private _driver: NetSocketDriver | undefined;
281
+ protected _driver: NetSocketDriver | undefined;
169
282
  public connecting: boolean = false; // Changed from private _connecting
170
- private _connected: boolean = false;
171
- private _hadError: boolean = false; // Added
283
+ protected _connected: boolean = false;
284
+ protected _hadError: boolean = false; // Added
172
285
  public remoteAddress?: string;
173
286
  public remotePort?: number;
174
287
  public remoteFamily?: string;
@@ -178,6 +291,7 @@ export class Socket extends Duplex {
178
291
  public bytesWritten: number = 0;
179
292
  public autoSelectFamilyAttemptedAddresses: string[] = [];
180
293
  private _autoSelectFamily: boolean = false;
294
+ private _timeout: number = 0;
181
295
 
182
296
  get localFamily(): string {
183
297
  return this.localAddress && this.localAddress.includes(':') ? 'IPv6' : 'IPv4';
@@ -203,7 +317,9 @@ export class Socket extends Duplex {
203
317
  super({
204
318
  allowHalfOpen: options?.allowHalfOpen ?? false,
205
319
  readable: options?.readable ?? true,
206
- writable: options?.writable ?? true
320
+ writable: options?.writable ?? true,
321
+ // @ts-ignore
322
+ autoDestroy: false
207
323
  });
208
324
 
209
325
  if (options?.socketDriver) {
@@ -211,6 +327,8 @@ export class Socket extends Duplex {
211
327
  this._driver = options.socketDriver;
212
328
  this._connected = true;
213
329
  this._setupEvents();
330
+ // Enable noDelay by default
331
+ this._driver.setNoDelay(true);
214
332
  // Resume the socket since it starts paused on server-accept
215
333
  this.resume();
216
334
  // Emit connect for server-side socket? No, it's already connected.
@@ -219,8 +337,10 @@ export class Socket extends Duplex {
219
337
  ensureInitialized();
220
338
  this._driver = Driver.createSocket();
221
339
  this._setupEvents();
222
- // Also resume client socket initially so it's ready to receive
223
- this.resume();
340
+ // Enable noDelay by default to match Node.js and reduce latency for small writes
341
+ this._driver.setNoDelay(true);
342
+ // Do NOT resume here - socket is not connected yet!
343
+ // resume() will be called after 'connect' event in _connect()
224
344
  }
225
345
 
226
346
  this.on('finish', () => {
@@ -245,13 +365,14 @@ export class Socket extends Duplex {
245
365
  if (!this._driver) return;
246
366
  const id = (this._driver as any).id ?? (this._driver as any)._id;
247
367
  this._driver.onEvent = (eventType: number, data: ArrayBuffer) => {
368
+ this.emit('event', eventType, data);
248
369
  if (eventType === 3) { // ERROR
249
370
  const msg = new TextDecoder().decode(data);
250
371
  debugLog(`Socket (id: ${id}) NATIVE ERROR: ${msg}`);
251
372
  }
252
- if (eventType === 9) { // DEBUG
253
- const msg = new TextDecoder().decode(data);
254
- debugLog(`Socket (id: ${id}) NATIVE DEBUG: ${msg}`);
373
+ if (eventType === 9) { // SESSION/DEBUG
374
+ debugLog(`Socket (id: ${id}) NATIVE SESSION EVENT RECEIVED`);
375
+ this.emit('session', data);
255
376
  return;
256
377
  }
257
378
  debugLog(`Socket (id: ${id}, localPort: ${this.localPort}) Event TYPE: ${eventType}, data len: ${data?.byteLength}`);
@@ -260,6 +381,8 @@ export class Socket extends Duplex {
260
381
  this.connecting = false;
261
382
  this._connected = true;
262
383
  this._updateAddresses();
384
+ // Now that we're connected, start receiving data
385
+ this.resume();
263
386
  this.emit('connect');
264
387
  this.emit('ready');
265
388
  break;
@@ -408,6 +531,7 @@ export class Socket extends Duplex {
408
531
  this._autoSelectFamily = true;
409
532
  }
410
533
 
534
+ debugLog(`Socket.connect: target=${host}:${port}, autoSelectFamily=${this._autoSelectFamily}`);
411
535
  return this._connect(port, host, connectionListener, options.signal);
412
536
  }
413
537
 
@@ -430,6 +554,7 @@ export class Socket extends Duplex {
430
554
  this.once('close', () => signal.removeEventListener('abort', abortHandler));
431
555
  }
432
556
 
557
+ debugLog(`Socket._connect: Calling driver.connect(${host}, ${port})`);
433
558
  this._driver?.connect(host, port);
434
559
  return this;
435
560
  }
@@ -510,6 +635,7 @@ export class Socket extends Duplex {
510
635
 
511
636
  // Standard net.Socket methods
512
637
  setTimeout(msecs: number, callback?: () => void): this {
638
+ this._timeout = msecs;
513
639
  if (this._driver) {
514
640
  this._driver.setTimeout(msecs);
515
641
  }
@@ -533,12 +659,13 @@ export class Socket extends Duplex {
533
659
  * Resume reading after a call to pause().
534
660
  */
535
661
  resume(): this {
536
- const id = (this._driver as any)?.id;
537
- debugLog(`Socket.resume() called, id: ${id}`);
662
+ const driver = this._driver as any;
663
+ const id = driver?.id;
664
+ debugLog(`Socket.resume() called, id: ${id === undefined ? 'none' : id}, destroyed: ${this.destroyed}`);
538
665
  super.resume();
539
- if (this._driver) {
666
+ if (driver) {
540
667
  debugLog(`Socket.resume() calling driver.resume(), id: ${id}`);
541
- this._driver.resume();
668
+ driver.resume();
542
669
  }
543
670
  return this;
544
671
  }
@@ -568,8 +695,8 @@ export class Socket extends Duplex {
568
695
  return this;
569
696
  }
570
697
 
571
- get timeout(): number | undefined {
572
- return undefined; // Not tracked strictly as a property yet
698
+ get timeout(): number {
699
+ return this._timeout;
573
700
  }
574
701
 
575
702
  get bufferSize(): number {
@@ -705,8 +832,8 @@ export class Server extends EventEmitter {
705
832
  this.emit('error', new Error(data ? Buffer.from(data).toString() : 'Unknown server error'));
706
833
  break;
707
834
  case NetServerEvent.DEBUG: {
708
- const msg = data ? Buffer.from(data).toString() : 'Unknown debug message';
709
- debugLog(`Server NATIVE DEBUG: ${msg}`);
835
+ debugLog(`Server NATIVE SESSION/DEBUG EVENT RECEIVED`);
836
+ this.emit('session', data);
710
837
  break;
711
838
  }
712
839
  case NetServerEvent.CLOSE:
@@ -726,7 +853,6 @@ export class Server extends EventEmitter {
726
853
  this.close(() => resolve());
727
854
  });
728
855
  }
729
-
730
856
  listen(port?: any, host?: any, backlog?: any, callback?: any): this {
731
857
  let _port = 0;
732
858
  let _host: string | undefined;
@@ -797,6 +923,13 @@ export class Server extends EventEmitter {
797
923
  }
798
924
 
799
925
  close(callback?: (err?: Error) => void): this {
926
+ // Destroy all active connections first
927
+ for (const socket of this._sockets) {
928
+ socket.destroy();
929
+ }
930
+ this._sockets.clear();
931
+ this._connections = 0;
932
+
800
933
  this._driver.close();
801
934
  if (callback) this.once('close', callback);
802
935
  return this;
@@ -840,12 +973,17 @@ export function createServer(options?: any, connectionListener?: (socket: Socket
840
973
  return new Server(options, connectionListener);
841
974
  }
842
975
 
976
+ export * as tls from './tls'
977
+ export * as http from './http'
978
+ export * as https from './https'
979
+
843
980
  export {
844
981
  isIP,
845
982
  isIPv4,
846
983
  isIPv6,
847
984
  getDefaultAutoSelectFamily,
848
985
  setDefaultAutoSelectFamily,
986
+ isVerbose,
849
987
  setVerbose,
850
988
  initWithConfig,
851
989
  };
@@ -867,4 +1005,6 @@ export default {
867
1005
  setDefaultAutoSelectFamily,
868
1006
  setVerbose,
869
1007
  initWithConfig,
1008
+ http: require('./http'),
1009
+ https: require('./https'),
870
1010
  };