Giter Club home page Giter Club logo

Comments (25)

sukunrt avatar sukunrt commented on June 11, 2024 1

This is not on the road map right now. However, https://docs.rs/libp2p/latest/libp2p/tutorials/hole_punching/index.html is a good introduction and maps well to the go implementation too.

from go-libp2p.

zhuwei avatar zhuwei commented on June 11, 2024 1

I also need it. Although I understand the principle, I cannot implement it using go-libp2p. Can someone provide a simple example?

from go-libp2p.

sukunrt avatar sukunrt commented on June 11, 2024 1

You don't need to implemenent anything. If you run go-libp2p with EnableHolepunching option it'll hole punch when it can.

If you can share more specific questions around what you do not understand in https://docs.rs/libp2p/latest/libp2p/tutorials/hole_punching/index.html, I'd be happy to answer.

from go-libp2p.

Jorropo avatar Jorropo commented on June 11, 2024 1

For lack of something better you can look at Kubo's implementation:
https://github.com/ipfs/kubo/blob/master/core/node/libp2p/relay.go

from go-libp2p.

Jorropo avatar Jorropo commented on June 11, 2024 1

Q1: I'm fairly sure EnableHolePunching should be passed to both nodes that wish to connect, it is not required on the relay.

Q2.1: you can find the multiaddr by calling host.Addrs() on a relayed host, you can use a notify or the event bus to receive a notification when the relay addresses have been added.
The address you shared should work (however it requires a routing system or OOB knowledge of the relay's address), in general you can do relayMaddr + "/p2p-circuit/p2p/" + peerid so example would be /ip4/1.2.3.4/udp/12345/quic-v1/p2p/RelayPeerid/p2p-circuit/p2p/DestinationPeerid

Q2.2: when you use a relay v2 with hole punching traffic is not sent on the relay, if you are using the latest release, NewStream will wait until a direct connection has been established (you can use a magic incantation to make it establish a stream on the relayed connection but you probably don't want to), if you are using a previous version NewStream will error if you try to use it before a direct connection has been established.


Note on Q1: you shouldn't need to do the address yourself, take what host.Addrs() gives you and share that as-is.

from go-libp2p.

xiguamee avatar xiguamee commented on June 11, 2024

You don't need to implemenent anything. If you run go-libp2p with EnableHolepunching option it'll hole punch when it can.

If you can share more specific questions around what you do not understand in https://docs.rs/libp2p/latest/libp2p/tutorials/hole_punching/index.html, I'd be happy to answer.

Thank you! It seems that the examples are in Rust. Now i am using the GoLang and I got an example from the Internet that I've forked. I will try to finish it with your document and that example. Thanks for
your answer~❤️ I will be back here when meeting the problem that I can't overcome.☃️

from go-libp2p.

zhuwei avatar zhuwei commented on June 11, 2024

You don't need to implemenent anything. If you run go-libp2p with EnableHolepunching option it'll hole punch when it can.
If you can share more specific questions around what you do not understand in https://docs.rs/libp2p/latest/libp2p/tutorials/hole_punching/index.html, I'd be happy to answer.

Thank you! It seems that the examples are in Rust. Now i am using the GoLang and I got an example from the Internet that I've forked. I will try to finish it with your document and that example. Thanks for your answer~❤️ I will be back here when meeting the problem that I can't overcome.☃️

Can you share an example?

from go-libp2p.

xiguamee avatar xiguamee commented on June 11, 2024

You don't need to implemenent anything. If you run go-libp2p with EnableHolepunching option it'll hole punch when it can.
If you can share more specific questions around what you do not understand in https://docs.rs/libp2p/latest/libp2p/tutorials/hole_punching/index.html, I'd be happy to answer.

Thank you! It seems that the examples are in Rust. Now i am using the GoLang and I got an example from the Internet that I've forked. I will try to finish it with your document and that example. Thanks for your answer~❤️ I will be back here when meeting the problem that I can't overcome.☃️

Can you share an example?

Yes, you can go to my homepage to find it which I'v forked.

from go-libp2p.

xiguamee avatar xiguamee commented on June 11, 2024

For lack of something better you can look at Kubo's implementation: https://github.com/ipfs/kubo/blob/master/core/node/libp2p/relay.go

Thanks you for the lead!❤️ I'll try to make it happen~

from go-libp2p.

xiguamee avatar xiguamee commented on June 11, 2024

You don't need to implemenent anything. If you run go-libp2p with EnableHolepunching option it'll hole punch when it can.

If you can share more specific questions around what you do not understand in https://docs.rs/libp2p/latest/libp2p/tutorials/hole_punching/index.html, I'd be happy to answer.

Thank you! I've solved it. It just need an option WithInfiniteLimits to break the realy-server's limitation, and now I can build a long-trem stream through the realy-server. o( ̄▽ ̄)ブ😊

Hi! I am doing with the relay-server and now I have host A and host B in diffirent NAT. After A taking a connection with B through the relay-server, A could use transient to create a short-time stream to B like this ss, err := (*local.host).NewStream(network.WithUseTransient(a.ctx, "chat"), peerID, "/chat/1.0.0"). But when I use this ss, err := (*local.host).NewStream(a.ctx, peerID, "/chat/1.0.0") without transient, there will be no stream founded. The err is failed to open stream: context deadline exceeded.
I want to know why is it like this and what should I do to have a long-term stream through relay-server.

from go-libp2p.

xiguamee avatar xiguamee commented on June 11, 2024

You don't need to implemenent anything. If you run go-libp2p with EnableHolepunching option it'll hole punch when it can.

If you can share more specific questions around what you do not understand in https://docs.rs/libp2p/latest/libp2p/tutorials/hole_punching/index.html, I'd be happy to answer.

Hi!!! I have two questions, it was so hard for me to find some latest-version go-libp2p hole-puching guide, so can you help me!!!!

Q1: Is the option libp2p.EnableHolePunching() only needed in the client host? Is there any option needed for the relay?

Q2: Now I have Host A and Host B in diffrient NAT, and they all have a connection with the relay. What multiaddress should they use to connect each other? Now I'm using multiaddr.NewMultiaddr("/p2p/" + relayid + "/p2p-circuit/p2p/" + peerid) to connect. Is that means they still using the relay to transmit the connection? What should I do to establish the direct connection?

from go-libp2p.

xiguamee avatar xiguamee commented on June 11, 2024

Q1:我相当确定EnableHolePunching应该传递给希望连接的两个节点,中继上不需要它。

Q2.1:您可以通过调用中继主机来找到多地址host.Addrs()​​,您可以使用通知或事件总线在添加中继地址时接收通知。 您共享的地址应该可以工作(但是它需要路由系统或中继地址的 OOB 知识),一般来说您可以relayMaddr + "/p2p-circuit/p2p/" + peerid这样做,例如/ip4/1.2.3.4/udp/12345/quic-v1/p2p/RelayPeerid/p2p-circuit/p2p/DestinationPeerid

Q2.2:当您使用带有打洞功能的中继 v2 时,中继上不会发送流量,如果您使用的是最新版本,NewStream 将等待直到建立直接连接(您可以使用魔法咒语使其建立)中继连接上的流,但您可能不想这样做),如果您使用的是以前的版本,如果您在建立直接连接之前尝试使用它,NewStream 将出错。

关于问题 1 的注意事项:您不需要自己编写地址,只需拿给host.Addrs()您的内容并按原样分享即可。

Thank you!

And I wanna know how to confirm that a hole-punching has happened. Now my code is like this

destination := "/ip4/106.15.180.40/tcp/55555/p2p/12D3KooWL6LJYwzmLj9Ny4WRYeYg6T58HrMPuhChNs8RfkQuCJhf/p2p-circuit/p2p/" + peerid
maddr, _ := multiaddr.NewMultiaddr(destination)
info, _ := peer.AddrInfoFromP2pAddr(maddr)
(*local.host).Peerstore().AddAddr(info.ID, info.Addrs[0], peerstore.PermanentAddrTTL)
s, err := (*local.host).NewStream(a.ctx, info.ID, "/chat/1.0.0")

The peerid is the receiver's p2pID, and I have set the EnableHolePunching when the peer started on both side. But the connection is still founded through the relay. When I trun off the relay, they will lose their stream. Why the hole-punching not happened. Is there something wrong with the destinationpeer's maddr or other? Or is that means I need to create a new Stream?

from go-libp2p.

Jorropo avatar Jorropo commented on June 11, 2024
s, err := (*local.host).NewStream(a.ctx, info.ID, "/chat/1.0.0")

Do you get anything in err ?
You can try this if it just remains stuck:

ctx, cancel := context.WithTimeout(a.ctx, time.Second * 15)
defer cancel()
s, err := (*local.host).NewStream(ctx, info.ID, "/chat/1.0.0")

from go-libp2p.

xiguamee avatar xiguamee commented on June 11, 2024
s, err := (*local.host).NewStream(a.ctx, info.ID, "/chat/1.0.0")

你有什么东西进来吗err? 如果它仍然卡住,您可以尝试此操作:

ctx, cancel := context.WithTimeout(a.ctx, time.Second * 15)
defer cancel()
s, err := (*local.host).NewStream(ctx, info.ID, "/chat/1.0.0")

There was no error when I run it. It seems that there no attempt to punch a hole, for the A immediately had a connection to B within 0.5s. But I am sure I set the EnableHolePunching option like this
localHost, _ := libp2p.New( libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/0"), libp2p.Identity(priv), libp2p.EnableRelay(), libp2p.EnableHolePunching(), )

from go-libp2p.

Jorropo avatar Jorropo commented on June 11, 2024

How do you know no attempt to hole punch ?
Does NewStream returns nil error ?

If yes can you please show:

fmt.Println(s.Conn().RemoteMultiaddr())

from go-libp2p.

xiguamee avatar xiguamee commented on June 11, 2024

How do you know no attempt to hole punch ? Does NewStream returns nil error ?

Yes, the error is nil. And here is the result of fmt.Println(s.Conn().RemoteMultiaddr())
/ip4/106.15.180.40/tcp/55555/p2p/12D3KooWL6LJYwzmLj9Ny4WRYeYg6T58HrMPuhChNs8RfkQuCJhf/p2p-circuit
Because the connection was founded so fast, in my opinion, the hole-punching should need a bit more time to realize.

from go-libp2p.

Jorropo avatar Jorropo commented on June 11, 2024

What versions of go-libp2p are you using ?

from go-libp2p.

xiguamee avatar xiguamee commented on June 11, 2024

What versions of go-libp2p are you using ?

Both on relay and client are go-libp2p v0.32.1, and the package used in relay is github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay and github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client in client.

Is there something notification when the hole-punching happens?

from go-libp2p.

Jorropo avatar Jorropo commented on June 11, 2024

This is surprising NewStream should not open on the relayed connection, can you your code please ?

from go-libp2p.

xiguamee avatar xiguamee commented on June 11, 2024

Yes, my project is using the wails. So let me send the whole project for you. I am not familiar with the github operation so let me use the transfer website . It is here https://f.ws59.cn/f/cqx9od6cv1d , please just click the blue button "下载" to download it. The main code is in the file app.go. Thank you!❤

My relay is operated on the Alibaba Cloud, the relay's multiaddr has been inserted in the code.

And below is the relay code:

package main

import (
	"fmt"
	"github.com/libp2p.go-libp2p/core/crypto"
	"github.com/libp2p/go-libp2p"
	"github.com/libp2p/go-libp2p/core/host"
	"github.com/libp2p/go-libp2p/core/peer"
	"github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay"
	"log"
	"strings"
)

var (
	localrelay host.Host
)

func main() {
	makeRelayHost()
	_, err := relay.New(localrelay, relay.WithInfiniteLimits())
	if err != nil {
		log.Printf("Failed to instantiate the relay: %s", err)
		return
	}
	localrelayinfo := peer.AddrInfo{
		ID:    localrelay.ID(),
		Addrs: localrelay.Addrs(),
	}
	fmt.Printf("relayinfo: %s", localrelayinfo)

	select {}
}

func makeRelayHost() {
	priv, err := tranStringPrivateKeyToCryptoPrivateKey("k2hjYJL/xGOoacg7kRz7rNNdqelCvpsSVWP1my893qiYrA2Ribc3oEHlDyDGiU599jb92d1OHqdZIGbZws16sg==")
	if err != nil {
		fmt.Println(err)
	}
	localrelay, _ = libp2p.New(
		libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/0"),
		libp2p.Identity(priv),
	)
}

func tranStringPrivateKeyToCryptoPrivateKey(privString string) (crypto.PrivKey, error) {
	// 解码 Base64,并去掉可能存在的空格
	privBytes, err := base64.StdEncoding.DecodeString(strings.TrimSpace(privStr))
	if err != nil {
		return nil, err
	}
	// 从字节数组中获取私钥
	priv, err := crypto.UnmarshalEd25519PrivateKey(privBytes)
	if err != nil {
		return nil, err
	}
	return priv, nil
}

from go-libp2p.

xiguamee avatar xiguamee commented on June 11, 2024

This is not on the road map right now. However, https://docs.rs/libp2p/latest/libp2p/tutorials/hole_punching/index.html is a good introduction and maps well to the go implementation too.

The EnableHolePunching option does't work. Can you help help me❤

May you teach me how should I do to confirm a hole-puching action is actually happened when I ues NewStream to connect with the EnableHolePunching option on? Thank you!!!

I use these simply code below:


import (
	"context"
	"fmt"
	"time"

	"github.com/libp2p/go-libp2p"
	"github.com/libp2p/go-libp2p/core/network"
	"github.com/libp2p/go-libp2p/core/peer"
	"github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/client"
	"github.com/multiformats/go-multiaddr"
)

func main() {
	h, err := libp2p.New(
		libp2p.EnableRelay(),
		libp2p.EnableHolePunching(),
	)
	if err != nil {
		fmt.Printf("create node fail: %s", err)
	}
	fmt.Print(h.ID())

	h.SetStreamHandler("/holepunch/circuit/1.0.0", func(s network.Stream) {
		fmt.Println("someone connect!")
	})

	relayMultiaddr, err := multiaddr.NewMultiaddr("/ip4/106.15.180.40/tcp/55555/p2p/12D3KooWL6LJYwzmLj9Ny4WRYeYg6T58HrMPuhChNs8RfkQuCJhf")
	if err != nil {
		fmt.Printf("connectRelayFail1: %s", err)
	}
	relayInfo, err := peer.AddrInfoFromP2pAddr(relayMultiaddr)
	if err != nil {
		fmt.Printf("onnectRelayFail2: %s", err)
	}
	h.Connect(context.Background(), *relayInfo)
	_, err = client.Reserve(context.Background(), h, *relayInfo)
	if err != nil {
		fmt.Printf("onnectRelayFail3: %s", err)
	}
	var peerid string
	fmt.Println("ID:")
	fmt.Scanln(&peerid)
	fmt.Println("You typed:", peerid)
	destination := "/ip4/106.15.180.40/tcp/55555/p2p/12D3KooWL6LJYwzmLj9Ny4WRYeYg6T58HrMPuhChNs8RfkQuCJhf/p2p-circuit/p2p/" + peerid
	maddr, err := multiaddr.NewMultiaddr(destination)
	if err != nil {
		fmt.Printf("create maddr fail: %s", err)
	}
	info, err := peer.AddrInfoFromP2pAddr(maddr)
	if err != nil {
		fmt.Printf("create info fail: %s", err)
	}
	h.Peerstore().AddAddr(info.ID, info.Addrs[0], 5*time.Second)
	s, err := h.NewStream(context.Background(), info.ID, "/holepunch/circuit/1.0.0")
	if err != nil {
		fmt.Printf("create stream fail: %s", err)
	}
	fmt.Println("success!")
	fmt.Println(s.Conn().RemoteMultiaddr())

	select {}
}

The result is /ip4/106.15.180.40/tcp/55555/p2p/12D3KooWL6LJYwzmLj9Ny4WRYeYg6T58HrMPuhChNs8RfkQuCJhf/p2p-circuit

from go-libp2p.

sukunrt avatar sukunrt commented on June 11, 2024

Can you run the relay host without the WithInfiniteLimits option

NewStream won't wait for a hole punch if the relayed connection has no limits on the data exchanged.

from go-libp2p.

xiguamee avatar xiguamee commented on June 11, 2024

Can you run the relay host without the WithInfiniteLimits option

NewStream won't wait for a hole punch if the relayed connection has no limits on the data exchanged.

Yes, Thank you~

But that didn't work, I met this error failed to open stream: context deadline exceeded. The NAT on both side is PortRestrictedCone.

Should I use the network.WithUseTransient() option when start a NewStream or other?

I found if containsPublicAddr(s.ids.OwnObservedAddrs()) {
log.Debug("Host now has a public address. Starting holepunch protocol.")
s.host.SetStreamHandler(Protocol, s.handleNewStream)
break
} in function watchForPublicAddr . But there was no log appeared in my terminal. What should I do ? Also there was no log.Debug("waiting until we have at least one public address", "peer", s.host.ID()) executed.

What dose containsPublicAddr means? Is that means I need another host with public address except the relay host?

from go-libp2p.

Jorropo avatar Jorropo commented on June 11, 2024

Should I use the network.WithUseTransient() option when start a NewStream or other?

No, it indicates that you allow the connection to be openned on the relay, if you DON'T use it, then the stream can only be open on reliable connection, such as direct connection (as you want).

from go-libp2p.

kt5ttk99 avatar kt5ttk99 commented on June 11, 2024

May I ask if this problem has been resolved?

from go-libp2p.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.