import ChunkedDC
import CocoaLumberjackSwift
import Foundation
final class WCSession: NSObject {
var privateKey: Data?
var webClientSession: WebClientSessionEntity?
var messageQueue: WebMessageQueue
private var connection: WCConnection?
private var requestedConversations = [String]()
private var requestedThumbnails = [Data]()
private var lastLoadedMessageIndexes = [Data: Int]()
private var requestCreateMessagesFromWeb = [String: WebAbstractMessage]()
private(set) var webClientProcessQueue: DispatchQueue
init(webClientSession: WebClientSessionEntity) {
self.webClientSession = webClientSession
self.privateKey = webClientSession.privateKey
var hash = webClientSession.initiatorPermanentPublicKeyHash
if hash == nil {
hash = WCSession.ccSha256(data: webClientSession.initiatorPermanentPublicKey).hexEncodedString()
WebClientSessionStore.shared.updateWebClientSession(session: webClientSession, hash: hash!)
}
self.webClientProcessQueue = DispatchQueue(label: "ch.threema.webClientProcessQueue", attributes: [])
self.messageQueue = WebMessageQueue()
super.init()
messageQueue.delegate = self
}
}
extension WCSession {
// MARK: class functions
class func ccSha256(data: Data) -> Data {
var digest = Data(count: Int(CC_SHA256_DIGEST_LENGTH))
digest.withUnsafeMutableBytes { digestBuffer in
data.withUnsafeBytes { buffer in
_ = CC_SHA256(
buffer.baseAddress!,
CC_LONG(buffer.count),
digestBuffer.bindMemory(to: UInt8.self).baseAddress
)
}
}
return digest
}
}
extension WCSession {
// MARK: Functions
func connect(authToken: Data?) {
let newConnection = WCConnection(delegate: self)
if connection != nil {
if connection!.context != nil {
newConnection.context = connection!.context!.copy() as? WebConnectionContext
}
let oldConnection = connection
DDLogNotice("[Threema Web] Close old session")
oldConnection?.close(close: false, forget: false, sendDisconnect: false, reason: .replace)
}
connection = newConnection
connection?.connect(authToken: authToken)
}
func sendMessage() { }
func receive() { }
func stop(close: Bool, forget: Bool, sendDisconnect: Bool, reason: WCConnection.WCConnectionStopReason) {
connection?.close(close: close, forget: forget, sendDisconnect: sendDisconnect, reason: reason)
}
func setWCConnectionStateToReady() {
connection?.setWCConnectionStateToReady()
}
func setWCConnectionStateToConnectionInfoReceived() {
connection?.setWCConnectionStateToConnectionInfoReceived()
}
func connectionContext() -> WebConnectionContext? {
connection?.context
}
func connectionInfoResponse() -> WebUpdateConnectionInfoResponse? {
connection?.connectionInfoResponse
}
func sendChunk(chunk: [UInt8], msgpack: Data?, connectionInfo: Bool) {
connection?.sendChunk(chunk: chunk, msgpack: msgpack, connectionInfo: connectionInfo)
}
func connectionWca() -> String? {
connection?.wca
}
func setWcaForConnection(wca: String) {
connection?.wca = wca
}
func addRequestCreateMessage(requestID: String, abstractMessage: WebAbstractMessage) {
requestCreateMessagesFromWeb[requestID] = abstractMessage
}
func removeRequestCreateMessage(requestID: String) {
requestCreateMessagesFromWeb.removeValue(forKey: requestID)
}
func requestMessage(for requestID: String) -> WebAbstractMessage? {
requestCreateMessagesFromWeb[requestID]
}
}
extension WCSession {
// MARK: Requested lists
func requestedConversations(contains conversationID: String) -> Bool {
requestedConversations.contains(conversationID)
}
func addRequestedConversation(conversationID: String) {
if !requestedConversations(contains: conversationID) {
requestedConversations.append(conversationID)
}
}
func requestedThumbnails(contains messageID: Data) -> Bool {
requestedThumbnails.contains(messageID)
}
func addRequestedThumbnail(messageID: Data) {
if !requestedThumbnails(contains: messageID) {
requestedThumbnails.append(messageID)
}
}
func lastLoadedMessageIndexes(contains messageID: Data) -> Int? {
lastLoadedMessageIndexes[messageID]
}
func addLastLoadedMessageIndex(messageID: Data, index: Int) {
lastLoadedMessageIndexes[messageID] = index
}
func clearAllRequestedLists() {
requestedConversations.removeAll()
requestedThumbnails.removeAll()
lastLoadedMessageIndexes.removeAll()
}
}
// MARK: - MessageCompleteDelegate
extension WCSession: MessageCompleteDelegate {
func messageComplete(message: Data) {
do {
let object = try message.unpack() as! [AnyHashable: Any?]
let webMessage = WebAbstractMessage(dictionary: object)
DDLogVerbose(
"[Threema Web] MessagePack -> Received \(webMessage.messageType)/\(webMessage.messageSubType ?? "")"
)
webClientProcessQueue.async {
webMessage.getResponseMsgpack(session: self, completionHandler: { responseMsgpack, blackListed in
if responseMsgpack != nil {
self.messageQueue.enqueue(data: responseMsgpack, blackListed: blackListed)
}
else {
print("ResponseMsgpack is nil")
}
})
}
}
catch {
print("Something went wrong while unpacking data: \(error)")
}
}
}
// MARK: - WCConnectionDelegate
extension WCSession: WCConnectionDelegate {
func currentWebClientSession() -> WebClientSessionEntity? {
webClientSession
}
func currentWCSession() -> WCSession {
self
}
func currentMessageQueue() -> WebMessageQueue {
messageQueue
}
}
// MARK: - WebMessageQueueDelegate
extension WCSession: WebMessageQueueDelegate {
func sendMessageToWeb(blacklisted: Bool, msgpack: Data, _ connectionInfo: Bool = false) {
connection?.sendMessageToWeb(blacklisted: blacklisted, msgpack: msgpack, connectionInfo)
}
func connectionStatus() -> WCConnectionState? {
connection?.connectionStatus
}
}
¤ Dauer der Verarbeitung: 0.9 Sekunden
¤
*© Formatika GbR, Deutschland