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

     1  package lnutil
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/sha256"
     6  	"encoding/hex"
     7  	"encoding/json"
     8  	"errors"
     9  	"net/http"
    10  	"net/url"
    11  	"strconv"
    12  	"strings"
    13  	"time"
    14  
    15  	"github.com/mit-dci/lit/crypto/koblitz"
    16  	"github.com/mit-dci/lit/logging"
    17  	"golang.org/x/net/proxy"
    18  )
    19  
    20  type announcement struct {
    21  	ipv4 string
    22  	ipv6 string
    23  	addr string
    24  	sig  string
    25  	pbk  string
    26  }
    27  
    28  type nodeinfo struct {
    29  	Success bool
    30  	Node    struct {
    31  		IPv4 string
    32  		IPv6 string
    33  		Addr string
    34  	}
    35  }
    36  
    37  func Announce(priv *koblitz.PrivateKey, port int, litadr string, trackerURL string) error {
    38  	client := &http.Client{
    39  		Timeout: time.Second * 4, // 4+4 to accomodate the 10s RPC timeout
    40  	}
    41  	strport := ":" + strconv.Itoa(port)
    42  	resp, err := client.Get("https://ipv4.myexternalip.com/raw")
    43  	if err != nil {
    44  		return err
    45  	}
    46  	defer resp.Body.Close()
    47  
    48  	buf := new(bytes.Buffer)
    49  	buf.ReadFrom(resp.Body)
    50  
    51  	liturlIPv4 := strings.TrimSpace(buf.String()) + strport
    52  
    53  	var liturlIPv6 string
    54  
    55  	/* TODO: Find a better way to get this information. Their
    56  	 * SSL cert doesn't work for IPv6.
    57  	 */
    58  	resp, err = client.Get("http://ipv6.myexternalip.com/raw")
    59  	if err != nil {
    60  		logging.Errorf("%v", err)
    61  	} else {
    62  		defer resp.Body.Close()
    63  		buf = new(bytes.Buffer)
    64  		buf.ReadFrom(resp.Body)
    65  		liturlIPv6 = strings.TrimSpace(buf.String()) + strport
    66  	}
    67  
    68  	urlBytes := []byte(liturlIPv4 + liturlIPv6)
    69  	urlHash := sha256.Sum256(urlBytes)
    70  	urlSig, err := priv.Sign(urlHash[:])
    71  	if err != nil {
    72  		return err
    73  	}
    74  
    75  	var ann announcement
    76  
    77  	ann.ipv4 = liturlIPv4
    78  	ann.ipv6 = liturlIPv6
    79  	ann.addr = litadr
    80  	ann.sig = hex.EncodeToString(urlSig.Serialize())
    81  	ann.pbk = hex.EncodeToString(priv.PubKey().SerializeCompressed())
    82  
    83  	_, err = http.PostForm(trackerURL+"/announce",
    84  		url.Values{"ipv4": {ann.ipv4},
    85  			"ipv6": {ann.ipv6},
    86  			"addr": {ann.addr},
    87  			"sig":  {ann.sig},
    88  			"pbk":  {ann.pbk}})
    89  
    90  	if err != nil {
    91  		return err
    92  	}
    93  
    94  	return nil
    95  }
    96  
    97  func Lookup(litadr string, trackerURL string, proxyURL string) (string, string, error) {
    98  	var client http.Client
    99  
   100  	if proxyURL != "" {
   101  		dialer, err := proxy.SOCKS5("tcp", proxyURL, nil, proxy.Direct)
   102  		if err != nil {
   103  			return "", "", err
   104  		}
   105  
   106  		client.Transport = &http.Transport{
   107  			Dial: dialer.Dial,
   108  		}
   109  	}
   110  
   111  	resp, err := client.Get(trackerURL + "/" + litadr)
   112  	if err != nil {
   113  		return "", "", err
   114  	}
   115  	defer resp.Body.Close()
   116  
   117  	decoder := json.NewDecoder(resp.Body)
   118  	var node nodeinfo
   119  	err = decoder.Decode(&node)
   120  	if err != nil {
   121  		return "", "", err
   122  	}
   123  
   124  	if !node.Success {
   125  		return "", "", errors.New("Node not found")
   126  	}
   127  
   128  	return node.Node.IPv4, node.Node.IPv6, nil
   129  }