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.transport.base;
20 
21 import thrift.base;
22 import thrift.transport.base;
23 import thrift.util.cancellation;
24 
25 /**
26  * Some kind of I/O device enabling servers to listen for incoming client
27  * connections and communicate with them via a TTransport interface.
28  */
29 interface TServerTransport {
30   /**
31    * Starts listening for server connections.
32    *
33    * Just as simliar functions commonly found in socket libraries, this
34    * function does not block.
35    *
36    * If the socket is already listening, nothing happens.
37    *
38    * Throws: TServerTransportException if listening failed or the transport
39    *   was already listening.
40    */
41   void listen();
42 
43   /**
44    * Closes the server transport, causing it to stop listening.
45    *
46    * Throws: TServerTransportException if the transport was not listening.
47    */
48   void close();
49 
50   /**
51    * Returns whether the server transport is currently listening.
52    */
53   bool isListening() @property;
54 
55   /**
56    * Accepts a client connection and returns an opened TTransport for it,
57    * never returning null.
58    *
59    * Blocks until a client connection is available.
60    *
61    * Params:
62    *   cancellation = If triggered, requests the call to stop blocking and
63    *     return with a TCancelledException. Implementations are free to
64    *     ignore this if they cannot provide a reasonable.
65    *
66    * Throws: TServerTransportException if accepting failed,
67    *   TCancelledException if it was cancelled.
68    */
69   TTransport accept(TCancellation cancellation = null) out (result) {
70     assert(result !is null);
71   }
72 }
73 
74 /**
75  * Server transport exception.
76  */
77 class TServerTransportException : TException {
78   /**
79    * Error codes for the various types of exceptions.
80    */
81   enum Type {
82     ///
83     UNKNOWN,
84 
85     /// The server socket is not listening, but excepted to be.
86     NOT_LISTENING,
87 
88     /// The server socket is already listening, but expected not to be.
89     ALREADY_LISTENING,
90 
91     /// An operation on the primary underlying resource, e.g. a socket used
92     /// for accepting connections, failed.
93     RESOURCE_FAILED
94   }
95 
96   ///
97   this(Type type, string file = __FILE__, size_t line = __LINE__, Throwable next = null) {
98     this(errorMsg(type), type, file, line, next);
99   }
100 
101   ///
102   this(string msg, string file = __FILE__, size_t line = __LINE__,
103     Throwable next = null)
104   {
105     this(msg, Type.UNKNOWN, file, line, next);
106   }
107 
108   ///
109   this(string msg, Type type, string file = __FILE__, size_t line = __LINE__,
110     Throwable next = null)
111   {
112     super(msg, file, line, next);
113     type_ = type;
114   }
115 
116   ///
117   Type type() const nothrow @property {
118     return type_;
119   }
120 
121 protected:
122   Type type_;
123 
124 private:
125   string errorMsg(Type type) {
126     string msg = "TTransportException: ";
127     switch (type) {
128       case Type.UNKNOWN: msg ~= "Unknown server transport exception"; break;
129       case Type.NOT_LISTENING: msg ~= "Server transport not listening"; break;
130       case Type.ALREADY_LISTENING: msg ~= "Server transport already listening"; break;
131       case Type.RESOURCE_FAILED: msg ~= "An underlying resource failed"; break;
132       default: msg ~= "(Invalid exception type)"; break;
133     }
134     return msg;
135   }
136 }
137