1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.fourthline.cling.transport.impl;
17
18 import org.fourthline.cling.transport.Router;
19 import org.fourthline.cling.transport.spi.DatagramProcessor;
20 import org.fourthline.cling.transport.spi.InitializationException;
21 import org.fourthline.cling.transport.spi.MulticastReceiver;
22 import org.fourthline.cling.model.UnsupportedDataException;
23 import org.fourthline.cling.transport.spi.NetworkAddressFactory;
24
25 import java.net.DatagramPacket;
26 import java.net.Inet6Address;
27 import java.net.InetAddress;
28 import java.net.InetSocketAddress;
29 import java.net.MulticastSocket;
30 import java.net.NetworkInterface;
31 import java.net.SocketException;
32 import java.util.logging.Logger;
33
34
35
36
37
38
39
40
41
42 public class MulticastReceiverImpl implements MulticastReceiver<MulticastReceiverConfigurationImpl> {
43
44 private static Logger log = Logger.getLogger(MulticastReceiver.class.getName());
45
46 final protected MulticastReceiverConfigurationImpl configuration;
47
48 protected Router router;
49 protected NetworkAddressFactory networkAddressFactory;
50 protected DatagramProcessor datagramProcessor;
51
52 protected NetworkInterface multicastInterface;
53 protected InetSocketAddress multicastAddress;
54 protected MulticastSocket socket;
55
56 public MulticastReceiverImpl(MulticastReceiverConfigurationImpl configuration) {
57 this.configuration = configuration;
58 }
59
60 public MulticastReceiverConfigurationImpl getConfiguration() {
61 return configuration;
62 }
63
64 synchronized public void init(NetworkInterface networkInterface,
65 Router router,
66 NetworkAddressFactory networkAddressFactory,
67 DatagramProcessor datagramProcessor) throws InitializationException {
68
69 this.router = router;
70 this.networkAddressFactory = networkAddressFactory;
71 this.datagramProcessor = datagramProcessor;
72 this.multicastInterface = networkInterface;
73
74 try {
75
76 log.info("Creating wildcard socket (for receiving multicast datagrams) on port: " + configuration.getPort());
77 multicastAddress = new InetSocketAddress(configuration.getGroup(), configuration.getPort());
78
79 socket = new MulticastSocket(configuration.getPort());
80 socket.setReuseAddress(true);
81 socket.setReceiveBufferSize(32768);
82
83 log.info("Joining multicast group: " + multicastAddress + " on network interface: " + multicastInterface.getDisplayName());
84 socket.joinGroup(multicastAddress, multicastInterface);
85
86 } catch (Exception ex) {
87 throw new InitializationException("Could not initialize " + getClass().getSimpleName() + ": " + ex);
88 }
89 }
90
91 synchronized public void stop() {
92 if (socket != null && !socket.isClosed()) {
93 try {
94 log.fine("Leaving multicast group");
95 socket.leaveGroup(multicastAddress, multicastInterface);
96
97 } catch (Exception ex) {
98 log.fine("Could not leave multicast group: " + ex);
99 }
100
101 socket.close();
102 }
103 }
104
105 public void run() {
106
107 log.fine("Entering blocking receiving loop, listening for UDP datagrams on: " + socket.getLocalAddress());
108 while (true) {
109
110 try {
111 byte[] buf = new byte[getConfiguration().getMaxDatagramBytes()];
112 DatagramPacket datagram = new DatagramPacket(buf, buf.length);
113
114 socket.receive(datagram);
115
116 InetAddress receivedOnLocalAddress =
117 networkAddressFactory.getLocalAddress(
118 multicastInterface,
119 multicastAddress.getAddress() instanceof Inet6Address,
120 datagram.getAddress()
121 );
122
123 log.fine(
124 "UDP datagram received from: " + datagram.getAddress().getHostAddress()
125 + ":" + datagram.getPort()
126 + " on local interface: " + multicastInterface.getDisplayName()
127 + " and address: " + receivedOnLocalAddress.getHostAddress()
128 );
129
130 router.received(datagramProcessor.read(receivedOnLocalAddress, datagram));
131
132 } catch (SocketException ex) {
133 log.fine("Socket closed");
134 break;
135 } catch (UnsupportedDataException ex) {
136 log.info("Could not read datagram: " + ex.getMessage());
137 } catch (Exception ex) {
138 throw new RuntimeException(ex);
139 }
140 }
141 try {
142 if (!socket.isClosed()) {
143 log.fine("Closing multicast socket");
144 socket.close();
145 }
146 } catch (Exception ex) {
147 throw new RuntimeException(ex);
148 }
149 }
150
151
152 }
153