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

ArSocket_LIN.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 <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   // MPL taking out this next code line from the if since it makes
00182   // everything we can't resolve try to connect to localhost
00183   // &&  !hostAddr("localhost", mySin.sin_addr))
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     //perror("connect");
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   /* 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       !hostAddr("localhost", mySin.sin_addr))
00267     return(false); */
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 }

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