godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.13k stars 78 forks source link

Being able to select the network card while sending UDP messages #3109

Open starcin opened 3 years ago

starcin commented 3 years ago

Describe the project you are working on

A hardware in the loop simulator for professional use on a workstation with multiple network interfaces.

Describe the problem or limitation you are having in your project

The simulator I am developing use multicast UDP messaging heavily because of some sensors connected to it or some sensors it is simulating. The simulator is connected to multiple networks on separate blocks via separate network interfaces.

Joining a multicast message is no problem since PacketPeerUDP has a method named join_multicast_group with a parameter interface_name. But while sending the message, we have to use put_packet which doesn't have an option to select a network interface.

Normally it isn't a problem since set_dest_address actually selects a network card by looking at the address block if two network interfaces are on different blocks, but multicast has IP blocks like 236...* (which are different than both of the network interfaces' IP blocks).

Now it looks like everytime the OS starts up, it puts network cards on a list and it seems like the put_packet just get the first one on that list. If my messages go to the wrong network, I just restart the PC. Or sometimes I change the cable connections of the network cards while also changing their IP adresses without restarting the PC but restarting the network switches.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Just like join_multicast_group ( String multicast_address, String interface_name ), there should be a way to select the network interface to send UDP packets. It can be an overloaded version of put_packet or set_dest_address.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

Instead of using put_packet(somePoolByteArray)

a user can use put_packet(somePoolByteArray, theNetworkCardInterfaceName) or set_dest_address(236.0.10.5, 6688, theNetworkCardInterfaceName)

If this enhancement will not be used often, can it be worked around with a few lines of script?

I couldn't find a workaround without modifying the C++ code.

Is there a reason why this should be core and not an add-on in the asset library?

The recommended solution is about two of the most used methods in multiplayer games. Just not used with this option often since not many user level computers are connected to multiple ethernet networks at the same time.

Calinou commented 3 years ago

cc @Faless

Faless commented 3 years ago

The implementation is not really possible the way you request it. There is no way to specify the outgoing interface for packets in general because the OS will decide the interface based on the destination address and the routing table.

Your problem is specific to multicast addresses, and while it's weird the OS chooses the first interface to send the multicast packet (and not the one joined the multicast group), this could be a problem if you join the same multicast group with 2 different interfaces (which may be your case?).

What we can do is add a method set_multicast_send_interface(String if_name) that uses setsockopt with IP_MULTICAST_IF/IPV6_MULTICAST_IF appropriately.

starcin commented 3 years ago

Your problem is specific to multicast addresses, and while it's weird the OS chooses the first interface to send the multicast packet (and not the one joined the multicast group), this could be a problem if you join the same multicast group with 2 different interfaces (which may be your case?).

To be honest "first" is just my guess. There may be another mechanism but it is not alphabetical or something like that because it randomly changes the network card when the PC restarts. And to be clear, in my application, only one interface is communicating with multicast packets. The other one uses normal UDP packets (with IP addresses like 5.x.x.x or 10.x.x.x).

What we can do is add a method set_multicast_send_interface(String if_name) that uses setsockopt with IP_MULTICAST_IF/IPV6_MULTICAST_IF appropriately.

I believe this would be a nice solution.

starcin commented 3 years ago

@Faless by the way, do you know any workaround for this? Or should I accept my fate and restart my PC everytime it chooses the wrong interface until we get this feature?

If there is not an easy workaround, would compiling the engine after adding this method into to C++ side be problematic?

starcin commented 3 years ago

Sorry for bugging again but at this point should I do anything?

I guess I don't know the procedure here. It looks like @Faless suggested a nice addition to the code, but does this mean we will see this feature in a future update, or maybe in version 4.0? I see some of the requests are assigned to someone or set as milestones. What should I do now?

Faless commented 3 years ago

You can open a PR with the proposed changes, and I'll try to review it. Or you'll have to wait until some other developer have the time to do the PR instead.

On Fri, Aug 27, 2021, 08:14 starcin @.***> wrote:

Sorry for bugging again but at this point should I do anything?

I guess I don't know the procedure here. It looks like @Faless https://github.com/Faless suggested a nice addition to the code, but does this mean we will see this feature in a future update? I see some of the requests are assigned to someone or set as milestones. What should I do now?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/godotengine/godot-proposals/issues/3109#issuecomment-906982218, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAM4C3SW22BLPFTMSTH5CYLT643O3ANCNFSM5BZMTWPA . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.