diff options
Diffstat (limited to 'src/csharp/Grpc.Core')
-rw-r--r-- | src/csharp/Grpc.Core/Grpc.Core.csproj | 5 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/Grpc.Core.nuspec | 8 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/Grpc.Core.targets | 29 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/Internal/NativeExtension.cs | 27 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs | 2 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs | 24 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/Logging/ConsoleLogger.cs | 97 | ||||
-rw-r--r-- | src/csharp/Grpc.Core/Logging/TextWriterLogger.cs | 176 |
8 files changed, 256 insertions, 112 deletions
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index 251a688946..95077a6ca5 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -58,6 +58,7 @@ <Compile Include="IServerStreamWriter.cs" /> <Compile Include="IAsyncStreamWriter.cs" /> <Compile Include="IAsyncStreamReader.cs" /> + <Compile Include="Logging\TextWriterLogger.cs" /> <Compile Include="Logging\NullLogger.cs" /> <Compile Include="ServerPort.cs" /> <Compile Include="Version.cs" /> @@ -140,9 +141,7 @@ </ItemGroup> <Import Project="NativeDeps.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> - <ItemGroup> - <Folder Include="Resources\" /> - </ItemGroup> + <ItemGroup /> <ItemGroup> <EmbeddedResource Include="..\..\..\etc\roots.pem"> <Link>Resources\roots.pem</Link> diff --git a/src/csharp/Grpc.Core/Grpc.Core.nuspec b/src/csharp/Grpc.Core/Grpc.Core.nuspec index 49bccb050e..0ada0049c2 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.nuspec +++ b/src/csharp/Grpc.Core/Grpc.Core.nuspec @@ -16,7 +16,6 @@ <tags>gRPC RPC Protocol HTTP/2</tags> <dependencies> <dependency id="Ix-Async" version="1.2.5" /> - <dependency id="grpc.native.csharp" version="$version$" /> </dependencies> </metadata> <files> @@ -24,5 +23,12 @@ <file src="bin/ReleaseSigned/Grpc.Core.pdb" target="lib/net45" /> <file src="bin/ReleaseSigned/Grpc.Core.xml" target="lib/net45" /> <file src="**\*.cs" target="src" /> + <file src="Grpc.Core.targets" target="\build\net45\Grpc.Core.targets" /> + <file src="windows_x86/grpc_csharp_ext.dll" target="/build/native/bin/windows_x86/grpc_csharp_ext.dll" /> + <file src="windows_x64/grpc_csharp_ext.dll" target="/build/native/bin/windows_x64/grpc_csharp_ext.dll" /> + <file src="linux_x86/libgrpc_csharp_ext.so" target="/build/native/bin/linux_x86/libgrpc_csharp_ext.so" /> + <file src="linux_x64/libgrpc_csharp_ext.so" target="/build/native/bin/linux_x64/libgrpc_csharp_ext.so" /> + <file src="macosx_x86/libgrpc_csharp_ext.dylib" target="/build/native/bin/macosx_x86/libgrpc_csharp_ext.dylib" /> + <file src="macosx_x64/libgrpc_csharp_ext.dylib" target="/build/native/bin/macosx_x64/libgrpc_csharp_ext.dylib" /> </files> </package> diff --git a/src/csharp/Grpc.Core/Grpc.Core.targets b/src/csharp/Grpc.Core/Grpc.Core.targets new file mode 100644 index 0000000000..501fc50548 --- /dev/null +++ b/src/csharp/Grpc.Core/Grpc.Core.targets @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\windows_x86\grpc_csharp_ext.dll"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <Link>nativelibs\windows_x86\grpc_csharp_ext.dll</Link> + </Content> + <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\windows_x64\grpc_csharp_ext.dll"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <Link>nativelibs\windows_x64\grpc_csharp_ext.dll</Link> + </Content> + <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\linux_x86\libgrpc_csharp_ext.so"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <Link>nativelibs\linux_x86\libgrpc_csharp_ext.so</Link> + </Content> + <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\linux_x64\libgrpc_csharp_ext.so"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <Link>nativelibs\linux_x64\libgrpc_csharp_ext.so</Link> + </Content> + <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\macosx_x86\libgrpc_csharp_ext.dylib"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <Link>nativelibs\macosx_x86\libgrpc_csharp_ext.dylib</Link> + </Content> + <Content Include="$(MSBuildThisFileDirectory)..\..\build\native\bin\macosx_x64\libgrpc_csharp_ext.dylib"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + <Link>nativelibs\macosx_x64\libgrpc_csharp_ext.dylib</Link> + </Content> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/src/csharp/Grpc.Core/Internal/NativeExtension.cs b/src/csharp/Grpc.Core/Internal/NativeExtension.cs index bff1e56582..b45ba19c24 100644 --- a/src/csharp/Grpc.Core/Internal/NativeExtension.cs +++ b/src/csharp/Grpc.Core/Internal/NativeExtension.cs @@ -32,7 +32,6 @@ #endregion using System; -using System.Globalization; using System.IO; using System.Reflection; @@ -46,6 +45,7 @@ namespace Grpc.Core.Internal internal sealed class NativeExtension { const string NativeLibrariesDir = "nativelibs"; + const string DnxStyleNativeLibrariesDir = "../../build/native/bin/"; static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<NativeExtension>(); static readonly object staticLock = new object(); @@ -100,31 +100,48 @@ namespace Grpc.Core.Internal // 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(Path.GetDirectoryName(GetAssemblyPath()), - NativeLibrariesDir, libraryFlavor, GetNativeLibraryFilename()); - return new UnmanagedLibrary(fullPath); + + var assemblyDirectory = Path.GetDirectoryName(GetAssemblyPath()); + + // With old-style VS projects, the native libraries get copied using a .targets rule to the build output folder + // alongside the compiled assembly. + var classicPath = Path.Combine(assemblyDirectory, NativeLibrariesDir, libraryFlavor, GetNativeLibraryFilename()); + + // DNX-style project.json projects will use Grpc.Core assembly directly in the location where it got restored + // by nuget. We locate the native libraries based on known structure of Grpc.Core nuget package. + var dnxStylePath = Path.Combine(assemblyDirectory, DnxStyleNativeLibrariesDir, libraryFlavor, GetNativeLibraryFilename()); + + return new UnmanagedLibrary(new string[] {classicPath, dnxStylePath}); } private static string GetAssemblyPath() { var assembly = typeof(NativeExtension).GetTypeInfo().Assembly; - +#if DOTNET5_4 + // Assembly.EscapedCodeBase does not exit under CoreCLR, but assemblies imported from a nuget package + // don't seem to be shadowed by DNX-based projects at all. + return assembly.Location; +#else // If assembly is shadowed (e.g. in a webapp), EscapedCodeBase is pointing // to the original location of the assembly, and Location is pointing // to the shadow copy. We care about the original location because // the native dlls don't get shadowed. + var escapedCodeBase = assembly.EscapedCodeBase; if (IsFileUri(escapedCodeBase)) { return new Uri(escapedCodeBase).LocalPath; } return assembly.Location; +#endif } +#if !DOTNET5_4 private static bool IsFileUri(string uri) { return uri.ToLowerInvariant().StartsWith(Uri.UriSchemeFile); } +#endif private static string GetPlatformString() { diff --git a/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs index 0e4d9070d3..26af6311d5 100644 --- a/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs +++ b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs @@ -87,7 +87,7 @@ namespace Grpc.Core.Internal } } - private async void StartGetMetadata(AuthInterceptorContext context, IntPtr callbackPtr, IntPtr userDataPtr) + private async Task StartGetMetadata(AuthInterceptorContext context, IntPtr callbackPtr, IntPtr userDataPtr) { try { diff --git a/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs b/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs index 47308f8c9e..5a80746101 100644 --- a/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs +++ b/src/csharp/Grpc.Core/Internal/UnmanagedLibrary.cs @@ -32,8 +32,6 @@ #endregion using System; -using System.Collections.Concurrent; -using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.InteropServices; @@ -63,14 +61,9 @@ namespace Grpc.Core.Internal readonly string libraryPath; readonly IntPtr handle; - public UnmanagedLibrary(string libraryPath) + public UnmanagedLibrary(string[] libraryPathAlternatives) { - this.libraryPath = GrpcPreconditions.CheckNotNull(libraryPath); - - if (!File.Exists(this.libraryPath)) - { - throw new FileNotFoundException("Error loading native library. File does not exist.", this.libraryPath); - } + this.libraryPath = FirstValidLibraryPath(libraryPathAlternatives); Logger.Debug("Attempting to load native library \"{0}\"", this.libraryPath); @@ -139,6 +132,19 @@ namespace Grpc.Core.Internal throw new InvalidOperationException("Unsupported platform."); } + private static string FirstValidLibraryPath(string[] libraryPathAlternatives) + { + GrpcPreconditions.CheckArgument(libraryPathAlternatives.Length > 0, "libraryPathAlternatives cannot be empty."); + foreach (var path in libraryPathAlternatives) + { + if (File.Exists(path)) + { + return path; + } + } + throw new FileNotFoundException(String.Format("Error loading native library. Not found in any of the possible locations {0}", libraryPathAlternatives)); + } + private static class Windows { [DllImport("kernel32.dll")] diff --git a/src/csharp/Grpc.Core/Logging/ConsoleLogger.cs b/src/csharp/Grpc.Core/Logging/ConsoleLogger.cs index da74e55a95..5e8dced641 100644 --- a/src/csharp/Grpc.Core/Logging/ConsoleLogger.cs +++ b/src/csharp/Grpc.Core/Logging/ConsoleLogger.cs @@ -38,117 +38,28 @@ using System.Globalization; namespace Grpc.Core.Logging { /// <summary>Logger that logs to System.Console.</summary> - public class ConsoleLogger : ILogger + public class ConsoleLogger : TextWriterLogger { - // Format similar enough to C core log format except nanosecond precision is not supported. - const string DateTimeFormatString = "MMdd HH:mm:ss.ffffff"; - - readonly Type forType; - readonly string forTypeString; - /// <summary>Creates a console logger not associated to any specific type.</summary> public ConsoleLogger() : this(null) { } /// <summary>Creates a console logger that logs messsage specific for given type.</summary> - private ConsoleLogger(Type forType) + private ConsoleLogger(Type forType) : base(() => Console.Error, forType) { - this.forType = forType; - if (forType != null) - { - var namespaceStr = forType.Namespace ?? ""; - if (namespaceStr.Length > 0) - { - namespaceStr += "."; - } - this.forTypeString = namespaceStr + forType.Name + " "; - } - else - { - this.forTypeString = ""; - } } /// <summary> /// Returns a logger associated with the specified type. /// </summary> - public ILogger ForType<T>() + public override ILogger ForType<T>() { - if (typeof(T) == forType) + if (typeof(T) == AssociatedType) { return this; } return new ConsoleLogger(typeof(T)); } - - /// <summary>Logs a message with severity Debug.</summary> - public void Debug(string message) - { - Log("D", message); - } - - /// <summary>Logs a formatted message with severity Debug.</summary> - public void Debug(string format, params object[] formatArgs) - { - Debug(string.Format(format, formatArgs)); - } - - /// <summary>Logs a message with severity Info.</summary> - public void Info(string message) - { - Log("I", message); - } - - /// <summary>Logs a formatted message with severity Info.</summary> - public void Info(string format, params object[] formatArgs) - { - Info(string.Format(format, formatArgs)); - } - - /// <summary>Logs a message with severity Warning.</summary> - public void Warning(string message) - { - Log("W", message); - } - - /// <summary>Logs a formatted message with severity Warning.</summary> - public void Warning(string format, params object[] formatArgs) - { - Warning(string.Format(format, formatArgs)); - } - - /// <summary>Logs a message and an associated exception with severity Warning.</summary> - public void Warning(Exception exception, string message) - { - Warning(message + " " + exception); - } - - /// <summary>Logs a message with severity Error.</summary> - public void Error(string message) - { - Log("E", message); - } - - /// <summary>Logs a formatted message with severity Error.</summary> - public void Error(string format, params object[] formatArgs) - { - Error(string.Format(format, formatArgs)); - } - - /// <summary>Logs a message and an associated exception with severity Error.</summary> - public void Error(Exception exception, string message) - { - Error(message + " " + exception); - } - - private void Log(string severityString, string message) - { - Console.Error.WriteLine("{0}{1} {2}{3}", - severityString, - DateTime.Now.ToString(DateTimeFormatString, CultureInfo.InvariantCulture), - forTypeString, - message); - } } } diff --git a/src/csharp/Grpc.Core/Logging/TextWriterLogger.cs b/src/csharp/Grpc.Core/Logging/TextWriterLogger.cs new file mode 100644 index 0000000000..397320ddff --- /dev/null +++ b/src/csharp/Grpc.Core/Logging/TextWriterLogger.cs @@ -0,0 +1,176 @@ +#region Copyright notice and license + +// Copyright 2015, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using Grpc.Core.Utils; + +namespace Grpc.Core.Logging +{ + /// <summary>Logger that logs to an arbitrary <c>System.IO.TextWriter</c>.</summary> + public class TextWriterLogger : ILogger + { + // Format similar enough to C core log format except nanosecond precision is not supported. + const string DateTimeFormatString = "MMdd HH:mm:ss.ffffff"; + + readonly Func<TextWriter> textWriterProvider; + readonly Type forType; + readonly string forTypeString; + + /// <summary> + /// Creates a console logger not associated to any specific type and writes to given <c>System.IO.TextWriter</c>. + /// User is responsible for providing an instance of TextWriter that is thread-safe. + /// </summary> + public TextWriterLogger(TextWriter textWriter) : this(() => textWriter) + { + GrpcPreconditions.CheckNotNull(textWriter); + } + + /// <summary> + /// Creates a console logger not associated to any specific type and writes to a <c>System.IO.TextWriter</c> obtained from given provider. + /// User is responsible for providing an instance of TextWriter that is thread-safe. + /// </summary> + public TextWriterLogger(Func<TextWriter> textWriterProvider) : this(textWriterProvider, null) + { + } + + /// <summary>Creates a console logger that logs messsage specific for given type.</summary> + protected TextWriterLogger(Func<TextWriter> textWriterProvider, Type forType) + { + this.textWriterProvider = GrpcPreconditions.CheckNotNull(textWriterProvider); + this.forType = forType; + if (forType != null) + { + var namespaceStr = forType.Namespace ?? ""; + if (namespaceStr.Length > 0) + { + namespaceStr += "."; + } + this.forTypeString = namespaceStr + forType.Name + " "; + } + else + { + this.forTypeString = ""; + } + } + + /// <summary> + /// Returns a logger associated with the specified type. + /// </summary> + public virtual ILogger ForType<T>() + { + if (typeof(T) == forType) + { + return this; + } + return new TextWriterLogger(this.textWriterProvider, typeof(T)); + } + + /// <summary>Logs a message with severity Debug.</summary> + public void Debug(string message) + { + Log("D", message); + } + + /// <summary>Logs a formatted message with severity Debug.</summary> + public void Debug(string format, params object[] formatArgs) + { + Debug(string.Format(format, formatArgs)); + } + + /// <summary>Logs a message with severity Info.</summary> + public void Info(string message) + { + Log("I", message); + } + + /// <summary>Logs a formatted message with severity Info.</summary> + public void Info(string format, params object[] formatArgs) + { + Info(string.Format(format, formatArgs)); + } + + /// <summary>Logs a message with severity Warning.</summary> + public void Warning(string message) + { + Log("W", message); + } + + /// <summary>Logs a formatted message with severity Warning.</summary> + public void Warning(string format, params object[] formatArgs) + { + Warning(string.Format(format, formatArgs)); + } + + /// <summary>Logs a message and an associated exception with severity Warning.</summary> + public void Warning(Exception exception, string message) + { + Warning(message + " " + exception); + } + + /// <summary>Logs a message with severity Error.</summary> + public void Error(string message) + { + Log("E", message); + } + + /// <summary>Logs a formatted message with severity Error.</summary> + public void Error(string format, params object[] formatArgs) + { + Error(string.Format(format, formatArgs)); + } + + /// <summary>Logs a message and an associated exception with severity Error.</summary> + public void Error(Exception exception, string message) + { + Error(message + " " + exception); + } + + /// <summary>Gets the type associated with this logger.</summary> + protected Type AssociatedType + { + get { return forType; } + } + + private void Log(string severityString, string message) + { + textWriterProvider().WriteLine("{0}{1} {2}{3}", + severityString, + DateTime.Now.ToString(DateTimeFormatString, CultureInfo.InvariantCulture), + forTypeString, + message); + } + } +} |