-
Notifications
You must be signed in to change notification settings - Fork 0
/
ipfs.go
190 lines (162 loc) · 5.68 KB
/
ipfs.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// Copyright (c) 2019 Laszlo Sari
//
// FileTribe is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// FileTribe is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
package ipfs
import (
"context"
"io"
ipfsapi "github.com/ipfs/go-ipfs-api"
ma "github.com/multiformats/go-multiaddr"
"strconv"
)
// IPubSubSubscription is an interface to IPFS pubsub subscriptions
type IPubSubSubscription interface {
Cancel() error
Next() (*ipfsapi.Message, error)
}
// PubSubSubscription is an own version of PubSubSubscription
type PubSubSubscription ipfsapi.PubSubSubscription
// Cancel cancels a pubsub subscription
func (sub *PubSubSubscription) Cancel() error {
return (*ipfsapi.PubSubSubscription)(sub).Cancel()
}
// Next reads the next message in the subscription
func (sub *PubSubSubscription) Next() (*ipfsapi.Message, error) {
return ((*ipfsapi.PubSubSubscription)(sub)).Next()
}
// IIpfs is an interface to IPFS. It is done this way to be able
// to mock IPFS in unit tests later
type IIpfs interface {
ID() (*ipfsapi.IdOutput, error)
PubSubPublish(topic string, data string) error
PubSubSubscribe(topic string) (IPubSubSubscription, error)
Get(hash string, outdir string) error
AddDir(dir string) (string, error)
Publish(node string, value string) error
Add(r io.Reader) (string, error)
P2PListen(ctx context.Context, protocol, maddr string) (*P2PListener, error)
P2PCloseListener(ctx context.Context, protocol string, closeAll bool) error
P2PStreamDial(ctx context.Context, peerID, protocol, listenerMaddr string) (*P2PStream, error)
P2PCloseStream(ctx context.Context, handlerID string, closeAll bool) error
}
// Ipfs is implementation of IIpfs
type Ipfs struct {
shell *ipfsapi.Shell
}
// NewIpfs creates a new IPFS instance
func NewIpfs(url string) *Ipfs {
return &Ipfs{shell: ipfsapi.NewShell(url)}
}
// ID returns the IPFS id
func (ipfs *Ipfs) ID() (*ipfsapi.IdOutput, error) {
return ipfs.shell.ID()
}
// PubSubPublish publishes a message in the given topic
func (ipfs *Ipfs) PubSubPublish(topic string, data string) error {
return ipfs.shell.PubSubPublish(topic, data)
}
// Get gets a file from ipfs
func (ipfs *Ipfs) Get(hash string, outdir string) error {
return ipfs.shell.Get(hash, outdir)
}
// AddDir adds a whole directory to ipfs
func (ipfs *Ipfs) AddDir(dir string) (string, error) {
return ipfs.shell.AddDir(dir)
}
// Publish publishes to IPNS
func (ipfs *Ipfs) Publish(node string, value string) error {
return ipfs.shell.Publish(node, value)
}
// Add adds a file to IPFS
func (ipfs *Ipfs) Add(r io.Reader) (string, error) {
return ipfs.shell.Add(r)
}
// PubSubSubscribe subscribes to a topic on IPFS pubsub
func (ipfs *Ipfs) PubSubSubscribe(topic string) (IPubSubSubscription, error) {
sub, err := ipfs.shell.PubSubSubscribe(topic)
return (*PubSubSubscription)(sub), err
}
// P2PListener is a struct for storing the results of IPFS p2p listen
type P2PListener struct {
Protocol string
Address string
}
// P2PListen will listen on the given multiaddress for libp2p connections
func (ipfs *Ipfs) P2PListen(ctx context.Context, protocol, maddr string) (*P2PListener, error) {
// TODO: replace with the official api version
// Note that this feature is not implemented yet by the official api
if _, err := ma.NewMultiaddr(maddr); err != nil {
return nil, err
}
var response *P2PListener
err := ipfs.shell.Request("p2p/listener/open").
Arguments(protocol, maddr).Exec(ctx, &response)
if err != nil {
return nil, err
}
return response, nil
}
// P2PCloseListener closes an open P2P listener
func (ipfs *Ipfs) P2PCloseListener(ctx context.Context, protocol string, closeAll bool) error {
// TODO: replace with the official api version
// Note that this feature is not implemented yet by the official api
req := ipfs.shell.Request("p2p/listener/close").
Option("all", strconv.FormatBool(closeAll))
if protocol != "" {
req.Arguments(protocol)
}
if err := req.Exec(ctx, nil); err != nil {
return err
}
return nil
}
// P2PStream is a struct for storing the results of IPFS p2p stream dial...
type P2PStream struct {
Protocol string
Address string
}
// P2PStreamDial dials to the given IPFS id and forwards the message to the
// listener multiaddress
func (ipfs *Ipfs) P2PStreamDial(ctx context.Context, peerID, protocol, listenerMaddr string) (*P2PStream, error) {
// TODO: replace with the official api version
// Note that this feature is not implemented yet by the official api
var response *P2PStream
req := ipfs.shell.Request("p2p/stream/dial").
Arguments(peerID, protocol)
if listenerMaddr != "" {
if _, err := ma.NewMultiaddr(listenerMaddr); err != nil {
return nil, err
}
req.Arguments(listenerMaddr)
}
if err := req.Exec(ctx, &response); err != nil {
return nil, err
}
return response, nil
}
// P2PCloseStream closes an open libp2p stream
func (ipfs *Ipfs) P2PCloseStream(ctx context.Context, handlerID string, closeAll bool) error {
// TODO: replace with the official api version
// Note that this feature is not implemented yet by the official api
req := ipfs.shell.Request("p2p/stream/close").
Option("all", strconv.FormatBool(closeAll))
if handlerID != "" {
req.Arguments(handlerID)
}
if err := req.Exec(ctx, nil); err != nil {
return err
}
return nil
}