Skip to content

Commit

Permalink
electrum: handle batched rpc requests
Browse files Browse the repository at this point in the history
Some clients will send batched rpc requests. To handle this, we assume
every request is a batched rpc request and fall back to unmarshalling as
a single request when it errors.
  • Loading branch information
kcalvinalvin committed May 7, 2024
1 parent cf9b5a7 commit 7a7f6d9
Showing 1 changed file with 23 additions and 11 deletions.
34 changes: 23 additions & 11 deletions electrum/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -998,22 +998,34 @@ func (s *ElectrumServer) handleConnection(conn net.Conn) {
}
idleTimer.Stop()

msg := btcjson.Request{}
err = msg.UnmarshalJSON(line)
// Attempt to unmarshal as a batched json request.
msgs := []btcjson.Request{}
err = json.Unmarshal(line, &msgs)
if err != nil {
log.Warnf("error while unmarshalling %v. Sending error message to %v. Error: %v",
hex.EncodeToString(line), conn.RemoteAddr().String(), err)
if e, ok := err.(*json.SyntaxError); ok {
log.Warnf("syntax error at byte offset %d", e.Offset)
// If that fails, attempt to unmarshal as a single request.
msg := btcjson.Request{}
err = msg.UnmarshalJSON(line)
if err != nil {
log.Warnf("error while unmarshalling %v. Sending error message to %v. Error: %v",
hex.EncodeToString(line), conn.RemoteAddr().String(), err)
if e, ok := err.(*json.SyntaxError); ok {
log.Warnf("syntax error at byte offset %d", e.Offset)
}

pid := &msgs[0].ID
s.writeErrorResponse(conn, *btcjson.ErrRPCParse, pid)
continue
}

pid := &msg.ID
s.writeErrorResponse(conn, *btcjson.ErrRPCParse, pid)
continue
// If the single request unmarshal was successful, append to the
// msgs for processing below.
msgs = append(msgs, msg)
}

s.handleSingleMsg(msg, conn)
idleTimer.Reset(idleTimeout)
for _, msg := range msgs {
s.handleSingleMsg(msg, conn)
idleTimer.Reset(idleTimeout)
}
}

idleTimer.Stop()
Expand Down

0 comments on commit 7a7f6d9

Please sign in to comment.