mirror of
https://github.com/arnaucube/bc.git
synced 2026-02-07 02:56:42 +01:00
first commit
This commit is contained in:
81
peer/p2plib/connections.go
Normal file
81
peer/p2plib/connections.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package p2plib
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
func (tp *ThisPeer) AcceptPeers(peer Peer) {
|
||||
fmt.Println("accepting peers at: " + peer.Port)
|
||||
l, err := net.Listen("tcp", peer.IP+":"+peer.Port)
|
||||
if err != nil {
|
||||
log.Println("Error accepting peers. Listening port: " + peer.Port)
|
||||
tp.Running = false
|
||||
}
|
||||
for tp.Running {
|
||||
conn, err := l.Accept()
|
||||
if err != nil {
|
||||
log.Println("Error accepting peers. Error accepting connection")
|
||||
tp.Running = false
|
||||
}
|
||||
var newPeer Peer
|
||||
newPeer.IP = GetIPFromConn(conn)
|
||||
newPeer.Port = GetPortFromConn(conn)
|
||||
newPeer.Conn = conn
|
||||
globalTP.PeersConnections.Incoming = AppendPeerIfNoExist(globalTP.PeersConnections.Incoming, newPeer)
|
||||
go HandleConn(conn, newPeer)
|
||||
}
|
||||
}
|
||||
func ConnectToPeer(peer Peer) {
|
||||
color.Green("connecting to new peer")
|
||||
log.Println("Connecting to new peer: " + peer.IP + ":" + peer.Port)
|
||||
conn, err := net.Dial("tcp", peer.IP+":"+peer.Port)
|
||||
if err != nil {
|
||||
log.Println("Error connecting to: " + peer.IP + ":" + peer.Port)
|
||||
return
|
||||
}
|
||||
peer.Conn = conn
|
||||
globalTP.PeersConnections.Outcoming = AppendPeerIfNoExist(globalTP.PeersConnections.Outcoming, peer)
|
||||
go HandleConn(conn, peer)
|
||||
}
|
||||
func HandleConn(conn net.Conn, connPeer Peer) {
|
||||
connRunning := true
|
||||
log.Println("handling conn: " + conn.RemoteAddr().String())
|
||||
//reply to the conn, send the peerList
|
||||
var msg Msg
|
||||
msg.Construct("PeersList", "here my outcomingPeersList")
|
||||
msg.PeersList = globalTP.PeersConnections.Outcoming
|
||||
msgB := msg.ToBytes()
|
||||
_, err := conn.Write(msgB)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
for connRunning {
|
||||
/*
|
||||
buffer := make([]byte, 1024)
|
||||
bytesRead, err := conn.Read(buffer)
|
||||
*/
|
||||
newmsg, err := bufio.NewReader(conn).ReadString('\n')
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
connRunning = false
|
||||
} else {
|
||||
var msg Msg
|
||||
//msg = msg.createFromBytes([]byte(string(buffer[0:bytesRead])))
|
||||
msg = msg.CreateFromBytes([]byte(newmsg))
|
||||
MessageHandler(connPeer, msg)
|
||||
}
|
||||
}
|
||||
//TODO add that if the peer closed is the p2p server, show a warning message at the peer
|
||||
log.Println("Peer: " + conn.RemoteAddr().String() + " connection closed")
|
||||
conn.Close()
|
||||
//TODO delete the peer from the outcomingPeersList --> DONE
|
||||
DeletePeerFromPeersList(connPeer, &globalTP.PeersConnections.Outcoming)
|
||||
/*color.Yellow("peer deleted, current peerList:")
|
||||
PrintPeersList()*/
|
||||
}
|
||||
15
peer/p2plib/errors.go
Normal file
15
peer/p2plib/errors.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package p2plib
|
||||
|
||||
import (
|
||||
"log"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func check(err error) {
|
||||
if err != nil {
|
||||
_, fn, line, _ := runtime.Caller(1)
|
||||
log.Println(line)
|
||||
log.Println(fn)
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
43
peer/p2plib/init.go
Normal file
43
peer/p2plib/init.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package p2plib
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
func InitializePeer(role, ip, port, restport, serverip, serverport string) ThisPeer {
|
||||
//initialize some vars
|
||||
rand.Seed(time.Now().Unix())
|
||||
|
||||
var tp ThisPeer
|
||||
tp.Running = true
|
||||
tp.RunningPeer.Role = role
|
||||
tp.RunningPeer.Port = port
|
||||
tp.RunningPeer.RESTPort = restport
|
||||
tp.RunningPeer.ID = HashPeer(tp.RunningPeer)
|
||||
|
||||
tp.ID = tp.RunningPeer.ID
|
||||
globalTP.PeersConnections.Outcoming.PeerID = tp.RunningPeer.ID
|
||||
fmt.Println(tp.RunningPeer)
|
||||
//outcomingPeersList.Peers = append(outcomingPeersList.Peers, peer.RunningPeer)
|
||||
globalTP.PeersConnections.Outcoming = AppendPeerIfNoExist(globalTP.PeersConnections.Outcoming, tp.RunningPeer)
|
||||
fmt.Println(globalTP.PeersConnections.Outcoming)
|
||||
|
||||
if tp.RunningPeer.Role == "server" {
|
||||
go tp.AcceptPeers(tp.RunningPeer)
|
||||
}
|
||||
if tp.RunningPeer.Role == "client" {
|
||||
var serverPeer Peer
|
||||
serverPeer.IP = serverip
|
||||
serverPeer.Port = serverport
|
||||
serverPeer.Role = "server"
|
||||
serverPeer.ID = HashPeer(serverPeer)
|
||||
go tp.AcceptPeers(tp.RunningPeer)
|
||||
ConnectToPeer(serverPeer)
|
||||
}
|
||||
globalTP = tp
|
||||
|
||||
return tp
|
||||
|
||||
}
|
||||
78
peer/p2plib/messages.go
Normal file
78
peer/p2plib/messages.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package p2plib
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
type Msg struct {
|
||||
Type string `json:"type"`
|
||||
Date time.Time `json:"date"`
|
||||
Content string `json:"content"`
|
||||
PeersList PeersList `json:"peerslist"`
|
||||
Data []byte `json:"data"`
|
||||
}
|
||||
|
||||
func MessageHandler(peer Peer, msg Msg) {
|
||||
|
||||
log.Println("[New msg]")
|
||||
log.Println(msg)
|
||||
|
||||
switch msg.Type {
|
||||
case "Hi":
|
||||
color.Yellow(msg.Type)
|
||||
color.Green(msg.Content)
|
||||
break
|
||||
case "PeersList":
|
||||
color.Blue("newPeerslist")
|
||||
fmt.Println(msg.PeersList)
|
||||
color.Red("PeersList")
|
||||
|
||||
UpdateNetworkPeersList(peer.Conn, msg.PeersList)
|
||||
PropagatePeersList(peer)
|
||||
PrintPeersList()
|
||||
break
|
||||
case "PeersList_Response":
|
||||
//for the moment is not beeing used
|
||||
color.Blue("newPeerslist, from PeersList_Response")
|
||||
fmt.Println(msg.PeersList)
|
||||
color.Red("PeersList_Response")
|
||||
|
||||
UpdateNetworkPeersList(peer.Conn, msg.PeersList)
|
||||
PropagatePeersList(peer)
|
||||
PrintPeersList()
|
||||
break
|
||||
case "Block":
|
||||
/*//TODO check if the block is signed by an autorized emitter
|
||||
if !blockchain.blockExists(msg.Block) {
|
||||
blockchain.addBlock(msg.Block)
|
||||
propagateBlock(msg.Block)
|
||||
}*/
|
||||
break
|
||||
default:
|
||||
log.Println("Msg.Type not supported")
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
func (msg *Msg) Construct(msgtype string, msgcontent string) {
|
||||
msg.Type = msgtype
|
||||
msg.Content = msgcontent
|
||||
msg.Date = time.Now()
|
||||
}
|
||||
func (msg Msg) ToBytes() []byte {
|
||||
msgS, err := json.Marshal(msg)
|
||||
check(err)
|
||||
l := string(msgS) + "\n"
|
||||
r := []byte(l)
|
||||
return r
|
||||
}
|
||||
func (msg Msg) CreateFromBytes(bytes []byte) Msg {
|
||||
err := json.Unmarshal(bytes, &msg)
|
||||
check(err)
|
||||
return msg
|
||||
}
|
||||
164
peer/p2plib/peers.go
Normal file
164
peer/p2plib/peers.go
Normal file
@@ -0,0 +1,164 @@
|
||||
package p2plib
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
type Peer struct {
|
||||
ID string `json:"id"` //in the future, this will be the peer hash
|
||||
IP string `json:"ip"`
|
||||
Port string `json:"port"`
|
||||
RESTPort string `json:"restport"`
|
||||
Role string `json:"role"` //client or server
|
||||
Conn net.Conn `json:"conn"`
|
||||
}
|
||||
|
||||
type PeersList struct {
|
||||
PeerID string
|
||||
Peers []Peer `json:"peerslist"`
|
||||
Date time.Time `json:"date"`
|
||||
}
|
||||
|
||||
type PeersConnections struct {
|
||||
Incoming PeersList
|
||||
Outcoming PeersList
|
||||
Network PeersList //the peers that have been received in the lists from other peers
|
||||
}
|
||||
|
||||
type ThisPeer struct {
|
||||
Running bool
|
||||
ID string
|
||||
RunningPeer Peer
|
||||
PeersConnections PeersConnections
|
||||
}
|
||||
|
||||
var globalTP ThisPeer
|
||||
|
||||
func PeerIsInPeersList(p Peer, pl []Peer) int {
|
||||
r := -1
|
||||
for i, peer := range pl {
|
||||
if peer.IP+":"+peer.Port == p.IP+":"+p.Port {
|
||||
r = i
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func DeletePeerFromPeersList(p Peer, pl *PeersList) {
|
||||
i := PeerIsInPeersList(p, pl.Peers)
|
||||
if i != -1 {
|
||||
//delete peer from pl.Peers
|
||||
pl.Peers = append(pl.Peers[:i], pl.Peers[i+1:]...)
|
||||
}
|
||||
}
|
||||
func AppendPeerIfNoExist(pl PeersList, p Peer) PeersList {
|
||||
i := PeerIsInPeersList(p, pl.Peers)
|
||||
if i == -1 {
|
||||
pl.Peers = append(pl.Peers, p)
|
||||
}
|
||||
return pl
|
||||
}
|
||||
func UpdateNetworkPeersList(conn net.Conn, newPeersList PeersList) {
|
||||
for _, peer := range newPeersList.Peers {
|
||||
if GetIPPortFromConn(conn) == peer.IP+":"+peer.Port {
|
||||
peer.ID = newPeersList.PeerID
|
||||
color.Yellow(peer.ID)
|
||||
}
|
||||
i := PeerIsInPeersList(peer, globalTP.PeersConnections.Network.Peers)
|
||||
if i == -1 {
|
||||
globalTP.PeersConnections.Network.Peers = append(globalTP.PeersConnections.Network.Peers, peer)
|
||||
} else {
|
||||
fmt.Println(globalTP.PeersConnections.Network.Peers[i])
|
||||
globalTP.PeersConnections.Network.Peers[i].ID = peer.ID
|
||||
}
|
||||
}
|
||||
}
|
||||
func SearchPeerAndUpdate(p Peer) {
|
||||
for _, peer := range globalTP.PeersConnections.Outcoming.Peers {
|
||||
color.Red(p.IP + ":" + p.Port)
|
||||
color.Yellow(peer.IP + ":" + peer.Port)
|
||||
if p.IP+":"+p.Port == peer.IP+":"+peer.Port {
|
||||
peer.ID = p.ID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//send the outcomingPeersList to all the peers except the peer p that has send the outcomingPeersList
|
||||
func PropagatePeersList(p Peer) {
|
||||
for _, peer := range globalTP.PeersConnections.Network.Peers {
|
||||
if peer.Conn != nil {
|
||||
if peer.ID != p.ID && p.ID != "" {
|
||||
color.Yellow(peer.ID + " - " + p.ID)
|
||||
var msg Msg
|
||||
msg.Construct("PeersList", "here my outcomingPeersList")
|
||||
msg.PeersList = globalTP.PeersConnections.Outcoming
|
||||
msgB := msg.ToBytes()
|
||||
_, err := peer.Conn.Write(msgB)
|
||||
check(err)
|
||||
} else {
|
||||
/*
|
||||
for the moment, this is not being called, due that in the IncomingPeersList,
|
||||
there is no peer.ID, so in the comparation wih the peer that has send the
|
||||
peersList, is comparing ID with "", so nevere enters this 'else' section
|
||||
|
||||
maybe it's not needed. TODO check if it's needed the PeerList_Response
|
||||
For the moment is working without it
|
||||
*/
|
||||
//to the peer that has sent the peerList, we send our PeersList
|
||||
|
||||
var msg Msg
|
||||
msg.Construct("PeersList_Response", "here my outcomingPeersList")
|
||||
msg.PeersList = globalTP.PeersConnections.Outcoming
|
||||
msgB := msg.ToBytes()
|
||||
_, err := peer.Conn.Write(msgB)
|
||||
check(err)
|
||||
}
|
||||
} else {
|
||||
//connect to peer
|
||||
if peer.ID != p.ID && peer.ID != globalTP.RunningPeer.ID {
|
||||
if PeerIsInPeersList(peer, globalTP.PeersConnections.Outcoming.Peers) == -1 {
|
||||
color.Red("no connection, connecting to peer: " + peer.Port)
|
||||
ConnectToPeer(peer)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
func PrintPeersList() {
|
||||
fmt.Println("")
|
||||
color.Blue("runningPeer.ID: " + globalTP.RunningPeer.ID)
|
||||
color.Green("OUTCOMING PEERSLIST:")
|
||||
for _, peer := range globalTP.PeersConnections.Outcoming.Peers {
|
||||
fmt.Println(peer)
|
||||
}
|
||||
color.Green("INCOMING PEERSLIST:")
|
||||
for _, peer := range globalTP.PeersConnections.Incoming.Peers {
|
||||
fmt.Println(peer)
|
||||
}
|
||||
|
||||
color.Green("NETWORK PEERSLIST:")
|
||||
for _, peer := range globalTP.PeersConnections.Network.Peers {
|
||||
fmt.Println(peer)
|
||||
}
|
||||
fmt.Println("")
|
||||
}
|
||||
|
||||
//send the block to all the peers of the outcomingPeersList
|
||||
/*func PropagateBlock(b Block) {
|
||||
//prepare the msg to send to all connected peers
|
||||
var msg Msg
|
||||
msg.construct("Block", "new block")
|
||||
msg.Block = b
|
||||
msgB := msg.toBytes()
|
||||
for _, peer := range outcomingPeersList.Peers {
|
||||
if peer.Conn != nil {
|
||||
_, err := peer.Conn.Write(msgB)
|
||||
check(err)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
38
peer/p2plib/utils.go
Normal file
38
peer/p2plib/utils.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package p2plib
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"math/rand"
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GetIPPortFromConn(conn net.Conn) string {
|
||||
ip := GetIPFromConn(conn)
|
||||
port := GetPortFromConn(conn)
|
||||
return ip + ":" + port
|
||||
}
|
||||
func GetIPFromConn(conn net.Conn) string {
|
||||
s := conn.RemoteAddr().String()
|
||||
s = strings.Split(s, ":")[0]
|
||||
s = strings.Trim(s, ":")
|
||||
return s
|
||||
}
|
||||
func GetPortFromConn(conn net.Conn) string {
|
||||
s := conn.RemoteAddr().String()
|
||||
s = strings.Split(s, ":")[1]
|
||||
s = strings.Trim(s, ":")
|
||||
return s
|
||||
}
|
||||
func RandInt(min int, max int) int {
|
||||
r := rand.Intn(max-min) + min
|
||||
return r
|
||||
}
|
||||
func HashPeer(p Peer) string {
|
||||
peerString := p.IP + ":" + p.Port
|
||||
|
||||
h := sha256.New()
|
||||
h.Write([]byte(peerString))
|
||||
return base64.URLEncoding.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
Reference in New Issue
Block a user