Example #1
0
 async def _bind_tcp_sockets_with_consistent_port_number(self, make_socket):
     # Find a random port number that is free on all self.interfaces,
     # and get a bound TCP socket with that port number on each
     # interface. The argument `make_socket` is expected to be a coroutine
     # with the signature `make_socket(interface, port)` that does whatever
     # library-specific incantation is necessary to return a bound socket or
     # raise an IOError.
     tcp_sockets = {}  # maps interface to bound socket
     stashed_ex = None
     for port in ca.random_ports(100, try_first=self.ca_server_port):
         try:
             for interface in self.interfaces:
                 s = await make_socket(interface, port)
                 tcp_sockets[interface] = s
         except IOError as ex:
             stashed_ex = ex
             for s in tcp_sockets.values():
                 s.close()
             tcp_sockets.clear()
         else:
             break
     else:
         raise CaprotoRuntimeError(
             'No available ports and/or bind failed') from stashed_ex
     return port, tcp_sockets
Example #2
0
def catvs_ioc(request):
    from caproto.curio.server import Context

    pvgroup = CatvsIOC(prefix='')

    # NOTE: catvs expects server tcp_port==udp_port, so make a weak attempt
    # here to avoid clashing between servers
    port = list(ca.random_ports(1))[0]

    try:
        # The environment variale only needs to e set for the initializer of
        # Context.
        os.environ['EPICS_CA_SERVER_PORT'] = str(port)
        context = Context(pvgroup.pvdb, ['127.0.0.1'])
    finally:
        os.environ['EPICS_CA_SERVER_PORT'] = '5064'

    thread = threading.Thread(target=server_thread,
                              daemon=True,
                              args=(context, ))
    thread.start()

    def stop_server():
        context.log.setLevel('INFO')
        context.stop()

    request.addfinalizer(stop_server)

    while getattr(context, 'port', None) is None:
        logger.info('Waiting on catvs test server...')
        time.sleep(0.1)

    tcp_port = context.port
    udp_port = context.ca_server_port
    logger.info('catvs test server started up on port %d (udp port %d)',
                tcp_port, udp_port)
    time.sleep(0.5)
    return pvgroup, context, thread
Example #3
0
    async def run(self, *, log_pv_names=False):
        'Start the server'
        self.log.info('Server starting up...')
        try:
            async with trio.open_nursery() as self.nursery:
                for address in ca.get_beacon_address_list():
                    sock = ca.bcast_socket(socket)
                    await sock.connect(address)
                    interface, _ = sock.getsockname()
                    self.beacon_socks[address] = (interface, sock)

                # This reproduces the common with
                # self._bind_tcp_sockets_with_consistent_port_number because
                # trio makes socket binding async where asyncio and curio make
                # it synchronous.
                # Find a random port number that is free on all interfaces,
                # and get a bound TCP socket with that port number on each
                # interface.
                tcp_sockets = {}  # maps interface to bound socket
                stashed_ex = None
                for port in ca.random_ports(100):
                    try:
                        for interface in self.interfaces:
                            s = trio.socket.socket()
                            await s.bind((interface, port))
                            tcp_sockets[interface] = s
                    except IOError as ex:
                        stashed_ex = ex
                        for s in tcp_sockets.values():
                            s.close()
                    else:
                        self.port = port
                        break
                else:
                    raise RuntimeError('No available ports and/or bind failed'
                                       ) from stashed_ex
                # (End of reproduced code)

                for interface, listen_sock in tcp_sockets.items():
                    self.log.info("Listening on %s:%d", interface, self.port)
                    await self.nursery.start(self.server_accept_loop,
                                             listen_sock)
                await self.nursery.start(self.broadcaster_udp_server_loop)
                await self.nursery.start(self.broadcaster_queue_loop)
                await self.nursery.start(self.subscription_queue_loop)
                await self.nursery.start(self.broadcast_beacon_loop)

                async_lib = TrioAsyncLayer()
                for name, method in self.startup_methods.items():
                    self.log.debug('Calling startup method %r', name)

                    async def startup(task_status):
                        task_status.started()
                        await method(async_lib)

                    await self.nursery.start(startup)
                self.log.info('Server startup complete.')
                if log_pv_names:
                    self.log.info('PVs available:\n%s', '\n'.join(self.pvdb))
        except trio.Cancelled:
            self.log.info('Server task cancelled. Will shut down.')
        finally:
            self.log.info('Server exiting....')