'Send SOCKS5 request with given command (CMD field) and
address (DST field). Returns resolved DST address that was used.'

def _SOCKS5_request(self, conn, cmd, dst):

    (proxy_type, addr, port, rdns, username, password) = self.proxy
    writer = conn.makefile('wb')
    reader = conn.makefile('rb', 0)
    try:
        if (username and password):
            writer.write('\x05\x02\x00\x02')
        else:
            writer.write('\x05\x01\x00')
        writer.flush()
        chosen_auth = self._readall(reader, 2)
        if (chosen_auth[0:1] != '\x05'):
            raise GeneralProxyError('SOCKS5    proxy    server    sent    invalid    data')
        if (chosen_auth[1:2] == '\x02'):
            writer.write((((('\x01' + chr(len(username)).encode()) + username) + chr(len(password)).encode()) + password))
            writer.flush()
            auth_status = self._readall(reader, 2)
            if (auth_status[0:1] != '\x01'):
                raise GeneralProxyError('SOCKS5    proxy    server    sent    invalid    data')
            if (auth_status[1:2] != '\x00'):
                raise SOCKS5AuthError('SOCKS5    authentication    failed')
        elif (chosen_auth[1:2] != '\x00'):
            if (chosen_auth[1:2] == '\xff'):
                raise SOCKS5AuthError('All    offered    SOCKS5    authentication    methods    were    rejected')
            else:
                raise GeneralProxyError('SOCKS5    proxy    server    sent    invalid    data')
        writer.write((('\x05' + cmd) + '\x00'))
        resolved = self._write_SOCKS5_address(dst, writer)
        writer.flush()
        resp = self._readall(reader, 3)
        if (resp[0:1] != '\x05'):
            raise GeneralProxyError('SOCKS5    proxy    server    sent    invalid    data')
        status = ord(resp[1:2])
        if (status != 0):
            error = SOCKS5_ERRORS.get(status, 'Unknown    error')
            raise SOCKS5Error('{0:#04x}:    {1}'.format(status, error))
        bnd = self._read_SOCKS5_address(reader)
        return (resolved, bnd)
    finally:
        reader.close()
        writer.close()
