Example #1
0
  protected void receiveQuery(DHTTransportUDPContact originator, Map request, Map response) {
    trace("received query request");

    InetSocketAddress address = originator.getTransportAddress();

    response.put("ip", address.getAddress().getHostAddress().getBytes());

    response.put("port", new Long(address.getPort()));

    response.put("ok", new Long(1));
  }
Example #2
0
  protected Map sendConnect(
      DHTTransportContact target, DHTTransportContact originator, Map originator_client_data) {
    try {
      Map request = new HashMap();

      request.put("type", new Long(RT_CONNECT_REQUEST));

      request.put("origin", encodeContact(originator));

      request.put(
          "port", new Long(((DHTTransportUDPContact) originator).getTransportAddress().getPort()));

      if (originator_client_data != null) {

        request.put("client_data", originator_client_data);
      }

      Map response = sendRequest(target, request, TRANSFER_TIMEOUT);

      if (response == null) {

        return (null);
      }

      if (((Long) response.get("type")).intValue() == RT_CONNECT_REPLY) {

        int result = ((Long) response.get("ok")).intValue();

        trace("received connect reply: " + (result == 0 ? "failed" : "ok"));

        if (result == 1) {

          Map target_client_data = (Map) response.get("client_data");

          if (target_client_data == null) {

            target_client_data = new HashMap();
          }

          return (target_client_data);
        }
      }

      return (null);

    } catch (Throwable e) {

      log(e);

      return (null);
    }
  }
Example #3
0
  protected int sendBind(DHTTransportContact target) {
    try {
      Map request = new HashMap();

      request.put("type", new Long(RT_BIND_REQUEST));

      Map response = sendRequest(target, request, TRANSFER_TIMEOUT);

      if (response == null) {

        return (RESP_FAILED);
      }

      if (((Long) response.get("type")).intValue() == RT_BIND_REPLY) {

        int result = ((Long) response.get("ok")).intValue();

        trace("received bind reply: " + (result == 0 ? "failed" : "ok"));

        if (result == 1) {

          return (RESP_OK);
        }
      }

      return (RESP_NOT_OK);

    } catch (Throwable e) {

      log(e);

      return (RESP_FAILED);
    }
  }
Example #4
0
  public void setRendezvous(DHTTransportContact target, DHTTransportContact rendezvous) {
    explicit_rendezvous_map.put(target.getAddress(), rendezvous);

    if (target.getAddress().equals(dht.getTransport().getLocalContact().getAddress())) {

      publish(true);
    }
  }
Example #5
0
  protected void receiveBind(DHTTransportUDPContact originator, Map request, Map response) {
    trace("received bind request");

    boolean ok = true;
    boolean log = true;

    try {
      server_mon.enter();

      Object[] entry = (Object[]) rendezvous_bindings.get(originator.getAddress().toString());

      if (entry == null) {

        if (rendezvous_bindings.size() == RENDEZVOUS_SERVER_MAX) {

          ok = false;
        }
      } else {

        // already present, no need to log again

        log = false;
      }

      if (ok) {

        long now = plugin_interface.getUtilities().getCurrentSystemTime();

        rendezvous_bindings.put(
            originator.getAddress().toString(), new Object[] {originator, new Long(now)});

        response.put("port", new Long(originator.getAddress().getPort()));
      }
    } finally {

      server_mon.exit();
    }

    if (log) {

      log("Rendezvous request from " + originator.getString() + " " + (ok ? "accepted" : "denied"));
    }

    response.put("ok", new Long(ok ? 1 : 0));
  }
Example #6
0
  protected void receivePunch(DHTTransportUDPContact originator, Map request, Map response) {
    trace("received punch request");

    boolean ok = false;

    String target_str = new String((byte[]) request.get("target"));

    Object[] entry;

    try {
      server_mon.enter();

      entry = (Object[]) rendezvous_bindings.get(target_str);

    } finally {

      server_mon.exit();
    }

    if (entry != null) {

      DHTTransportUDPContact target = (DHTTransportUDPContact) entry[0];

      Map target_client_data = sendConnect(target, originator, (Map) request.get("client_data"));

      if (target_client_data != null) {

        response.put("client_data", target_client_data);

        response.put("port", new Long(target.getTransportAddress().getPort()));

        ok = true;
      }
    }

    log(
        "Rendezvous punch request from "
            + originator.getString()
            + " to "
            + target_str
            + " "
            + (ok ? "initiated" : "failed"));

    response.put("ok", new Long(ok ? 1 : 0));
  }
