58 lines
1.5 KiB
Go
58 lines
1.5 KiB
Go
package httpnode
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"net/netip"
|
|
"net/url"
|
|
"path"
|
|
|
|
"git.sunturtle.xyz/zephyr/chord/chord"
|
|
)
|
|
|
|
type Client struct {
|
|
// HTTP is the client used to make requests.
|
|
HTTP http.Client
|
|
// APIBase is the path under which the Chord API is served.
|
|
APIBase string
|
|
}
|
|
|
|
// FindSuccessor asks s to find the first peer in the network preceding id.
|
|
func (cl *Client) FindSuccessor(ctx context.Context, s chord.Peer, id chord.ID) (chord.Peer, error) {
|
|
_, addr := s.Values()
|
|
if !addr.IsValid() {
|
|
return chord.Peer{}, errors.New("FindSuccessor with invalid peer")
|
|
}
|
|
url := url.URL{
|
|
Scheme: "http",
|
|
Host: addr.String(),
|
|
Path: path.Join("/", cl.APIBase, "succ"),
|
|
RawQuery: url.Values{"s": {id.String()}}.Encode(),
|
|
}
|
|
req, err := http.NewRequestWithContext(ctx, "GET", url.String(), nil)
|
|
if err != nil {
|
|
return chord.Peer{}, err
|
|
}
|
|
resp, err := cl.HTTP.Do(req)
|
|
if err != nil {
|
|
return chord.Peer{}, err
|
|
}
|
|
p, err := readResponse[netip.AddrPort](resp)
|
|
if err != nil {
|
|
return chord.Peer{}, fmt.Errorf("%w (%s)", err, resp.Status)
|
|
}
|
|
return chord.Address(p), nil
|
|
}
|
|
|
|
// Notify tells s we believe n to be its predecessor.
|
|
func (cl *Client) Notify(ctx context.Context, n *chord.Node, s chord.Peer) error {
|
|
panic("not implemented") // TODO: Implement
|
|
}
|
|
|
|
// Neighbors requests a peer's beliefs about its own neighbors.
|
|
func (cl *Client) Neighbors(ctx context.Context, p chord.Peer) (pred chord.Peer, succ []chord.Peer, err error) {
|
|
panic("not implemented") // TODO: Implement
|
|
}
|