context propagation API
diff --git a/src/csharp/Grpc.Core/CallOptions.cs b/src/csharp/Grpc.Core/CallOptions.cs
index a08986d..0d82b5a 100644
--- a/src/csharp/Grpc.Core/CallOptions.cs
+++ b/src/csharp/Grpc.Core/CallOptions.cs
@@ -48,6 +48,7 @@
         readonly DateTime deadline;
         readonly CancellationToken cancellationToken;
         readonly WriteOptions writeOptions;
+        readonly ContextPropagationToken propagationToken;
 
         /// <summary>
         /// Creates a new instance of <c>CallOptions</c>.
@@ -56,14 +57,16 @@
         /// <param name="deadline">Deadline for the call to finish. null means no deadline.</param>
         /// <param name="cancellationToken">Can be used to request cancellation of the call.</param>
         /// <param name="writeOptions">Write options that will be used for this call.</param>
-        public CallOptions(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken), WriteOptions writeOptions = null)
+        /// <param name="propagationToken">Context propagation token obtained from <see cref="ServerCallContext"/>.</param>
+        public CallOptions(Metadata headers = null, DateTime? deadline = null, CancellationToken? cancellationToken = null,
+                           WriteOptions writeOptions = null, ContextPropagationToken propagationToken = null)
         {
             // TODO(jtattermusch): consider only creating metadata object once it's really needed.
-            this.headers = headers != null ? headers : new Metadata();
-            // TODO(jtattermusch): allow null value of deadline?
-            this.deadline = deadline.HasValue ? deadline.Value : DateTime.MaxValue;
-            this.cancellationToken = cancellationToken;
+            this.headers = headers ?? new Metadata();
+            this.deadline = deadline ?? (propagationToken != null ? propagationToken.Deadline : DateTime.MaxValue);
+            this.cancellationToken = cancellationToken ?? (propagationToken != null ? propagationToken.CancellationToken : CancellationToken.None);
             this.writeOptions = writeOptions;
+            this.propagationToken = propagationToken;
         }
 
         /// <summary>
@@ -100,5 +103,16 @@
                 return this.writeOptions;
             }
         }
+
+        /// <summary>
+        /// Token for propagating parent call context.
+        /// </summary>
+        public ContextPropagationToken PropagationToken
+        {
+            get
+            {
+                return this.propagationToken;
+            }
+        }
     }
 }
diff --git a/src/csharp/Grpc.Core/ContextPropagationToken.cs b/src/csharp/Grpc.Core/ContextPropagationToken.cs
new file mode 100644
index 0000000..e765947
--- /dev/null
+++ b/src/csharp/Grpc.Core/ContextPropagationToken.cs
@@ -0,0 +1,139 @@
+#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.Threading;
+
+using Grpc.Core.Internal;
+using Grpc.Core.Utils;
+
+namespace Grpc.Core
+{
+    /// <summary>
+    /// Token for propagating context of server side handlers to child calls.
+    /// In situations when a backend is making calls to another backend,
+    /// it makes sense to propagate properties like deadline and cancellation 
+    /// token of the server call to the child call.
+    /// C core provides some other contexts (like tracing context) that
+    /// are not accessible to C# layer, but this token still allows propagating them.
+    /// </summary>
+    public class ContextPropagationToken
+    {
+        /// <summary>
+        /// Default propagation mask used by C core.
+        /// </summary>
+        const ContextPropagationFlags DefaultCoreMask = (ContextPropagationFlags) 0xffff;
+
+        /// <summary>
+        /// Default propagation mask used by C# - we want to propagate deadline 
+        /// and cancellation token by our own means.
+        /// </summary>
+        internal const ContextPropagationFlags DefaultMask = DefaultCoreMask
+            & ~ContextPropagationFlags.Deadline & ~ContextPropagationFlags.Cancellation;
+
+        readonly CallSafeHandle parentCall;
+        readonly DateTime deadline;
+        readonly CancellationToken cancellationToken;
+        readonly ContextPropagationOptions options;
+
+        internal ContextPropagationToken(CallSafeHandle parentCall, DateTime deadline, CancellationToken cancellationToken, ContextPropagationOptions options)
+        {
+            this.parentCall = Preconditions.CheckNotNull(parentCall);
+            this.deadline = deadline;
+            this.cancellationToken = cancellationToken;
+            this.options = options ?? ContextPropagationOptions.Default;
+        }
+
+        internal CallSafeHandle ParentCall
+        {
+            get
+            {
+                return this.parentCall;
+            }
+        }
+
+        internal DateTime Deadline
+        {
+            get
+            {
+                return this.deadline;
+            }
+        }
+
+        internal CancellationToken CancellationToken
+        {
+            get
+            {
+                return this.cancellationToken;
+            }
+        }
+
+        internal ContextPropagationOptions Options
+        {
+            get
+            {
+                return this.options;
+            }
+        }
+
+        internal bool IsPropagateDeadline
+        {
+            get { return false; }
+        }
+
+        internal bool IsPropagateCancellation
+        {
+            get { return false; }
+        }
+    }
+
+    /// <summary>
+    /// Options for <see cref="ContextPropagationToken"/>.
+    /// </summary>
+    public class ContextPropagationOptions
+    {
+        public static readonly ContextPropagationOptions Default = new ContextPropagationOptions();
+    }
+
+    /// <summary>
+    /// Context propagation flags from grpc/grpc.h.
+    /// </summary>
+    [Flags]
+    internal enum ContextPropagationFlags
+    {
+        Deadline = 1,
+        CensusStatsContext = 2,
+        CensusTracingContext = 4,
+        Cancellation = 8
+    }
+}
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index 0616ed9..e535c47 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -117,6 +117,7 @@
     <Compile Include="CallOptions.cs" />
     <Compile Include="CompressionLevel.cs" />
     <Compile Include="WriteOptions.cs" />
