mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
327 lines
11 KiB
Plaintext
327 lines
11 KiB
Plaintext
#import <TgVoip/OngoingCallThreadLocalContext.h>
|
|
|
|
#import "TgVoip.h"
|
|
|
|
using namespace TGVOIP_NAMESPACE;
|
|
|
|
@implementation OngoingCallConnectionDescriptionWebrtc
|
|
|
|
- (instancetype _Nonnull)initWithConnectionId:(int64_t)connectionId ip:(NSString * _Nonnull)ip ipv6:(NSString * _Nonnull)ipv6 port:(int32_t)port peerTag:(NSData * _Nonnull)peerTag {
|
|
self = [super init];
|
|
if (self != nil) {
|
|
_connectionId = connectionId;
|
|
_ip = ip;
|
|
_ipv6 = ipv6;
|
|
_port = port;
|
|
_peerTag = peerTag;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
@end
|
|
|
|
@interface OngoingCallThreadLocalContextWebrtc () {
|
|
id<OngoingCallThreadLocalContextQueueWebrtc> _queue;
|
|
int32_t _contextId;
|
|
|
|
OngoingCallNetworkTypeWebrtc _networkType;
|
|
NSTimeInterval _callReceiveTimeout;
|
|
NSTimeInterval _callRingTimeout;
|
|
NSTimeInterval _callConnectTimeout;
|
|
NSTimeInterval _callPacketTimeout;
|
|
|
|
TgVoip *_tgVoip;
|
|
|
|
OngoingCallStateWebrtc _state;
|
|
int32_t _signalBars;
|
|
NSData *_lastDerivedState;
|
|
}
|
|
|
|
- (void)controllerStateChanged:(TgVoipState)state;
|
|
- (void)signalBarsChanged:(int32_t)signalBars;
|
|
|
|
@end
|
|
|
|
@implementation VoipProxyServerWebrtc
|
|
|
|
- (instancetype _Nonnull)initWithHost:(NSString * _Nonnull)host port:(int32_t)port username:(NSString * _Nullable)username password:(NSString * _Nullable)password {
|
|
self = [super init];
|
|
if (self != nil) {
|
|
_host = host;
|
|
_port = port;
|
|
_username = username;
|
|
_password = password;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
@end
|
|
|
|
static TgVoipNetworkType callControllerNetworkTypeForType(OngoingCallNetworkTypeWebrtc type) {
|
|
switch (type) {
|
|
case OngoingCallNetworkTypeWifi:
|
|
return TgVoipNetworkType::WiFi;
|
|
case OngoingCallNetworkTypeCellularGprs:
|
|
return TgVoipNetworkType::Gprs;
|
|
case OngoingCallNetworkTypeCellular3g:
|
|
return TgVoipNetworkType::ThirdGeneration;
|
|
case OngoingCallNetworkTypeCellularLte:
|
|
return TgVoipNetworkType::Lte;
|
|
default:
|
|
return TgVoipNetworkType::ThirdGeneration;
|
|
}
|
|
}
|
|
|
|
static TgVoipDataSaving callControllerDataSavingForType(OngoingCallDataSavingWebrtc type) {
|
|
switch (type) {
|
|
case OngoingCallDataSavingNever:
|
|
return TgVoipDataSaving::Never;
|
|
case OngoingCallDataSavingCellular:
|
|
return TgVoipDataSaving::Mobile;
|
|
case OngoingCallDataSavingAlways:
|
|
return TgVoipDataSaving::Always;
|
|
default:
|
|
return TgVoipDataSaving::Never;
|
|
}
|
|
}
|
|
|
|
@implementation OngoingCallThreadLocalContextWebrtc
|
|
|
|
static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
|
|
|
+ (void)setupLoggingFunction:(void (*)(NSString *))loggingFunction {
|
|
InternalVoipLoggingFunction = loggingFunction;
|
|
TgVoip::setLoggingFunction([](std::string const &string) {
|
|
if (InternalVoipLoggingFunction) {
|
|
InternalVoipLoggingFunction([[NSString alloc] initWithUTF8String:string.c_str()]);
|
|
}
|
|
});
|
|
}
|
|
|
|
+ (void)applyServerConfig:(NSString *)string {
|
|
if (string.length != 0) {
|
|
TgVoip::setGlobalServerConfig(std::string(string.UTF8String));
|
|
}
|
|
}
|
|
|
|
+ (int32_t)maxLayer {
|
|
return 92;
|
|
}
|
|
|
|
+ (NSString *)version {
|
|
return @"2.7.7";
|
|
}
|
|
|
|
- (instancetype _Nonnull)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue proxy:(VoipProxyServerWebrtc * _Nullable)proxy networkType:(OngoingCallNetworkTypeWebrtc)networkType dataSaving:(OngoingCallDataSavingWebrtc)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing primaryConnection:(OngoingCallConnectionDescriptionWebrtc * _Nonnull)primaryConnection alternativeConnections:(NSArray<OngoingCallConnectionDescriptionWebrtc *> * _Nonnull)alternativeConnections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P logPath:(NSString * _Nonnull)logPath {
|
|
self = [super init];
|
|
if (self != nil) {
|
|
_queue = queue;
|
|
assert([queue isCurrent]);
|
|
|
|
_callReceiveTimeout = 20.0;
|
|
_callRingTimeout = 90.0;
|
|
_callConnectTimeout = 30.0;
|
|
_callPacketTimeout = 10.0;
|
|
_networkType = networkType;
|
|
|
|
std::vector<uint8_t> derivedStateValue;
|
|
derivedStateValue.resize(derivedState.length);
|
|
[derivedState getBytes:derivedStateValue.data() length:derivedState.length];
|
|
|
|
std::unique_ptr<TgVoipProxy> proxyValue = nullptr;
|
|
if (proxy != nil) {
|
|
TgVoipProxy *proxyObject = new TgVoipProxy();
|
|
proxyObject->host = proxy.host.UTF8String;
|
|
proxyObject->port = (uint16_t)proxy.port;
|
|
proxyObject->login = proxy.username.UTF8String ?: "";
|
|
proxyObject->password = proxy.password.UTF8String ?: "";
|
|
proxyValue = std::unique_ptr<TgVoipProxy>(proxyObject);
|
|
}
|
|
|
|
/*TgVoipCrypto crypto;
|
|
crypto.sha1 = &TGCallSha1;
|
|
crypto.sha256 = &TGCallSha256;
|
|
crypto.rand_bytes = &TGCallRandomBytes;
|
|
crypto.aes_ige_encrypt = &TGCallAesIgeEncrypt;
|
|
crypto.aes_ige_decrypt = &TGCallAesIgeDecrypt;
|
|
crypto.aes_ctr_encrypt = &TGCallAesCtrEncrypt;*/
|
|
|
|
std::vector<TgVoipEndpoint> endpoints;
|
|
NSArray<OngoingCallConnectionDescriptionWebrtc *> *connections = [@[primaryConnection] arrayByAddingObjectsFromArray:alternativeConnections];
|
|
for (OngoingCallConnectionDescriptionWebrtc *connection in connections) {
|
|
unsigned char peerTag[16];
|
|
[connection.peerTag getBytes:peerTag length:16];
|
|
|
|
TgVoipEndpoint endpoint;
|
|
endpoint.endpointId = connection.connectionId;
|
|
endpoint.host = {
|
|
.ipv4 = std::string(connection.ip.UTF8String),
|
|
.ipv6 = std::string(connection.ipv6.UTF8String)
|
|
};
|
|
endpoint.port = (uint16_t)connection.port;
|
|
endpoint.type = TgVoipEndpointType::UdpRelay;
|
|
memcpy(endpoint.peerTag, peerTag, 16);
|
|
endpoints.push_back(endpoint);
|
|
}
|
|
|
|
TgVoipConfig config = {
|
|
.initializationTimeout = _callConnectTimeout,
|
|
.receiveTimeout = _callPacketTimeout,
|
|
.dataSaving = callControllerDataSavingForType(dataSaving),
|
|
.enableP2P = allowP2P,
|
|
.enableAEC = false,
|
|
.enableNS = true,
|
|
.enableAGC = true,
|
|
.enableCallUpgrade = false,
|
|
.logPath = logPath.length == 0 ? "" : std::string(logPath.UTF8String),
|
|
.maxApiLayer = [OngoingCallThreadLocalContextWebrtc maxLayer]
|
|
};
|
|
|
|
std::vector<uint8_t> encryptionKeyValue;
|
|
encryptionKeyValue.resize(key.length);
|
|
memcpy(encryptionKeyValue.data(), key.bytes, key.length);
|
|
|
|
TgVoipEncryptionKey encryptionKey = {
|
|
.value = encryptionKeyValue,
|
|
.isOutgoing = isOutgoing,
|
|
};
|
|
|
|
_tgVoip = TgVoip::makeInstance(
|
|
config,
|
|
{ derivedStateValue },
|
|
endpoints,
|
|
proxyValue,
|
|
callControllerNetworkTypeForType(networkType),
|
|
encryptionKey
|
|
);
|
|
|
|
_state = OngoingCallStateInitializing;
|
|
_signalBars = -1;
|
|
|
|
__weak OngoingCallThreadLocalContextWebrtc *weakSelf = self;
|
|
_tgVoip->setOnStateUpdated([weakSelf](TgVoipState state) {
|
|
__strong OngoingCallThreadLocalContextWebrtc *strongSelf = weakSelf;
|
|
if (strongSelf) {
|
|
[strongSelf controllerStateChanged:state];
|
|
}
|
|
});
|
|
_tgVoip->setOnSignalBarsUpdated([weakSelf](int signalBars) {
|
|
__strong OngoingCallThreadLocalContextWebrtc *strongSelf = weakSelf;
|
|
if (strongSelf) {
|
|
[strongSelf signalBarsChanged:signalBars];
|
|
}
|
|
});
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc {
|
|
assert([_queue isCurrent]);
|
|
if (_tgVoip != NULL) {
|
|
[self stop:nil];
|
|
}
|
|
}
|
|
|
|
- (bool)needRate {
|
|
return false;
|
|
}
|
|
|
|
- (void)stop:(void (^)(NSString *, int64_t, int64_t, int64_t, int64_t))completion {
|
|
if (_tgVoip) {
|
|
TgVoipFinalState finalState = _tgVoip->stop();
|
|
|
|
NSString *debugLog = [NSString stringWithUTF8String:finalState.debugLog.c_str()];
|
|
_lastDerivedState = [[NSData alloc] initWithBytes:finalState.persistentState.value.data() length:finalState.persistentState.value.size()];
|
|
|
|
delete _tgVoip;
|
|
_tgVoip = NULL;
|
|
|
|
if (completion) {
|
|
completion(debugLog, finalState.trafficStats.bytesSentWifi, finalState.trafficStats.bytesReceivedWifi, finalState.trafficStats.bytesSentMobile, finalState.trafficStats.bytesReceivedMobile);
|
|
}
|
|
}
|
|
}
|
|
|
|
- (NSString *)debugInfo {
|
|
if (_tgVoip != nil) {
|
|
NSString *version = [self version];
|
|
return [NSString stringWithFormat:@"WebRTC, Version: %@", version];
|
|
//auto rawDebugString = _tgVoip->getDebugInfo();
|
|
//return [NSString stringWithUTF8String:rawDebugString.c_str()];
|
|
} else {
|
|
return nil;
|
|
}
|
|
}
|
|
|
|
- (NSString *)version {
|
|
if (_tgVoip != nil) {
|
|
return @"2.7.7";//[NSString stringWithUTF8String:_tgVoip->getVersion().c_str()];
|
|
} else {
|
|
return nil;
|
|
}
|
|
}
|
|
|
|
- (NSData * _Nonnull)getDerivedState {
|
|
if (_tgVoip) {
|
|
auto persistentState = _tgVoip->getPersistentState();
|
|
return [[NSData alloc] initWithBytes:persistentState.value.data() length:persistentState.value.size()];
|
|
} else if (_lastDerivedState != nil) {
|
|
return _lastDerivedState;
|
|
} else {
|
|
return [NSData data];
|
|
}
|
|
}
|
|
|
|
- (void)controllerStateChanged:(TgVoipState)state {
|
|
OngoingCallStateWebrtc callState = OngoingCallStateInitializing;
|
|
switch (state) {
|
|
case TgVoipState::Estabilished:
|
|
callState = OngoingCallStateConnected;
|
|
break;
|
|
case TgVoipState::Failed:
|
|
callState = OngoingCallStateFailed;
|
|
break;
|
|
case TgVoipState::Reconnecting:
|
|
callState = OngoingCallStateReconnecting;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (callState != _state) {
|
|
_state = callState;
|
|
|
|
if (_stateChanged) {
|
|
_stateChanged(callState);
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)signalBarsChanged:(int32_t)signalBars {
|
|
if (signalBars != _signalBars) {
|
|
_signalBars = signalBars;
|
|
|
|
if (_signalBarsChanged) {
|
|
_signalBarsChanged(signalBars);
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)setIsMuted:(bool)isMuted {
|
|
if (_tgVoip) {
|
|
_tgVoip->setMuteMicrophone(isMuted);
|
|
}
|
|
}
|
|
|
|
- (void)setNetworkType:(OngoingCallNetworkTypeWebrtc)networkType {
|
|
if (_networkType != networkType) {
|
|
_networkType = networkType;
|
|
if (_tgVoip) {
|
|
_tgVoip->setNetworkType(callControllerNetworkTypeForType(networkType));
|
|
}
|
|
}
|
|
}
|
|
|
|
@end
|
|
|