package getsvc import ( "context" "crypto/ecdsa" "errors" coreclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine" internalclient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/internal/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session" ) type epochSource interface { Epoch() (uint64, error) } type traverserGenerator interface { GenerateTraverser(cid.ID, *oid.ID, uint64) (*placement.Traverser, error) } type keyStorage interface { GetKey(info *util.SessionInfo) (*ecdsa.PrivateKey, error) } type localStorageEngine interface { Head(ctx context.Context, p engine.HeadPrm) (engine.HeadRes, error) GetRange(ctx context.Context, p engine.RngPrm) (engine.RngRes, error) Get(ctx context.Context, p engine.GetPrm) (engine.GetRes, error) } type clientConstructor interface { Get(coreclient.NodeInfo) (coreclient.MultiAddressClient, error) } type remoteStorageConstructor interface { Get(coreclient.NodeInfo) (remoteStorage, error) } type multiclientRemoteStorageConstructor struct { clientConstructor clientConstructor } func (c *multiclientRemoteStorageConstructor) Get(info coreclient.NodeInfo) (remoteStorage, error) { clt, err := c.clientConstructor.Get(info) if err != nil { return nil, err } return &multiaddressRemoteStorage{ client: clt, }, nil } type localStorage interface { Head(ctx context.Context, address oid.Address, isRaw bool) (*objectSDK.Object, error) Range(ctx context.Context, address oid.Address, rng *objectSDK.Range) (*objectSDK.Object, error) Get(ctx context.Context, address oid.Address) (*objectSDK.Object, error) } type engineLocalStorage struct { engine localStorageEngine } func (s *engineLocalStorage) Head(ctx context.Context, address oid.Address, isRaw bool) (*objectSDK.Object, error) { var headPrm engine.HeadPrm headPrm.WithAddress(address) headPrm.WithRaw(isRaw) r, err := s.engine.Head(ctx, headPrm) if err != nil { return nil, err } return r.Header(), nil } func (s *engineLocalStorage) Range(ctx context.Context, address oid.Address, rng *objectSDK.Range) (*objectSDK.Object, error) { var getRange engine.RngPrm getRange.WithAddress(address) getRange.WithPayloadRange(rng) r, err := s.engine.GetRange(ctx, getRange) if err != nil { return nil, err } return r.Object(), nil } func (s *engineLocalStorage) Get(ctx context.Context, address oid.Address) (*objectSDK.Object, error) { var getPrm engine.GetPrm getPrm.WithAddress(address) r, err := s.engine.Get(ctx, getPrm) if err != nil { return nil, err } return r.Object(), nil } type RemoteRequestParams struct { Epoch uint64 TTL uint32 PrivateKey *ecdsa.PrivateKey SessionToken *session.Object BearerToken *bearer.Token XHeaders []string IsRaw bool } type remoteStorage interface { Get(ctx context.Context, address oid.Address, requestParams RemoteRequestParams) (*objectSDK.Object, error) Head(ctx context.Context, address oid.Address, requestParams RemoteRequestParams) (*objectSDK.Object, error) Range(ctx context.Context, address oid.Address, rng *objectSDK.Range, requestParams RemoteRequestParams) (*objectSDK.Object, error) ForwardRequest(ctx context.Context, info coreclient.NodeInfo, forwarder RequestForwarder) (*objectSDK.Object, error) } type multiaddressRemoteStorage struct { client coreclient.MultiAddressClient } func (s *multiaddressRemoteStorage) ForwardRequest(ctx context.Context, info coreclient.NodeInfo, forwarder RequestForwarder) (*objectSDK.Object, error) { return forwarder(ctx, info, s.client) } func (s *multiaddressRemoteStorage) Range(ctx context.Context, address oid.Address, rng *objectSDK.Range, requestParams RemoteRequestParams) (*objectSDK.Object, error) { var prm internalclient.PayloadRangePrm prm.SetClient(s.client) prm.SetTTL(requestParams.TTL) prm.SetNetmapEpoch(requestParams.Epoch) prm.SetAddress(address) prm.SetPrivateKey(requestParams.PrivateKey) prm.SetSessionToken(requestParams.SessionToken) prm.SetBearerToken(requestParams.BearerToken) prm.SetXHeaders(requestParams.XHeaders) prm.SetRange(rng) if requestParams.IsRaw { prm.SetRawFlag() } res, err := internalclient.PayloadRange(ctx, prm) if err != nil { var errAccessDenied *apistatus.ObjectAccessDenied if errors.As(err, &errAccessDenied) { obj, err := s.Get(ctx, address, requestParams) if err != nil { return nil, err } payload := obj.Payload() from := rng.GetOffset() to := from + rng.GetLength() if pLen := uint64(len(payload)); to < from || pLen < from || pLen < to { return nil, new(apistatus.ObjectOutOfRange) } return s.payloadOnlyObject(payload[from:to]), nil } return nil, err } return s.payloadOnlyObject(res.PayloadRange()), nil } func (s *multiaddressRemoteStorage) Head(ctx context.Context, address oid.Address, requestParams RemoteRequestParams) (*objectSDK.Object, error) { var prm internalclient.HeadObjectPrm prm.SetClient(s.client) prm.SetTTL(requestParams.TTL) prm.SetNetmapEpoch(requestParams.Epoch) prm.SetAddress(address) prm.SetPrivateKey(requestParams.PrivateKey) prm.SetSessionToken(requestParams.SessionToken) prm.SetBearerToken(requestParams.BearerToken) prm.SetXHeaders(requestParams.XHeaders) if requestParams.IsRaw { prm.SetRawFlag() } res, err := internalclient.HeadObject(ctx, prm) if err != nil { return nil, err } return res.Header(), nil } func (s *multiaddressRemoteStorage) Get(ctx context.Context, address oid.Address, requestParams RemoteRequestParams) (*objectSDK.Object, error) { var prm internalclient.GetObjectPrm prm.SetClient(s.client) prm.SetTTL(requestParams.TTL) prm.SetNetmapEpoch(requestParams.Epoch) prm.SetAddress(address) prm.SetPrivateKey(requestParams.PrivateKey) prm.SetSessionToken(requestParams.SessionToken) prm.SetBearerToken(requestParams.BearerToken) prm.SetXHeaders(requestParams.XHeaders) if requestParams.IsRaw { prm.SetRawFlag() } res, err := internalclient.GetObject(ctx, prm) if err != nil { return nil, err } return res.Object(), nil } func (s *multiaddressRemoteStorage) payloadOnlyObject(payload []byte) *objectSDK.Object { obj := objectSDK.New() obj.SetPayload(payload) return obj } type RangeHashRes struct { hashes [][]byte } func (r *RangeHashRes) Hashes() [][]byte { return r.hashes }