Share files securely peer to peer with WEBRTC
Tags: webrtc, webdev, javascript, node
Published: 2021-12-23 15:39:42

Hello fellow developers, Have you ever wonder if you can share file without a server directly to another peer and realtime? Yes you can and here Ι will show you how to do it.

All code from this tutorial as a complete package is available in GitHub in [this repository](https://github.com/tzagiollari/share_file_securely_peer_to_peer_with_WEBRTC)


**The server**
Oh ok this is awkward, I just said before "without server" but you need a server just for signaling. How the other peer will find your computer among billion of devices in the internet?

Initialize a new node.js project:
`npm init`

Install express:
`npm install --save express`

Install socket.io for signaling:
`npm install --save socket.io`

Install ejs for server side rendering:
`npm install --save ejs`

Server code: server.js
This is the simplest server for signaling in order to connect max two peers and one view:
{% gist https://gist.github.com/EneasLari/120953281a9afbfa315c732001aba6ad file=server.js %}

**Code explanation**

- At line 12 we use express and ejs to render a simple html page that will help us to make the UI for the file sharing.

- At line 16 a http server is created and is set to listen to port 3000 or the port defined by a PORT environment variable at line 18

- At line 20 a new instance of socket.io is initialized and we pass http server as a parameter.

- At line 22 we listen at the connection event where we have defined all our other events that occur after connection.

- `function log()` is a function that emits to the client who sent  the message a log event and some message that are defined in the arguments as an array  

Lets talk about sockets events that are defined inside our server code.

- `create or join` when the server receives this event from the client initially at line 44 it gets the number of clients in room.
and stores it in var clientsInRoom, if this variable is null then we define the numClients as zero otherwise we set it as the clientsInRoom. At line 49 if the clients who sends the message is the first then we emit the `created` event to the client otherwise at line 54 if is the second who sends this message we send `join` to the first client, we join the second client and a `joined` event is sent to the second client that just joined the room.
At the end the two clients will receive `ready` event.
If anyone else except these two clients send other `create or join event` he will receive a `full` event.

- `ipaddr` event is for signaling webRTC

For the client your will need a config.js file which contains a json object for STUN/TURN server. I will not explain in details what is this for in this article but it is necessary to help two clients to exchange their public IP Adresses.
The gist above is not correct for security reasons but you can create your own config object at [xirsys](https://xirsys.com/ )

{% gist https://gist.github.com/EneasLari/120953281a9afbfa315c732001aba6ad file=config.js %} 

Client code for establishing a peer connection:
{% gist https://gist.github.com/EneasLari/120953281a9afbfa315c732001aba6ad file=main.js %}

And the html page:
{% gist https://gist.github.com/EneasLari/120953281a9afbfa315c732001aba6ad file=index.ejs %}

If you run the server as it is with
`node server.js`

and visit

`http://localhost:3000/`

you will see in the debug window in browser:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ez9pjj760083l9he7p3a.png)
 
If you open a second window and add the same room name you will see through console that an peer connection is established

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y5yrsk4lzw8n8qmktgqh.png)

After connection: 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4zxiopfc9x4pfoyavmtp.png)
 
**Datachannel on peer connection**
Now we are ready to create the datachannel for file trasfer
And then send the file to the other peer when the user clicks the send button.

The updated html:
{% gist https://gist.github.com/EneasLari/120953281a9afbfa315c732001aba6ad file=indexfinal.ejs %}

and finally the updated javascript file:
{% gist https://gist.github.com/EneasLari/120953281a9afbfa315c732001aba6ad file=mainfinal.js %}

Complete working project:
GitHub repo: [link](https://github.com/tzagiollari/share_file_securely_peer_to_peer_with_WEBRTC)

Any comments or corrections are welcome and appreciated!

Thank you for reading!