Webserver hosted on an ESP32 using p2p - node.js

I was thinking about how could i host a webserver from an esp32 that is accessible from outside of it's network.
The first thing i did was i port forwarded my esp32 private ip on my router and configured a dns server to my router's public ip ( no-ip , ddns.net )
That was good. I could reach my webserver hosted on my esp32 but if i want to create a product, this is not a good solution because i can not force the users to configure their routers and configure a dns provider for themselfs.
So the next thing in my mind was, i needed a server. I could have used mqtt or any other service to exchange data with the client but i wanted to do it myself.
So i set up a node js server on my PC. The esp32 can connect to this server because it is on a public network and port forwarded already. The esp32 can use websockets as a client or http requests to send data to the server. This is ok, but the web app that the client sees is not hosted on the esp32, but on the server. This makes it hard to update the web app files ( html and js files ) both on the server and on the esp32. Because what if the client want to reach the web app from within it's local network without internet. The esp32 should have the exact same web app hosted like on the server.
I was using socket io to communicate the esp32's data with the web app client. The node js server served the static html and js files to the client, and forwarded the esp's messages coming on websocket throught socket io to the client.
Okay so the problem in here as i said that i had to update the files on both the node server and on the esp32. This is not a good way.
So i need some kind of a p2p connection. At this point i read about hole punching and webrtc and things like that.
What i tried to establish p2p connection:
Esp32 connects to node js server every 100ms, sending it's router's
public IP, it's own private Ip and things like that.
Server stores the esp data.
Client connects to server, fetching esp's router public ip, trying to
connect to it.
Server sends a message back to esp32 as a response with the client's
ip address.
Esp get's the message, trying to send data to client's IP address.
Client trying the same...
aaand nothing happens. The router's don't want to open their ports.
I tried this with raw udp, http requests and websockets. These were unsecured connections.
I found literally no low level explanation about web rtc's data channel. If i would want to write this "open source" protocoll using the C language there is just the explanation about this webrtc with high level languages like *built in options on browsers in JS and things like that.
ESP32 microcontroller LINK.
The question is, how could i estabilish a p2p connection between a microcontroller ( like esp32 using esp idf or arduino framework ) and a browser client? Is it even possible?

Have you considered mDNS/DNS-SD? You can advertise your service from esp32 and discover it with your client via arbitrary network

Related

beginner webrtc/nodejs issue connecting remote clients

I'm trying to develop a web application in nodejs. I'm using an npm package called "simple-peer" but i don't think this issue is related to that. I was able to use this package and get it working when integrating it with a laravel application using an apache server as the back end. I could access the host machine through it's IP:PORT on the network and connect a separate client to the host successfully with a peer-to-peer connection. However, I'm now trying to develop this specifically in node without an apache back end. I have my express server up and running on port 3000, I can access the index page from a remote client on the same network through IP:3000. But when I try to connect through webrtc, I get a "Connection failed" error. If I connect two different browser instances on the same localhost device, the connection succeeds.
For reference: i'm just using the copy/pasted code from this usage demo. I have the "simplepeer.min.js" included and referenced in the correct directory.
So my main questions are: is there a setting or some webRTC protocol that could be blocking the remote clients from connecting? What would I need to change to meet this requirement? Why would it work in a laravel/webpack app with apache and not with express?
If your remote clients can not get icecandidates, you need TURN server.
When WebRTC Peer behind NAT, firewall or using Cellular Network(like smartphone), P2P Connection will fail.
At that time, for fallback, TURN server will work as a relay server.
I recommend coTURN.
Here is an simple implementation of simple-peer with nodejs backend for multi-user video/audio chat. You can find the client code in /public/js/main.js. Github Project and the Demo.
And just like #JinhoJang said. You do need a turn server to pass the information. Here is a list of public stun/turn servers.

NodeJs - how to use socket.io to send tcp packet to another computer in local area network

I have NodeJs web service in based web socket. One of my file by the server side tries send xml to printer in local area network on ip address 192.168.1.5 but this ip is in my physical network not in area network by server side. When I open the web service on localhost it's work but when I open my service via network it's not work. How can I use web socket that nodejs app will send xml via TCP to another localhost in local area network using socket client just like me?
for example (my local area network):
localhost - 192.168.1.100
printer - 192.168.1.5
localhost (my physical computer) -> opening web service (NodeJS) on browser -> running script (service) -> sending xml via TCP to printer (192.168.1.5)
is this scenario possible?
You can't directly use webSocket or socket.io to send a plain TCP packet. webocket is its own protocol and socket.io runs on top of webSocket. It initiates a connection with an http request, uses it's own data format framing and its own security scheme. As such a webSocket client can only connect to a webSocket server or a socket.io client to a socket.io server, not to a plain TCP device.
You can use the Net module in node.js to make plain TCP connections. So, you can contact the printer directly from node.js if that would work.
But, you can't make plain TCP connections directly form a browser web page without using some sort of browser plug-in that has access to native code or without sending some sort of http or webSocket or socket.io request to a server and having the server contact the printer on your behalf (which would require server and printer to be on the same local network).

