@ -0,0 +1,110 @@ | |||
package benchmarks | |||
import ( | |||
"testing" | |||
"github.com/tendermint/go-crypto" | |||
"github.com/tendermint/go-p2p" | |||
"github.com/tendermint/go-wire" | |||
proto "github.com/tendermint/tendermint/benchmarks/proto" | |||
ctypes "github.com/tendermint/tendermint/rpc/core/types" | |||
) | |||
func BenchmarkEncodeStatusWire(b *testing.B) { | |||
b.StopTimer() | |||
pubKey := crypto.GenPrivKeyEd25519().PubKey().(crypto.PubKeyEd25519) | |||
status := &ctypes.ResultStatus{ | |||
NodeInfo: &p2p.NodeInfo{ | |||
PubKey: pubKey, | |||
Moniker: "SOMENAME", | |||
Network: "SOMENAME", | |||
RemoteAddr: "SOMEADDR", | |||
ListenAddr: "SOMEADDR", | |||
Version: "SOMEVER", | |||
Other: []string{"SOMESTRING", "OTHERSTRING"}, | |||
}, | |||
PubKey: pubKey, | |||
LatestBlockHash: []byte("SOMEBYTES"), | |||
LatestBlockHeight: 123, | |||
LatestBlockTime: 1234, | |||
} | |||
b.StartTimer() | |||
counter := 0 | |||
for i := 0; i < b.N; i++ { | |||
jsonBytes := wire.JSONBytes(status) | |||
counter += len(jsonBytes) | |||
} | |||
} | |||
func BenchmarkEncodeNodeInfoWire(b *testing.B) { | |||
b.StopTimer() | |||
pubKey := crypto.GenPrivKeyEd25519().PubKey().(crypto.PubKeyEd25519) | |||
nodeInfo := &p2p.NodeInfo{ | |||
PubKey: pubKey, | |||
Moniker: "SOMENAME", | |||
Network: "SOMENAME", | |||
RemoteAddr: "SOMEADDR", | |||
ListenAddr: "SOMEADDR", | |||
Version: "SOMEVER", | |||
Other: []string{"SOMESTRING", "OTHERSTRING"}, | |||
} | |||
b.StartTimer() | |||
counter := 0 | |||
for i := 0; i < b.N; i++ { | |||
jsonBytes := wire.JSONBytes(nodeInfo) | |||
counter += len(jsonBytes) | |||
} | |||
} | |||
func BenchmarkEncodeNodeInfoBinary(b *testing.B) { | |||
b.StopTimer() | |||
pubKey := crypto.GenPrivKeyEd25519().PubKey().(crypto.PubKeyEd25519) | |||
nodeInfo := &p2p.NodeInfo{ | |||
PubKey: pubKey, | |||
Moniker: "SOMENAME", | |||
Network: "SOMENAME", | |||
RemoteAddr: "SOMEADDR", | |||
ListenAddr: "SOMEADDR", | |||
Version: "SOMEVER", | |||
Other: []string{"SOMESTRING", "OTHERSTRING"}, | |||
} | |||
b.StartTimer() | |||
counter := 0 | |||
for i := 0; i < b.N; i++ { | |||
jsonBytes := wire.BinaryBytes(nodeInfo) | |||
counter += len(jsonBytes) | |||
} | |||
} | |||
func BenchmarkEncodeNodeInfoProto(b *testing.B) { | |||
b.StopTimer() | |||
pubKey := crypto.GenPrivKeyEd25519().PubKey().(crypto.PubKeyEd25519) | |||
pubKey2 := &proto.PubKey{Ed25519: &proto.PubKeyEd25519{Bytes: pubKey[:]}} | |||
nodeInfo := &proto.NodeInfo{ | |||
PubKey: pubKey2, | |||
Moniker: "SOMENAME", | |||
Network: "SOMENAME", | |||
RemoteAddr: "SOMEADDR", | |||
ListenAddr: "SOMEADDR", | |||
Version: "SOMEVER", | |||
Other: []string{"SOMESTRING", "OTHERSTRING"}, | |||
} | |||
b.StartTimer() | |||
counter := 0 | |||
for i := 0; i < b.N; i++ { | |||
bytes, err := nodeInfo.Marshal() | |||
if err != nil { | |||
b.Fatal(err) | |||
return | |||
} | |||
//jsonBytes := wire.JSONBytes(nodeInfo) | |||
counter += len(bytes) | |||
} | |||
} |
@ -0,0 +1,2 @@ | |||
Doing some protobuf tests here. | |||
Using gogoprotobuf. |
@ -0,0 +1,25 @@ | |||
message ResultStatus { | |||
optional NodeInfo nodeInfo = 1; | |||
required PubKey pubKey = 2; | |||
required bytes latestBlockHash = 3; | |||
required int64 latestBlockHeight = 4; | |||
required int64 latestBlocktime = 5; | |||
} | |||
message NodeInfo { | |||
required PubKey pubKey = 1; | |||
required string moniker = 2; | |||
required string network = 3; | |||
required string remoteAddr = 4; | |||
required string listenAddr = 5; | |||
required string version = 6; | |||
repeated string other = 7; | |||
} | |||
message PubKey { | |||
optional PubKeyEd25519 ed25519 = 1; | |||
} | |||
message PubKeyEd25519 { | |||
required bytes bytes = 1; | |||
} |
@ -0,0 +1,56 @@ | |||
package main | |||
import ( | |||
"encoding/binary" | |||
"time" | |||
//"encoding/hex" | |||
"fmt" | |||
"github.com/gorilla/websocket" | |||
. "github.com/tendermint/go-common" | |||
"github.com/tendermint/go-wire" | |||
"github.com/tendermint/tendermint/rpc/client" | |||
// ctypes "github.com/tendermint/tendermint/rpc/core/types" | |||
"github.com/tendermint/tendermint/rpc/types" | |||
) | |||
func main() { | |||
ws := rpcclient.NewWSClient("ws://127.0.0.1:46657/websocket") | |||
// ws := rpcclient.NewWSClient("ws://104.236.69.128:46657/websocket") | |||
_, err := ws.Start() | |||
if err != nil { | |||
Exit(err.Error()) | |||
} | |||
// Read a bunch of responses | |||
go func() { | |||
for { | |||
_, ok := <-ws.ResultsCh | |||
if !ok { | |||
break | |||
} | |||
//fmt.Println("Received response", string(wire.JSONBytes(res))) | |||
} | |||
}() | |||
// Make a bunch of requests | |||
buf := make([]byte, 32) | |||
for i := 0; ; i++ { | |||
binary.LittleEndian.PutUint64(buf, uint64(i)) | |||
//txBytes := hex.EncodeToString(buf[:n]) | |||
request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx", Arr(buf[:8])) | |||
reqBytes := wire.JSONBytes(request) | |||
//fmt.Println("!!", string(reqBytes)) | |||
fmt.Print(".") | |||
err := ws.WriteMessage(websocket.TextMessage, reqBytes) | |||
if err != nil { | |||
Exit(err.Error()) | |||
} | |||
if i%1000 == 0 { | |||
fmt.Println(i) | |||
} | |||
time.Sleep(time.Microsecond * 250) | |||
} | |||
ws.Stop() | |||
} |
@ -0,0 +1,7 @@ | |||
package proxy | |||
import ( | |||
"github.com/tendermint/go-logger" | |||
) | |||
var log = logger.New("module", "proxy") |
@ -0,0 +1,126 @@ | |||
package rpcclient | |||
import ( | |||
"net/http" | |||
"strings" | |||
"time" | |||
"github.com/gorilla/websocket" | |||
. "github.com/tendermint/go-common" | |||
"github.com/tendermint/go-wire" | |||
ctypes "github.com/tendermint/tendermint/rpc/core/types" | |||
"github.com/tendermint/tendermint/rpc/types" | |||
) | |||
const ( | |||
wsEventsChannelCapacity = 10 | |||
wsResultsChannelCapacity = 10 | |||
wsWriteTimeoutSeconds = 10 | |||
) | |||
type WSClient struct { | |||
QuitService | |||
Address string | |||
*websocket.Conn | |||
EventsCh chan ctypes.ResultEvent // closes upon WSClient.Stop() | |||
ResultsCh chan ctypes.Result // closes upon WSClient.Stop() | |||
} | |||
// create a new connection | |||
func NewWSClient(addr string) *WSClient { | |||
wsClient := &WSClient{ | |||
Address: addr, | |||
Conn: nil, | |||
EventsCh: make(chan ctypes.ResultEvent, wsEventsChannelCapacity), | |||
ResultsCh: make(chan ctypes.Result, wsResultsChannelCapacity), | |||
} | |||
wsClient.QuitService = *NewQuitService(log, "WSClient", wsClient) | |||
return wsClient | |||
} | |||
func (wsc *WSClient) OnStart() error { | |||
wsc.QuitService.OnStart() | |||
err := wsc.dial() | |||
if err != nil { | |||
return err | |||
} | |||
go wsc.receiveEventsRoutine() | |||
return nil | |||
} | |||
func (wsc *WSClient) dial() error { | |||
// Dial | |||
dialer := websocket.DefaultDialer | |||
rHeader := http.Header{} | |||
con, _, err := dialer.Dial(wsc.Address, rHeader) | |||
if err != nil { | |||
return err | |||
} | |||
// Set the ping/pong handlers | |||
con.SetPingHandler(func(m string) error { | |||
// NOTE: https://github.com/gorilla/websocket/issues/97 | |||
go con.WriteControl(websocket.PongMessage, []byte(m), time.Now().Add(time.Second*wsWriteTimeoutSeconds)) | |||
return nil | |||
}) | |||
con.SetPongHandler(func(m string) error { | |||
// NOTE: https://github.com/gorilla/websocket/issues/97 | |||
return nil | |||
}) | |||
wsc.Conn = con | |||
return nil | |||
} | |||
func (wsc *WSClient) OnStop() { | |||
wsc.QuitService.OnStop() | |||
// EventsCh and ResultsCh are closed in receiveEventsRoutine. | |||
} | |||
func (wsc *WSClient) receiveEventsRoutine() { | |||
for { | |||
_, data, err := wsc.ReadMessage() | |||
if err != nil { | |||
log.Info("WSClient failed to read message", "error", err, "data", string(data)) | |||
wsc.Stop() | |||
break | |||
} else { | |||
var response ctypes.Response | |||
wire.ReadJSON(&response, data, &err) | |||
if err != nil { | |||
log.Info("WSClient failed to parse message", "error", err) | |||
wsc.Stop() | |||
break | |||
} | |||
if strings.HasSuffix(response.ID, "#event") { | |||
wsc.EventsCh <- *response.Result.(*ctypes.ResultEvent) | |||
} else { | |||
wsc.ResultsCh <- response.Result | |||
} | |||
} | |||
} | |||
// Cleanup | |||
close(wsc.EventsCh) | |||
close(wsc.ResultsCh) | |||
} | |||
// subscribe to an event | |||
func (wsc *WSClient) Subscribe(eventid string) error { | |||
err := wsc.WriteJSON(rpctypes.RPCRequest{ | |||
JSONRPC: "2.0", | |||
ID: "", | |||
Method: "subscribe", | |||
Params: []interface{}{eventid}, | |||
}) | |||
return err | |||
} | |||
// unsubscribe from an event | |||
func (wsc *WSClient) Unsubscribe(eventid string) error { | |||
err := wsc.WriteJSON(rpctypes.RPCRequest{ | |||
JSONRPC: "2.0", | |||
ID: "", | |||
Method: "unsubscribe", | |||
Params: []interface{}{eventid}, | |||
}) | |||
return err | |||
} |