diff --git a/UdpSocket.js b/UdpSocket.js index f21116a8..964d258e 100644 --- a/UdpSocket.js +++ b/UdpSocket.js @@ -85,7 +85,7 @@ UdpSocket.prototype.bind = function(...args) { if (!port) port = 0 - if (callback) this.once('listening', callback.bind(this)) + if (callback) this.once('bound', callback.bind(this)) this._state = STATE.BINDING this._debug('binding, address:', address, 'port:', port) @@ -109,7 +109,23 @@ UdpSocket.prototype.bind = function(...args) { self._address = addr.address self._port = addr.port self._state = STATE.BOUND - self.emit('listening') + self.emit('bound') + }) +} + +UdpSocket.prototype.startReceiving = function(callback=noop) { + if (this._state !== STATE.BOUND) { + throw new Error('you must bind before startReceiving()') + } + + this.once('listening', callback) + + Sockets.startReceiving(this._id, err => { + err = normalizeError(err) + if (err) return this.emit('error', err) + + this._debug('listening') + this.emit('listening') }) } diff --git a/android/build.gradle b/android/build.gradle index 1a8d75f9..d77b8c2f 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -32,7 +32,7 @@ android { dependencies { def supportLibVersion = project.hasProperty('supportLibVersion') ? project.supportLibVersion : DEFAULT_SUPPORT_LIB_VERSION - compile fileTree(dir: 'libs', include: ['*.jar']) - compile "com.android.support:appcompat-v7:$supportLibVersion" - compile 'com.facebook.react:react-native:+' + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "com.android.support:appcompat-v7:$supportLibVersion" + compileOnly 'com.facebook.react:react-native:+' } diff --git a/android/src/main/java/com/tradle/react/UdpSocketClient.java b/android/src/main/java/com/tradle/react/UdpSocketClient.java index 15d65266..7c82afd8 100644 --- a/android/src/main/java/com/tradle/react/UdpSocketClient.java +++ b/android/src/main/java/com/tradle/react/UdpSocketClient.java @@ -82,6 +82,17 @@ public void bind(Integer port, @Nullable String address) throws IOException { mSocket.setReuseAddress(mReuseAddress); mSocket.bind(socketAddress); + } + + /** + * Start receiving thread. + * + * @throws IllegalStateException if socket is not bound. + */ + public void startReceiving() throws IllegalStateException { + if (null == mSocket || !mSocket.isBound() || mReceiverTask == null) { + throw new IllegalStateException("Socket is not bound."); + } // begin listening for data in the background mReceiverTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, diff --git a/android/src/main/java/com/tradle/react/UdpSockets.java b/android/src/main/java/com/tradle/react/UdpSockets.java index 93693c98..856f8dc7 100644 --- a/android/src/main/java/com/tradle/react/UdpSockets.java +++ b/android/src/main/java/com/tradle/react/UdpSockets.java @@ -157,6 +157,30 @@ protected void doInBackgroundGuarded(Void... params) { }.execute(); } + /** + * Start receiving thread. + */ + @ReactMethod + public void startReceiving(final Integer cId, final Callback callback) { + new GuardedAsyncTask(getReactApplicationContext()) { + @Override + protected void doInBackgroundGuarded(Void... params) { + UdpSocketClient client = findClient(cId, callback); + if (client == null) { + return; + } + + try { + client.startReceiving(); + callback.invoke(); + } catch (IllegalStateException ise) { + // Socket is not bound or a problem occurred during starting thread + callback.invoke(UdpErrorUtil.getError(null, ise.getMessage())); + } + } + }.execute(); + } + /** * Joins a multi-cast group */ diff --git a/ios/UdpSocketClient.h b/ios/UdpSocketClient.h index 7c43af67..1207abab 100644 --- a/ios/UdpSocketClient.h +++ b/ios/UdpSocketClient.h @@ -66,6 +66,11 @@ typedef enum RCTUDPError RCTUDPError; */ - (BOOL)bind:(u_int16_t) port address:(NSString*)address options:(NSDictionary *)options error:(NSError**)error; +/** + * Start receiving thread + */ + - (BOOL)startReceiving:(NSError **) error; + /** * Join multicast groupt * diff --git a/ios/UdpSocketClient.m b/ios/UdpSocketClient.m index 82e3288e..97d6fcbb 100644 --- a/ios/UdpSocketClient.m +++ b/ios/UdpSocketClient.m @@ -93,13 +93,13 @@ - (BOOL)bind:(u_int16_t)port address:(NSString *)address options:(NSDictionary * _address = address; _udpSocket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:[self methodQueue]]; - + [_udpSocket setMaxReceiveIPv4BufferSize:UINT16_MAX]; [_udpSocket setMaxReceiveIPv6BufferSize:UINT16_MAX]; BOOL reusePort = options[@"reusePort"] ?: NO; [_udpSocket enableReusePort:reusePort error:error]; - + BOOL result; if (address) { struct sockaddr_in ip; @@ -114,7 +114,12 @@ - (BOOL)bind:(u_int16_t)port address:(NSString *)address options:(NSDictionary * result = [_udpSocket bindToPort:_port error:error]; } - return result && [_udpSocket beginReceiving:error]; + return result; +} + +- (BOOL)startReceiving:(NSError **) error +{ + return [_udpSocket beginReceiving:error]; } - (BOOL)joinMulticastGroup:(NSString *)address error:(NSError **) error diff --git a/ios/UdpSockets.m b/ios/UdpSockets.m index a007f212..5d032995 100644 --- a/ios/UdpSockets.m +++ b/ios/UdpSockets.m @@ -70,6 +70,22 @@ - (void)dealloc callback(@[[NSNull null], [client address]]); } +RCT_EXPORT_METHOD(startReceiving:(nonnull NSNumber*)cId + callback:(RCTResponseSenderBlock)callback) +{ + UdpSocketClient* client = [self findClient:cId callback:callback]; + if (!client) return; + + NSError *error = nil; + if (![client startReceiving:&error]) + { + NSString *msg = error.localizedFailureReason ?: error.localizedDescription; + callback(@[msg ?: @"unknown error when startReceiving"]); + return; + } + callback(@[[NSNull null]]); +} + RCT_EXPORT_METHOD(send:(nonnull NSNumber*)cId string:(NSString*)base64String port:(int)port @@ -108,9 +124,9 @@ - (void)dealloc RCT_EXPORT_METHOD(addMembership:(nonnull NSNumber*)cId multicastAddress:(NSString *)address) { UdpSocketClient *client = _clients[cId]; - + if (!client) return; - + NSError *error = nil; [client joinMulticastGroup:address error:&error]; } @@ -118,9 +134,9 @@ - (void)dealloc RCT_EXPORT_METHOD(dropMembership:(nonnull NSNumber*)cId multicastAddress:(NSString *)address) { UdpSocketClient *client = _clients[cId]; - + if (!client) return; - + NSError *error = nil; [client leaveMulticastGroup:address error:&error]; }