Пример #1
0
 def cf(self, **kwargs):
     # type: (**Any) -> Optional[AutopushSSLContextFactory]
     """Build our AutopushSSLContextFactory (if configured)"""
     if not self.key:
         return None
     return AutopushSSLContextFactory(self.key,
                                      self.cert,
                                      dh_file=self.dh_param,
                                      **kwargs)
Пример #2
0
def endpoint_main(sysargs=None):
    """Main entry point to setup an endpoint node, aka the autoendpoint
    script"""
    args, parser = _parse_endpoint(sysargs)
    settings = make_settings(
        args,
        endpoint_scheme="https" if args.ssl_key else "http",
        endpoint_hostname=args.hostname,
        endpoint_port=args.port,
        enable_cors=args.cors
    )

    setup_logging("Autoendpoint")

    # Endpoint HTTP router
    site = cyclone.web.Application([
        (r"/push/([^\/]+)", EndpointHandler, dict(ap_settings=settings)),
        # PUT /register/ => connect info
        # GET /register/uaid => chid + endpoint
        (r"/register(?:/(.+))?", RegistrationHandler,
         dict(ap_settings=settings)),
    ],
        default_host=settings.hostname, debug=args.debug,
        log_function=skip_request_logging
    )
    mount_health_handlers(site, settings)

    settings.metrics.start()

    if args.ssl_key:
        contextFactory = AutopushSSLContextFactory(args.ssl_key,
                                                   args.ssl_cert)
        if args.ssl_dh_param:
            contextFactory.getContext().load_tmp_dh(args.ssl_dh_param)
        reactor.listenSSL(args.port, site, contextFactory)
    else:
        reactor.listenTCP(args.port, site)

    reactor.suggestThreadPoolSize(50)
    reactor.run()
Пример #3
0
    def ssl_cf(self):
        # type: () -> Optional[AutopushSSLContextFactory]
        """Build our SSL Factory (if configured).

        Configured from the router_ssl_key/cert and ssl_dh_param
        values.

        """
        settings = self.ap_settings
        if not settings.router_ssl_key:
            return None
        return AutopushSSLContextFactory(settings.router_ssl_key,
                                         settings.router_ssl_cert,
                                         dh_file=settings.ssl_dh_param)
Пример #4
0
    def ssl_cf(self):
        # type: () -> Optional[AutopushSSLContextFactory]
        """Build our SSL Factory (if configured).

        Configured from the ssl_key/cert/dh_param and client_cert
        values.

        """
        settings = self.ap_settings
        if not settings.ssl_key:
            return None
        return AutopushSSLContextFactory(
            settings.ssl_key,
            settings.ssl_cert,
            dh_file=settings.ssl_dh_param,
            require_peer_certs=settings.enable_tls_auth)
