Skip to content

Commit

Permalink
Path-aware subclasses InetSocketAddress (#86)
Browse files Browse the repository at this point in the history
* receive() -> InetSocketAddress

---------

Co-authored-by: Tilmann Zäschke <tilmann.zaeschke@inf.ethz.ch>
  • Loading branch information
tzaeschke and Tilmann Zäschke authored Jun 10, 2024
1 parent 3058083 commit 31502f6
Show file tree
Hide file tree
Showing 13 changed files with 88 additions and 41 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

## Added
### Added
- SCMP echo responder [#78](https://github.com/scionproto-contrib/jpan/pull/78)
- Maven Java executor [#80](https://github.com/scionproto-contrib/jpan/pull/80)
- Dev environment setup hints doc [#82](https://github.com/scionproto-contrib/jpan/pull/82)
Expand All @@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Rename `DatagramSocket` to `ScionDatagramSopcketl` and move it to main package
- Rename `ScionSocketOptions` starting with `SN_` to `SCION_`
- SCMP API changes. [#71](https://github.com/scionproto-contrib/jpan/pull/71)
- **BREAKING CHANGE**: `DatagramChannel.receive()` returns a subclass of `InetSocketAddress`
[#69](https://github.com/scionproto-contrib/jpan/pull/69)

### Fixed
- Fixed locking and resizing of buffers. [#68](https://github.com/scionproto-contrib/jpan/pull/68)
Expand Down
8 changes: 6 additions & 2 deletions src/main/java/org/scion/jpan/ScionDatagramChannel.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public boolean isBlocking() {
return super.isBlocking();
}

public ResponsePath receive(ByteBuffer userBuffer) throws IOException {
public ScionResponseAddress receive(ByteBuffer userBuffer) throws IOException {
readLock().lock();
try {
ByteBuffer buffer = getBufferReceive(userBuffer.capacity());
Expand All @@ -67,7 +67,7 @@ public ResponsePath receive(ByteBuffer userBuffer) throws IOException {
}
ScionHeaderParser.extractUserPayload(buffer, userBuffer);
buffer.clear();
return receivePath;
return ScionResponseAddress.from(receivePath);
} finally {
readLock().unlock();
}
Expand All @@ -88,6 +88,10 @@ public void send(ByteBuffer srcBuffer, SocketAddress destination) throws IOExcep
if (!(destination instanceof InetSocketAddress)) {
throw new IllegalArgumentException("Address must be of type InetSocketAddress.");
}
if (destination instanceof ScionResponseAddress) {
send(srcBuffer, ((ScionResponseAddress) destination).getPath());
return;
}
InetSocketAddress dst = (InetSocketAddress) destination;
Path path = getPathPolicy().filter(getOrCreateService().getPaths(dst));
send(srcBuffer, path);
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/org/scion/jpan/ScionDatagramSocket.java
Original file line number Diff line number Diff line change
Expand Up @@ -323,11 +323,12 @@ public synchronized void receive(DatagramPacket packet) throws IOException {
synchronized (packet) {
ByteBuffer receiveBuffer =
ByteBuffer.wrap(packet.getData(), packet.getOffset(), packet.getLength());
ResponsePath path = channel.receive(receiveBuffer);
if (path == null) {
ScionResponseAddress responseAddress = channel.receive(receiveBuffer);
if (responseAddress == null) {
// timeout occurred
throw new SocketTimeoutException();
}
ResponsePath path = responseAddress.getPath();
// TODO this is not ideal, a client may not be connected. Use getService()==null?
if (!channel.isConnected()) {
synchronized (pathCache) {
Expand Down
35 changes: 35 additions & 0 deletions src/main/java/org/scion/jpan/ScionResponseAddress.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2024 ETH Zurich
//
// 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.scion.jpan;

import java.net.InetSocketAddress;

public class ScionResponseAddress extends InetSocketAddress {

private final ResponsePath responsePath;

public static ScionResponseAddress from(ResponsePath path) {
return new ScionResponseAddress(path);
}

private ScionResponseAddress(ResponsePath path) {
super(path.getRemoteAddress(), path.getRemotePort());
this.responsePath = path;
}

public ResponsePath getPath() {
return responsePath;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.util.Iterator;
import org.scion.jpan.ResponsePath;
import org.scion.jpan.ScionDatagramChannel;
import org.scion.jpan.ScionResponseAddress;
import org.scion.jpan.ScionService;

/**
Expand Down Expand Up @@ -89,7 +90,7 @@ private ResponsePath receiveFromTimeoutChannel(
}

@Override
public ResponsePath receive(ByteBuffer userBuffer) throws IOException {
public ScionResponseAddress receive(ByteBuffer userBuffer) throws IOException {
readLock().lock();
try {
ByteBuffer buffer = getBufferReceive(userBuffer.capacity());
Expand All @@ -99,7 +100,7 @@ public ResponsePath receive(ByteBuffer userBuffer) throws IOException {
}
ScionHeaderParser.extractUserPayload(buffer, userBuffer);
buffer.clear();
return receivePath;
return ScionResponseAddress.from(receivePath);
} finally {
readLock().unlock();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.scion.jpan.ResponsePath;
import org.scion.jpan.ScionDatagramChannel;
import org.scion.jpan.ScionResponseAddress;
import org.scion.jpan.ScionService;
import org.scion.jpan.testutil.MockDNS;
import org.scion.jpan.testutil.MockDaemon;
Expand Down Expand Up @@ -128,8 +128,8 @@ private void concurrentReceive(Reader c1, Reader c2, Writer w1, boolean connect)
}

// check that receive is responsive
ResponsePath path = server.receive(buffer);
server.send(buffer, path);
ScionResponseAddress responseAddress = server.receive(buffer);
server.send(buffer, responseAddress);
// wait
synchronized (receiveCount) {
receiveCount.wait(1000);
Expand All @@ -138,7 +138,7 @@ private void concurrentReceive(Reader c1, Reader c2, Writer w1, boolean connect)

// send again to trigger 2nd receiver
buffer.flip();
server.send(buffer, path);
server.send(buffer, responseAddress);
// wait
synchronized (receiveCount) {
receiveCount.wait(1000);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ void receive_withoutService() throws IOException {
try (ScionDatagramChannel channel = ScionDatagramChannel.open(null, mock)) {
assertNull(channel.getService());
ByteBuffer buffer = ByteBuffer.allocate(100);
Path path = channel.receive(buffer);
ScionResponseAddress responseAddress = channel.receive(buffer);
assertNull(channel.getService());
assertEquals(addr, path.getFirstHopAddress());
assertEquals(addr, responseAddress.getPath().getFirstHopAddress());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.junit.jupiter.api.Test;
import org.scion.jpan.Path;
import org.scion.jpan.ScionDatagramChannel;
import org.scion.jpan.ScionResponseAddress;
import org.scion.jpan.ScionService;
import org.scion.jpan.testutil.PingPongChannelHelper;

Expand Down Expand Up @@ -56,10 +57,12 @@ private void client(ScionDatagramChannel channel, Path serverAddress, int id) th

// System.out.println("CLIENT: Receiving ... (" + channel.getLocalAddress() + ")");
ByteBuffer response = ByteBuffer.allocate(512);
Path address = channel.receive(response);
ScionResponseAddress address = channel.receive(response);
assertNotNull(address);
assertEquals(serverAddress.getRemoteAddress(), address.getRemoteAddress());
assertEquals(serverAddress.getRemotePort(), address.getRemotePort());
assertEquals(serverAddress.getRemoteAddress(), address.getPath().getRemoteAddress());
assertEquals(serverAddress.getRemotePort(), address.getPath().getRemotePort());
assertEquals(serverAddress.getRemoteAddress(), address.getAddress());
assertEquals(serverAddress.getRemotePort(), address.getPort());

response.flip();
String pong = Charset.defaultCharset().decode(response).toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.junit.jupiter.api.Test;
import org.scion.jpan.Path;
import org.scion.jpan.ScionDatagramChannel;
import org.scion.jpan.ScionResponseAddress;
import org.scion.jpan.ScionService;
import org.scion.jpan.testutil.PingPongChannelHelper;

Expand Down Expand Up @@ -50,10 +51,12 @@ private void client(ScionDatagramChannel channel, Path serverAddress, int id) th

// System.out.println("CLIENT: Receiving ... (" + channel.getLocalAddress() + ")");
ByteBuffer response = ByteBuffer.allocate(512);
Path address = channel.receive(response);
ScionResponseAddress address = channel.receive(response);
assertNotNull(address);
assertEquals(serverAddress.getRemoteAddress(), address.getRemoteAddress());
assertEquals(serverAddress.getRemotePort(), address.getRemotePort());
assertEquals(serverAddress.getRemoteAddress(), address.getAddress());
assertEquals(serverAddress.getRemotePort(), address.getPort());
assertEquals(serverAddress.getRemoteAddress(), address.getPath().getRemoteAddress());
assertEquals(serverAddress.getRemotePort(), address.getPath().getRemotePort());

response.flip();
String pong = Charset.defaultCharset().decode(response).toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@
import java.nio.charset.Charset;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
import org.scion.jpan.Path;
import org.scion.jpan.RequestPath;
import org.scion.jpan.ScionDatagramChannel;
import org.scion.jpan.ScionService;
import org.scion.jpan.*;
import org.scion.jpan.testutil.PingPongChannelHelper;

/** Test read()/write() operations on DatagramChannel connected with a path. */
Expand Down Expand Up @@ -68,7 +65,7 @@ private void client(ScionDatagramChannel channel, RequestPath serverAddress, int
private void server(ScionDatagramChannel channel) throws IOException {
ByteBuffer request = ByteBuffer.allocate(512);
// System.out.println("SERVER: --- USER - Waiting for packet --------------------- " + i);
Path path = channel.receive(request);
ScionResponseAddress responseAddress = channel.receive(request);

request.flip();
String msg = Charset.defaultCharset().decode(request).toString();
Expand All @@ -77,6 +74,6 @@ private void server(ScionDatagramChannel channel) throws IOException {

// System.out.println("SERVER: --- USER - Sending packet ---------------------- " + i);
request.flip();
channel.send(request, path);
channel.send(request, responseAddress);
}
}
13 changes: 7 additions & 6 deletions src/test/java/org/scion/jpan/api/DatagramChannelStreamTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.junit.jupiter.api.Test;
import org.scion.jpan.Path;
import org.scion.jpan.ScionDatagramChannel;
import org.scion.jpan.ScionResponseAddress;
import org.scion.jpan.ScionService;
import org.scion.jpan.testutil.MockNetwork;
import org.scion.jpan.testutil.PingPongChannelHelper;
Expand Down Expand Up @@ -71,11 +72,11 @@ private void client(ScionDatagramChannel channel, Path serverAddress, int id) th
}

private static class Pair {
Path path;
ScionResponseAddress responseAddress;
String msg;

Pair(Path path, String msg) {
this.path = path;
Pair(ScionResponseAddress responseAddress, String msg) {
this.responseAddress = responseAddress;
this.msg = msg;
}
}
Expand All @@ -88,10 +89,10 @@ public void server(ScionDatagramChannel channel) throws IOException {
ArrayList<Pair> received = new ArrayList<>();
for (int i = 0; i < N_BULK; i++) {
request.clear();
Path returnAddress = channel.receive(request);
ScionResponseAddress responseAddress = channel.receive(request);
request.flip();
String msg = Charset.defaultCharset().decode(request).toString();
received.add(new Pair(returnAddress, msg));
received.add(new Pair(responseAddress, msg));
assertTrue(msg.startsWith(PingPongChannelHelper.MSG), msg);
assertTrue(PingPongChannelHelper.MSG.length() + 3 >= msg.length());
}
Expand All @@ -105,7 +106,7 @@ public void server(ScionDatagramChannel channel) throws IOException {
request.clear();
request.put(p.msg.getBytes());
request.flip();
channel.send(request, p.path);
channel.send(request, p.responseAddress);
}
}
}
7 changes: 3 additions & 4 deletions src/test/java/org/scion/jpan/demo/PingPongChannelServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@
import java.io.*;
import java.net.*;
import java.nio.ByteBuffer;
import org.scion.jpan.Path;
import org.scion.jpan.ScionDatagramChannel;
import org.scion.jpan.ScionUtil;
import org.scion.jpan.*;

public class PingPongChannelServer {

Expand Down Expand Up @@ -54,7 +52,8 @@ private static void service() throws IOException {
channel.bind(SERVER_ADDRESS);
ByteBuffer buffer = ByteBuffer.allocate(100);
println("Waiting for packet ... ");
Path path = channel.receive(buffer);
ScionResponseAddress responseAddress = channel.receive(buffer);
ResponsePath path = responseAddress.getPath();
String msg = extractMessage(buffer);
String remoteAddress = path.getRemoteAddress() + ":" + path.getRemotePort();
String borderRouterInterfaces = ScionUtil.toStringPath(path.getRawPath());
Expand Down
13 changes: 7 additions & 6 deletions src/test/java/org/scion/jpan/testutil/PingPongChannelHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.scion.jpan.Path;
import org.scion.jpan.RequestPath;
import org.scion.jpan.ScionDatagramChannel;
import org.scion.jpan.ScionResponseAddress;

public class PingPongChannelHelper extends PingPongHelperBase {

Expand Down Expand Up @@ -136,10 +137,10 @@ public static void defaultClient(ScionDatagramChannel channel, Path serverAddres

// System.out.println("CLIENT: Receiving ... (" + channel.getLocalAddress() + ")");
ByteBuffer response = ByteBuffer.allocate(512);
Path address = channel.receive(response);
ScionResponseAddress address = channel.receive(response);
assertNotNull(address);
assertEquals(serverAddress.getRemoteAddress(), address.getRemoteAddress());
assertEquals(serverAddress.getRemotePort(), address.getRemotePort());
assertEquals(serverAddress.getRemoteAddress(), address.getAddress());
assertEquals(serverAddress.getRemotePort(), address.getPort());

response.flip();
String pong = Charset.defaultCharset().decode(response).toString();
Expand All @@ -149,15 +150,15 @@ public static void defaultClient(ScionDatagramChannel channel, Path serverAddres
public static void defaultServer(ScionDatagramChannel channel) throws IOException {
ByteBuffer request = ByteBuffer.allocate(512);
// System.out.println("SERVER: Receiving ... (" + channel.getLocalAddress() + ")");
Path address = channel.receive(request);
ScionResponseAddress responseAddress = channel.receive(request);

request.flip();
String msg = Charset.defaultCharset().decode(request).toString();
assertTrue(msg.startsWith(MSG), msg);
assertTrue(MSG.length() + 3 >= msg.length());

request.flip();
channel.send(request, address);
// System.out.println("SERVER: Sent: " + address);
channel.send(request, responseAddress);
// System.out.println("SERVER: Sent: " + responseAddress);
}
}

0 comments on commit 31502f6

Please sign in to comment.