Example #7
0
  protected void rendezvousFailed(DHTTransportContact current_target, boolean tidy) {
    log("Rendezvous " + (tidy ? "closed" : "failed") + ": " + current_target.getString());

    try {
      pub_mon.enter();

      failed_rendezvous.put(current_target.getAddress(), "");

    } finally {

      pub_mon.exit();
    }

    publish(true);
  }
Example #8
0
  protected void receiveClose(DHTTransportUDPContact originator, Map request, Map response) {
    trace("received close request");

    final DHTTransportContact current_target = rendezvous_target;

    if (current_target != null && Arrays.equals(current_target.getID(), originator.getID())) {

      new AEThread2("DHTNATPuncher:close", true) {
        public void run() {
          rendezvousFailed(current_target, true);
        }
      }.start();
    }

    response.put("ok", new Long(1));
  }
Example #9
0
  protected boolean sendTunnelOutbound(DHTTransportContact target) {
    log("Sending tunnel outbound message to " + target.getString());

    try {
      Map message = new HashMap();

      message.put("type", new Long(RT_TUNNEL_OUTBOUND));

      return (sendTunnelMessage(target, message));

    } catch (Throwable e) {

      log(e);

      return (false);
    }
  }
Example #10
0
  protected Map receiveRequest(DHTTransportUDPContact originator, Map data) {
    int type = ((Long) data.get("type")).intValue();

    Map response = new HashMap();

    switch (type) {
      case RT_BIND_REQUEST:
        {
          response.put("type", new Long(RT_BIND_REPLY));

          receiveBind(originator, data, response);

          break;
        }
      case RT_CLOSE_REQUEST:
        {
          response.put("type", new Long(RT_CLOSE_REPLY));

          receiveClose(originator, data, response);

          break;
        }
      case RT_QUERY_REQUEST:
        {
          response.put("type", new Long(RT_QUERY_REPLY));

          receiveQuery(originator, data, response);

          break;
        }
      case RT_PUNCH_REQUEST:
        {
          response.put("type", new Long(RT_PUNCH_REPLY));

          receivePunch(originator, data, response);

          break;
        }
      case RT_CONNECT_REQUEST:
        {
          response.put("type", new Long(RT_CONNECT_REPLY));

          receiveConnect(originator, data, response);

          break;
        }
      case RT_TUNNEL_INBOUND:
        {
          receiveTunnelInbound(originator, data);

          response = null;

          break;
        }
      case RT_TUNNEL_OUTBOUND:
        {
          receiveTunnelOutbound(originator, data);

          response = null;

          break;
        }
      default:
        {
          response = null;

          break;
        }
    }

    return (response);
  }
Example #11
0
  protected void receiveConnect(DHTTransportContact rendezvous, Map request, Map response) {
    trace("received connect request");

    boolean ok = false;

    // ensure that we've received this from our current rendezvous node

    DHTTransportContact rt = rendezvous_target;

    if (rt != null && rt.getAddress().equals(rendezvous.getAddress())) {

      final DHTTransportUDPContact target = decodeContact((byte[]) request.get("origin"));

      if (target != null) {

        int transport_port = 0;

        Long indirect_port = (Long) request.get("port");

        if (indirect_port != null) {

          transport_port = indirect_port.intValue();
        }

        if (transport_port != 0) {

          InetSocketAddress existing_address = target.getTransportAddress();

          if (transport_port != existing_address.getPort()) {

            target.setTransportAddress(
                new InetSocketAddress(existing_address.getAddress(), transport_port));
          }
        }

        Map originator_client_data = (Map) request.get("client_data");

        boolean no_tunnel = false;

        if (originator_client_data == null) {

          originator_client_data = new HashMap();

        } else {

          no_tunnel = originator_client_data.get("_notunnel") != null;
        }

        if (no_tunnel) {

          log("Received message from " + target.getString());

        } else {

          log("Received connect request from " + target.getString());

          // ping the origin a few times to try and establish a tunnel

          UTTimerEvent event =
              timer.addPeriodicEvent(
                  3000,
                  new UTTimerEventPerformer() {
                    private int pings = 1;

                    public void perform(UTTimerEvent ev) {
                      if (pings > 3) {

                        ev.cancel();

                        return;
                      }

                      pings++;

                      if (sendTunnelInbound(target)) {

                        ev.cancel();
                      }
                    }
                  });

          if (sendTunnelInbound(target)) {

            event.cancel();
          }
        }

        Map client_data =
            adapter.getClientData(target.getTransportAddress(), originator_client_data);

        if (client_data == null) {

          client_data = new HashMap();
        }

        response.put("client_data", client_data);

        ok = true;

      } else {

        log("Connect request: failed to decode target");
      }
    } else {

      log("Connect request from invalid rendezvous: " + rendezvous.getString());
    }

    response.put("ok", new Long(ok ? 1 : 0));
  }
