From ec50f281be54eb4f1017f01ef15faad5e6270454 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 20 Jul 2015 19:44:29 -0700 Subject: [PATCH] reading of metadata --- .../Internal/BatchContextSafeHandle.cs | 28 +++++++++- .../Internal/MetadataArraySafeHandle.cs | 53 ++++++++++++++++++- src/csharp/ext/grpc_csharp_ext.c | 29 ++++++++++ 3 files changed, 108 insertions(+), 2 deletions(-) diff --git a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs index 861cbbe4c6b..bfd88a0940b 100644 --- a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs @@ -46,6 +46,9 @@ namespace Grpc.Core.Internal [DllImport("grpc_csharp_ext.dll")] static extern BatchContextSafeHandle grpcsharp_batch_context_create(); + [DllImport("grpc_csharp_ext.dll")] + static extern IntPtr grpcsharp_batch_context_receive_initial_metadata(BatchContextSafeHandle ctx); + [DllImport("grpc_csharp_ext.dll")] static extern IntPtr grpcsharp_batch_context_recv_message_length(BatchContextSafeHandle ctx); @@ -58,12 +61,18 @@ namespace Grpc.Core.Internal [DllImport("grpc_csharp_ext.dll")] static extern IntPtr grpcsharp_batch_context_recv_status_on_client_details(BatchContextSafeHandle ctx); // returns const char* + [DllImport("grpc_csharp_ext.dll")] + static extern IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata(BatchContextSafeHandle ctx); + [DllImport("grpc_csharp_ext.dll")] static extern CallSafeHandle grpcsharp_batch_context_server_rpc_new_call(BatchContextSafeHandle ctx); [DllImport("grpc_csharp_ext.dll")] static extern IntPtr grpcsharp_batch_context_server_rpc_new_method(BatchContextSafeHandle ctx); // returns const char* + [DllImport("grpc_csharp_ext.dll")] + static extern IntPtr grpcsharp_batch_context_server_rpc_new_request_metadata(BatchContextSafeHandle ctx); + [DllImport("grpc_csharp_ext.dll")] static extern int grpcsharp_batch_context_recv_close_on_server_cancelled(BatchContextSafeHandle ctx); @@ -87,13 +96,24 @@ namespace Grpc.Core.Internal } } + public Metadata GetReceivedInitialMetadata() + { + IntPtr metadataArrayPtr = grpcsharp_batch_context_receive_initial_metadata(this); + return MetadataArraySafeHandle.ReadMetadataFromPtrUnsafe(metadataArrayPtr); + } + public Status GetReceivedStatus() { - // TODO: can the native method return string directly? string details = Marshal.PtrToStringAnsi(grpcsharp_batch_context_recv_status_on_client_details(this)); return new Status(grpcsharp_batch_context_recv_status_on_client_status(this), details); } + public Metadata GetReceivedStatusTrailingMetadata() + { + IntPtr metadataArrayPtr = grpcsharp_batch_context_recv_status_on_client_trailing_metadata(this); + return MetadataArraySafeHandle.ReadMetadataFromPtrUnsafe(metadataArrayPtr); + } + public byte[] GetReceivedMessage() { IntPtr len = grpcsharp_batch_context_recv_message_length(this); @@ -116,6 +136,12 @@ namespace Grpc.Core.Internal return Marshal.PtrToStringAnsi(grpcsharp_batch_context_server_rpc_new_method(this)); } + public Metadata GetServerRpcNewRequestMetadata() + { + IntPtr metadataArrayPtr = grpcsharp_batch_context_server_rpc_new_request_metadata(this); + return MetadataArraySafeHandle.ReadMetadataFromPtrUnsafe(metadataArrayPtr); + } + public bool GetReceivedCloseOnServerCancelled() { return grpcsharp_batch_context_recv_close_on_server_cancelled(this) != 0; diff --git a/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs index 80aa7f56034..e17eb89abc7 100644 --- a/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs @@ -34,6 +34,8 @@ using System.Threading.Tasks; namespace Grpc.Core.Internal { + + /// /// grpc_metadata_array from /// @@ -45,13 +47,19 @@ namespace Grpc.Core.Internal [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] static extern void grpcsharp_metadata_array_add(MetadataArraySafeHandle array, string key, byte[] value, UIntPtr valueLength); + [DllImport("grpc_csharp_ext.dll")] + static extern UIntPtr grpcsharp_metadata_array_count(IntPtr metadataArray); + + [DllImport("grpc_csharp_ext.dll")] + static extern MetadataEntryStruct grpcsharp_metadata_array_get(IntPtr metadataArray, UIntPtr index); + [DllImport("grpc_csharp_ext.dll")] static extern void grpcsharp_metadata_array_destroy_full(IntPtr array); private MetadataArraySafeHandle() { } - + public static MetadataArraySafeHandle Create(Metadata metadata) { // TODO(jtattermusch): we might wanna check that the metadata is readonly @@ -63,10 +71,53 @@ namespace Grpc.Core.Internal return metadataArray; } + /// + /// Reads metadata from pointer to grpc_metadata_array + /// + public static Metadata ReadMetadataFromPtrUnsafe(IntPtr metadataArray) + { + if (metadataArray == IntPtr.Zero) + { + return null; + } + + ulong count = grpcsharp_metadata_array_count(metadataArray).ToUInt64(); + + var metadata = new Metadata(); + for (ulong index = 0; index < count; index ++) + { + var rawEntry = grpcsharp_metadata_array_get(metadataArray, new UIntPtr(index)); + string key = Marshal.PtrToStringAnsi(rawEntry.key); + var bytes = new byte[rawEntry.valueLength.ToUInt64()]; + Marshal.Copy(rawEntry.value, bytes, 0, bytes.Length); + metadata.Add(new Metadata.Entry(key, bytes)); + } + return metadata; + } + + internal IntPtr Handle + { + get + { + return handle; + } + } + protected override bool ReleaseHandle() { grpcsharp_metadata_array_destroy_full(handle); return true; } + + /// + /// gprc_metadata from grpc/grpc.h + /// + [StructLayout(LayoutKind.Sequential)] + private struct MetadataEntryStruct + { + public IntPtr key; // const char* + public IntPtr value; // const char* + public UIntPtr valueLength; + } } } diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index 7dd1959a5f7..d8996ae7a99 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -167,6 +167,17 @@ grpcsharp_metadata_array_add(grpc_metadata_array *array, const char *key, array->count++; } +GPR_EXPORT gpr_intptr GPR_CALLTYPE +grpcsharp_metadata_array_count(grpc_metadata_array *array) { + return (gpr_intptr) array->count; +} + +GPR_EXPORT const grpc_metadata *GPR_CALLTYPE +grpcsharp_metadata_array_get(grpc_metadata_array *array, size_t index) { + GPR_ASSERT(index < array->count); + return array->metadata[index]; +} + /* Move contents of metadata array */ void grpcsharp_metadata_array_move(grpc_metadata_array *dest, grpc_metadata_array *src) { @@ -218,6 +229,12 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_batch_context_destroy(grpcsharp_batch_con gpr_free(ctx); } +GPR_EXPORT const grpc_metadata_array *GPR_CALLTYPE +grpcsharp_batch_context_receive_initial_metadata( + const grpcsharp_batch_context *ctx) { + return &(ctx->recv_initial_metadata); +} + GPR_EXPORT gpr_intptr GPR_CALLTYPE grpcsharp_batch_context_recv_message_length( const grpcsharp_batch_context *ctx) { if (!ctx->recv_message) { @@ -260,6 +277,12 @@ grpcsharp_batch_context_recv_status_on_client_details( return ctx->recv_status_on_client.status_details; } +GPR_EXPORT const grpc_metadata_array *GPR_CALLTYPE +grpcsharp_batch_context_recv_status_on_client_trailing_metadata( + const grpcsharp_batch_context *ctx) { + return &(ctx->recv_status_on_client.trailing_metadata); +} + GPR_EXPORT grpc_call *GPR_CALLTYPE grpcsharp_batch_context_server_rpc_new_call( const grpcsharp_batch_context *ctx) { return ctx->server_rpc_new.call; @@ -271,6 +294,12 @@ grpcsharp_batch_context_server_rpc_new_method( return ctx->server_rpc_new.call_details.method; } +GPR_EXPORT const grpc_metadata_array *GPR_CALLTYPE +grpcsharp_batch_context_server_rpc_new_request_metadata( + const grpcsharp_batch_context *ctx) { + return &(ctx->server_rpc_new.request_metadata); +} + GPR_EXPORT gpr_int32 GPR_CALLTYPE grpcsharp_batch_context_recv_close_on_server_cancelled( const grpcsharp_batch_context *ctx) {