1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 module thrift.server.base;
20 
21 import std.variant : Variant;
22 import thrift.protocol.base;
23 import thrift.protocol.binary;
24 import thrift.protocol.processor;
25 import thrift.server.transport.base;
26 import thrift.transport.base;
27 import thrift.util.cancellation;
28 
29 /**
30  * Base class for all Thrift servers.
31  *
32  * By setting the eventHandler property to a TServerEventHandler
33  * implementation, custom code can be integrated into the processing pipeline,
34  * which can be used e.g. for gathering statistics.
35  */
36 class TServer {
37   /**
38    * Starts serving.
39    *
40    * Blocks until the server finishes, i.e. a serious problem occurred or the
41    * cancellation request has been triggered.
42    *
43    * Server implementations are expected to implement cancellation in a best-
44    * effort way – usually, it should be possible to immediately stop accepting
45    * connections and return after all currently active clients have been
46    * processed, but this might not be the case for every conceivable
47    * implementation.
48    */
49   abstract void serve(TCancellation cancellation = null);
50 
51   /// The server event handler to notify. Null by default.
52   TServerEventHandler eventHandler;
53 
54 protected:
55   this(
56     TProcessor processor,
57     TServerTransport serverTransport,
58     TTransportFactory transportFactory,
59     TProtocolFactory protocolFactory
60   ) {
61     this(processor, serverTransport, transportFactory, transportFactory,
62       protocolFactory, protocolFactory);
63   }
64 
65   this(
66     TProcessorFactory processorFactory,
67     TServerTransport serverTransport,
68     TTransportFactory transportFactory,
69     TProtocolFactory protocolFactory
70   ) {
71     this(processorFactory, serverTransport, transportFactory, transportFactory,
72       protocolFactory, protocolFactory);
73   }
74 
75   this(
76     TProcessor processor,
77     TServerTransport serverTransport,
78     TTransportFactory inputTransportFactory,
79     TTransportFactory outputTransportFactory,
80     TProtocolFactory inputProtocolFactory,
81     TProtocolFactory outputProtocolFactory
82   ) {
83     this(new TSingletonProcessorFactory(processor), serverTransport,
84       inputTransportFactory, outputTransportFactory,
85       inputProtocolFactory, outputProtocolFactory);
86   }
87 
88   this(
89     TProcessorFactory processorFactory,
90     TServerTransport serverTransport,
91     TTransportFactory inputTransportFactory,
92     TTransportFactory outputTransportFactory,
93     TProtocolFactory inputProtocolFactory,
94     TProtocolFactory outputProtocolFactory
95   ) {
96     import std.exception;
97     import thrift.base;
98     enforce(inputTransportFactory,
99       new TException("Input transport factory must not be null."));
100     enforce(outputTransportFactory,
101       new TException("Output transport factory must not be null."));
102     enforce(inputProtocolFactory,
103       new TException("Input protocol factory must not be null."));
104     enforce(outputProtocolFactory,
105       new TException("Output protocol factory must not be null."));
106 
107     processorFactory_ = processorFactory;
108     serverTransport_ = serverTransport;
109     inputTransportFactory_ = inputTransportFactory;
110     outputTransportFactory_ = outputTransportFactory;
111     inputProtocolFactory_ = inputProtocolFactory;
112     outputProtocolFactory_ = outputProtocolFactory;
113   }
114 
115   TProcessorFactory processorFactory_;
116   TServerTransport serverTransport_;
117   TTransportFactory inputTransportFactory_;
118   TTransportFactory outputTransportFactory_;
119   TProtocolFactory inputProtocolFactory_;
120   TProtocolFactory outputProtocolFactory_;
121 
122 public:
123 
124   @property TProcessorFactory processorFactory()
125   {
126     return processorFactory_;
127   }
128 
129   @property TServerTransport serverTransport()
130   {
131     return serverTransport_;
132   }
133 
134   @property TTransportFactory inputTransportFactory()
135   {
136     return inputTransportFactory_;
137   }
138 
139   @property TTransportFactory outputTransportFactory()
140   {
141     return outputTransportFactory_;
142   }
143 
144   @property TProtocolFactory inputProtocolFactory()
145   {
146     return inputProtocolFactory_;
147   }
148 
149   @property TProtocolFactory outputProtocolFactory()
150   {
151     return outputProtocolFactory_;
152   }
153 }
154 
155 /**
156  * Handles events from a TServer core.
157  */
158 interface TServerEventHandler {
159   /**
160    * Called before the server starts accepting connections.
161    */
162   void preServe();
163 
164   /**
165    * Called when a new client has connected and processing is about to begin.
166    */
167   Variant createContext(TProtocol input, TProtocol output);
168 
169   /**
170    * Called when request handling for a client has been finished – can be used
171    * to perform clean up work.
172    */
173   void deleteContext(Variant serverContext, TProtocol input, TProtocol output);
174 
175   /**
176    * Called when the processor for a client call is about to be invoked.
177    */
178   void preProcess(Variant serverContext, TTransport transport);
179 }