push socket creation into connect and listen methods
This commit is contained in:
parent
0d08f22a66
commit
bceff85694
21
TcpServer.js
21
TcpServer.js
|
@ -22,12 +22,14 @@ function TcpServer(connectionListener: (socket: Socket) => void) {
|
|||
return new TcpServer(connectionListener);
|
||||
}
|
||||
|
||||
// $FlowFixMe: suppressing this error flow doesn't like EventEmitter
|
||||
EventEmitter.call(this);
|
||||
if (EventEmitter instanceof Function) {
|
||||
EventEmitter.call(this);
|
||||
}
|
||||
|
||||
var self = this;
|
||||
|
||||
this._socket = new Socket();
|
||||
|
||||
// $FlowFixMe: suppressing this error flow doesn't like EventEmitter
|
||||
this._socket.on('connect', function() {
|
||||
self.emit('listening');
|
||||
|
@ -35,7 +37,6 @@ function TcpServer(connectionListener: (socket: Socket) => void) {
|
|||
// $FlowFixMe: suppressing this error flow doesn't like EventEmitter
|
||||
this._socket.on('connection', function(socket) {
|
||||
self._connections++;
|
||||
|
||||
self.emit('connection', socket);
|
||||
});
|
||||
// $FlowFixMe: suppressing this error flow doesn't like EventEmitter
|
||||
|
@ -45,7 +46,6 @@ function TcpServer(connectionListener: (socket: Socket) => void) {
|
|||
// $FlowFixMe: suppressing this error flow doesn't like EventEmitter
|
||||
this._socket.on('error', function(error) {
|
||||
self.emit('error', error);
|
||||
self._socket.destroy();
|
||||
});
|
||||
|
||||
if (typeof connectionListener === 'function') {
|
||||
|
@ -64,16 +64,21 @@ TcpServer.prototype._debug = function() {
|
|||
}
|
||||
};
|
||||
|
||||
TcpServer.prototype.listen = function(options: { port: number, hostname: ?string }, callback: ?() => void) : TcpServer {
|
||||
// TODO : determine how to properly overload this with flow
|
||||
TcpServer.prototype.listen = function() : TcpServer {
|
||||
var args = this._socket._normalizeConnectArgs(arguments);
|
||||
var options = args[0];
|
||||
var callback = args[1];
|
||||
|
||||
var port = options.port;
|
||||
var hostname = options.hostname || 'localhost';
|
||||
var host = options.host || 'localhost';
|
||||
|
||||
if (callback) {
|
||||
this.on('listening', callback);
|
||||
}
|
||||
|
||||
Sockets.createSocket(this._socket._id);
|
||||
Sockets.listen(this._socket._id, hostname, port);
|
||||
this._socket._registerEvents();
|
||||
Sockets.listen(this._socket._id, host, port);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
|
120
TcpSocket.js
120
TcpSocket.js
|
@ -19,7 +19,7 @@ var Sockets = NativeModules.TcpSockets;
|
|||
var base64 = require('base64-js');
|
||||
var Base64Str = require('./base64-str');
|
||||
var noop = function () {};
|
||||
var usedIds = [];
|
||||
var instances = 0;
|
||||
var STATE = {
|
||||
DISCONNECTED: 0,
|
||||
CONNECTING: 1,
|
||||
|
@ -27,37 +27,34 @@ var STATE = {
|
|||
};
|
||||
|
||||
function TcpSocket(options: ?{ id: ?number }) {
|
||||
// $FlowFixMe: suppressing this error flow doesn't like EventEmitter
|
||||
EventEmitter.call(this);
|
||||
if (!(this instanceof TcpSocket)) {
|
||||
return new TcpSocket(options);
|
||||
}
|
||||
|
||||
if (EventEmitter instanceof Function) {
|
||||
EventEmitter.call(this);
|
||||
}
|
||||
|
||||
if (options && options.id) {
|
||||
// native generated sockets range from 5000-6000
|
||||
// e.g. incoming server connections
|
||||
this._id = Number(options.id);
|
||||
|
||||
if (usedIds.indexOf(this._id) !== -1) {
|
||||
if (this._id <= instances) {
|
||||
throw new Error('Socket id ' + this._id + 'already in use');
|
||||
}
|
||||
} else {
|
||||
// javascript generated sockets range from 1-1000
|
||||
this._id = Math.floor((Math.random() * 1000) + 1);
|
||||
while (usedIds.indexOf(this._id) !== -1) {
|
||||
this._id = Math.floor((Math.random() * 1000) + 1);
|
||||
}
|
||||
this._id = instances++;
|
||||
}
|
||||
|
||||
usedIds.push(this._id);
|
||||
|
||||
// these will be set once there is a connection
|
||||
this.readable = this.writable = false;
|
||||
|
||||
this._registerEvents();
|
||||
|
||||
// ensure compatibility with node's EventEmitter
|
||||
if (!this.on) {
|
||||
this.on = this.addListener.bind(this);
|
||||
}
|
||||
|
||||
// these will be set once there is a connection
|
||||
this.writable = this.readable = false;
|
||||
|
||||
this._state = STATE.DISCONNECTED;
|
||||
}
|
||||
|
||||
|
@ -71,24 +68,21 @@ TcpSocket.prototype._debug = function() {
|
|||
}
|
||||
};
|
||||
|
||||
TcpSocket.prototype.connect = function(options: ?{ port: ?number | ?string, host: ?string, localAddress: ?string, localPort: ?number }, callback: ?() => void) {
|
||||
if (this._state !== STATE.DISCONNECTED) {
|
||||
throw new Error('Socket is already bound');
|
||||
// TODO : determine how to properly overload this with flow
|
||||
TcpSocket.prototype.connect = function(options, callback) : TcpSocket {
|
||||
this._registerEvents();
|
||||
|
||||
if (options === null || typeof options !== 'object') {
|
||||
// Old API:
|
||||
// connect(port, [host], [cb])
|
||||
var args = this._normalizeConnectArgs(arguments);
|
||||
return TcpSocket.prototype.connect.apply(this, args);
|
||||
}
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
this.once('connect', callback);
|
||||
}
|
||||
|
||||
if (!options) {
|
||||
options = {
|
||||
host: 'localhost',
|
||||
port: 0,
|
||||
localAddress: null,
|
||||
localPort: null
|
||||
};
|
||||
}
|
||||
|
||||
var host = options.host || 'localhost';
|
||||
var port = options.port || 0;
|
||||
var localAddress = options.localAddress;
|
||||
|
@ -107,7 +101,7 @@ TcpSocket.prototype.connect = function(options: ?{ port: ?number | ?string, host
|
|||
throw new TypeError('"port" option should be a number or string: ' + port);
|
||||
}
|
||||
|
||||
port = Number(port);
|
||||
port = +port;
|
||||
|
||||
if (!isLegalPort(port)) {
|
||||
throw new RangeError('"port" option should be >= 0 and < 65536: ' + port);
|
||||
|
@ -117,8 +111,10 @@ TcpSocket.prototype.connect = function(options: ?{ port: ?number | ?string, host
|
|||
this._state = STATE.CONNECTING;
|
||||
this._debug('connecting, host:', host, 'port:', port);
|
||||
|
||||
Sockets.createSocket(this._id);
|
||||
this._destroyed = false;
|
||||
Sockets.connect(this._id, host, Number(port), options);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
// Check that the port number is not NaN when coerced to a number,
|
||||
|
@ -181,6 +177,10 @@ TcpSocket.prototype.destroy = function() {
|
|||
};
|
||||
|
||||
TcpSocket.prototype._registerEvents = function(): void {
|
||||
if (this._subs && this._subs.length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._subs = [
|
||||
DeviceEventEmitter.addListener(
|
||||
'tcp-' + this._id + '-connect', this._onConnect.bind(this)
|
||||
|
@ -207,27 +207,20 @@ TcpSocket.prototype._unregisterEvents = function(): void {
|
|||
this._subs = [];
|
||||
};
|
||||
|
||||
TcpSocket.prototype._onConnect = function(address: { port: string, address: string, family: string }): void {
|
||||
TcpSocket.prototype._onConnect = function(address: { port: number, address: string, family: string }): void {
|
||||
this._debug('received', 'connect');
|
||||
|
||||
this.writable = this.readable = true;
|
||||
this._state = STATE.CONNECTED;
|
||||
this._address = address;
|
||||
this._address.port = Number(this._address.port);
|
||||
|
||||
setConnected(this, address);
|
||||
this.emit('connect');
|
||||
};
|
||||
|
||||
TcpSocket.prototype._onConnection = function(info: { id: number, address: { port: string, address: string, family: string } }): void {
|
||||
TcpSocket.prototype._onConnection = function(info: { id: number, address: { port: number, address: string, family: string } }): void {
|
||||
this._debug('received', 'connection');
|
||||
|
||||
var socket = new TcpSocket({ id: info.id });
|
||||
|
||||
socket.writable = this.readable = true;
|
||||
socket._state = STATE.CONNECTED;
|
||||
socket._address = info.address;
|
||||
socket._address.port = Number(socket._address.port);
|
||||
|
||||
socket._registerEvents();
|
||||
setConnected(socket, info.address);
|
||||
this.emit('connection', socket);
|
||||
};
|
||||
|
||||
|
@ -250,17 +243,14 @@ TcpSocket.prototype._onData = function(data: string): void {
|
|||
TcpSocket.prototype._onClose = function(hadError: boolean): void {
|
||||
this._debug('received', 'close');
|
||||
|
||||
this._unregisterEvents();
|
||||
|
||||
this._state = STATE.DISCONNECTED;
|
||||
|
||||
this.emit('close', hadError);
|
||||
setDisconnected(this, hadError);
|
||||
};
|
||||
|
||||
TcpSocket.prototype._onError = function(error: string): void {
|
||||
this._debug('received', 'error');
|
||||
|
||||
this.emit('error', normalizeError(error));
|
||||
this.destroy();
|
||||
};
|
||||
|
||||
TcpSocket.prototype.write = function(buffer: any, callback: ?(err: ?Error) => void) : boolean {
|
||||
|
@ -303,6 +293,22 @@ TcpSocket.prototype.write = function(buffer: any, callback: ?(err: ?Error) => vo
|
|||
return true;
|
||||
};
|
||||
|
||||
function setConnected(socket: TcpSocket, address: { port: number, address: string, family: string } ) {
|
||||
socket.writable = socket.readable = true;
|
||||
socket._state = STATE.CONNECTED;
|
||||
socket._address = address;
|
||||
}
|
||||
|
||||
function setDisconnected(socket: TcpSocket, hadError: boolean): void {
|
||||
if (socket._state === STATE.DISCONNECTED) {
|
||||
return;
|
||||
}
|
||||
|
||||
socket._unregisterEvents();
|
||||
socket._state = STATE.DISCONNECTED;
|
||||
socket.emit('close', hadError);
|
||||
}
|
||||
|
||||
function normalizeError(err) {
|
||||
if (err) {
|
||||
if (typeof err === 'string') {
|
||||
|
@ -313,4 +319,24 @@ function normalizeError(err) {
|
|||
}
|
||||
}
|
||||
|
||||
// Returns an array [options] or [options, cb]
|
||||
// It is the same as the argument of Socket.prototype.connect().
|
||||
TcpSocket.prototype._normalizeConnectArgs = function(args) {
|
||||
var options = {};
|
||||
|
||||
if (args[0] !== null && typeof args[0] === 'object') {
|
||||
// connect(options, [cb])
|
||||
options = 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];
|
||||
};
|
||||
|
||||
module.exports = TcpSocket;
|
||||
|
|
|
@ -17,10 +17,10 @@ exports.createServer = function(connectionListener: (socket: Socket) => void) :
|
|||
return new Server(connectionListener);
|
||||
};
|
||||
|
||||
exports.connect = exports.createConnection = function(options: ?{ port: ?number | ?string, host: ?string, localAddress: ?string, localPort: ?number}, callback: ?() => void) : Socket {
|
||||
// TODO : determine how to properly overload this with flow
|
||||
exports.connect = exports.createConnection = function() : Socket {
|
||||
var tcpSocket = new Socket();
|
||||
tcpSocket.connect(options, callback);
|
||||
return tcpSocket;
|
||||
return Socket.prototype.connect.apply(tcpSocket, tcpSocket._normalizeConnectArgs(arguments));
|
||||
};
|
||||
|
||||
exports.isIP = function(input: string) : number {
|
||||
|
|
|
@ -7,12 +7,24 @@
|
|||
# Some modules have their own node_modules with overlap
|
||||
.*/node_modules/node-haste/.*
|
||||
|
||||
# Ignore react-tools where there are overlaps, but don't ignore anything that
|
||||
# react-native relies on
|
||||
.*/node_modules/react-tools/src/React.js
|
||||
.*/node_modules/react-tools/src/renderers/shared/event/EventPropagators.js
|
||||
.*/node_modules/react-tools/src/renderers/shared/event/eventPlugins/ResponderEventPlugin.js
|
||||
.*/node_modules/react-tools/src/shared/vendor/core/ExecutionEnvironment.js
|
||||
# Ugh
|
||||
.*/node_modules/babel.*
|
||||
.*/node_modules/babylon.*
|
||||
.*/node_modules/invariant.*
|
||||
|
||||
# Ignore react and fbjs where there are overlaps, but don't ignore
|
||||
# anything that react-native relies on
|
||||
.*/node_modules/fbjs-haste/.*/__tests__/.*
|
||||
.*/node_modules/fbjs-haste/__forks__/Map.js
|
||||
.*/node_modules/fbjs-haste/__forks__/Promise.js
|
||||
.*/node_modules/fbjs-haste/__forks__/fetch.js
|
||||
.*/node_modules/fbjs-haste/core/ExecutionEnvironment.js
|
||||
.*/node_modules/fbjs-haste/core/isEmpty.js
|
||||
.*/node_modules/fbjs-haste/crypto/crc32.js
|
||||
.*/node_modules/fbjs-haste/stubs/ErrorUtils.js
|
||||
.*/node_modules/react-haste/React.js
|
||||
.*/node_modules/react-haste/renderers/dom/ReactDOM.js
|
||||
.*/node_modules/react-haste/renderers/shared/event/eventPlugins/ResponderEventPlugin.js
|
||||
|
||||
# Ignore commoner tests
|
||||
.*/node_modules/commoner/test/.*
|
||||
|
@ -43,9 +55,9 @@ suppress_type=$FlowIssue
|
|||
suppress_type=$FlowFixMe
|
||||
suppress_type=$FixMe
|
||||
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(1[0-7]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(1[0-7]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)? #[0-9]+
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(2[0-0]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(2[0-0]\\|1[0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
|
||||
suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
|
||||
|
||||
[version]
|
||||
0.17.0
|
||||
0.20.1
|
||||
|
|
|
@ -24,7 +24,7 @@ function randomPort() {
|
|||
var serverPort = randomPort();
|
||||
|
||||
var server = net.createServer(function(socket) {
|
||||
console.log('server connected');
|
||||
console.log('server connected on ' + JSON.stringify(socket.address()));
|
||||
|
||||
socket.on('data', function (data) {
|
||||
console.log('Server Received: ' + data);
|
||||
|
@ -34,21 +34,33 @@ var server = net.createServer(function(socket) {
|
|||
socket.on('error', function(error) {
|
||||
console.log('error ' + error);
|
||||
});
|
||||
}).listen({ port: serverPort }, function() {
|
||||
}).listen(serverPort, function() {
|
||||
console.log('opened server on ' + JSON.stringify(server.address()));
|
||||
});
|
||||
|
||||
var client = net.createConnection({ port: serverPort }, function() {
|
||||
server.on('error', function(error) {
|
||||
console.log('error ' + error);
|
||||
});
|
||||
|
||||
var client = net.createConnection(serverPort, function() {
|
||||
console.log('opened client on ' + JSON.stringify(client.address()));
|
||||
client.write('Hello, server! Love, Client.');
|
||||
});
|
||||
|
||||
client.on('data', function(data) {
|
||||
console.log('Client Received: ' + data);
|
||||
console.log('Client Received: ' + data);
|
||||
client.destroy(); // kill client after server's response
|
||||
server.close();
|
||||
});
|
||||
|
||||
client.on('error', function(error) {
|
||||
console.log('client error ' + error);
|
||||
});
|
||||
|
||||
client.on('close', function() {
|
||||
console.log('client close');
|
||||
});
|
||||
|
||||
var rctsockets = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
|
@ -80,14 +92,4 @@ var styles = StyleSheet.create({
|
|||
},
|
||||
});
|
||||
|
||||
// only works for 8-bit chars
|
||||
function toByteArray(obj) {
|
||||
var uint = new Uint8Array(obj.length);
|
||||
for (var i = 0, l = obj.length; i < l; i++){
|
||||
uint[i] = obj.charCodeAt(i);
|
||||
}
|
||||
|
||||
return new Uint8Array(uint);
|
||||
}
|
||||
|
||||
AppRegistry.registerComponent('rctsockets', () => rctsockets);
|
||||
|
|
|
@ -31,7 +31,7 @@ typedef enum RCTTCPError RCTTCPError;
|
|||
- (void)onData:(NSNumber *)clientID data:(NSData *)data;
|
||||
- (void)onClose:(TcpSocketClient*)client withError:(NSError *)err;
|
||||
- (void)onError:(TcpSocketClient*)client withError:(NSError *)err;
|
||||
- (NSNumber*)generateRandomId;
|
||||
- (NSNumber*)getNextId;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -67,7 +67,7 @@ typedef enum RCTTCPError RCTTCPError;
|
|||
|
||||
- (BOOL)listen:(NSString *)host port:(int)port error:(NSError **)error;
|
||||
|
||||
- (NSDictionary<NSString *, NSString *> *)getAddress;
|
||||
- (NSDictionary<NSString *, id> *)getAddress;
|
||||
|
||||
/**
|
||||
* write data
|
||||
|
|
|
@ -85,22 +85,22 @@ NSString *const RCTTCPErrorDomain = @"RCTTCPErrorDomain";
|
|||
return result;
|
||||
}
|
||||
|
||||
- (NSDictionary<NSString *, NSString *> *)getAddress
|
||||
- (NSDictionary<NSString *, id> *)getAddress
|
||||
{
|
||||
if (_tcpSocket)
|
||||
{
|
||||
if (_tcpSocket.isConnected) {
|
||||
return @{ @"port": @(_tcpSocket.connectedPort).stringValue,
|
||||
return @{ @"port": @(_tcpSocket.connectedPort),
|
||||
@"address": _tcpSocket.connectedHost ?: @"unknown",
|
||||
@"family": _tcpSocket.isIPv6?@"IPv6":@"IPv4" };
|
||||
} else {
|
||||
return @{ @"port": @(_tcpSocket.localPort).stringValue,
|
||||
return @{ @"port": @(_tcpSocket.localPort),
|
||||
@"address": _tcpSocket.localHost ?: @"unknown",
|
||||
@"family": _tcpSocket.isIPv6?@"IPv6":@"IPv4" };
|
||||
}
|
||||
}
|
||||
|
||||
return @{ @"port": @"0",
|
||||
return @{ @"port": @(0),
|
||||
@"address": @"unknown",
|
||||
@"family": @"unkown" };
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ NSString *const RCTTCPErrorDomain = @"RCTTCPErrorDomain";
|
|||
|
||||
- (void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket
|
||||
{
|
||||
TcpSocketClient *inComing = [[TcpSocketClient alloc] initWithClientId:[_clientDelegate generateRandomId]
|
||||
TcpSocketClient *inComing = [[TcpSocketClient alloc] initWithClientId:[_clientDelegate getNextId]
|
||||
andConfig:_clientDelegate
|
||||
andSocket:newSocket];
|
||||
[_clientDelegate onConnection: inComing
|
||||
|
|
|
@ -11,9 +11,13 @@
|
|||
#import "TcpSockets.h"
|
||||
#import "TcpSocketClient.h"
|
||||
|
||||
// offset native ids by 5000
|
||||
#define COUNTER_OFFSET 5000
|
||||
|
||||
@implementation TcpSockets
|
||||
{
|
||||
NSMutableDictionary<NSNumber *,TcpSocketClient *> *_clients;
|
||||
int _counter;
|
||||
}
|
||||
|
||||
RCT_EXPORT_MODULE()
|
||||
|
@ -27,11 +31,11 @@ RCT_EXPORT_MODULE()
|
|||
}
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(createSocket:(nonnull NSNumber*)cId)
|
||||
- (TcpSocketClient *)createSocket:(nonnull NSNumber*)cId
|
||||
{
|
||||
if (!cId) {
|
||||
RCTLogError(@"%@.createSocket called with nil id parameter.", [self class]);
|
||||
return;
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (!_clients) {
|
||||
|
@ -40,10 +44,12 @@ RCT_EXPORT_METHOD(createSocket:(nonnull NSNumber*)cId)
|
|||
|
||||
if (_clients[cId]) {
|
||||
RCTLogError(@"%@.createSocket called twice with the same id.", [self class]);
|
||||
return;
|
||||
return nil;
|
||||
}
|
||||
|
||||
_clients[cId] = [TcpSocketClient socketClientWithId:cId andConfig:self];
|
||||
|
||||
return _clients[cId];
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(connect:(nonnull NSNumber*)cId
|
||||
|
@ -51,8 +57,10 @@ RCT_EXPORT_METHOD(connect:(nonnull NSNumber*)cId
|
|||
port:(int)port
|
||||
withOptions:(NSDictionary *)options)
|
||||
{
|
||||
TcpSocketClient* client = [self findClient:cId callback:nil];
|
||||
if (!client) return;
|
||||
TcpSocketClient *client = _clients[cId];
|
||||
if (!client) {
|
||||
client = [self createSocket:cId];
|
||||
}
|
||||
|
||||
NSError *error = nil;
|
||||
if (![client connect:host port:port withOptions:options error:&error])
|
||||
|
@ -88,8 +96,10 @@ RCT_EXPORT_METHOD(listen:(nonnull NSNumber*)cId
|
|||
host:(NSString *)host
|
||||
port:(int)port)
|
||||
{
|
||||
TcpSocketClient* client = [self findClient:cId callback:nil];
|
||||
if (!client) return;
|
||||
TcpSocketClient* client = _clients[cId];
|
||||
if (!client) {
|
||||
client = [self createSocket:cId];
|
||||
}
|
||||
|
||||
NSError *error = nil;
|
||||
if (![client listen:host port:port error:&error])
|
||||
|
@ -176,13 +186,8 @@ RCT_EXPORT_METHOD(listen:(nonnull NSNumber*)cId
|
|||
[_clients removeObjectForKey:cId];
|
||||
}
|
||||
|
||||
-(NSNumber*)generateRandomId {
|
||||
int r = 0;
|
||||
do {
|
||||
r = (arc4random() % 1000) + 5001;
|
||||
} while(_clients[@(r)]);
|
||||
|
||||
return @(r);
|
||||
-(NSNumber*)getNextId {
|
||||
return @(_counter++ + COUNTER_OFFSET);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
Loading…
Reference in New Issue