From 5cc8efaa43505b25f32b6aa5716f728bebbf9328 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Sat, 16 Jan 2016 19:12:36 -0800 Subject: [PATCH] implement the gRPC "ConnectPeer" function within rpcserver --- omnihandler.go | 56 ------------ rpcserver.go | 234 +++++-------------------------------------------- 2 files changed, 24 insertions(+), 266 deletions(-) delete mode 100644 omnihandler.go diff --git a/omnihandler.go b/omnihandler.go deleted file mode 100644 index b92ab46c..00000000 --- a/omnihandler.go +++ /dev/null @@ -1,56 +0,0 @@ -package main - -import ( - "fmt" - "net" - - "github.com/lightningnetwork/lnd/lnwire" -) - -// it listens for incoming messages on the lndc and hands it over -// to the OmniHandler via omnichan -func LNDCReceiver(l net.Conn, id [16]byte, r *rpcServer) error { - for { - msg := make([]byte, 65535) - // fmt.Printf("read message from %x\n", l.RemoteLNId) - n, err := l.Read(msg) - if err != nil { - fmt.Printf("read error with %x: %s\n", - id, err.Error()) - delete(r.CnMap, id) - return l.Close() - } - msg = msg[:n] - msg = append(id[:], msg...) - r.OmniChan <- msg - } -} - -// handles stuff that comes in over the wire. Not user-initiated. -func OmniHandler(r *rpcServer) { - // var err error - var from [16]byte - for { - newdata := <-r.OmniChan // blocks here - if len(newdata) < 17 { - fmt.Printf("got too short message") - continue - } - copy(from[:], newdata[:16]) - msg := newdata[16:] - msgid := msg[0] - _, ok := r.CnMap[from] - if !ok { - fmt.Printf("not connected to %x\n", from) - continue - } - // TEXT MESSAGE. SIMPLE - if msgid == lnwire.MSGID_TEXTCHAT { //it's text - fmt.Printf("msg from %x: %s\n", from, msg[1:]) - continue - } - // Based on MSGID, hand it off to functions - fmt.Printf("Unknown message id byte %x", msgid) - continue - } -} diff --git a/rpcserver.go b/rpcserver.go index b61148a3..b32789dd 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -3,19 +3,13 @@ package main import ( "encoding/hex" "fmt" - "log" - "net" - "strings" - "github.com/btcsuite/btcd/chaincfg" + "sync" + "sync/atomic" - "github.com/btcsuite/btcd/btcec" "github.com/btcsuite/btcutil" "github.com/btcsuite/btcwallet/waddrmgr" - "github.com/lightningnetwork/lnd/lndc" "github.com/lightningnetwork/lnd/lnrpc" - "github.com/lightningnetwork/lnd/lnwallet" - "github.com/lightningnetwork/lnd/lnwire" "golang.org/x/net/context" ) @@ -35,66 +29,6 @@ type rpcServer struct { quit chan struct{} } -type LNAdr struct { - LNId [16]byte // redundant because adr contains it - Adr btcutil.Address - PubKey *btcec.PublicKey - - Name string - Host string - Endorsement []byte -} - -func (l *LNAdr) ParseFromString(s string) error { - var err error - if len(s) == 0 { - return fmt.Errorf("LNid ParseFromString: null string") - } - if l == nil { // make a LNId if it doesn't exist - return fmt.Errorf("null id, initialize first") - } - - ss := strings.Split(s, "@") - ident := ss[0] - if len(ss) > 1 { // redundant? no - l.Host = ss[1] - } - if len(ident) > 65 && len(ident) < 69 { // could be pubkey - pubkeyBytes, err := hex.DecodeString(ident) - if err != nil { - return err - } - l.PubKey, err = btcec.ParsePubKey(pubkeyBytes, btcec.S256()) - if err != nil { - return err - } - - // got pubey, populate address from pubkey - l.Adr, err = btcutil.NewAddressPubKeyHash(btcutil.Hash160( - l.PubKey.SerializeCompressed()), &chaincfg.TestNet3Params) - if err != nil { - return err - } - } else if len(ident) > 33 && len(ident) < 37 { // could be pkh - l.Adr, err = btcutil.DecodeAddress( - ident, &chaincfg.TestNet3Params) - if err != nil { - return err - } - } else { - return fmt.Errorf("invalid address %s", ident) - } - - // check for nonstandard port - // if strings.Count(lid.Host, ":") == 1 { - // } - //don't for now... stdlib should do this. ipv6 and stuff... - - // populate LNId from address - copy(l.LNId[:], l.Adr.ScriptAddress()) - return nil -} - var _ lnrpc.LightningServer = (*rpcServer)(nil) // newRpcServer... @@ -102,14 +36,22 @@ func newRpcServer(s *server) *rpcServer { return &rpcServer{server: s, quit: make(chan struct{}, 1)} } -// Stop... -func (r *rpcServer) Stop() error { +// Start... +func (r *rpcServer) Start() error { + if atomic.AddInt32(&r.started, 1) != 1 { + return nil + } + return nil } +// Stop... +func (r *rpcServer) Stop() error { + if atomic.AddInt32(&r.shutdown, 1) != 1 { + return nil } - fmt.Printf("got privkey %x\n", priv.Serialize()) // may want to remove this :) - return priv, nil + + return nil } // SendMany... @@ -120,7 +62,7 @@ func (r *rpcServer) SendMany(ctx context.Context, in *lnrpc.SendManyRequest) (*l sendMap[addr] = btcutil.Amount(amt) } - txid, err := r.lnwallet.SendPairs(sendMap, defaultAccount, 1) + txid, err := r.server.lnwallet.SendPairs(sendMap, defaultAccount, 1) if err != nil { return nil, err } @@ -131,10 +73,10 @@ func (r *rpcServer) SendMany(ctx context.Context, in *lnrpc.SendManyRequest) (*l // NewAddress... func (r *rpcServer) NewAddress(ctx context.Context, in *lnrpc.NewAddressRequest) (*lnrpc.NewAddressResponse, error) { - r.lnwallet.KeyGenMtx.Lock() - defer r.lnwallet.KeyGenMtx.Unlock() + r.server.lnwallet.KeyGenMtx.Lock() + defer r.server.lnwallet.KeyGenMtx.Unlock() - addr, err := r.lnwallet.NewAddress(defaultAccount) + addr, err := r.server.lnwallet.NewAddress(defaultAccount) if err != nil { return nil, err } @@ -142,150 +84,22 @@ func (r *rpcServer) NewAddress(ctx context.Context, in *lnrpc.NewAddressRequest) return &lnrpc.NewAddressResponse{Address: addr.String()}, nil } -// LNConnect -func (r *rpcServer) LNConnect(ctx context.Context, - in *lnrpc.LNConnectRequest) (*lnrpc.LnConnectResponse, error) { - - var err error +// LNConnect... +func (r *rpcServer) ConnectPeer(ctx context.Context, + in *lnrpc.ConnectPeerRequest) (*lnrpc.ConnectPeerResponse, error) { if len(in.IdAtHost) == 0 { return nil, fmt.Errorf("need: lnc pubkeyhash@hostname") } - var newNode LNAdr - err = newNode.ParseFromString(in.IdAtHost) - if err != nil { - return nil, err - } - if _, ok := r.CnMap[newNode.LNId]; ok { - return nil, fmt.Errorf("Already connected to %x", newNode.LNId) - } - if newNode.Host == "" { // do PBX connect; leave for now - return nil, fmt.Errorf("no hostname") - } - priv, err := getPriv(r.lnwallet) + peerAddr, err := newLnAddr(in.IdAtHost) if err != nil { return nil, err } - // dial TCP - newConn := new(lndc.LNDConn) - newConn.Cn, err = net.Dial("tcp", newNode.Host+":"+"2448") - if err != nil { - return nil, err - } - // TODO differentiate; right now only uses PKH - if newNode.PubKey != nil { // have pubkey, use that - err = newConn.Open(priv, newNode.Adr.ScriptAddress()) - if err != nil { - return nil, err - } - } else { // only have address (pubkey hash), use that - err = newConn.Open(priv, newNode.Adr.ScriptAddress()) - if err != nil { - return nil, err - } - } - - idslice := lndc.H160(newConn.RemotePub.SerializeCompressed()) - var newId [16]byte - copy(newId[:], idslice[:16]) - r.CnMap[newId] = newConn - log.Printf("added %x to map\n", newId) - - go LNDCReceiver(newConn, newId, r) - - resp := new(lnrpc.LnConnectResponse) - resp.LnID = newId[:] - return resp, nil -} - -// TCPListen -func (r *rpcServer) TCPListen(ctx context.Context, - in *lnrpc.TCPListenRequest) (*lnrpc.TCPListenResponse, error) { - // LnListen listens on the default port for incoming connections - //ignore args and launch listener goroutine - priv, err := getPriv(r.lnwallet) - if err != nil { + if err := r.server.ConnectToPeer(peerAddr); err != nil { return nil, err } - go TCPListener(priv, r) - - resp := new(lnrpc.TCPListenResponse) - return resp, nil -} - -// LNChat -func (r *rpcServer) LNChat(ctx context.Context, - in *lnrpc.LnChatRequest) (*lnrpc.LnChatResponse, error) { - log.Printf("requested to chat, message: %s\n", in.Msg) - - var dest [16]byte - if len(in.DestID) != 16 { - return nil, fmt.Errorf("Expect 16 byte destination Id, got %d byte", - len(in.DestID)) - } - copy(dest[:], in.DestID) - if len(in.Msg) == 0 { - return nil, fmt.Errorf("you have to say something") - } - if len(r.CnMap) == 0 { // This check is redundant. May still help though. - return nil, fmt.Errorf("Not connected to anyone") - } - if _, ok := r.CnMap[dest]; !ok { - return nil, fmt.Errorf("dest %x not connected", dest) - } - - msg := append([]byte{lnwire.MSGID_TEXTCHAT}, []byte(in.Msg)...) - - _, err := r.CnMap[dest].Write(msg) - if err != nil { - return nil, err - } - - resp := new(lnrpc.LnChatResponse) - return resp, nil -} - -func TCPListener(priv *btcec.PrivateKey, r *rpcServer) { - listener, err := net.Listen("tcp", ":"+"2448") - if err != nil { - fmt.Printf("TCP listen error: %s\n", err.Error()) - return - } - - fmt.Printf("Listening on %s\n", listener.Addr().String()) - for { - con, err := listener.Accept() // this blocks - if err != nil { - log.Printf("Listener error: %s\n", err.Error()) - continue - } - newConn, err := InitIncomingConn(priv, con) - if err != nil { - fmt.Printf("InitConn error: %s\n", err.Error()) - continue - } - idslice := lndc.H160(newConn.RemotePub.SerializeCompressed()) - var newId [16]byte - copy(newId[:], idslice[:16]) - r.CnMap[newId] = newConn - fmt.Printf("added %x to map\n", newId) - - go LNDCReceiver(newConn, newId, r) - } -} - -func InitIncomingConn(priv *btcec.PrivateKey, con net.Conn) (*lndc.LNDConn, error) { - LNcon := new(lndc.LNDConn) - LNcon.Cn = con - err := LNcon.Setup(priv) - if err != nil { - return LNcon, err - } - fmt.Printf("Got connection from %s authed with pubkey %x", - LNcon.Cn.RemoteAddr().String(), LNcon.RemotePub.SerializeCompressed()) - return LNcon, nil - + return &lnrpc.ConnectPeerResponse{[]byte(peerAddr.String())}, nil }