func (p *peers) VolumeSyncPull(req *wire.VolumeSyncPullRequest, stream wire.Peer_VolumeSyncPullServer) error { ctx := stream.Context() pub, err := p.auth(ctx) if err != nil { return err } var volID db.VolumeID if err := volID.UnmarshalBinary(req.VolumeID); err != nil { return err } view := func(tx *db.Tx) error { client, err := tx.Peers().Get(pub) if err != nil { return err } vol, err := tx.Volumes().GetByVolumeID(&volID) // do not leak names peer has no access to; not found gets the // same error as not allowed if (err == nil && !client.Volumes().IsAllowed(vol)) || err == db.ErrVolumeIDNotFound { err = grpc.Errorf(codes.PermissionDenied, "peer is not authorized for that volume") } if err != nil { return err } return nil } if err := p.app.DB.View(view); err != nil { return err } v, err := p.app.GetVolume(&volID) if err != nil { return err } defer v.Close() if err := v.FS().SyncSend(ctx, req.Path, stream.Send); err != nil { if err == fuse.ENOENT { return grpc.Errorf(codes.NotFound, "not found") } return err } return nil }
func (c controlRPC) VolumeConnect(ctx context.Context, req *wire.VolumeConnectRequest) (*wire.VolumeConnectResponse, error) { var pub peer.PublicKey if err := pub.UnmarshalBinary(req.Pub); err != nil { return nil, grpc.Errorf(codes.InvalidArgument, "bad peer public key: %v", err) } if err := c.app.ValidateKV(req.Backend); err != nil { return nil, grpc.Errorf(codes.InvalidArgument, "invalid backend: %q", req.Backend) } client, err := c.app.DialPeer(&pub) if err != nil { return nil, err } defer client.Close() presp, err := client.VolumeConnect(ctx, &wirepeer.VolumeConnectRequest{ VolumeName: req.VolumeName, }) if err != nil { return nil, err } var volID db.VolumeID if err := volID.UnmarshalBinary(presp.VolumeID); err != nil { return nil, err } volumeConnect := func(tx *db.Tx) error { sharingKey, err := tx.SharingKeys().Get(req.SharingKeyName) if err != nil { return err } v, err := tx.Volumes().Add(req.LocalVolumeName, &volID, req.Backend, sharingKey) if err != nil { return err } p, err := tx.Peers().Get(&pub) if err != nil { return err } if err := p.Volumes().Allow(v); err != nil { return err } return nil } if err := c.app.DB.Update(volumeConnect); err != nil { switch err { case db.ErrVolNameInvalid: return nil, grpc.Errorf(codes.InvalidArgument, "%v", err) case db.ErrVolNameExist: return nil, grpc.Errorf(codes.AlreadyExists, "%v", err) case db.ErrSharingKeyNameInvalid: return nil, grpc.Errorf(codes.InvalidArgument, "%v", err) case db.ErrSharingKeyNotFound: return nil, grpc.Errorf(codes.FailedPrecondition, "%v", err) } return nil, err } return &wire.VolumeConnectResponse{}, nil }