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.
session-ios/Signal/src/textsecure/Network/TSSocketManager.m

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