177 lines
5.2 KiB
Python
177 lines
5.2 KiB
Python
import socket
|
|
import selectors
|
|
|
|
from protocol import DefaultHandler
|
|
from protocol import NoReply
|
|
|
|
|
|
def accept_connection(sel, sock, callback):
|
|
"""
|
|
Accepts an incoming connection using protocol.DefaultHandler.
|
|
|
|
Args:
|
|
sel (selector): A selector from selectors module.
|
|
sock (socket): A socket from socket module.
|
|
callback (Pattern): Implementation of protocol.Pattern.
|
|
|
|
Returns:
|
|
None.
|
|
"""
|
|
conn, addr = sock.accept()
|
|
tag = addr
|
|
if conn.family == socket.AF_UNIX:
|
|
tag = f'<UNIX-{conn.getsockname()}>'
|
|
conn.setblocking(False)
|
|
handler = DefaultHandler(sel, conn, addr, tag)
|
|
handler.setpattern(callback)
|
|
events = selectors.EVENT_READ
|
|
sel.register(conn, events, data=handler)
|
|
|
|
|
|
def register_udp_handler(sel, ip, port):
|
|
"""
|
|
UPD listening with a predefined protocol.DefaultHandler.
|
|
|
|
Args:
|
|
sel (selector): A selector from selectors module.
|
|
ip (str): Broadcasting lan IP address.
|
|
port (int): Port to listen to.
|
|
|
|
Returns:
|
|
DefaultHandler: The handler registered in selector.
|
|
"""
|
|
udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM,
|
|
socket.IPPROTO_UDP)
|
|
udp_sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
|
udp_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
udp_sock.bind((ip, port)) # no need to listen for UDP
|
|
print(f'Listening on {(ip, port)}')
|
|
udp_sock.setblocking(False)
|
|
udp_handler = DefaultHandler(sel, udp_sock, ip, 'udp')
|
|
# set data=udp_handler right here as accept_connection()
|
|
# cannot be applied in case of UDP
|
|
sel.register(udp_sock, selectors.EVENT_READ, data=udp_handler)
|
|
return udp_handler
|
|
|
|
|
|
def register_unix_handler(sel, path):
|
|
"""
|
|
UNIX listening. A handler is to be set on accepting a new connection.
|
|
|
|
Args:
|
|
sel (selector): A selector from selectors module.
|
|
path (str): A path to the UNIX socket.
|
|
|
|
Returns:
|
|
None.
|
|
"""
|
|
unix_sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
unix_sock.bind(path)
|
|
unix_sock.listen(1)
|
|
unix_sock.setblocking(False)
|
|
sel.register(unix_sock, selectors.EVENT_READ, data=None)
|
|
|
|
|
|
def register_tcp_handler(sel, ip, port):
|
|
"""
|
|
TCP listening. A handler is to be set on accepting a new connection.
|
|
|
|
Args:
|
|
sel (selector): A selector from selectors module.
|
|
ip (str): This machine's lan IP address.
|
|
port (int): Port to listen to.
|
|
|
|
Returns:
|
|
None.
|
|
"""
|
|
tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
tcp_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
tcp_sock.bind((ip, port))
|
|
tcp_sock.listen()
|
|
print(f'Listening on {(ip, port)}')
|
|
tcp_sock.setblocking(False)
|
|
sel.register(tcp_sock, selectors.EVENT_READ, data=None)
|
|
|
|
|
|
def send_via_tcp(sel, ip, port, pattern, *missives):
|
|
"""
|
|
Initialize outbound TCP connection with protocol.DefaultHandler.
|
|
|
|
Args:
|
|
sel (selector): A selector from selectors module.
|
|
ip (str): This machine's lan IP address.
|
|
port (int): Port to listen to.
|
|
pattern (Pattern): Implementation of protocol.Pattern.
|
|
missives (Missive): A sequence of messages to send.
|
|
|
|
Returns:
|
|
None.
|
|
"""
|
|
if not missives:
|
|
return
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
sock.setblocking(True)
|
|
sock.connect((ip, port))
|
|
events = selectors.EVENT_WRITE
|
|
handler = DefaultHandler(sel, sock, ip, 'tcp-out')
|
|
handler.setpattern(pattern)
|
|
sel.register(sock, events, data=handler)
|
|
for missive in missives:
|
|
handler.enqueue(missive)
|
|
|
|
|
|
def broadcast_via_udp(sel, ip, port, missive):
|
|
"""
|
|
Initialize UDP broadcast with protocol.DefaultHandler.
|
|
|
|
Args:
|
|
sel (selector): A selector from selectors module.
|
|
ip (str): Broacasting lan IP address.
|
|
port (int): Port for broadcasting.
|
|
missive (Missive): A message to send out.
|
|
|
|
Returns:
|
|
None.
|
|
"""
|
|
if not missive:
|
|
return
|
|
sock = socket.socket(socket.AF_INET,
|
|
socket.SOCK_DGRAM,
|
|
socket.IPPROTO_UDP)
|
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
sock.setblocking(True)
|
|
sock.bind((ip, port))
|
|
events = selectors.EVENT_WRITE
|
|
handler = DefaultHandler(sel, sock, ip, 'udp-out')
|
|
handler.setpattern(NoReply())
|
|
sel.register(sock, events, data=handler)
|
|
handler.enqueue(missive)
|
|
|
|
|
|
def send_via_unix(sel, path, pattern, *missives):
|
|
"""
|
|
Initialize UNIX socket connection with protocol.DefaultHandler.
|
|
|
|
Args:
|
|
sel (selector): A selector from selectors module.
|
|
path (str): A path to a UNIX socket file.
|
|
pattern (Pattern): Implementation of protocol.Pattern.
|
|
missives (Missive): A sequence of messages to send.
|
|
|
|
Returns:
|
|
None.
|
|
"""
|
|
if not missives:
|
|
return
|
|
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
|
sock.setblocking(True)
|
|
sock.connect(path)
|
|
events = selectors.EVENT_WRITE
|
|
handler = DefaultHandler(sel, sock,
|
|
path, 'unix-out')
|
|
handler.setpattern(pattern)
|
|
sel.register(sock, events, data=handler)
|
|
for missive in missives:
|
|
handler.enqueue(missive)
|