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

ArClientFileUtils.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 "ArClientFileUtils.h"
00029 
00030 AREXPORT ArClientFileLister::ArClientFileLister(ArClientBase *client) :
00031   myGetDirListingCB(this, &ArClientFileLister::netGetDirListing)
00032 {
00033   myClient = client;
00034   myClient->addHandler("getDirListing", &myGetDirListingCB);
00035   myCurrentDir[0] = '\0';
00036   myWaitingForDir[0] = '\0';
00037 }
00038 
00039 AREXPORT ArClientFileLister::~ArClientFileLister()
00040 {
00041 
00042 }
00043 
00044 AREXPORT bool ArClientFileLister::isAvailable(void)
00045 {
00046   return myClient->dataExists("getDirListing");
00047 }
00048 
00049 AREXPORT void ArClientFileLister::changeToTopDir(void)
00050 {
00051   myDataMutex.lock();
00052   myCurrentDir[0] = '\0';
00053   myWaitingForDir[0] = '\0';
00054   myDataMutex.unlock();
00055   myClient->requestOnceWithString("getDirListing", "");
00056 
00057 }
00058 
00059 AREXPORT void ArClientFileLister::changeToDir(const char *dir)
00060 {
00061   myDataMutex.lock();
00062   strcpy(myWaitingForDir, myCurrentDir);
00063   if (myWaitingForDir[0] != '\0')
00064     ArUtil::appendSlash(myWaitingForDir, sizeof(myWaitingForDir));
00065   strncat(myWaitingForDir, dir, 
00066           sizeof(myWaitingForDir) - strlen(myWaitingForDir));
00067   myLastRequested.setToNow();
00068   //printf("Getting %s\n", myWaitingForDir);
00069   std::string waitingFor = myWaitingForDir;
00070   myDataMutex.unlock();
00071   myClient->requestOnceWithString("getDirListing", waitingFor.c_str());
00072 }
00073 
00074 AREXPORT void ArClientFileLister::changeToAbsDir(const char *dir)
00075 {
00076   myDataMutex.lock();
00077   strncpy(myWaitingForDir, dir, sizeof(myWaitingForDir));
00078   myLastRequested.setToNow();
00079   //printf("Getting %s\n", myWaitingForDir);
00080   std::string waitingFor = myWaitingForDir;
00081   myDataMutex.unlock();
00082   myClient->requestOnceWithString("getDirListing", waitingFor.c_str());
00083 }
00084 
00085 AREXPORT void ArClientFileLister::upOneDir()
00086 {
00087   char *str;
00088   myDataMutex.lock();
00089 
00090   if ( ((str = strrchr(myCurrentDir, '/')) == NULL) && 
00091            ((str = strrchr(myCurrentDir, '\\')) == NULL) ) {
00092         myDataMutex.unlock();
00093         return changeToTopDir();
00094   } // end if first level down
00095 
00096   strcpy(myWaitingForDir, myCurrentDir);
00097   if (myWaitingForDir[0] != '\0')
00098   {
00099     ArUtil::appendSlash(myWaitingForDir, sizeof(myWaitingForDir));
00100     // chop off the last couple slashes (ie last directory)
00101     if ((str = strrchr(myWaitingForDir, '/')) != NULL || 
00102         (str = strrchr(myWaitingForDir, '\\')) != NULL)
00103       *str = '\0';
00104     if ((str = strrchr(myWaitingForDir, '/')) != NULL || 
00105         (str = strrchr(myWaitingForDir, '\\')) != NULL)
00106       *str = '\0';
00107   }
00108   myLastRequested.setToNow();
00109   std::string waitingFor = myWaitingForDir;
00110   myDataMutex.unlock();
00111   //printf("Getting %s\n", myWaitingForDir);
00112   myClient->requestOnceWithString("getDirListing", waitingFor.c_str());
00113 
00114 }
00115 
00116 AREXPORT const char *ArClientFileLister::getCurrentDir(void) const
00117 {
00118   return myCurrentDir;
00119 }
00120 
00121 AREXPORT void ArClientFileLister::netGetDirListing(ArNetPacket *packet)
00122 {
00123   char name[2048];
00124   char directory[2048];
00125   time_t atime;
00126   time_t mtime;
00127   ArTypes::UByte4 size;
00128   unsigned int num;
00129   unsigned int ret;
00130   unsigned int i;
00131   
00132   myDataMutex.lock();
00133   ret = packet->bufToUByte2();
00134   if (ret != 0)
00135   {
00136     ArLog::log(ArLog::Normal, 
00137                "ArClientFileLister: Bad return for getDirListing of %d", ret);
00138     myDataMutex.unlock();
00139     callUpdatedCallbacks(ret);
00140     return;
00141   }
00142   packet->bufToStr(directory, sizeof(directory));
00143   ArLog::log(ArLog::Verbose, 
00144              "ArClientFileLister: Got dir listing for %s", directory);
00145   // if we got it but it wasn't the directory we were waiting for anymore then just skip
00146   if (strcmp(myWaitingForDir, directory) != 0)
00147   {
00148     ArLog::log(ArLog::Normal, 
00149                "ArClientFileLister: Got directory '%s' instead of %s (probably fine)", 
00150                directory,
00151                myWaitingForDir);
00152     myDataMutex.unlock();
00153     callUpdatedCallbacks(-1);
00154     return;
00155   }
00156   // dir was good, remember it and get rid of our old stuff
00157   strcpy(myCurrentDir, directory);
00158 
00159   myDirectories.clear();
00160   myFiles.clear();
00161   num = packet->bufToUByte2();
00162   for (i = 0; i < num; i++)
00163   {
00164     packet->bufToStr(name, sizeof(name));
00165     atime = packet->bufToUByte4();
00166     mtime = packet->bufToUByte4();
00167     size = packet->bufToUByte4();
00168     myDirectories.push_back(ArClientFileListerItem(name, atime, mtime,
00169                                                    size));
00170   }
00171   num = packet->bufToUByte2();
00172   for (i = 0; i < num; i++)
00173   {
00174     packet->bufToStr(name, sizeof(name));
00175     atime = packet->bufToUByte4();
00176     mtime = packet->bufToUByte4();
00177     size = packet->bufToUByte4();
00178     myFiles.push_back(ArClientFileListerItem(name, atime, mtime,
00179                                              size));
00180   }
00181   myDataMutex.unlock();
00182   callUpdatedCallbacks(0);
00183 }
00184 
00185 AREXPORT void ArClientFileLister::log(bool withTimes) 
00186 {
00187   myDataMutex.lock();
00188   ArLog::log(ArLog::Normal, "In Directory '%s'", getCurrentDir());
00189   ArLog::log(ArLog::Normal, "%d directories:", myDirectories.size()); 
00190   logList(&myDirectories, withTimes);
00191   ArLog::log(ArLog::Normal, "%d Files:", myFiles.size()); 
00192   logList(&myFiles, withTimes);
00193   myDataMutex.unlock();
00194 }
00195 
00196 AREXPORT void ArClientFileLister::logList(
00197         std::list<ArClientFileListerItem> *logThis, 
00198         bool withTimes) 
00199 {
00200   std::list<ArClientFileListerItem>::const_iterator it;
00201   char buf[128];  
00202   unsigned int i;
00203   time_t itime;
00204 
00205   for (it = logThis->begin(); it != logThis->end(); it++)
00206   {
00207     ArLog::log(ArLog::Normal, "\t%s", (*it).getName());
00208     if (!withTimes)
00209       continue;
00210     itime = (*it).getLastAccessedTime();
00211     strcpy(buf, ctime(&itime));
00212     // chop the new lines off
00213     for (i = 0; i < sizeof(buf); i++)
00214       if (buf[i] == '\r' || buf[i] == '\n')
00215         buf[i] = '\0';
00216     ArLog::log(ArLog::Normal, "\t\tlastModified:%s", buf);
00217            itime = (*it).getLastModifiedTime();
00218     strcpy(buf, ctime(&itime));
00219     // chop the new lines off
00220     for (i = 0; i < sizeof(buf); i++)
00221       if (buf[i] == '\r' || buf[i] == '\n')
00222         buf[i] = '\0';
00223     ArLog::log(ArLog::Normal, "\t\tlastAccess: %s", buf);
00224     ArLog::log(ArLog::Normal, "\t\tbytes: %d", (*it).getSize());
00225   }
00226 }
00227 
00228 AREXPORT std::list<ArClientFileListerItem>
00229 ArClientFileLister::getDirectories(void) const
00230 {
00231   return myDirectories;
00232 }
00233 AREXPORT std::list<ArClientFileListerItem> 
00234 ArClientFileLister::getFiles(void) const
00235 {
00236   return myFiles;
00237 }
00238 
00239 
00240 AREXPORT void ArClientFileLister::addUpdatedCallback(ArFunctor1<int> *functor, 
00241                                                      ArListPos::Pos position)
00242 {
00243   myCallbackMutex.lock();
00244   if (position == ArListPos::FIRST)
00245     myUpdatedCallbacks.push_front(functor);
00246   else if (position == ArListPos::LAST)
00247     myUpdatedCallbacks.push_back(functor);
00248   else
00249     ArLog::log(ArLog::Terse, 
00250                "ArClientFileListt::addUpdateCallback: Invalid position.");
00251   myCallbackMutex.unlock();
00252 
00253 }
00254 
00255 AREXPORT void ArClientFileLister::remUpdatedCallback(ArFunctor1<int> *functor)
00256 {
00257   myCallbackMutex.lock();
00258   myUpdatedCallbacks.remove(functor);
00259   myCallbackMutex.unlock();
00260 }
00261 
00262 AREXPORT void ArClientFileLister::callUpdatedCallbacks(int val)
00263 {
00264   std::list<ArFunctor1<int> *>::iterator it;
00265 
00266   myCallbackMutex.lock();
00267   for (it = myUpdatedCallbacks.begin(); it != myUpdatedCallbacks.end(); it++)
00268     (*it)->invoke(val);
00269   myCallbackMutex.unlock();
00270 }
00271 
00272 AREXPORT ArTime ArClientFileLister::getLastUpdated(void)
00273 {
00274   ArTime ret;
00275   myDataMutex.lock();
00276   ret = myLastUpdated;
00277   myDataMutex.unlock();
00278   return ret;
00279 }
00280 
00281 AREXPORT ArTime ArClientFileLister::getLastRequested(void)
00282 {
00283   ArTime ret;
00284   myDataMutex.lock();
00285   ret = myLastRequested;
00286   myDataMutex.unlock();
00287   return ret;
00288 }
00289 
00290 AREXPORT ArClientFileToClient::ArClientFileToClient(ArClientBase *client) :
00291   myGetFileCB(this, &ArClientFileToClient::netGetFile)
00292 {
00293   myClient = client;
00294   myClient->addHandler("getFile", &myGetFileCB);
00295   myFile = NULL;
00296   myIsWaitingForFile = false;
00297 }
00298 
00299 AREXPORT ArClientFileToClient::~ArClientFileToClient()
00300 {
00301 
00302 }
00303 
00304 AREXPORT bool ArClientFileToClient::isAvailable(void)
00305 {
00306   return myClient->dataExists("getFile");
00307 }
00308 
00309 
00310 AREXPORT bool ArClientFileToClient::getFileFromDirectory(
00311         const char *directory, const char *fileName, 
00312         const char *clientFileName)
00313 {
00314   myDataMutex.lock();
00315   if (fileName == NULL || clientFileName == NULL)
00316   {
00317     ArLog::log(ArLog::Terse, 
00318                "ArClientFileToClient: NULL fileName ('%s') or clientFileName ('%s')", 
00319                fileName, clientFileName);
00320     myDataMutex.unlock();
00321     return false;
00322   }
00323   if (!isAvailable())
00324   {
00325     ArLog::log(ArLog::Normal, "ArClientFileToClient::getFileFromDirectory: Tried to get file but the server doesn't support it.");
00326     return false;
00327   }
00328 
00329   if (myIsWaitingForFile)
00330   {
00331     ArLog::log(ArLog::Terse, 
00332                "ArClientFileToClient: already busy downloading a file '%s' cannot download '%s'", 
00333                myFileName.c_str(), fileName);
00334     myDataMutex.unlock();
00335     return false;
00336   }
00337   if (directory != NULL)
00338     myDirectory = directory;
00339   else
00340     myDirectory = "";
00341   myFileName = fileName;
00342   myClientFileName = clientFileName;
00343 
00344   char *dirStr = NULL;
00345   int dirLen;
00346   if (directory != NULL)
00347   {
00348     dirLen = strlen(directory) + 2;
00349     dirStr = new char[dirLen];
00350     strncpy(dirStr, directory, dirLen);
00351     // make sure it has a slash
00352     ArUtil::appendSlash(dirStr, dirLen);
00353     // and that the slashes go a consistent direction
00354     ArUtil::fixSlashes(dirStr, dirLen);
00355   }
00356 
00357   int fileLen = strlen(fileName) + 1;
00358   char *fileStr = new char[fileLen];
00359   strncpy(fileStr, fileName, fileLen);
00360   // and that the slashes go a consistent direction
00361   ArUtil::fixSlashes(fileStr, fileLen);
00362 
00363   if (directory == NULL)
00364     myWholeFileName = "";
00365   else
00366     myWholeFileName = dirStr;
00367 
00368   myWholeFileName += fileStr;
00369 
00370   ArNetPacket sendPacket;
00371   sendPacket.strToBuf(myWholeFileName.c_str());
00372   sendPacket.uByte2ToBuf(0);
00373   myClient->requestOnce("getFile", &sendPacket);
00374 
00375   myIsWaitingForFile = true;
00376   myLastRequested.setToNow();
00377   if (dirStr != NULL)
00378     delete[] dirStr;
00379   if (fileStr != NULL)
00380     delete[] fileStr;    
00381   myDataMutex.unlock();
00382   return true;
00383 }
00384 
00385 AREXPORT void ArClientFileToClient::netGetFile(ArNetPacket *packet)
00386 {
00387   int ret;
00388   char fileName[2048];
00389   // if its just the empty return packet at the end then don't worry about it
00390   if (packet->getDataLength() == 0)
00391     return;
00392 
00393   myDataMutex.lock();
00394   ret = packet->bufToUByte2();
00395   packet->bufToStr(fileName, sizeof(fileName));
00396   ArUtil::fixSlashes(fileName, sizeof(fileName));
00397   if (ArUtil::strcasecmp(fileName, myWholeFileName) != 0)
00398   {
00399     ArLog::log(ArLog::Normal, 
00400                "Got data for a file ('%s') we don't want (we want '%s') (ret %d)",
00401                fileName, myWholeFileName.c_str(), ret);
00402     myDataMutex.unlock();
00403     return;
00404   } 
00405   if (ret != 0)
00406   {
00407     if (myFile != NULL)
00408     {
00409       fclose(myFile);
00410       unlink(myClientFileName.c_str());
00411       myFile = NULL;
00412     }
00413     ArLog::log(ArLog::Normal, "ArClientFileToClient: Bad return %d on file %s", ret, fileName);
00414     myIsWaitingForFile = false;
00415     myLastReceived.setToNow();
00416     myDataMutex.unlock();    
00417     callFileReceivedCallbacks(ret);
00418     return;
00419   }
00420   if (myFile == NULL)
00421   {
00422     ArLog::log(ArLog::Verbose, "Getting file %s", myFileName.c_str());
00423     if ((myFile = fopen(myClientFileName.c_str(), "wb")) == NULL)
00424     {
00425       ArLog::log(ArLog::Normal, "Can't open '%s' to put file into", 
00426                  myClientFileName.c_str());
00427       myIsWaitingForFile = false;
00428       myLastReceived.setToNow();
00429       myDataMutex.unlock();    
00430       callFileReceivedCallbacks(-2);
00431       return;
00432     }
00433   }
00434   ArTypes::UByte4 numBytes;
00435   char buf[32000];
00436   // file should be good here, so just write into it
00437   numBytes = packet->bufToUByte4();
00438   if (numBytes == 0)
00439   {
00440     fclose(myFile);
00441     myFile = NULL;
00442     myIsWaitingForFile = false;
00443     ArLog::log(ArLog::Normal, "Received file %s", myFileName.c_str());
00444     myLastReceived.setToNow();
00445     myDataMutex.unlock();
00446     callFileReceivedCallbacks(0);
00447     return;
00448   }
00449   else
00450   {
00451     ArLog::log(ArLog::Verbose, "Got %d bytes of file '%s'", 
00452                numBytes, myFileName.c_str());
00453     packet->bufToData(buf, numBytes);
00454     fwrite(buf, 1, numBytes, myFile);
00455     myDataMutex.unlock();
00456   }
00457 
00458 }
00459 
00460 
00461 AREXPORT void ArClientFileToClient::addFileReceivedCallback(
00462         ArFunctor1<int> *functor, ArListPos::Pos position)
00463 {
00464   myCallbackMutex.lock();
00465   if (position == ArListPos::FIRST)
00466     myFileReceivedCallbacks.push_front(functor);
00467   else if (position == ArListPos::LAST)
00468     myFileReceivedCallbacks.push_back(functor);
00469   else
00470     ArLog::log(ArLog::Terse, 
00471                "ArClientFileToClient::addUpdateCallback: Invalid position.");
00472   myCallbackMutex.unlock();
00473 }
00474 
00475 AREXPORT void ArClientFileToClient::remFileReceivedCallback(
00476         ArFunctor1<int> *functor)
00477 {
00478   myCallbackMutex.lock();
00479   myFileReceivedCallbacks.remove(functor);
00480   myCallbackMutex.unlock();
00481 }
00482 
00483 AREXPORT void ArClientFileToClient::callFileReceivedCallbacks(int val)
00484 {
00485   std::list<ArFunctor1<int> *>::iterator it;
00486   myCallbackMutex.lock();
00487   for (it = myFileReceivedCallbacks.begin(); it != myFileReceivedCallbacks.end(); it++)
00488     (*it)->invoke(val);
00489   myCallbackMutex.unlock();
00490 }
00491 
00492 AREXPORT const char *ArClientFileToClient::getDirectory(void) 
00493 {
00494   std::string ret;
00495   myDataMutex.lock();
00496   ret = myDirectory;
00497   myDataMutex.unlock();
00498   return ret.c_str();
00499 }
00500 
00501 AREXPORT const char *ArClientFileToClient::getFileName(void) 
00502 {
00503   std::string ret;
00504   myDataMutex.lock();
00505   ret = myFileName;
00506   myDataMutex.unlock();
00507   return ret.c_str();
00508 }
00509 
00510 AREXPORT const char *ArClientFileToClient::getClientFileName(void) 
00511 {
00512   std::string ret;
00513   myDataMutex.lock();
00514   ret = myClientFileName;
00515   myDataMutex.unlock();
00516   return ret.c_str();
00517 }
00518   
00519 AREXPORT void ArClientFileToClient::cancelGet(void)
00520 {
00521   // Removed the following line because it causes the received packets
00522   // to be dropped, and the file getter remains permanently in the 
00523   // waiting for file state.
00524   // myWholeFileName = "";
00525   // TODO!
00526 }
00527 
00528 AREXPORT bool ArClientFileToClient::isWaitingForFile(void) 
00529 {
00530   bool ret;
00531   myDataMutex.lock();
00532   ret = myIsWaitingForFile;
00533   myDataMutex.unlock();
00534   return ret;
00535 }
00536 
00537 AREXPORT ArTime ArClientFileToClient::getLastReceived(void)
00538 {
00539   ArTime ret;
00540   myDataMutex.lock();
00541   ret = myLastReceived;
00542   myDataMutex.unlock();
00543   return ret;
00544 }
00545 
00546 AREXPORT ArTime ArClientFileToClient::getLastRequested(void)
00547 {
00548   ArTime ret;
00549   myDataMutex.lock();
00550   ret = myLastRequested;
00551   myDataMutex.unlock();
00552   return ret;
00553 }
00554 
00555 
00556 AREXPORT ArClientFileFromClient::ArClientFileFromClient(ArClientBase *client) :
00557   myPutFileCB(this, &ArClientFileFromClient::netPutFile)
00558 {
00559   myClient = client;
00560   myClient->addHandler("putFile", &myPutFileCB);
00561   myClient->addHandler("putFileInterleaved", &myPutFileCB);
00562   myFile = NULL;
00563   myIsWaitingForReturn = false;
00564 }
00565 
00566 AREXPORT ArClientFileFromClient::~ArClientFileFromClient()
00567 {
00568 
00569 }
00570 
00571 AREXPORT bool ArClientFileFromClient::isAvailable(void)
00572 {
00573   return (myClient->dataExists("putFile") || 
00574           myClient->dataExists("putFileInterleaved"));
00575 }
00576 
00577 AREXPORT bool ArClientFileFromClient::isAvailableSlow(void)
00578 {
00579   return myClient->dataExists("putFileInterleaved");
00580 }
00581 
00582 AREXPORT bool ArClientFileFromClient::isAvailableFast(void)
00583 {
00584   return myClient->dataExists("putFile");
00585 }
00586 
00587 AREXPORT bool ArClientFileFromClient::putFileToDirectory(
00588         const char *directory, const char *fileName, 
00589         const char *clientFileName, SendSpeed sendSpeed)
00590 {
00591   bool interleaved;
00592 
00593   myDataMutex.lock();
00594   if (fileName == NULL || fileName[0] == '\0' || 
00595       clientFileName == NULL || clientFileName[0] == '\0')
00596   {
00597     ArLog::log(ArLog::Terse, 
00598                "ArClientFileFromClient: NULL or empty fileName ('%s') or clientFileName ('%s')", 
00599                fileName, clientFileName);
00600     myDataMutex.unlock();
00601     return false;
00602   }
00603   if (myIsWaitingForReturn)
00604   {
00605     ArLog::log(ArLog::Terse, 
00606                "ArClientFileFromClient: already busy uploading a file '%s' cannot upload '%s'", 
00607                myFileName.c_str(), fileName);
00608     myDataMutex.unlock();
00609     return false;
00610   }
00611 
00612   if (myClient->dataExists("putFile") &&
00613       (sendSpeed == SPEED_FAST || sendSpeed == SPEED_AUTO))
00614   {
00615     myInterleaved = false;
00616     myCommandName = "putFile";
00617   }
00618   else if (myClient->dataExists("putFileInterleaved") && 
00619            (sendSpeed == SPEED_SLOW || sendSpeed == SPEED_AUTO))
00620   {
00621     myInterleaved = true;
00622     myReadyForNextPacket = false;
00623     myCommandName = "putFileInterleaved";
00624   }
00625   else
00626   {
00627     ArLog::log(ArLog::Normal, "ArClientFileFromClient::putFileToDirectory: Tried to put file but the server doesn't support it (or doesn't support it at the speed requested).");
00628     myDataMutex.unlock();
00629     return false;
00630   }
00631     
00632   interleaved = myInterleaved;
00633 
00634   if (directory != NULL)
00635     myDirectory = directory;
00636   else
00637     myDirectory = "";
00638   myFileName = fileName;
00639   myClientFileName = clientFileName;
00640 
00641   char *dirStr = NULL;
00642   int dirLen;
00643   if (directory != NULL)
00644   {
00645     dirLen = strlen(directory) + 2;
00646     dirStr = new char[dirLen];
00647     strncpy(dirStr, directory, dirLen);
00648     // make sure it has a slash
00649     ArUtil::appendSlash(dirStr, dirLen);
00650     // and that the slashes go a consistent direction
00651     ArUtil::fixSlashes(dirStr, dirLen);
00652   }
00653 
00654   int fileLen = strlen(fileName) + 1;
00655   char *fileStr = new char[fileLen];
00656   strncpy(fileStr, fileName, fileLen);
00657   // and that the slashes go a consistent direction
00658   ArUtil::fixSlashes(fileStr, fileLen);
00659 
00660   if (directory == NULL)
00661     myWholeFileName = "";
00662   else
00663     myWholeFileName = dirStr;
00664 
00665   myWholeFileName += fileStr;
00666 
00667   myIsWaitingForReturn = true;
00668   myLastStartedSend.setToNow();
00669   if (dirStr != NULL)
00670     delete[] dirStr;
00671   if (fileStr != NULL)
00672     delete[] fileStr;    
00673 
00674   ArNetPacket sendPacket;
00675 
00676   FILE *file;
00677   if ((file = fopen(myClientFileName.c_str(), "rb")) == NULL)
00678   {
00679     ArLog::log(ArLog::Normal, 
00680                "ArClientFileFromClient::putFile: can't open file '%s'", 
00681                clientFileName);
00682     myIsWaitingForReturn = false;
00683     myDataMutex.unlock();
00684     return false;
00685   }
00686   myDataMutex.unlock();
00687   // tell the server we're sending
00688   
00689   sendPacket.empty();
00690   sendPacket.uByte2ToBuf(0);
00691   sendPacket.strToBuf(myWholeFileName.c_str());
00692   myClient->requestOnce(myCommandName.c_str(), &sendPacket);
00693   ArLog::log(ArLog::Normal, "Starting send of file %s", 
00694              myWholeFileName.c_str());
00695   
00696   char buf[30000];
00697   size_t ret;
00698 
00699   ArTime started;
00700   started.setToNow();
00701 
00702   // now send the file
00703   while ((ret = fread(buf, 1, sizeof(buf), file)) == sizeof(buf))
00704   {
00705     // if we're interleaved wait for the next packet
00706     if (interleaved)
00707     {
00708       myDataMutex.lock();
00709 
00710       // myReadyForNextPacket is set to true when the response is received
00711       // from the server.
00712       while (!myReadyForNextPacket) 
00713       {
00714               if (!myIsWaitingForReturn)
00715               {
00716                 ArLog::log(ArLog::Normal, "ArFileFromClient::putFileToDirectory: Put was cancelled or failed.");
00717                 myDataMutex.unlock();
00718                 return false;
00719               }
00720               myDataMutex.unlock();
00721               ArUtil::sleep(1);
00722 
00723 
00724               if (started.secSince() > 30)
00725               {
00726           myDataMutex.lock();
00727           myIsWaitingForReturn = false;
00728           myDataMutex.unlock();
00729 
00730                 ArLog::log(ArLog::Normal, "ArFileFromClient::putFileToDirectory: No return from client within 15 seconds, failing put.");        
00731                 return false;
00732               }
00733               myDataMutex.lock();
00734       
00735       } // end while not ready for next packet
00736 
00737       // Reset the flag so we'll wait for a response during the next loop iteration.
00738       myReadyForNextPacket = false;
00739 
00740       myDataMutex.unlock();
00741     } // end if interleaved
00742 
00743     // Reset the time this packet was sent.
00744     started.setToNow();
00745 
00746     sendPacket.empty();
00747     sendPacket.uByte2ToBuf(1);
00748     sendPacket.strToBuf(myWholeFileName.c_str());
00749     sendPacket.uByte4ToBuf(ret);
00750     sendPacket.dataToBuf(buf, ret);
00751     myClient->requestOnce(myCommandName.c_str(), &sendPacket);
00752     //ArLog::log(ArLog::Normal, "Sent packet with %d", ret);
00753 
00754   } // end while more to read... 
00755 
00756   if (feof(file))
00757   {
00758     printf("end of file\n");
00759   }
00760   if (ferror(file))
00761   {
00762     ArLog::log(ArLog::Normal, "ArServerFileFromClient: Error sending file %s", 
00763                fileName);
00764     sendPacket.empty();
00765     sendPacket.uByte2ToBuf(3);
00766     sendPacket.strToBuf(myWholeFileName.c_str());
00767     myClient->requestOnce(myCommandName.c_str(), &sendPacket);
00768     myDataMutex.lock();
00769     myIsWaitingForReturn = false;
00770     myDataMutex.unlock();
00771     return false;
00772   }
00773   
00774   sendPacket.empty();
00775   sendPacket.uByte2ToBuf(1);
00776   sendPacket.strToBuf(myWholeFileName.c_str());
00777   sendPacket.uByte4ToBuf(ret);
00778   sendPacket.dataToBuf(buf, ret);
00779   myClient->requestOnce(myCommandName.c_str(), &sendPacket);
00780   //ArLog::log(ArLog::Verbose, "Sent packet with %d", ret);
00781   
00782   
00783   sendPacket.empty();
00784   sendPacket.uByte2ToBuf(2);
00785   sendPacket.strToBuf(myWholeFileName.c_str());
00786   myClient->requestOnce(myCommandName.c_str(), &sendPacket);
00787   
00788   if (feof(file))
00789   {
00790     ArLog::log(ArLog::Normal, "ArServerFileToClient: Sent file %s", fileName);
00791   }
00792   
00793   fclose(file);
00794   return true;
00795 }
00796 
00797 AREXPORT void ArClientFileFromClient::netPutFile(ArNetPacket *packet)
00798 {
00799   int ret;
00800   char fileName[2048];
00801   bool done;
00802 
00803   myDataMutex.lock();
00804   if (!myIsWaitingForReturn)
00805   {
00806     myDataMutex.unlock();
00807     return;
00808   }
00809   ret = packet->bufToUByte2();
00810   packet->bufToStr(fileName, sizeof(fileName));
00811   if (myInterleaved && ret == 10)
00812   {
00813     done = false;
00814     myReadyForNextPacket = true;
00815   }
00816   else
00817   {
00818     done = true;
00819     myIsWaitingForReturn = false;
00820   }
00821   myDataMutex.unlock();
00822   if (done)
00823     callFileSentCallbacks(ret);
00824 }
00825 
00826 
00827 AREXPORT void ArClientFileFromClient::addFileSentCallback(
00828         ArFunctor1<int> *functor, ArListPos::Pos position)
00829 {
00830   myCallbackMutex.lock();
00831   if (position == ArListPos::FIRST)
00832     myFileSentCallbacks.push_front(functor);
00833   else if (position == ArListPos::LAST)
00834     myFileSentCallbacks.push_back(functor);
00835   else
00836     ArLog::log(ArLog::Terse, 
00837                "ArClientFileFromClient::addUpdateCallback: Invalid position.");
00838   myCallbackMutex.unlock();
00839 }
00840 
00841 AREXPORT void ArClientFileFromClient::remFileSentCallback(
00842         ArFunctor1<int> *functor)
00843 {
00844   myCallbackMutex.lock();
00845   myFileSentCallbacks.remove(functor);
00846   myCallbackMutex.unlock();
00847 }
00848 
00849 AREXPORT void ArClientFileFromClient::callFileSentCallbacks(int val)
00850 {
00851   std::list<ArFunctor1<int> *>::iterator it;
00852   myCallbackMutex.lock();
00853   for (it = myFileSentCallbacks.begin(); it != myFileSentCallbacks.end(); it++)
00854     (*it)->invoke(val);
00855   myCallbackMutex.unlock();
00856 }
00857 
00858 AREXPORT const char *ArClientFileFromClient::getDirectory(void) 
00859 {
00860   std::string ret;
00861   myDataMutex.lock();
00862   ret = myDirectory;
00863   myDataMutex.unlock();
00864   return ret.c_str();
00865 }
00866 
00867 AREXPORT const char *ArClientFileFromClient::getFileName(void) 
00868 {
00869   std::string ret;
00870   myDataMutex.lock();
00871   ret = myFileName;
00872   myDataMutex.unlock();
00873   return ret.c_str();
00874 }
00875 
00876 AREXPORT const char *ArClientFileFromClient::getClientFileName(void) 
00877 {
00878   std::string ret;
00879   myDataMutex.lock();
00880   ret = myClientFileName;
00881   myDataMutex.unlock();
00882   return ret.c_str();
00883 }
00884   
00885 AREXPORT void ArClientFileFromClient::cancelPut(void)
00886 {
00887   ArNetPacket sendPacket;
00888 
00889   myDataMutex.lock();
00890   if (myIsWaitingForReturn)
00891   {
00892     myIsWaitingForReturn = false;
00893     
00894     sendPacket.uByte2ToBuf(3);
00895     sendPacket.strToBuf(myWholeFileName.c_str());
00896     myClient->requestOnce(myCommandName.c_str(), &sendPacket);
00897   }
00898   myDataMutex.unlock();
00899 }
00900 
00901 AREXPORT bool ArClientFileFromClient::isWaitingForReturn(void) 
00902 {
00903   bool ret;
00904   myDataMutex.lock();
00905   ret = myIsWaitingForReturn;
00906   myDataMutex.unlock();
00907   return ret;
00908 }
00909 
00910 AREXPORT ArTime ArClientFileFromClient::getLastCompletedSend(void)
00911 {
00912   ArTime ret;
00913   myDataMutex.lock();
00914   ret = myLastCompletedSend;
00915   myDataMutex.unlock();
00916   return ret;
00917 }
00918 
00919 AREXPORT ArTime ArClientFileFromClient::getLastStartedSend(void)
00920 {
00921   ArTime ret;
00922   myDataMutex.lock();
00923   ret = myLastStartedSend;
00924   myDataMutex.unlock();
00925   return ret;
00926 }
00927 
00928 AREXPORT ArClientDeleteFileOnServer::ArClientDeleteFileOnServer(
00929         ArClientBase *client) :
00930   myDeleteFileCB(this, &ArClientDeleteFileOnServer::netDeleteFile)
00931 {
00932   myClient = client;
00933   myClient->addHandler("deleteFile", &myDeleteFileCB);
00934   myIsWaitingForReturn = false;
00935 }
00936 
00937 AREXPORT ArClientDeleteFileOnServer::~ArClientDeleteFileOnServer()
00938 {
00939 
00940 }
00941 
00942 AREXPORT bool ArClientDeleteFileOnServer::isAvailable(void)
00943 {
00944   return myClient->dataExists("deleteFile");
00945 }
00946 
00947 AREXPORT bool ArClientDeleteFileOnServer::deleteFileFromDirectory(
00948         const char *directory, const char *fileName)
00949 {
00950   myDataMutex.lock();
00951   if (fileName == NULL || fileName[0] == '\0')
00952   {
00953     ArLog::log(ArLog::Terse, 
00954                "ArClientDeleteFileOnServer: NULL or empty fileName ('%s')", 
00955                fileName);
00956     myDataMutex.unlock();
00957     return false;
00958   }
00959   if (!isAvailable())
00960   {
00961     ArLog::log(ArLog::Normal, "ArClientDeleteFileOnServer::deleteFileFromDirectory: Tried to delete file but the server doesn't support it.");
00962     return false;
00963   }
00964 
00965   if (myIsWaitingForReturn)
00966   {
00967     ArLog::log(ArLog::Terse, 
00968                "ArClientDeleteFileOnServer: already busy deleting a file '%s' cannot delete '%s'", 
00969                myFileName.c_str(), fileName);
00970     myDataMutex.unlock();
00971     return false;
00972   }
00973   if (directory != NULL)
00974     myDirectory = directory;
00975   else
00976     myDirectory = "";
00977   myFileName = fileName;
00978 
00979   char *dirStr = NULL;
00980   int dirLen;
00981   if (directory != NULL)
00982   {
00983     dirLen = strlen(directory) + 2;
00984     dirStr = new char[dirLen];
00985     strncpy(dirStr, directory, dirLen);
00986     // make sure it has a slash
00987     ArUtil::appendSlash(dirStr, dirLen);
00988     // and that the slashes go a consistent direction
00989     ArUtil::fixSlashes(dirStr, dirLen);
00990   }
00991 
00992   int fileLen = strlen(fileName) + 1;
00993   char *fileStr = new char[fileLen];
00994   strncpy(fileStr, fileName, fileLen);
00995   // and that the slashes go a consistent direction
00996   ArUtil::fixSlashes(fileStr, fileLen);
00997 
00998   if (directory == NULL)
00999     myWholeFileName = "";
01000   else
01001     myWholeFileName = dirStr;
01002 
01003   myWholeFileName += fileStr;
01004 
01005   myIsWaitingForReturn = true;
01006   myLastStartedSend.setToNow();
01007   if (dirStr != NULL)
01008     delete[] dirStr;
01009   if (fileStr != NULL)
01010     delete[] fileStr;    
01011 
01012   ArNetPacket sendPacket;
01013 
01014   myDataMutex.unlock();
01015   // tell the server to delete it
01016   
01017   sendPacket.empty();
01018   sendPacket.strToBuf(myWholeFileName.c_str());
01019   myClient->requestOnce("deleteFile", &sendPacket);
01020   ArLog::log(ArLog::Normal, "Requested delete of file %s", 
01021              myWholeFileName.c_str());
01022   return true;
01023 }
01024 
01025 AREXPORT void ArClientDeleteFileOnServer::netDeleteFile(ArNetPacket *packet)
01026 {
01027   int ret;
01028   char fileName[2048];
01029 
01030   myDataMutex.lock();
01031   if (!myIsWaitingForReturn)
01032   {
01033     myDataMutex.unlock();
01034     return;
01035   }
01036   ret = packet->bufToUByte2();
01037   packet->bufToStr(fileName, sizeof(fileName));
01038   //printf("Ret of '%s' is %d\n", fileName, ret);
01039   myIsWaitingForReturn = 0;
01040   myDataMutex.unlock();
01041   callFileDeletedCallbacks(ret);
01042 }
01043 
01044 
01045 AREXPORT void ArClientDeleteFileOnServer::addFileDeletedCallback(
01046         ArFunctor1<int> *functor, ArListPos::Pos position)
01047 {
01048   myCallbackMutex.lock();
01049   if (position == ArListPos::FIRST)
01050     myFileDeletedCallbacks.push_front(functor);
01051   else if (position == ArListPos::LAST)
01052     myFileDeletedCallbacks.push_back(functor);
01053   else
01054     ArLog::log(ArLog::Terse, 
01055                "ArClientDeleteFileOnServer::addUpdateCallback: Invalid position.");
01056   myCallbackMutex.unlock();
01057 }
01058 
01059 AREXPORT void ArClientDeleteFileOnServer::remFileDeletedCallback(
01060         ArFunctor1<int> *functor)
01061 {
01062   myCallbackMutex.lock();
01063   myFileDeletedCallbacks.remove(functor);
01064   myCallbackMutex.unlock();
01065 }
01066 
01067 AREXPORT void ArClientDeleteFileOnServer::callFileDeletedCallbacks(int val)
01068 {
01069   std::list<ArFunctor1<int> *>::iterator it;
01070 
01071   myCallbackMutex.lock();
01072   for (it = myFileDeletedCallbacks.begin(); 
01073        it != myFileDeletedCallbacks.end(); 
01074        it++)
01075     (*it)->invoke(val);
01076   myCallbackMutex.unlock();
01077 }
01078 
01079 AREXPORT const char *ArClientDeleteFileOnServer::getDirectory(void) 
01080 {
01081   std::string ret;
01082   myDataMutex.lock();
01083   ret = myDirectory;
01084   myDataMutex.unlock();
01085   return ret.c_str();
01086 }
01087 
01088 AREXPORT const char *ArClientDeleteFileOnServer::getFileName(void) 
01089 {
01090   std::string ret;
01091   myDataMutex.lock();
01092   ret = myFileName;
01093   myDataMutex.unlock();
01094   return ret.c_str();
01095 }
01096 
01097 AREXPORT bool ArClientDeleteFileOnServer::isWaitingForReturn(void) 
01098 {
01099   bool ret;
01100   myDataMutex.lock();
01101   ret = myIsWaitingForReturn;
01102   myDataMutex.unlock();
01103   return ret;
01104 }
01105 
01106 AREXPORT ArTime ArClientDeleteFileOnServer::getLastCompletedSend(void)
01107 {
01108   ArTime ret;
01109   myDataMutex.lock();
01110   ret = myLastCompletedSend;
01111   myDataMutex.unlock();
01112   return ret;
01113 }
01114 
01115 AREXPORT ArTime ArClientDeleteFileOnServer::getLastStartedSend(void)
01116 {
01117   ArTime ret;
01118   myDataMutex.lock();
01119   ret = myLastStartedSend;
01120   myDataMutex.unlock();
01121   return ret;
01122 }
01123 

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