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 #include "ArExport.h"
00027 #include "ariaOSDef.h"
00028 #include "ArSocket.h"
00029 #include "ArLog.h"
00030 #include <errno.h>
00031 #include <stdio.h>
00032 #include <netdb.h>
00033 #include <arpa/inet.h>
00034 #include "ArFunctor.h"
00035 #include <sys/socket.h>
00036 #include <netinet/ip.h>
00037 #include <netinet/tcp.h>
00038
00040 bool ArSocket::ourInitialized=true;
00041
00042
00052 bool ArSocket::init()
00053 {
00054 return(true);
00055 }
00056
00066 void ArSocket::shutdown()
00067 {
00068 }
00069
00070 ArSocket::ArSocket() :
00071 myType(Unknown),
00072 myError(NoErr),
00073 myErrorStr(),
00074 myDoClose(true),
00075 myFD(-1),
00076 myNonBlocking(false),
00077 mySin()
00078 {
00079 internalInit();
00080 }
00081
00088 ArSocket::ArSocket(const char *host, int port, Type type) :
00089 myType(type),
00090 myError(NoErr),
00091 myErrorStr(),
00092 myDoClose(true),
00093 myFD(-1),
00094 myNonBlocking(false),
00095 mySin()
00096 {
00097 internalInit();
00098 connect(host, port, type);
00099 }
00100
00107 ArSocket::ArSocket(int port, bool doClose, Type type) :
00108 myType(type),
00109 myError(NoErr),
00110 myErrorStr(),
00111 myDoClose(doClose),
00112 myFD(-1),
00113 myNonBlocking(false),
00114 mySin()
00115 {
00116 internalInit();
00117 open(port, type);
00118 }
00119
00120 ArSocket::~ArSocket()
00121 {
00122 close();
00123 }
00124
00125 bool ArSocket::hostAddr(const char *host, struct in_addr &addr)
00126 {
00127 struct hostent *hp;
00128 if (!(hp=gethostbyname(host)))
00129 {
00130 perror("gethostbyname");
00131 memset(&addr, 0, sizeof(in_addr));
00132 return(false);
00133 }
00134 else
00135 {
00136 bcopy(hp->h_addr, &addr, hp->h_length);
00137 return(true);
00138 }
00139 }
00140
00141 bool ArSocket::addrHost(struct in_addr &addr, char *host)
00142 {
00143 struct hostent *hp;
00144
00145 hp=gethostbyaddr((char*)&addr.s_addr, sizeof(addr.s_addr), AF_INET);
00146 if (hp)
00147 strcpy(host, hp->h_name);
00148 else
00149 strcpy(host, inet_ntoa(addr));
00150
00151 return(true);
00152 }
00153
00154 std::string ArSocket::getHostName()
00155 {
00156 char localhost[maxHostNameLen()];
00157
00158 if (gethostname(localhost, sizeof(localhost)) == 1)
00159 return("");
00160 else
00161 return(localhost);
00162 }
00163
00164 bool ArSocket::connect(const char *host, int port, Type type)
00165 {
00166 char localhost[maxHostNameLen()];
00167
00168 if (!host)
00169 {
00170 if (gethostname(localhost, sizeof(localhost)) == 1)
00171 {
00172 myError=ConBadHost;
00173 myErrorStr="Failure to locate host '";
00174 myErrorStr+=localhost;
00175 myErrorStr+="'";
00176 perror("gethostname");
00177 return(false);
00178 }
00179 host=localhost;
00180 }
00181
00182 bzero(&mySin, sizeof(mySin));
00183
00184
00185
00186 if (!hostAddr(host, mySin.sin_addr))
00187 return(false);
00188 setIPString();
00189 mySin.sin_family=AF_INET;
00190 mySin.sin_port=hostToNetOrder(port);
00191
00192 if ((type == TCP) && ((myFD=socket(AF_INET, SOCK_STREAM, 0)) < 0))
00193 {
00194 myError=NetFail;
00195 myErrorStr="Failure to make TCP socket";
00196 perror("socket");
00197 return(false);
00198 }
00199 else if ((type == UDP) && ((myFD=socket(AF_INET, SOCK_DGRAM, 0)) < 0))
00200 {
00201 myError=NetFail;
00202 myErrorStr="Failure to make UDP socket";
00203 perror("socket");
00204 return(false);
00205 }
00206
00207 myType=type;
00208
00209 if (::connect(myFD, (struct sockaddr *)&mySin,
00210 sizeof(struct sockaddr_in)) < 0)
00211 {
00212 myErrorStr="Failure to connect socket";
00213 switch (errno)
00214 {
00215 case ECONNREFUSED:
00216 myError=ConRefused;
00217 myErrorStr+="; Connection refused";
00218 break;
00219 case ENETUNREACH:
00220 myError=ConNoRoute;
00221 myErrorStr+="; No route to host";
00222 break;
00223 default:
00224 myError=NetFail;
00225 break;
00226 }
00227
00228 ::close(myFD);
00229 myFD = -1;
00230 return(false);
00231 }
00232
00233 return(true);
00234 }
00235
00236 bool ArSocket::open(int port, Type type, const char *openOnIP)
00237 {
00238 int ret;
00239 char localhost[maxHostNameLen()];
00240
00241 if ((type == TCP) && ((myFD=socket(AF_INET, SOCK_STREAM, 0)) < 0))
00242 {
00243 myErrorStr="Failure to make TCP socket";
00244 perror("socket");
00245 return(false);
00246 }
00247 else if ((type == UDP) && ((myFD=socket(AF_INET, SOCK_DGRAM, 0)) < 0))
00248 {
00249 myErrorStr="Failure to make UDP socket";
00250 perror("socket");
00251 return(false);
00252 }
00253
00254 myType=type;
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 bzero(&mySin, sizeof(mySin));
00265
00266
00267
00268
00269
00270
00271
00272 if (openOnIP != NULL)
00273 {
00274
00275 if (!hostAddr(openOnIP, mySin.sin_addr))
00276 {
00277 ArLog::log(ArLog::Normal, "Couldn't find ip of %s to open on", openOnIP);
00278 return(false);
00279 }
00280 else
00281 {
00282
00283 }
00284 }
00285 else
00286 {
00287 mySin.sin_addr.s_addr=htonl(INADDR_ANY);
00288 }
00289
00290 setIPString();
00291 mySin.sin_family=AF_INET;
00292 mySin.sin_port=hostToNetOrder(port);
00293
00294 if ((ret=bind(myFD, (struct sockaddr *)&mySin, sizeof(mySin))) < 0)
00295 {
00296 myErrorStr="Failure to bind socket to port ";
00297 sprintf(localhost, "%d", port);
00298 myErrorStr+=localhost;
00299 perror("socket");
00300 return(false);
00301 }
00302
00303 if ((type == TCP) && (listen(myFD, 5) < 0))
00304 {
00305 myErrorStr="Failure to listen on socket";
00306 perror("listen");
00307 return(false);
00308 }
00309
00310 return(true);
00311 }
00312
00313 bool ArSocket::create(Type type)
00314 {
00315 if ((type == TCP) && ((myFD=socket(AF_INET, SOCK_STREAM, 0)) < 0))
00316 {
00317 myErrorStr="Failure to make TCP socket";
00318 perror("socket");
00319 return(false);
00320 }
00321 else if ((type == UDP) && ((myFD=socket(AF_INET, SOCK_DGRAM, 0)) < 0))
00322 {
00323 myErrorStr="Failure to make UDP socket";
00324 perror("socket");
00325 return(false);
00326 }
00327
00328 myType=type;
00329
00330 if (getSockName())
00331 return(true);
00332 else
00333 return(false);
00334 }
00335
00336 bool ArSocket::findValidPort(int startPort, const char *openOnIP)
00337 {
00338 char localhost[maxHostNameLen()];
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 for (int i=0; i+startPort < 65000; ++i)
00350 {
00351 bzero(&mySin, sizeof(mySin));
00352
00353
00354
00355
00356
00357 setIPString();
00358
00359 if (openOnIP != NULL)
00360 {
00361
00362 if (!hostAddr(openOnIP, mySin.sin_addr))
00363 {
00364 ArLog::log(ArLog::Normal, "Couldn't find ip of %s to open udp on", openOnIP);
00365 return(false);
00366 }
00367 else
00368 {
00369
00370 }
00371 }
00372 else
00373 {
00374 mySin.sin_addr.s_addr=htonl(INADDR_ANY);
00375 }
00376
00377 mySin.sin_family=AF_INET;
00378 mySin.sin_port=hostToNetOrder(startPort+i);
00379
00380 if (bind(myFD, (struct sockaddr *)&mySin, sizeof(mySin)) == 0)
00381 break;
00382 }
00383
00384 return(true);
00385 }
00386
00387 bool ArSocket::connectTo(const char *host, int port)
00388 {
00389 char localhost[maxHostNameLen()];
00390
00391 if (myFD < 0)
00392 return(false);
00393
00394 if (!host)
00395 {
00396 if (gethostname(localhost, sizeof(localhost)) == 1)
00397 {
00398 myErrorStr="Failure to locate host '";
00399 myErrorStr+=localhost;
00400 myErrorStr+="'";
00401 perror("gethostname");
00402 return(false);
00403 }
00404 host=localhost;
00405 }
00406
00407 bzero(&mySin, sizeof(mySin));
00408 if (!hostAddr(host, mySin.sin_addr))
00409 return(false);
00410 setIPString();
00411 mySin.sin_family=AF_INET;
00412 mySin.sin_port=hostToNetOrder(port);
00413
00414 return(connectTo(&mySin));
00415 }
00416
00417 bool ArSocket::connectTo(struct sockaddr_in *sin)
00418 {
00419 if (::connect(myFD, (struct sockaddr *)sin,
00420 sizeof(struct sockaddr_in)) < 0)
00421 {
00422 myErrorStr="Failure to connect socket";
00423 perror("connect");
00424 return(0);
00425 }
00426
00427 return(1);
00428 }
00429
00430
00431 bool ArSocket::close()
00432 {
00433 if (myFD != -1)
00434 ArLog::log(ArLog::Verbose, "Closing socket");
00435 if (myCloseFunctor != NULL)
00436 myCloseFunctor->invoke();
00437 if (myDoClose && ::close(myFD))
00438 {
00439 myFD=-1;
00440 return(false);
00441 }
00442 else
00443 {
00444 myFD=-1;
00445 return(true);
00446 }
00447 }
00448
00449 bool ArSocket::setLinger(int time)
00450 {
00451 struct linger lin;
00452
00453 if (time)
00454 {
00455 lin.l_onoff=1;
00456 lin.l_linger=time;
00457 }
00458 else
00459 {
00460 lin.l_onoff=0;
00461 lin.l_linger=time;
00462 }
00463
00464 if (setsockopt(myFD, SOL_SOCKET, SO_LINGER, &lin, sizeof(lin)) != 0)
00465 {
00466 myErrorStr="Failure to setsockopt LINGER";
00467 perror("setsockopt");
00468 return(false);
00469 }
00470 else
00471 return(true);
00472 }
00473
00474 bool ArSocket::setBroadcast()
00475 {
00476 if (setsockopt(myFD, SOL_SOCKET, SO_BROADCAST, NULL, 0) != 0)
00477 {
00478 myErrorStr="Failure to setsockopt BROADCAST";
00479 perror("setsockopt");
00480 return(false);
00481 }
00482 else
00483 return(true);
00484 }
00485
00486 bool ArSocket::setReuseAddress()
00487 {
00488 int opt=1;
00489
00490 if (setsockopt(myFD, SOL_SOCKET, SO_REUSEADDR,
00491 (char*)&opt, sizeof(opt)) != 0)
00492 {
00493 myErrorStr="Failure to setsockopt REUSEADDR";
00494 perror("setsockopt");
00495 return(false);
00496 }
00497 else
00498 return(true);
00499 }
00500
00501 bool ArSocket::setNonBlock()
00502 {
00503 if (fcntl(myFD, F_SETFL, O_NONBLOCK) != 0)
00504 {
00505 myErrorStr="Failure to fcntl O_NONBLOCK";
00506 perror("fcntl");
00507 return(false);
00508 }
00509 else
00510 {
00511 myNonBlocking = true;
00512 return(true);
00513 }
00514 }
00515
00520 bool ArSocket::copy(int fd, bool doclose)
00521 {
00522 socklen_t len;
00523
00524 myFD=fd;
00525 myDoClose=doclose;
00526 myType=Unknown;
00527
00528 len=sizeof(struct sockaddr_in);
00529 if (getsockname(myFD, (struct sockaddr*)&mySin, &len))
00530 {
00531 myErrorStr="Failed to getsockname on fd ";
00532 perror("setsockopt");
00533 return(false);
00534 }
00535 else
00536 return(true);
00537 }
00538
00546 bool ArSocket::accept(ArSocket *sock)
00547 {
00548 socklen_t len;
00549 unsigned char *bytes;
00550
00551 len=sizeof(struct sockaddr_in);
00552 sock->myFD=::accept(myFD, (struct sockaddr*)&(sock->mySin), &len);
00553 sock->myType=myType;
00554 bytes = (unsigned char *)sock->inAddr();
00555 sprintf(sock->myIPString, "%d.%d.%d.%d", bytes[0], bytes[1], bytes[2],
00556 bytes[3]);
00557 if ((sock->myFD < 0 && !myNonBlocking) ||
00558 (sock->myFD < 0 && errno != EWOULDBLOCK && myNonBlocking))
00559 {
00560 myErrorStr="Failed to accept on socket";
00561 perror("accept");
00562 return(false);
00563 }
00564
00565 return(true);
00566 }
00567
00568 void ArSocket::inToA(struct in_addr *addr, char *buff)
00569 {
00570 strcpy(buff, inet_ntoa(*addr));
00571 }
00572
00573 bool ArSocket::getSockName()
00574 {
00575 socklen_t size;
00576
00577 if (myFD < 0)
00578 {
00579 myErrorStr="Trying to get socket name on an unopened socket";
00580 printf(myErrorStr.c_str());
00581 return(false);
00582 }
00583
00584 size=sizeof(mySin);
00585 if (getsockname(myFD, (struct sockaddr *)&mySin, &size) != 0)
00586 {
00587 myErrorStr="Error getting socket name";
00588 perror(myErrorStr.c_str());
00589 return(false);
00590 }
00591
00592 return(true);
00593 }
00594
00595 unsigned int ArSocket::hostToNetOrder(int i)
00596 {
00597 return(htons(i));
00598 }
00599
00600 unsigned int ArSocket::netToHostOrder(int i)
00601 {
00602 return(ntohs(i));
00603 }
00604
00613 bool ArSocket::setNoDelay(bool flag)
00614 {
00615 if(myType != TCP) return false;
00616 int f = flag?1:0;
00617 int r = setsockopt(myFD, IPPROTO_TCP, TCP_NODELAY, (char*)&f, sizeof(f));
00618 return (r != -1);
00619 }
00620