Spaces Data
Minimal test - lines (330, 489)
path: .spaces[10].spaces[1].metrics.loc.sloc
old: 157.0
new: 160.0
path: .spaces[10].spaces[1].metrics.loc.blank
old: 30.0
new: 31.0
path: .spaces[10].spaces[1].metrics.loc.cloc
old: 8.0
new: 10.0
path: .spaces[10].spaces[1].metrics.mi.mi_sei
old: 3.1961097727804564
new: 4.5071485357971
path: .spaces[10].spaces[1].metrics.mi.mi_visual_studio
old: 24.21133533528953
new: 24.032017346900403
path: .spaces[10].spaces[1].metrics.mi.mi_original
old: 41.401383423345095
new: 41.09474966319969
Code
def handshake(self):
"""Performs opening handshake on the specified socket.
Raises:
ClientHandshakeError: handshake failed.
"""
request_line = _build_method_line(self._options.resource)
self._logger.debug('Client\'s opening handshake Request-Line: %r',
request_line)
self._socket.sendall(request_line.encode('UTF-8'))
fields = []
fields.append(
_format_host_header(self._options.server_host,
self._options.server_port,
self._options.use_tls))
fields.append(_UPGRADE_HEADER)
fields.append(_CONNECTION_HEADER)
if self._options.origin is not None:
fields.append(
_origin_header(common.ORIGIN_HEADER, self._options.origin))
original_key = os.urandom(16)
self._key = base64.b64encode(original_key)
self._logger.debug('%s: %r (%s)', common.SEC_WEBSOCKET_KEY_HEADER,
self._key, util.hexify(original_key))
fields.append(
'%s: %s\r\n' %
(common.SEC_WEBSOCKET_KEY_HEADER, self._key.decode('UTF-8')))
fields.append(
'%s: %d\r\n' %
(common.SEC_WEBSOCKET_VERSION_HEADER, common.VERSION_HYBI_LATEST))
extensions_to_request = []
if self._options.use_permessage_deflate:
extension = common.ExtensionParameter(
common.PERMESSAGE_DEFLATE_EXTENSION)
# Accept the client_max_window_bits extension parameter by default.
extension.add_parameter(
PerMessageDeflateExtensionProcessor.
_CLIENT_MAX_WINDOW_BITS_PARAM, None)
extensions_to_request.append(extension)
if len(extensions_to_request) != 0:
fields.append('%s: %s\r\n' %
(common.SEC_WEBSOCKET_EXTENSIONS_HEADER,
common.format_extensions(extensions_to_request)))
for field in fields:
self._socket.sendall(field.encode('UTF-8'))
self._socket.sendall(b'\r\n')
self._logger.debug('Sent client\'s opening handshake headers: %r',
fields)
self._logger.debug('Start reading Status-Line')
status_line = b''
while True:
ch = _receive_bytes(self._socket, 1)
status_line += ch
if ch == b'\n':
break
m = re.match(b'HTTP/\\d+\.\\d+ (\\d\\d\\d) .*\r\n', status_line)
if m is None:
raise ClientHandshakeError('Wrong status line format: %r' %
status_line)
status_code = m.group(1)
if status_code != b'101':
self._logger.debug(
'Unexpected status code %s with following headers: %r',
status_code, self._read_fields())
raise ClientHandshakeError(
'Expected HTTP status code 101 but found %r' % status_code)
self._logger.debug('Received valid Status-Line')
self._logger.debug('Start reading headers until we see an empty line')
fields = self._read_fields()
ch = _receive_bytes(self._socket, 1)
if ch != b'\n': # 0x0A
raise ClientHandshakeError(
'Expected LF but found %r while reading value %r for header '
'name %r' % (ch, value, name))
self._logger.debug('Received an empty line')
self._logger.debug('Server\'s opening handshake headers: %r', fields)
_validate_mandatory_header(fields, common.UPGRADE_HEADER,
common.WEBSOCKET_UPGRADE_TYPE, False)
_validate_mandatory_header(fields, common.CONNECTION_HEADER,
common.UPGRADE_CONNECTION_TYPE, False)
accept = _get_mandatory_header(fields,
common.SEC_WEBSOCKET_ACCEPT_HEADER)
# Validate
try:
binary_accept = base64.b64decode(accept)
except TypeError:
raise HandshakeError('Illegal value for header %s: %r' %
(common.SEC_WEBSOCKET_ACCEPT_HEADER, accept))
if len(binary_accept) != 20:
raise ClientHandshakeError(
'Decoded value of %s is not 20-byte long' %
common.SEC_WEBSOCKET_ACCEPT_HEADER)
self._logger.debug('Response for challenge : %r (%s)', accept,
util.hexify(binary_accept))
binary_expected_accept = sha1(self._key +
common.WEBSOCKET_ACCEPT_UUID).digest()
expected_accept = base64.b64encode(binary_expected_accept)
self._logger.debug('Expected response for challenge: %r (%s)',
expected_accept,
util.hexify(binary_expected_accept))
if accept != expected_accept.decode('UTF-8'):
raise ClientHandshakeError(
'Invalid %s header: %r (expected: %s)' %
(common.SEC_WEBSOCKET_ACCEPT_HEADER, accept, expected_accept))
permessage_deflate_accepted = False
extensions_header = fields.get(
common.SEC_WEBSOCKET_EXTENSIONS_HEADER.lower())
accepted_extensions = []
if extensions_header is not None and len(extensions_header) != 0:
accepted_extensions = common.parse_extensions(extensions_header[0])
for extension in accepted_extensions:
extension_name = extension.name()
if (extension_name == common.PERMESSAGE_DEFLATE_EXTENSION
and self._options.use_permessage_deflate):
permessage_deflate_accepted = True
framer = _get_permessage_deflate_framer(extension)
framer.set_compress_outgoing_enabled(True)
self._options.use_permessage_deflate = framer
continue
raise ClientHandshakeError('Unexpected extension %r' %
extension_name)
if (self._options.use_permessage_deflate
and not permessage_deflate_accepted):
raise ClientHandshakeError(
'Requested %s, but the server rejected it' %
common.PERMESSAGE_DEFLATE_EXTENSION)
# TODO(tyoshino): Handle Sec-WebSocket-Protocol
# TODO(tyoshino): Handle Cookie, etc.
Minimal test - lines (319, 489)
path: .spaces[10].metrics.mi.mi_sei
old: 1.9681006297045336
new: 3.0513733337096767
path: .spaces[10].metrics.mi.mi_original
old: 39.493756533503785
new: 39.20702338449348
path: .spaces[10].metrics.mi.mi_visual_studio
old: 23.095764054680576
new: 22.928083850580983
path: .spaces[10].metrics.loc.cloc
old: 10.0
new: 12.0
path: .spaces[10].metrics.loc.sloc
old: 168.0
new: 171.0
path: .spaces[10].metrics.loc.blank
old: 33.0
new: 34.0
Code
class ClientHandshakeProcessor(ClientHandshakeBase):
"""WebSocket opening handshake processor
"""
def __init__(self, socket, options):
super(ClientHandshakeProcessor, self).__init__()
self._socket = socket
self._options = options
self._logger = util.get_class_logger(self)
def handshake(self):
"""Performs opening handshake on the specified socket.
Raises:
ClientHandshakeError: handshake failed.
"""
request_line = _build_method_line(self._options.resource)
self._logger.debug('Client\'s opening handshake Request-Line: %r',
request_line)
self._socket.sendall(request_line.encode('UTF-8'))
fields = []
fields.append(
_format_host_header(self._options.server_host,
self._options.server_port,
self._options.use_tls))
fields.append(_UPGRADE_HEADER)
fields.append(_CONNECTION_HEADER)
if self._options.origin is not None:
fields.append(
_origin_header(common.ORIGIN_HEADER, self._options.origin))
original_key = os.urandom(16)
self._key = base64.b64encode(original_key)
self._logger.debug('%s: %r (%s)', common.SEC_WEBSOCKET_KEY_HEADER,
self._key, util.hexify(original_key))
fields.append(
'%s: %s\r\n' %
(common.SEC_WEBSOCKET_KEY_HEADER, self._key.decode('UTF-8')))
fields.append(
'%s: %d\r\n' %
(common.SEC_WEBSOCKET_VERSION_HEADER, common.VERSION_HYBI_LATEST))
extensions_to_request = []
if self._options.use_permessage_deflate:
extension = common.ExtensionParameter(
common.PERMESSAGE_DEFLATE_EXTENSION)
# Accept the client_max_window_bits extension parameter by default.
extension.add_parameter(
PerMessageDeflateExtensionProcessor.
_CLIENT_MAX_WINDOW_BITS_PARAM, None)
extensions_to_request.append(extension)
if len(extensions_to_request) != 0:
fields.append('%s: %s\r\n' %
(common.SEC_WEBSOCKET_EXTENSIONS_HEADER,
common.format_extensions(extensions_to_request)))
for field in fields:
self._socket.sendall(field.encode('UTF-8'))
self._socket.sendall(b'\r\n')
self._logger.debug('Sent client\'s opening handshake headers: %r',
fields)
self._logger.debug('Start reading Status-Line')
status_line = b''
while True:
ch = _receive_bytes(self._socket, 1)
status_line += ch
if ch == b'\n':
break
m = re.match(b'HTTP/\\d+\.\\d+ (\\d\\d\\d) .*\r\n', status_line)
if m is None:
raise ClientHandshakeError('Wrong status line format: %r' %
status_line)
status_code = m.group(1)
if status_code != b'101':
self._logger.debug(
'Unexpected status code %s with following headers: %r',
status_code, self._read_fields())
raise ClientHandshakeError(
'Expected HTTP status code 101 but found %r' % status_code)
self._logger.debug('Received valid Status-Line')
self._logger.debug('Start reading headers until we see an empty line')
fields = self._read_fields()
ch = _receive_bytes(self._socket, 1)
if ch != b'\n': # 0x0A
raise ClientHandshakeError(
'Expected LF but found %r while reading value %r for header '
'name %r' % (ch, value, name))
self._logger.debug('Received an empty line')
self._logger.debug('Server\'s opening handshake headers: %r', fields)
_validate_mandatory_header(fields, common.UPGRADE_HEADER,
common.WEBSOCKET_UPGRADE_TYPE, False)
_validate_mandatory_header(fields, common.CONNECTION_HEADER,
common.UPGRADE_CONNECTION_TYPE, False)
accept = _get_mandatory_header(fields,
common.SEC_WEBSOCKET_ACCEPT_HEADER)
# Validate
try:
binary_accept = base64.b64decode(accept)
except TypeError:
raise HandshakeError('Illegal value for header %s: %r' %
(common.SEC_WEBSOCKET_ACCEPT_HEADER, accept))
if len(binary_accept) != 20:
raise ClientHandshakeError(
'Decoded value of %s is not 20-byte long' %
common.SEC_WEBSOCKET_ACCEPT_HEADER)
self._logger.debug('Response for challenge : %r (%s)', accept,
util.hexify(binary_accept))
binary_expected_accept = sha1(self._key +
common.WEBSOCKET_ACCEPT_UUID).digest()
expected_accept = base64.b64encode(binary_expected_accept)
self._logger.debug('Expected response for challenge: %r (%s)',
expected_accept,
util.hexify(binary_expected_accept))
if accept != expected_accept.decode('UTF-8'):
raise ClientHandshakeError(
'Invalid %s header: %r (expected: %s)' %
(common.SEC_WEBSOCKET_ACCEPT_HEADER, accept, expected_accept))
permessage_deflate_accepted = False
extensions_header = fields.get(
common.SEC_WEBSOCKET_EXTENSIONS_HEADER.lower())
accepted_extensions = []
if extensions_header is not None and len(extensions_header) != 0:
accepted_extensions = common.parse_extensions(extensions_header[0])
for extension in accepted_extensions:
extension_name = extension.name()
if (extension_name == common.PERMESSAGE_DEFLATE_EXTENSION
and self._options.use_permessage_deflate):
permessage_deflate_accepted = True
framer = _get_permessage_deflate_framer(extension)
framer.set_compress_outgoing_enabled(True)
self._options.use_permessage_deflate = framer
continue
raise ClientHandshakeError('Unexpected extension %r' %
extension_name)
if (self._options.use_permessage_deflate
and not permessage_deflate_accepted):
raise ClientHandshakeError(
'Requested %s, but the server rejected it' %
common.PERMESSAGE_DEFLATE_EXTENSION)
# TODO(tyoshino): Handle Sec-WebSocket-Protocol
# TODO(tyoshino): Handle Cookie, etc.