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.model.message.OutgoingDatagramMessage;
19 import org.fourthline.cling.transport.Router;
20 import org.fourthline.cling.transport.spi.DatagramIO;
21 import org.fourthline.cling.transport.spi.DatagramProcessor;
22 import org.fourthline.cling.transport.spi.InitializationException;
23 import org.fourthline.cling.model.UnsupportedDataException;
24
25 import java.net.DatagramPacket;
26 import java.net.InetAddress;
27 import java.net.InetSocketAddress;
28 import java.net.MulticastSocket;
29 import java.net.SocketException;
30 import java.util.logging.Level;
31 import java.util.logging.Logger;
32
33
34
35
36
37
38
39
40
41
42
43
44
45 public class DatagramIOImpl implements DatagramIO<DatagramIOConfigurationImpl> {
46
47 private static Logger log = Logger.getLogger(DatagramIO.class.getName());
48
49
50
51
52
53
54
55
56
57
58 final protected DatagramIOConfigurationImpl configuration;
59
60 protected Router router;
61 protected DatagramProcessor datagramProcessor;
62
63 protected InetSocketAddress localAddress;
64 protected MulticastSocket socket;
65
66 public DatagramIOImpl(DatagramIOConfigurationImpl configuration) {
67 this.configuration = configuration;
68 }
69
70 public DatagramIOConfigurationImpl getConfiguration() {
71 return configuration;
72 }
73
74 synchronized public void init(InetAddress bindAddress, Router router, DatagramProcessor datagramProcessor) throws InitializationException {
75
76 this.router = router;
77 this.datagramProcessor = datagramProcessor;
78
79 try {
80
81
82
83
84 log.info("Creating bound socket (for datagram input/output) on: " + bindAddress);
85 localAddress = new InetSocketAddress(bindAddress, 0);
86 socket = new MulticastSocket(localAddress);
87 socket.setTimeToLive(configuration.getTimeToLive());
88 socket.setReceiveBufferSize(262144);
89 } catch (Exception ex) {
90 throw new InitializationException("Could not initialize " + getClass().getSimpleName() + ": " + ex);
91 }
92 }
93
94 synchronized public void stop() {
95 if (socket != null && !socket.isClosed()) {
96 socket.close();
97 }
98 }
99
100 public void run() {
101 log.fine("Entering blocking receiving loop, listening for UDP datagrams on: " + socket.getLocalAddress());
102
103 while (true) {
104
105 try {
106 byte[] buf = new byte[getConfiguration().getMaxDatagramBytes()];
107 DatagramPacket datagram = new DatagramPacket(buf, buf.length);
108
109 socket.receive(datagram);
110
111 log.fine(
112 "UDP datagram received from: "
113 + datagram.getAddress().getHostAddress()
114 + ":" + datagram.getPort()
115 + " on: " + localAddress
116 );
117
118
119 router.received(datagramProcessor.read(localAddress.getAddress(), datagram));
120
121 } catch (SocketException ex) {
122 log.fine("Socket closed");
123 break;
124 } catch (UnsupportedDataException ex) {
125 log.info("Could not read datagram: " + ex.getMessage());
126 } catch (Exception ex) {
127 throw new RuntimeException(ex);
128 }
129 }
130 try {
131 if (!socket.isClosed()) {
132 log.fine("Closing unicast socket");
133 socket.close();
134 }
135 } catch (Exception ex) {
136 throw new RuntimeException(ex);
137 }
138 }
139
140 synchronized public void send(OutgoingDatagramMessage message) {
141 if (log.isLoggable(Level.FINE)) {
142 log.fine("Sending message from address: " + localAddress);
143 }
144 DatagramPacket packet = datagramProcessor.write(message);
145
146 if (log.isLoggable(Level.FINE)) {
147 log.fine("Sending UDP datagram packet to: " + message.getDestinationAddress() + ":" + message.getDestinationPort());
148 }
149
150 send(packet);
151 }
152
153 synchronized public void send(DatagramPacket datagram) {
154 if (log.isLoggable(Level.FINE)) {
155 log.fine("Sending message from address: " + localAddress);
156 }
157
158 try {
159 socket.send(datagram);
160 } catch (SocketException ex) {
161 log.fine("Socket closed, aborting datagram send to: " + datagram.getAddress());
162 } catch (RuntimeException ex) {
163 throw ex;
164 } catch (Exception ex) {
165 log.log(Level.SEVERE, "Exception sending datagram to: " + datagram.getAddress() + ": " + ex, ex);
166 }
167 }
168 }