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>
64 using std::istringstream;
76 string err(
"Socket is already listening");
81 string err(
"Socket is already connected");
85 if (_host ==
"") _host =
"localhost";
87 struct protoent *pProtoEnt;
88 struct sockaddr_in sin;
91 if (isdigit(_host[0])) {
92 if ((address = inet_addr(_host.c_str())) == -1) {
93 string err(
"Invalid host ip address ");
97 sin.sin_addr.s_addr = address;
98 sin.sin_family = AF_INET;
101 if ((ph = gethostbyname(_host.c_str())) == NULL) {
103 case HOST_NOT_FOUND: {
104 string err(
"No such host ");
110 err += _host +
" is busy, try again later";
114 string err(
"DNS error for host ");
119 string err(
"No IP address for host ");
129 sin.sin_family = ph->h_addrtype;
130 for (
char **p = ph->h_addr_list; *p != NULL; p++) {
132 (void) memcpy(&in.s_addr, *p,
sizeof(in.s_addr));
133 memcpy((
char*) &sin.sin_addr, (
char*) &in,
sizeof(in));
138 sin.sin_port = htons( _portVal ) ;
139 pProtoEnt = getprotobyname(
"tcp");
141 string err(
"Error retreiving tcp protocol information");
146 int descript = socket(AF_INET, SOCK_STREAM, pProtoEnt->p_proto);
148 if (descript == -1) {
149 string err(
"getting socket descriptor: ");
150 const char* error_info = strerror(errno);
151 if (error_info) err += (string) error_info;
159 holder = fcntl(
_socket, F_GETFL, NULL);
160 holder = holder | O_NONBLOCK;
161 fcntl(
_socket, F_SETFL, holder);
164 setTcpRecvBufferSize();
165 setTcpSendBufferSize();
167 int res =
::connect(descript, (
struct sockaddr*) &sin,
sizeof(sin));
170 if (errno == EINPROGRESS) {
173 struct timeval timeout;
182 if (select(maxfd + 1, NULL, &write_fd, NULL, &timeout) < 0) {
185 holder = fcntl(
_socket, F_GETFL, NULL);
186 holder = holder & (~O_NONBLOCK);
187 fcntl(
_socket, F_SETFL, holder);
190 string err(
"selecting sockets: ");
191 const char *error_info = strerror(errno);
192 if (error_info) err += (string) error_info;
202 getsockopt(
_socket, SOL_SOCKET, SO_ERROR, (
void*) &valopt, &lon);
207 holder = fcntl(
_socket, F_GETFL, NULL);
208 holder = holder & (~O_NONBLOCK);
209 fcntl(
_socket, F_SETFL, holder);
212 string err(
"Did not successfully connect to server\n");
213 err +=
"Server may be down or you may be trying on the wrong port";
219 holder = fcntl(
_socket, F_GETFL, NULL);
220 holder = holder & (~O_NONBLOCK);
221 fcntl(
_socket, F_SETFL, holder);
231 holder = fcntl(
_socket, F_GETFL, NULL);
232 holder = holder & (~O_NONBLOCK);
233 fcntl(
_socket, F_SETFL, holder);
236 string err(
"socket connect: ");
237 const char* error_info = strerror(errno);
238 if (error_info) err += (string) error_info;
247 holder = fcntl(
_socket, F_GETFL, NULL);
248 holder = holder & (~O_NONBLOCK);
249 fcntl(
_socket, F_SETFL, holder);
258 string err(
"Socket is already connected");
263 string err(
"Socket is already listening");
268 struct sockaddr_in server;
269 server.sin_family = AF_INET;
270 server.sin_addr.s_addr = INADDR_ANY ;
271 struct servent *sir = 0;
272 BESDEBUG(
"ppt",
"Checking /etc/services for port " << _portVal << endl );
274 sir = getservbyport(htons(_portVal), 0);
276 std::ostringstream error_oss;
277 error_oss << endl <<
"CONFIGURATION ERROR: The requested port (" << _portVal
278 <<
") appears in the system services list. ";
279 error_oss <<
"Port " << _portVal <<
" is assigned to the service '" << sir->s_name << (string)
"'";
281 if (sir->s_aliases[0] != 0) {
282 error_oss <<
" which may also be known as: ";
283 for (
int i = 0; sir->s_aliases[i] != 0; i++) {
284 if (i > 0) error_oss <<
" or ";
286 error_oss << sir->s_aliases[i];
295 server.sin_port = htons( _portVal ) ;
296 _socket = socket(AF_INET, SOCK_STREAM, 0);
299 if (setsockopt(
_socket, SOL_SOCKET, SO_REUSEADDR, (
char*) &on,
sizeof(on))) {
300 std::ostringstream errMsg;
301 errMsg << endl <<
"ERROR: Failed to set SO_REUSEADDR on TCP socket";
302 const char* error_info = strerror(errno);
303 if (error_info) errMsg <<
". Msg:: " << error_info;
308 BESDEBUG(
"besdaemon",
"About to bind to port: " << _portVal <<
" in process: " << getpid() << endl);
310 if (bind(
_socket, (
struct sockaddr*) &server,
sizeof server) != -1) {
311 int length =
sizeof(server);
312 #ifdef _GETSOCKNAME_USES_SOCKLEN_T
313 if (getsockname(
_socket, (
struct sockaddr *) &server, (socklen_t *) &length) == -1)
315 if( getsockname(
_socket, (
struct sockaddr *)&server,
319 string error(
"getting socket name");
320 const char* error_info = strerror(errno);
321 if (error_info) error +=
" " + (string) error_info;
327 setTcpRecvBufferSize();
328 setTcpSendBufferSize();
334 string error(
"could not listen TCP socket");
335 const char* error_info = strerror(errno);
336 if (error_info) error +=
" " + (string) error_info;
341 std::ostringstream error_msg;
342 error_msg << endl <<
"ERROR: Failed to bind TCP socket: " << _portVal;
343 const char* error_info = strerror(errno);
344 if (error_info) error_msg <<
": " << error_info;
350 std::ostringstream error_oss;
351 error_oss << endl <<
"ERROR: Failed to create socket for port " << _portVal << endl;
352 const char *error_info = strerror(errno);
353 if (error_info) error_oss <<
" " << (string) error_info;
376 void TcpSocket::setTcpRecvBufferSize()
378 if (!_haveRecvBufferSize) {
389 if (setit ==
"Yes" || setit ==
"yes" || setit ==
"Yes") {
393 istringstream sizestrm(sizestr);
394 unsigned int sizenum = 0;
397 string err =
"Socket Recv Size malformed: " + sizestr;
402 int err = setsockopt(
_socket, SOL_SOCKET, SO_RCVBUF, (
char *) &sizenum, (socklen_t)
sizeof(sizenum));
405 char *serr = strerror(myerrno);
406 string err =
"Failed to set the socket receive buffer size: ";
410 err +=
"unknow error occurred";
414 BESDEBUG(
"ppt",
"Tcp receive buffer size set to "
415 << (
unsigned long)sizenum << endl );
438 void TcpSocket::setTcpSendBufferSize()
451 if (setit ==
"Yes" || setit ==
"yes" || setit ==
"Yes") {
460 istringstream sizestrm(sizestr);
461 unsigned int sizenum = 0;
464 string err =
"Socket Send Size malformed: " + sizestr;
469 int err = setsockopt(
_socket, SOL_SOCKET, SO_SNDBUF, (
char *) &sizenum, (socklen_t)
sizeof(sizenum));
472 char *serr = strerror(myerrno);
473 string err =
"Failed to set the socket send buffer size: ";
477 err +=
"unknow error occurred";
481 BESDEBUG(
"ppt",
"Tcp send buffer size set to "
482 << (
unsigned long)sizenum << endl );
496 if (!_haveRecvBufferSize) {
498 unsigned int sizenum = 0;
499 socklen_t sizelen =
sizeof(sizenum);
500 int err = getsockopt(
_socket, SOL_SOCKET, SO_RCVBUF, (
char *) &sizenum, (socklen_t *) &sizelen);
503 char *serr = strerror(myerrno);
504 string err =
"Failed to get the socket receive buffer size: ";
508 err +=
"unknow error occurred";
512 BESDEBUG(
"ppt",
"Tcp receive buffer size is "
513 << (
unsigned long)sizenum << endl );
515 _haveRecvBufferSize =
true;
516 _recvBufferSize = sizenum;
518 return _recvBufferSize;
531 if (!_haveSendBufferSize) {
533 unsigned int sizenum = 0;
534 socklen_t sizelen =
sizeof(sizenum);
535 int err = getsockopt(
_socket, SOL_SOCKET, SO_SNDBUF, (
char *) &sizenum, (socklen_t *) &sizelen);
538 char *serr = strerror(myerrno);
539 string err =
"Failed to get the socket send buffer size: ";
543 err +=
"unknow error occurred";
547 BESDEBUG(
"ppt",
"Tcp send buffer size is "
548 << (
unsigned long)sizenum << endl );
550 _haveSendBufferSize =
true;
551 _sendBufferSize = sizenum;
553 return _sendBufferSize;
564 struct request_info req;
565 request_init( &req, RQ_DAEMON,
"besdaemon", RQ_FILE,
569 if( STR_EQ( eval_hostname(), paranoid ) && hosts_access() )
586 strm <<
BESIndent::LMarg <<
"TcpSocket::dump - (" << (
void *)
this <<
")" << endl;
590 strm <<
BESIndent::LMarg <<
"have recv buffer size: " << _haveRecvBufferSize << endl;
591 strm <<
BESIndent::LMarg <<
"recv buffer size: " << _recvBufferSize << endl;
592 strm <<
BESIndent::LMarg <<
"have send buffer size: " << _haveSendBufferSize << endl;
593 strm <<
BESIndent::LMarg <<
"send buffer size: " << _sendBufferSize << endl;
virtual unsigned int getRecvBufferSize()
get the tcp receive buffer size using getsockopt
exception thrown if an internal error is found and is fatal to the BES
exception thrown if inernal error encountered
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual void dump(ostream &strm) const
dumps information about this object
virtual string get_file()
get the file name where the exception was thrown
virtual string get_message()
get the error message for this exception
Abstract exception class for the BES with basic string message.
virtual unsigned int getSendBufferSize()
get the tcp send buffer size using getsockopt
static ostream & LMarg(ostream &strm)
virtual int getSocketDescriptor()
void get_value(const string &s, string &val, bool &found)
Retrieve the value of a given key, if set.
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
static BESKeys * TheKeys()
virtual bool allowConnection()
is there any wrapper code for unix sockets
virtual int get_line()
get the line number where the exception was thrown