INT-1822 Add Attribute to Suppress Reverse DNS Lokup

This commit is contained in:
Gary Russell
2011-03-04 18:53:51 -05:00
parent 5e02a7e63b
commit 9a5c26581b
22 changed files with 167 additions and 77 deletions

View File

@@ -123,6 +123,13 @@
check-length="true" />]]></programlisting>
A basic multicast inbound udp channel adapter.
</para>
<para>
By default, reverse DNS lookups are done on inbound packets to convert IP addresses to
hostnames for use in message headers.
In environments where DNS is not configured, this can cause delays.
This default behavior can be overridden by setting the <literal>lookup-host</literal>
attribute to "false".
</para>
</section>
<section id="connection-factories">
<title>TCP Connection Factories</title>
@@ -306,6 +313,13 @@
For full details of the attributes available on connection factories, see the
reference at the end of this section.
</para>
<para>
By default, reverse DNS lookups are done on inbound packets to convert IP addresses to
hostnames for use in message headers.
In environments where DNS is not configured, this can cause connection delays.
This default behavior can be overridden by setting the <literal>lookup-host</literal>
attribute to "false".
</para>
</section>
<section id="ip-interceptors">
<title>Tcp Connection Interceptors</title>
@@ -782,6 +796,16 @@
However, pool-size is also used for the server socket backlog,
regardless of whether an external task executor is used. Defaults to 5.</entry>
</row>
<row>
<entry>lookup-host</entry>
<entry>Y</entry>
<entry>Y</entry>
<entry>true, false</entry>
<entry>
Specifies whether reverse lookups are done on IP addresses to convert to host names
for use in message headers. If false, the IP address is used instead. Defaults to true.
</entry>
</row>
<row>
<entry>interceptor-factory-chain</entry>
<entry>Y</entry>
@@ -885,6 +909,14 @@
component, the MessagingException message containing the exception
and failed message is sent to this channel.</entry>
</row>
<row>
<entry>lookup-host</entry>
<entry>true, false</entry>
<entry>
Specifies whether reverse lookups are done on IP addresses to convert to host names
for use in message headers. If false, the IP address is used instead. Defaults to true.
</entry>
</row>
</tbody>
</tgroup>
</table>

View File

