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
|
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
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
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",
|
"name": "cordova-plugin-socket-tcp",
|
||||||
"version": "1.2.0",
|
"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.",
|
"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": {
|
"cordova": {
|
||||||
"id": "cz.blocshop.socketsforcordova",
|
|
||||||
"platforms": [
|
"platforms": [
|
||||||
"ios",
|
"ios",
|
||||||
"android",
|
"android",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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>
|
<name>SocketsForCordova</name>
|
||||||
<description>
|
<description>
|
||||||
This Cordova plugin provides JavaScript API, that allows you to communicate with server through TCP protocol.
|
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 @@
|
|||||||
/**
|
cordova.define("cordova-plugin-socket-tcp.Socket", function(require, exports, module) {
|
||||||
* Copyright (c) 2015, Blocshop s.r.o.
|
/**
|
||||||
* All rights reserved.
|
* 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
|
* Redistribution and use in source and binary forms are permitted
|
||||||
* duplicated in all such forms and that any documentation,
|
* provided that the above copyright notice and this paragraph are
|
||||||
* advertising materials, and other materials related to such
|
* duplicated in all such forms and that any documentation,
|
||||||
* distribution and use acknowledge that the software was developed
|
* advertising materials, and other materials related to such
|
||||||
* by the Blocshop s.r.o.. The name of the
|
* distribution and use acknowledge that the software was developed
|
||||||
* Blocshop s.r.o. may not be used to endorse or promote products derived
|
* by the Blocshop s.r.o.. The name of the
|
||||||
* from this software without specific prior written permission.
|
* Blocshop s.r.o. may not be used to endorse or promote products derived
|
||||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
* from this software without specific prior written permission.
|
||||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
* 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 SOCKET_EVENT = "SOCKET_EVENT";
|
||||||
var CORDOVA_SERVICE_NAME = "SocketsForCordova";
|
var CORDOVA_SERVICE_NAME = "SocketsForCordova";
|
||||||
|
|
||||||
Socket.State = {};
|
Socket.State = {};
|
||||||
Socket.State[Socket.State.CLOSED = 0] = "CLOSED";
|
Socket.State[Socket.State.CLOSED = 0] = "CLOSED";
|
||||||
Socket.State[Socket.State.OPENING = 1] = "OPENING";
|
Socket.State[Socket.State.OPENING = 1] = "OPENING";
|
||||||
Socket.State[Socket.State.OPENED = 2] = "OPENED";
|
Socket.State[Socket.State.OPENED = 2] = "OPENED";
|
||||||
Socket.State[Socket.State.CLOSING = 3] = "CLOSING";
|
Socket.State[Socket.State.CLOSING = 3] = "CLOSING";
|
||||||
|
|
||||||
function Socket() {
|
Socket.ErrorType = {};
|
||||||
this._state = Socket.State.CLOSED;
|
Socket.ErrorType[Socket.ErrorType.GENERAL = 0] = "general";
|
||||||
this.onData = null;
|
Socket.ErrorType[Socket.ErrorType.OPEN_TIMEOUT = 1] = "openTimeout";
|
||||||
this.onClose = null;
|
Socket.ErrorType[Socket.ErrorType.WRITE_TIMEOUT = 2] = "writeTimeout";
|
||||||
this.onError = null;
|
|
||||||
this.socketKey = guid();
|
|
||||||
}
|
|
||||||
|
|
||||||
Socket.prototype.open = function (host, port, success, error) {
|
function Socket() {
|
||||||
|
this._state = Socket.State.CLOSED;
|
||||||
success = success || function() { };
|
this.onData = null;
|
||||||
error = error || function() { };
|
this.onClose = null;
|
||||||
|
this.onError = null;
|
||||||
if (!this._ensureState(Socket.State.CLOSED, error)) {
|
this.socketKey = guid();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 (!this._ensureState(Socket.State.CLOSED, error)) {
|
||||||
|
|
||||||
if (payload.socketKey !== _that.socketKey) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (payload.type) {
|
var _that = this;
|
||||||
case "Close":
|
|
||||||
_that._state = Socket.State.CLOSED;
|
function socketEventHandler(event) {
|
||||||
window.document.removeEventListener(SOCKET_EVENT, socketEventHandler);
|
|
||||||
_that.onClose(payload.hasError);
|
var payload = event.payload;
|
||||||
break;
|
|
||||||
case "DataReceived":
|
if (payload.socketKey !== _that.socketKey) {
|
||||||
_that.onData(new Uint8Array(payload.data));
|
return;
|
||||||
break;
|
}
|
||||||
case "Error":
|
|
||||||
_that.onError(payload.errorMessage);
|
switch (payload.type) {
|
||||||
break;
|
case "Close":
|
||||||
default:
|
_that._state = Socket.State.CLOSED;
|
||||||
console.error("SocketsForCordova: Unknown event type " + payload.type + ", socket key: " + payload.socketKey);
|
window.document.removeEventListener(SOCKET_EVENT, socketEventHandler);
|
||||||
break;
|
_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(
|
exec(
|
||||||
Socket.dispatchEvent,
|
function () {
|
||||||
function (errorMessage) {
|
_that._state = Socket.State.OPENED;
|
||||||
console.error("SocketsForCordova: Cannot register WP event dispatcher, Error: " + errorMessage);
|
window.document.addEventListener(SOCKET_EVENT, socketEventHandler);
|
||||||
|
success();
|
||||||
|
},
|
||||||
|
function(errorMessage) {
|
||||||
|
_that._state = Socket.State.CLOSED;
|
||||||
|
error(errorMessage);
|
||||||
},
|
},
|
||||||
CORDOVA_SERVICE_NAME,
|
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;
|
NSInputStream *inputStream1;
|
||||||
NSOutputStream *outputStream1;
|
NSOutputStream *outputStream1;
|
||||||
|
|
||||||
|
NSTimer *openTimer;
|
||||||
|
NSTimer *writeTimer;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)open:(NSString *)host port:(NSNumber*)port;
|
- (void)open:(NSString *)host port:(NSNumber*)port;
|
||||||
@ -36,6 +39,6 @@
|
|||||||
@property (copy) void (^openErrorEventHandler)(NSString*);
|
@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 (^errorEventHandler)(NSString*);
|
@property (copy) void (^errorEventHandler)(NSString*, NSString *);
|
||||||
|
|
||||||
@end
|
@end
|
@ -27,19 +27,24 @@ CFWriteStreamRef writeStream;
|
|||||||
NSInputStream *inputStream;
|
NSInputStream *inputStream;
|
||||||
NSOutputStream *outputStream;
|
NSOutputStream *outputStream;
|
||||||
|
|
||||||
|
NSTimer *openTimer;
|
||||||
|
NSTimer *writeTimer;
|
||||||
|
|
||||||
BOOL wasOpenned = FALSE;
|
BOOL wasOpenned = FALSE;
|
||||||
|
|
||||||
int const WRITE_BUFFER_SIZE = 10 * 1024;
|
int const WRITE_BUFFER_SIZE = 10 * 1024;
|
||||||
|
|
||||||
|
int openTimeoutSeconds = 5.0;
|
||||||
|
int writeTimeoutSeconds = 5.0;
|
||||||
|
|
||||||
@implementation SocketAdapter
|
@implementation SocketAdapter
|
||||||
|
|
||||||
- (void)open:(NSString *)host port:(NSNumber*)port {
|
- (void)open:(NSString *)host port:(NSNumber*)port {
|
||||||
|
|
||||||
CFReadStreamRef readStream2;
|
CFReadStreamRef readStream2;
|
||||||
CFWriteStreamRef writeStream2;
|
CFWriteStreamRef writeStream2;
|
||||||
|
|
||||||
|
NSLog(@"[NATIVE] Setting up connection to %@ : %@", host, [port stringValue]);
|
||||||
NSLog(@"Setting up connection to %@ : %@", host, [port stringValue]);
|
|
||||||
|
|
||||||
if (![self isIp:host]) {
|
if (![self isIp:host]) {
|
||||||
host = [self resolveIp:host];
|
host = [self resolveIp:host];
|
||||||
@ -51,7 +56,7 @@ int const WRITE_BUFFER_SIZE = 10 * 1024;
|
|||||||
CFWriteStreamSetProperty(writeStream2, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
|
CFWriteStreamSetProperty(writeStream2, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
|
||||||
|
|
||||||
if(!CFWriteStreamOpen(writeStream2) || !CFReadStreamOpen(readStream2)) {
|
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];
|
@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 setDelegate:self];
|
||||||
[inputStream1 open];
|
[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 = (__bridge NSOutputStream *)writeStream2;
|
||||||
[outputStream1 open];
|
[outputStream1 open];
|
||||||
|
|
||||||
[self performSelectorOnMainThread:@selector(runReadLoop) withObject:nil waitUntilDone:NO];
|
[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 {
|
-(BOOL)isIp:(NSString*) host {
|
||||||
const char *utf8 = [host UTF8String];
|
const char *utf8 = [host UTF8String];
|
||||||
|
|
||||||
@ -82,7 +103,7 @@ int const WRITE_BUFFER_SIZE = 10 * 1024;
|
|||||||
|
|
||||||
-(NSString*)resolveIp:(NSString*) host {
|
-(NSString*)resolveIp:(NSString*) host {
|
||||||
|
|
||||||
NSLog(@"Resolving host: %@", host);
|
NSLog(@"[NATIVE] Resolving host: %@", host);
|
||||||
|
|
||||||
const char *buff = [host cStringUsingEncoding:NSUTF8StringEncoding];
|
const char *buff = [host cStringUsingEncoding:NSUTF8StringEncoding];
|
||||||
struct hostent *host_entry = gethostbyname(buff);
|
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]));
|
char *hostCstring = inet_ntoa(*((struct in_addr *)host_entry->h_addr_list[0]));
|
||||||
host = [NSString stringWithUTF8String:hostCstring];
|
host = [NSString stringWithUTF8String:hostCstring];
|
||||||
|
|
||||||
NSLog(@"Resolved ip: %@", host);
|
NSLog(@"[NATIVE] Resolved ip: %@", host);
|
||||||
|
|
||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
@ -104,7 +125,7 @@ int const WRITE_BUFFER_SIZE = 10 * 1024;
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)shutdownWrite {
|
- (void)shutdownWrite {
|
||||||
NSLog(@"Shuting down write on socket.");
|
NSLog(@"[NATIVE] Shuting down write on socket.");
|
||||||
|
|
||||||
[self closeOutputStream];
|
[self closeOutputStream];
|
||||||
|
|
||||||
@ -143,10 +164,21 @@ int const WRITE_BUFFER_SIZE = 10 * 1024;
|
|||||||
case NSStreamEventOpenCompleted: {
|
case NSStreamEventOpenCompleted: {
|
||||||
self.openEventHandler();
|
self.openEventHandler();
|
||||||
wasOpenned = TRUE;
|
wasOpenned = TRUE;
|
||||||
|
if(openTimer != nil){
|
||||||
|
NSLog(@"[NATIVE] openTimer invalidate on open event");
|
||||||
|
[openTimer invalidate];
|
||||||
|
openTimer = nil;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NSStreamEventHasBytesAvailable: {
|
case NSStreamEventHasBytesAvailable: {
|
||||||
if(stream == inputStream1) {
|
if(stream == inputStream1) {
|
||||||
|
if(writeTimer != nil){
|
||||||
|
NSLog(@"[NATIVE] writeTimer invalidate on has bytes event");
|
||||||
|
[writeTimer invalidate];
|
||||||
|
writeTimer = nil;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t buf[65535];
|
uint8_t buf[65535];
|
||||||
long len = [inputStream1 read:buf maxLength:65535];
|
long len = [inputStream1 read:buf maxLength:65535];
|
||||||
|
|
||||||
@ -172,14 +204,14 @@ int const WRITE_BUFFER_SIZE = 10 * 1024;
|
|||||||
}
|
}
|
||||||
case NSStreamEventErrorOccurred:
|
case NSStreamEventErrorOccurred:
|
||||||
{
|
{
|
||||||
NSLog(@"Stream event error: %@", [[stream streamError] localizedDescription]);
|
NSLog(@"[NATIVE] Stream event error: %@", [[stream streamError] localizedDescription]);
|
||||||
|
|
||||||
if (wasOpenned) {
|
if (wasOpenned) {
|
||||||
self.errorEventHandler([[stream streamError] localizedDescription]);
|
self.errorEventHandler([[stream streamError] localizedDescription], @"general");
|
||||||
self.closeEventHandler(TRUE);
|
self.closeEventHandler(TRUE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.errorEventHandler([[stream streamError] localizedDescription]);
|
self.errorEventHandler([[stream streamError] localizedDescription], @"general");
|
||||||
self.openErrorEventHandler([[stream streamError] localizedDescription]);
|
self.openErrorEventHandler([[stream streamError] localizedDescription]);
|
||||||
}
|
}
|
||||||
//[self closeStreams];
|
//[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];
|
[self writeSubarray:dataArray offset:i * WRITE_BUFFER_SIZE length:WRITE_BUFFER_SIZE];
|
||||||
}
|
}
|
||||||
int lastBatchPosition = (numberOfBatches - 1) * 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)];
|
[self writeSubarray:dataArray offset:lastBatchPosition length:(dataArray.count - lastBatchPosition)];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,6 +261,18 @@ int const WRITE_BUFFER_SIZE = 10 * 1024;
|
|||||||
- (void)closeStreams {
|
- (void)closeStreams {
|
||||||
[self closeOutputStream];
|
[self closeOutputStream];
|
||||||
[self closeInputStream];
|
[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
|
@end
|
@ -47,9 +47,10 @@
|
|||||||
|
|
||||||
socketAdapter = nil;
|
socketAdapter = nil;
|
||||||
};
|
};
|
||||||
socketAdapter.errorEventHandler = ^ void (NSString *error){
|
socketAdapter.errorEventHandler = ^ void (NSString *error, NSString *errorType){
|
||||||
NSMutableDictionary *errorDictionaryData = [[NSMutableDictionary alloc] init];
|
NSMutableDictionary *errorDictionaryData = [[NSMutableDictionary alloc] init];
|
||||||
[errorDictionaryData setObject:@"Error" forKey:@"type"];
|
[errorDictionaryData setObject:@"Error" forKey:@"type"];
|
||||||
|
[errorDictionaryData setObject:errorType forKey:@"errorType"];
|
||||||
[errorDictionaryData setObject:error forKey:@"errorMessage"];
|
[errorDictionaryData setObject:error forKey:@"errorMessage"];
|
||||||
[errorDictionaryData setObject:socketKey forKey:@"socketKey"];
|
[errorDictionaryData setObject:socketKey forKey:@"socketKey"];
|
||||||
|
|
||||||
@ -97,7 +98,11 @@
|
|||||||
|
|
||||||
[self.commandDelegate runInBackground:^{
|
[self.commandDelegate runInBackground:^{
|
||||||
@try {
|
@try {
|
||||||
[socket write:data];
|
if (socket != nil) {
|
||||||
|
[socket write:data];
|
||||||
|
}else{
|
||||||
|
NSLog(@"[NATIVE] Write: socket is nil. SocketKey: %@", socketKey);
|
||||||
|
}
|
||||||
[self.commandDelegate
|
[self.commandDelegate
|
||||||
sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK]
|
sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK]
|
||||||
callbackId:command.callbackId];
|
callbackId:command.callbackId];
|
||||||
@ -118,7 +123,12 @@
|
|||||||
|
|
||||||
[self.commandDelegate runInBackground:^{
|
[self.commandDelegate runInBackground:^{
|
||||||
@try {
|
@try {
|
||||||
[socket shutdownWrite];
|
if (socket != nil) {
|
||||||
|
[socket shutdownWrite];
|
||||||
|
}else{
|
||||||
|
NSLog(@"[NATIVE] ShutdownWrite: socket is nil. SocketKey: %@", socketKey);
|
||||||
|
}
|
||||||
|
|
||||||
[self.commandDelegate
|
[self.commandDelegate
|
||||||
sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK]
|
sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK]
|
||||||
callbackId:command.callbackId];
|
callbackId:command.callbackId];
|
||||||
@ -139,7 +149,12 @@
|
|||||||
|
|
||||||
[self.commandDelegate runInBackground:^{
|
[self.commandDelegate runInBackground:^{
|
||||||
@try {
|
@try {
|
||||||
[socket close];
|
if (socket != nil) {
|
||||||
|
[socket close];
|
||||||
|
}else{
|
||||||
|
NSLog(@"[NATIVE] Close: socket is nil. SocketKey: %@", socketKey);
|
||||||
|
}
|
||||||
|
|
||||||
[self.commandDelegate
|
[self.commandDelegate
|
||||||
sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK]
|
sendPluginResult:[CDVPluginResult resultWithStatus:CDVCommandStatus_OK]
|
||||||
callbackId:command.callbackId];
|
callbackId:command.callbackId];
|
||||||
@ -158,15 +173,16 @@
|
|||||||
- (SocketAdapter*) getSocketAdapter: (NSString*) socketKey {
|
- (SocketAdapter*) getSocketAdapter: (NSString*) socketKey {
|
||||||
SocketAdapter* socketAdapter = [self->socketAdapters objectForKey:socketKey];
|
SocketAdapter* socketAdapter = [self->socketAdapters objectForKey:socketKey];
|
||||||
if (socketAdapter == nil) {
|
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;
|
return socketAdapter;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) removeSocketAdapter: (NSString*) socketKey {
|
- (void) removeSocketAdapter: (NSString*) socketKey {
|
||||||
NSLog(@"Removing socket adapter from storage.");
|
NSLog(@"[NATIVE] Removing socket adapter from storage.");
|
||||||
[self->socketAdapters removeObjectForKey:socketKey];
|
[self->socketAdapters removeObjectForKey:socketKey];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +194,7 @@
|
|||||||
- (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];
|
||||||
|
|
||||||
[self dispatchEvent:jsonString];
|
[self dispatchEvent:jsonString];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user