// // SocketServiceHandler.m // OneCable // // Created by KaRam Kim on 2017. 2. 17.. // Copyright © 2017년 ntels. All rights reserved. // #import "SocketServiceHandler.h" #import "Definitions.h" #import "JDJSONModel.h" #import "JDObject.h" #define MAX_RETRY_CONNECT_COUNT 1 @interface SocketServiceHandler() { SRWebSocket *_socket; NSMutableArray *_messages; NSMutableArray *_delegates; int _retryCount; } //@property NSMutableDictionary* controllers; //@property int controllerId; @end @implementation SocketServiceHandler + (id)sharedManager { static SocketServiceHandler *sharedSocketServiceHandler = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedSocketServiceHandler = [[self alloc] init]; }); return sharedSocketServiceHandler; } - (id) init { self = [super init]; if (self) { _isConnected = NO; _messages = [[NSMutableArray alloc] init]; _delegates = [[NSMutableArray alloc] init]; // self.controllerId = 0; [self socketOpen]; } return self; } //- (void) initDelegate:(id) delegate //{ // [self setDelegate:delegate]; //} - (SRReadyState) getSocketStatus { return _socket.readyState; } - (void) socketOpen { NSLog(@"socketOpen"); _strSocketURL = [NSString stringWithFormat:@"%@%@", kSocketServer, API_ROOT_PATH]; NSLog(@"socketURL : %@", _strSocketURL); if( _socket != nil ) { [_socket open]; } else { NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:_strSocketURL]]; if([[JDFacade facade].loginUser authorization]!=nil) { [request setValue:[[JDFacade facade].loginUser authorization] forHTTPHeaderField:API_AUTHORIZATION_KEY]; } NSLog(@"All Header Info : %@", request.allHTTPHeaderFields); _socket = [[SRWebSocket alloc] initWithURLRequest:request]; _socket.delegate = self; [_socket open]; } } - (void) open { if( !_isConnected ) { if( _socket.readyState == SR_OPEN ) { _isConnected = YES; } else if ( _socket.readyState == SR_CLOSED || _socket.readyState == SR_CLOSING ) { [self close]; _socket = nil; [self socketOpen]; } } } - (void) close { if( _isConnected ) { [_socket close]; _socket = nil; } else { if (_socket != nil) { _socket = nil; } } _isConnected = NO; } - (void) sendData:(NSDictionary *)data { NSLog(@"Send Data : %@", data); if(_socket.readyState == SR_OPEN) { NSLog(@"1"); NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:data options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string error:&error]; if (!jsonData) { NSLog(@"Got an error: %@", error); } else { NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; NSLog(@"Socket Send Data : %@", jsonString); [_socket send:jsonString]; } } else if ( _socket.readyState == SR_CLOSED || _socket.readyState == SR_CLOSING ) { NSLog(@"2"); [_messages addObject:data]; [self reConnect]; } else { NSLog(@"3"); [_messages addObject:data]; if(!_isConnected) { [self socketOpen]; } } } - (void) sendDataWithDelegate:(NSDictionary *)data delegate:(id)delegate { [self addDelegate:delegate]; [self sendData:data]; } - (void)addDelegate:(id)delegate { // short controllerId = self.controllerId++; // if (self.controllerId >= INT16_MAX) { // self.controllerId = 0; // } [_delegates addObject:delegate]; } - (void)removeDelegate:(id)delegate { [_delegates removeObject:delegate]; } -(void) reConnect { if(_retryCount < MAX_RETRY_CONNECT_COUNT) { _retryCount++; [self close]; _socket = nil; [self socketOpen]; } else { [self close]; } } #pragma mark - SRWebSocketDelegate - (void)webSocketDidOpen:(SRWebSocket *)webSocket { NSLog(@"SOCKET didOpen"); _retryCount = 0; // Open이 되지 않은 상태에서 전송시도한 메세지들을 발송한다. for (NSDictionary *data in _messages) { [self sendData:data]; [_messages removeObject:data]; } for (id controller in _delegates) { if (controller && [controller respondsToSelector:@selector(socketConnectComplete)]) { [controller socketConnectComplete]; } } } - (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message { NSLog(@"SOCKET didReceiveMessage : %@", message); NSString *errString = @""; if( message == nil || [message isEqualToString:@""] ) errString = @"message empty"; else { NSError* error = nil; NSDictionary *jsonObj = [NSJSONSerialization JSONObjectWithData:[message dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:&error]; if (error != nil) { NSLog(@"NSJSONSerialization JSONObject error: %@", [error localizedDescription]); return; } id JSONModel = nil; JSONModel = [[SocketModel alloc] initWithDictionary:jsonObj error:&error]; for (id controller in _delegates) { if (controller!=nil && [controller respondsToSelector:@selector(socketDidReceiveMessage:info:)]) { [controller socketDidReceiveMessage:JSONModel info:jsonObj]; [self removeDelegate:controller]; } } // TODO : 전달받은 데이터로 자동으로 처리할 내용이 있으면 이곳에서 처리할것 } } - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error { NSLog(@"WebSocket error: %@", error); _isConnected = NO; [self reConnect]; } - (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(NSData *)pongPayload { NSLog(@"WebSocket Receive Pong: %@", pongPayload); } - (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean { NSLog(@"WebSocket closed with code: %ld reason:%@ wasClean:%d", (long)code, reason, wasClean); _isConnected = NO; [self reConnect]; } @end