go-libp2p-daemon/dht.go

347 lines
7.8 KiB
Go
Raw Normal View History

2018-09-30 08:01:00 +00:00
package p2pd
import (
2018-09-30 09:25:26 +00:00
"context"
2018-09-30 08:01:00 +00:00
pb "github.com/libp2p/go-libp2p-daemon/pb"
2018-09-30 09:25:26 +00:00
2018-09-30 10:34:50 +00:00
cid "github.com/ipfs/go-cid"
2018-09-30 11:20:27 +00:00
crypto "github.com/libp2p/go-libp2p-crypto"
2018-09-30 10:34:50 +00:00
dht "github.com/libp2p/go-libp2p-kad-dht"
2018-09-30 09:25:26 +00:00
peer "github.com/libp2p/go-libp2p-peer"
pstore "github.com/libp2p/go-libp2p-peerstore"
2018-09-30 08:01:00 +00:00
)
func (d *Daemon) doDHT(req *pb.Request) (*pb.Response, <-chan *pb.DHTResponse, func()) {
if d.dht == nil {
2018-09-30 08:46:19 +00:00
return errorResponseString("DHT not enabled"), nil, nil
2018-09-30 08:01:00 +00:00
}
if req.Dht == nil {
2018-09-30 08:46:19 +00:00
return errorResponseString("Malformed request; missing parameters"), nil, nil
2018-09-30 08:01:00 +00:00
}
switch *req.Dht.Type {
case pb.DHTRequest_FIND_PEER:
return d.doDHTFindPeer(req.Dht)
case pb.DHTRequest_FIND_PEERS_CONNECTED_TO_PEER:
return d.doDHTFindPeersConnectedToPeer(req.Dht)
case pb.DHTRequest_FIND_PROVIDERS:
return d.doDHTFindProviders(req.Dht)
case pb.DHTRequest_GET_CLOSEST_PEERS:
return d.doDHTGetClosestPeers(req.Dht)
case pb.DHTRequest_GET_PUBLIC_KEY:
return d.doDHTGetPublicKey(req.Dht)
case pb.DHTRequest_GET_VALUE:
return d.doDHTGetValue(req.Dht)
case pb.DHTRequest_SEARCH_VALUE:
return d.doDHTSearchValue(req.Dht)
case pb.DHTRequest_PUT_VALUE:
return d.doDHTPutValue(req.Dht)
case pb.DHTRequest_PROVIDE:
return d.doDHTProvide(req.Dht)
default:
log.Debugf("Unexpected DHT request type: %d", *req.Dht.Type)
2018-09-30 08:46:19 +00:00
return errorResponseString("Unexpected request"), nil, nil
2018-09-30 08:01:00 +00:00
}
}
func (d *Daemon) doDHTFindPeer(req *pb.DHTRequest) (*pb.Response, <-chan *pb.DHTResponse, func()) {
2018-09-30 09:25:26 +00:00
if req.Peer == nil {
return errorResponseString("Malformed request; missing peer parameter"), nil, nil
}
p, err := peer.IDFromBytes(req.Peer)
if err != nil {
return errorResponse(err), nil, nil
}
ctx, cancel := d.dhtRequestContext(req)
defer cancel()
pi, err := d.dht.FindPeer(ctx, p)
if err != nil {
return errorResponse(err), nil, nil
}
2018-09-30 10:48:41 +00:00
return dhtOkResponse(dhtResponsePeerInfo(pi)), nil, nil
2018-09-30 08:01:00 +00:00
}
func (d *Daemon) doDHTFindPeersConnectedToPeer(req *pb.DHTRequest) (*pb.Response, <-chan *pb.DHTResponse, func()) {
2018-09-30 10:00:44 +00:00
if req.Peer == nil {
return errorResponseString("Malformed request; missing peer parameter"), nil, nil
}
p, err := peer.IDFromBytes(req.Peer)
if err != nil {
return errorResponse(err), nil, nil
}
ctx, cancel := d.dhtRequestContext(req)
ch, err := d.dht.FindPeersConnectedToPeer(ctx, p)
if err != nil {
cancel()
return errorResponse(err), nil, nil
}
rch := make(chan *pb.DHTResponse)
go func() {
defer cancel()
defer close(rch)
for pi := range ch {
select {
2018-09-30 10:48:41 +00:00
case rch <- dhtResponsePeerInfo(*pi):
2018-09-30 10:00:44 +00:00
case <-ctx.Done():
return
}
}
}()
return dhtOkResponse(dhtResponseBegin()), rch, cancel
2018-09-30 08:01:00 +00:00
}
func (d *Daemon) doDHTFindProviders(req *pb.DHTRequest) (*pb.Response, <-chan *pb.DHTResponse, func()) {
2018-09-30 10:34:50 +00:00
if req.Cid == nil {
return errorResponseString("Malformed request; missing cid parameter"), nil, nil
}
cid, err := cid.Cast(req.Cid)
if err != nil {
return errorResponse(err), nil, nil
}
count := dht.KValue
if req.GetCount() > 0 {
count = int(*req.Count)
}
ctx, cancel := d.dhtRequestContext(req)
ch := d.dht.FindProvidersAsync(ctx, cid, count)
rch := make(chan *pb.DHTResponse)
go func() {
defer cancel()
defer close(rch)
for pi := range ch {
select {
2018-09-30 10:48:41 +00:00
case rch <- dhtResponsePeerInfo(pi):
2018-09-30 10:34:50 +00:00
case <-ctx.Done():
return
}
}
}()
return dhtOkResponse(dhtResponseBegin()), rch, cancel
2018-09-30 08:01:00 +00:00
}
func (d *Daemon) doDHTGetClosestPeers(req *pb.DHTRequest) (*pb.Response, <-chan *pb.DHTResponse, func()) {
2018-09-30 10:48:41 +00:00
if req.Key == nil {
return errorResponseString("Malformed request; missing key parameter"), nil, nil
}
ctx, cancel := d.dhtRequestContext(req)
ch, err := d.dht.GetClosestPeers(ctx, *req.Key)
if err != nil {
cancel()
return errorResponse(err), nil, nil
}
rch := make(chan *pb.DHTResponse)
go func() {
defer cancel()
defer close(rch)
for p := range ch {
select {
case rch <- dhtResponsePeerID(p):
case <-ctx.Done():
return
}
}
}()
return dhtOkResponse(dhtResponseBegin()), rch, cancel
2018-09-30 08:01:00 +00:00
}
func (d *Daemon) doDHTGetPublicKey(req *pb.DHTRequest) (*pb.Response, <-chan *pb.DHTResponse, func()) {
2018-09-30 11:20:27 +00:00
if req.Peer == nil {
return errorResponseString("Malformed request; missing peer parameter"), nil, nil
}
p, err := peer.IDFromBytes(req.Peer)
if err != nil {
return errorResponse(err), nil, nil
}
ctx, cancel := d.dhtRequestContext(req)
defer cancel()
key, err := d.dht.GetPublicKey(ctx, p)
if err != nil {
return errorResponse(err), nil, nil
}
res, err := dhtResponsePublicKey(key)
if err != nil {
return errorResponse(err), nil, nil
}
return dhtOkResponse(res), nil, nil
2018-09-30 08:01:00 +00:00
}
func (d *Daemon) doDHTGetValue(req *pb.DHTRequest) (*pb.Response, <-chan *pb.DHTResponse, func()) {
if req.Key == nil {
return errorResponseString("Malformed request; missing key parameter"), nil, nil
}
ctx, cancel := d.dhtRequestContext(req)
defer cancel()
val, err := d.dht.GetValue(ctx, *req.Key)
if err != nil {
return errorResponse(err), nil, nil
}
return dhtOkResponse(dhtResponseValue(val)), nil, nil
2018-09-30 08:01:00 +00:00
}
func (d *Daemon) doDHTSearchValue(req *pb.DHTRequest) (*pb.Response, <-chan *pb.DHTResponse, func()) {
if req.Key == nil {
return errorResponseString("Malformed request; missing key parameter"), nil, nil
}
ctx, cancel := d.dhtRequestContext(req)
ch, err := d.dht.SearchValue(ctx, *req.Key)
if err != nil {
cancel()
return errorResponse(err), nil, nil
}
rch := make(chan *pb.DHTResponse)
go func() {
defer cancel()
defer close(rch)
for val := range ch {
select {
case rch <- dhtResponseValue(val):
case <-ctx.Done():
return
}
}
}()
return dhtOkResponse(dhtResponseBegin()), rch, cancel
2018-09-30 08:01:00 +00:00
}
func (d *Daemon) doDHTPutValue(req *pb.DHTRequest) (*pb.Response, <-chan *pb.DHTResponse, func()) {
if req.Key == nil {
return errorResponseString("Malformed request; missing key parameter"), nil, nil
}
if req.Value == nil {
return errorResponseString("Malformed request; missing value parameter"), nil, nil
}
ctx, cancel := d.dhtRequestContext(req)
defer cancel()
err := d.dht.PutValue(ctx, *req.Key, req.Value)
if err != nil {
return errorResponse(err), nil, nil
}
return okResponse(), nil, nil
2018-09-30 08:01:00 +00:00
}
func (d *Daemon) doDHTProvide(req *pb.DHTRequest) (*pb.Response, <-chan *pb.DHTResponse, func()) {
2018-09-30 11:34:32 +00:00
if req.Cid == nil {
return errorResponseString("Malformed request; missing cid parameter"), nil, nil
}
cid, err := cid.Cast(req.Cid)
if err != nil {
return errorResponse(err), nil, nil
}
ctx, cancel := d.dhtRequestContext(req)
defer cancel()
err = d.dht.Provide(ctx, cid, true)
if err != nil {
return errorResponse(err), nil, nil
}
return okResponse(), nil, nil
2018-09-30 08:01:00 +00:00
}
2018-09-30 09:25:26 +00:00
func (d *Daemon) dhtRequestContext(req *pb.DHTRequest) (context.Context, func()) {
return d.requestContext(req.GetTimeout())
2018-09-30 09:25:26 +00:00
}
2018-09-30 10:00:44 +00:00
func dhtResponseBegin() *pb.DHTResponse {
return &pb.DHTResponse{
Type: pb.DHTResponse_BEGIN.Enum(),
}
}
func dhtResponseEnd() *pb.DHTResponse {
return &pb.DHTResponse{
Type: pb.DHTResponse_END.Enum(),
}
}
2018-09-30 10:48:41 +00:00
func dhtResponsePeerInfo(pi pstore.PeerInfo) *pb.DHTResponse {
2018-09-30 09:25:26 +00:00
return &pb.DHTResponse{
Type: pb.DHTResponse_VALUE.Enum(),
Peer: peerInfo2pb(pi),
}
}
2018-09-30 10:48:41 +00:00
func dhtResponsePeerID(p peer.ID) *pb.DHTResponse {
return dhtResponseValue([]byte(p))
2018-09-30 10:48:41 +00:00
}
2018-09-30 11:20:27 +00:00
func dhtResponsePublicKey(key crypto.PubKey) (*pb.DHTResponse, error) {
bytes, err := crypto.MarshalPublicKey(key)
if err != nil {
return nil, err
}
return dhtResponseValue(bytes), nil
}
func dhtResponseValue(val []byte) *pb.DHTResponse {
2018-09-30 11:20:27 +00:00
return &pb.DHTResponse{
Type: pb.DHTResponse_VALUE.Enum(),
Value: val,
}
2018-09-30 11:20:27 +00:00
}
2018-09-30 09:25:26 +00:00
func dhtOkResponse(r *pb.DHTResponse) *pb.Response {
res := okResponse()
res.Dht = r
return res
}
func peerInfo2pb(pi pstore.PeerInfo) *pb.PeerInfo {
addrs := make([][]byte, len(pi.Addrs))
for x, addr := range pi.Addrs {
addrs[x] = addr.Bytes()
}
return &pb.PeerInfo{
Id: []byte(pi.ID),
Addrs: addrs,
}
}