You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

websocketcontext.py 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. from copy import deepcopy
  2. from struct import unpack
  3. from .gripcontrol import is_python3, websocket_control_message
  4. from .websocketevent import WebSocketEvent
  5. class WebSocketContext(object):
  6. def __init__(self, id, meta, in_events, grip_prefix=''):
  7. self.id = id
  8. self.in_events = in_events
  9. self.read_index = 0
  10. self.accepted = False
  11. self.close_code = None
  12. self.closed = False
  13. self.out_close_code = None
  14. self.out_events = []
  15. self.orig_meta = meta
  16. self.meta = deepcopy(meta)
  17. self.grip_prefix = grip_prefix
  18. def is_opening(self):
  19. return (self.in_events and self.in_events[0].type == 'OPEN')
  20. def accept(self):
  21. self.accepted = True
  22. def close(self, code=None):
  23. self.closed = True
  24. if code is not None:
  25. self.out_close_code = code
  26. else:
  27. self.out_close_code = 0
  28. def can_recv(self):
  29. for n in range(self.read_index, len(self.in_events)):
  30. if self.in_events[n].type in ('TEXT', 'BINARY', 'CLOSE', 'DISCONNECT'):
  31. return True
  32. return False
  33. def recv(self):
  34. e = None
  35. while e is None and self.read_index < len(self.in_events):
  36. if self.in_events[self.read_index].type in ('TEXT', 'BINARY', 'CLOSE', 'DISCONNECT'):
  37. e = self.in_events[self.read_index]
  38. elif self.in_events[self.read_index].type == 'PING':
  39. self.out_events.append(WebSocketEvent('PONG'))
  40. self.read_index += 1
  41. if e is None:
  42. raise IndexError('read from empty buffer')
  43. if e.type == 'TEXT':
  44. if e.content:
  45. return e.content.decode('utf-8')
  46. else:
  47. if is_python3:
  48. return ''
  49. else:
  50. return u''
  51. elif e.type == 'BINARY':
  52. if e.content:
  53. return e.content
  54. else:
  55. if is_python3:
  56. return b''
  57. else:
  58. return ''
  59. elif e.type == 'CLOSE':
  60. if e.content and len(e.content) == 2:
  61. self.close_code = unpack('>H', e.content)[0]
  62. return None
  63. else: # DISCONNECT
  64. raise IOError('client disconnected unexpectedly')
  65. def send(self, message):
  66. if is_python3:
  67. if isinstance(message, str):
  68. message = message.encode('utf-8')
  69. content = b'm:' + message
  70. else:
  71. if isinstance(message, unicode):
  72. message = message.encode('utf-8')
  73. content = 'm:' + message
  74. self.out_events.append(WebSocketEvent('TEXT', content))
  75. def send_binary(self, message):
  76. if is_python3:
  77. if isinstance(message, str):
  78. message = message.encode('utf-8')
  79. content = b'm:' + message
  80. else:
  81. if isinstance(message, unicode):
  82. message = message.encode('utf-8')
  83. content = 'm:' + message
  84. self.out_events.append(WebSocketEvent('BINARY', content))
  85. def send_control(self, message):
  86. if is_python3:
  87. if isinstance(message, str):
  88. message = message.encode('utf-8')
  89. content = b'c:' + message
  90. else:
  91. if isinstance(message, unicode):
  92. message = message.encode('utf-8')
  93. content = 'c:' + message
  94. self.out_events.append(WebSocketEvent('TEXT', content))
  95. def subscribe(self, channel):
  96. self.send_control(websocket_control_message(
  97. 'subscribe', {'channel': self.grip_prefix + channel}))
  98. def unsubscribe(self, channel):
  99. self.send_control(websocket_control_message(
  100. 'unsubscribe', {'channel': self.grip_prefix + channel}))
  101. def detach(self):
  102. self.send_control(websocket_control_message('detach'))