00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "RConfig.h"
00021
00022 #include <stdio.h>
00023 #include <string.h>
00024 #include <stdlib.h>
00025 #include <unistd.h>
00026 #include <signal.h>
00027 #include <sys/socket.h>
00028 #include <netinet/in.h>
00029 #include <netinet/tcp.h>
00030 #include <arpa/inet.h>
00031 #include <netdb.h>
00032 #include <errno.h>
00033
00034 #if (defined(R__AIX) && !defined(_AIX43)) || \
00035 (defined(R__SUNGCC3) && !defined(__arch64__))
00036 # define USE_SIZE_T
00037 #elif defined(R__GLIBC) || defined(R__FBSD) || \
00038 (defined(R__SUNGCC3) && defined(__arch64__)) || \
00039 defined(R__OBSD) || defined(MAC_OS_X_VERSION_10_4) || \
00040 (defined(R__AIX) && defined(_AIX43))
00041 # define USE_SOCKLEN_T
00042 #endif
00043
00044 #include "rpdp.h"
00045 #include "rpderr.h"
00046
00047 extern int gDebug;
00048
00049 namespace ROOT {
00050
00051 extern std::string gServName[3];
00052
00053 extern ErrorHandler_t gErrSys;
00054 extern ErrorHandler_t gErrFatal;
00055
00056 static double gBytesSent = 0;
00057 static double gBytesRecv = 0;
00058
00059 static std::string gOpenhost = "????";
00060
00061 static int gTcpSrvSock;
00062 static struct sockaddr_in gTcpSrvAddr;
00063 static struct sockaddr_in gTcpCliAddr;
00064
00065 static int gSockFd = -1;
00066 static SigPipe_t gSigPipeHook = 0;
00067 extern int gParallel;
00068
00069
00070 double NetGetBytesRecv()
00071 {
00072
00073 return gBytesRecv;
00074 }
00075
00076
00077 double NetGetBytesSent()
00078 {
00079
00080 return gBytesSent;
00081 }
00082
00083
00084 void NetGetRemoteHost(std::string &OpenHost)
00085 {
00086
00087 OpenHost = gOpenhost;
00088 }
00089
00090
00091 int NetGetSockFd()
00092 {
00093
00094 return gSockFd;
00095 }
00096
00097
00098 void NetResetByteCount()
00099 {
00100
00101 gBytesRecv = 0;
00102 gBytesSent = 0;
00103 }
00104
00105
00106 void NetSetSigPipeHook(SigPipe_t Hook)
00107 {
00108
00109 gSigPipeHook = Hook;
00110 }
00111
00112
00113 static int Sendn(int sock, const void *buffer, int length)
00114 {
00115
00116
00117 if (sock < 0) return -1;
00118
00119 int n, nsent = 0;
00120 const char *buf = (const char *)buffer;
00121
00122 for (n = 0; n < length; n += nsent) {
00123 if ((nsent = send(sock, buf+n, length-n, 0)) <= 0) {
00124 Error(gErrFatal, -1, "Sendn: error (sock: %d): errno: %d",
00125 sock, GetErrno());
00126 return nsent;
00127 }
00128 }
00129
00130 gBytesSent += n;
00131
00132 return n;
00133 }
00134
00135
00136 static int Recvn(int sock, void *buffer, int length)
00137 {
00138
00139
00140
00141 if (sock < 0) return -1;
00142
00143 int n, nrecv = 0;
00144 char *buf = (char *)buffer;
00145
00146 for (n = 0; n < length; n += nrecv) {
00147 while ((nrecv = recv(sock, buf+n, length-n, 0)) == -1 && GetErrno() == EINTR)
00148 ResetErrno();
00149 if (nrecv == 0)
00150 break;
00151 if (nrecv < 0) {
00152 Error(gErrFatal,-1,"Recvn: error (sock: %d): errno: %d",sock,GetErrno());
00153 return nrecv;
00154 }
00155 }
00156
00157 gBytesRecv += n;
00158
00159 return n;
00160 }
00161
00162
00163 int NetSendRaw(const void *buf, int len)
00164 {
00165
00166
00167 if (gParallel > 0) {
00168
00169 if (NetParSend(buf, len) != len) {
00170 Error(gErrFatal,-1,"NetSendRaw: NetParSend error");
00171 }
00172
00173 } else {
00174
00175 if (gSockFd == -1) return -1;
00176 if (Sendn(gSockFd, buf, len) != len) {
00177 Error(gErrFatal,-1,"NetSendRaw: Sendn error");
00178 }
00179 }
00180
00181 return len;
00182 }
00183
00184
00185 int NetRecvRaw(void *buf, int len)
00186 {
00187
00188
00189 if (gParallel > 0) {
00190
00191 if (NetParRecv(buf, len) != len) {
00192 Error(gErrFatal,-1,"NetRecvRaw: NetParRecv error");
00193 }
00194
00195 } else {
00196
00197 if (gSockFd == -1) return -1;
00198 if (Recvn(gSockFd, buf, len) < 0) {
00199 Error(gErrFatal,-1,"NetRecvRaw: Recvn error (gSockFd: %d)",gSockFd);
00200 }
00201 }
00202
00203 return len;
00204 }
00205
00206
00207 int NetRecvRaw(int sock, void *buf, int len)
00208 {
00209
00210
00211 if (sock == -1) return -1;
00212
00213 if (Recvn(sock, buf, len) < 0) {
00214 Error(gErrFatal,-1,"NetRecvRaw: Recvn error (sock: %d, errno: %d)",sock,GetErrno());
00215 }
00216
00217 return len;
00218 }
00219
00220
00221 int NetSend(const void *buf, int len, EMessageTypes kind)
00222 {
00223
00224
00225 int hdr[2];
00226 int hlen = sizeof(int) + len;
00227 hdr[0] = htonl(hlen);
00228 hdr[1] = htonl(kind);
00229 if (NetSendRaw(hdr, sizeof(hdr)) < 0)
00230 return -1;
00231
00232 return NetSendRaw(buf, len);
00233 }
00234
00235
00236 int NetSend(int code, EMessageTypes kind)
00237 {
00238
00239
00240 int hdr[3];
00241 int hlen = sizeof(int) + sizeof(int);
00242 hdr[0] = htonl(hlen);
00243 hdr[1] = htonl(kind);
00244 hdr[2] = htonl(code);
00245 return NetSendRaw(hdr, sizeof(hdr));
00246 }
00247
00248
00249 int NetSend(const char *msg, EMessageTypes kind)
00250 {
00251
00252
00253 int len = 0;
00254
00255 if (msg)
00256 len = strlen(msg)+1;
00257
00258 return NetSend(msg, len, kind);
00259 }
00260
00261
00262 int NetSendAck()
00263 {
00264 return NetSend(0, kROOTD_ACK);
00265 }
00266
00267
00268 int NetSendError(ERootdErrors err)
00269 {
00270 return NetSend(err, kROOTD_ERR);
00271 }
00272
00273
00274 int NetRecvAllocate(void *&buf, int &len, EMessageTypes &kind)
00275 {
00276
00277
00278
00279 int hdr[2] = { 0, 0 };
00280
00281 if (NetRecvRaw(hdr, sizeof(hdr)) < 0)
00282 return -1;
00283
00284 len = ntohl(hdr[0]) - sizeof(int);
00285 if (len < 0) len = 0;
00286 kind = (EMessageTypes) ntohl(hdr[1]);
00287 if (len) {
00288 buf = new char* [len];
00289 return NetRecvRaw(buf, len);
00290 }
00291 buf = 0;
00292 return 0;
00293 }
00294
00295
00296 int NetRecv(char *msg, int len, EMessageTypes &kind)
00297 {
00298
00299
00300
00301 int mlen;
00302
00303 void *tmpbuf = 0;
00304 if (NetRecvAllocate(tmpbuf, mlen, kind) < 0)
00305 return -1;
00306 char *buf = static_cast<char *>(tmpbuf);
00307
00308 if (mlen == 0) {
00309 msg[0] = 0;
00310 return 0;
00311 } else if (mlen > len-1) {
00312 strncpy(msg, buf, len-1);
00313 msg[len-1] = 0;
00314 mlen = len;
00315 } else {
00316 strncpy(msg, buf, mlen);
00317 msg[mlen] = 0;
00318 }
00319
00320 delete [] buf;
00321
00322 return mlen - 1;
00323 }
00324
00325
00326 int NetRecv(char *msg, int max)
00327 {
00328
00329
00330 EMessageTypes kind;
00331
00332 return NetRecv((char *)msg, max, kind);
00333 }
00334
00335
00336 int NetOpen(int inetdflag, EService service)
00337 {
00338
00339
00340
00341
00342
00343
00344
00345
00346 #if defined(USE_SIZE_T)
00347 size_t clilen = sizeof(gTcpCliAddr);
00348 #elif defined(USE_SOCKLEN_T)
00349 socklen_t clilen = sizeof(gTcpCliAddr);
00350 #else
00351 int clilen = sizeof(gTcpCliAddr);
00352 #endif
00353
00354 if (inetdflag) {
00355
00356
00357
00358
00359 gSockFd = 0;
00360 if (!getpeername(gSockFd, (struct sockaddr *)&gTcpCliAddr, &clilen)) {
00361 struct hostent *hp;
00362 if ((hp = gethostbyaddr((const char *)&gTcpCliAddr.sin_addr,
00363 sizeof(gTcpCliAddr.sin_addr), AF_INET)))
00364 gOpenhost = std::string(hp->h_name);
00365 else {
00366 struct in_addr *host_addr = (struct in_addr*)&gTcpCliAddr.sin_addr;
00367 gOpenhost = std::string(inet_ntoa(*host_addr));
00368 }
00369 }
00370
00371
00372 if (gDebug > 1)
00373 ErrorInfo("NetOpen: fired by inetd: connection from host %s"
00374 " via socket %d", gOpenhost.data(),gSockFd);
00375
00376
00377 NetSetOptions(service,gSockFd, 65535);
00378
00379 return 0;
00380 }
00381
00382
00383
00384
00385
00386
00387
00388
00389 again:
00390 int newsock = accept(gTcpSrvSock, (struct sockaddr *)&gTcpCliAddr, &clilen);
00391 if (newsock < 0) {
00392 if (GetErrno() == EINTR) {
00393 ResetErrno();
00394 goto again;
00395 }
00396 Error(gErrSys,kErrFatal, "NetOpen: accept error (errno: %d) ... socket %d",
00397 GetErrno(),gTcpSrvSock);
00398 return 0;
00399 }
00400
00401 struct hostent *hp;
00402 if ((hp = gethostbyaddr((const char *)&gTcpCliAddr.sin_addr,
00403 sizeof(gTcpCliAddr.sin_addr), AF_INET)))
00404 gOpenhost = std::string(hp->h_name);
00405 else {
00406 struct in_addr *host_addr = (struct in_addr*)&gTcpCliAddr.sin_addr;
00407 gOpenhost = std::string(inet_ntoa(*host_addr));
00408 }
00409
00410
00411
00412
00413
00414
00415 int childpid;
00416 if ((childpid = fork()) < 0)
00417 Error(gErrSys,kErrFatal, "NetOpen: server can't fork");
00418 else if (childpid > 0) {
00419 close(newsock);
00420 return childpid;
00421 }
00422
00423
00424
00425
00426
00427
00428
00429 close(gTcpSrvSock);
00430
00431 gSockFd = newsock;
00432
00433
00434 if (gDebug > 1)
00435 ErrorInfo("NetOpen: concurrent server: connection from host %s"
00436 " via socket %d", gOpenhost.data(), gSockFd);
00437
00438 return 0;
00439 }
00440
00441
00442 void NetClose()
00443 {
00444
00445
00446 if (gParallel > 0) {
00447
00448 NetParClose();
00449
00450 } else {
00451
00452 close(gSockFd);
00453 if (gDebug > 0)
00454 ErrorInfo("NetClose: host = %s, fd = %d",
00455 gOpenhost.data(), gSockFd);
00456 gSockFd = -1;
00457 }
00458 }
00459
00460
00461 int NetInit(EService servtype, int port1, int port2, int tcpwindowsize)
00462 {
00463
00464
00465
00466
00467
00468
00469
00470 std::string service = gServName[servtype];
00471
00472 if (port1 <= 0) {
00473 if (service.length()) {
00474 struct servent *sp = getservbyname(service.data(), "tcp");
00475 if (!sp) {
00476 if (servtype == kROOTD) {
00477 port1 = 1094;
00478 } else if (servtype == kPROOFD) {
00479 port1 = 1093;
00480 } else {
00481 fprintf(stderr,"NetInit: unknown service: %s/tcp\n", service.data());
00482 Error(gErrFatal, kErrFatal,
00483 "NetInit: unknown service: %s/tcp", service.data());
00484 }
00485 } else {
00486 port1 = ntohs(sp->s_port);
00487 }
00488 port2 += port1;
00489 } else {
00490 fprintf(stderr, "NetInit: must specify either service or port\n");
00491 Error(gErrFatal,kErrFatal,
00492 "NetInit: must specify either service or port");
00493 }
00494 }
00495
00496
00497
00498
00499 if ((gTcpSrvSock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
00500 fprintf(stderr, "NetInit: can't create socket\n");
00501 Error(gErrSys,kErrFatal, "NetInit: can't create socket");
00502 return gTcpSrvSock;
00503 }
00504
00505 int val = 1;
00506 if (setsockopt(gTcpSrvSock, SOL_SOCKET, SO_REUSEADDR, (char*) &val,
00507 sizeof(val)) == -1) {
00508 fprintf(stderr, "NetInit: can't set SO_REUSEADDR socket option\n");
00509 Error(gErrSys, kErrFatal, "NetInit: can't set SO_REUSEADDR socket option");
00510 }
00511
00512
00513 NetSetOptions(kROOTD,gTcpSrvSock, tcpwindowsize);
00514
00515 memset(&gTcpSrvAddr, 0, sizeof(gTcpSrvAddr));
00516 gTcpSrvAddr.sin_family = AF_INET;
00517 gTcpSrvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
00518
00519 int port;
00520 for (port= port1; port <= port2; port++) {
00521 gTcpSrvAddr.sin_port = htons(port);
00522 if (bind(gTcpSrvSock, (struct sockaddr *) &gTcpSrvAddr,
00523 sizeof(gTcpSrvAddr)) == 0) break;
00524 }
00525
00526 if (port > port2) {
00527 fprintf(stderr, "NetInit: can't bind local address to ports %d-%d\n", port1, port2);
00528 Error(gErrSys, kErrFatal, "NetInit: can't bind local address to ports %d-%d", port1, port2);
00529 }
00530
00531 printf("ROOTD_PORT=%d\n", port);
00532 port1 = port;
00533
00534
00535
00536
00537
00538 if (listen(gTcpSrvSock, 5)==-1) {
00539 ErrorInfo("NetInit: listen: error (errno: %d)",GetErrno());
00540 }
00541
00542 if (gDebug > 0)
00543 ErrorInfo("NetInit: socket %d listening on port %d", gTcpSrvSock,
00544 ntohs(gTcpSrvAddr.sin_port));
00545
00546 return gTcpSrvSock;
00547 }
00548
00549
00550 void NetSetOptions(EService serv, int sock, int tcpwindowsize)
00551 {
00552
00553
00554 int val = 1;
00555
00556 if (serv == kROOTD) {
00557 if (!setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,(char *)&val,sizeof(val)))
00558 if (gDebug > 0)
00559 ErrorInfo("NetSetOptions: set TCP_NODELAY");
00560 if (!setsockopt(sock,SOL_SOCKET,SO_KEEPALIVE,(char *)&val,sizeof(val))) {
00561 if (gDebug > 0)
00562 ErrorInfo("NetSetOptions: set SO_KEEPALIVE");
00563 if (gSigPipeHook != 0)
00564 signal(SIGPIPE, (*gSigPipeHook));
00565 }
00566 }
00567
00568 val = tcpwindowsize;
00569 if (!setsockopt(sock,SOL_SOCKET,SO_SNDBUF,(char *)&val,sizeof(val)))
00570 if (gDebug > 0)
00571 ErrorInfo("NetSetOptions: set SO_SNDBUF %d", val);
00572 if (!setsockopt(sock,SOL_SOCKET,SO_RCVBUF,(char *)&val,sizeof(val)))
00573 if (gDebug > 0)
00574 ErrorInfo("NetSetOptions: set SO_RCVBUF %d", val);
00575
00576 if (gDebug > 0) {
00577 #if defined(USE_SIZE_T)
00578 size_t optlen = sizeof(val);
00579 #elif defined(USE_SOCKLEN_T)
00580 socklen_t optlen = sizeof(val);
00581 #else
00582 int optlen = sizeof(val);
00583 #endif
00584 if (serv == kROOTD) {
00585 getsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&val, &optlen);
00586 ErrorInfo("NetSetOptions: get TCP_NODELAY: %d", val);
00587 getsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char*)&val, &optlen);
00588 ErrorInfo("NetSetOptions: get SO_KEEPALIVE: %d", val);
00589 }
00590 getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&val, &optlen);
00591 ErrorInfo("NetSetOptions: get SO_SNDBUF: %d", val);
00592 getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&val, &optlen);
00593 ErrorInfo("NetSetOptions: get SO_RCVBUF: %d", val);
00594 }
00595 }
00596
00597 }