[tor-commits] [flashproxy/master] migrate flashproxy-client to argparse

infinity0 at torproject.org infinity0 at torproject.org
Mon Jul 7 08:55:34 UTC 2014


commit c323a11f3c4fbf9ed0fd9721d62410584524197b
Author: Ximin Luo <infinity0 at gmx.com>
Date:   Tue Nov 19 17:17:59 2013 +0000

    migrate flashproxy-client to argparse
---
 flashproxy-client |  255 ++++++++++++++++++++++++-----------------------------
 1 file changed, 115 insertions(+), 140 deletions(-)

diff --git a/flashproxy-client b/flashproxy-client
index 09630b3..60068be 100755
--- a/flashproxy-client
+++ b/flashproxy-client
@@ -3,11 +3,11 @@
 The flashproxy client transport plugin.
 """
 
+import argparse
 import BaseHTTPServer
 import array
 import base64
 import cStringIO
-import getopt
 import os
 import os.path
 import select
@@ -69,70 +69,6 @@ class options(object):
     transport = DEFAULT_TRANSPORT
     safe_logging = True
 
-def usage(f = sys.stdout):
-    print >> f, """\
-Usage: %(progname)s --register [LOCAL][:PORT] [REMOTE][:PORT]
-Wait for connections on a local and a remote port. When any pair of connections
-exists, data is ferried between them until one side is closed. By default
-LOCAL is localhost addresses on port %(local_port)d and REMOTE is all addresses
-on port %(remote_port)d.
-
-The local connection acts as a SOCKS4a proxy, but the host and port in the SOCKS
-request are ignored and the local connection is always linked to a remote
-connection.
-
-By default, runs as a managed proxy: informs a parent Tor process of support for
-the "flashproxy" or "websocket" pluggable transport. In managed mode,
-the LOCAL port is chosen arbitrarily instead of defaulting to
-%(local_port)d; however this can be overridden by including a LOCAL port
-in the command. This is the way the program should be invoked in a torrc
-ClientTransportPlugin "exec" line. Use the --external option to run as
-an external proxy that does not interact with Tor.
-
-If any of the --register, --register-addr, or --register-methods options are
-used, then your IP address will be sent to the facilitator so that proxies can
-connect to you. You need to register in some way in order to get any service.
-The --facilitator option allows controlling which facilitator is used; if
-omitted, it uses a public default.
-
-  -4                        registration helpers use IPv4.
-  -6                        registration helpers use IPv6.
-      --daemon              daemonize (Unix only).
-      --external            be an external proxy (don't interact with Tor using
-                              environment variables and stdout).
-  -f, --facilitator=URL     advertise willingness to receive connections to URL.
-      --facilitator-pubkey=FILENAME
-                            encrypt registrations to the given PEM-formatted
-                              public key (default built-in).
-  -h, --help                show this help.
-  -l, --log FILENAME        write log to FILENAME (default stdout).
-      --pidfile FILENAME    write PID to FILENAME after daemonizing.
-      --port-forwarding     attempt to forward REMOTE port.
-      --port-forwarding-helper=PROGRAM  use the given PROGRAM to forward ports
-                              (default "%(port_forwarding_helper)s"). Implies --port-forwarding.
-      --port-forwarding-external=PORT  forward the external PORT to REMOTE on
-                              the local host (default same as REMOTE). Implies
-                              --port-forwarding.
-  -r, --register            register with the facilitator.
-      --register-addr=ADDR  register the given address (in case it differs from
-                              REMOTE). Implies --register.
-      --register-methods=METHOD[,METHOD...]
-                            register using the given comma-separated list of
-                              methods. Implies --register. Possible methods are
-                                appspot email http
-                              Default is "%(reg_methods)s".
-      --transport=TRANSPORT  register using the given transport
-                              (default "%(transport)s").
-      --unsafe-logging      don't scrub IP addresses from logs.\
-""" % {
-    "progname": sys.argv[0],
-    "local_port": DEFAULT_LOCAL_PORT_EXTERNAL,
-    "remote_port": DEFAULT_REMOTE_PORT,
-    "reg_methods": ",".join(DEFAULT_REGISTER_METHODS),
-    "port_forwarding_helper": DEFAULT_PORT_FORWARDING_HELPER,
-    "transport": DEFAULT_TRANSPORT,
-}
-
 def safe_str(s):
     """Return "[scrubbed]" if options.safe_logging is true, and s otherwise."""
     if options.safe_logging:
@@ -1070,69 +1006,109 @@ def main():
     global websocket_pending, socks_pending
     global unlinked_locals, unlinked_remotes
 
