1
2
3
4
5
6
7 package org.mule.transport.tcp;
8
9 import org.mule.api.MessagingException;
10 import org.mule.api.MuleContext;
11 import org.mule.api.MuleException;
12 import org.mule.api.MuleMessage;
13 import org.mule.api.endpoint.ImmutableEndpoint;
14 import org.mule.api.lifecycle.InitialisationException;
15 import org.mule.api.transport.Connector;
16 import org.mule.api.transport.MessageDispatcherFactory;
17 import org.mule.config.i18n.CoreMessages;
18 import org.mule.model.streaming.CallbackOutputStream;
19 import org.mule.transport.AbstractConnector;
20 import org.mule.transport.ConfigurableKeyedObjectPool;
21 import org.mule.transport.tcp.protocols.SafeProtocol;
22 import org.mule.util.concurrent.ThreadNameHelper;
23 import org.mule.util.monitor.ExpiryMonitor;
24
25 import java.io.BufferedOutputStream;
26 import java.io.DataOutputStream;
27 import java.io.IOException;
28 import java.io.OutputStream;
29 import java.net.ServerSocket;
30 import java.net.Socket;
31 import java.net.SocketException;
32 import java.net.URI;
33
34 import org.apache.commons.pool.impl.GenericKeyedObjectPool;
35
36
37
38
39
40
41
42 public class TcpConnector extends AbstractConnector
43 {
44 public static final String TCP = "tcp";
45
46
47 public static final String KEEP_SEND_SOCKET_OPEN_PROPERTY = "keepSendSocketOpen";
48 public static final int DEFAULT_SOCKET_TIMEOUT = INT_VALUE_NOT_SET;
49 public static final int DEFAULT_SO_LINGER = INT_VALUE_NOT_SET;
50 public static final int DEFAULT_BUFFER_SIZE = INT_VALUE_NOT_SET;
51 public static final int DEFAULT_BACKLOG = INT_VALUE_NOT_SET;
52 public static final int DEFAULT_WAIT_TIMEOUT = INT_VALUE_NOT_SET;
53
54
55 public static final boolean SERVER = false;
56 public static final boolean CLIENT = true;
57
58 private int clientSoTimeout = DEFAULT_SOCKET_TIMEOUT;
59 private int serverSoTimeout = DEFAULT_SOCKET_TIMEOUT;
60 private int socketMaxWait = DEFAULT_WAIT_TIMEOUT;
61 private int sendBufferSize = DEFAULT_BUFFER_SIZE;
62 private int receiveBufferSize = DEFAULT_BUFFER_SIZE;
63 private int receiveBacklog = DEFAULT_BACKLOG;
64 private boolean sendTcpNoDelay;
65 private Boolean reuseAddress = Boolean.TRUE;
66 private int socketSoLinger = DEFAULT_SO_LINGER;
67 private TcpProtocol tcpProtocol;
68 private AbstractTcpSocketFactory socketFactory;
69 private SimpleServerSocketFactory serverSocketFactory;
70 private GenericKeyedObjectPool socketsPool = new GenericKeyedObjectPool();
71 private int keepAliveTimeout = 0;
72 private ExpiryMonitor keepAliveMonitor;
73
74
75
76
77
78 private boolean keepSendSocketOpen = false;
79
80
81
82
83
84
85
86
87 private boolean keepAlive = false;
88
89
90 private TcpSocketKey lastSocketKey;
91
92 public TcpConnector(MuleContext context)
93 {
94 super(context);
95 setSocketFactory(new TcpSocketFactory());
96 setServerSocketFactory(new TcpServerSocketFactory());
97 setTcpProtocol(new SafeProtocol());
98 }
99
100 public void configureSocket(boolean client, Socket socket) throws SocketException
101 {
102
103
104
105 if (newValue(getReceiveBufferSize(), socket.getReceiveBufferSize()))
106 {
107 socket.setReceiveBufferSize(getReceiveBufferSize());
108 }
109 if (newValue(getSendBufferSize(), socket.getSendBufferSize()))
110 {
111 socket.setSendBufferSize(getSendBufferSize());
112 }
113 if (client)
114 {
115 if (newValue(getClientSoTimeout(), socket.getSoTimeout()))
116 {
117 socket.setSoTimeout(getClientSoTimeout());
118 }
119 }
120 else
121 {
122 if (newValue(getServerSoTimeout(), socket.getSoTimeout()))
123 {
124 socket.setSoTimeout(getServerSoTimeout());
125 }
126 }
127 if (newValue(getSocketSoLinger(), socket.getSoLinger()))
128 {
129 socket.setSoLinger(true, getSocketSoLinger());
130 }
131 try
132 {
133 socket.setTcpNoDelay(isSendTcpNoDelay());
134 }
135 catch (SocketException e)
136 {
137
138 }
139 socket.setKeepAlive(isKeepAlive());
140 }
141
142 private boolean newValue(int parameter, int socketValue)
143 {
144 return parameter != Connector.INT_VALUE_NOT_SET && parameter != socketValue;
145 }
146
147 @Override
148 protected void doInitialise() throws InitialisationException
149 {
150 socketsPool.setFactory(getSocketFactory());
151 socketsPool.setTestOnBorrow(true);
152 socketsPool.setTestOnReturn(true);
153 socketsPool.setMaxActive(getDispatcherThreadingProfile().getMaxThreadsActive());
154 socketsPool.setMaxIdle(getDispatcherThreadingProfile().getMaxThreadsIdle());
155 socketsPool.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_BLOCK);
156 socketsPool.setMaxWait(socketMaxWait);
157
158
159
160 final String monitorName = String.format("%s%s.socket",
161 ThreadNameHelper.getPrefix(muleContext),
162 getName());
163 keepAliveMonitor = new ExpiryMonitor(monitorName, 1000, this.getClass().getClassLoader());
164 }
165
166 @Override
167 protected void doDispose()
168 {
169 logger.debug("Closing TCP connector");
170 try
171 {
172 socketsPool.close();
173 }
174 catch (Exception e)
175 {
176 logger.warn("Failed to close dispatcher socket pool: " + e.getMessage());
177 }
178
179 keepAliveMonitor.dispose();
180 }
181
182
183
184
185
186 protected Socket getSocket(ImmutableEndpoint endpoint) throws Exception
187 {
188 TcpSocketKey socketKey = new TcpSocketKey(endpoint);
189 if (logger.isDebugEnabled())
190 {
191 logger.debug("borrowing socket for " + socketKey + "/" + socketKey.hashCode());
192 if (null != lastSocketKey)
193 {
194 logger.debug("same as " + lastSocketKey.hashCode() + "? " + lastSocketKey.equals(socketKey));
195 }
196 }
197 Socket socket = (Socket) socketsPool.borrowObject(socketKey);
198 if (logger.isDebugEnabled())
199 {
200 logger.debug("borrowed socket, "
201 + (socket.isClosed() ? "closed" : "open")
202 + "; debt " + socketsPool.getNumActive());
203 }
204 return socket;
205 }
206
207 void releaseSocket(Socket socket, ImmutableEndpoint endpoint) throws Exception
208 {
209 TcpSocketKey socketKey = new TcpSocketKey(endpoint);
210 lastSocketKey = socketKey;
211 socketsPool.returnObject(socketKey, socket);
212 if (logger.isDebugEnabled())
213 {
214 logger.debug("returning socket for " + socketKey.hashCode());
215 logger.debug("returned socket; debt " + socketsPool.getNumActive());
216 }
217 }
218
219 public OutputStream getOutputStream(final ImmutableEndpoint endpoint, MuleMessage message)
220 throws MuleException
221 {
222 final Socket socket;
223 try
224 {
225 socket = getSocket(endpoint);
226 }
227 catch (Exception e)
228 {
229 throw new MessagingException(CoreMessages.failedToGetOutputStream(), message, e);
230 }
231 if (socket == null)
232 {
233
234 throw new IllegalStateException("could not get socket for endpoint: "
235 + endpoint.getEndpointURI().getAddress());
236 }
237 try
238 {
239 return new CallbackOutputStream(
240 new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())),
241 new CallbackOutputStream.Callback()
242 {
243 public void onClose() throws Exception
244 {
245 releaseSocket(socket, endpoint);
246 }
247 });
248 }
249 catch (IOException e)
250 {
251 throw new MessagingException(CoreMessages.failedToGetOutputStream(), message, e);
252 }
253 }
254
255 @Override
256 protected void doConnect() throws Exception
257 {
258
259 }
260
261 @Override
262 protected void doDisconnect() throws Exception
263 {
264 socketsPool.clear();
265 }
266
267 @Override
268 protected void doStart() throws MuleException
269 {
270
271 }
272
273 @Override
274 protected void doStop() throws MuleException
275 {
276
277 }
278
279 public String getProtocol()
280 {
281 return TCP;
282 }
283
284
285
286 public boolean isKeepSendSocketOpen()
287 {
288 return keepSendSocketOpen;
289 }
290
291 public void setKeepSendSocketOpen(boolean keepSendSocketOpen)
292 {
293 this.keepSendSocketOpen = keepSendSocketOpen;
294 }
295
296
297
298
299
300
301 @Deprecated
302 public void setTimeout(int timeout)
303 {
304 setClientSoTimeout(timeout);
305 setServerSoTimeout(timeout);
306 }
307
308 public int getClientSoTimeout()
309 {
310 return this.clientSoTimeout;
311 }
312
313 public void setClientSoTimeout(int timeout)
314 {
315 this.clientSoTimeout = valueOrDefault(timeout, 0, DEFAULT_SOCKET_TIMEOUT);
316 }
317
318 public int getServerSoTimeout()
319 {
320 return serverSoTimeout;
321 }
322
323 public void setServerSoTimeout(int timeout)
324 {
325 this.serverSoTimeout = valueOrDefault(timeout, 0, DEFAULT_SOCKET_TIMEOUT);
326 }
327
328 public int getSocketMaxWait()
329 {
330 return socketMaxWait;
331 }
332
333 public void setSocketMaxWait(int timeout)
334 {
335 this.socketMaxWait = valueOrDefault(timeout, 0, DEFAULT_WAIT_TIMEOUT);
336 }
337
338
339 @Deprecated
340 public int getBufferSize()
341 {
342 return sendBufferSize;
343 }
344
345
346 @Deprecated
347 public void setBufferSize(int bufferSize)
348 {
349 sendBufferSize = valueOrDefault(bufferSize, 1, DEFAULT_BUFFER_SIZE);
350 }
351
352 public int getSendBufferSize()
353 {
354 return sendBufferSize;
355 }
356
357 public void setSendBufferSize(int bufferSize)
358 {
359 sendBufferSize = valueOrDefault(bufferSize, 1, DEFAULT_BUFFER_SIZE);
360 }
361
362 public int getReceiveBufferSize()
363 {
364 return receiveBufferSize;
365 }
366
367 public void setReceiveBufferSize(int bufferSize)
368 {
369 receiveBufferSize = valueOrDefault(bufferSize, 1, DEFAULT_BUFFER_SIZE);
370 }
371
372 public int getReceiveBacklog()
373 {
374 return receiveBacklog;
375 }
376
377 public void setReceiveBacklog(int receiveBacklog)
378 {
379 this.receiveBacklog = valueOrDefault(receiveBacklog, 0, DEFAULT_BACKLOG);
380 }
381
382 public int getSocketSoLinger()
383 {
384 return socketSoLinger;
385 }
386
387 public void setSocketSoLinger(int soLinger)
388 {
389 this.socketSoLinger = valueOrDefault(soLinger, 0, INT_VALUE_NOT_SET);
390 }
391
392
393
394
395 @Deprecated
396 public int getBacklog()
397 {
398 return receiveBacklog;
399 }
400
401
402
403
404
405 @Deprecated
406 public void setBacklog(int backlog)
407 {
408 this.receiveBacklog = backlog;
409 }
410
411 public TcpProtocol getTcpProtocol()
412 {
413 return tcpProtocol;
414 }
415
416 public void setTcpProtocol(TcpProtocol tcpProtocol)
417 {
418 this.tcpProtocol = tcpProtocol;
419 }
420
421 @Override
422 public boolean isResponseEnabled()
423 {
424 return true;
425 }
426
427 public boolean isKeepAlive()
428 {
429 return keepAlive;
430 }
431
432 public void setKeepAlive(boolean keepAlive)
433 {
434 this.keepAlive = keepAlive;
435 }
436
437 public boolean isSendTcpNoDelay()
438 {
439 return sendTcpNoDelay;
440 }
441
442 public void setSendTcpNoDelay(boolean sendTcpNoDelay)
443 {
444 this.sendTcpNoDelay = sendTcpNoDelay;
445 }
446
447 protected void setSocketFactory(AbstractTcpSocketFactory socketFactory)
448 {
449 this.socketFactory = socketFactory;
450 }
451
452 protected AbstractTcpSocketFactory getSocketFactory()
453 {
454 return socketFactory;
455 }
456
457 public SimpleServerSocketFactory getServerSocketFactory()
458 {
459 return serverSocketFactory;
460 }
461
462 public void setServerSocketFactory(SimpleServerSocketFactory serverSocketFactory)
463 {
464 this.serverSocketFactory = serverSocketFactory;
465 }
466
467 protected ServerSocket getServerSocket(URI uri) throws IOException
468 {
469 return getServerSocketFactory().createServerSocket(uri, getReceiveBacklog(), isReuseAddress());
470 }
471
472 private static int valueOrDefault(int value, int threshhold, int deflt)
473 {
474 if (value < threshhold)
475 {
476 return deflt;
477 }
478 else
479 {
480 return value;
481 }
482 }
483
484
485
486
487 public Boolean isReuseAddress()
488 {
489 return reuseAddress;
490 }
491
492
493
494
495
496
497 public void setReuseAddress(Boolean reuseAddress)
498 {
499 this.reuseAddress = reuseAddress;
500 }
501
502 public ExpiryMonitor getKeepAliveMonitor()
503 {
504 return keepAliveMonitor;
505 }
506
507
508
509
510 public int getKeepAliveTimeout()
511 {
512 return keepAliveTimeout;
513 }
514
515
516
517
518 public void setKeepAliveTimeout(int keepAliveTimeout)
519 {
520 this.keepAliveTimeout = keepAliveTimeout;
521 }
522
523 @Override
524 public void setDispatcherFactory(MessageDispatcherFactory dispatcherFactory)
525 {
526 if (this.dispatcherFactory == null) {
527 super.setDispatcherFactory(dispatcherFactory);
528 }
529 }
530
531 public ConfigurableKeyedObjectPool getDispatchers()
532 {
533 return dispatchers;
534 }
535
536 public int getSocketsPoolMaxActive()
537 {
538 return socketsPool.getMaxActive();
539 }
540
541 public int getSocketsPoolMaxIdle()
542 {
543 return socketsPool.getMaxIdle();
544 }
545
546 public int getSocketsPoolNumActive()
547 {
548 return socketsPool.getNumActive();
549 }
550
551 public long getSocketsPoolMaxWait()
552 {
553 return socketsPool.getMaxWait();
554 }
555
556 }