@gjsify/net 0.0.4 → 0.1.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.
package/README.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # @gjsify/net
2
2
 
3
- Node.js net module for Gjs
3
+ GJS implementation of the Node.js `net` module using Gio.SocketClient and Gio.SocketService. Provides Socket and Server.
4
+
5
+ Part of the [gjsify](https://github.com/gjsify/gjsify) project — Node.js and Web APIs for GJS (GNOME JavaScript).
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @gjsify/net
11
+ # or
12
+ yarn add @gjsify/net
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ```typescript
18
+ import { createServer, createConnection } from '@gjsify/net';
19
+
20
+ const server = createServer((socket) => {
21
+ socket.on('data', (data) => console.log(data.toString()));
22
+ socket.end('goodbye');
23
+ });
24
+ server.listen(8080);
25
+ ```
26
+
4
27
  ## Inspirations and credits
28
+
5
29
  - https://nodejs.org/api/net.html
30
+
31
+ ## License
32
+
33
+ MIT
package/lib/esm/index.js CHANGED
@@ -1,8 +1,13 @@
1
1
  import Gio from "@girs/gio-2.0";
2
+ import { Socket, SocketConnectOptions } from "./socket.js";
3
+ import { Server, ListenOptions } from "./server.js";
4
+ import { Socket as Socket2 } from "./socket.js";
5
+ import { Server as Server2 } from "./server.js";
2
6
  function isIP(input) {
3
- const addr = Gio.InetAddress.new_from_string(input);
4
- if (!addr)
5
- return 0;
7
+ if (typeof input !== "string") return 0;
8
+ const stripped = input.includes("%") ? input.split("%")[0] : input;
9
+ const addr = Gio.InetAddress.new_from_string(stripped);
10
+ if (!addr) return 0;
6
11
  const family = addr.get_family();
7
12
  switch (family) {
8
13
  case Gio.SocketFamily.INVALID:
@@ -19,7 +24,33 @@ function isIPv4(input) {
19
24
  function isIPv6(input) {
20
25
  return isIP(input) === 6;
21
26
  }
27
+ function createConnection(options, host, connectionListener) {
28
+ const socket = new Socket2();
29
+ return socket.connect(options, host, connectionListener);
30
+ }
31
+ const connect = createConnection;
32
+ function createServer(optionsOrListener, connectionListener) {
33
+ return new Server2(optionsOrListener, connectionListener);
34
+ }
35
+ var index_default = {
36
+ Socket: Socket2,
37
+ Server: Server2,
38
+ isIP,
39
+ isIPv4,
40
+ isIPv6,
41
+ createConnection,
42
+ connect,
43
+ createServer
44
+ };
22
45
  export {
46
+ ListenOptions,
47
+ Server,
48
+ Socket,
49
+ SocketConnectOptions,
50
+ connect,
51
+ createConnection,
52
+ createServer,
53
+ index_default as default,
23
54
  isIP,
24
55
  isIPv4,
25
56
  isIPv6
@@ -0,0 +1,133 @@
1
+ import Gio from "@girs/gio-2.0";
2
+ import { EventEmitter } from "node:events";
3
+ import { createNodeError, deferEmit, ensureMainLoop } from "@gjsify/utils";
4
+ import { Socket } from "./socket.js";
5
+ const _activeServers = /* @__PURE__ */ new Set();
6
+ class Server extends EventEmitter {
7
+ listening = false;
8
+ maxConnections;
9
+ allowHalfOpen;
10
+ _service = null;
11
+ _connections = /* @__PURE__ */ new Set();
12
+ _address = null;
13
+ constructor(optionsOrListener, connectionListener) {
14
+ super();
15
+ if (typeof optionsOrListener === "function") {
16
+ connectionListener = optionsOrListener;
17
+ this.allowHalfOpen = false;
18
+ } else {
19
+ this.allowHalfOpen = optionsOrListener?.allowHalfOpen ?? false;
20
+ }
21
+ if (connectionListener) {
22
+ this.on("connection", connectionListener);
23
+ }
24
+ }
25
+ listen(...args) {
26
+ let port = 0;
27
+ let host = "0.0.0.0";
28
+ let backlog = 511;
29
+ let callback;
30
+ if (typeof args[0] === "object" && args[0] !== null && !Array.isArray(args[0])) {
31
+ const opts = args[0];
32
+ port = opts.port ?? 0;
33
+ host = opts.host ?? "0.0.0.0";
34
+ backlog = opts.backlog ?? 511;
35
+ callback = args[1];
36
+ } else {
37
+ if (typeof args[0] === "number") port = args[0];
38
+ for (let i = 1; i < args.length; i++) {
39
+ if (typeof args[i] === "string") host = args[i];
40
+ else if (typeof args[i] === "number") backlog = args[i];
41
+ else if (typeof args[i] === "function") callback = args[i];
42
+ }
43
+ }
44
+ if (callback) {
45
+ this.once("listening", callback);
46
+ }
47
+ try {
48
+ this._service = new Gio.SocketService();
49
+ this._service.set_backlog(backlog);
50
+ let actualPort;
51
+ if (port === 0) {
52
+ actualPort = this._service.add_any_inet_port(null);
53
+ } else {
54
+ this._service.add_inet_port(port, null);
55
+ actualPort = port;
56
+ }
57
+ this._service.connect("incoming", (_service, connection) => {
58
+ this._handleConnection(connection);
59
+ return true;
60
+ });
61
+ this._service.start();
62
+ ensureMainLoop();
63
+ this.listening = true;
64
+ _activeServers.add(this);
65
+ const family = host.includes(":") ? "IPv6" : "IPv4";
66
+ this._address = { port: actualPort, family, address: host };
67
+ deferEmit(this, "listening");
68
+ } catch (err) {
69
+ const nodeErr = createNodeError(err, "listen", { address: host, port });
70
+ deferEmit(this, "error", nodeErr);
71
+ }
72
+ return this;
73
+ }
74
+ _handleConnection(connection) {
75
+ if (this.maxConnections && this._connections.size >= this.maxConnections) {
76
+ try {
77
+ connection.close(null);
78
+ } catch {
79
+ }
80
+ return;
81
+ }
82
+ const socket = new Socket({ allowHalfOpen: this.allowHalfOpen });
83
+ socket._setConnection(connection);
84
+ socket._setupConnection({});
85
+ this._connections.add(socket);
86
+ socket.on("close", () => {
87
+ this._connections.delete(socket);
88
+ });
89
+ this.emit("connection", socket);
90
+ }
91
+ /** Get the address the server is listening on. */
92
+ address() {
93
+ return this._address;
94
+ }
95
+ /** Close the server, stop accepting new connections. */
96
+ close(callback) {
97
+ if (callback) {
98
+ this.once("close", callback);
99
+ }
100
+ if (!this._service || !this.listening) {
101
+ setTimeout(() => {
102
+ const err = new Error("Server is not running");
103
+ err.code = "ERR_SERVER_NOT_RUNNING";
104
+ this.emit("error", err);
105
+ }, 0);
106
+ return this;
107
+ }
108
+ this._service.stop();
109
+ this._service.close();
110
+ this._service = null;
111
+ this.listening = false;
112
+ _activeServers.delete(this);
113
+ for (const socket of this._connections) {
114
+ socket.destroy();
115
+ }
116
+ this._connections.clear();
117
+ deferEmit(this, "close");
118
+ return this;
119
+ }
120
+ /** Get the number of concurrent connections. */
121
+ getConnections(callback) {
122
+ callback(null, this._connections.size);
123
+ }
124
+ ref() {
125
+ return this;
126
+ }
127
+ unref() {
128
+ return this;
129
+ }
130
+ }
131
+ export {
132
+ Server
133
+ };
@@ -0,0 +1,332 @@
1
+ import Gio from "@girs/gio-2.0";
2
+ import GLib from "@girs/glib-2.0";
3
+ import { Duplex } from "node:stream";
4
+ import { Buffer } from "node:buffer";
5
+ import { createNodeError, gbytesToUint8Array } from "@gjsify/utils";
6
+ class Socket extends Duplex {
7
+ // Public properties matching Node.js net.Socket
8
+ remoteAddress;
9
+ remotePort;
10
+ remoteFamily;
11
+ localAddress;
12
+ localPort;
13
+ bytesRead = 0;
14
+ bytesWritten = 0;
15
+ connecting = false;
16
+ destroyed = false;
17
+ pending = true;
18
+ readyState = "closed";
19
+ _connection = null;
20
+ _ioStream = null;
21
+ _inputStream = null;
22
+ _outputStream = null;
23
+ _cancellable = new Gio.Cancellable();
24
+ _reading = false;
25
+ _timeout = 0;
26
+ _timeoutId = null;
27
+ constructor(options) {
28
+ super(options);
29
+ this.allowHalfOpen = options?.allowHalfOpen ?? false;
30
+ }
31
+ /** @internal Set the connection from an accepted server socket. */
32
+ _setConnection(connection) {
33
+ this._connection = connection;
34
+ }
35
+ /**
36
+ * @internal Set up this socket from a raw Gio.IOStream (e.g., stolen from Soup.Server
37
+ * during an HTTP upgrade). Extracts I/O streams, attempts to read address info
38
+ * if the underlying stream is a SocketConnection, and starts reading.
39
+ */
40
+ _setupFromIOStream(ioStream) {
41
+ this._ioStream = ioStream;
42
+ try {
43
+ const sockConn = ioStream;
44
+ if (typeof sockConn.get_socket === "function") {
45
+ this._connection = sockConn;
46
+ const remoteAddr = sockConn.get_remote_address();
47
+ this.remoteAddress = remoteAddr.get_address().to_string();
48
+ this.remotePort = remoteAddr.get_port();
49
+ this.remoteFamily = remoteAddr.get_address().get_family() === Gio.SocketFamily.IPV6 ? "IPv6" : "IPv4";
50
+ const localAddr = sockConn.get_local_address();
51
+ this.localAddress = localAddr.get_address().to_string();
52
+ this.localPort = localAddr.get_port();
53
+ }
54
+ } catch {
55
+ }
56
+ this._inputStream = ioStream.get_input_stream();
57
+ this._outputStream = ioStream.get_output_stream();
58
+ this.connecting = false;
59
+ this.pending = false;
60
+ this.readyState = "open";
61
+ this.emit("connect");
62
+ this.emit("ready");
63
+ this._startReading();
64
+ }
65
+ connect(options, host, connectionListener) {
66
+ let opts;
67
+ if (typeof options === "number") {
68
+ opts = { port: options, host: typeof host === "string" ? host : "localhost" };
69
+ if (typeof host === "function") connectionListener = host;
70
+ } else {
71
+ opts = options;
72
+ if (typeof host === "function") connectionListener = host;
73
+ }
74
+ if (connectionListener) {
75
+ this.once("connect", connectionListener);
76
+ }
77
+ this.connecting = true;
78
+ this.readyState = "opening";
79
+ this.pending = true;
80
+ const targetHost = opts.host || "localhost";
81
+ const targetPort = opts.port;
82
+ const client = new Gio.SocketClient();
83
+ if (opts.timeout) {
84
+ client.set_timeout(Math.ceil(opts.timeout / 1e3));
85
+ }
86
+ client.connect_to_host_async(
87
+ targetHost,
88
+ targetPort,
89
+ this._cancellable,
90
+ (_source, asyncResult) => {
91
+ try {
92
+ this._connection = client.connect_to_host_finish(asyncResult);
93
+ this._setupConnection(opts);
94
+ } catch (err) {
95
+ this.connecting = false;
96
+ this.readyState = "closed";
97
+ const nodeErr = createNodeError(err, "connect", {
98
+ address: targetHost,
99
+ port: targetPort
100
+ });
101
+ this.destroy(nodeErr);
102
+ }
103
+ }
104
+ );
105
+ return this;
106
+ }
107
+ /** @internal Set up streams and emit connect after connection is established. */
108
+ _setupConnection(opts) {
109
+ if (!this._connection) return;
110
+ const sock = this._connection.get_socket();
111
+ this._inputStream = this._connection.get_input_stream();
112
+ this._outputStream = this._connection.get_output_stream();
113
+ if ("keepAlive" in opts && opts.keepAlive) {
114
+ sock.set_keepalive(true);
115
+ }
116
+ if (!("noDelay" in opts) || opts.noDelay !== false) {
117
+ try {
118
+ sock.set_option(6, 1, 1);
119
+ } catch {
120
+ }
121
+ }
122
+ try {
123
+ const remoteAddr = this._connection.get_remote_address();
124
+ this.remoteAddress = remoteAddr.get_address().to_string();
125
+ this.remotePort = remoteAddr.get_port();
126
+ this.remoteFamily = remoteAddr.get_address().get_family() === Gio.SocketFamily.IPV6 ? "IPv6" : "IPv4";
127
+ } catch {
128
+ }
129
+ try {
130
+ const localAddr = this._connection.get_local_address();
131
+ this.localAddress = localAddr.get_address().to_string();
132
+ this.localPort = localAddr.get_port();
133
+ } catch {
134
+ }
135
+ this.connecting = false;
136
+ this.pending = false;
137
+ this.readyState = "open";
138
+ this.emit("connect");
139
+ this.emit("ready");
140
+ this._startReading();
141
+ }
142
+ _startReading() {
143
+ if (this._reading || !this._inputStream) return;
144
+ this._reading = true;
145
+ this._readLoop();
146
+ }
147
+ async _readLoop() {
148
+ const inputStream = this._inputStream;
149
+ if (!inputStream) return;
150
+ const CHUNK_SIZE = 16384;
151
+ try {
152
+ while (this._reading && inputStream) {
153
+ const bytes = await new Promise((resolve, reject) => {
154
+ inputStream.read_bytes_async(
155
+ CHUNK_SIZE,
156
+ GLib.PRIORITY_DEFAULT,
157
+ this._cancellable,
158
+ (_source, asyncResult) => {
159
+ try {
160
+ resolve(inputStream.read_bytes_finish(asyncResult));
161
+ } catch (err) {
162
+ reject(err);
163
+ }
164
+ }
165
+ );
166
+ });
167
+ if (!bytes || bytes.get_size() === 0) {
168
+ this._reading = false;
169
+ if (!this.allowHalfOpen) {
170
+ this.once("end", () => {
171
+ this.end();
172
+ this.readyState = "closed";
173
+ });
174
+ } else {
175
+ this.readyState = this.writable ? "writeOnly" : "closed";
176
+ }
177
+ this.push(null);
178
+ break;
179
+ }
180
+ const data = gbytesToUint8Array(bytes);
181
+ this.bytesRead += data.length;
182
+ this._resetTimeout();
183
+ if (!this.push(Buffer.from(data))) {
184
+ this._reading = false;
185
+ break;
186
+ }
187
+ }
188
+ } catch (err) {
189
+ if (!this._cancellable.is_cancelled()) {
190
+ this.destroy(createNodeError(err, "read", { address: this.remoteAddress }));
191
+ }
192
+ }
193
+ }
194
+ // Duplex stream interface
195
+ _read(_size) {
196
+ if (!this._reading && this._inputStream) {
197
+ this._startReading();
198
+ }
199
+ }
200
+ _write(chunk, encoding, callback) {
201
+ if (!this._outputStream) {
202
+ callback(new Error("Socket is not connected"));
203
+ return;
204
+ }
205
+ const data = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, encoding);
206
+ this._outputStream.write_bytes_async(
207
+ new GLib.Bytes(data),
208
+ GLib.PRIORITY_DEFAULT,
209
+ this._cancellable,
210
+ (_source, asyncResult) => {
211
+ try {
212
+ const written = this._outputStream.write_bytes_finish(asyncResult);
213
+ this.bytesWritten += written;
214
+ this._resetTimeout();
215
+ callback(null);
216
+ } catch (err) {
217
+ callback(createNodeError(err, "write", { address: this.remoteAddress }));
218
+ }
219
+ }
220
+ );
221
+ }
222
+ _final(callback) {
223
+ if (this._connection) {
224
+ try {
225
+ this._connection.get_socket().shutdown(false, true);
226
+ this.readyState = this.readable ? "readOnly" : "closed";
227
+ } catch {
228
+ }
229
+ } else if (this._ioStream) {
230
+ try {
231
+ this._ioStream.close(null);
232
+ this.readyState = "closed";
233
+ } catch {
234
+ }
235
+ this._ioStream = null;
236
+ this._inputStream = null;
237
+ this._outputStream = null;
238
+ }
239
+ callback();
240
+ }
241
+ _destroy(err, callback) {
242
+ this._reading = false;
243
+ this._clearTimeout();
244
+ this._cancellable.cancel();
245
+ if (this._connection) {
246
+ try {
247
+ this._connection.close(null);
248
+ } catch {
249
+ }
250
+ this._connection = null;
251
+ } else if (this._ioStream) {
252
+ try {
253
+ this._ioStream.close(null);
254
+ } catch {
255
+ }
256
+ }
257
+ this._ioStream = null;
258
+ this._inputStream = null;
259
+ this._outputStream = null;
260
+ this.readyState = "closed";
261
+ this.destroyed = true;
262
+ callback(err);
263
+ }
264
+ /** Set the socket timeout in milliseconds. 0 disables. */
265
+ setTimeout(timeout, callback) {
266
+ this._timeout = timeout;
267
+ this._clearTimeout();
268
+ if (callback) {
269
+ this.once("timeout", callback);
270
+ }
271
+ if (timeout > 0) {
272
+ this._resetTimeout();
273
+ }
274
+ return this;
275
+ }
276
+ _resetTimeout() {
277
+ this._clearTimeout();
278
+ if (this._timeout > 0) {
279
+ this._timeoutId = setTimeout(() => {
280
+ this.emit("timeout");
281
+ }, this._timeout);
282
+ }
283
+ }
284
+ _clearTimeout() {
285
+ if (this._timeoutId !== null) {
286
+ clearTimeout(this._timeoutId);
287
+ this._timeoutId = null;
288
+ }
289
+ }
290
+ /** Enable/disable TCP keep-alive. */
291
+ setKeepAlive(enable, _initialDelay) {
292
+ if (this._connection) {
293
+ try {
294
+ this._connection.get_socket().set_keepalive(enable ?? false);
295
+ } catch {
296
+ }
297
+ }
298
+ return this;
299
+ }
300
+ /** Enable/disable TCP_NODELAY (disable Nagle algorithm). */
301
+ setNoDelay(noDelay) {
302
+ if (this._connection) {
303
+ try {
304
+ this._connection.get_socket().set_option(6, 1, noDelay !== false ? 1 : 0);
305
+ } catch {
306
+ }
307
+ }
308
+ return this;
309
+ }
310
+ /** Get the underlying socket address info. */
311
+ address() {
312
+ if (this.localAddress && this.localPort) {
313
+ return {
314
+ port: this.localPort,
315
+ family: this.remoteFamily || "IPv4",
316
+ address: this.localAddress
317
+ };
318
+ }
319
+ return {};
320
+ }
321
+ /** Reference this socket (keep event loop alive). No-op in GJS. */
322
+ ref() {
323
+ return this;
324
+ }
325
+ /** Unreference this socket. No-op in GJS. */
326
+ unref() {
327
+ return this;
328
+ }
329
+ }
330
+ export {
331
+ Socket
332
+ };
@@ -0,0 +1,30 @@
1
+ export { Socket, SocketConnectOptions } from './socket.js';
2
+ export { Server, ListenOptions } from './server.js';
3
+ import { Socket, SocketConnectOptions } from './socket.js';
4
+ import { Server } from './server.js';
5
+ /** Check if input is a valid IP address. Returns 0, 4, or 6. */
6
+ export declare function isIP(input: string): 0 | 4 | 6;
7
+ /** Check if input is a valid IPv4 address. */
8
+ export declare function isIPv4(input: string): boolean;
9
+ /** Check if input is a valid IPv6 address. */
10
+ export declare function isIPv6(input: string): boolean;
11
+ /** Create a new TCP connection. */
12
+ export declare function createConnection(options: SocketConnectOptions | number, host?: string | (() => void), connectionListener?: () => void): Socket;
13
+ /** Alias for createConnection. */
14
+ export declare const connect: typeof createConnection;
15
+ /** Create a new TCP server. */
16
+ export declare function createServer(connectionListener?: (socket: Socket) => void): Server;
17
+ export declare function createServer(options?: {
18
+ allowHalfOpen?: boolean;
19
+ }, connectionListener?: (socket: Socket) => void): Server;
20
+ declare const _default: {
21
+ Socket: typeof Socket;
22
+ Server: typeof Server;
23
+ isIP: typeof isIP;
24
+ isIPv4: typeof isIPv4;
25
+ isIPv6: typeof isIPv6;
26
+ createConnection: typeof createConnection;
27
+ connect: typeof createConnection;
28
+ createServer: typeof createServer;
29
+ };
30
+ export default _default;
@@ -0,0 +1,40 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import { Socket } from './socket.js';
3
+ export interface ListenOptions {
4
+ port?: number;
5
+ host?: string;
6
+ backlog?: number;
7
+ exclusive?: boolean;
8
+ }
9
+ export declare class Server extends EventEmitter {
10
+ listening: boolean;
11
+ maxConnections?: number;
12
+ allowHalfOpen: boolean;
13
+ private _service;
14
+ private _connections;
15
+ private _address;
16
+ constructor(connectionListener?: (socket: Socket) => void);
17
+ constructor(options?: {
18
+ allowHalfOpen?: boolean;
19
+ }, connectionListener?: (socket: Socket) => void);
20
+ /**
21
+ * Start listening for connections.
22
+ */
23
+ listen(port?: number, host?: string, backlog?: number, callback?: () => void): this;
24
+ listen(port?: number, host?: string, callback?: () => void): this;
25
+ listen(port?: number, callback?: () => void): this;
26
+ listen(options?: ListenOptions, callback?: () => void): this;
27
+ private _handleConnection;
28
+ /** Get the address the server is listening on. */
29
+ address(): {
30
+ port: number;
31
+ family: string;
32
+ address: string;
33
+ } | null;
34
+ /** Close the server, stop accepting new connections. */
35
+ close(callback?: (err?: Error) => void): this;
36
+ /** Get the number of concurrent connections. */
37
+ getConnections(callback: (err: Error | null, count: number) => void): void;
38
+ ref(): this;
39
+ unref(): this;
40
+ }
@@ -0,0 +1,78 @@
1
+ import Gio from '@girs/gio-2.0';
2
+ import { Duplex } from 'node:stream';
3
+ import type { DuplexOptions } from 'node:stream';
4
+ export interface SocketConnectOptions {
5
+ port: number;
6
+ host?: string;
7
+ localAddress?: string;
8
+ localPort?: number;
9
+ family?: 4 | 6 | 0;
10
+ keepAlive?: boolean;
11
+ keepAliveInitialDelay?: number;
12
+ noDelay?: boolean;
13
+ timeout?: number;
14
+ }
15
+ export interface SocketOptions extends DuplexOptions {
16
+ allowHalfOpen?: boolean;
17
+ }
18
+ export declare class Socket extends Duplex {
19
+ remoteAddress?: string;
20
+ remotePort?: number;
21
+ remoteFamily?: string;
22
+ localAddress?: string;
23
+ localPort?: number;
24
+ bytesRead: number;
25
+ bytesWritten: number;
26
+ connecting: boolean;
27
+ destroyed: boolean;
28
+ pending: boolean;
29
+ readyState: 'opening' | 'open' | 'readOnly' | 'writeOnly' | 'closed';
30
+ allowHalfOpen: boolean;
31
+ private _connection;
32
+ private _ioStream;
33
+ private _inputStream;
34
+ private _outputStream;
35
+ private _cancellable;
36
+ private _reading;
37
+ private _timeout;
38
+ private _timeoutId;
39
+ constructor(options?: SocketOptions);
40
+ /** @internal Set the connection from an accepted server socket. */
41
+ _setConnection(connection: Gio.SocketConnection): void;
42
+ /**
43
+ * @internal Set up this socket from a raw Gio.IOStream (e.g., stolen from Soup.Server
44
+ * during an HTTP upgrade). Extracts I/O streams, attempts to read address info
45
+ * if the underlying stream is a SocketConnection, and starts reading.
46
+ */
47
+ _setupFromIOStream(ioStream: Gio.IOStream): void;
48
+ /**
49
+ * Initiate a TCP connection.
50
+ */
51
+ connect(options: SocketConnectOptions | number, host?: string | (() => void), connectionListener?: () => void): this;
52
+ /** @internal Set up streams and emit connect after connection is established. */
53
+ _setupConnection(opts: SocketConnectOptions | Record<string, never>): void;
54
+ private _startReading;
55
+ private _readLoop;
56
+ _read(_size: number): void;
57
+ _write(chunk: any, encoding: string, callback: (error?: Error | null) => void): void;
58
+ _final(callback: (error?: Error | null) => void): void;
59
+ _destroy(err: Error | null, callback: (error?: Error | null) => void): void;
60
+ /** Set the socket timeout in milliseconds. 0 disables. */
61
+ setTimeout(timeout: number, callback?: () => void): this;
62
+ private _resetTimeout;
63
+ private _clearTimeout;
64
+ /** Enable/disable TCP keep-alive. */
65
+ setKeepAlive(enable?: boolean, _initialDelay?: number): this;
66
+ /** Enable/disable TCP_NODELAY (disable Nagle algorithm). */
67
+ setNoDelay(noDelay?: boolean): this;
68
+ /** Get the underlying socket address info. */
69
+ address(): {
70
+ port: number;
71
+ family: string;
72
+ address: string;
73
+ } | {};
74
+ /** Reference this socket (keep event loop alive). No-op in GJS. */
75
+ ref(): this;
76
+ /** Unreference this socket. No-op in GJS. */
77
+ unref(): this;
78
+ }