Merge pull request #9390 from jtattermusch/csharp_utf8_message

Make C# status messages truly UTF8
pull/9332/merge
Jan Tattermusch 8 years ago committed by GitHub
commit ca9d959f15
  1. 16
      src/csharp/Grpc.Core.Tests/ClientServerTest.cs
  2. 11
      src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs
  3. 5
      src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
  4. 2
      src/csharp/Grpc.Core/Internal/NativeMethods.cs
  5. 5
      src/csharp/ext/grpc_csharp_ext.c

@ -335,6 +335,22 @@ namespace Grpc.Core.Tests
Assert.AreEqual(StatusCode.Unimplemented, ex.Status.StatusCode);
}
[Test]
public void StatusDetailIsUtf8()
{
// some japanese and chinese characters
var nonAsciiString = "\u30a1\u30a2\u30a3 \u62b5\u6297\u662f\u5f92\u52b3\u7684";
helper.UnaryHandler = new UnaryServerMethod<string, string>(async (request, context) =>
{
context.Status = new Status(StatusCode.Unknown, nonAsciiString);
return "";
});
var ex = Assert.Throws<RpcException>(() => Calls.BlockingUnaryCall(helper.CreateUnaryCall(), "abc"));
Assert.AreEqual(StatusCode.Unknown, ex.Status.StatusCode);
Assert.AreEqual(nonAsciiString, ex.Status.Detail);
}
[Test]
public void ServerCallContext_PeerInfoPresent()
{

@ -33,6 +33,7 @@
using System;
using System.Runtime.InteropServices;
using System.Text;
using Grpc.Core;
namespace Grpc.Core.Internal
@ -42,6 +43,7 @@ namespace Grpc.Core.Internal
/// </summary>
internal class BatchContextSafeHandle : SafeHandleZeroIsInvalid
{
static readonly Encoding EncodingUTF8 = System.Text.Encoding.UTF8;
static readonly NativeMethods Native = NativeMethods.Get();
private BatchContextSafeHandle()
@ -73,7 +75,7 @@ namespace Grpc.Core.Internal
{
UIntPtr detailsLength;
IntPtr detailsPtr = Native.grpcsharp_batch_context_recv_status_on_client_details(this, out detailsLength);
string details = Marshal.PtrToStringAnsi(detailsPtr, (int) detailsLength.ToUInt32());
string details = PtrToStringUtf8(detailsPtr, (int) detailsLength.ToUInt32());
var status = new Status(Native.grpcsharp_batch_context_recv_status_on_client_status(this), details);
IntPtr metadataArrayPtr = Native.grpcsharp_batch_context_recv_status_on_client_trailing_metadata(this);
@ -106,5 +108,12 @@ namespace Grpc.Core.Internal
Native.grpcsharp_batch_context_destroy(handle);
return true;
}
string PtrToStringUtf8(IntPtr ptr, int len)
{
var bytes = new byte[len];
Marshal.Copy(ptr, bytes, 0, len);
return EncodingUTF8.GetString(bytes);
}
}
}

@ -32,6 +32,7 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using Grpc.Core;
using Grpc.Core.Utils;
using Grpc.Core.Profiling;
@ -44,6 +45,7 @@ namespace Grpc.Core.Internal
internal class CallSafeHandle : SafeHandleZeroIsInvalid, INativeCall
{
public static readonly CallSafeHandle NullInstance = new CallSafeHandle();
static readonly Encoding EncodingUTF8 = System.Text.Encoding.UTF8;
static readonly NativeMethods Native = NativeMethods.Get();
const uint GRPC_WRITE_BUFFER_HINT = 1;
@ -138,7 +140,8 @@ namespace Grpc.Core.Internal
var ctx = BatchContextSafeHandle.Create();
var optionalPayloadLength = optionalPayload != null ? new UIntPtr((ulong)optionalPayload.Length) : UIntPtr.Zero;
completionQueue.CompletionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success));
Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, status.Detail, metadataArray, sendEmptyInitialMetadata,
var statusDetailBytes = EncodingUTF8.GetBytes(status.Detail);
Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, statusDetailBytes, new UIntPtr((ulong)statusDetailBytes.Length), metadataArray, sendEmptyInitialMetadata,
optionalPayload, optionalPayloadLength, writeFlags).CheckOk();
}
}

@ -336,7 +336,7 @@ namespace Grpc.Core.Internal
public delegate CallError grpcsharp_call_send_close_from_client_delegate(CallSafeHandle call,
BatchContextSafeHandle ctx);
public delegate CallError grpcsharp_call_send_status_from_server_delegate(CallSafeHandle call,
BatchContextSafeHandle ctx, StatusCode statusCode, string statusMessage, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata,
BatchContextSafeHandle ctx, StatusCode statusCode, byte[] statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata,
byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags);
public delegate CallError grpcsharp_call_recv_message_delegate(CallSafeHandle call,
BatchContextSafeHandle ctx);

@ -734,14 +734,15 @@ grpcsharp_call_send_close_from_client(grpc_call *call,
GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_send_status_from_server(
grpc_call *call, grpcsharp_batch_context *ctx, grpc_status_code status_code,
const char *status_details, grpc_metadata_array *trailing_metadata,
const char *status_details, size_t status_details_len,
grpc_metadata_array *trailing_metadata,
int32_t send_empty_initial_metadata, const char* optional_send_buffer,
size_t optional_send_buffer_len, uint32_t write_flags) {
/* TODO: don't use magic number */
grpc_op ops[3];
memset(ops, 0, sizeof(ops));
size_t nops = 1;
grpc_slice status_details_slice = grpc_slice_from_copied_string(status_details);
grpc_slice status_details_slice = grpc_slice_from_copied_buffer(status_details, status_details_len);
ops[0].op = GRPC_OP_SEND_STATUS_FROM_SERVER;
ops[0].data.send_status_from_server.status = status_code;
ops[0].data.send_status_from_server.status_details = &status_details_slice;

Loading…
Cancel
Save