package core import ( "encoding/binary" "fmt" "io" "log" "net" "time" ) func Send(conn net.Conn, dataType DataType, data Marshaler) error { packet := []any{uint8(dataType)} packet = append(packet, data.Marshal()...) for _, v := range packet { err := binary.Write(conn, binary.BigEndian, v) if err != nil { return fmt.Errorf("cannot send: %v", err) } } return nil } func Read(r io.Reader) (any, error) { dType, err := ReadDataType(r) if err != nil { return nil, fmt.Errorf("cannot read data type", err) } switch dType { case TypeUnknown: return nil, fmt.Errorf("cannot read data type 0x00 (TypeUnknown)") case TypeHandshake: return ReadHandshake(r) case TypePing: return Ping{}, nil case TypePong: return ReadPong(r) case TypeTest: return ReadTest(r) default: return nil, fmt.Errorf("unsupported type: %v", dType) } } func Loop(conn net.Conn) error { for { d, err := Read(conn) if err != nil { return fmt.Errorf("cannot read data: %v", err) } if err := handleEvent(d, conn); err != nil { return fmt.Errorf("cannot handle event: %v", err) } } } func handleEvent(data any, conn net.Conn) error { switch v := data.(type) { case Handshake: case Ping: log.Print("received ping") return Send(conn, TypePong, Pong{time.Now()}) case Pong: log.Print("received pong ", v.Timestamp) case Test: default: return fmt.Errorf("unknown type") } return nil }