main.go 3.59 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"
9
	"math/rand"
Jeromy's avatar
Jeromy committed
10
	"strings"
11
	"time"
Jeromy's avatar
Jeromy committed
12

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

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

Jeromy's avatar
Jeromy committed
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
	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
52
53
	}

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

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

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

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

Jeromy's avatar
Jeromy committed
73
74
	flag.Parse()

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

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

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

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

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

Jeromy's avatar
Jeromy committed
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
	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
115
	// This creates a MA with the "/ip4/ipaddr/tcp/port" part of the target
Jeromy's avatar
Jeromy committed
116
	tptmaddr, err := ma.NewMultiaddr(tptaddr)
Jeromy's avatar
Jeromy committed
117
118
119
120
	if err != nil {
		log.Fatalln(err)
	}

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

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

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

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

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

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

Lars Gierth's avatar
Lars Gierth committed
156
157
158
159
160
	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
161
162
	}
}