-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(cli): replace TCP server with Named Pipe server for command hand…
…ling This change introduces a Named Pipe server to handle application control commands instead of the previous TCP server implementation. The new CLI pipe server improves communication efficiency and reliability, particularly in Windows environments. The relevant classes and methods have been updated to reflect this change, ensuring seamless operation of the application.
- Loading branch information
Showing
3 changed files
with
108 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,73 @@ | ||
import socket | ||
import logging | ||
import threading | ||
import win32pipe, win32file, pywintypes | ||
from settings import DEBUG | ||
|
||
class TCPHandler: | ||
class CliPipeHandler: | ||
def __init__(self, stop_or_reload_callback): | ||
self.stop_or_reload_callback = stop_or_reload_callback | ||
self.pipe_name = r'\\.\pipe\yasb_pipe' | ||
self.server_thread = None | ||
self.stop_event = threading.Event() | ||
|
||
def handle_client_connection(self, conn, addr): | ||
with conn: | ||
try: | ||
command = conn.recv(1024).decode('utf-8').strip() | ||
logging.info(f"YASB received command: {command}") | ||
def handle_client_connection(self, pipe): | ||
try: | ||
while True: | ||
data = win32file.ReadFile(pipe, 64*1024) | ||
command = data[1].decode('utf-8').strip() | ||
if DEBUG: | ||
logging.info(f"YASB received command {command}") | ||
if command.lower() == 'stop': | ||
conn.sendall(b'ACK') | ||
win32file.WriteFile(pipe, b'ACK') | ||
self.stop_or_reload_callback() | ||
self.stop_cli_pipe_server() | ||
elif command.lower() == 'reload': | ||
conn.sendall(b'ACK') | ||
win32file.WriteFile(pipe, b'ACK') | ||
self.stop_or_reload_callback(reload=True) | ||
self.stop_cli_pipe_server() | ||
else: | ||
conn.sendall(b'YASB Unknown Command') | ||
except Exception as e: | ||
logging.error(f"Error handling client {addr}: {e}") | ||
win32file.WriteFile(pipe, b'YASB Unknown Command') | ||
except pywintypes.error as e: | ||
if e.args[0] == 109: # ERROR_BROKEN_PIPE | ||
if DEBUG: | ||
logging.info("Pipe closed by client") | ||
else: | ||
logging.error(f"YASB CLI error handling client: {e}") | ||
|
||
def start_socket_server(self, host='localhost', port=65432): | ||
def start_cli_pipe_server(self): | ||
""" | ||
Start the TCP server to listen for incoming commands. | ||
Start the Named Pipe server to listen for incoming commands. | ||
""" | ||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server: | ||
try: | ||
server.bind((host, port)) | ||
server.listen() | ||
logging.info(f"YASB socket server started on {host}:{port}") | ||
while True: | ||
conn, addr = server.accept() | ||
client_thread = threading.Thread(target=self.handle_client_connection, args=(conn, addr)) | ||
def run_server(): | ||
if DEBUG: | ||
logging.info(f"YASB CLI Pipe server started") | ||
while not self.stop_event.is_set(): | ||
pipe = win32pipe.CreateNamedPipe( | ||
self.pipe_name, | ||
win32pipe.PIPE_ACCESS_DUPLEX, | ||
win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_READMODE_MESSAGE | win32pipe.PIPE_WAIT, | ||
1, 65536, 65536, | ||
0, | ||
None | ||
) | ||
try: | ||
win32pipe.ConnectNamedPipe(pipe, None) | ||
client_thread = threading.Thread(target=self.handle_client_connection, args=(pipe,)) | ||
client_thread.start() | ||
except Exception as e: | ||
logging.error(f"Socket server encountered an error: {e}") | ||
except Exception as e: | ||
logging.error(f"Pipe server encountered an error: {e}") | ||
win32pipe.DisconnectNamedPipe(pipe) | ||
|
||
self.stop_event.clear() | ||
self.server_thread = threading.Thread(target=run_server) | ||
self.server_thread.start() | ||
|
||
def stop_cli_pipe_server(self): | ||
""" | ||
Stop the Named Pipe server. | ||
""" | ||
self.stop_event.set() | ||
if self.server_thread: | ||
self.server_thread.join() | ||
if DEBUG: | ||
logging.info("YASB Named Pipe server stopped") |