main.go 3.58 KB
Newer Older
Jeromy's avatar
Jeromy committed
1
2
3
package main

import (
4
	"context"
Jeromy's avatar
Jeromy committed
5
6
7
8
	"flag"
	"fmt"
	"io/ioutil"
	"log"
Jeromy's avatar
Jeromy committed
9
	"strings"
Jeromy's avatar
Jeromy committed
10

Hector Sanjuan's avatar
Hector Sanjuan committed
11
	golog "github.com/ipfs/go-log"
Jeromy's avatar
Jeromy committed
12
	host "github.com/libp2p/go-libp2p-host"
Jeromy's avatar
Jeromy committed
13
14
	inet "github.com/libp2p/go-libp2p-net"
	net "github.com/libp2p/go-libp2p-net"
Jeromy's avatar
Jeromy committed
15
	peer "github.com/libp2p/go-libp2p-peer"
Hector Sanjuan's avatar
Hector Sanjuan committed
16
	peerstore "github.com/libp2p/go-libp2p-peerstore"
Jeromy's avatar
Jeromy committed
17
	pstore "github.com/libp2p/go-libp2p-peerstore"
Jeromy's avatar
Jeromy committed
18
	swarm "github.com/libp2p/go-libp2p-swarm"
Hector Sanjuan's avatar
Hector Sanjuan committed
19
	bhost "github.com/libp2p/go-libp2p/p2p/host/basic"
Jeromy's avatar
Jeromy committed
20
	testutil "github.com/libp2p/go-testutil"
Jeromy's avatar
Jeromy committed
21
	ma "github.com/multiformats/go-multiaddr"
Hector Sanjuan's avatar
Hector Sanjuan committed
22
	gologging "github.com/whyrusleeping/go-logging"
Jeromy's avatar
Jeromy committed
23
24
25
)

// create a 'Host' with a random peer to listen on the given address
Hector Sanjuan's avatar
Hector Sanjuan committed
26
func makeBasicHost(listen string, secio bool) (host.Host, error) {
Jeromy's avatar
Jeromy committed
27
28
29
30
31
	addr, err := ma.NewMultiaddr(listen)
	if err != nil {
		return nil, err
	}

Jeromy's avatar
Jeromy committed
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
	ps := pstore.NewPeerstore()
	var pid peer.ID

	if secio {
		ident, err := testutil.RandIdentity()
		if err != nil {
			return nil, err
		}

		ident.PrivateKey()
		ps.AddPrivKey(ident.ID(), ident.PrivateKey())
		ps.AddPubKey(ident.ID(), ident.PublicKey())
		pid = ident.ID()
	} else {
		fakepid, err := testutil.RandPeerID()
		if err != nil {
			return nil, err
		}
		pid = fakepid
Jeromy's avatar
Jeromy committed
51
52
	}

Jeromy's avatar
Jeromy committed
53
	ctx := context.Background()
Jeromy's avatar
Jeromy committed
54
55

	// create a new swarm to be used by the service host
Jeromy's avatar
Jeromy committed
56
	netw, err := swarm.NewNetwork(ctx, []ma.Multiaddr{addr}, pid, ps, nil)
Jeromy's avatar
Jeromy committed
57
58
59
60
61
62
63
64
65
	if err != nil {
		return nil, err
	}

	log.Printf("I am %s/ipfs/%s\n", addr, pid.Pretty())
	return bhost.New(netw), nil
}

