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
28 changes: 28 additions & 0 deletions src/main/java/com/trilead/ssh2/Connection.java
Original file line number Diff line number Diff line change
Expand Up @@ -1075,6 +1075,34 @@ public synchronized ConnectionInfo getConnectionInfo() throws IOException
return tm.getConnectionInfo(1);
}

/**
* Returns the local address to which the socket is bound.
*
* @return the local address to which the socket is bound.
* @throws IOException
* in case of any problem.
*/
public synchronized InetSocketAddress getLocalSocketAddress() throws IOException
{
if (tm == null)
throw new IllegalStateException("You need to establish a connection first.");
return tm.getLocalSocketAddress();
}

/**
* Returns the address of the endpoint this socket is connected to.
*
* @return the address of the endpoint this socket is connected to.
* @throws IOException
* in case of any problem.
*/
public synchronized InetSocketAddress getRemoteSocketAddress() throws IOException
{
if (tm == null)
throw new IllegalStateException("You need to establish a connection first.");
return tm.getRemoteSocketAddress();
}

/**
* After a successful connect, one has to authenticate oneself. This method
* can be used to tell which authentication methods are supported by the
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/trilead/ssh2/ConnectionInfo.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

package com.trilead.ssh2;

import java.net.InetSocketAddress;

/**
* In most cases you probably do not need the information contained in here.
*
Expand All @@ -9,6 +11,16 @@
*/
public class ConnectionInfo
{
/**
* The address of the local socket.
*/
public InetSocketAddress localSocketAddress;

Check warning on line 17 in src/main/java/com/trilead/ssh2/ConnectionInfo.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Make localSocketAddress a static final constant or non-public and provide accessors if needed.

See more on https://sonarcloud.io/project/issues?id=connectbot_sshlib&issues=AZ2363Bm443VIWnpbF_F&open=AZ2363Bm443VIWnpbF_F&pullRequest=487

/**
* The address of the remote socket.
*/
public InetSocketAddress remoteSocketAddress;

Check warning on line 22 in src/main/java/com/trilead/ssh2/ConnectionInfo.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Make remoteSocketAddress a static final constant or non-public and provide accessors if needed.

See more on https://sonarcloud.io/project/issues?id=connectbot_sshlib&issues=AZ2363Bm443VIWnpbF_G&open=AZ2363Bm443VIWnpbF_G&pullRequest=487

/**
* The used key exchange (KEX) algorithm in the latest key exchange.
*/
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/com/trilead/ssh2/transport/KexManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,16 @@ public synchronized void handleMessage(byte[] msg, int msglen) throws IOExceptio

ConnectionInfo sci = new ConnectionInfo();

try
{
sci.localSocketAddress = tm.getLocalSocketAddress();
sci.remoteSocketAddress = tm.getRemoteSocketAddress();
}
catch (IOException e)
{
/* Ignore, if the connection is closed then it doesn't matter much anyway */
}

kexCount++;

sci.keyExchangeAlgorithm = kxs.np.kex_algo;
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/com/trilead/ssh2/transport/TransportManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.trilead.ssh2.ExtensionInfo;
import com.trilead.ssh2.packets.PacketExtInfo;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.security.SecureRandom;
Comment thread
kruton marked this conversation as resolved.
import java.util.Vector;
Expand Down Expand Up @@ -184,6 +185,26 @@ public int getPort()
return port;
}

public InetSocketAddress getLocalSocketAddress() throws IOException
{
synchronized (connectionSemaphore)
{
if (sock == null)
throw new IOException("The connection is closed.");
return (InetSocketAddress) sock.getLocalSocketAddress();
}
}

public InetSocketAddress getRemoteSocketAddress() throws IOException
{
synchronized (connectionSemaphore)
{
if (sock == null)
throw new IOException("The connection is closed.");
return (InetSocketAddress) sock.getRemoteSocketAddress();
}
}

public ServerHostKeyVerifier getServerHostKeyVerifier()
{
return km != null ? km.getServerHostKeyVerifier() : null;
Expand Down
33 changes: 28 additions & 5 deletions src/test/java/com/trilead/ssh2/ConnectionTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,36 @@ public void testSetSecureRandomWithNull() {
@Test
public void testGetConnectionInfoThrowsWhenNotConnected() {
try {
connection.getConnectionInfo();
fail("Should throw IllegalStateException when not connected");
connection.getConnectionInfo();
fail("Should throw IllegalStateException when not connected");
} catch (IllegalStateException e) {
assertTrue(e.getMessage().contains("establish a connection first"), "Exception message should indicate connection required");
assertTrue(e.getMessage().contains("establish a connection first"), "Exception message should indicate connection required");
} catch (Exception e) {
fail("Should throw IllegalStateException, got: " +
e.getClass().getSimpleName());
fail("Should throw IllegalStateException, got: " + e.getClass().getSimpleName());
}
}

@Test
public void testGetLocalSocketAddressThrowsWhenNotConnected() {
try {
connection.getLocalSocketAddress();
fail("Should throw IllegalStateException when not connected");
} catch (IllegalStateException e) {
assertTrue(e.getMessage().contains("establish a connection first"), "Exception message should indicate connection required");
} catch (Exception e) {
fail("Should throw IllegalStateException, got: " + e.getClass().getSimpleName());
}
}

@Test
public void testGetRemoteSocketAddressThrowsWhenNotConnected() {
try {
connection.getRemoteSocketAddress();
fail("Should throw IllegalStateException when not connected");
} catch (IllegalStateException e) {
assertTrue(e.getMessage().contains("establish a connection first"), "Exception message should indicate connection required");
} catch (Exception e) {
fail("Should throw IllegalStateException, got: " + e.getClass().getSimpleName());
}
}

Expand Down
24 changes: 24 additions & 0 deletions src/test/java/com/trilead/ssh2/OpenSSHCompatibilityTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
import org.testcontainers.images.builder.ImageFromDockerfile;

import java.io.IOException;
import java.net.InetSocketAddress;

import com.trilead.ssh2.crypto.Base64;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;

/**
Expand Down Expand Up @@ -101,6 +103,28 @@ private void canConnectWithPubkey(String keyFilename) throws Exception {
}
}

@Test
public void testSocketAddress() throws IOException {
try (GenericContainer<?> server = getBaseContainer()) {
server.start();
try (Connection c = withServer(server)) {
c.connect(verifier);

InetSocketAddress local = c.getLocalSocketAddress();
InetSocketAddress remote = c.getRemoteSocketAddress();

assertThat(local, notNullValue());
assertThat(remote, notNullValue());
assertThat(remote.getHostString(), is(server.getHost()));
assertThat(remote.getPort(), is(server.getMappedPort(22)));

ConnectionInfo info = c.getConnectionInfo();
assertThat(info.localSocketAddress.toString(), is(local.toString()));
assertThat(info.remoteSocketAddress.toString(), is(remote.toString()));
}
}
}

@Test
public void canConnectWithEd25519() throws Exception {
canConnectWithPubkey("ed25519-openssh2-private-key.txt");
Expand Down
Loading