17
17
18
18
19
19
logging .basicConfig (level = logging .DEBUG )
20
- logger = logging .getLogger ()
21
20
here = pathlib .Path (__file__ ).parent
22
21
23
22
@@ -27,7 +26,6 @@ def commands():
27
26
print ('send <MESSAGE> -> send message' )
28
27
print ('ping <PAYLOAD> -> send ping with payload' )
29
28
print ('close [<REASON>] -> politely close connection with optional reason' )
30
- print ('[ctrl+D] -> rudely close connection' )
31
29
print ()
32
30
33
31
@@ -55,39 +53,54 @@ async def main(args):
55
53
try :
56
54
logging .debug ('Connecting to WebSocket…' )
57
55
async with open_websocket_url (args .url , ssl_context ) as conn :
58
- logging .debug ('Connected!' )
59
56
await handle_connection (conn )
60
- logging .debug ('Connection closed' )
61
57
except OSError as ose :
62
58
logging .error ('Connection attempt failed: %s' , ose )
63
59
return False
64
60
65
61
66
- async def handle_connection (connection ):
62
+ async def handle_connection (ws ):
67
63
''' Handle the connection. '''
64
+ logging .debug ('Connected!' )
65
+ try :
66
+ async with trio .open_nursery () as nursery :
67
+ nursery .start_soon (get_commands , ws )
68
+ nursery .start_soon (get_messages , ws )
69
+ except ConnectionClosed as cc :
70
+ reason = '<no reason>' if cc .reason .reason is None else '"{}"' .format (
71
+ cc .reason .reason )
72
+ print ('Closed: {}/{} {}' .format (cc .reason .code , cc .reason .name , reason ))
73
+
74
+
75
+ async def get_commands (ws ):
76
+ ''' In a loop: get a command from the user and execute it. '''
68
77
while True :
69
- try :
70
- logger .debug ('top of loop' )
71
- await trio .sleep (0.1 ) # allow time for connection logging
72
- cmd = await trio .run_sync_in_worker_thread (input , 'cmd> ' ,
73
- cancellable = True )
74
- if cmd .startswith ('ping ' ):
75
- await connection .ping (cmd [5 :].encode ('utf8' ))
76
- elif cmd .startswith ('send ' ):
77
- await connection .send_message (cmd [5 :])
78
- message = await connection .get_message ()
79
- print ('response> {}' .format (message ))
80
- elif cmd .startswith ('close' ):
81
- try :
82
- reason = cmd [6 :]
83
- except IndexError :
84
- reason = None
85
- await connection .aclose (code = 1000 , reason = reason )
86
- break
78
+ cmd = await trio .run_sync_in_worker_thread (input , 'cmd> ' ,
79
+ cancellable = True )
80
+ if cmd .startswith ('ping' ):
81
+ payload = cmd [5 :].encode ('utf8' ) or None
82
+ await ws .ping (payload )
83
+ elif cmd .startswith ('send' ):
84
+ message = cmd [5 :] or None
85
+ if message is None :
86
+ logging .error ('The "send" command requires a message.' )
87
87
else :
88
- commands ()
89
- except ConnectionClosed :
88
+ await ws .send_message (message )
89
+ elif cmd .startswith ('close' ):
90
+ reason = cmd [6 :] or None
91
+ await ws .aclose (code = 1000 , reason = reason )
90
92
break
93
+ else :
94
+ commands ()
95
+ # Allow time to receive response and log print logs:
96
+ await trio .sleep (0.25 )
97
+
98
+
99
+ async def get_messages (ws ):
100
+ ''' In a loop: get a WebSocket message and print it out. '''
101
+ while True :
102
+ message = await ws .get_message ()
103
+ print ('message: {}' .format (message ))
91
104
92
105
93
106
if __name__ == '__main__' :
0 commit comments