1.0.13 • Published 6 years ago

xp2pservice v1.0.13

Weekly downloads
3
License
BSD-3-Clause
Repository
-
Last release
6 years ago

# WindRibbon P2P Service (XP2PService)

Introduction

A peer-to-peer(P2P) UDP forwarder based on WebRTC technologies (especially RTCPeerConnection and RTCDataChannel).

Requirements

Here is the software requirement:

PackageVersion
NodeJS>= 8.7.0
node-pre-gypNot specified
node-cmakeNot specified

And you have to also WebRTC related terminologies before using this software package.

Installation

To install this program, type following command:

npm install xp2pservice -g

After installation, you can run xudpforwarder in your terminal, like (replace "server.json" and "client.json" with the path of your own configuration files):

xp2pservice-server --log-level=info --configuration server.json
xp2pservice-client --log-level=info --configuration client.json

Architecture

WebRTC gave us the ability to establish peer-to-peer (P2P) connection between two network points, so this software package is just an application of WebRTC and related protocols.

As we know, to establish a P2P connection by using WebRTC, you have to do signaling (exchange SDP and ICE candidates). In this package, we implemented this part with a carefully-designed protocol based on TCP (called "Control Channel"). The only work you have to do is to let the client-side software connect to the TCP port of the server-side software, and then they will do handshaking and establish the P2P connection aside of the TCP connection. There are many ways to let them connect (like VPN or some kinds of TCP forwarder/relay).

However, to use this software, you must have a full WebRTC server stack (including STUN/TURN server). Our recommendation is coturn, which you can implement your own logic easilly.

Hooks

Hooks is used to notify other applications some information about this program. Generally, hooks is a set of scripts that can handle certain parameters.

"ready" hook.

Once the program was ready to accept new connections (or incoming datagrams), this hook will be executed. We will bypass two parameters to this hook - the bind address and bind port.

Here is the template of this hook:

#!/bin/sh

#  Read bind information.
BIND_ADDR="$1"
BIND_PORT="$2"

#  TODO: Run your own logic here.
#  ...

exit 0

Configuration

Here is the template of client-side configuration:

{
    "socket": {
        "local": {
            "type": "udp4",                       //  Local socket type ("udp4" for IPv4, "udp6" for IPv6).
            "bind": {
                "address": "0.0.0.0",             //  Local address to listen to.
                "port": 2800                      //  Local port to listen to.
            },
            "ttl": 64,                            //  TTL of outgoing datagrams (optional, default: 64).
            "reuse": true,                        //  SO_REUSEADDR option (optional, default: true).
            "buffer": {
                "receive": 8388608,               //  SO_RCVBUF option (optional, default: not set).
                "send": 8388608                   //  SO_SNDBUF option (optional, default: not set).
            }
        },
        "remote": {
            "destination": {
                "address": "127.0.0.1",           //  Control channel (TCP) address.
                "port": 7500                      //  Control channel (TCP) port.
            },
            "timeout": 60000,                     //  Timeout of the socket (optional, default: not set).
            "keep-alive": true,                   //  SO_KEEPALIVE option (optional, default: true).
            "no-delay": true,                     //  TCP_NODELAY option (optional, default: true).
            "heartbeat": {
                "interval": 5000                  //  Interval between two heartbeat messages (unit: milliseconds).
            },
            "buffer": {
                "incoming": 524288,               //  TCP receive buffer (optional, unit: bytes, default: 512KB).
                "outgoing": 524288                //  TCP send buffer (optional, unit: bytes, default: 512KB).
            },
            "proxy": {
                "enable": false,                  //  Proxy enable switch.
                "address": "proxy-server.p2p-service.org",
                                                  //  (Required when proxy was enabled) Address of the proxy server.
                "port": 1080,                     //  (Required when proxy was enabled) Port of the proxy server.
                "type": "SOCKS5",                 //  (Required when proxy was enabled) Type of the proxy server ("SOCKS5" or "SOCKSv4a").
                "timeout": 30000,                 //  (Optional) The proxy connect timeout.
                "credential": {
                    "enable": false,              //  (Optional) Proxy credential enable switch.
                    "user": "-",                  //  (Required when proxy credential was enabled) The user name.
                    "password": "-"               //  (Required when proxy credential was enabled) The password.
                }
            }
        }
    },
    "p2p": {
        "session": {
            "max-count": null,                    //  Maximum session count (optional, default: not set).
            "timeout": 720000,                    //  Session timeout (optional, default: not set).
            "queue": {
                "incoming": {
                    "max-size": null,             //  Maximum size of the incoming queue of each session (optional, unit: bytes, default: not limited).
                    "max-count": null,            //  Maximum datagram count of the incoming queue of each session (optional, unit: datagrams, default: not limited).
                    "max-time": null              //  Maximum datagram alive time of the incoming queue of each session (optional, unit: milliseconds, default: not limited).
                },
                "outgoing": {
                    "max-size": null,             //  Maximum size of the outgoing queue of each session (optional, unit: bytes, default: not limited).
                    "max-count": null,            //  Maximum datagram count of the incoming queue of each session (optional, unit: datagrams, default: not limited).
                    "max-time": null              //  Maximum datagram alive time of the incoming queue of each session (optional, unit: milliseconds, default: not limited).
                }
            }
        },
        "webrtc": {
            "peer-settings": {                    //  Used by RTCPeerConnection() constructor, see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/RTCPeerConnection#RTCConfiguration_dictionary
                "iceServers": [
                    {
                        "urls": "stun:stun.l.google.com:19302"
                    }
                ]
            },
            "channel-name": "windribbon-p2p",     //  The name of the data channel.
            "channel-settings": {                 //  The configuration of the data channel. Used by createDataChannel(), see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createDataChannel
                "ordered": false,
                "maxRetransmits": 0
            },
            "candidate": {
                "blacklist": [                    //  Blocked candidate IPs, use CIDR-format only.
                    "10.8.0.0/16"                 //  In this case, the subnet "10.8.0.0/16" can't be used for establishing P2P connection.
                ]
            }
        }
    },
    "hooks": {                                    //  (Optional) The hooks.
        "ready": {                                //  (Optional) The "ready" hook.
            "cwd": ".",                           //  The working directory of the "ready" hook.
            "command": "scripts/ready.sh"         //  The command of the "ready" hook.
        }
    }
}

