34 #include <sys/types.h>
35 #include <sys/socket.h>
38 #include <sys/select.h>
41 #include <netinet/in.h>
42 #include <arpa/inet.h>
45 #include <netinet/tcp.h>
60 #include <arpa/inet.h>
62 #include "TcpSocket.h"
63 #include "SocketConfig.h"
64 #include "TheBESKeys.h"
66 #include "BESInternalError.h"
67 #include "BESInternalFatalError.h"
71 void TcpSocket::connect()
74 string err(
"Socket is already listening");
79 string err(
"Socket is already connected");
83 if (_host ==
"") _host =
"localhost";
85 struct protoent *pProtoEnt;
86 struct sockaddr_in sin;
91 if (isdigit(_host[0])) {
92 if (0 == inet_aton(_host.c_str(), &sin.sin_addr)) {
93 throw BESInternalError(
string(
"Invalid host ip address ") + _host, __FILE__, __LINE__);
96 if ((address = inet_addr(_host.c_str())) == -1) {
97 string err(
"Invalid host ip address ");
101 sin.sin_addr.s_addr = address;
103 sin.sin_family = AF_INET;
106 if ((ph = gethostbyname(_host.c_str())) == NULL) {
108 case HOST_NOT_FOUND: {
109 string err(
"No such host ");
115 err += _host +
" is busy, try again later";
119 string err(
"DNS error for host ");
124 string err(
"No IP address for host ");
134 sin.sin_family = ph->h_addrtype;
135 for (
char **p = ph->h_addr_list; *p != NULL; p++) {
137 (void) memcpy(&in.s_addr, *p,
sizeof(in.s_addr));
138 memcpy((
char*) &sin.sin_addr, (
char*) &in,
sizeof(in));
143 sin.sin_port = htons(_portVal);
144 pProtoEnt = getprotobyname(
"tcp");
146 string err(
"Error retreiving tcp protocol information");
151 int descript = socket(AF_INET, SOCK_STREAM, pProtoEnt->p_proto);
153 if (descript == -1) {
154 throw BESInternalError(
string(
"getting socket descriptor: ") + strerror(errno), __FILE__, __LINE__);
161 holder = fcntl(_socket, F_GETFL, NULL);
162 holder = holder | O_NONBLOCK;
163 int status = fcntl(_socket, F_SETFL, holder);
165 throw BESInternalError(
string(
"Could not reset socket to blocking mode: ") + strerror(errno), __FILE__, __LINE__);
168 setTcpRecvBufferSize();
169 setTcpSendBufferSize();
171 int res = ::connect(descript, (
struct sockaddr*) &sin,
sizeof(sin));
174 if (errno == EINPROGRESS) {
177 struct timeval timeout;
184 FD_SET(_socket, &write_fd);
186 if (select(maxfd + 1, NULL, &write_fd, NULL, &timeout) < 0) {
189 holder = fcntl(_socket, F_GETFL, NULL);
190 holder = holder & (~O_NONBLOCK);
191 int status = fcntl(_socket, F_SETFL, holder);
193 throw BESInternalError(
string(
"Could not reset socket to blocking mode: ") + strerror(errno), __FILE__, __LINE__);
196 throw BESInternalError(
string(
"selecting sockets: ") + strerror(errno), __FILE__, __LINE__);
205 int status = getsockopt(_socket, SOL_SOCKET, SO_ERROR, (
void*) &valopt, &lon);
207 throw BESInternalError(
string(
"Could not check socket status: ") + strerror(errno), __FILE__, __LINE__);
212 holder = fcntl(_socket, F_GETFL, NULL);
213 holder = holder & (~O_NONBLOCK);
214 int status = fcntl(_socket, F_SETFL, holder);
216 throw BESInternalError(
string(
"Could not reset socket to blocking mode: ") + strerror(errno), __FILE__, __LINE__);
220 "Server may be down or you may be trying on the wrong port", __FILE__, __LINE__);
225 holder = fcntl(_socket, F_GETFL, NULL);
226 holder = holder & (~O_NONBLOCK);
227 int status = fcntl(_socket, F_SETFL, holder);
229 throw BESInternalError(
string(
"Could not reset socket to blocking mode: ") + strerror(errno), __FILE__, __LINE__);
238 holder = fcntl(_socket, F_GETFL, NULL);
239 holder = holder & (~O_NONBLOCK);
240 int status = fcntl(_socket, F_SETFL, holder);
242 throw BESInternalError(
string(
"Could not reset socket to blocking mode: ") + strerror(errno), __FILE__, __LINE__);
245 throw BESInternalError(
string(
"socket connect: ") + strerror(errno), __FILE__, __LINE__);
253 holder = fcntl(_socket, F_GETFL, NULL);
254 holder = holder & (~O_NONBLOCK);
255 int status = fcntl(_socket, F_SETFL, holder);
257 throw BESInternalError(
string(
"Could not reset socket to blocking mode: ") + strerror(errno), __FILE__, __LINE__);
264 void TcpSocket::listen()
267 string err(
"Socket is already connected");
272 string err(
"Socket is already listening");
276 struct sockaddr_in server;
277 server.sin_family = AF_INET;
279 if (!_host.empty()) {
280 int status = inet_pton(AF_INET, _host.c_str(), &server.sin_addr.s_addr);
282 throw BESInternalError(
"Error using IP address: " + _host, __FILE__, __LINE__);
285 server.sin_addr.s_addr = INADDR_ANY;
288 BESDEBUG(
"ppt",
"Checking /etc/services for port " << _portVal << endl);
289 struct servent *sir = getservbyport(htons(_portVal), 0);
291 std::ostringstream error_oss;
292 error_oss << endl <<
"CONFIGURATION ERROR: The requested port (" << _portVal
293 <<
") appears in the system services list. ";
294 error_oss <<
"Port " << _portVal <<
" is assigned to the service '" << sir->s_name << (string)
"'";
296 if (sir->s_aliases[0] != 0) {
297 error_oss <<
" which may also be known as: ";
298 for (
int i = 0; sir->s_aliases[i] != 0; i++) {
299 if (i > 0) error_oss <<
" or ";
301 error_oss << sir->s_aliases[i];
310 server.sin_port = htons(_portVal);
311 _socket = socket(AF_INET, SOCK_STREAM, 0);
314 if (setsockopt(_socket, SOL_SOCKET, SO_REUSEADDR, (
char*)&on,
sizeof(on))) {
315 std::ostringstream errMsg;
316 errMsg << endl <<
"ERROR: Failed to set SO_REUSEADDR on TCP socket";
317 const char* error_info = strerror(errno);
318 if (error_info) errMsg <<
". Msg:: " << error_info;
323 BESDEBUG(
"besdaemon",
"About to bind to port: " << _portVal <<
" in process: " << getpid() << endl);
325 if (::bind(_socket, (
struct sockaddr*) &server,
sizeof server) != -1) {
326 int length =
sizeof(server);
327 #ifdef _GETSOCKNAME_USES_SOCKLEN_T
328 if (getsockname(_socket, (
struct sockaddr *) &server, (socklen_t *) &length) == -1) {
330 if( getsockname( _socket, (
struct sockaddr *)&server, &length ) == -1 ) {
332 string error(
"getting socket name");
333 const char* error_info = strerror(errno);
334 if (error_info) error +=
" " + (string) error_info;
340 setTcpRecvBufferSize();
341 setTcpSendBufferSize();
343 if (::listen(_socket, 5) == 0) {
347 string error(
"could not listen TCP socket");
348 const char* error_info = strerror(errno);
349 if (error_info) error +=
" " + (string) error_info;
354 std::ostringstream error_msg;
355 error_msg << endl <<
"ERROR: Failed to bind TCP socket: " << _portVal;
356 const char* error_info = strerror(errno);
357 if (error_info) error_msg <<
": " << error_info;
363 std::ostringstream error_oss;
364 error_oss << endl <<
"ERROR: Failed to create socket for port " << _portVal << endl;
365 const char *error_info = strerror(errno);
366 if (error_info) error_oss <<
" " << (string) error_info;
389 void TcpSocket::setTcpRecvBufferSize()
391 if (!_haveRecvBufferSize) {
402 if (setit ==
"Yes" || setit ==
"yes" || setit ==
"Yes") {
406 istringstream sizestrm(sizestr);
407 unsigned int sizenum = 0;
410 string err =
"Socket Recv Size malformed: " + sizestr;
415 int err = setsockopt(_socket, SOL_SOCKET, SO_RCVBUF, (
char *) &sizenum, (socklen_t)
sizeof(sizenum));
418 char *serr = strerror(myerrno);
419 string err =
"Failed to set the socket receive buffer size: ";
423 err +=
"unknow error occurred";
427 BESDEBUG(
"ppt",
"Tcp receive buffer size set to " << (
unsigned long)sizenum << endl);
450 void TcpSocket::setTcpSendBufferSize()
463 if (setit ==
"Yes" || setit ==
"yes" || setit ==
"Yes") {
472 istringstream sizestrm(sizestr);
473 unsigned int sizenum = 0;
476 string err =
"Socket Send Size malformed: " + sizestr;
481 int err = setsockopt(_socket, SOL_SOCKET, SO_SNDBUF, (
char *) &sizenum, (socklen_t)
sizeof(sizenum));
484 char *serr = strerror(myerrno);
485 string err =
"Failed to set the socket send buffer size: ";
489 err +=
"unknow error occurred";
493 BESDEBUG(
"ppt",
"Tcp send buffer size set to " << (
unsigned long)sizenum << endl);
507 if (!_haveRecvBufferSize) {
509 unsigned int sizenum = 0;
510 socklen_t sizelen =
sizeof(sizenum);
511 int err = getsockopt(_socket, SOL_SOCKET, SO_RCVBUF, (
char *) &sizenum, (socklen_t *) &sizelen);
514 char *serr = strerror(myerrno);
515 string err =
"Failed to get the socket receive buffer size: ";
519 err +=
"unknow error occurred";
523 BESDEBUG(
"ppt",
"Tcp receive buffer size is " << (
unsigned long)sizenum << endl);
525 _haveRecvBufferSize =
true;
526 _recvBufferSize = sizenum;
528 return _recvBufferSize;
541 if (!_haveSendBufferSize) {
543 unsigned int sizenum = 0;
544 socklen_t sizelen =
sizeof(sizenum);
545 int err = getsockopt(_socket, SOL_SOCKET, SO_SNDBUF, (
char *) &sizenum, (socklen_t *) &sizelen);
548 char *serr = strerror(myerrno);
549 string err =
"Failed to get the socket send buffer size: ";
553 err +=
"unknow error occurred";
557 BESDEBUG(
"ppt",
"Tcp send buffer size is " << (
unsigned long)sizenum << endl);
559 _haveSendBufferSize =
true;
560 _sendBufferSize = sizenum;
562 return _sendBufferSize;
573 struct request_info req;
574 request_init( &req, RQ_DAEMON,
"besdaemon", RQ_FILE,
575 getSocketDescriptor(), 0 );
578 if( STR_EQ( eval_hostname(), paranoid ) && hosts_access() )
595 strm << BESIndent::LMarg <<
"TcpSocket::dump - (" << (
void *)
this <<
")" << endl;
597 strm << BESIndent::LMarg <<
"host: " << _host << endl;
598 strm << BESIndent::LMarg <<
"port: " << _portVal << endl;
599 strm << BESIndent::LMarg <<
"have recv buffer size: " << _haveRecvBufferSize << endl;
600 strm << BESIndent::LMarg <<
"recv buffer size: " << _recvBufferSize << endl;
601 strm << BESIndent::LMarg <<
"have send buffer size: " << _haveSendBufferSize << endl;
602 strm << BESIndent::LMarg <<
"send buffer size: " << _sendBufferSize << endl;
604 BESIndent::UnIndent();