@signalapp/libsignal-client 0.67.1 → 0.67.3

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/Native.d.ts CHANGED
@@ -123,6 +123,7 @@ type ChatListener = {
123
123
  ack: ServerMessageAck
124
124
  ): void;
125
125
  _queue_empty(): void;
126
+ _received_alerts(alerts: string[]): void;
126
127
  _connection_interrupted(
127
128
  // A LibSignalError or null, but not naming the type to avoid circular import dependencies.
128
129
  reason: Error | null
@@ -463,6 +464,7 @@ export function ServerPublicParams_CreateProfileKeyCredentialRequestContextDeter
463
464
  export function ServerPublicParams_CreateReceiptCredentialPresentationDeterministic(serverPublicParams: Wrapper<ServerPublicParams>, randomness: Buffer, receiptCredential: Serialized<ReceiptCredential>): Serialized<ReceiptCredentialPresentation>;
464
465
  export function ServerPublicParams_CreateReceiptCredentialRequestContextDeterministic(serverPublicParams: Wrapper<ServerPublicParams>, randomness: Buffer, receiptSerial: Buffer): Serialized<ReceiptCredentialRequestContext>;
465
466
  export function ServerPublicParams_Deserialize(buffer: Buffer): ServerPublicParams;
467
+ export function ServerPublicParams_GetEndorsementPublicKey(params: Wrapper<ServerPublicParams>): Buffer;
466
468
  export function ServerPublicParams_ReceiveAuthCredentialWithPniAsServiceId(params: Wrapper<ServerPublicParams>, aci: Buffer, pni: Buffer, redemptionTime: Timestamp, authCredentialWithPniResponseBytes: Buffer): Buffer;
467
469
  export function ServerPublicParams_ReceiveExpiringProfileKeyCredential(serverPublicParams: Wrapper<ServerPublicParams>, requestContext: Serialized<ProfileKeyCredentialRequestContext>, response: Serialized<ExpiringProfileKeyCredentialResponse>, currentTimeInSeconds: Timestamp): Serialized<ExpiringProfileKeyCredential>;
468
470
  export function ServerPublicParams_ReceiveReceiptCredential(serverPublicParams: Wrapper<ServerPublicParams>, requestContext: Serialized<ReceiptCredentialRequestContext>, response: Serialized<ReceiptCredentialResponse>): Serialized<ReceiptCredential>;
@@ -531,7 +533,7 @@ export function TESTING_ErrorOnBorrowSync(_input: null): void;
531
533
  export function TESTING_ErrorOnReturnAsync(_needsCleanup: null): Promise<null>;
532
534
  export function TESTING_ErrorOnReturnIo(asyncRuntime: Wrapper<NonSuspendingBackgroundThreadRuntime>, _needsCleanup: null): CancellablePromise<null>;
533
535
  export function TESTING_ErrorOnReturnSync(_needsCleanup: null): null;
534
- export function TESTING_FakeChatConnection_Create(tokio: Wrapper<TokioAsyncContext>, listener: ChatListener): FakeChatConnection;
536
+ export function TESTING_FakeChatConnection_Create(tokio: Wrapper<TokioAsyncContext>, listener: ChatListener, alertsJoinedByNewlines: string): FakeChatConnection;
535
537
  export function TESTING_FakeChatConnection_TakeAuthenticatedChat(chat: Wrapper<FakeChatConnection>): AuthenticatedChatConnection;
536
538
  export function TESTING_FakeChatConnection_TakeRemote(chat: Wrapper<FakeChatConnection>): FakeChatRemoteEnd;
537
539
  export function TESTING_FakeChatRemoteEnd_InjectConnectionInterrupted(chat: Wrapper<FakeChatRemoteEnd>): void;
@@ -0,0 +1,29 @@
1
+ import type { ReadonlyDeep } from 'type-fest';
2
+ import * as Native from '../../Native';
3
+ import { TokioAsyncContext, ServiceAuth } from '../net';
4
+ export type CDSRequestOptionsType = {
5
+ e164s: Array<string>;
6
+ acisAndAccessKeys: Array<{
7
+ aci: string;
8
+ accessKey: string;
9
+ }>;
10
+ /**
11
+ * @deprecated this option is ignored by the server.
12
+ */
13
+ returnAcisWithoutUaks: boolean;
14
+ abortSignal?: AbortSignal;
15
+ useNewConnectLogic?: boolean;
16
+ };
17
+ export type CDSResponseEntryType<Aci, Pni> = {
18
+ aci: Aci | undefined;
19
+ pni: Pni | undefined;
20
+ };
21
+ export type CDSResponseEntries<Aci, Pni> = Map<string, CDSResponseEntryType<Aci, Pni>>;
22
+ export interface CDSResponseType<Aci, Pni> {
23
+ entries: CDSResponseEntries<Aci, Pni>;
24
+ debugPermitsUsed: number;
25
+ }
26
+ export declare function cdsiLookup({ asyncContext, connectionManager, }: Readonly<{
27
+ asyncContext: TokioAsyncContext;
28
+ connectionManager: Native.Wrapper<Native.ConnectionManager>;
29
+ }>, { username, password }: Readonly<ServiceAuth>, { e164s, acisAndAccessKeys, abortSignal, useNewConnectLogic, }: ReadonlyDeep<CDSRequestOptionsType>): Promise<CDSResponseType<string, string>>;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ //
3
+ // Copyright 2025 Signal Messenger, LLC.
4
+ // SPDX-License-Identifier: AGPL-3.0-only
5
+ //
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.cdsiLookup = void 0;
8
+ const Native = require("../../Native");
9
+ const Address_1 = require("../Address");
10
+ const node_buffer_1 = require("node:buffer");
11
+ const net_1 = require("../net");
12
+ async function cdsiLookup({ asyncContext, connectionManager, }, { username, password }, { e164s, acisAndAccessKeys, abortSignal, useNewConnectLogic, }) {
13
+ const request = (0, net_1.newNativeHandle)(Native.LookupRequest_new());
14
+ e164s.forEach((e164) => {
15
+ Native.LookupRequest_addE164(request, e164);
16
+ });
17
+ acisAndAccessKeys.forEach(({ aci: aciStr, accessKey: accessKeyStr }) => {
18
+ Native.LookupRequest_addAciAndAccessKey(request, Address_1.Aci.parseFromServiceIdString(aciStr).getServiceIdFixedWidthBinary(), node_buffer_1.Buffer.from(accessKeyStr, 'base64'));
19
+ });
20
+ const startLookup = useNewConnectLogic
21
+ ? Native.CdsiLookup_new_routes
22
+ : Native.CdsiLookup_new;
23
+ const lookup = await asyncContext.makeCancellable(abortSignal, startLookup(asyncContext, connectionManager, username, password, request));
24
+ return await asyncContext.makeCancellable(abortSignal, Native.CdsiLookup_complete(asyncContext, (0, net_1.newNativeHandle)(lookup)));
25
+ }
26
+ exports.cdsiLookup = cdsiLookup;
27
+ //# sourceMappingURL=CDSI.js.map
@@ -0,0 +1,121 @@
1
+ /// <reference types="node" />
2
+ import * as Native from '../../Native';
3
+ import { LibSignalError } from '../Errors';
4
+ import { Wrapper } from '../../Native';
5
+ import { Buffer } from 'node:buffer';
6
+ import { TokioAsyncContext } from '../net';
7
+ export type ChatRequest = Readonly<{
8
+ verb: string;
9
+ path: string;
10
+ headers: ReadonlyArray<[string, string]>;
11
+ body?: Uint8Array;
12
+ timeoutMillis?: number;
13
+ }>;
14
+ type ConnectionManager = Wrapper<Native.ConnectionManager>;
15
+ export declare class ChatServerMessageAck {
16
+ readonly _nativeHandle: Native.ServerMessageAck;
17
+ constructor(_nativeHandle: Native.ServerMessageAck);
18
+ send(statusCode: number): void;
19
+ }
20
+ export interface ConnectionEventsListener {
21
+ /**
22
+ * Called when the client gets disconnected from the server.
23
+ *
24
+ * This includes both deliberate disconnects as well as unexpected socket
25
+ * closures. If the closure was not due to a deliberate disconnect, the error
26
+ * will be provided.
27
+ */
28
+ onConnectionInterrupted(cause: LibSignalError | null): void;
29
+ }
30
+ export interface ChatServiceListener extends ConnectionEventsListener {
31
+ /**
32
+ * Called when the server delivers an incoming message to the client.
33
+ *
34
+ * `timestamp` is in milliseconds.
35
+ *
36
+ * If `ack`'s `send` method is not called, the server will leave this message in the message
37
+ * queue and attempt to deliver it again in the future.
38
+ */
39
+ onIncomingMessage(envelope: Buffer, timestamp: number, ack: ChatServerMessageAck): void;
40
+ /**
41
+ * Called when the server indicates that there are no further messages in the message queue.
42
+ *
43
+ * Note that further messages may still be delivered; this merely indicates that all messages that
44
+ * were in the queue *when the connection was established* have been delivered.
45
+ */
46
+ onQueueEmpty(): void;
47
+ /**
48
+ * Called when the server has alerts for the current device.
49
+ *
50
+ * In practice this happens as part of the connecting process.
51
+ */
52
+ onReceivedAlerts?(alerts: string[]): void;
53
+ }
54
+ /**
55
+ * A connection to the Chat Service.
56
+ *
57
+ * Provides API methods to communicate with the remote service. Make sure to
58
+ * call {@link #disconnect()} when the instance is no longer needed.
59
+ */
60
+ export type ChatConnection = {
61
+ /**
62
+ * Initiates termination of the underlying connection to the Chat Service. After the service is
63
+ * disconnected, it cannot be used again.
64
+ */
65
+ disconnect(): Promise<void>;
66
+ /**
67
+ * Sends request to the Chat service.
68
+ */
69
+ fetch(chatRequest: ChatRequest, options?: {
70
+ abortSignal?: AbortSignal;
71
+ }): Promise<Native.ChatResponse>;
72
+ /**
73
+ * Information about the connection to the Chat service.
74
+ */
75
+ connectionInfo(): ConnectionInfo;
76
+ };
77
+ export interface ConnectionInfo {
78
+ localPort: number;
79
+ ipVersion: 'IPv4' | 'IPv6';
80
+ toString: () => string;
81
+ }
82
+ export declare class UnauthenticatedChatConnection implements ChatConnection {
83
+ private readonly asyncContext;
84
+ private readonly chatService;
85
+ private readonly chatListener;
86
+ static connect(asyncContext: TokioAsyncContext, connectionManager: ConnectionManager, listener: ConnectionEventsListener, options?: {
87
+ abortSignal?: AbortSignal;
88
+ }): Promise<UnauthenticatedChatConnection>;
89
+ private constructor();
90
+ fetch(chatRequest: ChatRequest, options?: {
91
+ abortSignal?: AbortSignal;
92
+ }): Promise<Native.ChatResponse>;
93
+ disconnect(): Promise<void>;
94
+ connectionInfo(): ConnectionInfo;
95
+ }
96
+ export declare class AuthenticatedChatConnection implements ChatConnection {
97
+ private readonly asyncContext;
98
+ private readonly chatService;
99
+ private readonly chatListener;
100
+ static connect(asyncContext: TokioAsyncContext, connectionManager: ConnectionManager, username: string, password: string, receiveStories: boolean, listener: ChatServiceListener, options?: {
101
+ abortSignal?: AbortSignal;
102
+ }): Promise<AuthenticatedChatConnection>;
103
+ /**
104
+ * Creates a chat connection backed by a fake remote end.
105
+ *
106
+ * @param asyncContext the async runtime to use
107
+ * @param listener the listener to send events to
108
+ * @param alerts alerts to send immediately upon connect
109
+ * @returns an {@link AuthenticatedChatConnection} and handle for the remote
110
+ * end of the fake connection.
111
+ */
112
+ static fakeConnect(asyncContext: TokioAsyncContext, listener: ChatServiceListener, alerts?: ReadonlyArray<string>): [AuthenticatedChatConnection, Wrapper<Native.FakeChatRemoteEnd>];
113
+ private constructor();
114
+ fetch(chatRequest: ChatRequest, options?: {
115
+ abortSignal?: AbortSignal;
116
+ }): Promise<Native.ChatResponse>;
117
+ disconnect(): Promise<void>;
118
+ connectionInfo(): ConnectionInfo;
119
+ }
120
+ export declare function buildHttpRequest(chatRequest: ChatRequest): Wrapper<Native.HttpRequest>;
121
+ export {};
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ //
3
+ // Copyright 2025 Signal Messenger, LLC.
4
+ // SPDX-License-Identifier: AGPL-3.0-only
5
+ //
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.buildHttpRequest = exports.AuthenticatedChatConnection = exports.UnauthenticatedChatConnection = exports.ChatServerMessageAck = void 0;
8
+ const Native = require("../../Native");
9
+ const node_buffer_1 = require("node:buffer");
10
+ const net_1 = require("../net");
11
+ const DEFAULT_CHAT_REQUEST_TIMEOUT_MILLIS = 5000;
12
+ class ChatServerMessageAck {
13
+ constructor(_nativeHandle) {
14
+ this._nativeHandle = _nativeHandle;
15
+ }
16
+ send(statusCode) {
17
+ Native.ServerMessageAck_SendStatus(this, statusCode);
18
+ }
19
+ }
20
+ exports.ChatServerMessageAck = ChatServerMessageAck;
21
+ class ConnectionInfoImpl {
22
+ constructor(_nativeHandle) {
23
+ this._nativeHandle = _nativeHandle;
24
+ }
25
+ get localPort() {
26
+ return Native.ChatConnectionInfo_local_port(this);
27
+ }
28
+ get ipVersion() {
29
+ const value = Native.ChatConnectionInfo_ip_version(this);
30
+ switch (value) {
31
+ case 1:
32
+ return 'IPv4';
33
+ case 2:
34
+ return 'IPv6';
35
+ default:
36
+ throw new TypeError(`ip type was unexpectedly ${value}`);
37
+ }
38
+ }
39
+ toString() {
40
+ return Native.ChatConnectionInfo_description(this);
41
+ }
42
+ }
43
+ class UnauthenticatedChatConnection {
44
+ static async connect(asyncContext, connectionManager, listener, options) {
45
+ const nativeChatListener = makeNativeChatListener(asyncContext, listener);
46
+ const connect = Native.UnauthenticatedChatConnection_connect(asyncContext, connectionManager);
47
+ const chat = await asyncContext.makeCancellable(options?.abortSignal, connect);
48
+ const connection = (0, net_1.newNativeHandle)(chat);
49
+ Native.UnauthenticatedChatConnection_init_listener(connection, new WeakListenerWrapper(nativeChatListener));
50
+ return new UnauthenticatedChatConnection(asyncContext, connection, nativeChatListener);
51
+ }
52
+ constructor(asyncContext, chatService,
53
+ // Unused except to keep the listener alive since the Rust code only holds a
54
+ // weak reference to the same object.
55
+ chatListener) {
56
+ this.asyncContext = asyncContext;
57
+ this.chatService = chatService;
58
+ this.chatListener = chatListener;
59
+ }
60
+ fetch(chatRequest, options) {
61
+ return this.asyncContext.makeCancellable(options?.abortSignal, Native.UnauthenticatedChatConnection_send(this.asyncContext, this.chatService, buildHttpRequest(chatRequest), chatRequest.timeoutMillis ?? DEFAULT_CHAT_REQUEST_TIMEOUT_MILLIS));
62
+ }
63
+ disconnect() {
64
+ return Native.UnauthenticatedChatConnection_disconnect(this.asyncContext, this.chatService);
65
+ }
66
+ connectionInfo() {
67
+ return new ConnectionInfoImpl(Native.UnauthenticatedChatConnection_info(this.chatService));
68
+ }
69
+ }
70
+ exports.UnauthenticatedChatConnection = UnauthenticatedChatConnection;
71
+ class AuthenticatedChatConnection {
72
+ static async connect(asyncContext, connectionManager, username, password, receiveStories, listener, options) {
73
+ const nativeChatListener = makeNativeChatListener(asyncContext, listener);
74
+ const connect = Native.AuthenticatedChatConnection_connect(asyncContext, connectionManager, username, password, receiveStories);
75
+ const chat = await asyncContext.makeCancellable(options?.abortSignal, connect);
76
+ const connection = (0, net_1.newNativeHandle)(chat);
77
+ Native.AuthenticatedChatConnection_init_listener(connection, new WeakListenerWrapper(nativeChatListener));
78
+ return new AuthenticatedChatConnection(asyncContext, connection, nativeChatListener);
79
+ }
80
+ /**
81
+ * Creates a chat connection backed by a fake remote end.
82
+ *
83
+ * @param asyncContext the async runtime to use
84
+ * @param listener the listener to send events to
85
+ * @param alerts alerts to send immediately upon connect
86
+ * @returns an {@link AuthenticatedChatConnection} and handle for the remote
87
+ * end of the fake connection.
88
+ */
89
+ static fakeConnect(asyncContext, listener, alerts) {
90
+ const nativeChatListener = makeNativeChatListener(asyncContext, listener);
91
+ const fakeChat = (0, net_1.newNativeHandle)(Native.TESTING_FakeChatConnection_Create(asyncContext, new WeakListenerWrapper(nativeChatListener), alerts?.join('\n') ?? ''));
92
+ const chat = (0, net_1.newNativeHandle)(Native.TESTING_FakeChatConnection_TakeAuthenticatedChat(fakeChat));
93
+ return [
94
+ new AuthenticatedChatConnection(asyncContext, chat, nativeChatListener),
95
+ (0, net_1.newNativeHandle)(Native.TESTING_FakeChatConnection_TakeRemote(fakeChat)),
96
+ ];
97
+ }
98
+ constructor(asyncContext, chatService,
99
+ // Unused except to keep the listener alive since the Rust code only holds a
100
+ // weak reference to the same object.
101
+ chatListener) {
102
+ this.asyncContext = asyncContext;
103
+ this.chatService = chatService;
104
+ this.chatListener = chatListener;
105
+ }
106
+ fetch(chatRequest, options) {
107
+ return this.asyncContext.makeCancellable(options?.abortSignal, Native.AuthenticatedChatConnection_send(this.asyncContext, this.chatService, buildHttpRequest(chatRequest), chatRequest.timeoutMillis ?? DEFAULT_CHAT_REQUEST_TIMEOUT_MILLIS));
108
+ }
109
+ disconnect() {
110
+ return Native.AuthenticatedChatConnection_disconnect(this.asyncContext, this.chatService);
111
+ }
112
+ connectionInfo() {
113
+ return new ConnectionInfoImpl(Native.AuthenticatedChatConnection_info(this.chatService));
114
+ }
115
+ }
116
+ exports.AuthenticatedChatConnection = AuthenticatedChatConnection;
117
+ /**
118
+ * Holds a {@link Native.ChatListener} by {@link WeakRef} and delegates
119
+ * `ChatListener` calls to it.
120
+ *
121
+ * This lets us avoid passing anything across the bridge that has a normal
122
+ * (strong) reference to the app-side listener. The danger is that the passed-in
123
+ * listener might gain a reference to the JS connection object; that would
124
+ * result in a reference cycle that Node can't clean up because one of the
125
+ * references is through a Rust `Box`.
126
+ *
127
+ * When constructing a connection, calling code should wrap an app-side listener
128
+ * in this type and pass it across the bridge, then hold its own strong
129
+ * reference to the same listener as a field. This ensures that if there is a
130
+ * reference cycle between the connection and app-side listener, that cycle is
131
+ * visible to the Node runtime, while still ensuring the passed-in listener
132
+ * stays alive as long as the connection does.
133
+ */
134
+ class WeakListenerWrapper {
135
+ constructor(listener) {
136
+ this.listener = new WeakRef(listener);
137
+ }
138
+ _connection_interrupted(reason) {
139
+ this.listener.deref()?._connection_interrupted(reason);
140
+ }
141
+ _incoming_message(envelope, timestamp, ack) {
142
+ this.listener.deref()?._incoming_message(envelope, timestamp, ack);
143
+ }
144
+ _queue_empty() {
145
+ this.listener.deref()?._queue_empty();
146
+ }
147
+ _received_alerts(alerts) {
148
+ this.listener.deref()?._received_alerts(alerts);
149
+ }
150
+ }
151
+ function makeNativeChatListener(asyncContext, listener) {
152
+ if ('onQueueEmpty' in listener) {
153
+ return {
154
+ _incoming_message(envelope, timestamp, ack) {
155
+ listener.onIncomingMessage(envelope, timestamp, new ChatServerMessageAck(ack));
156
+ },
157
+ _queue_empty() {
158
+ listener.onQueueEmpty();
159
+ },
160
+ _received_alerts(alerts) {
161
+ listener.onReceivedAlerts?.(alerts);
162
+ },
163
+ _connection_interrupted(cause) {
164
+ listener.onConnectionInterrupted(cause);
165
+ },
166
+ };
167
+ }
168
+ return {
169
+ _incoming_message(_envelope, _timestamp, _ack) {
170
+ throw new Error('Event not supported on unauthenticated connection');
171
+ },
172
+ _queue_empty() {
173
+ throw new Error('Event not supported on unauthenticated connection');
174
+ },
175
+ _received_alerts(_alerts) {
176
+ throw new Error('Event not supported on unauthenticated connection');
177
+ },
178
+ _connection_interrupted(cause) {
179
+ listener.onConnectionInterrupted(cause);
180
+ },
181
+ };
182
+ }
183
+ function buildHttpRequest(chatRequest) {
184
+ const { verb, path, body, headers } = chatRequest;
185
+ const bodyBuffer = body !== undefined ? node_buffer_1.Buffer.from(body) : null;
186
+ const httpRequest = {
187
+ _nativeHandle: Native.HttpRequest_new(verb, path, bodyBuffer),
188
+ };
189
+ headers.forEach((header) => {
190
+ const [name, value] = header;
191
+ Native.HttpRequest_add_header(httpRequest, name, value);
192
+ });
193
+ return httpRequest;
194
+ }
195
+ exports.buildHttpRequest = buildHttpRequest;
196
+ //# sourceMappingURL=Chat.js.map
package/dist/net.d.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  /// <reference types="node" />
2
2
  import type { ReadonlyDeep } from 'type-fest';
3
3
  import * as Native from '../Native';
4
- import { LibSignalError } from './Errors';
5
- import { Wrapper } from '../Native';
6
4
  import { Buffer } from 'node:buffer';
5
+ import { CDSRequestOptionsType, CDSResponseType } from './net/CDSI';
6
+ import { ConnectionEventsListener, UnauthenticatedChatConnection, AuthenticatedChatConnection, ChatServiceListener } from './net/Chat';
7
+ export * from './net/CDSI';
8
+ export * from './net/Chat';
7
9
  export declare enum Environment {
8
10
  Staging = 0,
9
11
  Production = 1
@@ -12,28 +14,6 @@ export type ServiceAuth = {
12
14
  username: string;
13
15
  password: string;
14
16
  };
15
- export type CDSRequestOptionsType = {
16
- e164s: Array<string>;
17
- acisAndAccessKeys: Array<{
18
- aci: string;
19
- accessKey: string;
20
- }>;
21
- /**
22
- * @deprecated this option is ignored by the server.
23
- */
24
- returnAcisWithoutUaks: boolean;
25
- abortSignal?: AbortSignal;
26
- useNewConnectLogic?: boolean;
27
- };
28
- export type CDSResponseEntryType<Aci, Pni> = {
29
- aci: Aci | undefined;
30
- pni: Pni | undefined;
31
- };
32
- export type CDSResponseEntries<Aci, Pni> = Map<string, CDSResponseEntryType<Aci, Pni>>;
33
- export interface CDSResponseType<Aci, Pni> {
34
- entries: CDSResponseEntries<Aci, Pni>;
35
- debugPermitsUsed: number;
36
- }
37
17
  export type ChatRequest = Readonly<{
38
18
  verb: string;
39
19
  path: string;
@@ -41,113 +21,14 @@ export type ChatRequest = Readonly<{
41
21
  body?: Uint8Array;
42
22
  timeoutMillis?: number;
43
23
  }>;
44
- type ConnectionManager = Wrapper<Native.ConnectionManager>;
45
- export declare function newNativeHandle<T>(handle: T): Wrapper<T>;
24
+ type ConnectionManager = Native.Wrapper<Native.ConnectionManager>;
25
+ export declare function newNativeHandle<T>(handle: T): Native.Wrapper<T>;
46
26
  /** Low-level async runtime control, mostly just exported for testing. */
47
27
  export declare class TokioAsyncContext {
48
28
  readonly _nativeHandle: Native.TokioAsyncContext;
49
29
  constructor(handle: Native.TokioAsyncContext);
50
30
  makeCancellable<T>(abortSignal: AbortSignal | undefined, promise: Native.CancellablePromise<T>): Promise<T>;
51
31
  }
52
- export declare class ChatServerMessageAck {
53
- readonly _nativeHandle: Native.ServerMessageAck;
54
- constructor(_nativeHandle: Native.ServerMessageAck);
55
- send(statusCode: number): void;
56
- }
57
- export interface ConnectionEventsListener {
58
- /**
59
- * Called when the client gets disconnected from the server.
60
- *
61
- * This includes both deliberate disconnects as well as unexpected socket
62
- * closures. If the closure was not due to a deliberate disconnect, the error
63
- * will be provided.
64
- */
65
- onConnectionInterrupted(cause: LibSignalError | null): void;
66
- }
67
- export interface ChatServiceListener extends ConnectionEventsListener {
68
- /**
69
- * Called when the server delivers an incoming message to the client.
70
- *
71
- * `timestamp` is in milliseconds.
72
- *
73
- * If `ack`'s `send` method is not called, the server will leave this message in the message
74
- * queue and attempt to deliver it again in the future.
75
- */
76
- onIncomingMessage(envelope: Buffer, timestamp: number, ack: ChatServerMessageAck): void;
77
- /**
78
- * Called when the server indicates that there are no further messages in the message queue.
79
- *
80
- * Note that further messages may still be delivered; this merely indicates that all messages that
81
- * were in the queue *when the connection was established* have been delivered.
82
- */
83
- onQueueEmpty(): void;
84
- }
85
- /**
86
- * A connection to the Chat Service.
87
- *
88
- * Provides API methods to communicate with the remote service. Make sure to
89
- * call {@link #disconnect()} when the instance is no longer needed.
90
- */
91
- export type ChatConnection = {
92
- /**
93
- * Initiates termination of the underlying connection to the Chat Service. After the service is
94
- * disconnected, it cannot be used again.
95
- */
96
- disconnect(): Promise<void>;
97
- /**
98
- * Sends request to the Chat service.
99
- */
100
- fetch(chatRequest: ChatRequest, options?: {
101
- abortSignal?: AbortSignal;
102
- }): Promise<Native.ChatResponse>;
103
- /**
104
- * Information about the connection to the Chat service.
105
- */
106
- connectionInfo(): ConnectionInfo;
107
- };
108
- export interface ConnectionInfo {
109
- localPort: number;
110
- ipVersion: 'IPv4' | 'IPv6';
111
- toString: () => string;
112
- }
113
- export declare class UnauthenticatedChatConnection implements ChatConnection {
114
- private readonly asyncContext;
115
- private readonly chatService;
116
- private readonly chatListener;
117
- static connect(asyncContext: TokioAsyncContext, connectionManager: ConnectionManager, listener: ConnectionEventsListener, options?: {
118
- abortSignal?: AbortSignal;
119
- }): Promise<UnauthenticatedChatConnection>;
120
- private constructor();
121
- fetch(chatRequest: ChatRequest, options?: {
122
- abortSignal?: AbortSignal;
123
- }): Promise<Native.ChatResponse>;
124
- disconnect(): Promise<void>;
125
- connectionInfo(): ConnectionInfo;
126
- }
127
- export declare class AuthenticatedChatConnection implements ChatConnection {
128
- private readonly asyncContext;
129
- private readonly chatService;
130
- private readonly chatListener;
131
- static connect(asyncContext: TokioAsyncContext, connectionManager: ConnectionManager, username: string, password: string, receiveStories: boolean, listener: ChatServiceListener, options?: {
132
- abortSignal?: AbortSignal;
133
- }): Promise<AuthenticatedChatConnection>;
134
- /**
135
- * Creates a chat connection backed by a fake remote end.
136
- *
137
- * @param asyncContext the async runtime to use
138
- * @param listener the listener to send events to
139
- * @returns an {@link AuthenticatedChatConnection} and handle for the remote
140
- * end of the fake connection.
141
- */
142
- static fakeConnect(asyncContext: TokioAsyncContext, listener: ChatServiceListener): [AuthenticatedChatConnection, Wrapper<Native.FakeChatRemoteEnd>];
143
- private constructor();
144
- fetch(chatRequest: ChatRequest, options?: {
145
- abortSignal?: AbortSignal;
146
- }): Promise<Native.ChatResponse>;
147
- disconnect(): Promise<void>;
148
- connectionInfo(): ConnectionInfo;
149
- }
150
- export declare function buildHttpRequest(chatRequest: ChatRequest): Wrapper<Native.HttpRequest>;
151
32
  export type NetConstructorOptions = Readonly<{
152
33
  localTestServer?: false;
153
34
  env: Environment;
@@ -279,6 +160,5 @@ export declare class Net {
279
160
  * This will lead to, e.g. caches being cleared and cooldowns being reset.
280
161
  */
281
162
  onNetworkChange(): void;
282
- cdsiLookup({ username, password }: Readonly<ServiceAuth>, { e164s, acisAndAccessKeys, abortSignal, useNewConnectLogic, }: ReadonlyDeep<CDSRequestOptionsType>): Promise<CDSResponseType<string, string>>;
163
+ cdsiLookup(auth: Readonly<ServiceAuth>, options: ReadonlyDeep<CDSRequestOptionsType>): Promise<CDSResponseType<string, string>>;
283
164
  }
284
- export {};
package/dist/net.js CHANGED
@@ -3,12 +3,27 @@
3
3
  // Copyright 2023 Signal Messenger, LLC.
4
4
  // SPDX-License-Identifier: AGPL-3.0-only
5
5
  //
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
18
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
19
+ };
6
20
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.Net = exports.SIGNAL_TLS_PROXY_SCHEME = exports.buildHttpRequest = exports.AuthenticatedChatConnection = exports.UnauthenticatedChatConnection = exports.ChatServerMessageAck = exports.TokioAsyncContext = exports.newNativeHandle = exports.Environment = void 0;
21
+ exports.Net = exports.SIGNAL_TLS_PROXY_SCHEME = exports.TokioAsyncContext = exports.newNativeHandle = exports.Environment = void 0;
8
22
  const Native = require("../Native");
9
- const Address_1 = require("./Address");
10
- const node_buffer_1 = require("node:buffer");
11
- const DEFAULT_CHAT_REQUEST_TIMEOUT_MILLIS = 5000;
23
+ const CDSI_1 = require("./net/CDSI");
24
+ const Chat_1 = require("./net/Chat");
25
+ __exportStar(require("./net/CDSI"), exports);
26
+ __exportStar(require("./net/Chat"), exports);
12
27
  // This must match the libsignal-bridge Rust enum of the same name.
13
28
  var Environment;
14
29
  (function (Environment) {
@@ -43,180 +58,6 @@ class TokioAsyncContext {
43
58
  }
44
59
  }
45
60
  exports.TokioAsyncContext = TokioAsyncContext;
46
- class ChatServerMessageAck {
47
- constructor(_nativeHandle) {
48
- this._nativeHandle = _nativeHandle;
49
- }
50
- send(statusCode) {
51
- Native.ServerMessageAck_SendStatus(this, statusCode);
52
- }
53
- }
54
- exports.ChatServerMessageAck = ChatServerMessageAck;
55
- class ConnectionInfoImpl {
56
- constructor(_nativeHandle) {
57
- this._nativeHandle = _nativeHandle;
58
- }
59
- get localPort() {
60
- return Native.ChatConnectionInfo_local_port(this);
61
- }
62
- get ipVersion() {
63
- const value = Native.ChatConnectionInfo_ip_version(this);
64
- switch (value) {
65
- case 1:
66
- return 'IPv4';
67
- case 2:
68
- return 'IPv6';
69
- default:
70
- throw new TypeError(`ip type was unexpectedly ${value}`);
71
- }
72
- }
73
- toString() {
74
- return Native.ChatConnectionInfo_description(this);
75
- }
76
- }
77
- class UnauthenticatedChatConnection {
78
- static async connect(asyncContext, connectionManager, listener, options) {
79
- const nativeChatListener = makeNativeChatListener(asyncContext, listener);
80
- const connect = Native.UnauthenticatedChatConnection_connect(asyncContext, connectionManager);
81
- const chat = await asyncContext.makeCancellable(options?.abortSignal, connect);
82
- const connection = newNativeHandle(chat);
83
- Native.UnauthenticatedChatConnection_init_listener(connection, new WeakListenerWrapper(nativeChatListener));
84
- return new UnauthenticatedChatConnection(asyncContext, connection, nativeChatListener);
85
- }
86
- constructor(asyncContext, chatService,
87
- // Unused except to keep the listener alive since the Rust code only holds a
88
- // weak reference to the same object.
89
- chatListener) {
90
- this.asyncContext = asyncContext;
91
- this.chatService = chatService;
92
- this.chatListener = chatListener;
93
- }
94
- fetch(chatRequest, options) {
95
- return this.asyncContext.makeCancellable(options?.abortSignal, Native.UnauthenticatedChatConnection_send(this.asyncContext, this.chatService, buildHttpRequest(chatRequest), chatRequest.timeoutMillis ?? DEFAULT_CHAT_REQUEST_TIMEOUT_MILLIS));
96
- }
97
- disconnect() {
98
- return Native.UnauthenticatedChatConnection_disconnect(this.asyncContext, this.chatService);
99
- }
100
- connectionInfo() {
101
- return new ConnectionInfoImpl(Native.UnauthenticatedChatConnection_info(this.chatService));
102
- }
103
- }
104
- exports.UnauthenticatedChatConnection = UnauthenticatedChatConnection;
105
- class AuthenticatedChatConnection {
106
- static async connect(asyncContext, connectionManager, username, password, receiveStories, listener, options) {
107
- const nativeChatListener = makeNativeChatListener(asyncContext, listener);
108
- const connect = Native.AuthenticatedChatConnection_connect(asyncContext, connectionManager, username, password, receiveStories);
109
- const chat = await asyncContext.makeCancellable(options?.abortSignal, connect);
110
- const connection = newNativeHandle(chat);
111
- Native.AuthenticatedChatConnection_init_listener(connection, new WeakListenerWrapper(nativeChatListener));
112
- return new AuthenticatedChatConnection(asyncContext, connection, nativeChatListener);
113
- }
114
- /**
115
- * Creates a chat connection backed by a fake remote end.
116
- *
117
- * @param asyncContext the async runtime to use
118
- * @param listener the listener to send events to
119
- * @returns an {@link AuthenticatedChatConnection} and handle for the remote
120
- * end of the fake connection.
121
- */
122
- static fakeConnect(asyncContext, listener) {
123
- const nativeChatListener = makeNativeChatListener(asyncContext, listener);
124
- const fakeChat = newNativeHandle(Native.TESTING_FakeChatConnection_Create(asyncContext, new WeakListenerWrapper(nativeChatListener)));
125
- const chat = newNativeHandle(Native.TESTING_FakeChatConnection_TakeAuthenticatedChat(fakeChat));
126
- return [
127
- new AuthenticatedChatConnection(asyncContext, chat, nativeChatListener),
128
- newNativeHandle(Native.TESTING_FakeChatConnection_TakeRemote(fakeChat)),
129
- ];
130
- }
131
- constructor(asyncContext, chatService,
132
- // Unused except to keep the listener alive since the Rust code only holds a
133
- // weak reference to the same object.
134
- chatListener) {
135
- this.asyncContext = asyncContext;
136
- this.chatService = chatService;
137
- this.chatListener = chatListener;
138
- }
139
- fetch(chatRequest, options) {
140
- return this.asyncContext.makeCancellable(options?.abortSignal, Native.AuthenticatedChatConnection_send(this.asyncContext, this.chatService, buildHttpRequest(chatRequest), chatRequest.timeoutMillis ?? DEFAULT_CHAT_REQUEST_TIMEOUT_MILLIS));
141
- }
142
- disconnect() {
143
- return Native.AuthenticatedChatConnection_disconnect(this.asyncContext, this.chatService);
144
- }
145
- connectionInfo() {
146
- return new ConnectionInfoImpl(Native.AuthenticatedChatConnection_info(this.chatService));
147
- }
148
- }
149
- exports.AuthenticatedChatConnection = AuthenticatedChatConnection;
150
- /**
151
- * Holds a {@link Native.ChatListener} by {@link WeakRef} and delegates
152
- * `ChatListener` calls to it.
153
- *
154
- * This lets us avoid passing anything across the bridge that has a normal
155
- * (strong) reference to the app-side listener. The danger is that the passed-in
156
- * listener might gain a reference to the JS connection object; that would
157
- * result in a reference cycle that Node can't clean up because one of the
158
- * references is through a Rust `Box`.
159
- *
160
- * When constructing a connection, calling code should wrap an app-side listener
161
- * in this type and pass it across the bridge, then hold its own strong
162
- * reference to the same listener as a field. This ensures that if there is a
163
- * reference cycle between the connection and app-side listener, that cycle is
164
- * visible to the Node runtime, while still ensuring the passed-in listener
165
- * stays alive as long as the connection does.
166
- */
167
- class WeakListenerWrapper {
168
- constructor(listener) {
169
- this.listener = new WeakRef(listener);
170
- }
171
- _connection_interrupted(reason) {
172
- this.listener.deref()?._connection_interrupted(reason);
173
- }
174
- _incoming_message(envelope, timestamp, ack) {
175
- this.listener.deref()?._incoming_message(envelope, timestamp, ack);
176
- }
177
- _queue_empty() {
178
- this.listener.deref()?._queue_empty();
179
- }
180
- }
181
- function makeNativeChatListener(asyncContext, listener) {
182
- if ('onQueueEmpty' in listener) {
183
- return {
184
- _incoming_message(envelope, timestamp, ack) {
185
- listener.onIncomingMessage(envelope, timestamp, new ChatServerMessageAck(ack));
186
- },
187
- _queue_empty() {
188
- listener.onQueueEmpty();
189
- },
190
- _connection_interrupted(cause) {
191
- listener.onConnectionInterrupted(cause);
192
- },
193
- };
194
- }
195
- return {
196
- _incoming_message(_envelope, _timestamp, _ack) {
197
- throw new Error('Event not supported on unauthenticated connection');
198
- },
199
- _queue_empty() {
200
- throw new Error('Event not supported on unauthenticated connection');
201
- },
202
- _connection_interrupted(cause) {
203
- listener.onConnectionInterrupted(cause);
204
- },
205
- };
206
- }
207
- function buildHttpRequest(chatRequest) {
208
- const { verb, path, body, headers } = chatRequest;
209
- const bodyBuffer = body !== undefined ? node_buffer_1.Buffer.from(body) : null;
210
- const httpRequest = {
211
- _nativeHandle: Native.HttpRequest_new(verb, path, bodyBuffer),
212
- };
213
- headers.forEach((header) => {
214
- const [name, value] = header;
215
- Native.HttpRequest_add_header(httpRequest, name, value);
216
- });
217
- return httpRequest;
218
- }
219
- exports.buildHttpRequest = buildHttpRequest;
220
61
  /** The "scheme" for Signal TLS proxies. See {@link Net.setProxy()}. */
221
62
  exports.SIGNAL_TLS_PROXY_SCHEME = 'org.signal.tls';
222
63
  class Net {
@@ -238,13 +79,13 @@ class Net {
238
79
  * @returns the connected listener, if the connection succeeds.
239
80
  */
240
81
  async connectUnauthenticatedChat(listener, options) {
241
- return UnauthenticatedChatConnection.connect(this.asyncContext, this._connectionManager, listener, options);
82
+ return Chat_1.UnauthenticatedChatConnection.connect(this.asyncContext, this._connectionManager, listener, options);
242
83
  }
243
84
  /**
244
85
  * Creates a new instance of {@link AuthenticatedChatConnection}.
245
86
  */
246
87
  connectAuthenticatedChat(username, password, receiveStories, listener, options) {
247
- return AuthenticatedChatConnection.connect(this.asyncContext, this._connectionManager, username, password, receiveStories, listener, options);
88
+ return Chat_1.AuthenticatedChatConnection.connect(this.asyncContext, this._connectionManager, username, password, receiveStories, listener, options);
248
89
  }
249
90
  /**
250
91
  * Enables/disables IPv6 for all new connections (until changed).
@@ -376,19 +217,11 @@ class Net {
376
217
  onNetworkChange() {
377
218
  Native.ConnectionManager_on_network_change(this._connectionManager);
378
219
  }
379
- async cdsiLookup({ username, password }, { e164s, acisAndAccessKeys, abortSignal, useNewConnectLogic, }) {
380
- const request = newNativeHandle(Native.LookupRequest_new());
381
- e164s.forEach((e164) => {
382
- Native.LookupRequest_addE164(request, e164);
383
- });
384
- acisAndAccessKeys.forEach(({ aci: aciStr, accessKey: accessKeyStr }) => {
385
- Native.LookupRequest_addAciAndAccessKey(request, Address_1.Aci.parseFromServiceIdString(aciStr).getServiceIdFixedWidthBinary(), node_buffer_1.Buffer.from(accessKeyStr, 'base64'));
386
- });
387
- const startLookup = useNewConnectLogic
388
- ? Native.CdsiLookup_new_routes
389
- : Native.CdsiLookup_new;
390
- const lookup = await this.asyncContext.makeCancellable(abortSignal, startLookup(this.asyncContext, this._connectionManager, username, password, request));
391
- return await this.asyncContext.makeCancellable(abortSignal, Native.CdsiLookup_complete(this.asyncContext, newNativeHandle(lookup)));
220
+ async cdsiLookup(auth, options) {
221
+ return (0, CDSI_1.cdsiLookup)({
222
+ asyncContext: this.asyncContext,
223
+ connectionManager: this._connectionManager,
224
+ }, auth, options);
392
225
  }
393
226
  }
394
227
  exports.Net = Net;
@@ -4,6 +4,12 @@ import NotarySignature from './NotarySignature';
4
4
  export default class ServerPublicParams {
5
5
  readonly _nativeHandle: Native.ServerPublicParams;
6
6
  constructor(contents: Buffer | Native.ServerPublicParams);
7
+ /**
8
+ * Get the serialized form of the params' endorsement key.
9
+ *
10
+ * Allows decoupling RingRTC's use of endorsements from libsignal's.
11
+ */
12
+ getEndorsementPublicKey(): Buffer;
7
13
  verifySignature(message: Buffer, notarySignature: NotarySignature): void;
8
14
  serialize(): Buffer;
9
15
  }
@@ -14,6 +14,14 @@ class ServerPublicParams {
14
14
  this._nativeHandle = contents;
15
15
  }
16
16
  }
17
+ /**
18
+ * Get the serialized form of the params' endorsement key.
19
+ *
20
+ * Allows decoupling RingRTC's use of endorsements from libsignal's.
21
+ */
22
+ getEndorsementPublicKey() {
23
+ return Native.ServerPublicParams_GetEndorsementPublicKey(this);
24
+ }
17
25
  verifySignature(message, notarySignature) {
18
26
  Native.ServerPublicParams_VerifySignature(this, message, notarySignature.getContents());
19
27
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signalapp/libsignal-client",
3
- "version": "0.67.1",
3
+ "version": "0.67.3",
4
4
  "license": "AGPL-3.0-only",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -8,6 +8,8 @@
8
8
  "dist/acknowledgments.md",
9
9
  "dist/*.js",
10
10
  "dist/*.d.ts",
11
+ "dist/net/**/*.js",
12
+ "dist/net/**/*.d.ts",
11
13
  "dist/zkgroup/**/*.js",
12
14
  "dist/zkgroup/**/*.d.ts",
13
15
  "Native.js",