66 lines
1.7 KiB
Go
66 lines
1.7 KiB
Go
package protocol
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
// MessageDecoder handles decoding of protocol message headers
|
|
type MessageDecoder struct{}
|
|
|
|
// NewMessageDecoder creates a new message decoder
|
|
func NewMessageDecoder() *MessageDecoder {
|
|
return &MessageDecoder{}
|
|
}
|
|
|
|
// Decode reads the message header and returns a Message with the payload stream
|
|
func (d *MessageDecoder) Decode(r io.Reader) (*Message, error) {
|
|
// Read message type (1 byte)
|
|
var msgType MessageType
|
|
if err := binary.Read(r, binary.BigEndian, &msgType); err != nil {
|
|
if err == io.EOF {
|
|
return nil, err
|
|
}
|
|
return nil, fmt.Errorf("failed to read message type: %w", err)
|
|
}
|
|
|
|
// Validate message type (only request types are valid for server)
|
|
if !isValidRequestType(msgType) {
|
|
return nil, fmt.Errorf("invalid message type: 0x%02x", msgType)
|
|
}
|
|
|
|
// Read payload length (4 bytes, big-endian)
|
|
var payloadLength uint32
|
|
if err := binary.Read(r, binary.BigEndian, &payloadLength); err != nil {
|
|
return nil, fmt.Errorf("failed to read payload length: %w", err)
|
|
}
|
|
|
|
// Validate payload length
|
|
if payloadLength > MaxPayloadSize {
|
|
return nil, fmt.Errorf("payload length %d exceeds maximum %d", payloadLength, MaxPayloadSize)
|
|
}
|
|
|
|
// Create limited reader for the payload
|
|
var payloadStream io.Reader
|
|
if payloadLength > 0 {
|
|
payloadStream = io.LimitReader(r, int64(payloadLength))
|
|
}
|
|
|
|
return &Message{
|
|
Type: msgType,
|
|
PayloadLength: payloadLength,
|
|
PayloadStream: payloadStream,
|
|
}, nil
|
|
}
|
|
|
|
// isValidRequestType checks if the message type is a valid request type
|
|
func isValidRequestType(msgType MessageType) bool {
|
|
switch msgType {
|
|
case ChallengeRequestType, SolutionRequestType:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|