lnsocket.go (3904B)
1 package lnsocket 2 3 import ( 4 "bytes" 5 "encoding/hex" 6 "fmt" 7 "io" 8 "net" 9 10 "github.com/btcsuite/btcd/btcec" 11 "github.com/lightningnetwork/lnd/brontide" 12 "github.com/lightningnetwork/lnd/keychain" 13 "github.com/lightningnetwork/lnd/lnwire" 14 "github.com/lightningnetwork/lnd/tor" 15 ) 16 17 const ( 18 COMMANDO_CMD = 0x4c4f 19 COMMANDO_REPLY_CONTINUES = 0x594b 20 COMMANDO_REPLY_TERM = 0x594d 21 ) 22 23 type CommandoMsg struct { 24 Rune string 25 Method string 26 Params string 27 RequestId uint64 28 } 29 30 func NewCommandoMsg(token string, method string, params string) CommandoMsg { 31 return CommandoMsg{ 32 Rune: token, 33 Method: method, 34 Params: params, 35 } 36 } 37 38 // A compile time check to ensure Init implements the lnwire.Message 39 // interface. 40 41 func (msg *CommandoMsg) MsgType() lnwire.MessageType { 42 return COMMANDO_CMD 43 } 44 45 func (msg *CommandoMsg) Decode(reader io.Reader, size uint32) error { 46 return fmt.Errorf("implememt commando decode?") 47 } 48 49 func (msg *CommandoMsg) Encode(buf *bytes.Buffer, pver uint32) error { 50 if err := lnwire.WriteUint64(buf, msg.RequestId); err != nil { 51 return err 52 } 53 54 buf.WriteString("{\"method\": \"") 55 buf.WriteString(msg.Method) 56 buf.WriteString("\",\"params\":") 57 buf.WriteString(msg.Params) 58 buf.WriteString(",\"rune\":\"") 59 buf.WriteString(msg.Rune) 60 buf.WriteString("\"}") 61 62 return nil 63 } 64 65 type LNSocket struct { 66 Conn net.Conn 67 PrivKeyECDH *keychain.PrivKeyECDH 68 } 69 70 func (ln *LNSocket) GenKey() { 71 remotePriv, _ := btcec.NewPrivateKey(btcec.S256()) 72 ln.PrivKeyECDH = &keychain.PrivKeyECDH{PrivKey: remotePriv} 73 } 74 75 func (ln *LNSocket) ConnectWith(netAddr *lnwire.NetAddress) error { 76 conn, err := brontide.Dial(ln.PrivKeyECDH, netAddr, tor.DefaultConnTimeout, net.DialTimeout) 77 ln.Conn = conn 78 return err 79 } 80 81 func (ln *LNSocket) Connect(hostname string, pubkey string) error { 82 addr, err := net.ResolveTCPAddr("tcp", hostname) 83 if err != nil { 84 return err 85 } 86 bytes, err := hex.DecodeString(pubkey) 87 if err != nil { 88 return err 89 } 90 key, err := btcec.ParsePubKey(bytes, btcec.S256()) 91 if err != nil { 92 return err 93 } 94 95 netAddr := &lnwire.NetAddress{ 96 IdentityKey: key, 97 Address: addr, 98 } 99 100 return ln.ConnectWith(netAddr) 101 } 102 103 func (ln *LNSocket) PerformInit() error { 104 no_features := lnwire.NewRawFeatureVector() 105 init_reply_msg := lnwire.NewInitMessage(no_features, no_features) 106 107 var b bytes.Buffer 108 _, err := lnwire.WriteMessage(&b, init_reply_msg, 0) 109 if err != nil { 110 return err 111 } 112 _, err = ln.Conn.Write(b.Bytes()) 113 114 // receive the first init msg 115 _, _, err = ln.Recv() 116 if err != nil { 117 return err 118 } 119 120 return nil 121 } 122 123 func (ln *LNSocket) Rpc(token string, method string, params string) (string, error) { 124 commando_msg := NewCommandoMsg(token, method, params) 125 126 var b bytes.Buffer 127 _, err := lnwire.WriteMessage(&b, &commando_msg, 0) 128 if err != nil { 129 return "", err 130 } 131 132 bs := b.Bytes() 133 _, err = ln.Conn.Write(bs) 134 if err != nil { 135 return "", err 136 } 137 138 return ln.rpcReadAll() 139 } 140 141 func ParseMsgType(bytes []byte) uint16 { 142 return uint16(bytes[0])<<8 | uint16(bytes[1]) 143 } 144 145 func (ln *LNSocket) Recv() (uint16, []byte, error) { 146 res := make([]byte, 65535) 147 n, err := ln.Conn.Read(res) 148 if err != nil { 149 return 0, nil, err 150 } 151 if n < 2 { 152 return 0, nil, fmt.Errorf("read too small") 153 } 154 res = res[:n] 155 msgtype := ParseMsgType(res) 156 return msgtype, res[2:], nil 157 } 158 159 func (ln *LNSocket) rpcReadAll() (string, error) { 160 all := []byte{} 161 for { 162 msgtype, res, err := ln.Recv() 163 if err != nil { 164 return "", err 165 } 166 switch msgtype { 167 case COMMANDO_REPLY_CONTINUES: 168 all = append(all, res[8:]...) 169 continue 170 case COMMANDO_REPLY_TERM: 171 all = append(all, res[8:]...) 172 return string(all), nil 173 default: 174 continue 175 } 176 } 177 } 178 179 func (ln *LNSocket) Disconnect() { 180 ln.Conn.Close() 181 } 182 183 func (ln *LNSocket) ConnectAndInit(hostname string, pubkey string) error { 184 err := ln.Connect(hostname, pubkey) 185 if err != nil { 186 return err 187 } 188 189 return ln.PerformInit() 190 }