Skip to content

Commit 85dafb2

Browse files
authored
feat!: ressurect someguy with /routing/v1
1 parent 970f871 commit 85dafb2

File tree

8 files changed

+619
-1028
lines changed

8 files changed

+619
-1028
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
someguy

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM golang:1.18-bullseye
1+
FROM golang:1.21-bullseye
22

33
WORKDIR /app
44

README.md

+17-9
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
11
# someguy
22

3-
> ⚠️ Reframe has been deprecated in favour of the [Routing V1 Specification](https://specs.ipfs.tech/routing/http-routing-v1/).
3+
A [Delegated Routing V1](https://specs.ipfs.tech/routing/http-routing-v1/) server and client for all your routing needs. Ask `someguy` for directions.
44

5-
A Reframe server you can delegate routing requests to. Ask someguy for directions.
5+
## Install
6+
7+
```bash
8+
go install github.com/ipfs-shipyard/someguy@latest
9+
```
10+
11+
12+
## Build
13+
14+
```bash
15+
go build -o someguy
16+
```
617

718
## Usage
819

9-
`someguy start` runs a [Reframe](https://github.com/ipfs/specs/blob/6bdb7b2751038e1d0212a40494ea8fd4018f384c/REFRAME.md) server
10-
that proxies requests to the IPFS Public DHT and an Indexer node (planned to be upgraded to querying the indexer network more broadly).
20+
You can use `someguy` as a client or server.
1121

12-
If you don't feel like running any routing code yourself, that's ok just ask `someguy` to do it for you.
22+
`someguy start` runs a Delegated Routing V1 server that proxies requests to the [IPFS Amino DHT](https://blog.ipfs.tech/2023-09-amino-refactoring/) and the [cid.contact](https://cid.contact) indexer node.
1323

14-
If you're looking for an implementation of a Reframe client already packaged up and ready to use check out https://github.com/ipfs/go-delegated-routing.
24+
If you don't want to run a server yourself, but want to query some other server, you can run `someguy ask` and choose any of the subcommands and ask for a provider, a peer, or even an IPNS record.
1525

16-
If you're missing tooling in your language you can take a look at the spec to write an HTTP client yourself,
17-
or if you're up to it add codegeneration for your language into https://github.com/ipld/edelweiss/ to make it easier to maintain
18-
your implementation if/when more methods are added to Reframe.
26+
For more details run `someguy --help`.

client.go

+108-121
Original file line numberDiff line numberDiff line change
@@ -1,177 +1,164 @@
11
package main
22

33
import (
4-
"bytes"
54
"context"
5+
"encoding/json"
6+
"errors"
67
"fmt"
7-
"log"
8-
"strings"
8+
"io"
9+
"os"
910
"time"
1011

11-
pbuf "github.com/gogo/protobuf/proto"
12-
12+
"github.com/ipfs/boxo/ipns"
13+
"github.com/ipfs/boxo/routing/http/client"
14+
"github.com/ipfs/boxo/routing/http/types"
15+
"github.com/ipfs/boxo/routing/http/types/iter"
1316
"github.com/ipfs/go-cid"
14-
"github.com/ipfs/go-delegated-routing/client"
15-
"github.com/ipfs/go-ipns"
16-
ipns_pb "github.com/ipfs/go-ipns/pb"
17-
"github.com/ipld/go-ipld-prime/codec/dagjson"
18-
"github.com/libp2p/go-libp2p-core/peer"
19-
"github.com/multiformats/go-multiaddr"
20-
21-
drp "github.com/ipfs/go-delegated-routing/gen/proto"
17+
"github.com/libp2p/go-libp2p/core/peer"
2218
)
2319

24-
func identify(ctx context.Context, endpoint string, prettyOutput bool) error {
25-
ic, err := drp.New_DelegatedRouting_Client(endpoint)
20+
func findProviders(ctx context.Context, key cid.Cid, endpoint string, prettyOutput bool) error {
21+
drc, err := client.New(endpoint)
2622
if err != nil {
2723
return err
2824
}
2925

30-
respCh, err := ic.Identify_Async(ctx, &drp.DelegatedRouting_IdentifyArg{})
31-
for r := range respCh {
32-
if r.Err != nil {
33-
log.Println(r.Err)
34-
continue
35-
}
36-
37-
if !prettyOutput {
38-
var buf bytes.Buffer
39-
if err := dagjson.Encode(r.Resp, &buf); err != nil {
40-
return err
41-
}
42-
fmt.Println(buf.String())
43-
} else {
44-
var methods []string
45-
for _, m := range r.Resp.Methods {
46-
methods = append(methods, string(m))
47-
}
48-
fmt.Println(strings.Join(methods, ","))
49-
}
26+
recordsIter, err := drc.FindProviders(ctx, key)
27+
if err != nil {
28+
return err
5029
}
51-
return nil
30+
defer recordsIter.Close()
31+
32+
return printIter(os.Stdout, prettyOutput, recordsIter)
5233
}
5334

54-
func findprovs(ctx context.Context, c cid.Cid, endpoint string, prettyOutput bool) error {
55-
ic, err := drp.New_DelegatedRouting_Client(endpoint)
35+
func findPeers(ctx context.Context, pid peer.ID, endpoint string, prettyOutput bool) error {
36+
drc, err := client.New(endpoint)
5637
if err != nil {
5738
return err
5839
}
5940

60-
respCh, err := ic.FindProviders_Async(ctx, &drp.FindProvidersRequest{
61-
Key: drp.LinkToAny(c),
62-
})
41+
recordsIter, err := drc.FindPeers(ctx, pid)
6342
if err != nil {
6443
return err
6544
}
66-
for r := range respCh {
67-
if r.Err != nil {
68-
log.Println(r.Err)
69-
continue
45+
defer recordsIter.Close()
46+
47+
return printIter(os.Stdout, prettyOutput, recordsIter)
48+
}
49+
50+
func printIter(w io.Writer, prettyOutput bool, iter iter.ResultIter[types.Record]) error {
51+
for iter.Next() {
52+
res := iter.Val()
53+
54+
// Check for error, but do not complain if we exceeded the timeout. We are
55+
// expecting that to happen: we explicitly defined a timeout.
56+
if res.Err != nil {
57+
if !errors.Is(res.Err, context.DeadlineExceeded) {
58+
return res.Err
59+
}
60+
61+
return nil
7062
}
7163

72-
if !prettyOutput {
73-
var buf bytes.Buffer
74-
if err := dagjson.Encode(r.Resp, &buf); err != nil {
75-
return err
64+
if prettyOutput {
65+
switch res.Val.GetSchema() {
66+
case types.SchemaPeer:
67+
record := res.Val.(*types.PeerRecord)
68+
fmt.Fprintln(w, record.ID)
69+
fmt.Fprintln(w, "\tProtocols:", record.Protocols)
70+
fmt.Fprintln(w, "\tAddresses:", record.Addrs)
71+
72+
case types.SchemaBitswap:
73+
record := res.Val.(*types.BitswapRecord)
74+
fmt.Fprintln(w, record.ID)
75+
fmt.Fprintln(w, "\tProtocol:", record.Protocol)
76+
fmt.Fprintln(w, "\tAddresses:", record.Addrs)
77+
78+
default:
79+
// This is an unknown schema. Let's just print it raw.
80+
err := json.NewEncoder(w).Encode(res.Val)
81+
if err != nil {
82+
return err
83+
}
7684
}
77-
fmt.Println(buf.String())
85+
86+
fmt.Fprintln(w)
7887
} else {
79-
for _, prov := range r.Resp.Providers {
80-
if prov.ProviderNode.Peer != nil {
81-
ai := &peer.AddrInfo{}
82-
ai.ID = peer.ID(prov.ProviderNode.Peer.ID)
83-
for _, bma := range prov.ProviderNode.Peer.Multiaddresses {
84-
ma, err := multiaddr.NewMultiaddrBytes(bma)
85-
if err != nil {
86-
return err
87-
}
88-
ai.Addrs = append(ai.Addrs, ma)
89-
}
90-
fmt.Println(ai)
91-
}
92-
for _, proto := range prov.ProviderProto {
93-
if proto.Bitswap != nil {
94-
fmt.Println("\t Bitswap")
95-
} else if proto.GraphSyncFILv1 != nil {
96-
fmt.Println("\t GraphSyncFILv1")
97-
var buf bytes.Buffer
98-
if err := dagjson.Encode(proto.GraphSyncFILv1, &buf); err != nil {
99-
return err
100-
}
101-
fmt.Println("\t\t" + buf.String())
102-
} else {
103-
var buf bytes.Buffer
104-
if err := dagjson.Encode(proto, &buf); err != nil {
105-
return err
106-
}
107-
fmt.Println("\t" + buf.String())
108-
}
109-
}
88+
err := json.NewEncoder(w).Encode(res.Val)
89+
if err != nil {
90+
return err
11091
}
11192
}
11293
}
94+
11395
return nil
11496
}
11597

116-
func getIPNS(ctx context.Context, p peer.ID, endpoint string, prettyOutput bool) error {
117-
ic, err := drp.New_DelegatedRouting_Client(endpoint)
98+
func getIPNS(ctx context.Context, name ipns.Name, endpoint string, prettyOutput bool) error {
99+
drc, err := client.New(endpoint)
100+
if err != nil {
101+
return err
102+
}
103+
104+
rec, err := drc.GetIPNS(ctx, name)
118105
if err != nil {
119106
return err
120107
}
121108

122109
if prettyOutput {
123-
c := client.NewClient(ic)
124-
respCh, err := c.GetIPNSAsync(ctx, []byte(p))
110+
v, err := rec.Value()
125111
if err != nil {
126112
return err
127113
}
128-
for r := range respCh {
129-
if r.Err != nil {
130-
log.Println(r.Err)
131-
continue
132-
}
133-
rec := new(ipns_pb.IpnsEntry)
134-
if err := pbuf.Unmarshal(r.Record, rec); err != nil {
135-
return err
136-
}
137-
seqno := rec.GetSequence()
138-
ttl := time.Duration(rec.GetTtl())
139-
eol, err := ipns.GetEOL(rec)
140-
if err != nil {
141-
return err
142-
}
143-
value := string(rec.GetValue())
144-
fmt.Printf("Sequence: %d, TTL: %v, EOL: %v, Value: %s\n", seqno, ttl, eol, value)
114+
115+
seq, err := rec.Sequence()
116+
if err != nil {
117+
return err
118+
}
119+
120+
eol, err := rec.Validity()
121+
if err != nil {
122+
return err
145123
}
124+
125+
fmt.Printf("/ipns/%s\n", name)
126+
127+
// Since [client.Client.GetIPNS] verifies if the retrieved record is valid, we
128+
// do not need to verify it again. However, if you were not using this specific
129+
// client, but using some other tool, you should always validate the IPNS Record
130+
// using the [ipns.Validate] or [ipns.ValidateWithName] functions.
131+
fmt.Println("\tSignature Validated")
132+
fmt.Println("\tValue:", v.String())
133+
fmt.Println("\tSequence:", seq)
134+
fmt.Println("\tValidityType : EOL/End-of-Life")
135+
fmt.Println("\tValidity:", eol.Format(time.RFC3339))
136+
if ttl, err := rec.TTL(); err == nil {
137+
fmt.Println("\tTTL:", ttl.String())
138+
}
139+
146140
return nil
147141
}
148142

149-
respCh, err := ic.GetIPNS_Async(ctx, &drp.GetIPNSRequest{
150-
ID: []byte(p),
151-
})
143+
raw, err := ipns.MarshalRecord(rec)
152144
if err != nil {
153145
return err
154146
}
155-
for r := range respCh {
156-
if r.Err != nil {
157-
log.Println(r.Err)
158-
continue
159-
}
160-
var buf bytes.Buffer
161-
if err := dagjson.Encode(r.Resp, &buf); err != nil {
162-
return err
163-
}
164-
fmt.Println(buf.String())
165-
}
166-
return nil
147+
148+
_, err = os.Stdout.Write(raw)
149+
return err
167150
}
168151

169-
func putIPNS(ctx context.Context, key peer.ID, record []byte, endpoint string) error {
170-
ic, err := drp.New_DelegatedRouting_Client(endpoint)
152+
func putIPNS(ctx context.Context, name ipns.Name, record []byte, endpoint string) error {
153+
drc, err := client.New(endpoint)
154+
if err != nil {
155+
return err
156+
}
157+
158+
rec, err := ipns.UnmarshalRecord(record)
171159
if err != nil {
172160
return err
173161
}
174162

175-
c := client.NewClient(ic)
176-
return c.PutIPNS(ctx, []byte(key), record)
163+
return drc.PutIPNS(ctx, name, rec)
177164
}

0 commit comments

Comments
 (0)