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