2016-12-11 19:30:54 +01:00
// Copyright 2015, 2016 Parity Technologies (UK) Ltd.
2016-04-21 13:57:27 +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/>.
use std ::sync ::Arc ;
2016-08-05 10:32:04 +02:00
use io ::PanicHandler ;
2016-06-01 19:37:34 +02:00
use rpc_apis ;
2016-08-23 19:28:21 +02:00
use ethcore ::client ::Client ;
2016-09-01 11:16:19 +02:00
use ethsync ::SyncProvider ;
2016-07-25 16:09:47 +02:00
use helpers ::replace_home ;
2016-12-13 23:38:29 +01:00
use dir ::default_data_path ;
2016-12-27 11:15:02 +01:00
use rpc_apis ::SignerService ;
2016-12-22 18:26:39 +01:00
use hash_fetch ::fetch ::Client as FetchClient ;
use parity_reactor ::Remote ;
2016-04-21 13:57:27 +02:00
2016-07-25 16:09:47 +02:00
#[ derive(Debug, PartialEq, Clone) ]
2016-04-21 13:57:27 +02:00
pub struct Configuration {
pub enabled : bool ,
pub interface : String ,
pub port : u16 ,
2016-08-25 08:57:13 +02:00
pub hosts : Option < Vec < String > > ,
2016-04-21 13:57:27 +02:00
pub user : Option < String > ,
pub pass : Option < String > ,
2016-06-03 11:51:11 +02:00
pub dapps_path : String ,
2016-04-21 13:57:27 +02:00
}
2016-07-25 16:09:47 +02:00
impl Default for Configuration {
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
Configuration {
enabled : true ,
interface : " 127.0.0.1 " . into ( ) ,
port : 8080 ,
2016-08-25 08:57:13 +02:00
hosts : Some ( Vec ::new ( ) ) ,
2016-07-25 16:09:47 +02:00
user : None ,
pass : None ,
2016-12-15 21:56:45 +01:00
dapps_path : replace_home ( & data_dir , " $BASE/dapps " ) ,
2016-07-25 16:09:47 +02:00
}
}
}
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-08-23 19:28:21 +02:00
pub client : Arc < Client > ,
2016-09-01 11:16:19 +02:00
pub sync : Arc < SyncProvider > ,
2016-12-22 18:26:39 +01:00
pub remote : Remote ,
pub fetch : FetchClient ,
2016-12-27 11:15:02 +01:00
pub signer : Arc < SignerService > ,
2016-04-21 13:57:27 +02:00
}
2016-07-25 16:09:47 +02:00
pub fn new ( configuration : Configuration , deps : Dependencies ) -> Result < Option < WebappServer > , String > {
2016-04-21 13:57:27 +02:00
if ! configuration . 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! ( " {} : {} " , configuration . interface , configuration . port ) ;
2016-07-25 16:09:47 +02:00
let addr = try ! ( url . parse ( ) . map_err ( | _ | format! ( " Invalid Webapps listen host/port given: {} " , url ) ) ) ;
2016-04-21 13:57:27 +02:00
let auth = configuration . user . as_ref ( ) . map ( | username | {
let password = configuration . pass . as_ref ( ) . map_or_else ( | | {
use rpassword ::read_password ;
println! ( " Type password for WebApps server (user: {} ): " , username ) ;
let pass = read_password ( ) . unwrap ( ) ;
println! ( " OK, got it. Starting server... " ) ;
pass
} , | pass | pass . to_owned ( ) ) ;
( username . to_owned ( ) , password )
} ) ;
2016-12-27 11:15:02 +01:00
Ok ( Some ( try ! ( setup_dapps_server ( deps , configuration . dapps_path , & addr , configuration . hosts , auth ) ) ) )
2016-04-21 13:57:27 +02:00
}
2016-08-23 19:28:21 +02:00
pub use self ::server ::WebappServer ;
pub use self ::server ::setup_dapps_server ;
2016-05-26 18:21:15 +02:00
#[ cfg(not(feature = " dapps " )) ]
2016-08-23 19:28:21 +02:00
mod server {
use super ::Dependencies ;
use std ::net ::SocketAddr ;
pub struct WebappServer ;
pub fn setup_dapps_server (
_deps : Dependencies ,
_dapps_path : String ,
_url : & SocketAddr ,
2016-08-25 08:57:13 +02:00
_allowed_hosts : Option < Vec < String > > ,
2016-08-23 19:28:21 +02:00
_auth : Option < ( String , String ) > ,
) -> Result < WebappServer , String > {
Err ( " Your Parity version has been compiled without WebApps support. " . into ( ) )
}
2016-04-21 13:57:27 +02:00
}
2016-05-26 18:21:15 +02:00
#[ cfg(feature = " dapps " ) ]
2016-08-23 19:28:21 +02:00
mod server {
use super ::Dependencies ;
use std ::sync ::Arc ;
use std ::net ::SocketAddr ;
2016-10-25 15:55:53 +02:00
use std ::io ;
2016-08-23 19:28:21 +02:00
use util ::{ Bytes , Address , U256 } ;
use ethcore ::transaction ::{ Transaction , Action } ;
2016-12-09 23:01:43 +01:00
use ethcore ::client ::{ Client , BlockChainClient , BlockId } ;
2016-08-23 19:28:21 +02:00
use rpc_apis ;
2016-10-20 23:36:18 +02:00
use ethcore_rpc ::is_major_importing ;
2016-11-20 22:40:23 +01:00
use hash_fetch ::urlhint ::ContractClient ;
2016-08-23 19:28:21 +02:00
pub use ethcore_dapps ::Server as WebappServer ;
pub fn setup_dapps_server (
deps : Dependencies ,
dapps_path : String ,
url : & SocketAddr ,
2016-08-25 08:57:13 +02:00
allowed_hosts : Option < Vec < String > > ,
2016-10-19 11:02:21 +02:00
auth : Option < ( String , String ) > ,
2016-08-23 19:28:21 +02:00
) -> Result < WebappServer , String > {
use ethcore_dapps as dapps ;
2016-09-01 11:16:19 +02:00
let mut server = dapps ::ServerBuilder ::new (
dapps_path ,
2016-12-22 18:26:39 +01:00
Arc ::new ( Registrar { client : deps . client . clone ( ) } ) ,
deps . remote . clone ( ) ,
2016-09-01 11:16:19 +02:00
) ;
let sync = deps . sync . clone ( ) ;
2016-10-20 23:36:18 +02:00
let client = deps . client . clone ( ) ;
2016-12-27 11:15:02 +01:00
let signer = deps . signer . clone ( ) ;
2016-12-22 18:26:39 +01:00
server . with_fetch ( deps . fetch . clone ( ) ) ;
2016-10-20 23:36:18 +02:00
server . with_sync_status ( Arc ::new ( move | | is_major_importing ( Some ( sync . status ( ) . state ) , client . queue_info ( ) ) ) ) ;
2016-12-27 11:15:02 +01:00
server . with_web_proxy_tokens ( Arc ::new ( move | token | signer . is_valid_web_proxy_access_token ( & token ) ) ) ;
server . with_signer_address ( deps . signer . address ( ) ) ;
2016-10-19 11:02:21 +02:00
2016-08-23 19:28:21 +02:00
let server = rpc_apis ::setup_rpc ( server , deps . apis . clone ( ) , rpc_apis ::ApiSet ::UnsafeContext ) ;
let start_result = match auth {
None = > {
2016-08-25 08:57:13 +02:00
server . start_unsecured_http ( url , allowed_hosts )
2016-08-23 19:28:21 +02:00
} ,
Some ( ( username , password ) ) = > {
2016-08-25 08:57:13 +02:00
server . start_basic_auth_http ( url , allowed_hosts , & username , & password )
2016-08-23 19:28:21 +02:00
} ,
} ;
match start_result {
2016-10-25 15:55:53 +02:00
Err ( dapps ::ServerError ::IoError ( err ) ) = > match err . kind ( ) {
io ::ErrorKind ::AddrInUse = > Err ( format! ( " WebApps address {} is already in use, make sure that another instance of an Ethereum client is not running or change the address using the --dapps-port and --dapps-interface options. " , url ) ) ,
_ = > Err ( format! ( " WebApps io error: {} " , err ) ) ,
} ,
2016-08-23 19:28:21 +02:00
Err ( e ) = > Err ( format! ( " WebApps error: {:?} " , e ) ) ,
Ok ( server ) = > {
server . set_panic_handler ( move | | {
deps . panic_handler . notify_all ( " Panic in WebApp thread. " . to_owned ( ) ) ;
} ) ;
Ok ( server )
} ,
}
2016-04-21 13:57:27 +02:00
}
2016-08-23 19:28:21 +02:00
struct Registrar {
client : Arc < Client > ,
}
impl ContractClient for Registrar {
fn registrar ( & self ) -> Result < Address , String > {
self . client . additional_params ( ) . get ( " registrar " )
. ok_or_else ( | | " Registrar not defined. " . into ( ) )
. and_then ( | registrar | {
registrar . parse ( ) . map_err ( | e | format! ( " Invalid registrar address: {:?} " , e ) )
} )
}
fn call ( & self , address : Address , data : Bytes ) -> Result < Bytes , String > {
let from = Address ::default ( ) ;
let transaction = Transaction {
nonce : self . client . latest_nonce ( & from ) ,
action : Action ::Call ( address ) ,
gas : U256 ::from ( 50_000_000 ) ,
gas_price : U256 ::default ( ) ,
value : U256 ::default ( ) ,
data : data ,
} . fake_sign ( from ) ;
2016-12-09 23:01:43 +01:00
self . client . call ( & transaction , BlockId ::Latest , Default ::default ( ) )
2016-08-23 19:28:21 +02:00
. map_err ( | e | format! ( " {:?} " , e ) )
. map ( | executed | {
executed . output
} )
}
}
}