server.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /*
  2. This file is part of go-ethereum
  3. go-ethereum is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. go-ethereum is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. package rpcws
  15. import (
  16. "fmt"
  17. "net"
  18. "net/http"
  19. "code.google.com/p/go.net/websocket"
  20. "github.com/ethereum/go-ethereum/logger"
  21. "github.com/ethereum/go-ethereum/rpc"
  22. "github.com/ethereum/go-ethereum/xeth"
  23. )
  24. var wslogger = logger.NewLogger("RPC-WS")
  25. var JSON rpc.JsonWrapper
  26. type WebSocketServer struct {
  27. pipe *xeth.XEth
  28. port int
  29. doneCh chan bool
  30. listener net.Listener
  31. }
  32. func NewWebSocketServer(pipe *xeth.XEth, port int) (*WebSocketServer, error) {
  33. sport := fmt.Sprintf(":%d", port)
  34. l, err := net.Listen("tcp", sport)
  35. if err != nil {
  36. return nil, err
  37. }
  38. return &WebSocketServer{
  39. pipe,
  40. port,
  41. make(chan bool),
  42. l,
  43. }, nil
  44. }
  45. func (self *WebSocketServer) handlerLoop() {
  46. for {
  47. select {
  48. case <-self.doneCh:
  49. wslogger.Infoln("Shutdown RPC-WS server")
  50. return
  51. }
  52. }
  53. }
  54. func (self *WebSocketServer) Stop() {
  55. close(self.doneCh)
  56. }
  57. func (self *WebSocketServer) Start() {
  58. wslogger.Infof("Starting RPC-WS server on port %d", self.port)
  59. go self.handlerLoop()
  60. api := rpc.NewEthereumApi(self.pipe)
  61. h := self.apiHandler(api)
  62. http.Handle("/ws", h)
  63. err := http.Serve(self.listener, nil)
  64. if err != nil {
  65. wslogger.Errorln("Error on RPC-WS interface:", err)
  66. }
  67. }
  68. func (s *WebSocketServer) apiHandler(api *rpc.EthereumApi) http.Handler {
  69. fn := func(w http.ResponseWriter, req *http.Request) {
  70. h := sockHandler(api)
  71. s := websocket.Server{Handler: h}
  72. s.ServeHTTP(w, req)
  73. }
  74. return http.HandlerFunc(fn)
  75. }
  76. func sockHandler(api *rpc.EthereumApi) websocket.Handler {
  77. var jsonrpcver string = "2.0"
  78. fn := func(conn *websocket.Conn) {
  79. for {
  80. wslogger.Debugln("Handling connection")
  81. var reqParsed rpc.RpcRequest
  82. // reqParsed, reqerr := JSON.ParseRequestBody(conn.Request())
  83. if err := websocket.JSON.Receive(conn, &reqParsed); err != nil {
  84. jsonerr := &rpc.RpcErrorObject{-32700, rpc.ErrorParseRequest}
  85. JSON.Send(conn, &rpc.RpcErrorResponse{JsonRpc: jsonrpcver, ID: nil, Error: jsonerr})
  86. continue
  87. }
  88. var response interface{}
  89. reserr := api.GetRequestReply(&reqParsed, &response)
  90. if reserr != nil {
  91. wslogger.Warnln(reserr)
  92. jsonerr := &rpc.RpcErrorObject{-32603, reserr.Error()}
  93. JSON.Send(conn, &rpc.RpcErrorResponse{JsonRpc: jsonrpcver, ID: reqParsed.ID, Error: jsonerr})
  94. continue
  95. }
  96. wslogger.Debugf("Generated response: %T %s", response, response)
  97. JSON.Send(conn, &rpc.RpcSuccessResponse{JsonRpc: jsonrpcver, ID: reqParsed.ID, Result: response})
  98. }
  99. }
  100. return websocket.Handler(fn)
  101. }