Commits

Ginés Martínez Sánchez committed 90786a3 Draft

developing websocket

  • Participants
  • Parent commits f767c0d

Comments (0)

Files changed (1)

File ginsfsm/protocols/sockjs/server/c_websocket.py

 
 
 class FRAME_HEADER_S(object):
-    """ Websocket header: two bytes.
+    """ Websocket frame header
+
+    This class controls the first two bytes of header:
 
       0                   1
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
      |N|V|V|V|       |S|             |
      | |1|2|3|       |K|             |
      +-+-+-+-+-------+-+-------------+
+
+    Full header:
+
+      0                   1                   2                   3
+      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+     +-+-+-+-+-------+-+-------------+-------------------------------+
+     |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
+     |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
+     |N|V|V|V|       |S|             |   (if payload len==126/127)   |
+     | |1|2|3|       |K|             |                               |
+     +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
+     |     Extended payload length continued, if payload len == 127  |
+     + - - - - - - - - - - - - - - - +-------------------------------+
+     |                               |Masking-key, if MASK set to 1  |
+     +-------------------------------+-------------------------------+
+     | Masking-key (continued)       |          Payload Data         |
+     +-------------------------------- - - - - - - - - - - - - - - - +
+     :                     Payload Data continued ...                :
+     + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
+     |                     Payload Data continued ...                |
+     +---------------------------------------------------------------+
     """
 
     packer = struct.Struct('BB')
 
-    def __init__(self, opcode=0, final=0, mask=0, frame_len=0):
-        self.final = final
+    def __init__(self):
+        # Information of the first two bytes header
+        self.fin = 0  # final fragment in a message
         self.reserved_bits = 0
-        self.opcode = opcode
-        self.opcode_is_control = opcode & 0x8
-        self.mask = mask
-        self.frame_len = frame_len
+        self.opcode = 0
+        self.mask = 0  # Set to 1 a  masking key is present in masking-key
         self.payload_len = 0
+
+        # variables to help encode/decode frame
         self.complete = False
         self.error = False
-        self.to_close = False
+        self.must_close = False
+        self.must_read_extended_payload_length = False
+        self.must_read_masking_key = False
+        self.must_read_payload_data = False
+        self.masking_key = 0
+        self.payload_data_length = 0
 
-    def host_to_network(self):
-        if self.final:
-            byte1 = self.opcode | 0x80
+    def network_to_host(self, data):
+        if len(data) != 2:
+            raise RuntimeError('ERROR ntoh needs two bytes.')
+        byte1, byte2 = self.packer.unpack(bytes(data))
+
+        # decod byte1
+        self.fin = byte1 & 0x80
+        self.reserved_bits = byte1 & 0x70
+        self.opcode = byte1 & 0x0f
+
+        # decod byte2
+        self.mask = byte2 & 0x80
+        self.payload_len = byte2 & 0x7f
+
+    def host_to_network(self, fin, opcode, mask, payload_len):
+        self.fin = fin
+        self.reserved_bits = 0  # by the moment it's ignored.
+        self.opcode = opcode
+        self.mask = mask
+        self.payload_len = payload_len
+
+        if self.fin:
+            byte1 = (self.opcode & 0x0f) | 0x80
         else:
             byte1 = self.opcode
 
+        byte2 = self.
+        if self.mask:
+            byte2 = byte2 & 0x80
+
+        trama = self.packer.pack(byte1, byte2)
+        return bytearray(trama)
+
+    def yyy(self):
         ln = self.frame_len
         if ln < 126:
             # next: write 4 bytes of masking key IF client
         trama = self.packer.pack(byte1, byte2)
         return bytearray(trama)
 
-    def network_to_host(self, data):
-        byte1, byte2 = self.packer.unpack(bytes(data))
-
-        self.final = byte1 & 0x80
-        self.reserved_bits = byte1 & 0x70
-        self.opcode = byte1 & 0xf
-        self.opcode_is_control = self.opcode & 0x8
-        self.mask = byte2 & 0x80
-        ln = self.payload_len = byte2 & 0x7f
+    def xxx(self, ln):
         if ln < 126:
             # next: read 4 bytes of masking key
             self.frame_len = self.payload_len
             # next: read 4 bytes of masking key
             self.frame_len = 0
 
+
     @property
     def size(self):
         return self.packer.size
         #
         control = hd.opcode
         if control == OPCODE_CONTROL_CLOSE:
-            hd.to_close = True
+            hd.close = True
             pass
         elif control == OPCODE_CONTROL_PING:
             pass
         # Reject it if there is no at list 2 bytes.
         #
         hd = analize_header(gmsg, self.iam_server)
-        if hd.to_close or hd.error:
+        if hd.close or hd.error:
             self.remove_gmsgs()
             self.gsock.mt_drop()
             return
             for i in xrange(ln):
                 unmasked[i] = unmasked[i] ^ mask[i % 4]
 
-            if hd.final:
+            if hd.fin:
                 print "<====== MESSAGE", unmasked
                 self.handle_message(hd.opcode, unmasked)
 
         assert isinstance(message, binary_type)
         self._write_frame(True, opcode, message)
 
-    def _write_frame(self, final, opcode, data):
-        if final:
+    def _write_frame(self, fin, opcode, data):
+        if fin:
             finbit = opcode | 0x80
         else:
             finbit = opcode