blob: 171d0c799d1e576487f1dad666d9315d6727f827 [file] [log] [blame]
Jan Tattermuscha29d0f32015-03-04 17:54:56 -08001#region Copyright notice and license
2
3// Copyright 2015, Google Inc.
4// All rights reserved.
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met:
9//
10// * Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer.
12// * Redistributions in binary form must reproduce the above
13// copyright notice, this list of conditions and the following disclaimer
14// in the documentation and/or other materials provided with the
15// distribution.
16// * Neither the name of Google Inc. nor the names of its
17// contributors may be used to endorse or promote products derived from
18// this software without specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32#endregion
33
34using System;
35using System.Diagnostics;
36using System.Runtime.CompilerServices;
37using System.Runtime.InteropServices;
38using System.Threading;
39using System.Threading.Tasks;
40using Grpc.Core.Internal;
41using Grpc.Core.Utils;
42
43namespace Grpc.Core.Internal
44{
45 /// <summary>
Jan Tattermuscha5272b62015-04-30 11:56:46 -070046 /// Manages server side native call lifecycle.
Jan Tattermuscha29d0f32015-03-04 17:54:56 -080047 /// </summary>
48 internal class AsyncCallServer<TRequest, TResponse> : AsyncCallBase<TResponse, TRequest>
49 {
50 readonly CompletionCallbackDelegate finishedServersideHandler;
51 readonly TaskCompletionSource<object> finishedServersideTcs = new TaskCompletionSource<object>();
52
53 public AsyncCallServer(Func<TResponse, byte[]> serializer, Func<byte[], TRequest> deserializer) : base(serializer, deserializer)
54 {
55 this.finishedServersideHandler = CreateBatchCompletionCallback(HandleFinishedServerside);
56 }
57
58 public void Initialize(CallSafeHandle call)
59 {
Jan Tattermusch1b54fcf2015-05-01 14:30:16 -070060 DebugStats.ActiveServerCalls.Increment();
Jan Tattermuscha29d0f32015-03-04 17:54:56 -080061 InitializeInternal(call);
62 }
63
64 /// <summary>
Jan Tattermuscha5272b62015-04-30 11:56:46 -070065 /// Starts a server side call.
Jan Tattermuscha29d0f32015-03-04 17:54:56 -080066 /// </summary>
Jan Tattermuscha5272b62015-04-30 11:56:46 -070067 public Task ServerSideCallAsync()
Jan Tattermuscha29d0f32015-03-04 17:54:56 -080068 {
69 lock (myLock)
70 {
71 Preconditions.CheckNotNull(call);
72
73 started = true;
Jan Tattermuscha29d0f32015-03-04 17:54:56 -080074
75 call.StartServerSide(finishedServersideHandler);
Jan Tattermuscha29d0f32015-03-04 17:54:56 -080076 return finishedServersideTcs.Task;
77 }
78 }
79
80 /// <summary>
81 /// Sends a streaming response. Only one pending send action is allowed at any given time.
82 /// completionDelegate is called when the operation finishes.
83 /// </summary>
Jan Tattermuscha5272b62015-04-30 11:56:46 -070084 public void StartSendMessage(TResponse msg, AsyncCompletionDelegate<object> completionDelegate)
Jan Tattermuscha29d0f32015-03-04 17:54:56 -080085 {
86 StartSendMessageInternal(msg, completionDelegate);
87 }
88
89 /// <summary>
Jan Tattermuscha5272b62015-04-30 11:56:46 -070090 /// Receives a streaming request. Only one pending read action is allowed at any given time.
91 /// completionDelegate is called when the operation finishes.
92 /// </summary>
93 public void StartReadMessage(AsyncCompletionDelegate<TRequest> completionDelegate)
94 {
95 StartReadMessageInternal(completionDelegate);
96 }
97
98 /// <summary>
Jan Tattermuscha29d0f32015-03-04 17:54:56 -080099 /// Sends call result status, also indicating server is done with streaming responses.
100 /// Only one pending send action is allowed at any given time.
101 /// completionDelegate is called when the operation finishes.
102 /// </summary>
Jan Tattermuscha5272b62015-04-30 11:56:46 -0700103 public void StartSendStatusFromServer(Status status, AsyncCompletionDelegate<object> completionDelegate)
Jan Tattermuscha29d0f32015-03-04 17:54:56 -0800104 {
105 lock (myLock)
106 {
107 Preconditions.CheckNotNull(completionDelegate, "Completion delegate cannot be null");
108 CheckSendingAllowed();
109
110 call.StartSendStatusFromServer(status, halfclosedHandler);
111 halfcloseRequested = true;
112 sendCompletionDelegate = completionDelegate;
113 }
114 }
115
Jan Tattermusch1b54fcf2015-05-01 14:30:16 -0700116 protected override void OnReleaseResources()
117 {
118 DebugStats.ActiveServerCalls.Decrement();
119 }
120
Jan Tattermuscha29d0f32015-03-04 17:54:56 -0800121 /// <summary>
122 /// Handles the server side close completion.
123 /// </summary>
124 private void HandleFinishedServerside(bool wasError, BatchContextSafeHandleNotOwned ctx)
125 {
Jan Tattermusch8c2dd9d2015-05-04 09:20:43 -0700126 bool cancelled = ctx.GetReceivedCloseOnServerCancelled();
127
Jan Tattermuscha29d0f32015-03-04 17:54:56 -0800128 lock (myLock)
129 {
130 finished = true;
131
Jan Tattermusch8c2dd9d2015-05-04 09:20:43 -0700132 if (cancelled)
Jan Tattermusche5c44602015-05-01 11:12:34 -0700133 {
Jan Tattermusch8c2dd9d2015-05-04 09:20:43 -0700134 // Once we cancel, we don't have to care that much
135 // about reads and writes.
136 Cancel();
Jan Tattermusche5c44602015-05-01 11:12:34 -0700137 }
138
Jan Tattermuscha29d0f32015-03-04 17:54:56 -0800139 ReleaseResourcesIfPossible();
140 }
Jan Tattermusch9b9a8772015-05-06 14:43:51 -0700141 // TODO(jtattermusch): handle error
Jan Tattermuscha29d0f32015-03-04 17:54:56 -0800142
143 finishedServersideTcs.SetResult(null);
144 }
145 }
146}