100 lines
1.7 KiB
Go
100 lines
1.7 KiB
Go
|
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)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|