00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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
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 }
00095
00096 strcpy(myWaitingForDir, myCurrentDir);
00097 if (myWaitingForDir[0] != '\0')
00098 {
00099 ArUtil::appendSlash(myWaitingForDir, sizeof(myWaitingForDir));
00100
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
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
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
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
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
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
00352 ArUtil::appendSlash(dirStr, dirLen);
00353
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
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
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
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
00522
00523
00524
00525
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
00649 ArUtil::appendSlash(dirStr, dirLen);
00650
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
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
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
00703 while ((ret = fread(buf, 1, sizeof(buf), file)) == sizeof(buf))
00704 {
00705
00706 if (interleaved)
00707 {
00708 myDataMutex.lock();
00709
00710
00711
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 }
00736
00737
00738 myReadyForNextPacket = false;
00739
00740 myDataMutex.unlock();
00741 }
00742
00743
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
00753
00754 }
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
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
00987 ArUtil::appendSlash(dirStr, dirLen);
00988
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
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
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
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