'Does the SOCKS5 handshake and returns the address, port of the destination
Can raise a socket.error, ValueError, and struct.error if the other side isn\'t
speaking SOCKS5 or times out'

def _get_original_dest(self, sock):

    message = sock.recv(1024)
    (version, nmethods) = struct.unpack_from('BB', message)
    if (version != 5):
        raise ValueError('Bad    version    in    handshake')
    methods = struct.unpack_from(('%dB' % nmethods), message, 2)
    if (len(methods) != nmethods):
        raise ValueError('Methods    mismatch')
    sock.sendall('\x05\x00')
    request = sock.recv(1024)
    (ver, cmd, atype) = struct.unpack_from('BBxB', request)
    if (ver != 5):
        raise ValueError('Bad    version    in    handshake')
    if (cmd != SocksConnection.SOCKS_CONNECT):
        sock.sendall(self._build_error__response(SocksConnection.RESP_COMMAND_UNSUPPORTED))
        raise ValueError('Unsupported    command')
    if (atype == SocksConnection.ATYPE_IP):
        addr = request[4:8]
        addr = socket.inet_ntop(socket.AF_INET, addr)
        port = struct.unpack_from('!H', request, 8)[0]
    elif (atype == SocksConnection.ATYPE_DNS):
        length = struct.unpack_from('B', request, 4)[0]
        addr = request[5:(5 + length)]
        port = struct.unpack_from('!H', request, (5 + length))[0]
    elif (atype == SocksConnection.ATYPE_IP6):
        addr = request[4:20]
        addr = socket.inet_ntop(socket.AF_INET6, addr)
        port = struct.unpack_from('!H', request, 20)[0]
    else:
        sock.sendall(self._build_error_response(SocksConnection.RESP_GENERAL_ERROR))
        raise ValueError('Unknown    ATYP')
    return (addr, port)
