package main import ( "io" "log" "net/http" "sync" "github.com/gorilla/websocket" ) type WS struct { upgrader websocket.Upgrader pools *sync.Map } func NewWS() *WS { return &WS{ upgrader: websocket.Upgrader{ ReadBufferSize: 10240, WriteBufferSize: 10240, CheckOrigin: func(_ *http.Request) bool { return true }, }, pools: &sync.Map{}, } } func (ws *WS) ServeHTTP(w http.ResponseWriter, r *http.Request) { if err := ws.serveHTTP(w, r); err != nil { log.Println(r.URL.Path, err) http.Error(w, err.Error(), http.StatusInternalServerError) } } func (ws *WS) serveHTTP(w http.ResponseWriter, r *http.Request) error { log.Println("ws serve http", r.URL.Path) pooli, ok := ws.pools.Load(r.URL.Path) if !ok { pooli = NewPool() } pool := pooli.(*Pool) log.Println("ws upgrade") conn, err := ws.upgrader.Upgrade(w, r, nil) if err != nil { return err } log.Println("ws next reader") mt, _, err := conn.NextReader() if err != nil { return err } log.Println("funcs") go func() { for { _, r, err := conn.NextReader() if err != nil { panic(err) } log.Println("copying to pool...") if _, err := io.Copy(pool, r); err != nil { panic(err) } log.Println("/copying to pool...") } }() func() { for { w, err := conn.NextWriter(mt) if err != nil { panic(err) } log.Println("copying from pool...") if _, err := io.Copy(w, pool); err != nil { // todo impl broadcast to channel;; sync map to all channels, goes to a forking reader-writer pipe, all listeners to broadcast read from pipe panic(err) } log.Println("/copying from pool...") if err := w.Close(); err != nil { panic(err) } } }() return nil }