00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "Beowulf/SockServ.H"
00039
00040 #include "Beowulf/BeowulfOpts.H"
00041 #include "Beowulf/TCPdefs.H"
00042 #include "Component/OptionManager.H"
00043 #include "Util/log.H"
00044
00045 #include <arpa/inet.h>
00046 #include <ctype.h>
00047 #include <errno.h>
00048 #include <netdb.h>
00049 #include <netinet/in.h>
00050 #include <stdio.h>
00051 #include <string.h>
00052 #include <sys/socket.h>
00053 #include <sys/time.h>
00054 #include <sys/types.h>
00055 #include <time.h>
00056 #include <unistd.h>
00057
00058 #define MYLOGID sock
00059
00060
00061 #define SOCKSERV_UNCONFIGURED 0
00062 #define SOCKSERV_RUNNING 1
00063 #define SOCKSERV_BOGUS 2
00064
00065
00066 #define CLITIMEOUT 3000
00067
00068
00069 SockServ::SockServ(OptionManager& mgr, const std::string& descrName,
00070 const std::string& tagName) :
00071 ModelComponent(mgr, descrName, tagName),
00072 itsPort(&OPT_SockServPort, this),
00073 itsServ("SockServServiceName", this, "uscbeo"),
00074 itsServType("SockServServiceType", this, "tcp"),
00075 itsCliTout("SockServCliTout", this, 3000),
00076 itsQlen("SockServQlen", this, 256)
00077 { state = SOCKSERV_UNCONFIGURED; }
00078
00079
00080 SockServ::~SockServ()
00081 { IDLDEBUG("Terminating."); }
00082
00083
00084 void SockServ::start1()
00085 {
00086 state = SOCKSERV_BOGUS;
00087 nbclients = 0; nbnewcli = 0; nbrcli = 0; nbecli = 0; nbwcli = 0; nbnucli = 0;
00088
00089
00090 FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds);
00091
00092
00093 if (itsPort.getVal() == 0) {
00094 struct servent *sv =
00095 getservbyname(itsServ.getVal().c_str(), itsServType.getVal().c_str());
00096 if (sv == NULL)
00097 {
00098 LERROR("%s/%s not set in /etc/services -- USING DEFAULT PORT",
00099 itsServ.getVal().c_str(), itsServType.getVal().c_str());
00100 itsPort.setVal(DEFPORT);
00101 }
00102 else
00103 itsPort.setVal(ntohs(sv->s_port));
00104 LINFO("Listening to port %d...", itsPort.getVal());
00105 }
00106
00107
00108 sock = socket(AF_INET, SOCK_STREAM, 0);
00109 if (sock == -1) { PLERROR("Cannot create server socket"); return; }
00110
00111 struct sockaddr_in addr;
00112 addr.sin_family = AF_INET;
00113 addr.sin_addr.s_addr = htonl(INADDR_ANY);
00114 addr.sin_port = htons(itsPort.getVal());
00115 if (bind(sock, (struct sockaddr*)(&addr), sizeof(addr)) == -1)
00116 {
00117 IDPLFATAL("Cannot bind server socket to port %d",
00118 int(itsPort.getVal()));
00119 return;
00120 }
00121 if (listen(sock, itsQlen.getVal()) == -1)
00122 { IDPLFATAL("Cannot setup server listen queue"); return; }
00123 IDLDEBUG("Listen queue (len=%d) configured", itsQlen.getVal());
00124
00125
00126 FD_SET(sock, &readfds); FD_SET(sock, &exceptfds);
00127 state = SOCKSERV_RUNNING;
00128 }
00129
00130
00131 void SockServ::stop2()
00132 {
00133 while(nbnewcli)
00134 { IDLDEBUG("Terminating new client %d", newcli[nbnewcli-1]);
00135 close(newcli[--nbnewcli]); }
00136 while(nbclients)
00137 { IDLDEBUG("Terminating client %d", cli[nbclients-1]);
00138 close(cli[--nbclients]); }
00139 if (sock != -1)
00140 { IDLDEBUG("Terminating server"); close(sock); sock = -1; }
00141
00142
00143 FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds);
00144
00145
00146 nbclients = 0; nbnewcli = 0; nbrcli = 0; nbecli = 0; nbwcli = 0; nbnucli = 0;
00147 state = SOCKSERV_UNCONFIGURED;
00148 }
00149
00150
00151 int SockServ::check(const int stimeout, const int utimeout)
00152 {
00153 if (state != SOCKSERV_RUNNING) return SOCKSERV_BUG;
00154 struct timeval timeout; timeout.tv_sec=stimeout; timeout.tv_usec=utimeout;
00155
00156
00157 if (nbnewcli) {
00158 IDLERROR("Terminating %d new clients from previous check", nbnewcli);
00159 for (int i = 0; i < nbnewcli; i ++) disconnect(newcli[i]);
00160 nbnewcli = 0;
00161 }
00162
00163
00164 memcpy(&rfds, &readfds, sizeof(fd_set));
00165 memcpy(&wfds, &writefds, sizeof(fd_set));
00166 memcpy(&efds, &exceptfds, sizeof(fd_set));
00167 nbrcli = 0; nbwcli = 0; nbecli = 0;
00168
00169
00170
00171 int result = select(FD_SETSIZE, &rfds, &wfds, &efds, &timeout);
00172
00173
00174
00175 if (result == -1) { IDPLERROR("Error in select"); return SOCKSERV_BUG; }
00176 else if (result > 0) {
00177 int tim = time(NULL);
00178
00179
00180 if (FD_ISSET(sock, &rfds)) {
00181 FD_CLR(sock, &rfds);
00182
00183 struct sockaddr_in clientaddr;
00184 socklen_t client_addrlen = sizeof(clientaddr);
00185 int clientfd = accept(sock, (struct sockaddr *)(&clientaddr),
00186 &client_addrlen);
00187 if (clientfd == -1)
00188 IDPLDEBUG("Accept failed. Bogus client ignored.");
00189 else {
00190 cliIP[clientfd] = ntohl(clientaddr.sin_addr.s_addr);
00191 cliPort[clientfd] = ntohs(clientaddr.sin_port);
00192
00193 IDLDEBUG("Connect -- Adding %s:%hu as client %d",
00194 inet_ntoa(clientaddr.sin_addr), cliPort[clientfd], clientfd);
00195 newcli[nbnewcli++] = clientfd;
00196 }
00197 }
00198 if (FD_ISSET(sock, &efds)) {
00199 FD_CLR(sock, &efds); IDLFATAL("I got messed-up"); state = SOCKSERV_BOGUS;
00200 return SOCKSERV_BUG;
00201 }
00202
00203
00204 for (int i = 0; i < nbclients; i ++) {
00205 int fd = cli[i];
00206
00207 if (FD_ISSET(fd, &rfds))
00208 { rcli[nbrcli++] = fd; if (clitimeout[fd] != -1) clitimeout[fd]=tim; }
00209
00210 if (FD_ISSET(fd, &wfds))
00211 { wcli[nbwcli++] = fd; if (clitimeout[fd] != -1) clitimeout[fd]=tim; }
00212
00213 if (FD_ISSET(fd, &efds)) ecli[nbecli++] = fd;
00214
00215 else if (clitimeout[fd] != -1 && tim - clitimeout[fd] > CLITIMEOUT)
00216 { IDLDEBUG("Timeout on client %d", fd); ecli[nbecli++] = fd; }
00217 }
00218 } else {
00219 int tim = time(NULL);
00220 for (int i = 0; i < nbclients; i ++)
00221 if (clitimeout[cli[i]] != -1 && tim - clitimeout[cli[i]] > CLITIMEOUT)
00222 { IDLDEBUG("Timeout on client %d", cli[i]); ecli[nbecli++] = cli[i]; }
00223 }
00224
00225 if (nbnewcli == 0 && nbrcli == 0 && nbwcli == 0 && nbecli == 0)
00226 return SOCKSERV_IDLE;
00227
00228
00229 if (nbnewcli) addNewClients();
00230
00231 return SOCKSERV_ACTIV;
00232 }
00233
00234
00235 int SockServ::getNewClient()
00236 { if (nbnewcli) return newcli[--nbnewcli]; else return 0; }
00237
00238
00239 int SockServ::getReadClient()
00240 { if (nbrcli) return rcli[--nbrcli]; else return 0; }
00241
00242
00243 int SockServ::getWriteClient()
00244 { if (nbwcli) return wcli[--nbwcli]; else return 0; }
00245
00246
00247 int SockServ::getErrorClient()
00248 { if (nbecli) return ecli[--nbecli]; else return 0; }
00249
00250
00251 in_addr_t SockServ::getClientIP(const int clifd) const
00252 {
00253 for (int i = 0; i < nbclients; i ++)
00254 if (cli[i] == clifd) return cliIP[clifd];
00255 IDLERROR("Unknown client %d", clifd);
00256 return 0;
00257 }
00258
00259
00260 short int SockServ::getClientPort(const int clifd) const
00261 {
00262 for (int i = 0; i < nbclients; i ++)
00263 if (cli[i] == clifd) return cliPort[clifd];
00264 IDLERROR("Unknown client %d", clifd);
00265 return 0;
00266 }
00267
00268
00269 int SockServ::getRWClient()
00270 {
00271 if (nbwcli) return wcli[--nbwcli];
00272 if (nbrcli) return rcli[--nbrcli];
00273 return 0;
00274 }
00275
00276
00277 void SockServ::disconnect(const int client)
00278 {
00279 if (hasClient(client))
00280 {
00281 IDLDEBUG("Disconnecting client %d", client);
00282 FD_CLR(client, &readfds); FD_CLR(client, &writefds);
00283 FD_CLR(client, &exceptfds);
00284 close(client);
00285 deleteClient(client);
00286 }
00287 else
00288 IDLDEBUG("No client %d. Ignored.", client);
00289 }
00290
00291
00292 bool SockServ::addUserClient(void* data)
00293 {
00294 if (nbnucli == MAXNBNUCLI) return false;
00295 nuclidata[nbnucli++] = data; return true;
00296 }
00297
00298
00299 void* SockServ::getNewUserClient()
00300 {
00301 if (nbnucli) return nuclidata[--nbnucli];
00302 return NULL;
00303 }
00304
00305
00306 void SockServ::addNewClients()
00307 { for (int i = 0; i < nbnewcli; i ++) addClient(newcli[i]); }
00308
00309
00310 void SockServ::deleteClient(const int client)
00311 {
00312 for (int i = 0; i < nbclients; i ++)
00313 if (cli[i] == client) {
00314 for (int j = i+1; j < nbclients; j ++) cli[j-1] = cli[j];
00315 nbclients --; break;
00316 }
00317 }
00318
00319
00320 bool SockServ::hasClient(const int client)
00321 {
00322 if (client == sock)
00323 { IDLDEBUG("Called on server socket!"); return false; }
00324 for (int i = 0; i < nbclients; i ++) if (cli[i] == client) return true;
00325 return false;
00326 }
00327
00328
00329 bool SockServ::monitorRead(const int client, const bool startstop)
00330 {
00331 if (hasClient(client)) {
00332 if (startstop) FD_SET(client, &readfds); else FD_CLR(client, &readfds);
00333 return true;
00334 }
00335 return false;
00336 }
00337
00338
00339 bool SockServ::monitorWrite(const int client, const bool startstop)
00340 {
00341 if (hasClient(client)) {
00342 if (startstop) FD_SET(client, &writefds); else FD_CLR(client, &writefds);
00343 return true;
00344 }
00345 return false;
00346 }
00347
00348
00349 bool SockServ::monitorError(const int client, const bool startstop)
00350 {
00351 if (hasClient(client)) {
00352 if (startstop) FD_SET(client, &exceptfds); else FD_CLR(client, &exceptfds);
00353 return true;
00354 }
00355 return false;
00356
00357 }
00358
00359
00360 bool SockServ::noTimeOut(const int client)
00361 {
00362 if (hasClient(client)) { clitimeout[client] = -1; return true; }
00363 return false;
00364 }
00365
00366
00367 void SockServ::resetTimeOut(const int client)
00368 { if (hasClient(client)) clitimeout[client] = time(NULL); }
00369
00370
00371 void SockServ::addClient(const int client)
00372 {
00373 if (client < 0 || client >= FD_SETSIZE)
00374 { IDLDEBUG("Invalid client number %d. Ignored.", client); return; }
00375 if (hasClient(client)) IDLDEBUG("Already have client %d. Ignored.", client);
00376 else { cli[nbclients++] = client; clitimeout[client] = time(NULL); }
00377 }
00378
00379
00380 void SockServ::debug(const char *label)
00381 {
00382 printf("%s",label);
00383 for (int i = 0; i < FD_SETSIZE; i ++)
00384 if (FD_ISSET(i, &rfds) || FD_ISSET(i, &wfds) || FD_ISSET(i, &efds)) {
00385 printf("%d(", i);
00386 if (FD_ISSET(i, &rfds)) printf("R");
00387 if (FD_ISSET(i, &wfds)) printf("W");
00388 if (FD_ISSET(i, &efds)) printf("E");
00389 printf(") ");
00390 }
00391 printf("\n");
00392 }
00393
00394
00395
00396
00397
00398