NekoX/TMessagesProj/src/main/java/org/telegram/messenger/voip/Instance.java

451 lines
16 KiB
Java

package org.telegram.messenger.voip;
import android.os.Build;
import org.json.JSONException;
import org.json.JSONObject;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.BuildVars;
import org.telegram.messenger.FileLog;
import org.webrtc.ContextUtils;
import org.webrtc.VideoSink;
import java.util.Arrays;
import java.util.List;
public final class Instance {
public static final List<String> AVAILABLE_VERSIONS = Build.VERSION.SDK_INT >= 18 ? Arrays.asList("4.1.2", "4.0.2", "4.0.1", "4.0.0", "3.0.0", "2.7.7", "2.4.4") : Arrays.asList("2.4.4");
public static final int AUDIO_STATE_MUTED = 0;
public static final int AUDIO_STATE_ACTIVE = 1;
public static final int VIDEO_STATE_INACTIVE = 0;
public static final int VIDEO_STATE_PAUSED = 1;
public static final int VIDEO_STATE_ACTIVE = 2;
//region Constants
public static final int NET_TYPE_UNKNOWN = 0;
public static final int NET_TYPE_GPRS = 1;
public static final int NET_TYPE_EDGE = 2;
public static final int NET_TYPE_3G = 3;
public static final int NET_TYPE_HSPA = 4;
public static final int NET_TYPE_LTE = 5;
public static final int NET_TYPE_WIFI = 6;
public static final int NET_TYPE_ETHERNET = 7;
public static final int NET_TYPE_OTHER_HIGH_SPEED = 8;
public static final int NET_TYPE_OTHER_LOW_SPEED = 9;
public static final int NET_TYPE_DIALUP = 10;
public static final int NET_TYPE_OTHER_MOBILE = 11;
public static final int ENDPOINT_TYPE_INET = 0;
public static final int ENDPOINT_TYPE_LAN = 1;
public static final int ENDPOINT_TYPE_UDP_RELAY = 2;
public static final int ENDPOINT_TYPE_TCP_RELAY = 3;
public static final int STATE_WAIT_INIT = 1;
public static final int STATE_WAIT_INIT_ACK = 2;
public static final int STATE_ESTABLISHED = 3;
public static final int STATE_FAILED = 4;
public static final int STATE_RECONNECTING = 5;
public static final int DATA_SAVING_NEVER = 0;
public static final int DATA_SAVING_MOBILE = 1;
public static final int DATA_SAVING_ALWAYS = 2;
public static final int DATA_SAVING_ROAMING = 3;
public static final int PEER_CAP_GROUP_CALLS = 1;
// Java-side Errors
public static final String ERROR_CONNECTION_SERVICE = "ERROR_CONNECTION_SERVICE";
public static final String ERROR_INSECURE_UPGRADE = "ERROR_INSECURE_UPGRADE";
public static final String ERROR_LOCALIZED = "ERROR_LOCALIZED";
public static final String ERROR_PRIVACY = "ERROR_PRIVACY";
public static final String ERROR_PEER_OUTDATED = "ERROR_PEER_OUTDATED";
// Native-side Errors
public static final String ERROR_UNKNOWN = "ERROR_UNKNOWN";
public static final String ERROR_INCOMPATIBLE = "ERROR_INCOMPATIBLE";
public static final String ERROR_TIMEOUT = "ERROR_TIMEOUT";
public static final String ERROR_AUDIO_IO = "ERROR_AUDIO_IO";
//endregion
private static ServerConfig globalServerConfig = new ServerConfig(new JSONObject());
private static int bufferSize;
private static NativeInstance instance;
private Instance() {
}
public static ServerConfig getGlobalServerConfig() {
return globalServerConfig;
}
public static void setGlobalServerConfig(String serverConfigJson) {
try {
globalServerConfig = new ServerConfig(new JSONObject(serverConfigJson));
if (instance != null) {
instance.setGlobalServerConfig(serverConfigJson);
}
} catch (JSONException e) {
if (BuildVars.LOGS_ENABLED) {
FileLog.e("failed to parse tgvoip server config", e);
}
}
}
public static void destroyInstance() {
instance = null;
}
public static NativeInstance makeInstance(String version, Config config, String persistentStateFilePath, Endpoint[] endpoints, Proxy proxy, int networkType, EncryptionKey encryptionKey, VideoSink remoteSink, long videoCapturer, NativeInstance.AudioLevelsCallback audioLevelsCallback) {
if (!"2.4.4".equals(version)) {
ContextUtils.initialize(ApplicationLoader.applicationContext);
}
instance = NativeInstance.make(version, config, persistentStateFilePath, endpoints, proxy, networkType, encryptionKey, remoteSink, videoCapturer, audioLevelsCallback);
setGlobalServerConfig(globalServerConfig.jsonObject.toString());
setBufferSize(bufferSize);
return instance;
}
public static void setBufferSize(int size) {
bufferSize = size;
if (instance != null) {
instance.setBufferSize(size);
}
}
public static int getConnectionMaxLayer() {
return 92;
}
public static String getVersion() {
return instance != null ? instance.getVersion() : null;
}
private static void checkHasDelegate() {
if (instance == null) {
throw new IllegalStateException("tgvoip version is not set");
}
}
public interface OnStateUpdatedListener {
void onStateUpdated(int state, boolean inTransition);
}
public interface OnSignalBarsUpdatedListener {
void onSignalBarsUpdated(int signalBars);
}
public interface OnSignalingDataListener {
void onSignalingData(byte[] data);
}
public interface OnRemoteMediaStateUpdatedListener {
void onMediaStateUpdated(int audioState, int videoState);
}
public static final class Config {
public final double initializationTimeout;
public final double receiveTimeout;
public final int dataSaving;
public final boolean enableP2p;
public final boolean enableAec;
public final boolean enableNs;
public final boolean enableAgc;
public final boolean enableCallUpgrade;
public final String logPath;
public final String statsLogPath;
public final int maxApiLayer;
public final boolean enableSm;
public Config(double initializationTimeout, double receiveTimeout, int dataSaving, boolean enableP2p, boolean enableAec, boolean enableNs, boolean enableAgc, boolean enableCallUpgrade, boolean enableSm, String logPath, String statsLogPath, int maxApiLayer) {
this.initializationTimeout = initializationTimeout;
this.receiveTimeout = receiveTimeout;
this.dataSaving = dataSaving;
this.enableP2p = enableP2p;
this.enableAec = enableAec;
this.enableNs = enableNs;
this.enableAgc = enableAgc;
this.enableCallUpgrade = enableCallUpgrade;
this.logPath = logPath;
this.statsLogPath = statsLogPath;
this.maxApiLayer = maxApiLayer;
this.enableSm = enableSm;
}
@Override
public String toString() {
return "Config{" +
"initializationTimeout=" + initializationTimeout +
", receiveTimeout=" + receiveTimeout +
", dataSaving=" + dataSaving +
", enableP2p=" + enableP2p +
", enableAec=" + enableAec +
", enableNs=" + enableNs +
", enableAgc=" + enableAgc +
", enableCallUpgrade=" + enableCallUpgrade +
", logPath='" + logPath + '\'' +
", statsLogPath='" + statsLogPath + '\'' +
", maxApiLayer=" + maxApiLayer +
", enableSm=" + enableSm +
'}';
}
}
public static final class Endpoint {
public final boolean isRtc;
public final long id;
public final String ipv4;
public final String ipv6;
public final int port;
public final int type;
public final byte[] peerTag;
public final boolean turn;
public final boolean stun;
public final String username;
public final String password;
public Endpoint(boolean isRtc, long id, String ipv4, String ipv6, int port, int type, byte[] peerTag, boolean turn, boolean stun, String username, String password) {
this.isRtc = isRtc;
this.id = id;
this.ipv4 = ipv4;
this.ipv6 = ipv6;
this.port = port;
this.type = type;
this.peerTag = peerTag;
this.turn = turn;
this.stun = stun;
this.username = username;
this.password = password;
}
@Override
public String toString() {
return "Endpoint{" +
"id=" + id +
", ipv4='" + ipv4 + '\'' +
", ipv6='" + ipv6 + '\'' +
", port=" + port +
", type=" + type +
", peerTag=" + Arrays.toString(peerTag) +
", turn=" + turn +
", stun=" + stun +
", username=" + username +
", password=" + password +
'}';
}
}
public static final class Proxy {
public final String host;
public final int port;
public final String login;
public final String password;
public Proxy(String host, int port, String login, String password) {
this.host = host;
this.port = port;
this.login = login;
this.password = password;
}
@Override
public String toString() {
return "Proxy{" +
"host='" + host + '\'' +
", port=" + port +
", login='" + login + '\'' +
", password='" + password + '\'' +
'}';
}
}
public static final class EncryptionKey {
public final byte[] value;
public final boolean isOutgoing;
public EncryptionKey(byte[] value, boolean isOutgoing) {
this.value = value;
this.isOutgoing = isOutgoing;
}
@Override
public String toString() {
return "EncryptionKey{" +
"value=" + Arrays.toString(value) +
", isOutgoing=" + isOutgoing +
'}';
}
}
public static final class FinalState {
public final byte[] persistentState;
public String debugLog;
public final TrafficStats trafficStats;
public final boolean isRatingSuggested;
public FinalState(byte[] persistentState, String debugLog, TrafficStats trafficStats, boolean isRatingSuggested) {
this.persistentState = persistentState;
this.debugLog = debugLog;
this.trafficStats = trafficStats;
this.isRatingSuggested = isRatingSuggested;
}
@Override
public String toString() {
return "FinalState{" +
"persistentState=" + Arrays.toString(persistentState) +
", debugLog='" + debugLog + '\'' +
", trafficStats=" + trafficStats +
", isRatingSuggested=" + isRatingSuggested +
'}';
}
}
public static final class TrafficStats {
public final long bytesSentWifi;
public final long bytesReceivedWifi;
public final long bytesSentMobile;
public final long bytesReceivedMobile;
public TrafficStats(long bytesSentWifi, long bytesReceivedWifi, long bytesSentMobile, long bytesReceivedMobile) {
this.bytesSentWifi = bytesSentWifi;
this.bytesReceivedWifi = bytesReceivedWifi;
this.bytesSentMobile = bytesSentMobile;
this.bytesReceivedMobile = bytesReceivedMobile;
}
@Override
public String toString() {
return "TrafficStats{" +
"bytesSentWifi=" + bytesSentWifi +
", bytesReceivedWifi=" + bytesReceivedWifi +
", bytesSentMobile=" + bytesSentMobile +
", bytesReceivedMobile=" + bytesReceivedMobile +
'}';
}
}
public static final class Fingerprint {
public final String hash;
public final String setup;
public final String fingerprint;
public Fingerprint(String hash, String setup, String fingerprint) {
this.hash = hash;
this.setup = setup;
this.fingerprint = fingerprint;
}
@Override
public String toString() {
return "Fingerprint{" +
"hash=" + hash +
", setup=" + setup +
", fingerprint=" + fingerprint +
'}';
}
}
public static final class Candidate {
public final String port;
public final String protocol;
public final String network;
public final String generation;
public final String id;
public final String component;
public final String foundation;
public final String priority;
public final String ip;
public final String type;
public final String tcpType;
public final String relAddr;
public final String relPort;
public Candidate(String port, String protocol, String network, String generation, String id, String component, String foundation, String priority, String ip, String type, String tcpType, String relAddr, String relPort) {
this.port = port;
this.protocol = protocol;
this.network = network;
this.generation = generation;
this.id = id;
this.component = component;
this.foundation = foundation;
this.priority = priority;
this.ip = ip;
this.type = type;
this.tcpType = tcpType;
this.relAddr = relAddr;
this.relPort = relPort;
}
@Override
public String toString() {
return "Candidate{" +
"port=" + port +
", protocol=" + protocol +
", network=" + network +
", generation=" + generation +
", id=" + id +
", component=" + component +
", foundation=" + foundation +
", priority=" + priority +
", ip=" + ip +
", type=" + type +
", tcpType=" + tcpType +
", relAddr=" + relAddr +
", relPort=" + relPort +
'}';
}
}
public static final class ServerConfig {
public final boolean useSystemNs;
public final boolean useSystemAec;
public final boolean enableStunMarking;
public final double hangupUiTimeout;
public final boolean enable_vp8_encoder;
public final boolean enable_vp8_decoder;
public final boolean enable_vp9_encoder;
public final boolean enable_vp9_decoder;
public final boolean enable_h265_encoder;
public final boolean enable_h265_decoder;
public final boolean enable_h264_encoder;
public final boolean enable_h264_decoder;
private final JSONObject jsonObject;
private ServerConfig(JSONObject jsonObject) {
this.jsonObject = jsonObject;
this.useSystemNs = jsonObject.optBoolean("use_system_ns", true);
this.useSystemAec = jsonObject.optBoolean("use_system_aec", true);
this.enableStunMarking = jsonObject.optBoolean("voip_enable_stun_marking", false);
this.hangupUiTimeout = jsonObject.optDouble("hangup_ui_timeout", 5);
this.enable_vp8_encoder = jsonObject.optBoolean("enable_vp8_encoder", true);
this.enable_vp8_decoder = jsonObject.optBoolean("enable_vp8_decoder", true);
this.enable_vp9_encoder = jsonObject.optBoolean("enable_vp9_encoder", true);
this.enable_vp9_decoder = jsonObject.optBoolean("enable_vp9_decoder", true);
this.enable_h265_encoder = jsonObject.optBoolean("enable_h265_encoder", true);
this.enable_h265_decoder = jsonObject.optBoolean("enable_h265_decoder", true);
this.enable_h264_encoder = jsonObject.optBoolean("enable_h264_encoder", true);
this.enable_h264_decoder = jsonObject.optBoolean("enable_h264_decoder", true);
}
public String getString(String key) {
return getString(key, "");
}
public String getString(String key, String fallback) {
return jsonObject.optString(key, fallback);
}
}
}