From c1a92a0c80213d1eba912f47960f0184b0dd5cf9 Mon Sep 17 00:00:00 2001 From: rairyx Date: Tue, 7 May 2019 15:32:53 -0700 Subject: [PATCH] Add kademlia node discovery --- pubsub/Makefile | 2 +- pubsub/raven.go | 200 +++++++++++++++++++++++++++++++++++ util/private_key.bin.peer.w6 | Bin 0 -> 2353 bytes 3 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 pubsub/raven.go create mode 100755 util/private_key.bin.peer.w6 diff --git a/pubsub/Makefile b/pubsub/Makefile index 15836e0..d81dcba 100644 --- a/pubsub/Makefile +++ b/pubsub/Makefile @@ -1,4 +1,4 @@ -SRC = pubsub-interop.go +SRC = raven.go BIN = $(SRC:.go=) DHT_SERVER = libp2p-bootstrap.goelzer.io diff --git a/pubsub/raven.go b/pubsub/raven.go new file mode 100644 index 0000000..c7fe672 --- /dev/null +++ b/pubsub/raven.go @@ -0,0 +1,200 @@ +package main + +import ( + "bufio" + "context" + "fmt" + "io/ioutil" + "os" + _ "time" + "strconv" + "github.com/ipfs/go-log" + libp2p "github.com/libp2p/go-libp2p" + host "github.com/libp2p/go-libp2p-host" + inet "github.com/libp2p/go-libp2p-net" + peerstore "github.com/libp2p/go-libp2p-peerstore" + libp2pdht "github.com/libp2p/go-libp2p-kad-dht" + "github.com/libp2p/go-libp2p-crypto" + + logging "github.com/whyrusleeping/go-logging" + floodsub "github.com/libp2p/go-floodsub" + ma "github.com/multiformats/go-multiaddr" +) + +var logger = log.Logger("raven") +var ho host.Host + +//var TopicName string = "libp2p-demo-chat" +//h("libp2p-demo-chat") = "RDEpsjSPrAZF9JCK5REt3tao" - rust uses the hash unlike js/go () +var TopicName string = "RDEpsjSPrAZF9JCK5REt3tao" + +func parseArgs() (bool, string, int) { + usage := fmt.Sprintf("Usage: %s PRIVATE_KEY PORT [--bootstrapper] \n\nPRIVATE_KEY is the path to a private key like '../util/private_key.bin'\n PORT is port to listen on, default is 6000\n--bootstrapper to run in bootstrap mode (creates a DHT and listens for peers)\n", os.Args[0]) + var bBootstrap bool = false + var privKeyFilePath string + var listenPort = 6000 + var args []string = os.Args[1:] + if (len(args) == 0) || (len(args) > 3) { + fmt.Printf("Error: wrong number of arguments\n\n%s", usage) + os.Exit(1) + } + privKeyFilePath = args[0] + if (len(args) == 2) && (args[1] == "--bootstrapper") { + bBootstrap = true + }else if (len(args) == 2) { + listenPort, _ = strconv.Atoi(args[1]) + } + return bBootstrap, privKeyFilePath, listenPort +} + +func handleConn(conn inet.Conn) { + ctx := context.Background() + h := ho + fmt.Printf(" New peer joined: %v\n", conn.RemoteMultiaddr().String()) + _ = h + _ = ctx +} + +func main() { + log.SetAllLoggers(logging.INFO) + log.SetLogLevel("raven", "debug") + ctx := context.Background() + + bBootstrap, privKeyFilePath, port := parseArgs() + fmt.Printf("Starting up in ") + if bBootstrap { + fmt.Printf("bootstrapper mode (port 5555)") + } else { + fmt.Printf("peer mode port: %d", port) + } + fmt.Printf("\nPrivate key '%s'\n", privKeyFilePath) + + // + // Read the private key and unmarshall it into struct + // + var privBytes []byte + privBytes, err := ioutil.ReadFile(privKeyFilePath) + if err != nil { + fmt.Println("ioutil.ReadFile: failed: %v", err) + panic(err) + } + + var priv crypto.PrivKey + priv, err = crypto.UnmarshalPrivateKey(privBytes) + if err != nil { + fmt.Println("crypto.UnmarshalPrivateKey: failed: %v", err) + panic(err) + } + + // + // Construct our libp2p host + // + var host host.Host + if bBootstrap { + host, err = libp2p.New(ctx, + libp2p.ListenAddrStrings("/ip4/0.0.0.0/tcp/5555"), + libp2p.Identity(priv), + // libp2p.DisableRelay(), + ) + } else { + host, err = libp2p.New(ctx, + libp2p.ListenAddrStrings(fmt.Sprintf("/ip4/0.0.0.0/tcp/%d",port)), + libp2p.Identity(priv), + libp2p.DisableRelay(), + ) + + } + if err != nil { + fmt.Println("libp2p.New: failed: %v", err) + panic(err) + } + logger.Info("Host created. We are:", host.ID()) + kademliaDHT, err := libp2pdht.New(ctx, host) + if err != nil { + panic(err) + } + + // Bootstrap the DHT. In the default configuration, this spawns a Background + // thread that will refresh the peer table every five minutes. + logger.Debug("Bootstrapping the DHT") + if err = kademliaDHT.Bootstrap(ctx); err != nil { + panic(err) + } + // Construct a floodsub instance for this host + fsub, err := floodsub.NewFloodSub(ctx, host, floodsub.WithMessageSigning(false)) + if err != nil { + fmt.Println("Error (floodsub.NewFloodSub): %v", err) + panic(err) + } + const bootstrapAddrIP4Str string = "127.0.0.1" + // If we are the bootstrap node, we don't try to connect to any peers. + // Else: try to connect to the bootstrap node. + // + if !bBootstrap { + + var bootstrapMultiAddr ma.Multiaddr + var pinfo *peerstore.PeerInfo + bootstrapMultiAddrStr := fmt.Sprintf("/ip4/%s/tcp/5555/ipfs/QmehVYruznbyDZuHBV4vEHESpDevMoAovET6aJ9oRuEzWa", bootstrapAddrIP4Str) + fmt.Printf("bootstrapping to '%s'...\n", bootstrapMultiAddrStr) + bootstrapMultiAddr, err = ma.NewMultiaddr(bootstrapMultiAddrStr) + if err != nil { + fmt.Println("Error (ma.NewMultiaddr): %v", err) + panic(err) + } + + pinfo, err = peerstore.InfoFromP2pAddr(bootstrapMultiAddr) + if err != nil { + fmt.Println("Error (ma.NewMultiaddr): %v", err) + panic(err) + } + + if err := host.Connect(ctx, *pinfo); err != nil { + fmt.Println("bootstrapping to peer failed: ", err) + } + } + + // + // Subscribe to the topic and wait for messages published on that topic + // + sub, err := fsub.Subscribe(TopicName) + if err != nil { + fmt.Println("Error (fsub.Subscribe): %v", err) + panic(err) + } + + // Go and listen for messages from them, and print them to the screen + go func() { + for { + msg, err := sub.Next(ctx) + if err != nil { + fmt.Println("Error (sub.Next): %v", err) + panic(err) + } + + //fmt.Printf("%s: %s\n", msg.GetFrom(), string(msg.GetData())) + fmt.Printf("%s\n", string(msg.GetData())) + } + }() + + // SetConnHandler() should not normally be called. Instead, + // use Notify() and pass it a functioon. (The problem with + // SetConnHandler() is that it takes control of the connection.) + host.Network().Notify(&inet.NotifyBundle{ + ConnectedF: func(n inet.Network, c inet.Conn) { + fmt.Println("Got a connection:", c.RemotePeer()) + }, + }) + if bBootstrap { + fmt.Println("Bootstrapper running.\nPubSub object instantiated using FloodSubRouter.\nCtrl+C to exit.") + for true { + } + } else { + // Now, wait for input from the user, and send that out! + scan := bufio.NewScanner(os.Stdin) + for scan.Scan() { + if err := fsub.Publish(TopicName, scan.Bytes()); err != nil { + panic(err) + } + } + } +} diff --git a/util/private_key.bin.peer.w6 b/util/private_key.bin.peer.w6 new file mode 100755 index 0000000000000000000000000000000000000000..894dcc57233885588a33a2d4e1c09b53e6960ebd GIT binary patch literal 2353 zcmV-13C{Ki01~VcFoFpv0s#O5f&u{m^EkhQtDnwU@lVPQkVq};{BS*ZH%jKJGZ3T4 zUh@+xm2N&6=ykGz0}x!2h!VW(lRlvnG<277cX8exICPhW%Oq`#gr0^y%x5!9@dqbD z8(~RdMIdmRa%j)wO=EZCBH-soVkLf7WA|wi)Cd8zBw~C^1GFm@a50D(**R`vu|CSP zAd9ZOV48S8Sr;yleC@^`ky3M%EN2L;V<#-Zc5w9wl)kn}!@fIj4et%b|0D|ot<;z_ zqMQOxPJu!yz=P_Hpxj~xw5r3Q`M-KxkeVwy6{9ID)F&U?07<>!S@&;dluU)ItGVhh z#dO~a4Q078o}fbi#j8m40kri-??*dn4?Dodr0LZ2g3vKzQmo9p_oIWDXTzMBKZmeJ zWOaypV{jZ1&VP6BQxuWEKkaO>h$1O%?EaA-{vApZ+z4JmRZ1PJxxW++lcYalIlLge ziuFNI=K@(-3y6T^ado?seI#m4k?F;c#KSGBunR_PHc4%>do*n&E}os#$i6H>XaE z!8j!q7Ly>@WuByG8UsGfRTLB~YXC^R60LoA#lU{xt*g(B%){vIz7>|^D2@3v-fc8> zR*;Ke%`ADfQ)irGOQFP9PY=kCkR9Dx%7#MH)a@yLa@xLbe|u+x;N zunj%%(N!0^Tk${iYtp-R?WMoA-Y$2VV|B)@4OknW)2^d7F?++x?@6q)Rutun7BiYW zisa3LC~HT6h}fHxs>XMr$YIq!@hDBjWG7~LeK7=4PXk-J2yp*tkhU0*pjOubi)wNK{{nc~3r zlNOrqXzu541Zv2=5j5hu0Jc7#jQBj_sZP6JSq@*T18zj;N^O@hpOk_|Bz$VQrtdjl zms2rlYr4a^Xmu*Y8yG!w9Y`U7D<0X)Se-61hqF!b#XunG=B^W9sm&LE*tWUto;sRZ zyCmNjV%8s`Q!mbtxn$>(aG_P6$Onqv+ZU=MiuKXUAlmJn@vJjA3LxlHTK(J|gBJy1 z*W=Atz^Zr1v<`Vr_~+wvfhPdQYu|U91lWZa*Dz0=)<^5~Da_OIM$_~NcjHqoIO2DT z$=YzvXpK>~sS0Ra2X(@5--%MgW*EBa?qE|y~B=nZcrLa{1}%?Wed z!@T=S0aB-M9%tyEv#=oGbiCzjn};os&@pjoNv=7&}a3JY;j( z1OIxbvA`D?HY)OBo_?wEyQ8b@7u+Qtz>QV^0v3Y~Xckxh;jU^QE*_! z2QS5h{1dY~4{_Fg_JgvbQm1M%HRq8P?#?0q?CskAw|ena7w)AW#lXy@8l{mH@UabO z7{hx0dBkZHi3Ah9O3Q_@#tW3d7HRkbzy!Q6G8a%6enP)P_56L3#!bv-%&|y@R z_7ZbL$=mEOkEC4ubKZTpF5?1%0RaH_MN~?-o?!M0%q2U9aU6?VXNQn7R|jZ zJ@n2tj936SRxK*MH^2c;@m?bIA*rfn0I;vbvli=tP1+T`K*S$9ic;wK!0e0C99QN{tosOhU^ zkbqrs(2i?KU|dEZEZI_(TE*QqTB?U&$()ydW)`B?fe8q%`+@&mkJ9LxykljmjAMg4 z*%|<&jcTl*?yZ@tT1M^Y2O%h=nw0vjrnz{Lt8OW5u}Q=iKyWOS_dxUOTikR0G2z z75hA~VuiNMW1mteJpd_axuS@mCpcSg25iqAE1rqgwCE>uXKByse`~G=bpAMEV8EA0)hbmV$|%wVYSfjAQDy&=ru^wOAN_>?q>8-*W^lh=>0BMy|TFrTo=z6Zl~Rp zAsKy}g%h9fVTmS9}LCrNUd@khT5L Xnr{Jm)CVSC2YJ=1_e-TZF&s+sIV*lW literal 0 HcmV?d00001