1 /* 2 * Copyright (c) 1998-2002 The Jgroup Team. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License version 2 as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU Lesser General Public License for more details. 12 * 13 * You should have received a copy of the GNU Lesser General Public License 14 * along with this program; if not, write to the Free Software 15 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 16 * 17 */ 18 19 package jgroup.relacs.mss; 20 21 import java.io.IOException; 22 import java.net.DatagramPacket; 23 import java.net.DatagramSocket; 24 import java.net.SocketException; 25 26 import jgroup.core.EndPoint; 27 28 import org.apache.log4j.Logger; 29 import org.apache.log4j.NDC; 30 31 /** 32 * The <code>UnicastNetworkInterface</code> class implements a 33 * unicast version of the network interface. 34 * 35 * @author Salvatore Cammarata 36 * @author Hein Meling 37 * @since Jgroup 1.2 38 */ 39 final class UnicastNetworkInterface 40 extends Thread 41 implements NetworkInterface, MssConstants 42 { 43 44 //////////////////////////////////////////////////////////////////////////////////////////// 45 // Logger 46 //////////////////////////////////////////////////////////////////////////////////////////// 47 48 /** Obtain logger for this class */ 49 private static final Logger log = Logger.getLogger(UnicastNetworkInterface.class); 50 51 52 //////////////////////////////////////////////////////////////////////////////////////////// 53 // Fields 54 //////////////////////////////////////////////////////////////////////////////////////////// 55 56 /** Upper layer */ 57 private NIListener niListener; 58 59 /** UDP Socket */ 60 private DatagramSocket socket; 61 62 /** Receive buffer length */ 63 private int bufferlen; 64 65 /** True when the thread should continue to run */ 66 private boolean carryOn; 67 68 69 //////////////////////////////////////////////////////////////////////////////////////////// 70 // Constructor 71 //////////////////////////////////////////////////////////////////////////////////////////// 72 73 /** 74 * Constructs and starts the unicast network interface layer. 75 * 76 * @param name 77 * Thread identifier. 78 * @param niListener 79 * Reference to the upper listener layer through which multicast 80 * receive events are passed as upcall invocations. 81 * @param endpoint 82 * Endpoint socket address and port. 83 * @param bufferlen 84 * Size of receive buffer. 85 * @exception IOException 86 * Raised if the unicast socket could not be initialized. 87 */ 88 UnicastNetworkInterface(String name, NIListener niListener, EndPoint endpoint, int bufferlen) 89 throws IOException 90 { 91 /* Initialize thread */ 92 super(name); 93 this.setPriority(NI_PRIORITY); 94 this.setDaemon(true); 95 96 this.niListener = niListener; 97 this.bufferlen = bufferlen; 98 this.carryOn = true; 99 100 /* Initialize socket */ 101 boolean partitionSimulator = Boolean.getBoolean("jgroup.simulator"); 102 try { 103 if (partitionSimulator) { 104 socket = new UnreliableDatagramSocket(endpoint.getPort(), endpoint.getAddress()); 105 } else { 106 if (log.isDebugEnabled()) 107 log.debug("Trying to create a datagram socket at " + endpoint.getAddress() + " ." +endpoint.getPort() ); 108 socket = new DatagramSocket(endpoint.getPort(), endpoint.getAddress()); 109 } 110 } catch (SocketException e) { 111 if (log.isDebugEnabled()) 112 log.warn("Error initializing unicast socket at " + endpoint, e); 113 throw new IOException("Error initializing unicast socket: " + endpoint + "\n" ); 114 } 115 if (log.isDebugEnabled()) 116 log.debug("Unicast socket initialized: " + endpoint + " " + bufferlen); 117 } 118 119 120 //////////////////////////////////////////////////////////////////////////////////////////// 121 // Methods from NetworkInterface 122 //////////////////////////////////////////////////////////////////////////////////////////// 123 124 /* 125 * This operation is not supported by the unicast network interface, 126 * because a host does not send a message to itself through the 127 * network interface. If a host is running multiple daemons on 128 * different ports (JVMs), the method below can be used by specifying 129 * the endpoint. This is possible since the endpoint contains both 130 * the internet address and the port. 131 */ 132 public void send(byte[] buffer, int buflen) 133 { 134 throw new UnsupportedOperationException(); 135 } 136 137 138 // Javadoc comment inherited by NetworkInterface 139 public void send(EndPoint dest, byte[] buffer, int buflen) 140 { 141 DatagramPacket packet = 142 new DatagramPacket(buffer, buflen, dest.getAddress(), dest.getPort()); 143 144 try { 145 socket.send(packet); 146 } catch (IOException e) { 147 log.warn("Error sending packet to " + dest, e); 148 } 149 } 150 151 152 // Javadoc comment inherited by NetworkInterface 153 public void doStart() 154 { 155 start(); 156 } 157 158 159 // Javadoc comment inherited by NetworkInterface 160 public void doStop() 161 { 162 carryOn = false; 163 } 164 165 166 //////////////////////////////////////////////////////////////////////////////////////////// 167 // Methods from Object 168 //////////////////////////////////////////////////////////////////////////////////////////// 169 170 /** 171 * Clean up system resources used by this class. This method will be 172 * invoked when there are no more references to this object, and thus 173 * it should be garbage collected. 174 */ 175 protected void finalize() 176 { 177 carryOn = false; 178 if (socket != null) { 179 socket.close(); 180 socket = null; 181 } 182 } 183 184 185 //////////////////////////////////////////////////////////////////////////////////////////// 186 // Methods from Thread 187 //////////////////////////////////////////////////////////////////////////////////////////// 188 189 /** 190 * Run method of the thread. It blocks until a Datagram packet is received 191 * through the net. 192 */ 193 public void run() 194 { 195 while (carryOn) { 196 try { 197 byte[] buf = new byte[bufferlen]; 198 DatagramPacket packet = new DatagramPacket(buf, bufferlen); 199 socket.receive(packet); 200 if (log.isDebugEnabled()) { 201 String senderName = packet.getAddress().getHostName(); 202 NDC.push(senderName); 203 log.debug("unicast packet.length=" + packet.getLength() + ", sender=" + senderName); 204 } 205 niListener.rnotify(packet); 206 } catch (IOException e) { 207 log.warn("Error receiving packet", e); 208 } finally { 209 if (log.isDebugEnabled()) 210 NDC.pop(); 211 } 212 } 213 /* The thread was stopped, cleaning up system resources. */ 214 this.finalize(); 215 } 216 217 } // END UnicastNetworkInterface