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