Пример #5
0
def endpoint_main(sysargs=None, use_files=True):
    """Main entry point to setup an endpoint node, aka the autoendpoint
    script"""
    args, parser = _parse_endpoint(sysargs, use_files)
    senderid_list = None
    if args.senderid_list:
        try:
            senderid_list = json.loads(args.senderid_list)
        except (ValueError, TypeError):
            log.critical(format="Invalid JSON specified for senderid_list")
            return

    log_level = args.log_level or ("debug" if args.debug else "info")
    log_format = "text" if args.human_logs else "json"
    sentry_dsn = bool(os.environ.get("SENTRY_DSN"))
    PushLogger.setup_logging(
        "Autoendpoint",
        log_level=log_level,
        log_format=log_format,
        log_output=args.log_output,
        sentry_dsn=sentry_dsn,
        firehose_delivery_stream=args.firehose_stream_name)

    # Add some entropy to prevent potential conflicts.
    postfix = os.urandom(4).encode('hex').ljust(8, '0')
    settings = make_settings(
        args,
        endpoint_scheme=args.endpoint_scheme,
        endpoint_hostname=args.endpoint_hostname or args.hostname,
        endpoint_port=args.endpoint_port,
        enable_cors=not args.no_cors,
        s3_bucket=args.s3_bucket,
        senderid_expry=args.senderid_expry,
        senderid_list=senderid_list,
        bear_hash_key=args.auth_key,
        preflight_uaid="deadbeef000000000deadbeef" + postfix,
    )

    # Endpoint HTTP router
    site = cyclone.web.Application(
        [
            (r"/push/(?:(?P<api_ver>v\d+)\/)?(?P<token>[^\/]+)",
             EndpointHandler, dict(ap_settings=settings)),
            (r"/spush/(?:(?P<api_ver>v\d+)\/)?(?P<token>[^\/]+)",
             SimplePushHandler, dict(ap_settings=settings)),
            (r"/m/([^\/]+)", MessageHandler, dict(ap_settings=settings)),
            # PUT /register/ => connect info
            # GET /register/uaid => chid + endpoint
            (r"/v1/([^\/]+)/([^\/]+)/registration(?:/([^\/]+))"
             "?(?:/subscription)?(?:/([^\/]+))?", RegistrationHandler,
             dict(ap_settings=settings)),
            (r"/v1/err(?:/([^\/]+))?", LogCheckHandler,
             dict(ap_settings=settings)),
        ],
        default_host=settings.hostname,
        debug=args.debug,
        log_function=skip_request_logging)
    mount_health_handlers(site, settings)

    settings.metrics.start()

    # start the senderIDs refresh timer
    if settings.routers.get('gcm') and settings.routers['gcm'].senderIDs:
        # The following shows coverage on my local machine, but not
        # travis.
        settings.routers['gcm'].senderIDs.start()  # pragma: nocover

    if args.ssl_key:
        contextFactory = AutopushSSLContextFactory(args.ssl_key, args.ssl_cert)
        if args.ssl_dh_param:
            contextFactory.getContext().load_tmp_dh(args.ssl_dh_param)
        reactor.listenSSL(args.port, site, contextFactory)
    else:
        reactor.listenTCP(args.port, site)

    # Start the table rotation checker/updater
    l = task.LoopingCall(settings.update_rotating_tables)
    l.start(60)

    reactor.suggestThreadPoolSize(50)
    reactor.run()
Пример #6
0
def connection_main(sysargs=None, use_files=True):
    """Main entry point to setup a connection node, aka the autopush script"""
    args, parser = _parse_connection(sysargs, use_files)
    log_format = "text" if args.human_logs else "json"
    log_level = args.log_level or ("debug" if args.debug else "info")
    sentry_dsn = bool(os.environ.get("SENTRY_DSN"))
    PushLogger.setup_logging(
        "Autopush",
        log_level=log_level,
        log_format=log_format,
        log_output=args.log_output,
        sentry_dsn=sentry_dsn,
        firehose_delivery_stream=args.firehose_stream_name)
    # Add some entropy to prevent potential conflicts.
    postfix = os.urandom(4).encode('hex').ljust(8, '0')
    settings = make_settings(
        args,
        port=args.port,
        endpoint_scheme=args.endpoint_scheme,
        endpoint_hostname=args.endpoint_hostname,
        endpoint_port=args.endpoint_port,
        router_scheme="https" if args.router_ssl_key else "http",
        router_hostname=args.router_hostname,
        router_port=args.router_port,
        env=args.env,
        hello_timeout=args.hello_timeout,
        preflight_uaid="deadbeef000000000deadbeef" + postfix,
    )

    r = RouterHandler
    r.ap_settings = settings
    n = NotificationHandler
    n.ap_settings = settings

    # Internal HTTP notification router
    site = cyclone.web.Application([
        (r"/push/([^\/]+)", r),
        (r"/notif/([^\/]+)(/([^\/]+))?", n),
    ],
                                   default_host=settings.router_hostname,
                                   debug=args.debug,
                                   log_function=skip_request_logging)
    mount_health_handlers(site, settings)

    # Public websocket server
    proto = "wss" if args.ssl_key else "ws"
    factory = WebSocketServerFactory(
        "%s://%s:%s/" % (proto, args.hostname, args.port), )
    factory.protocol = PushServerProtocol
    factory.protocol.ap_settings = settings
    factory.setProtocolOptions(
        webStatus=False,
        openHandshakeTimeout=5,
        autoPingInterval=args.auto_ping_interval,
        autoPingTimeout=args.auto_ping_timeout,
        maxConnections=args.max_connections,
        closeHandshakeTimeout=args.close_handshake_timeout,
    )
    settings.factory = factory

    settings.metrics.start()

    # Wrap the WebSocket server in a default resource that exposes the
    # `/status` handler, and delegates to the WebSocket resource for all
    # other requests.
    resource = DefaultResource(WebSocketResource(factory))
    resource.putChild("status", StatusResource())
    siteFactory = Site(resource)

    # Start the WebSocket listener.
    if args.ssl_key:
        contextFactory = AutopushSSLContextFactory(args.ssl_key, args.ssl_cert)
        if args.ssl_dh_param:
            contextFactory.getContext().load_tmp_dh(args.ssl_dh_param)

        reactor.listenSSL(args.port, siteFactory, contextFactory)
    else:
        reactor.listenTCP(args.port, siteFactory)

    # Start the internal routing listener.
    if args.router_ssl_key:
        contextFactory = AutopushSSLContextFactory(args.router_ssl_key,
                                                   args.router_ssl_cert)
        if args.ssl_dh_param:
            contextFactory.getContext().load_tmp_dh(args.ssl_dh_param)
        reactor.listenSSL(args.router_port, site, contextFactory)
    else:
        reactor.listenTCP(args.router_port, site)

    reactor.suggestThreadPoolSize(50)

    l = task.LoopingCall(periodic_reporter, settings)
    l.start(1.0)

    # Start the table rotation checker/updater
    l = task.LoopingCall(settings.update_rotating_tables)
    l.start(60)
    reactor.run()
