blob: 75bd504d3d01a99e204e79fc5115fdd3acafb299 [file] [log] [blame]
Mark Sleee8540632006-05-30 09:24:40 +00001#include <sys/socket.h>
2#include <netinet/in.h>
Mark Slee8d7e1f62006-06-07 06:48:56 +00003#include <errno.h>
Mark Sleee8540632006-05-30 09:24:40 +00004
Marc Slemkod42a2c22006-08-10 03:30:18 +00005#include "TSocket.h"
6#include "TServerSocket.h"
Marc Slemko16698852006-08-04 03:16:10 +00007#include <boost/shared_ptr.hpp>
Mark Sleee8540632006-05-30 09:24:40 +00008
Marc Slemko6f038a72006-08-03 18:58:09 +00009namespace facebook { namespace thrift { namespace transport {
10
Marc Slemko16698852006-08-04 03:16:10 +000011using namespace boost;
12
Mark Sleee8540632006-05-30 09:24:40 +000013TServerSocket::TServerSocket(int port) :
14 port_(port), serverSocket_(0), acceptBacklog_(1024) {}
15
16TServerSocket::~TServerSocket() {
17 close();
18}
19
Mark Slee8d7e1f62006-06-07 06:48:56 +000020void TServerSocket::listen() {
Mark Sleee8540632006-05-30 09:24:40 +000021 serverSocket_ = socket(AF_INET, SOCK_STREAM, 0);
22 if (serverSocket_ == -1) {
Mark Slee8d7e1f62006-06-07 06:48:56 +000023 perror("TServerSocket::listen() socket");
Mark Sleee8540632006-05-30 09:24:40 +000024 close();
Mark Slee8d7e1f62006-06-07 06:48:56 +000025 throw TTransportException(TTX_NOT_OPEN, "Could not create server socket.");
Mark Sleee8540632006-05-30 09:24:40 +000026 }
27
28 // Set reusaddress to prevent 2MSL delay on accept
29 int one = 1;
30 if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_REUSEADDR,
31 &one, sizeof(one))) {
32 perror("TServerSocket::listen() SO_REUSEADDR");
33 close();
Mark Slee8d7e1f62006-06-07 06:48:56 +000034 throw TTransportException(TTX_NOT_OPEN, "Could not set SO_REUSEADDR");
Mark Sleee8540632006-05-30 09:24:40 +000035 }
36
37 // Turn linger off, don't want to block on calls to close
38 struct linger ling = {0, 0};
39 if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_LINGER,
40 &ling, sizeof(ling))) {
Mark Sleee8540632006-05-30 09:24:40 +000041 close();
Mark Slee8d7e1f62006-06-07 06:48:56 +000042 perror("TServerSocket::listen() SO_LINGER");
43 throw TTransportException(TTX_NOT_OPEN, "Could not set SO_LINGER");
Mark Sleee8540632006-05-30 09:24:40 +000044 }
45
46 // Bind to a port
47 struct sockaddr_in addr;
48 memset(&addr, 0, sizeof(addr));
49 addr.sin_family = AF_INET;
50 addr.sin_port = htons(port_);
51 addr.sin_addr.s_addr = INADDR_ANY;
52 if (-1 == bind(serverSocket_, (struct sockaddr *)&addr, sizeof(addr))) {
53 char errbuf[1024];
54 sprintf(errbuf, "TServerSocket::listen() BIND %d", port_);
55 perror(errbuf);
56 close();
Mark Slee8d7e1f62006-06-07 06:48:56 +000057 throw TTransportException(TTX_NOT_OPEN, "Could not bind");
Mark Sleee8540632006-05-30 09:24:40 +000058 }
59
60 // Call listen
61 if (-1 == ::listen(serverSocket_, acceptBacklog_)) {
62 perror("TServerSocket::listen() LISTEN");
63 close();
Mark Slee8d7e1f62006-06-07 06:48:56 +000064 throw TTransportException(TTX_NOT_OPEN, "Could not listen");
Mark Sleee8540632006-05-30 09:24:40 +000065 }
66
67 // The socket is now listening!
Mark Sleee8540632006-05-30 09:24:40 +000068}
69
Marc Slemko16698852006-08-04 03:16:10 +000070shared_ptr<TTransport> TServerSocket::acceptImpl() {
Mark Sleee8540632006-05-30 09:24:40 +000071 if (serverSocket_ <= 0) {
Mark Slee8d7e1f62006-06-07 06:48:56 +000072 throw TTransportException(TTX_NOT_OPEN, "TServerSocket not listening");
Mark Sleee8540632006-05-30 09:24:40 +000073 }
74
75 struct sockaddr_in clientAddress;
76 int size = sizeof(clientAddress);
77 int clientSocket = ::accept(serverSocket_,
78 (struct sockaddr *) &clientAddress,
79 (socklen_t *) &size);
80
81 if (clientSocket <= 0) {
82 perror("TServerSocket::accept()");
Mark Slee8d7e1f62006-06-07 06:48:56 +000083 throw TTransportException(TTX_UNKNOWN, "ERROR:" + errno);
Mark Sleee8540632006-05-30 09:24:40 +000084 }
85
Marc Slemko16698852006-08-04 03:16:10 +000086 return shared_ptr<TTransport>(new TSocket(clientSocket));
Mark Sleee8540632006-05-30 09:24:40 +000087}
88
89void TServerSocket::close() {
90 if (serverSocket_ > 0) {
91 shutdown(serverSocket_, SHUT_RDWR);
92 ::close(serverSocket_);
93 }
94 serverSocket_ = 0;
95}
Marc Slemko6f038a72006-08-03 18:58:09 +000096
97}}} // facebook::thrift::transport