diff --git a/examples/hosts/README.md b/examples/hosts/README.md new file mode 100644 index 0000000000000000000000000000000000000000..cec309d27f70207fa5b59d5c1877d203b4617854 --- /dev/null +++ b/examples/hosts/README.md @@ -0,0 +1,28 @@ +# libp2p host example + +## What this does +This example can be started in either listen mode, or dial mode. +When running as a listener, it will sit and wait for incoming connections on +the `/hello/1.0.0` protocol. Whenever it receives a stream, it will +write the message "hello libp2p" over the stream and close it. +When run in dial mode, the node will start up, connect to the given +address, open a stream to the target peer, and read a message on the +protocol `/hello/1.0.0` + +## Building +``` +$ go build +``` + +## Usage +In one terminal: +``` +$ ./hosts -l 4737 +``` + +In another, copy the address printed by the listener and do: + +``` +$ ./hosts -d ADDRESS +``` + diff --git a/examples/hosts/main.go b/examples/hosts/main.go new file mode 100644 index 0000000000000000000000000000000000000000..16c6de4936782e33aeb3b158a40fd6b023fbf3c3 --- /dev/null +++ b/examples/hosts/main.go @@ -0,0 +1,108 @@ +package main + +import ( + "flag" + "fmt" + "io/ioutil" + "log" + "time" + + pstore "github.com/ipfs/go-libp2p-peerstore" + host "github.com/ipfs/go-libp2p/p2p/host" + bhost "github.com/ipfs/go-libp2p/p2p/host/basic" + metrics "github.com/ipfs/go-libp2p/p2p/metrics" + net "github.com/ipfs/go-libp2p/p2p/net" + conn "github.com/ipfs/go-libp2p/p2p/net/conn" + swarm "github.com/ipfs/go-libp2p/p2p/net/swarm" + testutil "github.com/ipfs/go-libp2p/testutil" + + ipfsaddr "github.com/ipfs/go-ipfs/thirdparty/ipfsaddr" + ma "github.com/jbenet/go-multiaddr" + context "golang.org/x/net/context" +) + +// create a 'Host' with a random peer to listen on the given address +func makeDummyHost(listen string) (host.Host, error) { + addr, err := ma.NewMultiaddr(listen) + if err != nil { + return nil, err + } + + pid, err := testutil.RandPeerID() + if err != nil { + return nil, err + } + + // bandwidth counter, should be optional in the future + bwc := metrics.NewBandwidthCounter() + + // create a new swarm to be used by the service host + netw, err := swarm.NewNetwork(context.Background(), []ma.Multiaddr{addr}, pid, pstore.NewPeerstore(), bwc) + if err != nil { + return nil, err + } + + log.Printf("I am %s/ipfs/%s\n", addr, pid.Pretty()) + return bhost.New(netw), nil +} + +func main() { + conn.EncryptConnections = false + listenF := flag.Int("l", 0, "wait for incoming connections") + target := flag.String("d", "", "target peer to dial") + flag.Parse() + + listenaddr := fmt.Sprintf("/ip4/0.0.0.0/tcp/%d", *listenF) + + ha, err := makeDummyHost(listenaddr) + if err != nil { + log.Fatal(err) + } + + message := []byte("hello libp2p!") + // Set a stream handler on host A + ha.SetStreamHandler("/hello/1.0.0", func(s net.Stream) { + defer s.Close() + log.Println("writing message") + s.Write(message) + }) + + if *target == "" { + log.Println("listening on for connections...") + for { + time.Sleep(time.Hour) + } + } + + a, err := ipfsaddr.ParseString(*target) + if err != nil { + log.Fatalln(err) + } + + pi := pstore.PeerInfo{ + ID: a.ID(), + Addrs: []ma.Multiaddr{a.Transport()}, + } + + log.Println("connecting to target") + err = ha.Connect(context.Background(), pi) + if err != nil { + log.Fatalln(err) + } + + log.Println("opening stream...") + // make a new stream from host B to host A + // it should be handled on host A by the handler we set + s, err := ha.NewStream(context.Background(), "/hello/1.0.0", a.ID()) + if err != nil { + log.Fatalln(err) + } + + log.Println("reading message") + out, err := ioutil.ReadAll(s) + if err != nil { + log.Fatalln(err) + } + + log.Println("GOT: ", string(out)) +}