80 lines
1.8 KiB
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()))
|
|
}
|
|
}
|
|
}
|
|
}
|