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 }