/** * 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)); } }
/** * 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); } }
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); } } }
/** * <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); }
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); }
/** 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)); } } } }
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); } }
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(); } }
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... } }
/** * 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); } }
/** * 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; }
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"); } }
/** * 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(); } } }