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

ArNetPacketReceiverTcp.cpp

Go to the documentation of this file.
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 "Aria.h"
00027 #include "ArExport.h"
00028 #include "ArNetPacketReceiverTcp.h"
00029 #ifndef WIN32
00030 #include "errno.h"
00031 #endif
00032 
00033 AREXPORT ArNetPacketReceiverTcp::ArNetPacketReceiverTcp()
00034 {
00035   mySocket = NULL;
00036   myProcessPacketCB = NULL;
00037   mySync1 = 0xF;
00038   mySync2 = 0xC;
00039   myState = STATE_SYNC1;
00040   myQuiet = false;
00041 }
00042 
00043 AREXPORT ArNetPacketReceiverTcp::~ArNetPacketReceiverTcp()
00044 {
00045 
00046 }
00047 
00054 AREXPORT void ArNetPacketReceiverTcp::setSocket(ArSocket *socket)
00055 {
00056   mySocket = socket;
00057 }
00058 
00063 AREXPORT ArSocket *ArNetPacketReceiverTcp::getSocket(void)
00064 {
00065   return mySocket;
00066 }
00067 
00077 AREXPORT bool ArNetPacketReceiverTcp::readData(void)
00078 {
00079   Ret ret;
00080 
00081   while (1)
00082   {
00083     ret = readPacket(100);
00084     if (ret == RET_TIMED_OUT)
00085     {
00086       if (!myQuiet)
00087         ArLog::log(ArLog::Terse, "ReadTcp timed out");
00088       return true;
00089     }
00090     else if (ret == RET_CONN_CLOSED)
00091     {
00092       unsigned char *bytes = (unsigned char *)mySocket->inAddr();
00093       if (!myQuiet)
00094         ArLog::log(ArLog::Terse, "Connection to %d.%d.%d.%d closed",
00095                    bytes[0], bytes[1], bytes[2], bytes[3]);
00096       return false;
00097     }
00098     else if (ret == RET_FAILED_READ)
00099     {
00100       // if neither of these true's trap it the false is returned cause it was some bad error
00101 #ifdef WIN32
00102       if (WSAGetLastError() == WSAEWOULDBLOCK)
00103         return true;
00104       else if (!myQuiet)
00105         ArLog::log(ArLog::Terse, "Failed on read TCP, error %d", WSAGetLastError());
00106 #endif
00107 #ifndef WIN32
00108       if (errno == EAGAIN)
00109         return true;
00110       else if (!myQuiet)
00111         ArLog::log(ArLog::Terse, "Failed on read TCP, error %d", errno);
00112 #endif
00113       if (!myQuiet)
00114         ArLog::log(ArLog::Terse, "Failed on the tcp read");
00115       return false;
00116     }
00117     else if (ret == RET_BAD_PACKET)
00118     {
00119       // well... there was a bad checksum, keep going
00120     }
00121     else if (ret == RET_GOT_PACKET)
00122     {
00123       if (myProcessPacketCB != NULL)
00124       {
00125         //printf("Got in a packet of %d\n", myPacket.getCommand());
00126         myPacket.setPacketSource(ArNetPacket::TCP);
00127         myProcessPacketCB->invoke(&myPacket);
00128       }
00129     }
00130     else
00131     {
00132       if (!myQuiet)
00133         ArLog::log(ArLog::Terse, "ArNetPacketReceiverTcp: bad Ret value %d", ret);
00134       return false;
00135     }
00136   }
00137 }
00138 
00139 AREXPORT ArNetPacketReceiverTcp::Ret ArNetPacketReceiverTcp::readPacket(int msWait)
00140 {
00141   long timeToRunFor;
00142   ArTime timeDone;
00143   int numRead;
00144   bool printing = true;
00145   int ret;
00146   unsigned char c;
00147   timeDone.setToNow();
00148   timeDone.addMSec(msWait);
00149 
00150   //printf("Read packet!\n");
00151   do
00152   {
00153     timeToRunFor = timeDone.mSecTo();
00154     if (timeToRunFor < 0)
00155       timeToRunFor = 0;
00156 
00157     if (myState != STATE_ACQUIRE_DATA)
00158     {
00159       c = 0;
00160       if ((ret = mySocket->read((char *)&c, 1, 0/*timeToRunFor*/)) == -1) 
00161       {
00162         if (myState == STATE_SYNC1)
00163         {
00164           return RET_FAILED_READ;
00165         }
00166         else
00167         {
00168           //ArUtil::sleep(1);
00169           continue;
00170         }
00171       }
00172       else if (ret == 0)
00173       {
00174         return RET_CONN_CLOSED;
00175       }
00176     }
00177     
00178     /*
00179     if (myState != STATE_ACQUIRE_DATA)
00180     {
00181       printf("%d", myState);
00182       printf(" %d\n", c);
00183     }
00184     */
00185     //else
00186     //{
00187     //printf("\n");
00188     //}
00189     switch (myState) {
00190     case STATE_SYNC1:
00191       if (c == mySync1) // move on, resetting packet
00192       {
00193         myState = STATE_SYNC2;
00194         myPacket.empty();
00195         myPacket.setLength(0);
00196         myPacket.uByteToBuf(c);
00197       }
00198       else
00199       {
00200         if (printing)
00201           ArLog::log(ArLog::Terse, "Bad char in sync1 %d", c);
00202         return RET_BAD_PACKET;
00203       }
00204       break;
00205     case STATE_SYNC2:
00206       if (c == mySync2) // move on, adding this byte
00207       {
00208         myState = STATE_LENGTH1;
00209         myPacket.uByteToBuf(c);
00210       }
00211       else // go back to beginning, packet hosed
00212       {
00213         if (printing)
00214           ArLog::log(ArLog::Terse, "Bad char in sync2 %d, returning to sync1", c);
00215         myState = STATE_SYNC1;
00216         return RET_BAD_PACKET;
00217       }
00218       break;
00219     case STATE_LENGTH1:
00220       myState = STATE_LENGTH2;
00221       myReadLength = ((unsigned int)c & 0xff);
00222       myPacket.uByteToBuf(c);
00223       break;
00224     case STATE_LENGTH2:
00225       myState = STATE_ACQUIRE_DATA;
00226       myReadLength += ((unsigned int)c & 0xff) << 8;
00227       myPacket.uByteToBuf(c);
00228       myReadCount = 0;
00229       break;
00230     case STATE_ACQUIRE_DATA:
00231       if (myReadLength > ArNetPacket::MAX_LENGTH || 
00232           myReadLength < myPacket.getHeaderLength() + myPacket.getFooterLength())
00233       {
00234         if (!myQuiet)
00235           ArLog::log(ArLog::Normal, 
00236                      "ArNetPacketReceiverTcp::readPacket: bad packet length, it is %d which is more than max length of %d bytes or less than the minimum %d", 
00237                      myReadLength, ArNetPacket::MAX_LENGTH,
00238                      myPacket.getHeaderLength() + myPacket.getFooterLength());
00239         myState = STATE_SYNC1;
00240         return RET_BAD_PACKET;
00241       }
00242       // here we read until we get as much as we want, OR until
00243       // we go 100 ms without data... its arbitrary but it doesn't happen often
00244       // and it'll mean a bad packet anyways
00245       if (myReadCount < myReadLength - 4)
00246       {
00247         numRead = mySocket->read(myReadBuff + myReadCount, 
00248                                  myReadLength - myReadCount - 4);
00249         //printf("numRead %d myReadLength %d\n", numRead, myReadLength);
00250         // trap if it wasn't data
00251         if (numRead == 0)
00252           return RET_CONN_CLOSED;
00253         else if (numRead < 0)
00254           return RET_FAILED_READ;
00255         // if it was data add it to our number read
00256         myReadCount += numRead;
00257       }
00258       if (myReadCount > myReadLength - 4)
00259       {
00260         if (!myQuiet)
00261           ArLog::log(ArLog::Terse, 
00262                      "Read is greater than it should be at %d > %d", 
00263                      myReadCount, myReadLength - 4);
00264       }
00265       if (myReadCount == myReadLength - 4)
00266       {
00267         myPacket.dataToBuf(myReadBuff, myReadCount);
00268         if (myPacket.verifyCheckSum()) 
00269         {
00270           myPacket.resetRead();
00271           // take off the footer from the packets length Variable
00272           /* put this in if you want to see the packets received
00273              //printf("Input ");
00274              myPacket.log();
00275           */
00276           // you can also do this next line if you only care about type
00277           //printf("Input %x\n", myPacket.getCommand());
00278           //myPacket.log();
00279           myState = STATE_SYNC1;
00280           return RET_GOT_PACKET;
00281         }
00282         else 
00283         {
00284           myPacket.resetRead();
00285           if (!myQuiet)
00286             ArLog::log(ArLog::Normal, 
00287                        "ArNetPacketReceiverTcp::receivePacket: bad packet, bad checksum on packet %d", myPacket.getCommand());
00288           myState = STATE_SYNC1;
00289           return RET_BAD_PACKET;
00290         }
00291       }
00292       break;
00293     default:
00294       break;
00295     }
00296   } while (timeDone.mSecTo() >= 0 || myState != STATE_SYNC1);
00297   
00298   return RET_TIMED_OUT;
00299 
00300 }
00301 
00302 
00306 AREXPORT void ArNetPacketReceiverTcp::setProcessPacketCB(
00307         ArFunctor1<ArNetPacket *> *functor)
00308 {
00309   myProcessPacketCB = functor;
00310 }
00311 
00315 AREXPORT ArFunctor1<ArNetPacket *> *ArNetPacketReceiverTcp::getProcessPacketCB(void)
00316 {
00317   return myProcessPacketCB;
00318 }
00319 
00320 

Generated on Tue Feb 20 10:51:50 2007 for ArNetworking by  doxygen 1.4.0