Scert/backend/internal/localreset/recovery_server.go

53 lines
1.5 KiB
Go

package localreset
import (
"bufio"
"context"
"errors"
"io"
"net"
)
func (s *Server) handleRecovery(ctx context.Context, conn net.Conn, reader *bufio.Reader, peer Peer, session RecoverySession, request Request) {
for count := 0; count < MaxRecoveryRequests; count++ {
if ctx.Err() != nil {
return
}
nonce, err := newNonce()
if err != nil {
return
}
response := Response{Version: Version, OK: true, Code: "CHALLENGE", Nonce: nonce}
switch request.Action {
case "recovery_list":
page, readErr := session.ListRecoveries(ctx, request.Cursor)
err, response.RecoveryPage = readErr, &page
case "recovery_inspect":
inspection, readErr := session.InspectRecovery(ctx, request.TransactionID)
err, response.Inspection = readErr, &inspection
case "recovery_prepare", "recovery_execute", "recovery_result", "recovery_reconcile_prepare":
err = dispatchRecoveryDisposition(ctx, session, request, &response)
default:
err = ErrProtocol
}
if err != nil || ctx.Err() != nil {
s.failed(peer.Identity)
_ = writeFrame(conn, Response{Version: Version, Code: "REJECTED"})
return
}
if writeRecoveryResponse(ctx, conn, response) != nil {
return
}
request = Request{}
if _, err := reader.Peek(1); errors.Is(err, io.EOF) {
return
}
if readFrame(reader, &request) != nil || !validRecoveryRequest(request, nonce) {
s.failed(peer.Identity)
_ = writeFrame(conn, Response{Version: Version, Code: "INVALID_REQUEST"})
return
}
}
_ = writeFrame(conn, Response{Version: Version, Code: "LIMIT_REACHED"})
}