examples/webrtc/signalling: Fix compatibility with Python 3.10

- ssl module requires an explicit TLS_SERVER role
- asyncio throws a deprecation warning when using
  asyncio.get_event_loop().  Remove custom event loop handling entirely
- No need to keep the websocket server in a member variable, can use
  a future to signal exit case along with the async with context manager
  of websockets.serve()

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2711>
This commit is contained in:
Matthew Waters 2022-07-01 15:20:31 +10:00 committed by Tim-Philipp Müller
parent acde6ff8be
commit 3e3ee9e6f5

View file

@ -20,7 +20,7 @@ import concurrent
class WebRTCSimpleServer(object): class WebRTCSimpleServer(object):
def __init__(self, loop, options): def __init__(self, options):
############### Global data ############### ############### Global data ###############
# Format: {uid: (Peer WebSocketServerProtocol, # Format: {uid: (Peer WebSocketServerProtocol,
@ -35,11 +35,6 @@ class WebRTCSimpleServer(object):
# Room dict with a set of peers in each room # Room dict with a set of peers in each room
self.rooms = dict() self.rooms = dict()
# Event loop
self.loop = loop
# Websocket Server Instance
self.server = None
# Options # Options
self.addr = options.addr self.addr = options.addr
self.port = options.port self.port = options.port
@ -112,7 +107,6 @@ class WebRTCSimpleServer(object):
############### Handler functions ############### ############### Handler functions ###############
async def connection_handler(self, ws, uid): async def connection_handler(self, ws, uid):
raddr = ws.remote_address raddr = ws.remote_address
peer_status = None peer_status = None
@ -219,7 +213,7 @@ class WebRTCSimpleServer(object):
if hello != 'HELLO': if hello != 'HELLO':
await ws.close(code=1002, reason='invalid protocol') await ws.close(code=1002, reason='invalid protocol')
raise Exception("Invalid hello from {!r}".format(raddr)) raise Exception("Invalid hello from {!r}".format(raddr))
if not uid or uid in self.peers or uid.split() != [uid]: # no whitespace if not uid or uid in self.peers or uid.split() != [uid]: # no whitespace
await ws.close(code=1002, reason='invalid peer uid') await ws.close(code=1002, reason='invalid peer uid')
raise Exception("Invalid uid {!r} from {!r}".format(uid, raddr)) raise Exception("Invalid uid {!r} from {!r}".format(uid, raddr))
# Send back a HELLO # Send back a HELLO
@ -241,7 +235,7 @@ class WebRTCSimpleServer(object):
# Create an SSL context to be used by the websocket server # Create an SSL context to be used by the websocket server
print('Using TLS with keys in {!r}'.format(self.cert_path)) print('Using TLS with keys in {!r}'.format(self.cert_path))
chain_pem, key_pem = self.get_ssl_certs() chain_pem, key_pem = self.get_ssl_certs()
sslctx = ssl.create_default_context() sslctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
try: try:
sslctx.load_cert_chain(chain_pem, keyfile=key_pem) sslctx.load_cert_chain(chain_pem, keyfile=key_pem)
except FileNotFoundError: except FileNotFoundError:
@ -252,7 +246,7 @@ class WebRTCSimpleServer(object):
sslctx.verify_mode = ssl.CERT_NONE sslctx.verify_mode = ssl.CERT_NONE
return sslctx return sslctx
def run(self): async def run(self):
async def handler(ws, path): async def handler(ws, path):
''' '''
All incoming messages are handled here. @path is unused. All incoming messages are handled here. @path is unused.
@ -277,22 +271,30 @@ class WebRTCSimpleServer(object):
# https://websockets.readthedocs.io/en/stable/api.html#websockets.protocol.WebSocketCommonProtocol # https://websockets.readthedocs.io/en/stable/api.html#websockets.protocol.WebSocketCommonProtocol
max_queue=16) max_queue=16)
# Setup logging
logger = logging.getLogger('websockets') logger = logging.getLogger('websockets')
logger.setLevel(logging.INFO) logger.setLevel(logging.INFO)
logger.addHandler(logging.StreamHandler()) handler = logging.StreamHandler()
logger.addHandler(handler)
# Run the server try:
self.server = self.loop.run_until_complete(wsd) self.exit_future = asyncio.Future()
# Stop the server if certificate changes task = asyncio.create_task(self.check_server_needs_restart())
self.loop.run_until_complete(self.check_server_needs_restart())
async def stop(self): # Run the server
print('Stopping server... ', end='') async with wsd:
self.server.close() await self.exit_future
await self.server.wait_closed() self.exit_future = None
self.loop.stop() print('Stopped.')
print('Stopped.') finally:
logger.removeHandler(handler)
self.peers = dict()
self.sessions = dict()
self.rooms = dict()
def stop(self):
if self.exit_future:
print('Stopping server... ', end='')
self.exit_future.set_result(None)
def check_cert_changed(self): def check_cert_changed(self):
chain_pem, key_pem = self.get_ssl_certs() chain_pem, key_pem = self.get_ssl_certs()
@ -313,7 +315,7 @@ class WebRTCSimpleServer(object):
await asyncio.sleep(10) await asyncio.sleep(10)
if self.check_cert_changed(): if self.check_cert_changed():
print('Certificate changed, stopping server...') print('Certificate changed, stopping server...')
await self.stop() self.stop()
return return
@ -330,16 +332,14 @@ def main():
options = parser.parse_args(sys.argv[1:]) options = parser.parse_args(sys.argv[1:])
loop = asyncio.get_event_loop()
r = WebRTCSimpleServer(loop, options)
print('Starting server...') print('Starting server...')
while True: while True:
r.run() r = WebRTCSimpleServer(options)
loop.run_forever() asyncio.run(r.run())
print('Restarting server...') print('Restarting server...')
print("Goodbye!") print("Goodbye!")
if __name__ == "__main__": if __name__ == "__main__":
main() main()