add C# server reflection

pull/8857/head
Jan Tattermusch 8 years ago
parent f9ed9d98cf
commit 0201776d29
  1. 3
      src/csharp/Grpc.Core.Tests/SanityTest.cs
  2. 14
      src/csharp/Grpc.Dotnet.sln
  3. 2
      src/csharp/Grpc.Reflection.Tests/.gitignore
  4. 94
      src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.csproj
  5. 8
      src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.project.json
  6. 18
      src/csharp/Grpc.Reflection.Tests/Grpc.Reflection.Tests.xproj
  7. 59
      src/csharp/Grpc.Reflection.Tests/NUnitMain.cs
  8. 44
      src/csharp/Grpc.Reflection.Tests/Properties/AssemblyInfo.cs
  9. 154
      src/csharp/Grpc.Reflection.Tests/ReflectionClientServerTest.cs
  10. 63
      src/csharp/Grpc.Reflection.Tests/SymbolRegistryTest.cs
  11. 7
      src/csharp/Grpc.Reflection.Tests/packages.config
  12. 65
      src/csharp/Grpc.Reflection.Tests/project.json
  13. 2
      src/csharp/Grpc.Reflection/.gitignore
  14. 84
      src/csharp/Grpc.Reflection/Grpc.Reflection.csproj
  15. 28
      src/csharp/Grpc.Reflection/Grpc.Reflection.nuspec
  16. 8
      src/csharp/Grpc.Reflection/Grpc.Reflection.project.json
  17. 18
      src/csharp/Grpc.Reflection/Grpc.Reflection.xproj
  18. 44
      src/csharp/Grpc.Reflection/Properties/AssemblyInfo.cs
  19. 1556
      src/csharp/Grpc.Reflection/Reflection.cs
  20. 132
      src/csharp/Grpc.Reflection/ReflectionGrpc.cs
  21. 173
      src/csharp/Grpc.Reflection/ReflectionServiceImpl.cs
  22. 10
      src/csharp/Grpc.Reflection/Settings.StyleCop
  23. 160
      src/csharp/Grpc.Reflection/SymbolRegistry.cs
  24. 5
      src/csharp/Grpc.Reflection/packages.config
  25. 41
      src/csharp/Grpc.Reflection/project.json
  26. 16
      src/csharp/Grpc.sln
  27. 4
      src/csharp/generate_proto_csharp.sh
  28. 4
      src/csharp/tests.json
  29. 26
      templates/src/csharp/Grpc.Reflection.Tests/project.json.template
  30. 43
      templates/src/csharp/Grpc.Reflection/project.json.template

@ -115,7 +115,8 @@ namespace Grpc.Core.Tests
var otherAssemblies = new[] {
"Grpc.Examples.Tests",
"Grpc.HealthCheck.Tests",
"Grpc.IntegrationTesting"
"Grpc.IntegrationTesting",
"Grpc.Reflection.Tests",
};
foreach (var assemblyName in otherAssemblies)
{

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25123.0
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.Core", "Grpc.Core\Grpc.Core.xproj", "{DC9908B6-F291-4FC8-A46D-2EA2551790EC}"
EndProject
@ -31,6 +31,10 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.IntegrationTesting.Ser
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.IntegrationTesting.StressClient", "Grpc.IntegrationTesting.StressClient\Grpc.IntegrationTesting.StressClient.xproj", "{0EBC910B-8867-4D3E-8686-91F34183D839}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.Reflection", "Grpc.Reflection\Grpc.Reflection.xproj", "{2B372155-80BA-4CF9-82D6-4B938E8EC3A0}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Grpc.Reflection.Tests", "Grpc.Reflection.Tests\Grpc.Reflection.Tests.xproj", "{FE90181D-A4B3-4A5C-8490-F07561E18E3B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -93,6 +97,14 @@ Global
{0EBC910B-8867-4D3E-8686-91F34183D839}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0EBC910B-8867-4D3E-8686-91F34183D839}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0EBC910B-8867-4D3E-8686-91F34183D839}.Release|Any CPU.Build.0 = Release|Any CPU
{2B372155-80BA-4CF9-82D6-4B938E8EC3A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2B372155-80BA-4CF9-82D6-4B938E8EC3A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2B372155-80BA-4CF9-82D6-4B938E8EC3A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2B372155-80BA-4CF9-82D6-4B938E8EC3A0}.Release|Any CPU.Build.0 = Release|Any CPU
{FE90181D-A4B3-4A5C-8490-F07561E18E3B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FE90181D-A4B3-4A5C-8490-F07561E18E3B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FE90181D-A4B3-4A5C-8490-F07561E18E3B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FE90181D-A4B3-4A5C-8490-F07561E18E3B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B88F91D6-436D-4C78-8B99-47800FA8DE03}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Grpc.Reflection.Tests</RootNamespace>
<AssemblyName>Grpc.Reflection.Tests</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\ReleaseSigned</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="nunit.framework">
<HintPath>..\packages\NUnit.3.2.0\lib\net45\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="nunitlite">
<HintPath>..\packages\NUnitLite.3.2.0\lib\net45\nunitlite.dll</HintPath>
</Reference>
<Reference Include="Google.Protobuf">
<HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="System.Interactive.Async">
<HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
<Link>Version.cs</Link>
</Compile>
<Compile Include="SymbolRegistryTest.cs" />
<Compile Include="ReflectionClientServerTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="NUnitMain.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj">
<Project>{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}</Project>
<Name>Grpc.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Grpc.Reflection\Grpc.Reflection.csproj">
<Project>{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}</Project>
<Name>Grpc.Reflection</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="Grpc.Reflection.Tests.project.json" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

