github.com/mit-dci/lit@v0.0.0-20221102210550-8c3d3b49f2ce/qln/autoconnect.go (about)

     1  package qln
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/mit-dci/lit/logging"
     7  
     8  	"github.com/mit-dci/lit/bech32"
     9  	"github.com/mit-dci/lit/crypto/fastsha256"
    10  )
    11  
    12  func removeDuplicates(inputArr []uint32) []uint32 {
    13  	keys := make(map[uint32]bool)
    14  	outputArr := []uint32{}
    15  	for _, entry := range inputArr {
    16  		if _, value := keys[entry]; !value {
    17  			keys[entry] = true
    18  			outputArr = append(outputArr, entry)
    19  		}
    20  	}
    21  	return outputArr
    22  }
    23  
    24  // AutoReconnect will start listening for incoming connections
    25  // and attempt to automatically reconnect to all
    26  // previously known peers attached with the coin daemons running.
    27  func (nd *LitNode) AutoReconnect(port int, interval int64, connectedCoinOnly bool) {
    28  	// Listen myself after a timeout
    29  	_, err := nd.TCPListener(port)
    30  	if err != nil {
    31  		logging.Errorf("Could not start listening automatically: %s", err.Error())
    32  		return
    33  	}
    34  
    35  	// Reconnect to other nodes after an interval
    36  	ticker := time.NewTicker(time.Duration(interval) * time.Second)
    37  	qcs, _ := nd.GetAllQchans() // get all chan data
    38  	coinMap := make(map[uint32][]uint32)
    39  	for _, qc := range qcs {
    40  		// make a map of all channel data with the key as coinType
    41  		coinMap[qc.Coin()] = append(coinMap[qc.Coin()], qc.KeyGen.Step[3]&0x7fffffff)
    42  	}
    43  	for i, arr := range coinMap {
    44  		// remove duplicates in the map
    45  		if nd.ConnectedCoinTypes[i] {
    46  			coinMap[i] = removeDuplicates(arr)
    47  		}
    48  	}
    49  
    50  	isConnectedCoin := func(peerIdx uint32) bool {
    51  		// now only connect to those peers in the array
    52  		for _, arr := range coinMap {
    53  			for _, i := range arr {
    54  				if peerIdx == i {
    55  					return true
    56  				}
    57  			}
    58  		}
    59  		return false
    60  	}
    61  
    62  	var empty [33]byte
    63  	i := uint32(1)
    64  	for {
    65  
    66  		pubKey, _ := nd.GetPubHostFromPeerIdx(i)
    67  		if pubKey == empty {
    68  			logging.Infof("Done, tried %d hosts\n", i-1)
    69  			break
    70  		}
    71  
    72  		// If we're only reconnecting to peers we have channels with
    73  		// in a connected coin type (daemon is available), then skip
    74  		// peers that are not in that list
    75  		if connectedCoinOnly && !isConnectedCoin(i) {
    76  			logging.Infof("Skipping peer %d due to onlyConnectedCoins=true\n", i)
    77  			i++
    78  			continue
    79  		}
    80  
    81  		nd.RemoteMtx.Lock()
    82  		_, alreadyConnected := nd.RemoteCons[i]
    83  		nd.RemoteMtx.Unlock()
    84  		if alreadyConnected {
    85  			continue
    86  		}
    87  		idHash := fastsha256.Sum256(pubKey[:])
    88  		adr := bech32.Encode("ln", idHash[:20])
    89  		go func() {
    90  			err := nd.DialPeer(adr)
    91  			if err != nil {
    92  				logging.Errorf("Could not restore connection to %s: %s\n", adr, err.Error())
    93  			}
    94  			<-ticker.C
    95  		}()
    96  
    97  		i++
    98  	}
    99  
   100  }