Facebook Linkedin Twitter
Posted Wed Dec 22, 2021 •  Reading time: 4 minutes

Designing a Very Dumb p2p Network That Could Do Anything

Well I have seen a lot of fancy p2p networks with very fancy features such as quick look-ups using DHTs (Distributed Hash Tables). The only problem is noobs like me would just like to connect to a friend’s machine or a machine close by and run anything on it. It’s really as simple as that :).

Introducing P2PRC (A p2p network that should hopefully run anything)

The main aim of this project was to create a custom peer to peer network. The user acting as the client has total flexibility on how to batch the tasks and the user acting as the server has complete flexibility on tracking the containers usages and killing the containers at any point of time.

Challenges this project is solving:

  • Prioritising IPV6 over IPV4 address.
  • Preference of using nodes close by.
  • Self learning by traversing through the network.
  • Lighter version of container orchestration.
  • Focuses on making users focus on the instructions to execute rather than the virtualization itself.

Projects new keyword:

IPTable: A JSON file which stores information about nodes acting as servers in the network

Implementation

The programming language used for this project was Golang. The reason Go lang was chosen was because it is a compiled language. The entire codebase is just a single binary file. When distributing to other linux distributing the only requirement would be the binary file to run the code. It is easy to write independent modules and be monolithic at the sametime using Go. Using go.mod makes it very easy to handle external libraries and modularise code. The go.mod name for the project is git.sr.ht/~akilan1999/p2p-rendering-computation. The following subheadings are the important modules of P2PRC:

Read more

Server Module

The server module takes care of setting and removing the virtualization environment (i.e. containers) for accessing and doing the appropriate computation. It also interacts with the p2p module to update the IP table on the server-side. The server module accesses information regarding CPU and GPU specifications of the machine running the server module. To do speed tests the server has routes that allow it to upload and download a 50 MB file.

Read more

P2P module

The P2P module (i.e. Peer to Peer Module) is responsible for storing the IP table and interacting with the IP table. In the following implementation of the P2P module , the IP table stores information about servers available in the network. The other functionality the P2P module takes care of is doing the appropriate speed tests to the servers in the IP table. This is for informing the users about nodes that are close by and nodes that have quicker uploads and downloads speeds. The module is responsible to ensure that there are no duplicate server IPs in the IP table and to remove all server IPs which are not pingable.

Read more

Client Module

The client module interacts with the P2P module and Server Module. It is responsible for interacting with the server module and appropriately updating the IP table on the client-side. It connects to the server using the server’s REST APIs. It is also the primary decision maker on how the IP table is updated is on the client side. This is because each user can have requirements like how many number of hops they would want to do to update their IP table. Hops is the number of times the client is going to download the IP table from different servers ,once it gets the IP tables from the previous servers.

Read more

Plugin module

The plugin module is designed to ensure clients can execute instructions in a declarative manner across different containers created. This means the user (i.e. client) needs to write the instruction only once, and these instructions can be executed across different nodes in a repetitive manner. The plugin module currently uses Ansible to execute tasks in a declarative manner.

Ex: The following example is a VSCode server plugin built as a plugin for P2PRC Repo Link: https://github.com/Akilan1999/p2prc-vscode-browser

---

- hosts: all

  tasks:
    - name: apt install curl
      apt:
        name: curl
        state: present
    - name: setup vscode code server
      shell: "curl -fsSL https://code-server.dev/install.sh | sh"
      become: true
      become_user: root
    - name: start vscode code server
      shell: code-server --auth none --bind-addr 0.0.0.0:{{index . 0}}
      async: 2592000               # 60*60*24*30 – 1 month (This will keep the following command running for a month
      poll: 0

Read more

Usage

Below are the basic CLI commands that are implemented in P2PRC. The whole point is to ensure that running the network is straight forward and easy to use.

  1. To run as server mode:

    p2prc -s 
    

    This would ensure that you are running in the server mode. The default port used in 8088.

  2. Update the IP table

    p2prc --us 
    

    The following command would traverse the network and update the IP table based on new servers discovered in the network.

  3. List Servers

    p2prc --ls 
    

    output:

    IP Address: 2.49.230.232
    IPV6: 
    Latency: 28.172471ms
    ServerPort: 8088
    ----------------------------
    
    IP Address: 139.162.246.221
    IPV6: 
    Latency: 39.256396ms
    ServerPort: 8088
    ----------------------------
    
  4. Spin up containers on a server

    p2prc --touch <server ip address> --ports <number of TCP ports> --GPU
    

    output:

      {
         "SSHUsername": "master",
         "SSHPassword": "password",
         "ID": "01a1844f49f6c83739f69123918c6c876a4a9f90c6f2828b78f30398d5c99fcd",
         "TagName": "p2p-ubuntu",
         "ImagePath": "/home/akilan/Documents/akilan/p2p-rendering-computation/server/docker/containers/docker-ubuntu-sshd/",
         "Ports": {
                 "Port": [
    
                   "PortName": "SSH",
                                 "InternalPort": 22,
                                 "Type": "tcp",
                                 "ExternalPort": 40755,
                                 "IsUsed": true,
                                 "Description": "SSH Port"
                         },
                         {
                                 "PortName": "AutoGen Port",
                                 "InternalPort": 44607,
                                 "Type": "tcp",
                                 "ExternalPort": 44607,
                                 "IsUsed": false,
                                 "Description": "Auto generated TCP port"
                         }
                 ]
         },
         "GPU": "true"
    }
    

Read more on usage

Future work

  • Using UDT with UDP hole punching to escape NAT/Firewalls
  • Adding support for UPNP
  • Creating an interface for virtualization
  • Research on extending P2PRC for running High Performance games using WebRTC.

How to get involved with the project:

Gophercon Poland talk 2021