Skip to content

Commit

Permalink
Check socket host availability before binding
Browse files Browse the repository at this point in the history
  • Loading branch information
Frewacom committed Aug 3, 2020
1 parent a9b9c5d commit 1e51619
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 18 deletions.
2 changes: 0 additions & 2 deletions pywalfox/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ def run_daemon():

daemon = Daemon(python_version.major)
daemon.start()
daemon.close()

def handle_args(args):
"""Handles CLI arguments."""
Expand All @@ -76,7 +75,6 @@ def handle_args(args):
if args.action == 'daemon':
setup_logging(args.verbose, args.print_mode)
run_daemon()
sys.exit(0)

if args.action == 'log':
open_log_file()
Expand Down
45 changes: 41 additions & 4 deletions pywalfox/channel/connector.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
import socket
import logging
from ..config import UNIX_SOCKET_PATH, WIN_SOCKET_HOST

from ..config import UNIX_SOCKET_PATH, WIN_SOCKET_HOST, UNIX_SOCKET_PATH_ALT, WIN_SOCKET_HOST_ALT

class Connector:
"""
Expand All @@ -13,14 +13,51 @@ class Connector:
"""
def __init__(self, platform_id):
if platform_id == 'win32':
self.host = WIN_SOCKET_HOST
self.host = self.get_win_socket_host()
self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
logging.debug('Setup socket server using AF_INET (win32)')
else:
self.host = UNIX_SOCKET_PATH
self.host = self.get_unix_socket_path()
self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
logging.debug('Setup socket server using AF_UNIX (linux/darwin)')

def get_unix_socket_path(self):
"""
Get an available path to bind the UNIX-socket to.
:return: the path to be used when binding the UNIX-socket
:rType: str
"""
if os.path.exists(UNIX_SOCKET_PATH):
logging.debug('Default UNIX-socket is already in use')
return UNIX_SOCKET_PATH_ALT

return UNIX_SOCKET_PATH

def get_win_socket_host(self):
"""
Get an available host and port to bind the UDP-socket to.
:return: the host and port to be used when binding the UDP-socket
:rType: (host, port)
"""
is_valid = True
test_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
test_socket.bind(WIN_SOCKET_HOST)
test_socket.close()
except OSError as e:
is_valid = False
if e.errno == 98: # errno 98 means that address is already bound
logging.debug('Default UDP-socket host is already in use')
else:
logging.error('Failed to test UDP-socket host availability: %s' % str(e))

if is_valid is True:
return WIN_SOCKET_HOST

return WIN_SOCKET_HOST_ALT

def encode_message(self, message):
"""
Encodes a message to be sent using the socket.
Expand Down
12 changes: 11 additions & 1 deletion pywalfox/channel/unix/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,14 @@ def start(self):
def close(self):
"""Unbinds the socket and deletes the file."""
self.socket.close()
os.remove(self.host)

try:
"""
UNIX-sockets can be overwritten by other processes even if another process
is already using it. This may lead to the file not existing and will
cause a crash if not handled properly.
"""
os.remove(self.host)
logging.debug('UNIX-socket deleted')
except OSError as e:
logging.debug('UNIX-socket has already been deleted, skipping')
2 changes: 2 additions & 0 deletions pywalfox/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
DAEMON_VERSION = '2.5'

UNIX_SOCKET_PATH = '/tmp/pywalfox_socket'
UNIX_SOCKET_PATH_ALT = '/tmp/pywalfox_socket_alt'
WIN_SOCKET_HOST = ('127.0.0.1', 56744)
WIN_SOCKET_HOST_ALT = ('127.0.0.1', 56745)

SUPPORTED_BROWSERS = ['firefox']

Expand Down
25 changes: 14 additions & 11 deletions pywalfox/daemon.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import sys
import signal
import logging
from threading import Thread

Expand Down Expand Up @@ -28,6 +29,9 @@ def __init__(self, python_version):
self.socket_server = Server()
self.is_running = False

signal.signal(signal.SIGINT, self.close)
signal.signal(signal.SIGTERM, self.close)

def set_chrome_path(self):
"""Tries to set the path to the chrome directory."""
self.chrome_path = get_firefox_chrome_path()
Expand Down Expand Up @@ -198,16 +202,15 @@ def start(self):
"""Starts the daemon and listens for incoming messages."""
self.is_running = True
self.start_socket_server()
try:
while True:
message = self.messenger.get_message()
logging.debug('Received message from extension: %s' % message)
self.handle_message(message)
except KeyboardInterrupt:
return

def close(self):

while self.is_running:
message = self.messenger.get_message()
logging.debug('Received message from extension: %s' % message)
self.handle_message(message)

def close(self, signal, frame):
"""Application cleanup."""
self.socket_server.close()
logging.debug('Running cleanup')
self.is_running = False
logging.debug('Cleanup')
self.socket_server.close()
sys.exit(0)

0 comments on commit 1e51619

Please sign in to comment.