2016-04-21 13:12:43 +02:00
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// 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 ;
2016-07-25 16:09:47 +02:00
use ethcore_rpc ::{ RpcServerError , RpcServer as Server } ;
2016-05-04 15:37:09 +02:00
use jsonipc ;
2016-06-01 19:37:34 +02:00
use rpc_apis ;
2016-07-25 16:09:47 +02:00
use rpc_apis ::ApiSet ;
use helpers ::parity_ipc_path ;
2016-04-21 13:12:43 +02:00
2016-07-25 16:09:47 +02:00
pub use jsonipc ::Server as IpcServer ;
pub use ethcore_rpc ::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 {
IpcConfiguration {
enabled : true ,
socket_addr : parity_ipc_path ( " $HOME/.parity/jsonrpc.ipc " ) ,
apis : ApiSet ::UnsafeContext ,
}
}
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 > ,
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-07-25 16:09:47 +02:00
let addr = try ! ( url . parse ( ) . map_err ( | _ | format! ( " Invalid JSONRPC listen host/port given: {} " , url ) ) ) ;
Ok ( Some ( try ! ( setup_http_rpc_server ( deps , & addr , conf . cors , conf . hosts , conf . apis ) ) ) )
2016-04-21 13:57:27 +02:00
}
2016-07-25 16:09:47 +02:00
fn setup_rpc_server ( apis : ApiSet , deps : & Dependencies ) -> Result < Server , String > {
2016-04-21 13:12:43 +02:00
let server = Server ::new ( ) ;
2016-07-25 16:09:47 +02:00
Ok ( rpc_apis ::setup_rpc ( server , 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 > {
let server = try ! ( setup_rpc_server ( apis , dependencies ) ) ;
2016-06-01 19:37:34 +02:00
let ph = dependencies . panic_handler . clone ( ) ;
2016-07-20 12:34:17 +02:00
let start_result = server . start_http ( url , cors_domains , allowed_hosts , ph ) ;
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
2016-07-25 16:09:47 +02:00
pub fn new_ipc ( conf : IpcConfiguration , deps : & Dependencies ) -> Result < Option < IpcServer > , String > {
if ! conf . enabled { return Ok ( None ) ; }
Ok ( Some ( try ! ( setup_ipc_rpc_server ( deps , & conf . socket_addr , conf . apis ) ) ) )
2016-06-13 18:55:24 +02:00
}
2016-07-25 16:09:47 +02:00
pub fn setup_ipc_rpc_server ( dependencies : & Dependencies , addr : & str , apis : ApiSet ) -> Result < IpcServer , String > {
let server = try ! ( setup_rpc_server ( apis , dependencies ) ) ;
2016-05-04 15:37:09 +02:00
match server . start_ipc ( addr ) {
2016-07-25 16:09:47 +02:00
Err ( jsonipc ::Error ::Io ( io_error ) ) = > Err ( format! ( " RPC io error: {} " , io_error ) ) ,
Err ( any_error ) = > Err ( format! ( " Rpc error: {:?} " , any_error ) ) ,
Ok ( server ) = > Ok ( server )
2016-05-04 15:37:09 +02:00
}
}