Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ public AS2AsyncMDNServerConnection(Integer portNumber, SSLContext sslContext)
listenerThread.start();
}

public int getLocalPort() {
return listenerThread != null ? listenerThread.serverSocket.getLocalPort() : -1;
}

public void close() {
if (listenerThread != null) {
lock.lock();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,10 @@ public void registerConsumerConfiguration(String path, AS2ConsumerConfiguration
consumerConfigurations.put(path, config);
}

public int getLocalPort() {
return serversocket != null ? serversocket.getLocalPort() : -1;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we return 0 to let the system pick an ephemeral port?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code on behalf of Guillaume Nodet

Returning -1 is intentional — it follows the ServerSocket.getLocalPort() convention where -1 means "not bound / closed". Returning 0 would be misleading since 0 means "pick an ephemeral port" in socket APIs, which could cause silent bugs if the value is accidentally passed to another new ServerSocket(0) or bind() call. The -1 sentinel makes the error explicit.

}

public void close() {
if (acceptorThread != null) {
lock.lock();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import java.net.HttpURLConnection;
import java.net.URL;

import org.apache.camel.test.AvailablePortFinder;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.HttpException;
Expand All @@ -28,19 +27,18 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import static org.junit.jupiter.api.Assertions.*;

class AS2AsyncMDNServerConnectionTest {

@RegisterExtension
AvailablePortFinder.Port port = AvailablePortFinder.find();
private AS2AsyncMDNServerConnection connection;
private int port;

@BeforeEach
void setUp() throws Exception {
connection = new AS2AsyncMDNServerConnection(port.getPort(), null);
connection = new AS2AsyncMDNServerConnection(0, null);
port = connection.getLocalPort();
}

@AfterEach
Expand Down Expand Up @@ -69,7 +67,7 @@ public void handle(ClassicHttpRequest request, ClassicHttpResponse response, Htt
// Send a request with a Host header that doesn't match the server's hostname
// This previously caused HTTP 421 due to RequestValidateHost
HttpURLConnection conn
= (HttpURLConnection) new URL("http://localhost:" + port.getPort() + "/test-mdn").openConnection();
= (HttpURLConnection) new URL("http://localhost:" + port + "/test-mdn").openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Host", "different-host.example.com");
conn.setDoOutput(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,11 @@ public static void setUpOnce() throws Exception {
setupKeysAndCertificates();

testServer = new AS2ServerConnection(
AS2_VERSION, "MyServer-HTTP/1.1", SERVER_FQDN, TARGET_PORT.getPort(), AS2SignatureAlgorithm.SHA256WITHRSA,
AS2_VERSION, "MyServer-HTTP/1.1", SERVER_FQDN, 0, AS2SignatureAlgorithm.SHA256WITHRSA,
certList.toArray(new Certificate[0]), signingKP.getPrivate(), decryptingKP.getPrivate(), MDN_MESSAGE_TEMPLATE,
VALIDATE_SIGNING_CERTIFICATE_CHAIN, null, null, null, null);
targetPort = testServer.getLocalPort();
recipientDeliveryAddress = "http://localhost:" + targetPort + "/handle-receipts";
testServer.listen("*", new HttpRequestHandler() {
@Override
public void handle(ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context)
Expand Down Expand Up @@ -135,7 +137,7 @@ public void multipartSignedMessageRequestTest() throws Exception {
assertEquals(AS2_NAME, request.getFirstHeader(AS2Header.AS2_TO).getValue(), "Unexpected AS2 to value");
assertTrue(request.getFirstHeader(AS2Header.MESSAGE_ID).getValue().endsWith(CLIENT_FQDN + ">"),
"Unexpected message id value");
assertEquals(TARGET_HOST + ":" + TARGET_PORT, request.getFirstHeader(AS2Header.TARGET_HOST).getValue(),
assertEquals(TARGET_HOST + ":" + targetPort, request.getFirstHeader(AS2Header.TARGET_HOST).getValue(),
"Unexpected target host value");
assertEquals(USER_AGENT, request.getFirstHeader(AS2Header.USER_AGENT).getValue(), "Unexpected user agent value");
assertNotNull(request.getFirstHeader(AS2Header.DATE), "Date value missing");
Expand Down Expand Up @@ -204,7 +206,7 @@ public void envelopedMessageTest(AS2EncryptionAlgorithm encryptionAlgorithm) thr
assertEquals(AS2_NAME, request.getFirstHeader(AS2Header.AS2_TO).getValue(), "Unexpected AS2 to value");
assertTrue(request.getFirstHeader(AS2Header.MESSAGE_ID).getValue().endsWith(CLIENT_FQDN + ">"),
"Unexpected message id value");
assertEquals(TARGET_HOST + ":" + TARGET_PORT, request.getFirstHeader(AS2Header.TARGET_HOST).getValue(),
assertEquals(TARGET_HOST + ":" + targetPort, request.getFirstHeader(AS2Header.TARGET_HOST).getValue(),
"Unexpected target host value");
assertEquals(USER_AGENT, request.getFirstHeader(AS2Header.USER_AGENT).getValue(), "Unexpected user agent value");
assertNotNull(request.getFirstHeader(AS2Header.DATE), "Date value missing");
Expand Down Expand Up @@ -262,7 +264,7 @@ public void envelopedAndSignedMessageTest(AS2EncryptionAlgorithm encryptionAlgor
assertEquals(AS2_NAME, request.getFirstHeader(AS2Header.AS2_TO).getValue(), "Unexpected AS2 to value");
assertTrue(request.getFirstHeader(AS2Header.MESSAGE_ID).getValue().endsWith(CLIENT_FQDN + ">"),
"Unexpected message id value");
assertEquals(TARGET_HOST + ":" + TARGET_PORT,
assertEquals(TARGET_HOST + ":" + targetPort,
request.getFirstHeader(AS2Header.TARGET_HOST).getValue(), "Unexpected target host value");
assertEquals(USER_AGENT,
request.getFirstHeader(AS2Header.USER_AGENT).getValue(), "Unexpected user agent value");
Expand Down Expand Up @@ -375,7 +377,7 @@ public void asynchronousMdnMessageTest() throws Exception {
null, "Got ya message!", null);

// Send MDN
HttpCoreContext httpContext = mdnManager.send(mdn, mdn.getMainMessageContentType(), RECIPIENT_DELIVERY_ADDRESS);
HttpCoreContext httpContext = mdnManager.send(mdn, mdn.getMainMessageContentType(), recipientDeliveryAddress);
HttpRequest mndRequest = httpContext.getRequest();
Arrays.stream(request.getHeaders(AS2Header.CONTENT_DISPOSITION)).forEach(h -> LOG.debug("{}", h));
DispositionNotificationMultipartReportEntity reportEntity
Expand Down Expand Up @@ -440,7 +442,7 @@ private void signedAndCompressedMessage(Object msg) throws Exception {
assertEquals(AS2_NAME, request.getFirstHeader(AS2Header.AS2_TO).getValue(), "Unexpected AS2 to value");
assertTrue(request.getFirstHeader(AS2Header.MESSAGE_ID).getValue().endsWith(CLIENT_FQDN + ">"),
"Unexpected message id value");
assertEquals(TARGET_HOST + ":" + TARGET_PORT, request.getFirstHeader(AS2Header.TARGET_HOST).getValue(),
assertEquals(TARGET_HOST + ":" + targetPort, request.getFirstHeader(AS2Header.TARGET_HOST).getValue(),
"Unexpected target host value");
assertEquals(USER_AGENT, request.getFirstHeader(AS2Header.USER_AGENT).getValue(), "Unexpected user agent value");
assertNotNull(request.getFirstHeader(AS2Header.DATE), "Date value missing");
Expand Down Expand Up @@ -514,7 +516,7 @@ private void envelopedAndCompressedMessage(Object msg) throws Exception {
assertEquals(AS2_NAME, request.getFirstHeader(AS2Header.AS2_TO).getValue(), "Unexpected AS2 to value");
assertTrue(request.getFirstHeader(AS2Header.MESSAGE_ID).getValue().endsWith(CLIENT_FQDN + ">"),
"Unexpected message id value");
assertEquals(TARGET_HOST + ":" + TARGET_PORT, request.getFirstHeader(AS2Header.TARGET_HOST).getValue(),
assertEquals(TARGET_HOST + ":" + targetPort, request.getFirstHeader(AS2Header.TARGET_HOST).getValue(),
"Unexpected target host value");
assertEquals(USER_AGENT, request.getFirstHeader(AS2Header.USER_AGENT).getValue(), "Unexpected user agent value");
assertNotNull(request.getFirstHeader(AS2Header.DATE), "Date value missing");
Expand Down Expand Up @@ -668,7 +670,7 @@ private void envelopedCompressedAndSignedMessage(Object msg) throws Exception {
assertEquals(AS2_NAME, request.getFirstHeader(AS2Header.AS2_TO).getValue(), "Unexpected AS2 to value");
assertTrue(request.getFirstHeader(AS2Header.MESSAGE_ID).getValue().endsWith(CLIENT_FQDN + ">"),
"Unexpected message id value");
assertEquals(TARGET_HOST + ":" + TARGET_PORT, request.getFirstHeader(AS2Header.TARGET_HOST).getValue(),
assertEquals(TARGET_HOST + ":" + targetPort, request.getFirstHeader(AS2Header.TARGET_HOST).getValue(),
"Unexpected target host value");
assertEquals(USER_AGENT, request.getFirstHeader(AS2Header.USER_AGENT).getValue(), "Unexpected user agent value");
assertNotNull(request.getFirstHeader(AS2Header.DATE), "Date value missing");
Expand Down Expand Up @@ -735,7 +737,7 @@ private void verifyRequest(HttpRequest request) throws URISyntaxException {
assertEquals(AS2_NAME, request.getFirstHeader(AS2Header.AS2_TO).getValue(), "Unexpected AS2 to value");
assertTrue(request.getFirstHeader(AS2Header.MESSAGE_ID).getValue().endsWith(CLIENT_FQDN + ">"),
"Unexpected message id value");
assertEquals(TARGET_HOST + ":" + TARGET_PORT, request.getFirstHeader(AS2Header.TARGET_HOST).getValue(),
assertEquals(TARGET_HOST + ":" + targetPort, request.getFirstHeader(AS2Header.TARGET_HOST).getValue(),
"Unexpected target host value");
assertEquals(USER_AGENT, request.getFirstHeader(AS2Header.USER_AGENT).getValue(), "Unexpected user agent value");
assertNotNull(request.getFirstHeader(AS2Header.DATE), "Date value missing");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,10 @@
import com.helger.mail.cte.EContentTransferEncoding;
import com.helger.security.keystore.EKeyStoreType;
import org.apache.camel.component.as2.api.entity.ApplicationEntity;
import org.apache.camel.test.AvailablePortFinder;
import org.apache.hc.core5.http.protocol.HttpDateGenerator;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.extension.RegisterExtension;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
Expand Down Expand Up @@ -86,14 +84,13 @@ public class AS2MessageTestBase {

protected static final String METHOD = "POST";
protected static final String TARGET_HOST = "localhost";
@RegisterExtension
protected static AvailablePortFinder.Port TARGET_PORT = AvailablePortFinder.find();
protected static int targetPort;
protected static final Duration HTTP_SOCKET_TIMEOUT = Duration.ofSeconds(5);
protected static final Duration HTTP_CONNECTION_TIMEOUT = Duration.ofSeconds(5);
protected static final Integer HTTP_CONNECTION_POOL_SIZE = 5;
protected static final Duration HTTP_CONNECTION_POOL_TTL = Duration.ofMinutes(15);
protected static final Certificate[] VALIDATE_SIGNING_CERTIFICATE_CHAIN = null;
protected static final String RECIPIENT_DELIVERY_ADDRESS = "http://localhost:" + TARGET_PORT.getPort() + "/handle-receipts";
protected static String recipientDeliveryAddress;
protected static final String AS2_VERSION = "1.1";
protected static final String USER_AGENT = "Camel AS2 Endpoint";
protected static final String REQUEST_URI = "/";
Expand Down Expand Up @@ -174,7 +171,7 @@ protected void binaryContentTransferEncodingTest(boolean encrypt, boolean sign,
aSettings.setSenderData(AS2_NAME, FROM, "openas2a_alias");

// Fixed receiver
aSettings.setReceiverData(AS2_NAME, "openas2b_alias", "http://" + TARGET_HOST + ":" + TARGET_PORT.getPort() + "/");
aSettings.setReceiverData(AS2_NAME, "openas2b_alias", "http://" + TARGET_HOST + ":" + targetPort + "/");
aSettings.setReceiverCertificate(issueCert);

// AS2 stuff
Expand Down Expand Up @@ -220,7 +217,7 @@ protected void compressionSignatureOrderTest(boolean encrypt, boolean compressBe
aSettings.setSenderData(AS2_NAME, FROM, "openas2a_alias");

// Fixed receiver
aSettings.setReceiverData(AS2_NAME, "openas2b_alias", "http://" + TARGET_HOST + ":" + TARGET_PORT.getPort() + "/");
aSettings.setReceiverData(AS2_NAME, "openas2b_alias", "http://" + TARGET_HOST + ":" + targetPort + "/");
aSettings.setReceiverCertificate(issueCert);

// AS2 stuff
Expand Down Expand Up @@ -255,7 +252,7 @@ protected void compressionSignatureOrderTest(boolean encrypt, boolean compressBe
protected AS2ClientManager createDefaultClientManager() throws IOException {
AS2ClientConnection clientConnection = new AS2ClientConnection(
AS2_VERSION, USER_AGENT, CLIENT_FQDN,
TARGET_HOST, TARGET_PORT.getPort(), HTTP_SOCKET_TIMEOUT, HTTP_CONNECTION_TIMEOUT, HTTP_CONNECTION_POOL_SIZE,
TARGET_HOST, targetPort, HTTP_SOCKET_TIMEOUT, HTTP_CONNECTION_TIMEOUT, HTTP_CONNECTION_POOL_SIZE,
HTTP_CONNECTION_POOL_TTL, null, null);
return new AS2ClientManager(clientConnection);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,11 @@ public static void setUpOnce() throws Exception {
setupKeysAndCertificates();

testServer = new AS2ServerConnection(
AS2_VERSION, "MyServer-HTTP/1.1", SERVER_FQDN, TARGET_PORT.getPort(), AS2SignatureAlgorithm.SHA256WITHRSA,
AS2_VERSION, "MyServer-HTTP/1.1", SERVER_FQDN, 0, AS2SignatureAlgorithm.SHA256WITHRSA,
certList.toArray(new Certificate[0]), signingKP.getPrivate(), null, MDN_MESSAGE_TEMPLATE,
null, null, null, null, null);
targetPort = testServer.getLocalPort();
recipientDeliveryAddress = "http://localhost:" + targetPort + "/handle-receipts";
testServer.listen("*", new HttpRequestHandler() {
@Override
public void handle(ClassicHttpRequest request, ClassicHttpResponse response, HttpContext context)
Expand Down Expand Up @@ -102,7 +104,7 @@ public void plainEDIMessageRequestTest() throws Exception {
assertEquals(AS2_NAME, request.getFirstHeader(AS2Header.AS2_TO).getValue(), "Unexpected AS2 to value");
assertTrue(request.getFirstHeader(AS2Header.MESSAGE_ID).getValue().endsWith(CLIENT_FQDN + ">"),
"Unexpected message id value");
assertEquals(TARGET_HOST + ":" + TARGET_PORT, request.getFirstHeader(AS2Header.TARGET_HOST).getValue(),
assertEquals(TARGET_HOST + ":" + targetPort, request.getFirstHeader(AS2Header.TARGET_HOST).getValue(),
"Unexpected target host value");
assertEquals(USER_AGENT, request.getFirstHeader(AS2Header.USER_AGENT).getValue(), "Unexpected user agent value");
assertNotNull(request.getFirstHeader(AS2Header.DATE), "Date value missing");
Expand Down Expand Up @@ -144,7 +146,7 @@ public void compressedMessageRequestTest() throws Exception {
assertEquals(AS2_NAME, request.getFirstHeader(AS2Header.AS2_TO).getValue(), "Unexpected AS2 to value");
assertTrue(request.getFirstHeader(AS2Header.MESSAGE_ID).getValue().endsWith(CLIENT_FQDN + ">"),
"Unexpected message id value");
assertEquals(TARGET_HOST + ":" + TARGET_PORT, request.getFirstHeader(AS2Header.TARGET_HOST).getValue(),
assertEquals(TARGET_HOST + ":" + targetPort, request.getFirstHeader(AS2Header.TARGET_HOST).getValue(),
"Unexpected target host value");
assertEquals(USER_AGENT, request.getFirstHeader(AS2Header.USER_AGENT).getValue(), "Unexpected user agent value");
assertNotNull(request.getFirstHeader(AS2Header.DATE), "Date value missing");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ public class AS2AsyncMdnBasicAuthHeaderTest extends AbstractAS2ITSupport {
private static final String MDN_PASSWORD = "rider";
private static final String MDN_ACCESS_TOKEN = "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3";
@RegisterExtension
AvailablePortFinder.Port targetPort = AvailablePortFinder.find();
@RegisterExtension
AvailablePortFinder.Port receiptServerPort = AvailablePortFinder.find();
@RegisterExtension
AvailablePortFinder.Port jettyPort = AvailablePortFinder.find();
Expand Down Expand Up @@ -88,6 +86,7 @@ public class AS2AsyncMdnBasicAuthHeaderTest extends AbstractAS2ITSupport {
""";

private AS2ServerConnection serverConnection;
private int targetPort;

@Override
public void setupResources() throws Exception {
Expand Down Expand Up @@ -186,18 +185,19 @@ public void configure() {

@Override
protected void customizeConfiguration(AS2Configuration configuration) {
configuration.setTargetPortNumber(targetPort.getPort());
configuration.setTargetPortNumber(targetPort);
}

// AS2 server adds Authorization header to MDN returned asynchronously
private void receiveTestMessages() throws IOException {
serverConnection = new AS2ServerConnection(
"1.1", "AS2ClientManagerIntegrationTest Server",
"server.example.com", targetPort.getPort(), AS2SignatureAlgorithm.SHA256WITHRSA,
"server.example.com", 0, AS2SignatureAlgorithm.SHA256WITHRSA,
null, null, null,
"TBD", null, null,
// server authorization config
MDN_USER_NAME, MDN_PASSWORD, MDN_ACCESS_TOKEN);
targetPort = serverConnection.getLocalPort();
serverConnection.listen("/", new AS2AsyncMDNServerManagerIT.RequestHandler());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ public class AS2AsyncMdnTokenAuthHeaderTest extends AbstractAS2ITSupport {

private static final String MDN_ACCESS_TOKEN = "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3";
@RegisterExtension
AvailablePortFinder.Port targetPort = AvailablePortFinder.find();
@RegisterExtension
AvailablePortFinder.Port receiptServerPort = AvailablePortFinder.find();
private static final String EDI_MESSAGE = """
UNB+UNOA:1+005435656:1+006415160:1+060515:1434+00000000000778'
Expand Down Expand Up @@ -76,6 +74,7 @@ public class AS2AsyncMdnTokenAuthHeaderTest extends AbstractAS2ITSupport {
""";

private AS2ServerConnection serverConnection;
private int targetPort;

@Override
public void setupResources() throws Exception {
Expand Down Expand Up @@ -137,18 +136,19 @@ public void configure() {

@Override
protected void customizeConfiguration(AS2Configuration configuration) {
configuration.setTargetPortNumber(targetPort.getPort());
configuration.setTargetPortNumber(targetPort);
}

// AS2 server adds Authorization header to MDN returned asynchronously
private void receiveTestMessages() throws IOException {
serverConnection = new AS2ServerConnection(
"1.1", "AS2ClientManagerIntegrationTest Server",
"server.example.com", targetPort.getPort(), AS2SignatureAlgorithm.SHA256WITHRSA,
"server.example.com", 0, AS2SignatureAlgorithm.SHA256WITHRSA,
null, null, null,
"TBD", null, null,
// server authorization config
null, null, MDN_ACCESS_TOKEN);
targetPort = serverConnection.getLocalPort();
serverConnection.listen("/", new AS2AsyncMDNServerManagerIT.RequestHandler());
}
}
Loading
Loading