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 }