func main() {
Hector Sanjuan's avatar
Hector Sanjuan committed
66
	golog.SetAllLoggers(gologging.INFO) // Change to DEBUG for extra info
Jeromy's avatar
Jeromy committed
67
68
	listenF := flag.Int("l", 0, "wait for incoming connections")
	target := flag.String("d", "", "target peer to dial")
Jeromy's avatar
Jeromy committed
69
70
	secio := flag.Bool("secio", false, "enable secio")

Jeromy's avatar
Jeromy committed
71
72
	flag.Parse()

Hector Sanjuan's avatar
Hector Sanjuan committed
73
74
75
76
	if *listenF == 0 {
		log.Fatal("Please provide a port to bind on with -l")
	}

Lars Gierth's avatar
Lars Gierth committed
77
	listenaddr := fmt.Sprintf("/ip4/127.0.0.1/tcp/%d", *listenF)
Jeromy's avatar
Jeromy committed
78

Hector Sanjuan's avatar
Hector Sanjuan committed
79
	ha, err := makeBasicHost(listenaddr, *secio)
Jeromy's avatar
Jeromy committed
80
81
82
83
84
	if err != nil {
		log.Fatal(err)
	}

	// Set a stream handler on host A
Jeromy's avatar
Jeromy committed
85
	ha.SetStreamHandler("/echo/1.0.0", func(s net.Stream) {
Hector Sanjuan's avatar
Hector Sanjuan committed
86
		log.Println("Got a new stream!")
Jeromy's avatar
Jeromy committed
87
		defer s.Close()
Hector Sanjuan's avatar
Hector Sanjuan committed
88
		doEcho(s)
Jeromy's avatar
Jeromy committed
89
90
91
	})

	if *target == "" {
Lars Gierth's avatar
Lars Gierth committed
92
		log.Println("listening for connections")
Jeromy's avatar
Jeromy committed
93
		select {} // hang forever
Jeromy's avatar
Jeromy committed
94
	}
Hector Sanjuan's avatar
Hector Sanjuan committed
95
	// This is where the listener code ends
Jeromy's avatar
Jeromy committed
96

Jeromy's avatar
Jeromy committed
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
	ipfsaddr, err := ma.NewMultiaddr(*target)
	if err != nil {
		log.Fatalln(err)
	}

	pid, err := ipfsaddr.ValueForProtocol(ma.P_IPFS)
	if err != nil {
		log.Fatalln(err)
	}

	peerid, err := peer.IDB58Decode(pid)
	if err != nil {
		log.Fatalln(err)
	}

	tptaddr := strings.Split(ipfsaddr.String(), "/ipfs/")[0]
Hector Sanjuan's avatar
Hector Sanjuan committed
113
	// This creates a MA with the "/ip4/ipaddr/tcp/port" part of the target
Jeromy's avatar
Jeromy committed
114
	tptmaddr, err := ma.NewMultiaddr(tptaddr)
Jeromy's avatar
Jeromy committed
115
116
117
118
	if err != nil {
		log.Fatalln(err)
	}

Hector Sanjuan's avatar
Hector Sanjuan committed
119
120
121
	// We need to add the target to our peerstore, so we know how we can
	// contact it
	ha.Peerstore().AddAddr(peerid, tptmaddr, peerstore.PermanentAddrTTL)
Jeromy's avatar
Jeromy committed
122

Lars Gierth's avatar
Lars Gierth committed
123
	log.Println("opening stream")
Jeromy's avatar
Jeromy committed
124
	// make a new stream from host B to host A
Hector Sanjuan's avatar
Hector Sanjuan committed
125
	// it should be handled on host A by the handler we set above
Lars Gierth's avatar
Lars Gierth committed
126
	s, err := ha.NewStream(context.Background(), peerid, "/echo/1.0.0")
Jeromy's avatar
Jeromy committed
127
128
129
130
	if err != nil {
		log.Fatalln(err)
	}

Lars Gierth's avatar
Lars Gierth committed
131
	_, err = s.Write([]byte("Hello, world!"))
Jeromy's avatar
Jeromy committed
132
133
134
135
	if err != nil {
		log.Fatalln(err)
	}

Jeromy's avatar
Jeromy committed
136
137
138
139
140
	out, err := ioutil.ReadAll(s)
	if err != nil {
		log.Fatalln(err)
	}

Lars Gierth's avatar
Lars Gierth committed
141
	log.Printf("read reply: %q\n", out)
Jeromy's avatar
Jeromy committed
142
}
Jeromy's avatar
Jeromy committed
143

Hector Sanjuan's avatar
Hector Sanjuan committed
144
145
// doEcho reads some data from a stream, writes it back and closes the
// stream.
Jeromy's avatar
Jeromy committed
146
147
func doEcho(s inet.Stream) {
	buf := make([]byte, 1024)
Lars Gierth's avatar
Lars Gierth committed
148
149
150
151
152
	n, err := s.Read(buf)
	if err != nil {
		log.Println(err)
		return
	}
Jeromy's avatar
Jeromy committed
153

Lars Gierth's avatar
Lars Gierth committed
154
155
156
157
158
	log.Printf("read request: %q\n", buf[:n])
	_, err = s.Write(buf[:n])
	if err != nil {
		log.Println(err)
		return
Jeromy's avatar
Jeromy committed
159
160
	}
}