def setUp(self): self.channel = DummyChannel() request = Request(self.channel, False) transport = WebSocketTransport(request) handler = TestHandler(transport) transport._attachHandler(handler) self.decoder = WebSocketFrameDecoder(request, handler) # taken straight from the IETF spec, masking added where appropriate self.hello = "\x81\x85\x37\xfa\x21\x3d\x7f\x9f\x4d\x51\x58" self.frag_hello = ("\x01\x83\x12\x21\x65\x23\x5a\x44\x09", "\x80\x82\x63\x34\xf1\x00\x0f\x5b") self.binary_orig = "\x3f" * 256 self.binary = ("\x82\xfe\x01\x00\x12\x6d\xa6\x23" + "\x2d\x52\x99\x1c" * 64) self.long_binary = ("\x82\xff\x00\x00\x00\x00\x00\x01\x00\x00" + "\x12\x6d\xa6\x23" + "\x2d\x52\x99\x1c" * 16384) self.long_binary_orig = "\x3f" * 65536 self.ping = "\x89\x85\x56\x23\x88\x23\x1e\x46\xe4\x4f\x39" self.pong = "\x8a\x85\xde\x41\x0f\x34\x96\x24\x63\x58\xb1" self.pong_unmasked = "\x8a\x05\x48\x65\x6c\x6c\x6f" # code 1000, message "Normal Closure" self.close = ("\x88\x90\x34\x23\x87\xde\x37\xcb\xc9\xb1\x46" "\x4e\xe6\xb2\x14\x60\xeb\xb1\x47\x56\xf5\xbb") ## close message can be empty or with normal close code (1000) self.empty_unmasked_close_list = ("\x88\x00", "\x88\x02\x03\xe8") self.empty_text = "\x81\x80\x00\x01\x02\x03" self.cont_empty_text = "\x00\x80\x00\x01\x02\x03"
def setUp(self): self.channel = DummyChannel() self.request = request = Request(self.channel, False) # Simulate request handling request.startedWriting = True transport = WebSocketTransport(request) self.handler = TestHandler(transport) transport._attachHandler(self.handler)
def setUp(self): self.channel = DummyChannel() request = Request(self.channel, False) transport = WebSocketTransport(request) handler = TestHandler(transport) transport._attachHandler(handler) self.decoder = WebSocketFrameDecoder(request, handler) self.decoder.MAX_LENGTH = 100
def _checkClientHandshake(self): """ Verify client handshake, closing the connection in case of problem. @return: C{None} if a problem was detected, or a tuple of I{Origin} header, I{Host} header, I{WebSocket-Protocol} header, and C{WebSocketHandler} instance. The I{WebSocket-Protocol} header will be C{None} if not specified by the client. """ def finish(): self.channel.transport.loseConnection() if self.queued: return finish() originHeaders = self.requestHeaders.getRawHeaders("Origin", []) if len(originHeaders) != 1: return finish() hostHeaders = self.requestHeaders.getRawHeaders("Host", []) if len(hostHeaders) != 1: return finish() handlerFactory = self.site.handlers.get(self.uri) if not handlerFactory: return finish() transport = WebSocketTransport(self) handler = handlerFactory(transport) transport._attachHandler(handler) protocolHeaders = self.requestHeaders.getRawHeaders( "WebSocket-Protocol", []) if len(protocolHeaders) not in (0, 1): return finish() if protocolHeaders: if protocolHeaders[0] not in self.site.supportedProtocols: return finish() protocolHeader = protocolHeaders[0] else: protocolHeader = None return originHeaders[0], hostHeaders[0], protocolHeader, handler
def _clientHandshake76(self): """ Complete hixie-76 handshake, which consists of a challenge and response. If the request is not identified with a proper WebSocket handshake, the connection will be closed. Otherwise, the response to the handshake is sent and a C{WebSocketHandler} is created to handle the request. """ def finish(): self.channel.transport.loseConnection() if self.queued: return finish() secKey1 = self.requestHeaders.getRawHeaders("Sec-WebSocket-Key1", []) secKey2 = self.requestHeaders.getRawHeaders("Sec-WebSocket-Key2", []) if len(secKey1) != 1 or len(secKey2) != 1: return finish() # copied originHeaders = self.requestHeaders.getRawHeaders("Origin", []) if len(originHeaders) != 1: return finish() hostHeaders = self.requestHeaders.getRawHeaders("Host", []) if len(hostHeaders) != 1: return finish() handlerFactory = self.site.handlers.get(self.uri) if not handlerFactory: return finish() # key1 and key2 exist and are a string of characters # filter both keys to get a string with all numbers in order key1 = secKey1[0] key2 = secKey2[0] numBuffer1 = ''.join([x for x in key1 if x in _ascii_numbers]) numBuffer2 = ''.join([x for x in key2 if x in _ascii_numbers]) # make sure numbers actually exist if not numBuffer1 or not numBuffer2: return finish() # these should be int-like num1 = int(numBuffer1) num2 = int(numBuffer2) # count the number of spaces in each character string numSpaces1 = 0 for x in key1: if x == ' ': numSpaces1 += 1 numSpaces2 = 0 for x in key2: if x == ' ': numSpaces2 += 1 # there should be at least one space in each if numSpaces1 == 0 or numSpaces2 == 0: return finish() # get two resulting numbers, as specified in hixie-76 num1 = num1 / numSpaces1 num2 = num2 / numSpaces2 transport = WebSocketTransport(self) handler = handlerFactory(transport) transport._attachHandler(handler) self.channel.setRawMode() def finishHandshake(nonce): """ Receive nonce value from request body, and calculate repsonse. """ protocolHeaders = self.requestHeaders.getRawHeaders( "WebSocket-Protocol", []) if len(protocolHeaders) not in (0, 1): return finish() if protocolHeaders: if protocolHeaders[0] not in self.site.supportedProtocols: return finish() protocolHeader = protocolHeaders[0] else: protocolHeader = None originHeader = originHeaders[0] hostHeader = hostHeaders[0] self.startedWriting = True handshake = [ "HTTP/1.1 101 Web Socket Protocol Handshake", "Upgrade: WebSocket", "Connection: Upgrade"] handshake.append("Sec-WebSocket-Origin: %s" % (originHeader)) if self.isSecure(): scheme = "wss" else: scheme = "ws" handshake.append( "Sec-WebSocket-Location: %s://%s%s" % ( scheme, hostHeader, self.uri)) if protocolHeader is not None: handshake.append("Sec-WebSocket-Protocol: %s" % protocolHeader) for header in handshake: self.write("%s\r\n" % header) self.write("\r\n") # concatenate num1 (32 bit in), num2 (32 bit int), nonce, and take md5 of result res = struct.pack('>II8s', num1, num2, nonce) server_response = md5(res).digest() self.write(server_response) # XXX we probably don't want to set _transferDecoder self.channel._transferDecoder = WebSocketFrameDecoder( self, handler) transport._connectionMade() # we need the nonce from the request body self.channel._transferDecoder = _IdentityTransferDecoder(0, lambda _ : None, finishHandshake)
def _clientHandshake76(self): """ Complete hixie-76 handshake, which consists of a challenge and response. If the request is not identified with a proper WebSocket handshake, the connection will be closed. Otherwise, the response to the handshake is sent and a C{WebSocketHandler} is created to handle the request. """ def finish(): self.channel.transport.loseConnection() if self.queued: return finish() secKey1 = self.requestHeaders.getRawHeaders("Sec-WebSocket-Key1", []) secKey2 = self.requestHeaders.getRawHeaders("Sec-WebSocket-Key2", []) if len(secKey1) != 1 or len(secKey2) != 1: return finish() # copied originHeaders = self.requestHeaders.getRawHeaders("Origin", []) if len(originHeaders) != 1: return finish() hostHeaders = self.requestHeaders.getRawHeaders("Host", []) if len(hostHeaders) != 1: return finish() handlerFactory = self.site.handlers.get(self.uri) if not handlerFactory: return finish() # key1 and key2 exist and are a string of characters # filter both keys to get a string with all numbers in order key1 = secKey1[0] key2 = secKey2[0] numBuffer1 = ''.join([x for x in key1 if x in _ascii_numbers]) numBuffer2 = ''.join([x for x in key2 if x in _ascii_numbers]) # make sure numbers actually exist if not numBuffer1 or not numBuffer2: return finish() # these should be int-like num1 = int(numBuffer1) num2 = int(numBuffer2) # count the number of spaces in each character string numSpaces1 = 0 for x in key1: if x == ' ': numSpaces1 += 1 numSpaces2 = 0 for x in key2: if x == ' ': numSpaces2 += 1 # there should be at least one space in each if numSpaces1 == 0 or numSpaces2 == 0: return finish() # get two resulting numbers, as specified in hixie-76 num1 = num1 / numSpaces1 num2 = num2 / numSpaces2 transport = WebSocketTransport(self) handler = handlerFactory(transport) transport._attachHandler(handler) self.channel.setRawMode() def finishHandshake(nonce): """ Receive nonce value from request body, and calculate repsonse. """ protocolHeaders = self.requestHeaders.getRawHeaders( "WebSocket-Protocol", []) if len(protocolHeaders) not in (0, 1): return finish() if protocolHeaders: if protocolHeaders[0] not in self.site.supportedProtocols: return finish() protocolHeader = protocolHeaders[0] else: protocolHeader = None originHeader = originHeaders[0] hostHeader = hostHeaders[0] self.startedWriting = True handshake = [ "HTTP/1.1 101 Web Socket Protocol Handshake", "Upgrade: WebSocket", "Connection: Upgrade" ] handshake.append("Sec-WebSocket-Origin: %s" % (originHeader)) if self.isSecure(): scheme = "wss" else: scheme = "ws" handshake.append("Sec-WebSocket-Location: %s://%s%s" % (scheme, hostHeader, self.uri)) if protocolHeader is not None: handshake.append("Sec-WebSocket-Protocol: %s" % protocolHeader) for header in handshake: self.write("%s\r\n" % header) self.write("\r\n") # concatenate num1 (32 bit in), num2 (32 bit int), nonce, and take md5 of result res = struct.pack('>II8s', num1, num2, nonce) server_response = md5(res).digest() self.write(server_response) # XXX we probably don't want to set _transferDecoder self.channel._transferDecoder = WebSocketFrameDecoder( self, handler) transport._connectionMade() # we need the nonce from the request body self.channel._transferDecoder = _IdentityTransferDecoder( 0, lambda _: None, finishHandshake)