def _parseFrames(self): """ Find frames in incoming data and pass them to the underlying protocol. """ try: frames, rest = _parseFrames("".join(self._buffer)) except _WSException: # Couldn't parse all the frames, something went wrong, let's bail. log.err() self.loseConnection() return self._buffer[:] = [rest] for frame in frames: opcode, data = frame if opcode == _CONTROLS.NORMAL: # Business as usual. Decode the frame, if we have a decoder. # Pass the frame to the underlying protocol. ProtocolWrapper.dataReceived(self, data) elif opcode == _CONTROLS.CLOSE: # The other side wants us to close. I wonder why? reason, text = data log.msg("Closing connection: %r (%d)" % (text, reason)) # Close the connection. self.loseConnection() return elif opcode == _CONTROLS.PING: # 5.5.2 PINGs must be responded to with PONGs. # 5.5.3 PONGs must contain the data that was sent with the # provoking PING. self.transport.write(_makeFrame(data, _opcode=_CONTROLS.PONG))
def parseFrames(self): """ Find frames in incoming data and pass them to the underlying protocol. """ try: frames, self.buf = parse_hybi07_frames(self.buf) except WSException: # Couldn't parse all the frames, something went wrong, let's bail. log.err() self.loseConnection() return for frame in frames: opcode, data = frame if opcode == NORMAL: # Business as usual. Decode the frame, if we have a decoder. if self.codec: data = decoders[self.codec](data) # Pass the frame to the underlying protocol. ProtocolWrapper.dataReceived(self, data) elif opcode == CLOSE: # The other side wants us to close. I wonder why? reason, text = data log.msg("Closing connection: %r (%d)" % (text, reason)) # Close the connection. self.loseConnection() return elif opcode == PING: # 5.5.2 PINGs must be responded to with PONGs. # 5.5.3 PONGs must contain the data that was sent with the # provoking PING. raise AssertionError("this doesn't work") # due to unknown symbol below
def dataReceived(self, data): # type: (bytes) -> None if not self.tlsStarted: ProtocolWrapper.dataReceived(self, data) return self.encrypted += data try: while 1: decryptedData = self._decrypt() self._check() encryptedData = self._encrypt() ProtocolWrapper.write(self, encryptedData) ProtocolWrapper.dataReceived(self, decryptedData) if decryptedData == b'' and encryptedData == b'': break except BIO.BIOError as e: # See http://www.openssl.org/docs/apps/verify.html#DIAGNOSTICS # for the error codes returned by SSL_get_verify_result. e.args = (m2.ssl_get_verify_result(self.ssl._ptr()), e.args[0]) raise e
def parseFrames(self): """ Find frames in incoming data and pass them to the underlying protocol. """ if self.flavor == HYBI00: parser = parse_hybi00_frames elif self.flavor in (HYBI07, HYBI10, RFC6455): parser = parse_hybi07_frames else: raise WSException("Unknown flavor %r" % self.flavor) try: frames, self.buf = parser(self.buf) except WSException as wse: # Couldn't parse all the frames, something went wrong, let's bail. self.close(wse.args[0]) return for frame in frames: opcode, data = frame if opcode == NORMAL: # Business as usual. Decode the frame, if we have a decoder. if self.codec: data = decoders[self.codec](data) # Pass the frame to the underlying protocol. ProtocolWrapper.dataReceived(self, data) elif opcode == CLOSE: # The other side wants us to close. I wonder why? reason, text = data log.msg("Closing connection: %r (%d)" % (text, reason)) # Close the connection. self.close()
def parseFrames(self): """ Find frames in incoming data and pass them to the underlying protocol. """ try: frames, self.buf = parse_hybi07_frames(self.buf) except WSException: # Couldn't parse all the frames, something went wrong, let's bail. log.err() self.loseConnection() return for frame in frames: opcode, data = frame if opcode == NORMAL: # Business as usual. Decode the frame, if we have a decoder. if self.codec: data = decoders[self.codec](data) # Pass the frame to the underlying protocol. ProtocolWrapper.dataReceived(self, data) elif opcode == CLOSE: # The other side wants us to close. I wonder why? reason, text = data log.msg("Closing connection: %r (%d)" % (text, reason)) # Close the connection. self.loseConnection() return elif opcode == PING: # 5.5.2 PINGs must be responded to with PONGs. # 5.5.3 PONGs must contain the data that was sent with the # provoking PING. raise AssertionError( "this doesn't work") # due to unknown symbol below
def dataReceived(self, data): if not self.tlsStarted: ProtocolWrapper.dataReceived(self, data) return self.encrypted += data try: while 1: decryptedData = self._decrypt() self._check() encryptedData = self._encrypt() ProtocolWrapper.write(self, encryptedData) ProtocolWrapper.dataReceived(self, decryptedData) if decryptedData == '' and encryptedData == '': break except M2Crypto.BIO.BIOError as e: # See http://www.openssl.org/docs/apps/verify.html#DIAGNOSTICS # for the error codes returned by SSL_get_verify_result. e.args = (m2.ssl_get_verify_result(self.ssl._ptr()), e.args[0]) raise e
def dataReceived(self, data): if not data: return try: dat = json.loads(data) except ValueError: self.transport.loseConnection() else: for d in dat: ProtocolWrapper.dataReceived(self, d)
def dataReceived(self, data): if not data: return try: dat = json.loads(data) except ValueError: self.transport.loseConnection() else: for d in dat: d = normalize(d, self.parent._options['encoding']) ProtocolWrapper.dataReceived(self, d)
def dataReceived(self, data): try: if not self.tlsStarted: ProtocolWrapper.dataReceived(self, data) else: self.fakeSocket.data += data while self.fakeSocket.data: AsyncStateMachine.inReadEvent(self) except TLSError, e: self.connectionLost(Failure(e)) ProtocolWrapper.loseConnection(self)
def _flushReceiveBIO(self): """ Try to receive any application-level bytes which are now available because of a previous write into the receive BIO. This will take care of delivering any application-level bytes which are received to the protocol, as well as handling of the various exceptions which can come from trying to get such bytes. """ # Keep trying this until an error indicates we should stop or we # close the connection. Looping is necessary to make sure we # process all of the data which was put into the receive BIO, as # there is no guarantee that a single recv call will do it all. while not self._lostTLSConnection: try: bytes = self._tlsConnection.recv(2**15) except WantReadError: # The newly received bytes might not have been enough to produce # any application data. break except ZeroReturnError: # TLS has shut down and no more TLS data will be received over # this connection. self._shutdownTLS() # Passing in None means the user protocol's connnectionLost # will get called with reason from underlying transport: self._tlsShutdownFinished(None) except Error as e: # Something went pretty wrong. For example, this might be a # handshake failure (because there were no shared ciphers, because # a certificate failed to verify, etc). TLS can no longer proceed. # Squash EOF in violation of protocol into ConnectionLost; we # create Failure before calling _flushSendBio so that no new # exception will get thrown in the interim. if e.args[0] == -1 and e.args[1] == 'Unexpected EOF': failure = Failure(CONNECTION_LOST) else: failure = Failure() self._flushSendBIO() self._tlsShutdownFinished(failure) else: # If we got application bytes, the handshake must be done by # now. Keep track of this to control error reporting later. self._handshakeDone = True if not self._aborted: ProtocolWrapper.dataReceived(self, bytes) # The received bytes might have generated a response which needs to be # sent now. For example, the handshake involves several round-trip # exchanges without ever producing application-bytes. self._flushSendBIO()
def _flushReceiveBIO(self): """ Try to receive any application-level bytes which are now available because of a previous write into the receive BIO. This will take care of delivering any application-level bytes which are received to the protocol, as well as handling of the various exceptions which can come from trying to get such bytes. """ # Keep trying this until an error indicates we should stop or we # close the connection. Looping is necessary to make sure we # process all of the data which was put into the receive BIO, as # there is no guarantee that a single recv call will do it all. while not self._lostTLSConnection: try: bytes = self._tlsConnection.recv(2 ** 15) except WantReadError: # The newly received bytes might not have been enough to produce # any application data. break except ZeroReturnError: # TLS has shut down and no more TLS data will be received over # this connection. self._shutdownTLS() # Passing in None means the user protocol's connnectionLost # will get called with reason from underlying transport: self._tlsShutdownFinished(None) except Error as e: # Something went pretty wrong. For example, this might be a # handshake failure (because there were no shared ciphers, because # a certificate failed to verify, etc). TLS can no longer proceed. # Squash EOF in violation of protocol into ConnectionLost; we # create Failure before calling _flushSendBio so that no new # exception will get thrown in the interim. if e.args[0] == -1 and e.args[1] == 'Unexpected EOF': failure = Failure(CONNECTION_LOST) else: failure = Failure() self._flushSendBIO() self._tlsShutdownFinished(failure) else: # If we got application bytes, the handshake must be done by # now. Keep track of this to control error reporting later. self._handshakeDone = True if not self._aborted: ProtocolWrapper.dataReceived(self, bytes) # The received bytes might have generated a response which needs to be # sent now. For example, the handshake involves several round-trip # exchanges without ever producing application-bytes. self._flushSendBIO()
def parseFrames(self): """ Find frames in incoming data and pass them to the underlying protocol. """ try: frames, self.buf = parse_hybi07_frames(self.buf) except WSException: # Couldn't parse all the frames, something went wrong, let's bail. log.err() self.loseConnection() return for frame in frames: opcode, data, fin = frame if opcode == NORMAL: # Business as usual. Decode the frame, if we have a decoder. if self.codec: self.complete_data += decoders[self.codec](data) # If no decoder, just tack it on as is to any previous frame data. else: self.complete_data += data # If FIN bit is set this is the last data frame in this context. if fin: # Pass the data compiled from the frames to the underlying protocol. ProtocolWrapper.dataReceived(self, self.complete_data) self.complete_data = "" elif opcode == CLOSE: # The other side wants us to close. I wonder why? reason, text = data log.msg("Closing connection: %r (%d)" % (text, reason)) # Close the connection. self.loseConnection() return elif opcode == PING: # 5.5.2 PINGs must be responded to with PONGs. # 5.5.3 PONGs must contain the data that was sent with the # provoking PING. pong_data = data # DJM/JW - Chrome v39+ Websockets code breaks when you follow 5.5.3! if self.dumb_pong: pong_data = "" self.transport.write( make_hybi07_frame(pong_data, opcode=PONG) ) # DJM - this used to say make_hybi07_packet() but there is no definition for that!
def parseFrames(self): """ Find frames in incoming data and pass them to the underlying protocol. """ start = self.buf.find("\x00") while start != -1: end = self.buf.find("\xff") if end == -1: # Incomplete frame, try again later. return else: frame, self.buf = self.buf[start + 1:end], self.buf[end + 1:] # Decode the frame, if we have a decoder. if self.codec: frame = decoders[self.codec](frame) # Pass the frame to the underlying protocol. ProtocolWrapper.dataReceived(self, frame) start = self.buf.find("\x00")
def handle_frames(self): """ Use the correct frame parser and send parsed data to the underlying protocol """ if self.version == HYBI00: frame_parser = HyBi00Frame(self.buf) elif self.version in (HYBI07, HYBI10, RFC6455): frame_parser = HyBi07Frame(self.buf) else: raise InvalidProtocolVersion( 'Unknown version {!r}'.format(self.version) ) try: frames, self.buf = frame_parser.parse() except WebSocketError as error: log.err(error) self.close(error) return for frame in frames: opcode, data = frame if opcode == DATA: # pass the frame to the underlying protocol ProtocolWrapper.dataReceived(self, data) elif opcode == CLOSE: # the other side want's to close reason, text = data log.msg('Closing connection: {!r} ({:d})'.format( text, reason )) # close the connection self.close() elif opcode == PING: # send pong self.transport.write( HyBi07Frame(data).generate(0xa) )
def parseFrames(self): try: frames, self.buf = _parseFrames(self.buf, self.old) except _WSException: log.err() self.loseConnection() return for frame in frames: opcode, data = frame if opcode == _CONTROLS.NORMAL: if self.codec: data = _decoders[self.codec](data) ProtocolWrapper.dataReceived(self, data) elif opcode == _CONTROLS.CLOSE: reason, text = data log.msg("Closing connection: %r (%d)" % (text, reason)) self.transport.loseConnection() return elif opcode == _CONTROLS.PING: self.transport.write(_makeFrame(data, self.old, _opcode=_CONTROLS.PONG))
class WebSocketProtocol(ProtocolWrapper): """ Protocol which wraps another protocol to provide a WebSockets transport layer. """ buf = "" codec = None location = "/" host = "example.com" origin = "http://example.com" state = REQUEST flavor = None do_binary_frames = False def __init__(self, *args, **kwargs): ProtocolWrapper.__init__(self, *args, **kwargs) self.pending_frames = [] def setBinaryMode(self, mode): """ If True, send str as binary and unicode as text. Defaults to false for backwards compatibility. """ self.do_binary_frames = bool(mode) def isSecure(self): """ Borrowed technique for determining whether this connection is over SSL/TLS. """ return ISSLTransport(self.transport, None) is not None def sendCommonPreamble(self): """ Send the preamble common to all WebSockets connections. This might go away in the future if WebSockets continue to diverge. """ self.transport.writeSequence([ "HTTP/1.1 101 FYI I am not a webserver\r\n", "Server: TwistedWebSocketWrapper/1.0\r\n", "Date: %s\r\n" % datetimeToString(), "Upgrade: WebSocket\r\n", "Connection: Upgrade\r\n", ]) def sendHyBi00Preamble(self): """ Send a HyBi-00 preamble. """ protocol = "wss" if self.isSecure() else "ws" self.sendCommonPreamble() self.transport.writeSequence([ "Sec-WebSocket-Origin: %s\r\n" % self.origin, "Sec-WebSocket-Location: %s://%s%s\r\n" % (protocol, self.host, self.location), "WebSocket-Protocol: %s\r\n" % self.codec, "Sec-WebSocket-Protocol: %s\r\n" % self.codec, "\r\n", ]) def sendHyBi07Preamble(self): """ Send a HyBi-07 preamble. """ self.sendCommonPreamble() challenge = self.headers["Sec-WebSocket-Key"] response = make_accept(challenge) self.transport.write("Sec-WebSocket-Accept: %s\r\n\r\n" % response) def parseFrames(self): """ Find frames in incoming data and pass them to the underlying protocol. """ if self.flavor == HYBI00: parser = parse_hybi00_frames elif self.flavor in (HYBI07, HYBI10, RFC6455): parser = parse_hybi07_frames else: raise WSException("Unknown flavor %r" % self.flavor) try: frames, self.buf = parser(self.buf) except WSException, wse: # Couldn't parse all the frames, something went wrong, let's bail. self.close(wse.args[0]) return for frame in frames: opcode, data = frame if opcode == NORMAL: # Business as usual. Decode the frame, if we have a decoder. if self.codec: data = decoders[self.codec](data) # Pass the frame to the underlying protocol. ProtocolWrapper.dataReceived(self, data) elif opcode == CLOSE: # The other side wants us to close. I wonder why? reason, text = data log.msg("Closing connection: %r (%d)" % (text, reason)) # Close the connection. self.close()
def outReadEvent(self, data): if data == "": ProtocolWrapper.loseConnection(self) else: ProtocolWrapper.dataReceived(self, data)