using FrostFS.Object; using FrostFS.Refs; using FrostFS.SDK.ClientV2.Mappers.GRPC; using FrostFS.SDK.Cryptography; using FrostFS.SDK.ModelsV2; using FrostFS.Session; using Google.Protobuf; using Grpc.Core; namespace FrostFS.SDK.ClientV2; public partial class Client { public async Task GetObjectHeadAsync(ContainerID cid, ObjectID oid) { var request = new HeadRequest { Body = new HeadRequest.Types.Body { Address = new Address { ContainerId = cid, ObjectId = oid } }, }; request.AddMetaHeader(); request.Sign(_key); return await _objectServiceClient.HeadAsync(request); } public async Task PutObjectAsync(ContainerID cid, Stream data) { var sessionToken = await CreateSessionAsync(uint.MaxValue); var header = new Header { ContainerId = cid, OwnerId = _owner.ToGrpcMessage(), Version = Version.ToGrpcMessage() }; var oid = new ObjectID { Value = header.Sha256() }; var request = new PutRequest { Body = new PutRequest.Types.Body { Init = new PutRequest.Types.Body.Types.Init { Header = header, }, } }; request.AddMetaHeader(); request.AddObjectSessionToken(sessionToken, cid, oid, ObjectSessionContext.Types.Verb.Put, _key); request.Sign(_key); using var stream = await InitObject(request); var buffer = new byte[Constants.ObjectChunkSize]; var bufferLength = data.Read(buffer, 0, Constants.ObjectChunkSize); while (bufferLength > 0) { request.Body = new PutRequest.Types.Body { Chunk = ByteString.CopyFrom(buffer[..bufferLength]), }; request.VerifyHeader = null; request.Sign(_key); await stream.Write(request); bufferLength = data.Read(buffer, 0, Constants.ObjectChunkSize); } return await stream.Close(); } private async Task InitObject(PutRequest initRequest) { if (initRequest is null) { throw new ArgumentNullException(nameof(initRequest)); } var call = _objectServiceClient.Put(); await call.RequestStream.WriteAsync(initRequest); return new ObjectStreamer { Call = call }; } public async Task DeleteObjectAsync(ContainerID cid, ObjectID oid) { var request = new DeleteRequest { Body = new DeleteRequest.Types.Body { Address = new Address { ContainerId = cid, ObjectId = oid } } }; request.AddMetaHeader(); request.Sign(_key); return await _objectServiceClient.DeleteAsync(request); } } internal class ObjectStreamer : IDisposable { public AsyncClientStreamingCall Call { get; init; } public void Dispose() { Call.Dispose(); } public async Task Write(PutRequest request) { if (request is null) { throw new ArgumentNullException(nameof(request)); } await Call.RequestStream.WriteAsync(request); } public async Task Close() { await Call.RequestStream.CompleteAsync(); return await Call.ResponseAsync; } }