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();
145 
146   /**
147    * Get the port that the socket is connected to
148    *
149    * @return int port number
150    */
151   int getPort();
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();
159 
160   /**
161    * Set the host that socket will connect to
162    *
163    * @param host host identifier
164    */
165   void setHost(std::string host);
166 
167   /**
168    * Set the port that socket will connect to
169    *
170    * @param port port number
171    */
172   void setPort(int port);
173 
174   /**
175    * Set the Unix domain socket path for the socket
176    *
177    * @param path std::string path
178    */
179   void setPath(std::string path);
180 
181   /**
182    * Controls whether the linger option is set on the socket.
183    *
184    * @param on      Whether SO_LINGER is on
185    * @param linger  If linger is active, the number of seconds to linger for
186    */
187   void setLinger(bool on, int linger);
188 
189   /**
190    * Whether to enable/disable Nagle's algorithm.
191    *
192    * @param noDelay Whether or not to disable the algorithm.
193    * @return
194    */
195   void setNoDelay(bool noDelay);
196 
197   /**
198    * Set the connect timeout
199    */
200   void setConnTimeout(int ms);
201 
202   /**
203    * Set the receive timeout
204    */
205   void setRecvTimeout(int ms);
206 
207   /**
208    * Set the send timeout
209    */
210   void setSendTimeout(int ms);
211 
212   /**
213    * Set the max number of recv retries in case of an THRIFT_EAGAIN
214    * error
215    */
216   void setMaxRecvRetries(int maxRecvRetries);
217 
218   /**
219    * Set SO_KEEPALIVE
220    */
221   void setKeepAlive(bool keepAlive);
222 
223   /**
224    * Get socket information formatted as a string <Host: x Port: x>
225    */
226   std::string getSocketInfo() const;
227 
228   /**
229    * Returns the DNS name of the host to which the socket is connected
230    */
231   std::string getPeerHost() const;
232 
233   /**
234    * Returns the address of the host to which the socket is connected
235    */
236   std::string getPeerAddress() const;
237 
238   /**
239    * Returns the port of the host to which the socket is connected
240    **/
241   int getPeerPort() const;
242 
243   /**
244    * Returns the underlying socket file descriptor.
245    */
getSocketFD()246   THRIFT_SOCKET getSocketFD() { return socket_; }
247 
248   /**
249    * (Re-)initialize a TSocket for the supplied descriptor.  This is only
250    * intended for use by TNonblockingServer -- other use may result in
251    * unfortunate surprises.
252    *
253    * @param fd the descriptor for an already-connected socket
254    */
255   void setSocketFD(THRIFT_SOCKET fd);
256 
257   /*
258    * Returns a cached copy of the peer address.
259    */
260   sockaddr* getCachedAddress(socklen_t* len) const;
261 
262   /**
263    * Sets whether to use a low minimum TCP retransmission timeout.
264    */
265   static void setUseLowMinRto(bool useLowMinRto);
266 
267   /**
268    * Gets whether to use a low minimum TCP retransmission timeout.
269    */
270   static bool getUseLowMinRto();
271 
272   /**
273    * Get the origin the socket is connected to
274    *
275    * @return string peer host identifier and port
276    */
277   const std::string getOrigin() const override;
278 
279   /**
280    * Constructor to create socket from file descriptor.
281    */
282   TSocket(THRIFT_SOCKET socket, std::shared_ptr<TConfiguration> config = nullptr);
283 
284   /**
285    * Constructor to create socket from file descriptor that
286    * can be interrupted safely.
287    */
288   TSocket(THRIFT_SOCKET socket, std::shared_ptr<THRIFT_SOCKET> interruptListener,
289          std::shared_ptr<TConfiguration> config = nullptr);
290 
291   /**
292    * Set a cache of the peer address (used when trivially available: e.g.
293    * accept() or connect()). Only caches IPV4 and IPV6; unset for others.
294    */
295   void setCachedAddress(const sockaddr* addr, socklen_t len);
296 
297 protected:
298   /** connect, called by open */
299   void openConnection(struct addrinfo* res);
300 
301   /** Host to connect to */
302   std::string host_;
303 
304   /** Port number to connect on */
305   int port_;
306 
307   /** UNIX domain socket path */
308   std::string path_;
309 
310   /** Underlying socket handle */
311   THRIFT_SOCKET socket_;
312 
313   /** Peer hostname */
314   mutable std::string peerHost_;
315 
316   /** Peer address */
317   mutable std::string peerAddress_;
318 
319   /** Peer port */
320   mutable int peerPort_;
321 
322   /**
323    * A shared socket pointer that will interrupt a blocking read if data
324    * becomes available on it
325    */
326   std::shared_ptr<THRIFT_SOCKET> interruptListener_;
327 
328   /** Connect timeout in ms */
329   int connTimeout_;
330 
331   /** Send timeout in ms */
332   int sendTimeout_;
333 
334   /** Recv timeout in ms */
335   int recvTimeout_;
336 
337   /** Keep alive on */
338   bool keepAlive_;
339 
340   /** Linger on */
341   bool lingerOn_;
342 
343   /** Linger val */
344   int lingerVal_;
345 
346   /** Nodelay */
347   bool noDelay_;
348 
349   /** Recv EGAIN retries */
350   int maxRecvRetries_;
351 
352   /** Cached peer address */
353   union {
354     sockaddr_in ipv4;
355     sockaddr_in6 ipv6;
356   } cachedPeerAddr_;
357 
358   /** Whether to use low minimum TCP retransmission timeout */
359   static bool useLowMinRto_;
360 
361 private:
362   void unix_open();
363   void local_open();
364 };
365 }
366 }
367 } // apache::thrift::transport
368 
369 #endif // #ifndef _THRIFT_TRANSPORT_TSOCKET_H_
370