KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xsocket > datagram > MulticastEndpoint


1 // $Id: MulticastEndpoint.java 1546 2007-07-23 06:07:56Z grro $
2
/*
3  * Copyright (c) xsocket.org, 2006 - 2007. All rights reserved.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Please refer to the LGPL license at: http://www.gnu.org/copyleft/lesser.txt
20  * The latest copy of this software may be found on http://www.xsocket.org/
21  */

22 package org.xsocket.datagram;
23
24 import java.io.IOException JavaDoc;
25 import java.net.DatagramPacket JavaDoc;
26 import java.net.InetAddress JavaDoc;
27 import java.net.InetSocketAddress JavaDoc;
28 import java.net.MulticastSocket JavaDoc;
29 import java.net.SocketAddress JavaDoc;
30 import java.net.SocketOptions JavaDoc;
31 import java.nio.ByteBuffer JavaDoc;
32 import java.util.Collections JavaDoc;
33 import java.util.HashMap JavaDoc;
34 import java.util.Map JavaDoc;
35 import java.util.concurrent.Executor JavaDoc;
36 import java.util.logging.Level JavaDoc;
37 import java.util.logging.Logger JavaDoc;
38
39
40 import org.xsocket.ClosedConnectionException;
41
42
43
44 /**
45  * non blocking Mutlicast endpoint <br><br>
46  *
47  * Caused by the missing channel support for multicast Datagram (JSE 6.0) this
48  * class is implemented by using the "classic" MulticastSocket
49  *
50  * @author grro@xsocket.org
51  */

52 public final class MulticastEndpoint extends AbstractEndpoint implements IConnectedEndpoint {
53
54     /*
55      * * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4527345
56      */

57
58     
59     private static Logger JavaDoc LOG = Logger.getLogger(MulticastEndpoint.class.getName());
60     
61     
62     private static final Map JavaDoc<String JavaDoc ,Class JavaDoc> SUPPORTED_OPTIONS = new HashMap JavaDoc<String JavaDoc, Class JavaDoc>();
63     
64     static {
65         SUPPORTED_OPTIONS.put(SO_RCVBUF, Integer JavaDoc.class);
66         SUPPORTED_OPTIONS.put(SO_SNDBUF, Integer JavaDoc.class);
67         SUPPORTED_OPTIONS.put(IP_TOS, Integer JavaDoc.class);
68         SUPPORTED_OPTIONS.put(SO_REUSEADDR, Boolean JavaDoc.class);
69         SUPPORTED_OPTIONS.put(SO_REUSEADDR, Boolean JavaDoc.class);
70         SUPPORTED_OPTIONS.put(IP_MULTICAST_TTL, Integer JavaDoc.class);
71         SUPPORTED_OPTIONS.put(IP_MULTICAST_LOOP, Boolean JavaDoc.class);
72     }
73
74     
75         
76     // run flag
77
private boolean isRunning = true;
78     
79         
80     // socket
81
private MulticastSocket JavaDoc socket = null;
82     private InetSocketAddress JavaDoc multicastAddress = null;
83     
84     
85     /**
86      * Constructs a datagram socket and
87      * connects it to the given address
88      *
89      * @param address the group address
90      * @param port the port
91      * @throws IOException If some I/O error occurs
92      */

93     public MulticastEndpoint(InetAddress JavaDoc address, final int port) throws IOException JavaDoc {
94         this(address, port, null, 0, null);
95     }
96
97     
98     /**
99      * @deprecated
100      */

101     public MulticastEndpoint(InetAddress JavaDoc address, final int port, DatagramSocketConfiguration socketConfiguration) throws IOException JavaDoc {
102         this(address, port, socketConfiguration, 0, null);
103     }
104
105     
106
107     /**
108      * Constructs a datagram socket and
109      * connects it to the given address
110      *
111      * @param address the group address
112      * @param port the port
113      * @param receiveSize the size of the data packet to receive
114      * @param datagramHandler the datagram handler
115      * @throws IOException If some I/O error occurs
116      */

117     public MulticastEndpoint(String JavaDoc address, final int port, int receiveSize, IDatagramHandler datagramHandler) throws IOException JavaDoc {
118         this(InetAddress.getByName(address), port, new DatagramSocketConfiguration(), receiveSize, datagramHandler);
119     }
120
121     
122     /**
123      * @deprecated
124      */

125     public MulticastEndpoint(String JavaDoc address, final int port, DatagramSocketConfiguration socketConfiguration, int receiveSize, IDatagramHandler datagramHandler) throws IOException JavaDoc {
126         this(InetAddress.getByName(address), port, socketConfiguration, receiveSize, datagramHandler);
127     }
128
129     
130     
131     /**
132      * Constructs a datagram socket and
133      * connects it to the given address
134      *
135      * @param address the group address
136      * @param port the port
137      * @param receiveSize the size of the data packet to receive
138      * @param datagramHandler the datagram handler
139      * @throws IOException If some I/O error occurs
140      */

141     public MulticastEndpoint(InetAddress JavaDoc address, final int port, int receiveSize, IDatagramHandler datagramHandler) throws IOException JavaDoc {
142         this(address, port, new DatagramSocketConfiguration(), receiveSize, datagramHandler);
143     }
144     
145     
146     /**
147      * Constructs a datagram socket and
148      * connects it to the given address
149      *
150      * @param address the group address
151      * @param port the port
152      * @param receiveSize the size of the data packet to receive
153      * @param datagramHandler the datagram handler
154      * @param workerPool the workerPool
155      * @throws IOException If some I/O error occurs
156      */

157     public MulticastEndpoint(InetAddress JavaDoc address, final int port, int receiveSize, IDatagramHandler datagramHandler, Executor JavaDoc workerPool) throws IOException JavaDoc {
158         this(address, port, new DatagramSocketConfiguration(), receiveSize, datagramHandler, workerPool);
159     }
160
161     
162     /**
163      * @deprecated
164      */

165     public MulticastEndpoint(InetAddress JavaDoc address, int port, DatagramSocketConfiguration socketConfiguration, int receiveSize, IDatagramHandler datagramHandler) throws IOException JavaDoc {
166         this(address, port, socketConfiguration, receiveSize, datagramHandler, getGlobalWorkerPool());
167     }
168     
169     
170     /**
171      * @deprecated
172      */

173     public MulticastEndpoint(InetAddress JavaDoc address, int port, DatagramSocketConfiguration socketConfiguration, int receiveSize, IDatagramHandler datagramHandler, Executor JavaDoc workerPool) throws IOException JavaDoc {
174         this(address, port, socketConfiguration.toOptions(), receiveSize, datagramHandler, workerPool);
175     }
176     
177     /**
178      * Constructs a datagram socket and
179      * connects it to the given address
180      *
181      * @param address the group address
182      * @param port the port
183      * @param options the socket options
184      * @param receiveSize the size of the data packet to receive
185      * @param datagramHandler the datagram handler
186      * @param workerPool the workerPool
187      * @throws IOException If some I/O error occurs
188      */

189     public MulticastEndpoint(InetAddress JavaDoc address, int port, Map JavaDoc<String JavaDoc, Object JavaDoc> options, int receiveSize, IDatagramHandler datagramHandler, Executor JavaDoc workerPool) throws IOException JavaDoc {
190         super(datagramHandler, receiveSize, workerPool);
191                 
192         socket = new MulticastSocket JavaDoc(port);
193
194         for (String JavaDoc name : options.keySet()) {
195             setOption(name, options.get(name));
196         }
197         
198         socket.joinGroup(address);
199         multicastAddress = new InetSocketAddress JavaDoc(address, port);
200         
201         if (datagramHandler != null) {
202             startReceiver();
203         }
204         
205         if (LOG.isLoggable(Level.FINE)) {
206             LOG.fine("upd multicast endpoint bound to " + address.getCanonicalHostName() + "/" + port);
207         }
208     }
209     
210     
211     
212     /**
213      * @deprecated
214      */

215     public SocketOptions JavaDoc getSocketOptions() {
216         return getSocketOptions(socket);
217     }
218     
219     
220     private void startReceiver() {
221         Thread JavaDoc receiverThread = new Thread JavaDoc() {
222             public void run() {
223                 while (isRunning) {
224                     receiveData();
225                 }
226             }
227         };
228         
229         receiverThread.setDaemon(true);
230         receiverThread.setName("MulticastReceiver#" + hashCode());
231         receiverThread.start();
232     }
233
234     
235     
236     private void receiveData() {
237         try {
238             byte[] buf = new byte[getReceiveSize()];
239             DatagramPacket JavaDoc dp = new DatagramPacket JavaDoc(buf, buf.length);
240             socket.receive(dp);
241             
242             ByteBuffer JavaDoc data = ByteBuffer.wrap(dp.getData());
243             data.limit(dp.getLength()); // handles if received byte size is smaller than predefined receive size
244

245             onData(new InetSocketAddress JavaDoc(dp.getAddress(), dp.getPort()), data);
246             
247         } catch(IOException JavaDoc e) {
248             if (!socket.isClosed()) {
249                 if (LOG.isLoggable(Level.FINE)) {
250                     LOG.fine("error occured by receiving data. Reason: " + e.toString());
251                 }
252             }
253         }
254     }
255     
256     
257     
258     /**
259      * {@inheritDoc}
260      */

261     @Override JavaDoc
262     public String JavaDoc toString() {
263         return multicastAddress.toString() + " (ID=" + getId() + ")";
264     }
265     
266     
267     /**
268      * {@inheritDoc}
269      */

270     public void close() {
271         if (isRunning) {
272             isRunning = false;
273             
274             try {
275                 socket.leaveGroup(multicastAddress.getAddress());
276                 socket.close();
277             } catch (Exception JavaDoc e) {
278                 if (LOG.isLoggable(Level.FINE)) {
279                     LOG.fine("error occured by closing multicast socket. Reason: " + e.toString());
280                 }
281             }
282             
283             super.close();
284         }
285     }
286     
287     
288     /**
289      * {@inheritDoc}
290      */

291     public SocketAddress JavaDoc getLocalSocketAddress() {
292         return multicastAddress;
293     }
294     
295     
296     /**
297      * {@inheritDoc}
298      */

299     public InetAddress JavaDoc getLocalAddress() {
300         return multicastAddress.getAddress();
301     }
302     
303     
304     /**
305      * {@inheritDoc}
306      */

307     public int getLocalPort() {
308         return multicastAddress.getPort();
309     }
310     
311     
312     /**
313      * {@inheritDoc}
314      */

315     public SocketAddress JavaDoc getRemoteSocketAddress() {
316         return multicastAddress;
317     }
318     
319     
320     /**
321      * {@inheritDoc}
322      */

323     public boolean isOpen() {
324         return !socket.isClosed();
325     }
326     
327     
328     /**
329      * {@inheritDoc}
330      */

331     public void send(UserDatagram packet) throws ClosedConnectionException, IOException JavaDoc {
332         if (LOG.isLoggable(Level.FINER)) {
333             LOG.finer("[" + "/:" + getLocalPort() + " " + getId() + "] sending datagram " + packet.toString());
334         }
335         
336         packet.prepareForSend();
337         
338         byte[] bytes = new byte[packet.getData().remaining()];
339         packet.getData().get(bytes);
340         DatagramPacket JavaDoc dataPacket = new DatagramPacket JavaDoc(bytes, bytes.length, multicastAddress);
341         socket.send(dataPacket);
342             
343         incNumberOfHandledOutgoingDatagram();
344     }
345     
346     
347     /**
348      * {@inheritDoc}
349      */

350     protected MulticastEndpoint setOption(String JavaDoc name, Object JavaDoc value) throws IOException JavaDoc {
351     
352         if (name.equals(IEndpoint.SO_SNDBUF)) {
353             socket.setSendBufferSize((Integer JavaDoc) value);
354             
355         } else if (name.equals(IEndpoint.SO_REUSEADDR)) {
356             socket.setReuseAddress((Boolean JavaDoc) value);
357             
358         } else if (name.equals(IEndpoint.SO_RCVBUF)) {
359             socket.setReceiveBufferSize((Integer JavaDoc) value);
360
361         } else if (name.equals(IEndpoint.IP_TOS)) {
362             socket.setTrafficClass((Integer JavaDoc) value);
363             
364         } else if (name.equals(IEndpoint.IP_MULTICAST_TTL)) {
365             socket.setTimeToLive((Integer JavaDoc) value);
366
367         } else if (name.equals(IEndpoint.IP_MULTICAST_LOOP)) {
368             socket.setLoopbackMode((Boolean JavaDoc) value);
369             
370         } else {
371             LOG.warning("option " + name + " is not supproted for " + this.getClass().getName());
372         }
373         
374         return this;
375     }
376     
377     /**
378      * {@inheritDoc}
379      */

380     public Object JavaDoc getOption(String JavaDoc name) throws IOException JavaDoc {
381
382         if (name.equals(IEndpoint.SO_SNDBUF)) {
383             return socket.getSendBufferSize();
384             
385         } else if (name.equals(IEndpoint.SO_REUSEADDR)) {
386             return socket.getReuseAddress();
387             
388         } else if (name.equals(IEndpoint.SO_RCVBUF)) {
389             return socket.getReceiveBufferSize();
390
391         } else if (name.equals(IEndpoint.IP_TOS)) {
392             return socket.getTrafficClass();
393             
394         } else if (name.equals(IEndpoint.IP_MULTICAST_TTL)) {
395             return socket.getTimeToLive();
396
397         } else if (name.equals(IEndpoint.IP_MULTICAST_LOOP)) {
398             return socket.getLoopbackMode();
399             
400         } else {
401             LOG.warning("option " + name + " is not supproted for " + this.getClass().getName());
402             return null;
403         }
404     }
405     
406     public Map JavaDoc<String JavaDoc, Class JavaDoc> getOptions() {
407         return Collections.unmodifiableMap(SUPPORTED_OPTIONS);
408     }
409 }
410
Popular Tags