Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- initialiseSingleton(PatchMgr);
- PatchMgr::PatchMgr()
- {
- }
- PatchMgr::~PatchMgr()
- {
- }
- void PatchMgr::InitializePatchList()
- {
- Log.Notice ("PatchMgr", "Loading Patches...");
- const size_t path_length (MAX_PATH * 10);
- char base_path[path_length];
- char absolute_filename[path_length];
- #ifdef WIN32
- char file_pattern[path_length];
- if (!GetCurrentDirectory (sizeof (file_pattern), file_pattern))
- return;
- strcpy (base_path, file_pattern);
- strcat (file_pattern, "\\ClientPatches\\*.*");
- WIN32_FIND_DATA fd;
- HANDLE fHandle (FindFirstFile (file_pattern, &fd));
- if (fHandle == INVALID_HANDLE_VALUE)
- return;
- #else
- strcpy (base_path, ".");
- struct dirent ** list (NULL);
- int filecount (scandir ("./ClientPatches", &list, 0, 0));
- if (filecount <= 0 || list== NULL)
- {
- Log.Error("PatchMgr", "No patches found.");
- return;
- }
- #endif
- #ifdef WIN32
- do
- #else
- while (filecount--)
- #endif
- {
- #ifdef WIN32
- snprintf (absolute_filename, sizeof (absolute_filename), "%s\\ClientPatches\\%s", base_path, fd.cFileName);
- #else
- snprintf (absolute_filename, sizeof (absolute_filename), "%s/ClientPatches/%s", base_path, list[filecount]->d_name);
- #endif
- uint32 srcversion;
- char locale[5] = "****";
- if (sscanf(fd.cFileName,"%4s%u.", locale, &srcversion) != 2)
- {
- Log.Notice ("PatchMgr", "Found incorrect patch file: %4s %s", locale, fd.cFileName);
- continue;
- }
- #ifdef WIN32
- HANDLE hFile (CreateFile (absolute_filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL));
- if(hFile == INVALID_HANDLE_VALUE)
- continue;
- #else
- const int file_descriptor (open (absolute_filename, O_RDONLY));
- if (file_descriptor <= 0)
- {
- LOG_ERROR("Cannot open %s", absolute_filename);
- continue;
- }
- struct stat stat_buffer;
- if(fstat(file_descriptor, &stat_buffer) < 0)
- {
- LOG_ERROR("Cannot stat %s", absolute_filename);
- continue;
- }
- #endif
- Log.Notice ("PatchMgr", "Found patch for %u locale `%s`.", srcversion, locale);
- Patch* patch (new Patch);
- #ifdef WIN32
- DWORD sizehigh;
- DWORD size (GetFileSize (hFile, &sizehigh));
- #else
- unsigned int size (stat_buffer.st_size);
- #endif
- patch->FileSize = size;
- patch->Data = new uint8[size];
- patch->Version = srcversion;
- for(size_t i (0); i < 4; ++i)
- patch->Locality[i] = static_cast<char> (tolower (patch->Locality[i]));
- patch->Locality[4] = '\0';
- patch->uLocality = *(uint32*) (patch->Locality);
- #ifdef WIN32
- const bool result (ReadFile (hFile, patch->Data, patch->FileSize, &size, NULL));
- #else
- size = read (file_descriptor, pPatch->Data, size);
- const bool result (size > 0);
- #endif
- ASSERT (result);
- ASSERT (size == patch->FileSize);
- #ifdef WIN32
- CloseHandle (hFile);
- #else
- close (file_descriptor);
- #endif
- MD5Hash md5;
- md5.Initialize();
- md5.UpdateData (patch->Data, patch->FileSize);
- md5.Finalize();
- memcpy (patch->MD5, md5.GetDigest(), MD5_DIGEST_LENGTH);
- m_patches.push_back (patch);
- #ifndef WIN32
- free (list[filecount]);
- #endif
- }
- #ifdef WIN32
- while (FindNextFile (fHandle, &fd));
- FindClose(fHandle);
- #else
- free (list);
- #endif
- }
- const Patch* PatchMgr::FindPatchForClient(uint32 Version, const char * locale) const
- {
- const char lower_case[4] = {tolower (locale[0]), tolower (locale[1]), tolower (locale[2]), tolower (locale[3])};
- const uint32 ulocale (*(uint32*)lower_case);
- const Patch * fallbackPatch (NULL);
- for( std::vector<Patch*>::const_iterator patch_it (m_patches.begin())
- ; patch_it != m_patches.end()
- ; ++patch_it
- )
- {
- const Patch* patch (*patch_it);
- if(patch->uLocality == ulocale)
- {
- if(patch->Version == Version)
- return patch;
- if(fallbackPatch == NULL && patch->Version == 0)
- fallbackPatch = patch;
- }
- }
- return fallbackPatch;
- }
- void PatchMgr::BeginPatchJob(Patch * pPatch, AuthSocket * pClient, uint32 Skip)
- {
- Log.Debug("AutoPatcher","Creating new job.");
- PatchJob * pJob;
- pJob = new PatchJob(pPatch,pClient,Skip);
- pClient->m_patchJob=pJob;
- m_patchJobLock.Acquire();
- m_patchJobs.push_back(pJob);
- m_patchJobLock.Release();
- Log.Debug("AutoPatcher","New Job Created.");
- }
- void PatchMgr::UpdateJobs()
- {
- //Log.Debug("AutoPatcher","Updating Jobs...");
- list<PatchJob*>::iterator itr, itr2;
- m_patchJobLock.Acquire();
- for(itr = m_patchJobs.begin(); itr != m_patchJobs.end();)
- {
- itr2 = itr;
- ++itr;
- if(!(*itr2)->Update())
- {
- Log.Debug("AutoPatcher","Deleting job.");
- (*itr2)->GetClient()->m_patchJob= NULL;
- delete (*itr2);
- m_patchJobs.erase(itr2);
- }
- }
- m_patchJobLock.Release();
- }
- void PatchMgr::AbortPatchJob(PatchJob * pJob)
- {
- list<PatchJob*>::iterator itr;
- m_patchJobLock.Acquire();
- for(itr = m_patchJobs.begin(); itr != m_patchJobs.end(); ++itr)
- {
- if((*itr)==pJob)
- {
- m_patchJobs.erase(itr);
- break;
- }
- }
- delete pJob;
- m_patchJobLock.Release();
- }
- // this is what blizz sends.
- // Data (1412 bytes)
- // Data (91 bytes)
- // 1412+91=1503 (minus header bytes, 3) = 1500
- #define TRANSFER_CHUNK_SIZE 1500
- #pragma pack(push,1)
- struct TransferInitiatePacket
- {
- uint8 cmd;
- uint8 strsize;
- char name[5];
- uint64 filesize;
- uint8 md5hash[MD5_DIGEST_LENGTH];
- };
- struct TransferDataPacket
- {
- uint8 cmd;
- uint16 chunk_size;
- };
- #pragma pack(pop)
- bool PatchJob::Update()
- {
- //Log.Debug("AutoPatcher","Updating PatchJob...");
- // don't update unless the write buffer is empty
- m_client->BurstBegin();
- if(m_client->writeBuffer.GetSize()!= 0)
- {
- Log.Debug("AutoPatcher","Write buffer still got data since last write.");
- Log.Debug("PatchJob", "Client Write Buffer Size: %u", m_client->writeBuffer.GetSize());
- m_client->BurstEnd();
- return true;
- }
- // send 1500 byte chunks
- TransferDataPacket header;
- bool result;
- header.cmd = 0x31;
- header.chunk_size = static_cast<uint16>( (m_bytesLeft>1500)?1500:m_bytesLeft );
- Log.Debug("PatchJob", "Sending %u byte chunk", header.chunk_size);
- result = m_client->BurstSend((const uint8*)&header,sizeof(TransferDataPacket));
- if(result)
- {
- result = m_client->BurstSend(m_dataPointer, header.chunk_size);
- if(result)
- {
- m_dataPointer += header.chunk_size;
- m_bytesSent += header.chunk_size;
- m_bytesLeft -= header.chunk_size;
- }
- }
- if(result)
- {
- Log.Debug("PatchJob", "BurtPush()");
- m_client->BurstPush();
- }
- //Log.Debug("AutoPatcher", "Sent 1500byte chunk.");
- m_client->BurstEnd();
- Log.Debug("PatchJob", "Bytes Left: %u", m_bytesLeft);
- Log.Debug("PatchJob", "Client Write Buffer Size: %u", m_client->writeBuffer.GetSize());
- // no need to check the result here, could just be a full buffer and not necessarily a fatal error.
- return (m_bytesLeft>0)?true:false;
- }
- bool PatchMgr::InitiatePatch(Patch * pPatch, AuthSocket * pClient)
- {
- Log.Debug("AutoPatcher","Initiating patch.");
- // send initiate packet
- TransferInitiatePacket init;
- bool result;
- init.cmd = 0x30;
- init.strsize=5;
- init.name[0] = 'P';
- init.name[1] = 'a';
- init.name[2] = 't';
- init.name[3] = 'c';
- init.name[4] = 'h';
- //init.name[5] = '\0';
- init.filesize = pPatch->FileSize;
- Log.Debug("AutoPatcher", "File Size : %u", pPatch->FileSize);
- memcpy(init.md5hash, pPatch->MD5, MD5_DIGEST_LENGTH);
- // send it to the client
- pClient->BurstBegin();
- result = pClient->BurstSend((const uint8*)&init,sizeof(TransferInitiatePacket));
- Log.Debug("AutoPatcher","Burst Result : %s", (result)?"true":"false");
- if(result)
- pClient->BurstPush();
- pClient->BurstEnd();
- return result;
- }
Advertisement
Add Comment
Please, Sign In to add comment