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