Пример #7
0
def connection_main(sysargs=None):
    """Main entry point to setup a connection node, aka the autopush script"""
    args, parser = _parse_connection(sysargs)
    setup_logging("Autopush", args.human_logs)
    settings = make_settings(
        args,
        port=args.port,
        endpoint_scheme=args.endpoint_scheme,
        endpoint_hostname=args.endpoint_hostname,
        endpoint_port=args.endpoint_port,
        router_scheme="https" if args.router_ssl_key else "http",
        router_hostname=args.router_hostname,
        router_port=args.router_port,
        env=args.env,
        hello_timeout=args.hello_timeout,
    )

    r = RouterHandler
    r.ap_settings = settings
    n = NotificationHandler
    n.ap_settings = settings

    # Internal HTTP notification router
    site = cyclone.web.Application([
        (r"/push/([^\/]+)", r),
        (r"/notif/([^\/]+)(/([^\/]+))?", n),
    ],
        default_host=settings.router_hostname, debug=args.debug,
        log_function=skip_request_logging
    )
    mount_health_handlers(site, settings)

    # Public websocket server
    proto = "wss" if args.ssl_key else "ws"
    factory = WebSocketServerFactory(
        "%s://%s:%s/" % (proto, args.hostname, args.port),
        debug=args.debug,
        debugCodePaths=args.debug,
    )
    factory.protocol = PushServerProtocol
    factory.protocol.ap_settings = settings
    factory.setProtocolOptions(
        webStatus=False,
        maxFramePayloadSize=args.max_message_size,
        maxMessagePayloadSize=args.max_message_size,
        openHandshakeTimeout=5,
        autoPingInterval=args.auto_ping_interval,
        autoPingTimeout=args.auto_ping_timeout,
        maxConnections=args.max_connections,
        closeHandshakeTimeout=args.close_handshake_timeout,
    )
    settings.factory = factory

    settings.metrics.start()

    # Wrap the WebSocket server in a default resource that exposes the
    # `/status` handler, and delegates to the WebSocket resource for all
    # other requests.
    resource = DefaultResource(WebSocketResource(factory))
    resource.putChild("status", StatusResource())
    siteFactory = Site(resource)

    # Start the WebSocket listener.
    if args.ssl_key:
        contextFactory = AutopushSSLContextFactory(args.ssl_key,
                                                   args.ssl_cert)
        if args.ssl_dh_param:
            contextFactory.getContext().load_tmp_dh(args.ssl_dh_param)

        reactor.listenSSL(args.port, siteFactory, contextFactory)
    else:
        reactor.listenTCP(args.port, siteFactory)

    # Start the internal routing listener.
    if args.router_ssl_key:
        contextFactory = AutopushSSLContextFactory(args.router_ssl_key,
                                                   args.router_ssl_cert)
        if args.ssl_dh_param:
            contextFactory.getContext().load_tmp_dh(args.ssl_dh_param)
        reactor.listenSSL(args.router_port, site, contextFactory)
    else:
        reactor.listenTCP(args.router_port, site)

    reactor.suggestThreadPoolSize(50)

    l = task.LoopingCall(periodic_reporter, settings)
    l.start(1.0)

    # Start the table rotation checker/updater
    l = task.LoopingCall(settings.update_rotating_tables)
    l.start(60)
    reactor.run()
