stub out some more functionality
This commit is contained in:
parent
49dd5a926e
commit
1618cfb61f
164
TcpSocket.js
164
TcpSocket.js
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
var inherits = require('inherits');
|
var inherits = require('inherits');
|
||||||
var EventEmitter = require('events').EventEmitter;
|
var EventEmitter = require('events').EventEmitter;
|
||||||
|
var ipRegex = require('ip-regex');
|
||||||
var {
|
var {
|
||||||
DeviceEventEmitter,
|
DeviceEventEmitter,
|
||||||
NativeModules
|
NativeModules
|
||||||
|
@ -30,28 +31,30 @@ var STATE = {
|
||||||
|
|
||||||
module.exports = TcpSocket;
|
module.exports = TcpSocket;
|
||||||
|
|
||||||
function TcpSocket(options, onopen) {
|
function TcpSocket(options) {
|
||||||
EventEmitter.call(this);
|
EventEmitter.call(this);
|
||||||
|
|
||||||
this._id = instances++;
|
this._id = instances++;
|
||||||
this._state = STATE.DISCONNECTED;
|
this._state = STATE.DISCONNECTED;
|
||||||
this._connecting = false;
|
this._connecting = false;
|
||||||
this._hadError = false;
|
this._hadError = false;
|
||||||
this._handle = null;
|
|
||||||
this._parent = null;
|
|
||||||
this._host = null;
|
this._host = null;
|
||||||
|
|
||||||
if (typeof options === 'number') {
|
if (typeof options === 'number') {
|
||||||
options = { fd: options }; // Legacy interface.
|
options = { fd: options };
|
||||||
} else if (options === undefined) {
|
} else if (options === undefined) {
|
||||||
options = {};
|
options = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.fd) {
|
||||||
|
throw new Error('file descriptors are unsupoprted at this time.');
|
||||||
|
}
|
||||||
|
|
||||||
// these will be set once there is a connection
|
// these will be set once there is a connection
|
||||||
this.readable = this.writable = false;
|
this.readable = this.writable = false;
|
||||||
|
|
||||||
this._subscription = DeviceEventEmitter.addListener(
|
this._subscription = DeviceEventEmitter.addListener(
|
||||||
'tcp-' + this._id + '-data', this._onReceive.bind(this)
|
'tcp-' + this._id + '-event', this._onEvent.bind(this)
|
||||||
);
|
);
|
||||||
|
|
||||||
// ensure compatibility with node's EventEmitter
|
// ensure compatibility with node's EventEmitter
|
||||||
|
@ -59,11 +62,7 @@ function TcpSocket(options, onopen) {
|
||||||
this.on = this.addListener.bind(this);
|
this.on = this.addListener.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onopen) {
|
Sockets.createSocket(this._id); // later
|
||||||
this.on('open', onopen);
|
|
||||||
}
|
|
||||||
|
|
||||||
Sockets.createSocket(this._id, options); // later
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inherits(TcpSocket, EventEmitter);
|
inherits(TcpSocket, EventEmitter);
|
||||||
|
@ -79,71 +78,150 @@ TcpSocket.prototype._debug = function() {
|
||||||
TcpSocket.prototype.connect = function(options, callback) {
|
TcpSocket.prototype.connect = function(options, callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var port = options.port;
|
|
||||||
var host = options.host;
|
|
||||||
|
|
||||||
if (this._state !== STATE.DISCONNECTED) {
|
if (this._state !== STATE.DISCONNECTED) {
|
||||||
throw new Error('Socket is already bound');
|
throw new Error('Socket is already bound');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callback) {
|
if (typeof callback === 'function') {
|
||||||
this.once('connected', callback.bind(this));
|
this.once('connected', callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var host = options.host || 'localhost';
|
||||||
|
var port = options.port;
|
||||||
|
var localAddress = options.localAddress;
|
||||||
|
var localPort = options.localPort;
|
||||||
|
|
||||||
|
if (localAddress && !ipRegex({exact: true}).test(localAddress)) {
|
||||||
|
throw new TypeError('"localAddress" option must be a valid IP: ' + localAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localPort && typeof localPort !== 'number') {
|
||||||
|
throw new TypeError('"localPort" option should be a number: ' + localPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof port !== 'undefined') {
|
||||||
|
if (typeof port !== 'number' && typeof port !== 'string') {
|
||||||
|
throw new TypeError('"port" option should be a number or string: ' + port);
|
||||||
|
}
|
||||||
|
if (!isLegalPort(port)) {
|
||||||
|
throw new RangeError('"port" option should be >= 0 and < 65536: ' + port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
port |= 0;
|
||||||
|
|
||||||
this._state = STATE.CONNECTING;
|
this._state = STATE.CONNECTING;
|
||||||
this._connecting = true;
|
this._connecting = true;
|
||||||
this._debug('connecting, host:', host, 'port:', port);
|
this._debug('connecting, host:', host, 'port:', port);
|
||||||
Sockets.connect(this._id, port, host, function(err, addr) {
|
|
||||||
err = normalizeError(err);
|
|
||||||
if (err) {
|
|
||||||
// questionable: may want to self-destruct and
|
|
||||||
// force user to create a new socket
|
|
||||||
self._state = STATE.DISCONNECTED;
|
|
||||||
self._debug('failed to bind', err);
|
|
||||||
if (callback) {
|
|
||||||
callback(err);
|
|
||||||
}
|
|
||||||
return self.emit('error', err);
|
|
||||||
}
|
|
||||||
|
|
||||||
self._debug('connected to address:', host, 'port:', port);
|
Sockets.connect(this._id, host, Number(port), options);
|
||||||
// self._host = addr.host;
|
|
||||||
// self._port = addr.port;
|
|
||||||
self.writable = self.readable = true;
|
|
||||||
self._state = STATE.CONNECTED;
|
|
||||||
self._connecting = false;
|
|
||||||
self.emit('connected');
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Check that the port number is not NaN when coerced to a number,
|
||||||
|
// is an integer and that it falls within the legal range of port numbers.
|
||||||
|
function isLegalPort(port) {
|
||||||
|
if (typeof port === 'string' && port.trim() === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return +port === (port >>> 0) && port >= 0 && port <= 0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
TcpSocket.prototype.setTimeout = function(msecs, callback) {
|
TcpSocket.prototype.setTimeout = function(msecs, callback) {
|
||||||
|
if (this._timeout) {
|
||||||
|
clearTimeout(this._timeout);
|
||||||
|
this._timeout = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msecs > 0) {
|
||||||
|
if (callback) {
|
||||||
|
this.once('timeout', callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
this._timeout = setTimeout(msecs, function() {
|
||||||
|
self.emit('timeout');
|
||||||
|
this._timeout = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TcpSocket.prototype.setNoDelay = function(noDelay) {
|
||||||
// nothing yet
|
// nothing yet
|
||||||
};
|
};
|
||||||
|
|
||||||
TcpSocket.prototype.end = function() {
|
TcpSocket.prototype.setEncoding = function(encoding) {
|
||||||
|
// nothing yet
|
||||||
|
};
|
||||||
|
|
||||||
|
TcpSocket.prototype.setKeepAlive = function(enable, initialDelay) {
|
||||||
|
// nothing yet
|
||||||
|
};
|
||||||
|
|
||||||
|
TcpSocket.prototype.pause = function() {
|
||||||
|
// nothing yet
|
||||||
|
};
|
||||||
|
|
||||||
|
TcpSocket.prototype.resume = function() {
|
||||||
|
// nothing yet
|
||||||
|
};
|
||||||
|
|
||||||
|
TcpSocket.prototype.ref = function() {
|
||||||
|
// nothing yet
|
||||||
|
};
|
||||||
|
|
||||||
|
TcpSocket.prototype.unref = function() {
|
||||||
|
// nothing yet
|
||||||
|
};
|
||||||
|
|
||||||
|
TcpSocket.prototype.address = function() {
|
||||||
|
// nothing yet
|
||||||
|
};
|
||||||
|
|
||||||
|
TcpSocket.prototype.end = function(data, encoding) {
|
||||||
if (this._destroyed) {
|
if (this._destroyed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
this.write(data, encoding);
|
||||||
|
}
|
||||||
|
|
||||||
this._destroyed = true;
|
this._destroyed = true;
|
||||||
this._debug('closing');
|
this._debug('closing');
|
||||||
this._subscription.remove();
|
this._subscription.remove();
|
||||||
|
|
||||||
Sockets.close(this._id, this._debug.bind(this, 'closed'));
|
Sockets.end(this._id, this._debug.bind(this, 'closed'));
|
||||||
this.emit('close');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
TcpSocket.prototype.destroy = TcpSocket.prototype.end;
|
TcpSocket.prototype.destroy = function() {
|
||||||
|
this._destroyed = true;
|
||||||
|
this._debug('destroying');
|
||||||
|
this._subscription.remove();
|
||||||
|
|
||||||
TcpSocket.prototype._onReceive = function(info) {
|
Sockets.destroy(this._id);
|
||||||
this._debug('received', info);
|
};
|
||||||
|
|
||||||
|
TcpSocket.prototype._onEvent = function(info) {
|
||||||
|
this._debug('received', info.event);
|
||||||
|
|
||||||
|
if (info.event === 'connect') {
|
||||||
|
self.writable = self.readable = true;
|
||||||
|
self._state = STATE.CONNECTED;
|
||||||
|
self._connecting = false;
|
||||||
|
} else if (info.event === 'data') {
|
||||||
|
if (this._timeout) {
|
||||||
|
clearTimeout(this._timeout);
|
||||||
|
this._timeout = null;
|
||||||
|
}
|
||||||
|
|
||||||
// from base64 string
|
// from base64 string
|
||||||
var buf = typeof Buffer === 'undefined'
|
info.data = typeof Buffer === 'undefined'
|
||||||
? base64.toByteArray(info.data)
|
? base64.toByteArray(info.data)
|
||||||
: new global.Buffer(info.data, 'base64');
|
: new global.Buffer(info.data, 'base64');
|
||||||
|
} else if (info.event === 'close') {
|
||||||
|
self._state = STATE.DISCONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
this.emit('data', buf);
|
this.emit(info.event, info.data);
|
||||||
};
|
};
|
||||||
|
|
||||||
TcpSocket.prototype.write = function(buffer, encoding, callback) {
|
TcpSocket.prototype.write = function(buffer, encoding, callback) {
|
||||||
|
|
|
@ -4,10 +4,72 @@
|
||||||
*/
|
*/
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
var ipRegex = require('ip-regex');
|
||||||
|
|
||||||
exports.Socket = require('./TcpSocket');
|
exports.Socket = require('./TcpSocket');
|
||||||
|
|
||||||
|
// Target API:
|
||||||
|
//
|
||||||
|
// var s = net.connect({port: 80, host: 'google.com'}, function() {
|
||||||
|
// ...
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// There are various forms:
|
||||||
|
//
|
||||||
|
// connect(options, [cb])
|
||||||
|
// connect(port, [host], [cb])
|
||||||
|
// connect(path, [cb]);
|
||||||
|
//
|
||||||
|
exports.connect = exports.createConnection = function() {
|
||||||
|
var args = normalizeConnectArgs(arguments);
|
||||||
|
exports.Socket._debug('createConnection', args);
|
||||||
|
var s = new exports.Socket(args[0]);
|
||||||
|
return exports.Socket.prototype.connect.apply(s, args);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns an array [options] or [options, cb]
|
||||||
|
// It is the same as the argument of Socket.prototype.connect().
|
||||||
|
function normalizeConnectArgs(args) {
|
||||||
|
var options = {};
|
||||||
|
|
||||||
|
if (args[0] !== null && typeof args[0] === 'object') {
|
||||||
|
// connect(options, [cb])
|
||||||
|
options = args[0];
|
||||||
|
} else if (isPipeName(args[0])) {
|
||||||
|
// connect(path, [cb]);
|
||||||
|
options.path = args[0];
|
||||||
|
} else {
|
||||||
|
// connect(port, [host], [cb])
|
||||||
|
options.port = args[0];
|
||||||
|
if (typeof args[1] === 'string') {
|
||||||
|
options.host = args[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var cb = args[args.length - 1];
|
||||||
|
return typeof cb === 'function' ? [options, cb] : [options];
|
||||||
|
};
|
||||||
|
|
||||||
exports.createConnection = function(options, callback) {
|
exports.createConnection = function(options, callback) {
|
||||||
var tcpSocket = new exports.Socket();
|
var tcpSocket = new exports.Socket();
|
||||||
tcpSocket.connect(options, callback);
|
tcpSocket.connect(options, callback);
|
||||||
return tcpSocket;
|
return tcpSocket;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports.isIP = function(input) {
|
||||||
|
var result = 0;
|
||||||
|
if (ipRegex.v4({exact: true}).test(input)) {
|
||||||
|
result = 4;
|
||||||
|
} else if (ipRegex.v6({exact: true}).test(input)) {
|
||||||
|
result = 6;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.isIPv4 = function(input) {
|
||||||
|
return exports.isIP(input) === 4;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
exports.isIPv6 = function(input) {
|
||||||
|
return exports.isIP(input) === 6;
|
||||||
|
};
|
||||||
|
|
|
@ -10,61 +10,60 @@ var {
|
||||||
|
|
||||||
global.Buffer = global.Buffer || require('buffer').Buffer;
|
global.Buffer = global.Buffer || require('buffer').Buffer;
|
||||||
|
|
||||||
var telnet = require('./telnet-client');
|
var net = require('net');
|
||||||
var connection = new telnet();
|
|
||||||
|
|
||||||
// require('./test/simple/test-dgram-address')
|
function randomPort() {
|
||||||
// require('./test/simple/test-dgram-bind-default-address')
|
return Math.random() * 60536 | 0 + 5000 // 60536-65536
|
||||||
// require('./test/simple/test-dgram-bind-shared-ports')
|
}
|
||||||
|
|
||||||
// function randomPort() {
|
var a = net.createConnection({ port: randomPort() }, function(err) {
|
||||||
// return Math.random() * 60536 | 0 + 5000 // 60536-65536
|
if (err) throw err
|
||||||
// }
|
|
||||||
|
|
||||||
// var params = {
|
console.log('connected');
|
||||||
// host: 'towel.blinkenlights.nl',
|
|
||||||
// port: 23,
|
|
||||||
// shellPrompt: '/ # ',
|
|
||||||
// timeout: 1500,
|
|
||||||
// // removeEcho: 4
|
|
||||||
// };
|
|
||||||
|
|
||||||
var params = {
|
|
||||||
// host: '10.0.1.207',
|
|
||||||
port: 23,
|
|
||||||
timeout: 15000,
|
|
||||||
passwordPrompt: /Password[: ]*$/i
|
|
||||||
// removeEcho: 4
|
|
||||||
};
|
|
||||||
|
|
||||||
connection.on('ready', function(prompt) {
|
|
||||||
connection.exec('ls', function(err, response) {
|
|
||||||
console.log(response);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
connection.on('writedone', function() {
|
a.on('error', function(err) {
|
||||||
console.log('writedone');
|
console.log(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
connection.on('loginfailed', function() {
|
var b = net.createConnection({ port: randomPort() }, function(err) {
|
||||||
console.log('loginfailed');
|
if (err) throw err
|
||||||
|
|
||||||
|
console.log('connected');
|
||||||
});
|
});
|
||||||
|
|
||||||
connection.on('error', function(error) {
|
b.on('error', function(err) {
|
||||||
console.log(error);
|
console.log(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
connection.on('timeout', function() {
|
|
||||||
console.log('socket timeout!');
|
|
||||||
connection.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
connection.on('close', function() {
|
// a.on('message', function(data, rinfo) {
|
||||||
console.log('connection closed');
|
// var str = String.fromCharCode.apply(null, new Uint8Array(data));
|
||||||
});
|
// console.log('a received', str, rinfo)
|
||||||
|
// a.close()
|
||||||
connection.connect(params);
|
// b.close()
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
// b.on('message', function(data, rinfo) {
|
||||||
|
// var str = String.fromCharCode.apply(null, new Uint8Array(data));
|
||||||
|
// console.log('b received', str, rinfo)
|
||||||
|
//
|
||||||
|
// // echo back
|
||||||
|
// b.send(data, 0, data.length, aPort, '127.0.0.1', function(err) {
|
||||||
|
// if (err) throw err
|
||||||
|
//
|
||||||
|
// console.log('sent')
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
// b.once('listening', function() {
|
||||||
|
// var msg = toByteArray('hello')
|
||||||
|
// a.send(msg, 0, msg.length, bPort, '127.0.0.1', function(err) {
|
||||||
|
// if (err) throw err
|
||||||
|
//
|
||||||
|
// console.log('sent')
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
|
||||||
var rctsockets = React.createClass({
|
var rctsockets = React.createClass({
|
||||||
render: function() {
|
render: function() {
|
||||||
|
|
|
@ -2157,7 +2157,7 @@ enum GCDAsyncSocketConfig
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)connectToHost:(NSString*)host onPort:(uint16_t)port error:(NSError **)errPtr
|
- (BOOL)connectToHost:(NSString *)host onPort:(uint16_t)port error:(NSError **)errPtr
|
||||||
{
|
{
|
||||||
return [self connectToHost:host onPort:port withTimeout:-1 error:errPtr];
|
return [self connectToHost:host onPort:port withTimeout:-1 error:errPtr];
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,14 +29,17 @@ typedef enum RCTTCPError RCTTCPError;
|
||||||
|
|
||||||
@protocol SocketClientDelegate <NSObject>
|
@protocol SocketClientDelegate <NSObject>
|
||||||
|
|
||||||
|
- (void)onConnect:(TcpSocketClient*) client;
|
||||||
- (void)onData:(TcpSocketClient*) client data:(NSData *)data;
|
- (void)onData:(TcpSocketClient*) client data:(NSData *)data;
|
||||||
|
- (void)onClose:(TcpSocketClient*) client withError:(NSError *)err;
|
||||||
|
- (void)onError:(TcpSocketClient*) client withError:(NSError *)err;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface TcpSocketClient : NSObject
|
@interface TcpSocketClient : NSObject
|
||||||
|
|
||||||
@property (nonatomic, retain) NSString* id;
|
@property (nonatomic, retain) NSString * id;
|
||||||
@property (nonatomic, retain) NSString* host;
|
@property (nonatomic, retain) NSString * host;
|
||||||
@property (nonatomic) u_int16_t port;
|
@property (nonatomic) u_int16_t port;
|
||||||
|
|
||||||
///---------------------------------------------------------------------------------------
|
///---------------------------------------------------------------------------------------
|
||||||
|
@ -62,7 +65,7 @@ typedef enum RCTTCPError RCTTCPError;
|
||||||
* @param host ip address
|
* @param host ip address
|
||||||
* @return true if bound, false if there was an error
|
* @return true if bound, false if there was an error
|
||||||
*/
|
*/
|
||||||
- (BOOL)connect:(u_int16_t) port host:(NSString*) host error:(NSError**)error;
|
- (BOOL)connect:(NSString *)host port:(int)port withOptions:(NSDictionary *)options error:(NSError **)error;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* write data
|
* write data
|
||||||
|
@ -71,9 +74,14 @@ typedef enum RCTTCPError RCTTCPError;
|
||||||
- (void)writeData:(NSData*) data callback:(RCTResponseSenderBlock) callback;
|
- (void)writeData:(NSData*) data callback:(RCTResponseSenderBlock) callback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* close client
|
* end client
|
||||||
*/
|
*/
|
||||||
- (void)close;
|
- (void)end;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* destroy client
|
||||||
|
*/
|
||||||
|
- (void)destroy;
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -17,12 +17,10 @@ NSString *const RCTTCPErrorDomain = @"RCTTCPErrorDomain";
|
||||||
@interface TcpSocketClient()
|
@interface TcpSocketClient()
|
||||||
{
|
{
|
||||||
@private
|
@private
|
||||||
uint16_t _port;
|
|
||||||
NSString* _address;
|
|
||||||
GCDAsyncSocket *_tcpSocket;
|
GCDAsyncSocket *_tcpSocket;
|
||||||
id<SocketClientDelegate> _clientDelegate;
|
id<SocketClientDelegate> _clientDelegate;
|
||||||
NSMutableDictionary* _pendingSends;
|
NSMutableDictionary* _pendingSends;
|
||||||
long tag;
|
long _sendTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initWithConfig:(id<SocketClientDelegate>) aDelegate;
|
- (id)initWithConfig:(id<SocketClientDelegate>) aDelegate;
|
||||||
|
@ -47,10 +45,9 @@ NSString *const RCTTCPErrorDomain = @"RCTTCPErrorDomain";
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) connect:(u_int16_t)port host:(NSString *)host error:(NSError **) error
|
- (BOOL)connect:(NSString *)host port:(int)port withOptions:(NSDictionary *)options error:(NSError **)error
|
||||||
{
|
{
|
||||||
|
if (_tcpSocket) {
|
||||||
if (_port) {
|
|
||||||
if (error) {
|
if (error) {
|
||||||
*error = [self badInvocationError:@"this client's socket is already connected"];
|
*error = [self badInvocationError:@"this client's socket is already connected"];
|
||||||
}
|
}
|
||||||
|
@ -58,13 +55,25 @@ NSString *const RCTTCPErrorDomain = @"RCTTCPErrorDomain";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_port = port;
|
|
||||||
_address = host;
|
|
||||||
|
|
||||||
_tcpSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:[self methodQueue]];
|
_tcpSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:[self methodQueue]];
|
||||||
BOOL result;
|
BOOL result = false;
|
||||||
if (_address) {
|
|
||||||
result = [_tcpSocket connectToHost:_address onPort:_port error:error];
|
NSString *localAddress = (options?options[@"localAddress"]:nil);
|
||||||
|
NSNumber *localPort = (options?options[@"localPort"]:nil);
|
||||||
|
|
||||||
|
if (!localAddress && !localPort) {
|
||||||
|
result = [_tcpSocket connectToHost:host onPort:port error:error];
|
||||||
|
} else {
|
||||||
|
NSMutableArray *interface = [NSMutableArray arrayWithCapacity:2];
|
||||||
|
[interface addObject: localAddress?localAddress:@""];
|
||||||
|
if (localPort) {
|
||||||
|
[interface addObject:[localPort stringValue]];
|
||||||
|
}
|
||||||
|
result = [_tcpSocket connectToHost:host
|
||||||
|
onPort:port
|
||||||
|
viaInterface:[interface componentsJoinedByString:@":"]
|
||||||
|
withTimeout:-1
|
||||||
|
error:error];
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -83,23 +92,30 @@ NSString *const RCTTCPErrorDomain = @"RCTTCPErrorDomain";
|
||||||
- (void) writeData:(NSData *)data
|
- (void) writeData:(NSData *)data
|
||||||
callback:(RCTResponseSenderBlock)callback
|
callback:(RCTResponseSenderBlock)callback
|
||||||
{
|
{
|
||||||
[_tcpSocket writeData:data withTimeout:-1 tag:tag];
|
[_tcpSocket writeData:data withTimeout:-1 tag:_sendTag];
|
||||||
if (callback) {
|
if (callback) {
|
||||||
[_pendingSends setObject:callback forKey:[NSNumber numberWithLong:tag]];
|
[_pendingSends setObject:callback forKey:[NSNumber numberWithLong:_sendTag]];
|
||||||
}
|
}
|
||||||
|
|
||||||
tag++;
|
_sendTag++;
|
||||||
|
|
||||||
[_tcpSocket readDataWithTimeout:-1 tag:-1];
|
[_tcpSocket readDataWithTimeout:-1 tag:-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) close
|
- (void)end
|
||||||
{
|
{
|
||||||
[_tcpSocket disconnectAfterReadingAndWriting];
|
[_tcpSocket disconnectAfterReadingAndWriting];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)destroy
|
||||||
|
{
|
||||||
|
[_tcpSocket disconnect];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
|
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
|
||||||
if (!_clientDelegate) return;
|
if (!_clientDelegate) return;
|
||||||
[_clientDelegate onData:self data:data];
|
[_clientDelegate onData:self data:data];
|
||||||
|
|
||||||
[sock readDataWithTimeout:-1 tag:-1];
|
[sock readDataWithTimeout:-1 tag:-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,6 +124,16 @@ NSString *const RCTTCPErrorDomain = @"RCTTCPErrorDomain";
|
||||||
[sock readDataWithTimeout:-1 tag:-1];
|
[sock readDataWithTimeout:-1 tag:-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)socketDidCloseReadStream:(GCDAsyncSocket *)sock
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
|
||||||
|
{
|
||||||
|
if (!_clientDelegate) return;
|
||||||
|
[_clientDelegate onClose:self withError:err];
|
||||||
|
}
|
||||||
|
|
||||||
- (NSError *)badParamError:(NSString *)errMsg
|
- (NSError *)badParamError:(NSString *)errMsg
|
||||||
{
|
{
|
||||||
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
|
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
|
||||||
|
|
|
@ -40,7 +40,7 @@ RCT_EXPORT_MODULE()
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(createSocket:(nonnull NSNumber*)cId withOptions:(NSDictionary*)options)
|
RCT_EXPORT_METHOD(createSocket:(nonnull NSNumber*)cId)
|
||||||
{
|
{
|
||||||
NSMutableDictionary* _clients = [TcpSockets clients];
|
NSMutableDictionary* _clients = [TcpSockets clients];
|
||||||
if (!cId) {
|
if (!cId) {
|
||||||
|
@ -59,26 +59,23 @@ RCT_EXPORT_METHOD(createSocket:(nonnull NSNumber*)cId withOptions:(NSDictionary*
|
||||||
}
|
}
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(connect:(nonnull NSNumber*)cId
|
RCT_EXPORT_METHOD(connect:(nonnull NSNumber*)cId
|
||||||
port:(int)port
|
|
||||||
host:(NSString *)host
|
host:(NSString *)host
|
||||||
callback:(RCTResponseSenderBlock)callback)
|
port:(int)port
|
||||||
|
withOptions:(NSDictionary *)options)
|
||||||
{
|
{
|
||||||
TcpSocketClient* client = [TcpSockets findClient:cId callback:callback];
|
TcpSocketClient* client = [TcpSockets findClient:cId callback:nil];
|
||||||
if (!client) return;
|
if (!client) return;
|
||||||
|
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
if (![client connect:port host:host error:&error])
|
if (![client connect:host port:port withOptions:options error:&error])
|
||||||
{
|
{
|
||||||
NSString* msg = [[error userInfo] valueForKey:@"NSLocalizedFailureReason"];
|
[self onError:client withError:error];
|
||||||
callback(@[msg]);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(@[[NSNull null], [NSNull null]]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(write:(nonnull NSNumber*)cId
|
RCT_EXPORT_METHOD(write:(nonnull NSNumber*)cId
|
||||||
string:(NSString*)string
|
string:(NSString *)string
|
||||||
encoded:(BOOL)encoded
|
encoded:(BOOL)encoded
|
||||||
callback:(RCTResponseSenderBlock)callback) {
|
callback:(RCTResponseSenderBlock)callback) {
|
||||||
TcpSocketClient* client = [TcpSockets findClient:cId callback:callback];
|
TcpSocketClient* client = [TcpSockets findClient:cId callback:callback];
|
||||||
|
@ -96,9 +93,21 @@ RCT_EXPORT_METHOD(write:(nonnull NSNumber*)cId
|
||||||
[client writeData:data callback:callback];
|
[client writeData:data callback:callback];
|
||||||
}
|
}
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(close:(nonnull NSNumber*)cId
|
RCT_EXPORT_METHOD(end:(nonnull NSNumber*)cId
|
||||||
callback:(RCTResponseSenderBlock)callback) {
|
callback:(RCTResponseSenderBlock)callback) {
|
||||||
[TcpSockets closeClient:cId callback:callback];
|
[TcpSockets endClient:cId callback:callback];
|
||||||
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_METHOD(destroy:(nonnull NSNumber*)cId) {
|
||||||
|
[TcpSockets destroyClient:cId];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) onConnect:(TcpSocketClient*) client
|
||||||
|
{
|
||||||
|
NSMutableDictionary* _clients = [TcpSockets clients];
|
||||||
|
NSString *clientID = [[_clients allKeysForObject:client] objectAtIndex:0];
|
||||||
|
[self.bridge.eventDispatcher sendDeviceEventWithName:[NSString stringWithFormat:@"tcp-%@-event", clientID]
|
||||||
|
body:@{ @"event": @"connect" }];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) onData:(TcpSocketClient*) client data:(NSData *)data
|
- (void) onData:(TcpSocketClient*) client data:(NSData *)data
|
||||||
|
@ -106,8 +115,29 @@ RCT_EXPORT_METHOD(close:(nonnull NSNumber*)cId
|
||||||
NSMutableDictionary* _clients = [TcpSockets clients];
|
NSMutableDictionary* _clients = [TcpSockets clients];
|
||||||
NSString *clientID = [[_clients allKeysForObject:client] objectAtIndex:0];
|
NSString *clientID = [[_clients allKeysForObject:client] objectAtIndex:0];
|
||||||
NSString *base64String = [data base64EncodedStringWithOptions:0];
|
NSString *base64String = [data base64EncodedStringWithOptions:0];
|
||||||
[self.bridge.eventDispatcher sendDeviceEventWithName:[NSString stringWithFormat:@"tcp-%@-data", clientID]
|
[self.bridge.eventDispatcher sendDeviceEventWithName:[NSString stringWithFormat:@"tcp-%@-event", clientID]
|
||||||
body:@{ @"data": base64String }];
|
body:@{ @"event": @"data", @"data": base64String }];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) onClose:(TcpSocketClient*) client withError:(NSError *)err
|
||||||
|
{
|
||||||
|
[self onError:client withError:err];
|
||||||
|
|
||||||
|
NSMutableDictionary* _clients = [TcpSockets clients];
|
||||||
|
NSString *clientID = [[_clients allKeysForObject:client] objectAtIndex:0];
|
||||||
|
|
||||||
|
[self.bridge.eventDispatcher sendDeviceEventWithName:[NSString stringWithFormat:@"tcp-%@-event", clientID]
|
||||||
|
body:@{ @"event": @"close", @"data": err == nil ? @NO : @YES }];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onError:(TcpSocketClient*) client withError:(NSError *)err {
|
||||||
|
NSMutableDictionary* _clients = [TcpSockets clients];
|
||||||
|
NSString *clientID = [[_clients allKeysForObject:client] objectAtIndex:0];
|
||||||
|
|
||||||
|
NSString* msg = [[err userInfo] valueForKey:@"NSLocalizedFailureReason"];
|
||||||
|
[self.bridge.eventDispatcher sendDeviceEventWithName:[NSString stringWithFormat:@"tcp-%@-event", clientID]
|
||||||
|
body:@{ @"event": @"error", @"data": @[msg] }];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+(TcpSocketClient*)findClient:(nonnull NSNumber*)cId callback:(RCTResponseSenderBlock)callback
|
+(TcpSocketClient*)findClient:(nonnull NSNumber*)cId callback:(RCTResponseSenderBlock)callback
|
||||||
|
@ -128,23 +158,33 @@ RCT_EXPORT_METHOD(close:(nonnull NSNumber*)cId
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
+(void) closeClient:(nonnull NSNumber*)cId
|
+(void) endClient:(nonnull NSNumber*)cId
|
||||||
callback:(RCTResponseSenderBlock)callback
|
callback:(RCTResponseSenderBlock)callback
|
||||||
{
|
{
|
||||||
NSMutableDictionary* _clients = [TcpSockets clients];
|
NSMutableDictionary* _clients = [TcpSockets clients];
|
||||||
TcpSocketClient* client = [TcpSockets findClient:cId callback:callback];
|
TcpSocketClient* client = [TcpSockets findClient:cId callback:callback];
|
||||||
if (!client) return;
|
if (!client) return;
|
||||||
|
|
||||||
[client close];
|
[client end];
|
||||||
[_clients removeObjectForKey:cId];
|
[_clients removeObjectForKey:cId];
|
||||||
|
|
||||||
if (callback) callback(@[]);
|
if (callback) callback(@[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+(void) destroyClient:(nonnull NSNumber*)cId
|
||||||
|
{
|
||||||
|
NSMutableDictionary* _clients = [TcpSockets clients];
|
||||||
|
TcpSocketClient* client = [TcpSockets findClient:cId callback:nil];
|
||||||
|
if (!client) return;
|
||||||
|
|
||||||
|
[client destroy];
|
||||||
|
[_clients removeObjectForKey:cId];
|
||||||
|
}
|
||||||
|
|
||||||
+(void) closeAllSockets {
|
+(void) closeAllSockets {
|
||||||
NSMutableDictionary* _clients = [TcpSockets clients];
|
NSMutableDictionary* _clients = [TcpSockets clients];
|
||||||
for (NSNumber* cId in _clients) {
|
for (NSNumber* cId in _clients) {
|
||||||
[TcpSockets closeClient:cId callback:nil];
|
[TcpSockets endClient:cId callback:nil];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
13BE3DEE1AC21097009241FE /* TcpSockets.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* TcpSockets.m */; };
|
13BE3DEE1AC21097009241FE /* TcpSockets.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* TcpSockets.m */; };
|
||||||
7350006B1AFF9AB600ED3C82 /* TcpSocketClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 7350006A1AFF9AB600ED3C82 /* TcpSocketClient.m */; };
|
7350006B1AFF9AB600ED3C82 /* TcpSocketClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 7350006A1AFF9AB600ED3C82 /* TcpSocketClient.m */; };
|
||||||
73D9377D1AFF9EBE00450142 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73D9377C1AFF9EBE00450142 /* CFNetwork.framework */; };
|
73D9377D1AFF9EBE00450142 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73D9377C1AFF9EBE00450142 /* CFNetwork.framework */; };
|
||||||
73D9377F1AFF9F6E00450142 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73D9377E1AFF9F6E00450142 /* UIKit.framework */; };
|
|
||||||
96EDB0AC1C10C33B00D41E94 /* GCDAsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 96EDB0AB1C10C33B00D41E94 /* GCDAsyncSocket.m */; };
|
96EDB0AC1C10C33B00D41E94 /* GCDAsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 96EDB0AB1C10C33B00D41E94 /* GCDAsyncSocket.m */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
@ -33,7 +32,6 @@
|
||||||
735000691AFF9AB600ED3C82 /* TcpSocketClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TcpSocketClient.h; sourceTree = "<group>"; };
|
735000691AFF9AB600ED3C82 /* TcpSocketClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TcpSocketClient.h; sourceTree = "<group>"; };
|
||||||
7350006A1AFF9AB600ED3C82 /* TcpSocketClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TcpSocketClient.m; sourceTree = "<group>"; };
|
7350006A1AFF9AB600ED3C82 /* TcpSocketClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TcpSocketClient.m; sourceTree = "<group>"; };
|
||||||
73D9377C1AFF9EBE00450142 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
|
73D9377C1AFF9EBE00450142 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
|
||||||
73D9377E1AFF9F6E00450142 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
|
||||||
96EDB0AA1C10C33B00D41E94 /* GCDAsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDAsyncSocket.h; sourceTree = "<group>"; };
|
96EDB0AA1C10C33B00D41E94 /* GCDAsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCDAsyncSocket.h; sourceTree = "<group>"; };
|
||||||
96EDB0AB1C10C33B00D41E94 /* GCDAsyncSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDAsyncSocket.m; sourceTree = "<group>"; };
|
96EDB0AB1C10C33B00D41E94 /* GCDAsyncSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GCDAsyncSocket.m; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
@ -43,7 +41,6 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
73D9377F1AFF9F6E00450142 /* UIKit.framework in Frameworks */,
|
|
||||||
73D9377D1AFF9EBE00450142 /* CFNetwork.framework in Frameworks */,
|
73D9377D1AFF9EBE00450142 /* CFNetwork.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
@ -62,7 +59,6 @@
|
||||||
58B511D21A9E6C8500147676 = {
|
58B511D21A9E6C8500147676 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
73D9377E1AFF9F6E00450142 /* UIKit.framework */,
|
|
||||||
73D9377C1AFF9EBE00450142 /* CFNetwork.framework */,
|
73D9377C1AFF9EBE00450142 /* CFNetwork.framework */,
|
||||||
735000691AFF9AB600ED3C82 /* TcpSocketClient.h */,
|
735000691AFF9AB600ED3C82 /* TcpSocketClient.h */,
|
||||||
7350006A1AFF9AB600ED3C82 /* TcpSocketClient.m */,
|
7350006A1AFF9AB600ED3C82 /* TcpSocketClient.m */,
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
"base64-js": "0.0.8",
|
"base64-js": "0.0.8",
|
||||||
"events": "^1.0.2",
|
"events": "^1.0.2",
|
||||||
"inherits": "^2.0.1",
|
"inherits": "^2.0.1",
|
||||||
|
"ip-regex": "^1.0.3",
|
||||||
"util": "^0.10.3"
|
"util": "^0.10.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue