def __init__(self, wsgi_apps=(), stream_handlers=(), custom_servers=(), prefork=None, daemonize=None, **kw): """\ Create a new Group of servers which can be started/stopped/forked as a group. *wsgi_apps* should be of the form [ (wsgi_app, address, ssl), ... ] *stream_handlers* should be of the form [ (handler_func, address), ... ] *custom_servers* should be of the form [ (server_class, address), ... ] where server_class refers to subclasses of gevent.server.StreamServer which define their own handle function address here refers to a tuple (ip, port), or more generally anything which is acceptable as the address parameter to `socket.bind() <http://docs.python.org/2/library/socket.html#socket.socket.bind>`_. `handler_func` should have the following signature: f(socket, address), following the `convention of gevent <http://www.gevent.org/servers.html>`_. """ ctx = context.get_context() self.wsgi_apps = list(wsgi_apps or []) self.stream_handlers = list(stream_handlers or []) self.custom_servers = list(custom_servers or []) self.prefork = prefork self.daemonize = daemonize # max number of concurrent clients per worker self.max_clients = kw.pop('max_clients', DEFAULT_MAX_CLIENTS) self.num_workers = kw.pop('num_workers', DEFAULT_NUM_WORKERS) self.post_fork = kw.pop('post_fork', None) # post-fork callback self.server_log = kw.pop('gevent_log', None) self.meta_address = kw.pop('meta_address', None) self.console_address = kw.pop('console_address', None) self._require_client_auth = kw.pop('require_client_auth', True) if kw: raise TypeError('unexpected keyword args: %r' % kw.keys()) self.client_pool = gevent.pool.Pool(ctx.max_concurrent_clients) self.servers = [] self.socks = {} # we do NOT want a gevent socket if we're going to use a # thread to manage our accepts; it's critical that the # accept() call *blocks* socket_type = gevent.socket.socket if not ufork else socket.socket for app, address, ssl in wsgi_apps: sock = _make_server_sock(address, socket_type=socket_type) if isinstance(ssl, SSLContext): ssl_context = ssl elif ssl: ssl_context = ctx.ssl_context else: ssl_context = None if ssl_context: if self._no_client_auth_req: server = MultiProtocolWSGIServer( sock, app, spawn=self.client_pool, context=ssl_context) else: server = SslContextWSGIServer( sock, app, spawn=self.client_pool, context=ssl_context) else: server = ThreadQueueWSGIServer(sock, app) server.log = self.server_log or RotatingGeventLog() self.servers.append(server) self.socks[server] = sock # prevent a "blocking" call to DNS on each request # (NOTE: although the OS won't block, gevent will dispatch # to a threadpool which is expensive) server.set_environ({'SERVER_NAME': socket.getfqdn(address[0]), 'wsgi.multiprocess': True}) for handler, address in self.stream_handlers: sock = _make_server_sock(address) server = gevent.server.StreamServer(sock, handler, spawn=self.client_pool) self.servers.append(server) for server_class, address in self.custom_servers: # our stated requirement is that users provide a subclass # of StreamServer, which would *not* know about our thread # queue. consequently we can't give it a blocking socket sock = _make_server_sock(address) server = server_class(sock, spawn=self.client_pool) self.servers.append(server) if self.console_address is not None: try: sock = _make_server_sock(self.console_address) except Exception as e: print "WARNING: unable to start backdoor server on port", ctx.backdoor_port, repr(e) else: server = gevent.server.StreamServer(sock, console_sock_handle, spawn=self.client_pool) self.servers.append(server) # set all servers max_accept to 1 since we are in a pre-forked/multiprocess environment for server in self.servers: server.max_accept = 1
def __init__(self, wsgi_apps=(), stream_handlers=(), custom_servers=(), prefork=None, daemonize=None, socket_ark_self=None, socket_ark_peer=None, socket_ark_secret='secret', **kw): ctx = context.get_context() self.wsgi_apps = list(wsgi_apps or []) self.stream_handlers = list(stream_handlers or []) self.custom_servers = list(custom_servers or []) self.prefork = prefork self.daemonize = daemonize # max number of concurrent clients per worker self.max_clients = kw.pop('max_clients', DEFAULT_MAX_CLIENTS) self.num_workers = kw.pop('num_workers', DEFAULT_NUM_WORKERS) self.post_fork = kw.pop('post_fork', None) # post-fork callback self.server_log = kw.pop('gevent_log', None) self.meta_address = kw.pop('meta_address', None) self.console_address = kw.pop('console_address', None) self._require_client_auth = kw.pop('require_client_auth', True) if kw: raise TypeError('unexpected keyword args: %r' % kw.keys()) self.client_pool = gevent.pool.Pool(ctx.max_concurrent_clients) self.servers = [] self.socks = {} # setup socket ark if keeping sockets alive self._init_socket_ark(socket_ark_self, socket_ark_peer, socket_ark_secret) # we do NOT want a gevent socket if we're going to use a # thread to manage our accepts; it's critical that the # accept() call *blocks* socket_type = gevent.socket.socket if not ufork else socket.socket for app, address, ssl in wsgi_apps: sock = self.acquire_server_sock(address, socket_type=socket_type) if isinstance(ssl, SSLContext): ssl_context = ssl elif ssl: ssl_context = ctx.ssl_context else: ssl_context = None if ssl_context: if self._no_client_auth_req: server = MultiProtocolWSGIServer(sock, app, spawn=self.client_pool, context=ssl_context) else: server = SslContextWSGIServer(sock, app, spawn=self.client_pool, context=ssl_context) else: server = ThreadQueueWSGIServer(sock, app) server.log = self.server_log or RotatingGeventLog() self.servers.append(server) self.socks[server] = sock # prevent a "blocking" call to DNS on each request # (NOTE: although the OS won't block, gevent will dispatch # to a threadpool which is expensive) server.set_environ({ 'SERVER_NAME': socket.getfqdn(address[0]), 'wsgi.multiprocess': True }) for handler, address in self.stream_handlers: sock = self.acquire_server_sock(address) server = gevent.server.StreamServer(sock, handler, spawn=self.client_pool) self.servers.append(server) for server_class, address in self.custom_servers: # our stated requirement is that users provide a subclass # of StreamServer, which would *not* know about our thread # queue. consequently we can't give it a blocking socket sock = self.acquire_server_sock(address) server = server_class(sock, spawn=self.client_pool) self.servers.append(server) if self.console_address is not None: try: sock = self.acquire_server_sock(self.console_address) except Exception as e: print "WARNING: unable to start backdoor server on port", ctx.backdoor_port, repr( e) else: server = gevent.server.StreamServer(sock, console_sock_handle, spawn=self.client_pool) self.servers.append(server) # set all servers max_accept to 1 since we are in a pre-forked/multiprocess environment for server in self.servers: server.max_accept = 1
def __init__(self, wsgi_apps=(), stream_handlers=(), custom_servers=(), prefork=None, daemonize=None, socket_ark_self=None, socket_ark_peer=None, socket_ark_secret='secret', **kw): ctx = context.get_context() self.wsgi_apps = list(wsgi_apps or []) self.stream_handlers = list(stream_handlers or []) self.custom_servers = list(custom_servers or []) self.prefork = prefork self.daemonize = daemonize # max number of concurrent clients per worker self.max_clients = kw.pop('max_clients', DEFAULT_MAX_CLIENTS) self.num_workers = kw.pop('num_workers', DEFAULT_NUM_WORKERS) self.post_fork = kw.pop('post_fork', None) # post-fork callback self.server_log = kw.pop('gevent_log', None) self.meta_address = kw.pop('meta_address', None) self.console_address = kw.pop('console_address', None) self._require_client_auth = kw.pop('require_client_auth', True) if kw: raise TypeError('unexpected keyword args: %r' % kw.keys()) self.client_pool = gevent.pool.Pool(ctx.max_concurrent_clients) self.servers = [] self.socks = {} # setup socket ark if keeping sockets alive self._init_socket_ark(socket_ark_self, socket_ark_peer, socket_ark_secret) # we do NOT want a gevent socket if we're going to use a # thread to manage our accepts; it's critical that the # accept() call *blocks* socket_type = gevent.socket.socket if not ufork else socket.socket for app, address, ssl in wsgi_apps: sock = self.acquire_server_sock(address, socket_type=socket_type) if isinstance(ssl, SSLContext): ssl_context = ssl elif ssl: ssl_context = ctx.ssl_context else: ssl_context = None if ssl_context: if self._no_client_auth_req: server = MultiProtocolWSGIServer( sock, app, spawn=self.client_pool, context=ssl_context) else: server = SslContextWSGIServer( sock, app, spawn=self.client_pool, context=ssl_context) else: server = ThreadQueueWSGIServer(sock, app) server.log = self.server_log or RotatingGeventLog() self.servers.append(server) self.socks[server] = sock # prevent a "blocking" call to DNS on each request # (NOTE: although the OS won't block, gevent will dispatch # to a threadpool which is expensive) server.set_environ({'SERVER_NAME': socket.getfqdn(address[0]), 'wsgi.multiprocess': True}) for handler, address in self.stream_handlers: sock = self.acquire_server_sock(address) server = gevent.server.StreamServer(sock, handler, spawn=self.client_pool) self.servers.append(server) for server_class, address in self.custom_servers: # our stated requirement is that users provide a subclass # of StreamServer, which would *not* know about our thread # queue. consequently we can't give it a blocking socket sock = self.acquire_server_sock(address) server = server_class(sock, spawn=self.client_pool) self.servers.append(server) if self.console_address is not None: try: sock = self.acquire_server_sock(self.console_address) except Exception as e: print "WARNING: unable to start backdoor server on port", ctx.backdoor_port, repr(e) else: server = gevent.server.StreamServer(sock, console_sock_handle, spawn=self.client_pool) self.servers.append(server) # set all servers max_accept to 1 since we are in a pre-forked/multiprocess environment for server in self.servers: server.max_accept = 1