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