Simple Peer-to-Peer protocol implementation in pure Go. Uses HTTP client and server to communicate over internet to knowed network members.
go get github.com/lucasmenendez/gop2p@latest
- Checkout GoDoc Documentation.
- Also, it is available a simple example that implments a CLI Chat here.
The main component to use gop2p is the node.Node
struct, that contains:
- Required parameters to handle messages/errors, and connect/disconnect a
node.Node
:
type Node struct {
Self *peer.Peer // information about current node
Members *peer.Members // thread-safe list of peers on the network
Inbox chan *message.Message // readable channels to receive messages
Error chan error // readable channels to receive errors
Connection chan *peer.Peer // writtable channel to connect to a Peer
Outbox chan *message.Message // writtable channel to send messages
// ...
}
- Required functions to create, start and stop a
node.Node
:
func New(self *peer.Peer) *Node {
// ...
}
func (node *Node) Start() {
// ...
}
func (node *Node) Stop() error {
// ...
}
To start a new node.Node
ad be able to send and receive messages (message.Message
) is required to instance a new peer.Peer
with the network information (host IP address and port to listen requests).
Show a code example
package main
import (
"log"
"github.com/lucasmenendez/gop2p/pkg/node"
"github.com/lucasmenendez/gop2p/pkg/message"
"github.com/lucasmenendez/gop2p/pkg/peer"
)
func main() {
// Instance a new peer that identifies the current node
self, _ := peer.Me(5001, false)
// [FOR REMOTE CLIENT] self, _ := peer.Me(5001, true)
// Create a new node with the self peer defined
client := node.New(self)
// Start listening to be able to send and receive messages
client.Start()
//...
}
To connect to a network you must know the peer.Peer
information of an entrypoint. Use node.Node.Connection
channel to connect to it, the node.Node.Inbox
channel to listen for messages and the node.Node.Error
channel to listen for errors.
Show a code example
package main
import (
"log"
"github.com/lucasmenendez/gop2p/pkg/node"
"github.com/lucasmenendez/gop2p/pkg/message"
"github.com/lucasmenendez/gop2p/pkg/peer"
)
func main() {
// ...
// Create an entry point peer
entryPoint, _ := peer.Me(5000, false)
// [REMOTE ENTRYPOINT] entryPoint, _ := peer.New("192.68.1.43", 5000)
// Connection to the defined entry point peer usign the Connect channel
client.Connection <- entryPoint
// Print incoming messages and errors. Every incoming message is populated
// through Node.Inbox, and every error channel that occurs trough Node.Error
// channel
logger := log.New(os.Stdout, "", 0)
go func(logger *log.Logger) {
for {
select {
case msg := <-client.Inbox:
logger.Printf("[%s] -> %s\n", msg.From.String(), string(msg.Data))
case err := <-client.Error:
logger.Fatalln(err)
}
}
}(logger)
// ...
}
To broadcast data to the network it must be wrapped using message.Message
and the result must be sended using the node.Outbox
channel.
Show a code example
package main
import (
"log"
"github.com/lucasmenendez/gop2p/pkg/node"
"github.com/lucasmenendez/gop2p/pkg/message"
"github.com/lucasmenendez/gop2p/pkg/peer"
)
func main() {
// ...
// Create a []byte message
data := []byte("Hello network!")
// Create a message with Node.Self information as sender and the created
// data
msg := new(message.Message).SetFrom(client.Self).SetData(data)
// Broadcast the message to the network putting it into the Node.Outbox
// channel
client.Outbox <- msg
// ...
}
To send data to a single peer network, it must be wrapped using message.Message
and its Message.SetTo
function, and the result must be sended using the node.Outbox
channel.
Show a code example
package main
import (
"log"
"github.com/lucasmenendez/gop2p/pkg/node"
"github.com/lucasmenendez/gop2p/pkg/message"
"github.com/lucasmenendez/gop2p/pkg/peer"
)
func main() {
// ...
// Create a []byte message
data := []byte("Hello network!")
// Create a message with Node.Self information as sender, the created data
// and de intended peer.
msg := new(message.Message).SetFrom(client.Self).SetData(data).SetTo(entryPoint)
// Send the message to defined peer putting it into the Node.Outbox channel
client.Outbox <- msg
// ...
}
To disconnect from the current network (if the client is already connected to one), the node.Connection
channel must be closed. The client node.Node
broadcast a disconnection request to every network pee.Peer
. The node.Node
associated to every pee.Peer
, updates its current network member list unregistering the current pee.Peer
. At this moment, the current node.Node
could connect to other network in any moment (see step 2).
Show a code example
package main
import (
"log"
"github.com/lucasmenendez/gop2p/pkg/node"
"github.com/lucasmenendez/gop2p/pkg/message"
"github.com/lucasmenendez/gop2p/pkg/peer"
)
func main() {
// ...
// Close the Node.Connection channel to disconnect from the network
close(client.Connection)
// ...
}
To stop the current node.Node
the function node.Stop
must be executed. This will also disconnect the current node.Node
from a network, if it is connected. The function close every channel, stops the HTTP server to stop listening for other peer.Peer
s requests and stop waiting indifinitely.
Show a code example
package main
import (
"log"
"github.com/lucasmenendez/gop2p/pkg/node"
"github.com/lucasmenendez/gop2p/pkg/message"
"github.com/lucasmenendez/gop2p/pkg/peer"
)
func main() {
// ...
// Stop the Node
if err := client.Stop(); err != {
logger.Fatalln(err)
}
}
gop2p implements the following functional workflow:
sequenceDiagram
participant Client (Node)
participant Network entrypoint (Node)
participant Network peers (Node)
Note over Client (Node): 1. Start the node
Client (Node) ->> Client (Node): Create and start the client node
Note over Client (Node),Network entrypoint (Node): 2. Connect to the network
Client (Node) ->> Network entrypoint (Node): Send request to known entrypoint (address, port)
Network entrypoint (Node) -->> Network entrypoint (Node): Register a new member
Network entrypoint (Node) -->> Client (Node): Response with the current list of network members
Client (Node) -->> Client (Node): Register all the received members
Client (Node) ->> Network peers (Node): Send connection request
Network peers (Node) -->> Network peers (Node): Register Client as new member
Note over Client (Node),Network peers (Node): 3. Broadcast message
Client (Node) -->> Client (Node): Create the message
Client (Node) ->> Network peers (Node): Broadcast message request to current network Node's
Network peers (Node) -->> Network peers (Node): Handle received Client message
Note over Client (Node),Network peers (Node): 4. Disconnect from the network
Client (Node) -->> Client (Node): Create the disconnect request
Client (Node) ->> Network peers (Node): Broadcast disconnect request to current network Node's
Network peers (Node) -->> Network peers (Node): Unregister Client from current Node's network
Note over Client (Node): 5. Stop the node
Client (Node) ->> Client (Node): Stop the client node