@softtynet/zca-js 2.3.4 → 2.3.6

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 (129) hide show
  1. package/README.md +47 -11
  2. package/dist/apis/call/addUserGroupCall.d.ts +11 -0
  3. package/dist/apis/call/addUserGroupCall.js +48 -0
  4. package/dist/apis/call/answerAckVoiceCall.d.ts +5 -0
  5. package/dist/apis/call/answerAckVoiceCall.js +38 -0
  6. package/dist/apis/call/answerGroupCall.d.ts +10 -0
  7. package/dist/apis/call/answerGroupCall.js +45 -0
  8. package/dist/apis/call/answerVoiceCall.d.ts +11 -0
  9. package/dist/apis/call/answerVoiceCall.js +50 -0
  10. package/dist/apis/call/broadcastGroupCallState.d.ts +10 -0
  11. package/dist/apis/call/broadcastGroupCallState.js +45 -0
  12. package/dist/apis/call/cancelGroupCall.d.ts +10 -0
  13. package/dist/apis/call/cancelGroupCall.js +45 -0
  14. package/dist/apis/call/cancelVoiceCall.d.ts +1 -1
  15. package/dist/apis/call/cancelVoiceCall.js +5 -1
  16. package/dist/apis/call/createController.d.ts +7 -0
  17. package/dist/apis/call/createController.js +9 -0
  18. package/dist/apis/call/createRtcSession.d.ts +8 -0
  19. package/dist/apis/call/createRtcSession.js +10 -0
  20. package/dist/apis/call/endGroupCall.d.ts +10 -0
  21. package/dist/apis/call/endGroupCall.js +45 -0
  22. package/dist/apis/call/finishGroupCall.d.ts +12 -0
  23. package/dist/apis/call/finishGroupCall.js +47 -0
  24. package/dist/apis/call/getGroupCallState.d.ts +3 -0
  25. package/dist/apis/call/getGroupCallState.js +38 -0
  26. package/dist/apis/call/holdVoiceCall.d.ts +5 -0
  27. package/dist/apis/call/holdVoiceCall.js +34 -0
  28. package/dist/apis/call/joinGroupCall.d.ts +11 -0
  29. package/dist/apis/call/joinGroupCall.js +46 -0
  30. package/dist/apis/call/logEndVoiceCall.d.ts +8 -0
  31. package/dist/apis/call/logEndVoiceCall.js +46 -0
  32. package/dist/apis/call/notifyGroupCall.d.ts +9 -0
  33. package/dist/apis/call/notifyGroupCall.js +44 -0
  34. package/dist/apis/call/pingGroupCall.d.ts +10 -0
  35. package/dist/apis/call/pingGroupCall.js +45 -0
  36. package/dist/apis/call/requestAudioToVideoCall.d.ts +5 -0
  37. package/dist/apis/call/requestAudioToVideoCall.js +37 -0
  38. package/dist/apis/call/requestGroupCall.d.ts +9 -0
  39. package/dist/apis/call/requestGroupCall.js +46 -0
  40. package/dist/apis/call/requestShareScreenCall.d.ts +5 -0
  41. package/dist/apis/call/requestShareScreenCall.js +37 -0
  42. package/dist/apis/call/requestVoiceCall.d.ts +10 -0
  43. package/dist/apis/call/requestVoiceCall.js +47 -0
  44. package/dist/apis/call/ringRingGroupCall.d.ts +10 -0
  45. package/dist/apis/call/ringRingGroupCall.js +45 -0
  46. package/dist/apis/call/ringRingVoiceCall.d.ts +5 -0
  47. package/dist/apis/call/ringRingVoiceCall.js +38 -0
  48. package/dist/apis/call/sendRequestGroupCall.d.ts +11 -0
  49. package/dist/apis/call/sendRequestGroupCall.js +48 -0
  50. package/dist/apis/call/sendRequestVoiceCall.d.ts +11 -0
  51. package/dist/apis/call/sendRequestVoiceCall.js +51 -0
  52. package/dist/apis/call/sendVoiceCall.d.ts +8 -1
  53. package/dist/apis/call/sendVoiceCall.js +10 -8
  54. package/dist/apis/call/shareScreenGroupCall.d.ts +10 -0
  55. package/dist/apis/call/shareScreenGroupCall.js +45 -0
  56. package/dist/apis/call/unholdVoiceCall.d.ts +5 -0
  57. package/dist/apis/call/unholdVoiceCall.js +34 -0
  58. package/dist/apis/call/updateCallMediaState.d.ts +7 -0
  59. package/dist/apis/call/updateCallMediaState.js +61 -0
  60. package/dist/apis/sync/downloadTransferSync.js +19 -1
  61. package/dist/apis.d.ts +81 -0
  62. package/dist/apis.js +135 -0
  63. package/dist/call-engine/ZRTPPacketCodec.d.ts +262 -0
  64. package/dist/call-engine/ZRTPPacketCodec.js +506 -0
  65. package/dist/call-engine/ZaloCallController.d.ts +134 -0
  66. package/dist/call-engine/ZaloCallController.js +638 -0
  67. package/dist/call-engine/ZaloCallTransport.d.ts +83 -0
  68. package/dist/call-engine/ZaloCallTransport.js +259 -0
  69. package/dist/call-engine/ZaloRtcSession.d.ts +609 -0
  70. package/dist/call-engine/ZaloRtcSession.js +2939 -0
  71. package/dist/call-engine/ZaloSrtpSession.d.ts +80 -0
  72. package/dist/call-engine/ZaloSrtpSession.js +278 -0
  73. package/dist/call-engine/index.d.ts +18 -0
  74. package/dist/call-engine/index.js +24 -0
  75. package/dist/cjs/apis/call/addUserGroupCall.cjs +53 -0
  76. package/dist/cjs/apis/call/answerAckVoiceCall.cjs +43 -0
  77. package/dist/cjs/apis/call/answerGroupCall.cjs +50 -0
  78. package/dist/cjs/apis/call/answerVoiceCall.cjs +55 -0
  79. package/dist/cjs/apis/call/broadcastGroupCallState.cjs +50 -0
  80. package/dist/cjs/apis/call/cancelGroupCall.cjs +50 -0
  81. package/dist/cjs/apis/call/cancelVoiceCall.cjs +5 -1
  82. package/dist/cjs/apis/call/createController.cjs +14 -0
  83. package/dist/cjs/apis/call/createRtcSession.cjs +15 -0
  84. package/dist/cjs/apis/call/endGroupCall.cjs +50 -0
  85. package/dist/cjs/apis/call/finishGroupCall.cjs +52 -0
  86. package/dist/cjs/apis/call/getGroupCallState.cjs +43 -0
  87. package/dist/cjs/apis/call/holdVoiceCall.cjs +39 -0
  88. package/dist/cjs/apis/call/joinGroupCall.cjs +51 -0
  89. package/dist/cjs/apis/call/logEndVoiceCall.cjs +51 -0
  90. package/dist/cjs/apis/call/notifyGroupCall.cjs +49 -0
  91. package/dist/cjs/apis/call/pingGroupCall.cjs +50 -0
  92. package/dist/cjs/apis/call/requestAudioToVideoCall.cjs +42 -0
  93. package/dist/cjs/apis/call/requestGroupCall.cjs +51 -0
  94. package/dist/cjs/apis/call/requestShareScreenCall.cjs +42 -0
  95. package/dist/cjs/apis/call/requestVoiceCall.cjs +52 -0
  96. package/dist/cjs/apis/call/ringRingGroupCall.cjs +50 -0
  97. package/dist/cjs/apis/call/ringRingVoiceCall.cjs +43 -0
  98. package/dist/cjs/apis/call/sendRequestGroupCall.cjs +53 -0
  99. package/dist/cjs/apis/call/sendRequestVoiceCall.cjs +56 -0
  100. package/dist/cjs/apis/call/sendVoiceCall.cjs +10 -8
  101. package/dist/cjs/apis/call/shareScreenGroupCall.cjs +50 -0
  102. package/dist/cjs/apis/call/unholdVoiceCall.cjs +39 -0
  103. package/dist/cjs/apis/call/updateCallMediaState.cjs +66 -0
  104. package/dist/cjs/apis/sync/downloadTransferSync.cjs +19 -1
  105. package/dist/cjs/apis.cjs +135 -0
  106. package/dist/cjs/call-engine/ZRTPPacketCodec.cjs +525 -0
  107. package/dist/cjs/call-engine/ZaloCallController.cjs +643 -0
  108. package/dist/cjs/call-engine/ZaloCallTransport.cjs +265 -0
  109. package/dist/cjs/call-engine/ZaloRtcSession.cjs +2945 -0
  110. package/dist/cjs/call-engine/ZaloSrtpSession.cjs +287 -0
  111. package/dist/cjs/constants/protocol.cjs +1 -1
  112. package/dist/cjs/crypto/aes.cjs +3 -1
  113. package/dist/cjs/crypto/zdb-cipher.cjs +10 -3
  114. package/dist/cjs/index.cjs +61 -11
  115. package/dist/cjs/models/CallEvent.cjs +95 -1
  116. package/dist/cjs/realtime/handlers/control.handler.cjs +17 -3
  117. package/dist/cjs/realtime/listener.cjs +19 -0
  118. package/dist/constants/protocol.d.ts +1 -1
  119. package/dist/constants/protocol.js +1 -1
  120. package/dist/crypto/aes.js +3 -1
  121. package/dist/crypto/zdb-cipher.js +10 -3
  122. package/dist/index.d.ts +32 -4
  123. package/dist/index.js +2 -0
  124. package/dist/models/CallEvent.d.ts +15 -0
  125. package/dist/models/CallEvent.js +95 -1
  126. package/dist/realtime/handlers/control.handler.js +17 -3
  127. package/dist/realtime/listener.d.ts +5 -0
  128. package/dist/realtime/listener.js +19 -0
  129. package/package.json +2 -1