How to connect to a Node.js WebSocket Server from a port forwarded server?

I am trying out a chat program using HTML5 app and Node.js WebSocket on my computer, following the video https://youtu.be/hv9KdklXZqE.
The Node.js WebSocket listens to port 5555 and is at C:\xampp\htdocs\TestWebSocketServer. On the client side, we have a HTML5 website in XAMPP server also on my computer at C:\xampp\htdocs\TestWebsocket_client
We would like to send some messages from our client to the WebSocket server on my computer. My computer is in a LAN network behind our Main Server that is accessible online. (Let's assume it is named "http://exampleSite.com".)
To do this, we did a fixed IP address on my computer and did a port forwarding in the Main Server which points to my computer. We chose port forwarding port 5555.
To ensure my computer is accessible to outsiders on the Internet, we set the Firewall to allow network communication both public and private for apps such as node.exe and Evented I/O for V8 Javascript.
And to test that the computer is globally accessible, we tried access "http://exampleSite.com:5555/". The result is we can access the index.html and other files that resides in XAMPP's htdocs directory in my computer correctly.
To test WebSocket, we run our Node.js WebSocket server. Then we open our http://exampleSite.com:5555/TestWebsocket_client/ , our HTML5 site runs correctly, but then when we try to connect to the Node.js WebSocket, we got the error:
WebSocket connection to 'ws://exampleSite.com:5555/' failed: Error
during WebSocket handshake: Unexpected response code: 302
Codes
For the client side code, it is actually Construct 2 exported HTML5. We are using exactly 3 lines of same codes at https://youtu.be/hv9KdklXZqE?t=6m45s
For the server side code, the same code is also from the video above at https://youtu.be/hv9KdklXZqE?t=7m7s
We have verified in our localhost environment just like in the video that the client C2 side can connect to our Node.js server without any problem.
How to connect to the Node.js WebSocket Server in this case?

Bypassing socket connections in node.js

I'm working in a project where we need to connect clients to devices behind LAN networks.
Brief description: there are "devices" connected, in a home for example, under a LAN created by a router. These devices create a full webserver, operating under linux, and using nodejs as the backend implementation language. They also have access to Internet, through the public IP of the router. On the other side, there are clients which can choose to which device to connect to.
The goal is to connect the clients with the webServer created by any device.
Up to now, my idea is to try to implement something similar to how TeamViewer works. As I understand, Teamviewer has a central server, which the agents connect to. When an agent connects to the central server, this one gets hold of the TCP connection, keeping it alive. When another client wants to access to the first client, the server bypasses both TCP connections. That way the server acts like a proxy, where it additionally routes the TCP connections. This also allows to connect to clients under LAN or firewalls (because the connections are created always from the clients).
If this is correct, what I would like to implement is a central server, in nodejs as well, which manages a pool of socket connections coming from the different active devices, and when a client wants to connect to one specific device, the server bypasses the incoming TCP connection of the client with the already existing connection of the device.
What I first would like to know is if this is possible in nodejs. My idea is to keep the device connections alive, so clients can inmediately connect to them, creating some sort of pool of device connections.
If implemented in C, I guess I could get hold of the socket descriptor, keeping it alive, and bypassing it to the incoming client request. But in nodejs I can't seem to find any modules that manage TCP connections.
Are there any high level npm packages which do this function? Else, is it possible to use lower level modules (like net) which have those functionalities.
Ideally I would like to implement it with high level modules (express), but if it's not possible, I could always rewrite the server using low level modules.
Thanks in advance

adding lan support in a HTML5 game using javascript

i want to add lan support to tic-tac-toe game which is a HTML5 canvas based, so that two players can easily play. how can i do it using javascript/node.js?
OK, I'm assuming all of your HTML5 game is finished and you're distributing it with the server that hosts it. (Otherwise you're stuck to just the browser, which can't do all the awesome node.js net stuff, I am describing.)
NB: You need to have node.js running on both clients. Otherwise you can't do LAN-only without a central server's involvement.
One of your clients has decided they want to host a LAN game
The node.js server running on that client starts to listen on a port
That server find out its local IP Get local IP address in node.js
Options:
Your players can manually tell each other the IP of the hosting server
Your hosting server sends out broadcast messages to its local subnet, informing them that it's hosting a game
Your other client server scans for IPs in its local subnet to find any hosting gameservers (Tries to open the pre-determined port your hosting server is listening on.)
The other node.js client opens a connection to the hosting server.
Done.

Resources