View Javadoc

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.InetAddress;
24  import java.net.MulticastSocket;
25  import java.net.SocketException;
26  
27  import jgroup.relacs.simulator.SocketStatusImpl;
28  
29  import org.apache.log4j.Logger;
30  
31  /**
32   *  This class represents an unreliable socket for sending and receiving
33   *  multicast datagram packets.  It can be used to simulate packet loss.
34   *
35   *  @author Alberto Montresor
36   *  @author Hein Meling
37   *  @since Jgroup 0.5
38   */
39  final class UnreliableMulticastSocket
40    extends MulticastSocket
41  {
42  
43    ////////////////////////////////////////////////////////////////////////////////////////////
44    // Logger
45    ////////////////////////////////////////////////////////////////////////////////////////////
46  
47    /** Obtain logger for this class */
48    private static final Logger log = Logger.getLogger(UnreliableMulticastSocket.class);
49  
50  
51    ////////////////////////////////////////////////////////////////////////////////////////////
52    // Fields
53    ////////////////////////////////////////////////////////////////////////////////////////////
54  
55    private final SocketStatusImpl status;
56  
57  
58    ////////////////////////////////////////////////////////////////////////////////////////////
59    // Constructors
60    ////////////////////////////////////////////////////////////////////////////////////////////
61  
62    /**
63     *  Constructs an unreliable multicast socket and binds it to any
64     *  available port on the local host machine.
65     *
66     *  @exception SocketException
67     *    If the socket could not be opened, or the socket could not
68     *    be bound to the specified local port.
69     */
70    UnreliableMulticastSocket()
71      throws IOException
72    {
73      this(0);
74    }
75  
76  
77    /**
78     *  Constructs a unreliable multicast socket and binds it to the
79     *  specified port on the local host machine.  The local port must be
80     *  between 0 and 65535 inclusive.
81     *
82     *  @param port
83     *    Port to use on the local host.
84     *  @exception SocketException
85     *    If the socket could not be opened, or the socket could not
86     *    be bound to the specified local port.
87     */
88    UnreliableMulticastSocket(int port)
89      throws IOException
90    {
91      super(port);
92      status = SocketStatusImpl.instance();
93      if (log.isDebugEnabled())
94        log.debug("UnreliableMulticastSocket initialized at port=" + port + ", status="+status);
95    }
96  
97  
98    ////////////////////////////////////////////////////////////////////////////////////////////
99    // Socket methods to override
100   ////////////////////////////////////////////////////////////////////////////////////////////
101 
102   /**
103    *  Sends a datagram packet using this socket.  The specified
104    *  <code>DatagramPacket</code> includes information indicating the
105    *  data to be sent, its length, the IP address of the remote host,
106    *  and the port number on the remote host.
107    *
108    *  Note that in using the partition simulator, this method will
109    *  only enable partitioning between hosts with separate multicast
110    *  addresses.  The partition pattern file must therefore define the
111    *  link probabilities for multicast addresses rather than host
112    *  addresses.
113    *
114    *  @param packet
115    *    The <code>DatagramPacket</code> to be sent.
116    *  @exception IOException
117    *    If an I/O error occurs.
118    *  @see java.net.DatagramPacket
119    */
120   public void send(DatagramPacket packet)
121     throws IOException
122   {
123     // note that this receiver address is a multicast address
124     InetAddress receiver = packet.getAddress();
125     if (status == null || status.isReliable(receiver)) {
126       if (log.isDebugEnabled())
127         log.debug("Sending multicast packet to " + receiver.getHostAddress());
128       super.send(packet);
129     } else if (log.isDebugEnabled()) {
130       log.debug("Discarding multicast packet meant for " + receiver.getHostAddress());
131     }
132   }
133 
134   /**
135    *  Receive a datagram packet using this socket.  The specified
136    *  <code>DatagramPacket</code> should be filled with the received
137    *  data, its length, the IP address and port of the sender host.
138    *
139    *  Given that the partition simulator is activated for the link
140    *  between the receiver and the sender, the packet size will be set
141    *  to zero, and discarded in <code>MulticastNetworkInterface</code>.
142    *
143    *  @param packet
144    *    The <code>DatagramPacket</code> object to fill with the
145    *    received data.
146    *  @exception IOException
147    *    If an I/O error occurs.
148    *  @see java.net.DatagramPacket
149    */
150   public void receive(DatagramPacket packet)
151     throws IOException
152   {
153     super.receive(packet);
154     InetAddress sender = packet.getAddress();
155     if (log.isDebugEnabled()) {
156       log.debug("Received packet from: " + sender.getHostName());
157       log.debug("status=" + status + ", isReliable=" + status.isReliable(sender));
158     }
159     if (status != null && !status.isReliable(sender)) {
160       packet.setLength(0);
161       if (log.isDebugEnabled())
162         log.debug("Packet size set to zero; for discarding...");
163     }
164   }
165 
166 } // END UnreliableMulticastSocket