mirror of
https://bitbucket.org/theswgsource/src-1.2.git
synced 2026-07-15 00:08:07 -04:00
765 lines
20 KiB
C++
765 lines
20 KiB
C++
#pragma warning (disable : 4786)
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
#include <stdlib.h>
|
|
#include "CommonClient.h"
|
|
#include "CommonMessages.h"
|
|
#include "Base/Platform.h"
|
|
#include <algorithm>
|
|
|
|
|
|
using namespace std;
|
|
using namespace Base;
|
|
|
|
|
|
const int CONNECTION_ATTEMPT_TIMEOUT = 4; // connection timeout in seconds
|
|
const int CONNECTION_DELAY = 5; // pause between connection attempts in seconds
|
|
const int KEEP_ALIVE_DELAY = 15; // connection keep-alive timeout in seconds
|
|
const int PORT_ALIVE_DELAY = 0; // port-alive delay in milliseconds
|
|
const int NO_DATA_TIMEOUT = 0; // no-data timeout in seconds
|
|
const int UNACKNOWLEDGED_DATA_TIMEOUT = 15; // unacknowledged-data timeout in seconds
|
|
|
|
struct RandFunction : std::unary_function<int,int>
|
|
{
|
|
int operator()(int n) { return rand()%n; }
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
CConnectionHandler::CConnectionHandler(CConnectionManager & parent, UdpConnection * connection, unsigned index) :
|
|
mParent(parent),
|
|
mConnection(connection),
|
|
mIndex(index)
|
|
{
|
|
if (mConnection)
|
|
mConnection->SetHandler(this);
|
|
}
|
|
|
|
CConnectionHandler::~CConnectionHandler()
|
|
{
|
|
if (mConnection)
|
|
{
|
|
mConnection->SetHandler(NULL);
|
|
mConnection->Disconnect();
|
|
mConnection->Release();
|
|
}
|
|
}
|
|
|
|
void CConnectionHandler::Send(const Base::ByteStream & stream)
|
|
{
|
|
if (mConnection && mConnection->GetStatus() == UdpConnection::cStatusConnected)
|
|
{
|
|
mConnection->Send(cUdpChannelReliable1, stream.getBuffer(), stream.getSize());
|
|
}
|
|
}
|
|
|
|
void CConnectionHandler::OnConnectComplete(UdpConnection *)
|
|
{
|
|
if (mConnection->GetStatus() == UdpConnection::cStatusConnected)
|
|
{
|
|
Message::Connect message;
|
|
message.SetVersion(mParent.GetCore().GetVersion());
|
|
message.SetDescription(mParent.GetCore().GetDescription());
|
|
Base::ByteStream stream;
|
|
message.pack(stream);
|
|
Send(stream);
|
|
}
|
|
else
|
|
{
|
|
OnTerminated(mConnection);
|
|
}
|
|
}
|
|
|
|
void CConnectionHandler::OnTerminated(UdpConnection *)
|
|
{
|
|
mParent.OnConnectionClosed(mIndex);
|
|
|
|
if (mConnection)
|
|
{
|
|
mConnection->SetHandler(NULL);
|
|
mConnection->Release();
|
|
mConnection = 0;
|
|
}
|
|
}
|
|
|
|
void CConnectionHandler::OnRoutePacket(UdpConnection *, const uchar *data, int dataLen)
|
|
{
|
|
unsigned short itemCount;
|
|
unsigned short messageId = 0;
|
|
unsigned trackingNumber = 0;
|
|
|
|
if (dataLen < 8)
|
|
return;
|
|
|
|
Base::ByteStream stream(data,dataLen);
|
|
Base::ByteStream::ReadIterator streamIterator = stream.begin();
|
|
|
|
Base::get(streamIterator, itemCount);
|
|
Base::get(streamIterator, messageId);
|
|
Base::get(streamIterator, trackingNumber);
|
|
|
|
if (messageId == Message::MESSAGE_CONNECT_REPLY)
|
|
{
|
|
streamIterator = stream.begin();
|
|
Message::ConnectReply message(streamIterator);
|
|
if (message.GetResult() == RESULT_SUCCESS)
|
|
mParent.OnConnectionOpened(mIndex);
|
|
else
|
|
OnTerminated(mConnection);
|
|
}
|
|
|
|
mParent.GetCore().QueueTrackedCallback(stream);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
CConnectionManager::CConnectionManager(apiCore & parent, std::vector<std::string> & serverList, unsigned maxConnections) :
|
|
mParent(parent),
|
|
mServerArray(),
|
|
mServerCount(0),
|
|
mMaxConnections(maxConnections),
|
|
mParams(),
|
|
mUdpManager(0),
|
|
mConnectionArray(),
|
|
mConnectedSet(),
|
|
mPendingSet(),
|
|
mDisconnectedQueue(),
|
|
mSendQueue(),
|
|
mConnectionCount(0),
|
|
mActiveCount(0),
|
|
mConnectionDelay(0)
|
|
{
|
|
for (unsigned serverIndex = 0; serverIndex < serverList.size(); serverIndex++)
|
|
{
|
|
std::string address = serverList[serverIndex];
|
|
unsigned portIndex = address.find(':');
|
|
if (portIndex != string::npos)
|
|
{
|
|
std::string host = address.substr(0, portIndex);
|
|
std::string port = address.substr(portIndex+1);
|
|
|
|
if (!host.length() || !port.length())
|
|
continue;
|
|
|
|
portIndex = port.find('-');
|
|
if (portIndex == string::npos)
|
|
{
|
|
if (atoi(port.c_str()) == 0)
|
|
continue;
|
|
mServerArray.push_back(address);
|
|
mServerCount++;
|
|
}
|
|
else
|
|
{
|
|
int first = atoi(port.substr(0,portIndex).c_str());
|
|
int last = atoi(port.substr(portIndex+1).c_str());
|
|
|
|
if (!first || !last)
|
|
continue;
|
|
|
|
char buffer[64];
|
|
for (int rangeIndex=first; rangeIndex<=last; rangeIndex++)
|
|
{
|
|
sprintf(buffer,"%s:%d",host.c_str(),rangeIndex);
|
|
mServerArray.push_back(std::string(buffer));
|
|
mServerCount++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mMaxConnections > mServerCount)
|
|
mMaxConnections = mServerCount;
|
|
if (mMaxConnections == 0)
|
|
mMaxConnections = 1;
|
|
|
|
//mParams.handler = this;
|
|
mParams.keepAliveDelay = parent.GetKeepAliveDelay() * 1000;
|
|
mParams.portAliveDelay = parent.GetPortAliveDelay();
|
|
mParams.incomingBufferSize = 256 * 1024;
|
|
mParams.outgoingBufferSize = 256 * 1024;
|
|
mParams.maxConnections = mMaxConnections;
|
|
mParams.hashTableSize = mMaxConnections*10;
|
|
mParams.port = 0;
|
|
|
|
mUdpManager = new UdpManager(&mParams);
|
|
|
|
srand((int)Base::getTimer()+(int)time(0));
|
|
RandFunction myRand;
|
|
random_shuffle(mServerArray.begin(), mServerArray.end(), myRand);
|
|
mConnectionArray.resize(mServerCount,0);
|
|
for (unsigned i=0; i<mServerCount; i++)
|
|
{
|
|
mDisconnectedQueue.push_back(i);
|
|
}
|
|
}
|
|
|
|
CConnectionManager::~CConnectionManager()
|
|
{
|
|
for (unsigned i=0; i<mConnectionArray.size(); i++)
|
|
{
|
|
if (mConnectionArray[i] != 0)
|
|
{
|
|
delete mConnectionArray[i];
|
|
mConnectionArray[i] = 0;
|
|
}
|
|
}
|
|
|
|
mUdpManager->Release();
|
|
}
|
|
|
|
void CConnectionManager::Process()
|
|
{
|
|
mUdpManager->GiveTime();
|
|
|
|
////////////////////////////////////////
|
|
// try a new connection if:
|
|
// 1. active connection count (pending + connected) < max connections
|
|
// 2. (and) the set of disconnect servers is not empty
|
|
// 3. (and) connection delay has expired or there are no active connections
|
|
if (mActiveCount < mMaxConnections && !mDisconnectedQueue.empty())
|
|
{
|
|
if (!mConnectionCount || mConnectionDelay < (unsigned)time(0))
|
|
{
|
|
Connect();
|
|
}
|
|
}
|
|
|
|
for (unsigned i=0; i<mServerCount; i++)
|
|
{
|
|
CConnectionHandler * handler = mConnectionArray[i];
|
|
if (!handler)
|
|
continue;
|
|
|
|
if (!handler->mConnection)
|
|
{
|
|
std::set<unsigned>::iterator iterator;
|
|
|
|
// remove from connected set
|
|
if ((iterator = mConnectedSet.find(i)) != mConnectedSet.end())
|
|
{
|
|
mConnectedSet.erase(iterator);
|
|
mActiveCount--;
|
|
mConnectionCount--;
|
|
}
|
|
|
|
// remove from pending set
|
|
if ((iterator = mPendingSet.find(i)) != mPendingSet.end())
|
|
{
|
|
mPendingSet.erase(iterator);
|
|
mActiveCount--;
|
|
}
|
|
|
|
// add to disconnected set
|
|
mDisconnectedQueue.push_back(i);
|
|
|
|
delete handler;
|
|
mConnectionArray[i] = 0;
|
|
}
|
|
else
|
|
{
|
|
UdpConnection::ChannelStatus cs;
|
|
handler->mConnection->GetChannelStatus(cUdpChannelReliable1,&cs);
|
|
if (handler->mConnection->GetStatus() == UdpConnection::cStatusDisconnected || cs.oldestUnacknowledgedAge > mParent.GetUnacknowledgedDataTimeout()*1000) // 30 seconds, fairly liberal, odds are the connection is dead after 10 seconds
|
|
{
|
|
handler->OnTerminated(handler->mConnection);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CConnectionManager::Connect()
|
|
{
|
|
unsigned index = mDisconnectedQueue.front();
|
|
mDisconnectedQueue.pop_front();
|
|
|
|
std::string address;
|
|
int port;
|
|
|
|
if (!ParseAddress(mServerArray[index],address,port))
|
|
{
|
|
mDisconnectedQueue.push_back(index);
|
|
return;
|
|
}
|
|
|
|
UdpConnection * connection = mUdpManager->EstablishConnection(address.c_str(), port, CONNECTION_ATTEMPT_TIMEOUT*1000);
|
|
if (connection)
|
|
{
|
|
mConnectionArray[index] = new CConnectionHandler(*this, connection, index);
|
|
|
|
mPendingSet.insert(index);
|
|
mActiveCount++;
|
|
}
|
|
else
|
|
{
|
|
mDisconnectedQueue.push_back(index);
|
|
mParent.OnConnectionFailed(mServerArray[index],mConnectionCount);
|
|
}
|
|
}
|
|
|
|
void CConnectionManager::Send(const Base::ByteStream & stream)
|
|
{
|
|
if (CanSend())
|
|
{
|
|
unsigned index;
|
|
CConnectionHandler * handler = 0;
|
|
while (!handler && !mSendQueue.empty())
|
|
{
|
|
index = mSendQueue.front();
|
|
mSendQueue.pop_front();
|
|
|
|
handler = mConnectionArray[index];
|
|
}
|
|
|
|
if (handler)
|
|
{
|
|
mSendQueue.push_back(index);
|
|
handler->Send(stream);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CConnectionManager::CanSend()
|
|
{
|
|
return (mConnectionCount > 0);
|
|
}
|
|
|
|
void CConnectionManager::SetConnectionDelay()
|
|
{
|
|
mConnectionDelay = (int)time(0) + CONNECTION_DELAY;
|
|
}
|
|
|
|
void CConnectionManager::OnConnectionOpened(unsigned index)
|
|
{
|
|
mPendingSet.erase(index);
|
|
mConnectedSet.insert(index);
|
|
mSendQueue.push_back(index);
|
|
mConnectionCount++;
|
|
|
|
mParent.OnConnectionOpened(mServerArray[index],mConnectionCount);
|
|
}
|
|
|
|
void CConnectionManager::OnConnectionClosed(unsigned index)
|
|
{
|
|
if (mPendingSet.find(index) != mPendingSet.end())
|
|
{
|
|
mParent.OnConnectionFailed(mServerArray[index],mConnectionCount ? mConnectionCount-1 : mConnectionCount);
|
|
}
|
|
else
|
|
{
|
|
mSendQueue.remove(index);
|
|
mParent.OnConnectionClosed(mServerArray[index],mConnectionCount);
|
|
}
|
|
}
|
|
|
|
bool CConnectionManager::ParseAddress(const std::string & full, std::string & address, int & port)
|
|
{
|
|
unsigned index = full.find(':');
|
|
if (full.length() == 0 || index == string::npos)
|
|
return false;
|
|
|
|
address = full.substr(0,index);
|
|
port = atoi(full.substr(index+1).c_str());
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
apiClient::apiClient() :
|
|
mClientCore(0)
|
|
{
|
|
}
|
|
|
|
apiClient::~apiClient()
|
|
{
|
|
}
|
|
|
|
void apiClient::Process()
|
|
{
|
|
if (mClientCore)
|
|
static_cast<apiCore *>(mClientCore)->Process();
|
|
}
|
|
|
|
void apiClient::OnConnectionOpened(const char *, unsigned)
|
|
{
|
|
}
|
|
|
|
void apiClient::OnConnectionClosed(const char *, unsigned)
|
|
{
|
|
}
|
|
|
|
void apiClient::OnConnectionFailed(const char *, unsigned)
|
|
{
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
apiCore::apiCore(apiClient * parent, const char * version, const char * serverList, const char * description, unsigned maxConnections) :
|
|
mParent(parent),
|
|
mVersion(version),
|
|
mDescription(description),
|
|
mServerArray(),
|
|
mMaxConnections(maxConnections),
|
|
mConnectionManager(0),
|
|
mTrackingIndex(1),
|
|
mTrackedMessages(),
|
|
mRequestMap(),
|
|
mCallbackQueue(),
|
|
mTrackedCallbackQueue(),
|
|
mTimeoutQueue(),
|
|
mRequestQueueSize(0),
|
|
mExpirationTimeout(0),
|
|
mInCallback(false)
|
|
{
|
|
std::string list = serverList;
|
|
unsigned offset=0;
|
|
unsigned index=0;
|
|
|
|
while ((index = list.find(' ',offset)) != std::string::npos)
|
|
{
|
|
mServerArray.push_back(list.substr(offset, index-offset));
|
|
offset = index + 1;
|
|
}
|
|
|
|
mServerArray.push_back(list.substr(offset));
|
|
|
|
if (mDescription.length() > 64)
|
|
mDescription = mDescription.substr(0,64);
|
|
}
|
|
|
|
apiCore::apiCore(apiClient * parent, const char * version, const char ** serverList, unsigned serverCount, const char * description, unsigned maxConnections) :
|
|
mParent(parent),
|
|
mVersion(version),
|
|
mDescription(description),
|
|
mServerArray(),
|
|
mMaxConnections(maxConnections),
|
|
mConnectionManager(0),
|
|
mTrackingIndex(1),
|
|
mTrackedMessages(),
|
|
mRequestMap(),
|
|
mCallbackQueue(),
|
|
mTrackedCallbackQueue(),
|
|
mTimeoutQueue(),
|
|
mRequestQueueSize(0),
|
|
mExpirationTimeout(0),
|
|
mInCallback(false)
|
|
{
|
|
for (unsigned i=0; i<serverCount; i++)
|
|
{
|
|
mServerArray.push_back(serverList[i]);
|
|
}
|
|
|
|
if (mDescription.length() > 64)
|
|
mDescription = mDescription.substr(0,64);
|
|
}
|
|
|
|
apiCore::~apiCore()
|
|
{
|
|
delete mConnectionManager;
|
|
}
|
|
|
|
int apiCore::GetKeepAliveDelay()
|
|
{
|
|
return KEEP_ALIVE_DELAY;
|
|
}
|
|
|
|
int apiCore::GetPortAliveDelay()
|
|
{
|
|
return PORT_ALIVE_DELAY;
|
|
}
|
|
|
|
int apiCore::GetNoDataTimeout()
|
|
{
|
|
return NO_DATA_TIMEOUT;
|
|
}
|
|
|
|
int apiCore::GetUnacknowledgedDataTimeout()
|
|
{
|
|
return UNACKNOWLEDGED_DATA_TIMEOUT;
|
|
}
|
|
|
|
void apiCore::NotifyConnectionOpened(const char *address, unsigned connectionCount)
|
|
{
|
|
}
|
|
|
|
void apiCore::NotifyConnectionClosed(const char *address, unsigned connectionCount)
|
|
{
|
|
}
|
|
|
|
void apiCore::NotifyConnectionFailed(const char *address, unsigned connectionCount)
|
|
{
|
|
}
|
|
|
|
void apiCore::OnConnectionOpened(const std::string & address, unsigned connectionCount)
|
|
{
|
|
NotifyConnectionOpened(address.c_str(),connectionCount);
|
|
mParent->OnConnectionOpened(address.c_str(),connectionCount);
|
|
}
|
|
|
|
void apiCore::OnConnectionClosed(const std::string & address, unsigned connectionCount)
|
|
{
|
|
NotifyConnectionClosed(address.c_str(),connectionCount);
|
|
mParent->OnConnectionClosed(address.c_str(),connectionCount);
|
|
}
|
|
|
|
void apiCore::OnConnectionFailed(const std::string & address, unsigned connectionCount)
|
|
{
|
|
NotifyConnectionFailed(address.c_str(),connectionCount);
|
|
mParent->OnConnectionFailed(address.c_str(),connectionCount);
|
|
}
|
|
|
|
bool apiCore::IsTrackedMessage(const unsigned short messageId)
|
|
{
|
|
return mTrackedMessages.find(messageId) != mTrackedMessages.end();
|
|
}
|
|
|
|
void apiCore::RegisterTrackedMessage(const unsigned short messageId)
|
|
{
|
|
mTrackedMessages.insert(messageId);
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
// This function submits a request that expects no reply
|
|
void apiCore::SubmitRequest(Message::Basic & input)
|
|
{
|
|
Base::ByteStream stream;
|
|
input.pack(stream);
|
|
|
|
if (mConnectionManager && mConnectionManager->CanSend())
|
|
mConnectionManager->Send(stream);
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
// This function submits a request that expects a reply
|
|
apiTrackingNumber apiCore::SubmitRequest(Message::Tracked & input, Message::TrackedReply & output, const void * userData, unsigned timeout)
|
|
{
|
|
////////////////////////////////////////
|
|
// Set tracking number
|
|
apiTrackingNumber trackingNumber = mTrackingIndex++;
|
|
|
|
input.SetTrackingNumber(trackingNumber);
|
|
output.SetTrackingNumber(trackingNumber);
|
|
|
|
mRequestMap.insert(pair<apiTrackingNumber,apiTrackedRequest>(trackingNumber, apiTrackedRequest(trackingNumber, output.GetMessageID(), userData, timeout)));
|
|
|
|
////////////////////////////////////////
|
|
// Verify that the request needs to be sent.
|
|
// If the default result is not RESULT_TIMEOUT,
|
|
// trigger callback using the output
|
|
if (!mConnectionManager || !mConnectionManager->CanSend() || output.GetResult() != RESULT_TIMEOUT)
|
|
{
|
|
QueueTrackedCallback(output);
|
|
}
|
|
else
|
|
{
|
|
Base::ByteStream stream;
|
|
input.pack(stream);
|
|
|
|
mConnectionManager->Send(stream);
|
|
}
|
|
|
|
return input.GetTrackingNumber();
|
|
}
|
|
|
|
void apiCore::QueueCallback(const Base::ByteStream & stream)
|
|
{
|
|
mCallbackQueue.push_back(stream);
|
|
}
|
|
|
|
void apiCore::QueueCallback(const Message::Basic & message)
|
|
{
|
|
Base::ByteStream stream;
|
|
message.pack(stream);
|
|
|
|
mCallbackQueue.push_back(stream);
|
|
}
|
|
|
|
void apiCore::QueueTrackedCallback(const Base::ByteStream & stream)
|
|
{
|
|
mTrackedCallbackQueue.push_back(stream);
|
|
}
|
|
|
|
void apiCore::QueueTrackedCallback(const Message::Basic & message)
|
|
{
|
|
Base::ByteStream stream;
|
|
message.pack(stream);
|
|
|
|
mTrackedCallbackQueue.push_back(stream);
|
|
}
|
|
|
|
std::string & apiCore::GetVersion()
|
|
{
|
|
return mVersion;
|
|
}
|
|
|
|
std::string & apiCore::GetDescription()
|
|
{
|
|
return mDescription;
|
|
}
|
|
|
|
void apiCore::Process()
|
|
{
|
|
if (mInCallback)
|
|
return;
|
|
mInCallback = true;
|
|
|
|
unsigned currentTime = (unsigned)time(0);
|
|
|
|
////////////////////////////////////////
|
|
// Process connection manager
|
|
if (mConnectionManager)
|
|
mConnectionManager->Process();
|
|
else
|
|
{
|
|
mConnectionManager = new CConnectionManager(*this, mServerArray, mMaxConnections);
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
// Check timeout in Request Map
|
|
if (mExpirationTimeout <= currentTime)
|
|
{
|
|
map<unsigned,apiTrackedRequest>::iterator mapIterator = mRequestMap.begin();
|
|
while (mapIterator != mRequestMap.end())
|
|
{
|
|
apiTrackedRequest & request = (*mapIterator).second;
|
|
++mapIterator;
|
|
|
|
if (request.Expired())
|
|
{
|
|
mTimeoutQueue.push_back(request.GetTrackingNumber());
|
|
}
|
|
}
|
|
mExpirationTimeout = currentTime + 3;
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
// Process Timeout Queue
|
|
while (!mTimeoutQueue.empty())
|
|
{
|
|
apiTrackingNumber trackingNumber = mTimeoutQueue.front();
|
|
|
|
map<unsigned,apiTrackedRequest>::iterator mapIterator;
|
|
mapIterator = mRequestMap.find(trackingNumber);
|
|
if (mapIterator != mRequestMap.end())
|
|
{
|
|
apiTrackedRequest & request = mapIterator->second;
|
|
Timeout(request.GetMessageId(), trackingNumber, (void *)request.GetUserData());
|
|
mRequestMap.erase(mapIterator);
|
|
}
|
|
mTimeoutQueue.pop_front();
|
|
}
|
|
|
|
/*
|
|
////////////////////////////////////////
|
|
// Process Callback Queue
|
|
while (!mCallbackQueue.empty())
|
|
{
|
|
Base::ByteStream & stream = mCallbackQueue.front();
|
|
Callback(stream,0);
|
|
mCallbackQueue.pop_front();
|
|
}
|
|
*/
|
|
|
|
////////////////////////////////////////
|
|
// Process Tracked Callback Queue
|
|
while (!mTrackedCallbackQueue.empty())
|
|
{
|
|
unsigned short itemCount;
|
|
unsigned short messageId = 0;
|
|
|
|
Base::ByteStream & stream = mTrackedCallbackQueue.front();
|
|
Base::ByteStream::ReadIterator streamIterator = stream.begin();
|
|
Base::get(streamIterator, itemCount);
|
|
Base::get(streamIterator, messageId);
|
|
|
|
if (!IsTrackedMessage(messageId))
|
|
{
|
|
Callback(stream,0);
|
|
}
|
|
else
|
|
{
|
|
streamIterator = stream.begin();
|
|
Message::Tracked message(streamIterator);
|
|
|
|
map<apiTrackingNumber,apiTrackedRequest>::iterator mapIterator = mRequestMap.find(message.GetTrackingNumber());
|
|
if (mapIterator != mRequestMap.end())
|
|
{
|
|
apiTrackedRequest & request = (*mapIterator).second;
|
|
Callback(stream,(void *)request.GetUserData());
|
|
mRequestMap.erase(mapIterator);
|
|
}
|
|
}
|
|
mTrackedCallbackQueue.pop_front();
|
|
}
|
|
|
|
mInCallback = false;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
const int DEFAULT_TIMEOUT = 20;
|
|
|
|
|
|
apiTrackedRequest::apiTrackedRequest(apiTrackingNumber trackingNumber, const unsigned short messageId, const void * userData, unsigned duration) :
|
|
mTrackingNumber(trackingNumber),
|
|
mMessageId(messageId),
|
|
mUserData(userData),
|
|
mTimeout(0),
|
|
mDuration(duration)
|
|
{
|
|
if (mDuration == 0)
|
|
mDuration = DEFAULT_TIMEOUT;
|
|
|
|
mTimeout = (int)time(0) + mDuration;
|
|
}
|
|
|
|
apiTrackedRequest::apiTrackedRequest(const apiTrackedRequest & copy) :
|
|
mTrackingNumber(copy.mTrackingNumber),
|
|
mMessageId(copy.mMessageId),
|
|
mUserData(copy.mUserData),
|
|
mTimeout(copy.mTimeout),
|
|
mDuration(copy.mDuration)
|
|
{
|
|
}
|
|
|
|
apiTrackedRequest::~apiTrackedRequest()
|
|
{
|
|
}
|
|
|
|
apiTrackingNumber apiTrackedRequest::GetTrackingNumber()
|
|
{
|
|
return mTrackingNumber;
|
|
}
|
|
|
|
unsigned short apiTrackedRequest::GetMessageId()
|
|
{
|
|
return mMessageId;
|
|
}
|
|
|
|
const void * apiTrackedRequest::GetUserData()
|
|
{
|
|
return mUserData;
|
|
}
|
|
|
|
bool apiTrackedRequest::Expired()
|
|
{
|
|
return mTimeout < (unsigned)time(0);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|