package gophx import ( "context" "fmt" "nhooyr.io/websocket" ) type Socket struct { sendChan chan []byte websocket *websocket.Conn channels map[string]*Channel } func Connect(ctx context.Context) (*Socket, error) { serverUrl := "ws://localhost:4000/agent/websocket?vsn=2.0.0" c, _, err := websocket.Dial(ctx, serverUrl, nil) if err != nil { return nil, err } socket := Socket{ sendChan: make(chan []byte), channels: make(map[string]*Channel), websocket: c, } go socket.readMessages(ctx) go writeMessages(ctx, socket.sendChan, c) return &socket, nil } func (s *Socket) addChannel(ch *Channel) { s.channels[ch.topic] = ch } func (s *Socket) send(data []byte) { s.sendChan <- data } func (s *Socket) readMessages(ctx context.Context) { for { select { case <-ctx.Done(): return default: typ, data, err := s.websocket.Read(ctx) if err != nil { // TODO: try to reconnect fmt.Println("socket closed?", err) return } switch typ { case websocket.MessageBinary: fmt.Println("received binary", data) case websocket.MessageText: msg := message{} err := deserializeJSON(data, &msg) if err != nil { fmt.Println(err) } s.sendToChannel(msg) } } } } func (s *Socket) sendToChannel(msg message) { ch, ok := s.channels[msg.topic] if !ok { return } ch.handleMessage(msg) } func writeMessages(ctx context.Context, sendChan chan []byte, ws *websocket.Conn) { for { select { case message, ok := <-sendChan: if !ok { fmt.Println("sending channel closed") return } err := ws.Write(ctx, websocket.MessageText, message) if err != nil { fmt.Println(err) } } } }