Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for issue #53 - Receiving "Address Already in Use" error when binding two sockets to same port on iOS #54

Merged
merged 3 commits into from
Oct 25, 2017

Conversation

intmainvoid
Copy link
Contributor

  1. Updated GCDAsyncUdpSocket
  2. Set option to reuse port if socket bound to same port twice from same IP Address

@intmainvoid
Copy link
Contributor Author

Fix for issue #53

@mvayngrib
Copy link
Member

mvayngrib commented Aug 22, 2017

@intmainvoid thanks for the PR! I haven't reviewed the changes yet, but meanwhile, to be consistent with dgram's behavior, I think you should only allow reuse when the createSocket is called with reuseAddr: true:

see:

also:
do you know if this version of GCDAsyncUdpSocket introduces any breaking changes, e.g. what's the semver change in GCDAsyncUdpSocket?

@intmainvoid
Copy link
Contributor Author

I think you should only allow reuse when the createSocket is called with reuseAddr: true:

reuseAddr is quite different to reusePort on the POSIX socket level. (See here). Anyway I've updated the code and tried to make it adhere to the pattern as closely as possible to the patterns used in node.js's dgram. However, it seems that dgram doesn't actually use the SO_REUSEPORT option.

do you know if this version of GCDAsyncUdpSocket introduces any breaking changes, e.g. what's the semver change in GCDAsyncUdpSocket?

Tested relatively thoroughly in a new iOS app that is soon to be released. Crashes went away after this change (although I suspect it is due more to the introduction of the reusePort option than the update of GCDAsyncUdpSocket).

@intmainvoid
Copy link
Contributor Author

Oh just read: nodejs/node#2604. Based on that, node.js turns on SO_REUSEPORT without any option for the user to disable/enable it for OSX. This is how my original PR handled this. In any case, I'm happy either way as long as there is a way to turn it on.

@mvayngrib
Copy link
Member

@intmainvoid it's not entirely clear to me how reuseAddr works in node, but given this snippet (adapted from nodejs/node#2604), if you run it in two terminal tabs, it only works when reuseAddr is true:

const dgram = require('dgram')

dgram.createSocket({
  type: 'udp4',
  reuseAddr: true
})
.bind({
  address: '127.0.0.1',
  port: 9527
})

@intmainvoid
Copy link
Contributor Author

intmainvoid commented Oct 15, 2017

Yep, that all sounds good. So this PR proposes that this feature be used in the following way:

dgram.createSocket({
  type: 'udp4',
  reusePort: true
}).bind('127.0.0.1', (err) => {
  console.log("Connected Successfully?: ", err ? "false" : "true");
});

If the reusePort option is not provided, the default value is false.
This change to the react-native-udp's API follows your example for reuseAddr very closely.

@Double-Dude
Copy link

Hi @mvayngrib, please follow up this. This issue happens very often to my app when another app is also using UDP and being kill by OS in the background(you can see from the multi-task screen). I think somehow OS wakes up the other app and that app binds the port, so my app using this library can't bind the port. Have used "enableReusePort", but it didn't help.

@mvayngrib
Copy link
Member

mvayngrib commented Oct 25, 2017

@intmainvoid sorry, missed your update of the PR. Can you tell me to what version of GCDAsyncUdpSocket you updated? It would be good to have the commit hash from /~https://github.com/robbiehanson/CocoaAsyncSocket

thanks!

@@ -112,7 +112,7 @@ UdpSocket.prototype.bind = function(port, address, callback) {

UdpSocket.prototype.close = function (callback=noop) {
if (this._destroyed) {
return process.nextTick(callback)
return setImmediate(callback)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any particular reason?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

process.nextTick doesn't exist on React Native. This line was generating an error

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, right, i've gotten so used to using rn-nodeify, i've forgotten i'm not in node. Good catch!

@mvayngrib
Copy link
Member

for future reference, the current version (2.1.0) uses CocoaAsyncSocket 7.4.1, commit c0bbcbc

@intmainvoid
Copy link
Contributor Author

intmainvoid commented Oct 25, 2017

@intmainvoid sorry, missed your update of the PR. Can you tell me to what version of GCDAsyncUdpSocket you updated? It would be good to have the commit hash from /~https://github.com/robbiehanson/CocoaAsyncSocket

I believe it is this one:
[d0adf58ca694e733c75a8a157635e3deb66c061e] (or d0adf58)(robbiehanson/CocoaAsyncSocket@d0adf58)

So, basically the current master branch (minus a licensing update)

@mvayngrib
Copy link
Member

cool, that checks out :)

@mvayngrib mvayngrib merged commit 822b1e0 into tradle:master Oct 25, 2017
@mvayngrib
Copy link
Member

@intmainvoid released as 2.2.0, thanks again for the PR!
@quhaoran007 thanks for the poke :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants