hash-of-wisdom/internal/protocol/responses.go

83 lines
2.3 KiB
Go
Raw Normal View History

package protocol
import (
"encoding/binary"
"encoding/json"
"fmt"
"io"
"hash-of-wisdom/internal/pow/challenge"
"hash-of-wisdom/internal/quotes"
)
// writeHeader writes the message type and payload length to the writer
func writeHeader(w io.Writer, msgType MessageType, payloadLength uint32) error {
// Write message type (1 byte)
if err := binary.Write(w, binary.BigEndian, msgType); err != nil {
return fmt.Errorf("failed to write message type: %w", err)
}
// Write payload length (4 bytes, big-endian)
if err := binary.Write(w, binary.BigEndian, payloadLength); err != nil {
return fmt.Errorf("failed to write payload length: %w", err)
}
return nil
}
// encodeResponse is a helper function that encodes any response with the given message type
func encodeResponse(w io.Writer, msgType MessageType, payload interface{}) error {
// Marshal to get exact payload size
payloadBytes, err := json.Marshal(payload)
if err != nil {
return fmt.Errorf("failed to encode payload: %w", err)
}
// Write header
if err := writeHeader(w, msgType, uint32(len(payloadBytes))); err != nil {
return err
}
// Write JSON payload directly to stream
if len(payloadBytes) > 0 {
if _, err := w.Write(payloadBytes); err != nil {
return fmt.Errorf("failed to write payload: %w", err)
}
}
return nil
}
// ChallengeResponse represents a challenge response
type ChallengeResponse struct {
Challenge *challenge.Challenge
}
// SolutionResponse represents a successful solution response (contains quote)
type SolutionResponse struct {
Quote *quotes.Quote
}
// ErrorResponse represents an error response
type ErrorResponse struct {
Code string `json:"code"`
Message string `json:"message"`
RetryAfter int `json:"retry_after,omitempty"`
Details map[string]string `json:"details,omitempty"`
}
// Encode writes the challenge response to the writer
func (r *ChallengeResponse) Encode(w io.Writer) error {
return encodeResponse(w, ChallengeResponseType, r.Challenge)
}
// Encode writes the solution response to the writer
func (r *SolutionResponse) Encode(w io.Writer) error {
return encodeResponse(w, QuoteResponseType, r.Quote)
}
// Encode writes the error response to the writer
func (r *ErrorResponse) Encode(w io.Writer) error {
return encodeResponse(w, ErrorResponseType, r)
}