| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // Copyright 2015 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // This file is part of the go-ethereum library. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-23 18:35:11 +02:00
										 |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-08 10:41:04 +02:00
										 |  |  | package comms | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-16 11:16:50 +02:00
										 |  |  | import ( | 
					
						
							|  |  |  | 	"io" | 
					
						
							|  |  |  | 	"net" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-18 18:23:13 +02:00
										 |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-19 12:32:40 +02:00
										 |  |  | 	"strconv" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-16 11:16:50 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/logger" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/logger/glog" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/rpc/codec" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/rpc/shared" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-16 13:07:13 +02:00
										 |  |  | const ( | 
					
						
							|  |  |  | 	maxHttpSizeReqLength = 1024 * 1024 // 1MB | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-17 16:22:35 +02:00
										 |  |  | var ( | 
					
						
							|  |  |  | 	// List with all API's which are offered over the in proc interface by default | 
					
						
							| 
									
										
										
										
											2015-06-22 12:47:32 +02:00
										 |  |  | 	DefaultInProcApis = shared.AllApis | 
					
						
							| 
									
										
										
										
											2015-06-17 16:22:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// List with all API's which are offered over the IPC interface by default | 
					
						
							| 
									
										
										
										
											2015-06-22 12:47:32 +02:00
										 |  |  | 	DefaultIpcApis = shared.AllApis | 
					
						
							| 
									
										
										
										
											2015-06-17 16:22:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// List with API's which are offered over thr HTTP/RPC interface by default | 
					
						
							|  |  |  | 	DefaultHttpRpcApis = strings.Join([]string{ | 
					
						
							| 
									
										
										
										
											2015-06-22 12:47:32 +02:00
										 |  |  | 		shared.DbApiName, shared.EthApiName, shared.NetApiName, shared.Web3ApiName, | 
					
						
							| 
									
										
										
										
											2015-06-18 18:23:13 +02:00
										 |  |  | 	}, ",") | 
					
						
							| 
									
										
										
										
											2015-06-17 16:22:35 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-08 10:41:04 +02:00
										 |  |  | type EthereumClient interface { | 
					
						
							| 
									
										
										
										
											2015-08-07 09:56:49 +02:00
										 |  |  | 	// Close underlying connection | 
					
						
							| 
									
										
										
										
											2015-06-08 10:41:04 +02:00
										 |  |  | 	Close() | 
					
						
							| 
									
										
										
										
											2015-06-17 16:22:35 +02:00
										 |  |  | 	// Send request | 
					
						
							| 
									
										
										
										
											2015-06-08 10:41:04 +02:00
										 |  |  | 	Send(interface{}) error | 
					
						
							| 
									
										
										
										
											2015-06-17 16:22:35 +02:00
										 |  |  | 	// Receive response | 
					
						
							| 
									
										
										
										
											2015-06-08 10:41:04 +02:00
										 |  |  | 	Recv() (interface{}, error) | 
					
						
							| 
									
										
										
										
											2015-06-18 18:23:13 +02:00
										 |  |  | 	// List with modules this client supports | 
					
						
							|  |  |  | 	SupportedModules() (map[string]string, error) | 
					
						
							| 
									
										
										
										
											2015-06-08 10:41:04 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-06-16 11:16:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-25 15:54:16 +02:00
										 |  |  | func handle(id int, conn net.Conn, api shared.EthereumApi, c codec.Codec) { | 
					
						
							| 
									
										
										
										
											2015-06-16 11:16:50 +02:00
										 |  |  | 	codec := c.New(conn) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-29 08:40:07 +01:00
										 |  |  | 	defer func() { | 
					
						
							|  |  |  | 		if r := recover(); r != nil { | 
					
						
							|  |  |  | 			glog.Errorf("panic: %v\n", r) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		codec.Close() | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-16 11:16:50 +02:00
										 |  |  | 	for { | 
					
						
							| 
									
										
										
										
											2015-06-25 12:01:28 +02:00
										 |  |  | 		requests, isBatch, err := codec.ReadRequest() | 
					
						
							| 
									
										
										
										
											2015-06-16 11:16:50 +02:00
										 |  |  | 		if err == io.EOF { | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		} else if err != nil { | 
					
						
							| 
									
										
										
										
											2015-06-25 15:54:16 +02:00
										 |  |  | 			glog.V(logger.Debug).Infof("Closed IPC Conn %06d recv err - %v\n", id, err) | 
					
						
							| 
									
										
										
										
											2015-06-16 11:16:50 +02:00
										 |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-25 12:01:28 +02:00
										 |  |  | 		if isBatch { | 
					
						
							|  |  |  | 			responses := make([]*interface{}, len(requests)) | 
					
						
							|  |  |  | 			responseCount := 0 | 
					
						
							|  |  |  | 			for _, req := range requests { | 
					
						
							|  |  |  | 				res, err := api.Execute(req) | 
					
						
							|  |  |  | 				if req.Id != nil { | 
					
						
							|  |  |  | 					rpcResponse := shared.NewRpcResponse(req.Id, req.Jsonrpc, res, err) | 
					
						
							|  |  |  | 					responses[responseCount] = rpcResponse | 
					
						
							|  |  |  | 					responseCount += 1 | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-06-16 11:16:50 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-25 12:01:28 +02:00
										 |  |  | 			err = codec.WriteResponse(responses[:responseCount]) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2015-06-25 15:54:16 +02:00
										 |  |  | 				glog.V(logger.Debug).Infof("Closed IPC Conn %06d send err - %v\n", id, err) | 
					
						
							| 
									
										
										
										
											2015-06-25 12:01:28 +02:00
										 |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			var rpcResponse interface{} | 
					
						
							|  |  |  | 			res, err := api.Execute(requests[0]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			rpcResponse = shared.NewRpcResponse(requests[0].Id, requests[0].Jsonrpc, res, err) | 
					
						
							|  |  |  | 			err = codec.WriteResponse(rpcResponse) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2015-06-25 15:54:16 +02:00
										 |  |  | 				glog.V(logger.Debug).Infof("Closed IPC Conn %06d send err - %v\n", id, err) | 
					
						
							| 
									
										
										
										
											2015-06-25 12:01:28 +02:00
										 |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-06-16 11:16:50 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-06-18 18:23:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Endpoint must be in the form of: | 
					
						
							|  |  |  | // ${protocol}:${path} | 
					
						
							|  |  |  | // e.g. ipc:/tmp/geth.ipc | 
					
						
							|  |  |  | //      rpc:localhost:8545 | 
					
						
							|  |  |  | func ClientFromEndpoint(endpoint string, c codec.Codec) (EthereumClient, error) { | 
					
						
							|  |  |  | 	if strings.HasPrefix(endpoint, "ipc:") { | 
					
						
							|  |  |  | 		cfg := IpcConfig{ | 
					
						
							|  |  |  | 			Endpoint: endpoint[4:], | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return NewIpcClient(cfg, codec.JSON) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if strings.HasPrefix(endpoint, "rpc:") { | 
					
						
							| 
									
										
										
										
											2015-06-19 12:32:40 +02:00
										 |  |  | 		parts := strings.Split(endpoint, ":") | 
					
						
							|  |  |  | 		addr := "http://localhost" | 
					
						
							|  |  |  | 		port := uint(8545) | 
					
						
							|  |  |  | 		if len(parts) >= 3 { | 
					
						
							|  |  |  | 			addr = parts[1] + ":" + parts[2] | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if len(parts) >= 4 { | 
					
						
							|  |  |  | 			p, err := strconv.Atoi(parts[3]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			port = uint(p) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		cfg := HttpConfig{ | 
					
						
							|  |  |  | 			ListenAddress: addr, | 
					
						
							|  |  |  | 			ListenPort:    port, | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-06-18 18:23:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-19 12:32:40 +02:00
										 |  |  | 		return NewHttpClient(cfg, codec.JSON), nil | 
					
						
							| 
									
										
										
										
											2015-06-18 18:23:13 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil, fmt.Errorf("Invalid endpoint") | 
					
						
							|  |  |  | } |