@ -0,0 +1,8 @@
{
"frameworks": {
"net45": { }
},
"runtimes": {
"win": { }
}
}

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.25123" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25123</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>fe90181d-a4b3-4a5c-8490-f07561e18e3b</ProjectGuid>
<RootNamespace>Grpc.Reflection.Tests</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

@ -0,0 +1,59 @@
#region Copyright notice and license
// Copyright 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.Reflection;
using Grpc.Core;
using Grpc.Core.Logging;
using NUnit.Common;
using NUnitLite;
namespace Grpc.Reflection.Tests
{
/// <summary>
/// Provides entry point for NUnitLite
/// </summary>
public class NUnitMain
{
public static int Main(string[] args)
{
// Make logger immune to NUnit capturing stdout and stderr to workaround https://github.com/nunit/nunit/issues/1406.
GrpcEnvironment.SetLogger(new TextWriterLogger(Console.Error));
#if NETCOREAPP1_0
return new AutoRun(typeof(NUnitMain).GetTypeInfo().Assembly).Execute(args, new ExtendedTextWrapper(Console.Out), Console.In);
#else
return new AutoRun().Execute(args);
#endif
}
}
}

@ -0,0 +1,44 @@
#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.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle("Grpc.Reflection.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

@ -0,0 +1,154 @@
#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.Linq;
using System.Text;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Reflection;
using Grpc.Reflection.V1Alpha;
using NUnit.Framework;
namespace Grpc.Reflection.Tests
{
/// <summary>
/// Reflection client talks to reflection server.
/// </summary>
public class ReflectionClientServerTest
{
const string Host = "localhost";
Server server;
Channel channel;
ServerReflection.ServerReflectionClient client;
ReflectionServiceImpl serviceImpl;
[TestFixtureSetUp]
public void Init()
{
serviceImpl = new ReflectionServiceImpl(ServerReflection.Descriptor);
server = new Server
{
Services = { ServerReflection.BindService(serviceImpl) },
Ports = { { Host, ServerPort.PickUnused, ServerCredentials.Insecure } }
};
server.Start();
channel = new Channel(Host, server.Ports.Single().BoundPort, ChannelCredentials.Insecure);
client = new ServerReflection.ServerReflectionClient(channel);
}
[TestFixtureTearDown]
public void Cleanup()
{
channel.ShutdownAsync().Wait();
server.ShutdownAsync().Wait();
}
[Test]
public async Task FileByFilename_NotFound()
{
var response = await SingleRequestAsync(new ServerReflectionRequest
{
FileByFilename = "somepackage/nonexistent.proto"
});
Assert.AreEqual((int)StatusCode.NotFound, response.ErrorResponse.ErrorCode);
}
[Test]
public async Task FileByFilename()
{
var response = await SingleRequestAsync(new ServerReflectionRequest
{
FileByFilename = "grpc/reflection/v1alpha/reflection.proto"
});
Assert.AreEqual(1, response.FileDescriptorResponse.FileDescriptorProto.Count);
Assert.AreEqual(ReflectionReflection.Descriptor.SerializedData, response.FileDescriptorResponse.FileDescriptorProto[0]);
}
[Test]
public async Task FileContainingSymbol()
{
var response = await SingleRequestAsync(new ServerReflectionRequest
{
FileContainingSymbol = "grpc.reflection.v1alpha.ServerReflection"
});
Assert.AreEqual(1, response.FileDescriptorResponse.FileDescriptorProto.Count);
Assert.AreEqual(ReflectionReflection.Descriptor.SerializedData, response.FileDescriptorResponse.FileDescriptorProto[0]);
}
[Test]
public async Task FileContainingSymbol_NotFound()
{
var response = await SingleRequestAsync(new ServerReflectionRequest
{
FileContainingSymbol = "somepackage.Nonexistent"
});
Assert.AreEqual((int)StatusCode.NotFound, response.ErrorResponse.ErrorCode);
}
[Test]
public async Task ListServices()
{
var response = await SingleRequestAsync(new ServerReflectionRequest
{
ListServices = ""
});
Assert.AreEqual(1, response.ListServicesResponse.Service.Count);
Assert.AreEqual(ServerReflection.Descriptor.FullName, response.ListServicesResponse.Service[0].Name);
}
[Test]
public async Task FileContainingExtension()
{
var response = await SingleRequestAsync(new ServerReflectionRequest
{
FileContainingExtension = new ExtensionRequest()
});
Assert.AreEqual((int)StatusCode.Unimplemented, response.ErrorResponse.ErrorCode);
}
private async Task<ServerReflectionResponse> SingleRequestAsync(ServerReflectionRequest request)
{
var call = client.ServerReflectionInfo();
await call.RequestStream.WriteAsync(request);
Assert.IsTrue(await call.ResponseStream.MoveNext());
var response = call.ResponseStream.Current;
await call.RequestStream.CompleteAsync();
Assert.IsFalse(await call.ResponseStream.MoveNext());
return response;
}
}
}

