close-observer_wsh.py 1.9 KB

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