-
Notifications
You must be signed in to change notification settings - Fork 21
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
Add TCP port information to NetAddr #12
base: main
Are you sure you want to change the base?
Conversation
|
||
# Motivation | ||
|
||
One of the differences between TCP and UDP is that in UDP the connecton is usually not kept alive. The sender of a message simply sends the UDP package and does not bother if the package arrives, is actually sent, or even if the host exists. In TCP a connection between both points must be made before any packages are sent, and this connection is kept open until one of the ends closes it. This usually means that the sender opens a random port locally to receive incoming data from the other end of the TCP connection. One of the advantages of TCP is that a host behind a NAT or a complex network routing can open a connection to a public IP on the internet and, because the connection is two-way, the host receiving the connection can send messages back through the opened channel without the need to know the route or how to solve NAT routing and so on. This is not possible with UDP, when both ends need to know the IP of each other to exchange messages. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When receiving a UDP message, we also receive the sender address:
OSCdef(\x, { |msg, time, addr| addr.postln }, '/test').add;
NetAddr("127.0.0.1", NetAddr.langPort).sendMsg('/test');
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the problem is if both peers are not in the same network or if the IP of the sender is not directly accessible. example:
I'm behind a router with internet IP 194.42.123.98, my computer local IP is 192.168.8.42 and I send a UDP package to a public IP / host (for example if there is a server listening on scsynth.org port 57120).
The package arrives there with my router IP (194.42.123.98) the software running on scsynth.org tries to send me an UDP message back using that IP, but my router has no idea about where it should send this package to inside the network unless I configure Port Forward in the router (telling it that any packages arriving on 57120 should be sent to 192.168.8.42).
With TCP the connection is kept on and the route between scsynth.org and my computer inside the network is still reachable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest not making assumptions about peoples NAT situation. As an aside, in normally working NAT replies should be correctly delivered because of the routing table. It's making initial connections to computers behind NAT that usually requires configuration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but a UDP reply (as in the scenario I described) is basically making an initial connection to a computer behind NAT.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, normally when an internal address and port sends to an external one, replies are expected and routed accordingly. Otherwise no external to internal messages would be possible.
We did a remote recording for NIME this week with a shared server and Utopia Registrar that worked exactly like this. Port forwarding was only needed on the NAT at the server end as all clients sent out a /notify message. It's possible something else is going on in your situation (like a very short translation timeout), and I know there are some exotic forms of NAT, but normally the translation table just takes care of this.
TCP on its own of course will not solve the NAT problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you are correct @muellmusik that the translation will occur and I didn't know that sendMsg will open that port locally. So I tried now and it works:
OSCdef(\x, { |msg, time, addr| addr.postln }, '/test').add
and then on my machine:
NetAddr("bgo.la", 57120).sendMsg('/test');
and on bgo.la I get:
a NetAddr(95.91.208.191, 9435)
If I send back from bgo.la to that address in port 9435 I am able to get it back on my machine. So, somehow NetAddr is opening the port to listen. I guess the issue with TCP then is that once you do NetAddr.connect it won't register OSCFunc/Def to that TCP port?
I'm not so sure about the semantic drift of this. A NetAddr broadly models a particular endpoint, not a connection. (I admit it's slightly messy, but I'm not sure we should make it more so) Alternative approaches:
|
@muellmusik agreed. The Socket object should be a second proposal I would add in a next RFC. That is because currently sclang is only able to send / receive OSC messages, so having access to a Socket object would IMO mean a lot of extra work. I don't think it would make sense to have such object and still not be able to open local TCP port for accepting incoming connections or be able to send / receive any sort of bytes through that socket (and all other things that a Socket object should/could do). So for now having just the port and/or some other attributes would be nice. I have no preference between having NetAddr.tcpRecvPort or receving the port as the connectHandler.. Even tho I think it adds some unnecessary complexity for users who are not familiar with callbacks (but sclang is full of callbacks anyway, so it wouldn't be such a big issue) |
I'm totally sympathetic to reluctance to add a lot of stuff just to get a particular feature for now. That does need to be balanced though against the additional technical debt and complexity of adding multiple ways of doing the same thing, especially if we think a Socket object is the ultimate way to go. There's been some enthusiastic talk of adding WebSocket support, so perhaps it would be most productive to join forces and think about a broader network implementation. For myself I'd rather see an initially incomplete version of it 'done right' (if we can agree on that :-) than 1.5 times what we ultimately need.
The question I guess is how to deal with failures. Another approach could be to optionally request a port in connect() a la openUDP. We could return the port or a NetAddr if successful and nil if not. There is a small chance that this would break a small amount of code, though I suspect very little if any as it would only matter if people were relying on connect returning the instance. |
@muellmusik I am totally up for a broader network implementation and also very interested in WebSocket support. So yes, would make sense to have an initial Socket object for now. But then I'm not the most experienced in SC development to propose how that should be implemented. On the other hand, I think the way this NetAddr.connect / TCP support is really incomplete so would not hurt to have this "fixed" for now until we come up with a full network implementation. But as I said, I am happy with both. I would just like to know what port was used to send the message so I can register the proper callbacks for that message (without the need to include things on top of the application protocol like the randomId in OSCRouterClient). Thanks for the feedback :) |
So, to bring this up again - I think the network stack of sclang would really benefit from some care. The approach nowadays seems to be to spin up other node/python/... scripts to take care of any network translation (e.g. UDP->websocket, ... etc) and it would be great to get any kind of improvement here - and I'd consider any movement an improvement. Today's networking is really complex and to implement it properly on a first try is almost impossible. The only network implementation I know a bit of is from Python, see https://docs.python.org/3/library/socket.html - having a full socket implementation would be great, but I think this is a bit much to ask and to maintain. I'd vote to go with the proposed RFC but label the whole (hopefully evolving) network stack as "unstable API" and see where we go from there and eventually reach a stable API. Thinking that 4 years ago we could have the proposed RFC implemented seems to me more desirable than the current status quo of the network stack. Would you still be interested in providing some work on this @bgola? If you are still up for it I think we could ask if there are any oppositions to it and then you could give it a go :) |
@capital-G I am definitely up to work on this. Thanks for bringing it up. |
Thanks for still being interested in this @bgola! @muellmusik what is your view on it? There was some talk regarding NATing and UDP and I personally found that anytime you are confronted with NAT you are out of luck with sending UDP message to a host sitting behind a NAT. It is possible to forward a specific UDP port to a NATed host, but if your network is big (e.g. eduroam, company ...) you most likely don't get such a rule implemented within your organization - and as IPv4 addresses becomes more and more sparse (and SC is also bound to IPv4 iirc) NATing has become a default in many places, making UDP an one-way communication protocol. Having the ability to use TCP really helps in such cases because it allows to setup a back-channel through a NATed network by using the established connection which gets translated by a NAT w/o problems b/c it is stateful. Adding the opened TCP port to a At some point we could deprecate |
@capital-G Hey Dennis! Generally in favour of doing something. In fairness I'm not a networking expert, just someone who's had to make a lot of telematic stuff work, haha. That said, I'm not sure that TCP is a real solution for NAT problems, at least not a total one. If someone knows different, speak up, but my understanding is the problem is initial contact of an address behind NAT. Though not really originally intended that way, NAT acts as a security feature, since your LAN is invisible to the WAN/internet. Since LAN devices have a local rather than global address, you cannot initiate contact, you can only reply to a request. NAT keeps a table of outgoing messages, which it then uses route replies. You can't normally contact a device behind NAT, only the router. If NAT isn't expecting a reply it ignores the packet. So while TCP might help in the WAN->LAN case providing the LAN device initiates contact, it doesn't solve the LAN <-> WAN <-> LAN case since you cross NAT twice. I have actually seen this work however by both computers spoofing replies and then keeping a steady stream of messages going once connection succeeds! Anyways, apologies if this is all obvious, I just wanted to say that I don't think we should view this too much as a NAT solution, but there are other good reasons to do this. |
Anyway, yes would be great to take this forward! As NetAddr is in a lot of code, I think a new approach leading to deprecation seems very sensible. It would be nice if this was done as part of a bigger picture rethink of networking requirements, including web sockets, as suggested above. |
Indeed, but one could use ICE for this, see https://temasys.io/guides/developers/webrtc-ice-sorcery/ and https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Protocols (e.g. use https://github.com/libnice/libnice). @bgola I think you can start working on your implementation, I don't see that a PR would hit any obstacles now :) edit: Acutally it would be also great if we would be able to get the outbound UDP port of an OSC message as well - this (I think) would allow to implement STUN on top of OSC (with a simple custom web server which we could code and provide) |
I still remember oscgroups: http://www.rossbencina.com/code/oscgroups I'm not sure if anyone runs a server anymore... |
yep! mine is still up - I see some connections on to it every few weeks :D
Josh
… On Dec 16, 2024, at 8:32 PM, Scott Wilson ***@***.***> wrote:
I still remember oscgroups: http://www.rossbencina.com/code/oscgroups I'm not sure if anyone runs a server anymore...
—
Reply to this email directly, view it on GitHub <#12 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AAANHLFZJIAB3QV2EDFEDGL2F6SMVAVCNFSM6AAAAABTQTQYEOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKNBXGQ4DKMJTGQ>.
You are receiving this because you are subscribed to this thread.
|
But IIUC oscgroups isn't p2p but more of a tunneling service - STUN allows you to negotiate a P2P connection with the help of a third party to which the peers can directly connect and wouldn't require a custom client. I also tried to perform once with oscgroups within eduroam but it didn't work, so I had to quickly hack a websocket tunnel to transport the OSC messages. (btw - I am currently looking into websocket implementation within sclang) But a quark implementing oscgroups functionality and a rewrite of the oscgroups server in rust (or else) seems like a good project :) |
There was a quark… still is I think :)Josh/*Josh Parmenterwww.realizedsound.net/josh*/On Dec 17, 2024, at 04:12, Dennis Scheiba ***@***.***> wrote:
I still remember oscgroups: http://www.rossbencina.com/code/oscgroups I'm not sure if anyone runs a server anymore...
But IIUC oscgroups isn't p2p but more of a tunneling service - STUN allows you to negotiate a P2P connection with the help of a third party to which the peers can directly connect and wouldn't require a custom client.
I also tried to perform once with oscgroups within eduroam but it didn't work, so I had to quickly hack a websocket tunnel to transport the OSC messages. (btw - I am currently looking into websocket implementation within sclang)
But a quark implementing oscgroups functionality and a rewrite of the oscgroups server in rust (or else) seems like a good project :)
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you commented.Message ID: ***@***.***>
|
Yes, but it has still a dependency upon oscgroups client https://github.com/supercollider-quarks/OscGroupClient/blob/b02a838bf7333721c50ad02e1e85c41df03c4276/OscGroup.sc#L13 :) One could implement this natively within sclang if we'd have access to the outgoing port of an OSC message for UDP hole punching. |
There is bgola's tcposcrouter https://github.com/bgola/tcposcrouter, inspired by OSCgroups,
and the HyperDisCo https://github.com/aiberlin/HyperDisCo that supports it in SC :-)
… On 17. Dec 2024, at 17:33, Dennis Scheiba ***@***.***> wrote:
> There was a quark… still is I think :)
Yes, but it has still a dependency upon oscgroups client https://github.com/supercollider-quarks/OscGroupClient/blob/b02a838bf7333721c50ad02e1e85c41df03c4276/OscGroup.sc#L13 :)
One could implement this natively within sclang if we'd have access to the outgoing port of an OSC message for UDP hole punching.
—
Reply to this email directly, [view it on GitHub](#12 (comment)), or [unsubscribe](https://github.com/notifications/unsubscribe-auth/AA23A43IQ2NYHOMKQ7RITXT2GBG7HAVCNFSM6AAAAABTQTQYEOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKNBYHE3DOMRZGI).
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
Currently it is not possible to directly access an open TCP socket from sclang. This RFC proposes a way to access the metadata of the socket created when calling
NetAddr.connect
method so the user can listen to messages coming back from that socket.