More preparation towards transferring avatars.
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "avatarmanager.h"
|
||||
#include <net/netpacket.h>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <openssl/md5.h>
|
||||
@@ -27,6 +28,10 @@
|
||||
using namespace std;
|
||||
using namespace boost::filesystem;
|
||||
|
||||
struct AvatarFileState
|
||||
{
|
||||
ifstream inputStream;
|
||||
};
|
||||
|
||||
AvatarManager::AvatarManager()
|
||||
{
|
||||
@@ -53,6 +58,100 @@ AvatarManager::Init(const std::string &dataDir, const std::string &cacheDir)
|
||||
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
|
||||
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);
|
||||
tmpPath /= (md5buf.ToString() + "." + fileExtension);
|
||||
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);
|
||||
m_avatars.insert(AvatarMap::value_type(md5buf, fileName));
|
||||
retVal = true;
|
||||
|
||||
Reference in New Issue
Block a user