def start_proxy(ctx: click.Context, opts: ProxyContext, connection_data: RemoteAccessConnectionData, stop_signal: threading.Event=None, ready_signal: threading.Event=None) -> NoReturn:
    'Start the local proxy\n\n    Args:\n        ctx (click.Context): Click context\n        opts (ProxyContext): Proxy options\n    '
    is_main_thread = (threading.current_thread() is threading.main_thread())
    if is_main_thread:
        register_signals()
    client_opts = {'host': opts.host, 'config_id': connection_data.remote_config_id, 'device_id': connection_data.managed_object_id, 'session': connection_data.client.session, 'token': opts.token, 'ignore_ssl_validate': opts.ignore_ssl_validate, 'ping_interval': opts.ping_interval, 'max_retries': 2}
    tcp_server = None
    background = None
    try:
        tcp_server = TCPProxyServer(opts.port, WebsocketClient(**client_opts), opts.tcp_size, opts.tcp_timeout)
        exit_code = ExitCodes.OK
        click.secho(BANNER1)
        logging.info('Starting tcp server')
        background = threading.Thread(target=tcp_server.serve_forever, daemon=True)
        background.start()
        if (not tcp_server.wait_for_running(opts.wait_port_timeout)):
            opts.exit_server_not_ready()
        if tcp_server.server.socket:
            opts.used_port = tcp_server.server.socket.getsockname()[1]
        if is_main_thread:
            opts.show_info(f'''
c8ylp is listening for device (ext_id) {opts.device} ({opts.host}) on localhost:{opts.used_port}''')
            ssh_username = (opts.ssh_user or '<device_username>')
            opts.show_message(f'''
For example, if you are running a ssh proxy, you connect to {opts.device} by executing the following in a new tab/console:

	ssh -p {opts.used_port} {ssh_username}@localhost''')
            opts.show_info('\nPress ctrl-c to shutdown the server')
        if ready_signal:
            ready_signal.set()
        while background.is_alive():
            if (stop_signal and stop_signal.is_set()):
                break
            time.sleep(1)
            logging.debug('Waiting in background: alive=%s', background.is_alive())
    except Exception as ex:
        if isinstance(ex, click.exceptions.Exit):
            exit_code = getattr(ex, 'exit_code')
            raise
        if str(ex):
            opts.show_error(f'The local proxy TCP Server experienced an unexpected error. port={opts.port}, error={ex}')
            exit_code = ExitCodes.UNKNOWN
    finally:
        if tcp_server:
            tcp_server.shutdown()
        if background:
            background.join()
        if is_main_thread:
            if (int(exit_code) == 0):
                opts.show_message(f'Exiting: {str(exit_code)} ({int(exit_code)})')
            else:
                opts.show_error(f'Exiting: {str(exit_code)} ({int(exit_code)})')
            ctx.exit(exit_code)
        else:
            opts.show_info('Exiting')
Start the local proxy

Args:
    ctx (click.Context): Click context
    opts (ProxyContext): Proxy options
def start_proxy(ctx: click.Context, opts: ProxyContext, connection_data: RemoteAccessConnectionData, stop_signal: threading.Event=None, ready_signal: threading.Event=None) -> NoReturn:
    'Start the local proxy\n\n    Args:\n        ctx (click.Context): Click context\n        opts (ProxyContext): Proxy options\n    '
    is_main_thread = (threading.current_thread() is threading.main_thread())
    if is_main_thread:
        register_signals()
    client_opts = {'host': opts.host, 'config_id': connection_data.remote_config_id, 'device_id': connection_data.managed_object_id, 'session': connection_data.client.session, 'token': opts.token, 'ignore_ssl_validate': opts.ignore_ssl_validate, 'ping_interval': opts.ping_interval, 'max_retries': 2}
    tcp_server = None
    background = None
    try:
        tcp_server = TCPProxyServer(opts.port, WebsocketClient(**client_opts), opts.tcp_size, opts.tcp_timeout)
        exit_code = ExitCodes.OK
        click.secho(BANNER1)
        logging.info('Starting tcp server')
        background = threading.Thread(target=tcp_server.serve_forever, daemon=True)
        background.start()
        if (not tcp_server.wait_for_running(opts.wait_port_timeout)):
            opts.exit_server_not_ready()
        if tcp_server.server.socket:
            opts.used_port = tcp_server.server.socket.getsockname()[1]
        if is_main_thread:
            opts.show_info(f'
c8ylp is listening for device (ext_id) {opts.device} ({opts.host}) on localhost:{opts.used_port}')
            ssh_username = (opts.ssh_user or '<device_username>')
            opts.show_message(f'
For example, if you are running a ssh proxy, you connect to {opts.device} by executing the following in a new tab/console:

	ssh -p {opts.used_port} {ssh_username}@localhost')
            opts.show_info('\nPress ctrl-c to shutdown the server')
        if ready_signal:
            ready_signal.set()
        while background.is_alive():
            if (stop_signal and stop_signal.is_set()):
                break
            time.sleep(1)
            logging.debug('Waiting in background: alive=%s', background.is_alive())
    except Exception as ex:
        if isinstance(ex, click.exceptions.Exit):
            exit_code = getattr(ex, 'exit_code')
            raise
        if str(ex):
            opts.show_error(f'The local proxy TCP Server experienced an unexpected error. port={opts.port}, error={ex}')
            exit_code = ExitCodes.UNKNOWN
    finally:
        if tcp_server:
            tcp_server.shutdown()
        if background:
            background.join()
        if is_main_thread:
            if (int(exit_code) == 0):
                opts.show_message(f'Exiting: {str(exit_code)} ({int(exit_code)})')
            else:
                opts.show_error(f'Exiting: {str(exit_code)} ({int(exit_code)})')
            ctx.exit(exit_code)
        else:
            opts.show_info('Exiting')