From c0b3721d61fed71a3528cecfa6797cdc26722d3a Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 13 Mar 2015 08:35:41 -0700 Subject: added support for metadata --- src/csharp/Grpc.Core.Tests/ClientServerTest.cs | 14 +- src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj | 4 + .../Internal/MetadataArraySafeHandleTest.cs | 62 ++++++++ src/csharp/Grpc.Core/Call.cs | 55 +++---- src/csharp/Grpc.Core/Calls.cs | 30 ++-- src/csharp/Grpc.Core/Grpc.Core.csproj | 7 + src/csharp/Grpc.Core/Internal/AsyncCall.cs | 37 +++-- src/csharp/Grpc.Core/Internal/CallSafeHandle.cs | 33 +++-- .../Grpc.Core/Internal/MetadataArraySafeHandle.cs | 72 +++++++++ src/csharp/Grpc.Core/Marshaller.cs | 5 +- src/csharp/Grpc.Core/Metadata.cs | 126 ++++++++++++++++ src/csharp/Grpc.Core/ServerServiceDefinition.cs | 15 +- src/csharp/Grpc.Core/Stub/AbstractStub.cs | 73 ++++++++++ src/csharp/Grpc.Core/Stub/StubConfiguration.cs | 64 ++++++++ .../Grpc.Examples.Tests/MathClientServerTests.cs | 9 +- src/csharp/Grpc.Examples/MathGrpc.cs | 36 +++-- .../Grpc.IntegrationTesting.csproj | 3 +- .../Grpc.IntegrationTesting/TestServiceGrpc.cs | 41 +++--- src/csharp/ext/grpc_csharp_ext.c | 162 ++++++++++++++++----- 19 files changed, 694 insertions(+), 154 deletions(-) create mode 100644 src/csharp/Grpc.Core.Tests/Internal/MetadataArraySafeHandleTest.cs create mode 100644 src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs create mode 100644 src/csharp/Grpc.Core/Metadata.cs create mode 100644 src/csharp/Grpc.Core/Stub/AbstractStub.cs create mode 100644 src/csharp/Grpc.Core/Stub/StubConfiguration.cs (limited to 'src/csharp') diff --git a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs index e73159b350..807f5a6ded 100644 --- a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs +++ b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs @@ -46,6 +46,8 @@ namespace Grpc.Core.Tests { string host = "localhost"; + string serviceName = "/tests.Test"; + Method unaryEchoStringMethod = new Method( MethodType.Unary, "/tests.Test/UnaryEchoString", @@ -69,7 +71,7 @@ namespace Grpc.Core.Tests { Server server = new Server(); server.AddServiceDefinition( - ServerServiceDefinition.CreateBuilder("someService") + ServerServiceDefinition.CreateBuilder(serviceName) .AddMethod(unaryEchoStringMethod, HandleUnaryEchoString).Build()); int port = server.AddPort(host + ":0"); @@ -77,7 +79,7 @@ namespace Grpc.Core.Tests using (Channel channel = new Channel(host + ":" + port)) { - var call = new Call(unaryEchoStringMethod, channel); + var call = new Call(serviceName, unaryEchoStringMethod, channel, Metadata.Empty); Assert.AreEqual("ABC", Calls.BlockingUnaryCall(call, "ABC", default(CancellationToken))); @@ -92,7 +94,7 @@ namespace Grpc.Core.Tests { Server server = new Server(); server.AddServiceDefinition( - ServerServiceDefinition.CreateBuilder("someService") + ServerServiceDefinition.CreateBuilder(serviceName) .AddMethod(unaryEchoStringMethod, HandleUnaryEchoString).Build()); int port = server.AddPort(host + ":0"); @@ -100,7 +102,7 @@ namespace Grpc.Core.Tests using (Channel channel = new Channel(host + ":" + port)) { - var call = new Call(unaryEchoStringMethod, channel); + var call = new Call(serviceName, unaryEchoStringMethod, channel, Metadata.Empty); BenchmarkUtil.RunBenchmark(100, 1000, () => { Calls.BlockingUnaryCall(call, "ABC", default(CancellationToken)); }); } @@ -113,14 +115,14 @@ namespace Grpc.Core.Tests { Server server = new Server(); server.AddServiceDefinition( - ServerServiceDefinition.CreateBuilder("someService").Build()); + ServerServiceDefinition.CreateBuilder(serviceName).Build()); int port = server.AddPort(host + ":0"); server.Start(); using (Channel channel = new Channel(host + ":" + port)) { - var call = new Call(unaryEchoStringMethod, channel); + var call = new Call(serviceName, unaryEchoStringMethod, channel, Metadata.Empty); try { diff --git a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj index a365320f05..eac8d16fb1 100644 --- a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj +++ b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj @@ -42,6 +42,7 @@ + @@ -56,4 +57,7 @@ + + + \ No newline at end of file diff --git a/src/csharp/Grpc.Core.Tests/Internal/MetadataArraySafeHandleTest.cs b/src/csharp/Grpc.Core.Tests/Internal/MetadataArraySafeHandleTest.cs new file mode 100644 index 0000000000..2f6013483d --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/MetadataArraySafeHandleTest.cs @@ -0,0 +1,62 @@ +#region Copyright notice and license + +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + public class MetadataArraySafeHandleTest + { + [Test] + public void CreateEmptyAndDestroy() + { + var metadata = Metadata.CreateBuilder().Build(); + var nativeMetadata = MetadataArraySafeHandle.Create(metadata); + nativeMetadata.Dispose(); + } + + [Test] + public void CreateAndDestroy() + { + var metadata = Metadata.CreateBuilder() + .Add(new Metadata.MetadataEntry("host", "somehost")) + .Add(new Metadata.MetadataEntry("header2", "header value")).Build(); + var nativeMetadata = MetadataArraySafeHandle.Create(metadata); + nativeMetadata.Dispose(); + } + } +} diff --git a/src/csharp/Grpc.Core/Call.cs b/src/csharp/Grpc.Core/Call.cs index d84d5940c2..fe5f40f5e9 100644 --- a/src/csharp/Grpc.Core/Call.cs +++ b/src/csharp/Grpc.Core/Call.cs @@ -33,65 +33,70 @@ using System; using Grpc.Core.Internal; +using Grpc.Core.Utils; namespace Grpc.Core { public class Call { - readonly string methodName; - readonly Func requestSerializer; - readonly Func responseDeserializer; + readonly string name; + readonly Marshaller requestMarshaller; + readonly Marshaller responseMarshaller; readonly Channel channel; + readonly Metadata headers; - public Call(string methodName, - Func requestSerializer, - Func responseDeserializer, - TimeSpan timeout, - Channel channel) + public Call(string serviceName, Method method, Channel channel, Metadata headers) { - this.methodName = methodName; - this.requestSerializer = requestSerializer; - this.responseDeserializer = responseDeserializer; - this.channel = channel; + this.name = Preconditions.CheckNotNull(serviceName) + "/" + method.Name; + this.requestMarshaller = method.RequestMarshaller; + this.responseMarshaller = method.ResponseMarshaller; + this.channel = Preconditions.CheckNotNull(channel); + this.headers = Preconditions.CheckNotNull(headers); } - public Call(Method method, Channel channel) + public Channel Channel { - this.methodName = method.Name; - this.requestSerializer = method.RequestMarshaller.Serializer; - this.responseDeserializer = method.ResponseMarshaller.Deserializer; - this.channel = channel; + get + { + return this.channel; + } } - public Channel Channel + /// + /// Full methods name including the service name. + /// + public string Name { get { - return this.channel; + return name; } } - public string MethodName + /// + /// Headers to send at the beginning of the call. + /// + public Metadata Headers { get { - return this.methodName; + return headers; } } - public Func RequestSerializer + public Marshaller RequestMarshaller { get { - return this.requestSerializer; + return requestMarshaller; } } - public Func ResponseDeserializer + public Marshaller ResponseMarshaller { get { - return this.responseDeserializer; + return responseMarshaller; } } } diff --git a/src/csharp/Grpc.Core/Calls.cs b/src/csharp/Grpc.Core/Calls.cs index cc1d67afca..280387b323 100644 --- a/src/csharp/Grpc.Core/Calls.cs +++ b/src/csharp/Grpc.Core/Calls.cs @@ -45,30 +45,29 @@ namespace Grpc.Core { public static TResponse BlockingUnaryCall(Call call, TRequest req, CancellationToken token) { - var asyncCall = new AsyncCall(call.RequestSerializer, call.ResponseDeserializer); - return asyncCall.UnaryCall(call.Channel, call.MethodName, req); + var asyncCall = new AsyncCall(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer); + return asyncCall.UnaryCall(call.Channel, call.Name, req, call.Headers); } public static async Task AsyncUnaryCall(Call call, TRequest req, CancellationToken token) { - var asyncCall = new AsyncCall(call.RequestSerializer, call.ResponseDeserializer); - asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.MethodName); - return await asyncCall.UnaryCallAsync(req); + var asyncCall = new AsyncCall(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer); + asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name); + return await asyncCall.UnaryCallAsync(req, call.Headers); } public static void AsyncServerStreamingCall(Call call, TRequest req, IObserver outputs, CancellationToken token) { - var asyncCall = new AsyncCall(call.RequestSerializer, call.ResponseDeserializer); - - asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.MethodName); - asyncCall.StartServerStreamingCall(req, outputs); + var asyncCall = new AsyncCall(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer); + asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name); + asyncCall.StartServerStreamingCall(req, outputs, call.Headers); } public static ClientStreamingAsyncResult AsyncClientStreamingCall(Call call, CancellationToken token) { - var asyncCall = new AsyncCall(call.RequestSerializer, call.ResponseDeserializer); - asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.MethodName); - var task = asyncCall.ClientStreamingCallAsync(); + var asyncCall = new AsyncCall(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer); + asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name); + var task = asyncCall.ClientStreamingCallAsync(call.Headers); var inputs = new ClientStreamingInputObserver(asyncCall); return new ClientStreamingAsyncResult(task, inputs); } @@ -80,10 +79,9 @@ namespace Grpc.Core public static IObserver DuplexStreamingCall(Call call, IObserver outputs, CancellationToken token) { - var asyncCall = new AsyncCall(call.RequestSerializer, call.ResponseDeserializer); - asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.MethodName); - - asyncCall.StartDuplexStreamingCall(outputs); + var asyncCall = new AsyncCall(call.RequestMarshaller.Serializer, call.ResponseMarshaller.Deserializer); + asyncCall.Initialize(call.Channel, GetCompletionQueue(), call.Name); + asyncCall.StartDuplexStreamingCall(outputs, call.Headers); return new ClientStreamingInputObserver(asyncCall); } diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index 29f1a0604a..78ba32b277 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -79,6 +79,10 @@ + + + + @@ -96,4 +100,7 @@ + + + \ No newline at end of file diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs index 04fc28d988..bc72cb78de 100644 --- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs +++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs @@ -77,7 +77,7 @@ namespace Grpc.Core.Internal /// /// Blocking unary request - unary response call. /// - public TResponse UnaryCall(Channel channel, string methodName, TRequest msg) + public TResponse UnaryCall(Channel channel, string methodName, TRequest msg, Metadata headers) { using (CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create()) { @@ -92,7 +92,11 @@ namespace Grpc.Core.Internal halfcloseRequested = true; readingDone = true; } - call.BlockingUnary(cq, payload, unaryResponseHandler); + + using (var metadataArray = MetadataArraySafeHandle.Create(headers)) + { + call.BlockingUnary(cq, payload, unaryResponseHandler, metadataArray); + } try { @@ -109,7 +113,7 @@ namespace Grpc.Core.Internal /// /// Starts a unary request - unary response call. /// - public Task UnaryCallAsync(TRequest msg) + public Task UnaryCallAsync(TRequest msg, Metadata headers) { lock (myLock) { @@ -122,8 +126,10 @@ namespace Grpc.Core.Internal byte[] payload = UnsafeSerialize(msg); unaryResponseTcs = new TaskCompletionSource(); - call.StartUnary(payload, unaryResponseHandler); - + using (var metadataArray = MetadataArraySafeHandle.Create(headers)) + { + call.StartUnary(payload, unaryResponseHandler, metadataArray); + } return unaryResponseTcs.Task; } } @@ -132,7 +138,7 @@ namespace Grpc.Core.Internal /// Starts a streamed request - unary response call. /// Use StartSendMessage and StartSendCloseFromClient to stream requests. /// - public Task ClientStreamingCallAsync() + public Task ClientStreamingCallAsync(Metadata headers) { lock (myLock) { @@ -142,7 +148,10 @@ namespace Grpc.Core.Internal readingDone = true; unaryResponseTcs = new TaskCompletionSource(); - call.StartClientStreaming(unaryResponseHandler); + using (var metadataArray = MetadataArraySafeHandle.Create(headers)) + { + call.StartClientStreaming(unaryResponseHandler, metadataArray); + } return unaryResponseTcs.Task; } @@ -151,7 +160,7 @@ namespace Grpc.Core.Internal /// /// Starts a unary request - streamed response call. /// - public void StartServerStreamingCall(TRequest msg, IObserver readObserver) + public void StartServerStreamingCall(TRequest msg, IObserver readObserver, Metadata headers) { lock (myLock) { @@ -165,7 +174,10 @@ namespace Grpc.Core.Internal byte[] payload = UnsafeSerialize(msg); - call.StartServerStreaming(payload, finishedHandler); + using (var metadataArray = MetadataArraySafeHandle.Create(headers)) + { + call.StartServerStreaming(payload, finishedHandler, metadataArray); + } StartReceiveMessage(); } @@ -175,7 +187,7 @@ namespace Grpc.Core.Internal /// Starts a streaming request - streaming response call. /// Use StartSendMessage and StartSendCloseFromClient to stream requests. /// - public void StartDuplexStreamingCall(IObserver readObserver) + public void StartDuplexStreamingCall(IObserver readObserver, Metadata headers) { lock (myLock) { @@ -185,7 +197,10 @@ namespace Grpc.Core.Internal this.readObserver = readObserver; - call.StartDuplexStreaming(finishedHandler); + using (var metadataArray = MetadataArraySafeHandle.Create(headers)) + { + call.StartDuplexStreaming(finishedHandler, metadataArray); + } StartReceiveMessage(); } diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs index a8cef4a68b..14add60c72 100644 --- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs @@ -57,25 +57,28 @@ namespace Grpc.Core.Internal [DllImport("grpc_csharp_ext.dll")] static extern GRPCCallError grpcsharp_call_start_unary(CallSafeHandle call, [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback, - byte[] send_buffer, UIntPtr send_buffer_len); + byte[] send_buffer, UIntPtr send_buffer_len, MetadataArraySafeHandle metadataArray); [DllImport("grpc_csharp_ext.dll")] static extern void grpcsharp_call_blocking_unary(CallSafeHandle call, CompletionQueueSafeHandle dedicatedCq, [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback, - byte[] send_buffer, UIntPtr send_buffer_len); + byte[] send_buffer, UIntPtr send_buffer_len, MetadataArraySafeHandle metadataArray); [DllImport("grpc_csharp_ext.dll")] static extern GRPCCallError grpcsharp_call_start_client_streaming(CallSafeHandle call, - [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback); + [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback, + MetadataArraySafeHandle metadataArray); [DllImport("grpc_csharp_ext.dll")] static extern GRPCCallError grpcsharp_call_start_server_streaming(CallSafeHandle call, [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback, - byte[] send_buffer, UIntPtr send_buffer_len); + byte[] send_buffer, UIntPtr send_buffer_len, + MetadataArraySafeHandle metadataArray); [DllImport("grpc_csharp_ext.dll")] static extern GRPCCallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call, - [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback); + [MarshalAs(UnmanagedType.FunctionPtr)] CompletionCallbackDelegate callback, + MetadataArraySafeHandle metadataArray); [DllImport("grpc_csharp_ext.dll")] static extern GRPCCallError grpcsharp_call_send_message(CallSafeHandle call, @@ -109,29 +112,29 @@ namespace Grpc.Core.Internal return grpcsharp_channel_create_call(channel, cq, method, host, deadline); } - public void StartUnary(byte[] payload, CompletionCallbackDelegate callback) + public void StartUnary(byte[] payload, CompletionCallbackDelegate callback, MetadataArraySafeHandle metadataArray) { - AssertCallOk(grpcsharp_call_start_unary(this, callback, payload, new UIntPtr((ulong)payload.Length))); + AssertCallOk(grpcsharp_call_start_unary(this, callback, payload, new UIntPtr((ulong)payload.Length), metadataArray)); } - public void BlockingUnary(CompletionQueueSafeHandle dedicatedCq, byte[] payload, CompletionCallbackDelegate callback) + public void BlockingUnary(CompletionQueueSafeHandle dedicatedCq, byte[] payload, CompletionCallbackDelegate callback, MetadataArraySafeHandle metadataArray) { - grpcsharp_call_blocking_unary(this, dedicatedCq, callback, payload, new UIntPtr((ulong)payload.Length)); + grpcsharp_call_blocking_unary(this, dedicatedCq, callback, payload, new UIntPtr((ulong)payload.Length), metadataArray); } - public void StartClientStreaming(CompletionCallbackDelegate callback) + public void StartClientStreaming(CompletionCallbackDelegate callback, MetadataArraySafeHandle metadataArray) { - AssertCallOk(grpcsharp_call_start_client_streaming(this, callback)); + AssertCallOk(grpcsharp_call_start_client_streaming(this, callback, metadataArray)); } - public void StartServerStreaming(byte[] payload, CompletionCallbackDelegate callback) + public void StartServerStreaming(byte[] payload, CompletionCallbackDelegate callback, MetadataArraySafeHandle metadataArray) { - AssertCallOk(grpcsharp_call_start_server_streaming(this, callback, payload, new UIntPtr((ulong)payload.Length))); + AssertCallOk(grpcsharp_call_start_server_streaming(this, callback, payload, new UIntPtr((ulong)payload.Length), metadataArray)); } - public void StartDuplexStreaming(CompletionCallbackDelegate callback) + public void StartDuplexStreaming(CompletionCallbackDelegate callback, MetadataArraySafeHandle metadataArray) { - AssertCallOk(grpcsharp_call_start_duplex_streaming(this, callback)); + AssertCallOk(grpcsharp_call_start_duplex_streaming(this, callback, metadataArray)); } public void StartSendMessage(byte[] payload, CompletionCallbackDelegate callback) diff --git a/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs new file mode 100644 index 0000000000..c9c4d954c9 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs @@ -0,0 +1,72 @@ +#region Copyright notice and license +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion +using System; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace Grpc.Core.Internal +{ + /// + /// grpc_metadata_array from + /// + internal class MetadataArraySafeHandle : SafeHandleZeroIsInvalid + { + [DllImport("grpc_csharp_ext.dll")] + static extern MetadataArraySafeHandle grpcsharp_metadata_array_create(UIntPtr capacity); + + [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 void grpcsharp_metadata_array_destroy_full(IntPtr array); + + private MetadataArraySafeHandle() + { + } + + public static MetadataArraySafeHandle Create(Metadata metadata) + { + var entries = metadata.Entries; + var metadataArray = grpcsharp_metadata_array_create(new UIntPtr((ulong)entries.Count)); + for (int i = 0; i < entries.Count; i++) + { + grpcsharp_metadata_array_add(metadataArray, entries[i].Key, entries[i].ValueBytes, new UIntPtr((ulong)entries[i].ValueBytes.Length)); + } + return metadataArray; + } + + protected override bool ReleaseHandle() + { + grpcsharp_metadata_array_destroy_full(handle); + return true; + } + } +} diff --git a/src/csharp/Grpc.Core/Marshaller.cs b/src/csharp/Grpc.Core/Marshaller.cs index e73e7b762e..8b1a929074 100644 --- a/src/csharp/Grpc.Core/Marshaller.cs +++ b/src/csharp/Grpc.Core/Marshaller.cs @@ -32,6 +32,7 @@ #endregion using System; +using Grpc.Core.Utils; namespace Grpc.Core { @@ -45,8 +46,8 @@ namespace Grpc.Core public Marshaller(Func serializer, Func deserializer) { - this.serializer = serializer; - this.deserializer = deserializer; + this.serializer = Preconditions.CheckNotNull(serializer); + this.deserializer = Preconditions.CheckNotNull(deserializer); } public Func Serializer diff --git a/src/csharp/Grpc.Core/Metadata.cs b/src/csharp/Grpc.Core/Metadata.cs new file mode 100644 index 0000000000..eccec26a61 --- /dev/null +++ b/src/csharp/Grpc.Core/Metadata.cs @@ -0,0 +1,126 @@ +#region Copyright notice and license +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#endregion + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Runtime.InteropServices; +using System.Text; + +namespace Grpc.Core +{ + /// + /// gRPC call metadata. + /// + public class Metadata + { + public static readonly Metadata Empty = new Metadata(ImmutableList.Empty); + + readonly ImmutableList entries; + + public Metadata(ImmutableList entries) + { + this.entries = entries; + } + + public ImmutableList Entries + { + get + { + return this.entries; + } + } + + public static Builder CreateBuilder() + { + return new Builder(); + } + + public struct MetadataEntry + { + readonly string key; + readonly byte[] valueBytes; + + public MetadataEntry(string key, byte[] valueBytes) + { + this.key = key; + this.valueBytes = valueBytes; + } + + public MetadataEntry(string key, string value) + { + this.key = key; + this.valueBytes = Encoding.ASCII.GetBytes(value); + } + + public string Key + { + get + { + return this.key; + } + } + + // TODO: using ByteString would guarantee immutability. + public byte[] ValueBytes + { + get + { + return this.valueBytes; + } + } + } + + public class Builder + { + readonly List entries = new List(); + + public List Entries + { + get + { + return entries; + } + } + + public Builder Add(MetadataEntry entry) + { + entries.Add(entry); + return this; + } + + public Metadata Build() + { + return new Metadata(entries.ToImmutableList()); + } + } + } +} diff --git a/src/csharp/Grpc.Core/ServerServiceDefinition.cs b/src/csharp/Grpc.Core/ServerServiceDefinition.cs index 004415477c..f08c7d88f3 100644 --- a/src/csharp/Grpc.Core/ServerServiceDefinition.cs +++ b/src/csharp/Grpc.Core/ServerServiceDefinition.cs @@ -43,12 +43,10 @@ namespace Grpc.Core /// public class ServerServiceDefinition { - readonly string serviceName; readonly ImmutableDictionary callHandlers; - private ServerServiceDefinition(string serviceName, ImmutableDictionary callHandlers) + private ServerServiceDefinition(ImmutableDictionary callHandlers) { - this.serviceName = serviceName; this.callHandlers = callHandlers; } @@ -79,7 +77,7 @@ namespace Grpc.Core Method method, UnaryRequestServerMethod handler) { - callHandlers.Add(method.Name, ServerCalls.UnaryRequestCall(method, handler)); + callHandlers.Add(GetFullMethodName(serviceName, method.Name), ServerCalls.UnaryRequestCall(method, handler)); return this; } @@ -87,13 +85,18 @@ namespace Grpc.Core Method method, StreamingRequestServerMethod handler) { - callHandlers.Add(method.Name, ServerCalls.StreamingRequestCall(method, handler)); + callHandlers.Add(GetFullMethodName(serviceName, method.Name), ServerCalls.StreamingRequestCall(method, handler)); return this; } public ServerServiceDefinition Build() { - return new ServerServiceDefinition(serviceName, callHandlers.ToImmutableDictionary()); + return new ServerServiceDefinition(callHandlers.ToImmutableDictionary()); + } + + private string GetFullMethodName(string serviceName, string methodName) + { + return serviceName + "/" + methodName; } } } diff --git a/src/csharp/Grpc.Core/Stub/AbstractStub.cs b/src/csharp/Grpc.Core/Stub/AbstractStub.cs new file mode 100644 index 0000000000..cf5ab958c5 --- /dev/null +++ b/src/csharp/Grpc.Core/Stub/AbstractStub.cs @@ -0,0 +1,73 @@ +#region Copyright notice and license + +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; +using Grpc.Core.Internal; + +namespace Grpc.Core +{ + // TODO: support adding timeout to methods. + /// + /// Base for client-side stubs. + /// + public abstract class AbstractStub + where TConfig : StubConfiguration + { + readonly Channel channel; + readonly TConfig config; + + public AbstractStub(Channel channel, TConfig config) + { + this.channel = channel; + this.config = config; + } + + public Channel Channel + { + get + { + return this.channel; + } + } + + /// + /// Creates a new call to given method. + /// + protected Call CreateCall(string serviceName, Method method) + { + var headerBuilder = Metadata.CreateBuilder(); + config.HeaderInterceptor(headerBuilder); + return new Call(serviceName, method, channel, headerBuilder.Build()); + } + } +} diff --git a/src/csharp/Grpc.Core/Stub/StubConfiguration.cs b/src/csharp/Grpc.Core/Stub/StubConfiguration.cs new file mode 100644 index 0000000000..5bcb5b40d2 --- /dev/null +++ b/src/csharp/Grpc.Core/Stub/StubConfiguration.cs @@ -0,0 +1,64 @@ +#region Copyright notice and license + +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; +using Grpc.Core.Internal; +using Grpc.Core.Utils; + +namespace Grpc.Core +{ + public delegate void HeaderInterceptorDelegate(Metadata.Builder headerBuilder); + + public class StubConfiguration + { + /// + /// The default stub configuration. + /// + public static readonly StubConfiguration Default = new StubConfiguration((headerBuilder) => { }); + + readonly HeaderInterceptorDelegate headerInterceptor; + + public StubConfiguration(HeaderInterceptorDelegate headerInterceptor) + { + this.headerInterceptor = Preconditions.CheckNotNull(headerInterceptor); + } + + public HeaderInterceptorDelegate HeaderInterceptor + { + get + { + return headerInterceptor; + } + } + } +} diff --git a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs index c86da65af4..32a523f213 100644 --- a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs +++ b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs @@ -61,7 +61,14 @@ namespace math.Tests int port = server.AddPort(host + ":0"); server.Start(); channel = new Channel(host + ":" + port); - client = MathGrpc.NewStub(channel); + + // TODO: get rid of the custom header here once we have dedicated tests + // for header support. + var stubConfig = new StubConfiguration((headerBuilder) => + { + headerBuilder.Add(new Metadata.MetadataEntry("customHeader", "abcdef")); + }); + client = MathGrpc.NewStub(channel, stubConfig); } [TestFixtureTearDown] diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs index 33a9ca9287..24e6a1de8e 100644 --- a/src/csharp/Grpc.Examples/MathGrpc.cs +++ b/src/csharp/Grpc.Examples/MathGrpc.cs @@ -45,6 +45,8 @@ namespace math /// public class MathGrpc { + static readonly string ServiceName = "/math.Math"; + static readonly Marshaller DivArgsMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), DivArgs.ParseFrom); static readonly Marshaller DivReplyMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), DivReply.ParseFrom); static readonly Marshaller NumMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), Num.ParseFrom); @@ -52,25 +54,25 @@ namespace math static readonly Method DivMethod = new Method( MethodType.Unary, - "/math.Math/Div", + "Div", DivArgsMarshaller, DivReplyMarshaller); static readonly Method FibMethod = new Method( MethodType.ServerStreaming, - "/math.Math/Fib", + "Fib", FibArgsMarshaller, NumMarshaller); static readonly Method SumMethod = new Method( MethodType.ClientStreaming, - "/math.Math/Sum", + "Sum", NumMarshaller, NumMarshaller); static readonly Method DivManyMethod = new Method( MethodType.DuplexStreaming, - "/math.Math/DivMany", + "DivMany", DivArgsMarshaller, DivReplyMarshaller); @@ -87,42 +89,43 @@ namespace math IObserver DivMany(IObserver responseObserver, CancellationToken token = default(CancellationToken)); } - public class MathServiceClientStub : IMathServiceClient + public class MathServiceClientStub : AbstractStub, IMathServiceClient { - readonly Channel channel; + public MathServiceClientStub(Channel channel) : this(channel, StubConfiguration.Default) + { + } - public MathServiceClientStub(Channel channel) + public MathServiceClientStub(Channel channel, StubConfiguration config) : base(channel, config) { - this.channel = channel; } public DivReply Div(DivArgs request, CancellationToken token = default(CancellationToken)) { - var call = new Grpc.Core.Call(DivMethod, channel); + var call = CreateCall(ServiceName, DivMethod); return Calls.BlockingUnaryCall(call, request, token); } public Task DivAsync(DivArgs request, CancellationToken token = default(CancellationToken)) { - var call = new Grpc.Core.Call(DivMethod, channel); + var call = CreateCall(ServiceName, DivMethod); return Calls.AsyncUnaryCall(call, request, token); } public void Fib(FibArgs request, IObserver responseObserver, CancellationToken token = default(CancellationToken)) { - var call = new Grpc.Core.Call(FibMethod, channel); + var call = CreateCall(ServiceName, FibMethod); Calls.AsyncServerStreamingCall(call, request, responseObserver, token); } public ClientStreamingAsyncResult Sum(CancellationToken token = default(CancellationToken)) { - var call = new Grpc.Core.Call(SumMethod, channel); + var call = CreateCall(ServiceName, SumMethod); return Calls.AsyncClientStreamingCall(call, token); } public IObserver DivMany(IObserver responseObserver, CancellationToken token = default(CancellationToken)) { - var call = new Grpc.Core.Call(DivManyMethod, channel); + var call = CreateCall(ServiceName, DivManyMethod); return Calls.DuplexStreamingCall(call, responseObserver, token); } } @@ -141,7 +144,7 @@ namespace math public static ServerServiceDefinition BindService(IMathService serviceImpl) { - return ServerServiceDefinition.CreateBuilder("/math.Math/") + return ServerServiceDefinition.CreateBuilder(ServiceName) .AddMethod(DivMethod, serviceImpl.Div) .AddMethod(FibMethod, serviceImpl.Fib) .AddMethod(SumMethod, serviceImpl.Sum) @@ -152,5 +155,10 @@ namespace math { return new MathServiceClientStub(channel); } + + public static IMathServiceClient NewStub(Channel channel, StubConfiguration config) + { + return new MathServiceClientStub(channel, config); + } } } diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj index cfb258711a..c3e5f03074 100644 --- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj +++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj @@ -39,8 +39,7 @@ ..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll - - False + ..\packages\System.Collections.Immutable.1.1.34-rc\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll diff --git a/src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs index 9b0251c3ca..f63e0361a4 100644 --- a/src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs +++ b/src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs @@ -44,6 +44,8 @@ namespace grpc.testing /// public class TestServiceGrpc { + static readonly string ServiceName = "/grpc.testing.TestService"; + static readonly Marshaller EmptyMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), Empty.ParseFrom); static readonly Marshaller SimpleRequestMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), SimpleRequest.ParseFrom); static readonly Marshaller SimpleResponseMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), SimpleResponse.ParseFrom); @@ -54,37 +56,37 @@ namespace grpc.testing static readonly Method EmptyCallMethod = new Method( MethodType.Unary, - "/grpc.testing.TestService/EmptyCall", + "EmptyCall", EmptyMarshaller, EmptyMarshaller); static readonly Method UnaryCallMethod = new Method( MethodType.Unary, - "/grpc.testing.TestService/UnaryCall", + "UnaryCall", SimpleRequestMarshaller, SimpleResponseMarshaller); static readonly Method StreamingOutputCallMethod = new Method( MethodType.ServerStreaming, - "/grpc.testing.TestService/StreamingOutputCall", + "StreamingOutputCall", StreamingOutputCallRequestMarshaller, StreamingOutputCallResponseMarshaller); static readonly Method StreamingInputCallMethod = new Method( MethodType.ClientStreaming, - "/grpc.testing.TestService/StreamingInputCall", + "StreamingInputCall", StreamingInputCallRequestMarshaller, StreamingInputCallResponseMarshaller); static readonly Method FullDuplexCallMethod = new Method( MethodType.DuplexStreaming, - "/grpc.testing.TestService/FullDuplexCall", + "FullDuplexCall", StreamingOutputCallRequestMarshaller, StreamingOutputCallResponseMarshaller); static readonly Method HalfDuplexCallMethod = new Method( MethodType.DuplexStreaming, - "/grpc.testing.TestService/HalfDuplexCall", + "HalfDuplexCall", StreamingOutputCallRequestMarshaller, StreamingOutputCallResponseMarshaller); @@ -107,60 +109,61 @@ namespace grpc.testing IObserver HalfDuplexCall(IObserver responseObserver, CancellationToken token = default(CancellationToken)); } - public class TestServiceClientStub : ITestServiceClient + public class TestServiceClientStub : AbstractStub, ITestServiceClient { - readonly Channel channel; + public TestServiceClientStub(Channel channel) : base(channel, StubConfiguration.Default) + { + } - public TestServiceClientStub(Channel channel) + public TestServiceClientStub(Channel channel, StubConfiguration config) : base(channel, config) { - this.channel = channel; } public Empty EmptyCall(Empty request, CancellationToken token = default(CancellationToken)) { - var call = new Grpc.Core.Call(EmptyCallMethod, channel); + var call = CreateCall(ServiceName, EmptyCallMethod); return Calls.BlockingUnaryCall(call, request, token); } public Task EmptyCallAsync(Empty request, CancellationToken token = default(CancellationToken)) { - var call = new Grpc.Core.Call(EmptyCallMethod, channel); + var call = CreateCall(ServiceName, EmptyCallMethod); return Calls.AsyncUnaryCall(call, request, token); } public SimpleResponse UnaryCall(SimpleRequest request, CancellationToken token = default(CancellationToken)) { - var call = new Grpc.Core.Call(UnaryCallMethod, channel); + var call = CreateCall(ServiceName, UnaryCallMethod); return Calls.BlockingUnaryCall(call, request, token); } public Task UnaryCallAsync(SimpleRequest request, CancellationToken token = default(CancellationToken)) { - var call = new Grpc.Core.Call(UnaryCallMethod, channel); + var call = CreateCall(ServiceName, UnaryCallMethod); return Calls.AsyncUnaryCall(call, request, token); } public void StreamingOutputCall(StreamingOutputCallRequest request, IObserver responseObserver, CancellationToken token = default(CancellationToken)) { - var call = new Grpc.Core.Call(StreamingOutputCallMethod, channel); + var call = CreateCall(ServiceName, StreamingOutputCallMethod); Calls.AsyncServerStreamingCall(call, request, responseObserver, token); } public ClientStreamingAsyncResult StreamingInputCall(CancellationToken token = default(CancellationToken)) { - var call = new Grpc.Core.Call(StreamingInputCallMethod, channel); + var call = CreateCall(ServiceName, StreamingInputCallMethod); return Calls.AsyncClientStreamingCall(call, token); } public IObserver FullDuplexCall(IObserver responseObserver, CancellationToken token = default(CancellationToken)) { - var call = new Grpc.Core.Call(FullDuplexCallMethod, channel); + var call = CreateCall(ServiceName, FullDuplexCallMethod); return Calls.DuplexStreamingCall(call, responseObserver, token); } public IObserver HalfDuplexCall(IObserver responseObserver, CancellationToken token = default(CancellationToken)) { - var call = new Grpc.Core.Call(HalfDuplexCallMethod, channel); + var call = CreateCall(ServiceName, HalfDuplexCallMethod); return Calls.DuplexStreamingCall(call, responseObserver, token); } } @@ -183,7 +186,7 @@ namespace grpc.testing public static ServerServiceDefinition BindService(ITestService serviceImpl) { - return ServerServiceDefinition.CreateBuilder("/grpc.testing.TestService/") + return ServerServiceDefinition.CreateBuilder(ServiceName) .AddMethod(EmptyCallMethod, serviceImpl.EmptyCall) .AddMethod(UnaryCallMethod, serviceImpl.UnaryCall) .AddMethod(StreamingOutputCallMethod, serviceImpl.StreamingOutputCall) diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index 51abb632f7..9a1c908d11 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -102,34 +102,114 @@ grpcsharp_batch_context *grpcsharp_batch_context_create() { return ctx; } -/** - * Destroys metadata array including keys and values. +/* + * Destroys array->metadata. + * The array pointer itself is not freed. + */ +void grpcsharp_metadata_array_destroy_metadata_only( + grpc_metadata_array *array) { + gpr_free(array->metadata); +} + +/* + * Destroys keys, values and array->metadata. + * The array pointer itself is not freed. + */ +void grpcsharp_metadata_array_destroy_metadata_including_entries( + grpc_metadata_array *array) { + size_t i; + if (array->metadata) { + for (i = 0; i < array->count; i++) { + gpr_free((void *)array->metadata[i].key); + gpr_free((void *)array->metadata[i].value); + } + } + gpr_free(array->metadata); +} + +/* + * Fully destroys the metadata array. + */ +GPR_EXPORT void GPR_CALLTYPE +grpcsharp_metadata_array_destroy_full(grpc_metadata_array *array) { + if (!array) { + return; + } + grpcsharp_metadata_array_destroy_metadata_including_entries(array); + gpr_free(array); +} + +/* + * Creates an empty metadata array with given capacity. + * Array can later be destroyed by grpc_metadata_array_destroy_full. */ -void grpcsharp_metadata_array_destroy_recursive(grpc_metadata_array *array) { - if (!array->metadata) { +GPR_EXPORT grpc_metadata_array *GPR_CALLTYPE +grpcsharp_metadata_array_create(size_t capacity) { + grpc_metadata_array *array = + (grpc_metadata_array *)gpr_malloc(sizeof(grpc_metadata_array)); + grpc_metadata_array_init(array); + array->capacity = capacity; + array->count = 0; + if (capacity > 0) { + array->metadata = + (grpc_metadata *)gpr_malloc(sizeof(grpc_metadata) * capacity); + memset(array->metadata, 0, sizeof(grpc_metadata) * capacity); + } else { + array->metadata = NULL; + } + return array; +} + +GPR_EXPORT void GPR_CALLTYPE +grpcsharp_metadata_array_add(grpc_metadata_array *array, const char *key, + const char *value, size_t value_length) { + size_t i = array->count; + GPR_ASSERT(array->count < array->capacity); + array->metadata[i].key = gpr_strdup(key); + array->metadata[i].value = (char *)gpr_malloc(value_length); + memcpy((void *)array->metadata[i].value, value, value_length); + array->metadata[i].value_length = value_length; + array->count++; +} + +/* Move contents of metadata array */ +void grpcsharp_metadata_array_move(grpc_metadata_array *dest, + grpc_metadata_array *src) { + if (!src) { + dest->capacity = 0; + dest->count = 0; + dest->metadata = NULL; return; } - /* TODO: destroy also keys and values */ - grpc_metadata_array_destroy(array); + + dest->capacity = src->capacity; + dest->count = src->count; + dest->metadata = src->metadata; + + src->capacity = 0; + src->count = 0; + src->metadata = NULL; } void grpcsharp_batch_context_destroy(grpcsharp_batch_context *ctx) { if (!ctx) { return; } - grpcsharp_metadata_array_destroy_recursive(&(ctx->send_initial_metadata)); + grpcsharp_metadata_array_destroy_metadata_including_entries( + &(ctx->send_initial_metadata)); grpc_byte_buffer_destroy(ctx->send_message); - grpcsharp_metadata_array_destroy_recursive( + grpcsharp_metadata_array_destroy_metadata_including_entries( &(ctx->send_status_from_server.trailing_metadata)); gpr_free(ctx->send_status_from_server.status_details); - grpc_metadata_array_destroy(&(ctx->recv_initial_metadata)); + grpcsharp_metadata_array_destroy_metadata_only(&(ctx->recv_initial_metadata)); grpc_byte_buffer_destroy(ctx->recv_message); - grpc_metadata_array_destroy(&(ctx->recv_status_on_client.trailing_metadata)); + grpcsharp_metadata_array_destroy_metadata_only( + &(ctx->recv_status_on_client.trailing_metadata)); gpr_free((void *)ctx->recv_status_on_client.status_details); /* NOTE: ctx->server_rpc_new.call is not destroyed because callback handler is @@ -137,7 +217,8 @@ void grpcsharp_batch_context_destroy(grpcsharp_batch_context *ctx) { to take its ownership. */ grpc_call_details_destroy(&(ctx->server_rpc_new.call_details)); - grpc_metadata_array_destroy(&(ctx->server_rpc_new.request_metadata)); + grpcsharp_metadata_array_destroy_metadata_only( + &(ctx->server_rpc_new.request_metadata)); gpr_free(ctx); } @@ -346,17 +427,19 @@ grpcsharp_call_start_write_from_copied_buffer(grpc_call *call, GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_unary(grpc_call *call, callback_funcptr callback, - const char *send_buffer, size_t send_buffer_len) { + const char *send_buffer, size_t send_buffer_len, + grpc_metadata_array *initial_metadata) { /* TODO: don't use magic number */ grpc_op ops[6]; grpcsharp_batch_context *ctx = grpcsharp_batch_context_create(); ctx->callback = callback; - /* TODO: implement sending the metadata... */ ops[0].op = GRPC_OP_SEND_INITIAL_METADATA; - /* ctx->send_initial_metadata is already zeroed out. */ - ops[0].data.send_initial_metadata.count = 0; - ops[0].data.send_initial_metadata.metadata = NULL; + grpcsharp_metadata_array_move(&(ctx->send_initial_metadata), + initial_metadata); + ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count; + ops[0].data.send_initial_metadata.metadata = + ctx->send_initial_metadata.metadata; ops[1].op = GRPC_OP_SEND_MESSAGE; ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len); @@ -389,9 +472,11 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_call_blocking_unary(grpc_call *call, grpc_completion_queue *dedicated_cq, callback_funcptr callback, - const char *send_buffer, size_t send_buffer_len) { + const char *send_buffer, size_t send_buffer_len, + grpc_metadata_array *initial_metadata) { GPR_ASSERT(grpcsharp_call_start_unary(call, callback, send_buffer, - send_buffer_len) == GRPC_CALL_OK); + send_buffer_len, + initial_metadata) == GRPC_CALL_OK); /* TODO: we would like to use pluck, but we don't know the tag */ GPR_ASSERT(grpcsharp_completion_queue_next_with_callback(dedicated_cq) == @@ -403,17 +488,19 @@ grpcsharp_call_blocking_unary(grpc_call *call, GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_client_streaming(grpc_call *call, - callback_funcptr callback) { + callback_funcptr callback, + grpc_metadata_array *initial_metadata) { /* TODO: don't use magic number */ grpc_op ops[4]; grpcsharp_batch_context *ctx = grpcsharp_batch_context_create(); ctx->callback = callback; - /* TODO: implement sending the metadata... */ ops[0].op = GRPC_OP_SEND_INITIAL_METADATA; - /* ctx->send_initial_metadata is already zeroed out. */ - ops[0].data.send_initial_metadata.count = 0; - ops[0].data.send_initial_metadata.metadata = NULL; + grpcsharp_metadata_array_move(&(ctx->send_initial_metadata), + initial_metadata); + ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count; + ops[0].data.send_initial_metadata.metadata = + ctx->send_initial_metadata.metadata; ops[1].op = GRPC_OP_RECV_INITIAL_METADATA; ops[1].data.recv_initial_metadata = &(ctx->recv_initial_metadata); @@ -435,21 +522,20 @@ grpcsharp_call_start_client_streaming(grpc_call *call, return grpc_call_start_batch(call, ops, sizeof(ops) / sizeof(ops[0]), ctx); } -GPR_EXPORT grpc_call_error GPR_CALLTYPE -grpcsharp_call_start_server_streaming(grpc_call *call, - callback_funcptr callback, - const char *send_buffer, - size_t send_buffer_len) { +GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_server_streaming( + grpc_call *call, callback_funcptr callback, const char *send_buffer, + size_t send_buffer_len, grpc_metadata_array *initial_metadata) { /* TODO: don't use magic number */ grpc_op ops[5]; grpcsharp_batch_context *ctx = grpcsharp_batch_context_create(); ctx->callback = callback; - /* TODO: implement sending the metadata... */ ops[0].op = GRPC_OP_SEND_INITIAL_METADATA; - /* ctx->send_initial_metadata is already zeroed out. */ - ops[0].data.send_initial_metadata.count = 0; - ops[0].data.send_initial_metadata.metadata = NULL; + grpcsharp_metadata_array_move(&(ctx->send_initial_metadata), + initial_metadata); + ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count; + ops[0].data.send_initial_metadata.metadata = + ctx->send_initial_metadata.metadata; ops[1].op = GRPC_OP_SEND_MESSAGE; ctx->send_message = string_to_byte_buffer(send_buffer, send_buffer_len); @@ -476,17 +562,19 @@ grpcsharp_call_start_server_streaming(grpc_call *call, GPR_EXPORT grpc_call_error GPR_CALLTYPE grpcsharp_call_start_duplex_streaming(grpc_call *call, - callback_funcptr callback) { + callback_funcptr callback, + grpc_metadata_array *initial_metadata) { /* TODO: don't use magic number */ grpc_op ops[3]; grpcsharp_batch_context *ctx = grpcsharp_batch_context_create(); ctx->callback = callback; - /* TODO: implement sending the metadata... */ ops[0].op = GRPC_OP_SEND_INITIAL_METADATA; - /* ctx->send_initial_metadata is already zeroed out. */ - ops[0].data.send_initial_metadata.count = 0; - ops[0].data.send_initial_metadata.metadata = NULL; + grpcsharp_metadata_array_move(&(ctx->send_initial_metadata), + initial_metadata); + ops[0].data.send_initial_metadata.count = ctx->send_initial_metadata.count; + ops[0].data.send_initial_metadata.metadata = + ctx->send_initial_metadata.metadata; ops[1].op = GRPC_OP_RECV_INITIAL_METADATA; ops[1].data.recv_initial_metadata = &(ctx->recv_initial_metadata); -- cgit v1.2.3 From cfd6073a66fda3db150998ef40dbbc76c198c02e Mon Sep 17 00:00:00 2001 From: Nicolas Noble Date: Wed, 18 Mar 2015 16:27:43 -0700 Subject: Various Windows fixes. -) using dupenv_s instead of getenv_s and calling strdup ourselves. -) few impossible-to-obtain if checks. -) various signed/unsigned casting. -) using time_t instead of time32_t -) checking output of FormatMessage for failures. -) don't redefine _WIN32_WINNT without undefining it first. -) fixed msvc's interlocked casting. -) renamed AddPort to AddListeningPort. -) added protobuf's third_party includes to search path. -) added a missing definition for inet_ntop in mingw32. -) removed useless declarations. --- examples/pubsub/publisher_test.cc | 2 +- examples/pubsub/subscriber_test.cc | 2 +- include/grpc++/server.h | 2 +- include/grpc++/server_builder.h | 6 ++--- include/grpc/support/atm_win32.h | 26 +++++++++++++++------- src/core/iomgr/sockaddr_win32.h | 5 +++++ src/core/iomgr/tcp_server_windows.c | 3 --- src/core/iomgr/tcp_windows.c | 4 ++-- src/core/support/env_win32.c | 15 ++++++++----- src/core/support/file_win32.c | 2 +- src/core/support/log_win32.c | 8 ++++--- src/core/support/string_win32.c | 6 +++-- src/core/support/sync_win32.c | 1 + src/core/support/time_win32.c | 4 ++-- src/cpp/common/call.cc | 9 +++++--- src/cpp/server/server.cc | 3 ++- src/cpp/server/server_builder.cc | 8 +++---- src/csharp/Grpc.Core.Tests/ClientServerTest.cs | 6 ++--- src/csharp/Grpc.Core.Tests/ServerTest.cs | 2 +- src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs | 4 ++-- src/csharp/Grpc.Core/Server.cs | 8 +++---- .../Grpc.Examples.Tests/MathClientServerTests.cs | 2 +- .../InteropClientServerTest.cs | 2 +- .../Grpc.IntegrationTesting/InteropServer.cs | 4 ++-- test/cpp/end2end/async_end2end_test.cc | 2 +- test/cpp/end2end/end2end_test.cc | 2 +- test/cpp/end2end/generic_end2end_test.cc | 2 +- test/cpp/interop/server.cc | 2 +- test/cpp/qps/server.cc | 2 +- test/cpp/qps/server_async.cc | 2 +- test/cpp/qps/server_sync.cc | 2 +- test/cpp/qps/worker.cc | 2 +- vsprojects/vs2013/global.props | 2 +- 33 files changed, 88 insertions(+), 64 deletions(-) (limited to 'src/csharp') diff --git a/examples/pubsub/publisher_test.cc b/examples/pubsub/publisher_test.cc index f9b6bb3418..62442c7384 100644 --- a/examples/pubsub/publisher_test.cc +++ b/examples/pubsub/publisher_test.cc @@ -107,7 +107,7 @@ class PublisherTest : public ::testing::Test { int port = grpc_pick_unused_port_or_die(); server_address_ << "localhost:" << port; ServerBuilder builder; - builder.AddPort(server_address_.str(), grpc::InsecureServerCredentials()); + builder.AddListeningPort(server_address_.str(), grpc::InsecureServerCredentials()); builder.RegisterService(&service_); server_ = builder.BuildAndStart(); diff --git a/examples/pubsub/subscriber_test.cc b/examples/pubsub/subscriber_test.cc index 2d606336ad..b8dd1f9486 100644 --- a/examples/pubsub/subscriber_test.cc +++ b/examples/pubsub/subscriber_test.cc @@ -105,7 +105,7 @@ class SubscriberTest : public ::testing::Test { int port = grpc_pick_unused_port_or_die(); server_address_ << "localhost:" << port; ServerBuilder builder; - builder.AddPort(server_address_.str(), grpc::InsecureServerCredentials()); + builder.AddListeningPort(server_address_.str(), grpc::InsecureServerCredentials()); builder.RegisterService(&service_); server_ = builder.BuildAndStart(); diff --git a/include/grpc++/server.h b/include/grpc++/server.h index 8cd0a4f668..bddb4f62aa 100644 --- a/include/grpc++/server.h +++ b/include/grpc++/server.h @@ -86,7 +86,7 @@ class Server GRPC_FINAL : private CallHook, bool RegisterAsyncService(AsynchronousService* service); void RegisterAsyncGenericService(AsyncGenericService* service); // Add a listening port. Can be called multiple times. - int AddPort(const grpc::string& addr, ServerCredentials* creds); + int AddListeningPort(const grpc::string& addr, ServerCredentials* creds); // Start the server. bool Start(); diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h index c09c8fee52..9a9932ebe0 100644 --- a/include/grpc++/server_builder.h +++ b/include/grpc++/server_builder.h @@ -69,9 +69,9 @@ class ServerBuilder { void RegisterAsyncGenericService(AsyncGenericService* service); // Add a listening port. Can be called multiple times. - void AddPort(const grpc::string& addr, - std::shared_ptr creds, - int* selected_port = nullptr); + void AddListeningPort(const grpc::string& addr, + std::shared_ptr creds, + int* selected_port = nullptr); // Set the thread pool used for running appliation rpc handlers. // Does not take ownership. diff --git a/include/grpc/support/atm_win32.h b/include/grpc/support/atm_win32.h index 8b5322488e..4a21b5b547 100644 --- a/include/grpc/support/atm_win32.h +++ b/include/grpc/support/atm_win32.h @@ -63,25 +63,31 @@ static __inline int gpr_atm_no_barrier_cas(gpr_atm *p, gpr_atm o, gpr_atm n) { /* InterlockedCompareExchangePointerNoFence() not available on vista or windows7 */ #ifdef GPR_ARCH_64 - return o == (gpr_atm)InterlockedCompareExchangeAcquire64(p, n, o); + return o == (gpr_atm)InterlockedCompareExchangeAcquire64((volatile LONGLONG *) p, + (LONGLONG) n, (LONGLONG) o); #else - return o == (gpr_atm)InterlockedCompareExchangeAcquire(p, n, o); + return o == (gpr_atm)InterlockedCompareExchangeAcquire((volatile LONG *) p, + (LONG) n, (LONG) o); #endif } static __inline int gpr_atm_acq_cas(gpr_atm *p, gpr_atm o, gpr_atm n) { #ifdef GPR_ARCH_64 - return o == (gpr_atm)InterlockedCompareExchangeAcquire64(p, n, o); + return o == (gpr_atm)InterlockedCompareExchangeAcquire64((volatile LONGLONG) p, + (LONGLONG) n, (LONGLONG) o); #else - return o == (gpr_atm)InterlockedCompareExchangeAcquire(p, n, o); + return o == (gpr_atm)InterlockedCompareExchangeAcquire((volatile LONG *) p, + (LONG) n, (LONG) o); #endif } static __inline int gpr_atm_rel_cas(gpr_atm *p, gpr_atm o, gpr_atm n) { #ifdef GPR_ARCH_64 - return o == (gpr_atm)InterlockedCompareExchangeRelease64(p, n, o); + return o == (gpr_atm)InterlockedCompareExchangeRelease64((volatile LONGLONG *) p, + (LONGLONG) n, (LONGLONG) o); #else - return o == (gpr_atm)InterlockedCompareExchangeRelease(p, n, o); + return o == (gpr_atm)InterlockedCompareExchangeRelease((volatile LONG *) p, + (LONG) n, (LONG) o); #endif } @@ -101,11 +107,15 @@ static __inline gpr_atm gpr_atm_full_fetch_add(gpr_atm *p, gpr_atm delta) { #ifdef GPR_ARCH_64 do { old = *p; - } while (old != (gpr_atm)InterlockedCompareExchange64(p, old + delta, old)); + } while (old != (gpr_atm)InterlockedCompareExchange64((volatile LONGLONG *) p, + (LONGLONG) old + delta, + (LONGLONG) old)); #else do { old = *p; - } while (old != (gpr_atm)InterlockedCompareExchange(p, old + delta, old)); + } while (old != (gpr_atm)InterlockedCompareExchange((volatile LONG *) p, + (LONG) old + delta, + (LONG) old)); #endif return old; } diff --git a/src/core/iomgr/sockaddr_win32.h b/src/core/iomgr/sockaddr_win32.h index 3a5f27bb34..c0385ea614 100644 --- a/src/core/iomgr/sockaddr_win32.h +++ b/src/core/iomgr/sockaddr_win32.h @@ -38,4 +38,9 @@ #include #include +#ifdef __MINGW32__ +/* mingw seems to be missing that definition. */ +const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); +#endif + #endif /* GRPC_INTERNAL_CORE_IOMGR_SOCKADDR_WIN32_H */ diff --git a/src/core/iomgr/tcp_server_windows.c b/src/core/iomgr/tcp_server_windows.c index 59319da26d..0c3ab1dc91 100644 --- a/src/core/iomgr/tcp_server_windows.c +++ b/src/core/iomgr/tcp_server_windows.c @@ -53,9 +53,6 @@ #define INIT_PORT_CAP 2 #define MIN_SAFE_ACCEPT_QUEUE_SIZE 100 -static gpr_once s_init_max_accept_queue_size; -static int s_max_accept_queue_size; - /* one listening port */ typedef struct server_port { gpr_uint8 addresses[sizeof(struct sockaddr_in6) * 2 + 32]; diff --git a/src/core/iomgr/tcp_windows.c b/src/core/iomgr/tcp_windows.c index 3efd69a71b..ec5496e7ee 100644 --- a/src/core/iomgr/tcp_windows.c +++ b/src/core/iomgr/tcp_windows.c @@ -172,7 +172,7 @@ static void win_notify_on_read(grpc_endpoint *ep, tcp->read_slice = gpr_slice_malloc(8192); buffer.len = GPR_SLICE_LENGTH(tcp->read_slice); - buffer.buf = GPR_SLICE_START_PTR(tcp->read_slice); + buffer.buf = (char *)GPR_SLICE_START_PTR(tcp->read_slice); gpr_log(GPR_DEBUG, "win_notify_on_read: calling WSARecv without overlap"); status = WSARecv(tcp->socket->socket, &buffer, 1, &bytes_read, &flags, @@ -284,7 +284,7 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep, for (i = 0; i < tcp->write_slices.count; i++) { buffers[i].len = GPR_SLICE_LENGTH(tcp->write_slices.slices[i]); - buffers[i].buf = GPR_SLICE_START_PTR(tcp->write_slices.slices[i]); + buffers[i].buf = (char *)GPR_SLICE_START_PTR(tcp->write_slices.slices[i]); } gpr_log(GPR_DEBUG, "win_write: calling WSASend without overlap"); diff --git a/src/core/support/env_win32.c b/src/core/support/env_win32.c index 177cc36a30..9b4cd698ad 100644 --- a/src/core/support/env_win32.c +++ b/src/core/support/env_win32.c @@ -36,6 +36,7 @@ #ifdef GPR_WIN32 #include "src/core/support/env.h" +#include "src/core/support/string.h" #include @@ -43,14 +44,16 @@ #include char *gpr_getenv(const char *name) { - size_t required_size; + size_t size; char *result = NULL; + char *duplicated; + errno_t err; - getenv_s(&required_size, NULL, 0, name); - if (required_size == 0) return NULL; - result = gpr_malloc(required_size); - getenv_s(&required_size, result, required_size, name); - return result; + err = _dupenv_s(&result, &size, name); + if (err) return NULL; + duplicated = gpr_strdup(result); + free(result); + return duplicated; } void gpr_setenv(const char *name, const char *value) { diff --git a/src/core/support/file_win32.c b/src/core/support/file_win32.c index fe209af9b2..f59d3af397 100644 --- a/src/core/support/file_win32.c +++ b/src/core/support/file_win32.c @@ -72,7 +72,7 @@ FILE *gpr_tmpfile(const char *prefix, char **tmp_filename_out) { if (_tfopen_s(&result, tmp_filename, TEXT("wb+")) != 0) goto end; end: - if (result && tmp_filename) { + if (result && tmp_filename_out) { *tmp_filename_out = gpr_tchar_to_char(tmp_filename); } diff --git a/src/core/support/log_win32.c b/src/core/support/log_win32.c index 720dc141f5..159c7e052c 100644 --- a/src/core/support/log_win32.c +++ b/src/core/support/log_win32.c @@ -43,6 +43,7 @@ #include #include +#include "src/core/support/string.h" #include "src/core/support/string_win32.h" void gpr_log(const char *file, int line, gpr_log_severity severity, @@ -55,7 +56,7 @@ void gpr_log(const char *file, int line, gpr_log_severity severity, va_start(args, format); ret = _vscprintf(format, args); va_end(args); - if (!(0 <= ret && ret < ~(size_t)0)) { + if (ret < 0) { message = NULL; } else { /* Allocate a new buffer, with space for the NUL terminator. */ @@ -66,7 +67,7 @@ void gpr_log(const char *file, int line, gpr_log_severity severity, va_start(args, format); ret = vsnprintf_s(message, strp_buflen, _TRUNCATE, format, args); va_end(args); - if (ret != strp_buflen - 1) { + if ((size_t)ret != strp_buflen - 1) { /* This should never happen. */ gpr_free(message); message = NULL; @@ -90,7 +91,7 @@ void gpr_default_log(gpr_log_func_args *args) { strcpy(time_buffer, "error:strftime"); } - fprintf(stderr, "%s%s.%09u %5u %s:%d] %s\n", + fprintf(stderr, "%s%s.%09u %5lu %s:%d] %s\n", gpr_log_severity_string(args->severity), time_buffer, (int)(now.tv_nsec), GetCurrentThreadId(), args->file, args->line, args->message); @@ -105,6 +106,7 @@ char *gpr_format_message(DWORD messageid) { NULL, messageid, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)(&tmessage), 0, NULL); + if (status == 0) return gpr_strdup("Unable to retreive error string"); message = gpr_tchar_to_char(tmessage); LocalFree(tmessage); return message; diff --git a/src/core/support/string_win32.c b/src/core/support/string_win32.c index 583abd27d8..6d1d6337a9 100644 --- a/src/core/support/string_win32.c +++ b/src/core/support/string_win32.c @@ -44,6 +44,8 @@ #include +#include "src/core/support/string.h" + int gpr_asprintf(char **strp, const char *format, ...) { va_list args; int ret; @@ -53,7 +55,7 @@ int gpr_asprintf(char **strp, const char *format, ...) { va_start(args, format); ret = _vscprintf(format, args); va_end(args); - if (!(0 <= ret && ret < ~(size_t)0)) { + if (ret < 0) { *strp = NULL; return -1; } @@ -69,7 +71,7 @@ int gpr_asprintf(char **strp, const char *format, ...) { va_start(args, format); ret = vsnprintf_s(*strp, strp_buflen, _TRUNCATE, format, args); va_end(args); - if (ret == strp_buflen - 1) { + if ((size_t)ret == strp_buflen - 1) { return ret; } diff --git a/src/core/support/sync_win32.c b/src/core/support/sync_win32.c index c9a977cc80..cc31d9b052 100644 --- a/src/core/support/sync_win32.c +++ b/src/core/support/sync_win32.c @@ -37,6 +37,7 @@ #ifdef GPR_WIN32 +#undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 #include #include diff --git a/src/core/support/time_win32.c b/src/core/support/time_win32.c index 8256849655..f221cb5790 100644 --- a/src/core/support/time_win32.c +++ b/src/core/support/time_win32.c @@ -42,8 +42,8 @@ gpr_timespec gpr_now(void) { gpr_timespec now_tv; - struct __timeb32 now_tb; - _ftime32_s(&now_tb); + struct _timeb now_tb; + _ftime_s(&now_tb); now_tv.tv_sec = now_tb.time; now_tv.tv_nsec = now_tb.millitm * 1000000; return now_tv; diff --git a/src/cpp/common/call.cc b/src/cpp/common/call.cc index ebe7deec70..5c26a1ad7c 100644 --- a/src/cpp/common/call.cc +++ b/src/cpp/common/call.cc @@ -48,7 +48,6 @@ CallOpBuffer::CallOpBuffer() initial_metadata_count_(0), initial_metadata_(nullptr), recv_initial_metadata_(nullptr), - recv_initial_metadata_arr_{0, 0, nullptr}, send_message_(nullptr), send_message_buffer_(nullptr), send_buf_(nullptr), @@ -58,7 +57,6 @@ CallOpBuffer::CallOpBuffer() client_send_close_(false), recv_trailing_metadata_(nullptr), recv_status_(nullptr), - recv_trailing_metadata_arr_{0, 0, nullptr}, status_code_(GRPC_STATUS_OK), status_details_(nullptr), status_details_capacity_(0), @@ -66,7 +64,12 @@ CallOpBuffer::CallOpBuffer() trailing_metadata_count_(0), trailing_metadata_(nullptr), cancelled_buf_(0), - recv_closed_(nullptr) {} + recv_closed_(nullptr) { + memset(&recv_trailing_metadata_arr_, 0, sizeof(recv_trailing_metadata_arr_)); + memset(&recv_initial_metadata_arr_, 0, sizeof(recv_initial_metadata_arr_)); + recv_trailing_metadata_arr_.metadata = nullptr; + recv_initial_metadata_arr_.metadata = nullptr; +} void CallOpBuffer::Reset(void* next_return_tag) { return_tag_ = next_return_tag; diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc index 4d5e77e633..09a541c5a5 100644 --- a/src/cpp/server/server.cc +++ b/src/cpp/server/server.cc @@ -234,7 +234,8 @@ void Server::RegisterAsyncGenericService(AsyncGenericService* service) { service->server_ = this; } -int Server::AddPort(const grpc::string& addr, ServerCredentials* creds) { +int Server::AddListeningPort(const grpc::string& addr, + ServerCredentials* creds) { GPR_ASSERT(!started_); return creds->AddPortToServer(addr, server_); } diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index 835596d393..960734756e 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -62,9 +62,9 @@ void ServerBuilder::RegisterAsyncGenericService(AsyncGenericService* service) { generic_service_ = service; } -void ServerBuilder::AddPort(const grpc::string& addr, - std::shared_ptr creds, - int* selected_port) { +void ServerBuilder::AddListeningPort(const grpc::string& addr, + std::shared_ptr creds, + int* selected_port) { ports_.push_back(Port{addr, creds, selected_port}); } @@ -99,7 +99,7 @@ std::unique_ptr ServerBuilder::BuildAndStart() { server->RegisterAsyncGenericService(generic_service_); } for (auto& port : ports_) { - int r = server->AddPort(port.addr, port.creds.get()); + int r = server->AddListeningPort(port.addr, port.creds.get()); if (!r) return nullptr; if (port.selected_port != nullptr) { *port.selected_port = r; diff --git a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs index 807f5a6ded..3da9e33e53 100644 --- a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs +++ b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs @@ -74,7 +74,7 @@ namespace Grpc.Core.Tests ServerServiceDefinition.CreateBuilder(serviceName) .AddMethod(unaryEchoStringMethod, HandleUnaryEchoString).Build()); - int port = server.AddPort(host + ":0"); + int port = server.AddListeningPort(host + ":0"); server.Start(); using (Channel channel = new Channel(host + ":" + port)) @@ -97,7 +97,7 @@ namespace Grpc.Core.Tests ServerServiceDefinition.CreateBuilder(serviceName) .AddMethod(unaryEchoStringMethod, HandleUnaryEchoString).Build()); - int port = server.AddPort(host + ":0"); + int port = server.AddListeningPort(host + ":0"); server.Start(); using (Channel channel = new Channel(host + ":" + port)) @@ -117,7 +117,7 @@ namespace Grpc.Core.Tests server.AddServiceDefinition( ServerServiceDefinition.CreateBuilder(serviceName).Build()); - int port = server.AddPort(host + ":0"); + int port = server.AddListeningPort(host + ":0"); server.Start(); using (Channel channel = new Channel(host + ":" + port)) diff --git a/src/csharp/Grpc.Core.Tests/ServerTest.cs b/src/csharp/Grpc.Core.Tests/ServerTest.cs index 12f914bfad..2a1855da67 100644 --- a/src/csharp/Grpc.Core.Tests/ServerTest.cs +++ b/src/csharp/Grpc.Core.Tests/ServerTest.cs @@ -47,7 +47,7 @@ namespace Grpc.Core.Tests GrpcEnvironment.Initialize(); Server server = new Server(); - server.AddPort("localhost:0"); + server.AddListeningPort("localhost:0"); server.Start(); server.ShutdownAsync().Wait(); diff --git a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs index dc4781e796..a59da09822 100644 --- a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs @@ -80,12 +80,12 @@ namespace Grpc.Core.Internal return grpcsharp_server_create(cq, args); } - public int AddPort(string addr) + public int AddListeningPort(string addr) { return grpcsharp_server_add_http2_port(this, addr); } - public int AddPort(string addr, ServerCredentialsSafeHandle credentials) + public int AddListeningPort(string addr, ServerCredentialsSafeHandle credentials) { return grpcsharp_server_add_secure_http2_port(this, addr, credentials); } diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs index 2439cdb6dc..f086fa8beb 100644 --- a/src/csharp/Grpc.Core/Server.cs +++ b/src/csharp/Grpc.Core/Server.cs @@ -76,17 +76,17 @@ namespace Grpc.Core } // only call before Start() - public int AddPort(string addr) + public int AddListeningPort(string addr) { - return handle.AddPort(addr); + return handle.AddListeningPort(addr); } // only call before Start() - public int AddPort(string addr, ServerCredentials credentials) + public int AddListeningPort(string addr, ServerCredentials credentials) { using (var nativeCredentials = credentials.ToNativeCredentials()) { - return handle.AddPort(addr, nativeCredentials); + return handle.AddListeningPort(addr, nativeCredentials); } } diff --git a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs index 32a523f213..85f213cb39 100644 --- a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs +++ b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs @@ -58,7 +58,7 @@ namespace math.Tests server = new Server(); server.AddServiceDefinition(MathGrpc.BindService(new MathServiceImpl())); - int port = server.AddPort(host + ":0"); + int port = server.AddListeningPort(host + ":0"); server.Start(); channel = new Channel(host + ":" + port); diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs index 814f6311f2..1e76d3df21 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs @@ -59,7 +59,7 @@ namespace Grpc.IntegrationTesting server = new Server(); server.AddServiceDefinition(TestServiceGrpc.BindService(new TestServiceImpl())); - int port = server.AddPort(host + ":0", TestCredentials.CreateTestServerCredentials()); + int port = server.AddListeningPort(host + ":0", TestCredentials.CreateTestServerCredentials()); server.Start(); var channelArgs = ChannelArgs.CreateBuilder() diff --git a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs index 5e580280b6..ad5200774f 100644 --- a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs +++ b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs @@ -96,11 +96,11 @@ namespace Grpc.IntegrationTesting string addr = "0.0.0.0:" + options.port; if (options.useTls) { - server.AddPort(addr, TestCredentials.CreateTestServerCredentials()); + server.AddListeningPort(addr, TestCredentials.CreateTestServerCredentials()); } else { - server.AddPort(addr); + server.AddListeningPort(addr); } Console.WriteLine("Running server on " + addr); server.Start(); diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc index e011b788ff..c6b53c60a5 100644 --- a/test/cpp/end2end/async_end2end_test.cc +++ b/test/cpp/end2end/async_end2end_test.cc @@ -99,7 +99,7 @@ class AsyncEnd2endTest : public ::testing::Test { server_address_ << "localhost:" << port; // Setup server ServerBuilder builder; - builder.AddPort(server_address_.str(), grpc::InsecureServerCredentials()); + builder.AddListeningPort(server_address_.str(), grpc::InsecureServerCredentials()); builder.RegisterAsyncService(&service_); server_ = builder.BuildAndStart(); } diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index c586849349..41c2669533 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -151,7 +151,7 @@ class End2endTest : public ::testing::Test { server_address_ << "localhost:" << port; // Setup server ServerBuilder builder; - builder.AddPort(server_address_.str(), InsecureServerCredentials()); + builder.AddListeningPort(server_address_.str(), InsecureServerCredentials()); builder.RegisterService(&service_); builder.RegisterService(&dup_pkg_service_); builder.SetThreadPool(&thread_pool_); diff --git a/test/cpp/end2end/generic_end2end_test.cc b/test/cpp/end2end/generic_end2end_test.cc index 4a0d2c5c01..5377d05a4e 100644 --- a/test/cpp/end2end/generic_end2end_test.cc +++ b/test/cpp/end2end/generic_end2end_test.cc @@ -98,7 +98,7 @@ class GenericEnd2endTest : public ::testing::Test { server_address_ << "localhost:" << port; // Setup server ServerBuilder builder; - builder.AddPort(server_address_.str(), InsecureServerCredentials()); + builder.AddListeningPort(server_address_.str(), InsecureServerCredentials()); builder.RegisterAsyncGenericService(&generic_service_); server_ = builder.BuildAndStart(); } diff --git a/test/cpp/interop/server.cc b/test/cpp/interop/server.cc index 743482e967..eceb600d4c 100644 --- a/test/cpp/interop/server.cc +++ b/test/cpp/interop/server.cc @@ -217,7 +217,7 @@ void RunServer() { "", {{test_server1_key, test_server1_cert}}}; creds = grpc::SslServerCredentials(ssl_opts); } - builder.AddPort(server_address.str(), creds); + builder.AddListeningPort(server_address.str(), creds); std::unique_ptr server(builder.BuildAndStart()); gpr_log(GPR_INFO, "Server listening on %s", server_address.str().c_str()); while (!got_sigint) { diff --git a/test/cpp/qps/server.cc b/test/cpp/qps/server.cc index 005f0f9c5e..4ebedf83c1 100644 --- a/test/cpp/qps/server.cc +++ b/test/cpp/qps/server.cc @@ -137,7 +137,7 @@ static void RunServer() { SimpleResponse response; ServerBuilder builder; - builder.AddPort(server_address, grpc::InsecureServerCredentials()); + builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); builder.RegisterService(&service); std::unique_ptr pool(new ThreadPool(FLAGS_server_threads)); diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc index 19778e5a7c..121ac73c52 100644 --- a/test/cpp/qps/server_async.cc +++ b/test/cpp/qps/server_async.cc @@ -68,7 +68,7 @@ class AsyncQpsServerTest : public Server { gpr_join_host_port(&server_address, "::", port); ServerBuilder builder; - builder.AddPort(server_address, InsecureServerCredentials()); + builder.AddListeningPort(server_address, InsecureServerCredentials()); gpr_free(server_address); builder.RegisterAsyncService(&async_service_); diff --git a/test/cpp/qps/server_sync.cc b/test/cpp/qps/server_sync.cc index 5c6541989c..3e15fb61c0 100644 --- a/test/cpp/qps/server_sync.cc +++ b/test/cpp/qps/server_sync.cc @@ -84,7 +84,7 @@ class SynchronousServer GRPC_FINAL : public grpc::testing::Server { char* server_address = NULL; gpr_join_host_port(&server_address, "::", port); - builder.AddPort(server_address, InsecureServerCredentials()); + builder.AddListeningPort(server_address, InsecureServerCredentials()); gpr_free(server_address); builder.RegisterService(&service_); diff --git a/test/cpp/qps/worker.cc b/test/cpp/qps/worker.cc index faabfd1147..fdcd9d5069 100644 --- a/test/cpp/qps/worker.cc +++ b/test/cpp/qps/worker.cc @@ -210,7 +210,7 @@ static void RunServer() { WorkerImpl service; ServerBuilder builder; - builder.AddPort(server_address, InsecureServerCredentials()); + builder.AddListeningPort(server_address, InsecureServerCredentials()); builder.RegisterService(&service); gpr_free(server_address); diff --git a/vsprojects/vs2013/global.props b/vsprojects/vs2013/global.props index 27efc13b24..ae44e18d4e 100644 --- a/vsprojects/vs2013/global.props +++ b/vsprojects/vs2013/global.props @@ -5,7 +5,7 @@ - $(SolutionDir)\..\..;$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\third_party\zlib;$(SolutionDir)\..\third_party;$(SolutionDir)\..\..\third_party\openssl\inc32 + $(SolutionDir)\..\..;$(SolutionDir)\..\..\include;$(SolutionDir)\..\..\third_party\zlib;$(SolutionDir)\..\third_party;$(SolutionDir)\..\..\third_party\openssl\inc32;$(SolutionDir)\..\..\third_party\protobuf\src _CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions) EnableAllWarnings -- cgit v1.2.3