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

send() must return 'int' #92

Merged
merged 4 commits into from
Jun 18, 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Internal cleanup. [#88](https://github.com/scionproto-contrib/jpan/pull/88)
- Deprecated `getPaths(InetSocketAddress)` because it wasn't clear that it did a SCION lookup.
[#89](https://github.com/scionproto-contrib/jpan/pull/89)
- **BREAKING CHANGE**: ScionDatagramChannel.send(buffer, path) returns 'int'.
[#92](https://github.com/scionproto-contrib/jpan/pull/92)

### Fixed
- Fixed locking and resizing of buffers. [#68](https://github.com/scionproto-contrib/jpan/pull/68)
Expand Down
45 changes: 10 additions & 35 deletions src/main/java/org/scion/jpan/AbstractDatagramChannel.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.nio.channels.ClosedChannelException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.NotYetConnectedException;
import java.time.Instant;
import java.util.Objects;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
Expand Down Expand Up @@ -496,6 +495,10 @@ public <T> C setOption(SocketOption<T> option, T t) throws IOException {
}
}

protected int getCfgExpirationSafetyMargin() {
return cfgExpirationSafetyMargin;
}

private void checkLockedForRead() {
if (!readLock().isLocked()) {
throw new IllegalStateException("Access must be READ locked!");
Expand Down Expand Up @@ -532,24 +535,6 @@ protected final ByteBuffer getBufferReceive(int requiredSize) {
return bufferReceive;
}

/**
* @param path path
* @param payloadLength payload length
* @return argument path or a new path if the argument path was expired
* @throws IOException in case of IOException.
*/
protected Path checkPathAndBuildHeader(
ByteBuffer buffer, Path path, int payloadLength, InternalConstants.HdrTypes hdrType)
throws IOException {
synchronized (stateLock) {
if (path instanceof RequestPath) {
path = ensureUpToDate((RequestPath) path);
}
buildHeader(buffer, path, payloadLength, hdrType);
return path;
}
}

/**
* @param buffer The output buffer
* @param path path
Expand Down Expand Up @@ -622,23 +607,9 @@ protected void buildHeader(
}
}

protected RequestPath ensureUpToDate(RequestPath path) throws IOException {
synchronized (stateLock) {
if (Instant.now().getEpochSecond() + cfgExpirationSafetyMargin <= path.getExpiration()) {
return path;
}
// expired, get new path
RequestPath newPath = pathPolicy.filter(getOrCreateService().getPaths(path));
if (isConnected()) {
updateConnection(newPath, true);
}
return newPath;
}
}

private void updateConnection(RequestPath newPath, boolean mustBeConnected) throws IOException {
protected void updateConnection(RequestPath newPath, boolean mustBeConnected) throws IOException {
if (mustBeConnected && !isConnected()) {
throw new IllegalStateException();
return;
}
// update connected path
connectionPath = newPath;
Expand Down Expand Up @@ -672,4 +643,8 @@ protected ReentrantLock readLock() {
protected ReentrantLock writeLock() {
return writeLock;
}

protected Object stateLock() {
return stateLock;
}
}
300 changes: 300 additions & 0 deletions src/main/java/org/scion/jpan/PathMetadata.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,300 @@
// Copyright 2023 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.io.UncheckedIOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.scion.jpan.internal.IPHelper;
import org.scion.jpan.proto.daemon.Daemon;

/**
* PathMetadata contains the raw path and meta information such as bandwidth, latency or geo
* coordinates. PathMetadata is available from RequestPaths that are created/returned by the
* ScionService when requesting a new path from the control service.
*/
public class PathMetadata {

private final Daemon.Path pathProtoc;
private final byte[] pathRaw;
// We store the first hop separately to void creating unnecessary objects.
private final InetSocketAddress firstHop;

static PathMetadata create(Daemon.Path path, InetAddress dstIP, int dstPort) {
return new PathMetadata(path, dstIP, dstPort);

Check warning on line 40 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L40

Added line #L40 was not covered by tests
}

private PathMetadata(Daemon.Path path, InetAddress dstIP, int dstPort) {
this.pathProtoc = path;
this.pathRaw = path.getRaw().toByteArray();

Check warning on line 45 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L43-L45

Added lines #L43 - L45 were not covered by tests
if (getRawPath().length == 0) {
// local AS has path length 0
firstHop = new InetSocketAddress(dstIP, dstPort);

Check warning on line 48 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L48

Added line #L48 was not covered by tests
} else {
firstHop = getFirstHopAddress(path);

Check warning on line 50 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L50

Added line #L50 was not covered by tests
}
}

Check warning on line 52 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L52

Added line #L52 was not covered by tests

private InetSocketAddress getFirstHopAddress(Daemon.Path internalPath) {
try {
String underlayAddressString = internalPath.getInterface().getAddress().getAddress();
int splitIndex = underlayAddressString.indexOf(':');
InetAddress ip = IPHelper.toInetAddress(underlayAddressString.substring(0, splitIndex));
int port = Integer.parseUnsignedInt(underlayAddressString.substring(splitIndex + 1));
return new InetSocketAddress(ip, port);
} catch (UnknownHostException e) {

Check warning on line 61 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L56-L61

Added lines #L56 - L61 were not covered by tests
// This really should never happen, the first hop is a literal IP address.
throw new UncheckedIOException(e);

Check warning on line 63 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L63

Added line #L63 was not covered by tests
}
}

private Daemon.Path protoPath() {
if (pathProtoc == null) {
throw new IllegalStateException(

Check warning on line 69 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L69

Added line #L69 was not covered by tests
"Information is only available for paths that"
+ " were retrieved directly from a path server.");
}
return pathProtoc;

Check warning on line 73 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L73

Added line #L73 was not covered by tests
}

public InetSocketAddress getFirstHopAddress() throws UnknownHostException {
return firstHop;

Check warning on line 77 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L77

Added line #L77 was not covered by tests
}

public byte[] getRawPath() {
return pathRaw;

Check warning on line 81 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L81

Added line #L81 was not covered by tests
}

/**
* @return Interface for exiting the local AS using this path.
* @throws IllegalStateException if this is path is only a raw path
*/
public Interface getInterface() {
return new Interface(protoPath().getInterface());

Check warning on line 89 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L89

Added line #L89 was not covered by tests
}

/**
* @return The list of interfaces the path is composed of.
* @throws IllegalStateException if this is path is only a raw path
*/
public List<PathInterface> getInterfacesList() {
return Collections.unmodifiableList(
protoPath().getInterfacesList().stream()
.map(PathInterface::new)
.collect(Collectors.toList()));

Check warning on line 100 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L97-L100

Added lines #L97 - L100 were not covered by tests
}

/**
* @return The maximum transmission unit (MTU) on the path.
* @throws IllegalStateException if this is path is only a raw path
*/
public int getMtu() {
return protoPath().getMtu();

Check warning on line 108 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L108

Added line #L108 was not covered by tests
}

/**
* @return The point in time when this path expires. In seconds since UNIX epoch.
* @throws IllegalStateException if this is path is only a raw path
*/
public long getExpiration() {
return protoPath().getExpiration().getSeconds();

Check warning on line 116 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L116

Added line #L116 was not covered by tests
}

/**
* @return Latency lists the latencies between any two consecutive interfaces. Entry i describes
* the latency between interface i and i+1. Consequently, there are N-1 entries for N
* interfaces. A 0-value indicates that the AS did not announce a latency for this hop.
* @throws IllegalStateException if this is path is only a raw path
*/
public List<Integer> getLatencyList() {
return Collections.unmodifiableList(
protoPath().getLatencyList().stream()
.map(time -> (int) (time.getSeconds() * 1_000 + time.getNanos() / 1_000_000))
.collect(Collectors.toList()));

Check warning on line 129 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L126-L129

Added lines #L126 - L129 were not covered by tests
}

/**
* @return Bandwidth lists the bandwidth between any two consecutive interfaces, in Kbit/s. Entry
* i describes the bandwidth between interfaces i and i+1. A 0-value indicates that the AS did
* not announce a bandwidth for this hop.
* @throws IllegalStateException if this is path is only a raw path
*/
public List<Long> getBandwidthList() {
return protoPath().getBandwidthList();

Check warning on line 139 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L139

Added line #L139 was not covered by tests
}

/**
* @return Geo lists the geographical position of the border routers along the path. Entry i
* describes the position of the router for interface i. A 0-value indicates that the AS did
* not announce a position for this router.
* @throws IllegalStateException if this is path is only a raw path
*/
public List<GeoCoordinates> getGeoList() {
return Collections.unmodifiableList(
protoPath().getGeoList().stream().map(GeoCoordinates::new).collect(Collectors.toList()));

Check warning on line 150 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L149-L150

Added lines #L149 - L150 were not covered by tests
}

/**
* @return LinkType contains the announced link type of inter-domain links. Entry i describes the
* link between interfaces 2*i and 2*i+1.
* @throws IllegalStateException if this is path is only a raw path
*/
public List<LinkType> getLinkTypeList() {
return Collections.unmodifiableList(
protoPath().getLinkTypeList().stream()
.map(linkType -> LinkType.values()[linkType.getNumber()])
.collect(Collectors.toList()));

Check warning on line 162 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L159-L162

Added lines #L159 - L162 were not covered by tests
}

/**
* @return InternalHops lists the number of AS internal hops for the ASes on path. Entry i
* describes the hop between interfaces 2*i+1 and 2*i+2 in the same AS. Consequently, there
* are no entries for the first and last ASes, as these are not traversed completely by the
* path.
* @throws IllegalStateException if this is path is only a raw path
*/
public List<Integer> getInternalHopsList() {
return protoPath().getInternalHopsList();

Check warning on line 173 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L173

Added line #L173 was not covered by tests
}

/**
* @return Notes contains the notes added by ASes on the path, in the order of occurrence. Entry i
* is the note of AS i on the path.
* @throws IllegalStateException if this is path is only a raw path
*/
public List<String> getNotesList() {
return protoPath().getNotesList();

Check warning on line 182 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L182

Added line #L182 was not covered by tests
}

/**
* @return EpicAuths contains the EPIC authenticators used to calculate the PHVF and LHVF.
* @throws IllegalStateException if this is path is only a raw path
*/
public EpicAuths getEpicAuths() {
return new EpicAuths(protoPath().getEpicAuths());

Check warning on line 190 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L190

Added line #L190 was not covered by tests
}

public enum LinkType {

Check warning on line 193 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L193

Added line #L193 was not covered by tests
/** Unspecified link type. */
LINK_TYPE_UNSPECIFIED, // = 0

Check warning on line 195 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L195

Added line #L195 was not covered by tests
/** Direct physical connection. */
LINK_TYPE_DIRECT, // = 1

Check warning on line 197 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L197

Added line #L197 was not covered by tests
/** Connection with local routing/switching. */
LINK_TYPE_MULTI_HOP, // = 2

Check warning on line 199 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L199

Added line #L199 was not covered by tests
/** Connection overlayed over publicly routed Internet. */
LINK_TYPE_OPEN_NET, // = 3

Check warning on line 201 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L201

Added line #L201 was not covered by tests
}

public static class EpicAuths {
private final byte[] authPhvf;
private final byte[] authLhvf;

private EpicAuths(Daemon.EpicAuths epicAuths) {
this.authPhvf = epicAuths.getAuthPhvf().toByteArray();
this.authLhvf = epicAuths.getAuthLhvf().toByteArray();
}

Check warning on line 211 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L208-L211

Added lines #L208 - L211 were not covered by tests

/**
* @return AuthPHVF is the authenticator use to calculate the PHVF.
*/
public byte[] getAuthPhvf() {
return authPhvf;

Check warning on line 217 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L217

Added line #L217 was not covered by tests
}

/**
* @return AuthLHVF is the authenticator use to calculate the LHVF.
*/
public byte[] getAuthLhvf() {
return authLhvf;

Check warning on line 224 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L224

Added line #L224 was not covered by tests
}
}

public static class Interface {
private final String address;

private Interface(Daemon.Interface inter) {
this.address = inter.getAddress().getAddress();
}

Check warning on line 233 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L231-L233

Added lines #L231 - L233 were not covered by tests

/**
* @return Underlay address to exit through the interface.
*/
public String getAddress() {
return address;

Check warning on line 239 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L239

Added line #L239 was not covered by tests
}
}

public static class PathInterface {
private final long isdAs;

private final long id;

private PathInterface(Daemon.PathInterface pathInterface) {
this.isdAs = pathInterface.getIsdAs();
this.id = pathInterface.getId();
}

Check warning on line 251 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L248-L251

Added lines #L248 - L251 were not covered by tests

/**
* @return ISD-AS the interface belongs to.
*/
public long getIsdAs() {
return isdAs;

Check warning on line 257 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L257

Added line #L257 was not covered by tests
}

/**
* @return ID of the interface in the AS.
*/
public long getId() {
return id;

Check warning on line 264 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L264

Added line #L264 was not covered by tests
}
}

public static class GeoCoordinates {
private final float latitude;
private final float longitude;
private final String address;

private GeoCoordinates(Daemon.GeoCoordinates geoCoordinates) {
this.latitude = geoCoordinates.getLatitude();
this.longitude = geoCoordinates.getLongitude();
this.address = geoCoordinates.getAddress();
}

Check warning on line 277 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L273-L277

Added lines #L273 - L277 were not covered by tests

/**
* @return Latitude of the geographic coordinate, in the WGS 84 datum.
*/
public float getLatitude() {
return latitude;

Check warning on line 283 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L283

Added line #L283 was not covered by tests
}

/**
* @return Longitude of the geographic coordinate, in the WGS 84 datum.
*/
public float getLongitude() {
return longitude;

Check warning on line 290 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L290

Added line #L290 was not covered by tests
}

/**
* @return Civic address of the location.
*/
public String getAddress() {
return address;

Check warning on line 297 in src/main/java/org/scion/jpan/PathMetadata.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/org/scion/jpan/PathMetadata.java#L297

Added line #L297 was not covered by tests
}
}
}
Loading