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

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

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