Save current state of the world
This commit is contained in:
parent
ff69d46c98
commit
6e28e7a86f
@ -1023,7 +1023,8 @@ func (n *network) sendTo(method, channel string, peer *node, msg proto.Message)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c, err := n.tunnel.Dial(channel, tunnel.DialMode(tunnel.Multicast), tunnel.DialLink(peer.link))
|
// Create a unicast connection to the peer but don't do the open/accept flow
|
||||||
|
c, err := n.tunnel.Dial(channel, tunnel.DialWait(false), tunnel.DialLink(peer.link))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,7 @@ func (r *runtime) run(events <-chan Event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case <-r.closed:
|
case <-r.closed:
|
||||||
log.Debugf("Runtime stopped.")
|
log.Debugf("Runtime stopped")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,10 +73,10 @@ func newTunnel(opts ...Option) *tun {
|
|||||||
// Init initializes tunnel options
|
// Init initializes tunnel options
|
||||||
func (t *tun) Init(opts ...Option) error {
|
func (t *tun) Init(opts ...Option) error {
|
||||||
t.Lock()
|
t.Lock()
|
||||||
defer t.Unlock()
|
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
o(&t.options)
|
o(&t.options)
|
||||||
}
|
}
|
||||||
|
t.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +103,6 @@ func (t *tun) delSession(channel, session string) {
|
|||||||
// listChannels returns a list of listening channels
|
// listChannels returns a list of listening channels
|
||||||
func (t *tun) listChannels() []string {
|
func (t *tun) listChannels() []string {
|
||||||
t.RLock()
|
t.RLock()
|
||||||
defer t.RUnlock()
|
|
||||||
|
|
||||||
//nolint:prealloc
|
//nolint:prealloc
|
||||||
var channels []string
|
var channels []string
|
||||||
@ -113,6 +112,9 @@ func (t *tun) listChannels() []string {
|
|||||||
}
|
}
|
||||||
channels = append(channels, session.channel)
|
channels = append(channels, session.channel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.RUnlock()
|
||||||
|
|
||||||
return channels
|
return channels
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,53 +246,71 @@ func (t *tun) manageLink(link *link) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// manageLinks is a function that can be called to immediately to link setup
|
// manageLinks is a function that can be called to immediately to link setup
|
||||||
|
// it purges dead links while generating new links for any nodes not connected
|
||||||
func (t *tun) manageLinks() {
|
func (t *tun) manageLinks() {
|
||||||
var delLinks []string
|
delLinks := make(map[*link]string)
|
||||||
|
connected := make(map[string]bool)
|
||||||
|
|
||||||
t.RLock()
|
t.RLock()
|
||||||
|
|
||||||
|
// get list of nodes from options
|
||||||
|
nodes := t.options.Nodes
|
||||||
|
|
||||||
// check the link status and purge dead links
|
// check the link status and purge dead links
|
||||||
for node, link := range t.links {
|
for node, link := range t.links {
|
||||||
// check link status
|
// check link status
|
||||||
switch link.State() {
|
switch link.State() {
|
||||||
case "closed":
|
case "closed", "error":
|
||||||
delLinks = append(delLinks, node)
|
delLinks[link] = node
|
||||||
case "error":
|
default:
|
||||||
delLinks = append(delLinks, node)
|
connected[node] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
t.RUnlock()
|
t.RUnlock()
|
||||||
|
|
||||||
|
// build a list of links to connect to
|
||||||
|
var connect []string
|
||||||
|
|
||||||
|
for _, node := range nodes {
|
||||||
|
// check if we're connected
|
||||||
|
if _, ok := connected[node]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// add nodes to connect o
|
||||||
|
connect = append(connect, node)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// delete the dead links
|
// delete the dead links
|
||||||
if len(delLinks) > 0 {
|
if len(delLinks) > 0 {
|
||||||
t.Lock()
|
t.Lock()
|
||||||
for _, node := range delLinks {
|
|
||||||
|
for link, node := range delLinks {
|
||||||
log.Debugf("Tunnel deleting dead link for %s", node)
|
log.Debugf("Tunnel deleting dead link for %s", node)
|
||||||
if link, ok := t.links[node]; ok {
|
|
||||||
link.Close()
|
// check if the link exists
|
||||||
|
l, ok := t.links[node]
|
||||||
|
if ok {
|
||||||
|
// close and delete
|
||||||
|
l.Close()
|
||||||
delete(t.links, node)
|
delete(t.links, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if the link does not match our own
|
||||||
|
if l != link {
|
||||||
|
// close our link just in case
|
||||||
|
link.Close()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
t.Unlock()
|
t.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// check current link status
|
|
||||||
var connect []string
|
|
||||||
|
|
||||||
// build list of unknown nodes to connect to
|
|
||||||
t.RLock()
|
|
||||||
|
|
||||||
for _, node := range t.options.Nodes {
|
|
||||||
if _, ok := t.links[node]; !ok {
|
|
||||||
connect = append(connect, node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
t.RUnlock()
|
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
// establish new links
|
||||||
|
|
||||||
for _, node := range connect {
|
for _, node := range connect {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
|
||||||
@ -298,6 +318,7 @@ func (t *tun) manageLinks() {
|
|||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
// create new link
|
// create new link
|
||||||
|
// if we're using quic it should be a max 10 second handshake period
|
||||||
link, err := t.setupLink(node)
|
link, err := t.setupLink(node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debugf("Tunnel failed to setup node link to %s: %v", node, err)
|
log.Debugf("Tunnel failed to setup node link to %s: %v", node, err)
|
||||||
@ -313,6 +334,7 @@ func (t *tun) manageLinks() {
|
|||||||
link.Close()
|
link.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// save the link
|
// save the link
|
||||||
t.links[node] = link
|
t.links[node] = link
|
||||||
}(node)
|
}(node)
|
||||||
@ -469,7 +491,6 @@ func (t *tun) process() {
|
|||||||
|
|
||||||
func (t *tun) delLink(remote string) {
|
func (t *tun) delLink(remote string) {
|
||||||
t.Lock()
|
t.Lock()
|
||||||
defer t.Unlock()
|
|
||||||
|
|
||||||
// get the link
|
// get the link
|
||||||
for id, link := range t.links {
|
for id, link := range t.links {
|
||||||
@ -481,6 +502,8 @@ func (t *tun) delLink(remote string) {
|
|||||||
link.Close()
|
link.Close()
|
||||||
delete(t.links, id)
|
delete(t.links, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// process incoming messages
|
// process incoming messages
|
||||||
@ -1035,6 +1058,7 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) {
|
|||||||
// get opts
|
// get opts
|
||||||
options := DialOptions{
|
options := DialOptions{
|
||||||
Timeout: DefaultDialTimeout,
|
Timeout: DefaultDialTimeout,
|
||||||
|
Wait: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
@ -1119,11 +1143,16 @@ func (t *tun) Dial(channel string, opts ...DialOption) (Session, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// return early if its not unicast
|
// return early if its not unicast
|
||||||
// we will not call "open" for multicast
|
// we will not wait for "open" for multicast
|
||||||
if c.mode != Unicast {
|
if c.mode != Unicast {
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if we're not told to wait
|
||||||
|
if !options.Wait {
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Note: we go no further for multicast or broadcast.
|
// Note: we go no further for multicast or broadcast.
|
||||||
// This is a unicast session so we call "open" and wait
|
// This is a unicast session so we call "open" and wait
|
||||||
// for an "accept"
|
// for an "accept"
|
||||||
@ -1221,15 +1250,16 @@ func (t *tun) Listen(channel string, opts ...ListenOption) (Listener, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *tun) Links() []Link {
|
func (t *tun) Links() []Link {
|
||||||
t.RLock()
|
|
||||||
defer t.RUnlock()
|
|
||||||
|
|
||||||
links := make([]Link, 0, len(t.links))
|
links := make([]Link, 0, len(t.links))
|
||||||
|
|
||||||
|
t.RLock()
|
||||||
|
|
||||||
for _, link := range t.links {
|
for _, link := range t.links {
|
||||||
links = append(links, link)
|
links = append(links, link)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.RUnlock()
|
||||||
|
|
||||||
return links
|
return links
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,10 +138,10 @@ func (l *link) setRate(bits int64, delta time.Duration) {
|
|||||||
// setRTT sets a nanosecond based moving average roundtrip time for the link
|
// setRTT sets a nanosecond based moving average roundtrip time for the link
|
||||||
func (l *link) setRTT(d time.Duration) {
|
func (l *link) setRTT(d time.Duration) {
|
||||||
l.Lock()
|
l.Lock()
|
||||||
defer l.Unlock()
|
|
||||||
|
|
||||||
if l.length <= 0 {
|
if l.length <= 0 {
|
||||||
l.length = d.Nanoseconds()
|
l.length = d.Nanoseconds()
|
||||||
|
l.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,6 +149,8 @@ func (l *link) setRTT(d time.Duration) {
|
|||||||
length := 0.8*float64(l.length) + 0.2*float64(d.Nanoseconds())
|
length := 0.8*float64(l.length) + 0.2*float64(d.Nanoseconds())
|
||||||
// set new length
|
// set new length
|
||||||
l.length = int64(length)
|
l.length = int64(length)
|
||||||
|
|
||||||
|
l.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *link) delChannel(ch string) {
|
func (l *link) delChannel(ch string) {
|
||||||
@ -159,8 +161,9 @@ func (l *link) delChannel(ch string) {
|
|||||||
|
|
||||||
func (l *link) getChannel(ch string) time.Time {
|
func (l *link) getChannel(ch string) time.Time {
|
||||||
l.RLock()
|
l.RLock()
|
||||||
defer l.RUnlock()
|
t := l.channels[ch]
|
||||||
return l.channels[ch]
|
l.RUnlock()
|
||||||
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *link) setChannel(channels ...string) {
|
func (l *link) setChannel(channels ...string) {
|
||||||
@ -344,27 +347,31 @@ func (l *link) Delay() int64 {
|
|||||||
// Current transfer rate as bits per second (lower is better)
|
// Current transfer rate as bits per second (lower is better)
|
||||||
func (l *link) Rate() float64 {
|
func (l *link) Rate() float64 {
|
||||||
l.RLock()
|
l.RLock()
|
||||||
defer l.RUnlock()
|
r := l.rate
|
||||||
return l.rate
|
l.RUnlock()
|
||||||
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *link) Loopback() bool {
|
func (l *link) Loopback() bool {
|
||||||
l.RLock()
|
l.RLock()
|
||||||
defer l.RUnlock()
|
lo := l.loopback
|
||||||
return l.loopback
|
l.RUnlock()
|
||||||
|
return lo
|
||||||
}
|
}
|
||||||
|
|
||||||
// Length returns the roundtrip time as nanoseconds (lower is better).
|
// Length returns the roundtrip time as nanoseconds (lower is better).
|
||||||
// Returns 0 where no measurement has been taken.
|
// Returns 0 where no measurement has been taken.
|
||||||
func (l *link) Length() int64 {
|
func (l *link) Length() int64 {
|
||||||
l.RLock()
|
l.RLock()
|
||||||
defer l.RUnlock()
|
length := l.length
|
||||||
return l.length
|
l.RUnlock()
|
||||||
|
return length
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *link) Id() string {
|
func (l *link) Id() string {
|
||||||
l.RLock()
|
l.RLock()
|
||||||
defer l.RUnlock()
|
id := l.id
|
||||||
|
l.RUnlock()
|
||||||
return l.id
|
return l.id
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,11 +420,11 @@ func (l *link) Send(m *transport.Message) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
l.Lock()
|
l.Lock()
|
||||||
defer l.Unlock()
|
|
||||||
|
|
||||||
// there's an error increment the counter and bail
|
// there's an error increment the counter and bail
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.errCount++
|
l.errCount++
|
||||||
|
l.Unlock()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,6 +448,8 @@ func (l *link) Send(m *transport.Message) error {
|
|||||||
l.setRate(int64(bits), time.Since(now))
|
l.setRate(int64(bits), time.Since(now))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
l.Unlock()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -476,10 +485,13 @@ func (l *link) State() string {
|
|||||||
return "closed"
|
return "closed"
|
||||||
default:
|
default:
|
||||||
l.RLock()
|
l.RLock()
|
||||||
defer l.RUnlock()
|
errCount := l.errCount
|
||||||
if l.errCount > 3 {
|
l.RUnlock()
|
||||||
|
|
||||||
|
if lerrCount > 3 {
|
||||||
return "error"
|
return "error"
|
||||||
}
|
}
|
||||||
|
|
||||||
return "connected"
|
return "connected"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,8 @@ type DialOptions struct {
|
|||||||
Link string
|
Link string
|
||||||
// specify mode of the session
|
// specify mode of the session
|
||||||
Mode Mode
|
Mode Mode
|
||||||
|
// Wait for connection to be accepted
|
||||||
|
Wait bool
|
||||||
// the dial timeout
|
// the dial timeout
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
}
|
}
|
||||||
@ -124,6 +126,14 @@ func DialLink(id string) DialOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DialWait specifies whether to wait for the connection
|
||||||
|
// to be accepted before returning the session
|
||||||
|
func DialWait(b bool) DialOption {
|
||||||
|
return func(o *DialOptions) {
|
||||||
|
o.Wait = b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// DefaultOptions returns router default options
|
// DefaultOptions returns router default options
|
||||||
func DefaultOptions() Options {
|
func DefaultOptions() Options {
|
||||||
return Options{
|
return Options{
|
||||||
|
Loading…
Reference in New Issue
Block a user