Protect TcpNetConnectionSupport calls

5.0 introduced the `TcpNetConnectionSupport` user hook to create connection objects.

If a user-supplied instance threw an exception, the server socket would remain open
but the server `accept()` thread is gone.

- wrap the connection initialization code in try/catch
- close the server socket if necessary on an exception
This commit is contained in:
Gary Russell
2018-02-23 15:43:33 -05:00
committed by Artem Bilan
parent d5303ca4f3
commit 0e3034919d
3 changed files with 114 additions and 12 deletions

View File

@@ -0,0 +1,84 @@
/*
* Copyright 2018 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.tcp.connection;
import static org.assertj.core.api.Assertions.assertThat;
import java.net.Socket;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import javax.net.SocketFactory;
import org.junit.Test;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.messaging.Message;
/**
* @author Gary Russell
* @since 5.0.3
*
*/
public class TcpNetConnectionSupportTests {
@Test
public void testBadCode() throws Exception {
TcpNetServerConnectionFactory server = new TcpNetServerConnectionFactory(0);
AtomicReference<Message<?>> message = new AtomicReference<>();
CountDownLatch latch1 = new CountDownLatch(1);
server.registerListener(m -> {
message.set(m);
latch1.countDown();
return false;
});
AtomicBoolean firstTime = new AtomicBoolean(true);
server.setTcpNetConnectionSupport(new DefaultTcpNetConnectionSupport() {
@Override
public TcpNetConnection createNewConnection(Socket socket, boolean server, boolean lookupHost,
ApplicationEventPublisher applicationEventPublisher, String connectionFactoryName)
throws Exception {
if (firstTime.getAndSet(false)) {
throw new RuntimeException("intended");
}
return super.createNewConnection(socket, server, lookupHost, applicationEventPublisher, connectionFactoryName);
}
});
CountDownLatch latch2 = new CountDownLatch(1);
server.setApplicationEventPublisher(e -> {
if (e instanceof TcpConnectionServerListeningEvent) {
latch2.countDown();
}
});
server.afterPropertiesSet();
server.start();
assertThat(latch2.await(10, TimeUnit.SECONDS)).isTrue();
Socket socket = SocketFactory.getDefault().createSocket("localhost", server.getPort());
socket.close();
socket = SocketFactory.getDefault().createSocket("localhost", server.getPort());
socket.getOutputStream().write("foo\r\n".getBytes());
socket.close();
assertThat(latch1.await(10, TimeUnit.SECONDS)).isTrue();
assertThat(message.get()).isNotNull();
server.stop();
}
}