Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2023-03-03 21:32:51 +04:00
commit 4c794a0a91
13 changed files with 874 additions and 478 deletions

View File

@ -600,7 +600,7 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent
var text = "" var text = ""
if let timestamp = item.timestamp { if let timestamp = item.timestamp {
let dateText = humanReadableStringForTimestamp(strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, timestamp: timestamp, alwaysShowTime: false, allowYesterday: true, format: HumanReadableStringFormat( let dateText = humanReadableStringForTimestamp(strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, timestamp: timestamp, alwaysShowTime: true, allowYesterday: true, format: HumanReadableStringFormat(
dateFormatString: { value in dateFormatString: { value in
return PresentationStrings.FormattedString(string: presentationData.strings.Chat_MessageSeenTimestamp_Date(value).string, ranges: []) return PresentationStrings.FormattedString(string: presentationData.strings.Chat_MessageSeenTimestamp_Date(value).string, ranges: [])
}, },

View File

@ -100,7 +100,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
case voiceConference case voiceConference
case preferredVideoCodec(Int, String, String?, Bool) case preferredVideoCodec(Int, String, String?, Bool)
case disableVideoAspectScaling(Bool) case disableVideoAspectScaling(Bool)
case enableVoipTcp(Bool) case enableNetworkFramework(Bool)
case restorePurchases(PresentationTheme) case restorePurchases(PresentationTheme)
case hostInfo(PresentationTheme, String) case hostInfo(PresentationTheme, String)
case versionInfo(PresentationTheme) case versionInfo(PresentationTheme)
@ -121,7 +121,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
return DebugControllerSection.experiments.rawValue return DebugControllerSection.experiments.rawValue
case .preferredVideoCodec: case .preferredVideoCodec:
return DebugControllerSection.videoExperiments.rawValue return DebugControllerSection.videoExperiments.rawValue
case .disableVideoAspectScaling, .enableVoipTcp: case .disableVideoAspectScaling, .enableNetworkFramework:
return DebugControllerSection.videoExperiments2.rawValue return DebugControllerSection.videoExperiments2.rawValue
case .hostInfo, .versionInfo: case .hostInfo, .versionInfo:
return DebugControllerSection.info.rawValue return DebugControllerSection.info.rawValue
@ -224,7 +224,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
return 45 + index return 45 + index
case .disableVideoAspectScaling: case .disableVideoAspectScaling:
return 100 return 100
case .enableVoipTcp: case .enableNetworkFramework:
return 101 return 101
case .hostInfo: case .hostInfo:
return 102 return 102
@ -1281,15 +1281,15 @@ private enum DebugControllerEntry: ItemListNodeEntry {
}) })
}).start() }).start()
}) })
case let .enableVoipTcp(value): case let .enableNetworkFramework(value):
return ItemListSwitchItem(presentationData: presentationData, title: "Enable VoIP TCP", value: !value, sectionId: self.section, style: .blocks, updated: { value in return ItemListSwitchItem(presentationData: presentationData, title: "Network X [Restart App]", value: value, sectionId: self.section, style: .blocks, updated: { value in
let _ = arguments.sharedContext.accountManager.transaction ({ transaction in if let context = arguments.context {
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings, { settings in let _ = updateNetworkSettingsInteractively(postbox: context.account.postbox, network: context.account.network, { settings in
var settings = settings?.get(ExperimentalUISettings.self) ?? ExperimentalUISettings.defaultSettings var settings = settings
settings.enableVoipTcp = value settings.useNetworkFramework = value
return PreferencesEntry(settings) return settings
}) }).start()
}).start() }
}) })
case .restorePurchases: case .restorePurchases:
return ItemListActionItem(presentationData: presentationData, title: "Restore Purchases", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { return ItemListActionItem(presentationData: presentationData, title: "Restore Purchases", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
@ -1397,7 +1397,7 @@ private func debugControllerEntries(sharedContext: SharedAccountContext, present
if isMainApp { if isMainApp {
entries.append(.disableVideoAspectScaling(experimentalSettings.disableVideoAspectScaling)) entries.append(.disableVideoAspectScaling(experimentalSettings.disableVideoAspectScaling))
entries.append(.enableVoipTcp(experimentalSettings.enableVoipTcp)) entries.append(.enableNetworkFramework(networkSettings?.useNetworkFramework ?? false))
} }
if let backupHostOverride = networkSettings?.backupHostOverride { if let backupHostOverride = networkSettings?.backupHostOverride {

View File

@ -1,6 +1,7 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import <MtProtoKit/MTDatacenterAuthInfo.h> #import <MtProtoKit/MTDatacenterAuthInfo.h>
#import <MtProtoKit/MTNetworkUsageCalculationInfo.h>
#import <EncryptionProvider/EncryptionProvider.h> #import <EncryptionProvider/EncryptionProvider.h>
@ -15,6 +16,34 @@
@class MTSignal; @class MTSignal;
@class MTQueue; @class MTQueue;
@protocol MTTcpConnectionInterface;
@protocol MTTcpConnectionInterfaceDelegate <NSObject>
- (void)connectionInterfaceDidReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag;
- (void)connectionInterfaceDidReadData:(NSData * _Nonnull)rawData withTag:(long)tag;
- (void)connectionInterfaceDidConnect;
- (void)connectionInterfaceDidDisconnectWithError:(NSError * _Nullable)error;
@end
@protocol MTTcpConnectionInterface<NSObject>
- (void)setGetLogPrefix:(NSString * _Nonnull(^_Nullable)())getLogPrefix;
- (void)setUsageCalculationInfo:(MTNetworkUsageCalculationInfo * _Nullable)usageCalculationInfo;
- (bool)connectToHost:(NSString * _Nonnull)inHost
onPort:(uint16_t)port
viaInterface:(NSString * _Nullable)inInterface
withTimeout:(NSTimeInterval)timeout
error:(NSError * _Nullable * _Nullable)errPtr;
- (void)writeData:(NSData * _Nonnull)data;
- (void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;
- (void)disconnect;
- (void)resetDelegate;
@end
@protocol MTContextChangeListener <NSObject> @protocol MTContextChangeListener <NSObject>
@optional @optional
@ -51,6 +80,8 @@
@property (nonatomic, readonly) bool useTempAuthKeys; @property (nonatomic, readonly) bool useTempAuthKeys;
@property (nonatomic) int32_t tempKeyExpiration; @property (nonatomic) int32_t tempKeyExpiration;
@property (nonatomic, copy) id<MTTcpConnectionInterface> _Nonnull (^ _Nullable makeTcpConnectionInterface)(id<MTTcpConnectionInterfaceDelegate> _Nonnull delegate, dispatch_queue_t _Nonnull delegateQueue);
+ (int32_t)fixedTimeDifference; + (int32_t)fixedTimeDifference;
+ (void)setFixedTimeDifference:(int32_t)fixedTimeDifference; + (void)setFixedTimeDifference:(int32_t)fixedTimeDifference;

View File

@ -1,5 +1,3 @@
#import <MtProtoKit/MTTransport.h> #import <MtProtoKit/MTTransport.h>
@interface MTTcpTransport : MTTransport @interface MTTcpTransport : MTTransport

View File

@ -2432,7 +2432,7 @@ enum GCDAsyncSocketConfig
int result = connect(socketFD, (const struct sockaddr *)[address bytes], (socklen_t)[address length]); int result = connect(socketFD, (const struct sockaddr *)[address bytes], (socklen_t)[address length]);
if (result == 0) if (result == 0)
{ {
bool isWifi = false; bool isWifi = true;
struct sockaddr_in addr; struct sockaddr_in addr;
struct ifaddrs* ifaddr; struct ifaddrs* ifaddr;

View File

@ -280,6 +280,8 @@ static NSString *makeRandomPadding() {
MTContext *context = [[MTContext alloc] initWithSerialization:currentContext.serialization encryptionProvider:currentContext.encryptionProvider apiEnvironment:apiEnvironment isTestingEnvironment:currentContext.isTestingEnvironment useTempAuthKeys:false]; MTContext *context = [[MTContext alloc] initWithSerialization:currentContext.serialization encryptionProvider:currentContext.encryptionProvider apiEnvironment:apiEnvironment isTestingEnvironment:currentContext.isTestingEnvironment useTempAuthKeys:false];
context.makeTcpConnectionInterface = currentContext.makeTcpConnectionInterface;
NSInteger authTokenMasterDatacenterId = 0; NSInteger authTokenMasterDatacenterId = 0;
NSNumber *requiredAuthToken = nil; NSNumber *requiredAuthToken = nil;
bool allowUnboundEphemeralKeys = true; bool allowUnboundEphemeralKeys = true;

View File

@ -66,6 +66,8 @@
MTContext *proxyContext = [[MTContext alloc] initWithSerialization:context.serialization encryptionProvider:context.encryptionProvider apiEnvironment:[[context apiEnvironment] withUpdatedSocksProxySettings:settings] isTestingEnvironment:context.isTestingEnvironment useTempAuthKeys:false]; MTContext *proxyContext = [[MTContext alloc] initWithSerialization:context.serialization encryptionProvider:context.encryptionProvider apiEnvironment:[[context apiEnvironment] withUpdatedSocksProxySettings:settings] isTestingEnvironment:context.isTestingEnvironment useTempAuthKeys:false];
proxyContext.makeTcpConnectionInterface = context.makeTcpConnectionInterface;
MTTcpConnection *connection = [[MTTcpConnection alloc] initWithContext:proxyContext datacenterId:datacenterId scheme:[[MTTransportScheme alloc] initWithTransportClass:[MTTcpConnection class] address:address media:false] interface:nil usageCalculationInfo:nil getLogPrefix:nil]; MTTcpConnection *connection = [[MTTcpConnection alloc] initWithContext:proxyContext datacenterId:datacenterId scheme:[[MTTransportScheme alloc] initWithTransportClass:[MTTcpConnection class] address:address media:false] interface:nil usageCalculationInfo:nil getLogPrefix:nil];
__weak MTTcpConnection *weakConnection = connection; __weak MTTcpConnection *weakConnection = connection;
__block NSTimeInterval startTime = CFAbsoluteTimeGetCurrent(); __block NSTimeInterval startTime = CFAbsoluteTimeGetCurrent();

View File

@ -606,33 +606,6 @@ struct ctr_state {
@end @end
@protocol MTTcpConnectionInterface;
@protocol MTTcpConnectionInterfaceDelegate <NSObject>
- (void)connectionInterface:(id<MTTcpConnectionInterface>)connectionInterface didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag;
- (void)connectionInterface:(id<MTTcpConnectionInterface>)connectionInterface didReadData:(NSData *)rawData withTag:(long)tag;
- (void)connectionInterface:(id<MTTcpConnectionInterface>)connectionInterface didConnectToHost:(NSString *)host port:(uint16_t)port;
- (void)connectionInterfaceDidDisconnect:(id<MTTcpConnectionInterface>)connectionInterface withError:(NSError *)error;
@end
@protocol MTTcpConnectionInterface<NSObject>
- (void)setGetLogPrefix:(NSString *(^)())getLogPrefix;
- (void)setUsageCalculationInfo:(MTNetworkUsageCalculationInfo *)usageCalculationInfo;
- (bool)connectToHost:(NSString *)inHost
onPort:(uint16_t)port
viaInterface:(NSString *)inInterface
withTimeout:(NSTimeInterval)timeout
error:(NSError **)errPtr;
- (void)writeData:(NSData *)data;
- (void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;
- (void)disconnect;
- (void)resetDelegate;
@end
@interface MTGcdAsyncSocketTcpConnectionInterface: NSObject<MTTcpConnectionInterface, GCDAsyncSocketDelegate> { @interface MTGcdAsyncSocketTcpConnectionInterface: NSObject<MTTcpConnectionInterface, GCDAsyncSocketDelegate> {
GCDAsyncSocket *_socket; GCDAsyncSocket *_socket;
__weak id<MTTcpConnectionInterfaceDelegate> _delegate; __weak id<MTTcpConnectionInterfaceDelegate> _delegate;
@ -687,28 +660,28 @@ struct ctr_state {
- (void)socket:(GCDAsyncSocket *)socket didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag { - (void)socket:(GCDAsyncSocket *)socket didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag {
id<MTTcpConnectionInterfaceDelegate> delegate = _delegate; id<MTTcpConnectionInterfaceDelegate> delegate = _delegate;
if (delegate) { if (delegate) {
[delegate connectionInterface:self didReadPartialDataOfLength:partialLength tag:tag]; [delegate connectionInterfaceDidReadPartialDataOfLength:partialLength tag:tag];
} }
} }
- (void)socket:(GCDAsyncSocket *)socket didReadData:(NSData *)rawData withTag:(long)tag { - (void)socket:(GCDAsyncSocket *)socket didReadData:(NSData *)rawData withTag:(long)tag {
id<MTTcpConnectionInterfaceDelegate> delegate = _delegate; id<MTTcpConnectionInterfaceDelegate> delegate = _delegate;
if (delegate) { if (delegate) {
[delegate connectionInterface:self didReadData:rawData withTag:tag]; [delegate connectionInterfaceDidReadData:rawData withTag:tag];
} }
} }
- (void)socket:(GCDAsyncSocket *)socket didConnectToHost:(NSString *)host port:(uint16_t)port { - (void)socket:(GCDAsyncSocket *)socket didConnectToHost:(NSString *)host port:(uint16_t)port {
id<MTTcpConnectionInterfaceDelegate> delegate = _delegate; id<MTTcpConnectionInterfaceDelegate> delegate = _delegate;
if (delegate) { if (delegate) {
[delegate connectionInterface:self didConnectToHost:host port:port]; [delegate connectionInterfaceDidConnect];
} }
} }
- (void)socketDidDisconnect:(GCDAsyncSocket *)socket withError:(NSError *)error { - (void)socketDidDisconnect:(GCDAsyncSocket *)socket withError:(NSError *)error {
id<MTTcpConnectionInterfaceDelegate> delegate = _delegate; id<MTTcpConnectionInterfaceDelegate> delegate = _delegate;
if (delegate) { if (delegate) {
[delegate connectionInterfaceDidDisconnect:self withError:error]; [delegate connectionInterfaceDidDisconnectWithError:error];
} }
} }
@ -791,6 +764,8 @@ struct ctr_state {
@property (nonatomic) int64_t packetHeadDecodeToken; @property (nonatomic) int64_t packetHeadDecodeToken;
@property (nonatomic, strong) id packetProgressToken; @property (nonatomic, strong) id packetProgressToken;
@property (nonatomic, copy) id<MTTcpConnectionInterface> _Nonnull (^ _Nullable makeTcpConnectionInterface)(id<MTTcpConnectionInterfaceDelegate> _Nonnull delegate, dispatch_queue_t _Nonnull delegateQueue);
@end @end
@implementation MTTcpConnection @implementation MTTcpConnection
@ -826,6 +801,8 @@ struct ctr_state {
_interface = interface; _interface = interface;
_usageCalculationInfo = usageCalculationInfo; _usageCalculationInfo = usageCalculationInfo;
_makeTcpConnectionInterface = context.makeTcpConnectionInterface;
if (context.apiEnvironment.datacenterAddressOverrides[@(datacenterId)] != nil) { if (context.apiEnvironment.datacenterAddressOverrides[@(datacenterId)] != nil) {
_firstPacketControlByte = [context.apiEnvironment tcpPayloadPrefix]; _firstPacketControlByte = [context.apiEnvironment tcpPayloadPrefix];
} }
@ -917,7 +894,12 @@ struct ctr_state {
{ {
if (_socket == nil) if (_socket == nil)
{ {
_socket = [[MTGcdAsyncSocketTcpConnectionInterface alloc] initWithDelegate:self delegateQueue:[[MTTcpConnection tcpQueue] nativeQueue]]; if (_makeTcpConnectionInterface) {
_socket = _makeTcpConnectionInterface(self, [[MTTcpConnection tcpQueue] nativeQueue]);
}
if (_socket == nil) {
_socket = [[MTGcdAsyncSocketTcpConnectionInterface alloc] initWithDelegate:self delegateQueue:[[MTTcpConnection tcpQueue] nativeQueue]];
}
[_socket setGetLogPrefix:_getLogPrefix]; [_socket setGetLogPrefix:_getLogPrefix];
[_socket setUsageCalculationInfo:_usageCalculationInfo]; [_socket setUsageCalculationInfo:_usageCalculationInfo];
@ -1407,7 +1389,7 @@ struct ctr_state {
[self closeAndNotifyWithError:true]; [self closeAndNotifyWithError:true];
} }
- (void)connectionInterface:(id<MTTcpConnectionInterface>)__unused connectionInterface didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)__unused tag - (void)connectionInterfaceDidReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)__unused tag
{ {
if (_closed) if (_closed)
return; return;
@ -1477,7 +1459,7 @@ struct ctr_state {
[_socket readDataToLength:4 withTimeout:-1 tag:MTTcpSocksRequest]; [_socket readDataToLength:4 withTimeout:-1 tag:MTTcpSocksRequest];
} }
- (void)connectionInterface:(id<MTTcpConnectionInterface>)__unused connectionInterface didReadData:(NSData *)rawData withTag:(long)tag - (void)connectionInterfaceDidReadData:(NSData *)rawData withTag:(long)tag
{ {
if (_closed) if (_closed)
return; return;
@ -2018,7 +2000,7 @@ struct ctr_state {
} }
} }
- (void)connectionInterface:(id<MTTcpConnectionInterface>)__unused connectionInterface didConnectToHost:(NSString *)__unused host port:(uint16_t)__unused port - (void)connectionInterfaceDidConnect
{ {
if (_socksIp != nil) { if (_socksIp != nil) {
@ -2031,7 +2013,7 @@ struct ctr_state {
} }
} }
- (void)connectionInterfaceDidDisconnect:(id<MTTcpConnectionInterface>)__unused connectionInterface withError:(NSError *)error - (void)connectionInterfaceDidDisconnectWithError:(NSError *)error
{ {
if (error != nil) { if (error != nil) {
if (MTLogEnabled()) { if (MTLogEnabled()) {

View File

@ -3913,8 +3913,13 @@ public class Postbox {
} }
public func setCanBeginTransactions(_ value: Bool, afterTransactionIfRunning: @escaping () -> Void = {}) { public func setCanBeginTransactions(_ value: Bool, afterTransactionIfRunning: @escaping () -> Void = {}) {
let storageBox = self.mediaBox.storageBox
self.impl.with { impl in self.impl.with { impl in
impl.setCanBeginTransactions(value, afterTransactionIfRunning: afterTransactionIfRunning) impl.setCanBeginTransactions(value, afterTransactionIfRunning: {
storageBox.setCanBeginTransactions(value, afterTransactionIfRunning: {
afterTransactionIfRunning()
})
})
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -494,6 +494,14 @@ func initializedNetwork(accountId: AccountRecordId, arguments: NetworkInitializa
let context = MTContext(serialization: serialization, encryptionProvider: arguments.encryptionProvider, apiEnvironment: apiEnvironment, isTestingEnvironment: testingEnvironment, useTempAuthKeys: useTempAuthKeys) let context = MTContext(serialization: serialization, encryptionProvider: arguments.encryptionProvider, apiEnvironment: apiEnvironment, isTestingEnvironment: testingEnvironment, useTempAuthKeys: useTempAuthKeys)
if let networkSettings = networkSettings, networkSettings.useNetworkFramework {
if #available(iOS 12.0, *) {
context.makeTcpConnectionInterface = { delegate, delegateQueue in
return NetworkFrameworkTcpConnectionInterface(delegate: delegate, delegateQueue: delegateQueue)
}
}
}
let seedAddressList: [Int: [String]] let seedAddressList: [Int: [String]]
if testingEnvironment { if testingEnvironment {

View File

@ -0,0 +1,287 @@
import Foundation
import Network
import MtProtoKit
import SwiftSignalKit
@available(iOS 12.0, *)
final class NetworkFrameworkTcpConnectionInterface: NSObject, MTTcpConnectionInterface {
private final class Impl {
private let queue: Queue
private weak var delegate: MTTcpConnectionInterfaceDelegate?
private let delegateQueue: DispatchQueue
private var connection: NWConnection?
private var reportedDisconnection: Bool = false
private var currentInterfaceIsWifi: Bool = true
private var connectTimeoutTimer: SwiftSignalKit.Timer?
private var usageCalculationInfo: MTNetworkUsageCalculationInfo?
private var networkUsageManager: MTNetworkUsageManager?
init(
queue: Queue,
delegate: MTTcpConnectionInterfaceDelegate,
delegateQueue: DispatchQueue
) {
self.queue = queue
self.delegate = delegate
self.delegateQueue = delegateQueue
}
deinit {
}
func setUsageCalculationInfo(_ usageCalculationInfo: MTNetworkUsageCalculationInfo?) {
if self.usageCalculationInfo !== usageCalculationInfo {
self.usageCalculationInfo = usageCalculationInfo
if let usageCalculationInfo = usageCalculationInfo {
self.networkUsageManager = MTNetworkUsageManager(info: usageCalculationInfo)
} else {
self.networkUsageManager = nil
}
}
}
func connect(host: String, port: UInt16, timeout: Double) {
if self.connection != nil {
assertionFailure("A connection already exists")
return
}
let host = NWEndpoint.Host(host)
let port = NWEndpoint.Port(rawValue: port)!
let tcpOptions = NWProtocolTCP.Options()
tcpOptions.noDelay = true
tcpOptions.enableKeepalive = true
tcpOptions.keepaliveIdle = 5
tcpOptions.keepaliveCount = 2
tcpOptions.keepaliveInterval = 5
tcpOptions.enableFastOpen = true
let parameters = NWParameters(tls: nil, tcp: tcpOptions)
let connection = NWConnection(host: host, port: port, using: parameters)
self.connection = connection
let queue = self.queue
connection.stateUpdateHandler = { [weak self] state in
queue.async {
self?.stateUpdated(state: state)
}
}
connection.pathUpdateHandler = { [weak self] path in
queue.async {
guard let self = self else {
return
}
if path.usesInterfaceType(.cellular) {
self.currentInterfaceIsWifi = false
} else {
self.currentInterfaceIsWifi = true
}
}
}
connection.viabilityUpdateHandler = { [weak self] isViable in
queue.async {
guard let self = self else {
return
}
if !isViable {
self.cancelWithError(error: nil)
}
}
}
connection.betterPathUpdateHandler = { [weak self] hasBetterPath in
queue.async {
guard let self = self else {
return
}
if hasBetterPath {
self.cancelWithError(error: nil)
}
}
}
self.connectTimeoutTimer = SwiftSignalKit.Timer(timeout: timeout, repeat: false, completion: { [weak self] in
guard let self = self else {
return
}
self.connectTimeoutTimer = nil
self.cancelWithError(error: nil)
}, queue: self.queue)
self.connectTimeoutTimer?.start()
connection.start(queue: self.queue.queue)
}
private func stateUpdated(state: NWConnection.State) {
switch state {
case .ready:
if let path = self.connection?.currentPath {
if path.usesInterfaceType(.cellular) {
self.currentInterfaceIsWifi = false
} else {
self.currentInterfaceIsWifi = true
}
}
if let connectTimeoutTimer = connectTimeoutTimer {
self.connectTimeoutTimer = nil
connectTimeoutTimer.invalidate()
}
weak var delegate = self.delegate
self.delegateQueue.async {
if let delegate = delegate {
delegate.connectionInterfaceDidConnect()
}
}
case let .failed(error):
self.cancelWithError(error: error)
default:
break
}
}
func write(data: Data) {
guard let connection = self.connection else {
assertionFailure("Connection not ready")
return
}
connection.send(content: data, completion: .contentProcessed({ _ in
}))
self.networkUsageManager?.addOutgoingBytes(UInt(data.count), interface: self.currentInterfaceIsWifi ? MTNetworkUsageManagerInterfaceOther : MTNetworkUsageManagerInterfaceWWAN)
}
func read(length: Int, timeout: Double, tag: Int) {
guard let connection = self.connection else {
print("Connection not ready")
return
}
connection.receive(minimumIncompleteLength: length, maximumLength: length, completion: { [weak self] data, context, isComplete, error in
guard let self = self else {
return
}
if let data = data {
self.networkUsageManager?.addIncomingBytes(UInt(data.count), interface: self.currentInterfaceIsWifi ? MTNetworkUsageManagerInterfaceOther : MTNetworkUsageManagerInterfaceWWAN)
if isComplete || data.count == length {
if data.count == length {
weak var delegate = self.delegate
self.delegateQueue.async {
if let delegate = delegate {
delegate.connectionInterfaceDidRead(data, withTag: tag)
}
}
} else {
self.cancelWithError(error: error)
}
} else {
weak var delegate = self.delegate
let dataCount = data.count
self.delegateQueue.async {
if let delegate = delegate {
delegate.connectionInterfaceDidReadPartialData(ofLength: UInt(dataCount), tag: tag)
}
}
}
} else {
self.cancelWithError(error: error)
}
})
}
private func cancelWithError(error: Error?) {
if let connectTimeoutTimer = self.connectTimeoutTimer {
self.connectTimeoutTimer = nil
connectTimeoutTimer.invalidate()
}
if !self.reportedDisconnection {
self.reportedDisconnection = true
weak var delegate = self.delegate
self.delegateQueue.async {
if let delegate = delegate {
delegate.connectionInterfaceDidDisconnectWithError(error)
}
}
}
if let connection = self.connection {
self.connection = nil
connection.cancel()
}
}
func disconnect() {
self.cancelWithError(error: nil)
}
func resetDelegate() {
self.delegate = nil
}
}
private static let sharedQueue = Queue(name: "NetworkFrameworkTcpConnectionInteface")
private let queue: Queue
private let impl: QueueLocalObject<Impl>
init(delegate: MTTcpConnectionInterfaceDelegate, delegateQueue: DispatchQueue) {
let queue = NetworkFrameworkTcpConnectionInterface.sharedQueue
self.queue = queue
self.impl = QueueLocalObject(queue: queue, generate: {
return Impl(queue: queue, delegate: delegate, delegateQueue: delegateQueue)
})
}
func setGetLogPrefix(_ getLogPrefix: (() -> String)?) {
}
func setUsageCalculationInfo(_ usageCalculationInfo: MTNetworkUsageCalculationInfo?) {
self.impl.with { impl in
impl.setUsageCalculationInfo(usageCalculationInfo)
}
}
func connect(toHost inHost: String, onPort port: UInt16, viaInterface inInterface: String?, withTimeout timeout: TimeInterval, error errPtr: NSErrorPointer) -> Bool {
self.impl.with { impl in
impl.connect(host: inHost, port: port, timeout: timeout)
}
return true
}
func write(_ data: Data) {
self.impl.with { impl in
impl.write(data: data)
}
}
func readData(toLength length: UInt, withTimeout timeout: TimeInterval, tag: Int) {
self.impl.with { impl in
impl.read(length: Int(length), timeout: timeout, tag: tag)
}
}
func disconnect() {
self.impl.with { impl in
impl.disconnect()
}
}
func resetDelegate() {
self.impl.with { impl in
impl.resetDelegate()
}
}
}

View File

@ -4,15 +4,17 @@ public struct NetworkSettings: Codable {
public var reducedBackupDiscoveryTimeout: Bool public var reducedBackupDiscoveryTimeout: Bool
public var applicationUpdateUrlPrefix: String? public var applicationUpdateUrlPrefix: String?
public var backupHostOverride: String? public var backupHostOverride: String?
public var useNetworkFramework: Bool
public static var defaultSettings: NetworkSettings { public static var defaultSettings: NetworkSettings {
return NetworkSettings(reducedBackupDiscoveryTimeout: false, applicationUpdateUrlPrefix: nil, backupHostOverride: nil) return NetworkSettings(reducedBackupDiscoveryTimeout: false, applicationUpdateUrlPrefix: nil, backupHostOverride: nil, useNetworkFramework: false)
} }
public init(reducedBackupDiscoveryTimeout: Bool, applicationUpdateUrlPrefix: String?, backupHostOverride: String?) { public init(reducedBackupDiscoveryTimeout: Bool, applicationUpdateUrlPrefix: String?, backupHostOverride: String?, useNetworkFramework: Bool) {
self.reducedBackupDiscoveryTimeout = reducedBackupDiscoveryTimeout self.reducedBackupDiscoveryTimeout = reducedBackupDiscoveryTimeout
self.applicationUpdateUrlPrefix = applicationUpdateUrlPrefix self.applicationUpdateUrlPrefix = applicationUpdateUrlPrefix
self.backupHostOverride = backupHostOverride self.backupHostOverride = backupHostOverride
self.useNetworkFramework = useNetworkFramework
} }
public init(from decoder: Decoder) throws { public init(from decoder: Decoder) throws {
@ -21,6 +23,7 @@ public struct NetworkSettings: Codable {
self.reducedBackupDiscoveryTimeout = ((try? container.decode(Int32.self, forKey: "reducedBackupDiscoveryTimeout")) ?? 0) != 0 self.reducedBackupDiscoveryTimeout = ((try? container.decode(Int32.self, forKey: "reducedBackupDiscoveryTimeout")) ?? 0) != 0
self.applicationUpdateUrlPrefix = try? container.decodeIfPresent(String.self, forKey: "applicationUpdateUrlPrefix") self.applicationUpdateUrlPrefix = try? container.decodeIfPresent(String.self, forKey: "applicationUpdateUrlPrefix")
self.backupHostOverride = try? container.decodeIfPresent(String.self, forKey: "backupHostOverride") self.backupHostOverride = try? container.decodeIfPresent(String.self, forKey: "backupHostOverride")
self.useNetworkFramework = try container.decodeIfPresent(Bool.self, forKey: "useNetworkFramework") ?? NetworkSettings.defaultSettings.useNetworkFramework
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
@ -29,5 +32,6 @@ public struct NetworkSettings: Codable {
try container.encode((self.reducedBackupDiscoveryTimeout ? 1 : 0) as Int32, forKey: "reducedBackupDiscoveryTimeout") try container.encode((self.reducedBackupDiscoveryTimeout ? 1 : 0) as Int32, forKey: "reducedBackupDiscoveryTimeout")
try container.encodeIfPresent(self.applicationUpdateUrlPrefix, forKey: "applicationUpdateUrlPrefix") try container.encodeIfPresent(self.applicationUpdateUrlPrefix, forKey: "applicationUpdateUrlPrefix")
try container.encodeIfPresent(self.backupHostOverride, forKey: "backupHostOverride") try container.encodeIfPresent(self.backupHostOverride, forKey: "backupHostOverride")
try container.encode(self.useNetworkFramework, forKey: "useNetworkFramework")
} }
} }