Пример #8
0
        # GET /register/uaid => chid + endpoint
        (r"/v1/([^\/]+)/([^\/]+)/registration(?:/([^\/]+))"
            "?(?:/subscription)?(?:/([^\/]+))?",
         RegistrationHandler,
         dict(ap_settings=settings)),
    ],
        default_host=settings.hostname, debug=args.debug,
        log_function=skip_request_logging
    )
    mount_health_handlers(site, settings)

    settings.metrics.start()

    # start the senderIDs refresh timer
    if settings.routers.get('gcm') and settings.routers['gcm'].senderIDs:
        # The following shows coverage on my local machine, but not
        # travis.
        settings.routers['gcm'].senderIDs.start()  # pragma: nocover

    if args.ssl_key:
        contextFactory = AutopushSSLContextFactory(args.ssl_key,
                                                   args.ssl_cert)
        if args.ssl_dh_param:
            contextFactory.getContext().load_tmp_dh(args.ssl_dh_param)
        reactor.listenSSL(args.port, site, contextFactory)
    else:
        reactor.listenTCP(args.port, site)

    reactor.suggestThreadPoolSize(50)
    reactor.run()
Пример #9
0
def connection_main(sysargs=None):
    """Main entry point to setup a connection node, aka the autopush script"""
    args, parser = _parse_connection(sysargs)
    settings = make_settings(
        args,
        port=args.port,
        endpoint_scheme=args.endpoint_scheme,
        endpoint_hostname=args.endpoint_hostname,
        endpoint_port=args.endpoint_port,
        router_scheme="https" if args.router_ssl_key else "http",
        router_hostname=args.router_hostname,
        router_port=args.router_port,
    )
    setup_logging("Autopush")

    r = RouterHandler
    r.ap_settings = settings
    n = NotificationHandler
    n.ap_settings = settings

    # Internal HTTP notification router
    site = cyclone.web.Application([
        (r"/push/([^\/]+)", r),
        (r"/notif/([^\/]+)(/([^\/]+))?", n),
    ],
        default_host=settings.router_hostname, debug=args.debug,
        log_function=skip_request_logging
    )
    mount_health_handlers(site, settings)

    # Public websocket server
    proto = "wss" if args.ssl_key else "ws"
    factory = WebSocketServerFactory(
        "%s://%s:%s/" % (proto, args.hostname, args.port),
        debug=args.debug,
        debugCodePaths=args.debug,
    )
    factory.protocol = SimplePushServerProtocol
    factory.protocol.ap_settings = settings
    factory.setProtocolOptions(
        webStatus=False,
        maxFramePayloadSize=2048,
        maxMessagePayloadSize=2048,
        openHandshakeTimeout=5,
        autoPingInterval=args.auto_ping_interval,
        autoPingTimeout=args.auto_ping_timeout,
        maxConnections=args.max_connections
    )
    settings.factory = factory

    settings.metrics.start()

    # Start the WebSocket listener.
    if args.ssl_key:
        contextFactory = AutopushSSLContextFactory(args.ssl_key,
                                                   args.ssl_cert)
        if args.ssl_dh_param:
            contextFactory.getContext().load_tmp_dh(args.ssl_dh_param)
        listenWS(factory, contextFactory)
    else:
        reactor.listenTCP(args.port, factory)

    # Start the internal routing listener.
    if args.router_ssl_key:
        contextFactory = AutopushSSLContextFactory(args.router_ssl_key,
                                                   args.router_ssl_cert)
        if args.ssl_dh_param:
            contextFactory.getContext().load_tmp_dh(args.ssl_dh_param)
        reactor.listenSSL(args.router_port, site, contextFactory)
    else:
        reactor.listenTCP(args.router_port, site)

    reactor.suggestThreadPoolSize(50)

    l = task.LoopingCall(periodic_reporter, settings)
    l.start(1.0)
    reactor.run()
