lux/rpc/lux_rpc_client.go

80 lines
1.8 KiB
Go

package rpc
import (
"encoding/xml"
"fmt"
"net"
)
type LuxRpcClient struct {
conn net.Conn
counter int
}
func LuxDialRpc(network string, address string) (LuxRpcClient, error) {
conn, err := net.Dial(network, address)
if err != nil {
return LuxRpcClient{}, err
}
return LuxRpcClient{
conn: conn,
counter: 0,
}, nil
}
func (rpc *LuxRpcClient) Close() {
rpc.conn.Close()
}
func (rpc *LuxRpcClient) Execute(request LuxRpcRequest) (LuxRpcResponse, LuxRpcError, error) {
var rpcRes LuxRpcResponse
var rpcErr LuxRpcError
request.RequestID = rpc.counter
rpc.counter++
xmlBytes, err := xml.Marshal(&request)
if err != nil {
log.Errorf("failed to marshal request: %v", err)
return rpcRes, rpcErr, err
}
_, err = rpc.conn.Write(xmlBytes)
if err != nil {
log.Debugf("rpc client send failed: %v", err)
return rpcRes, rpcErr, err
}
def := NewLuxRpcDefrag()
part := make([]byte, 1500)
for {
n, err := rpc.conn.Read(part)
if err != nil {
log.Debugf("rpc client recv failed: %v", err)
return rpcRes, rpcErr, err
}
if def.Feed(part[n:]) {
// got full data, either its response or error
if def.HasResponse() {
xmlBytes := def.GetAndForget()
if err := xml.Unmarshal(xmlBytes, &rpcRes); err != nil {
return rpcRes, rpcErr, fmt.Errorf("failed to unmarshal rpc response %v: %s", err, string(xmlBytes))
}
return rpcRes, rpcErr, nil
} else if def.HasError() {
xmlBytes := def.GetAndForget()
if err := xml.Unmarshal(xmlBytes, &rpcErr); err != nil {
return rpcRes, rpcErr, fmt.Errorf("failed to unmarshal rpc error %v: %s", err, string(xmlBytes))
}
return rpcRes, rpcErr, nil
} else {
return rpcRes, rpcErr, fmt.Errorf("got unknown response from rpc server: %s", string(def.GetAndForget()))
}
}
}
}