Example #12
0
  protected Map sendPunch(
      DHTTransportContact rendezvous,
      final DHTTransportUDPContact target,
      Map originator_client_data,
      boolean no_tunnel) {
    AESemaphore wait_sem = new AESemaphore("DHTNatPuncher::sendPunch");
    Object[] wait_data = new Object[] {target, wait_sem, new Integer(0)};

    try {

      try {
        punch_mon.enter();

        oustanding_punches.add(wait_data);

      } finally {

        punch_mon.exit();
      }

      Map request = new HashMap();

      request.put("type", new Long(RT_PUNCH_REQUEST));

      request.put("target", target.getAddress().toString().getBytes());

      if (originator_client_data != null) {

        if (no_tunnel) {

          originator_client_data.put("_notunnel", new Long(1));
        }

        request.put("client_data", originator_client_data);
      }

      // for a message payload (i.e. no_tunnel) we double the initiator timeout to give
      // more chance for reasonable size messages to get through as they have to go through
      // 2 xfer processes

      Map response =
          sendRequest(rendezvous, request, no_tunnel ? TRANSFER_TIMEOUT * 2 : TRANSFER_TIMEOUT);

      if (response == null) {

        return (null);
      }

      if (((Long) response.get("type")).intValue() == RT_PUNCH_REPLY) {

        int result = ((Long) response.get("ok")).intValue();

        trace(
            "received "
                + (no_tunnel ? "message" : "punch")
                + " reply: "
                + (result == 0 ? "failed" : "ok"));

        if (result == 1) {

          // pick up port changes from the rendezvous

          Long indirect_port = (Long) response.get("port");

          if (indirect_port != null) {

            int transport_port = indirect_port.intValue();

            if (transport_port != 0) {

              InetSocketAddress existing_address = target.getTransportAddress();

              if (transport_port != existing_address.getPort()) {

                target.setTransportAddress(
                    new InetSocketAddress(existing_address.getAddress(), transport_port));
              }
            }
          }

          if (!no_tunnel) {

            // ping the target a few times to try and establish a tunnel

            UTTimerEvent event =
                timer.addPeriodicEvent(
                    3000,
                    new UTTimerEventPerformer() {
                      private int pings = 1;

                      public void perform(UTTimerEvent event) {
                        if (pings > 3) {

                          event.cancel();

                          return;
                        }

                        pings++;

                        if (sendTunnelOutbound(target)) {

                          event.cancel();
                        }
                      }
                    });

            if (sendTunnelOutbound(target)) {

              event.cancel();
            }

            // give the other end a few seconds to kick off some tunnel events to us

            if (wait_sem.reserve(10000)) {

              event.cancel();
            }
          }

          // routers often fiddle with the port when not mapped so we need to grab the right one to
          // use
          // for direct communication

          // first priority goes to direct tunnel messages received

          int transport_port = 0;

          try {
            punch_mon.enter();

            transport_port = ((Integer) wait_data[2]).intValue();

          } finally {

            punch_mon.exit();
          }

          if (transport_port != 0) {

            InetSocketAddress existing_address = target.getTransportAddress();

            if (transport_port != existing_address.getPort()) {

              target.setTransportAddress(
                  new InetSocketAddress(existing_address.getAddress(), transport_port));
            }
          }

          Map target_client_data = (Map) response.get("client_data");

          if (target_client_data == null) {

            target_client_data = new HashMap();
          }

          return (target_client_data);
        }
      }

      return (null);

    } catch (Throwable e) {

      log(e);

      return (null);

    } finally {

      try {
        punch_mon.enter();

        oustanding_punches.remove(wait_data);

      } finally {

        punch_mon.exit();
      }
    }
  }