Skip to content

Commit

Permalink
Fix JPAN refactoring (#46)
Browse files Browse the repository at this point in the history
Co-authored-by: Tilmann Zäschke <tilmann.zaeschke@inf.ethz.ch>
  • Loading branch information
tzaeschke and Tilmann Zäschke authored Apr 17, 2024
1 parent f2ddc39 commit e0f9fb8
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 13 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Support for `/etc/scion/hosts` and for OS search domains (e.g. `/etc/resolv.conf`).
[#40](https://github.com/netsec-ethz/scion-java-client/pull/40)
- CI builds for Windows and MacOS. [#41](https://github.com/netsec-ethz/scion-java-client/pull/41)
- Added support communicating with a dispatcher-endhost in the local AS, see
`DatagramChannel.configureRemoteDispatcher`.
[#46](https://github.com/netsec-ethz/scion-java-client/pull/46)

### Changed
- BREAKING CHANGE: Changed maven artifactId to "client"
Expand All @@ -38,7 +41,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
[#35](https://github.com/netsec-ethz/scion-java-client/pull/35)
- **BREAKING CHANGE**: Renamed project to `jpan`.
[#43](https://github.com/netsec-ethz/scion-java-client/pull/43),
[#46](https://github.com/netsec-ethz/scion-java-client/pull/46)
[#45](https://github.com/netsec-ethz/scion-java-client/pull/45)
- **BREAKING CHANGE**: `Path` now returns `InetAddress` instead of `byte[]`
[#44](https://github.com/netsec-ethz/scion-java-client/pull/44)

Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ JPAN can be used in one of the following ways:
- You can use JPAN stand-alone (without local SCION installation),
however it must listen on port 30041 for incoming SCION packets because
SCION routers currently will forward data only to that port.
- If you need a local SCION installation (Go implementation),
- If you are contacting an endhost within your own AS, and the endhost uses a dispatcher, then you
must set the flag `DatagramChannel.configureRemoteDispatcher(true)`. This ensure that the outgoing
packet is sent to port 30041 on the remote machine. The flag has no effect on traffic sent to a
remote AS.
- If you need a local SCION installation on your machine (Go implementation),
consider using the dispatch-off branch/PR.
- When you need to run a local system with dispatcher, you can try to use port forwarding
to forward incoming data to your Java application port. The application port must not be 30041.
Expand Down
47 changes: 38 additions & 9 deletions src/main/java/org/scion/jpan/AbstractDatagramChannel.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ abstract class AbstractDatagramChannel<C extends AbstractDatagramChannel<?>> imp
// Whether we have a connectionPath is independent of whether the underlying channel is connected.
private RequestPath connectionPath;
private InetAddress localAddress;
private boolean isBoundToAddress = false;
private boolean cfgReportFailedValidation = false;
private PathPolicy pathPolicy = PathPolicy.DEFAULT;
private ScionService service;
Expand All @@ -55,6 +56,7 @@ abstract class AbstractDatagramChannel<C extends AbstractDatagramChannel<?>> imp
Constants.DEFAULT_PATH_EXPIRY_MARGIN);
private int cfgTrafficClass;
private Consumer<Scmp.Message> errorListener;
private boolean cfgRemoteDispatcher = false;

protected AbstractDatagramChannel(ScionService service) throws IOException {
this(service, DatagramChannel.open());
Expand Down Expand Up @@ -132,6 +134,7 @@ protected DatagramChannel channel() {
public C bind(InetSocketAddress address) throws IOException {
synchronized (stateLock) {
channel.bind(address);
isBoundToAddress = address != null;
localAddress = ((InetSocketAddress) channel.getLocalAddress()).getAddress();
return (C) this;
}
Expand Down Expand Up @@ -348,8 +351,32 @@ protected void checkListeners(Scmp.Message scmpMsg) {
}
}

protected void sendRaw(ByteBuffer buffer, InetSocketAddress address) throws IOException {
channel.send(buffer, address);
/**
* Assume that the destination host uses a dispatcher.
*
* <p>Calling this method sets an internal flag that forces the destination port of intra-AS
* packets to be 30041 independent of the UDP-overlay port. This flag has no effect for inter-AS
* packets or if the overlay port is already 30041.
*
* @param hasDispatcher Set to 'true' if remote end-host uses a dispatcher and requires using port
* 30041.
* @deprecated To be removed once dispatchers have been removed
*/
@Deprecated
public void configureRemoteDispatcher(boolean hasDispatcher) {
this.cfgRemoteDispatcher = hasDispatcher;
}

protected int sendRaw(ByteBuffer buffer, InetSocketAddress address, Path path)
throws IOException {
if (cfgRemoteDispatcher && path != null && path.getRawPath().length == 0) {
return channel.send(buffer, new InetSocketAddress(address.getAddress(), 30041));
}
return channel.send(buffer, address);
}

protected int sendRaw(ByteBuffer buffer, InetSocketAddress address) throws IOException {
return sendRaw(buffer, address, null);
}

public Consumer<Scmp.Message> setScmpErrorListener(Consumer<Scmp.Message> listener) {
Expand Down Expand Up @@ -573,13 +600,15 @@ private void updateConnection(RequestPath newPath, boolean mustBeConnected) thro
connectionPath = newPath;
// update local address
InetAddress oldLocalAddress = localAddress;
// TODO we should not change the local address if bind() was called with an explicit address!
// API: returning the localAddress should return non-ANY if we have a connection
// I.e. getExternalIP() is fine if we have a connection.
// It is NOT fine if we are bound to an explicit IP/port
localAddress = getOrCreateService().getExternalIP(newPath.getFirstHopAddress());
if (!Objects.equals(localAddress, oldLocalAddress)) {
resizeBuffers(localAddress);
// we should not change the local address if bind() was called with an explicit address!
if (!isBoundToAddress) {
// API: returning the localAddress should return non-ANY if we have a connection
// I.e. getExternalIP() is fine if we have a connection.
// It is NOT fine if we are bound to an explicit IP/port
localAddress = getOrCreateService().getExternalIP(newPath.getFirstHopAddress());
if (!Objects.equals(localAddress, oldLocalAddress)) {
resizeBuffers(localAddress);
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/scion/jpan/DatagramChannel.java
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public Path send(ByteBuffer srcBuffer, Path path) throws IOException {
throw new IOException("Packet is larger than max send buffer size.");
}
buffer.flip();
sendRaw(buffer, actualPath.getFirstHopAddress());
sendRaw(buffer, actualPath.getFirstHopAddress(), actualPath);
return actualPath;
} finally {
writeLock().unlock();
Expand Down Expand Up @@ -173,7 +173,7 @@ public synchronized int write(ByteBuffer src) throws IOException {
buffer.put(src);
buffer.flip();

int sent = channel().send(buffer, getConnectionPath().getFirstHopAddress());
int sent = sendRaw(buffer, getConnectionPath().getFirstHopAddress(), getConnectionPath());
if (sent < buffer.limit() || buffer.remaining() > 0) {
throw new ScionException("Failed to send all data.");
}
Expand Down

0 comments on commit e0f9fb8

Please sign in to comment.