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_TSOCKET_H_ 21 #define _THRIFT_TRANSPORT_TSOCKET_H_ 1 22 23 #include <string> 24 25 #include <thrift/transport/TTransport.h> 26 #include <thrift/transport/TVirtualTransport.h> 27 #include <thrift/transport/TServerSocket.h> 28 #include <thrift/transport/PlatformSocket.h> 29 30 #ifdef HAVE_ARPA_INET_H 31 #include <arpa/inet.h> 32 #endif 33 #ifdef HAVE_SYS_TIME_H 34 #include <sys/time.h> 35 #endif 36 #ifdef HAVE_NETDB_H 37 #include <netdb.h> 38 #endif 39 40 namespace apache { 41 namespace thrift { 42 namespace transport { 43 44 /** 45 * TCP Socket implementation of the TTransport interface. 46 * 47 */ 48 class TSocket : public TVirtualTransport<TSocket> { 49 public: 50 /** 51 * Constructs a new socket. Note that this does NOT actually connect the 52 * socket. 53 * 54 */ 55 TSocket(std::shared_ptr<TConfiguration> config = nullptr); 56 57 /** 58 * Constructs a new socket. Note that this does NOT actually connect the 59 * socket. 60 * 61 * @param host An IP address or hostname to connect to 62 * @param port The port to connect on 63 */ 64 TSocket(const std::string& host, int port, std::shared_ptr<TConfiguration> config = nullptr); 65 66 /** 67 * Constructs a new Unix domain socket. 68 * Note that this does NOT actually connect the socket. 69 * 70 * @param path The Unix domain socket e.g. "/tmp/ThriftTest.binary.thrift" 71 * or a zero-prefixed string to create an abstract domain socket on Linux. 72 */ 73 TSocket(const std::string& path, std::shared_ptr<TConfiguration> config = nullptr); 74 75 /** 76 * Destroyes the socket object, closing it if necessary. 77 */ 78 ~TSocket() override; 79 80 /** 81 * Whether the socket is alive. 82 * 83 * @return Is the socket alive? 84 */ 85 bool isOpen() const override; 86 87 /** 88 * Checks whether there is more data available in the socket to read. 89 * 90 * This call blocks until at least one byte is available or the socket is closed. 91 */ 92 bool peek() override; 93 94 /** 95 * Creates and opens the UNIX socket. 96 * 97 * @throws TTransportException If the socket could not connect 98 */ 99 void open() override; 100 101 /** 102 * Shuts down communications on the socket. 103 */ 104 void close() override; 105 106 /** 107 * Determines whether there is pending data to read or not. 108 * 109 * This call does not block. 110 * \throws TTransportException of types: 111 * NOT_OPEN means the socket has been closed 112 * UNKNOWN means something unexpected happened 113 * \returns true if there is pending data to read, false otherwise 114 */ 115 virtual bool hasPendingDataToRead(); 116 117 /** 118 * Reads from the underlying socket. 119 * \returns the number of bytes read or 0 indicates EOF 120 * \throws TTransportException of types: 121 * INTERRUPTED means the socket was interrupted 122 * out of a blocking call 123 * NOT_OPEN means the socket has been closed 124 * TIMED_OUT means the receive timeout expired 125 * UNKNOWN means something unexpected happened 126 */ 127 virtual uint32_t read(uint8_t* buf, uint32_t len); 128 129 /** 130 * Writes to the underlying socket. Loops until done or fail. 131 */ 132 virtual void write(const uint8_t* buf, uint32_t len); 133 134 /** 135 * Writes to the underlying socket. Does single send() and returns result. 136 */ 137 virtual uint32_t write_partial(const uint8_t* buf, uint32_t len); 138 139 /** 140 * Get the host that the socket is connected to 141 * 142 * @return string host identifier 143 */ 144 std::string getHost() const; 145 146 /** 147 * Get the port that the socket is connected to 148 * 149 * @return int port number 150 */ 151 int getPort() const; 152 153 /** 154 * Get the Unix domain socket path that the socket is connected to 155 * 156 * @return std::string path 157 */ 158 std::string getPath() const; 159 160 /** 161 * Whether the socket is a Unix domain socket. This is the same as checking 162 * if getPath() is not empty. 163 * 164 * @return Is the socket a Unix domain socket? 165 */ 166 bool isUnixDomainSocket() const; 167 168 /** 169 * Set the host that socket will connect to 170 * 171 * @param host host identifier 172 */ 173 void setHost(std::string host); 174 175 /** 176 * Set the port that socket will connect to 177 * 178 * @param port port number 179 */ 180 void setPort(int port); 181 182 /** 183 * Set the Unix domain socket path for the socket 184 * 185 * @param path std::string path 186 */ 187 void setPath(std::string path); 188 189 /** 190 * Controls whether the linger option is set on the socket. 191 * 192 * @param on Whether SO_LINGER is on 193 * @param linger If linger is active, the number of seconds to linger for 194 */ 195 void setLinger(bool on, int linger); 196 197 /** 198 * Whether to enable/disable Nagle's algorithm. 199 * 200 * @param noDelay Whether or not to disable the algorithm. 201 * @return 202 */ 203 void setNoDelay(bool noDelay); 204 205 /** 206 * Set the connect timeout 207 */ 208 void setConnTimeout(int ms); 209 210 /** 211 * Set the receive timeout 212 */ 213 void setRecvTimeout(int ms); 214 215 /** 216 * Set the send timeout 217 */ 218 void setSendTimeout(int ms); 219 220 /** 221 * Set the max number of recv retries in case of an THRIFT_EAGAIN 222 * error 223 */ 224 void setMaxRecvRetries(int maxRecvRetries); 225 226 /** 227 * Set SO_KEEPALIVE 228 */ 229 void setKeepAlive(bool keepAlive); 230 231 /** 232 * Get socket information formatted as a string <Host: x Port: x> 233 */ 234 std::string getSocketInfo() const; 235 236 /** 237 * Returns the DNS name of the host to which the socket is connected 238 */ 239 std::string getPeerHost() const; 240 241 /** 242 * Returns the address of the host to which the socket is connected 243 */ 244 std::string getPeerAddress() const; 245 246 /** 247 * Returns the port of the host to which the socket is connected 248 **/ 249 int getPeerPort() const; 250 251 /** 252 * Returns the underlying socket file descriptor. 253 */ getSocketFD()254 THRIFT_SOCKET getSocketFD() { return socket_; } 255 256 /** 257 * (Re-)initialize a TSocket for the supplied descriptor. This is only 258 * intended for use by TNonblockingServer -- other use may result in 259 * unfortunate surprises. 260 * 261 * @param fd the descriptor for an already-connected socket 262 */ 263 void setSocketFD(THRIFT_SOCKET fd); 264 265 /* 266 * Returns a cached copy of the peer address. 267 */ 268 sockaddr* getCachedAddress(socklen_t* len) const; 269 270 /** 271 * Sets whether to use a low minimum TCP retransmission timeout. 272 */ 273 static void setUseLowMinRto(bool useLowMinRto); 274 275 /** 276 * Gets whether to use a low minimum TCP retransmission timeout. 277 */ 278 static bool getUseLowMinRto(); 279 280 /** 281 * Get the origin the socket is connected to 282 * 283 * @return string peer host identifier and port 284 */ 285 const std::string getOrigin() const override; 286 287 /** 288 * Constructor to create socket from file descriptor. 289 */ 290 TSocket(THRIFT_SOCKET socket, std::shared_ptr<TConfiguration> config = nullptr); 291 292 /** 293 * Constructor to create socket from file descriptor that 294 * can be interrupted safely. 295 */ 296 TSocket(THRIFT_SOCKET socket, std::shared_ptr<THRIFT_SOCKET> interruptListener, 297 std::shared_ptr<TConfiguration> config = nullptr); 298 299 /** 300 * Set a cache of the peer address (used when trivially available: e.g. 301 * accept() or connect()). Only caches IPV4 and IPV6; unset for others. 302 */ 303 void setCachedAddress(const sockaddr* addr, socklen_t len); 304 305 protected: 306 /** connect, called by open */ 307 void openConnection(struct addrinfo* res); 308 309 /** Host to connect to */ 310 std::string host_; 311 312 /** Port number to connect on */ 313 int port_; 314 315 /** UNIX domain socket path */ 316 std::string path_; 317 318 /** Underlying socket handle */ 319 THRIFT_SOCKET socket_; 320 321 /** Peer hostname */ 322 mutable std::string peerHost_; 323 324 /** Peer address */ 325 mutable std::string peerAddress_; 326 327 /** Peer port */ 328 mutable int peerPort_; 329 330 /** 331 * A shared socket pointer that will interrupt a blocking read if data 332 * becomes available on it 333 */ 334 std::shared_ptr<THRIFT_SOCKET> interruptListener_; 335 336 /** Connect timeout in ms */ 337 int connTimeout_; 338 339 /** Send timeout in ms */ 340 int sendTimeout_; 341 342 /** Recv timeout in ms */ 343 int recvTimeout_; 344 345 /** Keep alive on */ 346 bool keepAlive_; 347 348 /** Linger on */ 349 bool lingerOn_; 350 351 /** Linger val */ 352 int lingerVal_; 353 354 /** Nodelay */ 355 bool noDelay_; 356 357 /** Recv EGAIN retries */ 358 int maxRecvRetries_; 359 360 /** Cached peer address */ 361 union { 362 sockaddr_in ipv4; 363 sockaddr_in6 ipv6; 364 } cachedPeerAddr_; 365 366 /** Whether to use low minimum TCP retransmission timeout */ 367 static bool useLowMinRto_; 368 369 private: 370 void unix_open(); 371 void local_open(); 372 }; 373 } 374 } 375 } // apache::thrift::transport 376 377 #endif // #ifndef _THRIFT_TRANSPORT_TSOCKET_H_ 378