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

1.1.1 Release #367

Merged
merged 12 commits into from
May 22, 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
55 changes: 55 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Bug Report
description: Create a bug report for jvm-libp2p

body:
- type: markdown
attributes:
value: |
Thank you for filing a bug report!
- type: textarea
attributes:
label: Summary
description: Please provide a short summary of the bug, along with any information you feel relevant to replicate the bug.
validations:
required: true
- type: textarea
attributes:
label: Expected behavior
description: Describe what you expect to happen.
validations:
required: true
- type: textarea
attributes:
label: Actual behavior
description: Describe what actually happens.
validations:
required: true
- type: textarea
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
validations:
required: false
- type: textarea
attributes:
label: Possible Solution
description: Suggest a fix/reason for the bug, or ideas how to implement the addition or change.
validations:
required: false
- type: textarea
attributes:
label: Version
description: Which version of libp2p are you using? libp2p version (version number, commit, or branch)
validations:
required: false
- type: dropdown
attributes:
label: Would you like to work on fixing this bug ?
description: Any contribution towards fixing the bug is greatly appreciated. We are more than happy to provide help on the process.
options:
- "Yes"
- "No"
- Maybe
validations:
required: true
8 changes: 8 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
blank_issues_enabled: true
contact_links:
- name: Technical Questions
url: https://github.com/libp2p/jvm-libp2p/discussions/new?category=q-a
about: Please ask technical questions in the jvm-libp2p Github Discussions forum.
- name: Community-wide libp2p Discussion
url: https://discuss.libp2p.io
about: Discussions and questions about the libp2p community.
31 changes: 31 additions & 0 deletions .github/ISSUE_TEMPLATE/enhancement.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Enhancement
description: Suggest an improvement to an existing jvm-libp2p feature.
body:
- type: textarea
attributes:
label: Description
description: Describe the enhancement that you are proposing.
validations:
required: true
- type: textarea
attributes:
label: Motivation
description: Explain why this enhancement is beneficial.
validations:
required: true
- type: textarea
attributes:
label: Current Implementation
description: Describe the current implementation.
validations:
required: true
- type: dropdown
attributes:
label: Are you planning to do it yourself in a pull request ?
description: Any contribution is greatly appreciated. We are more than happy to provide help on the process.
options:
- "Yes"
- "No"
- Maybe
validations:
required: true
42 changes: 42 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Feature request
description: Suggest a new feature in jvm-libp2p
body:
- type: markdown
attributes:
value: |
If you'd like to suggest a feature related to libp2p but not specifically related to the JVM implementation, please file an issue at https://github.com/libp2p/specs instead.
- type: textarea
attributes:
label: Description
description: Briefly describe the feature that you are requesting.
validations:
required: true
- type: textarea
attributes:
label: Motivation
description: Explain why this feature is needed.
validations:
required: true
- type: textarea
attributes:
label: Requirements
description: Write a list of what you want this feature to do.
placeholder: "1."
validations:
required: true
- type: textarea
attributes:
label: Open questions
description: Use this section to ask any questions that are related to the feature.
validations:
required: false
- type: dropdown
attributes:
label: Are you planning to do it yourself in a pull request ?
description: Any contribution is greatly appreciated. We are more than happy to provide help on the process.
options:
- "Yes"
- "No"
- Maybe
validations:
required: true
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ List of components in the Libp2p spec and their JVM implementation status
| **Stream Multiplexing** | [yamux](https://github.com/libp2p/specs/blob/master/yamux/README.md) | :lemon: |
| | [mplex](https://github.com/libp2p/specs/blob/master/mplex/README.md) | :green_apple: |
| **NAT Traversal** | [circuit-relay-v2](https://github.com/libp2p/specs/blob/master/relay/circuit-v2.md) | :lemon: |
| | [autonat](https://github.com/libp2p/specs/tree/master/autonat) | |
| | [autonat](https://github.com/libp2p/specs/tree/master/autonat) | :lemon: |
| | [hole-punching](https://github.com/libp2p/specs/blob/master/connections/hole-punching.md) | |
| **Discovery** | [bootstrap](https://github.com/libp2p/specs/blob/master/kad-dht/README.md#bootstrap-process) | |
| | random-walk | |
Expand Down
4 changes: 2 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ plugins {
id("io.gitlab.arturbosch.detekt").version("1.22.0")
id("java")
id("maven-publish")
id("org.jetbrains.dokka").version("1.9.0")
id("org.jetbrains.dokka").version("1.9.20")
id("com.diffplug.spotless").version("6.21.0")
id("java-test-fixtures")
id("io.spring.dependency-management").version("1.1.3")
Expand All @@ -37,7 +37,7 @@ configure(
}
) {
group = "io.libp2p"
version = "1.1.0-RELEASE"
version = "1.1.1-RELEASE"

apply(plugin = "kotlin")
apply(plugin = "idea")
Expand Down
172 changes: 172 additions & 0 deletions libp2p/src/main/java/io/libp2p/protocol/autonat/AutonatProtocol.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
package io.libp2p.protocol.autonat;

import com.google.protobuf.*;
import io.libp2p.core.*;
import io.libp2p.core.Stream;
import io.libp2p.core.multiformats.*;
import io.libp2p.core.multistream.*;
import io.libp2p.protocol.*;
import io.libp2p.protocol.autonat.pb.*;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.*;
import org.jetbrains.annotations.*;

public class AutonatProtocol extends ProtobufProtocolHandler<AutonatProtocol.AutoNatController> {

public static class Binding extends StrictProtocolBinding<AutoNatController> {
public Binding() {
super("/libp2p/autonat/v1.0.0", new AutonatProtocol());
}
}

public interface AutoNatController {
CompletableFuture<Autonat.Message> rpc(Autonat.Message req);

default CompletableFuture<Autonat.Message.DialResponse> requestDial(
PeerId ourId, List<Multiaddr> us) {
if (us.isEmpty())
throw new IllegalStateException("Requested autonat dial with no addresses!");
return rpc(Autonat.Message.newBuilder()
.setType(Autonat.Message.MessageType.DIAL)
.setDial(
Autonat.Message.Dial.newBuilder()
.setPeer(
Autonat.Message.PeerInfo.newBuilder()
.addAllAddrs(
us.stream()
.map(a -> ByteString.copyFrom(a.serialize()))
.collect(Collectors.toList()))
.setId(ByteString.copyFrom(ourId.getBytes()))))
.build())
.thenApply(msg -> msg.getDialResponse());
}
}

public static class Sender implements ProtocolMessageHandler<Autonat.Message>, AutoNatController {
private final Stream stream;
private final LinkedBlockingDeque<CompletableFuture<Autonat.Message>> queue =
new LinkedBlockingDeque<>();

public Sender(Stream stream) {
this.stream = stream;
}

@Override
public void onMessage(@NotNull Stream stream, Autonat.Message msg) {
queue.poll().complete(msg);
}

public CompletableFuture<Autonat.Message> rpc(Autonat.Message req) {
CompletableFuture<Autonat.Message> res = new CompletableFuture<>();
queue.add(res);
stream.writeAndFlush(req);
return res;
}
}

private static boolean sameIP(Multiaddr a, Multiaddr b) {
if (a.has(Protocol.IP4))
return a.getFirstComponent(Protocol.IP4).equals(b.getFirstComponent(Protocol.IP4));
if (a.has(Protocol.IP6))
return a.getFirstComponent(Protocol.IP6).equals(b.getFirstComponent(Protocol.IP6));
return false;
}

private static boolean reachableIP(Multiaddr a) {
try {
if (a.has(Protocol.IP4))
return InetAddress.getByName(a.getFirstComponent(Protocol.IP4).getStringValue())
.isReachable(1000);
if (a.has(Protocol.IP6))
return InetAddress.getByName(a.getFirstComponent(Protocol.IP6).getStringValue())
.isReachable(1000);
} catch (IOException e) {
}
return false;
}

public static class Receiver
implements ProtocolMessageHandler<Autonat.Message>, AutoNatController {
private final Stream p2pstream;

public Receiver(Stream p2pstream) {
this.p2pstream = p2pstream;
}

@Override
public void onMessage(@NotNull Stream stream, Autonat.Message msg) {
switch (msg.getType()) {
case DIAL:
{
Autonat.Message.Dial dial = msg.getDial();
PeerId peerId = new PeerId(dial.getPeer().getId().toByteArray());
List<Multiaddr> requestedDials =
dial.getPeer().getAddrsList().stream()
.map(s -> Multiaddr.deserialize(s.toByteArray()))
.collect(Collectors.toList());
PeerId streamPeerId = stream.remotePeerId();
if (!peerId.equals(streamPeerId)) {
p2pstream.close();
return;
}

Multiaddr remote = stream.getConnection().remoteAddress();
Optional<Multiaddr> reachable =
requestedDials.stream()
.filter(a -> sameIP(a, remote))
.filter(a -> !a.has(Protocol.P2PCIRCUIT))
.filter(a -> reachableIP(a))
.findAny();
Autonat.Message.Builder resp =
Autonat.Message.newBuilder().setType(Autonat.Message.MessageType.DIAL_RESPONSE);
if (reachable.isPresent()) {
resp =
resp.setDialResponse(
Autonat.Message.DialResponse.newBuilder()
.setStatus(Autonat.Message.ResponseStatus.OK)
.setAddr(ByteString.copyFrom(reachable.get().serialize())));
} else {
resp =
resp.setDialResponse(
Autonat.Message.DialResponse.newBuilder()
.setStatus(Autonat.Message.ResponseStatus.E_DIAL_ERROR));
}
p2pstream.writeAndFlush(resp);
}
default:
{
}
}
}

public CompletableFuture<Autonat.Message> rpc(Autonat.Message msg) {
return CompletableFuture.failedFuture(
new IllegalStateException("Cannot send form a receiver!"));
}
}

private static final int TRAFFIC_LIMIT = 2 * 1024;

public AutonatProtocol() {
super(Autonat.Message.getDefaultInstance(), TRAFFIC_LIMIT, TRAFFIC_LIMIT);
}

@NotNull
@Override
protected CompletableFuture<AutoNatController> onStartInitiator(@NotNull Stream stream) {
Sender replyPropagator = new Sender(stream);
stream.pushHandler(replyPropagator);
return CompletableFuture.completedFuture(replyPropagator);
}

@NotNull
@Override
protected CompletableFuture<AutoNatController> onStartResponder(@NotNull Stream stream) {
Receiver dialer = new Receiver(stream);
stream.pushHandler(dialer);
return CompletableFuture.completedFuture(dialer);
}
}
9 changes: 8 additions & 1 deletion libp2p/src/main/kotlin/io/libp2p/discovery/MDnsDiscovery.kt
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,14 @@ class MDnsDiscovery(
val address = host.listenAddresses().find {
it.has(Protocol.IP4)
}
val str = address?.getFirstComponent(Protocol.TCP)?.stringValue!!
val ipv6OnlyAddress = if (address == null) {
host.listenAddresses().find {
it.has(Protocol.IP6)
}
} else {
address
}
val str = ipv6OnlyAddress?.getFirstComponent(Protocol.TCP)?.stringValue!!
return Integer.parseInt(str)
}

Expand Down
6 changes: 5 additions & 1 deletion libp2p/src/main/kotlin/io/libp2p/pubsub/AbstractRouter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,11 @@ abstract class AbstractRouter(

override fun getPeerTopics(): CompletableFuture<Map<PeerId, Set<Topic>>> {
return submitOnEventThread {
peersTopics.asFirstToSecondMap().mapKeys { it.key.peerId }
peersTopics.asFirstToSecondMap()
.map { (key, value) ->
key.peerId to value.toSet()
}
.toMap()
}
}

Expand Down
10 changes: 7 additions & 3 deletions libp2p/src/main/kotlin/io/libp2p/pubsub/gossip/GossipRouter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,10 @@ open class GossipRouter(
}

private fun handleIHave(msg: Rpc.ControlIHave, peer: PeerHandler) {
// we ignore IHAVE gossip for unknown topics
if (msg.hasTopicID() && !mesh.containsKey(msg.topicID)) {
return
}
val peerScore = score.score(peer.peerId)
// we ignore IHAVE gossip from any peer whose score is below the gossip threshold
if (peerScore < scoreParams.gossipThreshold) return
Expand Down Expand Up @@ -544,7 +548,7 @@ open class GossipRouter(

peers.shuffled(random)
.take(max((params.gossipFactor * peers.size).toInt(), params.DLazy))
.forEach { enqueueIhave(it, shuffledMessageIds) }
.forEach { enqueueIhave(it, shuffledMessageIds, topic) }
}

private fun graft(peer: PeerHandler, topic: Topic) {
Expand Down Expand Up @@ -587,8 +591,8 @@ open class GossipRouter(
private fun enqueueIwant(peer: PeerHandler, messageIds: List<MessageId>) =
pendingRpcParts.getQueue(peer).addIWants(messageIds)

private fun enqueueIhave(peer: PeerHandler, messageIds: List<MessageId>) =
pendingRpcParts.getQueue(peer).addIHaves(messageIds)
private fun enqueueIhave(peer: PeerHandler, messageIds: List<MessageId>, topic: Topic) =
pendingRpcParts.getQueue(peer).addIHaves(messageIds, topic)

data class AcceptRequestsWhitelistEntry(val whitelistedTill: Long, val messagesAccepted: Int = 0) {
fun incrementMessageCount() = AcceptRequestsWhitelistEntry(whitelistedTill, messagesAccepted + 1)
Expand Down
Loading
Loading