@@ -27,6 +27,7 @@ import (
2727 "reflect"
2828 "strconv"
2929 "strings"
30+ "time"
3031 "unicode"
3132 "unicode/utf8"
3233)
@@ -36,7 +37,7 @@ const usage = `msgpack-cli
3637Usage:
3738 msgpack-cli encode <input-file> [--out=<output-file>]
3839 msgpack-cli decode <input-file> [--out=<output-file>] [--pp]
39- msgpack-cli rpc <host> <port> <method> [<params>|--file=<input-file>] [--pp]
40+ msgpack-cli rpc <host> <port> <method> [<params>|--file=<input-file>] [--pp] [--timeout=<timeout>]
4041 msgpack-cli -h | --help
4142 msgpack-cli --version
4243
@@ -51,6 +52,7 @@ Options:
5152 --out=<output-file> Write output data to file instead of STDOUT
5253 --file=<input-file> File where parameters or RPC method are read from
5354 --pp Pretty-print - indent output JSON data
55+ --timeout=<timeout> Timeout of RPC call [default: 30]
5456
5557Arguments:
5658 <input-file> File where data are read from
@@ -60,7 +62,13 @@ Arguments:
6062 <params> Parameters of RPC method in JSON format`
6163
6264type Options struct {
63- indent bool
65+ indent bool
66+ timeout uint32
67+ }
68+
69+ type RPCResult struct {
70+ reply interface {}
71+ err error
6472}
6573
6674func main () {
@@ -86,12 +94,21 @@ func main() {
8694 host := arguments ["<host>" ].(string )
8795 port := arguments ["<port>" ].(string )
8896 method := arguments ["<method>" ].(string )
89- params , err := getRPCParams (arguments )
97+ var params string
98+ params , err = getRPCParams (arguments )
99+ if err != nil {
100+ break
101+ }
102+ var timeout uint32
103+ timeout , err = getTimeout (arguments )
90104 if err != nil {
91105 break
92106 }
93107
94- options := Options {indent : arguments ["--pp" ].(bool )}
108+ options := Options {
109+ indent : arguments ["--pp" ].(bool ),
110+ timeout : timeout ,
111+ }
95112
96113 err = doRPC (host , port , method , params , options )
97114 default :
@@ -160,22 +177,31 @@ func doRPC(host, port, method, params string, options Options) error {
160177 }
161178 defer conn .Close ()
162179
163- var reply interface {}
164- if reply , err = callRPC (conn , method , args ); err != nil {
165- return err
166- }
180+ result := make (chan RPCResult )
181+ defer close (result )
167182
168- var jsonData string
169- if jsonData , err = encodeJSON (reply , options .indent ); err != nil {
170- return err
171- }
183+ go callRPC (result , conn , method , args )
184+
185+ select {
186+ case res := <- result :
187+ if res .err != nil {
188+ return res .err
189+ }
172190
173- fmt .Println (jsonData )
191+ var jsonData string
192+ if jsonData , err = encodeJSON (res .reply , options .indent ); err != nil {
193+ return err
194+ }
195+
196+ fmt .Println (jsonData )
197+ case <- time .After (time .Duration (options .timeout ) * time .Second ):
198+ return fmt .Errorf ("RPC call timed out" )
199+ }
174200
175201 return nil
176202}
177203
178- func callRPC (conn net.Conn , method string , args interface {}) ( interface {}, error ) {
204+ func callRPC (result chan <- RPCResult , conn net.Conn , method string , args interface {}) {
179205 handle := getHandle ()
180206 rpcCodec := codec .MsgpackSpecRpc .ClientCodec (conn , & handle )
181207 client := rpc .NewClientWithCodec (rpcCodec )
@@ -184,10 +210,10 @@ func callRPC(conn net.Conn, method string, args interface{}) (interface{}, error
184210 var mArgs codec.MsgpackSpecRpcMultiArgs = args .([]interface {})
185211
186212 if err := client .Call (method , mArgs , & reply ); err != nil {
187- return nil , fmt .Errorf ("RPC error: %s" , err )
213+ result <- RPCResult { reply : nil , err : fmt .Errorf ("RPC error: %s" , err )}
188214 }
189215
190- return reply , nil
216+ result <- RPCResult { reply : reply , err : nil }
191217}
192218
193219func convertJSON2Msgpack (data []byte , options Options ) (result []byte , err error ) {
@@ -279,3 +305,13 @@ func getRPCParams(arguments map[string]interface{}) (params string, err error) {
279305
280306 return params , nil
281307}
308+
309+ func getTimeout (arguments map [string ]interface {}) (timeout uint32 , err error ) {
310+ timeout = uint32 (30 )
311+ if str := arguments ["--timeout" ].(string ); str != "" {
312+ var tmp uint64
313+ tmp , err = strconv .ParseUint (str , 10 , 32 )
314+ timeout = uint32 (tmp )
315+ }
316+ return timeout , err
317+ }
0 commit comments