-    register_addr_spec = None
-    register_methods = []
-
-    opts, args = getopt.gnu_getopt(sys.argv[1:], "46f:hl:r", [
-        "daemon",
-        "external",
-        "facilitator=",
-        "facilitator-pubkey=",
-        "help",
-        "log=",
-        "pidfile=",
-        "register",
-        "register-addr=",
-        "register-methods=",
-        "port-forwarding",
-        "port-forwarding-helper=",
-        "port-forwarding-external=",
-        "transport=",
-        "unsafe-logging",
-    ])
-    for o, a in opts:
-        if o == "-4":
-            options.address_family = socket.AF_INET
-        elif o == "-6":
-            options.address_family = socket.AF_INET6
-        elif o == "--daemon":
-            options.daemonize = True
-        elif o == "--external":
-            options.managed = False
-        elif o == "-f" or o == "--facilitator":
-            options.facilitator_url = a
-        elif o == "--facilitator-pubkey":
-            options.facilitator_pubkey_filename = a
-        elif o == "-h" or o == "--help":
-            usage()
-            sys.exit()
-        elif o == "-l" or o == "--log":
-            options.log_filename = a
-        elif o == "--pidfile":
-            options.pid_filename = a
-        elif o == "-r" or o == "--register":
-            options.register = True
-        elif o == "--register-addr":
-            if register_addr_spec is not None:
-                print >> sys.stderr, "%s: only one --register-addr is allowed." % sys.argv[0]
-                sys.exit(1)
-            options.register = True
-            register_addr_spec = a
-        elif o == "--register-methods":
-            options.register = True
-            register_methods.extend(a.split(","))
-        elif o == "--port-forwarding":
-            options.port_forwarding = True
-        elif o == "--port-forwarding-helper":
-            options.port_forwarding = True
-            options.port_forwarding_helper = a
-        elif o == "--port-forwarding-external":
-            options.port_forwarding = True
-            options.port_forwarding_external = int(a)
-        elif o == "--transport":
-            options.transport = a
-        elif o == "--unsafe-logging":
-            options.safe_logging = False
+    parser = argparse.ArgumentParser(
+        formatter_class=argparse.RawDescriptionHelpFormatter,
+        description="""\
+Wait for connections on a local and a remote port. When any pair of connections
+exists, data is ferried between them until one side is closed.
+
+The local connection acts as a SOCKS4a proxy, but the host and port in the SOCKS
+request are ignored and the local connection is always linked to a remote
+connection.
+
+By default, runs as a managed proxy: informs a parent Tor process of support for
+the "flashproxy" or "websocket" pluggable transport. In managed mode, the LOCAL
+port is chosen arbitrarily instead of the default; this can be overridden by
+including a LOCAL port in the command. This is the way the program should be
+invoked in a torrc ClientTransportPlugin "exec" line. Use the --external option
+to run as an external proxy that does not interact with Tor.
+
+If any of the --register, --register-addr, or --register-methods options are
+used, then your IP address will be sent to the facilitator so that proxies can
+connect to you. You need to register in some way in order to get any service.
+The --facilitator option allows controlling which facilitator is used; if
+omitted, it uses a public default.""",
+        epilog="""\
+The -4, -6, --unsafe-logging, --transport and --facilitator-pubkey options are
+propagated to the child registration helpers. For backwards compatilibility,
+the --facilitator option is also propagated to the http registration helper.
+If you need to pass more options, use TODO #9976.""")
+    # common opts
+    parser.add_argument("-4", help="name lookups use only IPv4.",
+        action="store_const", const=socket.AF_INET, dest="address_family")
+    parser.add_argument("-6", help="name lookups use only IPv6.",
+        action="store_const", const=socket.AF_INET6, dest="address_family")
+    parser.add_argument("--unsafe-logging", help="don't scrub IP addresses and "
+        "other sensitive information from logs.", action="store_true")
+    parser.add_argument("--facilitator-pubkey", help="encrypt registrations to "
+        "the given PEM-formatted public key file (default built-in).",
+        metavar='FILENAME')
+    parser.add_argument("--transport",
+        help="register using the given transport, default %(default)s.",
+        default=DEFAULT_TRANSPORT)
+    parser.add_argument("-f", "--facilitator", metavar="URL",
+        help="register with the facilitator at this URL, default %(default)s. "
+        "This is passed to the http registration ONLY.")
+    # specific opts and args
+    parser.add_argument("--daemon",
+        help="daemonize (Unix only).", action="store_true")
+    parser.add_argument("--external",
+        help="be an external (non-managed) proxy - don't interact with Tor "
+        "using environment variables and stdout.", action="store_true")
+    parser.add_argument("-l", "--log", metavar="FILENAME",
+        help="write log to FILENAME (default stderr).")
+    parser.add_argument("--pidfile", metavar="FILENAME",
+        help="write PID to FILENAME after daemonizing.")
+    parser.add_argument("--port-forwarding",
+        help="attempt to forward REMOTE port.", action="store_true")
+    parser.add_argument("--port-forwarding-helper", metavar="PROGRAM",
+        help="use the given PROGRAM to forward ports, default %s. Implies "
+        "--port-forwarding." % DEFAULT_PORT_FORWARDING_HELPER)
+    parser.add_argument("--port-forwarding-external", metavar="PORT",
+        help="forward the external PORT to REMOTE on the local host, default "
+        "same as the REMOTE. Implies --port-forwarding.", type=int)
+    parser.add_argument("-r", "--register",
+        help="register with the facilitator.", action="store_true")
+    parser.add_argument("--register-addr", metavar="ADDR",
+        help="register the given address (in case it differs from REMOTE). "
+        "Implies --register.")
+    parser.add_argument("--register-methods", metavar="METHOD[,METHOD...]",
+        help="register using the given comma-separated list of methods. "
+        "Implies --register. Possible methods are appspot,email,http. Default "
+        "is %s." % ",".join(DEFAULT_REGISTER_METHODS),
+        type=lambda x: None if x is None else x.split(",") if x else [])
+    parser.add_argument("local_addr", metavar="LOCAL:PORT",
+        help="local addr+port to listen on, default all localhost addresses on "
+        "port %s. In managed mode, the port is chosen arbitrarily if not given."
+        % DEFAULT_LOCAL_PORT_EXTERNAL, default="", nargs="?")
+    parser.add_argument("remote_addr", metavar="REMOTE:PORT",
+        help="remote addr+port to listen on, default all addresses on port %s"
+        % DEFAULT_REMOTE_PORT, default="", nargs="?")
+
+    ns = parser.parse_args(sys.argv[1:])
+    options.address_family = ns.address_family or socket.AF_UNSPEC
+    if options.address_family != socket.AF_UNSPEC:
+        getaddrinfo = socket.getaddrinfo
+        def getaddrinfo_replacement(host, port, family, *args, **kwargs):
+            return getaddrinfo(host, port, options.address_family, *args, **kwargs)
+        socket.getaddrinfo = getaddrinfo_replacement
+    options.safe_logging = not ns.unsafe_logging
+
+    options.managed = not ns.external
+
+    # do registration if any of the register options were set
+    do_register = (ns.register or
+                   ns.register_addr is not None or
+                   ns.register_methods is not None)
+
+    # do port forwarding if any of the port-forwarding options were set
+    do_port_forwarding = (ns.port_forwarding or
+                          ns.port_forwarding_helper is not None or
+                          ns.port_forwarding_external is not None)
+
+    options.log_filename = ns.log
+    options.daemonize = ns.daemon
+    options.pid_filename = ns.pidfile
 
     if options.log_filename:
         options.log_file = open(options.log_filename, "a")
