dotfiles/goagent/pkg/gophx/socket.go

100 lines
1.7 KiB
Go
Raw Normal View History

2024-02-17 15:20:08 +00:00
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)
}
}
}
}