Пример #1
0
  /**
   * Processes a packet read from either the multicast or unicast socket. Needs to be synchronized
   * because mcast or unicast socket reads can be concurrent
   */
  void handleIncomingUdpPacket(byte[] data) {
    ByteArrayInputStream inp_stream;
    ObjectInputStream inp;
    Message msg = null;
    List l; // used if bundling is enabled

    try {
      // skip the first n bytes (default: 4), this is the version info
      inp_stream = new ByteArrayInputStream(data, VERSION_LENGTH, data.length - VERSION_LENGTH);
      inp = new ObjectInputStream(inp_stream);
      if (enable_bundling) {
        l = new List();
        l.readExternal(inp);
        for (Enumeration en = l.elements(); en.hasMoreElements(); ) {
          msg = (Message) en.nextElement();
          try {
            handleMessage(msg);
          } catch (Throwable t) {
            Trace.error("UDP.handleIncomingUdpPacket()", "failure: " + t.toString());
          }
        }
      } else {
        msg = new Message();
        msg.readExternal(inp);
        handleMessage(msg);
      }
    } catch (Throwable e) {
      Trace.error("UDP.handleIncomingUdpPacket()", "exception=" + Trace.getStackTrace(e));
    }
  }
Пример #2
0
  /**
   * Workaround for the problem encountered in certains JDKs that a thread listening on a socket
   * cannot be interrupted. Therefore we just send a dummy datagram packet so that the thread 'wakes
   * up' and realizes it has to terminate. Should be removed when all JDKs support
   * Thread.interrupt() on reads. Uses sock t send dummy packet, so this socket has to be still
   * alive.
   *
   * @param dest The destination host. Will be local host if null
   * @param port The destination port
   */
  void sendDummyPacket(InetAddress dest, int port) {
    DatagramPacket packet;
    byte[] buf = {0};

    if (dest == null) {
      try {
        dest = InetAddress.getLocalHost();
      } catch (Exception e) {
      }
    }

    if (Trace.debug) {
      Trace.info("UDP.sendDummyPacket()", "sending packet to " + dest + ":" + port);
    }
    if (sock == null || dest == null) {
      Trace.warn(
          "UDP.sendDummyPacket()", "sock was null or dest was null, cannot send dummy packet");
      return;
    }
    packet = new DatagramPacket(buf, buf.length, dest, port);
    try {
      sock.send(packet);
    } catch (Throwable e) {
      Trace.error(
          "UDP.sendDummyPacket()",
          "exception sending dummy packet to " + dest + ":" + port + ": " + e);
    }
  }
Пример #3
0
  public void run() {
    Event evt;

    while (evt_thread != null && event_queue != null) {
      try {
        evt = (Event) event_queue.remove();
        switch (evt.getType()) {
          case Event.SUSPECT:
            impl.suspect((Address) evt.getArg());
            break;
          case Event.MERGE:
            impl.merge((Vector) evt.getArg());
            break;
          default:
            Trace.error(
                "GMS.run()",
                "event handler thread encountered event of type "
                    + Event.type2String(evt.getType())
                    + ": not handled by me !");
            break;
        }
      } catch (QueueClosedException closed) {
        break;
      } catch (Exception ex) {
        Trace.warn("GMS.run()", "exception=" + ex);
      }
    }
  }
Пример #4
0
  /**
   * <b>Callback</b>. Called by superclass when event may be handled.
   *
   * <p><b>Do not use <code>PassDown</code> in this method as the event is passed down by default by
   * the superclass after this method returns !</b>
   *
   * @return boolean Defaults to true. If false, event will not be passed down the stack.
   */
  public boolean handleDownEvent(Event evt) {
    switch (evt.getType()) {
      case Event.CONNECT:
        passDown(evt);
        try {
          group_addr = (String) evt.getArg();
        } catch (ClassCastException cce) {
          Trace.error(
              "GMS.handleDownEvent(CONNECT)",
              "group address must " + "be a string (group name) to make sense");
        }
        impl.join(local_addr);
        passUp(new Event(Event.CONNECT_OK));
        startEventHandlerThread();
        return false; // don't pass down: was already passed down

      case Event.DISCONNECT:
        impl.leave((Address) evt.getArg());
        passUp(new Event(Event.DISCONNECT_OK));
        stopEventHandlerThread();
        initState();
        return true; // pass down
    }

    return impl.handleDownEvent(evt);
  }
