mirror of https://github.com/oxen-io/session-ios
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
164 lines
5.5 KiB
Objective-C
164 lines
5.5 KiB
Objective-C
//
|
|
// TSSocketManager.m
|
|
// TextSecureiOS
|
|
//
|
|
// Created by Frederic Jacobs on 17/05/14.
|
|
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
|
//
|
|
|
|
#import "TSConstants.h"
|
|
#import "TSAccountManager.h"
|
|
#import "TSMessagesManager.h"
|
|
#import "TSSocketManager.h"
|
|
#import "TSStorageManager+keyingMaterial.h"
|
|
#import <CocoaLumberjack/DDLog.h>
|
|
|
|
#define kWebSocketHeartBeat 15
|
|
|
|
NSString * const SocketOpenedNotification = @"SocketOpenedNotification";
|
|
NSString * const SocketClosedNotification = @"SocketClosedNotification";
|
|
NSString * const SocketConnectingNotification = @"SocketConnectingNotification";
|
|
|
|
@interface TSSocketManager ()
|
|
@property (nonatomic, retain) NSTimer *timer;
|
|
@property (nonatomic, retain) SRWebSocket *websocket;
|
|
@property (nonatomic) NSUInteger status;
|
|
@end
|
|
|
|
@implementation TSSocketManager
|
|
|
|
- (id)init{
|
|
self = [super init];
|
|
|
|
if (self) {
|
|
self.websocket = nil;
|
|
[self addObserver:self forKeyPath:@"status" options:0 context:kSocketStatusObservationContext];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
+ (id)sharedManager {
|
|
static TSSocketManager *sharedMyManager = nil;
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^{
|
|
sharedMyManager = [[self alloc] init];
|
|
});
|
|
return sharedMyManager;
|
|
}
|
|
|
|
#pragma mark - Manage Socket
|
|
|
|
+ (void)becomeActive{
|
|
TSSocketManager *sharedInstance = [self sharedManager];
|
|
SRWebSocket *socket =[sharedInstance websocket];
|
|
|
|
if (socket) {
|
|
switch ([socket readyState]) {
|
|
case SR_OPEN:
|
|
DDLogVerbose(@"WebSocket already open on connection request");
|
|
sharedInstance.status = kSocketStatusOpen;
|
|
return;
|
|
case SR_CONNECTING:
|
|
DDLogVerbose(@"WebSocket is already connecting");
|
|
sharedInstance.status = kSocketStatusConnecting;
|
|
return;
|
|
default:
|
|
[socket close];
|
|
sharedInstance.status = kSocketStatusClosed;
|
|
socket.delegate = nil;
|
|
socket = nil;
|
|
break;
|
|
}
|
|
}
|
|
|
|
NSString *webSocketConnect = [textSecureWebSocketAPI stringByAppendingString:[[self sharedManager] webSocketAuthenticationString]];
|
|
NSURL *webSocketConnectURL = [NSURL URLWithString:webSocketConnect];
|
|
socket = [[SRWebSocket alloc] initWithURL:webSocketConnectURL];
|
|
socket.delegate = [self sharedManager];
|
|
[socket open];
|
|
[[self sharedManager] setWebsocket:socket];
|
|
}
|
|
|
|
+ (void)resignActivity{
|
|
SRWebSocket *socket =[[self sharedManager] websocket];
|
|
[socket close];
|
|
}
|
|
|
|
#pragma mark - Delegate methods
|
|
|
|
- (void) webSocketDidOpen:(SRWebSocket *)webSocket{
|
|
NSLog(@"WebSocket was sucessfully opened");
|
|
self.timer = [NSTimer scheduledTimerWithTimeInterval:kWebSocketHeartBeat target:self selector:@selector(webSocketHeartBeat) userInfo:nil repeats:YES];
|
|
self.status = kSocketStatusOpen;
|
|
}
|
|
|
|
- (void) webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error{
|
|
NSLog(@"Error connecting to socket %@", error);
|
|
[self.timer invalidate];
|
|
self.status = kSocketStatusClosed;
|
|
}
|
|
|
|
- (void) webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message{
|
|
NSData *data = [message dataUsingEncoding:NSUTF8StringEncoding];
|
|
NSError *error = nil;
|
|
|
|
NSDictionary *serializedMessage = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
|
|
NSString *base64message = [serializedMessage objectForKey:@"message"];
|
|
|
|
|
|
if (!base64message || error) {
|
|
return;
|
|
}
|
|
|
|
[[TSMessagesManager sharedManager] handleBase64MessageSignal:base64message];
|
|
|
|
|
|
NSString *ackedId = [serializedMessage objectForKey:@"id"];
|
|
[self.websocket send:[[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:@{@"type":@"1", @"id":ackedId}
|
|
options:0 error:nil]
|
|
encoding:NSUTF8StringEncoding]];
|
|
}
|
|
|
|
- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean{
|
|
DDLogVerbose(@"WebSocket did close");
|
|
[self.timer invalidate];
|
|
self.status = kSocketStatusClosed;
|
|
}
|
|
|
|
- (void)webSocketHeartBeat{
|
|
DDLogVerbose(@"WebSocket sent ping");
|
|
[self.websocket sendPing:nil];
|
|
}
|
|
|
|
- (NSString*)webSocketAuthenticationString{
|
|
return [NSString stringWithFormat:@"?login=%@&password=%@", [[TSAccountManager registeredNumber] stringByReplacingOccurrencesOfString:@"+" withString:@"%2B"],[TSStorageManager serverAuthToken]];
|
|
}
|
|
|
|
#pragma mark UI Delegates
|
|
|
|
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
|
|
if (context == kSocketStatusObservationContext)
|
|
{
|
|
switch (self.status) {
|
|
case kSocketStatusOpen:
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:SocketOpenedNotification object:self];
|
|
break;
|
|
case kSocketStatusClosed:
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:SocketClosedNotification object:self];
|
|
break;
|
|
case kSocketStatusConnecting:
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:SocketConnectingNotification object:self];
|
|
break;
|
|
default:
|
|
break;
|
|
|
|
}
|
|
} else {
|
|
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
|
|
}
|
|
}
|
|
|
|
|
|
@end
|