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