stoneharry

Untitled

Apr 22nd, 2012
150
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.65 KB | None | 0 0
  1. /*
  2.  * ArcEmu MMORPG Server
  3.  * Copyright (C) 2008-2011 <http://www.ArcEmu.org/>
  4.  *
  5.  * This program is free software: you can redistribute it and/or modify
  6.  * it under the terms of the GNU Affero General Public License as published by
  7.  * the Free Software Foundation, either version 3 of the License, or
  8.  * any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU Affero General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Affero General Public License
  16.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17.  *
  18.  */
  19.  
  20. #include "LogonStdAfx.h"
  21. #include "../arcemu-shared/Auth/MD5.h"
  22.  
  23. #ifndef WIN32
  24. #include <fcntl.h>
  25. #include <dirent.h>
  26. #include <sys/stat.h>
  27. #endif
  28.  
  29. initialiseSingleton(PatchMgr);
  30. PatchMgr::PatchMgr()
  31. {
  32.     // load patches
  33. #ifdef WIN32
  34.     Log.Notice("PatchMgr", "Loading Patches...");
  35.     char Buffer[MAX_PATH*10];
  36.     char Buffer2[MAX_PATH*10];
  37.     char Buffer3[MAX_PATH*10];
  38.  
  39.     WIN32_FIND_DATA fd;
  40.     HANDLE fHandle;
  41.     MD5Hash md5;
  42.     Patch * pPatch;
  43.     DWORD size,sizehigh;
  44.     HANDLE hFile;
  45.     uint32 srcversion;
  46.     char locality[5];
  47.     uint32 i;
  48.  
  49.     if(!GetCurrentDirectory(MAX_PATH*10, Buffer))
  50.         return;
  51.  
  52.     strcpy(Buffer2,Buffer);
  53.     strcat(Buffer, "\\ClientPatches\\*.*");
  54.     fHandle = FindFirstFile(Buffer, &fd);
  55.     if(fHandle == INVALID_HANDLE_VALUE)
  56.         return;
  57.  
  58.     do
  59.     {
  60.         snprintf(Buffer3,MAX_PATH*10,"%s\\ClientPatches\\%s",Buffer2,fd.cFileName);
  61.         if(sscanf(fd.cFileName,"%4s%u.", locality, &srcversion) != 2)
  62.         {
  63.             Log.Notice("Found Incorrect : %s %s", locality, fd.cFileName);
  64.             continue;
  65.         }
  66.         else
  67.         {
  68.             Log.Notice("Found Correct : %s %s", locality, fd.cFileName);
  69.         }
  70.  
  71.         hFile = CreateFile(Buffer3, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL);
  72.         if(hFile == INVALID_HANDLE_VALUE)
  73.             continue;
  74.  
  75.         Log.Notice("PatchMgr", "Found patch for %u locale `%s`.", srcversion,locality);
  76.         pPatch = new Patch;
  77.         size = GetFileSize(hFile, &sizehigh);
  78.         pPatch->FileSize = size;
  79.         pPatch->Data = new uint8[size];
  80.         pPatch->Version = srcversion;
  81.         for(i = 0; i < 4; ++i)
  82.             pPatch->Locality[i] = static_cast<char>(tolower(locality[i]));
  83.         pPatch->Locality[4] = 0;
  84.         pPatch->uLocality = *(uint32*)pPatch->Locality;
  85.  
  86.         if(pPatch->Data== NULL)
  87.         {
  88.             // shouldn't really happen
  89.             delete pPatch;
  90.             CloseHandle(hFile);
  91.             continue;
  92.         }
  93.  
  94.         // read the whole file
  95.         ASSERT(ReadFile(hFile, pPatch->Data, pPatch->FileSize, &size, NULL));
  96.         ASSERT(size == pPatch->FileSize);
  97.  
  98.         // close the handle, no longer needed
  99.         CloseHandle(hFile);
  100.  
  101.         // md5hash the file
  102.         md5.Initialize();
  103.         md5.UpdateData(pPatch->Data, pPatch->FileSize);
  104.         md5.Finalize();
  105.         memcpy(pPatch->MD5, md5.GetDigest(), MD5_DIGEST_LENGTH);
  106.        
  107.         // add the patch to the patchlist
  108.         m_patches.push_back(pPatch);
  109.  
  110.     } while(FindNextFile(fHandle,&fd));
  111.     FindClose(fHandle);
  112. #else
  113.     /*
  114.      *nix patch loader
  115.      */
  116.     Log.Notice("PatchMgr", "Loading Patches...");
  117.     char Buffer[MAX_PATH*10];
  118.     char Buffer2[MAX_PATH*10];
  119.     char Buffer3[MAX_PATH*10];
  120.  
  121.     struct dirent ** list;
  122.     int filecount;
  123.     int read_fd;
  124.     MD5Hash md5;
  125.     Patch * pPatch;
  126.     int size;
  127.     uint32 srcversion;
  128.     char locality[5];
  129.     uint32 i;
  130.     struct stat sb;
  131.  
  132.     strcpy(Buffer, "./ClientPatches");
  133.     strcpy(Buffer2,Buffer);
  134.  
  135.     filecount = scandir("./ClientPatches", &list, 0, 0);
  136.     if(filecount <= 0 || list== NULL)
  137.     {
  138.         Log.Error("PatchMgr", "No patches found.");
  139.         return;
  140.     }
  141.  
  142.     while(filecount--)
  143.     {
  144.         snprintf(Buffer3,MAX_PATH*10,"./ClientPatches/%s",list[filecount]->d_name);
  145.         if(sscanf(list[filecount]->d_name,"%4s%u.", locality, &srcversion) != 2)
  146.             continue;
  147.  
  148.         read_fd = open(Buffer3, O_RDONLY);
  149.         if(read_fd <= 0)
  150.         {
  151.             LOG_ERROR("Cannot open %s", Buffer3);
  152.             continue;
  153.         }
  154.  
  155.         if(fstat(read_fd, &sb) < 0)
  156.         {
  157.             LOG_ERROR("Cannot stat %s", Buffer3);
  158.             continue;
  159.         }
  160.  
  161.         Log.Notice("PatchMgr", "Found patch for b%u locale `%s` (%u bytes).", srcversion,locality, sb.st_size);
  162.         pPatch = new Patch;
  163.         size = sb.st_size;
  164.         pPatch->FileSize = size;
  165.         pPatch->Data = new uint8[size];
  166.         pPatch->Version = srcversion;
  167.         for(i = 0; i < 4; ++i)
  168.             pPatch->Locality[i] = tolower(locality[i]);
  169.         pPatch->Locality[4] = 0;
  170.         pPatch->uLocality = *(uint32*)pPatch->Locality;
  171.  
  172.         if(pPatch->Data== NULL)
  173.         {
  174.             // shouldn't really happen
  175.             delete pPatch;
  176.             close(read_fd);
  177.             continue;
  178.         }
  179.  
  180.         // read the whole file
  181.         ASSERT(read(read_fd, pPatch->Data, size) == size);
  182.  
  183.         // close handle
  184.         close(read_fd);
  185.  
  186.         // md5hash the file
  187.         md5.Initialize();
  188.         md5.UpdateData(pPatch->Data, pPatch->FileSize);
  189.         md5.Finalize();
  190.         memcpy(pPatch->MD5, md5.GetDigest(), MD5_DIGEST_LENGTH);
  191.  
  192.         // add the patch to the patchlist
  193.         m_patches.push_back(pPatch);
  194.         free(list[filecount]);
  195.     }
  196.     free(list);
  197. #endif
  198. }
  199.  
  200. PatchMgr::~PatchMgr()
  201. {
  202.  
  203. }
  204.  
  205. Patch * PatchMgr::FindPatchForClient(uint32 Version, const char * Locality)
  206. {
  207.     Log.Debug("Patch", "Called");
  208.     char tmplocality[5];
  209.     uint32 ulocality;
  210.     uint32 i;
  211.     vector<Patch*>::iterator itr;
  212.     Patch * fallbackPatch = NULL;
  213.     for(i = 0; i < 4; ++i)
  214.         tmplocality[i]= static_cast<char>( tolower(Locality[i]) );
  215.     tmplocality[4]= 0;
  216.     ulocality = *(uint32*)tmplocality;
  217.     for(itr = m_patches.begin(); itr != m_patches.end(); ++itr)
  218.     {
  219.         // since localities are always 4 bytes we can do a simple int compare,
  220.         // saving a string compare ;)
  221.         Log.Debug("Patch", "Loop Happening");
  222.         Log.Debug("Patch", "Stuff %u %s", (*itr)->Version, (*itr)->uLocality);
  223.         if((*itr)->uLocality==ulocality)
  224.         {
  225.             if(fallbackPatch== NULL && (*itr)->Version== 0)
  226.                 fallbackPatch = (*itr);
  227.            
  228.             if((*itr)->Version == Version)
  229.                 return (*itr);
  230.         }
  231.     }
  232.  
  233.     return fallbackPatch;
  234. }
  235.  
  236. void PatchMgr::BeginPatchJob(Patch * pPatch, AuthSocket * pClient, uint32 Skip)
  237. {
  238.     PatchJob * pJob;
  239.  
  240.     pJob = new PatchJob(pPatch,pClient,Skip);
  241.     pClient->m_patchJob=pJob;
  242.     m_patchJobLock.Acquire();
  243.     m_patchJobs.push_back(pJob);
  244.     m_patchJobLock.Release();
  245. }
  246.  
  247. void PatchMgr::UpdateJobs()
  248. {
  249.     list<PatchJob*>::iterator itr, itr2;
  250.     m_patchJobLock.Acquire();
  251.     for(itr = m_patchJobs.begin(); itr != m_patchJobs.end();)
  252.     {
  253.         itr2 = itr;
  254.         ++itr;
  255.  
  256.         if(!(*itr2)->Update())
  257.         {
  258.             (*itr2)->GetClient()->m_patchJob= NULL;
  259.             delete (*itr2);
  260.             m_patchJobs.erase(itr2);
  261.         }
  262.     }
  263.     m_patchJobLock.Release();
  264. }
  265.  
  266. void PatchMgr::AbortPatchJob(PatchJob * pJob)
  267. {
  268.     list<PatchJob*>::iterator itr;
  269.     m_patchJobLock.Acquire();
  270.     for(itr = m_patchJobs.begin(); itr != m_patchJobs.end(); ++itr)
  271.     {
  272.         if((*itr)==pJob)
  273.         {
  274.             m_patchJobs.erase(itr);
  275.             break;
  276.         }
  277.     }
  278.     delete pJob;
  279.     m_patchJobLock.Release();
  280. }
  281.  
  282. // this is what blizz sends.
  283. // Data (1412 bytes)
  284. // Data (91 bytes)
  285. // 1412+91=1503 (minus header bytes, 3) = 1500
  286.  
  287. #define TRANSFER_CHUNK_SIZE 1500
  288.  
  289. #pragma pack(push,1)
  290.  
  291. struct TransferInitiatePacket
  292. {
  293.     uint8 cmd;
  294.     uint8 strsize;
  295.     char name[6];
  296.     uint64 filesize;
  297.     uint8 md5hash[MD5_DIGEST_LENGTH];
  298. };
  299.  
  300. struct TransferDataPacket
  301. {
  302.     uint8 cmd;
  303.     uint16 chunk_size;
  304. };
  305.  
  306. #pragma pack(pop)
  307.  
  308. bool PatchJob::Update()
  309. {
  310.     // don't update unless the write buffer is empty
  311.     m_client->BurstBegin();
  312.     if(m_client->writeBuffer.GetSize()!= 0)
  313.     {
  314.         m_client->BurstEnd();
  315.         return true;
  316.     }
  317.  
  318.     // send 1500 byte chunks
  319.     TransferDataPacket header;
  320.     bool result;
  321.     header.cmd = 0x31;
  322.     header.chunk_size = static_cast<uint16>( (m_bytesLeft>1500)?1500:m_bytesLeft );
  323.     //Log.Debug("PatchJob", "Sending %u byte chunk", header.chunk_size);
  324.  
  325.     result = m_client->BurstSend((const uint8*)&header,sizeof(TransferDataPacket));
  326.     if(result)
  327.     {
  328.         result = m_client->BurstSend(m_dataPointer, header.chunk_size);
  329.         if(result)
  330.         {
  331.             m_dataPointer += header.chunk_size;
  332.             m_bytesSent += header.chunk_size;
  333.             m_bytesLeft -= header.chunk_size;
  334.         }
  335.     }
  336.  
  337.     if(result)
  338.         m_client->BurstPush();
  339.  
  340.     m_client->BurstEnd();
  341.  
  342.     // no need to check the result here, could just be a full buffer and not necessarily a fatal error.
  343.     return (m_bytesLeft>0)?true:false;
  344. }
  345.  
  346. bool PatchMgr::InitiatePatch(Patch * pPatch, AuthSocket * pClient)
  347. {
  348.     // send initiate packet
  349.     TransferInitiatePacket init;
  350.     bool result;
  351.  
  352.     init.cmd = 0x30;
  353.     init.strsize=5;
  354.     init.name[0] = 'P'; init.name[1] = 'a'; init.name[2] = 't'; init.name[3] = 'c'; init.name[4] = 'h'; init.name[5] = '\0';
  355.     init.filesize = pPatch->FileSize;
  356.     memcpy(init.md5hash, pPatch->MD5, MD5_DIGEST_LENGTH);
  357.  
  358.     // send it to the client
  359.     pClient->BurstBegin();
  360.     result = pClient->BurstSend((const uint8*)&init,sizeof(TransferInitiatePacket));
  361.     if(result)
  362.         pClient->BurstPush();
  363.     pClient->BurstEnd();
  364.     return result;
  365. }
Advertisement
Add Comment
Please, Sign In to add comment