Пример #5
0
  void handleMessage(Message msg) {
    Event evt;
    UdpHeader hdr;

    // discard my own multicast loopback copy
    if (loopback) {
      Address dst = msg.getDest();
      Address src = msg.getSrc();

      if (dst != null && dst.isMulticastAddress() && src != null && local_addr.equals(src)) {
        if (Trace.debug) {
          Trace.info("UDP.handleMessage()", "discarded own loopback multicast packet");
        }
        return;
      }
    }

    evt = new Event(Event.MSG, msg);
    if (Trace.debug) {
      Trace.info("UDP.handleMessage()", "message is " + msg + ", headers are " + msg.getHeaders());

      /* Because Protocol.up() is never called by this bottommost layer, we call up() directly in the observer.
       * This allows e.g. PerfObserver to get the time of reception of a message */
    }
    if (observer != null) {
      observer.up(evt, up_queue.size());
    }
    hdr = (UdpHeader) msg.removeHeader(name);
    if (hdr != null) {

      /* Discard all messages destined for a channel with a different name */
      String ch_name = null;

      if (hdr.group_addr != null) {
        ch_name = hdr.group_addr;

        // Discard if message's group name is not the same as our group name unless the
        // message is a diagnosis message (special group name DIAG_GROUP)
      }
      if (ch_name != null
          && group_addr != null
          && !group_addr.equals(ch_name)
          && !ch_name.equals(Util.DIAG_GROUP)) {
        if (Trace.trace) {
          Trace.warn(
              "UDP.handleMessage()",
              "discarded message from different group ("
                  + ch_name
                  + "). Sender was "
                  + msg.getSrc());
        }
        return;
      }
    } else {
      Trace.error("UDP.handleMessage()", "message does not have a UDP header");
    }
    passUp(evt);
  }
Пример #6
0
  /** Send a message to the address specified in msg.dest */
  private void sendUnicastMessage(Message msg) {
    IpAddress dest;
    Message copy;
    Object hdr;
    Event evt;

    dest = (IpAddress) msg.getDest(); // guaranteed not to be null
    if (!(dest instanceof IpAddress)) {
      Trace.error("TCP.sendUnicastMessage()", "destination address is not of type IpAddress !");
      return;
    }
    setSourceAddress(msg);

    /* Don't send if destination is local address. Instead, switch dst and src and put in up_queue  */
    if (loopback && local_addr != null && dest != null && dest.equals(local_addr)) {
      copy = msg.copy();
      hdr = copy.getHeader(getName());
      if (hdr != null && hdr instanceof TcpHeader) copy.removeHeader(getName());
      copy.setSrc(local_addr);
      copy.setDest(local_addr);

      evt = new Event(Event.MSG, copy);

      /* Because Protocol.up() is never called by this bottommost layer, we call up() directly in the observer.
      This allows e.g. PerfObserver to get the time of reception of a message */
      if (observer != null) observer.up(evt, up_queue.size());

      passUp(evt);
      return;
    }
    if (Trace.trace)
      Trace.info(
          "TCP.sendUnicastMessage()",
          "dest=" + msg.getDest() + ", hdrs:\n" + msg.printObjectHeaders());
    try {
      if (skip_suspected_members) {
        if (suspected_mbrs.contains(dest)) {
          if (Trace.trace)
            Trace.info(
                "TCP.sendUnicastMessage()",
                "will not send unicast message to " + dest + " as it is currently suspected");
          return;
        }
      }
      ct.send(msg);
    } catch (SocketException e) {
      if (members.contains(dest)) {
        if (!suspected_mbrs.contains(dest)) {
          suspected_mbrs.add(dest);
          passUp(new Event(Event.SUSPECT, dest));
        }
      }
    }
  }
Пример #7
0
 void handleDiagnosticProbe(InetAddress sender, int port) {
   try {
     byte[] diag_rsp = getDiagResponse().getBytes();
     DatagramPacket rsp = new DatagramPacket(diag_rsp, 0, diag_rsp.length, sender, port);
     if (Trace.trace) {
       Trace.info(
           "UDP.handleDiagnosticProbe()", "sending diag response to " + sender + ":" + port);
     }
     sock.send(rsp);
   } catch (Throwable t) {
     Trace.error(
         "UDP.handleDiagnosticProbe()",
         "failed sending diag rsp to " + sender + ":" + port + ", exception=" + t);
   }
 }
Пример #8
0
    void bundleAndSend() {
      Map.Entry entry;
      IpAddress dest;
      ObjectOutputStream out;
      InetAddress addr;
      int port;
      byte[] data;
      List l;

      if (Trace.trace) {
        Trace.info(
            "UDP.BundlingOutgoingPacketHandler.bundleAndSend()",
            "\nsending msgs:\n" + dumpMessages(msgs));
      }
      synchronized (msgs) {
        stopTimer();

        if (msgs.size() == 0) {
          return;
        }

        for (Iterator it = msgs.entrySet().iterator(); it.hasNext(); ) {
          entry = (Map.Entry) it.next();
          dest = (IpAddress) entry.getKey();
          addr = dest.getIpAddress();
          port = dest.getPort();
          l = (List) entry.getValue();
          try {
            out_stream.reset();
            // BufferedOutputStream bos=new BufferedOutputStream(out_stream);
            out_stream.write(Version.version_id, 0, Version.version_id.length); // write the version
            // bos.write(Version.version_id, 0, Version.version_id.length); // write the version
            out = new ObjectOutputStream(out_stream);
            // out=new ObjectOutputStream(bos);
            l.writeExternal(out);
            out.close(); // needed if out buffers its output to out_stream
            data = out_stream.toByteArray();
            doSend(data, addr, port);
          } catch (IOException e) {
            Trace.error(
                "UDP.BundlingOutgoingPacketHandle.bundleAndSend()",
                "exception sending msg (to dest=" + dest + "): " + e);
          }
        }
        msgs.clear();
      }
    }
Пример #9
0
    public void run() {
      Message msg;

      while (outgoing_queue != null && outgoing_packet_handler != null) {
        try {
          msg = (Message) outgoing_queue.remove();
          handleMessage(msg);
        } catch (QueueClosedException closed_ex) {
          if (Trace.trace) {
            Trace.info("UDP.OutgoingPacketHandler.run()", "packet_handler thread terminating");
          }
          break;
        } catch (Throwable t) {
          Trace.error(
              "UDP.OutgoingPacketHandler.run()",
              "exception sending packet: " + Util.printStackTrace(t));
        }
        msg = null; // let's give the poor garbage collector a hand...
      }
    }
Пример #10
0
  /**
   * Caller by the layer above this layer. Usually we just put this Message into the send queue and
   * let one or more worker threads handle it. A worker thread then removes the Message from the
   * send queue, performs a conversion and adds the modified Message to the send queue of the layer
   * below it, by calling Down).
   */
  public void down(Event evt) {
    Message msg;
    Object dest_addr;

    if (evt.getType() != Event.MSG) { // unless it is a message handle it and respond
      handleDownEvent(evt);
      return;
    }

    // ****************** profiling ******************
    /*if(num_msgs == 0) {
    start=System.currentTimeMillis();
    num_msgs++;
         }
         else if(num_msgs >= 1000) {
    stop=System.currentTimeMillis();

    long total_time=stop-start;
    double msgs_per_msec=num_msgs / (double)total_time;

    if(Trace.trace)
        Trace.info("UDP.down.profile()",
                "total_time=" + total_time + ", msgs/ms=" + msgs_per_msec);
    num_msgs=0;
         }
         else {
    num_msgs++;
         }*/
    // ****************** profiling ******************

    msg = (Message) evt.getArg();

    if (udp_hdr != null && udp_hdr.group_addr != null) {
      // added patch by Roland Kurmann (March 20 2003)
      msg.putHeader(name, udp_hdr);
    }

    dest_addr = msg.getDest();

    // Because we don't call Protocol.passDown(), we notify the observer directly (e.g.
    // PerfObserver).
    // This way, we still have performance numbers for UDP
    if (observer != null) {
      observer.passDown(evt);
    }
    if (dest_addr == null) { // 'null' means send to all group members
      if (ip_mcast) {
        if (mcast_addr == null) {
          Trace.error(
              "UDP.down()",
              "dest address of message is null, and "
                  + "sending to default address fails as mcast_addr is null, too !"
                  + " Discarding message "
                  + Util.printEvent(evt));
          return;
        }
        // if we want to use IP multicast, then set the destination of the message
        msg.setDest(mcast_addr);
      } else {
        // sends a separate UDP message to each address
        sendMultipleUdpMessages(msg, members);
        return;
      }
    }

    try {
      sendUdpMessage(msg);
    } catch (Exception e) {
      Trace.error("UDP.down()", "exception=" + e + ", msg=" + msg + ", mcast_addr=" + mcast_addr);
    }
  }
Пример #11
0
  /**
   * Setup the Protocol instance acording to the configuration string The following properties are
   * being read by the UDP protocol param mcast_addr - the multicast address to use default is
   * 224.0.0.200 param mcast_port - (int) the port that the multicast is sent on default is 7500
   * param ip_mcast - (boolean) flag whether to use IP multicast - default is true param ip_ttl -
   * Set the default time-to-live for multicast packets sent out on this socket. default is 32
   *
   * @return true if no other properties are left. false if the properties still have data in them,
   *     ie , properties are left over and not handled by the protocol stack
   */
  public boolean setProperties(Properties props) {
    String str, tmp;

    tmp = System.getProperty("UDP.bind_addr");
    if (tmp != null) {
      str = tmp;
    } else {
      str = props.getProperty("bind_addr");
    }
    if (str != null) {
      try {
        bind_addr = InetAddress.getByName(str);
      } catch (UnknownHostException unknown) {
        Trace.fatal("UDP.setProperties()", "(bind_addr): host " + str + " not known");
        return false;
      }
      props.remove("bind_addr");
    }

    str = props.getProperty("bind_port");
    if (str != null) {
      bind_port = new Integer(str).intValue();
      props.remove("bind_port");
    }

    str = props.getProperty("start_port");
    if (str != null) {
      bind_port = new Integer(str).intValue();
      props.remove("start_port");
    }

    str = props.getProperty("port_range");
    if (str != null) {
      port_range = new Integer(str).intValue();
      props.remove("port_range");
    }

    str = props.getProperty("mcast_addr");
    if (str != null) {
      mcast_addr_name = new String(str);
      props.remove("mcast_addr");
    }

    str = props.getProperty("mcast_port");
    if (str != null) {
      mcast_port = new Integer(str).intValue();
      props.remove("mcast_port");
    }

    str = props.getProperty("ip_mcast");
    if (str != null) {
      ip_mcast = new Boolean(str).booleanValue();
      props.remove("ip_mcast");
    }

    str = props.getProperty("ip_ttl");
    if (str != null) {
      ip_ttl = new Integer(str).intValue();
      props.remove("ip_ttl");
    }

    str = props.getProperty("mcast_send_buf_size");
    if (str != null) {
      mcast_send_buf_size = Integer.parseInt(str);
      props.remove("mcast_send_buf_size");
    }

    str = props.getProperty("mcast_recv_buf_size");
    if (str != null) {
      mcast_recv_buf_size = Integer.parseInt(str);
      props.remove("mcast_recv_buf_size");
    }

    str = props.getProperty("ucast_send_buf_size");
    if (str != null) {
      ucast_send_buf_size = Integer.parseInt(str);
      props.remove("ucast_send_buf_size");
    }

    str = props.getProperty("ucast_recv_buf_size");
    if (str != null) {
      ucast_recv_buf_size = Integer.parseInt(str);
      props.remove("ucast_recv_buf_size");
    }

    str = props.getProperty("loopback");
    if (str != null) {
      loopback = new Boolean(str).booleanValue();
      props.remove("loopback");
    }

    // this is deprecated, just left for compatibility (use use_incoming_packet_handler)
    str = props.getProperty("use_packet_handler");
    if (str != null) {
      use_incoming_packet_handler = new Boolean(str).booleanValue();
      props.remove("use_packet_handler");
      Trace.warn(
          "UDP.setProperties()",
          "'use_packet_handler' is deprecated; use 'use_incoming_packet_handler' instead");
    }

    str = props.getProperty("use_incoming_packet_handler");
    if (str != null) {
      use_incoming_packet_handler = new Boolean(str).booleanValue();
      props.remove("use_incoming_packet_handler");
    }

    str = props.getProperty("use_outgoing_packet_handler");
    if (str != null) {
      use_outgoing_packet_handler = new Boolean(str).booleanValue();
      props.remove("use_outgoing_packet_handler");
    }

    str = props.getProperty("max_bundle_size");
    if (str != null) {
      int bundle_size = Integer.parseInt(str);
      if (bundle_size > max_bundle_size) {
        Trace.error(
            "UDP.setProperties()",
            "max_bundle_size ("
                + bundle_size
                + ") is greater than largest UDP fragmentation size ("
                + max_bundle_size
                + ")");
        return false;
      }
      if (bundle_size <= 0) {
        Trace.error("UDP.setProperties()", "max_bundle_size (" + bundle_size + ") is <= 0");
        return false;
      }
      max_bundle_size = bundle_size;
      props.remove("max_bundle_size");
    }

    str = props.getProperty("max_bundle_timeout");
    if (str != null) {
      max_bundle_timeout = Long.parseLong(str);
      if (max_bundle_timeout <= 0) {
        Trace.error(
            "UDP.setProperties()", "max_bundle_timeout of " + max_bundle_timeout + " is invalid");
        return false;
      }
      props.remove("max_bundle_timeout");
    }

    str = props.getProperty("enable_bundling");
    if (str != null) {
      enable_bundling = new Boolean(str).booleanValue();
      props.remove("enable_bundling");
    }

    if (props.size() > 0) {
      System.err.println("UDP.setProperties(): the following properties are not recognized:");
      props.list(System.out);
      return false;
    }

    if (enable_bundling) {
      if (use_outgoing_packet_handler == false) {
        Trace.warn(
            "UDP.setProperties()",
            "enable_bundling is true; setting use_outgoing_packet_handler=true");
      }
      use_outgoing_packet_handler = true;
    }

    return true;
  }
