Merge branch 'master' into untypedAPI
diff --git a/include/grpc++/channel_arguments.h b/include/grpc++/channel_arguments.h
index b649ba2..8d338c6 100644
--- a/include/grpc++/channel_arguments.h
+++ b/include/grpc++/channel_arguments.h
@@ -66,7 +66,7 @@
   void SetChannelArgs(grpc_channel_args* channel_args) const;
 
  private:
-  friend class Channel;
+  friend class SecureCredentials;
   friend class testing::ChannelArgumentsTest;
 
   // TODO(yangg) implement copy and assign
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index ab2cc08..c297622 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -167,10 +167,9 @@
 grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
     void);
 
-/* --- Secure server creation. --- */
+/* --- Server-side secure ports. --- */
 
 /* Add a HTTP2 over an encrypted link over tcp listener.
-   Server must have been created with grpc_secure_server_create.
    Returns bound port number on success, 0 on failure.
    REQUIRES: server not started */
 int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc
index 5eb5c54..47f645c 100644
--- a/src/cpp/client/secure_credentials.cc
+++ b/src/cpp/client/secure_credentials.cc
@@ -54,7 +54,8 @@
     grpc_channel_args channel_args;
     args.SetChannelArgs(&channel_args);
     return std::shared_ptr<ChannelInterface>(new Channel(
-        target,
+        args.GetSslTargetNameOverride().empty()
+            ? target : args.GetSslTargetNameOverride(),
         grpc_secure_channel_create(c_creds_, target.c_str(), &channel_args)));
   }
 
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index 78b6cdde..c4b12b1 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -74,6 +74,8 @@
     <Compile Include="OperationFailedException.cs" />
     <Compile Include="Internal\AsyncCall.cs" />
     <Compile Include="Utils\Preconditions.cs" />
+    <Compile Include="Internal\ServerCredentialsSafeHandle.cs" />
+    <Compile Include="ServerCredentials.cs" />
   </ItemGroup>
   <Choose>
     <!-- Under older versions of Monodevelop, Choose is not supported and is just
