More preparation towards transferring avatars.

This commit is contained in:
lotodore
2007-10-05 14:23:36 +00:00
parent 90bd87d776
commit 5d974a6450
6 changed files with 228 additions and 1 deletions
+11
View File
@@ -136,6 +136,17 @@ Server/Client Reply: Avatar File
[Additional blocks will be sent if data is more than 256 Bytes.] [Additional blocks will be sent if data is more than 256 Bytes.]
Server/Client Reply: End of Avatar
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Message Type = 6 | Message Length = 8 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Request ID |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Basic Structure: Game Info Block Basic Structure: Game Info Block
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+13
View File
@@ -24,6 +24,14 @@
#include <core/crypthelper.h> #include <core/crypthelper.h>
#include <map> #include <map>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#define MAX_AVATAR_FILE_SIZE 30720
struct AvatarFileState;
class NetPacket;
class AvatarManager class AvatarManager
{ {
public: public:
@@ -33,6 +41,11 @@ public:
bool Init(const std::string &dataDir, const std::string &cacheDir); bool Init(const std::string &dataDir, const std::string &cacheDir);
boost::shared_ptr<AvatarFileState> OpenAvatarFileForChunkRead(const std::string &fileName, unsigned &outFileSize);
unsigned ChunkReadAvatarFile(boost::shared_ptr<AvatarFileState> fileState, unsigned char *data, unsigned chunkSize);
bool SendAvatarFile(const std::string &fileName, unsigned requestId, boost::function<void (boost::shared_ptr<NetPacket>)> sender);
bool GetHashForAvatar(const std::string &fileName, MD5Buf &md5buf); bool GetHashForAvatar(const std::string &fileName, MD5Buf &md5buf);
bool GetAvatarFileName(const MD5Buf &md5buf, std::string &fileName) const; bool GetAvatarFileName(const MD5Buf &md5buf, std::string &fileName) const;
bool StoreAvatarInCache(const MD5Buf &md5buf, const std::string &fileExtension, const unsigned char *data, unsigned size); bool StoreAvatarInCache(const MD5Buf &md5buf, const std::string &fileExtension, const unsigned char *data, unsigned size);
+100 -1
View File
@@ -18,6 +18,7 @@
***************************************************************************/ ***************************************************************************/
#include "avatarmanager.h" #include "avatarmanager.h"
#include <net/netpacket.h>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <openssl/md5.h> #include <openssl/md5.h>
@@ -27,6 +28,10 @@
using namespace std; using namespace std;
using namespace boost::filesystem; using namespace boost::filesystem;
struct AvatarFileState
{
ifstream inputStream;
};
AvatarManager::AvatarManager() AvatarManager::AvatarManager()
{ {
@@ -53,6 +58,100 @@ AvatarManager::Init(const std::string &dataDir, const std::string &cacheDir)
return retVal; return retVal;
} }
boost::shared_ptr<AvatarFileState>
AvatarManager::OpenAvatarFileForChunkRead(const std::string &fileName, unsigned &outFileSize)
{
outFileSize = 0;
boost::shared_ptr<AvatarFileState> retVal;
try
{
boost::shared_ptr<AvatarFileState> fileState(new AvatarFileState);
fileState->inputStream.open(fileName.c_str(), ios_base::in | ios_base::binary);
if (!fileState->inputStream.fail())
{
// Find out file size.
// Not fully portable, but works on win/linux/mac.
fileState->inputStream.seekg(0, ios_base::beg);
std::streampos startPos = fileState->inputStream.tellg();
fileState->inputStream.seekg(0, ios_base::end);
std::streampos endPos = fileState->inputStream.tellg();
fileState->inputStream.seekg(0, ios_base::beg);
std::streamoff posDiff(endPos - startPos);
outFileSize = (unsigned)posDiff;
if (outFileSize <= MAX_AVATAR_FILE_SIZE)
retVal = fileState;
}
} catch (...)
{
}
return retVal;
}
unsigned
AvatarManager::ChunkReadAvatarFile(boost::shared_ptr<AvatarFileState> fileState, unsigned char *data, unsigned chunkSize)
{
unsigned retVal = 0;
if (fileState.get())
{
try
{
if (!fileState->inputStream.fail() && !fileState->inputStream.eof())
{
fileState->inputStream.read((char *)data, chunkSize);
retVal = fileState->inputStream.gcount();
}
} catch (...)
{
}
}
return retVal;
}
bool
AvatarManager::SendAvatarFile(const string &fileName, unsigned requestId, boost::function<void (boost::shared_ptr<NetPacket>)> sender)
{
bool retVal = false;
unsigned fileSize;
boost::shared_ptr<AvatarFileState> tmpState = OpenAvatarFileForChunkRead(fileName, fileSize);
if (tmpState.get() && fileSize)
{
boost::shared_ptr<NetPacket> avatarHeader(new NetPacketAvatarHeader);
NetPacketAvatarHeader::Data avatarHeaderData;
avatarHeaderData.requestId = requestId;
avatarHeaderData.avatarFileSize = fileSize;
avatarHeaderData.avatarFileType = AVATAR_TYPE_PNG; // TODO
static_cast<NetPacketAvatarHeader *>(avatarHeader.get())->SetData(avatarHeaderData);
sender(avatarHeader);
unsigned numBytes = 0;
unsigned totalBytesRead = 0;
do
{
boost::shared_ptr<NetPacketAvatarFile> avatarFile(new NetPacketAvatarFile);
NetPacketAvatarFile::Data avatarFileData;
avatarFileData.fileData.resize(MAX_FILE_DATA_SIZE);
numBytes = ChunkReadAvatarFile(tmpState, &avatarFileData.fileData[0], MAX_FILE_DATA_SIZE);
if (numBytes)
{
avatarFileData.fileData.resize(numBytes);
avatarFileData.requestId = requestId;
totalBytesRead += numBytes;
static_cast<NetPacketAvatarFile *>(avatarFile.get())->SetData(avatarFileData);
sender(avatarFile);
}
} while (numBytes);
// TODO error handling if numBytes != totalBytesRead
boost::shared_ptr<NetPacket> avatarEnd(new NetPacketAvatarEnd);
NetPacketAvatarEnd::Data avatarEndData;
avatarEndData.requestId = requestId;
static_cast<NetPacketAvatarEnd *>(avatarEnd.get())->SetData(avatarEndData);
sender(avatarEnd);
retVal = true;
}
// else TODO error handling
return retVal;
}
bool bool
AvatarManager::GetHashForAvatar(const std::string &fileName, MD5Buf &md5buf) AvatarManager::GetHashForAvatar(const std::string &fileName, MD5Buf &md5buf)
{ {
@@ -106,7 +205,7 @@ AvatarManager::StoreAvatarInCache(const MD5Buf &md5buf, const std::string &fileE
path tmpPath(m_cacheDir); path tmpPath(m_cacheDir);
tmpPath /= (md5buf.ToString() + "." + fileExtension); tmpPath /= (md5buf.ToString() + "." + fileExtension);
string fileName(tmpPath.file_string()); string fileName(tmpPath.file_string());
ofstream o(fileName.c_str()); ofstream o(fileName.c_str(), ios_base::out | ios_base::binary);
o.write((const char *)data, size); o.write((const char *)data, size);
m_avatars.insert(AvatarMap::value_type(md5buf, fileName)); m_avatars.insert(AvatarMap::value_type(md5buf, fileName));
retVal = true; retVal = true;
+7
View File
@@ -527,6 +527,13 @@ ClientStateWaitSession::InternalProcess(ClientThread &client, boost::shared_ptr<
client.SetSessionEstablished(true); client.SetSessionEstablished(true);
retVal = MSG_SOCK_SESSION_DONE; retVal = MSG_SOCK_SESSION_DONE;
} }
else if (packet->ToNetPacketRetrieveAvatar())
{
NetPacketRetrieveAvatar::Data retrieveAvatarData;
packet->ToNetPacketRetrieveAvatar()->GetData(retrieveAvatarData);
// Before letting us join the lobby, the server requests our avatar.
}
return retVal; return retVal;
} }
+72
View File
@@ -32,6 +32,7 @@ using namespace std;
#define NET_TYPE_RETRIEVE_AVATAR 0x0003 #define NET_TYPE_RETRIEVE_AVATAR 0x0003
#define NET_TYPE_AVATAR_HEADER 0x0004 #define NET_TYPE_AVATAR_HEADER 0x0004
#define NET_TYPE_AVATAR_FILE 0x0005 #define NET_TYPE_AVATAR_FILE 0x0005
#define NET_TYPE_AVATAR_END 0x0006
#define NET_TYPE_GAME_LIST_NEW 0x0010 #define NET_TYPE_GAME_LIST_NEW 0x0010
#define NET_TYPE_GAME_LIST_UPDATE 0x0011 #define NET_TYPE_GAME_LIST_UPDATE 0x0011
#define NET_TYPE_GAME_LIST_PLAYER_JOINED 0x0012 #define NET_TYPE_GAME_LIST_PLAYER_JOINED 0x0012
@@ -157,6 +158,12 @@ struct GCC_PACKED NetPacketAvatarFileData
u_int32_t requestId; u_int32_t requestId;
}; };
struct GCC_PACKED NetPacketAvatarEndData
{
NetPacketHeader head;
u_int32_t requestId;
};
struct GCC_PACKED GameInfoData struct GCC_PACKED GameInfoData
{ {
u_int16_t maxNumberOfPlayers; u_int16_t maxNumberOfPlayers;
@@ -587,6 +594,9 @@ NetPacket::Create(char *data, unsigned &dataSize)
case NET_TYPE_AVATAR_FILE: case NET_TYPE_AVATAR_FILE:
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketAvatarFile); tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketAvatarFile);
break; break;
case NET_TYPE_AVATAR_END:
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketAvatarEnd);
break;
case NET_TYPE_GAME_LIST_NEW: case NET_TYPE_GAME_LIST_NEW:
tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketGameListNew); tmpPacket = boost::shared_ptr<NetPacket>(new NetPacketGameListNew);
break; break;
@@ -800,6 +810,12 @@ NetPacket::ToNetPacketAvatarFile() const
return NULL; return NULL;
} }
const NetPacketAvatarEnd *
NetPacket::ToNetPacketAvatarEnd() const
{
return NULL;
}
const NetPacketGameListNew * const NetPacketGameListNew *
NetPacket::ToNetPacketGameListNew() const NetPacket::ToNetPacketGameListNew() const
{ {
@@ -1431,6 +1447,62 @@ NetPacketAvatarFile::InternalCheck(const NetPacketHeader*) const
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
NetPacketAvatarEnd::NetPacketAvatarEnd()
: NetPacket(NET_TYPE_AVATAR_END, sizeof(NetPacketAvatarEndData), sizeof(NetPacketAvatarEndData))
{
}
NetPacketAvatarEnd::~NetPacketAvatarEnd()
{
}
boost::shared_ptr<NetPacket>
NetPacketAvatarEnd::Clone() const
{
boost::shared_ptr<NetPacket> newPacket(new NetPacketAvatarEnd);
try
{
newPacket->SetRawData(GetRawData());
} catch (const NetException &)
{
// Need to return the new packet anyway.
}
return newPacket;
}
void
NetPacketAvatarEnd::SetData(const NetPacketAvatarEnd::Data &inData)
{
NetPacketAvatarEndData *tmpData = (NetPacketAvatarEndData *)GetRawData();
tmpData->requestId = htonl(inData.requestId);
// Check the packet - just in case.
Check(GetRawData());
}
void
NetPacketAvatarEnd::GetData(NetPacketAvatarEnd::Data &outData) const
{
NetPacketAvatarEndData *tmpData = (NetPacketAvatarEndData *)GetRawData();
outData.requestId = ntohl(tmpData->requestId);
}
const NetPacketAvatarEnd *
NetPacketAvatarEnd::ToNetPacketAvatarEnd() const
{
return this;
}
void
NetPacketAvatarEnd::InternalCheck(const NetPacketHeader*) const
{
// Nothing to do.
}
//-----------------------------------------------------------------------------
NetPacketGameListNew::NetPacketGameListNew() NetPacketGameListNew::NetPacketGameListNew()
: NetPacket(NET_TYPE_GAME_LIST_NEW, sizeof(NetPacketGameListNewData), MAX_PACKET_SIZE) : NetPacket(NET_TYPE_GAME_LIST_NEW, sizeof(NetPacketGameListNewData), MAX_PACKET_SIZE)
{ {
+25
View File
@@ -50,6 +50,7 @@ class NetPacketInitAck;
class NetPacketRetrieveAvatar; class NetPacketRetrieveAvatar;
class NetPacketAvatarHeader; class NetPacketAvatarHeader;
class NetPacketAvatarFile; class NetPacketAvatarFile;
class NetPacketAvatarEnd;
class NetPacketGameListNew; class NetPacketGameListNew;
class NetPacketGameListUpdate; class NetPacketGameListUpdate;
class NetPacketGameListPlayerJoined; class NetPacketGameListPlayerJoined;
@@ -106,6 +107,7 @@ public:
virtual const NetPacketRetrieveAvatar *ToNetPacketRetrieveAvatar() const; virtual const NetPacketRetrieveAvatar *ToNetPacketRetrieveAvatar() const;
virtual const NetPacketAvatarHeader *ToNetPacketAvatarHeader() const; virtual const NetPacketAvatarHeader *ToNetPacketAvatarHeader() const;
virtual const NetPacketAvatarFile *ToNetPacketAvatarFile() const; virtual const NetPacketAvatarFile *ToNetPacketAvatarFile() const;
virtual const NetPacketAvatarEnd *ToNetPacketAvatarEnd() const;
virtual const NetPacketGameListNew *ToNetPacketGameListNew() const; virtual const NetPacketGameListNew *ToNetPacketGameListNew() const;
virtual const NetPacketGameListUpdate *ToNetPacketGameListUpdate() const; virtual const NetPacketGameListUpdate *ToNetPacketGameListUpdate() const;
virtual const NetPacketGameListPlayerJoined *ToNetPacketGameListPlayerJoined() const; virtual const NetPacketGameListPlayerJoined *ToNetPacketGameListPlayerJoined() const;
@@ -281,6 +283,29 @@ protected:
virtual void InternalCheck(const NetPacketHeader* data) const; virtual void InternalCheck(const NetPacketHeader* data) const;
}; };
class NetPacketAvatarEnd : public NetPacket
{
public:
struct Data
{
u_int32_t requestId;
};
NetPacketAvatarEnd();
virtual ~NetPacketAvatarEnd();
virtual boost::shared_ptr<NetPacket> Clone() const;
void SetData(const Data &inData);
void GetData(Data &outData) const;
virtual const NetPacketAvatarEnd *ToNetPacketAvatarEnd() const;
protected:
virtual void InternalCheck(const NetPacketHeader* data) const;
};
class NetPacketGameListNew : public NetPacket class NetPacketGameListNew : public NetPacket
{ {
public: public: