Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Path-aware subclasses InetSocketAddress #86

Merged
merged 2 commits into from
Jun 10, 2024
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
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);
}
}