@signalapp/libsignal-client
Advanced tools
Comparing version 0.50.0 to 0.51.0
@@ -5,2 +5,3 @@ /// <reference types="node" /> | ||
import { Wrapper } from '../Native'; | ||
import { Buffer } from 'node:buffer'; | ||
export declare enum Environment { | ||
@@ -46,2 +47,37 @@ Staging = 0, | ||
} | ||
export declare class ChatServerMessageAck { | ||
private readonly asyncContext; | ||
readonly _nativeHandle: Native.ServerMessageAck; | ||
private promise; | ||
constructor(asyncContext: TokioAsyncContext, _nativeHandle: Native.ServerMessageAck); | ||
send(): Promise<void>; | ||
} | ||
export interface ChatServiceListener { | ||
/** | ||
* Called when the server delivers an incoming message to the client. | ||
* | ||
* `timestamp` is in milliseconds. | ||
* | ||
* If `ack`'s `send` method is not called, the server will leave this message in the message | ||
* queue and attempt to deliver it again in the future. | ||
*/ | ||
onIncomingMessage(envelope: Buffer, timestamp: number, ack: ChatServerMessageAck): void; | ||
/** | ||
* Called when the server indicates that there are no further messages in the message queue. | ||
* | ||
* Note that further messages may still be delivered; this merely indicates that all messages that | ||
* were in the queue *when the connection was established* have been delivered. | ||
*/ | ||
onQueueEmpty(): void; | ||
/** | ||
* Called when the client gets disconnected from the server. | ||
* | ||
* This includes both deliberate disconnects as well as unexpected socket closures that will be | ||
* automatically retried. | ||
* | ||
* Will not be called if no other requests have been invoked for this connection attempt. That is, | ||
* you should never see this as the first callback, nor two of these callbacks in a row. | ||
*/ | ||
onConnectionInterrupted(): void; | ||
} | ||
/** | ||
@@ -55,5 +91,16 @@ * Provides API methods to connect and communicate with the Chat Service. | ||
private readonly asyncContext; | ||
private readonly chatService; | ||
readonly chatService: Wrapper<Native.Chat>; | ||
constructor(asyncContext: TokioAsyncContext, connectionManager: ConnectionManager); | ||
/** | ||
* Sets the listener for server push messages on the authenticated connection. | ||
* | ||
* Note that this creates a **non-garbage-collectable** reference to `listener`. If `listener` | ||
* contains a reference to this ChatService (directly or indirectly), both objects will be kept | ||
* alive even with no other references. This may be fine if `listener` is a long-lived object | ||
* anyway, but if not, make sure to eventually break the cycle, possibly by calling | ||
* {@link #clearListener}. | ||
*/ | ||
setListener(listener: ChatServiceListener): void; | ||
clearListener(): void; | ||
/** | ||
* Initiates termination of the underlying connection to the Chat Service. After the service is | ||
@@ -86,2 +133,3 @@ * disconnected, it will not attempt to automatically reconnect until you call | ||
* Calling this method will result in starting to accept incoming requests from the Chat Service. | ||
* You should set a listener first using {@link #setListener()}. | ||
* | ||
@@ -88,0 +136,0 @@ * @throws {AppExpiredError} if the current app version is too old (as judged by the server). |
@@ -7,5 +7,6 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.RestoredSecret = exports.Net = exports.ChatService = exports.TokioAsyncContext = exports.Environment = void 0; | ||
exports.RestoredSecret = exports.Net = exports.ChatService = exports.ChatServerMessageAck = exports.TokioAsyncContext = exports.Environment = void 0; | ||
const Native = require("../Native"); | ||
const Address_1 = require("./Address"); | ||
const node_buffer_1 = require("node:buffer"); | ||
const DEFAULT_CHAT_REQUEST_TIMEOUT_MILLIS = 5000; | ||
@@ -47,2 +48,16 @@ // This must match the libsignal-bridge Rust enum of the same name. | ||
exports.TokioAsyncContext = TokioAsyncContext; | ||
class ChatServerMessageAck { | ||
constructor(asyncContext, _nativeHandle) { | ||
this.asyncContext = asyncContext; | ||
this._nativeHandle = _nativeHandle; | ||
this.promise = null; | ||
} | ||
send() { | ||
if (!this.promise) { | ||
this.promise = Native.ServerMessageAck_Send(this.asyncContext, this); | ||
} | ||
return this.promise; | ||
} | ||
} | ||
exports.ChatServerMessageAck = ChatServerMessageAck; | ||
/** | ||
@@ -60,2 +75,29 @@ * Provides API methods to connect and communicate with the Chat Service. | ||
/** | ||
* Sets the listener for server push messages on the authenticated connection. | ||
* | ||
* Note that this creates a **non-garbage-collectable** reference to `listener`. If `listener` | ||
* contains a reference to this ChatService (directly or indirectly), both objects will be kept | ||
* alive even with no other references. This may be fine if `listener` is a long-lived object | ||
* anyway, but if not, make sure to eventually break the cycle, possibly by calling | ||
* {@link #clearListener}. | ||
*/ | ||
setListener(listener) { | ||
const asyncContext = this.asyncContext; | ||
const nativeChatListener = { | ||
_incoming_message(envelope, timestamp, ack) { | ||
listener.onIncomingMessage(envelope, timestamp, new ChatServerMessageAck(asyncContext, ack)); | ||
}, | ||
_queue_empty() { | ||
listener.onQueueEmpty(); | ||
}, | ||
_connection_interrupted() { | ||
listener.onConnectionInterrupted(); | ||
}, | ||
}; | ||
Native.ChatServer_SetListener(asyncContext, this.chatService, nativeChatListener); | ||
} | ||
clearListener() { | ||
Native.ChatServer_SetListener(this.asyncContext, this.chatService, null); | ||
} | ||
/** | ||
* Initiates termination of the underlying connection to the Chat Service. After the service is | ||
@@ -90,2 +132,3 @@ * disconnected, it will not attempt to automatically reconnect until you call | ||
* Calling this method will result in starting to accept incoming requests from the Chat Service. | ||
* You should set a listener first using {@link #setListener()}. | ||
* | ||
@@ -143,3 +186,3 @@ * @throws {AppExpiredError} if the current app version is too old (as judged by the server). | ||
const { verb, path, body, headers } = chatRequest; | ||
const bodyBuffer = body !== undefined ? Buffer.from(body) : null; | ||
const bodyBuffer = body !== undefined ? node_buffer_1.Buffer.from(body) : null; | ||
const httpRequest = { | ||
@@ -203,3 +246,3 @@ _nativeHandle: Native.HttpRequest_new(verb, path, bodyBuffer), | ||
acisAndAccessKeys.forEach(({ aci: aciStr, accessKey: accessKeyStr }) => { | ||
Native.LookupRequest_addAciAndAccessKey(request, Address_1.Aci.parseFromServiceIdString(aciStr).getServiceIdFixedWidthBinary(), Buffer.from(accessKeyStr, 'base64')); | ||
Native.LookupRequest_addAciAndAccessKey(request, Address_1.Aci.parseFromServiceIdString(aciStr).getServiceIdFixedWidthBinary(), node_buffer_1.Buffer.from(accessKeyStr, 'base64')); | ||
}); | ||
@@ -206,0 +249,0 @@ Native.LookupRequest_setReturnAcisWithoutUaks(request, returnAcisWithoutUaks); |
@@ -117,2 +117,14 @@ // | ||
export abstract class ChatListener { | ||
_incoming_message( | ||
envelope: Buffer, | ||
timestamp: number, | ||
ack: ServerMessageAck | ||
): void; | ||
_queue_empty(): void; | ||
_connection_interrupted(): void; | ||
} | ||
export abstract class MakeChatListener extends ChatListener {} | ||
type Wrapper<T> = Readonly<{ | ||
@@ -172,2 +184,3 @@ _nativeHandle: T; | ||
export function CdsiLookup_token(lookup: Wrapper<CdsiLookup>): Buffer; | ||
export function ChatServer_SetListener(runtime: Wrapper<TokioAsyncContext>, chat: Wrapper<Chat>, makeListener: MakeChatListener | null): void; | ||
export function ChatService_auth_send(asyncRuntime: Wrapper<TokioAsyncContext>, chat: Wrapper<Chat>, httpRequest: Wrapper<HttpRequest>, timeoutMillis: number): Promise<ChatResponse>; | ||
@@ -485,2 +498,3 @@ export function ChatService_auth_send_and_debug(asyncRuntime: Wrapper<TokioAsyncContext>, chat: Wrapper<Chat>, httpRequest: Wrapper<HttpRequest>, timeoutMillis: number): Promise<ResponseAndDebugInfo>; | ||
export function TESTING_ChatServiceResponseConvert(bodyPresent: boolean): ChatResponse; | ||
export function TESTING_ChatService_InjectConnectionInterrupted(chat: Wrapper<Chat>): void; | ||
export function TESTING_ChatService_InjectRawServerRequest(chat: Wrapper<Chat>, bytes: Buffer): void; | ||
@@ -487,0 +501,0 @@ export function TESTING_ErrorOnBorrowAsync(_input: null): Promise<void>; |
{ | ||
"name": "@signalapp/libsignal-client", | ||
"version": "0.50.0", | ||
"version": "0.51.0", | ||
"license": "AGPL-3.0-only", | ||
@@ -22,2 +22,3 @@ "main": "dist/index.js", | ||
"build": "node-gyp build", | ||
"build-with-debug-level-logs": "npx --libsignal-debug-level-logs node-gyp build", | ||
"tsc": "tsc -b", | ||
@@ -43,2 +44,4 @@ "clean": "rimraf dist build prebuilds", | ||
"@types/node": "~18.15.0", | ||
"@types/sinon": "^17.0.3", | ||
"@types/sinon-chai": "^3.2.12", | ||
"@types/uuid": "^8.3.0", | ||
@@ -62,2 +65,4 @@ "@typescript-eslint/eslint-plugin": "^5.47.0", | ||
"rimraf": "^3.0.1", | ||
"sinon": "^18.0.0", | ||
"sinon-chai": "^3.7.0", | ||
"source-map-support": "^0.5.19", | ||
@@ -64,0 +69,0 @@ "typescript": "4.9.3" |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
90418623
6251
0
31