diff --git a/peer/connections.go b/peer/connections.go index c961421..5c7dcf4 100644 --- a/peer/connections.go +++ b/peer/connections.go @@ -1,12 +1,10 @@ package main import ( - "encoding/json" + "bufio" "fmt" "log" "net" - - "github.com/fatih/color" ) func acceptPeers(peer Peer) { @@ -26,7 +24,7 @@ func acceptPeers(peer Peer) { newPeer.IP = getIPFromConn(conn) newPeer.Port = getPortFromConn(conn) newPeer.Conn = conn - listPeers = append(listPeers, newPeer) + peersList.Peers = append(peersList.Peers, newPeer) go handleConn(conn) } } @@ -37,32 +35,38 @@ func connectToPeer(peer Peer) { return } peer.Conn = conn - listPeers = append(listPeers, peer) + peersList.Peers = append(peersList.Peers, peer) go handleConn(conn) } func handleConn(conn net.Conn) { connRunning := true log.Println("handling conn: " + conn.RemoteAddr().String()) - //reply to the conn - msgB := newMsgBytes("Hi", "New Peer connected") + //reply to the conn, send the peerList + var msg Msg + msg = msg.construct("PeersList", "here my peersList", peersList) + msgB := msg.toBytes() _, err := conn.Write(msgB) - if err != nil { - check(err) - } + check(err) - buffer := make([]byte, 1024) for connRunning { - bytesRead, err := conn.Read(buffer) + /* + 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 { - s := string(buffer[0:bytesRead]) + /* + fmt.Println(buffer) + fmt.Println(bytesRead) + */ var msg Msg - err := json.Unmarshal([]byte(s), &msg) - check(err) - log.Println("[New msg] [Title]: " + msg.Type + " [Content]: " + msg.Content) - color.Green(msg.Content) + //color.Blue(string(buffer[0:bytesRead])) + //msg = msg.createFromBytes([]byte(string(buffer[0:bytesRead]))) + msg = msg.createFromBytes([]byte(newmsg)) + messageHandler(conn, msg) } } //TODO add that if the peer closed is the p2p server, show a warning message at the peer diff --git a/peer/errors.go b/peer/errors.go index e997ec1..b3cf6b2 100755 --- a/peer/errors.go +++ b/peer/errors.go @@ -1,9 +1,15 @@ package main -import "log" +import ( + "log" + "runtime" +) func check(err error) { if err != nil { + _, fn, line, _ := runtime.Caller(1) + log.Println(line) + log.Println(fn) log.Println(err) } } diff --git a/peer/main.go b/peer/main.go index b5d5ba7..6390224 100644 --- a/peer/main.go +++ b/peer/main.go @@ -2,35 +2,36 @@ package main import ( "fmt" + "math/rand" "net" "os" + "strconv" "time" "github.com/fatih/color" ) type Peer struct { - IP string - Port string - Role string //client or server - Conn net.Conn -} -type Msg struct { - Type string `json:"type"` - Content string `json:"content"` + ID string `json:"id"` + IP string `json:"ip"` + Port string `json:"port"` + Role string `json:"role"` //client or server + Conn net.Conn `json:"conn"` } -var listPeers []Peer var running bool +var thisPeerID string func main() { //initialize some vars + rand.Seed(time.Now().Unix()) running = true var peer Peer color.Blue("Starting Peer") readConfig("config.json") + peer.ID = strconv.Itoa(randInt(1, 1000)) //0 is reserved for server peer.IP = config.IP peer.Port = config.Port peer.Role = "client" @@ -41,10 +42,17 @@ func main() { color.Yellow("Running as p2p server") peer.Role = "server" peer.Port = config.ServerPort - go acceptPeers(peer) + peer.ID = "0" } } + thisPeerID = peer.ID + peersList.PeerID = peer.ID fmt.Println(peer) + peersList.Peers = append(peersList.Peers, peer) + fmt.Println(peersList) + if peer.Role == "server" { + go acceptPeers(peer) + } if peer.Role == "client" { var newPeer Peer newPeer.IP = config.ServerIP diff --git a/peer/messages.go b/peer/messages.go new file mode 100644 index 0000000..eaf35ed --- /dev/null +++ b/peer/messages.go @@ -0,0 +1,62 @@ +package main + +import ( + "encoding/json" + "fmt" + "log" + "net" + "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"` +} + +func messageHandler(conn net.Conn, 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) + + time.Sleep(1000 * time.Millisecond) + updatePeersList(conn, msg.PeersList) + propagatePeersList() + printPeersList() + default: + log.Println("Msg.Type not supported") + break + } + +} +func (msg Msg) construct(msgtype string, msgcontent string, peersList PeersList) Msg { + msg.Type = msgtype + msg.Content = msgcontent + msg.PeersList = peersList + msg.Date = time.Now() + return msg +} +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 +} diff --git a/peer/peersList.go b/peer/peersList.go new file mode 100644 index 0000000..c955ee1 --- /dev/null +++ b/peer/peersList.go @@ -0,0 +1,64 @@ +package main + +import ( + "fmt" + "net" + "time" + + "github.com/fatih/color" +) + +type PeersList struct { + PeerID string + Peers []Peer `json:"peerslist"` + Date time.Time `json:"date"` +} + +//var peersList []Peer +var peersList PeersList + +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 updatePeersList(conn net.Conn, newPeersList PeersList) { + for _, peer := range newPeersList.Peers { + if getIPPortFromConn(conn) == peer.IP+":"+peer.Port { + peer.ID = newPeersList.PeerID + } + i := peerIsInPeersList(peer, peersList.Peers) + if i == -1 { + peersList.Peers = append(peersList.Peers, peer) + } else { + fmt.Println(peersList.Peers[i]) + peersList.Peers[i].ID = peer.ID + } + } +} + +//send the peersList to all the peers except the peer that has send the peersList +func propagatePeersList() { + for _, peer := range peersList.Peers { + if peer.Conn != nil { + var msg Msg + msg = msg.construct("PeersList", "here my peersList", peersList) + msgB := msg.toBytes() + _, err := peer.Conn.Write(msgB) + check(err) + } + } +} +func printPeersList() { + fmt.Println("") + color.Green("PEERSLIST:") + color.Green("thisPeerId: " + thisPeerID) + for _, peer := range peersList.Peers { + fmt.Println(peer) + } + fmt.Println("") +} diff --git a/peer/utils.go b/peer/utils.go index be7df16..c9f62f1 100644 --- a/peer/utils.go +++ b/peer/utils.go @@ -1,18 +1,15 @@ package main import ( - "encoding/json" + "math/rand" "net" "strings" ) -func newMsgBytes(msgtype string, msgcontent string) []byte { - var msg Msg - msg.Type = msgtype - msg.Content = msgcontent - msgS, err := json.Marshal(msg) - check(err) - return msgS +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() @@ -26,3 +23,7 @@ func getPortFromConn(conn net.Conn) string { s = strings.Trim(s, ":") return s } +func randInt(min int, max int) int { + r := rand.Intn(max-min) + min + return r +}