2019-03-09 06:37:57 +00:00
'''
2019-06-12 20:12:56 +00:00
Onionr - Private P2P Communication
2019-03-09 06:37:57 +00:00
launch the api server and communicator
'''
'''
This program 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 .
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 General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < https : / / www . gnu . org / licenses / > .
'''
2019-04-20 22:55:54 +00:00
import os , time , sys , platform , sqlite3 , signal
2019-03-08 01:08:06 +00:00
from threading import Thread
import onionr , api , logger , communicator
import onionrevents as events
from netcontroller import NetController
2019-06-23 17:41:07 +00:00
from onionrutils import localcommand
2019-06-15 01:31:01 +00:00
def _proper_shutdown ( o_inst ) :
2019-06-23 17:41:07 +00:00
localcommand . local_command ( o_inst . onionrCore , ' shutdown ' )
2019-06-15 01:31:01 +00:00
sys . exit ( 1 )
2019-03-08 01:08:06 +00:00
def daemon ( o_inst ) :
'''
Starts the Onionr communication daemon
'''
# remove runcheck if it exists
2019-06-07 05:09:14 +00:00
if os . path . isfile ( ' %s /.runcheck ' % ( o_inst . onionrCore . dataDir , ) ) :
2019-03-08 01:08:06 +00:00
logger . debug ( ' Runcheck file found on daemon start, deleting in advance. ' )
2019-06-07 05:09:14 +00:00
os . remove ( ' %s /.runcheck ' % ( o_inst . onionrCore . dataDir , ) )
2019-03-08 01:08:06 +00:00
2019-06-23 07:00:27 +00:00
Thread ( target = api . API , args = ( o_inst , o_inst . debug , onionr . API_VERSION ) , daemon = True ) . start ( )
Thread ( target = api . PublicAPI , args = [ o_inst . getClientApi ( ) ] , daemon = True ) . start ( )
2019-03-08 01:08:06 +00:00
apiHost = ' '
while apiHost == ' ' :
try :
with open ( o_inst . onionrCore . publicApiHostFile , ' r ' ) as hostFile :
apiHost = hostFile . read ( )
except FileNotFoundError :
pass
time . sleep ( 0.5 )
2019-05-15 23:25:36 +00:00
#onionr.Onionr.setupConfig('data/', self = o_inst)
2019-03-08 01:08:06 +00:00
2019-06-19 20:29:27 +00:00
logger . raw ( ' ' , terminal = True )
# print nice header thing :)
if o_inst . onionrCore . config . get ( ' general.display_header ' , True ) :
o_inst . header ( )
o_inst . version ( verbosity = 5 , function = logger . info )
logger . debug ( ' Python version %s ' % platform . python_version ( ) )
2019-03-08 01:08:06 +00:00
if o_inst . _developmentMode :
2019-06-26 00:15:04 +00:00
logger . warn ( ' Development mode enabled ' , timestamp = False , terminal = True )
2019-03-08 01:08:06 +00:00
net = NetController ( o_inst . onionrCore . config . get ( ' client.public.port ' , 59497 ) , apiServerIP = apiHost )
2019-06-19 20:29:27 +00:00
logger . info ( ' Tor is starting... ' , terminal = True )
2019-03-08 01:08:06 +00:00
if not net . startTor ( ) :
2019-06-23 17:41:07 +00:00
localcommand . local_command ( o_inst . onionrCore , ' shutdown ' )
2019-03-08 01:08:06 +00:00
sys . exit ( 1 )
2019-05-15 23:25:36 +00:00
if len ( net . myID ) > 0 and o_inst . onionrCore . config . get ( ' general.security_level ' , 1 ) == 0 :
2019-03-08 01:08:06 +00:00
logger . debug ( ' Started .onion service: %s ' % ( logger . colors . underline + net . myID ) )
else :
logger . debug ( ' .onion service disabled ' )
2019-06-19 20:29:27 +00:00
logger . info ( ' Using public key: %s ' % ( logger . colors . underline + o_inst . onionrCore . _crypto . pubKey [ : 52 ] ) , terminal = True )
2019-06-15 01:31:01 +00:00
try :
time . sleep ( 1 )
except KeyboardInterrupt :
_proper_shutdown ( o_inst )
2019-03-08 01:08:06 +00:00
o_inst . onionrCore . torPort = net . socksPort
2019-06-23 07:00:27 +00:00
communicatorThread = Thread ( target = communicator . startCommunicator , args = ( o_inst , str ( net . socksPort ) ) , daemon = True )
2019-03-08 01:08:06 +00:00
communicatorThread . start ( )
while o_inst . communicatorInst is None :
time . sleep ( 0.1 )
logger . debug ( ' Started communicator. ' )
events . event ( ' daemon_start ' , onionr = o_inst )
2019-04-20 22:55:54 +00:00
while True :
try :
2019-03-08 01:08:06 +00:00
time . sleep ( 3 )
2019-04-20 22:55:54 +00:00
except KeyboardInterrupt :
o_inst . communicatorInst . shutdown = True
finally :
2019-03-08 01:08:06 +00:00
# Debug to print out used FDs (regular and net)
#proc = psutil.Process()
#print('api-files:',proc.open_files(), len(psutil.net_connections()))
# Break if communicator process ends, so we don't have left over processes
if o_inst . communicatorInst . shutdown :
break
if o_inst . killed :
break # Break out if sigterm for clean exit
2019-04-20 22:55:54 +00:00
signal . signal ( signal . SIGINT , _ignore_sigint )
o_inst . onionrCore . daemonQueueAdd ( ' shutdown ' )
2019-06-23 17:41:07 +00:00
localcommand . local_command ( o_inst . onionrCore , ' shutdown ' )
2019-04-20 22:55:54 +00:00
2019-03-08 01:08:06 +00:00
net . killTor ( )
2019-06-23 17:41:07 +00:00
time . sleep ( 5 ) # Time to allow threads to finish, if not any "daemon" threads will be slaughtered http://docs.python.org/library/threading.html#threading.Thread.daemon
2019-03-08 01:08:06 +00:00
o_inst . deleteRunFiles ( )
return
2019-04-20 22:55:54 +00:00
def _ignore_sigint ( sig , frame ) :
return
2019-03-08 01:08:06 +00:00
def kill_daemon ( o_inst ) :
'''
Shutdown the Onionr daemon
'''
2019-06-19 20:29:27 +00:00
logger . warn ( ' Stopping the running daemon... ' , timestamp = False , terminal = True )
2019-03-08 01:08:06 +00:00
try :
events . event ( ' daemon_stop ' , onionr = o_inst )
net = NetController ( o_inst . onionrCore . config . get ( ' client.port ' , 59496 ) )
try :
o_inst . onionrCore . daemonQueueAdd ( ' shutdown ' )
except sqlite3 . OperationalError :
pass
net . killTor ( )
except Exception as e :
2019-06-19 20:29:27 +00:00
logger . error ( ' Failed to shutdown daemon. ' , error = e , timestamp = False , terminal = True )
2019-03-09 01:57:44 +00:00
return
def start ( o_inst , input = False , override = False ) :
if os . path . exists ( ' .onionr-lock ' ) and not override :
2019-06-19 20:29:27 +00:00
logger . fatal ( ' Cannot start. Daemon is already running, or it did not exit cleanly. \n (if you are sure that there is not a daemon running, delete .onionr-lock & try again). ' , terminal = True )
2019-03-09 01:57:44 +00:00
else :
if not o_inst . debug and not o_inst . _developmentMode :
lockFile = open ( ' .onionr-lock ' , ' w ' )
lockFile . write ( ' ' )
lockFile . close ( )
o_inst . running = True
o_inst . daemon ( )
o_inst . running = False
if not o_inst . debug and not o_inst . _developmentMode :
try :
os . remove ( ' .onionr-lock ' )
except FileNotFoundError :
pass