| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- #!/usr/bin/env python
- """
- classic rpyc server (threaded, forking or std) running a SlaveService
- usage:
- rpyc_classic.py # default settings
- rpyc_classic.py -m forking -p 12345 # custom settings
- rpyc_classic.py --vdb file.vdb # tlslite-authenticated server
-
- # ssl-authenticated server (keyfile and certfile are required)
- rpyc_classic.py --ssl-keyfile keyfile.pem --ssl-certfile certfile.pem --ssl-cafile cafile.pem
- """
- import sys
- import os
- import rpyc
- from optparse import OptionParser
- from rpyc.utils.server import ThreadedServer, ForkingServer
- from rpyc.utils.classic import DEFAULT_SERVER_PORT, DEFAULT_SERVER_SSL_PORT
- from rpyc.utils.registry import REGISTRY_PORT
- from rpyc.utils.registry import UDPRegistryClient, TCPRegistryClient
- from rpyc.utils.authenticators import TlsliteVdbAuthenticator, SSLAuthenticator
- from rpyc.lib import setup_logger
- from rpyc.core import SlaveService
- parser = OptionParser()
- parser.add_option("-m", "--mode", action="store", dest="mode", metavar="MODE",
- default="threaded", type="string", help="mode can be 'threaded', 'forking', "
- "or 'stdio' to operate over the standard IO pipes (for inetd, etc.). "
- "Default is 'threaded'")
- #
- # TCP options
- #
- parser.add_option("-p", "--port", action="store", dest="port", type="int",
- metavar="PORT", default=None,
- help="specify a different TCP listener port (default = %s, default for SSL = %s)" %
- (DEFAULT_SERVER_PORT, DEFAULT_SERVER_SSL_PORT))
- parser.add_option("--host", action="store", dest="host", type="str",
- metavar="HOST", default="0.0.0.0", help="specify a different "
- "host to bind to. Default is 0.0.0.0")
- #
- # logging
- #
- parser.add_option("--logfile", action="store", dest="logfile", type="str",
- metavar="FILE", default=None, help="specify the log file to use; the "
- "default is stderr")
- parser.add_option("-q", "--quiet", action="store_true", dest="quiet",
- default=False,
- help="quiet mode (no logging). in stdio mode, writes to /dev/null")
- #
- # TLSlite
- #
- parser.add_option("--vdb", action="store", dest="vdbfile", metavar="FILENAME",
- default=None, help="starts an TLS/SSL authenticated server (using tlslite);"
- "the credentials are loaded from the vdb file. if not given, the server"
- "is not secure (unauthenticated). use vdbconf.py to manage vdb files"
- )
- #
- # SSL
- #
- parser.add_option("--ssl-keyfile", action="store", dest="ssl_keyfile", metavar="FILENAME",
- default=None, help="the keyfile to use for SSL. required for SSL"
- )
- parser.add_option("--ssl-certfile", action="store", dest="ssl_certfile", metavar="FILENAME",
- default=None, help="the certificate file to use for SSL. required for SSL"
- )
- parser.add_option("--ssl-cafile", action="store", dest="ssl_cafile", metavar="FILENAME",
- default=None, help="the certificate authority chain file to use for SSL. "
- "optional, allows client-side authentication"
- )
- #
- # registry
- #
- parser.add_option("--register", action="store_true", dest="auto_register",
- default=False, help="asks the server to attempt registering with a registry server"
- "By default, the server will not attempt to register")
- parser.add_option("--registry-type", action="store", dest="regtype", type="str",
- default="udp", help="can be 'udp' or 'tcp', default is 'udp'")
- parser.add_option("--registry-port", action="store", dest="regport", type="int",
- default=REGISTRY_PORT, help="the UDP/TCP port. default is %s" % (REGISTRY_PORT,))
- parser.add_option("--registry-host", action="store", dest="reghost", type="str",
- default=None, help="the registry host machine. for UDP, the default is "
- "255.255.255.255; for TCP, a value is required")
- def get_options():
- options, args = parser.parse_args()
- if args:
- parser.error("does not take positional arguments: %r" % (args,))
- options.mode = options.mode.lower()
- if options.regtype.lower() == "udp":
- if options.reghost is None:
- options.reghost = "255.255.255.255"
- options.registrar = UDPRegistryClient(ip = options.reghost, port = options.regport)
- elif options.regtype.lower() == "tcp":
- if options.reghost is None:
- parser.error("must specific --registry-host")
- options.registrar = TCPRegistryClient(ip = options.reghost, port = options.regport)
- else:
- parser.error("invalid registry type %r" % (options.regtype,))
- if options.vdbfile:
- if not os.path.exists(options.vdbfile):
- parser.error("vdb file does not exist")
- options.authenticator = TlsliteVdbAuthenticator.from_file(options.vdbfile, mode = "r")
- if options.ssl_keyfile or options.ssl_certfile or options.ssl_cafile:
- if not options.ssl_keyfile:
- parser.error("SSL: keyfile required")
- if not options.ssl_certfile:
- parser.error("SSL: certfile required")
- options.authenticator = SSLAuthenticator(options.ssl_keyfile,
- options.ssl_certfile, options.ssl_cafile)
- if not options.port:
- options.port = DEFAULT_SERVER_SSL_PORT
- else:
- options.authenticator = None
- if not options.port:
- options.port = DEFAULT_SERVER_PORT
- options.handler = "serve_%s" % (options.mode,)
- if options.handler not in globals():
- parser.error("invalid mode %r" % (options.mode,))
-
- return options
- def serve_threaded(options):
- setup_logger(options)
- t = ThreadedServer(SlaveService, hostname = options.host,
- port = options.port, reuse_addr = True,
- authenticator = options.authenticator, registrar = options.registrar,
- auto_register = options.auto_register)
- t.logger.quiet = options.quiet
- if options.logfile:
- t.logger.console = open(options.logfile, "w")
- t.start()
- def serve_forking(options):
- setup_logger(options)
- t = ForkingServer(SlaveService, hostname = options.host,
- port = options.port, reuse_addr = True,
- authenticator = options.authenticator, registrar = options.registrar,
- auto_register = options.auto_register)
- t.logger.quiet = options.quiet
- if options.logfile:
- t.logger.console = open(options.logfile, "w")
- t.start()
- def serve_stdio(options):
- origstdin = sys.stdin
- origstdout = sys.stdout
- if options.quiet:
- dev = os.devnull
- elif sys.platform == "win32":
- dev = "con:"
- else:
- dev = "/dev/tty"
- try:
- sys.stdin = open(dev, "r")
- sys.stdout = open(dev, "w")
- except (IOError, OSError):
- sys.stdin = open(os.devnull, "r")
- sys.stdout = open(os.devnull, "w")
- conn = rpyc.classic.connect_pipes(origstdin, origstdout)
- try:
- try:
- conn.serve_all()
- except KeyboardInterrupt:
- print( "User interrupt!" )
- finally:
- conn.close()
- def main():
- options = get_options()
- handler = globals()[options.handler]
- handler(options)
- if __name__ == "__main__":
- main()
|