@@ -104,6 +104,8 @@ public abstract class IpAdapterParserUtils {
public static final String REPLY_TIMEOUT = "reply-timeout";
public static final String REPLY_CHANNEL = "reply-channel";
public static final String LOOKUP_HOST = "lookup-host";
/**

View File

@@ -92,6 +92,8 @@ public class TcpConnectionParser extends AbstractBeanDefinitionParser {
IpAdapterParserUtils.SINGLE_USE);
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element,
IpAdapterParserUtils.INTERCEPTOR_FACTORY_CHAIN);
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
IpAdapterParserUtils.LOOKUP_HOST);
return builder.getBeanDefinition();
}

View File

@@ -47,6 +47,8 @@ public class UdpInboundChannelAdapterParser extends AbstractChannelAdapterParser
element, "error-channel", "errorChannel");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element,
IpAdapterParserUtils.TASK_EXECUTOR);
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
IpAdapterParserUtils.LOOKUP_HOST);
return builder.getBeanDefinition();
}

View File

@@ -86,9 +86,11 @@ public abstract class AbstractConnectionFactory
protected int poolSize = 5;
protected boolean active;
protected volatile boolean active;
protected TcpConnectionInterceptorFactoryChain interceptorFactoryChain;
private boolean lookupHost = true;
/**
* Sets socket attributes on the socket.
@@ -305,6 +307,22 @@ public abstract class AbstractConnectionFactory
this.interceptorFactoryChain = interceptorFactoryChain;
}
/**
* If true, DNS reverse lookup is done on the remote ip address.
* Default true.
* @param lookupHost the lookupHost to set
*/
public void setLookupHost(boolean lookupHost) {
this.lookupHost = lookupHost;
}
/**
* @return the lookupHost
*/
public boolean isLookupHost() {
return lookupHost;
}
/**
* Closes the server.
*/

View File

@@ -70,13 +70,26 @@ public abstract class AbstractTcpConnection implements TcpConnection {
private String hostAddress = "unknown";
public AbstractTcpConnection(Socket socket, boolean server) {
private int port;
private final boolean lookupHost;
private int hashCode;
public AbstractTcpConnection(Socket socket, boolean server, boolean lookupHost) {
this.server = server;
this.lookupHost = lookupHost;
this.hashCode = socket.hashCode();
InetAddress inetAddress = socket.getInetAddress();
if (inetAddress != null) {
this.hostAddress = inetAddress.getHostAddress();
this.hostName = inetAddress.getHostName();
if (this.lookupHost) {
this.hostName = inetAddress.getHostName();
} else {
this.hostName = this.hostAddress;
}
}
this.connectionId = this.hostName + ":" + this.port + ":" + this.hashCode;
try {
this.soLinger = socket.getSoLinger();
} catch (SocketException e) { }
@@ -239,5 +252,8 @@ public abstract class AbstractTcpConnection implements TcpConnection {
return this.hostName;
}
public String getConnectionId() {
return this.connectionId;
}
}

View File

@@ -50,7 +50,7 @@ public class TcpNetClientConnectionFactory extends
logger.debug("Opening new socket connection to " + this.host + ":" + this.port);
Socket socket = SocketFactory.getDefault().createSocket(this.host, this.port);
setSocketAttributes(socket);
TcpConnection connection = new TcpNetConnection(socket, false);
TcpConnection connection = new TcpNetConnection(socket, false, this.isLookupHost());
connection = wrapConnection(connection);
initializeConnection(connection, socket);
this.taskExecutor.execute(connection);

View File

@@ -16,14 +16,12 @@
package org.springframework.integration.ip.tcp.connection;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import org.springframework.core.serializer.Deserializer;
import org.springframework.integration.Message;
import org.springframework.integration.ip.tcp.serializer.SoftEndOfStreamException;
import org.springframework.integration.ip.util.SocketUtils;
/**
* A TcpConnection that uses and underlying {@link Socket}.
@@ -44,10 +42,9 @@ public class TcpNetConnection extends AbstractTcpConnection {
* @param server if true this connection was created as
* a result of an incoming request.
*/
public TcpNetConnection(Socket socket, boolean server) {
super(socket, server);
public TcpNetConnection(Socket socket, boolean server, boolean lookupHost) {
super(socket, server, lookupHost);
this.socket = socket;
getConnectionId();
}
/**
@@ -162,12 +159,4 @@ public class TcpNetConnection extends AbstractTcpConnection {
}
}
public String getConnectionId() {
if (this.connectionId == null) {
this.connectionId = SocketUtils.getSocketId(this.socket);
}
return this.connectionId;
}
}

View File

@@ -72,7 +72,7 @@ public class TcpNetServerConnectionFactory extends AbstractServerConnectionFacto
final Socket socket = serverSocket.accept();
logger.debug("Accepted connection from " + socket.getInetAddress().getHostAddress());
setSocketAttributes(socket);
TcpConnection connection = new TcpNetConnection(socket, true);
TcpConnection connection = new TcpNetConnection(socket, true, this.isLookupHost());
connection = wrapConnection(connection);
this.initializeConnection(connection, socket);
this.taskExecutor.execute(connection);

View File

@@ -78,7 +78,7 @@ public class TcpNioClientConnectionFactory extends
logger.debug("Opening new socket channel connection to " + this.host + ":" + this.port);
SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(this.host, this.port));
setSocketAttributes(socketChannel.socket());
TcpNioConnection connection = new TcpNioConnection(socketChannel, false);
TcpNioConnection connection = new TcpNioConnection(socketChannel, false, this.isLookupHost());
connection.setUsingDirectBuffers(this.usingDirectBuffers);
if (this.taskExecutor == null) {
connection.setTaskExecutor(Executors.newSingleThreadExecutor());

View File

@@ -32,7 +32,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.springframework.integration.Message;
import org.springframework.integration.ip.tcp.serializer.SoftEndOfStreamException;
import org.springframework.integration.ip.util.SocketUtils;
/**
* A TcpConnection that uses and underlying {@link SocketChannel}.
@@ -71,16 +70,12 @@ public class TcpNioConnection extends AbstractTcpConnection {
* @param server if true this connection was created as
* a result of an incoming request.
*/
public TcpNioConnection(SocketChannel socketChannel, boolean server) throws Exception {
super(socketChannel.socket(), server);
public TcpNioConnection(SocketChannel socketChannel, boolean server, boolean lookupHost) throws Exception {
super(socketChannel.socket(), server, lookupHost);
this.socketChannel = socketChannel;
this.pipedInputStream = new PipedInputStream();
this.pipedOutputStream = new PipedOutputStream(this.pipedInputStream);
this.channelOutputStream = new ChannelOutputStream();
getConnectionId();
if (this.connectionId == null) {
throw new Exception("Null id");
}
}
public void close() {
@@ -338,13 +333,6 @@ public class TcpNioConnection extends AbstractTcpConnection {
this.usingDirectBuffers = usingDirectBuffers;
}
public String getConnectionId() {
if (this.connectionId == null) {
this.connectionId = SocketUtils.getSocketId(this.socketChannel.socket());
}
return this.connectionId;
}
/**
*
* @return Time of last read.

View File

@@ -142,7 +142,7 @@ public class TcpNioServerConnectionFactory extends AbstractServerConnectionFacto
private TcpNioConnection createTcpNioConnection(SocketChannel socketChannel) {
try {
TcpNioConnection connection = new TcpNioConnection(socketChannel, true);
TcpNioConnection connection = new TcpNioConnection(socketChannel, true, this.isLookupHost());
connection.setUsingDirectBuffers(this.usingDirectBuffers);
TcpConnection wrappedConnection = wrapConnection(connection);
this.initializeConnection(wrappedConnection, socketChannel.socket());

View File

@@ -66,6 +66,8 @@ public class DatagramPacketMessageMapper implements InboundMessageMapper<Datagra
private boolean lengthCheck = false;
private boolean lookupHost = true;
private static Pattern udpHeadersPattern =
Pattern.compile(RegexUtils.escapeRegexSpecials(IpHeaders.ACK_ADDRESS) +
"=" + "([^;]*);" +
@@ -89,6 +91,13 @@ public class DatagramPacketMessageMapper implements InboundMessageMapper<Datagra
this.lengthCheck = lengthCheck;
}
/**
* @param lookupHost the lookupHost to set
*/
public void setLookupHost(boolean lookupHost) {
this.lookupHost = lookupHost;
}
/**
* Raw byte[] from message, possibly with a length field up front.
*/
@@ -174,6 +183,13 @@ public class DatagramPacketMessageMapper implements InboundMessageMapper<Datagra
offset += 4;
length -= 4;
}
String hostAddress = packet.getAddress().getHostAddress();
String hostName;
if (this.lookupHost) {
hostName = packet.getAddress().getHostName();
} else {
hostName = hostAddress;
}
// Peek at the message in case they didn't configure us for ack but the sending
// side expects it.
if (this.acknowledge || startsWith(buffer, IpHeaders.ACK_ADDRESS)) {
@@ -188,8 +204,8 @@ public class DatagramPacketMessageMapper implements InboundMessageMapper<Datagra
message = MessageBuilder.withPayload(payload)
.setHeader(IpHeaders.ACK_ID, UUID.fromString(matcher.group(2)))
.setHeader(IpHeaders.ACK_ADDRESS, matcher.group(1))
.setHeader(IpHeaders.HOSTNAME, packet.getAddress().getHostName())
.setHeader(IpHeaders.IP_ADDRESS, packet.getAddress().getHostAddress())
.setHeader(IpHeaders.HOSTNAME, hostName)
.setHeader(IpHeaders.IP_ADDRESS, hostAddress)
.build();
} // on no match, just treat as simple payload
}
@@ -202,8 +218,8 @@ public class DatagramPacketMessageMapper implements InboundMessageMapper<Datagra
System.arraycopy(packet.getData(), offset, payload, 0, length);
if (payload.length > 0) {
message = MessageBuilder.withPayload(payload)
.setHeader(IpHeaders.HOSTNAME, packet.getAddress().getHostName())
.setHeader(IpHeaders.IP_ADDRESS, packet.getAddress().getHostAddress())
.setHeader(IpHeaders.HOSTNAME, hostName)
.setHeader(IpHeaders.IP_ADDRESS, hostAddress)
.build();
}
}

View File

@@ -189,7 +189,7 @@ public class UnicastReceivingChannelAdapter extends AbstractInternetProtocolRece
super.doStop();
try {
this.socket.close();
socket = null;
this.socket = null;
}
catch (Exception e) {
// ignore
@@ -200,6 +200,10 @@ public class UnicastReceivingChannelAdapter extends AbstractInternetProtocolRece
this.soSendBufferSize = soSendBufferSize;
}
public void setLookupHost(boolean lookupHost) {
this.mapper.setLookupHost(lookupHost);
}
public String getComponentType(){
return "ip:udp-inbound-channel-adapter";
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.ip.util;
import java.net.InetAddress;
import java.net.Socket;
/**
* @author Gary Russell
* @since 2.0
*/
public abstract class SocketUtils {
public static String getSocketId(Socket socket) {
InetAddress inetAddress = socket.getInetAddress();
String hostName = "";
if (inetAddress != null) {
hostName = inetAddress.getHostName();
}
return hostName + ":" + socket.getPort() + ":" + socket.hashCode();
}
}

View File

@@ -62,6 +62,14 @@ its configuration specifies the number of threads.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="lookup-host" type="xsd:string" >
<xsd:annotation>
<xsd:documentation>
Whether or not to do a DNS reverse-lookup on the remote ip address to insert the host name into the
message headers (ip_hostName). Default "true".
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
@@ -385,6 +393,14 @@ its configuration specifies the number of threads.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="lookup-host" type="xsd:string" >
<xsd:annotation>
<xsd:documentation>
Whether or not to do a DNS reverse-lookup on the remote ip address to insert the host name into the
message headers (ip_connectionId, ip_hostName). Default "true".
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="interceptor-factory-chain" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>

View File

@@ -30,6 +30,7 @@
local-address="127.0.0.1"
task-executor="externalTE"
error-channel="errorChannel"
lookup-host="false"
/>
<ip:udp-inbound-channel-adapter id="testInUdpMulticast"
@@ -49,6 +50,7 @@
<ip:tcp-connection-factory id="cfS1"
type="server"
port="#{tcpIpUtils.findAvailableServerSocket(5200)}"
lookup-host="false"
/>
<ip:tcp-inbound-channel-adapter id="testInTcp"
@@ -95,6 +97,7 @@
type="client"
port="#{tcpIpUtils.findAvailableServerSocket(5700)}"
host="localhost"
lookup-host="false"
/>
<ip:tcp-outbound-channel-adapter id="testOutTcpNio"

View File

@@ -17,6 +17,7 @@
package org.springframework.integration.ip.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
@@ -178,6 +179,9 @@ public class ParserUnitTests {
assertEquals("127.0.0.1", dfa.getPropertyValue("localAddress"));
assertSame(taskExecutor, dfa.getPropertyValue("taskExecutor"));
assertEquals(errorChannel, dfa.getPropertyValue("errorChannel"));
DatagramPacketMessageMapper mapper = (DatagramPacketMessageMapper) dfa.getPropertyValue("mapper");
DirectFieldAccessor mapperAccessor = new DirectFieldAccessor(mapper);
assertFalse((Boolean)mapperAccessor.getPropertyValue("lookupHost"));
}
@Test
@@ -193,6 +197,9 @@ public class ParserUnitTests {
assertEquals("127.0.0.1", dfa.getPropertyValue("localAddress"));
assertNotSame(taskExecutor, dfa.getPropertyValue("taskExecutor"));
assertNull(dfa.getPropertyValue("errorChannel"));
DatagramPacketMessageMapper mapper = (DatagramPacketMessageMapper) dfa.getPropertyValue("mapper");
DirectFieldAccessor mapperAccessor = new DirectFieldAccessor(mapper);
assertTrue((Boolean)mapperAccessor.getPropertyValue("lookupHost"));
}
@Test
@@ -202,6 +209,7 @@ public class ParserUnitTests {
assertEquals("testInTcp",tcpIn.getComponentName());
assertEquals("ip:tcp-inbound-channel-adapter", tcpIn.getComponentType());
assertEquals(errorChannel, dfa.getPropertyValue("errorChannel"));
assertFalse(cfS1.isLookupHost());
}
@Test
@@ -253,6 +261,7 @@ public class ParserUnitTests {
assertSame(cfC1, dfa.getPropertyValue("clientConnectionFactory"));
assertEquals("testOutTcpNio",tcpOut.getComponentName());
assertEquals("ip:tcp-outbound-channel-adapter", tcpOut.getComponentType());
assertFalse(cfC1.isLookupHost());
}
@Test
@@ -263,6 +272,7 @@ public class ParserUnitTests {
assertEquals("inGateway1",tcpInboundGateway1.getComponentName());
assertEquals("ip:tcp-inbound-gateway", tcpInboundGateway1.getComponentType());
assertEquals(errorChannel, dfa.getPropertyValue("errorChannel"));
assertTrue(cfS2.isLookupHost());
}
@Test
@@ -283,6 +293,7 @@ public class ParserUnitTests {
assertEquals(567L, dfa.getPropertyValue("replyTimeout"));
assertEquals("outGateway",tcpOutboundGateway.getComponentName());
assertEquals("ip:tcp-outbound-gateway", tcpOutboundGateway.getComponentType());
assertTrue(cfC2.isLookupHost());
}
@Test

View File

@@ -19,6 +19,7 @@
single-use="true"
port="#{tcpIpUtils.findAvailableServerSocket(10000)}"
task-executor="exec"
lookup-host="false"
so-timeout="20000"
/>
@@ -27,6 +28,7 @@
host="localhost"
port="#{server.port}"
single-use="true"
lookup-host="false"
so-timeout="100000"
/>

View File

@@ -18,6 +18,7 @@ package org.springframework.integration.ip.tcp;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import java.util.Properties;
@@ -99,4 +100,19 @@ public class ConnectionToConnectionTests {
assertNotNull(message);
assertEquals("Test", new String((byte[]) message.getPayload()));
}
@Test
public void testLookup() throws Exception {
TcpConnection connection = client.getConnection();
assertFalse(connection.getConnectionId().contains("localhost"));
connection.close();
client.setLookupHost(true);
connection = client.getConnection();
assertTrue(connection.getConnectionId().contains("localhost"));
connection.close();
client.setLookupHost(false);
connection = client.getConnection();
assertFalse(connection.getConnectionId().contains("localhost"));
connection.close();
}
}

View File

@@ -73,7 +73,7 @@ public class TcpMessageMapperTests {
TcpMessageMapper mapper = new TcpMessageMapper();
Socket socket = SocketFactory.getDefault().createSocket();
TcpConnection connection = new AbstractTcpConnection(socket, false) {
TcpConnection connection = new AbstractTcpConnection(socket, false, false) {
public void run() {
}
public void send(Message<?> message) throws Exception {

View File

@@ -18,6 +18,7 @@ package org.springframework.integration.ip.udp;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;
import java.net.DatagramPacket;
@@ -71,6 +72,15 @@ public class DatagramPacketMessageMapperTests {
assertEquals(messageOut.getHeaders().get(IpHeaders.ACK_ID).toString(),
message.getHeaders().getId().toString());
}
assertTrue(((String)messageOut.getHeaders().get(IpHeaders.HOSTNAME)).contains("localhost"));
mapper.setLookupHost(false);
messageOut = mapper.toMessage(packet);
assertEquals(new String(message.getPayload()), new String(messageOut.getPayload()));
if (ack) {
assertEquals(messageOut.getHeaders().get(IpHeaders.ACK_ID).toString(),
message.getHeaders().getId().toString());
}
assertFalse(((String)messageOut.getHeaders().get(IpHeaders.HOSTNAME)).contains("localhost"));
}
@Test