github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/rpc/comms/comms.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package comms 18 19 import ( 20 "io" 21 "net" 22 23 "fmt" 24 "strings" 25 26 "strconv" 27 28 "github.com/ethereum/go-ethereum/logger" 29 "github.com/ethereum/go-ethereum/logger/glog" 30 "github.com/ethereum/go-ethereum/rpc/codec" 31 "github.com/ethereum/go-ethereum/rpc/shared" 32 ) 33 34 const ( 35 maxHttpSizeReqLength = 1024 * 1024 // 1MB 36 ) 37 38 var ( 39 // List with all API's which are offered over the in proc interface by default 40 DefaultInProcApis = shared.AllApis 41 42 // List with all API's which are offered over the IPC interface by default 43 DefaultIpcApis = shared.AllApis 44 45 // List with API's which are offered over thr HTTP/RPC interface by default 46 DefaultHttpRpcApis = strings.Join([]string{ 47 shared.DbApiName, shared.EthApiName, shared.NetApiName, shared.Web3ApiName, 48 }, ",") 49 ) 50 51 type EthereumClient interface { 52 // Close underlying connection 53 Close() 54 // Send request 55 Send(interface{}) error 56 // Receive response 57 Recv() (interface{}, error) 58 // List with modules this client supports 59 SupportedModules() (map[string]string, error) 60 } 61 62 func handle(id int, conn net.Conn, api shared.EthereumApi, c codec.Codec) { 63 codec := c.New(conn) 64 65 for { 66 requests, isBatch, err := codec.ReadRequest() 67 if err == io.EOF { 68 codec.Close() 69 return 70 } else if err != nil { 71 codec.Close() 72 glog.V(logger.Debug).Infof("Closed IPC Conn %06d recv err - %v\n", id, err) 73 return 74 } 75 76 if isBatch { 77 responses := make([]*interface{}, len(requests)) 78 responseCount := 0 79 for _, req := range requests { 80 res, err := api.Execute(req) 81 if req.Id != nil { 82 rpcResponse := shared.NewRpcResponse(req.Id, req.Jsonrpc, res, err) 83 responses[responseCount] = rpcResponse 84 responseCount += 1 85 } 86 } 87 88 err = codec.WriteResponse(responses[:responseCount]) 89 if err != nil { 90 codec.Close() 91 glog.V(logger.Debug).Infof("Closed IPC Conn %06d send err - %v\n", id, err) 92 return 93 } 94 } else { 95 var rpcResponse interface{} 96 res, err := api.Execute(requests[0]) 97 98 rpcResponse = shared.NewRpcResponse(requests[0].Id, requests[0].Jsonrpc, res, err) 99 err = codec.WriteResponse(rpcResponse) 100 if err != nil { 101 codec.Close() 102 glog.V(logger.Debug).Infof("Closed IPC Conn %06d send err - %v\n", id, err) 103 return 104 } 105 } 106 } 107 } 108 109 // Endpoint must be in the form of: 110 // ${protocol}:${path} 111 // e.g. ipc:/tmp/geth.ipc 112 // rpc:localhost:8545 113 func ClientFromEndpoint(endpoint string, c codec.Codec) (EthereumClient, error) { 114 if strings.HasPrefix(endpoint, "ipc:") { 115 cfg := IpcConfig{ 116 Endpoint: endpoint[4:], 117 } 118 return NewIpcClient(cfg, codec.JSON) 119 } 120 121 if strings.HasPrefix(endpoint, "rpc:") { 122 parts := strings.Split(endpoint, ":") 123 addr := "http://localhost" 124 port := uint(8545) 125 if len(parts) >= 3 { 126 addr = parts[1] + ":" + parts[2] 127 } 128 129 if len(parts) >= 4 { 130 p, err := strconv.Atoi(parts[3]) 131 132 if err != nil { 133 return nil, err 134 } 135 port = uint(p) 136 } 137 138 cfg := HttpConfig{ 139 ListenAddress: addr, 140 ListenPort: port, 141 } 142 143 return NewHttpClient(cfg, codec.JSON), nil 144 } 145 146 return nil, fmt.Errorf("Invalid endpoint") 147 }