Пример #10
0
def connection_main(sysargs=None):
    """Main entry point to setup a connection node, aka the autopush script"""
    args, parser = _parse_connection(sysargs)
    setup_logging("Autopush", args.human_logs)
    settings = make_settings(
        args,
        port=args.port,
        endpoint_scheme=args.endpoint_scheme,
        endpoint_hostname=args.endpoint_hostname,
        endpoint_port=args.endpoint_port,
        router_scheme="https" if args.router_ssl_key else "http",
        router_hostname=args.router_hostname,
        router_port=args.router_port,
        env=args.env,
        hello_timeout=args.hello_timeout,
    )

    r = RouterHandler
    r.ap_settings = settings
    n = NotificationHandler
    n.ap_settings = settings

    # Internal HTTP notification router
    site = cyclone.web.Application([
        (r"/push/([^\/]+)", r),
        (r"/notif/([^\/]+)(/([^\/]+))?", n),
    ],
                                   default_host=settings.router_hostname,
                                   debug=args.debug,
                                   log_function=skip_request_logging)
    mount_health_handlers(site, settings)

    # Public websocket server
    proto = "wss" if args.ssl_key else "ws"
    factory = WebSocketServerFactory(
        "%s://%s:%s/" % (proto, args.hostname, args.port),
        debug=args.debug,
        debugCodePaths=args.debug,
    )
    factory.protocol = PushServerProtocol
    factory.protocol.ap_settings = settings
    factory.setProtocolOptions(
        webStatus=False,
        maxFramePayloadSize=args.max_message_size,
        maxMessagePayloadSize=args.max_message_size,
        openHandshakeTimeout=5,
        autoPingInterval=args.auto_ping_interval,
        autoPingTimeout=args.auto_ping_timeout,
        maxConnections=args.max_connections,
        closeHandshakeTimeout=args.close_handshake_timeout,
    )
    settings.factory = factory

    settings.metrics.start()

    # Wrap the WebSocket server in a default resource that exposes the
    # `/status` handler, and delegates to the WebSocket resource for all
    # other requests.
    resource = DefaultResource(WebSocketResource(factory))
    resource.putChild("status", StatusResource())
    siteFactory = Site(resource)

    # Start the WebSocket listener.
    if args.ssl_key:
        contextFactory = AutopushSSLContextFactory(args.ssl_key, args.ssl_cert)
        if args.ssl_dh_param:
            contextFactory.getContext().load_tmp_dh(args.ssl_dh_param)

        reactor.listenSSL(args.port, siteFactory, contextFactory)
    else:
        reactor.listenTCP(args.port, siteFactory)

    # Start the internal routing listener.
    if args.router_ssl_key:
        contextFactory = AutopushSSLContextFactory(args.router_ssl_key,
                                                   args.router_ssl_cert)
        if args.ssl_dh_param:
            contextFactory.getContext().load_tmp_dh(args.ssl_dh_param)
        reactor.listenSSL(args.router_port, site, contextFactory)
    else:
        reactor.listenTCP(args.router_port, site)

    reactor.suggestThreadPoolSize(50)

    l = task.LoopingCall(periodic_reporter, settings)
    l.start(1.0)
    reactor.run()
