stoneharry

Untitled

May 13th, 2012
273
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.67 KB | None | 0 0
  1.  
  2. initialiseSingleton(PatchMgr);
  3. PatchMgr::PatchMgr()
  4. {
  5.  
  6. }
  7.  
  8. PatchMgr::~PatchMgr()
  9. {
  10.  
  11. }
  12.  
  13. void PatchMgr::InitializePatchList()
  14. {
  15.   Log.Notice ("PatchMgr", "Loading Patches...");
  16.  
  17.   const size_t path_length (MAX_PATH * 10);
  18.  
  19.   char base_path[path_length];
  20.   char absolute_filename[path_length];
  21.  
  22. #ifdef WIN32
  23.   char file_pattern[path_length];
  24.  
  25.   if (!GetCurrentDirectory (sizeof (file_pattern), file_pattern))
  26.     return;
  27.  
  28.   strcpy (base_path, file_pattern);
  29.   strcat (file_pattern, "\\ClientPatches\\*.*");
  30.  
  31.   WIN32_FIND_DATA fd;
  32.   HANDLE fHandle (FindFirstFile (file_pattern, &fd));
  33.   if (fHandle == INVALID_HANDLE_VALUE)
  34.     return;
  35. #else
  36.   strcpy (base_path, ".");
  37.  
  38.   struct dirent ** list (NULL);
  39.   int filecount (scandir ("./ClientPatches", &list, 0, 0));
  40.   if (filecount <= 0 || list== NULL)
  41.   {
  42.     Log.Error("PatchMgr", "No patches found.");
  43.     return;
  44.   }
  45. #endif
  46.  
  47. #ifdef WIN32
  48.   do
  49. #else
  50.   while (filecount--)
  51. #endif
  52.   {
  53. #ifdef WIN32
  54.     snprintf (absolute_filename, sizeof (absolute_filename), "%s\\ClientPatches\\%s", base_path, fd.cFileName);
  55. #else
  56.     snprintf (absolute_filename, sizeof (absolute_filename), "%s/ClientPatches/%s", base_path, list[filecount]->d_name);
  57. #endif
  58.  
  59.     uint32 srcversion;
  60.     char locale[5] = "****";
  61.     if (sscanf(fd.cFileName,"%4s%u.", locale, &srcversion) != 2)
  62.     {
  63.       Log.Notice ("PatchMgr", "Found incorrect patch file: %4s %s", locale, fd.cFileName);
  64.       continue;
  65.     }
  66.  
  67. #ifdef WIN32
  68.     HANDLE hFile (CreateFile (absolute_filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL));
  69.     if(hFile == INVALID_HANDLE_VALUE)
  70.       continue;
  71. #else
  72.     const int file_descriptor (open (absolute_filename, O_RDONLY));
  73.  
  74.     if (file_descriptor <= 0)
  75.     {
  76.       LOG_ERROR("Cannot open %s", absolute_filename);
  77.       continue;
  78.     }
  79.  
  80.     struct stat stat_buffer;
  81.     if(fstat(file_descriptor, &stat_buffer) < 0)
  82.     {
  83.       LOG_ERROR("Cannot stat %s", absolute_filename);
  84.       continue;
  85.     }
  86. #endif
  87.  
  88.     Log.Notice ("PatchMgr", "Found patch for %u locale `%s`.", srcversion, locale);
  89.  
  90.     Patch* patch (new Patch);
  91.  
  92. #ifdef WIN32
  93.     DWORD sizehigh;
  94.     DWORD size (GetFileSize (hFile, &sizehigh));
  95. #else
  96.     unsigned int size (stat_buffer.st_size);
  97. #endif
  98.     patch->FileSize = size;
  99.     patch->Data = new uint8[size];
  100.     patch->Version = srcversion;
  101.     for(size_t i (0); i < 4; ++i)
  102.       patch->Locality[i] = static_cast<char> (tolower (patch->Locality[i]));
  103.     patch->Locality[4] = '\0';
  104.     patch->uLocality = *(uint32*) (patch->Locality);
  105.  
  106. #ifdef WIN32
  107.     const bool result (ReadFile (hFile, patch->Data, patch->FileSize, &size, NULL));
  108. #else
  109.     size = read (file_descriptor, pPatch->Data, size);
  110.     const bool result (size > 0);
  111. #endif
  112.     ASSERT (result);
  113.     ASSERT (size == patch->FileSize);
  114.  
  115. #ifdef WIN32
  116.     CloseHandle (hFile);
  117. #else
  118.     close (file_descriptor);
  119. #endif
  120.  
  121.     MD5Hash md5;
  122.     md5.Initialize();
  123.     md5.UpdateData (patch->Data, patch->FileSize);
  124.     md5.Finalize();
  125.     memcpy (patch->MD5, md5.GetDigest(), MD5_DIGEST_LENGTH);
  126.  
  127.     m_patches.push_back (patch);
  128.  
  129. #ifndef WIN32
  130.     free (list[filecount]);
  131. #endif
  132.   }
  133. #ifdef WIN32
  134.   while (FindNextFile (fHandle, &fd));
  135.  
  136.   FindClose(fHandle);
  137. #else
  138.   free (list);
  139. #endif
  140. }
  141.  
  142. const Patch* PatchMgr::FindPatchForClient(uint32 Version, const char * locale) const
  143. {
  144.   const char lower_case[4] = {tolower (locale[0]), tolower (locale[1]), tolower (locale[2]), tolower (locale[3])};
  145.   const uint32 ulocale (*(uint32*)lower_case);
  146.  
  147.   const Patch * fallbackPatch (NULL);
  148.   for( std::vector<Patch*>::const_iterator patch_it (m_patches.begin())
  149.      ; patch_it != m_patches.end()
  150.      ; ++patch_it
  151.      )
  152.   {
  153.     const Patch* patch (*patch_it);
  154.     if(patch->uLocality == ulocale)
  155.     {
  156.       if(patch->Version == Version)
  157.         return patch;
  158.  
  159.       if(fallbackPatch == NULL && patch->Version == 0)
  160.         fallbackPatch = patch;
  161.     }
  162.   }
  163.  
  164.   return fallbackPatch;
  165. }
  166.  
  167. void PatchMgr::BeginPatchJob(Patch * pPatch, AuthSocket * pClient, uint32 Skip)
  168. {
  169.     Log.Debug("AutoPatcher","Creating new job.");
  170.     PatchJob * pJob;
  171.  
  172.     pJob = new PatchJob(pPatch,pClient,Skip);
  173.     pClient->m_patchJob=pJob;
  174.     m_patchJobLock.Acquire();
  175.     m_patchJobs.push_back(pJob);
  176.     m_patchJobLock.Release();
  177.     Log.Debug("AutoPatcher","New Job Created.");
  178. }
  179.  
  180. void PatchMgr::UpdateJobs()
  181. {
  182.     //Log.Debug("AutoPatcher","Updating Jobs...");
  183.     list<PatchJob*>::iterator itr, itr2;
  184.     m_patchJobLock.Acquire();
  185.     for(itr = m_patchJobs.begin(); itr != m_patchJobs.end();)
  186.     {
  187.         itr2 = itr;
  188.         ++itr;
  189.  
  190.         if(!(*itr2)->Update())
  191.         {
  192.             Log.Debug("AutoPatcher","Deleting job.");
  193.             (*itr2)->GetClient()->m_patchJob= NULL;
  194.             delete (*itr2);
  195.             m_patchJobs.erase(itr2);
  196.         }
  197.     }
  198.     m_patchJobLock.Release();
  199. }
  200.  
  201. void PatchMgr::AbortPatchJob(PatchJob * pJob)
  202. {
  203.     list<PatchJob*>::iterator itr;
  204.     m_patchJobLock.Acquire();
  205.     for(itr = m_patchJobs.begin(); itr != m_patchJobs.end(); ++itr)
  206.     {
  207.         if((*itr)==pJob)
  208.         {
  209.             m_patchJobs.erase(itr);
  210.             break;
  211.         }
  212.     }
  213.     delete pJob;
  214.     m_patchJobLock.Release();
  215. }
  216.  
  217. // this is what blizz sends.
  218. // Data (1412 bytes)
  219. // Data (91 bytes)
  220. // 1412+91=1503 (minus header bytes, 3) = 1500
  221.  
  222. #define TRANSFER_CHUNK_SIZE 1500
  223.  
  224. #pragma pack(push,1)
  225.  
  226. struct TransferInitiatePacket
  227. {
  228.     uint8 cmd;
  229.     uint8 strsize;
  230.     char name[5];
  231.     uint64 filesize;
  232.     uint8 md5hash[MD5_DIGEST_LENGTH];
  233. };
  234.  
  235. struct TransferDataPacket
  236. {
  237.     uint8 cmd;
  238.     uint16 chunk_size;
  239. };
  240.  
  241. #pragma pack(pop)
  242.  
  243. bool PatchJob::Update()
  244. {
  245.     //Log.Debug("AutoPatcher","Updating PatchJob...");
  246.     // don't update unless the write buffer is empty
  247.  
  248.     m_client->BurstBegin();
  249.     if(m_client->writeBuffer.GetSize()!= 0)
  250.     {
  251.         Log.Debug("AutoPatcher","Write buffer still got data since last write.");
  252.         Log.Debug("PatchJob", "Client Write Buffer Size: %u", m_client->writeBuffer.GetSize());
  253.         m_client->BurstEnd();
  254.         return true;
  255.     }
  256.  
  257.     // send 1500 byte chunks
  258.     TransferDataPacket header;
  259.     bool result;
  260.     header.cmd = 0x31;
  261.     header.chunk_size = static_cast<uint16>( (m_bytesLeft>1500)?1500:m_bytesLeft );
  262.     Log.Debug("PatchJob", "Sending %u byte chunk", header.chunk_size);
  263.  
  264.     result = m_client->BurstSend((const uint8*)&header,sizeof(TransferDataPacket));
  265.     if(result)
  266.     {
  267.         result = m_client->BurstSend(m_dataPointer, header.chunk_size);
  268.         if(result)
  269.         {
  270.             m_dataPointer += header.chunk_size;
  271.             m_bytesSent += header.chunk_size;
  272.             m_bytesLeft -= header.chunk_size;
  273.         }
  274.     }
  275.  
  276.     if(result)
  277.     {
  278.         Log.Debug("PatchJob", "BurtPush()");
  279.         m_client->BurstPush();
  280.     }
  281.  
  282.     //Log.Debug("AutoPatcher", "Sent 1500byte chunk.");
  283.     m_client->BurstEnd();
  284.     Log.Debug("PatchJob", "Bytes Left: %u", m_bytesLeft);
  285.     Log.Debug("PatchJob", "Client Write Buffer Size: %u", m_client->writeBuffer.GetSize());
  286.     // no need to check the result here, could just be a full buffer and not necessarily a fatal error.
  287.     return (m_bytesLeft>0)?true:false;
  288. }
  289.  
  290. bool PatchMgr::InitiatePatch(Patch * pPatch, AuthSocket * pClient)
  291. {
  292.     Log.Debug("AutoPatcher","Initiating patch.");
  293.     // send initiate packet
  294.     TransferInitiatePacket init;
  295.     bool result;
  296.  
  297.     init.cmd = 0x30;
  298.     init.strsize=5;
  299.     init.name[0] = 'P';
  300.     init.name[1] = 'a';
  301.     init.name[2] = 't';
  302.     init.name[3] = 'c';
  303.     init.name[4] = 'h';
  304.     //init.name[5] = '\0';
  305.     init.filesize = pPatch->FileSize;
  306.     Log.Debug("AutoPatcher", "File Size : %u", pPatch->FileSize);
  307.     memcpy(init.md5hash, pPatch->MD5, MD5_DIGEST_LENGTH);
  308.  
  309.     // send it to the client
  310.     pClient->BurstBegin();
  311.     result = pClient->BurstSend((const uint8*)&init,sizeof(TransferInitiatePacket));
  312.     Log.Debug("AutoPatcher","Burst Result : %s", (result)?"true":"false");
  313.     if(result)
  314.         pClient->BurstPush();
  315.     pClient->BurstEnd();
  316.     return result;
  317. }
Advertisement
Add Comment
Please, Sign In to add comment