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