| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 | 
							- // Skeleton to part 7 of the Whispering Gophers code lab.
 
- //
 
- // This program extends part 6 by adding a Peers type.
 
- // The rest of the code is left as-is, so functionally there is no change.
 
- //
 
- // However we have added a peers_test.go file, so that running
 
- //   go test
 
- // from the package directory will test your implementation of the Peers type.
 
- //
 
- package main
 
- import (
 
- 	"bufio"
 
- 	"encoding/json"
 
- 	"flag"
 
- 	"fmt"
 
- 	"log"
 
- 	"net"
 
- 	"os"
 
- 	"sync"
 
- 	"code.google.com/p/whispering-gophers/util"
 
- )
 
- var (
 
- 	peerAddr = flag.String("peer", "", "peer host:port")
 
- 	self     string
 
- )
 
- type Message struct {
 
- 	Addr string
 
- 	Body string
 
- }
 
- func main() {
 
- 	flag.Parse()
 
- 	l, err := util.Listen()
 
- 	if err != nil {
 
- 		log.Fatal(err)
 
- 	}
 
- 	self = l.Addr().String()
 
- 	log.Println("Listening on", self)
 
- 	go dial(*peerAddr)
 
- 	go readInput()
 
- 	for {
 
- 		c, err := l.Accept()
 
- 		if err != nil {
 
- 			log.Fatal(err)
 
- 		}
 
- 		go serve(c)
 
- 	}
 
- }
 
- type Peers struct {
 
- 	m  map[string]chan<- Message
 
- 	mu sync.RWMutex
 
- }
 
- // Add creates and returns a new channel for the given peer address.
 
- // If an address already exists in the registry, it returns nil.
 
- func (p *Peers) Add(addr string) <-chan Message {
 
- 	// TODO: Take the write lock on p.mu. Unlock it before returning (using defer).
 
- 	defer p.mu.Unlock()
 
- 	p.mu.Lock()
 
- 	// TODO: Check if the address is already in the peers map under the key addr.
 
- 	if _, ok := p.m[addr] ; ok {
 
- 	  // TODO: If it is, return nil.
 
- 		return nil
 
- 	}
 
- 	// TODO: Make a new channel of messages
 
- 	messages := make(chan Message)
 
- 	// TODO: Add it to the peers map
 
- 	p.m[addr] = messages
 
- 	// TODO: Return the newly created channel.
 
- 	return messages
 
- }
 
- // Remove deletes the specified peer from the registry.
 
- func (p *Peers) Remove(addr string) {
 
- 	// TODO: Take the write lock on p.mu. Unlock it before returning (using defer).
 
- 	defer p.mu.Unlock()
 
- 	p.mu.Lock()
 
- 	// TODO: Delete the peer from the peers map.
 
- 	delete(p.m, addr)
 
- }
 
- // List returns a slice of all active peer channels.
 
- func (p *Peers) List() []chan<- Message {
 
- 	// TODO: Take the read lock on p.mu. Unlock it before returning (using defer).
 
- 	defer p.mu.RUnlock()
 
- 	p.mu.RLock()
 
- 	// TODO: Declare a slice of chan<- Message.
 
- 	var s []chan <- Message
 
- 	/* TODO: Iterate over the map using range */
 
- 	for _, v := range p.m {
 
- 		// TODO: Append each channel into the slice.
 
- 		s = append(s, v)
 
- 	}
 
- 	// TODO: Return the slice.
 
- 	return s
 
- }
 
- func serve(c net.Conn) {
 
- 	defer c.Close()
 
- 	d := json.NewDecoder(c)
 
- 	for {
 
- 		var m Message
 
- 		err := d.Decode(&m)
 
- 		if err != nil {
 
- 			log.Println(err)
 
- 			return
 
- 		}
 
- 		fmt.Printf("%#v\n", m)
 
- 	}
 
- }
 
- var peer = make(chan Message)
 
- func readInput() {
 
- 	s := bufio.NewScanner(os.Stdin)
 
- 	for s.Scan() {
 
- 		m := Message{
 
- 			Addr: self,
 
- 			Body: s.Text(),
 
- 		}
 
- 		peer <- m
 
- 	}
 
- 	if err := s.Err(); err != nil {
 
- 		log.Fatal(err)
 
- 	}
 
- }
 
- func dial(addr string) {
 
- 	c, err := net.Dial("tcp", addr)
 
- 	if err != nil {
 
- 		log.Println(addr, err)
 
- 		return
 
- 	}
 
- 	defer c.Close()
 
- 	e := json.NewEncoder(c)
 
- 	for m := range peer {
 
- 		err := e.Encode(m)
 
- 		if err != nil {
 
- 			log.Println(addr, err)
 
- 			return
 
- 		}
 
- 	}
 
- }
 
 
  |