@@ -1152,18 +1128,8 @@ def main():
         default_local_port = DEFAULT_LOCAL_PORT_EXTERNAL
     default_remote_port = DEFAULT_REMOTE_PORT
 
-    if len(args) == 0:
-        local_addr = ("", default_local_port)
-        remote_addr = ("", default_remote_port)
-    elif len(args) == 1:
-        local_addr = parse_addr_spec(args[0], defhost="", defport=default_local_port)
-        remote_addr = ("", default_remote_port)
-    elif len(args) == 2:
-        local_addr = parse_addr_spec(args[0], defhost="", defport=default_local_port)
-        remote_addr = parse_addr_spec(args[1], defhost="", defport=default_remote_port)
-    else:
-        usage(sys.stderr)
-        sys.exit(1)
+    local_addr = parse_addr_spec(ns.local_addr, defhost="", defport=default_local_port)
+    remote_addr = parse_addr_spec(ns.remote_addr, defhost="", defport=default_remote_port)
 
     if local_addr[0]:
         options.local_addrs.append(local_addr)
@@ -1180,11 +1146,20 @@ def main():
         if socket.has_ipv6:
             options.remote_addrs.append(("::", remote_addr[1]))
 
+    # Determine registration info if requested.
+    options.register = do_register
+    register_addr_spec = ns.register_addr
+    register_methods = ns.register_methods
+
     if not register_methods:
         register_methods = DEFAULT_REGISTER_METHODS
     for method in register_methods:
         options.register_commands.append(build_register_command(method))
 
+    options.port_forwarding = do_port_forwarding
+    options.port_forwarding_helper = ns.port_forwarding_helper or DEFAULT_PORT_FORWARDING_HELPER
+    options.port_forwarding_external = ns.port_forwarding_external
+
     # Remote sockets, accepting remote WebSocket connections from proxies.
     remote_listen = []
     for addr in options.remote_addrs:





More information about the tor-commits mailing list