89 lines
2.8 KiB
Go
89 lines
2.8 KiB
Go
|
|
package application
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"fmt"
|
||
|
|
"io"
|
||
|
|
|
||
|
|
"hash-of-wisdom/internal/pow/challenge"
|
||
|
|
"hash-of-wisdom/internal/protocol"
|
||
|
|
"hash-of-wisdom/internal/quotes"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Response represents an encodable response that can write itself to a connection
|
||
|
|
type Response interface {
|
||
|
|
Encode(w io.Writer) error
|
||
|
|
}
|
||
|
|
|
||
|
|
// WisdomService defines the interface for the wisdom service
|
||
|
|
type WisdomService interface {
|
||
|
|
GenerateChallenge(ctx context.Context, resource string) (*challenge.Challenge, error)
|
||
|
|
VerifySolution(ctx context.Context, solution *challenge.Solution) error
|
||
|
|
GetQuote(ctx context.Context) (*quotes.Quote, error)
|
||
|
|
}
|
||
|
|
|
||
|
|
// WisdomApplication handles the Word of Wisdom application logic
|
||
|
|
type WisdomApplication struct {
|
||
|
|
wisdomService WisdomService
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewWisdomApplication creates a new wisdom application handler
|
||
|
|
func NewWisdomApplication(wisdomService WisdomService) *WisdomApplication {
|
||
|
|
return &WisdomApplication{
|
||
|
|
wisdomService: wisdomService,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// HandleMessage processes a protocol message and returns an encodable response
|
||
|
|
func (a *WisdomApplication) HandleMessage(ctx context.Context, msg *protocol.Message) (Response, error) {
|
||
|
|
switch msg.Type {
|
||
|
|
case protocol.ChallengeRequestType:
|
||
|
|
return a.handleChallengeRequest(ctx)
|
||
|
|
case protocol.SolutionRequestType:
|
||
|
|
return a.handleSolutionRequest(ctx, msg)
|
||
|
|
default:
|
||
|
|
return &protocol.ErrorResponse{
|
||
|
|
Code: protocol.ErrMalformedMessage,
|
||
|
|
Message: fmt.Sprintf("unsupported message type: 0x%02x", msg.Type),
|
||
|
|
}, nil
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// handleChallengeRequest processes challenge requests
|
||
|
|
func (a *WisdomApplication) handleChallengeRequest(ctx context.Context) (Response, error) {
|
||
|
|
challenge, err := a.wisdomService.GenerateChallenge(ctx, "quotes")
|
||
|
|
if err != nil {
|
||
|
|
return &protocol.ErrorResponse{Code: protocol.ErrServerError, Message: "Contact administrator"}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
return &protocol.ChallengeResponse{Challenge: challenge}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// handleSolutionRequest processes solution requests
|
||
|
|
func (a *WisdomApplication) handleSolutionRequest(ctx context.Context, msg *protocol.Message) (Response, error) {
|
||
|
|
// Parse solution request
|
||
|
|
var solutionReq protocol.SolutionRequest
|
||
|
|
if err := solutionReq.Decode(msg.PayloadStream); err != nil {
|
||
|
|
return &protocol.ErrorResponse{Code: protocol.ErrMalformedMessage, Message: "invalid solution format"}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create solution object
|
||
|
|
solution := &challenge.Solution{
|
||
|
|
Challenge: solutionReq.Challenge,
|
||
|
|
Nonce: solutionReq.Nonce,
|
||
|
|
}
|
||
|
|
|
||
|
|
// Verify solution
|
||
|
|
if err := a.wisdomService.VerifySolution(ctx, solution); err != nil {
|
||
|
|
return &protocol.ErrorResponse{Code: protocol.ErrInvalidSolution, Message: "solution verification failed"}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get quote
|
||
|
|
quote, err := a.wisdomService.GetQuote(ctx)
|
||
|
|
if err != nil {
|
||
|
|
return &protocol.ErrorResponse{Code: protocol.ErrServerError, Message: "Contact administrator"}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
return &protocol.SolutionResponse{Quote: quote}, nil
|
||
|
|
}
|