package protocol import ( "encoding/binary" "encoding/json" "fmt" "io" ) const ( MsgRegister byte = 1 MsgRegisterAck byte = 2 MsgPing byte = 3 MsgPong byte = 4 MsgOpenStream byte = 5 MsgStreamReady byte = 6 MsgClose byte = 7 ) const ( ConnTypeTCP = "tcp" ConnTypeUDP = "udp" ConnTypeHTTP = "http" ) type RegisterPayload struct { VerifyKey string `json:"verify_key"` Version string `json:"version"` } type RegisterAckPayload struct { ClientID uint `json:"client_id"` Message string `json:"message"` OK bool `json:"ok"` } type LinkMeta struct { ConnType string `json:"conn_type"` Target string `json:"target"` RemoteAddr string `json:"remote_addr"` StreamID uint32 `json:"stream_id"` } func WriteMessage(w io.Writer, msgType byte, payload interface{}) error { var body []byte var err error if payload != nil { body, err = json.Marshal(payload) if err != nil { return err } } header := make([]byte, 5) header[0] = msgType binary.BigEndian.PutUint32(header[1:], uint32(len(body))) if _, err := w.Write(header); err != nil { return err } if len(body) > 0 { _, err = w.Write(body) } return err } func ReadMessage(r io.Reader) (byte, []byte, error) { header := make([]byte, 5) if _, err := io.ReadFull(r, header); err != nil { return 0, nil, err } msgType := header[0] length := binary.BigEndian.Uint32(header[1:]) if length == 0 { return msgType, nil, nil } if length > 1<<20 { return 0, nil, fmt.Errorf("message too large: %d", length) } body := make([]byte, length) if _, err := io.ReadFull(r, body); err != nil { return 0, nil, err } return msgType, body, nil } func ParseRegister(body []byte) (*RegisterPayload, error) { var p RegisterPayload if err := json.Unmarshal(body, &p); err != nil { return nil, err } return &p, nil } func ParseLinkMeta(body []byte) (*LinkMeta, error) { var p LinkMeta if err := json.Unmarshal(body, &p); err != nil { return nil, err } return &p, nil }