78 lines
1.5 KiB
Go
78 lines
1.5 KiB
Go
package fcast
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"encoding/json"
|
|
"errors"
|
|
"log"
|
|
"net"
|
|
"strconv"
|
|
)
|
|
|
|
type Connection struct {
|
|
net.Conn
|
|
}
|
|
|
|
func Connect(host string) (*Connection, error) {
|
|
conn, err := net.Dial("tcp", host+":"+strconv.Itoa(DefaultPort))
|
|
return &Connection{conn}, err
|
|
}
|
|
|
|
func (c *Connection) ListenForMessages(em *EventManager) error {
|
|
|
|
c.addPingHandlerIfNotSet(em)
|
|
|
|
for {
|
|
|
|
var (
|
|
bodyLenBuf = make([]byte, 4)
|
|
opCodeBuf [1]byte
|
|
// bodyBuf's size depends on bodyLen's value
|
|
)
|
|
|
|
_, err := c.Read(bodyLenBuf)
|
|
bodyBuf := make([]byte, binary.LittleEndian.Uint32(bodyLenBuf)-1)
|
|
_, err = c.Read(opCodeBuf[:])
|
|
_, err = c.Read(bodyBuf)
|
|
|
|
if err != nil {
|
|
if errors.Is(err, net.ErrClosed) {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
|
|
rawMsg, err := DeserializeRaw(bodyLenBuf, opCodeBuf[:], bodyBuf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = em.dispatchMessage(rawMsg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
func (c *Connection) addPingHandlerIfNotSet(em *EventManager) {
|
|
if em.codes[Ping].handler == nil {
|
|
em.SetHandler(PingMessage{}, func(message Message) {
|
|
err := c.SendMessage(PongMessage{})
|
|
if err != nil {
|
|
log.Println("[ERROR} fcast: error in default pong responder:", err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func (c *Connection) SendMessage(message Message) error {
|
|
body, _ := json.Marshal(message)
|
|
rawMessage := NewMessage(message.getOpCode(), body)
|
|
serialized := SerializeRaw(rawMessage)
|
|
_, err := c.Write(serialized)
|
|
return err
|
|
}
|