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

ArSocket_WIN.cpp

00001 /*
00002 ActivMedia Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004,2005 ActivMedia Robotics, LLC
00004 
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 ActivMedia Robotics for information about a commercial version of ARIA at 
00022 robots@activmedia.com or 
00023 ActivMedia Robotics, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
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 //  if (!ourInitialized)
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     //perror("connect");
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   /* MPL took this out since it was just overriding it with the
00256      INADDR_ANY anyways and it could cause slowdowns if a machine wasn't
00257      configured so lookups are quick
00258   if (!hostAddr(localhost, mySin.sin_addr))
00259     return(false);
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   int zero = 0;
00304   if (setsockopt(myFD, SOL_SOCKET, SO_SNDBUF, (char *)&zero, sizeof(zero)) != 0)
00305   {
00306     perror("setsockopt");
00307     ArLog::log(ArLog::Normal, "Could not set SNDBUF %d", WSAGetLastError());
00308     return(false);
00309   }
00310 
00311   if (setsockopt(myFD, SOL_SOCKET, SO_RCVBUF, (char *)&zero, sizeof(zero)) != 0)
00312   {
00313     perror("setsockopt");
00314     ArLog::log(ArLog::Normal, "Could not set SNDBUF %d", WSAGetLastError());
00315     return(false);
00316   }
00317 
00318   myType=type;
00319 */
00320   /*if (getSockName())
00321     return(true);
00322   else
00323     return(false);*/
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     //perror("connect");
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 }

Generated on Wed Oct 19 12:56:37 2005 for Aria by  doxygen 1.4.0