Commits

Arkaitz Jimenez committed 102a461

Receiving works for hybi sockets, tested with Firefox and Chromium

Also, fileno() added to WebSocket for polling

  • Participants
  • Parent commits ddce9d8
  • Branches default

Comments (0)

Files changed (1)

File geventwebsocket/websocket.py

         with self._writelock:
             self.socket.sendall(framebytes)
 
+    def fileno(self):
+        return self.socket.fileno()
+
     def detach(self):
         self.socket = None
         self.rfile = None
             self.detach()
 
 
-    def _message_length(self):
-        # TODO: buildin security agains lengths greater than 2**31 or 2**32
-        length = 0
-
-        while True:
-            byte_str = self.rfile.read(1)
-
-            if not byte_str:
-                return 0
-            else:
-                byte = ord(byte_str)
-
-            if byte != 0x00:
-                length = length * 128 + (byte & 0x7f)
-                if (byte & 0x80) != 0x80:
-                    break
-
+    def _extended_length(self,length):
+        if length == 126:
+            (length,) = struct.unpack("!H",self.rfile.read(2))[0]
+        elif length == 127:
+            (length,) = struct.unpack("!Q",self.rfile.read(8))[0]
         return length
 
     def _read_until(self):
 
         return ''.join(bytes)
 
+    def apply_mask(self,data,mask):
+        output = ''
+        for i,val in enumerate(data):
+            off = i % 4
+            output += chr(ord(mask[off]) ^ ord(val))
+
+        return output
+
+
     def receive(self):
-        while self.socket is not None:
+        if self.socket is not None:
             frame_str = self.rfile.read(1)
             if not frame_str:
                 # Connection lost?
                 self.close()
-                break
+                return None
             else:
                 frame_type = ord(frame_str)
 
-
-            if (frame_type & 0x80) == 0x00: # most significant byte is not set
+            if (frame_type & 0x80) == 0x00: # most significant byte is not set, Old version
                 if frame_type == 0x00:
-                    bytes = self._read_until()
-                    return bytes.decode("utf-8", "replace")
+                    buff = self._read_until()
+                    return buff.decode("utf-8", "replace")
                 else:
                     self.close()
-            elif (frame_type & 0x80) == 0x80: # most significant byte is set
-                # Read binary data (forward-compatibility)
-                if frame_type != 0xff:
+            elif (frame_type & 0x80) == 0x80: # most significant byte is set, New version
+                opcode = (frame_type & 0xF)
+                if opcode != 1:
                     self.close()
-                    break
+                    return None
                 else:
-                    length = self._message_length()
+                    maskandlength = ord(self.rfile.read(1))
+                    (mask,length) = (maskandlength >> 7), (maskandlength & 0x7F)
+                    if length > 125:
+                        length = self._extended_length(length)
                     if length == 0:
                         self.close()
-                        break
+                        return None
+                    if mask:
+                        mask_value = self.rfile.read(4)
+                        data = self.rfile.read(length)
+                        return self.apply_mask(data,mask_value)
                     else:
-                        self.rfile.read(length) # discard the bytes
+                        return self.rfile.read(length) # discard the bytes
             else:
                 raise IOError("Reveiced an invalid message")