blob: 6b5bf05a5ad7f59408a651b365839658eae8f677 [file] [log] [blame]
David Reissea2cba82009-03-30 21:35:00 +00001/*
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 */
Mark Slee9f0c6512007-02-28 23:58:26 +000019
David Reissc88eb8c2008-06-11 01:18:54 +000020#include <cstring>
David Reiss08d2f112009-05-21 02:28:36 +000021#include <sys/types.h>
Mark Sleee8540632006-05-30 09:24:40 +000022#include <sys/socket.h>
David Reiss1677ac92008-04-08 06:26:27 +000023#include <sys/poll.h>
Mark Sleedd564972007-08-21 02:39:57 +000024#include <sys/types.h>
Mark Sleee8540632006-05-30 09:24:40 +000025#include <netinet/in.h>
Mark Slee29050782006-09-29 00:12:30 +000026#include <netinet/tcp.h>
Mark Slee6d56eb92007-07-06 22:28:15 +000027#include <netdb.h>
Mark Sleea5a783f2007-03-02 19:41:08 +000028#include <fcntl.h>
Mark Slee8d7e1f62006-06-07 06:48:56 +000029#include <errno.h>
David Reiss5105b2e2009-05-21 02:28:27 +000030#include <unistd.h>
Mark Sleee8540632006-05-30 09:24:40 +000031
Marc Slemkod42a2c22006-08-10 03:30:18 +000032#include "TSocket.h"
33#include "TServerSocket.h"
Marc Slemko16698852006-08-04 03:16:10 +000034#include <boost/shared_ptr.hpp>
Mark Sleee8540632006-05-30 09:24:40 +000035
David Reiss9b903442009-10-21 05:51:28 +000036#ifndef AF_LOCAL
37#define AF_LOCAL AF_UNIX
38#endif
39
T Jake Lucianib5e62212009-01-31 22:36:20 +000040namespace apache { namespace thrift { namespace transport {
Marc Slemko6f038a72006-08-03 18:58:09 +000041
Martin Kraemere6c4fa62007-07-09 19:08:25 +000042using namespace std;
David Reissd4a269c2007-08-23 02:37:19 +000043using boost::shared_ptr;
Marc Slemko16698852006-08-04 03:16:10 +000044
Mark Sleee8540632006-05-30 09:24:40 +000045TServerSocket::TServerSocket(int port) :
Mark Slee29050782006-09-29 00:12:30 +000046 port_(port),
Martin Kraemeree341cb2007-02-05 21:40:38 +000047 serverSocket_(-1),
Mark Slee29050782006-09-29 00:12:30 +000048 acceptBacklog_(1024),
49 sendTimeout_(0),
Mark Sleea5a783f2007-03-02 19:41:08 +000050 recvTimeout_(0),
boz1ea81ce2007-05-14 23:04:33 +000051 retryLimit_(0),
52 retryDelay_(0),
Christopher Piro9cc63b52008-03-21 00:40:42 +000053 tcpSendBuffer_(0),
54 tcpRecvBuffer_(0),
Mark Slee561b5362007-03-09 19:26:29 +000055 intSock1_(-1),
56 intSock2_(-1) {}
Mark Slee29050782006-09-29 00:12:30 +000057
58TServerSocket::TServerSocket(int port, int sendTimeout, int recvTimeout) :
59 port_(port),
Martin Kraemeree341cb2007-02-05 21:40:38 +000060 serverSocket_(-1),
Mark Slee29050782006-09-29 00:12:30 +000061 acceptBacklog_(1024),
62 sendTimeout_(sendTimeout),
Mark Sleea5a783f2007-03-02 19:41:08 +000063 recvTimeout_(recvTimeout),
boz1ea81ce2007-05-14 23:04:33 +000064 retryLimit_(0),
65 retryDelay_(0),
Christopher Piro9cc63b52008-03-21 00:40:42 +000066 tcpSendBuffer_(0),
67 tcpRecvBuffer_(0),
Mark Slee561b5362007-03-09 19:26:29 +000068 intSock1_(-1),
69 intSock2_(-1) {}
Mark Sleee8540632006-05-30 09:24:40 +000070
71TServerSocket::~TServerSocket() {
72 close();
73}
74
Mark Slee29050782006-09-29 00:12:30 +000075void TServerSocket::setSendTimeout(int sendTimeout) {
76 sendTimeout_ = sendTimeout;
77}
78
79void TServerSocket::setRecvTimeout(int recvTimeout) {
80 recvTimeout_ = recvTimeout;
81}
82
boz1ea81ce2007-05-14 23:04:33 +000083void TServerSocket::setRetryLimit(int retryLimit) {
84 retryLimit_ = retryLimit;
85}
86
87void TServerSocket::setRetryDelay(int retryDelay) {
88 retryDelay_ = retryDelay;
89}
90
Christopher Piro9cc63b52008-03-21 00:40:42 +000091void TServerSocket::setTcpSendBuffer(int tcpSendBuffer) {
92 tcpSendBuffer_ = tcpSendBuffer;
93}
94
95void TServerSocket::setTcpRecvBuffer(int tcpRecvBuffer) {
96 tcpRecvBuffer_ = tcpRecvBuffer;
97}
98
Mark Slee8d7e1f62006-06-07 06:48:56 +000099void TServerSocket::listen() {
Mark Slee561b5362007-03-09 19:26:29 +0000100 int sv[2];
101 if (-1 == socketpair(AF_LOCAL, SOCK_STREAM, 0, sv)) {
David Reiss01e55c12008-07-13 22:18:51 +0000102 GlobalOutput.perror("TServerSocket::listen() socketpair() ", errno);
Mark Slee561b5362007-03-09 19:26:29 +0000103 intSock1_ = -1;
104 intSock2_ = -1;
105 } else {
Mark Sleee02385b2007-06-09 01:21:16 +0000106 intSock1_ = sv[1];
107 intSock2_ = sv[0];
Mark Slee561b5362007-03-09 19:26:29 +0000108 }
109
Mark Slee6d56eb92007-07-06 22:28:15 +0000110 struct addrinfo hints, *res, *res0;
111 int error;
112 char port[sizeof("65536") + 1];
David Reissc88eb8c2008-06-11 01:18:54 +0000113 std::memset(&hints, 0, sizeof(hints));
Mark Slee6d56eb92007-07-06 22:28:15 +0000114 hints.ai_family = PF_UNSPEC;
115 hints.ai_socktype = SOCK_STREAM;
Mark Slee256bdc42007-11-27 08:42:19 +0000116 hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
Mark Slee6d56eb92007-07-06 22:28:15 +0000117 sprintf(port, "%d", port_);
118
119 // Wildcard address
120 error = getaddrinfo(NULL, port, &hints, &res0);
121 if (error) {
David Reiss01e55c12008-07-13 22:18:51 +0000122 GlobalOutput.printf("getaddrinfo %d: %s", error, gai_strerror(error));
Mark Slee6d56eb92007-07-06 22:28:15 +0000123 close();
124 throw TTransportException(TTransportException::NOT_OPEN, "Could not resolve host for server socket.");
125 }
126
127 // Pick the ipv6 address first since ipv4 addresses can be mapped
128 // into ipv6 space.
129 for (res = res0; res; res = res->ai_next) {
130 if (res->ai_family == AF_INET6 || res->ai_next == NULL)
131 break;
132 }
Mark Slee256bdc42007-11-27 08:42:19 +0000133
Mark Slee6d56eb92007-07-06 22:28:15 +0000134 serverSocket_ = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
Mark Sleee8540632006-05-30 09:24:40 +0000135 if (serverSocket_ == -1) {
David Reiss9b209552008-04-08 06:26:05 +0000136 int errno_copy = errno;
David Reiss01e55c12008-07-13 22:18:51 +0000137 GlobalOutput.perror("TServerSocket::listen() socket() ", errno_copy);
Mark Sleee8540632006-05-30 09:24:40 +0000138 close();
David Reiss9b209552008-04-08 06:26:05 +0000139 throw TTransportException(TTransportException::NOT_OPEN, "Could not create server socket.", errno_copy);
Mark Sleee8540632006-05-30 09:24:40 +0000140 }
141
142 // Set reusaddress to prevent 2MSL delay on accept
143 int one = 1;
144 if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_REUSEADDR,
145 &one, sizeof(one))) {
David Reiss9b209552008-04-08 06:26:05 +0000146 int errno_copy = errno;
David Reiss01e55c12008-07-13 22:18:51 +0000147 GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_REUSEADDR ", errno_copy);
Mark Sleee8540632006-05-30 09:24:40 +0000148 close();
David Reiss9b209552008-04-08 06:26:05 +0000149 throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_REUSEADDR", errno_copy);
Mark Sleee8540632006-05-30 09:24:40 +0000150 }
151
Christopher Piro9cc63b52008-03-21 00:40:42 +0000152 // Set TCP buffer sizes
153 if (tcpSendBuffer_ > 0) {
154 if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_SNDBUF,
155 &tcpSendBuffer_, sizeof(tcpSendBuffer_))) {
David Reiss9b209552008-04-08 06:26:05 +0000156 int errno_copy = errno;
David Reiss01e55c12008-07-13 22:18:51 +0000157 GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_SNDBUF ", errno_copy);
Christopher Piro9cc63b52008-03-21 00:40:42 +0000158 close();
David Reiss9b209552008-04-08 06:26:05 +0000159 throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_SNDBUF", errno_copy);
Christopher Piro9cc63b52008-03-21 00:40:42 +0000160 }
161 }
162
163 if (tcpRecvBuffer_ > 0) {
164 if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_RCVBUF,
165 &tcpRecvBuffer_, sizeof(tcpRecvBuffer_))) {
David Reiss9b209552008-04-08 06:26:05 +0000166 int errno_copy = errno;
David Reiss01e55c12008-07-13 22:18:51 +0000167 GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_RCVBUF ", errno_copy);
Christopher Piro9cc63b52008-03-21 00:40:42 +0000168 close();
David Reiss9b209552008-04-08 06:26:05 +0000169 throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_RCVBUF", errno_copy);
Christopher Piro9cc63b52008-03-21 00:40:42 +0000170 }
171 }
172
Mark Slee29050782006-09-29 00:12:30 +0000173 // Defer accept
174 #ifdef TCP_DEFER_ACCEPT
175 if (-1 == setsockopt(serverSocket_, SOL_SOCKET, TCP_DEFER_ACCEPT,
176 &one, sizeof(one))) {
David Reiss9b209552008-04-08 06:26:05 +0000177 int errno_copy = errno;
David Reiss01e55c12008-07-13 22:18:51 +0000178 GlobalOutput.perror("TServerSocket::listen() setsockopt() TCP_DEFER_ACCEPT ", errno_copy);
Mark Slee29050782006-09-29 00:12:30 +0000179 close();
David Reiss9b209552008-04-08 06:26:05 +0000180 throw TTransportException(TTransportException::NOT_OPEN, "Could not set TCP_DEFER_ACCEPT", errno_copy);
Mark Slee29050782006-09-29 00:12:30 +0000181 }
182 #endif // #ifdef TCP_DEFER_ACCEPT
183
David Reiss13aea462008-06-10 22:56:04 +0000184 #ifdef IPV6_V6ONLY
185 int zero = 0;
David Reiss1a2f2182008-06-11 01:14:01 +0000186 if (-1 == setsockopt(serverSocket_, IPPROTO_IPV6, IPV6_V6ONLY,
David Reiss13aea462008-06-10 22:56:04 +0000187 &zero, sizeof(zero))) {
David Reiss01e55c12008-07-13 22:18:51 +0000188 GlobalOutput.perror("TServerSocket::listen() IPV6_V6ONLY ", errno);
David Reiss13aea462008-06-10 22:56:04 +0000189 }
190 #endif // #ifdef IPV6_V6ONLY
191
Mark Sleee8540632006-05-30 09:24:40 +0000192 // Turn linger off, don't want to block on calls to close
193 struct linger ling = {0, 0};
194 if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_LINGER,
195 &ling, sizeof(ling))) {
David Reiss9b209552008-04-08 06:26:05 +0000196 int errno_copy = errno;
David Reiss01e55c12008-07-13 22:18:51 +0000197 GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_LINGER ", errno_copy);
Mark Sleee8540632006-05-30 09:24:40 +0000198 close();
David Reiss9b209552008-04-08 06:26:05 +0000199 throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_LINGER", errno_copy);
Mark Sleee8540632006-05-30 09:24:40 +0000200 }
201
Mark Slee29050782006-09-29 00:12:30 +0000202 // TCP Nodelay, speed over bandwidth
203 if (-1 == setsockopt(serverSocket_, IPPROTO_TCP, TCP_NODELAY,
204 &one, sizeof(one))) {
David Reiss9b209552008-04-08 06:26:05 +0000205 int errno_copy = errno;
David Reiss01e55c12008-07-13 22:18:51 +0000206 GlobalOutput.perror("TServerSocket::listen() setsockopt() TCP_NODELAY ", errno_copy);
Mark Slee29050782006-09-29 00:12:30 +0000207 close();
David Reiss9b209552008-04-08 06:26:05 +0000208 throw TTransportException(TTransportException::NOT_OPEN, "Could not set TCP_NODELAY", errno_copy);
Mark Slee29050782006-09-29 00:12:30 +0000209 }
210
Mark Sleea5a783f2007-03-02 19:41:08 +0000211 // Set NONBLOCK on the accept socket
212 int flags = fcntl(serverSocket_, F_GETFL, 0);
213 if (flags == -1) {
David Reiss9b209552008-04-08 06:26:05 +0000214 int errno_copy = errno;
David Reiss01e55c12008-07-13 22:18:51 +0000215 GlobalOutput.perror("TServerSocket::listen() fcntl() F_GETFL ", errno_copy);
David Reiss9b209552008-04-08 06:26:05 +0000216 throw TTransportException(TTransportException::NOT_OPEN, "fcntl() failed", errno_copy);
Mark Sleea5a783f2007-03-02 19:41:08 +0000217 }
Mark Slee561b5362007-03-09 19:26:29 +0000218
Mark Sleea5a783f2007-03-02 19:41:08 +0000219 if (-1 == fcntl(serverSocket_, F_SETFL, flags | O_NONBLOCK)) {
David Reiss9b209552008-04-08 06:26:05 +0000220 int errno_copy = errno;
David Reiss01e55c12008-07-13 22:18:51 +0000221 GlobalOutput.perror("TServerSocket::listen() fcntl() O_NONBLOCK ", errno_copy);
David Reiss9b209552008-04-08 06:26:05 +0000222 throw TTransportException(TTransportException::NOT_OPEN, "fcntl() failed", errno_copy);
Mark Sleea5a783f2007-03-02 19:41:08 +0000223 }
224
boz1ea81ce2007-05-14 23:04:33 +0000225 // prepare the port information
Mark Slee256bdc42007-11-27 08:42:19 +0000226 // we may want to try to bind more than once, since SO_REUSEADDR doesn't
boz1ea81ce2007-05-14 23:04:33 +0000227 // always seem to work. The client can configure the retry variables.
228 int retries = 0;
229 do {
Mark Slee6d56eb92007-07-06 22:28:15 +0000230 if (0 == bind(serverSocket_, res->ai_addr, res->ai_addrlen)) {
boz1ea81ce2007-05-14 23:04:33 +0000231 break;
232 }
233
234 // use short circuit evaluation here to only sleep if we need to
235 } while ((retries++ < retryLimit_) && (sleep(retryDelay_) == 0));
236
Mark Slee6d56eb92007-07-06 22:28:15 +0000237 // free addrinfo
238 freeaddrinfo(res0);
Mark Slee256bdc42007-11-27 08:42:19 +0000239
boz1ea81ce2007-05-14 23:04:33 +0000240 // throw an error if we failed to bind properly
241 if (retries > retryLimit_) {
Mark Sleee8540632006-05-30 09:24:40 +0000242 char errbuf[1024];
243 sprintf(errbuf, "TServerSocket::listen() BIND %d", port_);
boz6ded7752007-06-05 22:41:18 +0000244 GlobalOutput(errbuf);
Mark Sleee8540632006-05-30 09:24:40 +0000245 close();
Mark Sleef9831082007-02-20 20:59:21 +0000246 throw TTransportException(TTransportException::NOT_OPEN, "Could not bind");
Mark Sleee8540632006-05-30 09:24:40 +0000247 }
248
249 // Call listen
250 if (-1 == ::listen(serverSocket_, acceptBacklog_)) {
David Reiss9b209552008-04-08 06:26:05 +0000251 int errno_copy = errno;
David Reiss01e55c12008-07-13 22:18:51 +0000252 GlobalOutput.perror("TServerSocket::listen() listen() ", errno_copy);
Mark Sleee8540632006-05-30 09:24:40 +0000253 close();
David Reiss9b209552008-04-08 06:26:05 +0000254 throw TTransportException(TTransportException::NOT_OPEN, "Could not listen", errno_copy);
Mark Sleee8540632006-05-30 09:24:40 +0000255 }
256
257 // The socket is now listening!
Mark Sleee8540632006-05-30 09:24:40 +0000258}
259
Marc Slemko16698852006-08-04 03:16:10 +0000260shared_ptr<TTransport> TServerSocket::acceptImpl() {
Martin Kraemer10640d82007-02-03 01:59:12 +0000261 if (serverSocket_ < 0) {
Mark Sleef9831082007-02-20 20:59:21 +0000262 throw TTransportException(TTransportException::NOT_OPEN, "TServerSocket not listening");
Mark Sleee8540632006-05-30 09:24:40 +0000263 }
264
David Reiss1677ac92008-04-08 06:26:27 +0000265 struct pollfd fds[2];
Mark Sleea5a783f2007-03-02 19:41:08 +0000266
Aditya Agarwal7859a572007-05-31 01:33:07 +0000267 int maxEintrs = 5;
268 int numEintrs = 0;
269
Mark Sleea5a783f2007-03-02 19:41:08 +0000270 while (true) {
David Reissc88eb8c2008-06-11 01:18:54 +0000271 std::memset(fds, 0 , sizeof(fds));
David Reiss1677ac92008-04-08 06:26:27 +0000272 fds[0].fd = serverSocket_;
273 fds[0].events = POLLIN;
Mark Slee561b5362007-03-09 19:26:29 +0000274 if (intSock2_ >= 0) {
David Reiss1677ac92008-04-08 06:26:27 +0000275 fds[1].fd = intSock2_;
David Reiss2724c7a2008-04-18 17:48:03 +0000276 fds[1].events = POLLIN;
Mark Sleea5a783f2007-03-02 19:41:08 +0000277 }
David Reiss1677ac92008-04-08 06:26:27 +0000278 int ret = poll(fds, 2, -1);
Mark Sleea5a783f2007-03-02 19:41:08 +0000279
Mark Slee561b5362007-03-09 19:26:29 +0000280 if (ret < 0) {
Aditya Agarwal7859a572007-05-31 01:33:07 +0000281 // error cases
bozf83c9db2007-05-31 23:38:37 +0000282 if (errno == EINTR && (numEintrs++ < maxEintrs)) {
Mark Slee256bdc42007-11-27 08:42:19 +0000283 // EINTR needs to be handled manually and we can tolerate
Aditya Agarwal7859a572007-05-31 01:33:07 +0000284 // a certain number
285 continue;
286 }
David Reiss9b209552008-04-08 06:26:05 +0000287 int errno_copy = errno;
David Reiss01e55c12008-07-13 22:18:51 +0000288 GlobalOutput.perror("TServerSocket::acceptImpl() poll() ", errno_copy);
David Reiss9b209552008-04-08 06:26:05 +0000289 throw TTransportException(TTransportException::UNKNOWN, "Unknown", errno_copy);
Mark Slee561b5362007-03-09 19:26:29 +0000290 } else if (ret > 0) {
291 // Check for an interrupt signal
David Reiss1677ac92008-04-08 06:26:27 +0000292 if (intSock2_ >= 0 && (fds[1].revents & POLLIN)) {
Mark Slee561b5362007-03-09 19:26:29 +0000293 int8_t buf;
294 if (-1 == recv(intSock2_, &buf, sizeof(int8_t), 0)) {
David Reiss01e55c12008-07-13 22:18:51 +0000295 GlobalOutput.perror("TServerSocket::acceptImpl() recv() interrupt ", errno);
Mark Slee561b5362007-03-09 19:26:29 +0000296 }
297 throw TTransportException(TTransportException::INTERRUPTED);
298 }
David Reiss9b209552008-04-08 06:26:05 +0000299
Mark Slee561b5362007-03-09 19:26:29 +0000300 // Check for the actual server socket being ready
David Reiss1677ac92008-04-08 06:26:27 +0000301 if (fds[0].revents & POLLIN) {
Mark Slee561b5362007-03-09 19:26:29 +0000302 break;
303 }
304 } else {
David Reiss1677ac92008-04-08 06:26:27 +0000305 GlobalOutput("TServerSocket::acceptImpl() poll 0");
Mark Slee256bdc42007-11-27 08:42:19 +0000306 throw TTransportException(TTransportException::UNKNOWN);
Mark Sleea5a783f2007-03-02 19:41:08 +0000307 }
308 }
309
Mark Slee6d56eb92007-07-06 22:28:15 +0000310 struct sockaddr_storage clientAddress;
Mark Sleee8540632006-05-30 09:24:40 +0000311 int size = sizeof(clientAddress);
312 int clientSocket = ::accept(serverSocket_,
313 (struct sockaddr *) &clientAddress,
314 (socklen_t *) &size);
Mark Slee256bdc42007-11-27 08:42:19 +0000315
Martin Kraemeree341cb2007-02-05 21:40:38 +0000316 if (clientSocket < 0) {
David Reissbc3dddb2007-08-22 23:20:24 +0000317 int errno_copy = errno;
David Reiss01e55c12008-07-13 22:18:51 +0000318 GlobalOutput.perror("TServerSocket::acceptImpl() ::accept() ", errno_copy);
David Reissbc3dddb2007-08-22 23:20:24 +0000319 throw TTransportException(TTransportException::UNKNOWN, "accept()", errno_copy);
Mark Sleee8540632006-05-30 09:24:40 +0000320 }
Mark Sleea5a783f2007-03-02 19:41:08 +0000321
322 // Make sure client socket is blocking
323 int flags = fcntl(clientSocket, F_GETFL, 0);
324 if (flags == -1) {
David Reissbc3dddb2007-08-22 23:20:24 +0000325 int errno_copy = errno;
David Reiss01e55c12008-07-13 22:18:51 +0000326 GlobalOutput.perror("TServerSocket::acceptImpl() fcntl() F_GETFL ", errno_copy);
David Reissbc3dddb2007-08-22 23:20:24 +0000327 throw TTransportException(TTransportException::UNKNOWN, "fcntl(F_GETFL)", errno_copy);
Mark Sleea5a783f2007-03-02 19:41:08 +0000328 }
David Reiss9b209552008-04-08 06:26:05 +0000329
Mark Sleea5a783f2007-03-02 19:41:08 +0000330 if (-1 == fcntl(clientSocket, F_SETFL, flags & ~O_NONBLOCK)) {
David Reissbc3dddb2007-08-22 23:20:24 +0000331 int errno_copy = errno;
David Reiss01e55c12008-07-13 22:18:51 +0000332 GlobalOutput.perror("TServerSocket::acceptImpl() fcntl() F_SETFL ~O_NONBLOCK ", errno_copy);
David Reissbc3dddb2007-08-22 23:20:24 +0000333 throw TTransportException(TTransportException::UNKNOWN, "fcntl(F_SETFL)", errno_copy);
Mark Sleea5a783f2007-03-02 19:41:08 +0000334 }
Mark Slee256bdc42007-11-27 08:42:19 +0000335
Mark Slee29050782006-09-29 00:12:30 +0000336 shared_ptr<TSocket> client(new TSocket(clientSocket));
337 if (sendTimeout_ > 0) {
338 client->setSendTimeout(sendTimeout_);
339 }
340 if (recvTimeout_ > 0) {
341 client->setRecvTimeout(recvTimeout_);
Mark Sleea5a783f2007-03-02 19:41:08 +0000342 }
Mark Slee256bdc42007-11-27 08:42:19 +0000343
Mark Slee29050782006-09-29 00:12:30 +0000344 return client;
Mark Sleee8540632006-05-30 09:24:40 +0000345}
346
Mark Slee561b5362007-03-09 19:26:29 +0000347void TServerSocket::interrupt() {
348 if (intSock1_ >= 0) {
349 int8_t byte = 0;
350 if (-1 == send(intSock1_, &byte, sizeof(int8_t), 0)) {
David Reiss01e55c12008-07-13 22:18:51 +0000351 GlobalOutput.perror("TServerSocket::interrupt() send() ", errno);
Mark Slee561b5362007-03-09 19:26:29 +0000352 }
353 }
354}
355
Mark Sleee8540632006-05-30 09:24:40 +0000356void TServerSocket::close() {
Martin Kraemeree341cb2007-02-05 21:40:38 +0000357 if (serverSocket_ >= 0) {
Mark Sleee8540632006-05-30 09:24:40 +0000358 shutdown(serverSocket_, SHUT_RDWR);
359 ::close(serverSocket_);
360 }
Mark Slee561b5362007-03-09 19:26:29 +0000361 if (intSock1_ >= 0) {
362 ::close(intSock1_);
363 }
364 if (intSock2_ >= 0) {
365 ::close(intSock2_);
366 }
Martin Kraemeree341cb2007-02-05 21:40:38 +0000367 serverSocket_ = -1;
Mark Slee561b5362007-03-09 19:26:29 +0000368 intSock1_ = -1;
369 intSock2_ = -1;
Mark Sleee8540632006-05-30 09:24:40 +0000370}
Marc Slemko6f038a72006-08-03 18:58:09 +0000371
T Jake Lucianib5e62212009-01-31 22:36:20 +0000372}}} // apache::thrift::transport