implement RPC client, tho bug - client does not receive response
This commit is contained in:
parent
9d15dba9d5
commit
e532b5c57b
4 changed files with 132 additions and 0 deletions
80
rpc/lux_rpc_client.go
Normal file
80
rpc/lux_rpc_client.go
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
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()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,7 @@ package rpc
|
||||||
import (
|
import (
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -41,6 +42,11 @@ func (rpc *LuxRpcServer) HandleRequest(request LuxRpcRequest, rpcType LuxRpcType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rpc *LuxRpcServer) AddEndpoint(network string, listenOn string, rpcType LuxRpcType) error {
|
func (rpc *LuxRpcServer) AddEndpoint(network string, listenOn string, rpcType LuxRpcType) error {
|
||||||
|
// cleanup old socket files
|
||||||
|
if network == "unix" {
|
||||||
|
os.Remove(listenOn)
|
||||||
|
}
|
||||||
|
|
||||||
listener, err := net.Listen(network, listenOn)
|
listener, err := net.Listen(network, listenOn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
46
tests/lux_rpc_server_test.go
Normal file
46
tests/lux_rpc_server_test.go
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"lux/rpc"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DummyController struct {
|
||||||
|
t *testing.T
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctrl *DummyController) GetRpcName() string {
|
||||||
|
return "dummy"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctrl *DummyController) Register(sv *rpc.LuxRpcServer) {}
|
||||||
|
|
||||||
|
func (ctrl *DummyController) Handle(request rpc.LuxRpcRequest, rpcType rpc.LuxRpcType) (rpc.LuxRpcResponse, rpc.LuxRpcError, bool) {
|
||||||
|
ctrl.t.Log(request, rpcType)
|
||||||
|
|
||||||
|
return rpc.LuxRpcResponse{}, rpc.LuxRpcError{}, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRpcServerClient(t *testing.T) {
|
||||||
|
sv := rpc.NewLuxRpcServer()
|
||||||
|
sv.RegisterController(&DummyController{t: t})
|
||||||
|
err := sv.AddEndpoint("unix", "/tmp/lux-rpc-test.sock", rpc.LuxRpcTypeRoot)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cl, err := rpc.LuxDialRpc("unix", "/tmp/lux-rpc-test.sock")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rpcRes, rpcErr, err := cl.Execute(rpc.LuxRpcRequest{
|
||||||
|
Controller: "dummy",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log(rpcRes)
|
||||||
|
t.Log(rpcErr)
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue