perlin-network / noise Goto Github PK
View Code? Open in Web Editor NEWA decentralized P2P networking stack written in Go.
Home Page: https://godoc.org/github.com/perlin-network/noise
License: MIT License
A decentralized P2P networking stack written in Go.
Home Page: https://godoc.org/github.com/perlin-network/noise
License: MIT License
If you run two Docker containers with internal ports set at 3000 exposed to the host on a different port and attempt to connect them together you get the following error.
I0810 10:10:30.231989 1 plugin.go:32] Setting up NAT traversal for address: tcp://0.0.0.0:3000
W0810 10:10:40.233060 1 plugin.go:43] Unable to discover gateway: no NAT found
I0810 10:10:40.233504 1 network.go:205] Listening for peers on tcp://0.0.0.0:3000.
E0810 10:10:49.348053 1 network.go:407] network: peer should not dial itself
Right now there is unnecessary construction of a Kademlia DHT despite users not necessarily needing peer discovery.
We should abstract features such as message signing/peer discovery into Plugins instead.
MessageProcessor
s to a Network.builder.NetworkBuilder
.network.Routes
to the plugin.)network
through a concurrent-safe map.Simplify concurrency/ongoing locking in the system.
We should give the choice of choosing to include in peer discovery as an option to developers, as it is currently baked in forcibly in PeerClient
.
To do so, we need to package it with an type MessageHandler interface
or type MessageProcessor interface
and allow users to attach new message handlers/processors to a *Network
.
From type PeerClient struct
there is a reference to server *Server
which can access network *Network
so that we can get a reference list of all registered message handlers/processors to the *Network
.
From a performance optimization perspective, we shouldn't naively loop through all registered message handlers and apply them to incoming messages from the network though.
Most probably, upon registration of a message handler/processor users should designate somehow (perhaps through a go bind on the struct implementing the MessageHandler/MessageProcessor interface?) what sort of messages are handled by a specific registered handler/processor, such that we can add it to a map of a list of processors that would then handle said message.
examples/chat/messages/chat.pb.go:63:33: undefined: proto.InternalMessageInfo
protobuf/stream.pb.go:67:24: undefined: proto.InternalMessageInfo
protobuf/stream.pb.go:127:29: undefined: proto.InternalMessageInfo
protobuf/stream.pb.go:199:26: undefined: proto.InternalMessageInfo
protobuf/stream.pb.go:236:26: undefined: proto.InternalMessageInfo
protobuf/stream.pb.go:274:39: undefined: proto.InternalMessageInfo
protobuf/stream.pb.go:319:40: undefined: proto.InternalMessageInfo
protobuf/stream.pb.go:364:27: undefined: proto.InternalMessageInfo
protoc --version
libprotoc 3.6.0
Due to this error I'm unable to build the project and test it using Windows10. Maybe is a good idea indicate it on readme?
Result of execute command vgo mod -vendor
:
Javi@FOOOCK D:\Projects\go\src\github.com\perlin-network\noise (master)
> vgo generate ./...
go: extracting github.com/xtaci/kcp-go v0.0.0-20180203133237-42bc1dfefff5
-> unzip D:\Projects\go\src\mod\cache\download\github.com\xtaci\kcp-go\@v\v0.0.0-20180203133237-42bc1dfefff5.zip: invalid file name github.com/xtaci/[email protected]/.gitignore
go: extracting github.com/pkg/errors v0.8.0
-> unzip D:\Projects\go\src\mod\cache\download\github.com\pkg\errors\@v\v0.8.0.zip: invalid file name github.com/pkg/[email protected]/.gitignore
go: extracting github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
-> unzip D:\Projects\go\src\mod\cache\download\github.com\golang\glog\@v\v0.0.0-20160126235308-23def4e6c14b.zip: invalid file name github.com/golang/[email protected]/LICENSE
go: extracting github.com/gogo/protobuf v1.0.0
-> unzip D:\Projects\go\src\mod\cache\download\github.com\gogo\protobuf\@v\v1.0.0.zip: invalid file name github.com/gogo/[email protected]/.gitignore
go: extracting golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8
-> unzip D:\Projects\go\src\mod\cache\download\golang.org\x\crypto\@v\v0.0.0-20180621125126-a49355c7e3f8.zip: invalid file name golang.org/x/[email protected]/.gitattributes
go: extracting github.com/xtaci/smux v1.0.7
-> unzip D:\Projects\go\src\mod\cache\download\github.com\xtaci\smux\@v\v1.0.7.zip: invalid file name github.com/xtaci/[email protected]/.gitignore
go: extracting github.com/fd/go-nat v1.0.0
-> unzip D:\Projects\go\src\mod\cache\download\github.com\fd\go-nat\@v\v1.0.0.zip: invalid file name github.com/fd/[email protected]/LICENSE
go: import "github.com/perlin-network/noise/crypto/hashing/blake2b" ->
import "golang.org/x/crypto/blake2b": unzip D:\Projects\go\src\mod\cache\download\golang.org\x\crypto\@v\v0.0.0-20180621125126-a49355c7e3f8.zip: invalid file name golang.org/x/[email protected]/.gitattributes
go: import "github.com/perlin-network/noise/crypto/signing/ed25519" ->
import "golang.org/x/crypto/ed25519": unzip D:\Projects\go\src\mod\cache\download\golang.org\x\crypto\@v\v0.0.0-20180621125126-a49355c7e3f8.zip: invalid file name golang.org/x/[email protected]/.gitattributes
go: import "github.com/perlin-network/noise/examples/basic/messages" ->
import "github.com/gogo/protobuf/gogoproto": unzip D:\Projects\go\src\mod\cache\download\github.com\gogo\protobuf\@v\v1.0.0.zip: invalid file name github.com/gogo/[email protected]/.gitignore
go: import "github.com/perlin-network/noise/examples/basic/messages" ->
import "github.com/gogo/protobuf/proto": unzip D:\Projects\go\src\mod\cache\download\github.com\gogo\protobuf\@v\v1.0.0.zip: invalid file name github.com/gogo/[email protected]/.gitignore
go: import "github.com/perlin-network/noise/examples/chat" ->
import "github.com/golang/glog": unzip D:\Projects\go\src\mod\cache\download\github.com\golang\glog\@v\v0.0.0-20160126235308-23def4e6c14b.zip: invalid file name github.com/golang/[email protected]/LICENSE
go: import "github.com/perlin-network/noise/examples/stream" ->
import "github.com/xtaci/smux": unzip D:\Projects\go\src\mod\cache\download\github.com\xtaci\smux\@v\v1.0.7.zip: invalid file name github.com/xtaci/[email protected]/.gitignore
go: import "github.com/perlin-network/noise/network" ->
import "github.com/gogo/protobuf/types": unzip D:\Projects\go\src\mod\cache\download\github.com\gogo\protobuf\@v\v1.0.0.zip: invalid file name github.com/gogo/[email protected]/.gitignore
go: import "github.com/perlin-network/noise/network" ->
import "github.com/pkg/errors": unzip D:\Projects\go\src\mod\cache\download\github.com\pkg\errors\@v\v0.8.0.zip: invalid file name github.com/pkg/[email protected]/.gitignore
go: import "github.com/perlin-network/noise/network" ->
import "github.com/xtaci/kcp-go": unzip D:\Projects\go\src\mod\cache\download\github.com\xtaci\kcp-go\@v\v0.0.0-20180203133237-42bc1dfefff5.zip: invalid file name github.com/xtaci/[email protected]/.gitignore
go: import "github.com/perlin-network/noise/network/nat" ->
import "github.com/fd/go-nat": unzip D:\Projects\go\src\mod\cache\download\github.com\fd\go-nat\@v\v1.0.0.zip: invalid file name github.com/fd/[email protected]/LICENSE
chat.gif is outdated since "-peers localhost:3000" is not working without protocol specification
one more thing, under macos and win10,client on win10 exit; under macOS and ubuntu, it goes well.
Use the routing table and XOR pairwise distance ID scheme from the Kademlia protocol for discovering new peers on the network.
Benchmark with various message sizes w.r.t. number of peers.
Say we receive messages with nonce 1, 2, 3 and 5. Calling Update()
will process messages 1, 2, 3.
Calling Update()
once message 4 comes in will process messages 4 and 5.
Receive window is used for buffering messages that are out of order.
Implement streaming on top of messages and the net.Conn interface.
The current method in which one can choose to reply to a message, or otherwise asynchronously send a message to a remote peer looks very hackish.
Perhaps we can make them methods of client *PeerClient
such that they would look like:
client.Reply()
client.Tell()
So, in one window I have a cloud machine open, which is running like this:
root@testnet2:~/go/bin# ./chat -host 149.28.45.92
I0713 21:07:49.195013 19634 main.go:45] Private Key: 537d7e7c0e196c1ad8b7afe172db0739e978665db78797305a30b7ed57e0602779f64ca55b2a9cc8ceffa4db958b8c9439049ebd4dcbd5e544f255c054a88b52
I0713 21:07:49.195447 19634 main.go:46] Public Key: 79f64ca55b2a9cc8ceffa4db958b8c9439049ebd4dcbd5e544f255c054a88b52
I0713 21:07:49.196079 19634 network.go:215] Listening for peers on tcp://149.28.45.92:3000.
E0713 21:08:28.989027 19634 network.go:411] dial tcp 98.118.185.162:26110: connect: connection refused
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0x5d9ade]
goroutine 19 [running]:
github.com/perlin-network/noise/network.(*Network).Accept.func2(0xc420084180, 0xc42008a0a0, 0xc42001c460, 0xc42000e088, 0xc42000e080, 0xc42000c3c0, 0xc42000e078)
/root/go/src/github.com/perlin-network/noise/network/network.go:433 +0x15e
created by github.com/perlin-network/noise/network.(*Network).Accept
/root/go/src/github.com/perlin-network/noise/network/network.go:394 +0x333
root@testnet2:~/go/bin#
In my IDE, where I've modified "chat" to use NAT and connect to the cloud instance of chat, I have this going on:
admins-MacBook-Pro:chat admin$ ./chat -peers tcp://149.28.45.92:3000
I0713 17:08:26.661685 10198 main.go:46] Private Key: c3e6c04553b19f9d44057a06dd884429183a20a3b11c4b2fc3138ad8a3bbf32fb6848b3ec12e9ca2259ee98f6442a2b6d402e7897938ef32c337606518c9a712
I0713 17:08:26.661753 10198 main.go:47] Public Key: b6848b3ec12e9ca2259ee98f6442a2b6d402e7897938ef32c337606518c9a712
I0713 17:08:26.663017 10198 plugin.go:25] Setting up NAT traversal...
I0713 17:08:28.786533 10198 plugin.go:52] Discovered gateway following the protocol UPNP (IG1-IP1).
I0713 17:08:28.786559 10198 plugin.go:54] Internal IP: 192.168.1.166
I0713 17:08:28.786571 10198 plugin.go:55] External IP: 98.118.185.162
I0713 17:08:28.941708 10198 plugin.go:64] External port 26110 now forwards to your local port 3000.
I0713 17:08:28.941745 10198 plugin.go:75] Other peers may connect to you through the address tcp://98.118.185.162:26110.
I0713 17:08:28.942029 10198 network.go:215] Listening for peers on tcp://98.118.185.162:26110.
hi
I0713 17:08:32.445675 10198 main.go:82] <tcp://98.118.185.162:26110> hi
When I send "hi" to the cloud instance from my mac, the cloud instance crashes and burns.
When I was making a test on lru/cache
, on inserting excessive items to lru/cache
, item := c.order.Remove(c.order.Back()).(*cacheItem)
will cause problem due to:
panic: interface conversion: interface {} is string, not *lru.cacheItem
as c.order
is only built up by value
, so there is no way to get back key
from it.
Also, we don't have to evict items before checking if cache key is hit.
So... a little bit of background-- I first saw this issue after building the chat example multiplatform using Gox after I put the app on a raspberry Pi of mine. Since then, I've seen it on my mac as well.
I can't quite make heads or tails of it (I've tried) so I'm filing this issue. I'm in the discord if you've any questions.
./chat
./chat flag redefined: log_dir
panic: ./chat flag redefined: log_dir
goroutine 1 [running]:
flag.(*FlagSet).Var(0xc420074060, 0x1292b40, 0xc4200107e0, 0x1269f85, 0x7, 0x12756a5, 0x2f)
/usr/local/Cellar/go/1.10/libexec/src/flag/flag.go:810 +0x540
flag.(*FlagSet).StringVar(0xc420074060, 0xc4200107e0, 0x1269f85, 0x7, 0x0, 0x0, 0x12756a5, 0x2f)
/usr/local/Cellar/go/1.10/libexec/src/flag/flag.go:713 +0x8b
flag.(*FlagSet).String(0xc420074060, 0x1269f85, 0x7, 0x0, 0x0, 0x12756a5, 0x2f, 0xc4200107d0)
/usr/local/Cellar/go/1.10/libexec/src/flag/flag.go:726 +0x8b
flag.String(0x1269f85, 0x7, 0x0, 0x0, 0x12756a5, 0x2f, 0x11b3a87)
/usr/local/Cellar/go/1.10/libexec/src/flag/flag.go:733 +0x69
After leaving a peer for a long period (in our case a day or so) the error below is rapidly logged.
W1004 15:11:53.124320 14174 network.go:114] i/o timeout
Looks like it comes from this block:
if err := state.writer.Flush(); err != nil {
log.Warn().Err(err).Msg("")
}
Allows for more flexible choice of networking protocols and makes message proxying easier.
Allow developers to choose which cryptosystems and hashing functions they want to use with Noise.
log:
I0910 11:42:08.731264 15248 main1.go:46] Private Key: 79f92dfe6267bcc95d347a0447408bf57c14fb8781e223e273afedbe5248dd12c3206ae6362428246fea928366b993f66d5ce0d938c50a2b36cb91be280cf148
I0910 11:42:08.738208 15248 main1.go:47] Public Key: c3206ae6362428246fea928366b993f66d5ce0d938c50a2b36cb91be280cf148
I0910 11:42:08.741184 15248 plugin.go:32] Setting up NAT traversal for address: kcp://127.0.0.1:3002
I0910 11:42:10.946909 15248 plugin.go:59] Discovered gateway following the protocol UPNP (IG1-IP1).
I0910 11:42:10.946909 15248 plugin.go:61] Internal IP: 192.168.2.102
I0910 11:42:10.946909 15248 plugin.go:62] External IP: 100.100.149.137
I0910 11:42:11.093523 15248 plugin.go:71] External port 60858 now forwards to your local port 3002.
I0910 11:42:11.093523 15248 plugin.go:82] Other peers may connect to you through the address kcp://100.100.149.137:60858.
I0910 11:42:11.094019 15248 network.go:206] Listening for peers on kcp://100.100.149.137:60858.
Why the External IP is not my public network IP?
We should enforce somehow that requests received should only be replied to once. sync.Once
may be an option.
Additionally, we should make it possible to not have to provide the request nonce to client.Reply(request nonce, message)
with an example case of its usage in network/discovery/incoming.go
.
We can cache the request nonce somehow specifically to a given processed IncomingMessage
.
If the current incoming message is not a request/reply RPC, client.Reply()
will error.
Upon enabling the NAT traversal plugin, one's peer.ID
gets set to their external WAN IP.
This prevents users from spawning up local peer nodes and having them formate a cluster with one another, and only allows for peers coming from an external network.
This is because the peer.ID
that gets distributed out contains the users external WAN IP, which is not directly connectable to from peers in a local network. Hence, peer discovery will fail locally.
Best solution for now is to check if a nodes own peer.ID
address is equivalent to a peer that is being dialed peer.ID
address, and to automatically default it to dialing the loopback address 127.0.0.1
.
when I blank protocol it's fine, when use protocol=kcp, error reported:
xxxx$ go run main.go -host=192.168.1.102 -peers=kcp://192.168.1.104:3000 -protocol=kcp
2018-10-20T18:28:21+08:00 |WARN| caller=/Users/xxxx/go/src/github.com/perlin-network/noise/network/network.go:116 error="broken pipe"
one more thing, when peer on win10, it exit; ok under macOS and ubuntu
Not mandatory for release.
Syntax:
0<2
implies that Node 2 bootstrapped with Node 0.0<=2
implies that Node 2 sent a message to Node 0.Say we have a setup 0<1 + 1<2
. Proxying means: 0=>1 + 1=>2
. Node 0 sends a message to Node 1 who notices the request to have the message proxied/propagated to Node 2.
To do this, some requirements need to be done:
Add in methods to choose how to broadcast messages to select peers.
Clean-up documentation and code and create usage examples for Go developers.
I did an experiment:
1:I ran chat/main.go on the public network.
2:I also ran chat/main.go on my local intranet.
The intranet takes the initiative to connect to the public network.
and connect failure
log:
1:public network:
I0914 15:35:59.067335 5092 main.go:45] Private Key: e1c79968020ee18a725849826e7130c4bb9e4962d255b6829fd8ab64534658f85640464458ddeef9eeb93368779c7015a2a43ff374ff23b3eae23b47dbfb75e8
I0914 15:35:59.067392 5092 main.go:46] Public Key: 5640464458ddeef9eeb93368779c7015a2a43ff374ff23b3eae23b47dbfb75e8
I0914 15:35:59.067700 5092 network.go:206] Listening for peers on tcp://47.91.166.18:3001.
E0914 15:38:06.366141 5092 network.go:319] dial tcp 183.192.11.228:3000: connect: connection timed out
2:local intranet:
I0914 15:36:05.452905 21932 main.go:46] Private Key: 31d4fefef611b233374a1b99363eb55dd0919b383108911bc909f455de22af0d425efc07c0d7d68d203d0e3ea1c8702a2968dd3d16f34a3909648520ade5c91d
I0914 15:36:05.459852 21932 main.go:47] Public Key: 425efc07c0d7d68d203d0e3ea1c8702a2968dd3d16f34a3909648520ade5c91d
I0914 15:36:05.464287 21932 network.go:206] Listening for peers on tcp://127.0.0.1:3000.
I think the port of public network connect local intranet should‘t be 3000 ,is right?
forgive my poor English
It would be great to be able to make the underlying protocol pluggable.
This way plugging in a tor layer can give you anonymous peers.
Hi!
I'm trying to determine if Noise can be used when a member of the p2p network cannot be dialed. I was experimenting using docker where host B can dial host A, but host A cannot dial host B.
I tried to have host B bootstrap to A, but then it appears that A tries to dial B and it fails... it doesn't look like a bi-directional connection is setup.
Is that true?
My use-case is for clients to connect to the network where the built-in NAT busting doesn't work, but we could establish relays (similar to your proxy example) to get messages to the clients.
Should a connection cut out, attempt to reconnect a certain amount of times. After a certain amount of time should the connection still fail, disconnect the peer.
Refer to the code here: https://github.com/jpillora/backoff
Test the cases in which nodes may be slow, or randomly dropping connection. Complements changes to be made by #45.
What exactly is the motivation? After all, TCP itself is decentralized and robust. Cryptography is an addon and HTTP/2 already supports it.
Is there a read up somewhere on the reasoning and the potential applications?
Hello.
I am looking for solution for 2P2 file sharing. Your library looks good, but it seems, that there is a problem with nat traversal. You use UPnP nat traversal. But, what if client router does not support it?
I would be happy to know, why you decide to use UPnP nat traversal instead of ICE? Can you explain, please?
CPU utilization is quite low on the senders side; we most probably can send significantly more messages per second.
I am running into a vgo mod -sync error, that tells me it cannot find:
go: import "github.com/gogo/protobuf/protoc-gen-gogofaster/gocode/src/github.com/golang/mock/mockgen/tests/vendor_dep" ->
import "a": cannot find module providing package a
I had an issue with protobufs 3.6 not working and versioned down to 3.5.1, that fixed the protobuf issue so maybe there are other versioning issues?
running ubuntu 18.04
Might take some time to get node IDs done due to refactoring on noise's networking.
Looking to implement the disjoint path lookup method denoted in S/Kademlia.
a, k, j := 3, 16, 8
Paper: https://gnunet.org/sites/default/files/SKademlia2007.pdf
Address string
in *Network
and *PeerClient
with AddressInfo
.AddressInfo
with NoiseAddr
in *PeerClient
.*PeerClient
.StreamPacket
to Bytes
.If the local peer binds to 0.0.0.0
with the code
builder.SetAddress(network.FormatAddress(
"kcp",
"0.0.0.0",
7946))
and a message is sent to the remote (in my case the initial state sync), the remote peer will try to dial itself and panic with the error:
E1001 14:12:43.652615 6010 network.go:397] network: peer should not dial itself
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0xa6fecd]
goroutine 48 [running]:
github.com/gladiusio/gladius-controld/vendor/github.com/perlin-network/noise/network.(*Network).Accept.func2(0xc0003ba840, 0xc0002d1ee0, 0xc000350c80, 0xc00000e170, 0xc0003b87f0, 0xc0003b87d0, 0xc0003b51a0)
/home/alex/go/src/github.com/gladiusio/gladius-controld/vendor/github.com/perlin-network/noise/network/network.go:402 +0xed
created by github.com/gladiusio/gladius-controld/vendor/github.com/perlin-network/noise/network.(*Network).Accept
/home/alex/go/src/github.com/gladiusio/gladius-controld/vendor/github.com/perlin-network/noise/network/network.go:375 +0x1cf
Cache network.ToUnifiedAddress()
calls.
Will each peer connect to all the 10M peers?
If there is a limit of max connection for each peer, how to handle so many peers?
Of course, the main goal is to make examples as intuitive as possible. We should all try out different examples to illustrate that it's relatively easy to use Noise with a minimal number of LoC.
This example constitutes of proxying messages from one node to another.
Please refer to the comment styling and example directory format for the basic
example located here: https://github.com/perlin-network/noise/tree/master/examples/basic
Initiating a request to a peer should be configurable with many options.
We can utilize the same builder pattern we see in building new peer networks to create requests with specific options.
Example usage:
request := &builders.RequestBuilder{}
request.SetTimeout(3 * time.Second)
request.SetMessage(message proto.Message)
...
client.Request(request.BuildRequest())
I've been having random crashes with a peer (sometimes connected to other peers, and sometimes on it's own) with the error:
2018/09/19 16:45:50
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0xa3815d]
goroutine 49 [running]:
github.com/gladiusio/gladius-node/vendor/github.com/perlin-network/noise/network.(*Network).Accept.func2(0xc4203aba60, 0xc420312d00, 0xc42006c380, 0xc42000f220, 0xc4203ad6b0, 0xc4203ad690, 0xc4203df890)
/ext-go/1/src/github.com/gladiusio/gladius-node/vendor/github.com/perlin-network/noise/network/network.go:402 +0xed
created by github.com/gladiusio/gladius-node/vendor/github.com/perlin-network/noise/network.(*Network).Accept
/ext-go/1/src/github.com/gladiusio/gladius-node/vendor/github.com/perlin-network/noise/network/network.go:375 +0x1d4
The random nature of this, and the fact it happens when there are no peers connected makes me think it's this section of our code:
func (state *StatePlugin) Startup(net *network.Network) {
// TODO: Find out why this crashes the network on ocassion
go func() {
time.Sleep(60 * time.Second)
net.BroadcastRandomly(&messages.SyncRequest{}, 1)
}()
}
It looks like this if statement is the problem at network.go:402
, dereferencing msg.Sender
causes a panic.
// Peer sent message with a completely different ID. Disconnect.
if !client.ID.Equals(peer.ID(*msg.Sender)) {
glog.Errorf("message signed by peer %s but client is %s", peer.ID(*msg.Sender), client.ID.Address)
return
}
I also get an error about the peer should not dial itself even if I haven't explicitly called p.net.Bootstrap(addressList...)
so I believe that the above code is broadcasting before the network has been bootstrapped, and that the BroadcastRandomly
method seems to be able to dial itself. This is running on a VPS and listening on it's public IP with the code:
// Use KCP instead of TCP, and config bind address and bind port
builder.SetAddress(network.FormatAddress(
"kcp",
viper.GetString("P2P.BindAddress"),
uint16(viper.GetInt("P2P.BindPort")))
// This is our network state object
s := state.New()
s.RegisterNodeSingleFields("ip_address", "content_port", "heartbeat")
s.RegisterNodeListFields("disk_content")
s.RegisterPoolListFields("required_content")
// Register peer discovery plugin.
// TODO: Setup an authorized DHT plugin
builder.AddPlugin(new(discovery.Plugin))
// Add the exponential backoff plugin
builder.AddPlugin(new(backoff.Plugin))
// Create our state sync plugin
statePlugin := new(StatePlugin)
statePlugin.peerState = s
builder.AddPlugin(statePlugin)
net, err := builder.Build()
if err != nil {
log.Fatal(err)
return nil
}
go net.Listen()
I haven't tested with TCP instead of KCP though.
I add AddPlugin(new(backoff.Plugin)) in chat example, and disconnect main node ,and restart it
but client cant reconnect main node, do i have to config some backoff parameters? can you give some demo to show backoff reconnect case? thanks
Rather than having users always supply their external IP to builders.NetworkBuilder
, utilize UPnP for devices whose network interfaces and routers support it to discover their external IP with specific ports open.
UPnP can essentially be used to open ports (without manually going to an users router page) and discover an users external IP.
Refer to library: https://github.com/NebulousLabs/go-upnp
Export core features as C API to allow:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.