Пример #11
0
            (r"/push/([^\/]+)", EndpointHandler, dict(ap_settings=settings)),
            (r"/m/([^\/]+)", MessageHandler, dict(ap_settings=settings)),
            # PUT /register/ => connect info
            # GET /register/uaid => chid + endpoint
            (r"/register(?:/(.+))?", RegistrationHandler,
             dict(ap_settings=settings)),
        ],
        default_host=settings.hostname,
        debug=args.debug,
        log_function=skip_request_logging)
    mount_health_handlers(site, settings)

    settings.metrics.start()

    # start the senderIDs refresh timer
    if settings.routers.get('gcm') and settings.routers['gcm'].senderIDs:
        # The following shows coverage on my local machine, but not
        # travis.
        settings.routers['gcm'].senderIDs.start()  # pragma: nocover

    if args.ssl_key:
        contextFactory = AutopushSSLContextFactory(args.ssl_key, args.ssl_cert)
        if args.ssl_dh_param:
            contextFactory.getContext().load_tmp_dh(args.ssl_dh_param)
        reactor.listenSSL(args.port, site, contextFactory)
    else:
        reactor.listenTCP(args.port, site)

    reactor.suggestThreadPoolSize(50)
    reactor.run()
Пример #12
0
def endpoint_main(sysargs=None, use_files=True):
    """Main entry point to setup an endpoint node, aka the autoendpoint
    script"""
    args, parser = _parse_endpoint(sysargs, use_files)
    log_level = args.log_level or ("debug" if args.debug else "info")
    log_format = "text" if args.human_logs else "json"
    sentry_dsn = bool(os.environ.get("SENTRY_DSN"))
    PushLogger.setup_logging(
        "Autoendpoint",
        log_level=log_level,
        log_format=log_format,
        log_output=args.log_output,
        sentry_dsn=sentry_dsn,
        firehose_delivery_stream=args.firehose_stream_name)

    # Add some entropy to prevent potential conflicts.
    postfix = os.urandom(4).encode('hex').ljust(8, '0')
    settings = make_settings(
        args,
        endpoint_scheme=args.endpoint_scheme,
        endpoint_hostname=args.endpoint_hostname or args.hostname,
        endpoint_port=args.endpoint_port,
        enable_cors=not args.no_cors,
        bear_hash_key=args.auth_key,
        preflight_uaid="deadbeef000000000deadbeef" + postfix,
        debug=args.debug)
    if not settings:
        return 1

    # Endpoint HTTP router
    h_kwargs = dict(ap_settings=settings)
    site = cyclone.web.Application([
        (endpoint_paths['simple'], SimplePushHandler, h_kwargs),
        (endpoint_paths['webpush'], WebPushHandler, h_kwargs),
        (endpoint_paths['message'], MessageHandler, h_kwargs),
        (endpoint_paths['registration'], RegistrationHandler, h_kwargs),
        (endpoint_paths['logcheck'], LogCheckHandler, h_kwargs),
    ],
                                   default_host=settings.hostname,
                                   debug=args.debug,
                                   log_function=skip_request_logging)
    site.protocol = LimitedHTTPConnection
    site.protocol.maxData = settings.max_data
    mount_health_handlers(site, settings)
    site.noisy = args.debug

    settings.metrics.start()

    if args.ssl_key:
        ssl_cf = AutopushSSLContextFactory(
            args.ssl_key,
            args.ssl_cert,
            dh_file=args.ssl_dh_param,
            require_peer_certs=settings.enable_tls_auth)
        endpoint = SSL4ServerEndpoint(reactor, args.port, ssl_cf)
    else:
        ssl_cf = None
        endpoint = TCP4ServerEndpoint(reactor, args.port)
    endpoint.listen(site)

    if args.proxy_protocol_port:
        from autopush.haproxy import HAProxyServerEndpoint
        pendpoint = HAProxyServerEndpoint(reactor, args.proxy_protocol_port,
                                          ssl_cf)
        pendpoint.listen(site)

    reactor.suggestThreadPoolSize(50)
    # Start the table rotation checker/updater
    start_looping_call(60, settings.update_rotating_tables)
    if args.memusage_port:
        create_memusage_site(settings, args.memusage_port, args.debug)
    reactor.run()
