|  |  |  | @ -1,23 +1,51 @@ | 
			
		
	
		
			
				
					|  |  |  |  | #!/usr/bin/env python3 | 
			
		
	
		
			
				
					|  |  |  |  | import re | 
			
		
	
		
			
				
					|  |  |  |  | import errno | 
			
		
	
		
			
				
					|  |  |  |  | import fcntl | 
			
		
	
		
			
				
					|  |  |  |  | import os | 
			
		
	
		
			
				
					|  |  |  |  | import signal | 
			
		
	
		
			
				
					|  |  |  |  | import subprocess | 
			
		
	
		
			
				
					|  |  |  |  | import sys | 
			
		
	
		
			
				
					|  |  |  |  | import time | 
			
		
	
		
			
				
					|  |  |  |  | import json | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | import requests | 
			
		
	
		
			
				
					|  |  |  |  | import subprocess | 
			
		
	
		
			
				
					|  |  |  |  | from common.timeout import Timeout | 
			
		
	
		
			
				
					|  |  |  |  | from http.server import BaseHTTPRequestHandler, HTTPServer | 
			
		
	
		
			
				
					|  |  |  |  | from os.path import expanduser | 
			
		
	
		
			
				
					|  |  |  |  | from threading import Thread | 
			
		
	
		
			
				
					|  |  |  |  | from selfdrive.manager import unblock_stdout | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | from common.params import Params | 
			
		
	
		
			
				
					|  |  |  |  | import os | 
			
		
	
		
			
				
					|  |  |  |  | from common.timeout import Timeout | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | HOST = "testing.comma.life" | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | if __name__ == "__main__": | 
			
		
	
		
			
				
					|  |  |  |  |   unblock_stdout() | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | HOST = "testing.comma.life" | 
			
		
	
		
			
				
					|  |  |  |  | def unblock_stdout(): | 
			
		
	
		
			
				
					|  |  |  |  |   # get a non-blocking stdout | 
			
		
	
		
			
				
					|  |  |  |  |   child_pid, child_pty = os.forkpty() | 
			
		
	
		
			
				
					|  |  |  |  |   if child_pid != 0:  # parent | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # child is in its own process group, manually pass kill signals | 
			
		
	
		
			
				
					|  |  |  |  |     signal.signal(signal.SIGINT, lambda signum, frame: os.kill(child_pid, signal.SIGINT)) | 
			
		
	
		
			
				
					|  |  |  |  |     signal.signal(signal.SIGTERM, lambda signum, frame: os.kill(child_pid, signal.SIGTERM)) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     fcntl.fcntl(sys.stdout, fcntl.F_SETFL, fcntl.fcntl(sys.stdout, fcntl.F_GETFL) | os.O_NONBLOCK) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     while True: | 
			
		
	
		
			
				
					|  |  |  |  |       try: | 
			
		
	
		
			
				
					|  |  |  |  |         dat = os.read(child_pty, 4096) | 
			
		
	
		
			
				
					|  |  |  |  |       except OSError as e: | 
			
		
	
		
			
				
					|  |  |  |  |         if e.errno == errno.EIO: | 
			
		
	
		
			
				
					|  |  |  |  |           break | 
			
		
	
		
			
				
					|  |  |  |  |         continue | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       if not dat: | 
			
		
	
		
			
				
					|  |  |  |  |         break | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       try: | 
			
		
	
		
			
				
					|  |  |  |  |         sys.stdout.write(dat.decode('utf8')) | 
			
		
	
		
			
				
					|  |  |  |  |       except (OSError, IOError, UnicodeDecodeError): | 
			
		
	
		
			
				
					|  |  |  |  |         pass | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     # os.wait() returns a tuple with the pid and a 16 bit value | 
			
		
	
		
			
				
					|  |  |  |  |     # whose low byte is the signal number and whose high byte is the exit satus | 
			
		
	
		
			
				
					|  |  |  |  |     exit_status = os.wait()[1] >> 8 | 
			
		
	
		
			
				
					|  |  |  |  |     os._exit(exit_status) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def heartbeat(): | 
			
		
	
	
		
			
				
					|  |  |  | @ -30,9 +58,9 @@ def heartbeat(): | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       tmux = "" | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       #try: | 
			
		
	
		
			
				
					|  |  |  |  |       # try: | 
			
		
	
		
			
				
					|  |  |  |  |       #  tmux = os.popen('tail -n 100 /tmp/tmux_out').read() | 
			
		
	
		
			
				
					|  |  |  |  |       #except Exception: | 
			
		
	
		
			
				
					|  |  |  |  |       # except Exception: | 
			
		
	
		
			
				
					|  |  |  |  |       #  pass | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       params = Params() | 
			
		
	
	
		
			
				
					|  |  |  | @ -52,75 +80,6 @@ def heartbeat(): | 
			
		
	
		
			
				
					|  |  |  |  |     time.sleep(5) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | class HTTPHandler(BaseHTTPRequestHandler): | 
			
		
	
		
			
				
					|  |  |  |  |     def _set_headers(self, response=200, content='text/html'): | 
			
		
	
		
			
				
					|  |  |  |  |         self.send_response(response) | 
			
		
	
		
			
				
					|  |  |  |  |         self.send_header('Content-type', content) | 
			
		
	
		
			
				
					|  |  |  |  |         self.end_headers() | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def do_GET(self): | 
			
		
	
		
			
				
					|  |  |  |  |         self._set_headers() | 
			
		
	
		
			
				
					|  |  |  |  |         self.wfile.write("EON alive") | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def do_HEAD(self): | 
			
		
	
		
			
				
					|  |  |  |  |         self._set_headers() | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     def do_POST(self): | 
			
		
	
		
			
				
					|  |  |  |  |         # Doesn't do anything with posted data | 
			
		
	
		
			
				
					|  |  |  |  |         self._set_headers(response=204) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         content_length = int(self.headers['Content-Length']) | 
			
		
	
		
			
				
					|  |  |  |  |         post_data = self.rfile.read(content_length) | 
			
		
	
		
			
				
					|  |  |  |  |         post_data = json.loads(post_data) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if 'command' not in post_data or 'dongle_id' not in post_data: | 
			
		
	
		
			
				
					|  |  |  |  |           return | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         params = Params() | 
			
		
	
		
			
				
					|  |  |  |  |         if params.get("DongleId").rstrip() != post_data['dongle_id']: | 
			
		
	
		
			
				
					|  |  |  |  |           return | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if post_data['command'] == "reboot": | 
			
		
	
		
			
				
					|  |  |  |  |           subprocess.check_output(["reboot"]) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if post_data['command'] == "update": | 
			
		
	
		
			
				
					|  |  |  |  |           print("Pulling new version") | 
			
		
	
		
			
				
					|  |  |  |  |           work_dir = get_workdir() | 
			
		
	
		
			
				
					|  |  |  |  |           env = { | 
			
		
	
		
			
				
					|  |  |  |  |             "GIT_SSH_COMMAND": "ssh -i /data/gitkey", | 
			
		
	
		
			
				
					|  |  |  |  |             "LD_LIBRARY_PATH": "/data/data/com.termux/files/usr/lib/", | 
			
		
	
		
			
				
					|  |  |  |  |             "ANDROID_DATA": "/data", | 
			
		
	
		
			
				
					|  |  |  |  |             "ANDROID_ROOT": "/system", | 
			
		
	
		
			
				
					|  |  |  |  |           } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |           subprocess.check_output(["git", "reset", "--hard"], cwd=work_dir, env=env) | 
			
		
	
		
			
				
					|  |  |  |  |           # subprocess.check_output(["git", "clean", "-xdf"], cwd=work_dir, env=env) | 
			
		
	
		
			
				
					|  |  |  |  |           try: | 
			
		
	
		
			
				
					|  |  |  |  |             subprocess.check_output(["git", "fetch", "--unshallow"], cwd=work_dir, env=env) | 
			
		
	
		
			
				
					|  |  |  |  |           except subprocess.CalledProcessError: | 
			
		
	
		
			
				
					|  |  |  |  |             pass | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |           if 'revision' in post_data and re.match(r'\b[0-9a-f]{5,40}\b', post_data['revision']): | 
			
		
	
		
			
				
					|  |  |  |  |             subprocess.check_output(["git", "fetch", "origin"], cwd=work_dir, env=env) | 
			
		
	
		
			
				
					|  |  |  |  |             subprocess.check_output(["git", "checkout", post_data['revision']], cwd=work_dir, env=env) | 
			
		
	
		
			
				
					|  |  |  |  |           else: | 
			
		
	
		
			
				
					|  |  |  |  |             subprocess.check_output(["git", "pull"], cwd=work_dir, env=env) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |           subprocess.check_output(["git", "submodule", "update"], cwd=work_dir, env=env) | 
			
		
	
		
			
				
					|  |  |  |  |           subprocess.check_output(["git", "lfs", "pull"], cwd=work_dir, env=env) | 
			
		
	
		
			
				
					|  |  |  |  |           subprocess.check_output(["reboot"], cwd=work_dir, env=env) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | def control_server(server_class=HTTPServer, handler_class=HTTPHandler, port=8080): | 
			
		
	
		
			
				
					|  |  |  |  |     server_address = ('', port) | 
			
		
	
		
			
				
					|  |  |  |  |     httpd = server_class(server_address, handler_class) | 
			
		
	
		
			
				
					|  |  |  |  |     print('Starting httpd...') | 
			
		
	
		
			
				
					|  |  |  |  |     httpd.serve_forever() | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | if __name__ == "__main__": | 
			
		
	
		
			
				
					|  |  |  |  |   control_thread = Thread(target=control_server) | 
			
		
	
		
			
				
					|  |  |  |  |   control_thread.daemon = True | 
			
		
	
		
			
				
					|  |  |  |  |   control_thread.start() | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   unblock_stdout() | 
			
		
	
		
			
				
					|  |  |  |  |   heartbeat() | 
			
		
	
	
		
			
				
					|  |  |  | 
 |