lbcwallet/rpc.go
2014-04-09 13:02:12 -05:00

100 lines
3.1 KiB
Go

/*
* Copyright (c) 2013, 2014 Conformal Systems LLC <info@conformal.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package main
import (
"encoding/json"
"github.com/conformal/btcjson"
)
// RawRPCResponse is a response to a JSON-RPC request with delayed
// unmarshaling.
type RawRPCResponse struct {
Id *uint64
Result *json.RawMessage `json:"result"`
Error *json.RawMessage `json:"error"`
}
// FinishUnmarshal unmarshals the result and error of a raw RPC response.
// If v is non-nil, the result is unmarshaled into the variable pointed
// to by the interface rather than using the rules in the encoding/json
// package to allocate a new variable for the result. The final result
// and JSON-RPC error is returned.
func (r *RawRPCResponse) FinishUnmarshal(v interface{}) (interface{}, *btcjson.Error) {
// JSON-RPC spec makes this handling easier-ish because both result and
// error cannot be non-nil.
var jsonErr *btcjson.Error
if r.Error != nil {
if err := json.Unmarshal([]byte(*r.Error), &jsonErr); err != nil {
return nil, &btcjson.Error{
Code: btcjson.ErrParse.Code,
Message: err.Error(),
}
}
return nil, jsonErr
}
if r.Result != nil {
if err := json.Unmarshal([]byte(*r.Result), &v); err != nil {
return nil, &btcjson.Error{
Code: btcjson.ErrParse.Code,
Message: err.Error(),
}
}
return v, nil
}
return nil, nil
}
// ClientRequest is a type holding a bitcoin client's request and
// a channel to send the response.
type ClientRequest struct {
ws bool
request btcjson.Cmd
response chan RawRPCResponse
}
// NewClientRequest creates a new ClientRequest from a btcjson.Cmd.
func NewClientRequest(request btcjson.Cmd, ws bool) *ClientRequest {
return &ClientRequest{
ws: ws,
request: request,
response: make(chan RawRPCResponse),
}
}
// Handle sends a client request to the RPC gateway for processing,
// and returns the result when handling is finished.
func (r *ClientRequest) Handle() RawRPCResponse {
clientRequests <- r
return <-r.response
}
// ServerRequest is a type responsible for handling requests to a bitcoin
// server and providing a method to access the response.
type ServerRequest struct {
request btcjson.Cmd
response chan RawRPCResponse
}
// NewServerRequest creates a new ServerRequest from a btcjson.Cmd.
func NewServerRequest(request btcjson.Cmd) *ServerRequest {
return &ServerRequest{
request: request,
response: make(chan RawRPCResponse, 1),
}
}