2016-12-11 19:30:54 +01:00
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
2016-04-21 13:12:43 +02:00
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
2016-07-25 16:09:47 +02:00
use std ::fmt ;
2016-04-21 13:12:43 +02:00
use std ::sync ::Arc ;
use std ::net ::SocketAddr ;
2016-10-25 15:55:53 +02:00
use std ::io ;
2016-08-05 10:32:04 +02:00
use io ::PanicHandler ;
2017-01-11 20:02:27 +01:00
use dir ::default_data_path ;
use ethcore_rpc ::{ self as rpc , RpcServerError , IpcServerError , Metadata } ;
use helpers ::parity_ipc_path ;
use jsonrpc_core ::MetaIoHandler ;
use jsonrpc_core ::reactor ::{ RpcHandler , Remote } ;
2016-06-01 19:37:34 +02:00
use rpc_apis ;
2016-07-25 16:09:47 +02:00
use rpc_apis ::ApiSet ;
2016-04-21 13:12:43 +02:00
2016-11-22 11:56:27 +01:00
pub use ethcore_rpc ::{ IpcServer , Server as HttpServer } ;
2016-04-21 13:12:43 +02:00
2016-07-25 16:09:47 +02:00
#[ derive(Debug, PartialEq) ]
2016-05-04 15:37:09 +02:00
pub struct HttpConfiguration {
2016-04-21 13:57:27 +02:00
pub enabled : bool ,
pub interface : String ,
pub port : u16 ,
2016-07-25 16:09:47 +02:00
pub apis : ApiSet ,
2016-07-20 12:34:17 +02:00
pub cors : Option < Vec < String > > ,
pub hosts : Option < Vec < String > > ,
2016-04-21 13:57:27 +02:00
}
2016-07-25 16:09:47 +02:00
impl Default for HttpConfiguration {
fn default ( ) -> Self {
HttpConfiguration {
enabled : true ,
interface : " 127.0.0.1 " . into ( ) ,
port : 8545 ,
apis : ApiSet ::UnsafeContext ,
cors : None ,
hosts : Some ( Vec ::new ( ) ) ,
}
}
}
#[ derive(Debug, PartialEq) ]
2016-05-04 15:37:09 +02:00
pub struct IpcConfiguration {
pub enabled : bool ,
pub socket_addr : String ,
2016-07-25 16:09:47 +02:00
pub apis : ApiSet ,
}
impl Default for IpcConfiguration {
fn default ( ) -> Self {
2016-12-13 23:38:29 +01:00
let data_dir = default_data_path ( ) ;
2016-07-25 16:09:47 +02:00
IpcConfiguration {
enabled : true ,
2016-12-15 21:56:45 +01:00
socket_addr : parity_ipc_path ( & data_dir , " $BASE/jsonrpc.ipc " ) ,
2016-11-04 09:58:39 +01:00
apis : ApiSet ::IpcContext ,
2016-07-25 16:09:47 +02:00
}
}
2016-05-04 15:37:09 +02:00
}
2016-06-13 18:55:24 +02:00
impl fmt ::Display for IpcConfiguration {
fn fmt ( & self , f : & mut fmt ::Formatter ) -> fmt ::Result {
if self . enabled {
2016-07-25 16:09:47 +02:00
write! ( f , " endpoint address [{}], api list [{:?}] " , self . socket_addr , self . apis )
} else {
2016-06-13 18:55:24 +02:00
write! ( f , " disabled " )
}
}
}
2016-04-21 13:57:27 +02:00
pub struct Dependencies {
2016-04-23 12:29:12 +02:00
pub panic_handler : Arc < PanicHandler > ,
2016-06-01 19:37:34 +02:00
pub apis : Arc < rpc_apis ::Dependencies > ,
2017-01-11 20:02:27 +01:00
pub remote : Remote ,
2016-04-21 13:57:27 +02:00
}
2016-07-25 16:09:47 +02:00
pub fn new_http ( conf : HttpConfiguration , deps : & Dependencies ) -> Result < Option < HttpServer > , String > {
2016-04-21 13:57:27 +02:00
if ! conf . enabled {
2016-07-25 16:09:47 +02:00
return Ok ( None ) ;
2016-04-21 13:57:27 +02:00
}
2016-06-24 12:10:36 +02:00
let url = format! ( " {} : {} " , conf . interface , conf . port ) ;
2016-12-27 12:53:56 +01:00
let addr = url . parse ( ) . map_err ( | _ | format! ( " Invalid JSONRPC listen host/port given: {} " , url ) ) ? ;
Ok ( Some ( setup_http_rpc_server ( deps , & addr , conf . cors , conf . hosts , conf . apis ) ? ) )
2016-04-21 13:57:27 +02:00
}
2017-01-11 20:02:27 +01:00
fn setup_apis ( apis : ApiSet , deps : & Dependencies ) -> MetaIoHandler < Metadata > {
rpc_apis ::setup_rpc ( MetaIoHandler ::default ( ) , deps . apis . clone ( ) , apis )
2016-05-04 15:37:09 +02:00
}
pub fn setup_http_rpc_server (
2016-06-01 19:37:34 +02:00
dependencies : & Dependencies ,
2016-05-04 15:37:09 +02:00
url : & SocketAddr ,
2016-07-20 12:34:17 +02:00
cors_domains : Option < Vec < String > > ,
allowed_hosts : Option < Vec < String > > ,
2016-07-25 16:09:47 +02:00
apis : ApiSet
) -> Result < HttpServer , String > {
2017-01-11 20:02:27 +01:00
let apis = setup_apis ( apis , dependencies ) ;
let handler = RpcHandler ::new ( Arc ::new ( apis ) , dependencies . remote . clone ( ) ) ;
2016-06-01 19:37:34 +02:00
let ph = dependencies . panic_handler . clone ( ) ;
2017-01-11 20:02:27 +01:00
let start_result = rpc ::start_http ( url , cors_domains , allowed_hosts , ph , handler ) ;
2016-04-21 13:12:43 +02:00
match start_result {
2016-10-25 15:55:53 +02:00
Err ( RpcServerError ::IoError ( err ) ) = > match err . kind ( ) {
io ::ErrorKind ::AddrInUse = > Err ( format! ( " RPC address {} is already in use, make sure that another instance of an Ethereum client is not running or change the address using the --jsonrpc-port and --jsonrpc-interface options. " , url ) ) ,
_ = > Err ( format! ( " RPC io error: {} " , err ) ) ,
} ,
2016-07-25 16:09:47 +02:00
Err ( e ) = > Err ( format! ( " RPC error: {:?} " , e ) ) ,
Ok ( server ) = > Ok ( server ) ,
2016-04-21 13:12:43 +02:00
}
}
2016-06-13 18:55:24 +02:00
2017-01-11 20:02:27 +01:00
pub fn new_ipc ( conf : IpcConfiguration , deps : & Dependencies ) -> Result < Option < IpcServer < Metadata > > , String > {
2016-07-25 16:09:47 +02:00
if ! conf . enabled { return Ok ( None ) ; }
2016-12-27 12:53:56 +01:00
Ok ( Some ( setup_ipc_rpc_server ( deps , & conf . socket_addr , conf . apis ) ? ) )
2016-06-13 18:55:24 +02:00
}
2017-01-11 20:02:27 +01:00
pub fn setup_ipc_rpc_server ( dependencies : & Dependencies , addr : & str , apis : ApiSet ) -> Result < IpcServer < Metadata > , String > {
let apis = setup_apis ( apis , dependencies ) ;
let handler = RpcHandler ::new ( Arc ::new ( apis ) , dependencies . remote . clone ( ) ) ;
match rpc ::start_ipc ( addr , handler ) {
2016-11-22 11:56:27 +01:00
Err ( IpcServerError ::Io ( io_error ) ) = > Err ( format! ( " RPC io error: {} " , io_error ) ) ,
2016-07-25 16:09:47 +02:00
Err ( any_error ) = > Err ( format! ( " Rpc error: {:?} " , any_error ) ) ,
Ok ( server ) = > Ok ( server )
2016-05-04 15:37:09 +02:00
}
}