Added shutdown write method for ios platform. Fixed few bugs.
This commit is contained in:
parent
479c5003bd
commit
4b99d73adf
31
socket.js
31
socket.js
@ -104,17 +104,30 @@ Socket._copyToArray = function(array) {
|
|||||||
return outputArray;
|
return outputArray;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Socket.prototype.shutdownWrite = function () {
|
||||||
|
exec(
|
||||||
|
function() {
|
||||||
|
console.debug("SocketsForCordova: Shutdown write successfully called.");
|
||||||
|
},
|
||||||
|
function(errorMessage) {
|
||||||
|
console.error("SocketsForCordova: Error when call shutdownWrite on socket. Error: " + errorMessage);
|
||||||
|
},
|
||||||
|
CORDOVA_SERVICE_NAME,
|
||||||
|
"shutdownWrite",
|
||||||
|
[ this.socketKey ]);
|
||||||
|
};
|
||||||
|
|
||||||
Socket.prototype.close = function () {
|
Socket.prototype.close = function () {
|
||||||
exec(
|
exec(
|
||||||
function() {
|
function() {
|
||||||
console.debug("SocketsForCordova: Close successfully closed.");
|
console.debug("SocketsForCordova: Close successfully called.");
|
||||||
},
|
},
|
||||||
function(errorMessage) {
|
function(errorMessage) {
|
||||||
console.error("SocketsForCordova: Error when call close on socket. Error: " + errorMessage);
|
console.error("SocketsForCordova: Error when call close on socket. Error: " + errorMessage);
|
||||||
},
|
},
|
||||||
CORDOVA_SERVICE_NAME,
|
CORDOVA_SERVICE_NAME,
|
||||||
"close",
|
"close",
|
||||||
[ this.socketKey ]);
|
[ this.socketKey ]);
|
||||||
};
|
};
|
||||||
|
|
||||||
Socket.dispatchEvent = function(event) {
|
Socket.dispatchEvent = function(event) {
|
||||||
|
@ -6,11 +6,14 @@
|
|||||||
|
|
||||||
- (void)connect:(NSString *)host port:(NSNumber*)port;
|
- (void)connect:(NSString *)host port:(NSNumber*)port;
|
||||||
- (void)write:(NSArray *)dataArray;
|
- (void)write:(NSArray *)dataArray;
|
||||||
|
- (void)shutdownWrite;
|
||||||
- (void)close;
|
- (void)close;
|
||||||
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)event;
|
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)event;
|
||||||
|
|
||||||
|
@property (copy) void (^openEventHandler)();
|
||||||
|
@property (copy) void (^openErrorEventHandler)(NSString*);
|
||||||
@property (copy) void (^dataConsumer)(NSArray*);
|
@property (copy) void (^dataConsumer)(NSArray*);
|
||||||
@property (copy) void (^closeEventHandler)(BOOL);
|
@property (copy) void (^closeEventHandler)(BOOL);
|
||||||
@property (copy) void (^errorHandler)(NSString*);
|
@property (copy) void (^errorEventHandler)(NSString*);
|
||||||
|
|
||||||
@end
|
@end
|
@ -1,4 +1,6 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
#import "SocketAdapter.h"
|
#import "SocketAdapter.h"
|
||||||
|
|
||||||
CFReadStreamRef readStream;
|
CFReadStreamRef readStream;
|
||||||
@ -7,35 +9,79 @@ CFWriteStreamRef writeStream;
|
|||||||
NSInputStream *inputStream;
|
NSInputStream *inputStream;
|
||||||
NSOutputStream *outputStream;
|
NSOutputStream *outputStream;
|
||||||
|
|
||||||
|
BOOL wasOpenned = FALSE;
|
||||||
|
|
||||||
@implementation SocketAdapter
|
@implementation SocketAdapter
|
||||||
|
|
||||||
- (void)connect:(NSString *)host port:(NSNumber*)port {
|
- (void)connect:(NSString *)host port:(NSNumber*)port {
|
||||||
|
|
||||||
NSLog(@"Setting up connection to %@ : %@", host, [port stringValue]);
|
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);
|
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (__bridge CFStringRef)host, [port intValue], &readStream, &writeStream);
|
||||||
|
|
||||||
CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
|
CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
|
||||||
CFWriteStreamSetProperty(writeStream, 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 = (__bridge NSInputStream *)readStream;
|
||||||
[inputStream setDelegate:self];
|
[inputStream setDelegate:self];
|
||||||
//[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
|
||||||
[inputStream open];
|
[inputStream open];
|
||||||
|
|
||||||
outputStream = (__bridge NSOutputStream *)writeStream;
|
outputStream = (__bridge NSOutputStream *)writeStream;
|
||||||
|
//[outputStream setDelegate:self];
|
||||||
[outputStream open];
|
[outputStream open];
|
||||||
|
|
||||||
[self performSelectorOnMainThread:@selector(runReadLoop) withObject:nil waitUntilDone:NO];
|
[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 {
|
- (void)runReadLoop {
|
||||||
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)close {
|
- (void)shutdownWrite {
|
||||||
NSLog(@"Closing socket.");
|
NSLog(@"Shuting down write on socket.");
|
||||||
|
|
||||||
[self closeOutputStream];
|
[self closeOutputStream];
|
||||||
|
|
||||||
@ -71,6 +117,11 @@ NSOutputStream *outputStream;
|
|||||||
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)event {
|
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)event {
|
||||||
|
|
||||||
switch(event) {
|
switch(event) {
|
||||||
|
case NSStreamEventOpenCompleted: {
|
||||||
|
self.openEventHandler();
|
||||||
|
wasOpenned = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case NSStreamEventHasBytesAvailable: {
|
case NSStreamEventHasBytesAvailable: {
|
||||||
if(stream == inputStream) {
|
if(stream == inputStream) {
|
||||||
uint8_t buf[65535];
|
uint8_t buf[65535];
|
||||||
@ -90,18 +141,28 @@ NSOutputStream *outputStream;
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NSStreamEventEndEncountered: {
|
case NSStreamEventEndEncountered: {
|
||||||
[self closeInputStream];
|
|
||||||
|
|
||||||
self.closeEventHandler(FALSE);
|
if(stream == inputStream) {
|
||||||
break;
|
[self closeInputStream];
|
||||||
|
|
||||||
|
self.closeEventHandler(FALSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case NSStreamEventErrorOccurred:
|
case NSStreamEventErrorOccurred:
|
||||||
{
|
{
|
||||||
self.errorHandler([[stream streamError] localizedDescription]);
|
NSLog(@"Stream event error: %@", [[stream streamError] localizedDescription]);
|
||||||
|
|
||||||
[self abort];
|
if (wasOpenned) {
|
||||||
|
self.errorEventHandler([[stream streamError] localizedDescription]);
|
||||||
|
self.closeEventHandler(TRUE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self.openErrorEventHandler([[stream streamError] localizedDescription]);
|
||||||
|
self.errorEventHandler([[stream streamError] localizedDescription]);
|
||||||
|
}
|
||||||
|
|
||||||
self.closeEventHandler(TRUE);
|
[self close];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
@ -122,7 +183,7 @@ NSOutputStream *outputStream;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)abort {
|
- (void)close {
|
||||||
[self closeOutputStream];
|
[self closeOutputStream];
|
||||||
[self closeInputStream];
|
[self closeInputStream];
|
||||||
}
|
}
|
||||||
|
@ -6,14 +6,47 @@
|
|||||||
@implementation SocketPlugin : CDVPlugin
|
@implementation SocketPlugin : CDVPlugin
|
||||||
|
|
||||||
- (void) create : (CDVInvokedUrlCommand*) command {
|
- (void) create : (CDVInvokedUrlCommand*) command {
|
||||||
NSString* socketKey = [command.arguments objectAtIndex : 0];
|
//NSString* socketKey = [command.arguments objectAtIndex : 0];
|
||||||
|
|
||||||
if (socketAdapters == nil) {
|
|
||||||
|
[self.commandDelegate
|
||||||
|
sendPluginResult: [CDVPluginResult resultWithStatus : CDVCommandStatus_OK]
|
||||||
|
callbackId: command.callbackId];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (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];
|
self->socketAdapters = [[NSMutableDictionary alloc] init];
|
||||||
}
|
}
|
||||||
|
|
||||||
SocketAdapter* socketAdapter = [[SocketAdapter 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) {
|
socketAdapter.dataConsumer = ^ void (NSArray* dataArray) {
|
||||||
NSMutableDictionary *dataDictionary = [[NSMutableDictionary alloc] init];
|
NSMutableDictionary *dataDictionary = [[NSMutableDictionary alloc] init];
|
||||||
[dataDictionary setObject:@"DataReceived" forKey:@"type"];
|
[dataDictionary setObject:@"DataReceived" forKey:@"type"];
|
||||||
@ -29,55 +62,20 @@
|
|||||||
[closeDictionaryData setObject:socketKey forKey:@"socketKey"];
|
[closeDictionaryData setObject:socketKey forKey:@"socketKey"];
|
||||||
|
|
||||||
[self dispatchEventWithDictionary:closeDictionaryData];
|
[self dispatchEventWithDictionary:closeDictionaryData];
|
||||||
|
|
||||||
|
[self removeSocketAdapter:socketKey];
|
||||||
};
|
};
|
||||||
socketAdapter.errorHandler = ^ 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];
|
|
||||||
};
|
|
||||||
|
|
||||||
[self->socketAdapters
|
|
||||||
setObject:socketAdapter
|
|
||||||
forKey:socketKey];
|
|
||||||
|
|
||||||
[self.commandDelegate
|
|
||||||
sendPluginResult: [CDVPluginResult resultWithStatus : CDVCommandStatus_OK]
|
|
||||||
callbackId: command.callbackId];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (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) connect : (CDVInvokedUrlCommand*) command {
|
|
||||||
|
|
||||||
NSString *socketKey = [command.arguments objectAtIndex:0];
|
|
||||||
NSString *host = [command.arguments objectAtIndex:1];
|
|
||||||
NSNumber *port = [command.arguments objectAtIndex:2];
|
|
||||||
|
|
||||||
SocketAdapter *socket = [self getSocketAdapter:socketKey];
|
|
||||||
|
|
||||||
[self.commandDelegate runInBackground:^{
|
[self.commandDelegate runInBackground:^{
|
||||||
@try {
|
@try {
|
||||||
[socket connect:host port:port];
|
[socketAdapter connect:host port:port];
|
||||||
|
|
||||||
[self.commandDelegate
|
|
||||||
sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK]
|
|
||||||
callbackId:command.callbackId];
|
|
||||||
}
|
}
|
||||||
@catch (NSException *e) {
|
@catch (NSException *e) {
|
||||||
[self.commandDelegate
|
[self.commandDelegate
|
||||||
sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:e.reason]
|
sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:e.reason]
|
||||||
callbackId:command.callbackId];
|
callbackId:command.callbackId];
|
||||||
|
|
||||||
|
socketAdapter = nil;
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
@ -104,6 +102,27 @@
|
|||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (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 {
|
- (void) close:(CDVInvokedUrlCommand *) command {
|
||||||
|
|
||||||
NSString* socketKey = [command.arguments objectAtIndex:0];
|
NSString* socketKey = [command.arguments objectAtIndex:0];
|
||||||
@ -128,6 +147,26 @@
|
|||||||
- (void) setOptions: (CDVInvokedUrlCommand *) command {
|
- (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 {
|
- (void) dispatchEventWithDictionary: (NSDictionary*) dictionary {
|
||||||
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:nil];
|
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:nil];
|
||||||
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||||
|
Loading…
Reference in New Issue
Block a user