commit 7b3010e1d4338d173bd9aec35e2ed819842d080d Author: George Kadianakis desnacked@riseup.net Date: Fri Sep 6 17:27:11 2013 +0300
Support new client registrations. --- facilitator/fac.py | 3 +- facilitator/facilitator | 25 ++++++++++++++--- facilitator/facilitator.cgi | 64 ++++++++++++++++++++++++++++++++++++------- 3 files changed, 77 insertions(+), 15 deletions(-)
diff --git a/facilitator/fac.py b/facilitator/fac.py index 70d482d..c79e415 100644 --- a/facilitator/fac.py +++ b/facilitator/fac.py @@ -239,11 +239,12 @@ def transact(f, command, *params): raise ValueError("No newline at end of string returned by facilitator") return parse_transaction(line[:-1])
-def put_reg(facilitator_addr, client_addr, registrant_addr=None): +def put_reg(facilitator_addr, client_addr, transport_chain, registrant_addr=None): """Send a registration to the facilitator using a one-time socket. Returns true iff the command was successful.""" f = fac_socket(facilitator_addr) params = [("CLIENT", format_addr(client_addr))] + params.append(("TRANSPORT_CHAIN", transport_chain)) if registrant_addr is not None: params.append(("FROM", format_addr(registrant_addr))) try: diff --git a/facilitator/facilitator b/facilitator/facilitator index 7b1c51a..3b99346 100755 --- a/facilitator/facilitator +++ b/facilitator/facilitator @@ -299,18 +299,35 @@ class Handler(SocketServer.StreamRequestHandler): print >> self.wfile, fac.render_transaction("NONE", ("CHECK-BACK-IN", str(check_back_in))) return True
+ # Handle a PUT request (client made a registration request; register it.) + # Example: PUT CLIENT="1.1.1.1:5555" FROM="1.1.1.2:6666" TRANSPORT_CHAIN="obfs3|websocket" def do_PUT(self, params): + # Check out if we recognize the transport chain in this registration request + transport_chain = fac.param_first("TRANSPORT_CHAIN", params) + if transport_chain is None: + log(u"PUT missing TRANSPORT_CHAIN param") + self.send_error() + return False + + # See if we have relays that support this transport chain + if transport_chain not in options.relays: + log(u"Unrecognized transport chain: %s" % transport_chain) + self.send_error() # XXX can we tell the flashproxy client of this error? + return False + # if we have relays that support this transport chain, we + # certainly have a regset for its outermost transport too. + assert(get_outermost_transport(transport_chain) in REGSETS_IPV4) + client_spec = fac.param_first("CLIENT", params) if client_spec is None: log(u"PUT missing CLIENT param") self.send_error() return False
- # FROM - try: - reg = Reg.parse(client_spec) - except ValueError, e: + reg = Reg.parse(client_spec, transport_chain) + except (UnknownTransport, ValueError) as e: + # XXX should we throw a better error message to the client? Is it possible? log(u"syntax error in %s: %s" % (safe_str(repr(client_spec)), safe_str(repr(str(e))))) self.send_error() return False diff --git a/facilitator/facilitator.cgi b/facilitator/facilitator.cgi index 3adbc15..b20a9ed 100755 --- a/facilitator/facilitator.cgi +++ b/facilitator/facilitator.cgi @@ -79,18 +79,62 @@ Access-Control-Allow-Origin: *\r exit_error(400)
def do_post(): + """Parse client registration.""" + + # Old style client registration: + # client=1.2.3.4:9000 + # New style client registration: + # client-websocket=1.2.3.4:9000&client-obfs3|websocket=1.2.3.4:10000 + + is_new_style = True + if path_info != "/": exit_error(400) - client_specs = fs.getlist("client") - if len(client_specs) != 1: - exit_error(400) - client_spec = client_specs[0].strip() - try: - client_addr = fac.parse_addr_spec(client_spec, defhost=remote_addr[0]) - except ValueError: - exit_error(400) - if not fac.put_reg(FACILITATOR_ADDR, client_addr, remote_addr): - exit_error(500) + + if "client" in fs.keys(): + is_new_style = False + + if is_new_style: + # It's a new style registration. We iterate through the items + # in the POST body, and see if any of them look like + # "client-websocket=1.2.3.4:9000". We then split all those + # items and send them as separate registrations to the + # facilitator. + for key in fs.keys(): + if not key.startswith("client-"): + continue + + # Get the "webssocket" part of "client-webscoket". + transport_chain = key[len("client-"):] + # Get the "1.2.3.4:9000" part of "client-websocket=1.2.3.4:9000". + client_spec = fs[key].value.strip() + try: + client_addr = fac.parse_addr_spec(client_spec, defhost=remote_addr[0]) + except ValueError: + exit_error(400) + + # XXX what if previous registrations passed through + # successfully, but the last one failed and called + # exit_error()? + + # XXX need to link these registrations together, so that + # when one is answerered the rest are invalidated. + if not fac.put_reg(FACILITATOR_ADDR, client_addr, transport_chain, remote_addr): + exit_error(500) + + else: # old-stle registration: + client_specs = fs.getlist("client") + if len(client_specs) != 1: + exit_error(400) + client_spec = client_specs[0].strip() + try: + client_addr = fac.parse_addr_spec(client_spec, defhost=remote_addr[0]) + except ValueError: + exit_error(400) + + if not fac.put_reg(FACILITATOR_ADDR, client_addr, "websocket", remote_addr): + exit_error(500) + print """\ Status: 200\r \r"""
tor-commits@lists.torproject.org