2019-12-18 10:00:39 +00:00
""" Onionr - Private P2P Communication
launch the api servers and communicator
"""
import os
import sys
import platform
import sqlite3
2019-03-08 01:08:06 +00:00
from threading import Thread
2019-11-30 08:42:49 +00:00
from gevent import time
2019-08-02 23:00:04 +00:00
import toomanyobjs
2019-12-18 10:00:39 +00:00
import config
import apiservers
import logger
import communicator
2019-09-21 22:45:46 +00:00
from onionrplugins import onionrevents as events
2019-03-08 01:08:06 +00:00
from netcontroller import NetController
2019-06-23 17:41:07 +00:00
from onionrutils import localcommand
2019-07-19 04:59:44 +00:00
import filepaths
2019-07-17 22:41:33 +00:00
from coredb import daemonqueue
2019-07-31 05:10:28 +00:00
from etc import onionrvalues , cleanup
2019-07-20 00:01:16 +00:00
from onionrcrypto import getourkeypair
2019-07-30 05:19:22 +00:00
from utils import hastor , logoheader
2019-07-31 05:10:28 +00:00
from . import version
2019-08-05 04:08:56 +00:00
import serializeddata
2019-09-26 07:43:03 +00:00
import runtests
2019-07-27 02:42:55 +00:00
2019-07-31 05:10:28 +00:00
def _proper_shutdown ( ) :
2019-07-19 04:59:44 +00:00
localcommand . local_command ( ' shutdown ' )
2019-06-15 01:31:01 +00:00
sys . exit ( 1 )
2019-07-31 05:10:28 +00:00
def daemon ( ) :
2019-03-08 01:08:06 +00:00
'''
Starts the Onionr communication daemon
'''
2019-07-27 02:42:55 +00:00
if not hastor . has_tor ( ) :
logger . error ( " Tor is not present in system path or Onionr directory " , terminal = True )
2019-11-29 23:49:14 +00:00
cleanup . delete_run_files ( )
2019-07-27 02:42:55 +00:00
sys . exit ( 1 )
2019-03-08 01:08:06 +00:00
# remove runcheck if it exists
2019-07-19 04:59:44 +00:00
if os . path . isfile ( filepaths . run_check_file ) :
2019-03-08 01:08:06 +00:00
logger . debug ( ' Runcheck file found on daemon start, deleting in advance. ' )
2019-07-19 04:59:44 +00:00
os . remove ( filepaths . run_check_file )
2019-08-04 04:52:57 +00:00
2019-09-26 07:43:03 +00:00
# Create shared objects
2019-08-04 04:52:57 +00:00
shared_state = toomanyobjs . TooMany ( )
2019-03-08 01:08:06 +00:00
2019-09-12 19:50:06 +00:00
Thread ( target = shared_state . get ( apiservers . ClientAPI ) . start , daemon = True , name = ' client HTTP API ' ) . start ( )
Thread ( target = shared_state . get ( apiservers . PublicAPI ) . start , daemon = True , name = ' public HTTP API ' ) . start ( )
2019-09-26 07:43:03 +00:00
# Init run time tester (ensures Onionr is running right, for testing purposes)
shared_state . get ( runtests . OnionrRunTestManager )
2019-08-05 04:08:56 +00:00
shared_state . get ( serializeddata . SerializedData )
2019-08-04 04:52:57 +00:00
shared_state . share_object ( ) # share the parent object to the threads
2019-03-08 01:08:06 +00:00
apiHost = ' '
while apiHost == ' ' :
try :
2019-07-19 04:59:44 +00:00
with open ( filepaths . public_API_host_file , ' r ' ) as hostFile :
2019-03-08 01:08:06 +00:00
apiHost = hostFile . read ( )
except FileNotFoundError :
pass
time . sleep ( 0.5 )
2019-06-19 20:29:27 +00:00
logger . raw ( ' ' , terminal = True )
# print nice header thing :)
2019-07-31 05:10:28 +00:00
if config . get ( ' general.display_header ' , True ) :
2019-07-30 05:19:22 +00:00
logoheader . header ( )
2019-07-31 05:10:28 +00:00
version . version ( verbosity = 5 , function = logger . info )
2019-06-19 20:29:27 +00:00
logger . debug ( ' Python version %s ' % platform . python_version ( ) )
2019-07-31 05:10:28 +00:00
if onionrvalues . DEVELOPMENT_MODE :
2019-06-26 00:15:04 +00:00
logger . warn ( ' Development mode enabled ' , timestamp = False , terminal = True )
2019-08-04 04:52:57 +00:00
2019-07-31 05:10:28 +00:00
net = NetController ( config . get ( ' client.public.port ' , 59497 ) , apiServerIP = apiHost )
2019-08-04 04:52:57 +00:00
shared_state . add ( net )
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-07-19 04:59:44 +00:00
localcommand . local_command ( ' shutdown ' )
2019-10-08 22:26:44 +00:00
cleanup . delete_run_files ( )
2019-03-08 01:08:06 +00:00
sys . exit ( 1 )
2019-07-31 05:10:28 +00:00
if len ( net . myID ) > 0 and 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-09-12 19:50:06 +00:00
logger . info ( ' Using public key: %s ' % ( logger . colors . underline + getourkeypair . get_keypair ( ) [ 0 ] [ : 52 ] ) )
2019-06-15 01:31:01 +00:00
try :
time . sleep ( 1 )
except KeyboardInterrupt :
2019-10-08 22:26:44 +00:00
pass
2019-11-30 08:42:49 +00:00
2019-08-04 04:52:57 +00:00
events . event ( ' init ' , threaded = False )
2019-07-31 05:10:28 +00:00
events . event ( ' daemon_start ' )
2019-08-04 04:52:57 +00:00
communicator . startCommunicator ( shared_state )
2019-03-08 01:08:06 +00:00
2019-07-19 04:59:44 +00:00
localcommand . local_command ( ' shutdown ' )
2019-04-20 22:55:54 +00:00
2019-03-08 01:08:06 +00:00
net . killTor ( )
2019-08-08 06:25:48 +00:00
try :
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
except KeyboardInterrupt :
pass
2019-07-31 05:10:28 +00:00
cleanup . delete_run_files ( )
2019-03-08 01:08:06 +00:00
2019-04-20 22:55:54 +00:00
def _ignore_sigint ( sig , frame ) :
2019-07-31 05:10:28 +00:00
''' This space intentionally left blank '''
2019-04-20 22:55:54 +00:00
return
2019-07-31 05:10:28 +00:00
def kill_daemon ( ) :
2019-03-08 01:08:06 +00:00
'''
2019-09-12 19:50:06 +00:00
Shutdown the Onionr daemon ( communicator )
2019-03-08 01:08:06 +00:00
'''
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 :
2019-11-01 18:35:28 +00:00
# On platforms where we can, fork out to prevent locking
try :
pid = os . fork ( )
if pid != 0 : return
except ( AttributeError , OSError ) as e : pass
2019-07-31 05:10:28 +00:00
events . event ( ' daemon_stop ' )
net = NetController ( config . get ( ' client.port ' , 59496 ) )
2019-03-08 01:08:06 +00:00
try :
2019-07-24 18:23:31 +00:00
daemonqueue . daemon_queue_add ( ' shutdown ' )
2019-03-08 01:08:06 +00:00
except sqlite3 . OperationalError :
pass
net . killTor ( )
except Exception as e :
2019-07-24 18:23:31 +00:00
logger . error ( ' Failed to shutdown daemon: ' + str ( e ) , error = e , timestamp = False , terminal = True )
2019-03-09 01:57:44 +00:00
return
2019-09-21 05:06:49 +00:00
kill_daemon . onionr_help = " Gracefully stops the Onionr API servers "
2019-09-12 19:50:06 +00:00
def start ( input : bool = False , override : bool = False ) :
""" If no lock file, make one and start onionr, error if there is and its not overridden """
2019-10-08 00:02:12 +00:00
if os . path . exists ( filepaths . lock_file ) and not override :
2019-10-08 02:32:33 +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 :
2019-07-31 05:10:28 +00:00
if not onionrvalues . DEVELOPMENT_MODE :
2019-10-08 00:02:12 +00:00
lockFile = open ( filepaths . lock_file , ' w ' )
lockFile . write ( ' delete at your own risk ' )
2019-03-09 01:57:44 +00:00
lockFile . close ( )
2019-07-31 05:10:28 +00:00
daemon ( )
2019-10-08 22:26:44 +00:00
try :
os . remove ( filepaths . lock_file )
except FileNotFoundError :
pass
2019-09-21 05:06:49 +00:00
2019-10-08 00:02:12 +00:00
start . onionr_help = " Start Onionr node (public and clients API servers) "