Пример #12
0
  public void run() {
    DatagramPacket packet;
    byte receive_buf[] = new byte[65535];
    int len;
    byte[] tmp, data;

    // moved out of loop to avoid excessive object creations (bela March 8 2001)
    packet = new DatagramPacket(receive_buf, receive_buf.length);

    while (mcast_receiver != null && mcast_sock != null) {
      try {
        packet.setData(receive_buf, 0, receive_buf.length);
        mcast_sock.receive(packet);
        len = packet.getLength();
        data = packet.getData();
        if (len == 1 && data[0] == 0) {
          if (Trace.debug) {
            Trace.info("UDP.run()", "received dummy packet");
          }
          continue;
        }

        if (len == 4) { // received a diagnostics probe
          if (data[0] == 'd' && data[1] == 'i' && data[2] == 'a' && data[3] == 'g') {
            handleDiagnosticProbe(packet.getAddress(), packet.getPort());
            continue;
          }
        }

        if (Trace.debug) {
          Trace.info(
              "UDP.receive()",
              "received (mcast) "
                  + packet.getLength()
                  + " bytes from "
                  + packet.getAddress()
                  + ":"
                  + packet.getPort()
                  + " (size="
                  + len
                  + " bytes)");
        }
        if (len > receive_buf.length) {
          Trace.error(
              "UDP.run()",
              "size of the received packet ("
                  + len
                  + ") is bigger than "
                  + "allocated buffer ("
                  + receive_buf.length
                  + "): will not be able to handle packet. "
                  + "Use the FRAG protocol and make its frag_size lower than "
                  + receive_buf.length);
        }

        if (Version.compareTo(data) == false) {
          Trace.warn(
              "UDP.run()",
              "packet from "
                  + packet.getAddress()
                  + ":"
                  + packet.getPort()
                  + " has different version ("
                  + Version.printVersionId(data, Version.version_id.length)
                  + ") from ours ("
                  + Version.printVersionId(Version.version_id)
                  + "). This may cause problems");
        }

        if (use_incoming_packet_handler) {
          tmp = new byte[len];
          System.arraycopy(data, 0, tmp, 0, len);
          incoming_queue.add(tmp);
        } else {
          handleIncomingUdpPacket(data);
        }
      } catch (SocketException sock_ex) {
        if (Trace.trace) {
          Trace.info("UDP.run()", "multicast socket is closed, exception=" + sock_ex);
        }
        break;
      } catch (InterruptedIOException io_ex) { // thread was interrupted
        ; // go back to top of loop, where we will terminate loop
      } catch (Throwable ex) {
        Trace.error("UDP.run()", "exception=" + ex + ", stack trace=" + Util.printStackTrace(ex));
        Util.sleep(300); // so we don't get into 100% cpu spinning (should NEVER happen !)
      }
    }
    if (Trace.trace) {
      Trace.info("UDP.run()", "multicast thread terminated");
    }
  }
