first commit

This commit is contained in:
arnaucode
2018-01-27 00:13:41 +01:00
parent 682fe68b0e
commit 51e2d00603
24 changed files with 1034 additions and 0 deletions

View 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
View 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
View 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
View 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
View 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
View 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))
}