2 * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "PatchHandler.h"
24 #include "AuthCodes.h"
28 #include <ace/OS_NS_sys_socket.h>
29 #include <ace/OS_NS_dirent.h>
30 #include <ace/OS_NS_errno.h>
31 #include <ace/OS_NS_unistd.h>
33 #include <ace/os_include/netinet/os_tcp.h>
36 #define MSG_NOSIGNAL 0
39 #if defined( __GNUC__ )
49 ACE_UINT8 data
[4096]; // 4096 - page size on most arch
52 #if defined( __GNUC__ )
58 PatchHandler::PatchHandler(ACE_HANDLE socket
, ACE_HANDLE patch
)
65 PatchHandler::~PatchHandler()
67 if(patch_fd_
!= ACE_INVALID_HANDLE
)
68 ACE_OS::close(patch_fd_
);
71 int PatchHandler::open(void*)
73 if(get_handle() == ACE_INVALID_HANDLE
|| patch_fd_
== ACE_INVALID_HANDLE
)
77 if (-1 == peer().set_option(ACE_IPPROTO_TCP
,
87 if (-1 == peer().set_option(ACE_IPPROTO_TCP
,
96 (void) peer().disable(ACE_NONBLOCK
);
98 return activate(THR_NEW_LWP
| THR_DETACHED
| THR_INHERIT_SCHED
);
101 int PatchHandler::svc(void)
103 // Do 1 second sleep, similar to the one in game/WorldSocket.cpp
104 // Seems client have problems with too fast sends.
107 int flags
= MSG_NOSIGNAL
;
110 data
.cmd
= XFER_DATA
;
114 while((r
= ACE_OS::read(patch_fd_
, data
.data
, sizeof(data
.data
))) > 0)
116 data
.data_size
= (ACE_UINT16
)r
;
118 if(peer().send((const char*)&data
,
119 ((size_t) r
) + sizeof(data
) - sizeof(data
.data
),
134 PatchCache::~PatchCache()
136 for (Patches::iterator i
= patches_
.begin (); i
!= patches_
.end (); i
++)
140 PatchCache::PatchCache()
145 PatchCache
* PatchCache::instance()
147 return ACE_Singleton
<PatchCache
, ACE_Thread_Mutex
>::instance();
150 void PatchCache::LoadPatchMD5(const char* szFileName
)
152 // Try to open the patch file
153 std::string path
= "./patches/";
155 FILE * pPatch
= fopen(path
.c_str (), "rb");
156 sLog
.outDebug("Loading patch info from %s", path
.c_str());
161 // Calculate the MD5 hash
165 const size_t check_chunk_size
= 4*1024;
167 ACE_UINT8 buf
[check_chunk_size
];
169 while(!feof (pPatch
))
171 size_t read
= fread(buf
, 1, check_chunk_size
, pPatch
);
172 MD5_Update(&ctx
, buf
, read
);
177 // Store the result in the internal patch hash map
178 patches_
[path
] = new PATCH_INFO
;
179 MD5_Final((ACE_UINT8
*) & patches_
[path
]->md5
, &ctx
);
182 bool PatchCache::GetHash(const char * pat
, ACE_UINT8 mymd5
[MD5_DIGEST_LENGTH
])
184 for (Patches::iterator i
= patches_
.begin (); i
!= patches_
.end (); i
++)
185 if (!stricmp(pat
, i
->first
.c_str ()))
187 memcpy(mymd5
, i
->second
->md5
, MD5_DIGEST_LENGTH
);
194 void PatchCache::LoadPatchesInfo()
196 ACE_DIR
* dirp
= ACE_OS::opendir(ACE_TEXT("./patches/"));
203 while((dp
= ACE_OS::readdir(dirp
)) != NULL
)
205 int l
= strlen(dp
->d_name
);
209 if(!memcmp(&dp
->d_name
[l
- 4], ".mpq", 4))
210 LoadPatchMD5(dp
->d_name
);
213 ACE_OS::closedir(dirp
);