def test_send_message_without_masking(self): tm = TextMessage(b'hello world') m = MagicMock() ws = WebSocket(sock=m) ws.send(tm) m.sendall.assert_called_once_with(tm.single())
def received_message(self, message): cherrypy.engine.publish('websocket-broadcast', TextMessage(message.data)) while message.data != 99: RGratio = (2*random.random()-1) #cherrypy.engine.publish('websocket-broadcast', TextMessage(message)) cherrypy.engine.publish('websocket-broadcast',TextMessage(printStuff())) time.sleep(0.4)
def received_message(self, message): """Handle received message.""" message = json.loads(message.data.decode('utf8')) self.logger.info('<--- {0}'.format(message)) response = None if message['command'] == 'hello': # Handshake response = { 'command': 'hello', 'protocols': [ 'http://livereload.com/protocols/official-7', ], 'serverName': 'nikola-livereload', } elif message['command'] == 'info': # Someone connected self.logger.info('****** Browser connected: {0}'.format( message.get('url'))) self.logger.info('****** sending {0} pending messages'.format( len(pending))) while pending: msg = pending.pop() self.logger.info('---> {0}'.format(msg.data)) self.send(msg, msg.is_binary) else: response = { 'command': 'alert', 'message': 'HEY', } if response is not None: response = json.dumps(response) self.logger.info('---> {0}'.format(response)) response = TextMessage(response) self.send(response, response.is_binary)
def test_receive_message_text(mocker): mocker.patch( 'autosubliminal.core.websocket.WebSocketHandler.handle_message', return_value=True) handler = WebSocketHandler(None) handler.received_message(TextMessage('{"key1": "value1"}')) handler.handle_message.assert_called_once_with({'key1': 'value1'})
def text_message(self, text): """ Returns a :class:`ws4py.messaging.TextMessage` instance ready to be built. Convenience method so that the caller doesn't need to import the :class:`ws4py.messaging.TextMessage` class itself. """ return TextMessage(text=text)
def received_message(self, m): if not hasattr(self,'msgNum'): self.msgNum=0 self.recvMsg = str(m) print "=> In Server, received message is: %s" % self.recvMsg #self.send(m.data, m.is_binary) msg = TextMessage("Ok! Response from server number:%d." %self.msgNum) self.send(msg) self.msgNum += 1
def send_text(self, text): """Send a message to the websocket. This method is a wrapper for the 'send' method. It shouldn't be calle directly, though. Prefer the 'send_JSON' method. """ msg = TextMessage(text) self.send(msg)
def text_message(self, text): """ Returns a messaging.TextMessage instance ready to be built. Convenience method so that the caller doesn't need to import the TextMessage class itself. @param text: data to be carried by the message """ return TextMessage(text=text)
def received_message(self, m): if not hasattr(self,'msgNum'): self.msgNum=0 print "=> In Client, received message is: %s" % str(m) if self.msgNum >= 5: self.close(reason='Bye bye') else: msg = TextMessage("Message again from client, number: %d." %self.msgNum) self.send(msg) self.msgNum+=1
def loader(self, status): """ CherryPy WSGI server doesn't offer a log facility, we add a straightforward WSGI middleware to do so, based on the CherryPy built-in logger. """ if status == 'finished': self.bus.log("Mounting the Django application") cherrypy.tree.graft(HTTPLogger(WSGIHandler())) cherrypy.engine.publish('websocket-broadcast', TextMessage('domoweb-ready'))
def closed(self, code, reason="A client left the room without a proper explanation."): #global CONNECTED_USERS #dict = {}#json.loads( m.data.decode(m.encoding) ) #dict['message'] = "{" + str(datetime.datetime.today().strftime("%H:%M:%S %d.%m.%y")) + " from " + str(dict['users']) + " } " + str(dict['message']) #CONNECTED_USERS = list(set(CONNECTED_USERS + dict['users'])) #dict['users'] = [user for user in CONNECTED_USERS] #cherrypy.log(str((dict))) #m.data = json.dumps(dict).encode(m.encoding) cherrypy.engine.publish('websocket-broadcast', TextMessage("param "))
def test_send_bytes_with_masking(self): tm = TextMessage(b'hello world').single(mask=True) m = MagicMock() ws = WebSocket(sock=m) ws.stream = MagicMock() ws.stream.always_mask = True ws.stream.text_message.return_value.single.return_value = tm ws.send(b'hello world') m.sendall.assert_called_once_with(tm)
def send_error(self, sender, error=None): """Send reload requests to the client.""" if self.stream is None: # No client connected or whatever return message = { 'command': 'alert', 'message': error, } response = json.dumps(message) response = TextMessage(response) if self.stream is None: # No client connected or whatever pending.append(response) else: self.send(response, response.is_binary)
def notify(self, sender, path): """Send reload requests to the client.""" p = os.path.join('/', path) message = { 'command': 'reload', 'liveCSS': True, 'path': p, } response = json.dumps(message) self.logger.info('---> {0}'.format(p)) response = TextMessage(response) if self.stream is None: # No client connected or whatever pending.append(response) else: self.send(response, response.is_binary)
def websocket_send(self, message): """ Send a message to all connected websockets. Args: message (JSON parsable object): Something we want to transmit to all the connected WebSocket instances. Must be parsable by json.dumps(), so strings, dicts, arrays and so on. """ logger.info('Broadcasting message to scene {}'.format( self._scene_hash)) msg = TextMessage(json.dumps(message)) for socket in self._websocket_list: socket.send(msg.data, msg.is_binary) return None
import gevent from gevent import monkey; monkey.patch_all() from ws4py.client.geventclient import WebSocketClient from ws4py.messaging import TextMessage class Lab126Client(WebSocketClient): def received_message(self, m): self.handle_message(m) #self.close(reason='Bye bye') def handle_message(self, m): print "===> In Client, received message from server is: %s" % str(m) #gevent.sleep(2) #self.send("Continue.") try: webSocketUrl = 'http://localhost:9000/ws' ws = Lab126Client(webSocketUrl) #ws.daemon = False ws.connect() msg = TextMessage("Message from lib client.") ws.send(msg) while True: message = ws.receive() print "+++receive response from server:%s" %message gevent.sleep(1) ws.send("Continue.") gevent.joinall([ws.run()]) except KeyboardInterrupt: ws.close()
def run(self, message): if not cherrypy.engine.state == cherrypy.engine.states.STARTED: return """ check if we need to update the config """ message = TextMessage(message.__str__()) """ first check memcache """ if not self.memcache is None: salt = hashlib.md5(message.__str__()).hexdigest() m = self.memcache.get(salt) if m: bytes = m if self.multiplex: if self.multiplex_current == self.multiplex_amount: """ send the message """ message = dict(message=self.multiplex_container) bytes = map(ord, bsonlib.dumps(message)).__str__() for i in client: i.send(bytes) try: inspect.currentframe().f_back.f_locals['self'].provider(bytes) except: pass self.multiplex_current = 0 self.multiplex_container = [] else: """ store the message """ #self.multiplex_container.append(m) self.multiplex_current += 1 else: for i in client: i.send(bytes) try: inspect.currentframe().f_back.f_locals['self'].provider(bytes) except: pass _time.sleep(self.caller.freq) return if len(re.findall(r'interop', message.__str__())) > 0: m = json.loads(message.__str__()) is_json = True else: literal = ast.literal_eval(message.__str__()) """ ensure the message fits in """ m = bsonlib.loads(bytearray(literal).__str__()) is_json = False if self._objs == '': self._objs = [globals()[i]() for i in m['packet'] if i in OBJS] p = m['packet'] """ if no limit is set set the limit to the default """ if not 'limit' in dir(p): m['limit'] = 20 else: m['limit'] = p['limit'] c = 0 i_m = m for i in self._objs: try: i.storage = self.storage i.logger = self.logger if c == 0: m = i.run(m) else: m = i.run(self._append(m, p)) except: i.log() c += 1 c += 1 if self.storage.union_table: mp = m m = i_m _OL_DB = self.storage.get()['db'] _OL_TABLE = self.storage.get()['table'] self.storage.set('table', self.storage.union_table) c = 0 for i in self._objs: try: i.storage = self.storage i.logger = self.logger if c == 0: m = i.run(m) else: m = i.run(self._append(m, p)) except: i.log() c += 1 c += 1 m = list(set(m + mp)) else: pass """ if we dont have a confidence value by now append one to all before filtering """ try: if not 'confidence' in m[0].keys(): m = [dict(i.items() + [('confidence', 1)]) for i in m] """ by now m should be a nodecollection. we must filter this to only the needed amount of node:ws """ if type(m) is list: m = self._filter(m) except: pass """ add any join table if set also look for id if available if it isnt use "table_name"_id for match """ if self.storage.join_table and type(m) is list: _OL_DB = self.storage.get()['db'] _OL_TABLE = self.storage.get()['table'] _OL_JOIN_TABLE = self.storage.join_table if _OL_JOIN_TABLE in getattr(_OL_DB, 'tables'): if self.storage.join_on: _OL_JOIN_ON = self.storage.join_on else: _OL_JOIN_ON = _OL_TABLE for i in range(0, len(m)): queries = [] queries.append(getattr(getattr(_OL_DB, _OL_JOIN_TABLE), _OL_JOIN_ON) == m[i]['id']) query = reduce(lambda a,b:(a&b),queries) row = _OL_DB(query).select() try: row = row.as_list()[0] for j in row.items(): """ prepend ambigious columns with join table name """ if j[0] in m[i].keys(): continue m[i][j[0]] = j[1] except: pass else: self.logger.append(dict(message="Could not find join table", object=self.__str__())) """ omit any fields that need to be erased """ if self.storage.omitlist: for i in range(0, len(m)): for j in self.storage.omitlist: if j == 'confidence': continue del m[i][j] """ if this is a downstream request simply return it """ if self.config['downstream']: return m """ is this an upstream request? then bind a socket to the request, and listen for the responses when all responses are fulfilled, return """ if self.config['upstream']: faddrs = [] cluster = self.config['cluster'] addr = self.config['dispatcher_address'] timeout = int(self.config['dispatcher_timeout']); port = int(self.config['dispatcher_port']) print "Upstreaming to other servers" sock = socket.socket() sock.bind((addr, port)) sock.listen(5) try: start = time_.time() while True: now = time_.time() if now - start > timeout: break if len(faddrs) == len(cluster): break client, addr = sock.accept() if not addr in self.config.cluster: continue ## dont do it twice if addr in faddrs: continue faddrs.append(addr) client.send(m['packet']) message_ = client.recv(20024) literal = ast.literal_eval(message_.__str__()) """ ensure the message fits in """ m_ = bsonlib.loads(bytearray(literal).__str__()) """ now merge both m_ and m """ except: self.logger.append(dict(message="Unable to bind socket to upstream", object=self.__str__())) """ if results are met we need to run the provider. First get the client this message was received from """ client = cherrypy.engine.publish('get-client', self.caller.unique).pop() try: for k in range(0, len(m)): if isinstance(m[k], dict): for k1, v1 in m[k].iteritems(): if isinstance(m[k][k1], str): m[k][k1] = unicode(m[k][k1]) m = dict(data=m, status=u'ok') except: m = dict(data=[], status=u'empty') if is_json: bytes = json.dumps(m) else: bytes = map(ord, bsonlib.dumps(m)).__str__() if self.multiplex: if self.multiplex_current == self.multiplex_amount: """ send the message """ message = dict(message=self.multiplex_container) bytes = map(ord, bsonlib.dumps(message)).__str__() for i in client: i.send(bytes) try: inspect.currentframe().f_back.f_locals['self'].provider(bytes) except: pass self.multiplex_current = 0 self.multiplex_container = [] else: """ store the message """ self.multiplex_container.append(m) self.multiplex_current += 1 else: for i in client: i.send(bytes) try: inspect.currentframe().f_back.f_locals['self'].provider(bytes) except: pass """ stream output into another file """ """ we recognize the following file types: """ """ .php, .py, .pl, .rb, and .txt """ """ first four will invoke their interpreter. .txt will """ """ merely dump contents """ """ fix for subprocess """ """ NOTE: interop data in this case should always be JSON to """ """ let ease of integration. For this cause it is best to use 'JSON' as """ """ interop when using stream_into """ if self.config['stream_into']: type = re.findall("\.(\w+)$", self.config['stream_into']) if len(type) > 0: inter = type[0] try: if inter == 'php': os.system("php {0} '{1}'".format(os.path.abspath(self.config['stream_into']), json.dumps(m))) elif inter == 'py': os.system("python {0} '{1}'".format(self.config['stream_into'], json.dumps(m))) elif inter == 'pl': os.system("perl {0} '{1}'".format(self.config['stream_into'], json.dumps(m))) elif inter == 'rb': os.system("ruby {0} '{1}'".format(self.config['stream_into'], json.dumps(m))) except: self.logger.append(dict(message="Unable to call ScriptingEngine for {1}".format(inter), object=self.__str__())) if not self.memcache is None: salt = hashlib.md5(message.__str__()).hexdigest() self.memcache.set(salt, bytes) _time.sleep(self.caller.freq)
def closed(self, code, reason="A client left the room without a proper explanation."): cherrypy.engine.publish('websocket-broadcast', TextMessage(reason))
def on_event(self, name, **data): event = data event['event'] = name message = json.dumps(event, cls=models.ModelJSONEncoder) cherrypy.engine.publish('websocket-broadcast', TextMessage(message))
def feed(self, message): if isinstance(message, Message): message = message.single(mask=True) else: message = TextMessage(message).single(mask=True) self.frames.add(message)
def receiver(self): """ Parser that keeps trying to interpret bytes it is fed with as incoming frames part of a message. Control message are single frames only while data messages, like text and binary, may be fragmented accross frames. The way it works is by instanciating a :class:`wspy.framing.Frame` object, then running its parser generator which yields how much bytes it requires to performs its task. The stream parser yields this value to its caller and feeds the frame parser. When the frame parser raises :exc:`StopIteration`, the stream parser tries to make sense of the parsed frame. It dispatches the frame's bytes to the most appropriate message type based on the frame's opcode. Overall this makes the stream parser totally agonstic to the data provider. """ utf8validator = Utf8Validator() running = True frame = None while running: frame = Frame() while 1: try: bytes = (yield next(frame.parser)) frame.parser.send(bytes) except StopIteration: frame._cleanup() bytes = frame.body # Let's avoid unmasking when there is no payload if bytes: if frame.masking_key and self.expect_masking: bytes = frame.unmask(bytes) elif not frame.masking_key and self.expect_masking: msg = CloseControlMessage(code=1002, reason='Missing masking when expected') self.errors.append(msg) break elif frame.masking_key and not self.expect_masking: msg = CloseControlMessage(code=1002, reason='Masked when not expected') self.errors.append(msg) break else: bytes = bytearray(bytes) if frame.opcode == OPCODE_TEXT: if self.message and not self.message.completed: # We got a text frame before we completed the previous one msg = CloseControlMessage(code=1002, reason='Received a new message before completing previous') self.errors.append(msg) break m = TextMessage(bytes) m.completed = (frame.fin == 1) self.message = m if bytes: is_valid, end_on_code_point, _, _ = utf8validator.validate(bytes) if not is_valid or (m.completed and not end_on_code_point): self.errors.append(CloseControlMessage(code=1007, reason='Invalid UTF-8 bytes')) break elif frame.opcode == OPCODE_BINARY: m = BinaryMessage(bytes) m.completed = (frame.fin == 1) self.message = m elif frame.opcode == OPCODE_CONTINUATION: m = self.message if m is None: self.errors.append(CloseControlMessage(code=1002, reason='Message not started yet')) break m.extend(bytes) m.completed = (frame.fin == 1) if m.opcode == OPCODE_TEXT: if bytes: is_valid, end_on_code_point, _, _ = utf8validator.validate(bytes) if not is_valid or (m.completed and not end_on_code_point): self.errors.append(CloseControlMessage(code=1007, reason='Invalid UTF-8 bytes')) break elif frame.opcode == OPCODE_CLOSE: code = 1000 reason = "" if frame.payload_length == 0: self.closing = CloseControlMessage(code=1000) elif frame.payload_length == 1: self.closing = CloseControlMessage(code=1002, reason='Payload has invalid length') else: try: code = int(unpack("!H", enc(bytes[0:2]))[0]) except TypeError: code = 1002 reason = 'Invalid Closing Frame Code Type' except struct.error as sr: code = 1002 reason = 'Failed at decoding closing code' else: # Those codes are reserved or plainly forbidden if code not in VALID_CLOSING_CODES and not (2999 < code < 5000): reason = 'Invalid Closing Frame Code: %d' % code code = 1002 elif frame.payload_length > 1: reason = bytes[2:] if frame.masking_key else bytearray(frame.body[2:]) is_valid, end_on_code_point, _, _ = utf8validator.validate(reason) if not is_valid or not end_on_code_point: self.errors.append(CloseControlMessage(code=1007, reason='Invalid UTF-8 bytes')) break self.closing = CloseControlMessage(code=code, reason=reason) elif frame.opcode == OPCODE_PING: self.pings.append(PingControlMessage(bytes)) elif frame.opcode == OPCODE_PONG: self.pongs.append(PongControlMessage(bytes)) else: self.errors.append(CloseControlMessage(code=1003)) break except ProtocolException: self.errors.append(CloseControlMessage(code=1002)) break except FrameTooLargeException: self.errors.append(CloseControlMessage(code=1002, reason="Frame was too large")) break except StreamClosed: running = False break frame.body = None frame = None if self.message is not None and self.message.completed: utf8validator.reset() if frame: frame._cleanup() frame = None utf8validator.reset() utf8validator = None self._cleanup()
def receiver(self): global logAudio """ Parser that keeps trying to interpret bytes it is fed with as incoming frames part of a message. Control message are single frames only while data messages, like text and binary, may be fragmented accross frames. The way it works is by instanciating a :class:`wspy.framing.Frame` object, then running its parser generator which yields how much bytes it requires to performs its task. The stream parser yields this value to its caller and feeds the frame parser. When the frame parser raises :exc:`StopIteration`, the stream parser tries to make sense of the parsed frame. It dispatches the frame's bytes to the most appropriate message type based on the frame's opcode. Overall this makes the stream parser totally agonstic to the data provider. """ logAudio=settings.getVal("logAudio") print("debug: streaming.py in receiver function | logAudio=%s" % logAudio) utf8validator = Utf8Validator() running = True frame = None while running: frame = Frame() while 1: try: some_bytes = (yield next(frame.parser)) frame.parser.send(some_bytes) except GeneratorExit: running = False break except StopIteration: frame._cleanup() some_bytes = frame.body # Let's avoid unmasking when there is no payload if some_bytes: if frame.masking_key and self.expect_masking: some_bytes = frame.unmask(some_bytes) elif not frame.masking_key and self.expect_masking: msg = CloseControlMessage(code=1002, reason='Missing masking when expected') self.errors.append(msg) break elif frame.masking_key and not self.expect_masking: msg = CloseControlMessage(code=1002, reason='Masked when not expected') self.errors.append(msg) break else: # If we reach this stage, it's because # the frame wasn't masked and we didn't expect # it anyway. Therefore, on py2k, the bytes # are actually a str object and can't be used # in the utf8 validator as we need integers # when we get each byte one by one. # Our only solution here is to convert our # string to a bytearray. some_bytes = bytearray(some_bytes) if frame.opcode == OPCODE_TEXT: if self.message and not self.message.completed: # We got a text frame before we completed the previous one msg = CloseControlMessage(code=1002, reason='Received a new message before completing previous') self.errors.append(msg) break m = TextMessage(some_bytes) m.completed = (frame.fin == 1) self.message = m if some_bytes: is_valid, end_on_code_point, _, _ = utf8validator.validate(some_bytes) if not is_valid or (m.completed and not end_on_code_point): self.errors.append(CloseControlMessage(code=1007, reason='Invalid UTF-8 bytes')) break elif frame.opcode == OPCODE_BINARY: if self.message and not self.message.completed: # We got a text frame before we completed the previous one msg = CloseControlMessage(code=1002, reason='Received a new message before completing previous') self.errors.append(msg) break if logAudio != "0": print("debug:: received a binary frame with %d bytes, log it via localhost listner (port:%s)" % (len(some_bytes),logAudio)) #bstr1="" #for i in range(20): # str1="%d " % some_bytes[i] # bstr1 = bstr1 + " " + str1 #print("binary msg 1st 20 bytes: %s" % bstr1) # Create a TCP/IP socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Connect the socket to the port where the server is listening server_address = ('localhost', int(logAudio)) #print >>sys.stderr, 'connecting to %s port %s' % server_address sock.connect(server_address) try: # Send data traceUtf8="" for i in range(10): traceUtf8 = traceUtf8 + ' ' + str(some_bytes[i]) print("debug:send a mp3 frame (len=%d) to a log server [ %s ]" % (len(some_bytes),traceUtf8)) #print >>sys.stderr, '"%s"' % message sock.sendall(some_bytes) # Look for the response amount_received = 0 amount_expected = 7 while amount_received < amount_expected: data = sock.recv(10) amount_received += len(data) #print >>sys.stderr, 'received "%s"' % data finally: #print >>sys.stderr, 'closing socket' sock.close() # --- end of logAudio action m = BinaryMessage(some_bytes) m.completed = (frame.fin == 1) self.message = m elif frame.opcode == OPCODE_CONTINUATION: m = self.message if m is None: self.errors.append(CloseControlMessage(code=1002, reason='Message not started yet')) break m.extend(some_bytes) m.completed = (frame.fin == 1) if m.opcode == OPCODE_TEXT: if some_bytes: is_valid, end_on_code_point, _, _ = utf8validator.validate(some_bytes) if not is_valid or (m.completed and not end_on_code_point): self.errors.append(CloseControlMessage(code=1007, reason='Invalid UTF-8 bytes')) break elif frame.opcode == OPCODE_CLOSE: code = 1000 reason = "" if frame.payload_length == 0: self.closing = CloseControlMessage(code=1000) elif frame.payload_length == 1: self.closing = CloseControlMessage(code=1002, reason='Payload has invalid length') else: try: # at this stage, some_bytes have been unmasked # so actually are held in a bytearray code = int(unpack("!H", bytes(some_bytes[0:2]))[0]) except struct.error: code = 1002 reason = 'Failed at decoding closing code' else: # Those codes are reserved or plainly forbidden if code not in VALID_CLOSING_CODES and not (2999 < code < 5000): reason = 'Invalid Closing Frame Code: %d' % code code = 1002 elif frame.payload_length > 1: reason = some_bytes[2:] if frame.masking_key else frame.body[2:] if not py3k: reason = bytearray(reason) is_valid, end_on_code_point, _, _ = utf8validator.validate(reason) if not is_valid or not end_on_code_point: self.errors.append(CloseControlMessage(code=1007, reason='Invalid UTF-8 bytes')) break reason = bytes(reason) self.closing = CloseControlMessage(code=code, reason=reason) elif frame.opcode == OPCODE_PING: self.pings.append(PingControlMessage(some_bytes)) elif frame.opcode == OPCODE_PONG: self.pongs.append(PongControlMessage(some_bytes)) else: self.errors.append(CloseControlMessage(code=1003)) break except ProtocolException: self.errors.append(CloseControlMessage(code=1002)) break except FrameTooLargeException: self.errors.append(CloseControlMessage(code=1002, reason="Frame was too large")) break frame._cleanup() frame.body = None frame = None if self.message is not None and self.message.completed: utf8validator.reset() utf8validator.reset() utf8validator = None self._cleanup()
def receiver(self): """ Parser that keeps trying to interpret bytes it is fed with as incoming frames part of a message. Control message are single frames only while data messages, like text and binary, may be fragmented accross frames. The way it works is by instanciating a :class:`wspy.framing.Frame` object, then running its parser generator which yields how much bytes it requires to performs its task. The stream parser yields this value to its caller and feeds the frame parser. When the frame parser raises :exc:`StopIteration`, the stream parser tries to make sense of the parsed frame. It dispatches the frame's bytes to the most appropriate message type based on the frame's opcode. Overall this makes the stream parser totally agonstic to the data provider. """ utf8validator = Utf8Validator() running = True frame = None while running: frame = Frame() while 1: try: bytes = (yield frame.parser.next()) frame.parser.send(bytes) except StopIteration: frame._cleanup() bytes = frame.body or '' # Let's avoid unmasking when there is no payload if bytes: if frame.masking_key and self.expect_masking: bytes = frame.unmask(bytes) elif not frame.masking_key and self.expect_masking: msg = CloseControlMessage( code=1002, reason='Missing masking when expected') self.errors.append(msg) break elif frame.masking_key and not self.expect_masking: msg = CloseControlMessage( code=1002, reason='Masked when not expected') self.errors.append(msg) break else: bytes = bytearray(bytes) if frame.opcode == OPCODE_TEXT: if self.message and not self.message.completed: # We got a text frame before we completed the previous one msg = CloseControlMessage( code=1002, reason= 'Received a new message before completing previous' ) self.errors.append(msg) break m = TextMessage(bytes) m.completed = (frame.fin == 1) self.message = m if bytes: is_valid, end_on_code_point, _, _ = utf8validator.validate( bytes) if not is_valid or (m.completed and not end_on_code_point): self.errors.append( CloseControlMessage( code=1007, reason='Invalid UTF-8 bytes')) break elif frame.opcode == OPCODE_BINARY: m = BinaryMessage(bytes) m.completed = (frame.fin == 1) self.message = m elif frame.opcode == OPCODE_CONTINUATION: m = self.message if m is None: self.errors.append( CloseControlMessage( code=1002, reason='Message not started yet')) break m.extend(bytes) m.completed = (frame.fin == 1) if m.opcode == OPCODE_TEXT: if bytes: is_valid, end_on_code_point, _, _ = utf8validator.validate( bytes) if not is_valid or (m.completed and not end_on_code_point): self.errors.append( CloseControlMessage( code=1007, reason='Invalid UTF-8 bytes')) break elif frame.opcode == OPCODE_CLOSE: code = 1000 reason = "" if frame.payload_length == 0: self.closing = CloseControlMessage(code=1000) elif frame.payload_length == 1: self.closing = CloseControlMessage( code=1002, reason='Payload has invalid length') else: try: code = int( struct.unpack("!H", str(bytes[0:2]))[0]) except TypeError: code = 1002 reason = 'Invalid Closing Frame Code Type' except struct.error, sr: code = 1002 reason = 'Failed at decoding closing code' else: # Those codes are reserved or plainly forbidden if code not in VALID_CLOSING_CODES and not ( 2999 < code < 5000): reason = 'Invalid Closing Frame Code: %d' % code code = 1002 elif frame.payload_length > 1: reason = bytes[ 2:] if frame.masking_key else bytearray( frame.body[2:]) is_valid, end_on_code_point, _, _ = utf8validator.validate( reason) if not is_valid or not end_on_code_point: self.errors.append( CloseControlMessage( code=1007, reason='Invalid UTF-8 bytes')) break self.closing = CloseControlMessage( code=code, reason=reason.decode('utf-8')) elif frame.opcode == OPCODE_PING: self.pings.append(PingControlMessage(bytes)) elif frame.opcode == OPCODE_PONG: self.pongs.append(PongControlMessage(bytes))
def receiver(self): """ Parser that keeps trying to interpret bytes it is fed with as incoming frames part of a message. Control message are single frames only while data messages, like text and binary, may be fragmented accross frames. The way it works is by instanciating a framing.Frame object, then running its parser generator which yields how much bytes it requires to performs its task. The stream parser yields this value to its caller and feeds the frame parser. When the frame parser raises StopIteration, the stream parser tries to make sense of the parsed frame. It dispatches the frame's bytes to the most appropriate message type based on the frame's opcode. Overall this makes the stream parser totally agonstic to the data provider. """ utf8validator = Utf8Validator() running = True while running: frame = Frame() while True: try: bytes = (yield frame.parser.next()) if bytes is None: raise InvalidBytesError() frame.parser.send(bytes) except StopIteration: bytes = frame.body or '' if frame.masking_key and bytes: bytes = frame.unmask(bytes) if frame.opcode == OPCODE_TEXT: if self.message and not self.message.completed: # We got a text frame before we completed the previous one self.errors.append(CloseControlMessage(code=1002)) break is_valid, _, _, _ = utf8validator.validate(bytes) if is_valid or (not is_valid and frame.fin == 0): m = TextMessage(bytes) m.completed = (frame.fin == 1) self.message = m elif not is_valid and frame.fin == 1: self.errors.append(CloseControlMessage(code=1007)) elif frame.opcode == OPCODE_BINARY: m = BinaryMessage(bytes) m.completed = (frame.fin == 1) self.message = m elif frame.opcode == OPCODE_CONTINUATION: m = self.message if m is None: self.errors.append(CloseControlMessage(code=1002)) break m.completed = (frame.fin == 1) if m.opcode == OPCODE_TEXT: is_valid, _, _, _ = utf8validator.validate(bytes) if is_valid: m.extend(bytes) else: self.errors.append(CloseControlMessage(code=1007)) #except UnicodeDecodeError: # self.errors.append(CloseControlMessage(code=1007)) # break else: m.extend(bytes) elif frame.opcode == OPCODE_CLOSE: code = 1000 reason = "" if len(bytes) == 0: self.errors.append(CloseControlMessage(code=1000)) elif 1 < len(bytes) < 126: code = struct.unpack("!H", str(bytes[0:2]))[0] try: code = int(code) except TypeError: code = 1002 reason = 'Invalid Closing Frame Code Type' else: # Those codes are reserved or plainly forbidden if code < 1000 or code in [1004, 1005, 1006, 1012, 1013, 1014, 1015, 1016, 1100, 2000, 2999, 5000, 65536]: code = 1002 reason = 'Invalid Closing Frame Code' else: if len(bytes) > 2: try: reason = frame.body[2:].decode("utf-8") except UnicodeDecodeError: code = 1007 reason = '' self.closing = CloseControlMessage(code=code, reason=reason) else: self.errors.append(CloseControlMessage(code=1002)) elif frame.opcode == OPCODE_PING: self.pings.append(PingControlMessage(bytes)) elif frame.opcode == OPCODE_PONG: self.pongs.append(PongControlMessage(bytes)) else: self.errors.append(CloseControlMessage(code=1003)) # When the frame's payload is empty, we must yield # once more so that the caller is properly aligned if not bytes: yield 0 break except ProtocolException: self.errors.append(CloseControlMessage(code=1002)) except FrameTooLargeException: self.errors.append(CloseControlMessage(code=1002)) except StreamClosed: running = False break frame.parser.close() utf8validator.reset() utf8validator = None
def sendWebsocketMessage(self, txt): cherrypy.engine.publish('websocket-broadcast', TextMessage("DET" + txt))
def receiver(self): """ Parser that keeps trying to interpret bytes it is fed with as incoming frames part of a message. Control message are single frames only while data messages, like text and binary, may be fragmented accross frames. The way it works is by instanciating a :class:`wspy.framing.Frame` object, then running its parser generator which yields how much bytes it requires to performs its task. The stream parser yields this value to its caller and feeds the frame parser. When the frame parser raises :exc:`StopIteration`, the stream parser tries to make sense of the parsed frame. It dispatches the frame's bytes to the most appropriate message type based on the frame's opcode. Overall this makes the stream parser totally agonstic to the data provider. """ utf8validator = Utf8Validator() running = True frame = None while running: frame = Frame() while 1: try: some_bytes = (yield next(frame.parser)) frame.parser.send(some_bytes) except GeneratorExit: running = False break except StopIteration: frame._cleanup() some_bytes = frame.body # Let's avoid unmasking when there is no payload if some_bytes: if frame.masking_key and self.expect_masking: some_bytes = frame.unmask(some_bytes) elif not frame.masking_key and self.expect_masking: msg = CloseControlMessage( code=1002, reason='Missing masking when expected') self.errors.append(msg) break elif frame.masking_key and not self.expect_masking: msg = CloseControlMessage( code=1002, reason='Masked when not expected') self.errors.append(msg) break else: # If we reach this stage, it's because # the frame wasn't masked and we didn't expect # it anyway. Therefore, on py2k, the bytes # are actually a str object and can't be used # in the utf8 validator as we need integers # when we get each byte one by one. # Our only solution here is to convert our # string to a bytearray. some_bytes = bytearray(some_bytes) if frame.opcode == OPCODE_TEXT: if self.message and not self.message.completed: # We got a text frame before we completed the previous one msg = CloseControlMessage( code=1002, reason= 'Received a new message before completing previous' ) self.errors.append(msg) break m = TextMessage(some_bytes) m.completed = (frame.fin == 1) self.message = m if some_bytes: is_valid, end_on_code_point, _, _ = utf8validator.validate( some_bytes) if not is_valid or (m.completed and not end_on_code_point): self.errors.append( CloseControlMessage( code=1007, reason='Invalid UTF-8 bytes')) break elif frame.opcode == OPCODE_BINARY: if self.message and not self.message.completed: # We got a text frame before we completed the previous one msg = CloseControlMessage( code=1002, reason= 'Received a new message before completing previous' ) self.errors.append(msg) break m = BinaryMessage(some_bytes) m.completed = (frame.fin == 1) self.message = m elif frame.opcode == OPCODE_CONTINUATION: m = self.message if m is None: self.errors.append( CloseControlMessage( code=1002, reason='Message not started yet')) break m.extend(some_bytes) m.completed = (frame.fin == 1) if m.opcode == OPCODE_TEXT: if some_bytes: is_valid, end_on_code_point, _, _ = utf8validator.validate( some_bytes) if not is_valid or (m.completed and not end_on_code_point): self.errors.append( CloseControlMessage( code=1007, reason='Invalid UTF-8 bytes')) break elif frame.opcode == OPCODE_CLOSE: code = 1005 reason = "" if frame.payload_length == 0: self.closing = CloseControlMessage(code=1005) elif frame.payload_length == 1: self.closing = CloseControlMessage( code=1005, reason='Payload has invalid length') else: try: # at this stage, some_bytes have been unmasked # so actually are held in a bytearray code = int( unpack("!H", bytes(some_bytes[0:2]))[0]) except struct.error: reason = 'Failed at decoding closing code' else: # Those codes are reserved or plainly forbidden if code not in VALID_CLOSING_CODES and not ( 2999 < code < 5000): reason = 'Invalid Closing Frame Code: %d' % code code = 1005 elif frame.payload_length > 1: reason = some_bytes[ 2:] if frame.masking_key else frame.body[ 2:] if not py3k: reason = bytearray(reason) is_valid, end_on_code_point, _, _ = utf8validator.validate( reason) if not is_valid or not end_on_code_point: self.errors.append( CloseControlMessage( code=1007, reason='Invalid UTF-8 bytes')) break reason = bytes(reason) self.closing = CloseControlMessage(code=code, reason=reason) elif frame.opcode == OPCODE_PING: self.pings.append(PingControlMessage(some_bytes)) elif frame.opcode == OPCODE_PONG: self.pongs.append(PongControlMessage(some_bytes)) else: self.errors.append(CloseControlMessage(code=1003)) break except ProtocolException: self.errors.append(CloseControlMessage(code=1002)) break except FrameTooLargeException: self.errors.append( CloseControlMessage(code=1002, reason="Frame was too large")) break frame._cleanup() frame.body = None frame = None if self.message is not None and self.message.completed: utf8validator.reset() utf8validator.reset() utf8validator = None self._cleanup()
def doRFID(): cherrypy.engine.publish("websocket-broadcast", TextMessage(rfidHandler.blockingRead()))
def closed(self, code, reason="Socket closed."): cherrypy.engine.publish('websocket-broadcast', TextMessage(reason))
def receiver(self): """ Parser that keeps trying to interpret bytes it is fed with as incoming frames part of a message. Control message are single frames only while data messages, like text and binary, may be fragmented accross frames. The way it works is by instanciating a framing.Frame object, then running its parser generator which yields how much bytes it requires to performs its task. The stream parser yields this value to its caller and feeds the frame parser. When the frame parser raises StopIteration, the stream parser tries to make sense of the parsed frame. It dispatches the frame's bytes to the most appropriate message type based on the frame's opcode. Overall this makes the stream parser totally agonstic to the data provider. """ running = True while running: frame = Frame() while True: try: bytes = (yield frame.parser.next()) if bytes is None: raise InvalidBytesError() frame.parser.send(bytes) except StopIteration: bytes = frame.body or '' if frame.masking_key and bytes: bytes = frame.unmask(bytes) if frame.opcode == OPCODE_TEXT: if self.message and not self.message.completed: # We got a text frame before we completed the previous one raise ProtocolException() try: m = TextMessage(bytes.decode("utf-8", "replace")) m.completed = (frame.fin == 1) self.message = m except UnicodeDecodeError: self.errors.append(CloseControlMessage(code=1007)) break elif frame.opcode == OPCODE_BINARY: m = BinaryMessage(bytes) m.completed = (frame.fin == 1) self.message = m elif frame.opcode == OPCODE_CONTINUATION: m = self.message if m is None: raise ProtocolException() m.completed = (frame.fin == 1) if m.opcode == OPCODE_TEXT: try: m.extend(bytes.decode("utf-8", "replace")) except UnicodeDecodeError: self.errors.append(CloseControlMessage(code=1007)) break else: m.extend(bytes) elif frame.opcode == OPCODE_CLOSE: self.closing = CloseControlMessage(reason=bytes.decode("utf-8", "replace")) elif frame.opcode == OPCODE_PING: self.pings.append(PingControlMessage(bytes)) elif frame.opcode == OPCODE_PONG: self.pongs.append(PongControlMessage(bytes)) else: self.errors.append(CloseControlMessage(code=1003)) # When the frame's payload is empty, we must yield # once more so that the caller is properly aligned if not bytes: yield 0 break except ProtocolException: self.errors.append(CloseControlMessage(code=1002)) except FrameTooLargeException: self.errors.append(CloseControlMessage(code=1004)) except StreamClosed: running = False break frame.parser.close()
def updateStatus(self, status): cherrypy.engine.publish('websocket-broadcast', TextMessage('loader-%s' % status)) cherrypy.engine.publish('loader-status', status)
def emit(self, record): msg = self.format(record) cherrypy.engine.publish('websocket-broadcast', TextMessage(msg + '\n'))
def receiver(self): """ Parser that keeps trying to interpret bytes it is fed with as incoming frames part of a message. Control message are single frames only while data messages, like text and binary, may be fragmented accross frames. The way it works is by instanciating a framing.Frame object, then running its parser generator which yields how much bytes it requires to performs its task. The stream parser yields this value to its caller and feeds the frame parser. When the frame parser raises StopIteration, the stream parser tries to make sense of the parsed frame. It dispatches the frame's bytes to the most appropriate message type based on the frame's opcode. Overall this makes the stream parser totally agonstic to the data provider. """ running = True while running: frame = Frame() while True: try: bytes = (yield frame.parser.next()) if bytes is None: raise InvalidBytesError() frame.parser.send(bytes) except StopIteration: bytes = frame.body or '' if frame.masking_key and bytes: bytes = frame.unmask(bytes) if frame.opcode == OPCODE_TEXT: if self.message and not self.message.completed: # We got a text frame before we completed the previous one self.errors.append(CloseControlMessage(code=1002)) break try: m = TextMessage(bytes.decode("utf-8")) m.completed = (frame.fin == 1) self.message = m except UnicodeDecodeError: self.errors.append(CloseControlMessage(code=1007)) break elif frame.opcode == OPCODE_BINARY: m = BinaryMessage(bytes) m.completed = (frame.fin == 1) self.message = m elif frame.opcode == OPCODE_CONTINUATION: m = self.message if m is None: self.errors.append(CloseControlMessage(code=1002)) break m.completed = (frame.fin == 1) if m.opcode == OPCODE_TEXT: try: m.extend(bytes.decode("utf-8")) except UnicodeDecodeError: self.errors.append(CloseControlMessage(code=1007)) break else: m.extend(bytes) elif frame.opcode == OPCODE_CLOSE: self.closing = CloseControlMessage(reason=bytes.decode("utf-8", "replace")) elif frame.opcode == OPCODE_PING: self.pings.append(PingControlMessage(bytes)) elif frame.opcode == OPCODE_PONG: self.pongs.append(PongControlMessage(bytes)) else: self.errors.append(CloseControlMessage(code=1003)) # When the frame's payload is empty, we must yield # once more so that the caller is properly aligned if not bytes: yield 0 break except ProtocolException: self.errors.append(CloseControlMessage(code=1002)) except FrameTooLargeException: self.errors.append(CloseControlMessage(code=1004)) except StreamClosed: running = False break frame.parser.close()
def closed( self, code, reason="A user left pysenteishon, seems the talk is too boring :(" ): cherrypy.engine.publish('/slides', TextMessage(reason))