From 5083cfe79b15dfc598489a88711bea58da2ff1fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Obr=C3=A1til?= Date: Wed, 12 Nov 2014 16:40:46 +0100 Subject: [PATCH] Fixed ios api --- .../SocketsForCordova/Classes/SocketAdapter.h | 36 +- .../SocketsForCordova/Classes/SocketAdapter.m | 379 +++++++++--------- .../SocketsForCordova/Classes/SocketPlugin.h | 22 +- .../SocketsForCordova/Classes/SocketPlugin.m | 344 ++++++++-------- 4 files changed, 392 insertions(+), 389 deletions(-) diff --git a/src/ios/SocketsForCordova/Classes/SocketAdapter.h b/src/ios/SocketsForCordova/Classes/SocketAdapter.h index df026d6..670e5de 100644 --- a/src/ios/SocketsForCordova/Classes/SocketAdapter.h +++ b/src/ios/SocketsForCordova/Classes/SocketAdapter.h @@ -1,19 +1,19 @@ -#import - -@interface SocketAdapter : NSObject { -@public -} - -- (void)connect:(NSString *)host port:(NSNumber*)port; -- (void)write:(NSArray *)dataArray; -- (void)shutdownWrite; -- (void)close; -- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)event; - -@property (copy) void (^openEventHandler)(); -@property (copy) void (^openErrorEventHandler)(NSString*); -@property (copy) void (^dataConsumer)(NSArray*); -@property (copy) void (^closeEventHandler)(BOOL); -@property (copy) void (^errorEventHandler)(NSString*); - +#import + +@interface SocketAdapter : NSObject { +@public +} + +- (void)open:(NSString *)host port:(NSNumber*)port; +- (void)write:(NSArray *)dataArray; +- (void)shutdownWrite; +- (void)close; +- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)event; + +@property (copy) void (^openEventHandler)(); +@property (copy) void (^openErrorEventHandler)(NSString*); +@property (copy) void (^dataConsumer)(NSArray*); +@property (copy) void (^closeEventHandler)(BOOL); +@property (copy) void (^errorEventHandler)(NSString*); + @end \ No newline at end of file diff --git a/src/ios/SocketsForCordova/Classes/SocketAdapter.m b/src/ios/SocketsForCordova/Classes/SocketAdapter.m index dd29830..7534ddc 100644 --- a/src/ios/SocketsForCordova/Classes/SocketAdapter.m +++ b/src/ios/SocketsForCordova/Classes/SocketAdapter.m @@ -1,189 +1,192 @@ -#include -#include -#include -#import "SocketAdapter.h" - -CFReadStreamRef readStream; -CFWriteStreamRef writeStream; - -NSInputStream *inputStream; -NSOutputStream *outputStream; - -BOOL wasOpenned = FALSE; - -@implementation SocketAdapter - -- (void)connect:(NSString *)host port:(NSNumber*)port { - - NSLog(@"Setting up connection to %@ : %@", host, [port stringValue]); - - if (![self isIp:host]) { - host = [self resolveIp:host]; - } - - CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (__bridge CFStringRef)host, [port intValue], &readStream, &writeStream); - - CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); - CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); - - if(!CFWriteStreamOpen(writeStream) || !CFReadStreamOpen(readStream)) { - NSLog(@"Error, streams not open"); - - @throw [NSException exceptionWithName:@"SocketException" reason:@"Cannot open streams." userInfo:nil]; - } - - inputStream = (__bridge NSInputStream *)readStream; - [inputStream setDelegate:self]; - [inputStream open]; - - outputStream = (__bridge NSOutputStream *)writeStream; - [outputStream open]; - - [self performSelectorOnMainThread:@selector(runReadLoop) withObject:nil waitUntilDone:NO]; -} - --(BOOL)isIp:(NSString*) host { - const char *utf8 = [host UTF8String]; - - // Check valid IPv4. - struct in_addr dst; - int success = inet_pton(AF_INET, utf8, &(dst.s_addr)); - if (success != 1) { - // Check valid IPv6. - struct in6_addr dst6; - success = inet_pton(AF_INET6, utf8, &dst6); - } - return (success == 1); -} - --(NSString*)resolveIp:(NSString*) host { - - NSLog(@"Resolving host: %@", host); - - const char *buff = [host cStringUsingEncoding:NSUTF8StringEncoding]; - struct hostent *host_entry = gethostbyname(buff); - - if(host_entry == NULL) { - @throw [NSException exceptionWithName:@"NSException" reason:@"Cannot resolve hostname." userInfo:nil]; - } - - char *hostCstring = inet_ntoa(*((struct in_addr *)host_entry->h_addr_list[0])); - host = [NSString stringWithUTF8String:hostCstring]; - - NSLog(@"Resolved ip: %@", host); - - return host; -} - -- (void)runReadLoop { - [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; -} - -- (void)shutdownWrite { - NSLog(@"Shuting down write on socket."); - - [self closeOutputStream]; - - int socket = [self socknumForStream: inputStream]; - shutdown(socket, 1); -} - -- (void)closeInputStream { - [inputStream close]; - [inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; - [inputStream setDelegate:nil]; - inputStream = nil; -} - -- (void)closeOutputStream { - [outputStream close]; - outputStream = nil; -} - --(int) socknumForStream: (NSStream *)stream -{ - int sock = -1; - NSData *sockObj = [stream propertyForKey: - (__bridge NSString *)kCFStreamPropertySocketNativeHandle]; - if ([sockObj isKindOfClass:[NSData class]] && - ([sockObj length] == sizeof(int)) ) { - const int *sockptr = (const int *)[sockObj bytes]; - sock = *sockptr; - } - return sock; -} - -- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)event { - - switch(event) { - case NSStreamEventOpenCompleted: { - self.openEventHandler(); - wasOpenned = TRUE; - break; - } - case NSStreamEventHasBytesAvailable: { - if(stream == inputStream) { - uint8_t buf[65535]; - long len = [inputStream read:buf maxLength:65535]; - - if(len > 0) { - NSMutableArray *dataArray = [[NSMutableArray alloc] init]; - for (long i = 0; i < len; i++) { - - [dataArray addObject:[NSNumber numberWithUnsignedChar:buf[i]]]; - } - self.dataConsumer(dataArray); - } - } - break; - } - case NSStreamEventEndEncountered: { - - if(stream == inputStream) { - [self closeInputStream]; - - self.closeEventHandler(FALSE); - break; - } - } - case NSStreamEventErrorOccurred: - { - NSLog(@"Stream event error: %@", [[stream streamError] localizedDescription]); - - [self close]; - - if (wasOpenned) { - self.errorEventHandler([[stream streamError] localizedDescription]); - self.closeEventHandler(TRUE); - } - else { - self.errorEventHandler([[stream streamError] localizedDescription]); - self.openErrorEventHandler([[stream streamError] localizedDescription]); - } - break; - } - default: { - - break; - } - } -} - -- (void)write:(NSArray *)dataArray { - uint8_t buf[dataArray.count]; - for (int i = 0; i < dataArray.count; i++) { - buf[i] = (unsigned char)[[dataArray objectAtIndex:i] integerValue]; - } - NSInteger bytesWritten = [outputStream write:buf maxLength:dataArray.count]; - if (bytesWritten == -1) { - @throw [NSException exceptionWithName:@"SocketException" reason:[outputStream.streamError localizedDescription] userInfo:nil]; - } -} - -- (void)close { - self.closeEventHandler(FALSE); - [self closeOutputStream]; - [self closeInputStream]; -} - +#include +#include +#include +#import "SocketAdapter.h" + +CFReadStreamRef readStream; +CFWriteStreamRef writeStream; + +NSInputStream *inputStream; +NSOutputStream *outputStream; + +BOOL wasOpenned = FALSE; + +@implementation SocketAdapter + +- (void)open:(NSString *)host port:(NSNumber*)port { + + NSLog(@"Setting up connection to %@ : %@", host, [port stringValue]); + + if (![self isIp:host]) { + host = [self resolveIp:host]; + } + + CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (__bridge CFStringRef)host, [port intValue], &readStream, &writeStream); + + CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); + CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); + + if(!CFWriteStreamOpen(writeStream) || !CFReadStreamOpen(readStream)) { + NSLog(@"Error, streams not open"); + + @throw [NSException exceptionWithName:@"SocketException" reason:@"Cannot open streams." userInfo:nil]; + } + + inputStream = (__bridge NSInputStream *)readStream; + [inputStream setDelegate:self]; + [inputStream open]; + + outputStream = (__bridge NSOutputStream *)writeStream; + [outputStream open]; + + [self performSelectorOnMainThread:@selector(runReadLoop) withObject:nil waitUntilDone:NO]; +} + +-(BOOL)isIp:(NSString*) host { + const char *utf8 = [host UTF8String]; + + // Check valid IPv4. + struct in_addr dst; + int success = inet_pton(AF_INET, utf8, &(dst.s_addr)); + if (success != 1) { + // Check valid IPv6. + struct in6_addr dst6; + success = inet_pton(AF_INET6, utf8, &dst6); + } + return (success == 1); +} + +-(NSString*)resolveIp:(NSString*) host { + + NSLog(@"Resolving host: %@", host); + + const char *buff = [host cStringUsingEncoding:NSUTF8StringEncoding]; + struct hostent *host_entry = gethostbyname(buff); + + if(host_entry == NULL) { + @throw [NSException exceptionWithName:@"NSException" reason:@"Cannot resolve hostname." userInfo:nil]; + } + + char *hostCstring = inet_ntoa(*((struct in_addr *)host_entry->h_addr_list[0])); + host = [NSString stringWithUTF8String:hostCstring]; + + NSLog(@"Resolved ip: %@", host); + + return host; +} + +- (void)runReadLoop { + [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; +} + +- (void)shutdownWrite { + NSLog(@"Shuting down write on socket."); + + [self closeOutputStream]; + + int socket = [self socknumForStream: inputStream]; + shutdown(socket, 1); +} + +- (void)closeInputStream { + [inputStream close]; + [inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + [inputStream setDelegate:nil]; + inputStream = nil; +} + +- (void)closeOutputStream { + [outputStream close]; + outputStream = nil; +} + +-(int) socknumForStream: (NSStream *)stream +{ + int sock = -1; + NSData *sockObj = [stream propertyForKey: + (__bridge NSString *)kCFStreamPropertySocketNativeHandle]; + if ([sockObj isKindOfClass:[NSData class]] && + ([sockObj length] == sizeof(int)) ) { + const int *sockptr = (const int *)[sockObj bytes]; + sock = *sockptr; + } + return sock; +} + +- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)event { + + switch(event) { + case NSStreamEventOpenCompleted: { + self.openEventHandler(); + wasOpenned = TRUE; + break; + } + case NSStreamEventHasBytesAvailable: { + if(stream == inputStream) { + uint8_t buf[65535]; + long len = [inputStream read:buf maxLength:65535]; + + if(len > 0) { + NSMutableArray *dataArray = [[NSMutableArray alloc] init]; + for (long i = 0; i < len; i++) { + + [dataArray addObject:[NSNumber numberWithUnsignedChar:buf[i]]]; + } + self.dataConsumer(dataArray); + } + } + break; + } + case NSStreamEventEndEncountered: { + + if(stream == inputStream) { + [self closeInputStream]; + + self.closeEventHandler(FALSE); + break; + } + } + case NSStreamEventErrorOccurred: + { + NSLog(@"Stream event error: %@", [[stream streamError] localizedDescription]); + + if (wasOpenned) { + self.errorEventHandler([[stream streamError] localizedDescription]); + self.closeEventHandler(TRUE); + } + else { + self.errorEventHandler([[stream streamError] localizedDescription]); + self.openErrorEventHandler([[stream streamError] localizedDescription]); + } + //[self closeStreams]; + break; + } + default: { + + break; + } + } +} + +- (void)write:(NSArray *)dataArray { + uint8_t buf[dataArray.count]; + for (int i = 0; i < dataArray.count; i++) { + buf[i] = (unsigned char)[[dataArray objectAtIndex:i] integerValue]; + } + NSInteger bytesWritten = [outputStream write:buf maxLength:dataArray.count]; + if (bytesWritten == -1) { + @throw [NSException exceptionWithName:@"SocketException" reason:[outputStream.streamError localizedDescription] userInfo:nil]; + } +} + +- (void)close { + self.closeEventHandler(FALSE); + [self closeStreams]; +} + +- (void)closeStreams { + [self closeOutputStream]; + [self closeInputStream]; +} + @end \ No newline at end of file diff --git a/src/ios/SocketsForCordova/Classes/SocketPlugin.h b/src/ios/SocketsForCordova/Classes/SocketPlugin.h index 7c1a02c..30bb03e 100644 --- a/src/ios/SocketsForCordova/Classes/SocketPlugin.h +++ b/src/ios/SocketsForCordova/Classes/SocketPlugin.h @@ -1,12 +1,12 @@ -#import - -@interface SocketPlugin : CDVPlugin { - NSMutableDictionary *socketAdapters; -} - --(void) connect: (CDVInvokedUrlCommand *) command; --(void) write: (CDVInvokedUrlCommand *) command; --(void) close: (CDVInvokedUrlCommand *) command; --(void) setOptions: (CDVInvokedUrlCommand *) command; - +#import + +@interface SocketPlugin : CDVPlugin { + NSMutableDictionary *socketAdapters; +} + +-(void) open: (CDVInvokedUrlCommand *) command; +-(void) write: (CDVInvokedUrlCommand *) command; +-(void) close: (CDVInvokedUrlCommand *) command; +-(void) setOptions: (CDVInvokedUrlCommand *) command; + @end \ No newline at end of file diff --git a/src/ios/SocketsForCordova/Classes/SocketPlugin.m b/src/ios/SocketsForCordova/Classes/SocketPlugin.m index c24cd97..75edd69 100644 --- a/src/ios/SocketsForCordova/Classes/SocketPlugin.m +++ b/src/ios/SocketsForCordova/Classes/SocketPlugin.m @@ -1,173 +1,173 @@ -#import "SocketPlugin.h" -#import "SocketAdapter.h" -#import -#import - -@implementation SocketPlugin : CDVPlugin - -- (void) connect : (CDVInvokedUrlCommand*) command { - - NSString *socketKey = [command.arguments objectAtIndex:0]; - NSString *host = [command.arguments objectAtIndex:1]; - NSNumber *port = [command.arguments objectAtIndex:2]; - - if (socketAdapters == nil) { - self->socketAdapters = [[NSMutableDictionary alloc] init]; - } - - __block SocketAdapter* socketAdapter = [[SocketAdapter alloc] init]; - socketAdapter.openEventHandler = ^ void () { - [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK] callbackId:command.callbackId]; - - [self->socketAdapters setObject:socketAdapter forKey:socketKey]; - - socketAdapter = nil; - }; - socketAdapter.openErrorEventHandler = ^ void (NSString *error){ - [self.commandDelegate - sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:error] - callbackId:command.callbackId]; - - socketAdapter = nil; - }; - socketAdapter.errorEventHandler = ^ void (NSString *error){ - NSMutableDictionary *errorDictionaryData = [[NSMutableDictionary alloc] init]; - [errorDictionaryData setObject:@"Error" forKey:@"type"]; - [errorDictionaryData setObject:error forKey:@"errorMessage"]; - [errorDictionaryData setObject:socketKey forKey:@"socketKey"]; - - [self dispatchEventWithDictionary:errorDictionaryData]; - }; - socketAdapter.dataConsumer = ^ void (NSArray* dataArray) { - NSMutableDictionary *dataDictionary = [[NSMutableDictionary alloc] init]; - [dataDictionary setObject:@"DataReceived" forKey:@"type"]; - [dataDictionary setObject:dataArray forKey:@"data"]; - [dataDictionary setObject:socketKey forKey:@"socketKey"]; - - [self dispatchEventWithDictionary:dataDictionary]; - }; - socketAdapter.closeEventHandler = ^ void (BOOL hasErrors) { - NSMutableDictionary *closeDictionaryData = [[NSMutableDictionary alloc] init]; - [closeDictionaryData setObject:@"Close" forKey:@"type"]; - [closeDictionaryData setObject:(hasErrors == TRUE ? @"true": @"false") forKey:@"hasError"]; - [closeDictionaryData setObject:socketKey forKey:@"socketKey"]; - - [self dispatchEventWithDictionary:closeDictionaryData]; - - [self removeSocketAdapter:socketKey]; - }; - - [self.commandDelegate runInBackground:^{ - @try { - [socketAdapter connect:host port:port]; - } - @catch (NSException *e) { - [self.commandDelegate - sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:e.reason] - callbackId:command.callbackId]; - - socketAdapter = nil; - } - }]; -} - -- (void) write:(CDVInvokedUrlCommand *) command { - - NSString* socketKey = [command.arguments objectAtIndex:0]; - NSArray *data = [command.arguments objectAtIndex:1]; - - SocketAdapter *socket = [self getSocketAdapter:socketKey]; - - [self.commandDelegate runInBackground:^{ - @try { - [socket write:data]; - [self.commandDelegate - sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK] - callbackId:command.callbackId]; - } - @catch (NSException *e) { - [self.commandDelegate - sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:e.reason] - callbackId:command.callbackId]; - } - }]; -} - -- (void) shutdownWrite:(CDVInvokedUrlCommand *) command { - - NSString* socketKey = [command.arguments objectAtIndex:0]; - - SocketAdapter *socket = [self getSocketAdapter:socketKey]; - - [self.commandDelegate runInBackground:^{ - @try { - [socket shutdownWrite]; - [self.commandDelegate - sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK] - callbackId:command.callbackId]; - } - @catch (NSException *e) { - [self.commandDelegate - sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:e.reason] - callbackId:command.callbackId]; - } - }]; -} - -- (void) close:(CDVInvokedUrlCommand *) command { - - NSString* socketKey = [command.arguments objectAtIndex:0]; - - SocketAdapter *socket = [self getSocketAdapter:socketKey]; - - [self.commandDelegate runInBackground:^{ - @try { - [socket close]; - [self.commandDelegate - sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK] - callbackId:command.callbackId]; - } - @catch (NSException *e) { - [self.commandDelegate - sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:e.reason] - callbackId:command.callbackId]; - } - }]; -} - -- (void) setOptions: (CDVInvokedUrlCommand *) command { -} - -- (SocketAdapter*) getSocketAdapter: (NSString*) socketKey { - SocketAdapter* socketAdapter = [self->socketAdapters objectForKey:socketKey]; - if (socketAdapter == nil) { - NSString *exceptionReason = [NSString stringWithFormat:@"Cannot find socketKey: %@. Connection is probably closed.", socketKey]; - - @throw [NSException exceptionWithName:@"IllegalArgumentException" reason:exceptionReason userInfo:nil]; - } - return socketAdapter; -} - -- (void) removeSocketAdapter: (NSString*) socketKey { - NSLog(@"Removing socket adapter from storage."); - [self->socketAdapters removeObjectForKey:socketKey]; -} - -- (BOOL) socketAdapterExists: (NSString*) socketKey { - SocketAdapter* socketAdapter = [self->socketAdapters objectForKey:socketKey]; - return socketAdapter != nil; -} - -- (void) dispatchEventWithDictionary: (NSDictionary*) dictionary { - NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:nil]; - NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; - - [self dispatchEvent:jsonString]; -} - -- (void) dispatchEvent: (NSString *) jsonEventString { - NSString *jsToEval = [NSString stringWithFormat : @"window.Socket.dispatchEvent(%@);", jsonEventString]; - [self.commandDelegate evalJs:jsToEval]; -} - +#import "SocketPlugin.h" +#import "SocketAdapter.h" +#import +#import + +@implementation SocketPlugin : CDVPlugin + +- (void) open : (CDVInvokedUrlCommand*) command { + + NSString *socketKey = [command.arguments objectAtIndex:0]; + NSString *host = [command.arguments objectAtIndex:1]; + NSNumber *port = [command.arguments objectAtIndex:2]; + + if (socketAdapters == nil) { + self->socketAdapters = [[NSMutableDictionary alloc] init]; + } + + __block SocketAdapter* socketAdapter = [[SocketAdapter alloc] init]; + socketAdapter.openEventHandler = ^ void () { + [self.commandDelegate sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK] callbackId:command.callbackId]; + + [self->socketAdapters setObject:socketAdapter forKey:socketKey]; + + socketAdapter = nil; + }; + socketAdapter.openErrorEventHandler = ^ void (NSString *error){ + [self.commandDelegate + sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:error] + callbackId:command.callbackId]; + + socketAdapter = nil; + }; + socketAdapter.errorEventHandler = ^ void (NSString *error){ + NSMutableDictionary *errorDictionaryData = [[NSMutableDictionary alloc] init]; + [errorDictionaryData setObject:@"Error" forKey:@"type"]; + [errorDictionaryData setObject:error forKey:@"errorMessage"]; + [errorDictionaryData setObject:socketKey forKey:@"socketKey"]; + + [self dispatchEventWithDictionary:errorDictionaryData]; + }; + socketAdapter.dataConsumer = ^ void (NSArray* dataArray) { + NSMutableDictionary *dataDictionary = [[NSMutableDictionary alloc] init]; + [dataDictionary setObject:@"DataReceived" forKey:@"type"]; + [dataDictionary setObject:dataArray forKey:@"data"]; + [dataDictionary setObject:socketKey forKey:@"socketKey"]; + + [self dispatchEventWithDictionary:dataDictionary]; + }; + socketAdapter.closeEventHandler = ^ void (BOOL hasErrors) { + NSMutableDictionary *closeDictionaryData = [[NSMutableDictionary alloc] init]; + [closeDictionaryData setObject:@"Close" forKey:@"type"]; + [closeDictionaryData setObject:(hasErrors == TRUE ? @"true": @"false") forKey:@"hasError"]; + [closeDictionaryData setObject:socketKey forKey:@"socketKey"]; + + [self dispatchEventWithDictionary:closeDictionaryData]; + + [self removeSocketAdapter:socketKey]; + }; + + [self.commandDelegate runInBackground:^{ + @try { + [socketAdapter open:host port:port]; + } + @catch (NSException *e) { + [self.commandDelegate + sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:e.reason] + callbackId:command.callbackId]; + + socketAdapter = nil; + } + }]; +} + +- (void) write:(CDVInvokedUrlCommand *) command { + + NSString* socketKey = [command.arguments objectAtIndex:0]; + NSArray *data = [command.arguments objectAtIndex:1]; + + SocketAdapter *socket = [self getSocketAdapter:socketKey]; + + [self.commandDelegate runInBackground:^{ + @try { + [socket write:data]; + [self.commandDelegate + sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK] + callbackId:command.callbackId]; + } + @catch (NSException *e) { + [self.commandDelegate + sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:e.reason] + callbackId:command.callbackId]; + } + }]; +} + +- (void) shutdownWrite:(CDVInvokedUrlCommand *) command { + + NSString* socketKey = [command.arguments objectAtIndex:0]; + + SocketAdapter *socket = [self getSocketAdapter:socketKey]; + + [self.commandDelegate runInBackground:^{ + @try { + [socket shutdownWrite]; + [self.commandDelegate + sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK] + callbackId:command.callbackId]; + } + @catch (NSException *e) { + [self.commandDelegate + sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:e.reason] + callbackId:command.callbackId]; + } + }]; +} + +- (void) close:(CDVInvokedUrlCommand *) command { + + NSString* socketKey = [command.arguments objectAtIndex:0]; + + SocketAdapter *socket = [self getSocketAdapter:socketKey]; + + [self.commandDelegate runInBackground:^{ + @try { + [socket close]; + [self.commandDelegate + sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK] + callbackId:command.callbackId]; + } + @catch (NSException *e) { + [self.commandDelegate + sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:e.reason] + callbackId:command.callbackId]; + } + }]; +} + +- (void) setOptions: (CDVInvokedUrlCommand *) command { +} + +- (SocketAdapter*) getSocketAdapter: (NSString*) socketKey { + SocketAdapter* socketAdapter = [self->socketAdapters objectForKey:socketKey]; + if (socketAdapter == nil) { + NSString *exceptionReason = [NSString stringWithFormat:@"Cannot find socketKey: %@. Connection is probably closed.", socketKey]; + + @throw [NSException exceptionWithName:@"IllegalArgumentException" reason:exceptionReason userInfo:nil]; + } + return socketAdapter; +} + +- (void) removeSocketAdapter: (NSString*) socketKey { + NSLog(@"Removing socket adapter from storage."); + [self->socketAdapters removeObjectForKey:socketKey]; +} + +- (BOOL) socketAdapterExists: (NSString*) socketKey { + SocketAdapter* socketAdapter = [self->socketAdapters objectForKey:socketKey]; + return socketAdapter != nil; +} + +- (void) dispatchEventWithDictionary: (NSDictionary*) dictionary { + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:nil]; + NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + + [self dispatchEvent:jsonString]; +} + +- (void) dispatchEvent: (NSString *) jsonEventString { + NSString *jsToEval = [NSString stringWithFormat : @"window.Socket.dispatchEvent(%@);", jsonEventString]; + [self.commandDelegate evalJs:jsToEval]; +} + @end \ No newline at end of file