set version to 0.0.1
end now closes the socket after writes are done
This commit is contained in:
parent
87e2093be5
commit
3eb82c2fde
27
TcpSocket.js
27
TcpSocket.js
|
@ -21,6 +21,7 @@ var {
|
|||
} = require('react-native');
|
||||
var Sockets = NativeModules.TcpSockets;
|
||||
var base64 = require('base64-js');
|
||||
var Base64Str = require('./base64-str');
|
||||
var noop = function () {};
|
||||
var instances = 0;
|
||||
var STATE = {
|
||||
|
@ -124,6 +125,8 @@ function isLegalPort(port) {
|
|||
}
|
||||
|
||||
TcpSocket.prototype.setTimeout = function(msecs, callback) {
|
||||
var self = this;
|
||||
|
||||
if (this._timeout) {
|
||||
clearTimeout(this._timeout);
|
||||
this._timeout = null;
|
||||
|
@ -137,7 +140,8 @@ TcpSocket.prototype.setTimeout = function(msecs, callback) {
|
|||
var self = this;
|
||||
this._timeout = setTimeout(msecs, function() {
|
||||
self.emit('timeout');
|
||||
this._timeout = null;
|
||||
self._timeout = null;
|
||||
self.destroy();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -191,11 +195,13 @@ TcpSocket.prototype.end = function(data, encoding) {
|
|||
};
|
||||
|
||||
TcpSocket.prototype.destroy = function() {
|
||||
this._destroyed = true;
|
||||
this._debug('destroying');
|
||||
this._subscription.remove();
|
||||
if (!this._destroyed) {
|
||||
this._destroyed = true;
|
||||
this._debug('destroying');
|
||||
this._subscription.remove();
|
||||
|
||||
Sockets.destroy(this._id);
|
||||
Sockets.destroy(this._id, this._debug.bind(this, 'closed'));
|
||||
}
|
||||
};
|
||||
|
||||
TcpSocket.prototype._onEvent = function(info) {
|
||||
|
@ -239,8 +245,8 @@ TcpSocket.prototype.write = function(buffer, encoding, callback) {
|
|||
callback = callback || noop;
|
||||
var str;
|
||||
if (typeof buffer === 'string') {
|
||||
console.warn('socket.WRITE(): interpreting as UTF8');
|
||||
str = buffer;
|
||||
console.warn('socket.WRITE(): encoding as base64');
|
||||
str = Base64Str.encode(buffer);
|
||||
} else if (typeof Buffer !== 'undefined' && global.Buffer.isBuffer(buffer)) {
|
||||
encoded = true;
|
||||
str = buffer.toString('base64');
|
||||
|
@ -252,9 +258,14 @@ TcpSocket.prototype.write = function(buffer, encoding, callback) {
|
|||
}
|
||||
|
||||
Sockets.write(this._id, str, encoded, function(err) {
|
||||
if (self._timeout) {
|
||||
clearTimeout(self._timeout);
|
||||
self._timeout = null;
|
||||
}
|
||||
|
||||
err = normalizeError(err);
|
||||
if (err) {
|
||||
self._debug('send failed', err);
|
||||
self._debug('write failed', err);
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
/**
|
||||
* Source: https://gist.github.com/ncerminara/11257943
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
(function () {
|
||||
var Base64Str = {
|
||||
_keyStr: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
|
||||
encode: function(e: string) {
|
||||
var t = '';
|
||||
var n, r, i, s, o, u, a;
|
||||
var f = 0;
|
||||
e = Base64Str._utf8_encode(e);
|
||||
while (f < e.length) {
|
||||
n = e.charCodeAt(f++);
|
||||
r = e.charCodeAt(f++);
|
||||
i = e.charCodeAt(f++);
|
||||
s = n >> 2;
|
||||
o = (n & 3) << 4 | r >> 4;
|
||||
u = (r & 15) << 2 | i >> 6;
|
||||
a = i & 63;
|
||||
if (isNaN(r)) {
|
||||
u = a = 64;
|
||||
} else if (isNaN(i)) {
|
||||
a = 64;
|
||||
}
|
||||
t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr
|
||||
.charAt(u) + this._keyStr.charAt(a);
|
||||
}
|
||||
return t;
|
||||
},
|
||||
decode: function(e: string) {
|
||||
var t = '';
|
||||
var n, r, i;
|
||||
var s, o, u, a;
|
||||
var f = 0;
|
||||
e = e.replace(/[^A-Za-z0-9\+\/\=]/g, '');
|
||||
while (f < e.length) {
|
||||
s = this._keyStr.indexOf(e.charAt(f++));
|
||||
o = this._keyStr.indexOf(e.charAt(f++));
|
||||
u = this._keyStr.indexOf(e.charAt(f++));
|
||||
a = this._keyStr.indexOf(e.charAt(f++));
|
||||
n = s << 2 | o >> 4;
|
||||
r = (o & 15) << 4 | u >> 2;
|
||||
i = (u & 3) << 6 | a;
|
||||
t = t + String.fromCharCode(n);
|
||||
if (u !== 64) {
|
||||
t = t + String.fromCharCode(r);
|
||||
}
|
||||
if (a !== 64) {
|
||||
t = t + String.fromCharCode(i);
|
||||
}
|
||||
}
|
||||
t = Base64Str._utf8_decode(t);
|
||||
return t;
|
||||
},
|
||||
_utf8_encode: function(e) {
|
||||
e = e.replace(/\r\n/g, '\n');
|
||||
var t = '';
|
||||
for (var n = 0; n < e.length; n++) {
|
||||
var r = e.charCodeAt(n);
|
||||
if (r < 128) {
|
||||
t += String.fromCharCode(r);
|
||||
} else if (r > 127 && r < 2048) {
|
||||
t += String.fromCharCode(r >> 6 | 192);
|
||||
t += String.fromCharCode(r & 63 | 128);
|
||||
} else {
|
||||
t += String.fromCharCode(r >> 12 | 224);
|
||||
t += String.fromCharCode(r >> 6 & 63 | 128);
|
||||
t += String.fromCharCode(r & 63 | 128);
|
||||
}
|
||||
}
|
||||
return t;
|
||||
},
|
||||
_utf8_decode: function(e) {
|
||||
var t = '';
|
||||
var n = 0;
|
||||
var r = 0, /*c1 = 0, */c2 = 0;
|
||||
while (n < e.length) {
|
||||
r = e.charCodeAt(n);
|
||||
if (r < 128) {
|
||||
t += String.fromCharCode(r);
|
||||
n++;
|
||||
} else if (r > 191 && r < 224) {
|
||||
c2 = e.charCodeAt(n + 1);
|
||||
t += String.fromCharCode((r & 31) << 6 | c2 & 63);
|
||||
n += 2;
|
||||
} else {
|
||||
c2 = e.charCodeAt(n + 1);
|
||||
var c3 = e.charCodeAt(n + 2);
|
||||
t += String.fromCharCode((r & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
|
||||
n += 3;
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = Base64Str;
|
||||
}());
|
|
@ -38,9 +38,7 @@ typedef enum RCTTCPError RCTTCPError;
|
|||
|
||||
@interface TcpSocketClient : NSObject
|
||||
|
||||
@property (nonatomic, retain) NSString * id;
|
||||
@property (nonatomic, retain) NSString * host;
|
||||
@property (nonatomic) u_int16_t port;
|
||||
@property (nonatomic, retain) NSNumber * id;
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Class Methods
|
||||
|
@ -53,7 +51,7 @@ typedef enum RCTTCPError RCTTCPError;
|
|||
* @return New RCTTCPClient
|
||||
*/
|
||||
|
||||
+ (id)socketClientWithConfig:(id<SocketClientDelegate>) delegate;
|
||||
+ (id)socketClientWithId:(NSNumber *)clientID andConfig:(id<SocketClientDelegate>) delegate;
|
||||
|
||||
///---------------------------------------------------------------------------------------
|
||||
/// @name Instance Methods
|
||||
|
|
|
@ -23,21 +23,22 @@ NSString *const RCTTCPErrorDomain = @"RCTTCPErrorDomain";
|
|||
long _sendTag;
|
||||
}
|
||||
|
||||
- (id)initWithConfig:(id<SocketClientDelegate>) aDelegate;
|
||||
- (id)initWithClientId:(NSNumber *)clientID andConfig:(id<SocketClientDelegate>) aDelegate;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TcpSocketClient
|
||||
|
||||
+ (id)socketClientWithConfig:(id<SocketClientDelegate>)delegate
|
||||
+ (id)socketClientWithId:(nonnull NSNumber *)clientID andConfig:(id<SocketClientDelegate>)delegate
|
||||
{
|
||||
return [[[self class] alloc] initWithConfig:delegate];
|
||||
return [[[self class] alloc] initWithClientId:clientID andConfig:delegate];
|
||||
}
|
||||
|
||||
- (id)initWithConfig:(id<SocketClientDelegate>) aDelegate
|
||||
- (id)initWithClientId:(NSNumber *)clientID andConfig:(id<SocketClientDelegate>) aDelegate
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_id = clientID;
|
||||
_clientDelegate = aDelegate;
|
||||
_pendingSends = [NSMutableDictionary dictionary];
|
||||
}
|
||||
|
@ -104,7 +105,7 @@ NSString *const RCTTCPErrorDomain = @"RCTTCPErrorDomain";
|
|||
|
||||
- (void)end
|
||||
{
|
||||
[_tcpSocket disconnectAfterReadingAndWriting];
|
||||
[_tcpSocket disconnectAfterWriting];
|
||||
}
|
||||
|
||||
- (void)destroy
|
||||
|
@ -121,6 +122,9 @@ NSString *const RCTTCPErrorDomain = @"RCTTCPErrorDomain";
|
|||
|
||||
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
|
||||
{
|
||||
if (!_clientDelegate) return;
|
||||
[_clientDelegate onConnect:self];
|
||||
|
||||
[sock readDataWithTimeout:-1 tag:-1];
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ RCT_EXPORT_METHOD(createSocket:(nonnull NSNumber*)cId)
|
|||
return;
|
||||
}
|
||||
|
||||
client = [TcpSocketClient socketClientWithConfig:self];
|
||||
client = [TcpSocketClient socketClientWithId:cId andConfig:self];
|
||||
[_clients setObject:client forKey:cId];
|
||||
}
|
||||
|
||||
|
@ -75,21 +75,15 @@ RCT_EXPORT_METHOD(connect:(nonnull NSNumber*)cId
|
|||
}
|
||||
|
||||
RCT_EXPORT_METHOD(write:(nonnull NSNumber*)cId
|
||||
string:(NSString *)string
|
||||
string:(NSString *)base64String
|
||||
encoded:(BOOL)encoded
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
TcpSocketClient* client = [TcpSockets findClient:cId callback:callback];
|
||||
if (!client) return;
|
||||
|
||||
NSData *data;
|
||||
if (encoded) {
|
||||
// iOS7+
|
||||
// TODO: use https://github.com/nicklockwood/Base64 for compatibility with earlier iOS versions
|
||||
data = [[NSData alloc] initWithBase64EncodedString:string options:0];
|
||||
} else {
|
||||
data = [string dataUsingEncoding:[NSString defaultCStringEncoding]];
|
||||
}
|
||||
|
||||
// iOS7+
|
||||
// TODO: use https://github.com/nicklockwood/Base64 for compatibility with earlier iOS versions
|
||||
NSData *data = [[NSData alloc] initWithBase64EncodedString:base64String options:0];
|
||||
[client writeData:data callback:callback];
|
||||
}
|
||||
|
||||
|
@ -98,15 +92,14 @@ RCT_EXPORT_METHOD(end:(nonnull NSNumber*)cId
|
|||
[TcpSockets endClient:cId callback:callback];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(destroy:(nonnull NSNumber*)cId) {
|
||||
[TcpSockets destroyClient:cId];
|
||||
RCT_EXPORT_METHOD(destroy:(nonnull NSNumber*)cId
|
||||
callback:(RCTResponseSenderBlock)callback) {
|
||||
[TcpSockets destroyClient:cId callback:callback];
|
||||
}
|
||||
|
||||
- (void) onConnect:(TcpSocketClient*) client
|
||||
{
|
||||
NSMutableDictionary<NSNumber *,TcpSocketClient *> *_clients = [TcpSockets clients];
|
||||
NSNumber *clientID = [[_clients allKeysForObject:client] objectAtIndex:0];
|
||||
[self.bridge.eventDispatcher sendDeviceEventWithName:[NSString stringWithFormat:@"tcp-%@-event", clientID]
|
||||
[self.bridge.eventDispatcher sendDeviceEventWithName:[NSString stringWithFormat:@"tcp-%@-event", client.id]
|
||||
body:@{ @"event": @"connect" }];
|
||||
}
|
||||
|
||||
|
@ -121,21 +114,20 @@ RCT_EXPORT_METHOD(destroy:(nonnull NSNumber*)cId) {
|
|||
|
||||
- (void) onClose:(TcpSocketClient*) client withError:(NSError *)err
|
||||
{
|
||||
[self onError:client withError:err];
|
||||
if (err) {
|
||||
[self onError:client withError:err];
|
||||
}
|
||||
|
||||
[self.bridge.eventDispatcher sendDeviceEventWithName:[NSString stringWithFormat:@"tcp-%@-event", client.id]
|
||||
body:@{ @"event": @"close", @"data": err == nil ? @NO : @YES }];
|
||||
|
||||
NSMutableDictionary<NSNumber *,TcpSocketClient *> *_clients = [TcpSockets clients];
|
||||
NSNumber *clientID = [[_clients allKeysForObject:client] objectAtIndex:0];
|
||||
|
||||
[self.bridge.eventDispatcher sendDeviceEventWithName:[NSString stringWithFormat:@"tcp-%@-event", clientID]
|
||||
body:@{ @"event": @"close", @"data": err == nil ? @NO : @YES }];
|
||||
[_clients removeObjectForKey:client.id];
|
||||
}
|
||||
|
||||
- (void)onError:(TcpSocketClient*) client withError:(NSError *)err {
|
||||
NSMutableDictionary<NSNumber *,TcpSocketClient *> *_clients = [TcpSockets clients];
|
||||
NSNumber *clientID = [[_clients allKeysForObject:client] objectAtIndex:0];
|
||||
|
||||
NSString* msg = [[err userInfo] valueForKey:@"NSLocalizedFailureReason"];
|
||||
[self.bridge.eventDispatcher sendDeviceEventWithName:[NSString stringWithFormat:@"tcp-%@-event", clientID]
|
||||
[self.bridge.eventDispatcher sendDeviceEventWithName:[NSString stringWithFormat:@"tcp-%@-event", client.id]
|
||||
body:@{ @"event": @"error", @"data": @[msg] }];
|
||||
|
||||
}
|
||||
|
@ -147,8 +139,7 @@ RCT_EXPORT_METHOD(destroy:(nonnull NSNumber*)cId) {
|
|||
if (!client) {
|
||||
if (!callback) {
|
||||
RCTLogError(@"%@.missing callback parameter.", [self class]);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
callback(@[[NSString stringWithFormat:@"no client found with id %@", cId]]);
|
||||
}
|
||||
|
||||
|
@ -161,17 +152,16 @@ RCT_EXPORT_METHOD(destroy:(nonnull NSNumber*)cId) {
|
|||
+(void) endClient:(nonnull NSNumber*)cId
|
||||
callback:(RCTResponseSenderBlock)callback
|
||||
{
|
||||
NSMutableDictionary<NSNumber *,TcpSocketClient *> *_clients = [TcpSockets clients];
|
||||
TcpSocketClient* client = [TcpSockets findClient:cId callback:callback];
|
||||
if (!client) return;
|
||||
|
||||
[client end];
|
||||
[_clients removeObjectForKey:cId];
|
||||
|
||||
if (callback) callback(@[]);
|
||||
}
|
||||
|
||||
+(void) destroyClient:(nonnull NSNumber*)cId
|
||||
callback:(RCTResponseSenderBlock)callback
|
||||
{
|
||||
NSMutableDictionary<NSNumber *,TcpSocketClient *> *_clients = [TcpSockets clients];
|
||||
TcpSocketClient* client = [TcpSockets findClient:cId callback:nil];
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
58B511D31A9E6C8500147676 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0610;
|
||||
LastUpgradeCheck = 0720;
|
||||
ORGANIZATIONNAME = "Tradle, Inc.";
|
||||
TargetAttributes = {
|
||||
58B511DA1A9E6C8500147676 = {
|
||||
|
@ -179,6 +179,7 @@
|
|||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "react-native-tcp",
|
||||
"version": "1.1.1",
|
||||
"version": "0.0.1",
|
||||
"description": "node's dgram API for react-native",
|
||||
"main": "TcpSockets.js",
|
||||
"scripts": {
|
||||
|
|
Loading…
Reference in New Issue