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