+    <Compile Include="ContextPropagationToken.cs" />
   </ItemGroup>
   <ItemGroup>
     <None Include="Grpc.Core.nuspec" />
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
index dee31c6..0db9d2a 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
@@ -324,7 +324,11 @@
 
         private void Initialize(CompletionQueueSafeHandle cq)
         {
-            var call = details.Channel.Handle.CreateCall(details.Channel.Environment.CompletionRegistry, cq,
+            var propagationToken = details.Options.PropagationToken;
+            var parentCall = propagationToken != null ? propagationToken.ParentCall : CallSafeHandle.NullInstance;
+
+            var call = details.Channel.Handle.CreateCall(details.Channel.Environment.CompletionRegistry,
+                parentCall, ContextPropagationToken.DefaultMask, cq,
                 details.Method, details.Host, Timespec.FromDateTime(details.Options.Deadline));
             details.Channel.Environment.DebugStats.ActiveClientCalls.Increment();
             InitializeInternal(call);
diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
index 1b9d0ab..3cb01e2 100644
--- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
@@ -42,6 +42,8 @@
     /// </summary>
     internal class CallSafeHandle : SafeHandleZeroIsInvalid
     {
+        public static readonly CallSafeHandle NullInstance = new CallSafeHandle();
+
         const uint GRPC_WRITE_BUFFER_HINT = 1;
         CompletionRegistry completionRegistry;
 
diff --git a/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs
index 7324ebd..7f03bf4 100644
--- a/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ChannelSafeHandle.cs
@@ -47,7 +47,7 @@
         static extern ChannelSafeHandle grpcsharp_secure_channel_create(CredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs);
 
         [DllImport("grpc_csharp_ext.dll")]
-        static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline);
+        static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline);
 
         [DllImport("grpc_csharp_ext.dll")]
         static extern ChannelState grpcsharp_channel_check_connectivity_state(ChannelSafeHandle channel, int tryToConnect);
@@ -76,9 +76,9 @@
             return grpcsharp_secure_channel_create(credentials, target, channelArgs);
         }
 
-        public CallSafeHandle CreateCall(CompletionRegistry registry, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline)
+        public CallSafeHandle CreateCall(CompletionRegistry registry, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline)
         {
-            var result = grpcsharp_channel_create_call(this, cq, method, host, deadline);
+            var result = grpcsharp_channel_create_call(this, parentCall, propagationMask, cq, method, host, deadline);
             result.SetCompletionRegistry(registry);
             return result;
         }
diff --git a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
index 74af19d..688f9f6 100644
--- a/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
@@ -310,8 +310,7 @@
         {
             DateTime realtimeDeadline = newRpc.Deadline.ToClockType(GPRClockType.Realtime).ToDateTime();
 
-            return new ServerCallContext(
-                newRpc.Method, newRpc.Host, peer, realtimeDeadline,
+            return new ServerCallContext(newRpc.Call, newRpc.Method, newRpc.Host, peer, realtimeDeadline,
                 newRpc.RequestMetadata, cancellationToken, serverResponseStream.WriteResponseHeadersAsync, serverResponseStream);
         }
     }
diff --git a/src/csharp/Grpc.Core/ServerCallContext.cs b/src/csharp/Grpc.Core/ServerCallContext.cs
index 7849df9..75d81c6 100644
--- a/src/csharp/Grpc.Core/ServerCallContext.cs
+++ b/src/csharp/Grpc.Core/ServerCallContext.cs
@@ -45,6 +45,7 @@
     /// </summary>
     public class ServerCallContext
     {
+        private readonly CallSafeHandle callHandle;
         private readonly string method;
         private readonly string host;
         private readonly string peer;
@@ -57,9 +58,10 @@
         private Func<Metadata, Task> writeHeadersFunc;
         private IHasWriteOptions writeOptionsHolder;
 
-        public ServerCallContext(string method, string host, string peer, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken,
+        internal ServerCallContext(CallSafeHandle callHandle, string method, string host, string peer, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken,
             Func<Metadata, Task> writeHeadersFunc, IHasWriteOptions writeOptionsHolder)
         {
+            this.callHandle = callHandle;
             this.method = method;
             this.host = host;
             this.peer = peer;
@@ -74,6 +76,14 @@
         {
             return writeHeadersFunc(responseHeaders);
         }
+
+        /// <summary>
+        /// Creates a propagation token to be used to propagate call context to a child call.
+        /// </summary>
+        public ContextPropagationToken CreatePropagationToken(ContextPropagationOptions options = null)
+        {
+            return new ContextPropagationToken(callHandle, deadline, cancellationToken, options);
+        }
             
         /// <summary>Name of method called in this RPC.</summary>
         public string Method
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index 5d17360..133b2d8 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -376,10 +376,12 @@
 }
 
 GPR_EXPORT grpc_call *GPR_CALLTYPE
-grpcsharp_channel_create_call(grpc_channel *channel, grpc_completion_queue *cq,
+grpcsharp_channel_create_call(grpc_channel *channel, grpc_call *parent_call,
+                              gpr_uint32 propagation_mask,
+                              grpc_completion_queue *cq,
                               const char *method, const char *host,
                               gpr_timespec deadline) {
-  return grpc_channel_create_call(channel, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
+  return grpc_channel_create_call(channel, parent_call, propagation_mask, cq,
                                   method, host, deadline);
 }