2018-09-28 18:15:10 -04:00
/*
* RetroShare Service
* Copyright ( C ) 2016 - 2018 Gioacchino Mazzurco < gio @ eigenlab . org >
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation , either version 3 of the
* License , or ( at your option ) any later version .
*
* This program 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 Affero General Public License for more details .
*
* You should have received a copy of the GNU Affero General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2018-11-04 18:19:45 -05:00
# include "util/stacktrace.h"
2019-08-29 17:15:46 -04:00
# include "util/argstream.h"
2019-09-05 17:54:48 -04:00
# include "util/rskbdinput.h"
2019-08-29 17:15:46 -04:00
# include "retroshare/rsinit.h"
2019-08-29 04:57:15 -04:00
# include "jsonapi/jsonapi.h"
2018-11-04 18:19:45 -05:00
CrashStackTrace gCrashStackTrace ;
2019-08-29 17:15:46 -04:00
# include <cmath>
2018-09-28 18:15:10 -04:00
# include <csignal>
2019-08-27 15:54:17 -04:00
2018-10-05 16:29:49 -04:00
# ifdef __ANDROID__
# include <QAndroidService>
2019-08-27 15:54:17 -04:00
# include <QCoreApplication>
# include <QObject>
# include <QStringList>
# include "util / androiddebug.h"
2018-10-05 16:29:49 -04:00
# endif // def __ANDROID__
2018-09-28 18:15:10 -04:00
# include "retroshare/rsinit.h"
# include "retroshare/rsiface.h"
2019-08-29 04:57:15 -04:00
class RsServiceNotify : public NotifyClient
2019-08-27 15:54:17 -04:00
{
public :
2019-08-29 04:57:15 -04:00
RsServiceNotify ( ) { }
virtual ~ RsServiceNotify ( ) { }
2019-08-27 15:54:17 -04:00
virtual bool askForPassword ( const std : : string & title , const std : : string & question , bool prev_is_bad , std : : string & password , bool & cancel )
{
std : : string question1 = title + " \n Please enter your PGP password for key: \n " + question + " : " ;
2019-09-05 17:54:48 -04:00
password = RsUtil : : rs_getpass ( question1 . c_str ( ) ) ;
2019-08-27 15:54:17 -04:00
cancel = false ;
return ! password . empty ( ) ;
}
} ;
2018-09-28 18:15:10 -04:00
int main ( int argc , char * argv [ ] )
{
# ifdef __ANDROID__
AndroidStdIOCatcher dbg ; ( void ) dbg ;
2018-10-05 16:29:49 -04:00
QAndroidService app ( argc , argv ) ;
2018-09-28 18:15:10 -04:00
signal ( SIGINT , QCoreApplication : : exit ) ;
signal ( SIGTERM , QCoreApplication : : exit ) ;
# ifdef SIGBREAK
signal ( SIGBREAK , QCoreApplication : : exit ) ;
# endif // ifdef SIGBREAK
2019-08-27 15:54:17 -04:00
# endif // def __ANDROID__
2019-09-02 16:13:12 -04:00
std : : cerr < < " +================================================================+ " < < std : : endl ;
std : : cerr < < " | o---o o | " < < std : : endl ;
std : : cerr < < " | \\ / - Retroshare Service - / \\ | " < < std : : endl ;
std : : cerr < < " | o o---o | " < < std : : endl ;
std : : cerr < < " +================================================================+ " < < std : : endl ;
std : : cerr < < std : : endl ;
2019-08-27 15:54:17 -04:00
2018-09-28 18:15:10 -04:00
RsInit : : InitRsConfig ( ) ;
2019-08-27 15:54:17 -04:00
RsControl : : earlyInitNotificationSystem ( ) ;
2018-09-28 18:15:10 -04:00
2019-08-29 17:15:46 -04:00
# ifdef __APPLE__
// TODO: is this still needed with argstream?
/* HACK to avoid stupid OSX Finder behaviour
* remove the commandline arguments - if we detect we are launched from Finder ,
* and we have the unparsable " -psn_0_12332 " option .
* this is okay , as you cannot pass commandline arguments via Finder anyway
*/
if ( ( argc > = 2 ) & & ( 0 = = strncmp ( argv [ 1 ] , " -psn " , 4 ) ) ) argc = 1 ;
# endif
2019-08-29 04:57:15 -04:00
2019-08-29 17:15:46 -04:00
std : : string prefUserString ;
RsConfigOptions conf ;
argstream as ( argc , argv ) ;
as > > option ( ' s ' , " stderr " , conf . outStderr , " output to stderr instead of log file. " )
> > option ( ' u ' , " udp " , conf . udpListenerOnly , " Only listen to UDP. " )
> > parameter ( ' c ' , " base-dir " , conf . optBaseDir , " directory " , " Set base directory. " , false )
> > parameter ( ' l ' , " log-file " , conf . logfname , " logfile " , " Set Log filename. " , false )
> > parameter ( ' d ' , " debug-level " , conf . debugLevel , " level " , " Set debug level. " , false )
> > parameter ( ' i ' , " ip-address " , conf . forcedInetAddress , " nnn.nnn.nnn.nnn " , " Force IP address to use (if cannot be detected). " , false )
> > parameter ( ' o ' , " opmode " , conf . opModeStr , " opmode " , " Set Operating mode (Full, NoTurtle, Gaming, Minimal). " , false )
> > parameter ( ' p ' , " port " , conf . forcedPort , " port " , " Set listenning port to use. " , false )
2019-09-02 16:13:12 -04:00
> > parameter ( ' U ' , " user-id " , prefUserString , " ID " , " [node Id] Selected account to use and asks for passphrase. Use \" -U list \" in order to list available accounts. " , false ) ;
2019-08-29 17:15:46 -04:00
# ifdef RS_JSONAPI
as > > parameter ( ' J ' , " jsonApiPort " , conf . jsonApiPort , " jsonApiPort " , " Enable JSON API on the specified port " , false )
> > parameter ( ' P ' , " jsonApiBindAddress " , conf . jsonApiBindAddress , " jsonApiBindAddress " , " JSON API Bind Address. " , false ) ;
# endif // ifdef RS_JSONAPI
# ifdef LOCALNET_TESTING
as > > parameter ( ' R ' , " restrict-port " , portRestrictions , " port1-port2 " , " Apply port restriction " , false ) ;
# endif // ifdef LOCALNET_TESTING
# ifdef RS_AUTOLOGIN
as > > option ( ' a ' , " auto-login " , conf . autoLogin , " AutoLogin (Windows Only) + StartMinimised " ) ;
# endif // ifdef RS_AUTOLOGIN
as > > help ( ' h ' , " help " , " Display this Help " ) ;
as . defaultErrorHandling ( true , true ) ;
2019-08-30 15:16:00 -04:00
std : : string webui_pass1 = " Y " ;
2019-09-02 16:13:12 -04:00
if ( ! prefUserString . empty ( ) )
2019-08-30 15:16:00 -04:00
{
2019-09-02 16:13:12 -04:00
std : : string webui_pass2 = " N " ;
2019-08-30 15:16:00 -04:00
2019-09-02 16:13:12 -04:00
for ( ; ; )
2019-08-30 15:16:00 -04:00
{
2019-09-05 17:54:48 -04:00
webui_pass1 = RsUtil : : rs_getpass ( " Please register a password for the web interface: " ) ;
webui_pass2 = RsUtil : : rs_getpass ( " Please enter the same password again : " ) ;
2019-09-02 16:13:12 -04:00
if ( webui_pass1 ! = webui_pass2 )
{
std : : cerr < < " Passwords do not match! " < < std : : endl ;
continue ;
}
if ( webui_pass1 . empty ( ) )
{
std : : cerr < < " Password cannot be empty! " < < std : : endl ;
continue ;
}
2019-08-30 15:16:00 -04:00
2019-09-02 16:13:12 -04:00
break ;
}
2019-08-30 15:16:00 -04:00
}
2019-08-29 04:57:15 -04:00
2019-08-29 17:15:46 -04:00
conf . main_executable_path = argv [ 0 ] ;
if ( RS_INIT_OK ! = RsInit : : InitRetroShare ( conf ) )
2019-08-27 15:54:17 -04:00
{
std : : cerr < < " Could not properly init Retroshare core. " < < std : : endl ;
return 1 ;
}
2019-08-29 04:57:15 -04:00
2019-08-29 17:15:46 -04:00
// choose alternative account.
if ( prefUserString ! = " " )
{
if ( prefUserString = = " list " )
{
std : : cerr < < " Available accounts: " < < std : : endl ;
std : : vector < RsLoginHelper : : Location > locations ;
rsLoginHelper - > getLocations ( locations ) ;
int account_number_size = ( int ) ceil ( log ( locations . size ( ) ) / log ( 10.0f ) ) ;
for ( uint32_t i = 0 ; i < locations . size ( ) ; + + i )
std : : cout < < " [ " < < std : : setw ( account_number_size ) < < std : : setfill ( ' 0 ' )
< < i + 1 < < " ] " < < locations [ i ] . mLocationId < < " ( " < < locations [ i ] . mPgpId < < " ): " < < locations [ i ] . mPgpName
< < " \t ( " < < locations [ i ] . mLocationName < < " ) " < < std : : endl ;
int nacc = 0 ;
while ( nacc < 1 | | nacc > = locations . size ( ) )
{
std : : cout < < " Please enter account number: " ;
std : : cout . flush ( ) ;
std : : string str ;
std : : getline ( std : : cin , str ) ;
nacc = atoi ( str . c_str ( ) ) - 1 ;
if ( nacc > = 0 & & nacc < locations . size ( ) )
{
prefUserString = locations [ nacc ] . mLocationId . toStdString ( ) ;
break ;
}
nacc = 0 ; // allow to continue if something goes wrong.
}
}
RsPeerId ssl_id ( prefUserString ) ;
if ( ssl_id . isNull ( ) )
{
std : : cerr < < " Invalid User location id: a hexadecimal ID is expected. " < < std : : endl ;
return 1 ;
}
2019-09-02 16:13:12 -04:00
RsServiceNotify * notify = new RsServiceNotify ( ) ;
rsNotify - > registerNotifyClient ( notify ) ;
2019-08-29 17:15:46 -04:00
RsInit : : LoadCertificateStatus result = rsLoginHelper - > attemptLogin ( ssl_id , std : : string ( ) ) ; // supply empty passwd so that it is properly asked 3 times on console
std : : string lock_file_path = RsAccounts : : AccountDirectory ( ) + " /lock " ;
switch ( result )
{
case RsInit : : OK : break ;
case RsInit : : ERR_ALREADY_RUNNING : std : : cerr < < " Another RetroShare using the same profile is already running on your system. Please close "
" that instance first. \n Lock file: " < < RsInit : : lockFilePath ( ) < < std : : endl ;
return 1 ;
case RsInit : : ERR_CANT_ACQUIRE_LOCK : std : : cerr < < " An unexpected error occurred when Retroshare tried to acquire the single instance lock file. \n Lock file: " < < RsInit : : lockFilePath ( ) < < std : : endl ;
return 1 ;
case RsInit : : ERR_UNKNOWN :
2019-09-02 16:13:12 -04:00
default : std : : cerr < < " Cannot login. Check your passphrase. " < < std : : endl < < std : : endl ;
2019-08-29 17:15:46 -04:00
return 1 ;
}
}
2019-08-27 15:54:17 -04:00
# ifdef __ANDROID__
2018-09-28 18:15:10 -04:00
rsControl - > setShutdownCallback ( QCoreApplication : : exit ) ;
2019-08-27 15:54:17 -04:00
2018-09-28 18:15:10 -04:00
QObject : : connect (
& app , & QCoreApplication : : aboutToQuit ,
[ ] ( ) {
if ( RsControl : : instance ( ) - > isReady ( ) )
RsControl : : instance ( ) - > rsGlobalShutDown ( ) ; } ) ;
return app . exec ( ) ;
2019-08-27 15:54:17 -04:00
# else
2019-09-02 16:13:12 -04:00
if ( jsonApiServer & & ! webui_pass1 . empty ( ) )
2019-08-29 04:57:15 -04:00
jsonApiServer - > authorizeToken ( " webui: " + webui_pass1 ) ;
2019-08-30 16:11:33 -04:00
std : : atomic < bool > keepRunning ( true ) ;
2019-08-30 16:09:47 -04:00
rsControl - > setShutdownCallback ( [ & ] ( int ) { keepRunning = false ; } ) ;
while ( keepRunning )
2019-09-02 16:13:12 -04:00
std : : this_thread : : sleep_for ( std : : chrono : : seconds ( 2 ) ) ;
2019-08-27 15:54:17 -04:00
# endif
2018-09-28 18:15:10 -04:00
}