package main import ( "log" "time" "git.ali33.ru/fcg-xvii/go-tools/json" "github.com/gorilla/websocket" "golang.org/x/net/context" ) type WSClient struct { clients *WSClients conn *websocket.Conn ctx context.Context cancel context.CancelFunc //callClose func(*WSClient) //callIncoming func(*WSClient, json.Map) } func (s *WSClient) SendData(data json.Map) error { w, err := s.conn.NextWriter(websocket.TextMessage) if err != nil { return err } _, err = w.Write(data.JSON()) w.Close() return err } func (s *WSClient) SendSingle(data json.Map) error { jm := json.Map{ "data": data, } return s.SendData(jm) } func (s *WSClient) SendMessage(data json.Map, deadline time.Duration) (<-chan json.Map, error) { dl := time.Now().Add(deadline) id := s.clients.nextID() jm := json.Map{ "id": id, "data": data, } if err := s.SendData(jm); err != nil { return nil, err } ctx, _ := context.WithDeadline(context.Background(), dl) ch := make(chan json.Map) rch := make(chan json.Map) s.clients.rStore.Store(id, ch) go func() { select { case <-ctx.Done(): s.clients.rStore.Delete(id) close(rch) case rData := <-ch: select { case rch <- rData: default: } } }() return rch, nil } func (s *WSClient) Context() context.Context { return s.ctx } func (s *WSClient) Read() <-chan *Message { ch := make(chan *Message, 10) go func() { defer func() { s.cancel() close(ch) }() for { t, src, err := s.conn.ReadMessage() log.Println(t, string(src), err) if err != nil { s.clients.clientDisconnected(s) return } var jm json.Map if err = json.Unmarshal(src, &jm); err == nil { if jm.Bool("is_response", false) { //log.Println("AAAAAAAAAAAAAAAAAAA") if rch, check := s.clients.rStore.LoadAndDelete(jm.Int("id", -1)); check { rch.(chan json.Map) <- jm.Map("data", json.Map{}) } } else { //log.Println("UUUUUUUUUUUUUUUU") mes := MessageFromMap(jm, s) select { case ch <- mes: default: } } } } }() return ch } /////////////////////////