main.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // Skeleton to part 7 of the Whispering Gophers code lab.
  2. //
  3. // This program extends part 6 by adding a Peers type.
  4. // The rest of the code is left as-is, so functionally there is no change.
  5. //
  6. // However we have added a peers_test.go file, so that running
  7. // go test
  8. // from the package directory will test your implementation of the Peers type.
  9. //
  10. package main
  11. import (
  12. "bufio"
  13. "encoding/json"
  14. "flag"
  15. "fmt"
  16. "log"
  17. "net"
  18. "os"
  19. "sync"
  20. "code.osinet.fr/fgm/whispering_gophers/util"
  21. )
  22. var (
  23. listenAddr = flag.String("listen", "", "peer host:port")
  24. peerAddr = flag.String("peer", "", "peer host:port")
  25. self string
  26. )
  27. type Message struct {
  28. Addr string
  29. Body string
  30. }
  31. func main() {
  32. flag.Parse()
  33. var l net.Listener
  34. var err error
  35. // Create a new listener using util.Listen and put it in a variable named l.
  36. if *listenAddr == "" {
  37. l, err = util.ListenOnFirstUsableInterface()
  38. } else {
  39. l, err = net.Listen("tcp4", *listenAddr)
  40. }
  41. if err != nil {
  42. log.Fatal(err)
  43. }
  44. self = l.Addr().String()
  45. log.Println("Listening on", self)
  46. go dial(*peerAddr)
  47. go readInput()
  48. for {
  49. c, err := l.Accept()
  50. if err != nil {
  51. log.Fatal(err)
  52. }
  53. go serve(c)
  54. }
  55. }
  56. type Peers struct {
  57. m map[string]chan<- Message
  58. mu sync.RWMutex
  59. }
  60. // Add creates and returns a new channel for the given peer address.
  61. // If an address already exists in the registry, it returns nil.
  62. func (p *Peers) Add(addr string) <-chan Message {
  63. // Take the write lock on p.mu. Unlock it before returning (using defer).
  64. p.mu.Lock()
  65. defer p.mu.Unlock()
  66. // Check if the address is already in the peers map under the key addr.
  67. // If it is, return nil.
  68. _, ok := p.m[addr]
  69. if ok {
  70. return nil
  71. }
  72. // Make a new channel of messages
  73. peer := make(chan Message)
  74. // Add it to the peers map
  75. p.m[addr] = peer
  76. // Return the newly created channel.
  77. return peer
  78. }
  79. // Remove deletes the specified peer from the registry.
  80. func (p *Peers) Remove(addr string) {
  81. // Take the write lock on p.mu. Unlock it before returning (using defer).
  82. p.mu.Lock()
  83. defer p.mu.Unlock()
  84. // Delete the peer from the peers map.
  85. delete(p.m, addr)
  86. }
  87. // List returns a slice of all active peer channels.
  88. func (p *Peers) List() []chan<- Message {
  89. // Take the read lock on p.mu. Unlock it before returning (using defer).
  90. p.mu.Lock()
  91. defer p.mu.Unlock()
  92. // Declare a slice of chan<- Message.
  93. channels := make([]chan<- Message, 0, len(p.m))
  94. /* Iterate over the map using range */
  95. for _, v := range p.m {
  96. // Append each channel into the slice.
  97. channels = append(channels, v)
  98. }
  99. // Return the slice.
  100. return channels
  101. }
  102. func serve(c net.Conn) {
  103. defer c.Close()
  104. d := json.NewDecoder(c)
  105. for {
  106. var m Message
  107. err := d.Decode(&m)
  108. if err != nil {
  109. log.Println(err)
  110. return
  111. }
  112. fmt.Printf("%#v\n", m)
  113. }
  114. }
  115. var peer = make(chan Message)
  116. func readInput() {
  117. s := bufio.NewScanner(os.Stdin)
  118. for s.Scan() {
  119. m := Message{
  120. Addr: self,
  121. Body: s.Text(),
  122. }
  123. peer <- m
  124. }
  125. if err := s.Err(); err != nil {
  126. log.Fatal(err)
  127. }
  128. os.Exit(0)
  129. }
  130. func dial(addr string) {
  131. c, err := net.Dial("tcp", addr)
  132. if err != nil {
  133. log.Println(addr, err)
  134. return
  135. }
  136. defer c.Close()
  137. e := json.NewEncoder(c)
  138. for m := range peer {
  139. err := e.Encode(m)
  140. if err != nil {
  141. log.Println(addr, err)
  142. return
  143. }
  144. }
  145. }