Initial SDK structure #1

Merged
i.pchelintsev merged 1 commit from i.pchelintsev/frostfs-sdk-csharp:master into master 2024-09-04 19:51:24 +00:00
6 changed files with 91 additions and 10 deletions
Showing only changes of commit ae3fc419a4 - Show all commits

View file

@ -0,0 +1,19 @@
using FrostFS.SDK.ModelsV2.Enums;
namespace FrostFS.SDK.ClientV2.Mappers.GRPC;
public static class StatusMapper
{
public static ModelsV2.Status ToModel(this Status.Status status)
{
if (status is null) return new ModelsV2.Status(StatusCode.Success);
var codeName = Enum.GetName(typeof(StatusCode), status.Code);
if (codeName is null)
{
throw new ArgumentException($"Unknown StatusCode. Value: '{status.Code}'.");
}
return new ModelsV2.Status(Enum.Parse<StatusCode>(codeName), status.Message);
}
}

View file

@ -18,6 +18,7 @@ public partial class Client
request.AddMetaHeader();
request.Sign(_key);
var response = await _containerServiceClient.GetAsync(request);
Verifier.CheckResponse(response);
return response.Body.Container.ToModel();
}
@ -33,6 +34,7 @@ public partial class Client
request.AddMetaHeader();
request.Sign(_key);
var response = await _containerServiceClient.ListAsync(request);
Verifier.CheckResponse(response);
foreach (var cid in response.Body.ContainerIds)
{
yield return ContainerId.FromHash(cid.Value.ToByteArray());
@ -55,7 +57,7 @@ public partial class Client
request.AddMetaHeader();
request.Sign(_key);
var response = await _containerServiceClient.PutAsync(request);
RequestVerifier.ProcessResponse(response);
Verifier.CheckResponse(response);
return ContainerId.FromHash(response.Body.ContainerId.Value.ToByteArray());
}
@ -71,6 +73,7 @@ public partial class Client
};
request.AddMetaHeader();
request.Sign(_key);
await _containerServiceClient.DeleteAsync(request);
var response = await _containerServiceClient.DeleteAsync(request);
Verifier.CheckResponse(response);
}
}

View file

@ -27,6 +27,7 @@ public partial class Client
request.AddMetaHeader();
request.Sign(_key);
var response = await _objectServiceClient.HeadAsync(request);
Verifier.CheckResponse(response);
return response.Body.Header.Header.ToModel();
}
@ -55,8 +56,8 @@ public partial class Client
);
request.Sign(_key);
var response = await GetObject(request);
return response.ToModel();
var obj = await GetObject(request);
return obj.ToModel();
}
private async Task<Object.Object> GetObject(GetRequest request)
@ -146,6 +147,7 @@ public partial class Client
}
var response = await stream.Close();
Verifier.CheckResponse(response);
return ObjectId.FromHash(response.Body.ObjectId.Value.ToByteArray());
}
@ -176,7 +178,8 @@ public partial class Client
};
request.AddMetaHeader();
request.Sign(_key);
await _objectServiceClient.DeleteAsync(request);
var response = await _objectServiceClient.DeleteAsync(request);
Verifier.CheckResponse(response);
}
public async IAsyncEnumerable<ObjectId> SearchObjectsAsync(ContainerId cid, params ObjectFilter[] filters)
@ -245,6 +248,7 @@ internal class ObjectReader : IDisposable
}
var response = Call.ResponseStream.Current;
Verifier.CheckResponse(response);
if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Init)
throw new InvalidOperationException("unexpect message type");
return new Object.Object
@ -262,6 +266,7 @@ internal class ObjectReader : IDisposable
}
var response = Call.ResponseStream.Current;
Verifier.CheckResponse(response);
if (response.Body.ObjectPartCase != GetResponse.Types.Body.ObjectPartOneofCase.Chunk)
throw new InvalidOperationException("unexpect message type");
return response.Body.Chunk.ToByteArray();
@ -311,6 +316,7 @@ internal class SearchReader : IDisposable
}
var response = Call.ResponseStream.Current;
Verifier.CheckResponse(response);
return response.Body?.IdList.ToList();
}

View file

@ -1,5 +1,6 @@
using System.Security.Cryptography;
using FrostFS.Refs;
using FrostFS.SDK.ClientV2.Mappers.GRPC;
using FrostFS.SDK.Cryptography;
using FrostFS.Session;
using Google.Protobuf;
@ -9,8 +10,9 @@ using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Math;
namespace FrostFS.SDK.ClientV2 {
public static class RequestVerifier
namespace FrostFS.SDK.ClientV2
{
public static class Verifier
{
public const int RFC6979SignatureSize = 64;
@ -72,12 +74,16 @@ namespace FrostFS.SDK.ClientV2 {
{
return VerifyMatryoskaLevel(message.GetBody(), message.GetMetaHeader(), message.GetVerificationHeader());
}
public static void ProcessResponse(IResponse resp)
public static void CheckResponse(IResponse resp)
{
Console.WriteLine(resp.MetaHeader.Status);
if (!resp.Verify())
throw new FormatException($"invalid response, type={resp.GetType()}");
var status = resp.MetaHeader.Status.ToModel();
if (!status.IsSuccess())
{
throw new ApplicationException(status.ToString());
}
}
}
}

View file

@ -0,0 +1,22 @@
namespace FrostFS.SDK.ModelsV2.Enums;
public enum StatusCode
{
Success = 0,
Internal = 1024,
WrongMagicNumber = 1025,
SignatureVerificationFailure = 1026,
NodeUnderMaintenance = 1027,
ObjectAccessDenied = 2048,
ObjectNotFound = 2049,
ObjectLocked = 2050,
LockNotRegularObject = 2051,
ObjectAlreadyRemoved = 2052,
OutOfRange = 2053,
ContainerNotFound = 3072,
EAclNotFound = 3073,
ContainerAccessDenied = 3074,
TokenNotFound = 4096,
TokenExpired = 4097,
ApeManagerAccessDenied = 5120
}

View file

@ -0,0 +1,25 @@
using FrostFS.SDK.ModelsV2.Enums;
namespace FrostFS.SDK.ModelsV2;
public class Status
{
public StatusCode Code { get; set; }
public string Message { get; set; }
public Status(StatusCode code, string? message = null)
{
Code = code;
Message = message ?? string.Empty;
}
public bool IsSuccess()
{
return Code == StatusCode.Success;
}
public override string ToString()
{
return $"Response status: {Code}. Message: {Message}.";
}
}