Added ios open and write timeouts, changed js errors format
This commit is contained in:
parent
64acef4ce9
commit
462dfdafc8
@ -156,3 +156,7 @@ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
## What's new
|
||||
1.2.3 - fixed ios socket closing crashes
|
||||
1.5.0 - added ios open and write timeouts, changed js errors format
|
@ -1,9 +1,8 @@
|
||||
{
|
||||
"name": "SocketsForCordova",
|
||||
"version": "1.2.0",
|
||||
"name": "cordova-plugin-socket-tcp",
|
||||
"version": "1.5.0",
|
||||
"description": "This Cordova plugin provides JavaScript API, that allows you to communicate with server through TCP protocol. Currently we support these platforms: iOS, Android, WP8.",
|
||||
"cordova": {
|
||||
"id": "cz.blocshop.socketsforcordova",
|
||||
"platforms": [
|
||||
"ios",
|
||||
"android",
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" id="cz.blocshop.socketsforcordova" version="1.2.0">
|
||||
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0" id="cordova-plugin-socket-tcp" version="1.5.0">
|
||||
<name>SocketsForCordova</name>
|
||||
<description>
|
||||
This Cordova plugin provides JavaScript API, that allows you to communicate with server through TCP protocol.
|
||||
|
394
socket.js
394
socket.js
@ -1,213 +1,221 @@
|
||||
/**
|
||||
* Copyright (c) 2015, Blocshop s.r.o.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the Blocshop s.r.o.. The name of the
|
||||
* Blocshop s.r.o. may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
cordova.define("cordova-plugin-socket-tcp.Socket", function(require, exports, module) {
|
||||
/**
|
||||
* Copyright (c) 2015, Blocshop s.r.o.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the Blocshop s.r.o.. The name of the
|
||||
* Blocshop s.r.o. may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
|
||||
var exec = require('cordova/exec');
|
||||
var exec = require('cordova/exec');
|
||||
|
||||
var SOCKET_EVENT = "SOCKET_EVENT";
|
||||
var CORDOVA_SERVICE_NAME = "SocketsForCordova";
|
||||
var SOCKET_EVENT = "SOCKET_EVENT";
|
||||
var CORDOVA_SERVICE_NAME = "SocketsForCordova";
|
||||
|
||||
Socket.State = {};
|
||||
Socket.State[Socket.State.CLOSED = 0] = "CLOSED";
|
||||
Socket.State[Socket.State.OPENING = 1] = "OPENING";
|
||||
Socket.State[Socket.State.OPENED = 2] = "OPENED";
|
||||
Socket.State[Socket.State.CLOSING = 3] = "CLOSING";
|
||||
Socket.State = {};
|
||||
Socket.State[Socket.State.CLOSED = 0] = "CLOSED";
|
||||
Socket.State[Socket.State.OPENING = 1] = "OPENING";
|
||||
Socket.State[Socket.State.OPENED = 2] = "OPENED";
|
||||
Socket.State[Socket.State.CLOSING = 3] = "CLOSING";
|
||||
|
||||
function Socket() {
|
||||
this._state = Socket.State.CLOSED;
|
||||
this.onData = null;
|
||||
this.onClose = null;
|
||||
this.onError = null;
|
||||
this.socketKey = guid();
|
||||
}
|
||||
Socket.ErrorType = {};
|
||||
Socket.ErrorType[Socket.ErrorType.GENERAL = 0] = "general";
|
||||
Socket.ErrorType[Socket.ErrorType.OPEN_TIMEOUT = 1] = "openTimeout";
|
||||
Socket.ErrorType[Socket.ErrorType.WRITE_TIMEOUT = 2] = "writeTimeout";
|
||||
|
||||
Socket.prototype.open = function (host, port, success, error) {
|
||||
|
||||
success = success || function() { };
|
||||
error = error || function() { };
|
||||
|
||||
if (!this._ensureState(Socket.State.CLOSED, error)) {
|
||||
return;
|
||||
function Socket() {
|
||||
this._state = Socket.State.CLOSED;
|
||||
this.onData = null;
|
||||
this.onClose = null;
|
||||
this.onError = null;
|
||||
this.socketKey = guid();
|
||||
}
|
||||
|
||||
var _that = this;
|
||||
Socket.prototype.open = function (host, port, success, error) {
|
||||
|
||||
function socketEventHandler(event) {
|
||||
success = success || function() { };
|
||||
error = error || function() { };
|
||||
|
||||
var payload = event.payload;
|
||||
|
||||
if (payload.socketKey !== _that.socketKey) {
|
||||
if (!this._ensureState(Socket.State.CLOSED, error)) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (payload.type) {
|
||||
case "Close":
|
||||
_that._state = Socket.State.CLOSED;
|
||||
window.document.removeEventListener(SOCKET_EVENT, socketEventHandler);
|
||||
_that.onClose(payload.hasError);
|
||||
break;
|
||||
case "DataReceived":
|
||||
_that.onData(new Uint8Array(payload.data));
|
||||
break;
|
||||
case "Error":
|
||||
_that.onError(payload.errorMessage);
|
||||
break;
|
||||
default:
|
||||
console.error("SocketsForCordova: Unknown event type " + payload.type + ", socket key: " + payload.socketKey);
|
||||
break;
|
||||
var _that = this;
|
||||
|
||||
function socketEventHandler(event) {
|
||||
|
||||
var payload = event.payload;
|
||||
|
||||
if (payload.socketKey !== _that.socketKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (payload.type) {
|
||||
case "Close":
|
||||
_that._state = Socket.State.CLOSED;
|
||||
window.document.removeEventListener(SOCKET_EVENT, socketEventHandler);
|
||||
_that.onClose(payload.hasError);
|
||||
break;
|
||||
case "DataReceived":
|
||||
_that.onData(new Uint8Array(payload.data));
|
||||
break;
|
||||
case "Error":
|
||||
_that.onError(payload);
|
||||
break;
|
||||
default:
|
||||
console.error("SocketsForCordova: Unknown event type " + payload.type + ", socket key: " + payload.socketKey);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_that._state = Socket.State.OPENING;
|
||||
_that._state = Socket.State.OPENING;
|
||||
|
||||
exec(
|
||||
function () {
|
||||
_that._state = Socket.State.OPENED;
|
||||
window.document.addEventListener(SOCKET_EVENT, socketEventHandler);
|
||||
success();
|
||||
},
|
||||
function(errorMessage) {
|
||||
_that._state = Socket.State.CLOSED;
|
||||
error(errorMessage);
|
||||
},
|
||||
CORDOVA_SERVICE_NAME,
|
||||
"open",
|
||||
[ this.socketKey, host, port ]);
|
||||
};
|
||||
|
||||
Socket.prototype.write = function (data, success, error) {
|
||||
|
||||
success = success || function() { };
|
||||
error = error || function() { };
|
||||
|
||||
if (!this._ensureState(Socket.State.OPENED, error)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var dataToWrite = data instanceof Uint8Array
|
||||
? Socket._copyToArray(data)
|
||||
: data;
|
||||
|
||||
exec(
|
||||
success,
|
||||
error,
|
||||
CORDOVA_SERVICE_NAME,
|
||||
"write",
|
||||
[ this.socketKey, dataToWrite ]);
|
||||
};
|
||||
|
||||
Socket.prototype.shutdownWrite = function (success, error) {
|
||||
|
||||
success = success || function() { };
|
||||
error = error || function() { };
|
||||
|
||||
if (!this._ensureState(Socket.State.OPENED, error)) {
|
||||
return;
|
||||
}
|
||||
|
||||
exec(
|
||||
success,
|
||||
error,
|
||||
CORDOVA_SERVICE_NAME,
|
||||
"shutdownWrite",
|
||||
[ this.socketKey ]);
|
||||
};
|
||||
|
||||
Socket.prototype.close = function (success, error) {
|
||||
|
||||
success = success || function() { };
|
||||
error = error || function() { };
|
||||
|
||||
if (!this._ensureState(Socket.State.OPENED, error)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._state = Socket.State.CLOSING;
|
||||
|
||||
exec(
|
||||
success,
|
||||
error,
|
||||
CORDOVA_SERVICE_NAME,
|
||||
"close",
|
||||
[ this.socketKey ]);
|
||||
};
|
||||
|
||||
Object.defineProperty(Socket.prototype, "state", {
|
||||
get: function () {
|
||||
return this._state;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Socket.prototype._ensureState = function(requiredState, errorCallback) {
|
||||
var state = this._state;
|
||||
if (state != requiredState) {
|
||||
window.setTimeout(function() {
|
||||
errorCallback("Invalid operation for this socket state: " + Socket.State[state]);
|
||||
});
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
Socket.dispatchEvent = function (event) {
|
||||
var eventReceive = document.createEvent('Events');
|
||||
eventReceive.initEvent(SOCKET_EVENT, true, true);
|
||||
eventReceive.payload = event;
|
||||
|
||||
document.dispatchEvent(eventReceive);
|
||||
};
|
||||
|
||||
Socket._copyToArray = function (array) {
|
||||
var outputArray = new Array(array.length);
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
outputArray[i] = array[i];
|
||||
}
|
||||
return outputArray;
|
||||
};
|
||||
|
||||
var guid = (function () {
|
||||
function s4() {
|
||||
return Math.floor((1 + Math.random()) * 0x10000)
|
||||
.toString(16)
|
||||
.substring(1);
|
||||
}
|
||||
|
||||
return function () {
|
||||
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
|
||||
s4() + '-' + s4() + s4() + s4();
|
||||
};
|
||||
})();
|
||||
|
||||
// Register event dispatcher for Windows Phone
|
||||
if (navigator.userAgent.match(/iemobile/i)) {
|
||||
window.document.addEventListener("deviceready", function () {
|
||||
exec(
|
||||
Socket.dispatchEvent,
|
||||
function (errorMessage) {
|
||||
console.error("SocketsForCordova: Cannot register WP event dispatcher, Error: " + errorMessage);
|
||||
function () {
|
||||
_that._state = Socket.State.OPENED;
|
||||
window.document.addEventListener(SOCKET_EVENT, socketEventHandler);
|
||||
success();
|
||||
},
|
||||
function(errorMessage) {
|
||||
_that._state = Socket.State.CLOSED;
|
||||
error(errorMessage);
|
||||
},
|
||||
CORDOVA_SERVICE_NAME,
|
||||
"registerWPEventDispatcher",
|
||||
[ ]);
|
||||
});
|
||||
}
|
||||
"open",
|
||||
[ this.socketKey, host, port ]);
|
||||
};
|
||||
|
||||
module.exports = Socket;
|
||||
Socket.prototype.write = function (data, success, error) {
|
||||
|
||||
success = success || function() { };
|
||||
error = error || function() { };
|
||||
|
||||
if (!this._ensureState(Socket.State.OPENED, error)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var dataToWrite = data instanceof Uint8Array
|
||||
? Socket._copyToArray(data)
|
||||
: data;
|
||||
|
||||
exec(
|
||||
success,
|
||||
error,
|
||||
CORDOVA_SERVICE_NAME,
|
||||
"write",
|
||||
[ this.socketKey, dataToWrite ]);
|
||||
};
|
||||
|
||||
Socket.prototype.shutdownWrite = function (success, error) {
|
||||
|
||||
success = success || function() { };
|
||||
error = error || function() { };
|
||||
|
||||
if (!this._ensureState(Socket.State.OPENED, error)) {
|
||||
return;
|
||||
}
|
||||
|
||||
exec(
|
||||
success,
|
||||
error,
|
||||
CORDOVA_SERVICE_NAME,
|
||||
"shutdownWrite",
|
||||
[ this.socketKey ]);
|
||||
};
|
||||
|
||||
Socket.prototype.close = function (success, error) {
|
||||
|
||||
success = success || function() { };
|
||||
error = error || function() { };
|
||||
|
||||
if (!this._ensureState(Socket.State.OPENED, error)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._state = Socket.State.CLOSING;
|
||||
|
||||
exec(
|
||||
success,
|
||||
error,
|
||||
CORDOVA_SERVICE_NAME,
|
||||
"close",
|
||||
[ this.socketKey ]);
|
||||
};
|
||||
|
||||
Object.defineProperty(Socket.prototype, "state", {
|
||||
get: function () {
|
||||
return this._state;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Socket.prototype._ensureState = function(requiredState, errorCallback) {
|
||||
var state = this._state;
|
||||
if (state != requiredState) {
|
||||
window.setTimeout(function() {
|
||||
errorCallback("Invalid operation for this socket state: " + Socket.State[state]);
|
||||
});
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
Socket.dispatchEvent = function (event) {
|
||||
var eventReceive = document.createEvent('Events');
|
||||
eventReceive.initEvent(SOCKET_EVENT, true, true);
|
||||
eventReceive.payload = event;
|
||||
|
||||
document.dispatchEvent(eventReceive);
|
||||
};
|
||||
|
||||
Socket._copyToArray = function (array) {
|
||||
var outputArray = new Array(array.length);
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
outputArray[i] = array[i];
|
||||
}
|
||||
return outputArray;
|
||||
};
|
||||
|
||||
var guid = (function () {
|
||||
function s4() {
|
||||
return Math.floor((1 + Math.random()) * 0x10000)
|
||||
.toString(16)
|
||||
.substring(1);
|
||||
}
|
||||
|
||||
return function () {
|
||||
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
|
||||
s4() + '-' + s4() + s4() + s4();
|
||||
};
|
||||
})();
|
||||
|
||||
// Register event dispatcher for Windows Phone
|
||||
if (navigator.userAgent.match(/iemobile/i)) {
|
||||
window.document.addEventListener("deviceready", function () {
|
||||
exec(
|
||||
Socket.dispatchEvent,
|
||||
function (errorMessage) {
|
||||
console.error("SocketsForCordova: Cannot register WP event dispatcher, Error: " + errorMessage);
|
||||
},
|
||||
CORDOVA_SERVICE_NAME,
|
||||
"registerWPEventDispatcher",
|
||||
[ ]);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = Socket;
|
||||
|
||||
});
|
@ -24,6 +24,9 @@
|
||||
|
||||
NSInputStream *inputStream1;
|
||||
NSOutputStream *outputStream1;
|
||||
|
||||
NSTimer *openTimer;
|
||||
NSTimer *writeTimer;
|
||||
}
|
||||
|
||||
- (void)open:(NSString *)host port:(NSNumber*)port;
|
||||
@ -36,6 +39,6 @@
|
||||
@property (copy) void (^openErrorEventHandler)(NSString*);
|
||||
@property (copy) void (^dataConsumer)(NSArray*);
|
||||
@property (copy) void (^closeEventHandler)(BOOL);
|
||||
@property (copy) void (^errorEventHandler)(NSString*);
|
||||
@property (copy) void (^errorEventHandler)(NSString*, NSString *);
|
||||
|
||||
@end
|
@ -27,19 +27,24 @@ CFWriteStreamRef writeStream;
|
||||
NSInputStream *inputStream;
|
||||
NSOutputStream *outputStream;
|
||||
|
||||
NSTimer *openTimer;
|
||||
NSTimer *writeTimer;
|
||||
|
||||
BOOL wasOpenned = FALSE;
|
||||
|
||||
int const WRITE_BUFFER_SIZE = 10 * 1024;
|
||||
|
||||
int openTimeoutSeconds = 5.0;
|
||||
int writeTimeoutSeconds = 5.0;
|
||||
|
||||
@implementation SocketAdapter
|
||||
|
||||
- (void)open:(NSString *)host port:(NSNumber*)port {
|
||||
|
||||
|
||||
CFReadStreamRef readStream2;
|
||||
CFWriteStreamRef writeStream2;
|
||||
|
||||
|
||||
NSLog(@"Setting up connection to %@ : %@", host, [port stringValue]);
|
||||
NSLog(@"[NATIVE] Setting up connection to %@ : %@", host, [port stringValue]);
|
||||
|
||||
if (![self isIp:host]) {
|
||||
host = [self resolveIp:host];
|
||||
@ -51,7 +56,7 @@ int const WRITE_BUFFER_SIZE = 10 * 1024;
|
||||
CFWriteStreamSetProperty(writeStream2, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
|
||||
|
||||
if(!CFWriteStreamOpen(writeStream2) || !CFReadStreamOpen(readStream2)) {
|
||||
NSLog(@"Error, streams not open");
|
||||
NSLog(@"[NATIVE] Error, streams not open");
|
||||
|
||||
@throw [NSException exceptionWithName:@"SocketException" reason:@"Cannot open streams." userInfo:nil];
|
||||
}
|
||||
@ -60,12 +65,28 @@ int const WRITE_BUFFER_SIZE = 10 * 1024;
|
||||
[inputStream1 setDelegate:self];
|
||||
[inputStream1 open];
|
||||
|
||||
NSTimer *timer = [NSTimer timerWithTimeInterval:openTimeoutSeconds target:self selector:@selector(onOpenTimeout:) userInfo:nil repeats:NO];
|
||||
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
|
||||
openTimer = timer;
|
||||
|
||||
outputStream1 = (__bridge NSOutputStream *)writeStream2;
|
||||
[outputStream1 open];
|
||||
|
||||
[self performSelectorOnMainThread:@selector(runReadLoop) withObject:nil waitUntilDone:NO];
|
||||
}
|
||||
|
||||
-(void)onOpenTimeout:(NSTimer *)timer {
|
||||
NSLog(@"[NATIVE] Open timeout: %d", openTimeoutSeconds);
|
||||
self.errorEventHandler(@"openTimeout", @"timeout");
|
||||
openTimer = nil;
|
||||
}
|
||||
|
||||
-(void)onWriteTimeout:(NSTimer *)timer {
|
||||
NSLog(@"[NATIVE] Write timeout: %d", writeTimeoutSeconds);
|
||||
self.errorEventHandler(@"writeTimeout", @"timeout");
|
||||
writeTimer = nil;
|
||||
}
|
||||
|
||||
-(BOOL)isIp:(NSString*) host {
|
||||
const char *utf8 = [host UTF8String];
|
||||
|
||||
@ -82,7 +103,7 @@ int const WRITE_BUFFER_SIZE = 10 * 1024;
|
||||
|
||||
-(NSString*)resolveIp:(NSString*) host {
|
||||
|
||||
NSLog(@"Resolving host: %@", host);
|
||||
NSLog(@"[NATIVE] Resolving host: %@", host);
|
||||
|
||||
const char *buff = [host cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
struct hostent *host_entry = gethostbyname(buff);
|
||||
@ -94,7 +115,7 @@ int const WRITE_BUFFER_SIZE = 10 * 1024;
|
||||
char *hostCstring = inet_ntoa(*((struct in_addr *)host_entry->h_addr_list[0]));
|
||||
host = [NSString stringWithUTF8String:hostCstring];
|
||||
|
||||
NSLog(@"Resolved ip: %@", host);
|
||||
NSLog(@"[NATIVE] Resolved ip: %@", host);
|
||||
|
||||
return host;
|
||||
}
|
||||
@ -104,7 +125,7 @@ int const WRITE_BUFFER_SIZE = 10 * 1024;
|
||||
}
|
||||
|
||||
- (void)shutdownWrite {
|
||||
NSLog(@"Shuting down write on socket.");
|
||||
NSLog(@"[NATIVE] Shuting down write on socket.");
|
||||
|
||||
[self closeOutputStream];
|
||||
|
||||
@ -143,10 +164,21 @@ int const WRITE_BUFFER_SIZE = 10 * 1024;
|
||||
case NSStreamEventOpenCompleted: {
|
||||
self.openEventHandler();
|
||||
wasOpenned = TRUE;
|
||||
if(openTimer != nil){
|
||||
NSLog(@"[NATIVE] openTimer invalidate on open event");
|
||||
[openTimer invalidate];
|
||||
openTimer = nil;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NSStreamEventHasBytesAvailable: {
|
||||
if(stream == inputStream1) {
|
||||
if(writeTimer != nil){
|
||||
NSLog(@"[NATIVE] writeTimer invalidate on has bytes event");
|
||||
[writeTimer invalidate];
|
||||
writeTimer = nil;
|
||||
}
|
||||
|
||||
uint8_t buf[65535];
|
||||
long len = [inputStream1 read:buf maxLength:65535];
|
||||
|
||||
@ -172,14 +204,14 @@ int const WRITE_BUFFER_SIZE = 10 * 1024;
|
||||
}
|
||||
case NSStreamEventErrorOccurred:
|
||||
{
|
||||
NSLog(@"Stream event error: %@", [[stream streamError] localizedDescription]);
|
||||
NSLog(@"[NATIVE] Stream event error: %@", [[stream streamError] localizedDescription]);
|
||||
|
||||
if (wasOpenned) {
|
||||
self.errorEventHandler([[stream streamError] localizedDescription]);
|
||||
self.errorEventHandler([[stream streamError] localizedDescription], @"general");
|
||||
self.closeEventHandler(TRUE);
|
||||
}
|
||||
else {
|
||||
self.errorEventHandler([[stream streamError] localizedDescription]);
|
||||
self.errorEventHandler([[stream streamError] localizedDescription], @"general");
|
||||
self.openErrorEventHandler([[stream streamError] localizedDescription]);
|
||||
}
|
||||
//[self closeStreams];
|
||||
@ -198,6 +230,11 @@ int const WRITE_BUFFER_SIZE = 10 * 1024;
|
||||
[self writeSubarray:dataArray offset:i * WRITE_BUFFER_SIZE length:WRITE_BUFFER_SIZE];
|
||||
}
|
||||
int lastBatchPosition = (numberOfBatches - 1) * WRITE_BUFFER_SIZE;
|
||||
|
||||
NSTimer *timer = [NSTimer timerWithTimeInterval:writeTimeoutSeconds target:self selector:@selector(onWriteTimeout:) userInfo:nil repeats:NO];
|
||||
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
|
||||
writeTimer = timer;
|
||||
|
||||
[self writeSubarray:dataArray offset:lastBatchPosition length:(dataArray.count - lastBatchPosition)];
|
||||
}
|
||||
|
||||
@ -224,6 +261,18 @@ int const WRITE_BUFFER_SIZE = 10 * 1024;
|
||||
- (void)closeStreams {
|
||||
[self closeOutputStream];
|
||||
[self closeInputStream];
|
||||
|
||||
if(writeTimer != nil){
|
||||
[writeTimer invalidate];
|
||||
writeTimer = nil;
|
||||
NSLog(@"[NATIVE] writeTimer invalidate on close");
|
||||
}
|
||||
|
||||
if(openTimer != nil){
|
||||
[openTimer invalidate];
|
||||
openTimer = nil;
|
||||
NSLog(@"[NATIVE] openTimer invalidate on close");
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
@ -47,9 +47,10 @@
|
||||
|
||||
socketAdapter = nil;
|
||||
};
|
||||
socketAdapter.errorEventHandler = ^ void (NSString *error){
|
||||
socketAdapter.errorEventHandler = ^ void (NSString *error, NSString *errorType){
|
||||
NSMutableDictionary *errorDictionaryData = [[NSMutableDictionary alloc] init];
|
||||
[errorDictionaryData setObject:@"Error" forKey:@"type"];
|
||||
[errorDictionaryData setObject:errorType forKey:@"errorType"];
|
||||
[errorDictionaryData setObject:error forKey:@"errorMessage"];
|
||||
[errorDictionaryData setObject:socketKey forKey:@"socketKey"];
|
||||
|
||||
@ -97,7 +98,11 @@
|
||||
|
||||
[self.commandDelegate runInBackground:^{
|
||||
@try {
|
||||
[socket write:data];
|
||||
if (socket != nil) {
|
||||
[socket write:data];
|
||||
}else{
|
||||
NSLog(@"[NATIVE] Write: socket is nil. SocketKey: %@", socketKey);
|
||||
}
|
||||
[self.commandDelegate
|
||||
sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK]
|
||||
callbackId:command.callbackId];
|
||||
@ -118,7 +123,12 @@
|
||||
|
||||
[self.commandDelegate runInBackground:^{
|
||||
@try {
|
||||
[socket shutdownWrite];
|
||||
if (socket != nil) {
|
||||
[socket shutdownWrite];
|
||||
}else{
|
||||
NSLog(@"[NATIVE] ShutdownWrite: socket is nil. SocketKey: %@", socketKey);
|
||||
}
|
||||
|
||||
[self.commandDelegate
|
||||
sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK]
|
||||
callbackId:command.callbackId];
|
||||
@ -139,7 +149,12 @@
|
||||
|
||||
[self.commandDelegate runInBackground:^{
|
||||
@try {
|
||||
[socket close];
|
||||
if (socket != nil) {
|
||||
[socket close];
|
||||
}else{
|
||||
NSLog(@"[NATIVE] Close: socket is nil. SocketKey: %@", socketKey);
|
||||
}
|
||||
|
||||
[self.commandDelegate
|
||||
sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK]
|
||||
callbackId:command.callbackId];
|
||||
@ -158,15 +173,16 @@
|
||||
- (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];
|
||||
NSLog(@"[NATIVE] Cannot find socketKey: %@. Connection is probably closed.", socketKey);
|
||||
//NSString *exceptionReason = [NSString stringWithFormat:@"Cannot find socketKey: %@. Connection is probably closed.", socketKey];
|
||||
|
||||
@throw [NSException exceptionWithName:@"IllegalArgumentException" reason:exceptionReason userInfo:nil];
|
||||
//@throw [NSException exceptionWithName:@"IllegalArgumentException" reason:exceptionReason userInfo:nil];
|
||||
}
|
||||
return socketAdapter;
|
||||
}
|
||||
|
||||
- (void) removeSocketAdapter: (NSString*) socketKey {
|
||||
NSLog(@"Removing socket adapter from storage.");
|
||||
NSLog(@"[NATIVE] Removing socket adapter from storage.");
|
||||
[self->socketAdapters removeObjectForKey:socketKey];
|
||||
}
|
||||
|
||||
@ -178,7 +194,7 @@
|
||||
- (void) dispatchEventWithDictionary: (NSDictionary*) dictionary {
|
||||
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:nil];
|
||||
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
|
||||
|
||||
[self dispatchEvent:jsonString];
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user