Skip to content
This repository was archived by the owner on Feb 7, 2024. It is now read-only.

Commit 0b55b4d

Browse files
committed
Support for P2P listeners and streams
1 parent be6da7c commit 0b55b4d

File tree

2 files changed

+213
-0
lines changed

2 files changed

+213
-0
lines changed

p2p.go

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
package shell
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"strconv"
7+
8+
ma "github.com/multiformats/go-multiaddr"
9+
)
10+
11+
// P2PListener describes a P2P listener.
12+
type P2PListener struct {
13+
Protocol string
14+
Address string
15+
}
16+
17+
// P2POpenListener forwards P2P connections to a network multiaddr.
18+
func (s *Shell) P2POpenListener(ctx context.Context, protocol, maddr string) (*P2PListener, error) {
19+
if _, err := ma.NewMultiaddr(maddr); err != nil {
20+
return nil, err
21+
}
22+
23+
req := s.newRequest(ctx, "p2p/listener/open", protocol, maddr)
24+
resp, err := req.Send(s.httpcli)
25+
if err != nil {
26+
return nil, err
27+
}
28+
defer resp.Close()
29+
30+
if resp.Error != nil {
31+
return nil, resp.Error
32+
}
33+
34+
var response *P2PListener
35+
if err := json.NewDecoder(resp.Output).Decode(&response); err != nil {
36+
return nil, err
37+
}
38+
39+
return response, nil
40+
}
41+
42+
// P2PCloseListener closes one or all active P2P listeners.
43+
func (s *Shell) P2PCloseListener(ctx context.Context, protocol string, closeAll bool) error {
44+
var args []string
45+
if protocol != "" {
46+
args = append(args, protocol)
47+
}
48+
49+
req := s.newRequest(ctx, "p2p/listener/close", args...)
50+
req.Opts["all"] = strconv.FormatBool(closeAll)
51+
52+
resp, err := req.Send(s.httpcli)
53+
if err != nil {
54+
return err
55+
}
56+
defer resp.Close()
57+
58+
if resp.Error != nil {
59+
return resp.Error
60+
}
61+
62+
return nil
63+
}
64+
65+
// P2PListenerList contains a slice of P2PListeners.
66+
type P2PListenerList struct {
67+
Listeners []*P2PListener
68+
}
69+
70+
// P2PListListeners lists all P2P listeners.
71+
func (s *Shell) P2PListListeners(ctx context.Context) (*P2PListenerList, error) {
72+
req := s.newRequest(ctx, "p2p/listener/ls")
73+
resp, err := req.Send(s.httpcli)
74+
if err != nil {
75+
return nil, err
76+
}
77+
defer resp.Close()
78+
79+
if resp.Error != nil {
80+
return nil, resp.Error
81+
}
82+
83+
var response *P2PListenerList
84+
if err := json.NewDecoder(resp.Output).Decode(&response); err != nil {
85+
return nil, err
86+
}
87+
88+
return response, nil
89+
}
90+
91+
// P2PStream describes a P2P stream.
92+
type P2PStream struct {
93+
Protocol string
94+
Address string
95+
}
96+
97+
// P2PStreamDial dials to a peer's P2P listener.
98+
func (s *Shell) P2PStreamDial(ctx context.Context, peerID, protocol, listenerMaddr string) (*P2PStream, error) {
99+
if _, err := ma.NewMultiaddr(listenerMaddr); err != nil {
100+
return nil, err
101+
}
102+
103+
args := []string{peerID, protocol}
104+
if listenerMaddr != "" {
105+
args = append(args, listenerMaddr)
106+
}
107+
108+
req := s.newRequest(ctx, "p2p/stream/dial", args...)
109+
resp, err := req.Send(s.httpcli)
110+
if err != nil {
111+
return nil, err
112+
}
113+
defer resp.Close()
114+
115+
if resp.Error != nil {
116+
return nil, resp.Error
117+
}
118+
119+
var response *P2PStream
120+
if err := json.NewDecoder(resp.Output).Decode(&response); err != nil {
121+
return nil, err
122+
}
123+
124+
return response, nil
125+
}
126+
127+
// P2PCloseStream closes one or all active P2P streams.
128+
func (s *Shell) P2PCloseStream(ctx context.Context, handlerID string, closeAll bool) error {
129+
var args []string
130+
if handlerID != "" {
131+
args = append(args, handlerID)
132+
}
133+
134+
req := s.newRequest(ctx, "p2p/stream/close", args...)
135+
req.Opts["all"] = strconv.FormatBool(closeAll)
136+
137+
resp, err := req.Send(s.httpcli)
138+
if err != nil {
139+
return err
140+
}
141+
defer resp.Close()
142+
143+
if resp.Error != nil {
144+
return resp.Error
145+
}
146+
147+
return nil
148+
}
149+
150+
// P2PStreamsList contains a slice of streams.
151+
type P2PStreamsList struct {
152+
Streams []*struct {
153+
HandlerID string
154+
Protocol string
155+
LocalPeer string
156+
LocalAddress string
157+
RemotePeer string
158+
RemoteAddress string
159+
}
160+
}
161+
162+
// P2PListStreams lists all P2P streams.
163+
func (s *Shell) P2PListStreams(ctx context.Context) (*P2PStreamsList, error) {
164+
req := s.newRequest(ctx, "p2p/stream/ls")
165+
req.Opts["headers"] = strconv.FormatBool(true)
166+
167+
resp, err := req.Send(s.httpcli)
168+
if err != nil {
169+
return nil, err
170+
}
171+
defer resp.Close()
172+
173+
if resp.Error != nil {
174+
return nil, resp.Error
175+
}
176+
177+
var response *P2PStreamsList
178+
if err := json.NewDecoder(resp.Output).Decode(&response); err != nil {
179+
return nil, err
180+
}
181+
182+
return response, nil
183+
}

p2p_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package shell
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/cheekybits/is"
8+
)
9+
10+
func TestP2PListener(t *testing.T) {
11+
is := is.New(t)
12+
s := NewShell(shellUrl)
13+
14+
listener, err := s.P2POpenListener(context.Background(), "p2p-open-listener-test", "/ip4/127.0.0.1/udp/3000")
15+
is.Nil(err)
16+
is.Equal(listener.Address, "/ip4/127.0.0.1/udp/3000")
17+
is.Equal(listener.Protocol, "/p2p/p2p-open-listener-test")
18+
19+
listenerList, err := s.P2PListListeners(context.Background())
20+
is.Nil(err)
21+
is.Equal(len(listenerList.Listeners), 1)
22+
is.Equal(listenerList.Listeners[0].Address, "/ip4/127.0.0.1/udp/3000")
23+
is.Equal(listenerList.Listeners[0].Protocol, "/p2p/p2p-open-listener-test")
24+
25+
is.Nil(s.P2PCloseListener(context.Background(), "p2p-open-listener-test", false))
26+
27+
listenerList, err = s.P2PListListeners(context.Background())
28+
is.Nil(err)
29+
is.Equal(len(listenerList.Listeners), 0)
30+
}

0 commit comments

Comments
 (0)