@ -0,0 +1,63 @@
#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 Grpc.Reflection;
using Grpc.Reflection.V1Alpha;
using NUnit.Framework;
namespace Grpc.Reflection.Tests
{
/// <summary>
/// Tests for ReflectionServiceImpl
/// </summary>
public class SymbolRegistryTest
{
SymbolRegistry registry = SymbolRegistry.FromFiles(new[] { ReflectionReflection.Descriptor, Google.Protobuf.WellKnownTypes.Duration.Descriptor.File });
[Test]
public void FileByName()
{
Assert.AreSame(Google.Protobuf.WellKnownTypes.Duration.Descriptor.File, registry.FileByName("google/protobuf/duration.proto"));
Assert.IsNull(registry.FileByName("somepackage/nonexistent.proto"));
}
[Test]
public void FileContainingSymbol()
{
Assert.AreSame(Google.Protobuf.WellKnownTypes.Duration.Descriptor.File, registry.FileContainingSymbol("google.protobuf.Duration"));
Assert.AreSame(ReflectionReflection.Descriptor, registry.FileContainingSymbol("grpc.reflection.v1alpha.ServerReflection.ServerReflectionInfo")); // method
Assert.AreSame(ReflectionReflection.Descriptor, registry.FileContainingSymbol("grpc.reflection.v1alpha.ServerReflection")); // service
Assert.AreSame(ReflectionReflection.Descriptor, registry.FileContainingSymbol("grpc.reflection.v1alpha.ServerReflectionRequest")); // message
Assert.IsNull(registry.FileContainingSymbol("somepackage.Nonexistent"));
}
}
}

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
<package id="NUnit" version="3.2.0" targetFramework="net45" />
<package id="NUnitLite" version="3.2.0" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages>

@ -0,0 +1,65 @@
{
"buildOptions": {
"emitEntryPoint": true
},
"configurations": {
"Debug": {
"buildOptions": {
"define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk",
"xmlDoc": true,
"compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ]
},
"copyToOutput": {
"mappings": {
"grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Debug/grpc_csharp_ext.dll",
"grpc_csharp_ext.x86.dll": "../../../vsprojects/Debug/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/dbg/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/dbg/libgrpc_csharp_ext.dylib"
}
}
}
},
"Release": {
"buildOptions": {
"define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk",
"xmlDoc": true,
"compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ]
},
"copyToOutput": {
"mappings": {
"grpc_csharp_ext.x64.dll": "../../../vsprojects/x64/Release/grpc_csharp_ext.dll",
"grpc_csharp_ext.x86.dll": "../../../vsprojects/Release/grpc_csharp_ext.dll",
"libgrpc_csharp_ext.x64.so": "../../../libs/opt/libgrpc_csharp_ext.so",
"libgrpc_csharp_ext.x64.dylib": "../../../libs/opt/libgrpc_csharp_ext.dylib"
}
}
}
}
},
"dependencies": {
"Grpc.Reflection": {
"target": "project"
},
"NUnit": "3.2.0",
"NUnitLite": "3.2.0-*"
},
"frameworks": {
"net45": { },
"netcoreapp1.0": {
"imports": [
"portable-net45"
],
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
}
}
}
}
}

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Grpc.Reflection</RootNamespace>
<AssemblyName>Grpc.Reflection</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<DocumentationFile>bin\$(Configuration)\Grpc.Reflection.Xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\ReleaseSigned</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\keys\Grpc.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Google.Protobuf">
<HintPath>..\packages\Google.Protobuf.3.0.0\lib\net45\Google.Protobuf.dll</HintPath>
</Reference>
<Reference Include="System.Interactive.Async">
<HintPath>..\packages\System.Interactive.Async.3.1.1\lib\net45\System.Interactive.Async.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Grpc.Core\Version.cs">
<Link>Version.cs</Link>
</Compile>
<Compile Include="SymbolRegistry.cs" />
<Compile Include="ReflectionServiceImpl.cs" />
<Compile Include="Reflection.cs" />
<Compile Include="ReflectionGrpc.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Grpc.Reflection.nuspec" />
<None Include="Grpc.Reflection.project.json" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Grpc.Core\Grpc.Core.csproj">
<Project>{ccc4440e-49f7-4790-b0af-feabb0837ae7}</Project>
<Name>Grpc.Core</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<package>
<metadata>
<id>Grpc.Reflection</id>
<title>gRPC C# Reflection</title>
<summary>Implementation of gRPC reflection service</summary>
<description>Provides information about services running on a gRPC C# server.</description>
<version>$version$</version>
<authors>Google Inc.</authors>
<owners>grpc-packages</owners>
<licenseUrl>https://github.com/grpc/grpc/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/grpc/grpc</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<copyright>Copyright 2016, Google Inc.</copyright>
<tags>gRPC reflection</tags>
<dependencies>
<dependency id="Google.Protobuf" version="$ProtobufVersion$" />
<dependency id="Grpc.Core" version="$version$" />
<dependency id="System.Interactive.Async" version="3.1.1" />
</dependencies>
</metadata>
<files>
<file src="bin/ReleaseSigned/Grpc.Reflection.dll" target="lib/net45" />
<file src="bin/ReleaseSigned/Grpc.Reflection.pdb" target="lib/net45" />
<file src="bin/ReleaseSigned/Grpc.Reflection.xml" target="lib/net45" />
<file src="**\*.cs" target="src" />
</files>
</package>

@ -0,0 +1,8 @@
{
"frameworks": {
"net45": { }
},
"runtimes": {
"win": { }
}
}

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0.25123" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0.25123</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>2b372155-80ba-4cf9-82d6-4b938e8ec3a0</ProjectGuid>
<RootNamespace>Grpc.Reflection</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

@ -0,0 +1,44 @@
#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.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle("Grpc.Reflection")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("Google Inc. All rights reserved.")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

File diff suppressed because it is too large Load Diff

@ -0,0 +1,132 @@
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: reflection.proto
// Original file comments:
// Copyright 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.
//
// Service exported by server reflection
//
#region Designer generated code
using System;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
namespace Grpc.Reflection.V1Alpha {
public static class ServerReflection
{
static readonly string __ServiceName = "grpc.reflection.v1alpha.ServerReflection";
static readonly Marshaller<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest> __Marshaller_ServerReflectionRequest = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Reflection.V1Alpha.ServerReflectionRequest.Parser.ParseFrom);
static readonly Marshaller<global::Grpc.Reflection.V1Alpha.ServerReflectionResponse> __Marshaller_ServerReflectionResponse = Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Reflection.V1Alpha.ServerReflectionResponse.Parser.ParseFrom);
static readonly Method<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest, global::Grpc.Reflection.V1Alpha.ServerReflectionResponse> __Method_ServerReflectionInfo = new Method<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest, global::Grpc.Reflection.V1Alpha.ServerReflectionResponse>(
MethodType.DuplexStreaming,
__ServiceName,
"ServerReflectionInfo",
__Marshaller_ServerReflectionRequest,
__Marshaller_ServerReflectionResponse);
/// <summary>Service descriptor</summary>
public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
{
get { return global::Grpc.Reflection.V1Alpha.ReflectionReflection.Descriptor.Services[0]; }
}
/// <summary>Base class for server-side implementations of ServerReflection</summary>
public abstract class ServerReflectionBase
{
/// <summary>
/// The reflection service is structured as a bidirectional stream, ensuring
/// all related requests go to a single server.
/// </summary>
public virtual global::System.Threading.Tasks.Task ServerReflectionInfo(IAsyncStreamReader<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest> requestStream, IServerStreamWriter<global::Grpc.Reflection.V1Alpha.ServerReflectionResponse> responseStream, ServerCallContext context)
{
throw new RpcException(new Status(StatusCode.Unimplemented, ""));
}
}
/// <summary>Client for ServerReflection</summary>
public class ServerReflectionClient : ClientBase<ServerReflectionClient>
{
/// <summary>Creates a new client for ServerReflection</summary>
/// <param name="channel">The channel to use to make remote calls.</param>
public ServerReflectionClient(Channel channel) : base(channel)
{
}
/// <summary>Creates a new client for ServerReflection that uses a custom <c>CallInvoker</c>.</summary>
/// <param name="callInvoker">The callInvoker to use to make remote calls.</param>
public ServerReflectionClient(CallInvoker callInvoker) : base(callInvoker)
{
}
/// <summary>Protected parameterless constructor to allow creation of test doubles.</summary>
protected ServerReflectionClient() : base()
{
}
/// <summary>Protected constructor to allow creation of configured clients.</summary>
/// <param name="configuration">The client configuration.</param>
protected ServerReflectionClient(ClientBaseConfiguration configuration) : base(configuration)
{
}
/// <summary>
/// The reflection service is structured as a bidirectional stream, ensuring
/// all related requests go to a single server.
/// </summary>
public virtual AsyncDuplexStreamingCall<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest, global::Grpc.Reflection.V1Alpha.ServerReflectionResponse> ServerReflectionInfo(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
{
return ServerReflectionInfo(new CallOptions(headers, deadline, cancellationToken));
}
/// <summary>
/// The reflection service is structured as a bidirectional stream, ensuring
/// all related requests go to a single server.
/// </summary>
public virtual AsyncDuplexStreamingCall<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest, global::Grpc.Reflection.V1Alpha.ServerReflectionResponse> ServerReflectionInfo(CallOptions options)
{
return CallInvoker.AsyncDuplexStreamingCall(__Method_ServerReflectionInfo, null, options);
}
/// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
protected override ServerReflectionClient NewInstance(ClientBaseConfiguration configuration)
{
return new ServerReflectionClient(configuration);
}
}
/// <summary>Creates service definition that can be registered with a server</summary>
public static ServerServiceDefinition BindService(ServerReflectionBase serviceImpl)
{
return ServerServiceDefinition.CreateBuilder()
.AddMethod(__Method_ServerReflectionInfo, serviceImpl.ServerReflectionInfo).Build();
}
}
}
#endregion

@ -0,0 +1,173 @@
#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.Linq;
using System.Text;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Core.Utils;
using Grpc.Reflection.V1Alpha;
using Google.Protobuf.Reflection;
namespace Grpc.Reflection
{
/// <summary>
/// Implementation of server reflection service.
/// </summary>
public class ReflectionServiceImpl : Grpc.Reflection.V1Alpha.ServerReflection.ServerReflectionBase
{
readonly List<string> services;
readonly SymbolRegistry symbolRegistry;
/// <summary>
/// Creates a new instance of <c>ReflectionServiceIml</c>.
/// </summary>
public ReflectionServiceImpl(IEnumerable<string> services, SymbolRegistry symbolRegistry)
{
this.services = new List<string>(services);
this.symbolRegistry = symbolRegistry;
}
/// <summary>
/// Creates a new instance of <c>ReflectionServiceIml</c>.
/// </summary>
public ReflectionServiceImpl(IEnumerable<ServiceDescriptor> serviceDescriptors)
{
this.services = new List<string>(serviceDescriptors.Select((serviceDescriptor) => serviceDescriptor.FullName));
this.symbolRegistry = SymbolRegistry.FromFiles(serviceDescriptors.Select((serviceDescriptor) => serviceDescriptor.File));
}
/// <summary>
/// Creates a new instance of <c>ReflectionServiceIml</c>.
/// </summary>
public ReflectionServiceImpl(params ServiceDescriptor[] serviceDescriptors) : this((IEnumerable<ServiceDescriptor>) serviceDescriptors)
{
}
public override async Task ServerReflectionInfo(IAsyncStreamReader<ServerReflectionRequest> requestStream, IServerStreamWriter<ServerReflectionResponse> responseStream, ServerCallContext context)
{
while (await requestStream.MoveNext())
{
var response = ProcessRequest(requestStream.Current);
await responseStream.WriteAsync(response);
}
}
ServerReflectionResponse ProcessRequest(ServerReflectionRequest request)
{
switch (request.MessageRequestCase)
{
case ServerReflectionRequest.MessageRequestOneofCase.FileByFilename:
return FileByFilename(request.FileByFilename);
case ServerReflectionRequest.MessageRequestOneofCase.FileContainingSymbol:
return FileContainingSymbol(request.FileContainingSymbol);
case ServerReflectionRequest.MessageRequestOneofCase.ListServices:
return ListServices();
case ServerReflectionRequest.MessageRequestOneofCase.AllExtensionNumbersOfType:
case ServerReflectionRequest.MessageRequestOneofCase.FileContainingExtension:
default:
return CreateErrorResponse(StatusCode.Unimplemented, "Request type not supported by C# reflection service.");
}
}
ServerReflectionResponse FileByFilename(string filename)
{
FileDescriptor file = symbolRegistry.FileByName(filename);
if (file == null)
{
return CreateErrorResponse(StatusCode.NotFound, "File not found.");
}
var transitiveDependencies = new HashSet<FileDescriptor>();
CollectTransitiveDependencies(file, transitiveDependencies);
return new ServerReflectionResponse
{
FileDescriptorResponse = new FileDescriptorResponse { FileDescriptorProto = { transitiveDependencies.Select((d) => d.SerializedData) } }
};
}
ServerReflectionResponse FileContainingSymbol(string symbol)
{
FileDescriptor file = symbolRegistry.FileContainingSymbol(symbol);
if (file == null)
{
return CreateErrorResponse(StatusCode.NotFound, "Symbol not found.");
}
var transitiveDependencies = new HashSet<FileDescriptor>();
CollectTransitiveDependencies(file, transitiveDependencies);
return new ServerReflectionResponse
{
FileDescriptorResponse = new FileDescriptorResponse { FileDescriptorProto = { transitiveDependencies.Select((d) => d.SerializedData) } }
};
}
ServerReflectionResponse ListServices()
{
var serviceResponses = new ListServiceResponse();
foreach (string serviceName in services)
{
serviceResponses.Service.Add(new ServiceResponse { Name = serviceName });
}
return new ServerReflectionResponse
{
ListServicesResponse = serviceResponses
};
}
ServerReflectionResponse CreateErrorResponse(StatusCode status, string message)
{
return new ServerReflectionResponse
{
ErrorResponse = new ErrorResponse { ErrorCode = (int) status, ErrorMessage = message }
};
}
void CollectTransitiveDependencies(FileDescriptor descriptor, HashSet<FileDescriptor> pool)
{
pool.Add(descriptor);
foreach (var dependency in descriptor.Dependencies)
{
if (pool.Add(dependency))
{
// descriptors cannot have circular dependencies
CollectTransitiveDependencies(dependency, pool);
}
}
}
}
}

@ -0,0 +1,10 @@
<StyleCopSettings Version="105">
<SourceFileList>
<SourceFile>Health.cs</SourceFile>
<Settings>
<GlobalSettings>
<BooleanProperty Name="RulesEnabledByDefault">False</BooleanProperty>
</GlobalSettings>
</Settings>
</SourceFileList>
</StyleCopSettings>

@ -0,0 +1,160 @@
#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.Collections.Generic;
using Grpc.Core.Utils;
using Google.Protobuf.Reflection;
namespace Grpc.Reflection
{
/// <summary>Registry of protobuf symbols</summary>
public class SymbolRegistry
{
private readonly Dictionary<string, FileDescriptor> filesByName;
private readonly Dictionary<string, FileDescriptor> filesBySymbol;
private SymbolRegistry(Dictionary<string, FileDescriptor> filesByName, Dictionary<string, FileDescriptor> filesBySymbol)
{
this.filesByName = new Dictionary<string, FileDescriptor>(filesByName);
this.filesBySymbol = new Dictionary<string, FileDescriptor>(filesBySymbol);
}
/// <summary>
/// Creates a symbol registry from the specified set of file descriptors.
/// </summary>
/// <param name="fileDescriptors">The set of files to include in the registry. Must not contain null values.</param>
/// <returns>A symbol registry for the given files.</returns>
public static SymbolRegistry FromFiles(IEnumerable<FileDescriptor> fileDescriptors)
{
GrpcPreconditions.CheckNotNull(fileDescriptors);
var builder = new Builder();
foreach (var file in fileDescriptors)
{
builder.AddFile(file);
}
return builder.Build();
}
/// <summary>
/// Gets file descriptor for given file name (including package path). Returns <c>null</c> if not found.
/// </summary>
public FileDescriptor FileByName(string filename)
{
FileDescriptor file;
filesByName.TryGetValue(filename, out file);
return file;
}
/// <summary>
/// Gets file descriptor that contains definition of given symbol full name (including package path). Returns <c>null</c> if not found.
/// </summary>
public FileDescriptor FileContainingSymbol(string symbol)
{
FileDescriptor file;
filesBySymbol.TryGetValue(symbol, out file);
return file;
}
/// <summary>
/// Builder class which isn't exposed, but acts as a convenient alternative to passing round two dictionaries in recursive calls.
/// </summary>
private class Builder
{
private readonly Dictionary<string, FileDescriptor> filesByName;
private readonly Dictionary<string, FileDescriptor> filesBySymbol;
internal Builder()
{
filesByName = new Dictionary<string, FileDescriptor>();
filesBySymbol = new Dictionary<string, FileDescriptor>();
}
internal void AddFile(FileDescriptor fileDescriptor)
{
if (filesByName.ContainsKey(fileDescriptor.Name))
{
return;
}
filesByName.Add(fileDescriptor.Name, fileDescriptor);
foreach (var dependency in fileDescriptor.Dependencies)
{
AddFile(dependency);
}
foreach (var enumeration in fileDescriptor.EnumTypes)
{
AddEnum(enumeration);
}
foreach (var message in fileDescriptor.MessageTypes)
{
AddMessage(message);
}
foreach (var service in fileDescriptor.Services)
{
AddService(service);
}
}
private void AddEnum(EnumDescriptor enumDescriptor)
{
filesBySymbol[enumDescriptor.FullName] = enumDescriptor.File;
}
private void AddMessage(MessageDescriptor messageDescriptor)
{
foreach (var nestedEnum in messageDescriptor.EnumTypes)
{
AddEnum(nestedEnum);
}
foreach (var nestedType in messageDescriptor.NestedTypes)
{
AddMessage(nestedType);
}
filesBySymbol[messageDescriptor.FullName] = messageDescriptor.File;
}
private void AddService(ServiceDescriptor serviceDescriptor)
{
foreach (var method in serviceDescriptor.Methods)
{
filesBySymbol[method.FullName] = method.File;
}
filesBySymbol[serviceDescriptor.FullName] = serviceDescriptor.File;
}
internal SymbolRegistry Build()
{
return new SymbolRegistry(filesByName, filesBySymbol);
}
}
}
}

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Google.Protobuf" version="3.0.0" targetFramework="net45" />
<package id="System.Interactive.Async" version="3.1.1" targetFramework="net45" />
</packages>

@ -0,0 +1,41 @@
{
"version": "1.1.0-dev",
"title": "gRPC C# Reflection",
"authors": [ "Google Inc." ],
"copyright": "Copyright 2016, Google Inc.",
"packOptions": {
"summary": "Implementation of gRPC reflection service",
"description": "Provides information about services running on a gRPC C# server.",
"owners": [ "grpc-packages" ],
"licenseUrl": "https://github.com/grpc/grpc/blob/master/LICENSE",
"projectUrl": "https://github.com/grpc/grpc",
"requireLicenseAcceptance": false,
"tags": [ "gRPC reflection" ]
},
"buildOptions": {
"define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true,
"compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ]
}
},
"dependencies": {
"Grpc.Core": "1.1.0-dev",
"Google.Protobuf": "3.0.0"
},
"frameworks": {
"net45": {
"frameworkAssemblies": {
"System.Runtime": "",
"System.IO": ""
}
},
"netstandard1.5": {
"dependencies": {
"NETStandard.Library": "1.6.0"
}
}
}
}

@ -36,6 +36,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.Qps
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.IntegrationTesting.StressClient", "Grpc.IntegrationTesting.StressClient\Grpc.IntegrationTesting.StressClient.csproj", "{ADEBA147-80AE-4710-82E9-5B7F93690266}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Reflection", "Grpc.Reflection\Grpc.Reflection.csproj", "{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grpc.Reflection.Tests", "Grpc.Reflection.Tests\Grpc.Reflection.Tests.csproj", "{B88F91D6-436D-4C78-8B99-47800FA8DE03}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -55,6 +59,12 @@ Global
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|Any CPU.Build.0 = Release|Any CPU
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}.Release|Any CPU.Build.0 = Release|Any CPU
{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{4F18CF52-B3DB-4A77-97C5-7F7F4B6C1715}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -103,6 +113,12 @@ Global
{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.Release|Any CPU.Build.0 = Release|Any CPU
{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.ReleaseSigned|Any CPU.ActiveCfg = Release|Any CPU
{B82B7DFE-7F7B-40EF-B3D6-064FF2B01294}.ReleaseSigned|Any CPU.Build.0 = Release|Any CPU
{B88F91D6-436D-4C78-8B99-47800FA8DE03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B88F91D6-436D-4C78-8B99-47800FA8DE03}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B88F91D6-436D-4C78-8B99-47800FA8DE03}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B88F91D6-436D-4C78-8B99-47800FA8DE03}.Release|Any CPU.Build.0 = Release|Any CPU
{B88F91D6-436D-4C78-8B99-47800FA8DE03}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU
{B88F91D6-436D-4C78-8B99-47800FA8DE03}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|Any CPU.ActiveCfg = Release|Any CPU

@ -36,6 +36,7 @@ PROTOC=bins/opt/protobuf/protoc
PLUGIN=protoc-gen-grpc=bins/opt/grpc_csharp_plugin
EXAMPLES_DIR=src/csharp/Grpc.Examples
HEALTHCHECK_DIR=src/csharp/Grpc.HealthCheck
REFLECTION_DIR=src/csharp/Grpc.Reflection
TESTING_DIR=src/csharp/Grpc.IntegrationTesting
$PROTOC --plugin=$PLUGIN --csharp_out=$EXAMPLES_DIR --grpc_out=$EXAMPLES_DIR \
@ -43,6 +44,9 @@ $PROTOC --plugin=$PLUGIN --csharp_out=$EXAMPLES_DIR --grpc_out=$EXAMPLES_DIR \
$PROTOC --plugin=$PLUGIN --csharp_out=$HEALTHCHECK_DIR --grpc_out=$HEALTHCHECK_DIR \
-I src/proto/grpc/health/v1 src/proto/grpc/health/v1/health.proto
$PROTOC --plugin=$PLUGIN --csharp_out=$REFLECTION_DIR --grpc_out=$REFLECTION_DIR \
-I src/proto/grpc/reflection/v1alpha src/proto/grpc/reflection/v1alpha/reflection.proto
$PROTOC --plugin=$PLUGIN --csharp_out=$TESTING_DIR --grpc_out=$TESTING_DIR \
-I . src/proto/grpc/testing/{control,empty,messages,metrics,payloads,services,stats,test}.proto

@ -48,5 +48,9 @@
"Grpc.IntegrationTesting.MetadataCredentialsTest",
"Grpc.IntegrationTesting.RunnerClientServerTest",
"Grpc.IntegrationTesting.SslCredentialsTest"
],
"Grpc.Reflection.Tests": [
"Grpc.Reflection.Tests.ReflectionClientServerTest",
"Grpc.Reflection.Tests.SymbolRegistryTest"
]
}

@ -0,0 +1,26 @@
%YAML 1.2
--- |
{
<%include file="../build_options.include" args="executable=True"/>
"dependencies": {
"Grpc.Reflection": {
"target": "project"
},
"NUnit": "3.2.0",
"NUnitLite": "3.2.0-*"
},
"frameworks": {
"net45": { },
"netcoreapp1.0": {
"imports": [
"portable-net45"
],
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
}
}
}
}
}

@ -0,0 +1,43 @@
%YAML 1.2
--- |
{
"version": "${settings.csharp_version}",
"title": "gRPC C# Reflection",
"authors": [ "Google Inc." ],
"copyright": "Copyright 2016, Google Inc.",
"packOptions": {
"summary": "Implementation of gRPC reflection service",
"description": "Provides information about services running on a gRPC C# server.",
"owners": [ "grpc-packages" ],
"licenseUrl": "https://github.com/grpc/grpc/blob/master/LICENSE",
"projectUrl": "https://github.com/grpc/grpc",
"requireLicenseAcceptance": false,
"tags": [ "gRPC reflection" ]
},
"buildOptions": {
"define": [ "SIGNED" ],
"keyFile": "../keys/Grpc.snk",
"publicSign": true,
"xmlDoc": true,
"compile": {
"includeFiles": [ "../Grpc.Core/Version.cs" ]
}
},
"dependencies": {
"Grpc.Core": "${settings.csharp_version}",
"Google.Protobuf": "3.0.0"
},
"frameworks": {
"net45": {
"frameworkAssemblies": {
"System.Runtime": "",
"System.IO": ""
}
},
"netstandard1.5": {
"dependencies": {
"NETStandard.Library": "1.6.0"
}
}
}
}
Loading…
Cancel
Save