2019-09-04 19:29:34 +01:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package contact
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2019-09-10 17:05:07 +01:00
|
|
|
"fmt"
|
|
|
|
"net"
|
2019-09-04 19:29:34 +01:00
|
|
|
|
2019-09-18 21:17:04 +01:00
|
|
|
"github.com/zeebo/errs"
|
2019-09-04 19:29:34 +01:00
|
|
|
"go.uber.org/zap"
|
2019-09-10 17:05:07 +01:00
|
|
|
"google.golang.org/grpc"
|
2019-09-19 09:01:34 +01:00
|
|
|
"google.golang.org/grpc/codes"
|
2019-09-10 17:05:07 +01:00
|
|
|
"google.golang.org/grpc/peer"
|
2019-09-19 09:01:34 +01:00
|
|
|
"google.golang.org/grpc/status"
|
2019-09-04 19:29:34 +01:00
|
|
|
|
2019-09-10 17:05:07 +01:00
|
|
|
"storj.io/storj/pkg/identity"
|
2019-09-04 19:29:34 +01:00
|
|
|
"storj.io/storj/pkg/pb"
|
2019-09-10 17:05:07 +01:00
|
|
|
"storj.io/storj/pkg/storj"
|
2019-09-19 19:37:31 +01:00
|
|
|
"storj.io/storj/satellite/overlay"
|
2019-09-04 19:29:34 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// Endpoint implements the contact service Endpoints.
|
|
|
|
type Endpoint struct {
|
|
|
|
log *zap.Logger
|
|
|
|
service *Service
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewEndpoint returns a new contact service endpoint.
|
|
|
|
func NewEndpoint(log *zap.Logger, service *Service) *Endpoint {
|
|
|
|
return &Endpoint{
|
|
|
|
log: log,
|
|
|
|
service: service,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-14 01:37:32 +01:00
|
|
|
// CheckIn is periodically called by storage nodes to keep the satellite informed of its existence,
|
2019-09-04 19:29:34 +01:00
|
|
|
// address, and operator information. In return, this satellite keeps the node informed of its
|
|
|
|
// reachability.
|
2019-09-14 01:37:32 +01:00
|
|
|
// When a node checks-in with the satellite, the satellite pings the node back to confirm they can
|
2019-09-10 17:05:07 +01:00
|
|
|
// successfully connect.
|
2019-09-14 01:37:32 +01:00
|
|
|
func (endpoint *Endpoint) CheckIn(ctx context.Context, req *pb.CheckInRequest) (_ *pb.CheckInResponse, err error) {
|
2019-09-04 19:29:34 +01:00
|
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
|
2019-09-10 17:05:07 +01:00
|
|
|
peerID, err := peerIDFromContext(ctx)
|
|
|
|
if err != nil {
|
2019-09-19 09:01:34 +01:00
|
|
|
return nil, status.Error(codes.Internal, Error.Wrap(err).Error())
|
2019-09-10 17:05:07 +01:00
|
|
|
}
|
2019-09-12 17:33:04 +01:00
|
|
|
nodeID := peerID.ID
|
|
|
|
|
|
|
|
err = endpoint.service.peerIDs.Set(ctx, nodeID, peerID)
|
|
|
|
if err != nil {
|
2019-09-19 09:01:34 +01:00
|
|
|
return nil, status.Error(codes.Internal, Error.Wrap(err).Error())
|
2019-09-12 17:33:04 +01:00
|
|
|
}
|
|
|
|
|
2019-09-19 19:37:31 +01:00
|
|
|
lastIP, err := overlay.GetNetwork(ctx, req.Address)
|
2019-09-10 17:05:07 +01:00
|
|
|
if err != nil {
|
2019-09-19 09:01:34 +01:00
|
|
|
return nil, status.Error(codes.Internal, Error.Wrap(err).Error())
|
2019-09-10 17:05:07 +01:00
|
|
|
}
|
|
|
|
|
2019-09-19 19:37:31 +01:00
|
|
|
pingNodeSuccess, pingErrorMessage, err := endpoint.pingBack(ctx, req, nodeID)
|
2019-09-10 17:05:07 +01:00
|
|
|
if err != nil {
|
2019-09-19 09:01:34 +01:00
|
|
|
return nil, status.Error(codes.Internal, Error.Wrap(err).Error())
|
2019-09-10 17:05:07 +01:00
|
|
|
}
|
2019-09-19 19:37:31 +01:00
|
|
|
nodeInfo := overlay.NodeCheckInInfo{
|
|
|
|
NodeID: peerID.ID,
|
|
|
|
Address: &pb.NodeAddress{
|
|
|
|
Address: req.Address,
|
|
|
|
Transport: pb.NodeTransport_TCP_TLS_GRPC,
|
|
|
|
},
|
|
|
|
LastIP: lastIP,
|
|
|
|
IsUp: pingNodeSuccess,
|
|
|
|
Capacity: req.Capacity,
|
|
|
|
Operator: req.Operator,
|
|
|
|
Version: req.Version,
|
2019-09-10 17:05:07 +01:00
|
|
|
}
|
2019-09-19 19:37:31 +01:00
|
|
|
err = endpoint.service.overlay.UpdateCheckIn(ctx, nodeInfo)
|
2019-09-10 17:05:07 +01:00
|
|
|
if err != nil {
|
2019-09-19 09:01:34 +01:00
|
|
|
return nil, status.Error(codes.Internal, Error.Wrap(err).Error())
|
2019-09-10 17:05:07 +01:00
|
|
|
}
|
|
|
|
|
2019-09-14 01:37:32 +01:00
|
|
|
endpoint.log.Debug("checking in", zap.String("node addr", req.Address), zap.Bool("ping node succes", pingNodeSuccess))
|
|
|
|
return &pb.CheckInResponse{
|
2019-09-10 17:05:07 +01:00
|
|
|
PingNodeSuccess: pingNodeSuccess,
|
|
|
|
PingErrorMessage: pingErrorMessage,
|
|
|
|
}, nil
|
|
|
|
}
|
2019-09-04 19:29:34 +01:00
|
|
|
|
2019-09-14 01:37:32 +01:00
|
|
|
func (endpoint *Endpoint) pingBack(ctx context.Context, req *pb.CheckInRequest, peerID storj.NodeID) (bool, string, error) {
|
2019-09-10 17:05:07 +01:00
|
|
|
client, err := newClient(ctx,
|
|
|
|
endpoint.service.transport,
|
2019-09-14 01:37:32 +01:00
|
|
|
req.Address,
|
2019-09-10 17:05:07 +01:00
|
|
|
peerID,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
// if this is a network error, then return the error otherwise just report internal error
|
|
|
|
_, ok := err.(net.Error)
|
|
|
|
if ok {
|
2019-09-14 01:37:32 +01:00
|
|
|
return false, "", Error.New("failed to connect to %s: %v", req.Address, err)
|
2019-09-10 17:05:07 +01:00
|
|
|
}
|
|
|
|
endpoint.log.Info("pingBack internal error", zap.String("error", err.Error()))
|
2019-09-14 01:37:32 +01:00
|
|
|
return false, "", Error.New("couldn't connect to client at addr: %s due to internal error.", req.Address)
|
2019-09-10 17:05:07 +01:00
|
|
|
}
|
2019-09-18 21:17:04 +01:00
|
|
|
defer func() {
|
|
|
|
err = errs.Combine(err, client.close())
|
|
|
|
}()
|
2019-09-10 17:05:07 +01:00
|
|
|
|
|
|
|
pingNodeSuccess := true
|
|
|
|
var pingErrorMessage string
|
|
|
|
|
|
|
|
p := &peer.Peer{}
|
|
|
|
_, err = client.pingNode(ctx, &pb.ContactPingRequest{}, grpc.Peer(p))
|
|
|
|
if err != nil {
|
|
|
|
pingNodeSuccess = false
|
|
|
|
pingErrorMessage = "erroring while trying to pingNode due to internal error"
|
|
|
|
_, ok := err.(net.Error)
|
|
|
|
if ok {
|
|
|
|
pingErrorMessage = fmt.Sprintf("network erroring while trying to pingNode: %v\n", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-18 21:17:04 +01:00
|
|
|
return pingNodeSuccess, pingErrorMessage, err
|
2019-09-10 17:05:07 +01:00
|
|
|
}
|
|
|
|
|
2019-09-12 17:33:04 +01:00
|
|
|
func peerIDFromContext(ctx context.Context) (*identity.PeerIdentity, error) {
|
2019-09-10 17:05:07 +01:00
|
|
|
p, ok := peer.FromContext(ctx)
|
|
|
|
if !ok {
|
2019-09-12 17:33:04 +01:00
|
|
|
return nil, Error.New("unable to get grpc peer from context")
|
2019-09-10 17:05:07 +01:00
|
|
|
}
|
|
|
|
peerIdentity, err := identity.PeerIdentityFromPeer(p)
|
|
|
|
if err != nil {
|
2019-09-12 17:33:04 +01:00
|
|
|
return nil, err
|
2019-09-10 17:05:07 +01:00
|
|
|
}
|
2019-09-12 17:33:04 +01:00
|
|
|
return peerIdentity, nil
|
2019-09-04 19:29:34 +01:00
|
|
|
}
|