mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-17 11:00:07 +00:00
183 lines
7.0 KiB
Swift
183 lines
7.0 KiB
Swift
import Foundation
|
|
#if os(macOS)
|
|
import PostboxMac
|
|
import MtProtoKitMac
|
|
import SwiftSignalKitMac
|
|
#else
|
|
import Postbox
|
|
import MtProtoKitDynamic
|
|
import SwiftSignalKit
|
|
#endif
|
|
|
|
private func roundUp(_ value: Int, to multiple: Int) -> Int {
|
|
if multiple == 0 {
|
|
return value
|
|
}
|
|
|
|
let remainder = value % multiple
|
|
if remainder == 0 {
|
|
return value
|
|
}
|
|
|
|
return value + multiple - remainder
|
|
}
|
|
|
|
class Download: NSObject, MTRequestMessageServiceDelegate {
|
|
let datacenterId: Int
|
|
let context: MTContext
|
|
let mtProto: MTProto
|
|
let requestService: MTRequestMessageService
|
|
|
|
init(datacenterId: Int, context: MTContext, masterDatacenterId: Int, usageInfo: MTNetworkUsageCalculationInfo?) {
|
|
self.datacenterId = datacenterId
|
|
self.context = context
|
|
|
|
self.mtProto = MTProto(context: self.context, datacenterId: datacenterId, usageCalculationInfo: usageInfo)
|
|
if datacenterId != masterDatacenterId {
|
|
self.mtProto.authTokenMasterDatacenterId = masterDatacenterId
|
|
self.mtProto.requiredAuthToken = Int(datacenterId) as NSNumber
|
|
}
|
|
self.requestService = MTRequestMessageService(context: self.context)
|
|
|
|
super.init()
|
|
|
|
self.requestService.delegate = self
|
|
self.mtProto.add(self.requestService)
|
|
}
|
|
|
|
deinit {
|
|
self.mtProto.remove(self.requestService)
|
|
self.mtProto.stop()
|
|
}
|
|
|
|
func requestMessageServiceAuthorizationRequired(_ requestMessageService: MTRequestMessageService!) {
|
|
self.context.updateAuthTokenForDatacenter(withId: self.datacenterId, authToken: nil)
|
|
self.context.authTokenForDatacenter(withIdRequired: self.datacenterId, authToken:self.mtProto.requiredAuthToken, masterDatacenterId: self.mtProto.authTokenMasterDatacenterId)
|
|
}
|
|
|
|
func uploadPart(fileId: Int64, index: Int, data: Data, bigTotalParts: Int? = nil) -> Signal<Void, NoError> {
|
|
return Signal<Void, MTRpcError> { subscriber in
|
|
let request = MTRequest()
|
|
|
|
let saveFilePart: (CustomStringConvertible, Buffer, (Buffer) -> Api.Bool?)
|
|
if let bigTotalParts = bigTotalParts {
|
|
saveFilePart = Api.functions.upload.saveBigFilePart(fileId: fileId, filePart: Int32(index), fileTotalParts: Int32(bigTotalParts), bytes: Buffer(data: data))
|
|
} else {
|
|
saveFilePart = Api.functions.upload.saveFilePart(fileId: fileId, filePart: Int32(index), bytes: Buffer(data: data))
|
|
}
|
|
|
|
request.setPayload(saveFilePart.1.makeData() as Data!, metadata: WrappedRequestMetadata(metadata: saveFilePart.0, tag: nil), responseParser: { response in
|
|
if let result = saveFilePart.2(Buffer(data: response)) {
|
|
return BoxedMessage(result)
|
|
}
|
|
return nil
|
|
})
|
|
|
|
request.dependsOnPasswordEntry = false
|
|
|
|
request.completed = { (boxedResponse, timestamp, error) -> () in
|
|
if let error = error {
|
|
subscriber.putError(error)
|
|
} else {
|
|
subscriber.putCompletion()
|
|
}
|
|
}
|
|
|
|
let internalId: Any! = request.internalId
|
|
|
|
self.requestService.add(request)
|
|
|
|
return ActionDisposable {
|
|
self.requestService.removeRequest(byInternalId: internalId)
|
|
}
|
|
} |> retryRequest
|
|
}
|
|
|
|
func part(location: Api.InputFileLocation, offset: Int, length: Int) -> Signal<Data, NoError> {
|
|
return Signal<Data, MTRpcError> { subscriber in
|
|
let request = MTRequest()
|
|
|
|
var updatedLength = roundUp(length, to: 4096)
|
|
while updatedLength % 4096 != 0 || 1048576 % updatedLength != 0 {
|
|
updatedLength += 1
|
|
}
|
|
|
|
let data = Api.functions.upload.getFile(location: location, offset: Int32(offset), limit: Int32(updatedLength))
|
|
|
|
request.setPayload(data.1.makeData() as Data!, metadata: WrappedRequestMetadata(metadata: data.0, tag: nil), responseParser: { response in
|
|
if let result = data.2(Buffer(data: response)) {
|
|
return BoxedMessage(result)
|
|
}
|
|
return nil
|
|
})
|
|
|
|
request.dependsOnPasswordEntry = false
|
|
|
|
request.completed = { (boxedResponse, timestamp, error) -> () in
|
|
if let error = error {
|
|
subscriber.putError(error)
|
|
} else {
|
|
if let result = (boxedResponse as! BoxedMessage).body as? Api.upload.File {
|
|
switch result {
|
|
case let .file(_, _, bytes):
|
|
subscriber.putNext(bytes.makeData())
|
|
case let .fileCdnRedirect(dcId, fileToken, encryptionKey, encryptionIv):
|
|
break
|
|
}
|
|
subscriber.putCompletion()
|
|
}
|
|
else {
|
|
subscriber.putError(MTRpcError(errorCode: 500, errorDescription: "TL_VERIFICATION_ERROR"))
|
|
}
|
|
}
|
|
}
|
|
|
|
let internalId: Any! = request.internalId
|
|
|
|
self.requestService.add(request)
|
|
|
|
return ActionDisposable {
|
|
self.requestService.removeRequest(byInternalId: internalId)
|
|
}
|
|
} |> retryRequest
|
|
}
|
|
|
|
func request<T>(_ data: (CustomStringConvertible, Buffer, (Buffer) -> T?)) -> Signal<T, MTRpcError> {
|
|
let requestService = self.requestService
|
|
return Signal { subscriber in
|
|
let request = MTRequest()
|
|
|
|
request.setPayload(data.1.makeData() as Data!, metadata: WrappedRequestMetadata(metadata: data.0, tag: nil), responseParser: { response in
|
|
if let result = data.2(Buffer(data: response)) {
|
|
return BoxedMessage(result)
|
|
}
|
|
return nil
|
|
})
|
|
|
|
request.dependsOnPasswordEntry = false
|
|
|
|
request.completed = { (boxedResponse, timestamp, error) -> () in
|
|
if let error = error {
|
|
subscriber.putError(error)
|
|
} else {
|
|
if let result = (boxedResponse as! BoxedMessage).body as? T {
|
|
subscriber.putNext(result)
|
|
subscriber.putCompletion()
|
|
}
|
|
else {
|
|
subscriber.putError(MTRpcError(errorCode: 500, errorDescription: "TL_VERIFICATION_ERROR"))
|
|
}
|
|
}
|
|
}
|
|
|
|
let internalId: Any! = request.internalId
|
|
|
|
requestService.add(request)
|
|
|
|
return ActionDisposable {
|
|
self.requestService.removeRequest(byInternalId: internalId)
|
|
}
|
|
}
|
|
}
|
|
}
|