github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/talks/2012/chat/http-noembed/chat.go (about)

     1  // +build OMIT
     2  
     3  package main
     4  
     5  import (
     6  	"fmt"
     7  	"io"
     8  	"log"
     9  	"net/http"
    10  
    11  	"golang.org/x/net/websocket"
    12  )
    13  
    14  const listenAddr = "localhost:4000"
    15  
    16  func main() {
    17  	http.HandleFunc("/", rootHandler)
    18  	http.Handle("/socket", websocket.Handler(socketHandler))
    19  	err := http.ListenAndServe(listenAddr, nil)
    20  	if err != nil {
    21  		log.Fatal(err)
    22  	}
    23  }
    24  
    25  type socket struct {
    26  	conn *websocket.Conn
    27  	done chan bool
    28  }
    29  
    30  func (s socket) Read(b []byte) (int, error)  { return s.conn.Read(b) }
    31  func (s socket) Write(b []byte) (int, error) { return s.conn.Write(b) }
    32  
    33  func (s socket) Close() error {
    34  	s.done <- true
    35  	return nil
    36  }
    37  
    38  func socketHandler(ws *websocket.Conn) {
    39  	s := socket{conn: ws, done: make(chan bool)}
    40  	go match(s)
    41  	<-s.done
    42  }
    43  
    44  // END OMIT
    45  
    46  var partner = make(chan io.ReadWriteCloser)
    47  
    48  func match(c io.ReadWriteCloser) {
    49  	fmt.Fprint(c, "Waiting for a partner...")
    50  	select {
    51  	case partner <- c:
    52  		// now handled by the other goroutine
    53  	case p := <-partner:
    54  		chat(p, c)
    55  	}
    56  }
    57  
    58  func chat(a, b io.ReadWriteCloser) {
    59  	fmt.Fprintln(a, "Found one! Say hi.")
    60  	fmt.Fprintln(b, "Found one! Say hi.")
    61  	errc := make(chan error, 1)
    62  	go cp(a, b, errc)
    63  	go cp(b, a, errc)
    64  	if err := <-errc; err != nil {
    65  		log.Println(err)
    66  	}
    67  	a.Close()
    68  	b.Close()
    69  }
    70  
    71  func cp(w io.Writer, r io.Reader, errc chan<- error) {
    72  	_, err := io.Copy(w, r)
    73  	errc <- err
    74  }