1
2
3
4
5
6
7
8
9
10
11 package org.mule.transport.udp;
12
13 import org.mule.api.MuleEvent;
14 import org.mule.api.MuleException;
15 import org.mule.api.MuleMessage;
16 import org.mule.api.config.MuleProperties;
17 import org.mule.api.construct.FlowConstruct;
18 import org.mule.api.endpoint.InboundEndpoint;
19 import org.mule.api.lifecycle.CreateException;
20 import org.mule.api.lifecycle.Disposable;
21 import org.mule.api.transport.Connector;
22 import org.mule.api.transport.PropertyScope;
23 import org.mule.config.i18n.CoreMessages;
24 import org.mule.transport.AbstractMessageReceiver;
25 import org.mule.transport.ConnectException;
26 import org.mule.transport.udp.i18n.UdpMessages;
27
28 import java.io.IOException;
29 import java.net.DatagramPacket;
30 import java.net.DatagramSocket;
31 import java.net.InetAddress;
32 import java.net.SocketAddress;
33 import java.net.SocketTimeoutException;
34 import java.net.URI;
35 import java.net.UnknownHostException;
36 import java.util.List;
37
38 import javax.resource.spi.work.Work;
39 import javax.resource.spi.work.WorkException;
40 import javax.resource.spi.work.WorkManager;
41
42 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
43
44
45 public class UdpMessageReceiver extends AbstractMessageReceiver implements Work
46 {
47 protected DatagramSocket socket = null;
48 protected InetAddress inetAddress;
49 protected int bufferSize;
50 private URI uri;
51 protected List responseTransformers = null;
52
53 protected final AtomicBoolean disposing = new AtomicBoolean(false);
54
55 public UdpMessageReceiver(Connector connector, FlowConstruct flowConstruct, InboundEndpoint endpoint)
56 throws CreateException
57 {
58
59 super(connector, flowConstruct, endpoint);
60
61 bufferSize = ((UdpConnector) connector).getReceiveBufferSize();
62
63 uri = endpoint.getEndpointURI().getUri();
64
65 try
66 {
67 if (!"null".equalsIgnoreCase(uri.getHost()))
68 {
69 inetAddress = InetAddress.getByName(uri.getHost());
70 }
71 }
72 catch (UnknownHostException e)
73 {
74 throw new CreateException(UdpMessages.failedToLocateHost(uri), e, this);
75 }
76
77 responseTransformers = getResponseTransformers();
78 }
79
80 @Override
81 protected void doConnect() throws Exception
82 {
83 try
84 {
85 socket = ((UdpConnector) connector).getServerSocket(endpoint);
86 }
87 catch (Exception e)
88 {
89 throw new ConnectException(UdpMessages.failedToBind(uri), e, this);
90 }
91
92 try
93 {
94 getWorkManager().scheduleWork(this, WorkManager.INDEFINITE, null, connector);
95 }
96 catch (WorkException e)
97 {
98 throw new ConnectException(CoreMessages.failedToScheduleWork(), e, this);
99 }
100 }
101
102 @Override
103 protected void doDisconnect() throws Exception
104 {
105
106 disposing.set(true);
107 if (socket != null)
108 {
109 socket.close();
110 }
111
112 }
113
114 @Override
115 protected void doStart() throws MuleException
116 {
117
118 }
119
120 @Override
121 protected void doStop() throws MuleException
122 {
123
124 }
125
126 protected List getResponseTransformers()
127 {
128 List transformers = endpoint.getResponseTransformers();
129 if (transformers == null)
130 {
131 return connector.getDefaultResponseTransformers(endpoint);
132 }
133 return transformers;
134 }
135
136 protected DatagramSocket createSocket(URI uri, InetAddress inetAddress) throws IOException
137 {
138 return new DatagramSocket(uri.getPort(), inetAddress);
139 }
140
141
142 public DatagramSocket getSocket()
143 {
144 return socket;
145 }
146
147 protected DatagramPacket createPacket()
148 {
149 DatagramPacket packet = new DatagramPacket(new byte[bufferSize], bufferSize);
150
151
152
153
154
155 return packet;
156 }
157
158 public void run()
159 {
160 while (!disposing.get())
161 {
162 if (connector.isStarted())
163 {
164
165 try
166 {
167 DatagramPacket packet = createPacket();
168 try
169 {
170 if (logger.isDebugEnabled())
171 {
172 logger.debug("Receiving packet on " + uri);
173 }
174 socket.receive(packet);
175
176 if (logger.isTraceEnabled())
177 {
178 logger.trace("Received packet on: " + uri);
179 }
180
181 Work work = createWork(packet);
182 try
183 {
184 getWorkManager().scheduleWork(work, WorkManager.INDEFINITE, null, connector);
185 }
186 catch (WorkException e)
187 {
188 logger.error("Udp receiver interrupted: " + e.getMessage(), e);
189 }
190 }
191 catch (SocketTimeoutException e)
192 {
193
194 }
195
196 }
197 catch (Exception e)
198 {
199 if (!connector.isDisposed() && !disposing.get())
200 {
201 logger.debug("Accept failed on socket: " + e, e);
202 getConnector().getMuleContext().getExceptionListener().handleException(e);
203 }
204 }
205 }
206 }
207 }
208
209 public void release()
210 {
211 dispose();
212 }
213
214 @Override
215 protected void doDispose()
216 {
217 if (socket != null && !socket.isClosed())
218 {
219 logger.debug("Closing Udp connection: " + uri);
220 socket.close();
221 logger.info("Closed Udp connection: " + uri);
222 }
223 }
224
225 protected Work createWork(DatagramPacket packet) throws IOException
226 {
227 return new UdpWorker(new DatagramSocket(0), packet);
228 }
229
230 protected class UdpWorker implements Work, Disposable
231 {
232 private DatagramSocket socket = null;
233 private DatagramPacket packet;
234
235 public UdpWorker(DatagramSocket socket, DatagramPacket packet)
236 {
237 this.socket = socket;
238 this.packet = packet;
239 }
240
241 public void release()
242 {
243 dispose();
244 }
245
246 public void dispose()
247 {
248 if (socket != null && !socket.isClosed())
249 {
250 try
251 {
252 socket.close();
253 }
254 catch (Exception e)
255 {
256 logger.error("Socket close failed", e);
257 }
258 }
259 socket = null;
260 }
261
262
263 public void run()
264 {
265 MuleMessage returnMessage = null;
266 try
267 {
268 MuleMessage message = createMuleMessage(packet, endpoint.getEncoding());
269 final SocketAddress clientAddress = socket.getRemoteSocketAddress();
270 if (clientAddress != null)
271 {
272 message.setProperty(MuleProperties.MULE_REMOTE_CLIENT_ADDRESS, clientAddress, PropertyScope.INBOUND);
273 }
274 MuleEvent event = routeMessage(message);
275 returnMessage = event == null ? null : event.getMessage();
276
277 if (returnMessage != null)
278 {
279 byte[] data;
280 if (responseTransformers != null)
281 {
282 returnMessage.applyTransformers(event, responseTransformers);
283 Object response = returnMessage.getPayload();
284 if (response instanceof byte[])
285 {
286 data = (byte[]) response;
287 }
288 else
289 {
290 data = response.toString().getBytes();
291 }
292 }
293 else
294 {
295 data = returnMessage.getPayloadAsBytes();
296 }
297 DatagramPacket result = new DatagramPacket(data, data.length, packet.getAddress(),
298 packet.getPort());
299 socket.send(result);
300 }
301 }
302 catch (Exception e)
303 {
304 if (!disposing.get())
305 {
306 getConnector().getMuleContext().getExceptionListener().handleException(e);
307 }
308 }
309 finally
310 {
311 dispose();
312 }
313 }
314 }
315 }