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