|
@@ -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
|
|
|
}
|