Here is the template of server-side configuration:

{
    "webrtc": {
        "peer-settings": {                    //  Used by RTCPeerConnection() constructor, see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/RTCPeerConnection#RTCConfiguration_dictionary
            "iceServers": [
                {
                    "urls": "stun:stun.l.google.com:19302"
                }
            ]
        },
        "channel-name": "windribbon-p2p",     //  The name of the data channel.
        "channel-settings": {                 //  The configuration of the data channel. Used by createDataChannel(), see https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/createDataChannel
            "ordered": false,
            "maxRetransmits": 0
        },
        "candidate": {
            "blacklist": [                    //  Blocked candidate IPs, use CIDR-format only.
                "10.8.0.0/16"                 //  In this case, the subnet "10.8.0.0/16" can't be used for establishing P2P connection.
            ]
        }
    },
    "socket": {
        "local": {
            "bind": {
                "address": "0.0.0.0",         //  Server address of the control channel (TCP).
                "port": 7500                  //  Server port of the control channel (TCP).
            },
            "timeout": 60000,                 //  Timeout of the socket (optional, default: not set).
            "keep-alive": true,               //  SO_KEEPALIVE option (optional, default: true).
            "no-delay": true                  //  TCP_NODELAY option (optional, default: true).
        },
        "remote": {                           //  Remote socket is used to send datagrams from the peer to the destination.
            "type": "udp4",                   //  Remote socket type ("udp4" for IPv4, "udp6" for IPv6).
            "bind": {
                "address": "0.0.0.0"          //  Remote socket bind address.
            },
            "ttl": 64,                        //  TTL of outgoing datagrams (optional, default: 64).
            "reuse": true,                    //  SO_REUSEADDR option (optional, default: true).
            "buffer": {
                "receive": 8388608,           //  SO_RCVBUF option (optional, default: not set).
                "send": 8388608               //  SO_SNDBUF option (optional, default: not set).
            }
        }
    },
    "buffer": {
        "incoming": 524288,                   //  TCP receive buffer (optional, unit: bytes, default: 512KB).
        "outgoing": 524288                    //  TCP send buffer (optional, unit: bytes, default: 512KB).
    },
    "destination": {
        "address": "127.0.0.1",               //  The destination address.
        "port": 2801                          //  The destination port.
    },
    "hooks": {                                //  (Optional) The hooks.
        "ready": {                            //  (Optional) The "ready" hook.
            "cwd": ".",                       //  The working directory of the "ready" hook.
            "command": "scripts/ready.sh"     //  The command of the "ready" hook.
        }
    }
}

See "examples" directory for more example configurations.

As a library

You can use this program as a library and imports it in your program.

To import this program(library), use following statement:

var XP2PService = require("xp2pservice");

And then, you can call the entry point of the client or the server and pass arguments to them, like:

XP2PService.ClientMain(["-c", "[Path of your client configuration.]"]);
XP2PService.ServerMain(["-c", "[Path of your server configuration.]"]);