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 
20 #ifndef _THRIFT_TRANSPORT_TSERVERSOCKET_H_
21 #define _THRIFT_TRANSPORT_TSERVERSOCKET_H_ 1
22 
23 #include <thrift/concurrency/Mutex.h>
24 #include <thrift/transport/PlatformSocket.h>
25 #include <thrift/transport/TServerTransport.h>
26 
27 #include <sys/types.h>
28 #ifdef HAVE_SYS_SOCKET_H
29 #include <sys/socket.h>
30 #endif
31 #ifdef HAVE_NETDB_H
32 #include <netdb.h>
33 #endif
34 
35 namespace apache {
36 namespace thrift {
37 namespace transport {
38 
39 class TSocket;
40 
41 class TGetAddrInfoWrapper {
42 public:
43   TGetAddrInfoWrapper(const char* node, const char* service, const struct addrinfo* hints);
44 
45   virtual ~TGetAddrInfoWrapper();
46 
47   int init();
48   const struct addrinfo* res();
49 
50 private:
51   const char* node_;
52   const char* service_;
53   const struct addrinfo* hints_;
54   struct addrinfo* res_;
55 };
56 
57 /**
58  * Server socket implementation of TServerTransport. Wrapper around a unix
59  * socket listen and accept calls.
60  *
61  */
62 class TServerSocket : public TServerTransport {
63 public:
64   typedef std::function<void(THRIFT_SOCKET fd)> socket_func_t;
65 
66   const static int DEFAULT_BACKLOG = 1024;
67 
68   /**
69    * Constructor.
70    *
71    * @param port    Port number to bind to
72    */
73   TServerSocket(int port);
74 
75   /**
76    * Constructor.
77    *
78    * @param port        Port number to bind to
79    * @param sendTimeout Socket send timeout
80    * @param recvTimeout Socket receive timeout
81    */
82   TServerSocket(int port, int sendTimeout, int recvTimeout);
83 
84   /**
85    * Constructor.
86    *
87    * @param address Address to bind to
88    * @param port    Port number to bind to
89    */
90   TServerSocket(const std::string& address, int port);
91 
92   /**
93    * Constructor used for unix sockets.
94    *
95    * @param path Pathname for unix socket.
96    */
97   TServerSocket(const std::string& path);
98 
99   ~TServerSocket() override;
100 
101   void setSendTimeout(int sendTimeout);
102   void setRecvTimeout(int recvTimeout);
103 
104   void setAcceptTimeout(int accTimeout);
105   void setAcceptBacklog(int accBacklog);
106 
107   void setRetryLimit(int retryLimit);
108   void setRetryDelay(int retryDelay);
109 
setKeepAlive(bool keepAlive)110   void setKeepAlive(bool keepAlive) { keepAlive_ = keepAlive; }
111 
112   void setTcpSendBuffer(int tcpSendBuffer);
113   void setTcpRecvBuffer(int tcpRecvBuffer);
114 
115   // listenCallback gets called just before listen, and after all Thrift
116   // setsockopt calls have been made.  If you have custom setsockopt
117   // things that need to happen on the listening socket, this is the place to do it.
setListenCallback(const socket_func_t & listenCallback)118   void setListenCallback(const socket_func_t& listenCallback) { listenCallback_ = listenCallback; }
119 
120   // acceptCallback gets called after each accept call, on the newly created socket.
121   // It is called after all Thrift setsockopt calls have been made.  If you have
122   // custom setsockopt things that need to happen on the accepted
123   // socket, this is the place to do it.
setAcceptCallback(const socket_func_t & acceptCallback)124   void setAcceptCallback(const socket_func_t& acceptCallback) { acceptCallback_ = acceptCallback; }
125 
126   // When enabled (the default), new children TSockets will be constructed so
127   // they can be interrupted by TServerTransport::interruptChildren().
128   // This is more expensive in terms of system calls (poll + recv) however
129   // ensures a connected client cannot interfere with TServer::stop().
130   //
131   // When disabled, TSocket children do not incur an additional poll() call.
132   // Server-side reads are more efficient, however a client can interfere with
133   // the server's ability to shutdown properly by staying connected.
134   //
135   // Must be called before listen(); mode cannot be switched after that.
136   // \throws std::logic_error if listen() has been called
137   void setInterruptableChildren(bool enable);
138 
getSocketFD()139   THRIFT_SOCKET getSocketFD() override { return serverSocket_; }
140 
141   int getPort();
142 
143   void listen() override;
144   void interrupt() override;
145   void interruptChildren() override;
146   void close() override;
147 
148 protected:
149   std::shared_ptr<TTransport> acceptImpl() override;
150   virtual std::shared_ptr<TSocket> createSocket(THRIFT_SOCKET client);
151   bool interruptableChildren_;
152   std::shared_ptr<THRIFT_SOCKET> pChildInterruptSockReader_; // if interruptableChildren_ this is shared with child TSockets
153 
154 private:
155   void notify(THRIFT_SOCKET notifySock);
156 
157   int port_;
158   std::string address_;
159   std::string path_;
160   THRIFT_SOCKET serverSocket_;
161   int acceptBacklog_;
162   int sendTimeout_;
163   int recvTimeout_;
164   int accTimeout_;
165   int retryLimit_;
166   int retryDelay_;
167   int tcpSendBuffer_;
168   int tcpRecvBuffer_;
169   bool keepAlive_;
170   bool listening_;
171 
172   concurrency::Mutex rwMutex_;                                 // thread-safe interrupt
173   THRIFT_SOCKET interruptSockWriter_;                          // is notified on interrupt()
174   THRIFT_SOCKET interruptSockReader_;                          // is used in select/poll with serverSocket_ for interruptability
175   THRIFT_SOCKET childInterruptSockWriter_;                     // is notified on interruptChildren()
176 
177   socket_func_t listenCallback_;
178   socket_func_t acceptCallback_;
179 };
180 }
181 }
182 } // apache::thrift::transport
183 
184 #endif // #ifndef _THRIFT_TRANSPORT_TSERVERSOCKET_H_
185