diff --git a/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs
new file mode 100644
index 0000000..9611807
--- /dev/null
+++ b/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs
@@ -0,0 +1,68 @@
+#region Copyright notice and license
+// Copyright 2015, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core.Utils;
+
+namespace Grpc.Core.Internal
+{
+    /// <summary>
+    /// grpc_server_credentials from <grpc/grpc_security.h>
+    /// </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);
+
+        [DllImport("grpc_csharp_ext.dll")]
+        static extern void grpcsharp_server_credentials_release(IntPtr credentials);
+
+        private ServerCredentialsSafeHandle()
+        {
+        }
+
+        public static ServerCredentialsSafeHandle CreateSslCredentials(string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray)
+        {
+            Preconditions.CheckArgument(keyCertPairCertChainArray.Length == keyCertPairPrivateKeyArray.Length);
+            return grpcsharp_ssl_server_credentials_create(null,
+                                                           keyCertPairCertChainArray, keyCertPairPrivateKeyArray,
+                                                           new UIntPtr((ulong)keyCertPairCertChainArray.Length));
+        }
+
+        protected override bool ReleaseHandle()
+        {
+            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 de9bbaf..b5a5ae4 100644
--- a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
@@ -56,6 +56,9 @@
         static extern Int32 grpcsharp_server_add_http2_port(ServerSafeHandle server, string addr);
 
         [DllImport("grpc_csharp_ext.dll")]
+        static extern Int32 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")]
@@ -74,7 +77,6 @@
 
         public static ServerSafeHandle NewServer(CompletionQueueSafeHandle cq, IntPtr args)
         {
-            // TODO: also grpc_secure_server_create...
             return grpcsharp_server_create(cq, args);
         }
 
@@ -83,6 +85,11 @@
             return grpcsharp_server_add_http2_port(this, addr);
         }
 
+        public int AddPort(string addr, ServerCredentialsSafeHandle credentials)
+        {
+            return grpcsharp_server_add_secure_http2_port(this, addr, credentials);
+        }
+
         public void Start()
         {
             grpcsharp_server_start(this);
diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs
index 152cc21..cafdb3b 100644
--- a/src/csharp/Grpc.Core/Server.cs
+++ b/src/csharp/Grpc.Core/Server.cs
@@ -75,10 +75,20 @@
         }
 
         // only call before Start()
-        public int AddPort(string addr) {
+        public int AddPort(string addr)
+        {
             return handle.AddPort(addr);
         }
 
+        // only call before Start()
+        public int AddPort(string addr, ServerCredentials credentials)
+        {
+            using (var nativeCredentials = credentials.ToNativeCredentials())
+            {
+                return handle.AddPort(addr, nativeCredentials);
+            }
+        }
+
         public void Start()
         {
             handle.Start();
diff --git a/src/csharp/Grpc.Core/ServerCredentials.cs b/src/csharp/Grpc.Core/ServerCredentials.cs
new file mode 100644
index 0000000..1372e61
--- /dev/null
+++ b/src/csharp/Grpc.Core/ServerCredentials.cs
@@ -0,0 +1,107 @@
+#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 Grpc.Core.Internal;
+
+namespace Grpc.Core
+{
+    public abstract class ServerCredentials
+    {
+        /// <summary>
+        /// Creates native object for the credentials.
+        /// </summary>
+        /// <returns>The native credentials.</returns>
+        internal abstract ServerCredentialsSafeHandle ToNativeCredentials();
+    }
+
+    /// <summary>
+    /// Key certificate pair (in PEM encoding).
+    /// </summary>
+    public class KeyCertificatePair
+    {
+        string certChain;
+        string privateKey;
+
+        public KeyCertificatePair(string certChain, string privateKey)
+        {
+            this.certChain = certChain;
+            this.privateKey = privateKey;
+        }
+
+        public string CertChain
+        {
+            get
+            {
+                return certChain;
+            }
+        }
+
+        public string PrivateKey
+        {
+            get
+            {
+                return privateKey;
+            }
+        }
+    }
+
+    /// <summary>
+    /// Server-side SSL credentials.
+    /// </summary>
+    public class SslServerCredentials : ServerCredentials
+    {
+        // TODO: immutable list...
+        List<KeyCertificatePair> keyCertPairs;
+
+        public SslServerCredentials(List<KeyCertificatePair> keyCertPairs)
+        {
+            this.keyCertPairs = keyCertPairs;
+        }
+
+        internal override ServerCredentialsSafeHandle ToNativeCredentials()
+        {
+            int count = keyCertPairs.Count;
+            string[] certChains = new string[count];
+            string[] keys = new string[count];
+            for (int i = 0; i < count; i++)
+            {
+                certChains[i] = keyCertPairs[i].CertChain;
+                keys[i] = keyCertPairs[i].PrivateKey;
+            }
+            return ServerCredentialsSafeHandle.CreateSslCredentials(certChains, keys);
+        }
+    }
+}
+
diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
index 8f7a17e..438bf9e 100644
--- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
+++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
@@ -49,6 +49,7 @@
     <Compile Include="TestServiceImpl.cs" />
     <Compile Include="InteropServer.cs" />
     <Compile Include="InteropClient.cs" />
+    <Compile Include="TestCredentials.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ItemGroup>
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
index 30301f1..2992c42 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
@@ -51,7 +51,7 @@
         {
             public bool help;
             public string serverHost= "127.0.0.1";
-            public string serverHostOverride = "foo.test.google.fr";
+            public string serverHostOverride = TestCredentials.DefaultHostOverride;
             public int? serverPort;
             public string testCase = "large_unary";
             public bool useTls;
@@ -103,16 +103,7 @@
             Credentials credentials = null;
             if (options.useTls)
             {
-                string caPath = "data/ca.pem";  // Default testing CA
-                if (!options.useTestCa)
-                {
-                    caPath = Environment.GetEnvironmentVariable("SSL_CERT_FILE");
-                    if (string.IsNullOrEmpty(caPath))
-                    {
-                        throw new ArgumentException("CA path environment variable is not set.");
-                    }
-                }
-                credentials = new SslCredentials(File.ReadAllText(caPath));
+                credentials = TestCredentials.CreateTestClientCredentials(options.useTestCa);
             }
 
             ChannelArgs channelArgs = null;
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
index 4bb0b9e..ab2d6f4 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
@@ -59,9 +59,13 @@
 
             server = new Server();
             server.AddServiceDefinition(TestServiceGrpc.BindService(new TestServiceImpl()));
-            int port = server.AddPort(host + ":0");
+            int port = server.AddPort(host + ":0", TestCredentials.CreateTestServerCredentials());
             server.Start();
-            channel = new Channel(host + ":" + port);
+
+            var channelArgs = ChannelArgs.NewBuilder()
+                .AddString(ChannelArgs.SslTargetNameOverrideKey, TestCredentials.DefaultHostOverride).Build();
+
+            channel = new Channel(host + ":" + port, TestCredentials.CreateTestClientCredentials(true), channelArgs);
             client = TestServiceGrpc.NewStub(channel);
         }
 
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
index a25d3b3..24d72da 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
@@ -34,6 +34,7 @@
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.IO;
 using System.Text.RegularExpressions;
 using System.Threading.Tasks;
 using Google.ProtocolBuffers;
@@ -49,7 +50,7 @@
         private class ServerOptions
         {
             public bool help;
-            public int? port;
+            public int? port = 8070;
             public bool useTls;
         }
 
@@ -93,7 +94,14 @@
             server.AddServiceDefinition(TestServiceGrpc.BindService(new TestServiceImpl()));
 
             string addr = "0.0.0.0:" + options.port;
-            server.AddPort(addr);
+            if (options.useTls)
+            {
+                server.AddPort(addr, TestCredentials.CreateTestServerCredentials());
+            }
+            else
+            {
+                server.AddPort(addr);
+            }
             Console.WriteLine("Running server on " + addr);
             server.Start();
 
diff --git a/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs b/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs
new file mode 100644
index 0000000..b31abf1
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs
@@ -0,0 +1,83 @@
+#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.Diagnostics;
+using System.IO;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using Google.ProtocolBuffers;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+using grpc.testing;
+
+namespace Grpc.IntegrationTesting
+{
+    /// <summary>
+    /// SSL Credentials for testing.
+    /// </summary>
+    public static class TestCredentials
+    {
+        public const string DefaultHostOverride = "foo.test.google.fr";
+
+        public const string ClientCertAuthorityPath = "data/ca.pem";
+        public const string ClientCertAuthorityEnvName = "SSL_CERT_FILE";
+
+        public const string ServerCertChainPath = "data/server1.pem";
+        public const string ServerPrivateKeyPath = "data/server1.key";
+
+        public static SslCredentials CreateTestClientCredentials(bool useTestCa)
+        {
+            string caPath = ClientCertAuthorityPath;
+            if (!useTestCa)
+            {
+                caPath = Environment.GetEnvironmentVariable(ClientCertAuthorityEnvName);
+                if (string.IsNullOrEmpty(caPath))
+                {
+                    throw new ArgumentException("CA path environment variable is not set.");
+                }
+            }
+            return new SslCredentials(File.ReadAllText(caPath));
+        }
+
+        public static SslServerCredentials CreateTestServerCredentials()
+        {
+            var keyCertPair = new KeyCertificatePair(
+                File.ReadAllText(ServerCertChainPath),
+                File.ReadAllText(ServerPrivateKeyPath));
+            return new SslServerCredentials(new List<KeyCertificatePair> {keyCertPair});
+        }
+    }
+}
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index e244387..51abb63 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -653,6 +653,41 @@
   return grpc_secure_channel_create(creds, target, args);
 }
 
+GPR_EXPORT grpc_server_credentials *GPR_CALLTYPE
+grpcsharp_ssl_server_credentials_create(
+    const char *pem_root_certs, const char **key_cert_pair_cert_chain_array,
+    const char **key_cert_pair_private_key_array, size_t num_key_cert_pairs) {
+  size_t i;
+  grpc_server_credentials *creds;
+  grpc_ssl_pem_key_cert_pair *key_cert_pairs =
+      gpr_malloc(sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs);
+  memset(key_cert_pairs, 0,
+         sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs);
+
+  for (i = 0; i < num_key_cert_pairs; i++) {
+    if (key_cert_pair_cert_chain_array[i] ||
+        key_cert_pair_private_key_array[i]) {
+      key_cert_pairs[i].cert_chain = key_cert_pair_cert_chain_array[i];
+      key_cert_pairs[i].private_key = key_cert_pair_private_key_array[i];
+    }
+  }
+  creds = grpc_ssl_server_credentials_create(pem_root_certs, key_cert_pairs,
+                                             num_key_cert_pairs);
+  gpr_free(key_cert_pairs);
+  return creds;
+}
+
+GPR_EXPORT void grpcsharp_server_credentials_release(
+    grpc_server_credentials *creds) {
+  grpc_server_credentials_release(creds);
+}
+
+GPR_EXPORT gpr_int32 GPR_CALLTYPE
+grpcsharp_server_add_secure_http2_port(grpc_server *server, const char *addr,
+                                       grpc_server_credentials *creds) {
+  return grpc_server_add_secure_http2_port(server, addr, creds);
+}
+
 /* Logging */
 
 typedef void(GPR_CALLTYPE *grpcsharp_log_func)(const char *file, gpr_int32 line,
diff --git a/tools/dockerfile/grpc_csharp_mono/Dockerfile b/tools/dockerfile/grpc_csharp_mono/Dockerfile
index 8f86366..703b658 100644
--- a/tools/dockerfile/grpc_csharp_mono/Dockerfile
+++ b/tools/dockerfile/grpc_csharp_mono/Dockerfile
@@ -51,5 +51,5 @@
 # Add a service_account directory containing the auth creds file
 ADD service_account service_account
 
-# TODO: add command to run the interop server
-CMD ["/bin/bash", "-l"]
+# Run the C# Interop Server
+CMD ["/bin/bash", "-l", "-c", "cd /var/local/git/grpc/src/csharp/Grpc.IntegrationTesting.Server/bin/Debug && mono Grpc.IntegrationTesting.Server.exe --use_tls=true --port=8070"]