bes  Updated for version 3.20.8
SocketListener.cc
1 // SocketListener.cc
2 
3 // This file is part of bes, A C++ back-end server implementation framework
4 // for the OPeNDAP Data Access Protocol.
5 
6 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research
7 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact University Corporation for Atmospheric Research at
24 // 3080 Center Green Drive, Boulder, CO 80301
25 
26 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
27 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
28 //
29 // Authors:
30 // pwest Patrick West <pwest@ucar.edu>
31 // jgarcia Jose Garcia <jgarcia@ucar.edu>
32 
33 #include "config.h"
34 
35 #include <string>
36 #include <ctype.h>
37 #include <cstring>
38 #include <cerrno>
39 
40 #include <sys/types.h>
41 #include <sys/socket.h>
42 
43 // Added for CentOS 6 jhrg
44 #include <sys/wait.h>
45 
46 // Added for OSX 10.9 jhrg
47 #include <sys/select.h>
48 
49 #include "SocketListener.h"
50 #include "BESInternalError.h"
51 #include "Socket.h"
52 #include "SocketConfig.h"
53 #include "BESDebug.h"
54 
55 //extern volatile int bes_num_children; // defined in PPTServer.cc jhrg 3/5/14
56 //extern string bes_exit_message(int cpid, int stat);
57 
58 using namespace std;
59 
60 #define MODULE "ppt"
61 #define prolog string("SocketListener::").append(__func__).append("() - ")
62 
63 SocketListener::SocketListener() :
64  _accepting(false)
65 {
66 }
67 
68 SocketListener::~SocketListener()
69 {
70 }
71 
72 void SocketListener::listen(Socket *s)
73 {
74  if (_accepting)
75  throw BESInternalError("Already accepting connections, no more sockets can be added", __FILE__, __LINE__);
76 
77  if (s && !s->isConnected() && !s->isListening()) {
78  s->listen();
79  _socket_list[s->getSocketDescriptor()] = s;
80  }
81  else {
82  if (!s)
83  throw BESInternalError("null socket passed", __FILE__, __LINE__);
84  else if (s->isConnected())
85  throw BESInternalError("socket already connected, cannot listen", __FILE__, __LINE__);
86  else if (s->isListening())
87  throw BESInternalError("socket already listening", __FILE__, __LINE__);
88  }
89 }
90 
92 Socket *
94 {
95  BESDEBUG(MODULE, prolog << "START" << endl);
96 
97  fd_set read_fd;
98  FD_ZERO(&read_fd);
99 
100  int maxfd = 0;
101  for (Socket_citer i = _socket_list.begin(), e = _socket_list.end(); i != e; i++) {
102  Socket *s_ptr = (*i).second;
103  if (s_ptr->getSocketDescriptor() > maxfd) maxfd = s_ptr->getSocketDescriptor();
104  FD_SET(s_ptr->getSocketDescriptor(), &read_fd);
105  }
106 
107  struct timeval timeout;
108  timeout.tv_sec = 120;
109  timeout.tv_usec = 0;
110  int status = select(maxfd + 1, &read_fd, (fd_set*) NULL, (fd_set*) NULL, &timeout);
111  if (status < 0) {
112  // left over and not needed. jhrg 10/14/15
113  // while (select(maxfd + 1, &read_fd, (fd_set*) NULL, (fd_set*) NULL, &timeout) < 0) {
114  switch (errno) {
115  case EAGAIN: // rerun select on interrupted calls, ...
116  BESDEBUG(MODULE, prolog << "select() encountered EAGAIN" << endl);
117  // This case and the one below used to just 'break' so that the select call
118  // above would run again. I modified it to return null so that the caller could
119  // do other things, like process the results of signals.
120  return 0;
121 
122  case EINTR:
123  BESDEBUG(MODULE, prolog << "select() encountered EINTR" << endl);
124  return 0;
125 
126  default:
127  throw BESInternalError(string("select(): ") + strerror(errno), __FILE__, __LINE__);
128  }
129  }
130 
131  BESDEBUG(MODULE, prolog << "select() completed without error." << endl);
132 
133  for (Socket_citer i = _socket_list.begin(), e = _socket_list.end(); i != e; i++) {
134  Socket *s_ptr = (*i).second;
135  if (FD_ISSET( s_ptr->getSocketDescriptor(), &read_fd )) {
136  struct sockaddr from;
137  socklen_t len_from = sizeof(from);
138 
139  BESDEBUG(MODULE, prolog << "Attempting to accept on "<< s_ptr->getIp() << ":"
140  << s_ptr->getPort() << endl);
141 
142  int msgsock;
143  while ((msgsock = ::accept(s_ptr->getSocketDescriptor(), &from, &len_from)) < 0) {
144  if (errno == EINTR) {
145  continue;
146  }
147  else {
148  throw BESInternalError(string("accept: ") + strerror(errno), __FILE__, __LINE__);
149  }
150  }
151 
152  BESDEBUG(MODULE, prolog << "END (returning new Socket)" << endl);
153  return s_ptr->newSocket(msgsock, (struct sockaddr *) &from);
154  }
155  }
156 
157  BESDEBUG(MODULE, prolog << "END (returning 0)" << endl);
158  return 0;
159 }
160 
167 void SocketListener::dump(ostream &strm) const
168 {
169  strm << BESIndent::LMarg << "SocketListener::dump - (" << (void *) this << ")" << endl;
170  BESIndent::Indent();
171  if (_socket_list.size()) {
172  strm << BESIndent::LMarg << "registered sockets:" << endl;
173  Socket_citer i = _socket_list.begin();
174  Socket_citer ie = _socket_list.end();
175  for (; i != ie; i++) {
176  strm << BESIndent::LMarg << "socket: " << (*i).first;
177  Socket *s_ptr = (*i).second;
178  s_ptr->dump(strm);
179  }
180  }
181  else {
182  strm << BESIndent::LMarg << "registered sockets: none" << endl;
183  }
184  BESIndent::UnIndent();
185 }
186 
exception thrown if internal error encountered
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual Socket * accept()
Definition: Socket.h:42
virtual void dump(std::ostream &strm) const
dumps information about this object
Definition: Socket.cc:137