) (
respHdr AnnounceResponseHeader, err error,
) {
- body, err := marshal(req)
- if err != nil {
- return
- }
- respBody, err := cl.request(ctx, ActionAnnounce, append(body, opts.Encode()...))
+ respBody, err := cl.request(ctx, ActionAnnounce, append(mustMarshal(req), opts.Encode()...))
if err != nil {
return
}
return
}
+func (cl *Client) Scrape(
+ ctx context.Context, ihs []InfoHash,
+) (
+ out ScrapeResponse, err error,
+) {
+ // There's no way to pass options in a scrape, since we don't when the request body ends.
+ respBody, err := cl.request(ctx, ActionScrape, mustMarshal(ScrapeRequest(ihs)))
+ if err != nil {
+ return
+ }
+ r := bytes.NewBuffer(respBody)
+ for r.Len() != 0 {
+ var item ScrapeInfohashResult
+ err = Read(r, &item)
+ if err != nil {
+ return
+ }
+ out = append(out, item)
+ }
+ if len(out) > len(ihs) {
+ err = fmt.Errorf("got %v results but expected %v", len(out), len(ihs))
+ return
+ }
+ return
+}
+
func (cl *Client) connect(ctx context.Context) (err error) {
if time.Since(cl.connIdIssued) < time.Minute {
return nil
}
type ConnClient struct {
- cl Client
+ Client Client
conn net.Conn
d Dispatcher
readErr error
return
}
cc = &ConnClient{
- cl: Client{
+ Client: Client{
Writer: conn,
},
conn: conn,
ipv6: ipv6(opts.Ipv6, opts.Network, conn),
}
- cc.cl.Dispatcher = &cc.d
+ cc.Client.Dispatcher = &cc.d
go cc.reader()
return
}
return &krpc.CompactIPv4NodeAddrs{}
}
}()
- h, err = c.cl.Announce(ctx, req, nas, opts)
+ h, err = c.Client.Announce(ctx, req, nas, opts)
return
}
Seeders int32
}
+type InfoHash = [20]byte
+
func marshal(data interface{}) (b []byte, err error) {
var buf bytes.Buffer
err = binary.Write(&buf, binary.BigEndian, data)
return
}
+func mustMarshal(data interface{}) []byte {
+ b, err := marshal(data)
+ if err != nil {
+ panic(err)
+ }
+ return b
+}
+
func Write(w io.Writer, data interface{}) error {
return binary.Write(w, binary.BigEndian, data)
}