Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages | Examples

ArSocket_WIN.cpp

00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004, 2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006, 2007 MobileRobots Inc.
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
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 #include <sys/socket.h>
00036 #include <netinet/ip.h>
00037 #include <netinet/tcp.h>
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 //  if (!ourInitialized)
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     //perror("connect");
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   /* MPL this is useless withw hat I Took out below
00253   if (gethostname(localhost, sizeof(localhost)) == 1)
00254   {
00255     myErrorStr="Failure to locate localhost";
00256     perror("gethostname");
00257     return(false);
00258   }
00259   */
00260 
00261   memset(&mySin, 0, sizeof(mySin));
00262   /* MPL took this out since it was just overriding it with the
00263      INADDR_ANY anyways and it could cause slowdowns if a machine wasn't
00264      configured so lookups are quick
00265   if (!hostAddr(localhost, mySin.sin_addr))
00266     return(false);
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       //printf("Opening on %s\n", openOnIP);
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   int zero = 0;
00327   if (setsockopt(myFD, SOL_SOCKET, SO_SNDBUF, (char *)&zero, sizeof(zero)) != 0)
00328   {
00329     perror("setsockopt");
00330     ArLog::log(ArLog::Normal, "Could not set SNDBUF %d", WSAGetLastError());
00331     return(false);
00332   }
00333 
00334   if (setsockopt(myFD, SOL_SOCKET, SO_RCVBUF, (char *)&zero, sizeof(zero)) != 0)
00335   {
00336     perror("setsockopt");
00337     ArLog::log(ArLog::Normal, "Could not set SNDBUF %d", WSAGetLastError());
00338     return(false);
00339   }
00340 
00341   myType=type;
00342 */
00343   /*if (getSockName())
00344     return(true);
00345   else
00346     return(false);*/
00347   return(true);
00348 }
00349 
00350 AREXPORT bool ArSocket::findValidPort(int startPort, const char *openOnIP)
00351 {
00352   char localhost[MAXGETHOSTSTRUCT];
00353 
00354   /*
00355   if (gethostname(localhost, sizeof(localhost)) == 1)
00356   {
00357     myErrorStr="Failure to locate localhost";
00358     perror("gethostname");
00359     return(false);
00360   }
00361   */
00362   for (int i=0; i+startPort < 65000; ++i)
00363   {
00364     memset(&mySin, 0, sizeof(mySin));
00365     /*
00366     if (!hostAddr(localhost, mySin.sin_addr))
00367       return(false);
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     //printf("Opening on %s\n", openOnIP);
00381       }
00382     }
00383     else
00384     {
00385       mySin.sin_addr.s_addr=htonl(INADDR_ANY);
00386     }
00387 
00388     mySin.sin_family=AF_INET;
00389     //mySin.sin_addr.s_addr=htonl(INADDR_ANY);
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     //perror("connect");
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 

Generated on Tue Feb 20 10:51:41 2007 for Aria by  doxygen 1.4.0