Skip to content
Snippets Groups Projects

Rewrite devkit service in python.

Merged Jeremy Whiting requested to merge pythonrewrite into main
@@ -52,12 +52,16 @@ PROPERTIES = {"txtvers": 1,
"devkit1": [
ENTRY_POINT
]}
MACHINE_NAME = ''
HOOK_DIRS = []
USE_DEFAULT_HOOKS = True
def writefile(data: bytes) -> str:
def write_file(data: bytes) -> str:
""" Write given bytes to a temporary file and return the filename
Return the empty string if unable to open temp file for some reason
"""
# Get 1 from the resulting tuple, since that's the filename
filename = tempfile.mkstemp(prefix="devkit-", dir="/tmp/", text=True)[1]
@@ -66,12 +70,16 @@ def writefile(data: bytes) -> str:
file.write(data.decode())
file.close()
return filename
return filename
return ''
def write_key(post_body: bytes) -> str:
# Write key to temp file and return filename if valid, etc.
# Return None if invalid
""" Write key to temp file and return filename if valid
Return the empty string if invalid
"""
length = len(post_body)
found_name = False
@@ -132,14 +140,19 @@ def write_key(post_body: bytes) -> str:
# write data to the file
data = body_decoded[:length]
filename = writefile(data.encode())
filename = write_file(data.encode())
print(f"Filename key written to: {filename}")
if filename:
print(f"Filename key written to: {filename}")
return filename
def find_hook(name: str) -> str:
""" Find a hook with the given name
Return the path to the hook if found. '' if not found
"""
# First see if it exists in the given paths.
for path in HOOK_DIRS:
test_path = os.path.join(path, name)
@@ -170,31 +183,43 @@ def find_hook(name: str) -> str:
return ''
# Run devkit-1-identify hook to get hostname, otherwise use default platform.node()
identify_hook = find_hook("devkit-1-identify")
if identify_hook:
# Run hook and parse machine_name out
process = subprocess.Popen(identify_hook, shell=False, stdout=subprocess.PIPE)
output = ''
for line in process.stdout:
textline = line.decode(encoding='utf-8', errors="ignore")
output += textline
process.wait()
output_object = json.loads(output)
if 'machine_name' in output_object:
MACHINE_NAME = output_object["machine_name"]
def get_machine_name() -> str:
""" Get the machine name and return it in a string
Use identify hook first, and if that fails just get the hostname.
"""
machine_name = ''
# Run devkit-1-identify hook to get hostname, otherwise use default platform.node()
identify_hook = find_hook("devkit-1-identify")
if identify_hook:
# Run hook and parse machine_name out
process = subprocess.Popen(identify_hook, shell=False, stdout=subprocess.PIPE)
output = ''
for line in process.stdout:
textline = line.decode(encoding='utf-8', errors="ignore")
output += textline
process.wait()
output_object = json.loads(output)
if 'machine_name' in output_object:
machine_name = output_object["machine_name"]
if not MACHINE_NAME:
MACHINE_NAME = platform.node()
if not machine_name:
machine_name = platform.node()
return machine_name
class DevkitHandler(BaseHTTPRequestHandler):
""" Class to handle http requests on selected port for registration, getting properties.
"""
def _send_headers(self, code, content_type):
self.send_response(code)
self.send_header("Content-type", content_type)
self.end_headers()
def do_GET(self):
""" Handle GET requests
"""
print(f"GET request to path {self.path} from {self.client_address[0]}")
if self.path == "/login-name":
@@ -221,10 +246,12 @@ class DevkitHandler(BaseHTTPRequestHandler):
self._send_headers(404, "")
return
self._send_headers(200, "text/html")
self.wfile.write("Get works\n".encode())
self._send_headers(404, "")
self.wfile.write("Unknown request\n".encode())
def do_POST(self):
""" Handle POST requests
"""
if self.path == "/register":
from_ip = self.client_address[0]
content_len = int(self.headers.get('Content-Length'))
@@ -256,7 +283,7 @@ class DevkitHandler(BaseHTTPRequestHandler):
approve_process.wait()
approve_object = json.loads(approve_output)
if "error" in output_object:
if "error" in approve_object:
self._send_headers(403, "text/plain")
self.wfile.write("approve-ssh-key:\n".encode())
self.wfile.write(approve_object["error"].encode())
@@ -297,12 +324,16 @@ class DevkitHandler(BaseHTTPRequestHandler):
class DevkitService:
""" Class to run as service.
Parses configuration, creates handler, registers with avahi, etc.
"""
def __init__(self):
global ENTRY_POINT_USER
global DEVICE_USERS
self.port = SERVICE_PORT
self.name = MACHINE_NAME
self.name = get_machine_name()
self.host = ""
self.domain = ""
self.stype = "_steamos-devkit._tcp"
@@ -312,10 +343,9 @@ class DevkitService:
config = configparser.ConfigParser()
# Use str form to preserve case
config.optionxform = str
user_config_path = os.path.join(os.path.expanduser('~'), '.config', PACKAGE, PACKAGE + '.conf')
config.read(["/etc/steamos-devkit/steamos-devkit.conf",
"/usr/share/steamos-devkit/steamos-devkit.conf",
user_config_path])
os.path.join(os.path.expanduser('~'), '.config', PACKAGE, PACKAGE + '.conf')])
if 'Settings' in config:
settings = config["Settings"]
@@ -349,12 +379,14 @@ class DevkitService:
self.httpd = socketserver.TCPServer(("", self.port), DevkitHandler, bind_and_activate=False)
print(f"serving at port: {self.port}")
print(f"machine name: {MACHINE_NAME}")
print(f"machine name: {self.name}")
self.httpd.allow_reuse_address = True
self.httpd.server_bind()
self.httpd.server_activate()
def publish(self):
""" Publish ourselves on avahi mdns system as an available devkit device.
"""
bus = dbus.SystemBus()
self.text = [f"{CURRENT_TXTVERS}".encode(),
f"settings={json.dumps(self.settings)}".encode(),
@@ -379,9 +411,13 @@ class DevkitService:
self.group = avahi_object
def unpublish(self):
""" Remove publishing of ourselves as devkit device since we are quitting.
"""
self.group.Reset()
def run_server(self):
""" Run server until keyboard interrupt or we are killed
"""
try:
self.httpd.serve_forever()
except KeyboardInterrupt:
Loading