diff options
44 files changed, 1580 insertions, 669 deletions
@@ -42,8 +42,8 @@ from setuptools.command import egg_info # Redirect the manifest template from MANIFEST.in to PYTHON-MANIFEST.in. egg_info.manifest_maker.template = 'PYTHON-MANIFEST.in' -PYTHON_STEM = './src/python/grpcio/' -CORE_INCLUDE = ('./include', './',) +PYTHON_STEM = './src/python/grpcio' +CORE_INCLUDE = ('./include', '.',) BORINGSSL_INCLUDE = ('./third_party/boringssl/include',) # Ensure we're in the proper directory whether or not we're being used by pip. diff --git a/src/compiler/python_generator.cc b/src/compiler/python_generator.cc index 83133f2b6e..c754ae299b 100644 --- a/src/compiler/python_generator.cc +++ b/src/compiler/python_generator.cc @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -148,91 +148,6 @@ class IndentScope { // END FORMATTING BOILERPLATE // //////////////////////////////// -bool PrintAlphaServicer(const ServiceDescriptor* service, - Printer* out) { - grpc::string doc = "<fill me in later!>"; - map<grpc::string, grpc::string> dict = ListToDict({ - "Service", service->name(), - "Documentation", doc, - }); - out->Print(dict, "class EarlyAdopter$Service$Servicer(object):\n"); - { - IndentScope raii_class_indent(out); - out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); - out->Print("__metaclass__ = abc.ABCMeta\n"); - for (int i = 0; i < service->method_count(); ++i) { - auto meth = service->method(i); - grpc::string arg_name = meth->client_streaming() ? - "request_iterator" : "request"; - out->Print("@abc.abstractmethod\n"); - out->Print("def $Method$(self, $ArgName$, context):\n", - "Method", meth->name(), "ArgName", arg_name); - { - IndentScope raii_method_indent(out); - out->Print("raise NotImplementedError()\n"); - } - } - } - return true; -} - -bool PrintAlphaServer(const ServiceDescriptor* service, Printer* out) { - grpc::string doc = "<fill me in later!>"; - map<grpc::string, grpc::string> dict = ListToDict({ - "Service", service->name(), - "Documentation", doc, - }); - out->Print(dict, "class EarlyAdopter$Service$Server(object):\n"); - { - IndentScope raii_class_indent(out); - out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); - out->Print("__metaclass__ = abc.ABCMeta\n"); - out->Print("@abc.abstractmethod\n"); - out->Print("def start(self):\n"); - { - IndentScope raii_method_indent(out); - out->Print("raise NotImplementedError()\n"); - } - - out->Print("@abc.abstractmethod\n"); - out->Print("def stop(self):\n"); - { - IndentScope raii_method_indent(out); - out->Print("raise NotImplementedError()\n"); - } - } - return true; -} - -bool PrintAlphaStub(const ServiceDescriptor* service, - Printer* out) { - grpc::string doc = "<fill me in later!>"; - map<grpc::string, grpc::string> dict = ListToDict({ - "Service", service->name(), - "Documentation", doc, - }); - out->Print(dict, "class EarlyAdopter$Service$Stub(object):\n"); - { - IndentScope raii_class_indent(out); - out->Print(dict, "\"\"\"$Documentation$\"\"\"\n"); - out->Print("__metaclass__ = abc.ABCMeta\n"); - for (int i = 0; i < service->method_count(); ++i) { - const MethodDescriptor* meth = service->method(i); - grpc::string arg_name = meth->client_streaming() ? - "request_iterator" : "request"; - auto methdict = ListToDict({"Method", meth->name(), "ArgName", arg_name}); - out->Print("@abc.abstractmethod\n"); - out->Print(methdict, "def $Method$(self, $ArgName$):\n"); - { - IndentScope raii_method_indent(out); - out->Print("raise NotImplementedError()\n"); - } - out->Print(methdict, "$Method$.async = None\n"); - } - } - return true; -} - // TODO(protobuf team): Export `ModuleName` from protobuf's // `src/google/protobuf/compiler/python/python_generator.cc` file. grpc::string ModuleName(const grpc::string& filename) { @@ -268,172 +183,6 @@ bool GetModuleAndMessagePath(const Descriptor* type, return true; } -bool PrintAlphaServerFactory(const grpc::string& package_qualified_service_name, - const ServiceDescriptor* service, Printer* out) { - out->Print("def early_adopter_create_$Service$_server(servicer, port, " - "private_key=None, certificate_chain=None):\n", - "Service", service->name()); - { - IndentScope raii_create_server_indent(out); - map<grpc::string, grpc::string> method_description_constructors; - map<grpc::string, pair<grpc::string, grpc::string>> - input_message_modules_and_classes; - map<grpc::string, pair<grpc::string, grpc::string>> - output_message_modules_and_classes; - for (int i = 0; i < service->method_count(); ++i) { - const MethodDescriptor* method = service->method(i); - const grpc::string method_description_constructor = - grpc::string(method->client_streaming() ? "stream_" : "unary_") + - grpc::string(method->server_streaming() ? "stream_" : "unary_") + - "service_description"; - pair<grpc::string, grpc::string> input_message_module_and_class; - if (!GetModuleAndMessagePath(method->input_type(), - &input_message_module_and_class)) { - return false; - } - pair<grpc::string, grpc::string> output_message_module_and_class; - if (!GetModuleAndMessagePath(method->output_type(), - &output_message_module_and_class)) { - return false; - } - // Import the modules that define the messages used in RPCs. - out->Print("import $Module$\n", "Module", - input_message_module_and_class.first); - out->Print("import $Module$\n", "Module", - output_message_module_and_class.first); - method_description_constructors.insert( - make_pair(method->name(), method_description_constructor)); - input_message_modules_and_classes.insert( - make_pair(method->name(), input_message_module_and_class)); - output_message_modules_and_classes.insert( - make_pair(method->name(), output_message_module_and_class)); - } - out->Print("method_service_descriptions = {\n"); - for (auto name_and_description_constructor = - method_description_constructors.begin(); - name_and_description_constructor != - method_description_constructors.end(); - name_and_description_constructor++) { - IndentScope raii_descriptions_indent(out); - const grpc::string method_name = name_and_description_constructor->first; - auto input_message_module_and_class = - input_message_modules_and_classes.find(method_name); - auto output_message_module_and_class = - output_message_modules_and_classes.find(method_name); - out->Print("\"$Method$\": alpha_utilities.$Constructor$(\n", "Method", - method_name, "Constructor", - name_and_description_constructor->second); - { - IndentScope raii_description_arguments_indent(out); - out->Print("servicer.$Method$,\n", "Method", method_name); - out->Print( - "$InputTypeModule$.$InputTypeClass$.FromString,\n", - "InputTypeModule", input_message_module_and_class->second.first, - "InputTypeClass", input_message_module_and_class->second.second); - out->Print( - "$OutputTypeModule$.$OutputTypeClass$.SerializeToString,\n", - "OutputTypeModule", output_message_module_and_class->second.first, - "OutputTypeClass", output_message_module_and_class->second.second); - } - out->Print("),\n"); - } - out->Print("}\n"); - out->Print( - "return early_adopter_implementations.server(" - "\"$PackageQualifiedServiceName$\"," - " method_service_descriptions, port, private_key=private_key," - " certificate_chain=certificate_chain)\n", - "PackageQualifiedServiceName", package_qualified_service_name); - } - return true; -} - -bool PrintAlphaStubFactory(const grpc::string& package_qualified_service_name, - const ServiceDescriptor* service, Printer* out) { - map<grpc::string, grpc::string> dict = ListToDict({ - "Service", service->name(), - }); - out->Print(dict, "def early_adopter_create_$Service$_stub(host, port," - " metadata_transformer=None," - " secure=False, root_certificates=None, private_key=None," - " certificate_chain=None, server_host_override=None):\n"); - { - IndentScope raii_create_server_indent(out); - map<grpc::string, grpc::string> method_description_constructors; - map<grpc::string, pair<grpc::string, grpc::string>> - input_message_modules_and_classes; - map<grpc::string, pair<grpc::string, grpc::string>> - output_message_modules_and_classes; - for (int i = 0; i < service->method_count(); ++i) { - const MethodDescriptor* method = service->method(i); - const grpc::string method_description_constructor = - grpc::string(method->client_streaming() ? "stream_" : "unary_") + - grpc::string(method->server_streaming() ? "stream_" : "unary_") + - "invocation_description"; - pair<grpc::string, grpc::string> input_message_module_and_class; - if (!GetModuleAndMessagePath(method->input_type(), - &input_message_module_and_class)) { - return false; - } - pair<grpc::string, grpc::string> output_message_module_and_class; - if (!GetModuleAndMessagePath(method->output_type(), - &output_message_module_and_class)) { - return false; - } - // Import the modules that define the messages used in RPCs. - out->Print("import $Module$\n", "Module", - input_message_module_and_class.first); - out->Print("import $Module$\n", "Module", - output_message_module_and_class.first); - method_description_constructors.insert( - make_pair(method->name(), method_description_constructor)); - input_message_modules_and_classes.insert( - make_pair(method->name(), input_message_module_and_class)); - output_message_modules_and_classes.insert( - make_pair(method->name(), output_message_module_and_class)); - } - out->Print("method_invocation_descriptions = {\n"); - for (auto name_and_description_constructor = - method_description_constructors.begin(); - name_and_description_constructor != - method_description_constructors.end(); - name_and_description_constructor++) { - IndentScope raii_descriptions_indent(out); - const grpc::string method_name = name_and_description_constructor->first; - auto input_message_module_and_class = - input_message_modules_and_classes.find(method_name); - auto output_message_module_and_class = - output_message_modules_and_classes.find(method_name); - out->Print("\"$Method$\": alpha_utilities.$Constructor$(\n", "Method", - method_name, "Constructor", - name_and_description_constructor->second); - { - IndentScope raii_description_arguments_indent(out); - out->Print( - "$InputTypeModule$.$InputTypeClass$.SerializeToString,\n", - "InputTypeModule", input_message_module_and_class->second.first, - "InputTypeClass", input_message_module_and_class->second.second); - out->Print( - "$OutputTypeModule$.$OutputTypeClass$.FromString,\n", - "OutputTypeModule", output_message_module_and_class->second.first, - "OutputTypeClass", output_message_module_and_class->second.second); - } - out->Print("),\n"); - } - out->Print("}\n"); - out->Print( - "return early_adopter_implementations.stub(" - "\"$PackageQualifiedServiceName$\"," - " method_invocation_descriptions, host, port," - " metadata_transformer=metadata_transformer, secure=secure," - " root_certificates=root_certificates, private_key=private_key," - " certificate_chain=certificate_chain," - " server_host_override=server_host_override)\n", - "PackageQualifiedServiceName", package_qualified_service_name); - } - return true; -} - bool PrintBetaServicer(const ServiceDescriptor* service, Printer* out) { grpc::string doc = "<fill me in later!>"; @@ -703,9 +452,6 @@ bool PrintPreamble(const FileDescriptor* file, out->Print("import abc\n"); out->Print("from $Package$ import implementations as beta_implementations\n", "Package", config.beta_package_root); - out->Print("from $Package$ import implementations as early_adopter_implementations\n", - "Package", config.early_adopter_package_root); - out->Print("from grpc.framework.alpha import utilities as alpha_utilities\n"); out->Print("from grpc.framework.common import cardinality\n"); out->Print("from grpc.framework.interfaces.face import utilities as face_utilities\n"); return true; @@ -714,7 +460,7 @@ bool PrintPreamble(const FileDescriptor* file, } // namespace pair<bool, grpc::string> GetServices(const FileDescriptor* file, - const GeneratorConfiguration& config) { + const GeneratorConfiguration& config) { grpc::string output; { // Scope the output stream so it closes and finalizes output to the string. @@ -730,12 +476,7 @@ pair<bool, grpc::string> GetServices(const FileDescriptor* file, for (int i = 0; i < file->service_count(); ++i) { auto service = file->service(i); auto package_qualified_service_name = package + service->name(); - if (!(PrintAlphaServicer(service, &out) && - PrintAlphaServer(service, &out) && - PrintAlphaStub(service, &out) && - PrintAlphaServerFactory(package_qualified_service_name, service, &out) && - PrintAlphaStubFactory(package_qualified_service_name, service, &out) && - PrintBetaServicer(service, &out) && + if (!(PrintBetaServicer(service, &out) && PrintBetaStub(service, &out) && PrintBetaServerFactory(package_qualified_service_name, service, &out) && PrintBetaStubFactory(package_qualified_service_name, service, &out))) { diff --git a/src/compiler/python_generator.h b/src/compiler/python_generator.h index 44ed4b3f98..68da18f9ba 100644 --- a/src/compiler/python_generator.h +++ b/src/compiler/python_generator.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,7 +43,6 @@ namespace grpc_python_generator { // Data pertaining to configuration of the generator with respect to anything // that may be used internally at Google. struct GeneratorConfiguration { - grpc::string early_adopter_package_root; grpc::string beta_package_root; }; diff --git a/src/compiler/python_plugin.cc b/src/compiler/python_plugin.cc index c7cef54900..d781ddbee5 100644 --- a/src/compiler/python_plugin.cc +++ b/src/compiler/python_plugin.cc @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,7 +38,6 @@ int main(int argc, char* argv[]) { grpc_python_generator::GeneratorConfiguration config; - config.early_adopter_package_root = "grpc.early_adopter"; config.beta_package_root = "grpc.beta"; grpc_python_generator::PythonGrpcGenerator generator(config); return grpc::protobuf::compiler::PluginMain(argc, argv, &generator); diff --git a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs index af55cb0566..da0ea2e6dc 100644 --- a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs +++ b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs @@ -1,6 +1,6 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -45,13 +45,9 @@ namespace Grpc.Core.Tests { public class PInvokeTest { - int counter; - - [DllImport("grpc_csharp_ext.dll")] - static extern GRPCCallError grpcsharp_test_callback([MarshalAs(UnmanagedType.FunctionPtr)] OpCompletionDelegate callback); + static readonly NativeMethods Native = NativeMethods.Get(); - [DllImport("grpc_csharp_ext.dll")] - static extern IntPtr grpcsharp_test_nop(IntPtr ptr); + int counter; /// <summary> /// (~1.26us .NET Windows) @@ -87,7 +83,7 @@ namespace Grpc.Core.Tests 1000000, 10000000, () => { - grpcsharp_test_callback(handler); + Native.grpcsharp_test_callback(handler); }); Assert.AreNotEqual(0, counter); } @@ -106,7 +102,7 @@ namespace Grpc.Core.Tests 10000, 10000, () => { - grpcsharp_test_callback(new OpCompletionDelegate(Handler)); + Native.grpcsharp_test_callback(new OpCompletionDelegate(Handler)); }); Assert.AreNotEqual(0, counter); } @@ -122,7 +118,7 @@ namespace Grpc.Core.Tests 1000000, 100000000, () => { - grpcsharp_test_nop(IntPtr.Zero); + Native.grpcsharp_test_nop(IntPtr.Zero); }); } diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index 852b212114..ef4ec70a4a 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -19,7 +19,6 @@ <DefineConstants>DEBUG;</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> - <NativeDependenciesConfiguration>Debug</NativeDependenciesConfiguration> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugType>pdbonly</DebugType> @@ -27,7 +26,6 @@ <OutputPath>bin\Release</OutputPath> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> - <NativeDependenciesConfiguration>Release</NativeDependenciesConfiguration> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' "> <DebugType>pdbonly</DebugType> @@ -38,7 +36,6 @@ <WarningLevel>4</WarningLevel> <SignAssembly>True</SignAssembly> <AssemblyOriginatorKeyFile>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile> - <NativeDependenciesConfiguration>Release</NativeDependenciesConfiguration> </PropertyGroup> <ItemGroup> <Reference Include="System" /> @@ -52,6 +49,10 @@ <Compile Include="AsyncAuthInterceptor.cs" /> <Compile Include="CallCredentials.cs" /> <Compile Include="IClientStreamWriter.cs" /> + <Compile Include="Internal\NativeMethods.cs" /> + <Compile Include="Internal\PlatformApis.cs" /> + <Compile Include="Internal\NativeExtension.cs" /> + <Compile Include="Internal\UnmanagedLibrary.cs" /> <Compile Include="Internal\NativeMetadataCredentialsPlugin.cs" /> <Compile Include="Internal\INativeCall.cs" /> <Compile Include="IServerStreamWriter.cs" /> @@ -131,20 +132,6 @@ <None Include="Grpc.Core.nuspec" /> <None Include="packages.config" /> </ItemGroup> - <Choose> - <!-- Under older versions of Monodevelop, Choose is not supported and is just - ignored, which gives us the desired effect. --> - <When Condition=" '$(OS)' != 'Unix' "> - <ItemGroup> - <Content Include="..\..\..\vsprojects\$(NativeDependenciesConfiguration)\grpc_csharp_ext.dll"> - <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> - </Content> - </ItemGroup> - </When> - <Otherwise /> - </Choose> + <Import Project="NativeDeps.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> - <ItemGroup /> - <ItemGroup /> - <ItemGroup /> </Project>
\ No newline at end of file diff --git a/src/csharp/Grpc.Core/GrpcEnvironment.cs b/src/csharp/Grpc.Core/GrpcEnvironment.cs index e7c04185c2..f3aa3d79de 100644 --- a/src/csharp/Grpc.Core/GrpcEnvironment.cs +++ b/src/csharp/Grpc.Core/GrpcEnvironment.cs @@ -1,6 +1,6 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -47,15 +47,6 @@ namespace Grpc.Core { const int THREAD_POOL_SIZE = 4; - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_init(); - - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_shutdown(); - - [DllImport("grpc_csharp_ext.dll")] - static extern IntPtr grpcsharp_version_string(); // returns not-owned const char* - static object staticLock = new object(); static GrpcEnvironment instance; static int refCount; @@ -136,7 +127,6 @@ namespace Grpc.Core /// </summary> private GrpcEnvironment() { - NativeLogRedirector.Redirect(); GrpcNativeInit(); completionRegistry = new CompletionRegistry(this); threadPool = new GrpcThreadPool(this, THREAD_POOL_SIZE); @@ -181,18 +171,18 @@ namespace Grpc.Core /// </summary> internal static string GetCoreVersionString() { - var ptr = grpcsharp_version_string(); // the pointer is not owned + var ptr = NativeMethods.Get().grpcsharp_version_string(); // the pointer is not owned return Marshal.PtrToStringAnsi(ptr); } internal static void GrpcNativeInit() { - grpcsharp_init(); + NativeMethods.Get().grpcsharp_init(); } internal static void GrpcNativeShutdown() { - grpcsharp_shutdown(); + NativeMethods.Get().grpcsharp_shutdown(); } /// <summary> diff --git a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs index 125fb40b32..0e2108f0f2 100644 --- a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandle.cs @@ -42,47 +42,7 @@ namespace Grpc.Core.Internal /// </summary> internal class BatchContextSafeHandle : SafeHandleZeroIsInvalid { - [DllImport("grpc_csharp_ext.dll")] - static extern BatchContextSafeHandle grpcsharp_batch_context_create(); - - [DllImport("grpc_csharp_ext.dll")] - static extern IntPtr grpcsharp_batch_context_recv_initial_metadata(BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - static extern IntPtr grpcsharp_batch_context_recv_message_length(BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_batch_context_recv_message_to_buffer(BatchContextSafeHandle ctx, byte[] buffer, UIntPtr bufferLen); - - [DllImport("grpc_csharp_ext.dll")] - static extern StatusCode grpcsharp_batch_context_recv_status_on_client_status(BatchContextSafeHandle ctx); - - [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_host(BatchContextSafeHandle ctx); // returns const char* - - [DllImport("grpc_csharp_ext.dll")] - static extern Timespec grpcsharp_batch_context_server_rpc_new_deadline(BatchContextSafeHandle ctx); - - [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); - - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_batch_context_destroy(IntPtr ctx); + static readonly NativeMethods Native = NativeMethods.Get(); private BatchContextSafeHandle() { @@ -90,7 +50,7 @@ namespace Grpc.Core.Internal public static BatchContextSafeHandle Create() { - return grpcsharp_batch_context_create(); + return Native.grpcsharp_batch_context_create(); } public IntPtr Handle @@ -104,17 +64,17 @@ namespace Grpc.Core.Internal // Gets data of recv_initial_metadata completion. public Metadata GetReceivedInitialMetadata() { - IntPtr metadataArrayPtr = grpcsharp_batch_context_recv_initial_metadata(this); + IntPtr metadataArrayPtr = Native.grpcsharp_batch_context_recv_initial_metadata(this); return MetadataArraySafeHandle.ReadMetadataFromPtrUnsafe(metadataArrayPtr); } // Gets data of recv_status_on_client completion. public ClientSideStatus GetReceivedStatusOnClient() { - string details = Marshal.PtrToStringAnsi(grpcsharp_batch_context_recv_status_on_client_details(this)); - var status = new Status(grpcsharp_batch_context_recv_status_on_client_status(this), details); + string details = Marshal.PtrToStringAnsi(Native.grpcsharp_batch_context_recv_status_on_client_details(this)); + var status = new Status(Native.grpcsharp_batch_context_recv_status_on_client_status(this), details); - IntPtr metadataArrayPtr = grpcsharp_batch_context_recv_status_on_client_trailing_metadata(this); + IntPtr metadataArrayPtr = Native.grpcsharp_batch_context_recv_status_on_client_trailing_metadata(this); var metadata = MetadataArraySafeHandle.ReadMetadataFromPtrUnsafe(metadataArrayPtr); return new ClientSideStatus(status, metadata); @@ -123,26 +83,26 @@ namespace Grpc.Core.Internal // Gets data of recv_message completion. public byte[] GetReceivedMessage() { - IntPtr len = grpcsharp_batch_context_recv_message_length(this); + IntPtr len = Native.grpcsharp_batch_context_recv_message_length(this); if (len == new IntPtr(-1)) { return null; } byte[] data = new byte[(int)len]; - grpcsharp_batch_context_recv_message_to_buffer(this, data, new UIntPtr((ulong)data.Length)); + Native.grpcsharp_batch_context_recv_message_to_buffer(this, data, new UIntPtr((ulong)data.Length)); return data; } // Gets data of server_rpc_new completion. public ServerRpcNew GetServerRpcNew(Server server) { - var call = grpcsharp_batch_context_server_rpc_new_call(this); + var call = Native.grpcsharp_batch_context_server_rpc_new_call(this); - var method = Marshal.PtrToStringAnsi(grpcsharp_batch_context_server_rpc_new_method(this)); - var host = Marshal.PtrToStringAnsi(grpcsharp_batch_context_server_rpc_new_host(this)); - var deadline = grpcsharp_batch_context_server_rpc_new_deadline(this); + var method = Marshal.PtrToStringAnsi(Native.grpcsharp_batch_context_server_rpc_new_method(this)); + var host = Marshal.PtrToStringAnsi(Native.grpcsharp_batch_context_server_rpc_new_host(this)); + var deadline = Native.grpcsharp_batch_context_server_rpc_new_deadline(this); - IntPtr metadataArrayPtr = grpcsharp_batch_context_server_rpc_new_request_metadata(this); + IntPtr metadataArrayPtr = Native.grpcsharp_batch_context_server_rpc_new_request_metadata(this); var metadata = MetadataArraySafeHandle.ReadMetadataFromPtrUnsafe(metadataArrayPtr); return new ServerRpcNew(server, call, method, host, deadline, metadata); @@ -151,12 +111,12 @@ namespace Grpc.Core.Internal // Gets data of receive_close_on_server completion. public bool GetReceivedCloseOnServerCancelled() { - return grpcsharp_batch_context_recv_close_on_server_cancelled(this) != 0; + return Native.grpcsharp_batch_context_recv_close_on_server_cancelled(this) != 0; } protected override bool ReleaseHandle() { - grpcsharp_batch_context_destroy(handle); + Native.grpcsharp_batch_context_destroy(handle); return true; } } diff --git a/src/csharp/Grpc.Core/Internal/CStringSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CStringSafeHandle.cs index 92fbe8cf0f..4ae57aa773 100644 --- a/src/csharp/Grpc.Core/Internal/CStringSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/CStringSafeHandle.cs @@ -1,5 +1,5 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -39,8 +39,7 @@ namespace Grpc.Core.Internal /// </summary> internal class CStringSafeHandle : SafeHandleZeroIsInvalid { - [DllImport("grpc_csharp_ext.dll")] - static extern void gprsharp_free(IntPtr ptr); + static readonly NativeMethods Native = NativeMethods.Get(); private CStringSafeHandle() { @@ -53,7 +52,7 @@ namespace Grpc.Core.Internal protected override bool ReleaseHandle() { - gprsharp_free(handle); + Native.gprsharp_free(handle); return true; } } diff --git a/src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs index 3678c7dd86..0f36337f11 100644 --- a/src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/CallCredentialsSafeHandle.cs @@ -1,5 +1,5 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -40,11 +40,7 @@ namespace Grpc.Core.Internal /// </summary> internal class CallCredentialsSafeHandle : SafeHandleZeroIsInvalid { - [DllImport("grpc_csharp_ext.dll")] - static extern CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2); - - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_call_credentials_release(IntPtr credentials); + static readonly NativeMethods Native = NativeMethods.Get(); private CallCredentialsSafeHandle() { @@ -52,12 +48,12 @@ namespace Grpc.Core.Internal public static CallCredentialsSafeHandle CreateComposite(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2) { - return grpcsharp_composite_call_credentials_create(creds1, creds2); + return Native.grpcsharp_composite_call_credentials_create(creds1, creds2); } protected override bool ReleaseHandle() { - grpcsharp_call_credentials_release(handle); + Native.grpcsharp_call_credentials_release(handle); return true; } } diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs index 298c5e29ab..bc045b67b1 100644 --- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs @@ -44,71 +44,12 @@ namespace Grpc.Core.Internal internal class CallSafeHandle : SafeHandleZeroIsInvalid, INativeCall { public static readonly CallSafeHandle NullInstance = new CallSafeHandle(); + static readonly NativeMethods Native = NativeMethods.Get(); const uint GRPC_WRITE_BUFFER_HINT = 1; CompletionRegistry completionRegistry; CompletionQueueSafeHandle completionQueue; - [DllImport("grpc_csharp_ext.dll")] - static extern GRPCCallError grpcsharp_call_cancel(CallSafeHandle call); - - [DllImport("grpc_csharp_ext.dll")] - static extern GRPCCallError grpcsharp_call_cancel_with_status(CallSafeHandle call, StatusCode status, string description); - - [DllImport("grpc_csharp_ext.dll")] - static extern GRPCCallError grpcsharp_call_start_unary(CallSafeHandle call, - BatchContextSafeHandle ctx, byte[] send_buffer, UIntPtr send_buffer_len, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags); - - [DllImport("grpc_csharp_ext.dll")] - static extern GRPCCallError grpcsharp_call_start_client_streaming(CallSafeHandle call, - BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); - - [DllImport("grpc_csharp_ext.dll")] - static extern GRPCCallError grpcsharp_call_start_server_streaming(CallSafeHandle call, - BatchContextSafeHandle ctx, byte[] send_buffer, UIntPtr send_buffer_len, - MetadataArraySafeHandle metadataArray, WriteFlags writeFlags); - - [DllImport("grpc_csharp_ext.dll")] - static extern GRPCCallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call, - BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); - - [DllImport("grpc_csharp_ext.dll")] - static extern GRPCCallError grpcsharp_call_send_message(CallSafeHandle call, - BatchContextSafeHandle ctx, byte[] send_buffer, UIntPtr send_buffer_len, WriteFlags writeFlags, bool sendEmptyInitialMetadata); - - [DllImport("grpc_csharp_ext.dll")] - static extern GRPCCallError grpcsharp_call_send_close_from_client(CallSafeHandle call, - BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - static extern GRPCCallError grpcsharp_call_send_status_from_server(CallSafeHandle call, - BatchContextSafeHandle ctx, StatusCode statusCode, string statusMessage, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata); - - [DllImport("grpc_csharp_ext.dll")] - static extern GRPCCallError grpcsharp_call_recv_message(CallSafeHandle call, - BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - static extern GRPCCallError grpcsharp_call_recv_initial_metadata(CallSafeHandle call, - BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - static extern GRPCCallError grpcsharp_call_start_serverside(CallSafeHandle call, - BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - static extern GRPCCallError grpcsharp_call_send_initial_metadata(CallSafeHandle call, - BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); - - [DllImport("grpc_csharp_ext.dll")] - static extern GRPCCallError grpcsharp_call_set_credentials(CallSafeHandle call, CallCredentialsSafeHandle credentials); - - [DllImport("grpc_csharp_ext.dll")] - static extern CStringSafeHandle grpcsharp_call_get_peer(CallSafeHandle call); - - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_call_destroy(IntPtr call); - private CallSafeHandle() { } @@ -121,7 +62,7 @@ namespace Grpc.Core.Internal public void SetCredentials(CallCredentialsSafeHandle credentials) { - grpcsharp_call_set_credentials(this, credentials).CheckOk(); + Native.grpcsharp_call_set_credentials(this, credentials).CheckOk(); } public void StartUnary(UnaryResponseClientHandler callback, byte[] payload, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags) @@ -130,7 +71,7 @@ namespace Grpc.Core.Internal { var ctx = BatchContextSafeHandle.Create(); completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient(), context.GetReceivedMessage(), context.GetReceivedInitialMetadata())); - grpcsharp_call_start_unary(this, ctx, payload, new UIntPtr((ulong)payload.Length), metadataArray, writeFlags) + Native.grpcsharp_call_start_unary(this, ctx, payload, new UIntPtr((ulong)payload.Length), metadataArray, writeFlags) .CheckOk(); } } @@ -139,7 +80,7 @@ namespace Grpc.Core.Internal { using (Profilers.ForCurrentThread().NewScope("CallSafeHandle.StartUnary")) { - grpcsharp_call_start_unary(this, ctx, payload, new UIntPtr((ulong)payload.Length), metadataArray, writeFlags) + Native.grpcsharp_call_start_unary(this, ctx, payload, new UIntPtr((ulong)payload.Length), metadataArray, writeFlags) .CheckOk(); } } @@ -150,7 +91,7 @@ namespace Grpc.Core.Internal { var ctx = BatchContextSafeHandle.Create(); completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient(), context.GetReceivedMessage(), context.GetReceivedInitialMetadata())); - grpcsharp_call_start_client_streaming(this, ctx, metadataArray).CheckOk(); + Native.grpcsharp_call_start_client_streaming(this, ctx, metadataArray).CheckOk(); } } @@ -160,7 +101,7 @@ namespace Grpc.Core.Internal { var ctx = BatchContextSafeHandle.Create(); completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient())); - grpcsharp_call_start_server_streaming(this, ctx, payload, new UIntPtr((ulong)payload.Length), metadataArray, writeFlags).CheckOk(); + Native.grpcsharp_call_start_server_streaming(this, ctx, payload, new UIntPtr((ulong)payload.Length), metadataArray, writeFlags).CheckOk(); } } @@ -170,7 +111,7 @@ namespace Grpc.Core.Internal { var ctx = BatchContextSafeHandle.Create(); completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedStatusOnClient())); - grpcsharp_call_start_duplex_streaming(this, ctx, metadataArray).CheckOk(); + Native.grpcsharp_call_start_duplex_streaming(this, ctx, metadataArray).CheckOk(); } } @@ -180,7 +121,7 @@ namespace Grpc.Core.Internal { var ctx = BatchContextSafeHandle.Create(); completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success)); - grpcsharp_call_send_message(this, ctx, payload, new UIntPtr((ulong)payload.Length), writeFlags, sendEmptyInitialMetadata).CheckOk(); + Native.grpcsharp_call_send_message(this, ctx, payload, new UIntPtr((ulong)payload.Length), writeFlags, sendEmptyInitialMetadata).CheckOk(); } } @@ -190,7 +131,7 @@ namespace Grpc.Core.Internal { var ctx = BatchContextSafeHandle.Create(); completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success)); - grpcsharp_call_send_close_from_client(this, ctx).CheckOk(); + Native.grpcsharp_call_send_close_from_client(this, ctx).CheckOk(); } } @@ -200,7 +141,7 @@ namespace Grpc.Core.Internal { var ctx = BatchContextSafeHandle.Create(); completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success)); - grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, status.Detail, metadataArray, sendEmptyInitialMetadata).CheckOk(); + Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, status.Detail, metadataArray, sendEmptyInitialMetadata).CheckOk(); } } @@ -210,7 +151,7 @@ namespace Grpc.Core.Internal { var ctx = BatchContextSafeHandle.Create(); completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedMessage())); - grpcsharp_call_recv_message(this, ctx).CheckOk(); + Native.grpcsharp_call_recv_message(this, ctx).CheckOk(); } } @@ -220,7 +161,7 @@ namespace Grpc.Core.Internal { var ctx = BatchContextSafeHandle.Create(); completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedInitialMetadata())); - grpcsharp_call_recv_initial_metadata(this, ctx).CheckOk(); + Native.grpcsharp_call_recv_initial_metadata(this, ctx).CheckOk(); } } @@ -230,7 +171,7 @@ namespace Grpc.Core.Internal { var ctx = BatchContextSafeHandle.Create(); completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success, context.GetReceivedCloseOnServerCancelled())); - grpcsharp_call_start_serverside(this, ctx).CheckOk(); + Native.grpcsharp_call_start_serverside(this, ctx).CheckOk(); } } @@ -240,23 +181,23 @@ namespace Grpc.Core.Internal { var ctx = BatchContextSafeHandle.Create(); completionRegistry.RegisterBatchCompletion(ctx, (success, context) => callback(success)); - grpcsharp_call_send_initial_metadata(this, ctx, metadataArray).CheckOk(); + Native.grpcsharp_call_send_initial_metadata(this, ctx, metadataArray).CheckOk(); } } public void Cancel() { - grpcsharp_call_cancel(this).CheckOk(); + Native.grpcsharp_call_cancel(this).CheckOk(); } public void CancelWithStatus(Status status) { - grpcsharp_call_cancel_with_status(this, status.StatusCode, status.Detail).CheckOk(); + Native.grpcsharp_call_cancel_with_status(this, status.StatusCode, status.Detail).CheckOk(); } public string GetPeer() { - using (var cstring = grpcsharp_call_get_peer(this)) + using (var cstring = Native.grpcsharp_call_get_peer(this)) { return cstring.GetValue(); } @@ -264,7 +205,7 @@ namespace Grpc.Core.Internal protected override bool ReleaseHandle() { - grpcsharp_call_destroy(handle); + Native.grpcsharp_call_destroy(handle); return true; } diff --git a/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs index ea5b52374e..f6aa710b21 100644 --- a/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs @@ -1,5 +1,5 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -39,17 +39,7 @@ namespace Grpc.Core.Internal /// </summary> internal class ChannelArgsSafeHandle : SafeHandleZeroIsInvalid { - [DllImport("grpc_csharp_ext.dll")] - static extern ChannelArgsSafeHandle grpcsharp_channel_args_create(UIntPtr numArgs); - - [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - static extern void grpcsharp_channel_args_set_string(ChannelArgsSafeHandle args, UIntPtr index, string key, string value); - - [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - static extern void grpcsharp_channel_args_set_integer(ChannelArgsSafeHandle args, UIntPtr index, string key, int value); - - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_channel_args_destroy(IntPtr args); + static readonly NativeMethods Native = NativeMethods.Get(); private ChannelArgsSafeHandle() { @@ -62,22 +52,22 @@ namespace Grpc.Core.Internal public static ChannelArgsSafeHandle Create(int size) { - return grpcsharp_channel_args_create(new UIntPtr((uint)size)); + return Native.grpcsharp_channel_args_create(new UIntPtr((uint)size)); } public void SetString(int index, string key, string value) { - grpcsharp_channel_args_set_string(this, new UIntPtr((uint)index), key, value); + Native.grpcsharp_channel_args_set_string(this, new UIntPtr((uint)index), key, value); } public void SetInteger(int index, string key, int value) { - grpcsharp_channel_args_set_integer(this, new UIntPtr((uint)index), key, value); + Native.grpcsharp_channel_args_set_integer(this, new UIntPtr((uint)index), key, value); } protected override bool ReleaseHandle() { - grpcsharp_channel_args_destroy(handle); + Native.grpcsharp_channel_args_destroy(handle); return true; } } diff --git a/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs index 8a58c64478..65cc2e019f 100644 --- a/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs @@ -1,5 +1,5 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -40,14 +40,7 @@ namespace Grpc.Core.Internal /// </summary> internal class ChannelCredentialsSafeHandle : SafeHandleZeroIsInvalid { - [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey); - - [DllImport("grpc_csharp_ext.dll")] - static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); - - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_channel_credentials_release(IntPtr credentials); + static readonly NativeMethods Native = NativeMethods.Get(); private ChannelCredentialsSafeHandle() { @@ -64,22 +57,22 @@ namespace Grpc.Core.Internal { if (keyCertPair != null) { - return grpcsharp_ssl_credentials_create(pemRootCerts, keyCertPair.CertificateChain, keyCertPair.PrivateKey); + return Native.grpcsharp_ssl_credentials_create(pemRootCerts, keyCertPair.CertificateChain, keyCertPair.PrivateKey); } else { - return grpcsharp_ssl_credentials_create(pemRootCerts, null, null); + return Native.grpcsharp_ssl_credentials_create(pemRootCerts, null, null); } } public static ChannelCredentialsSafeHandle CreateComposite(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds) { - return grpcsharp_composite_channel_credentials_create(channelCreds, callCreds); + return Native.grpcsharp_composite_channel_credentials_create(channelCreds, callCreds); } protected override bool ReleaseHandle() { - grpcsharp_channel_credentials_release(handle); + Native.grpcsharp_channel_credentials_release(handle); return true; } } diff --git a/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs index 4a5584121e..2199905cc6 100644 --- a/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs @@ -1,5 +1,5 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -41,27 +41,7 @@ namespace Grpc.Core.Internal /// </summary> internal class ChannelSafeHandle : SafeHandleZeroIsInvalid { - [DllImport("grpc_csharp_ext.dll")] - static extern ChannelSafeHandle grpcsharp_insecure_channel_create(string target, ChannelArgsSafeHandle channelArgs); - - [DllImport("grpc_csharp_ext.dll")] - static extern ChannelSafeHandle grpcsharp_secure_channel_create(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs); - - [DllImport("grpc_csharp_ext.dll")] - static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline); - - [DllImport("grpc_csharp_ext.dll")] - static extern ChannelState grpcsharp_channel_check_connectivity_state(ChannelSafeHandle channel, int tryToConnect); - - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_channel_watch_connectivity_state(ChannelSafeHandle channel, ChannelState lastObservedState, - Timespec deadline, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - static extern CStringSafeHandle grpcsharp_channel_get_target(ChannelSafeHandle call); - - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_channel_destroy(IntPtr channel); + static readonly NativeMethods Native = NativeMethods.Get(); private ChannelSafeHandle() { @@ -72,7 +52,7 @@ namespace Grpc.Core.Internal // Increment reference count for the native gRPC environment to make sure we don't do grpc_shutdown() before destroying the server handle. // Doing so would make object finalizer crash if we end up abandoning the handle. GrpcEnvironment.GrpcNativeInit(); - return grpcsharp_insecure_channel_create(target, channelArgs); + return Native.grpcsharp_insecure_channel_create(target, channelArgs); } public static ChannelSafeHandle CreateSecure(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs) @@ -80,14 +60,14 @@ namespace Grpc.Core.Internal // Increment reference count for the native gRPC environment to make sure we don't do grpc_shutdown() before destroying the server handle. // Doing so would make object finalizer crash if we end up abandoning the handle. GrpcEnvironment.GrpcNativeInit(); - return grpcsharp_secure_channel_create(credentials, target, channelArgs); + return Native.grpcsharp_secure_channel_create(credentials, target, channelArgs); } public CallSafeHandle CreateCall(CompletionRegistry registry, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline, CallCredentialsSafeHandle credentials) { using (Profilers.ForCurrentThread().NewScope("ChannelSafeHandle.CreateCall")) { - var result = grpcsharp_channel_create_call(this, parentCall, propagationMask, cq, method, host, deadline); + var result = Native.grpcsharp_channel_create_call(this, parentCall, propagationMask, cq, method, host, deadline); if (credentials != null) { result.SetCredentials(credentials); @@ -99,7 +79,7 @@ namespace Grpc.Core.Internal public ChannelState CheckConnectivityState(bool tryToConnect) { - return grpcsharp_channel_check_connectivity_state(this, tryToConnect ? 1 : 0); + return Native.grpcsharp_channel_check_connectivity_state(this, tryToConnect ? 1 : 0); } public void WatchConnectivityState(ChannelState lastObservedState, Timespec deadline, CompletionQueueSafeHandle cq, @@ -107,12 +87,12 @@ namespace Grpc.Core.Internal { var ctx = BatchContextSafeHandle.Create(); completionRegistry.RegisterBatchCompletion(ctx, callback); - grpcsharp_channel_watch_connectivity_state(this, lastObservedState, deadline, cq, ctx); + Native.grpcsharp_channel_watch_connectivity_state(this, lastObservedState, deadline, cq, ctx); } public string GetTarget() { - using (var cstring = grpcsharp_channel_get_target(this)) + using (var cstring = Native.grpcsharp_channel_get_target(this)) { return cstring.GetValue(); } @@ -120,7 +100,7 @@ namespace Grpc.Core.Internal protected override bool ReleaseHandle() { - grpcsharp_channel_destroy(handle); + Native.grpcsharp_channel_destroy(handle); GrpcEnvironment.GrpcNativeShutdown(); return true; } diff --git a/src/csharp/Grpc.Core/Internal/CompletionQueueEvent.cs b/src/csharp/Grpc.Core/Internal/CompletionQueueEvent.cs index 3f517514a3..36a92ecd8e 100644 --- a/src/csharp/Grpc.Core/Internal/CompletionQueueEvent.cs +++ b/src/csharp/Grpc.Core/Internal/CompletionQueueEvent.cs @@ -1,6 +1,6 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -42,8 +42,7 @@ namespace Grpc.Core.Internal [StructLayout(LayoutKind.Sequential)] internal struct CompletionQueueEvent { - [DllImport("grpc_csharp_ext.dll")] - static extern int grpcsharp_sizeof_grpc_event(); + static readonly NativeMethods Native = NativeMethods.Get(); public GRPCCompletionType type; public int success; @@ -53,7 +52,7 @@ namespace Grpc.Core.Internal { get { - return grpcsharp_sizeof_grpc_event(); + return Native.grpcsharp_sizeof_grpc_event(); } } } diff --git a/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs index 3754ad382e..9d7a990c42 100644 --- a/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs @@ -1,5 +1,5 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -42,22 +42,9 @@ namespace Grpc.Core.Internal /// </summary> internal class CompletionQueueSafeHandle : SafeHandleZeroIsInvalid { - AtomicCounter shutdownRefcount = new AtomicCounter(1); - - [DllImport("grpc_csharp_ext.dll")] - static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create(); - - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_completion_queue_shutdown(CompletionQueueSafeHandle cq); + static readonly NativeMethods Native = NativeMethods.Get(); - [DllImport("grpc_csharp_ext.dll")] - static extern CompletionQueueEvent grpcsharp_completion_queue_next(CompletionQueueSafeHandle cq); - - [DllImport("grpc_csharp_ext.dll")] - static extern CompletionQueueEvent grpcsharp_completion_queue_pluck(CompletionQueueSafeHandle cq, IntPtr tag); - - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_completion_queue_destroy(IntPtr cq); + AtomicCounter shutdownRefcount = new AtomicCounter(1); private CompletionQueueSafeHandle() { @@ -65,20 +52,20 @@ namespace Grpc.Core.Internal public static CompletionQueueSafeHandle Create() { - return grpcsharp_completion_queue_create(); + return Native.grpcsharp_completion_queue_create(); } public CompletionQueueEvent Next() { - return grpcsharp_completion_queue_next(this); + return Native.grpcsharp_completion_queue_next(this); } public CompletionQueueEvent Pluck(IntPtr tag) { using (Profilers.ForCurrentThread().NewScope("CompletionQueueSafeHandle.Pluck")) { - return grpcsharp_completion_queue_pluck(this, tag); + return Native.grpcsharp_completion_queue_pluck(this, tag); } } @@ -98,7 +85,7 @@ namespace Grpc.Core.Internal protected override bool ReleaseHandle() { - grpcsharp_completion_queue_destroy(handle); + Native.grpcsharp_completion_queue_destroy(handle); return true; } @@ -106,7 +93,7 @@ namespace Grpc.Core.Internal { if (shutdownRefcount.Decrement() == 0) { - grpcsharp_completion_queue_shutdown(this); + Native.grpcsharp_completion_queue_shutdown(this); } } diff --git a/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs index ed1bd24498..81760d7a10 100644 --- a/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/MetadataArraySafeHandle.cs @@ -1,5 +1,5 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -40,26 +40,7 @@ namespace Grpc.Core.Internal /// </summary> 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 UIntPtr grpcsharp_metadata_array_count(IntPtr metadataArray); - - [DllImport("grpc_csharp_ext.dll")] - static extern IntPtr grpcsharp_metadata_array_get_key(IntPtr metadataArray, UIntPtr index); - - [DllImport("grpc_csharp_ext.dll")] - static extern IntPtr grpcsharp_metadata_array_get_value(IntPtr metadataArray, UIntPtr index); - - [DllImport("grpc_csharp_ext.dll")] - static extern UIntPtr grpcsharp_metadata_array_get_value_length(IntPtr metadataArray, UIntPtr index); - - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_metadata_array_destroy_full(IntPtr array); + static readonly NativeMethods Native = NativeMethods.Get(); private MetadataArraySafeHandle() { @@ -70,11 +51,11 @@ namespace Grpc.Core.Internal using (Profilers.ForCurrentThread().NewScope("MetadataArraySafeHandle.Create")) { // TODO(jtattermusch): we might wanna check that the metadata is readonly - var metadataArray = grpcsharp_metadata_array_create(new UIntPtr((ulong)metadata.Count)); + var metadataArray = Native.grpcsharp_metadata_array_create(new UIntPtr((ulong)metadata.Count)); for (int i = 0; i < metadata.Count; i++) { var valueBytes = metadata[i].GetSerializedValueUnsafe(); - grpcsharp_metadata_array_add(metadataArray, metadata[i].Key, valueBytes, new UIntPtr((ulong)valueBytes.Length)); + Native.grpcsharp_metadata_array_add(metadataArray, metadata[i].Key, valueBytes, new UIntPtr((ulong)valueBytes.Length)); } return metadataArray; } @@ -90,15 +71,15 @@ namespace Grpc.Core.Internal return null; } - ulong count = grpcsharp_metadata_array_count(metadataArray).ToUInt64(); + ulong count = Native.grpcsharp_metadata_array_count(metadataArray).ToUInt64(); var metadata = new Metadata(); for (ulong i = 0; i < count; i++) { var index = new UIntPtr(i); - string key = Marshal.PtrToStringAnsi(grpcsharp_metadata_array_get_key(metadataArray, index)); - var bytes = new byte[grpcsharp_metadata_array_get_value_length(metadataArray, index).ToUInt64()]; - Marshal.Copy(grpcsharp_metadata_array_get_value(metadataArray, index), bytes, 0, bytes.Length); + string key = Marshal.PtrToStringAnsi(Native.grpcsharp_metadata_array_get_key(metadataArray, index)); + var bytes = new byte[Native.grpcsharp_metadata_array_get_value_length(metadataArray, index).ToUInt64()]; + Marshal.Copy(Native.grpcsharp_metadata_array_get_value(metadataArray, index), bytes, 0, bytes.Length); metadata.Add(Metadata.Entry.CreateUnsafe(key, bytes)); } return metadata; @@ -114,7 +95,7 @@ namespace Grpc.Core.Internal protected override bool ReleaseHandle() { - grpcsharp_metadata_array_destroy_full(handle); + Native.grpcsharp_metadata_array_destroy_full(handle); return true; } } diff --git a/src/csharp/Grpc.Core/Internal/NativeExtension.cs b/src/csharp/Grpc.Core/Internal/NativeExtension.cs new file mode 100644 index 0000000000..137533b3ef --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/NativeExtension.cs @@ -0,0 +1,158 @@ +#region Copyright notice and license + +// Copyright 2015-2016, 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.IO; +using System.Reflection; + +using Grpc.Core.Logging; + +namespace Grpc.Core.Internal +{ + /// <summary> + /// Takes care of loading C# native extension and provides access to PInvoke calls the library exports. + /// </summary> + internal sealed class NativeExtension + { + const string NativeLibrariesDir = "nativelibs"; + + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<NativeExtension>(); + static readonly object staticLock = new object(); + static volatile NativeExtension instance; + + readonly NativeMethods nativeMethods; + + private NativeExtension() + { + this.nativeMethods = new NativeMethods(Load()); + + // Redirect the the native logs as the very first thing after loading the native extension + // to make sure we don't lose any logs. + NativeLogRedirector.Redirect(this.nativeMethods); + + Logger.Debug("gRPC native library loaded successfully."); + } + + /// <summary> + /// Gets singleton instance of this class. + /// The native extension is loaded when called for the first time. + /// </summary> + public static NativeExtension Get() + { + if (instance == null) + { + lock (staticLock) + { + if (instance == null) { + instance = new NativeExtension(); + } + } + } + return instance; + } + + /// <summary> + /// Provides access to the exported native methods. + /// </summary> + public NativeMethods NativeMethods + { + get { return this.nativeMethods; } + } + + /// <summary> + /// Detects which configuration of native extension to load and load it. + /// </summary> + private static UnmanagedLibrary Load() + { + // TODO: allow customizing path to native extension (possibly through exposing a GrpcEnvironment property). + + var libraryFlavor = string.Format("{0}_{1}", GetPlatformString(), GetArchitectureString()); + var fullPath = Path.Combine(GetExecutingAssemblyDirectory(), + NativeLibrariesDir, libraryFlavor, GetNativeLibraryFilename()); + return new UnmanagedLibrary(fullPath); + } + + private static string GetExecutingAssemblyDirectory() + { + return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + } + + private static string GetPlatformString() + { + if (PlatformApis.IsWindows) + { + return "windows"; + } + if (PlatformApis.IsLinux) + { + return "linux"; + } + if (PlatformApis.IsMacOSX) + { + return "macosx"; + } + throw new InvalidOperationException("Unsupported platform."); + } + + // Currently, only Intel platform is supported. + private static string GetArchitectureString() + { + if (PlatformApis.Is64Bit) + { + return "x64"; + } + else + { + return "x86"; + } + } + + // platform specific file name of the extension library + private static string GetNativeLibraryFilename() + { + if (PlatformApis.IsWindows) + { + return "grpc_csharp_ext.dll"; + } + if (PlatformApis.IsLinux) + { + return "libgrpc_csharp_ext.so"; + } + if (PlatformApis.IsMacOSX) + { + return "libgrpc_csharp_ext.dylib"; + } + throw new InvalidOperationException("Unsupported platform."); + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/NativeLogRedirector.cs b/src/csharp/Grpc.Core/Internal/NativeLogRedirector.cs index b8a55c5fe8..4bbbb4808c 100644 --- a/src/csharp/Grpc.Core/Internal/NativeLogRedirector.cs +++ b/src/csharp/Grpc.Core/Internal/NativeLogRedirector.cs @@ -1,6 +1,6 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -51,20 +51,17 @@ namespace Grpc.Core.Internal static object staticLock = new object(); static GprLogDelegate writeCallback; - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_redirect_log(GprLogDelegate callback); - /// <summary> /// Redirects logs from native gRPC C core library to a general logger. /// </summary> - public static void Redirect() + public static void Redirect(NativeMethods native) { lock (staticLock) { if (writeCallback == null) { writeCallback = new GprLogDelegate(HandleWrite); - grpcsharp_redirect_log(writeCallback); + native.grpcsharp_redirect_log(writeCallback); } } } diff --git a/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs index 8bb646d303..36b865c09c 100644 --- a/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs +++ b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs @@ -1,5 +1,5 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -44,12 +44,7 @@ namespace Grpc.Core.Internal { const string GetMetadataExceptionMsg = "Exception occured in metadata credentials plugin."; static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<NativeMetadataCredentialsPlugin>(); - - [DllImport("grpc_csharp_ext.dll")] - static extern CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(NativeMetadataInterceptor interceptor); - - [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - static extern void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails); + static readonly NativeMethods Native = NativeMethods.Get(); AsyncAuthInterceptor interceptor; GCHandle gcHandle; @@ -63,7 +58,7 @@ namespace Grpc.Core.Internal // Make sure the callback doesn't get garbage collected until it is destroyed. this.gcHandle = GCHandle.Alloc(this.nativeInterceptor, GCHandleType.Normal); - this.credentials = grpcsharp_metadata_credentials_create_from_plugin(nativeInterceptor); + this.credentials = Native.grpcsharp_metadata_credentials_create_from_plugin(nativeInterceptor); } public CallCredentialsSafeHandle Credentials @@ -87,7 +82,7 @@ namespace Grpc.Core.Internal } catch (Exception e) { - grpcsharp_metadata_credentials_notify_from_plugin(callbackPtr, userDataPtr, MetadataArraySafeHandle.Create(Metadata.Empty), StatusCode.Unknown, GetMetadataExceptionMsg); + Native.grpcsharp_metadata_credentials_notify_from_plugin(callbackPtr, userDataPtr, MetadataArraySafeHandle.Create(Metadata.Empty), StatusCode.Unknown, GetMetadataExceptionMsg); Logger.Error(e, GetMetadataExceptionMsg); } } @@ -101,12 +96,12 @@ namespace Grpc.Core.Internal using (var metadataArray = MetadataArraySafeHandle.Create(metadata)) { - grpcsharp_metadata_credentials_notify_from_plugin(callbackPtr, userDataPtr, metadataArray, StatusCode.OK, null); + Native.grpcsharp_metadata_credentials_notify_from_plugin(callbackPtr, userDataPtr, metadataArray, StatusCode.OK, null); } } catch (Exception e) { - grpcsharp_metadata_credentials_notify_from_plugin(callbackPtr, userDataPtr, MetadataArraySafeHandle.Create(Metadata.Empty), StatusCode.Unknown, GetMetadataExceptionMsg); + Native.grpcsharp_metadata_credentials_notify_from_plugin(callbackPtr, userDataPtr, MetadataArraySafeHandle.Create(Metadata.Empty), StatusCode.Unknown, GetMetadataExceptionMsg); Logger.Error(e, GetMetadataExceptionMsg); } } diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.cs new file mode 100644 index 0000000000..af37d61c73 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/NativeMethods.cs @@ -0,0 +1,816 @@ +#region Copyright notice and license + +// Copyright 2015-2016, 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.Concurrent; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; + +using Grpc.Core.Logging; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// <summary> + /// Provides access to all native methods provided by <c>NativeExtension</c>. + /// An extra level of indirection is added to P/Invoke calls to allow intelligent loading + /// of the right configuration of the native extension based on current platform, architecture etc. + /// </summary> + internal class NativeMethods + { + #region Native methods + + public readonly Delegates.grpcsharp_init_delegate grpcsharp_init; + public readonly Delegates.grpcsharp_shutdown_delegate grpcsharp_shutdown; + public readonly Delegates.grpcsharp_version_string_delegate grpcsharp_version_string; + + public readonly Delegates.grpcsharp_batch_context_create_delegate grpcsharp_batch_context_create; + public readonly Delegates.grpcsharp_batch_context_recv_initial_metadata_delegate grpcsharp_batch_context_recv_initial_metadata; + public readonly Delegates.grpcsharp_batch_context_recv_message_length_delegate grpcsharp_batch_context_recv_message_length; + public readonly Delegates.grpcsharp_batch_context_recv_message_to_buffer_delegate grpcsharp_batch_context_recv_message_to_buffer; + public readonly Delegates.grpcsharp_batch_context_recv_status_on_client_status_delegate grpcsharp_batch_context_recv_status_on_client_status; + public readonly Delegates.grpcsharp_batch_context_recv_status_on_client_details_delegate grpcsharp_batch_context_recv_status_on_client_details; + public readonly Delegates.grpcsharp_batch_context_recv_status_on_client_trailing_metadata_delegate grpcsharp_batch_context_recv_status_on_client_trailing_metadata; + public readonly Delegates.grpcsharp_batch_context_server_rpc_new_call_delegate grpcsharp_batch_context_server_rpc_new_call; + public readonly Delegates.grpcsharp_batch_context_server_rpc_new_method_delegate grpcsharp_batch_context_server_rpc_new_method; + public readonly Delegates.grpcsharp_batch_context_server_rpc_new_host_delegate grpcsharp_batch_context_server_rpc_new_host; + public readonly Delegates.grpcsharp_batch_context_server_rpc_new_deadline_delegate grpcsharp_batch_context_server_rpc_new_deadline; + public readonly Delegates.grpcsharp_batch_context_server_rpc_new_request_metadata_delegate grpcsharp_batch_context_server_rpc_new_request_metadata; + public readonly Delegates.grpcsharp_batch_context_recv_close_on_server_cancelled_delegate grpcsharp_batch_context_recv_close_on_server_cancelled; + public readonly Delegates.grpcsharp_batch_context_destroy_delegate grpcsharp_batch_context_destroy; + + public readonly Delegates.grpcsharp_composite_call_credentials_create_delegate grpcsharp_composite_call_credentials_create; + public readonly Delegates.grpcsharp_call_credentials_release_delegate grpcsharp_call_credentials_release; + + public readonly Delegates.grpcsharp_call_cancel_delegate grpcsharp_call_cancel; + public readonly Delegates.grpcsharp_call_cancel_with_status_delegate grpcsharp_call_cancel_with_status; + public readonly Delegates.grpcsharp_call_start_unary_delegate grpcsharp_call_start_unary; + public readonly Delegates.grpcsharp_call_start_client_streaming_delegate grpcsharp_call_start_client_streaming; + public readonly Delegates.grpcsharp_call_start_server_streaming_delegate grpcsharp_call_start_server_streaming; + public readonly Delegates.grpcsharp_call_start_duplex_streaming_delegate grpcsharp_call_start_duplex_streaming; + public readonly Delegates.grpcsharp_call_send_message_delegate grpcsharp_call_send_message; + public readonly Delegates.grpcsharp_call_send_close_from_client_delegate grpcsharp_call_send_close_from_client; + public readonly Delegates.grpcsharp_call_send_status_from_server_delegate grpcsharp_call_send_status_from_server; + public readonly Delegates.grpcsharp_call_recv_message_delegate grpcsharp_call_recv_message; + public readonly Delegates.grpcsharp_call_recv_initial_metadata_delegate grpcsharp_call_recv_initial_metadata; + public readonly Delegates.grpcsharp_call_start_serverside_delegate grpcsharp_call_start_serverside; + public readonly Delegates.grpcsharp_call_send_initial_metadata_delegate grpcsharp_call_send_initial_metadata; + public readonly Delegates.grpcsharp_call_set_credentials_delegate grpcsharp_call_set_credentials; + public readonly Delegates.grpcsharp_call_get_peer_delegate grpcsharp_call_get_peer; + public readonly Delegates.grpcsharp_call_destroy_delegate grpcsharp_call_destroy; + + public readonly Delegates.grpcsharp_channel_args_create_delegate grpcsharp_channel_args_create; + public readonly Delegates.grpcsharp_channel_args_set_string_delegate grpcsharp_channel_args_set_string; + public readonly Delegates.grpcsharp_channel_args_set_integer_delegate grpcsharp_channel_args_set_integer; + public readonly Delegates.grpcsharp_channel_args_destroy_delegate grpcsharp_channel_args_destroy; + + public readonly Delegates.grpcsharp_ssl_credentials_create_delegate grpcsharp_ssl_credentials_create; + public readonly Delegates.grpcsharp_composite_channel_credentials_create_delegate grpcsharp_composite_channel_credentials_create; + public readonly Delegates.grpcsharp_channel_credentials_release_delegate grpcsharp_channel_credentials_release; + + public readonly Delegates.grpcsharp_insecure_channel_create_delegate grpcsharp_insecure_channel_create; + public readonly Delegates.grpcsharp_secure_channel_create_delegate grpcsharp_secure_channel_create; + public readonly Delegates.grpcsharp_channel_create_call_delegate grpcsharp_channel_create_call; + public readonly Delegates.grpcsharp_channel_check_connectivity_state_delegate grpcsharp_channel_check_connectivity_state; + public readonly Delegates.grpcsharp_channel_watch_connectivity_state_delegate grpcsharp_channel_watch_connectivity_state; + public readonly Delegates.grpcsharp_channel_get_target_delegate grpcsharp_channel_get_target; + public readonly Delegates.grpcsharp_channel_destroy_delegate grpcsharp_channel_destroy; + + public readonly Delegates.grpcsharp_sizeof_grpc_event_delegate grpcsharp_sizeof_grpc_event; + + public readonly Delegates.grpcsharp_completion_queue_create_delegate grpcsharp_completion_queue_create; + public readonly Delegates.grpcsharp_completion_queue_shutdown_delegate grpcsharp_completion_queue_shutdown; + public readonly Delegates.grpcsharp_completion_queue_next_delegate grpcsharp_completion_queue_next; + public readonly Delegates.grpcsharp_completion_queue_pluck_delegate grpcsharp_completion_queue_pluck; + public readonly Delegates.grpcsharp_completion_queue_destroy_delegate grpcsharp_completion_queue_destroy; + + public readonly Delegates.gprsharp_free_delegate gprsharp_free; + + public readonly Delegates.grpcsharp_metadata_array_create_delegate grpcsharp_metadata_array_create; + public readonly Delegates.grpcsharp_metadata_array_add_delegate grpcsharp_metadata_array_add; + public readonly Delegates.grpcsharp_metadata_array_count_delegate grpcsharp_metadata_array_count; + public readonly Delegates.grpcsharp_metadata_array_get_key_delegate grpcsharp_metadata_array_get_key; + public readonly Delegates.grpcsharp_metadata_array_get_value_delegate grpcsharp_metadata_array_get_value; + public readonly Delegates.grpcsharp_metadata_array_get_value_length_delegate grpcsharp_metadata_array_get_value_length; + public readonly Delegates.grpcsharp_metadata_array_destroy_full_delegate grpcsharp_metadata_array_destroy_full; + + public readonly Delegates.grpcsharp_redirect_log_delegate grpcsharp_redirect_log; + + public readonly Delegates.grpcsharp_metadata_credentials_create_from_plugin_delegate grpcsharp_metadata_credentials_create_from_plugin; + public readonly Delegates.grpcsharp_metadata_credentials_notify_from_plugin_delegate grpcsharp_metadata_credentials_notify_from_plugin; + + public readonly Delegates.grpcsharp_ssl_server_credentials_create_delegate grpcsharp_ssl_server_credentials_create; + public readonly Delegates.grpcsharp_server_credentials_release_delegate grpcsharp_server_credentials_release; + + public readonly Delegates.grpcsharp_server_create_delegate grpcsharp_server_create; + public readonly Delegates.grpcsharp_server_add_insecure_http2_port_delegate grpcsharp_server_add_insecure_http2_port; + public readonly Delegates.grpcsharp_server_add_secure_http2_port_delegate grpcsharp_server_add_secure_http2_port; + public readonly Delegates.grpcsharp_server_start_delegate grpcsharp_server_start; + public readonly Delegates.grpcsharp_server_request_call_delegate grpcsharp_server_request_call; + public readonly Delegates.grpcsharp_server_cancel_all_calls_delegate grpcsharp_server_cancel_all_calls; + public readonly Delegates.grpcsharp_server_shutdown_and_notify_callback_delegate grpcsharp_server_shutdown_and_notify_callback; + public readonly Delegates.grpcsharp_server_destroy_delegate grpcsharp_server_destroy; + + public readonly Delegates.gprsharp_now_delegate gprsharp_now; + public readonly Delegates.gprsharp_inf_future_delegate gprsharp_inf_future; + public readonly Delegates.gprsharp_inf_past_delegate gprsharp_inf_past; + public readonly Delegates.gprsharp_convert_clock_type_delegate gprsharp_convert_clock_type; + public readonly Delegates.gprsharp_sizeof_timespec_delegate gprsharp_sizeof_timespec; + + public readonly Delegates.grpcsharp_test_callback_delegate grpcsharp_test_callback; + public readonly Delegates.grpcsharp_test_nop_delegate grpcsharp_test_nop; + + #endregion + + public NativeMethods(UnmanagedLibrary library) + { + if (PlatformApis.IsLinux || PlatformApis.IsMacOSX) + { + this.grpcsharp_init = GetMethodDelegate<Delegates.grpcsharp_init_delegate>(library); + this.grpcsharp_shutdown = GetMethodDelegate<Delegates.grpcsharp_shutdown_delegate>(library); + this.grpcsharp_version_string = GetMethodDelegate<Delegates.grpcsharp_version_string_delegate>(library); + + this.grpcsharp_batch_context_create = GetMethodDelegate<Delegates.grpcsharp_batch_context_create_delegate>(library); + this.grpcsharp_batch_context_recv_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_initial_metadata_delegate>(library); + this.grpcsharp_batch_context_recv_message_length = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_message_length_delegate>(library); + this.grpcsharp_batch_context_recv_message_to_buffer = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_message_to_buffer_delegate>(library); + this.grpcsharp_batch_context_recv_status_on_client_status = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_status_delegate>(library); + this.grpcsharp_batch_context_recv_status_on_client_details = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_details_delegate>(library); + this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_status_on_client_trailing_metadata_delegate>(library); + this.grpcsharp_batch_context_server_rpc_new_call = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_call_delegate>(library); + this.grpcsharp_batch_context_server_rpc_new_method = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_method_delegate>(library); + this.grpcsharp_batch_context_server_rpc_new_host = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_host_delegate>(library); + this.grpcsharp_batch_context_server_rpc_new_deadline = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_deadline_delegate>(library); + this.grpcsharp_batch_context_server_rpc_new_request_metadata = GetMethodDelegate<Delegates.grpcsharp_batch_context_server_rpc_new_request_metadata_delegate>(library); + this.grpcsharp_batch_context_recv_close_on_server_cancelled = GetMethodDelegate<Delegates.grpcsharp_batch_context_recv_close_on_server_cancelled_delegate>(library); + this.grpcsharp_batch_context_destroy = GetMethodDelegate<Delegates.grpcsharp_batch_context_destroy_delegate>(library); + + this.grpcsharp_composite_call_credentials_create = GetMethodDelegate<Delegates.grpcsharp_composite_call_credentials_create_delegate>(library); + this.grpcsharp_call_credentials_release = GetMethodDelegate<Delegates.grpcsharp_call_credentials_release_delegate>(library); + + this.grpcsharp_call_cancel = GetMethodDelegate<Delegates.grpcsharp_call_cancel_delegate>(library); + this.grpcsharp_call_cancel_with_status = GetMethodDelegate<Delegates.grpcsharp_call_cancel_with_status_delegate>(library); + this.grpcsharp_call_start_unary = GetMethodDelegate<Delegates.grpcsharp_call_start_unary_delegate>(library); + this.grpcsharp_call_start_client_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_client_streaming_delegate>(library); + this.grpcsharp_call_start_server_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_server_streaming_delegate>(library); + this.grpcsharp_call_start_duplex_streaming = GetMethodDelegate<Delegates.grpcsharp_call_start_duplex_streaming_delegate>(library); + this.grpcsharp_call_send_message = GetMethodDelegate<Delegates.grpcsharp_call_send_message_delegate>(library); + this.grpcsharp_call_send_close_from_client = GetMethodDelegate<Delegates.grpcsharp_call_send_close_from_client_delegate>(library); + this.grpcsharp_call_send_status_from_server = GetMethodDelegate<Delegates.grpcsharp_call_send_status_from_server_delegate>(library); + this.grpcsharp_call_recv_message = GetMethodDelegate<Delegates.grpcsharp_call_recv_message_delegate>(library); + this.grpcsharp_call_recv_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_call_recv_initial_metadata_delegate>(library); + this.grpcsharp_call_start_serverside = GetMethodDelegate<Delegates.grpcsharp_call_start_serverside_delegate>(library); + this.grpcsharp_call_send_initial_metadata = GetMethodDelegate<Delegates.grpcsharp_call_send_initial_metadata_delegate>(library); + this.grpcsharp_call_set_credentials = GetMethodDelegate<Delegates.grpcsharp_call_set_credentials_delegate>(library); + this.grpcsharp_call_get_peer = GetMethodDelegate<Delegates.grpcsharp_call_get_peer_delegate>(library); + this.grpcsharp_call_destroy = GetMethodDelegate<Delegates.grpcsharp_call_destroy_delegate>(library); + + this.grpcsharp_channel_args_create = GetMethodDelegate<Delegates.grpcsharp_channel_args_create_delegate>(library); + this.grpcsharp_channel_args_set_string = GetMethodDelegate<Delegates.grpcsharp_channel_args_set_string_delegate>(library); + this.grpcsharp_channel_args_set_integer = GetMethodDelegate<Delegates.grpcsharp_channel_args_set_integer_delegate>(library); + this.grpcsharp_channel_args_destroy = GetMethodDelegate<Delegates.grpcsharp_channel_args_destroy_delegate>(library); + + this.grpcsharp_ssl_credentials_create = GetMethodDelegate<Delegates.grpcsharp_ssl_credentials_create_delegate>(library); + this.grpcsharp_composite_channel_credentials_create = GetMethodDelegate<Delegates.grpcsharp_composite_channel_credentials_create_delegate>(library); + this.grpcsharp_channel_credentials_release = GetMethodDelegate<Delegates.grpcsharp_channel_credentials_release_delegate>(library); + + this.grpcsharp_insecure_channel_create = GetMethodDelegate<Delegates.grpcsharp_insecure_channel_create_delegate>(library); + this.grpcsharp_secure_channel_create = GetMethodDelegate<Delegates.grpcsharp_secure_channel_create_delegate>(library); + this.grpcsharp_channel_create_call = GetMethodDelegate<Delegates.grpcsharp_channel_create_call_delegate>(library); + this.grpcsharp_channel_check_connectivity_state = GetMethodDelegate<Delegates.grpcsharp_channel_check_connectivity_state_delegate>(library); + this.grpcsharp_channel_watch_connectivity_state = GetMethodDelegate<Delegates.grpcsharp_channel_watch_connectivity_state_delegate>(library); + this.grpcsharp_channel_get_target = GetMethodDelegate<Delegates.grpcsharp_channel_get_target_delegate>(library); + this.grpcsharp_channel_destroy = GetMethodDelegate<Delegates.grpcsharp_channel_destroy_delegate>(library); + + this.grpcsharp_sizeof_grpc_event = GetMethodDelegate<Delegates.grpcsharp_sizeof_grpc_event_delegate>(library); + + this.grpcsharp_completion_queue_create = GetMethodDelegate<Delegates.grpcsharp_completion_queue_create_delegate>(library); + this.grpcsharp_completion_queue_shutdown = GetMethodDelegate<Delegates.grpcsharp_completion_queue_shutdown_delegate>(library); + this.grpcsharp_completion_queue_next = GetMethodDelegate<Delegates.grpcsharp_completion_queue_next_delegate>(library); + this.grpcsharp_completion_queue_pluck = GetMethodDelegate<Delegates.grpcsharp_completion_queue_pluck_delegate>(library); + this.grpcsharp_completion_queue_destroy = GetMethodDelegate<Delegates.grpcsharp_completion_queue_destroy_delegate>(library); + + this.gprsharp_free = GetMethodDelegate<Delegates.gprsharp_free_delegate>(library); + + this.grpcsharp_metadata_array_create = GetMethodDelegate<Delegates.grpcsharp_metadata_array_create_delegate>(library); + this.grpcsharp_metadata_array_add = GetMethodDelegate<Delegates.grpcsharp_metadata_array_add_delegate>(library); + this.grpcsharp_metadata_array_count = GetMethodDelegate<Delegates.grpcsharp_metadata_array_count_delegate>(library); + this.grpcsharp_metadata_array_get_key = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_key_delegate>(library); + this.grpcsharp_metadata_array_get_value = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_value_delegate>(library); + this.grpcsharp_metadata_array_get_value_length = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_value_length_delegate>(library); + this.grpcsharp_metadata_array_destroy_full = GetMethodDelegate<Delegates.grpcsharp_metadata_array_destroy_full_delegate>(library); + + this.grpcsharp_redirect_log = GetMethodDelegate<Delegates.grpcsharp_redirect_log_delegate>(library); + + this.grpcsharp_metadata_credentials_create_from_plugin = GetMethodDelegate<Delegates.grpcsharp_metadata_credentials_create_from_plugin_delegate>(library); + this.grpcsharp_metadata_credentials_notify_from_plugin = GetMethodDelegate<Delegates.grpcsharp_metadata_credentials_notify_from_plugin_delegate>(library); + + this.grpcsharp_ssl_server_credentials_create = GetMethodDelegate<Delegates.grpcsharp_ssl_server_credentials_create_delegate>(library); + this.grpcsharp_server_credentials_release = GetMethodDelegate<Delegates.grpcsharp_server_credentials_release_delegate>(library); + + this.grpcsharp_server_create = GetMethodDelegate<Delegates.grpcsharp_server_create_delegate>(library); + this.grpcsharp_server_add_insecure_http2_port = GetMethodDelegate<Delegates.grpcsharp_server_add_insecure_http2_port_delegate>(library); + this.grpcsharp_server_add_secure_http2_port = GetMethodDelegate<Delegates.grpcsharp_server_add_secure_http2_port_delegate>(library); + this.grpcsharp_server_start = GetMethodDelegate<Delegates.grpcsharp_server_start_delegate>(library); + this.grpcsharp_server_request_call = GetMethodDelegate<Delegates.grpcsharp_server_request_call_delegate>(library); + this.grpcsharp_server_cancel_all_calls = GetMethodDelegate<Delegates.grpcsharp_server_cancel_all_calls_delegate>(library); + this.grpcsharp_server_shutdown_and_notify_callback = GetMethodDelegate<Delegates.grpcsharp_server_shutdown_and_notify_callback_delegate>(library); + this.grpcsharp_server_destroy = GetMethodDelegate<Delegates.grpcsharp_server_destroy_delegate>(library); + + this.gprsharp_now = GetMethodDelegate<Delegates.gprsharp_now_delegate>(library); + this.gprsharp_inf_future = GetMethodDelegate<Delegates.gprsharp_inf_future_delegate>(library); + this.gprsharp_inf_past = GetMethodDelegate<Delegates.gprsharp_inf_past_delegate>(library); + this.gprsharp_convert_clock_type = GetMethodDelegate<Delegates.gprsharp_convert_clock_type_delegate>(library); + this.gprsharp_sizeof_timespec = GetMethodDelegate<Delegates.gprsharp_sizeof_timespec_delegate>(library); + + this.grpcsharp_test_callback = GetMethodDelegate<Delegates.grpcsharp_test_callback_delegate>(library); + this.grpcsharp_test_nop = GetMethodDelegate<Delegates.grpcsharp_test_nop_delegate>(library); + } + else + { + // Windows or fallback + this.grpcsharp_init = PInvokeMethods.grpcsharp_init; + this.grpcsharp_shutdown = PInvokeMethods.grpcsharp_shutdown; + this.grpcsharp_version_string = PInvokeMethods.grpcsharp_version_string; + + this.grpcsharp_batch_context_create = PInvokeMethods.grpcsharp_batch_context_create; + this.grpcsharp_batch_context_recv_initial_metadata = PInvokeMethods.grpcsharp_batch_context_recv_initial_metadata; + this.grpcsharp_batch_context_recv_message_length = PInvokeMethods.grpcsharp_batch_context_recv_message_length; + this.grpcsharp_batch_context_recv_message_to_buffer = PInvokeMethods.grpcsharp_batch_context_recv_message_to_buffer; + this.grpcsharp_batch_context_recv_status_on_client_status = PInvokeMethods.grpcsharp_batch_context_recv_status_on_client_status; + this.grpcsharp_batch_context_recv_status_on_client_details = PInvokeMethods.grpcsharp_batch_context_recv_status_on_client_details; + this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = PInvokeMethods.grpcsharp_batch_context_recv_status_on_client_trailing_metadata; + this.grpcsharp_batch_context_server_rpc_new_call = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_call; + this.grpcsharp_batch_context_server_rpc_new_method = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_method; + this.grpcsharp_batch_context_server_rpc_new_host = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_host; + this.grpcsharp_batch_context_server_rpc_new_deadline = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_deadline; + this.grpcsharp_batch_context_server_rpc_new_request_metadata = PInvokeMethods.grpcsharp_batch_context_server_rpc_new_request_metadata; + this.grpcsharp_batch_context_recv_close_on_server_cancelled = PInvokeMethods.grpcsharp_batch_context_recv_close_on_server_cancelled; + this.grpcsharp_batch_context_destroy = PInvokeMethods.grpcsharp_batch_context_destroy; + + this.grpcsharp_composite_call_credentials_create = PInvokeMethods.grpcsharp_composite_call_credentials_create; + this.grpcsharp_call_credentials_release = PInvokeMethods.grpcsharp_call_credentials_release; + + this.grpcsharp_call_cancel = PInvokeMethods.grpcsharp_call_cancel; + this.grpcsharp_call_cancel_with_status = PInvokeMethods.grpcsharp_call_cancel_with_status; + this.grpcsharp_call_start_unary = PInvokeMethods.grpcsharp_call_start_unary; + this.grpcsharp_call_start_client_streaming = PInvokeMethods.grpcsharp_call_start_client_streaming; + this.grpcsharp_call_start_server_streaming = PInvokeMethods.grpcsharp_call_start_server_streaming; + this.grpcsharp_call_start_duplex_streaming = PInvokeMethods.grpcsharp_call_start_duplex_streaming; + this.grpcsharp_call_send_message = PInvokeMethods.grpcsharp_call_send_message; + this.grpcsharp_call_send_close_from_client = PInvokeMethods.grpcsharp_call_send_close_from_client; + this.grpcsharp_call_send_status_from_server = PInvokeMethods.grpcsharp_call_send_status_from_server; + this.grpcsharp_call_recv_message = PInvokeMethods.grpcsharp_call_recv_message; + this.grpcsharp_call_recv_initial_metadata = PInvokeMethods.grpcsharp_call_recv_initial_metadata; + this.grpcsharp_call_start_serverside = PInvokeMethods.grpcsharp_call_start_serverside; + this.grpcsharp_call_send_initial_metadata = PInvokeMethods.grpcsharp_call_send_initial_metadata; + this.grpcsharp_call_set_credentials = PInvokeMethods.grpcsharp_call_set_credentials; + this.grpcsharp_call_get_peer = PInvokeMethods.grpcsharp_call_get_peer; + this.grpcsharp_call_destroy = PInvokeMethods.grpcsharp_call_destroy; + + this.grpcsharp_channel_args_create = PInvokeMethods.grpcsharp_channel_args_create; + this.grpcsharp_channel_args_set_string = PInvokeMethods.grpcsharp_channel_args_set_string; + this.grpcsharp_channel_args_set_integer = PInvokeMethods.grpcsharp_channel_args_set_integer; + this.grpcsharp_channel_args_destroy = PInvokeMethods.grpcsharp_channel_args_destroy; + + this.grpcsharp_ssl_credentials_create = PInvokeMethods.grpcsharp_ssl_credentials_create; + this.grpcsharp_composite_channel_credentials_create = PInvokeMethods.grpcsharp_composite_channel_credentials_create; + this.grpcsharp_channel_credentials_release = PInvokeMethods.grpcsharp_channel_credentials_release; + + this.grpcsharp_insecure_channel_create = PInvokeMethods.grpcsharp_insecure_channel_create; + this.grpcsharp_secure_channel_create = PInvokeMethods.grpcsharp_secure_channel_create; + this.grpcsharp_channel_create_call = PInvokeMethods.grpcsharp_channel_create_call; + this.grpcsharp_channel_check_connectivity_state = PInvokeMethods.grpcsharp_channel_check_connectivity_state; + this.grpcsharp_channel_watch_connectivity_state = PInvokeMethods.grpcsharp_channel_watch_connectivity_state; + this.grpcsharp_channel_get_target = PInvokeMethods.grpcsharp_channel_get_target; + this.grpcsharp_channel_destroy = PInvokeMethods.grpcsharp_channel_destroy; + + this.grpcsharp_sizeof_grpc_event = PInvokeMethods.grpcsharp_sizeof_grpc_event; + + this.grpcsharp_completion_queue_create = PInvokeMethods.grpcsharp_completion_queue_create; + this.grpcsharp_completion_queue_shutdown = PInvokeMethods.grpcsharp_completion_queue_shutdown; + this.grpcsharp_completion_queue_next = PInvokeMethods.grpcsharp_completion_queue_next; + this.grpcsharp_completion_queue_pluck = PInvokeMethods.grpcsharp_completion_queue_pluck; + this.grpcsharp_completion_queue_destroy = PInvokeMethods.grpcsharp_completion_queue_destroy; + + this.gprsharp_free = PInvokeMethods.gprsharp_free; + + this.grpcsharp_metadata_array_create = PInvokeMethods.grpcsharp_metadata_array_create; + this.grpcsharp_metadata_array_add = PInvokeMethods.grpcsharp_metadata_array_add; + this.grpcsharp_metadata_array_count = PInvokeMethods.grpcsharp_metadata_array_count; + this.grpcsharp_metadata_array_get_key = PInvokeMethods.grpcsharp_metadata_array_get_key; + this.grpcsharp_metadata_array_get_value = PInvokeMethods.grpcsharp_metadata_array_get_value; + this.grpcsharp_metadata_array_get_value_length = PInvokeMethods.grpcsharp_metadata_array_get_value_length; + this.grpcsharp_metadata_array_destroy_full = PInvokeMethods.grpcsharp_metadata_array_destroy_full; + + this.grpcsharp_redirect_log = PInvokeMethods.grpcsharp_redirect_log; + + this.grpcsharp_metadata_credentials_create_from_plugin = PInvokeMethods.grpcsharp_metadata_credentials_create_from_plugin; + this.grpcsharp_metadata_credentials_notify_from_plugin = PInvokeMethods.grpcsharp_metadata_credentials_notify_from_plugin; + + this.grpcsharp_ssl_server_credentials_create = PInvokeMethods.grpcsharp_ssl_server_credentials_create; + this.grpcsharp_server_credentials_release = PInvokeMethods.grpcsharp_server_credentials_release; + + this.grpcsharp_server_create = PInvokeMethods.grpcsharp_server_create; + this.grpcsharp_server_add_insecure_http2_port = PInvokeMethods.grpcsharp_server_add_insecure_http2_port; + this.grpcsharp_server_add_secure_http2_port = PInvokeMethods.grpcsharp_server_add_secure_http2_port; + this.grpcsharp_server_start = PInvokeMethods.grpcsharp_server_start; + this.grpcsharp_server_request_call = PInvokeMethods.grpcsharp_server_request_call; + this.grpcsharp_server_cancel_all_calls = PInvokeMethods.grpcsharp_server_cancel_all_calls; + this.grpcsharp_server_shutdown_and_notify_callback = PInvokeMethods.grpcsharp_server_shutdown_and_notify_callback; + this.grpcsharp_server_destroy = PInvokeMethods.grpcsharp_server_destroy; + + this.gprsharp_now = PInvokeMethods.gprsharp_now; + this.gprsharp_inf_future = PInvokeMethods.gprsharp_inf_future; + this.gprsharp_inf_past = PInvokeMethods.gprsharp_inf_past; + this.gprsharp_convert_clock_type = PInvokeMethods.gprsharp_convert_clock_type; + this.gprsharp_sizeof_timespec = PInvokeMethods.gprsharp_sizeof_timespec; + + this.grpcsharp_test_callback = PInvokeMethods.grpcsharp_test_callback; + this.grpcsharp_test_nop = PInvokeMethods.grpcsharp_test_nop; + } + } + + /// <summary> + /// Gets singleton instance of this class. + /// </summary> + public static NativeMethods Get() + { + return NativeExtension.Get().NativeMethods; + } + + static T GetMethodDelegate<T>(UnmanagedLibrary library) + where T : class + { + var methodName = RemoveStringSuffix(typeof(T).Name, "_delegate"); + return library.GetNativeMethodDelegate<T>(methodName); + } + + static string RemoveStringSuffix(string str, string toRemove) + { + if (!str.EndsWith(toRemove)) + { + return str; + } + return str.Substring(0, str.Length - toRemove.Length); + } + + /// <summary> + /// Delegate types for all published native methods. Declared under inner class to prevent scope pollution. + /// </summary> + public class Delegates + { + public delegate void grpcsharp_init_delegate(); + public delegate void grpcsharp_shutdown_delegate(); + public delegate IntPtr grpcsharp_version_string_delegate(); // returns not-owned const char* + + public delegate BatchContextSafeHandle grpcsharp_batch_context_create_delegate(); + public delegate IntPtr grpcsharp_batch_context_recv_initial_metadata_delegate(BatchContextSafeHandle ctx); + public delegate IntPtr grpcsharp_batch_context_recv_message_length_delegate(BatchContextSafeHandle ctx); + public delegate void grpcsharp_batch_context_recv_message_to_buffer_delegate(BatchContextSafeHandle ctx, byte[] buffer, UIntPtr bufferLen); + public delegate StatusCode grpcsharp_batch_context_recv_status_on_client_status_delegate(BatchContextSafeHandle ctx); + public delegate IntPtr grpcsharp_batch_context_recv_status_on_client_details_delegate(BatchContextSafeHandle ctx); // returns const char* + public delegate IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata_delegate(BatchContextSafeHandle ctx); + public delegate CallSafeHandle grpcsharp_batch_context_server_rpc_new_call_delegate(BatchContextSafeHandle ctx); + public delegate IntPtr grpcsharp_batch_context_server_rpc_new_method_delegate(BatchContextSafeHandle ctx); // returns const char* + public delegate IntPtr grpcsharp_batch_context_server_rpc_new_host_delegate(BatchContextSafeHandle ctx); // returns const char* + public delegate Timespec grpcsharp_batch_context_server_rpc_new_deadline_delegate(BatchContextSafeHandle ctx); + public delegate IntPtr grpcsharp_batch_context_server_rpc_new_request_metadata_delegate(BatchContextSafeHandle ctx); + public delegate int grpcsharp_batch_context_recv_close_on_server_cancelled_delegate(BatchContextSafeHandle ctx); + public delegate void grpcsharp_batch_context_destroy_delegate(IntPtr ctx); + + public delegate CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create_delegate(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2); + public delegate void grpcsharp_call_credentials_release_delegate(IntPtr credentials); + + public delegate GRPCCallError grpcsharp_call_cancel_delegate(CallSafeHandle call); + public delegate GRPCCallError grpcsharp_call_cancel_with_status_delegate(CallSafeHandle call, StatusCode status, string description); + public delegate GRPCCallError grpcsharp_call_start_unary_delegate(CallSafeHandle call, + BatchContextSafeHandle ctx, byte[] send_buffer, UIntPtr send_buffer_len, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags); + public delegate GRPCCallError grpcsharp_call_start_client_streaming_delegate(CallSafeHandle call, + BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); + public delegate GRPCCallError grpcsharp_call_start_server_streaming_delegate(CallSafeHandle call, + BatchContextSafeHandle ctx, byte[] send_buffer, UIntPtr send_buffer_len, + MetadataArraySafeHandle metadataArray, WriteFlags writeFlags); + public delegate GRPCCallError grpcsharp_call_start_duplex_streaming_delegate(CallSafeHandle call, + BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); + public delegate GRPCCallError grpcsharp_call_send_message_delegate(CallSafeHandle call, + BatchContextSafeHandle ctx, byte[] send_buffer, UIntPtr send_buffer_len, WriteFlags writeFlags, bool sendEmptyInitialMetadata); + public delegate GRPCCallError grpcsharp_call_send_close_from_client_delegate(CallSafeHandle call, + BatchContextSafeHandle ctx); + public delegate GRPCCallError grpcsharp_call_send_status_from_server_delegate(CallSafeHandle call, + BatchContextSafeHandle ctx, StatusCode statusCode, string statusMessage, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata); + public delegate GRPCCallError grpcsharp_call_recv_message_delegate(CallSafeHandle call, + BatchContextSafeHandle ctx); + public delegate GRPCCallError grpcsharp_call_recv_initial_metadata_delegate(CallSafeHandle call, + BatchContextSafeHandle ctx); + public delegate GRPCCallError grpcsharp_call_start_serverside_delegate(CallSafeHandle call, + BatchContextSafeHandle ctx); + public delegate GRPCCallError grpcsharp_call_send_initial_metadata_delegate(CallSafeHandle call, + BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); + public delegate GRPCCallError grpcsharp_call_set_credentials_delegate(CallSafeHandle call, CallCredentialsSafeHandle credentials); + public delegate CStringSafeHandle grpcsharp_call_get_peer_delegate(CallSafeHandle call); + public delegate void grpcsharp_call_destroy_delegate(IntPtr call); + + public delegate ChannelArgsSafeHandle grpcsharp_channel_args_create_delegate(UIntPtr numArgs); + public delegate void grpcsharp_channel_args_set_string_delegate(ChannelArgsSafeHandle args, UIntPtr index, string key, string value); + public delegate void grpcsharp_channel_args_set_integer_delegate(ChannelArgsSafeHandle args, UIntPtr index, string key, int value); + public delegate void grpcsharp_channel_args_destroy_delegate(IntPtr args); + + public delegate ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create_delegate(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey); + public delegate ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create_delegate(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); + public delegate void grpcsharp_channel_credentials_release_delegate(IntPtr credentials); + + public delegate ChannelSafeHandle grpcsharp_insecure_channel_create_delegate(string target, ChannelArgsSafeHandle channelArgs); + public delegate ChannelSafeHandle grpcsharp_secure_channel_create_delegate(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs); + public delegate CallSafeHandle grpcsharp_channel_create_call_delegate(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline); + public delegate ChannelState grpcsharp_channel_check_connectivity_state_delegate(ChannelSafeHandle channel, int tryToConnect); + public delegate void grpcsharp_channel_watch_connectivity_state_delegate(ChannelSafeHandle channel, ChannelState lastObservedState, + Timespec deadline, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + public delegate CStringSafeHandle grpcsharp_channel_get_target_delegate(ChannelSafeHandle call); + public delegate void grpcsharp_channel_destroy_delegate(IntPtr channel); + + public delegate int grpcsharp_sizeof_grpc_event_delegate(); + + public delegate CompletionQueueSafeHandle grpcsharp_completion_queue_create_delegate(); + public delegate void grpcsharp_completion_queue_shutdown_delegate(CompletionQueueSafeHandle cq); + public delegate CompletionQueueEvent grpcsharp_completion_queue_next_delegate(CompletionQueueSafeHandle cq); + public delegate CompletionQueueEvent grpcsharp_completion_queue_pluck_delegate(CompletionQueueSafeHandle cq, IntPtr tag); + public delegate void grpcsharp_completion_queue_destroy_delegate(IntPtr cq); + + public delegate void gprsharp_free_delegate(IntPtr ptr); + + public delegate MetadataArraySafeHandle grpcsharp_metadata_array_create_delegate(UIntPtr capacity); + public delegate void grpcsharp_metadata_array_add_delegate(MetadataArraySafeHandle array, string key, byte[] value, UIntPtr valueLength); + public delegate UIntPtr grpcsharp_metadata_array_count_delegate(IntPtr metadataArray); + public delegate IntPtr grpcsharp_metadata_array_get_key_delegate(IntPtr metadataArray, UIntPtr index); + public delegate IntPtr grpcsharp_metadata_array_get_value_delegate(IntPtr metadataArray, UIntPtr index); + public delegate UIntPtr grpcsharp_metadata_array_get_value_length_delegate(IntPtr metadataArray, UIntPtr index); + public delegate void grpcsharp_metadata_array_destroy_full_delegate(IntPtr array); + + public delegate void grpcsharp_redirect_log_delegate(GprLogDelegate callback); + + public delegate CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin_delegate(NativeMetadataInterceptor interceptor); + public delegate void grpcsharp_metadata_credentials_notify_from_plugin_delegate(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails); + + public delegate ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create_delegate(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, bool forceClientAuth); + public delegate void grpcsharp_server_credentials_release_delegate(IntPtr credentials); + + public delegate ServerSafeHandle grpcsharp_server_create_delegate(CompletionQueueSafeHandle cq, ChannelArgsSafeHandle args); + public delegate int grpcsharp_server_add_insecure_http2_port_delegate(ServerSafeHandle server, string addr); + public delegate int grpcsharp_server_add_secure_http2_port_delegate(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds); + public delegate void grpcsharp_server_start_delegate(ServerSafeHandle server); + public delegate GRPCCallError grpcsharp_server_request_call_delegate(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + public delegate void grpcsharp_server_cancel_all_calls_delegate(ServerSafeHandle server); + public delegate void grpcsharp_server_shutdown_and_notify_callback_delegate(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + public delegate void grpcsharp_server_destroy_delegate(IntPtr server); + + public delegate Timespec gprsharp_now_delegate(GPRClockType clockType); + public delegate Timespec gprsharp_inf_future_delegate(GPRClockType clockType); + public delegate Timespec gprsharp_inf_past_delegate(GPRClockType clockType); + + public delegate Timespec gprsharp_convert_clock_type_delegate(Timespec t, GPRClockType targetClock); + public delegate int gprsharp_sizeof_timespec_delegate(); + + public delegate GRPCCallError grpcsharp_test_callback_delegate([MarshalAs(UnmanagedType.FunctionPtr)] OpCompletionDelegate callback); + public delegate IntPtr grpcsharp_test_nop_delegate(IntPtr ptr); + } + + /// <summary> + /// Default PInvoke bindings for native methods that are used on Windows. + /// Alternatively, they can also be used as a fallback on Mono + /// (if libgrpc_csharp_ext is installed on your system, or is made accessible through e.g. LD_LIBRARY_PATH environment variable + /// or using Mono's dllMap feature). + /// </summary> + private class PInvokeMethods + { + // Environment + + [DllImport("grpc_csharp_ext.dll")] + public static extern void grpcsharp_init(); + + [DllImport("grpc_csharp_ext.dll")] + public static extern void grpcsharp_shutdown(); + + [DllImport("grpc_csharp_ext.dll")] + public static extern IntPtr grpcsharp_version_string(); // returns not-owned const char* + + // BatchContextSafeHandle + + [DllImport("grpc_csharp_ext.dll")] + public static extern BatchContextSafeHandle grpcsharp_batch_context_create(); + + [DllImport("grpc_csharp_ext.dll")] + public static extern IntPtr grpcsharp_batch_context_recv_initial_metadata(BatchContextSafeHandle ctx); + + [DllImport("grpc_csharp_ext.dll")] + public static extern IntPtr grpcsharp_batch_context_recv_message_length(BatchContextSafeHandle ctx); + + [DllImport("grpc_csharp_ext.dll")] + public static extern void grpcsharp_batch_context_recv_message_to_buffer(BatchContextSafeHandle ctx, byte[] buffer, UIntPtr bufferLen); + + [DllImport("grpc_csharp_ext.dll")] + public static extern StatusCode grpcsharp_batch_context_recv_status_on_client_status(BatchContextSafeHandle ctx); + + [DllImport("grpc_csharp_ext.dll")] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_details(BatchContextSafeHandle ctx); // returns const char* + + [DllImport("grpc_csharp_ext.dll")] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata(BatchContextSafeHandle ctx); + + [DllImport("grpc_csharp_ext.dll")] + public static extern CallSafeHandle grpcsharp_batch_context_server_rpc_new_call(BatchContextSafeHandle ctx); + + [DllImport("grpc_csharp_ext.dll")] + public static extern IntPtr grpcsharp_batch_context_server_rpc_new_method(BatchContextSafeHandle ctx); // returns const char* + + [DllImport("grpc_csharp_ext.dll")] + public static extern IntPtr grpcsharp_batch_context_server_rpc_new_host(BatchContextSafeHandle ctx); // returns const char* + + [DllImport("grpc_csharp_ext.dll")] + public static extern Timespec grpcsharp_batch_context_server_rpc_new_deadline(BatchContextSafeHandle ctx); + + [DllImport("grpc_csharp_ext.dll")] + public static extern IntPtr grpcsharp_batch_context_server_rpc_new_request_metadata(BatchContextSafeHandle ctx); + + [DllImport("grpc_csharp_ext.dll")] + public static extern int grpcsharp_batch_context_recv_close_on_server_cancelled(BatchContextSafeHandle ctx); + + [DllImport("grpc_csharp_ext.dll")] + public static extern void grpcsharp_batch_context_destroy(IntPtr ctx); + + // CallCredentialsSafeHandle + + [DllImport("grpc_csharp_ext.dll")] + public static extern CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2); + + [DllImport("grpc_csharp_ext.dll")] + public static extern void grpcsharp_call_credentials_release(IntPtr credentials); + + // CallSafeHandle + + [DllImport("grpc_csharp_ext.dll")] + public static extern GRPCCallError grpcsharp_call_cancel(CallSafeHandle call); + + [DllImport("grpc_csharp_ext.dll")] + public static extern GRPCCallError grpcsharp_call_cancel_with_status(CallSafeHandle call, StatusCode status, string description); + + [DllImport("grpc_csharp_ext.dll")] + public static extern GRPCCallError grpcsharp_call_start_unary(CallSafeHandle call, + BatchContextSafeHandle ctx, byte[] send_buffer, UIntPtr send_buffer_len, MetadataArraySafeHandle metadataArray, WriteFlags writeFlags); + + [DllImport("grpc_csharp_ext.dll")] + public static extern GRPCCallError grpcsharp_call_start_client_streaming(CallSafeHandle call, + BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); + + [DllImport("grpc_csharp_ext.dll")] + public static extern GRPCCallError grpcsharp_call_start_server_streaming(CallSafeHandle call, + BatchContextSafeHandle ctx, byte[] send_buffer, UIntPtr send_buffer_len, + MetadataArraySafeHandle metadataArray, WriteFlags writeFlags); + + [DllImport("grpc_csharp_ext.dll")] + public static extern GRPCCallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call, + BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); + + [DllImport("grpc_csharp_ext.dll")] + public static extern GRPCCallError grpcsharp_call_send_message(CallSafeHandle call, + BatchContextSafeHandle ctx, byte[] send_buffer, UIntPtr send_buffer_len, WriteFlags writeFlags, bool sendEmptyInitialMetadata); + + [DllImport("grpc_csharp_ext.dll")] + public static extern GRPCCallError grpcsharp_call_send_close_from_client(CallSafeHandle call, + BatchContextSafeHandle ctx); + + [DllImport("grpc_csharp_ext.dll")] + public static extern GRPCCallError grpcsharp_call_send_status_from_server(CallSafeHandle call, + BatchContextSafeHandle ctx, StatusCode statusCode, string statusMessage, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata); + + [DllImport("grpc_csharp_ext.dll")] + public static extern GRPCCallError grpcsharp_call_recv_message(CallSafeHandle call, + BatchContextSafeHandle ctx); + + [DllImport("grpc_csharp_ext.dll")] + public static extern GRPCCallError grpcsharp_call_recv_initial_metadata(CallSafeHandle call, + BatchContextSafeHandle ctx); + + [DllImport("grpc_csharp_ext.dll")] + public static extern GRPCCallError grpcsharp_call_start_serverside(CallSafeHandle call, + BatchContextSafeHandle ctx); + + [DllImport("grpc_csharp_ext.dll")] + public static extern GRPCCallError grpcsharp_call_send_initial_metadata(CallSafeHandle call, + BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); + + [DllImport("grpc_csharp_ext.dll")] + public static extern GRPCCallError grpcsharp_call_set_credentials(CallSafeHandle call, CallCredentialsSafeHandle credentials); + + [DllImport("grpc_csharp_ext.dll")] + public static extern CStringSafeHandle grpcsharp_call_get_peer(CallSafeHandle call); + + [DllImport("grpc_csharp_ext.dll")] + public static extern void grpcsharp_call_destroy(IntPtr call); + + // ChannelArgsSafeHandle + + [DllImport("grpc_csharp_ext.dll")] + public static extern ChannelArgsSafeHandle grpcsharp_channel_args_create(UIntPtr numArgs); + + [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] + public static extern void grpcsharp_channel_args_set_string(ChannelArgsSafeHandle args, UIntPtr index, string key, string value); + + [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] + public static extern void grpcsharp_channel_args_set_integer(ChannelArgsSafeHandle args, UIntPtr index, string key, int value); + + [DllImport("grpc_csharp_ext.dll")] + public static extern void grpcsharp_channel_args_destroy(IntPtr args); + + // ChannelCredentialsSafeHandle + + [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] + public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey); + + [DllImport("grpc_csharp_ext.dll")] + public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); + + [DllImport("grpc_csharp_ext.dll")] + public static extern void grpcsharp_channel_credentials_release(IntPtr credentials); + + // ChannelSafeHandle + + [DllImport("grpc_csharp_ext.dll")] + public static extern ChannelSafeHandle grpcsharp_insecure_channel_create(string target, ChannelArgsSafeHandle channelArgs); + + [DllImport("grpc_csharp_ext.dll")] + public static extern ChannelSafeHandle grpcsharp_secure_channel_create(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs); + + [DllImport("grpc_csharp_ext.dll")] + public static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline); + + [DllImport("grpc_csharp_ext.dll")] + public static extern ChannelState grpcsharp_channel_check_connectivity_state(ChannelSafeHandle channel, int tryToConnect); + + [DllImport("grpc_csharp_ext.dll")] + public static extern void grpcsharp_channel_watch_connectivity_state(ChannelSafeHandle channel, ChannelState lastObservedState, + Timespec deadline, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + + [DllImport("grpc_csharp_ext.dll")] + public static extern CStringSafeHandle grpcsharp_channel_get_target(ChannelSafeHandle call); + + [DllImport("grpc_csharp_ext.dll")] + public static extern void grpcsharp_channel_destroy(IntPtr channel); + + // CompletionQueueEvent + + [DllImport("grpc_csharp_ext.dll")] + public static extern int grpcsharp_sizeof_grpc_event(); + + // CompletionQueueSafeHandle + + [DllImport("grpc_csharp_ext.dll")] + public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create(); + + [DllImport("grpc_csharp_ext.dll")] + public static extern void grpcsharp_completion_queue_shutdown(CompletionQueueSafeHandle cq); + + [DllImport("grpc_csharp_ext.dll")] + public static extern CompletionQueueEvent grpcsharp_completion_queue_next(CompletionQueueSafeHandle cq); + + [DllImport("grpc_csharp_ext.dll")] + public static extern CompletionQueueEvent grpcsharp_completion_queue_pluck(CompletionQueueSafeHandle cq, IntPtr tag); + + [DllImport("grpc_csharp_ext.dll")] + public static extern void grpcsharp_completion_queue_destroy(IntPtr cq); + + // CStringSafeHandle + + [DllImport("grpc_csharp_ext.dll")] + public static extern void gprsharp_free(IntPtr ptr); + + // MetadataArraySafeHandle + + [DllImport("grpc_csharp_ext.dll")] + public static extern MetadataArraySafeHandle grpcsharp_metadata_array_create(UIntPtr capacity); + + [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] + public static extern void grpcsharp_metadata_array_add(MetadataArraySafeHandle array, string key, byte[] value, UIntPtr valueLength); + + [DllImport("grpc_csharp_ext.dll")] + public static extern UIntPtr grpcsharp_metadata_array_count(IntPtr metadataArray); + + [DllImport("grpc_csharp_ext.dll")] + public static extern IntPtr grpcsharp_metadata_array_get_key(IntPtr metadataArray, UIntPtr index); + + [DllImport("grpc_csharp_ext.dll")] + public static extern IntPtr grpcsharp_metadata_array_get_value(IntPtr metadataArray, UIntPtr index); + + [DllImport("grpc_csharp_ext.dll")] + public static extern UIntPtr grpcsharp_metadata_array_get_value_length(IntPtr metadataArray, UIntPtr index); + + [DllImport("grpc_csharp_ext.dll")] + public static extern void grpcsharp_metadata_array_destroy_full(IntPtr array); + + // NativeLogRedirector + + [DllImport("grpc_csharp_ext.dll")] + public static extern void grpcsharp_redirect_log(GprLogDelegate callback); + + // NativeMetadataCredentialsPlugin + + [DllImport("grpc_csharp_ext.dll")] + public static extern CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(NativeMetadataInterceptor interceptor); + + [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] + public static extern void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails); + + // ServerCredentialsSafeHandle + + [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] + public static extern ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, bool forceClientAuth); + + [DllImport("grpc_csharp_ext.dll")] + public static extern void grpcsharp_server_credentials_release(IntPtr credentials); + + // ServerSafeHandle + + [DllImport("grpc_csharp_ext.dll")] + public static extern ServerSafeHandle grpcsharp_server_create(CompletionQueueSafeHandle cq, ChannelArgsSafeHandle args); + + [DllImport("grpc_csharp_ext.dll")] + public static extern int grpcsharp_server_add_insecure_http2_port(ServerSafeHandle server, string addr); + + [DllImport("grpc_csharp_ext.dll")] + public static extern int grpcsharp_server_add_secure_http2_port(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds); + + [DllImport("grpc_csharp_ext.dll")] + public static extern void grpcsharp_server_start(ServerSafeHandle server); + + [DllImport("grpc_csharp_ext.dll")] + public static extern GRPCCallError grpcsharp_server_request_call(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + + [DllImport("grpc_csharp_ext.dll")] + public static extern void grpcsharp_server_cancel_all_calls(ServerSafeHandle server); + + [DllImport("grpc_csharp_ext.dll")] + public static extern void grpcsharp_server_shutdown_and_notify_callback(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + + [DllImport("grpc_csharp_ext.dll")] + public static extern void grpcsharp_server_destroy(IntPtr server); + + // Timespec + + [DllImport("grpc_csharp_ext.dll")] + public static extern Timespec gprsharp_now(GPRClockType clockType); + + [DllImport("grpc_csharp_ext.dll")] + public static extern Timespec gprsharp_inf_future(GPRClockType clockType); + + [DllImport("grpc_csharp_ext.dll")] + public static extern Timespec gprsharp_inf_past(GPRClockType clockType); + + [DllImport("grpc_csharp_ext.dll")] + public static extern Timespec gprsharp_convert_clock_type(Timespec t, GPRClockType targetClock); + + [DllImport("grpc_csharp_ext.dll")] + public static extern int gprsharp_sizeof_timespec(); + + // Testing + + [DllImport("grpc_csharp_ext.dll")] + public static extern GRPCCallError grpcsharp_test_callback([MarshalAs(UnmanagedType.FunctionPtr)] OpCompletionDelegate callback); + + [DllImport("grpc_csharp_ext.dll")] + public static extern IntPtr grpcsharp_test_nop(IntPtr ptr); + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/PlatformApis.cs b/src/csharp/Grpc.Core/Internal/PlatformApis.cs new file mode 100644 index 0000000000..d71e7eccdd --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/PlatformApis.cs @@ -0,0 +1,110 @@ +#region Copyright notice and license + +// Copyright 2015-2016, 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.Concurrent; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; + +namespace Grpc.Core.Internal +{ + /// <summary> + /// Utility methods for detecting platform and architecture. + /// </summary> + internal static class PlatformApis + { + static readonly bool isLinux; + static readonly bool isMacOSX; + static readonly bool isWindows; + + static PlatformApis() + { + var platform = Environment.OSVersion.Platform; + + // PlatformID.MacOSX is never returned, commonly used trick is to identify Mac is by using uname. + isMacOSX = (platform == PlatformID.Unix && GetUname() == "Darwin"); + isLinux = (platform == PlatformID.Unix && !isMacOSX); + isWindows = (platform == PlatformID.Win32NT || platform == PlatformID.Win32S || platform == PlatformID.Win32Windows); + } + + public static bool IsLinux + { + get { return isLinux; } + } + + public static bool IsMacOSX + { + get { return isMacOSX; } + } + + public static bool IsWindows + { + get { return isWindows; } + } + + public static bool Is64Bit + { + get { return IntPtr.Size == 8; } + } + + [DllImport("libc")] + static extern int uname(IntPtr buf); + + static string GetUname() + { + var buffer = Marshal.AllocHGlobal(8192); + try + { + if (uname(buffer) == 0) + { + return Marshal.PtrToStringAnsi(buffer); + } + return string.Empty; + } + catch + { + return string.Empty; + } + finally + { + if (buffer != IntPtr.Zero) + { + Marshal.FreeHGlobal(buffer); + } + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs index 51e352a18b..a1d080c7f1 100644 --- a/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs @@ -1,5 +1,5 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -41,11 +41,7 @@ namespace Grpc.Core.Internal /// </summary> internal class ServerCredentialsSafeHandle : SafeHandleZeroIsInvalid { - [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] - static extern ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, bool forceClientAuth); - - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_server_credentials_release(IntPtr credentials); + static readonly NativeMethods Native = NativeMethods.Get(); private ServerCredentialsSafeHandle() { @@ -54,15 +50,15 @@ namespace Grpc.Core.Internal public static ServerCredentialsSafeHandle CreateSslCredentials(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, bool forceClientAuth) { Preconditions.CheckArgument(keyCertPairCertChainArray.Length == keyCertPairPrivateKeyArray.Length); - return grpcsharp_ssl_server_credentials_create(pemRootCerts, - keyCertPairCertChainArray, keyCertPairPrivateKeyArray, - new UIntPtr((ulong)keyCertPairCertChainArray.Length), - forceClientAuth); + return Native.grpcsharp_ssl_server_credentials_create(pemRootCerts, + keyCertPairCertChainArray, keyCertPairPrivateKeyArray, + new UIntPtr((ulong)keyCertPairCertChainArray.Length), + forceClientAuth); } protected override bool ReleaseHandle() { - grpcsharp_server_credentials_release(handle); + Native.grpcsharp_server_credentials_release(handle); return true; } } diff --git a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs index 5ee7ac14e8..a57fb3b789 100644 --- a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs +++ b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs @@ -1,6 +1,6 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -44,29 +44,7 @@ namespace Grpc.Core.Internal /// </summary> internal sealed class ServerSafeHandle : SafeHandleZeroIsInvalid { - [DllImport("grpc_csharp_ext.dll")] - static extern ServerSafeHandle grpcsharp_server_create(CompletionQueueSafeHandle cq, ChannelArgsSafeHandle args); - - [DllImport("grpc_csharp_ext.dll")] - static extern int grpcsharp_server_add_insecure_http2_port(ServerSafeHandle server, string addr); - - [DllImport("grpc_csharp_ext.dll")] - static extern int grpcsharp_server_add_secure_http2_port(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds); - - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_server_start(ServerSafeHandle server); - - [DllImport("grpc_csharp_ext.dll")] - static extern GRPCCallError grpcsharp_server_request_call(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_server_cancel_all_calls(ServerSafeHandle server); - - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_server_shutdown_and_notify_callback(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); - - [DllImport("grpc_csharp_ext.dll")] - static extern void grpcsharp_server_destroy(IntPtr server); + static readonly NativeMethods Native = NativeMethods.Get(); private ServerSafeHandle() { @@ -77,41 +55,41 @@ namespace Grpc.Core.Internal // Increment reference count for the native gRPC environment to make sure we don't do grpc_shutdown() before destroying the server handle. // Doing so would make object finalizer crash if we end up abandoning the handle. GrpcEnvironment.GrpcNativeInit(); - return grpcsharp_server_create(cq, args); + return Native.grpcsharp_server_create(cq, args); } public int AddInsecurePort(string addr) { - return grpcsharp_server_add_insecure_http2_port(this, addr); + return Native.grpcsharp_server_add_insecure_http2_port(this, addr); } public int AddSecurePort(string addr, ServerCredentialsSafeHandle credentials) { - return grpcsharp_server_add_secure_http2_port(this, addr, credentials); + return Native.grpcsharp_server_add_secure_http2_port(this, addr, credentials); } public void Start() { - grpcsharp_server_start(this); + Native.grpcsharp_server_start(this); } public void ShutdownAndNotify(BatchCompletionDelegate callback, GrpcEnvironment environment) { var ctx = BatchContextSafeHandle.Create(); environment.CompletionRegistry.RegisterBatchCompletion(ctx, callback); - grpcsharp_server_shutdown_and_notify_callback(this, environment.CompletionQueue, ctx); + Native.grpcsharp_server_shutdown_and_notify_callback(this, environment.CompletionQueue, ctx); } public void RequestCall(BatchCompletionDelegate callback, GrpcEnvironment environment) { var ctx = BatchContextSafeHandle.Create(); environment.CompletionRegistry.RegisterBatchCompletion(ctx, callback); - grpcsharp_server_request_call(this, environment.CompletionQueue, ctx).CheckOk(); + Native.grpcsharp_server_request_call(this, environment.CompletionQueue, ctx).CheckOk(); } protected override bool ReleaseHandle() { - grpcsharp_server_destroy(handle); + Native.grpcsharp_server_destroy(handle); GrpcEnvironment.GrpcNativeShutdown(); return true; } @@ -119,7 +97,7 @@ namespace Grpc.Core.Internal // Only to be called after ShutdownAndNotify. public void CancelAllCalls() { - grpcsharp_server_cancel_all_calls(this); + Native.grpcsharp_server_cancel_all_calls(this); } } } diff --git a/src/csharp/Grpc.Core/Internal/Timespec.cs b/src/csharp/Grpc.Core/Internal/Timespec.cs index 3031175c8a..148d877da5 100644 --- a/src/csharp/Grpc.Core/Internal/Timespec.cs +++ b/src/csharp/Grpc.Core/Internal/Timespec.cs @@ -1,5 +1,5 @@ #region Copyright notice and license -// Copyright 2015, Google Inc. +// Copyright 2015-2016, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -46,23 +46,9 @@ namespace Grpc.Core.Internal const long NanosPerTick = 100; const long TicksPerSecond = NanosPerSecond / NanosPerTick; + static readonly NativeMethods Native = NativeMethods.Get(); static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); - [DllImport("grpc_csharp_ext.dll")] - static extern Timespec gprsharp_now(GPRClockType clockType); - - [DllImport("grpc_csharp_ext.dll")] - static extern Timespec gprsharp_inf_future(GPRClockType clockType); - - [DllImport("grpc_csharp_ext.dll")] - static extern Timespec gprsharp_inf_past(GPRClockType clockType); - - [DllImport("grpc_csharp_ext.dll")] - static extern Timespec gprsharp_convert_clock_type(Timespec t, GPRClockType targetClock); - - [DllImport("grpc_csharp_ext.dll")] - static extern int gprsharp_sizeof_timespec(); - public Timespec(long tv_sec, int tv_nsec) : this(tv_sec, tv_nsec, GPRClockType.Realtime) { } @@ -85,7 +71,7 @@ namespace Grpc.Core.Internal { get { - return gprsharp_inf_future(GPRClockType.Realtime); + return Native.gprsharp_inf_future(GPRClockType.Realtime); } } @@ -96,7 +82,7 @@ namespace Grpc.Core.Internal { get { - return gprsharp_inf_past(GPRClockType.Realtime); + return Native.gprsharp_inf_past(GPRClockType.Realtime); } } @@ -107,7 +93,7 @@ namespace Grpc.Core.Internal { get { - return gprsharp_now(GPRClockType.Realtime); + return Native.gprsharp_now(GPRClockType.Realtime); } } @@ -138,7 +124,7 @@ namespace Grpc.Core.Internal /// </summary> public Timespec ToClockType(GPRClockType targetClock) { - return gprsharp_convert_clock_type(this, targetClock); + return Native.gprsharp_convert_clock_type(this, targetClock); } /// <summary> @@ -241,7 +227,7 @@ namespace Grpc.Core.Internal { get { - return gprsharp_now(GPRClockType.Precise); + return Native.gprsharp_now(GPRClockType.Precise); } } @@ -249,7 +235,7 @@ namespace Grpc.Core.Internal { get { - return gprsharp_sizeof_timespec(); + return Native.gprsharp_sizeof_timespec(); } } } diff --git a/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs b/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs new file mode 100644 index 0000000000..e614cab6ab --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs @@ -0,0 +1,158 @@ +#region Copyright notice and license + +// Copyright 2015-2016, 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.Concurrent; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; + +using Grpc.Core.Logging; +using Grpc.Core.Utils; + +namespace Grpc.Core.Internal +{ + /// <summary> + /// Represents a dynamically loaded unmanaged library in a (partially) platform independent manner. + /// An important difference in library loading semantics is that on Windows, once we load a dynamic library using LoadLibrary, + /// that library becomes instantly available for <c>DllImport</c> P/Invoke calls referring to the same library name. + /// On Unix systems, dlopen has somewhat different semantics, so we need to use dlsym and <c>Marshal.GetDelegateForFunctionPointer</c> + /// to obtain delegates to native methods. + /// See http://stackoverflow.com/questions/13461989/p-invoke-to-dynamically-loaded-library-on-mono. + /// </summary> + internal class UnmanagedLibrary + { + static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<UnmanagedLibrary>(); + + // flags for dlopen + const int RTLD_LAZY = 1; + const int RTLD_GLOBAL = 8; + + readonly string libraryPath; + readonly IntPtr handle; + + public UnmanagedLibrary(string libraryPath) + { + this.libraryPath = Preconditions.CheckNotNull(libraryPath); + + if (!File.Exists(this.libraryPath)) + { + throw new FileNotFoundException("Error loading native library. File does not exist.", this.libraryPath); + } + + Logger.Debug("Attempting to load native library \"{0}\"", this.libraryPath); + + this.handle = PlatformSpecificLoadLibrary(this.libraryPath); + + if (this.handle == IntPtr.Zero) + { + throw new IOException(string.Format("Error loading native library \"{0}\"", this.libraryPath)); + } + } + + /// <summary> + /// Loads symbol in a platform specific way. + /// </summary> + /// <param name="symbolName"></param> + /// <returns></returns> + public IntPtr LoadSymbol(string symbolName) + { + if (PlatformApis.IsLinux) + { + return Linux.dlsym(this.handle, symbolName); + } + if (PlatformApis.IsMacOSX) + { + return MacOSX.dlsym(this.handle, symbolName); + } + throw new InvalidOperationException("Unsupported platform."); + } + + public T GetNativeMethodDelegate<T>(string methodName) + where T : class + { + var ptr = LoadSymbol(methodName); + if (ptr == IntPtr.Zero) + { + throw new MissingMethodException(string.Format("The native method \"{0}\" does not exist", methodName)); + } + return Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)) as T; + } + + /// <summary> + /// Loads library in a platform specific way. + /// </summary> + private static IntPtr PlatformSpecificLoadLibrary(string libraryPath) + { + if (PlatformApis.IsWindows) + { + return Windows.LoadLibrary(libraryPath); + } + if (PlatformApis.IsLinux) + { + return Linux.dlopen(libraryPath, RTLD_GLOBAL + RTLD_LAZY); + } + if (PlatformApis.IsMacOSX) + { + return MacOSX.dlopen(libraryPath, RTLD_GLOBAL + RTLD_LAZY); + } + throw new InvalidOperationException("Unsupported platform."); + } + + private static class Windows + { + [DllImport("kernel32.dll")] + internal static extern IntPtr LoadLibrary(string filename); + } + + private static class Linux + { + [DllImport("libdl.so")] + internal static extern IntPtr dlopen(string filename, int flags); + + [DllImport("libdl.so")] + internal static extern IntPtr dlsym(IntPtr handle, string symbol); + } + + private static class MacOSX + { + [DllImport("libSystem.dylib")] + internal static extern IntPtr dlopen(string filename, int flags); + + [DllImport("libSystem.dylib")] + internal static extern IntPtr dlsym(IntPtr handle, string symbol); + } + } +} diff --git a/src/csharp/Grpc.Core/NativeDeps.Linux.targets b/src/csharp/Grpc.Core/NativeDeps.Linux.targets new file mode 100644 index 0000000000..a3848c6f2e --- /dev/null +++ b/src/csharp/Grpc.Core/NativeDeps.Linux.targets @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Content Include="..\..\..\libs\$(NativeDependenciesConfigurationUnix)\libgrpc_csharp_ext.so"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <Link>nativelibs\linux_x64\libgrpc_csharp_ext.so</Link> + </Content> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/src/csharp/Grpc.Core/NativeDeps.Mac.targets b/src/csharp/Grpc.Core/NativeDeps.Mac.targets new file mode 100644 index 0000000000..c3c6264fd3 --- /dev/null +++ b/src/csharp/Grpc.Core/NativeDeps.Mac.targets @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Content Include="..\..\..\libs\$(NativeDependenciesConfigurationUnix)\libgrpc_csharp_ext.dylib"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <Link>nativelibs\macosx_x86\libgrpc_csharp_ext.dylib</Link> + </Content> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/src/csharp/Grpc.Core/NativeDeps.Windows.targets b/src/csharp/Grpc.Core/NativeDeps.Windows.targets new file mode 100644 index 0000000000..f6a3405e29 --- /dev/null +++ b/src/csharp/Grpc.Core/NativeDeps.Windows.targets @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Content Include="..\..\..\vsprojects\$(NativeDependenciesConfiguration)\grpc_csharp_ext.dll"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <Link>nativelibs\windows_x86\grpc_csharp_ext.dll</Link> + </Content> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/src/csharp/Grpc.Core/NativeDeps.targets b/src/csharp/Grpc.Core/NativeDeps.targets new file mode 100644 index 0000000000..66c5ec1292 --- /dev/null +++ b/src/csharp/Grpc.Core/NativeDeps.targets @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + + <PropertyGroup Condition=" '$(NativeDependenciesConfiguration)' == '' "> + <NativeDependenciesConfiguration Condition=" '$(Configuration)' == 'Debug' ">Debug</NativeDependenciesConfiguration> + <NativeDependenciesConfiguration Condition=" '$(Configuration)' == 'Release' ">Release</NativeDependenciesConfiguration> + <NativeDependenciesConfiguration Condition=" '$(Configuration)' == 'ReleaseSigned' ">Release</NativeDependenciesConfiguration> + </PropertyGroup> + + <PropertyGroup Condition=" '$(NativeDependenciesConfigurationUnix)' == '' "> + <NativeDependenciesConfigurationUnix Condition=" '$(Configuration)' == 'Debug' ">dbg</NativeDependenciesConfigurationUnix> + <NativeDependenciesConfigurationUnix Condition=" '$(Configuration)' == 'Release' ">opt</NativeDependenciesConfigurationUnix> + <NativeDependenciesConfigurationUnix Condition=" '$(Configuration)' == 'ReleaseSigned' ">opt</NativeDependenciesConfigurationUnix> + </PropertyGroup> + + <!-- Autodetect platform --> + <PropertyGroup Condition=" '$(OS)' != 'Unix' "> + <NativeDepsPlatform>Windows</NativeDepsPlatform> + </PropertyGroup> + <PropertyGroup Condition=" '$(OS)' == 'Unix' And Exists('/Applications') And Exists('/Library') And Exists('/System') "> + <NativeDepsPlatform>Mac</NativeDepsPlatform> + </PropertyGroup> + <PropertyGroup Condition=" '$(OS)' == 'Unix' And '$(NativeDepsPlatform)' == '' "> + <NativeDepsPlatform>Linux</NativeDepsPlatform> + </PropertyGroup> + + <Import Project="NativeDeps.$(NativeDepsPlatform).targets" /> +</Project>
\ No newline at end of file diff --git a/src/php/ext/grpc/config.m4 b/src/php/ext/grpc/config.m4 index 7928687943..0fb843d51f 100755 --- a/src/php/ext/grpc/config.m4 +++ b/src/php/ext/grpc/config.m4 @@ -1,6 +1,9 @@ PHP_ARG_ENABLE(grpc, whether to enable grpc support, [ --enable-grpc Enable grpc support]) +PHP_ARG_ENABLE(coverage, whether to include code coverage symbols, +[ --enable-coverage Enable coverage support], no, no) + if test "$PHP_GRPC" != "no"; then dnl Write more examples of tests here... @@ -75,3 +78,66 @@ if test "$PHP_GRPC" != "no"; then channel_credentials.c completion_queue.c timeval.c server.c \ server_credentials.c php_grpc.c, $ext_shared, , -Wall -Werror -std=c11) fi + +if test "$PHP_COVERAGE" = "yes"; then + + if test "$GCC" != "yes"; then + AC_MSG_ERROR([GCC is required for --enable-coverage]) + fi + + dnl Check if ccache is being used + case `$php_shtool path $CC` in + *ccache*[)] gcc_ccache=yes;; + *[)] gcc_ccache=no;; + esac + + if test "$gcc_ccache" = "yes" && (test -z "$CCACHE_DISABLE" || test "$CCACHE_DISABLE" != "1"); then + AC_MSG_ERROR([ccache must be disabled when --enable-coverage option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.]) + fi + + lcov_version_list="1.5 1.6 1.7 1.9 1.10 1.11" + + AC_CHECK_PROG(LCOV, lcov, lcov) + AC_CHECK_PROG(GENHTML, genhtml, genhtml) + PHP_SUBST(LCOV) + PHP_SUBST(GENHTML) + + if test "$LCOV"; then + AC_CACHE_CHECK([for lcov version], php_cv_lcov_version, [ + php_cv_lcov_version=invalid + lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'` #' + for lcov_check_version in $lcov_version_list; do + if test "$lcov_version" = "$lcov_check_version"; then + php_cv_lcov_version="$lcov_check_version (ok)" + fi + done + ]) + else + lcov_msg="To enable code coverage reporting you must have one of the following LCOV versions installed: $lcov_version_list" + AC_MSG_ERROR([$lcov_msg]) + fi + + case $php_cv_lcov_version in + ""|invalid[)] + lcov_msg="You must have one of the following versions of LCOV: $lcov_version_list (found: $lcov_version)." + AC_MSG_ERROR([$lcov_msg]) + LCOV="exit 0;" + ;; + esac + + if test -z "$GENHTML"; then + AC_MSG_ERROR([Could not find genhtml from the LCOV package]) + fi + + PHP_ADD_MAKEFILE_FRAGMENT + + dnl Remove all optimization flags from CFLAGS + changequote({,}) + CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9s]*//g'` + CXXFLAGS=`echo "$CXXFLAGS" | $SED -e 's/-O[0-9s]*//g'` + changequote([,]) + + dnl Add the special gcc flags + CFLAGS="$CFLAGS -O0 -ggdb -fprofile-arcs -ftest-coverage" + CXXFLAGS="$CXXFLAGS -ggdb -O0 -fprofile-arcs -ftest-coverage" +fi diff --git a/src/php/ext/grpc/package.xml b/src/php/ext/grpc/package.xml index 9c98f82540..daf2ee5a53 100644 --- a/src/php/ext/grpc/package.xml +++ b/src/php/ext/grpc/package.xml @@ -10,8 +10,8 @@ <email>grpc-packages@google.com</email> <active>yes</active> </lead> - <date>2015-12-16</date> - <time>12:56:11</time> + <date>2016-01-13</date> + <time>16:06:07</time> <version> <release>0.7.0</release> <api>0.7.0</api> @@ -29,6 +29,7 @@ </notes> <contents> <dir baseinstalldir="/" name="/"> + <file baseinstalldir="/" md5sum="f201d644fdbd8228ffd1d4a69cc44f1f" name="tests/grpc-basic.phpt" role="test" /> <file baseinstalldir="/" md5sum="6f19828fb869b7b8a590cbb76b4f996d" name="byte_buffer.c" role="src" /> <file baseinstalldir="/" md5sum="c8de0f819499c48adfc8d7f472c0196b" name="byte_buffer.h" role="src" /> <file baseinstalldir="/" md5sum="ee7eb7757f9e6f0e36f8f616b6bd0af5" name="call.c" role="src" /> @@ -41,9 +42,9 @@ <file baseinstalldir="/" md5sum="a86250e03f610ce6c2c7595a84e08821" name="channel_credentials.h" role="src" /> <file baseinstalldir="/" md5sum="55ab7a42f9dd9bfc7e28a61cfc5fca63" name="completion_queue.c" role="src" /> <file baseinstalldir="/" md5sum="f10b5bb232d74a6878e829e2e76cdaa2" name="completion_queue.h" role="src" /> - <file baseinstalldir="/" md5sum="c7bba7f0f00d1b1483de457d55311382" name="config.m4" role="src" /> + <file baseinstalldir="/" md5sum="cafed254127007ff2271dad7d56a06c8" name="config.m4" role="src" /> <file baseinstalldir="/" md5sum="38a1bc979d810c36ebc2a52d4b7b5319" name="CREDITS" role="doc" /> - <file baseinstalldir="/" md5sum="3f35b472bbdef5a788cd90617d7d0847" name="LICENSE" role="doc" /> + <file baseinstalldir="/" md5sum="8847cf67b1b54c981d47ecbb0d139a0c" name="LICENSE" role="doc" /> <file baseinstalldir="/" md5sum="3131a8af38fe5918e5409016b89d6cdb" name="php_grpc.c" role="src" /> <file baseinstalldir="/" md5sum="673b07859d9f69232f8a754c56780686" name="php_grpc.h" role="src" /> <file baseinstalldir="/" md5sum="7533a6d3ea02c78cad23a9651de0825d" name="README.md" role="doc" /> @@ -142,7 +143,7 @@ Update to wrap gRPC C Core version 0.10.0 <release>beta</release> <api>beta</api> </stability> - <date>2015-12-16</date> + <date>2016-01-13</date> <license>BSD</license> <notes> - Breaking change to Credentials class (removed) #3765 diff --git a/src/php/ext/grpc/tests/grpc-basic.phpt b/src/php/ext/grpc/tests/grpc-basic.phpt new file mode 100644 index 0000000000..523cc4a59f --- /dev/null +++ b/src/php/ext/grpc/tests/grpc-basic.phpt @@ -0,0 +1,10 @@ +--TEST-- +Check for grpc presence +--SKIPIF-- +<?php if (!extension_loaded("grpc")) print "skip"; ?> +--FILE-- +<?php +echo "grpc extension is available"; +?> +--EXPECT-- +grpc extension is available
\ No newline at end of file diff --git a/tools/jenkins/build_interop_stress_image.sh b/tools/jenkins/build_interop_stress_image.sh index 6b22dce6c0..395eaa32d9 100755 --- a/tools/jenkins/build_interop_stress_image.sh +++ b/tools/jenkins/build_interop_stress_image.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2015, Google Inc. +# Copyright 2015-2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tools/jenkins/grpc_interop_csharp/build_interop.sh b/tools/jenkins/grpc_interop_csharp/build_interop.sh index 8fde687900..e87fe2f692 100755 --- a/tools/jenkins/grpc_interop_csharp/build_interop.sh +++ b/tools/jenkins/grpc_interop_csharp/build_interop.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2015, Google Inc. +# Copyright 2015-2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -42,6 +42,6 @@ cd /var/local/git/grpc make install-certs # build C# interop client & server -make install_grpc_csharp_ext +make CONFIG=dbg grpc_csharp_ext (cd src/csharp && mono /var/local/NuGet.exe restore Grpc.sln) (cd src/csharp && xbuild Grpc.sln) diff --git a/tools/jenkins/grpc_interop_stress_cxx/Dockerfile b/tools/jenkins/grpc_interop_stress_cxx/Dockerfile index 1fa1907533..58a8c32e34 100644 --- a/tools/jenkins/grpc_interop_stress_cxx/Dockerfile +++ b/tools/jenkins/grpc_interop_stress_cxx/Dockerfile @@ -1,4 +1,4 @@ -# Copyright 2015, Google Inc. +# Copyright 2015-2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tools/jenkins/grpc_interop_stress_cxx/build_interop_stress.sh b/tools/jenkins/grpc_interop_stress_cxx/build_interop_stress.sh index 01f9a9c02e..6ed3ccb3fa 100755 --- a/tools/jenkins/grpc_interop_stress_cxx/build_interop_stress.sh +++ b/tools/jenkins/grpc_interop_stress_cxx/build_interop_stress.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2015, Google Inc. +# Copyright 2015-2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tools/jenkins/run_interop_stress.sh b/tools/jenkins/run_interop_stress.sh index 22d81db8bc..8166f34e05 100755 --- a/tools/jenkins/run_interop_stress.sh +++ b/tools/jenkins/run_interop_stress.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# Copyright 2015, Google Inc. +# Copyright 2015-2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tools/run_tests/build_csharp.sh b/tools/run_tests/build_csharp.sh index 55643ff924..aadd11e205 100755 --- a/tools/run_tests/build_csharp.sh +++ b/tools/run_tests/build_csharp.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2015, Google Inc. +# Copyright 2015-2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -32,4 +32,5 @@ set -ex cd $(dirname $0)/../../src/csharp -xbuild /p:Configuration=$MSBUILD_CONFIG Grpc.sln +# overriding NativeDependenciesConfigurationUnix is needed to make gcov code coverage work. +xbuild /p:Configuration=$MSBUILD_CONFIG /p:NativeDependenciesConfigurationUnix=$CONFIG Grpc.sln diff --git a/tools/run_tests/build_php.sh b/tools/run_tests/build_php.sh index 1d81779b6a..0f9cfe5e3a 100755 --- a/tools/run_tests/build_php.sh +++ b/tools/run_tests/build_php.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2015, Google Inc. +# Copyright 2015-2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -44,5 +44,9 @@ cd src/php cd ext/grpc phpize -./configure --enable-grpc=$root +if [ "$CONFIG" != "gcov" ] ; then + ./configure --enable-grpc=$root +else + ./configure --enable-grpc=$root --enable-coverage +fi make diff --git a/tools/run_tests/post_tests_php.sh b/tools/run_tests/post_tests_php.sh new file mode 100755 index 0000000000..01a44d03dc --- /dev/null +++ b/tools/run_tests/post_tests_php.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# Copyright 2015-2016, 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. + +set -ex + +if [ "$CONFIG" != "gcov" ] ; then exit ; fi + +root=$(readlink -f $(dirname $0)/../..) +out=$root/reports/php_ext_coverage +tmp1=$(mktemp) +tmp2=$(mktemp) +cd $root +lcov --capture --directory . --output-file $tmp1 +lcov --extract $tmp1 "$root/src/php/ext/grpc/*" --output-file $tmp2 +genhtml $tmp2 --output-directory $out +rm $tmp2 +rm $tmp1 + +cp -rv $root/src/php/coverage $root/reports/php diff --git a/tools/run_tests/run_csharp.sh b/tools/run_tests/run_csharp.sh index 744df07e1c..10f1c28521 100755 --- a/tools/run_tests/run_csharp.sh +++ b/tools/run_tests/run_csharp.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright 2015, Google Inc. +# Copyright 2015-2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -36,9 +36,6 @@ NUNIT_CONSOLE="mono packages/NUnit.Runners.2.6.4/tools/nunit-console.exe" # change to gRPC repo root cd $(dirname $0)/../.. -# path needs to be absolute -export LD_LIBRARY_PATH=$(pwd)/libs/$CONFIG - (cd src/csharp; $NUNIT_CONSOLE $@) if [ "$CONFIG" = "gcov" ] diff --git a/tools/run_tests/run_stress_tests.py b/tools/run_tests/run_stress_tests.py index b01a07af90..193ff2e53a 100755 --- a/tools/run_tests/run_stress_tests.py +++ b/tools/run_tests/run_stress_tests.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright 2015, Google Inc. +# Copyright 2015-2016, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py index 97962bd928..775bec9499 100755 --- a/tools/run_tests/run_tests.py +++ b/tools/run_tests/run_tests.py @@ -245,7 +245,7 @@ class PhpLanguage(object): return [['tools/run_tests/build_php.sh']] def post_tests_steps(self): - return [] + return [['tools/run_tests/post_tests_php.sh']] def makefile_name(self): return 'Makefile' @@ -1093,4 +1093,3 @@ else: if BuildAndRunError.POST_TEST in errors: exit_code |= 4 sys.exit(exit_code) - |