I am trying to make an application that utilizes UPnP if necessary to open ports so incoming transmissions can be received. The thing is, I don't want to specify an external port (because one, the external port doesn't matter for the application to be found, and two, I want to make sure multiple people on the same router can use the application, and sharing a port is not an option, obviously). None of the API's I'm looking at says anything about begin able to not specifying a port, but would sending something like 0 or -1 cause it to choose a port itself, or do I have to choose a random number and hope for the best?
Also, will the port mappings ever expire, or do I have to forcefully de-map all of them? I was wondering for in-case the application crashes or the computer looses power or something.
Related
I am trying to implement a publish and subscribe hello world program for communication between 2 devices using eclipse cyclone DDS protocol, I am able to do it when devices are connected in the same network but when devices are in a different network there is no communication happening. As per my understanding, it's because of the default DDS domain but how do I change it?
I followed https://github.com/eclipse-cyclonedds/cyclonedds
Here there's a mention to make use of an XML file, but I am not understanding how to use it or where to use the file.
Any suggestion would be of much help, thank you!
Cyclone DDS looks at the value of the CYCLONEDDS_URI environment variable to find its configuration file. What you can do is make an XML file somewhere on your computer and put its path in that environment variable. E.g., on Linux:
export CYCLONEDDS_URI=/path/to/cdds.xml
or on Windows (“cmd”, I don’t know how to do it in powershell):
set "CYCLONEDDS_URI=c:/path/to/cdds.xml"
Windows is a bit tricky with the quotes, this seems to work fine. Then, when you start your application, Cyclone DDS will read that file and apply the settings in it. Of course you also need to know what to put in it.
For that, it is useful to know a few things about the networks you are using. In one network, it all works without any configuration because the UDP/IP multicast works semi-magically in a single network. If there are multiple networks, there is a router in between and those routers are often configured not to route multicast traffic.
That means you basically have two options:
Configure the routers to route multicast traffic between the networks (especially the 239.255.0.1 address used by default by DDS). If that works, you’re all set, no need to configure anything in Cyclone DDS.
Disable the use of multicast and instead list the hostnames/IP addresses of the machines you want to communicate with in the configuration file. You still need a router willing to route traffic from the one network to the other, but that is usually not a problem with unicast packets. (If for example you can ping it or login to it remotely, it’s fine.)
For (2), something like:
<CycloneDDS>
<Domain>
<General>
<AllowMulticast>false</AllowMulticast>
</General>
<Discovery>
<ParticipantIndex>auto</ParticipantIndex>
<Peers>
<Peer Address="ip-of-node-1" />
<Peer Address="ip-of-node-2" />
<Peer Address="ip-of-node-3" />
/Peers>
</Discovery>
</Domain>
</CycloneDDS>
should work (obviously with the ip-of-node-1 &c. replaced with the correct addresses/hostnames). Setting “AllowMulticast” to false simply disables all use of multicast. If multicast doesn’t work reliably with all nodes, assuming it works can give a broken system. So at this stage, it is definitely easier to just not use it.
The “ParticipantIndex” has to do with the UDP port numbers it uses. With multicast, multiple processes on a single machine can all use the same UDP port number for receiving the discovery packets, and so there is this agreed-upon port number for discovery that makes everything work without any configuration (port number 7400 for domain id 0). That in turn allows it to use random port numbers for receiving unicast traffic.
With unicast, however, each process needs to have its own unique port number, and that in turn means the other processes need to know to which port numbers to send the data to. Setting the “ParticipantIndex” to auto forces it use predictable port numbers so that the processes can find each other.
I'm new to WebRTC and I was wondering if it's possible to have webRTC application on a local network without need for signaling since we have the IP addresses of all members on the network and if so how should I use RTCPeerconnectio to create an offer?
Thank you
No it is not possible.
Signalling is for more than just exchanging IP addresses. The clients also exchange information about media types and codecs.
You could possibly do some of the exchange via hard coding. But you would basically need to go through the whole negotiation, logging out all the candidates, offer, and answer. Even then I don't know if it would work the second time (with everything hardcoded). It also wouldn't work if you ever wanted to change media. It would be an interesting experiment.. but probably a huge waste of time.
It can be done! But kradical is right there will need to be some configuration ahead of time check out pion/offline-browser-communication
Here are the things you need to worry about
You don't need to hardcoded IP addresses anymore thanks to mDNS candidates. If you know the hostnames of the two computers they can both change IP addresses, and still be able to connect.
You need to know the DTLS certificate and ICE credentials ahead of time. If you look at the repo I shared you can see how it is done there. I did Go <-> Browser because it is the Open Source project I work on, but can easily be Browser <-> Browser as well.
I would connect with only a DataChannel at first, and then re-negotiate with all the details around media (tracks you wish to send and supported codecs)
Is it somehow possible to tell the browser to choose a specific interface and ignore the Windows routing table?
I have the following problem:
I have a PPP dial-up, where I have to access some https websites, if I make my standard gateway point to this PPP interface, I can access the website.
But I don't want to add a specific route, as I connect to different devices, and all have different IP Addresses, so it is also possible that my local LAN Interface, where I have my internet access, has the same IP Address as the remote https address I need to connect to.
So I think the only way would be to somehow tell the browser to use a specific interface for all the traffic. Is this somehow possible, or possible with VB.net programming?
"Is it somehow possible to tell the browser to choose a specific interface and ignore the Windows routing table?"
No. As an application, the browser relies entirely on the OS's network stack to establish communication.
The point of a network is to allow many-to-many communication. So, if you do it right, you can use a single network adapter to communication with hundreds or even thousands of other nodes at the same time.
You could use a NIC to establish a PPPoE session to the Internet while at the same time communicating with your local network. However, this in turn requires you to connect the modem to the LAN as well which is not a good idea - you should either use two separate NICs or an Internet router.
What I want is, basically, to create a connection between two different computers on same local network. But i want to do this by computers' local IP's. (like 192.168.2.23 etc)
This must be a totally local connection. no TURN or STUN Servers. I am not sure if this is possible. Because there are not much documentation/example/information about WebRTC.
So, how can I create a connection from my computer to another one just passing its local IP as parameter?
Update: To be more clear; imagine there is an html page contains some code that activates my camera and audio services. and another -almost same- page is open in other computer. Waiting a connection request... And there is a textbox in my page to type an IP belongs to other computer on my local network. type 192.168.2.xx and bingo! i have connection between me and other computer.
I want this process as IP based, because there may be more than 2 devices on the network. And all of them are possible devices to create connection. So i need to reach them by their IP's.
Any example code or explanation would be great! even if it tells that this is not possible.
Thanks
Peer discovery is a vital part in any WebRTC application. It's an expensive term for saying: "Hi, I'm computer 4 and I want to talk to you!".
See it as calling a friend over the phone. You need to dial his number first.
This part is not defined in the WebRTC standards. You need to implement this logic in your application. Once you know who you want to call, you need a way of exchanging vital information. This is called signaling, like flo850 put in his answer.
Signaling is needed before any peer-to-peer connection can be set up.
To come up with an idea for your use case of 7 devices in a LAN.
If you have these devices connected to for example a WebSockets server and are in the same channel.
The WebSockets server can be written to route messages to specific receivers.
Devices connected to the channel often are identified with some kind of ID, imagine you use the device's IP.
When you want to talk to computer 4 with IP 192.168.0.4 you send the exchange messages (signaling) on the channel to the receiver with ID, the IP of the device you want to connect with.
How to send the signaling (offer, answer) is described here with example code.
Hope this helps
Users usually sit behind NATs; that's why ICE concept implemented in WebRTC.
If both users are sitting behind same NAT; you can skip ICE servers by passing "NULL" parameter value over "RTCPeerConnection" constructor:
var peer = new [webkit|moz]RTCPeerConnection ( null );
Now, browser will use "host" candidates, also known as "local" candidates.
you still need a signaling server. During the ICE candidate search, your clients will exchange their local ip through this signaling server
For an iOS app I am developing, I want multiple phone to connect to each other and be able to voice chat between those devices.
I have it working when both devices are on the same network. This was quite simple and most of the stuff I want to do, is possible.
But now I am adding internet support, which is quite a hassle. I'll first try to explain how I want to match the devices, using a small webservice I set up.
Server
Start a new GameKit session, with session-mode GKSessionModePeer
Find the "Peer ID" of the server on the session I just created
Create a new CFSocketRef on an free port and keep it ready to accept connections
Send Peer ID and Port number to my webservice, running on an external server.
WebService
Webservice receives the information and stores it together with an ID and the IP address of the client in a database.
Send ID back to Server, which displays the ID
Client
When the user chooses to use the "Online" feature of GameKit to search for games, I ask the user for an ID (where the user should input the ID the server receives).
Client connects to the webservice supplying the ID. The webservice returns the information about the session (IP, PORT, Peer ID) of the server.
The user tries to connect to the IP address, with the port information and set up an input and output stream with the server.
This does not work ofcourse, because my network does not allow incoming connections and a random port (from an external network).
But now the question is, how do I solve this? I want to be able to set up a peer to peer connection between 2 devices, those devices could be on the same network, but also on separate networks.
Is there a framework, example or anything showing how to do this? I want to be able to send data from device to device, without sending it to a server first.
I'm not aware of any frameworks that do this. I do however have a lot of experience with p2p networking across multiple networks.
One important rule I learned: when communicating between networks, don't create a direct connection unless necessary. There are just too many factors that can (will?) cause issues, such as firewalls, NATs, etc.
Sure, you can let the connection try first. You can try to connect to the given IP addresses*, but in most cases it will fail. Even when using UPnP and NAT-PMP, you'll find that in a lot of cases (more than half?) you won't be able to accept incoming connections at all.
So make sure to have a backup plan. Make a network layer abstraction that doesn't only listen(), but also connects to a server. That way, when you can't connect to the IPs* of the client, you simply setup a connection via the server and the network abstraction takes care of it all.
Let me reiterate the above: don't rely on incoming connections only, always have a backup plan.
* I write IPs because clients can have multiple local/remote IPs. Always iterate over all these IPs when connecting. Example: my phone has 2 local IPv4 addresses (10.0.0.172 and 10.8.0.2), and an IPv6 address ([2001:x:x::6]). Of these three addresses, only the IPv6 address is publicly reachable, and the two IPv4 addresses are on different subnets so whether you can connect to them depends on the subnet that the other client is on. Always try to connect to both, and fall back to a server-proxied connection when it fails.
** I mentioned IPv6, yes. Let's not forget that IPv6 is not limited by NATs, unlike IPv4, and this means that you're far more likely to get a good connection via IPv6 than IPv4, if supported.