Пример #13
0
  /**
   * Assigns the new ltime. Installs view and view_id. Changes role to coordinator if necessary.
   * Sends VIEW_CHANGE event up and down the stack.
   */
  public void installView(ViewId new_view, Vector mbrs) {
    Object coord;
    int rc;

    synchronized (view_mutex) { // serialize access to views
      ltime = Math.max(new_view.getId(), ltime); // compute Lamport logical time
      if (Trace.trace) Trace.info("GMS.installView()", "received view change, vid=" + new_view);

      /* Check for self-inclusion: if I'm not part of the new membership, I just discard it.
      This ensures that messages sent in view V1 are only received by members of V1 */
      if (checkSelfInclusion(mbrs) == false) {
        if (Trace.trace)
          Trace.warn("GMS.installView()", "I'm not member of " + mbrs + ", discarding");
        return;
      }

      if (view_id == null) {
        if (new_view == null) {
          Trace.error("GMS.installView()", "view_id and new_view are null !");
          return;
        } else { // view_id is null, new_view not: just install new_view (we're still a client)
          view_id = (ViewId) new_view.clone();
        }
      } else {
        if (new_view == null) { // this should never happen though !
          Trace.error("GMS.installView()", "new_view is null !");
          return;
        } else { // both view_id and new_view are not null
          rc = new_view.compareTo(view_id); // rc should always be a positive number
          if (rc <= 0) { // don't accept view id lower than our own
            if (Trace.trace) {
              Trace.warn(
                  "GMS.installView()",
                  "received view <= current view; discarding it ! "
                      + "(view_id: "
                      + view_id
                      + ", new_view: "
                      + new_view
                      + ")");
            }
            return;
          } else { // the check for vid equality was okay, assign new_view to view_id

            if (new_view.getCoordAddress() != null) {
              view_id = new ViewId(new_view.getCoordAddress(), new_view.getId());
            } else {
              view_id = new ViewId(view_id.getCoordAddress(), new_view.getId());
            }
          }
        }
      }

      if (mbrs != null && mbrs.size() > 0) members.set(mbrs);

      // Send VIEW_CHANGE event up and down the stack:
      Event view_event = new Event(Event.VIEW_CHANGE, makeView(members.getMembers()));
      passDown(view_event); // needed e.g. by failure detector or UDP
      passUp(view_event);

      coord = determineCoordinator();
      if (coord != null
          && coord.equals(local_addr)
          && !(coord.equals(new_view.getCoordAddress()))) {
        becomeCoordinator();
      }
    }
  }