blob: 178de812385336119a6eba71dab62bdb660eb9c2 [file] [log] [blame]
Mark Sleee8540632006-05-30 09:24:40 +00001#include <sys/socket.h>
2#include <netinet/in.h>
3
4#include "transport/TSocket.h"
5#include "transport/TServerSocket.h"
6
7TServerSocket::TServerSocket(int port) :
8 port_(port), serverSocket_(0), acceptBacklog_(1024) {}
9
10TServerSocket::~TServerSocket() {
11 close();
12}
13
14bool TServerSocket::listen() {
15 serverSocket_ = socket(AF_INET, SOCK_STREAM, 0);
16 if (serverSocket_ == -1) {
17 close();
18 return false;
19 }
20
21 // Set reusaddress to prevent 2MSL delay on accept
22 int one = 1;
23 if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_REUSEADDR,
24 &one, sizeof(one))) {
25 perror("TServerSocket::listen() SO_REUSEADDR");
26 close();
27 return false;
28 }
29
30 // Turn linger off, don't want to block on calls to close
31 struct linger ling = {0, 0};
32 if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_LINGER,
33 &ling, sizeof(ling))) {
34 perror("TServerSocket::listen() SO_LINGER");
35 close();
36 return false;
37 }
38
39 // Bind to a port
40 struct sockaddr_in addr;
41 memset(&addr, 0, sizeof(addr));
42 addr.sin_family = AF_INET;
43 addr.sin_port = htons(port_);
44 addr.sin_addr.s_addr = INADDR_ANY;
45 if (-1 == bind(serverSocket_, (struct sockaddr *)&addr, sizeof(addr))) {
46 char errbuf[1024];
47 sprintf(errbuf, "TServerSocket::listen() BIND %d", port_);
48 perror(errbuf);
49 close();
50 return false;
51 }
52
53 // Call listen
54 if (-1 == ::listen(serverSocket_, acceptBacklog_)) {
55 perror("TServerSocket::listen() LISTEN");
56 close();
57 return false;
58 }
59
60 // The socket is now listening!
61 return true;
62}
63
64TTransport* TServerSocket::accept() {
65 if (serverSocket_ <= 0) {
66 // TODO(mcslee): Log error with common logging tool
67 return NULL;
68 }
69
70 struct sockaddr_in clientAddress;
71 int size = sizeof(clientAddress);
72 int clientSocket = ::accept(serverSocket_,
73 (struct sockaddr *) &clientAddress,
74 (socklen_t *) &size);
75
76 if (clientSocket <= 0) {
77 perror("TServerSocket::accept()");
78 return NULL;
79 }
80
81 return new TSocket(clientSocket);
82}
83
84void TServerSocket::close() {
85 if (serverSocket_ > 0) {
86 shutdown(serverSocket_, SHUT_RDWR);
87 ::close(serverSocket_);
88 }
89 serverSocket_ = 0;
90}