@@ -0,0 +1,83 @@
1
+ import EventEmitter from "node:events";
2
+ export type ZaloCallIpcMessage = {
3
+ type: string;
4
+ command?: number | string;
5
+ data?: unknown;
6
+ [key: string]: unknown;
7
+ };
8
+ /**
9
+ * Khoá AES-128-CBC tĩnh chuẩn trong module `4KIH` của Zalo PC và binary `ZaloCall` (`yjAF9oqMWl6XfXYJn9mA7w==`).
10
+ */
11
+ export declare const DEFAULT_ZALOCALL_IPC_KEY_BASE64 = "yjAF9oqMWl6XfXYJn9mA7w==";
12
+ export type ZaloCallTransportOptions = {
13
+ /**
14
+ * Hậu tố định danh cho Unix Domain Socket / Named Pipe (mặc định dùng `process.pid`
15
+ * để cô lập hoàn toàn, không đụng độ với Zalo PC đang chạy có hậu tố `1111111111`).
16
+ */
17
+ socketId?: string;
18
+ /**
19
+ * Khoá AES-128-CBC dạng Base64 (mặc định `yjAF9oqMWl6XfXYJn9mA7w==`).
20
+ */
21
+ keyBase64?: string;
22
+ /**
23
+ * Thời gian chờ phản hồi `"ack"` tối đa trên một khung truyền (mặc định `250` ms).
24
+ */
25
+ ackTimeoutMs?: number;
26
+ };
27
+ export interface ZaloCallTransportEvents {
28
+ ready: [];
29
+ client_connected: [];
30
+ message: [message: ZaloCallIpcMessage];
31
+ raw_ack: [];
32
+ error: [error: unknown];
33
+ close: [];
34
+ }
35
+ /**
36
+ * Tầng giao thức IPC双kênh (`receiveSocketPath` & `sendSocketPath`) mã hoá AES-128-CBC (Hex + `$` framing + 4000-char chunking)
37
+ * khớp 100% với module `3Zc2` / `4KIH` của Zalo PC và `zrtc_call::ZIpcClientMac` (`0x10012eb50`).
38
+ */
39
+ export declare class ZaloCallTransport extends EventEmitter<ZaloCallTransportEvents> {
40
+ readonly socketId: string;
41
+ readonly sendSocketPath: string;
42
+ readonly receiveSocketPath: string;
43
+ readonly keyBase64: string;
44
+ private readonly keyBuffer;
45
+ private readonly ivBuffer;
46
+ private readonly ackTimeoutMs;
47
+ private sendServer;
48
+ private receiveServer;
49
+ private sendClient;
50
+ private receiveClient;
51
+ private receiveBuffer;
52
+ private outgoingQueue;
53
+ private waitingForAck;
54
+ private ackTimer;
55
+ private emittedConnected;
56
+ constructor(options?: ZaloCallTransportOptions);
57
+ /**
58
+ * Mã hoá đối tượng JSON thành mảng các mảnh Hex (tối đa 4000 ký tự/mảnh, mảnh cuối kết thúc bằng `$`).
59
+ */
60
+ encryptFrames(payload: unknown): string[];
61
+ /**
62
+ * Giải mã một khung chuỗi Hex (không bao gồm ký tự `$`) thành đối tượng JSON.
63
+ */
64
+ decryptFrame(encryptedHex: string): ZaloCallIpcMessage;
65
+ /**
66
+ * Khởi tạo 2 máy chủ IPC (`receiveSocketPath` và `sendSocketPath`) sẵn sàng đón tiến trình `ZaloCall`.
67
+ */
68
+ start(): Promise<void>;
69
+ /**
70
+ * Gửi một thông điệp IPC đã mã hoá AES-128-CBC xuống tiến trình `ZaloCall` (qua hàng đợi `"ack"`).
71
+ */
72
+ send(message: ZaloCallIpcMessage): void;
73
+ isConnected(): boolean;
74
+ /**
75
+ * Đóng toàn bộ kết nối và dọn dẹp file socket trên đĩa.
76
+ */
77
+ close(): Promise<void>;
78
+ private checkBothConnected;
79
+ private onAckReceived;
80
+ private flushOutgoingQueue;
81
+ private handleReceiveChunk;
82
+ private unlinkUnixSockets;
83
+ }
@@ -0,0 +1,259 @@
1
+ import crypto from "node:crypto";
2
+ import EventEmitter from "node:events";
3
+ import fs from "node:fs";
4
+ import net from "node:net";
5
+ import { Buffer } from "node:buffer";
6
+ /**
7
+ * Khoá AES-128-CBC tĩnh chuẩn trong module `4KIH` của Zalo PC và binary `ZaloCall` (`yjAF9oqMWl6XfXYJn9mA7w==`).
8
+ */
9
+ export const DEFAULT_ZALOCALL_IPC_KEY_BASE64 = "yjAF9oqMWl6XfXYJn9mA7w==";
10
+ const MAX_IPC_CHUNK_LENGTH = 4000;
11
+ const MAX_IPC_RECEIVE_BUFFER_LENGTH = 4 * 1024 * 1024;
12
+ /**
13
+ * Tầng giao thức IPC双kênh (`receiveSocketPath` & `sendSocketPath`) mã hoá AES-128-CBC (Hex + `$` framing + 4000-char chunking)
14
+ * khớp 100% với module `3Zc2` / `4KIH` của Zalo PC và `zrtc_call::ZIpcClientMac` (`0x10012eb50`).
15
+ */
16
+ export class ZaloCallTransport extends EventEmitter {
17
+ socketId;
18
+ sendSocketPath;
19
+ receiveSocketPath;
20
+ keyBase64;
21
+ keyBuffer;
22
+ ivBuffer;
23
+ ackTimeoutMs;
24
+ sendServer = null;
25
+ receiveServer = null;
26
+ sendClient = null;
27
+ receiveClient = null;
28
+ receiveBuffer = "";
29
+ outgoingQueue = [];
30
+ waitingForAck = false;
31
+ ackTimer = null;
32
+ emittedConnected = false;
33
+ constructor(options = {}) {
34
+ super();
35
+ this.socketId = options.socketId ?? `${process.pid}_${Math.floor(Math.random() * 10000)}`;
36
+ this.keyBase64 = options.keyBase64 ?? DEFAULT_ZALOCALL_IPC_KEY_BASE64;
37
+ this.ackTimeoutMs = options.ackTimeoutMs ?? 250;
38
+ const decodedKey = Buffer.from(this.keyBase64, "base64");
39
+ this.keyBuffer = Buffer.alloc(16, 0);
40
+ decodedKey.copy(this.keyBuffer, 0, 0, Math.min(16, decodedKey.length));
41
+ this.ivBuffer = Buffer.alloc(16, 0);
42
+ if (process.platform === "win32") {
43
+ this.receiveSocketPath = `\\\\.\\pipe\\receive_socket_${this.socketId}`;
44
+ this.sendSocketPath = `\\\\.\\pipe\\send_socket_${this.socketId}`;
45
+ }
46
+ else {
47
+ this.receiveSocketPath = `/tmp/zcall_r_${this.socketId}`;
48
+ this.sendSocketPath = `/tmp/zcall_s_${this.socketId}`;
49
+ }
50
+ }
51
+ /**
52
+ * Mã hoá đối tượng JSON thành mảng các mảnh Hex (tối đa 4000 ký tự/mảnh, mảnh cuối kết thúc bằng `$`).
53
+ */
54
+ encryptFrames(payload) {
55
+ const json = typeof payload === "string" ? payload : JSON.stringify(payload);
56
+ const cipher = crypto.createCipheriv("aes-128-cbc", this.keyBuffer, this.ivBuffer);
57
+ const encryptedHex = cipher.update(json, "utf-8", "hex") + cipher.final("hex");
58
+ const chunks = [];
59
+ let offset = 0;
60
+ while (offset < encryptedHex.length) {
61
+ chunks.push(encryptedHex.slice(offset, offset + MAX_IPC_CHUNK_LENGTH));
62
+ offset += MAX_IPC_CHUNK_LENGTH;
63
+ }
64
+ if (chunks.length === 0) {
65
+ chunks.push("$");
66
+ }
67
+ else {
68
+ chunks[chunks.length - 1] += "$";
69
+ }
70
+ return chunks;
71
+ }
72
+ /**
73
+ * Giải mã một khung chuỗi Hex (không bao gồm ký tự `$`) thành đối tượng JSON.
74
+ */
75
+ decryptFrame(encryptedHex) {
76
+ const clean = encryptedHex.endsWith("$") ? encryptedHex.slice(0, -1) : encryptedHex;
77
+ const decipher = crypto.createDecipheriv("aes-128-cbc", this.keyBuffer, this.ivBuffer);
78
+ const plain = decipher.update(clean, "hex", "utf-8") + decipher.final("utf-8");
79
+ return JSON.parse(plain);
80
+ }
81
+ /**
82
+ * Khởi tạo 2 máy chủ IPC (`receiveSocketPath` và `sendSocketPath`) sẵn sàng đón tiến trình `ZaloCall`.
83
+ */
84
+ async start() {
85
+ this.unlinkUnixSockets();
86
+ this.emittedConnected = false;
87
+ this.sendServer = net.createServer((socket) => {
88
+ this.sendClient = socket;
89
+ socket.on("data", (chunk) => {
90
+ const text = chunk.toString("utf-8");
91
+ if (text.includes("ack")) {
92
+ this.emit("raw_ack");
93
+ this.onAckReceived();
94
+ }
95
+ });
96
+ socket.on("error", (err) => this.emit("error", err));
97
+ this.checkBothConnected();
98
+ this.flushOutgoingQueue();
99
+ });
100
+ this.receiveServer = net.createServer((socket) => {
101
+ this.receiveClient = socket;
102
+ socket.on("data", (chunk) => {
103
+ this.handleReceiveChunk(chunk.toString("utf-8"));
104
+ });
105
+ socket.on("error", (err) => this.emit("error", err));
106
+ this.checkBothConnected();
107
+ });
108
+ await Promise.all([
109
+ new Promise((resolve, reject) => {
110
+ this.receiveServer.once("error", reject);
111
+ this.receiveServer.listen(this.receiveSocketPath, () => {
112
+ if (process.platform !== "win32") {
113
+ try {
114
+ fs.chmodSync(this.receiveSocketPath, 0o600);
115
+ }
116
+ catch {
117
+ // Ignore chmod error if unsupported
118
+ }
119
+ }
120
+ resolve();
121
+ });
122
+ }),
123
+ new Promise((resolve, reject) => {
124
+ this.sendServer.once("error", reject);
125
+ this.sendServer.listen(this.sendSocketPath, () => {
126
+ if (process.platform !== "win32") {
127
+ try {
128
+ fs.chmodSync(this.sendSocketPath, 0o600);
129
+ }
130
+ catch {
131
+ // Ignore chmod error if unsupported
132
+ }
133
+ }
134
+ resolve();
135
+ });
136
+ }),
137
+ ]);
138
+ this.emit("ready");
139
+ }
140
+ /**
141
+ * Gửi một thông điệp IPC đã mã hoá AES-128-CBC xuống tiến trình `ZaloCall` (qua hàng đợi `"ack"`).
142
+ */
143
+ send(message) {
144
+ const frames = this.encryptFrames(message);
145
+ this.outgoingQueue.push(...frames);
146
+ this.flushOutgoingQueue();
147
+ }
148
+ isConnected() {
149
+ return Boolean(this.sendClient &&
150
+ !this.sendClient.destroyed &&
151
+ this.receiveClient &&
152
+ !this.receiveClient.destroyed);
153
+ }
154
+ /**
155
+ * Đóng toàn bộ kết nối và dọn dẹp file socket trên đĩa.
156
+ */
157
+ async close() {
158
+ if (this.ackTimer) {
159
+ clearTimeout(this.ackTimer);
160
+ this.ackTimer = null;
161
+ }
162
+ this.outgoingQueue = [];
163
+ this.waitingForAck = false;
164
+ this.emittedConnected = false;
165
+ if (this.sendClient) {
166
+ this.sendClient.destroy();
167
+ this.sendClient = null;
168
+ }
169
+ if (this.receiveClient) {
170
+ this.receiveClient.destroy();
171
+ this.receiveClient = null;
172
+ }
173
+ await Promise.all([
174
+ new Promise((resolve) => {
175
+ if (this.sendServer)
176
+ this.sendServer.close(() => resolve());
177
+ else
178
+ resolve();
179
+ }),
180
+ new Promise((resolve) => {
181
+ if (this.receiveServer)
182
+ this.receiveServer.close(() => resolve());
183
+ else
184
+ resolve();
185
+ }),
186
+ ]);
187
+ this.sendServer = null;
188
+ this.receiveServer = null;
189
+ this.unlinkUnixSockets();
190
+ this.emit("close");
191
+ }
192
+ checkBothConnected() {
193
+ if (this.isConnected() && !this.emittedConnected) {
194
+ this.emittedConnected = true;
195
+ this.emit("client_connected");
196
+ }
197
+ }
198
+ onAckReceived() {
199
+ if (this.ackTimer) {
200
+ clearTimeout(this.ackTimer);
201
+ this.ackTimer = null;
202
+ }
203
+ this.waitingForAck = false;
204
+ this.flushOutgoingQueue();
205
+ }
206
+ flushOutgoingQueue() {
207
+ if (this.waitingForAck || !this.sendClient || this.sendClient.destroyed) {
208
+ return;
209
+ }
210
+ const nextFrame = this.outgoingQueue.shift();
211
+ if (!nextFrame)
212
+ return;
213
+ this.waitingForAck = true;
214
+ this.sendClient.write(nextFrame, "utf-8");
215
+ this.ackTimer = setTimeout(() => {
216
+ this.waitingForAck = false;
217
+ this.flushOutgoingQueue();
218
+ }, this.ackTimeoutMs);
219
+ if (typeof this.ackTimer.unref === "function") {
220
+ this.ackTimer.unref();
221
+ }
222
+ }
223
+ handleReceiveChunk(chunk) {
224
+ if (this.receiveBuffer.length + chunk.length > MAX_IPC_RECEIVE_BUFFER_LENGTH) {
225
+ this.receiveBuffer = "";
226
+ this.emit("error", new Error("IPC receive buffer exceeded maximum allowed size (4MB)"));
227
+ return;
228
+ }
229
+ this.receiveBuffer += chunk;
230
+ let dollarIdx = this.receiveBuffer.indexOf("$");
231
+ while (dollarIdx !== -1) {
232
+ const frame = this.receiveBuffer.slice(0, dollarIdx);
233
+ this.receiveBuffer = this.receiveBuffer.slice(dollarIdx + 1);
234
+ if (frame.length > 0) {
235
+ try {
236
+ const parsed = this.decryptFrame(frame);
237
+ this.emit("message", parsed);
238
+ }
239
+ catch (err) {
240
+ this.emit("error", err);
241
+ }
242
+ }
243
+ dollarIdx = this.receiveBuffer.indexOf("$");
244
+ }
245
+ }
246
+ unlinkUnixSockets() {
247
+ if (process.platform === "win32")
248
+ return;
249
+ for (const p of [this.sendSocketPath, this.receiveSocketPath]) {
250
+ try {
251
+ if (fs.existsSync(p))
252
+ fs.unlinkSync(p);
253
+ }
254
+ catch {
255
+ // Ignore unlink errors
256
+ }
257
+ }
258
+ }
259
+ }