xref: /aosp_15_r20/external/cronet/net/data/websocket/close-observer_wsh.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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