| 
					
				 | 
			
			
				@@ -7,7 +7,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // When it sees a peer with an address it hasn't seen before, it makes a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // connection to that peer. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // It adds an ID field containing a random string to each outgoing message. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// When it recevies a message with an ID it hasn't seen before, it broadcasts 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// When it receives a message with an ID it hasn't seen before, it broadcasts 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // that message to all connected peers. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 package main 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -22,16 +22,18 @@ import ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	"os" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	"sync" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	"github.com/campoy/whispering-gophers/util" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"code.osinet.fr/fgm/whispering_gophers/util" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 var ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	peerAddr = flag.String("peer", "", "peer host:port") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	self     string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	listenAddr = flag.String("listen", "", "peer host:port") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	peerAddr   = flag.String("peer", "", "peer host:port") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	self       string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 type Message struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// TODO: add ID field 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// Add ID field 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ID   string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	Addr string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	Body string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -39,7 +41,14 @@ type Message struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 func main() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	flag.Parse() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	l, err := util.Listen() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	var l net.Listener 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	var err error 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// Create a new listener using util.Listen and put it in a variable named l. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if *listenAddr == "" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		l, err = util.ListenOnFirstUsableInterface() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		l, err = net.Listen("tcp4", *listenAddr) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	if err != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		log.Fatal(err) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -117,7 +126,10 @@ func serve(c net.Conn) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		// TODO: If this message has seen before, ignore it. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// If this message has seen before, ignore it. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if Seen(m.ID) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			continue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		fmt.Printf("%#v\n", m) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		broadcast(m) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -129,16 +141,18 @@ func readInput() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	s := bufio.NewScanner(os.Stdin) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	for s.Scan() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		m := Message{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			// TODO: use util.RandomID to populate the ID field. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			// Use util.RandomID to populate the ID field. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			Addr: self, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			Body: s.Text(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			ID: util.RandomID(), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		// TODO: Mark the message ID as seen. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		Seen(m.ID) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		broadcast(m) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	if err := s.Err(); err != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		log.Fatal(err) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	os.Exit(0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 func dial(addr string) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -169,12 +183,21 @@ func dial(addr string) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// TODO: Create a new map of seen message IDs and a mutex to protect it. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// Create a new map of seen message IDs and a mutex to protect it. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+var seenIDs = struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	m map[string]bool 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	sync.Mutex 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}{m: make(map[string]bool)} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // Seen returns true if the specified id has been seen before. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // If not, it returns false and marks the given id as "seen". 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 func Seen(id string) bool { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// TODO: Get a write lock on the seen message IDs map and unlock it at before returning. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// TODO: Check if the id has been seen before and return that later. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	// TODO: Mark the ID as seen in the map. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// Get a write lock on the seen message IDs map and unlock it at before returning. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	seenIDs.Lock() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	defer seenIDs.Unlock() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// Check if the id has been seen before and return that later. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	ok := seenIDs.m[id] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// Mark the ID as seen in the map. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	seenIDs.m[id] = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return ok 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |