diff --git a/.gitignore b/.gitignore
index 894a44cc..57a8c6a4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -102,3 +102,24 @@ venv.bak/
# mypy
.mypy_cache/
+
+# Visual Studio
+.vs/
+.vscode/
+
+# CSharp
+[Oo]bj/
+[Dd]ebug/
+[Rr]elease/
+[Pp]roperties/
+*.dll
+*.exe
+appsettings.json
+appsettings.*.json
+
+# Certificate files
+*.cer
+*.pfx
+
+
+
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 56422821..663d2eb0 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,3 +1,4 @@
{
- "workbench.colorCustomizations": {}
+ "workbench.colorCustomizations": {},
+ "python.pythonPath": "C:\\Users\\shbanerj\\.conda\\envs\\py-azurefunctions\\python.exe"
}
\ No newline at end of file
diff --git a/investigations/DotNetGrpcClient/DotNetGrpcClient.csproj b/investigations/DotNetGrpcClient/DotNetGrpcClient.csproj
new file mode 100644
index 00000000..b9261141
--- /dev/null
+++ b/investigations/DotNetGrpcClient/DotNetGrpcClient.csproj
@@ -0,0 +1,19 @@
+
+
+
+ Exe
+ netcoreapp3.0
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
diff --git a/investigations/DotNetGrpcClient/Program.cs b/investigations/DotNetGrpcClient/Program.cs
new file mode 100644
index 00000000..a8d9e08c
--- /dev/null
+++ b/investigations/DotNetGrpcClient/Program.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Net.Http;
+using System.Threading.Tasks;
+using DotNetGrpcService;
+using Grpc.Net.Client;
+
+namespace GrpcGreeterClient
+{
+ class Program
+ {
+ static async Task Main(string[] args)
+ {
+ // The port number(5001) must match the port of the gRPC server.
+
+ Console.WriteLine("Calling C# Endpoint...");
+ await CallEndpoint("http://localhost:5000", true);
+
+ Console.WriteLine("Calling Python Endpoint...");
+ await CallEndpoint("http://localhost:50051", true);
+
+
+ Console.WriteLine("Press any key to exit...");
+ Console.ReadKey();
+ }
+
+ static GrpcChannel GetChannel(string grpcEndpointAddress, bool isInsecure = false)
+ {
+ AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", isInsecure);
+ return GrpcChannel.ForAddress(grpcEndpointAddress);
+ }
+
+ static async Task CallEndpoint(string grpcEndpointAddress, bool isInsecure = false)
+ {
+ var channel = GetChannel(grpcEndpointAddress, isInsecure);
+ var client = new Greeter.GreeterClient(channel);
+
+ var reply = await client.SayHelloAsync(
+ new HelloRequest { Name = "GreeterClient" });
+ Console.WriteLine("Greeting: " + reply.Message);
+ }
+ }
+}
\ No newline at end of file
diff --git a/investigations/DotNetGrpcClient/Protos/greet.proto b/investigations/DotNetGrpcClient/Protos/greet.proto
new file mode 100644
index 00000000..62060ee9
--- /dev/null
+++ b/investigations/DotNetGrpcClient/Protos/greet.proto
@@ -0,0 +1,21 @@
+syntax = "proto3";
+
+option csharp_namespace = "DotNetGrpcService";
+
+package Greet;
+
+// The greeting service definition.
+service Greeter {
+ // Sends a greeting
+ rpc SayHello (HelloRequest) returns (HelloReply);
+}
+
+// The request message containing the user's name.
+message HelloRequest {
+ string name = 1;
+}
+
+// The response message containing the greetings.
+message HelloReply {
+ string message = 1;
+}
diff --git a/investigations/DotNetGrpcService/DotNetGrpcService.csproj b/investigations/DotNetGrpcService/DotNetGrpcService.csproj
new file mode 100644
index 00000000..6dbc3bbd
--- /dev/null
+++ b/investigations/DotNetGrpcService/DotNetGrpcService.csproj
@@ -0,0 +1,21 @@
+
+
+
+ netcoreapp3.0
+
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
diff --git a/investigations/DotNetGrpcService/DotNetGrpcService.sln b/investigations/DotNetGrpcService/DotNetGrpcService.sln
new file mode 100644
index 00000000..e2331799
--- /dev/null
+++ b/investigations/DotNetGrpcService/DotNetGrpcService.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29316.153
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetGrpcService", "DotNetGrpcService.csproj", "{6D265B48-69E0-4511-9E77-A8B6501AAB48}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DotNetGrpcClient", "..\DotNetGrpcClient\DotNetGrpcClient.csproj", "{3E1D7598-32EE-43DC-B9E6-22C3568742FF}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6D265B48-69E0-4511-9E77-A8B6501AAB48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6D265B48-69E0-4511-9E77-A8B6501AAB48}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6D265B48-69E0-4511-9E77-A8B6501AAB48}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6D265B48-69E0-4511-9E77-A8B6501AAB48}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3E1D7598-32EE-43DC-B9E6-22C3568742FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3E1D7598-32EE-43DC-B9E6-22C3568742FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3E1D7598-32EE-43DC-B9E6-22C3568742FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3E1D7598-32EE-43DC-B9E6-22C3568742FF}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {75B6A36C-EF88-4E3A-83FD-5BD41A270F0C}
+ EndGlobalSection
+EndGlobal
diff --git a/investigations/DotNetGrpcService/Program.cs b/investigations/DotNetGrpcService/Program.cs
new file mode 100644
index 00000000..6f6597c1
--- /dev/null
+++ b/investigations/DotNetGrpcService/Program.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+
+namespace DotNetGrpcService
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateHostBuilder(args).Build().Run();
+ }
+
+ // Additional configuration is required to successfully run gRPC on macOS.
+ // For instructions on how to configure Kestrel and gRPC clients on macOS, visit https://go.microsoft.com/fwlink/?linkid=2099682
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ });
+ }
+}
diff --git a/investigations/DotNetGrpcService/Protos/greet.proto b/investigations/DotNetGrpcService/Protos/greet.proto
new file mode 100644
index 00000000..62060ee9
--- /dev/null
+++ b/investigations/DotNetGrpcService/Protos/greet.proto
@@ -0,0 +1,21 @@
+syntax = "proto3";
+
+option csharp_namespace = "DotNetGrpcService";
+
+package Greet;
+
+// The greeting service definition.
+service Greeter {
+ // Sends a greeting
+ rpc SayHello (HelloRequest) returns (HelloReply);
+}
+
+// The request message containing the user's name.
+message HelloRequest {
+ string name = 1;
+}
+
+// The response message containing the greetings.
+message HelloReply {
+ string message = 1;
+}
diff --git a/investigations/DotNetGrpcService/Services/GreeterService.cs b/investigations/DotNetGrpcService/Services/GreeterService.cs
new file mode 100644
index 00000000..7d7fc516
--- /dev/null
+++ b/investigations/DotNetGrpcService/Services/GreeterService.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Grpc.Core;
+using Microsoft.Extensions.Logging;
+
+namespace DotNetGrpcService
+{
+ public class GreeterService : Greeter.GreeterBase
+ {
+ private readonly ILogger _logger;
+ public GreeterService(ILogger logger)
+ {
+ _logger = logger;
+ }
+
+ public override Task SayHello(HelloRequest request, ServerCallContext context)
+ {
+ return Task.FromResult(new HelloReply
+ {
+ Message = "Hello " + request.Name
+ });
+ }
+ }
+}
diff --git a/investigations/DotNetGrpcService/Startup.cs b/investigations/DotNetGrpcService/Startup.cs
new file mode 100644
index 00000000..d8bf433a
--- /dev/null
+++ b/investigations/DotNetGrpcService/Startup.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+
+namespace DotNetGrpcService
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddGrpc();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ app.UseRouting();
+
+ app.UseEndpoints(endpoints =>
+ {
+
+ endpoints.MapGrpcService();
+
+ endpoints.MapGet("/", async context =>
+ {
+ await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
+ });
+ });
+ }
+ }
+}
diff --git a/investigations/PythonGrpc/greet_client.py b/investigations/PythonGrpc/greet_client.py
new file mode 100644
index 00000000..bc4780dd
--- /dev/null
+++ b/investigations/PythonGrpc/greet_client.py
@@ -0,0 +1,26 @@
+import grpc
+
+import greet_pb2_grpc
+import greet_pb2
+
+
+
+def getChannel(grpcEndpointAddress):
+ return grpc.insecure_channel(grpcEndpointAddress)
+
+def sendGreetings(grpcChannel):
+ stub = greet_pb2_grpc.GreeterStub(grpcChannel)
+ reply = stub.SayHello(greet_pb2.HelloRequest(name='Shashank'))
+ return reply
+
+def main():
+ print ("Send greetings to C# Server...")
+ channel = getChannel("localhost:5000")
+ print(sendGreetings(channel))
+
+ print ("Send greetings to Python Server...")
+ channel = getChannel("localhost:50051")
+ print(sendGreetings(channel))
+
+if __name__ == '__main__':
+ main()
diff --git a/investigations/PythonGrpc/greet_pb2.py b/investigations/PythonGrpc/greet_pb2.py
new file mode 100644
index 00000000..2bb81b75
--- /dev/null
+++ b/investigations/PythonGrpc/greet_pb2.py
@@ -0,0 +1,134 @@
+# -*- coding: utf-8 -*-
+# Generated by the protocol buffer compiler. DO NOT EDIT!
+# source: greet.proto
+
+import sys
+_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
+from google.protobuf import descriptor as _descriptor
+from google.protobuf import message as _message
+from google.protobuf import reflection as _reflection
+from google.protobuf import symbol_database as _symbol_database
+# @@protoc_insertion_point(imports)
+
+_sym_db = _symbol_database.Default()
+
+
+
+
+DESCRIPTOR = _descriptor.FileDescriptor(
+ name='greet.proto',
+ package='Greet',
+ syntax='proto3',
+ serialized_options=_b('\252\002\021DotNetGrpcService'),
+ serialized_pb=_b('\n\x0bgreet.proto\x12\x05Greet\"\x1c\n\x0cHelloRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"\x1d\n\nHelloReply\x12\x0f\n\x07message\x18\x01 \x01(\t2=\n\x07Greeter\x12\x32\n\x08SayHello\x12\x13.Greet.HelloRequest\x1a\x11.Greet.HelloReplyB\x14\xaa\x02\x11\x44otNetGrpcServiceb\x06proto3')
+)
+
+
+
+
+_HELLOREQUEST = _descriptor.Descriptor(
+ name='HelloRequest',
+ full_name='Greet.HelloRequest',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='name', full_name='Greet.HelloRequest.name', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=22,
+ serialized_end=50,
+)
+
+
+_HELLOREPLY = _descriptor.Descriptor(
+ name='HelloReply',
+ full_name='Greet.HelloReply',
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name='message', full_name='Greet.HelloReply.message', index=0,
+ number=1, type=9, cpp_type=9, label=1,
+ has_default_value=False, default_value=_b("").decode('utf-8'),
+ message_type=None, enum_type=None, containing_type=None,
+ is_extension=False, extension_scope=None,
+ serialized_options=None, file=DESCRIPTOR),
+ ],
+ extensions=[
+ ],
+ nested_types=[],
+ enum_types=[
+ ],
+ serialized_options=None,
+ is_extendable=False,
+ syntax='proto3',
+ extension_ranges=[],
+ oneofs=[
+ ],
+ serialized_start=52,
+ serialized_end=81,
+)
+
+DESCRIPTOR.message_types_by_name['HelloRequest'] = _HELLOREQUEST
+DESCRIPTOR.message_types_by_name['HelloReply'] = _HELLOREPLY
+_sym_db.RegisterFileDescriptor(DESCRIPTOR)
+
+HelloRequest = _reflection.GeneratedProtocolMessageType('HelloRequest', (_message.Message,), {
+ 'DESCRIPTOR' : _HELLOREQUEST,
+ '__module__' : 'greet_pb2'
+ # @@protoc_insertion_point(class_scope:Greet.HelloRequest)
+ })
+_sym_db.RegisterMessage(HelloRequest)
+
+HelloReply = _reflection.GeneratedProtocolMessageType('HelloReply', (_message.Message,), {
+ 'DESCRIPTOR' : _HELLOREPLY,
+ '__module__' : 'greet_pb2'
+ # @@protoc_insertion_point(class_scope:Greet.HelloReply)
+ })
+_sym_db.RegisterMessage(HelloReply)
+
+
+DESCRIPTOR._options = None
+
+_GREETER = _descriptor.ServiceDescriptor(
+ name='Greeter',
+ full_name='Greet.Greeter',
+ file=DESCRIPTOR,
+ index=0,
+ serialized_options=None,
+ serialized_start=83,
+ serialized_end=144,
+ methods=[
+ _descriptor.MethodDescriptor(
+ name='SayHello',
+ full_name='Greet.Greeter.SayHello',
+ index=0,
+ containing_service=None,
+ input_type=_HELLOREQUEST,
+ output_type=_HELLOREPLY,
+ serialized_options=None,
+ ),
+])
+_sym_db.RegisterServiceDescriptor(_GREETER)
+
+DESCRIPTOR.services_by_name['Greeter'] = _GREETER
+
+# @@protoc_insertion_point(module_scope)
diff --git a/investigations/PythonGrpc/greet_pb2_grpc.py b/investigations/PythonGrpc/greet_pb2_grpc.py
new file mode 100644
index 00000000..cf5f056d
--- /dev/null
+++ b/investigations/PythonGrpc/greet_pb2_grpc.py
@@ -0,0 +1,46 @@
+# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
+import grpc
+
+import greet_pb2 as greet__pb2
+
+
+class GreeterStub(object):
+ """The greeting service definition.
+ """
+
+ def __init__(self, channel):
+ """Constructor.
+
+ Args:
+ channel: A grpc.Channel.
+ """
+ self.SayHello = channel.unary_unary(
+ '/Greet.Greeter/SayHello',
+ request_serializer=greet__pb2.HelloRequest.SerializeToString,
+ response_deserializer=greet__pb2.HelloReply.FromString,
+ )
+
+
+class GreeterServicer(object):
+ """The greeting service definition.
+ """
+
+ def SayHello(self, request, context):
+ """Sends a greeting
+ """
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
+ context.set_details('Method not implemented!')
+ raise NotImplementedError('Method not implemented!')
+
+
+def add_GreeterServicer_to_server(servicer, server):
+ rpc_method_handlers = {
+ 'SayHello': grpc.unary_unary_rpc_method_handler(
+ servicer.SayHello,
+ request_deserializer=greet__pb2.HelloRequest.FromString,
+ response_serializer=greet__pb2.HelloReply.SerializeToString,
+ ),
+ }
+ generic_handler = grpc.method_handlers_generic_handler(
+ 'Greet.Greeter', rpc_method_handlers)
+ server.add_generic_rpc_handlers((generic_handler,))
diff --git a/investigations/PythonGrpc/greet_server.py b/investigations/PythonGrpc/greet_server.py
new file mode 100644
index 00000000..825ea02f
--- /dev/null
+++ b/investigations/PythonGrpc/greet_server.py
@@ -0,0 +1,24 @@
+from concurrent import futures
+import grpc
+
+import greet_pb2_grpc
+import greet_pb2
+
+class GreetServer (greet_pb2_grpc.GreeterServicer):
+
+ def SayHello(self, request, context):
+ print(f'Received client request from {request.name}')
+ return greet_pb2.HelloReply(message='Hello ' + request.name)
+
+def serve():
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
+ greet_pb2_grpc.add_GreeterServicer_to_server(GreetServer(), server)
+ print('Starting gRPC Server on port 50051')
+ server.add_insecure_port('[::]:50051')
+ server.start()
+ print('Started. Waiting for client connections...')
+ server.wait_for_termination()
+
+
+if __name__ == '__main__':
+ serve()
\ No newline at end of file