1# Copyright 2019 The Chromium Authors 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5from six.moves.urllib import parse 6from mod_pywebsocket import stream 7import threading 8 9 10cv = threading.Condition() 11connected = False 12close_code = None 13 14 15def get_role(request): 16 """Look up the "role" query parameter in the URL.""" 17 query = request.ws_resource.split('?', 1) 18 if len(query) == 1: 19 raise LookupError('No query string found in URL') 20 param = parse.parse_qs(query[1]) 21 if 'role' not in param: 22 raise LookupError('No role parameter found in the query string') 23 return param['role'][0] 24 25 26def be_observed(request): 27 global connected 28 with cv: 29 connected = True 30 # Wait for a Close frame 31 try: 32 request.ws_stream.receive_message() 33 except stream.ConnectionTerminatedException: 34 observe_close(1006) # "Abnormal Closure" 35 36 37def be_observer(request): 38 with cv: 39 if not connected: 40 request.ws_stream.send_message('NOT CONNECTED', binary = False) 41 else: 42 while close_code is None: 43 cv.wait() 44 if close_code == 1001: # "Going Away" 45 request.ws_stream.send_message('OK', binary = False) 46 else: 47 request.ws_stream.send_message('WRONG CODE %d' % close_code, 48 binary = False) 49 request.ws_stream.close_connection() 50 51 52def web_socket_do_extra_handshake(request): 53 pass 54 55 56def web_socket_transfer_data(request): 57 role = get_role(request) 58 if role == 'observed': 59 be_observed(request) 60 elif role == 'observer': 61 be_observer(request) 62 else: 63 raise ValueError('Bad role "%s"' % role) 64 65 66def web_socket_passive_closing_handshake(request): 67 if get_role(request) == 'observed': 68 observe_close(request.ws_close_code) 69 return request.ws_close_code, request.ws_close_reason 70 71 72def observe_close(code): 73 global close_code 74 with cv: 75 close_code = code 76 cv.notify() 77