frame.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. import struct
  2. from os import urandom
  3. from exceptions import SocketClosed
  4. OPCODE_CONTINUATION = 0x0
  5. OPCODE_TEXT = 0x1
  6. OPCODE_BINARY = 0x2
  7. OPCODE_CLOSE = 0x8
  8. OPCODE_PING = 0x9
  9. OPCODE_PONG = 0xA
  10. CLOSE_NORMAL = 1000
  11. CLOSE_GOING_AWAY = 1001
  12. CLOSE_PROTOCOL_ERROR = 1002
  13. CLOSE_NOACCEPT_DTYPE = 1003
  14. CLOSE_INVALID_DATA = 1007
  15. CLOSE_POLICY = 1008
  16. CLOSE_MESSAGE_TOOBIG = 1009
  17. CLOSE_MISSING_EXTENSIONS = 1010
  18. CLOSE_UNABLE = 1011
  19. class Frame(object):
  20. """
  21. A Frame instance represents a web socket data frame as defined in RFC 6455.
  22. To encoding a frame for sending it over a socket, use Frame.pack(). To
  23. receive and decode a frame from a socket, use receive_frame() (or,
  24. preferably, receive_fragments()).
  25. """
  26. def __init__(self, opcode, payload, masking_key='', final=True, rsv1=False,
  27. rsv2=False, rsv3=False):
  28. """
  29. Create a new frame.
  30. `opcode' is one of the constants as defined above.
  31. `payload' is a string of bytes containing the data sendt in the frame.
  32. `final` is a boolean indicating whether this frame is the last in a
  33. chain of fragments.
  34. `rsv1', `rsv2' and `rsv3' are booleans indicating bit values for RSV1,
  35. RVS2 and RSV3, which are only non-zero if defined so by extensions.
  36. """
  37. if len(masking_key) not in (0, 4):
  38. raise ValueError('invalid masking key "%s"' % masking_key)
  39. self.final = final
  40. self.rsv1 = rsv1
  41. self.rsv2 = rsv2
  42. self.rsv3 = rsv3
  43. self.opcode = opcode
  44. self.masking_key = masking_key
  45. self.payload = payload
  46. def pack(self):
  47. """
  48. Pack the frame into a string according to the following scheme:
  49. +-+-+-+-+-------+-+-------------+-------------------------------+
  50. |F|R|R|R| opcode|M| Payload len | Extended payload length |
  51. |I|S|S|S| (4) |A| (7) | (16/64) |
  52. |N|V|V|V| |S| | (if payload len==126/127) |
  53. | |1|2|3| |K| | |
  54. +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
  55. | Extended payload length continued, if payload len == 127 |
  56. + - - - - - - - - - - - - - - - +-------------------------------+
  57. | |Masking-key, if MASK set to 1 |
  58. +-------------------------------+-------------------------------+
  59. | Masking-key (continued) | Payload Data |
  60. +-------------------------------- - - - - - - - - - - - - - - - +
  61. : Payload Data continued ... :
  62. + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
  63. | Payload Data continued ... |
  64. +---------------------------------------------------------------+
  65. """
  66. header = struct.pack('!B', (self.fin << 7) | (self.rsv1 << 6) |
  67. (self.rsv2 << 5) | (self.rsv3 << 4) | self.opcode)
  68. mask = bool(self.masking_key) << 7
  69. payload_len = len(self.payload)
  70. if payload_len <= 125:
  71. header += struct.pack('!B', mask | payload_len)
  72. elif payload_len < (1 << 16):
  73. header += struct.pack('!BH', mask | 126, payload_len)
  74. elif payload_len < (1 << 63):
  75. header += struct.pack('!BQ', mask | 127, payload_len)
  76. else:
  77. raise Exception('the payload length is too damn high!')
  78. if mask:
  79. return header + self.masking_key + self.mask_payload()
  80. return header + self.payload
  81. def mask_payload(self):
  82. return mask(self.masking_key, self.payload)
  83. def fragment(self, fragment_size, mask=False):
  84. """
  85. Fragment the frame into a chain of fragment frames, as explained in the
  86. docs of the function receive_fragments().
  87. `fragment_size' indicates the maximum payload size of each fragment.
  88. The payload of the original frame is split into one or more parts, and
  89. each part is converted to a Frame instance.
  90. `mask' is a boolean (default False) indicating whether the payloads
  91. should be masked. If True, each frame is assigned a randomly generated
  92. masking key.
  93. """
  94. frames = []
  95. for start in range(0, len(self.payload), fragment_size):
  96. payload = self.payload[start:start + fragment_size]
  97. key = urandom(4) if mask else ''
  98. frames.append(Frame(OPCODE_CONTINUATION, payload, key, False))
  99. frames[0].opcode = self.opcode
  100. frames[-1].final = True
  101. return frames
  102. def __str__(self):
  103. s = '<%s opcode=0x%X len=%d' \
  104. % (self.__class__.__name__, self.opcode, len(self.payload))
  105. if self.masking_key:
  106. s += ' masking_key=%4s' % self.masking_key
  107. return s + '>'
  108. class ControlFrame(Frame):
  109. """
  110. A Control frame is a frame with an opcode OPCODE_CLOSE, OPCODE_PING or
  111. OPCODE_PONG. These frames must be handled as defined by RFC 6455, and
  112. """
  113. def fragment(self, fragment_size, mask=False):
  114. """
  115. Control frames must not be fragmented.
  116. """
  117. raise TypeError('control frames must not be fragmented')
  118. def pack(self):
  119. """
  120. Same as Frame.pack(), but asserts that the payload size does not exceed
  121. 125 bytes.
  122. """
  123. if len(self.payload) > 125:
  124. raise ValueError('control frames must not be larger than 125' \
  125. 'bytes')
  126. return Frame.pack(self)
  127. def unpack_close(self):
  128. """
  129. Unpack a close message into a status code and a reason. If no payload
  130. is given, the code is None and the reason is an empty string.
  131. """
  132. if self.payload:
  133. code = struct.unpack('!H', self.payload[:2])
  134. reason = self.payload[2:]
  135. else:
  136. code = None
  137. reason = ''
  138. return code, reason
  139. def receive_fragments(sock, control_frame_handler):
  140. """
  141. Receive a sequence of frames that belong together on socket `sock':
  142. - An initial frame with non-zero opcode
  143. - Zero or more frames with opcode = 0 and final = False
  144. - A final frame with opcode = 0 and final = True
  145. The first and last frame may be the same frame, having a non-zero opcode
  146. and final = True. Thus, this function returns a list of at least a single
  147. frame.
  148. `control_frame_handler' is a callback function taking a single argument,
  149. which is a Frame instance
  150. """
  151. fragments = []
  152. while not len(fragments) or not fragments[-1].final:
  153. frame = receive_frame(sock)
  154. if isinstance(frame, ControlFrame):
  155. control_frame_handler(frame)
  156. # No more receiving data after a close message
  157. if frame.opcode == OPCODE_CLOSE:
  158. break
  159. else:
  160. fragments.append(frame)
  161. return fragments
  162. def receive_frame(sock):
  163. """
  164. Receive a single frame on socket `sock'. The frame schme is explained in
  165. the docs of Frame.pack().
  166. """
  167. b1, b2 = struct.unpack('!BB', recvn(sock, 2))
  168. final = bool(b1 & 0x80)
  169. rsv1 = bool(b1 & 0x40)
  170. rsv2 = bool(b1 & 0x20)
  171. rsv3 = bool(b1 & 0x10)
  172. opcode = b1 & 0x0F
  173. mask = bool(b2 & 0x80)
  174. payload_len = b2 & 0x7F
  175. if payload_len == 126:
  176. payload_len = struct.unpack('!H', recvn(sock, 2))
  177. elif payload_len == 127:
  178. payload_len = struct.unpack('!Q', recvn(sock, 8))
  179. if mask:
  180. masking_key = recvn(sock, 4)
  181. payload = mask(masking_key, recvn(sock, payload_len))
  182. else:
  183. masking_key = ''
  184. payload = recvn(sock, payload_len)
  185. # Control frames have most significant bit 1
  186. cls = ControlFrame if opcode & 0x8 else Frame
  187. return cls(opcode, payload, masking_key=masking_key, final=final,
  188. rsv1=rsv1, rsv2=rsv2, rsv3=rsv3)
  189. def recvn(sock, n):
  190. """
  191. Keep receiving data from `sock' until exactly `n' bytes have been read.
  192. """
  193. data = ''
  194. while len(data) < n:
  195. received = sock.recv(n - len(data))
  196. if not len(received):
  197. raise SocketClosed()
  198. data += received
  199. return data
  200. def mask(key, original):
  201. """
  202. Mask an octet string using the given masking key.
  203. The following masking algorithm is used, as defined in RFC 6455:
  204. for each octet:
  205. j = i MOD 4
  206. transformed-octet-i = original-octet-i XOR masking-key-octet-j
  207. """
  208. if len(key) != 4:
  209. raise ValueError('invalid masking key "%s"' % key)
  210. key = map(ord, key)
  211. masked = bytearray(original)
  212. for i in xrange(len(masked)):
  213. masked[i] ^= key[i % 4]
  214. return masked