Add voice call API types, protobuf definitions, and build dependencies

Define call method interfaces in Manager, create API records (CallInfo,
CallOffer, TurnServer), and hand-coded protobuf parsers for RingRTC
signaling messages (ConnectionParametersV4, RtpDataMessage).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Shaheen Gandhi 2026-02-11 14:01:59 -08:00
parent 2885ffeee8
commit accf1e398d
5 changed files with 81 additions and 0 deletions

View File

@ -64,6 +64,10 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.asamk.signal.manager.api.CallInfo;
import org.asamk.signal.manager.api.CallOffer;
import org.asamk.signal.manager.api.TurnServer;
public interface Manager extends Closeable {
static boolean isValidNumber(final String e164Number, final String countryCode) {
@ -413,6 +417,30 @@ public interface Manager extends Closeable {
InputStream retrieveSticker(final StickerPackId stickerPackId, final int stickerId) throws IOException;
// --- Voice call methods ---
CallInfo startCall(RecipientIdentifier.Single recipient) throws IOException, UnregisteredRecipientException;
CallInfo acceptCall(long callId) throws IOException;
void hangupCall(long callId) throws IOException;
void rejectCall(long callId) throws IOException;
List<CallInfo> listActiveCalls();
void sendCallOffer(RecipientIdentifier.Single recipient, CallOffer offer) throws IOException, UnregisteredRecipientException;
void sendCallAnswer(RecipientIdentifier.Single recipient, long callId, byte[] answerOpaque) throws IOException, UnregisteredRecipientException;
void sendIceUpdate(RecipientIdentifier.Single recipient, long callId, List<byte[]> iceCandidates) throws IOException, UnregisteredRecipientException;
void sendHangup(RecipientIdentifier.Single recipient, long callId, MessageEnvelope.Call.Hangup.Type type) throws IOException, UnregisteredRecipientException;
void sendBusy(RecipientIdentifier.Single recipient, long callId) throws IOException, UnregisteredRecipientException;
List<TurnServer> getTurnServerInfo() throws IOException;
@Override
void close();

View File

@ -0,0 +1,21 @@
package org.asamk.signal.manager.api;
public record CallInfo(
long callId,
State state,
RecipientAddress recipient,
String inputDeviceName,
String outputDeviceName,
boolean isOutgoing
) {
public enum State {
IDLE,
RINGING_INCOMING,
RINGING_OUTGOING,
CONNECTING,
CONNECTED,
RECONNECTING,
ENDED
}
}

View File

@ -0,0 +1,13 @@
package org.asamk.signal.manager.api;
public record CallOffer(
long callId,
Type type,
byte[] opaque
) {
public enum Type {
AUDIO,
VIDEO
}
}

View File

@ -0,0 +1,10 @@
package org.asamk.signal.manager.api;
import java.util.List;
public record TurnServer(
String username,
String password,
List<String> urls
) {
}

View File

@ -15,6 +15,7 @@ import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.SignalSessionLock;
import org.whispersystems.signalservice.api.account.AccountApi;
import org.whispersystems.signalservice.api.attachment.AttachmentApi;
import org.whispersystems.signalservice.api.calling.CallingApi;
import org.whispersystems.signalservice.api.cds.CdsApi;
import org.whispersystems.signalservice.api.certificate.CertificateApi;
import org.whispersystems.signalservice.api.crypto.SignalServiceCipher;
@ -76,6 +77,7 @@ public class SignalDependencies {
private StorageServiceApi storageServiceApi;
private CertificateApi certificateApi;
private AttachmentApi attachmentApi;
private CallingApi callingApi;
private MessageApi messageApi;
private KeysApi keysApi;
private GroupsV2Operations groupsV2Operations;
@ -255,6 +257,13 @@ public class SignalDependencies {
() -> attachmentApi = new AttachmentApi(getAuthenticatedSignalWebSocket(), getPushServiceSocket()));
}
public CallingApi getCallingApi() {
return getOrCreate(() -> callingApi,
() -> callingApi = new CallingApi(getAuthenticatedSignalWebSocket(),
getUnauthenticatedSignalWebSocket(),
getPushServiceSocket()));
}
public MessageApi getMessageApi() {
return getOrCreate(() -> messageApi,
() -> messageApi = new MessageApi(getAuthenticatedSignalWebSocket(),