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