mirror of
https://github.com/mangosfour/server.git
synced 2025-12-16 13:37:00 +00:00
[9935] ACE realmd, thanks to Zor and Vladimir for windows.
This commit is contained in:
parent
d4f1b510ae
commit
8a1fd9e086
13 changed files with 835 additions and 338 deletions
194
src/realmd/PatchHandler.cpp
Normal file
194
src/realmd/PatchHandler.cpp
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
|
||||
#include "PatchHandler.h"
|
||||
#include "AuthCodes.h"
|
||||
#include "Log.h"
|
||||
#include "Common.h"
|
||||
|
||||
#include <ace/OS_NS_sys_socket.h>
|
||||
#include <ace/OS_NS_dirent.h>
|
||||
#include <ace/OS_NS_errno.h>
|
||||
#include <ace/OS_NS_unistd.h>
|
||||
|
||||
#include <ace/os_include/netinet/os_tcp.h>
|
||||
|
||||
#ifndef MSG_NOSIGNAL
|
||||
#define MSG_NOSIGNAL 0
|
||||
#endif
|
||||
|
||||
#if defined( __GNUC__ )
|
||||
#pragma pack(1)
|
||||
#else
|
||||
#pragma pack(push,1)
|
||||
#endif
|
||||
|
||||
struct Chunk
|
||||
{
|
||||
ACE_UINT8 cmd;
|
||||
ACE_UINT16 data_size;
|
||||
ACE_UINT8 data[4096]; // 4096 - page size on most arch
|
||||
};
|
||||
|
||||
#if defined( __GNUC__ )
|
||||
#pragma pack()
|
||||
#else
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
PatchHandler::PatchHandler(ACE_HANDLE socket, ACE_HANDLE patch)
|
||||
{
|
||||
reactor(NULL);
|
||||
set_handle(socket);
|
||||
patch_fd_ = patch;
|
||||
}
|
||||
|
||||
PatchHandler::~PatchHandler()
|
||||
{
|
||||
if(patch_fd_ != ACE_INVALID_HANDLE)
|
||||
ACE_OS::close(patch_fd_);
|
||||
}
|
||||
|
||||
int PatchHandler::open(void*)
|
||||
{
|
||||
if(get_handle() == ACE_INVALID_HANDLE || patch_fd_ == ACE_INVALID_HANDLE)
|
||||
return -1;
|
||||
|
||||
int nodelay = 0;
|
||||
if (-1 == peer().set_option(ACE_IPPROTO_TCP,
|
||||
TCP_NODELAY,
|
||||
&nodelay,
|
||||
sizeof(nodelay)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(TCP_CORK)
|
||||
int cork = 1;
|
||||
if (-1 == peer().set_option(ACE_IPPROTO_TCP,
|
||||
TCP_CORK,
|
||||
&cork,
|
||||
sizeof(cork)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif //TCP_CORK
|
||||
|
||||
(void) peer().disable(ACE_NONBLOCK);
|
||||
|
||||
return activate(THR_NEW_LWP | THR_DETACHED | THR_INHERIT_SCHED);
|
||||
}
|
||||
|
||||
int PatchHandler::svc(void)
|
||||
{
|
||||
// Do 1 second sleep, similar to the one in game/WorldSocket.cpp
|
||||
// Seems client have problems with too fast sends.
|
||||
ACE_OS::sleep(1);
|
||||
|
||||
int flags = MSG_NOSIGNAL;
|
||||
|
||||
Chunk data;
|
||||
data.cmd = XFER_DATA;
|
||||
|
||||
ssize_t r;
|
||||
|
||||
while((r = ACE_OS::read(patch_fd_, data.data, sizeof(data.data))) > 0)
|
||||
{
|
||||
data.data_size = (ACE_UINT16)r;
|
||||
|
||||
if(peer().send((const char*)&data,
|
||||
((size_t) r) + sizeof(data) - sizeof(data.data),
|
||||
flags) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if(r == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PatchCache::~PatchCache()
|
||||
{
|
||||
for (Patches::iterator i = patches_.begin (); i != patches_.end (); i++)
|
||||
delete i->second;
|
||||
}
|
||||
|
||||
PatchCache::PatchCache()
|
||||
{
|
||||
LoadPatchesInfo();
|
||||
}
|
||||
|
||||
PatchCache* PatchCache::instance()
|
||||
{
|
||||
return ACE_Singleton<PatchCache, ACE_Thread_Mutex>::instance();
|
||||
}
|
||||
|
||||
void PatchCache::LoadPatchMD5(const char* szFileName)
|
||||
{
|
||||
// Try to open the patch file
|
||||
std::string path = "./patches/";
|
||||
path += szFileName;
|
||||
FILE * pPatch = fopen(path.c_str (), "rb");
|
||||
sLog.outDebug("Loading patch info from %s", path.c_str());
|
||||
|
||||
if(!pPatch)
|
||||
return;
|
||||
|
||||
// Calculate the MD5 hash
|
||||
MD5_CTX ctx;
|
||||
MD5_Init(&ctx);
|
||||
|
||||
const size_t check_chunk_size = 4*1024;
|
||||
|
||||
ACE_UINT8 buf[check_chunk_size];
|
||||
|
||||
while(!feof (pPatch))
|
||||
{
|
||||
size_t read = fread(buf, 1, check_chunk_size, pPatch);
|
||||
MD5_Update(&ctx, buf, read);
|
||||
}
|
||||
|
||||
fclose(pPatch);
|
||||
|
||||
// Store the result in the internal patch hash map
|
||||
patches_[path] = new PATCH_INFO;
|
||||
MD5_Final((ACE_UINT8 *) & patches_[path]->md5, &ctx);
|
||||
}
|
||||
|
||||
bool PatchCache::GetHash(const char * pat, ACE_UINT8 mymd5[MD5_DIGEST_LENGTH])
|
||||
{
|
||||
for (Patches::iterator i = patches_.begin (); i != patches_.end (); i++)
|
||||
if (!stricmp(pat, i->first.c_str ()))
|
||||
{
|
||||
memcpy(mymd5, i->second->md5, MD5_DIGEST_LENGTH);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void PatchCache::LoadPatchesInfo()
|
||||
{
|
||||
ACE_DIR* dirp = ACE_OS::opendir(ACE_TEXT("./patches/"));
|
||||
|
||||
if(!dirp)
|
||||
return;
|
||||
|
||||
ACE_DIRENT* dp;
|
||||
|
||||
while((dp = ACE_OS::readdir(dirp)) != NULL)
|
||||
{
|
||||
int l = strlen(dp->d_name);
|
||||
if (l < 8)
|
||||
continue;
|
||||
|
||||
if(!memcmp(&dp->d_name[l - 4], ".mpq", 4))
|
||||
LoadPatchMD5(dp->d_name);
|
||||
}
|
||||
|
||||
ACE_OS::closedir(dirp);
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue