'Authenticate a client and if it succeeds, wraps the socket in a connection object.
Note that this code is cut and paste from the rpyc internals and may have to be
changed if rpyc evolves'

def _setup_connection(self, lock, sock, queue):

    tup = sock.getpeername()
    (h, p) = (tup[0], tup[1])
    credentials = None
    if self.authenticator:
        try:
            (wrapper, credentials) = self.authenticator(sock)
        except AuthenticationError:
            self.logger.info('{}:{}    failed    to    authenticate,    rejecting    connection'.format(h, p))
            queue.put_nowait((None, None, None))
            return
    else:
        wrapper = sock
    config = dict(self.protocol_config, credentials=credentials, connid='{}:{}'.format(h, p))
    stream = self.stream_class(wrapper, self.transport_class, self.transport_kwargs)
    connection = None
    try:
        self.logger.debug('{}:{}    Authenticated.    Starting    connection'.format(h, p))
        connection = PupyConnection(lock, self.pupy_srv, self.service, PupyChannel(stream), ping=self.ping_interval, timeout=self.ping_timeout, config=config)
        self.logger.debug('{}:{}    Connection    complete'.format(h, p))
    finally:
        self.logger.debug('{}:{}    Report    connection:    {}'.format(h, p, connection))
        queue.put_nowait((connection, wrapper, credentials))
