A real time peer to peer video calling application, provided as a service. Approach, Working and Installation steps mentioned below.
- Implementation Approach
- Setting up project locally
- Running on Cloud
- Monitoring using Process Manager
- Architecture
- Limitations and Future Work
-
Former Approach
-
This approach involved a server acting as a middleware for connecting and passing data between 2 peers. The communication takes place using sockets and connection details are stored at server.
-
Forces the data to pass through server (peer -> server -> peer).
-
Additional security required on top of sockets.
-
Increased latency and encoding/decoding of media stream required at peer.
-
-
New Approach
-
Using Peer to Peer (P2P) communication paradigm between 2 clients (browsers).
-
WebRTC (Web Real time communication) standard. More details can be found here and here.
-
Only signalling server used as middleware for connecting 2 peers.
-
This leads to low latency and delay as compared to previous case.
-
Datagram transport layer security provided for data streams (by WebRTC).
-
Specific format for media streams.
-
The communication between peer and server takes place through WebSockets.
-
The application runs 2 servers, the HTTP Server used for setting up the routes and the WebSocket Server for communicating with the peers. Following messaging format is followed for communicating using websockets.
{
"type": TYPE_OF_MESSAGE,
"id": YOUR_ID
"clientId": PEER_ID
}
The message also includes some other parameters as per request. The connection variables and client IDs are stored at server. This messaging format allows us to implement multi-tenency upto certain extent and helps to use common functions (listners) for peers (callers and callee). We used Hoppscotch for testing websockets.
The WebRTC architechture used for real time peer to peer data exchange is given below.
The communication flow for generating and accepting the call is given below.
- Each Peer has a
RTCPeerConnection
instance which can be used to get the session descriptions. The caller sends avideo-offer-request
along with session description, which is forwarded to corresponsing callee by server. The callee accepts/rejects the call, sets the session description and returns the response to caller. If callee has accepted the call, media transfer by usinggetUserMedia()
starts between 2 clients.
This project is created using npm
version 6.14.8 and Node.js
version 10.19.0
Running the project
-
git clone
-
cd video-calling && npm install
-
npm start
starts the server -
Visit
localhost:5000
If the app doesn't work on normal mode, try running in incognito.
Once you finish setting up, the folder structure will be as follows
video-calling/
README.md
node_modules/
package.json
package-lock.json
video-calling-app.conf
index.js
public/
index.html
scripts/
client.js
styles
styles.css
For project to build, these files must exist with exact filenames:
public/index.html
is the page template;index.js
is the JavaScript entry point.
-
This project was hosted on Google Cloud Compute Engine under a virtual machine instance with following configurations.
- Guest OS: Ubuntu 18.04
- Number of virtual cpus: 2
- Memory: 4 GB
- Disk Space: 10 GB
- Allowed for HTTP Traffic
-
Detailed steps for setting up project and pricing are available here and here respectively.
-
Make sure that you have a billing account and compute engine service enabled in your google cloud console.
-
Follow these steps to replicate.
-
SSH into your virtual machine.
-
Install nginx web proxy server using
sudo apt update
andsudo apt install nginx
. More details about nginx webserver can be found here. -
Adjusting the firewall using
ufw
utility. More details about ufw can be found here.sudo ufw app list
- Output
Available Applications:- Nginx Full
- Nginx HTTP
- Nginx HTTPS
- OpenSSH
- If you've your SSL configured, enable Nginx HTTPS else enable Nginx HTTP
sudo ufw allow 'Nginx HTTP'
sudo ufw allow 'OpenSSH'
sudo ufw allow ssh
sudo ufw logging on
sudo ufw enable
- Verify by checking
sudo ufw status
-
Check if your Nginx webserver is running by
systemctl status nginx
command and go to web browser and typehttp://your_server_ip
. This should load the default Nginx Welcome page. -
Now, you need to setup the server blocks which includes the configuration details. You can either make a new file in
conf.d
directory or insites-available
directory located in/etc/nginx/
- If you create a file in
conf.d
, make sure that your file is named<YOUR_DOMAIN>.conf
. - If you create a file in
sites-available
, once configuration is done, create a link from this file tosites-enabled
directory, which Nginx reads during startup using below commandsudo ln -s /etc/nginx/sites-available/<YOUR_DOMAIN> /etc/nginx/sites-enabled/
The configuration file is as follows
server { listen 80; listen [::]:80; server_name EXTERNAL_IP OR DOMAIN_NAME; location / { proxy_pass http://localhost:5000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } location /socket { proxy_pass http://localhost:5000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } }
Replace the term
EXTERNAL_IP / DOMAIN NAME
with your public IP (given in cloud console) or domain name. This setups a reverse proxy which maps the requests from external IP to localhost. The HTTP server listens on/
route and the Websocket Server listens on/socket
route. Hence on the client side, the websocket connection url is given as:ws://<IP/DOMAIN_NAME>:80/socket
. - If you create a file in
-
Make sure there is no syntax errors with your config files by
sudo nginx -t
. -
If all issues are resolved, restart the webserver using
sudo systemctl restart nginx
. -
Now, follow the steps for setting up the project locally and setup the project in the virtual machine and run the app using
npm start
. -
If you haven't configures SSL certificate, you need to explicitly enable
unsafely-treat-insecure-origin-as-secure
flag and mention thePublic IP or DOMAIN NAME
in your browser. If SSL is configured, no need to set the flag. -
If everything was configured properly, the app would work on hitting public IP of virtual machine on browser.
Find the detailed guide to configure nginx and host your node.js application here and here respectively.
- Process Manager 2 can be used to monitor production level Node.js applications and reload on crash with minimum downtime.
- It can be configured using
sudo npm install pm2@latest -g
and start the application usingpm2 start video-calling/index.js
. Further info on it can be found here. - The following image shows the monitoring process through PM2.
The architecture is given below
-
Short lived websocket connections.
- According to the property of websockets, the connections should be long lived but the connections keep closing after few minutes of usage and hence user needs to regenerate ID for further use. Also, the client is now aware of the connection closing.
-
Single server instance and data (connections + ids) are stored on server in an array. No database or storage is configured yet. Hence, multiple instances can't be used until that.