Пример #13
0
def connection_main(sysargs=None, use_files=True):
    """Main entry point to setup a connection node, aka the autopush script"""
    args, parser = _parse_connection(sysargs, use_files)
    log_format = "text" if args.human_logs else "json"
    log_level = args.log_level or ("debug" if args.debug else "info")
    sentry_dsn = bool(os.environ.get("SENTRY_DSN"))
    PushLogger.setup_logging(
        "Autopush",
        log_level=log_level,
        log_format=log_format,
        log_output=args.log_output,
        sentry_dsn=sentry_dsn,
        firehose_delivery_stream=args.firehose_stream_name)
    # Add some entropy to prevent potential conflicts.
    postfix = os.urandom(4).encode('hex').ljust(8, '0')
    settings = make_settings(
        args,
        port=args.port,
        endpoint_scheme=args.endpoint_scheme,
        endpoint_hostname=args.endpoint_hostname,
        endpoint_port=args.endpoint_port,
        router_scheme="https" if args.router_ssl_key else "http",
        router_hostname=args.router_hostname,
        router_port=args.router_port,
        env=args.env,
        hello_timeout=args.hello_timeout,
        preflight_uaid="deadbeef000000000deadbeef" + postfix,
        debug=args.debug,
    )
    if not settings:
        return 1  # pragma: nocover

    # Internal HTTP notification router
    h_kwargs = dict(ap_settings=settings)
    site = cyclone.web.Application([
        (endpoint_paths['route'], RouterHandler, h_kwargs),
        (endpoint_paths['notification'], NotificationHandler, h_kwargs),
    ],
                                   default_host=settings.router_hostname,
                                   debug=args.debug,
                                   log_function=skip_request_logging)
    site.noisy = args.debug
    mount_health_handlers(site, settings)

    # Public websocket server
    proto = "wss" if args.ssl_key else "ws"
    factory = PushServerFactory(
        settings,
        "%s://%s:%s/" % (proto, args.hostname, args.port),
    )
    factory.setProtocolOptions(
        webStatus=False,
        openHandshakeTimeout=5,
        autoPingInterval=args.auto_ping_interval,
        autoPingTimeout=args.auto_ping_timeout,
        maxConnections=args.max_connections,
        closeHandshakeTimeout=args.close_handshake_timeout,
    )

    settings.metrics.start()

    # Wrap the WebSocket server in a default resource that exposes the
    # `/status` handler, and delegates to the WebSocket resource for all
    # other requests.
    resource = DefaultResource(WebSocketResource(factory))
    resource.putChild("status", StatusResource())
    site_factory = Site(resource)
    # Silence starting/stopping messages
    site_factory.noisy = args.debug
    site.noisy = args.debug

    # Start the WebSocket listener.
    if args.ssl_key:
        context_factory = AutopushSSLContextFactory(args.ssl_key,
                                                    args.ssl_cert,
                                                    dh_file=args.ssl_dh_param)
        reactor.listenSSL(args.port, site_factory, context_factory)
    else:
        reactor.listenTCP(args.port, site_factory)

    # Start the internal routing listener.
    if args.router_ssl_key:
        context_factory = AutopushSSLContextFactory(args.router_ssl_key,
                                                    args.router_ssl_cert,
                                                    dh_file=args.ssl_dh_param)
        reactor.listenSSL(args.router_port, site, context_factory)
    else:
        reactor.listenTCP(args.router_port, site)

    reactor.suggestThreadPoolSize(50)
    start_looping_call(1.0, periodic_reporter, settings, factory)
    # Start the table rotation checker/updater
    start_looping_call(60, settings.update_rotating_tables)
    if args.memusage_port:
        create_memusage_site(settings, args.memusage_port, args.debug)
    reactor.run()