Protocols are now either synchronous or asynchronous. This avoids a problem
that in (rare) circumstances e.g. a message that is only handled synchronously is deleted from the asynchronous thread (if the main thread is too slow and a time out is reached).
This commit is contained in:
@@ -137,12 +137,30 @@ void Protocol::sendMessageToPeersChangingToken(uint8_t type,
|
||||
// ----------------------------------------------------------------------------
|
||||
void Protocol::sendMessage(const NetworkString& message, bool reliable)
|
||||
{
|
||||
ProtocolManager::getInstance()->sendMessage(this, message, reliable);
|
||||
ProtocolManager::getInstance()->sendMessage(this, message, reliable,
|
||||
/*synchronous*/false);
|
||||
} // sendMessage
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void Protocol::sendSynchronousMessage(const NetworkString& message,
|
||||
bool reliable)
|
||||
{
|
||||
ProtocolManager::getInstance()->sendMessage(this, message, reliable,
|
||||
/*synchron*/true);
|
||||
} // sendMessage
|
||||
// ----------------------------------------------------------------------------
|
||||
void Protocol::sendMessage(STKPeer* peer, const NetworkString& message,
|
||||
bool reliable)
|
||||
{
|
||||
ProtocolManager::getInstance()->sendMessage(this, peer, message, reliable);
|
||||
ProtocolManager::getInstance()->sendMessage(this, peer, message, reliable,
|
||||
/*synchronous*/false);
|
||||
} // sendMessage
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void Protocol::sendSynchronousMessage(STKPeer* peer,
|
||||
const NetworkString& message,
|
||||
bool reliable)
|
||||
{
|
||||
ProtocolManager::getInstance()->sendMessage(this, peer, message, reliable,
|
||||
/*synchronous*/true);
|
||||
} // sendSynchronousMessage
|
||||
|
||||
@@ -39,15 +39,16 @@ class STKPeer;
|
||||
*/
|
||||
enum ProtocolType
|
||||
{
|
||||
PROTOCOL_NONE = 0, //!< No protocol type assigned.
|
||||
PROTOCOL_CONNECTION = 1, //!< Protocol that deals with client-server connection.
|
||||
PROTOCOL_LOBBY_ROOM = 2, //!< Protocol that is used during the lobby room phase.
|
||||
PROTOCOL_START_GAME = 3, //!< Protocol used when starting the game.
|
||||
PROTOCOL_SYNCHRONIZATION = 4, //!<Protocol used to synchronize clocks.
|
||||
PROTOCOL_KART_UPDATE = 5, //!< Protocol to update karts position, rotation etc...
|
||||
PROTOCOL_GAME_EVENTS = 6, //!< Protocol to communicate the game events.
|
||||
PROTOCOL_CONTROLLER_EVENTS = 7, //!< Protocol to transfer controller modifications
|
||||
PROTOCOL_SILENT = 0xffff //!< Used for protocols that do not subscribe to any network event.
|
||||
PROTOCOL_NONE = 0x00, //!< No protocol type assigned.
|
||||
PROTOCOL_CONNECTION = 0x01, //!< Protocol that deals with client-server connection.
|
||||
PROTOCOL_LOBBY_ROOM = 0x02, //!< Protocol that is used during the lobby room phase.
|
||||
PROTOCOL_START_GAME = 0x03, //!< Protocol used when starting the game.
|
||||
PROTOCOL_SYNCHRONIZATION = 0x04, //!<Protocol used to synchronize clocks.
|
||||
PROTOCOL_KART_UPDATE = 0x05, //!< Protocol to update karts position, rotation etc...
|
||||
PROTOCOL_GAME_EVENTS = 0x06, //!< Protocol to communicate the game events.
|
||||
PROTOCOL_CONTROLLER_EVENTS = 0x07, //!< Protocol to transfer controller modifications
|
||||
PROTOCOL_SYNCHRONOUS = 0x80, //!< Flag, indicates synchronous delivery
|
||||
PROTOCOL_SILENT = 0xff //!< Used for protocols that do not subscribe to any network event.
|
||||
}; // ProtocolType
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -128,6 +129,10 @@ public:
|
||||
bool reliable = true);
|
||||
void sendMessage(STKPeer* peer, const NetworkString& message,
|
||||
bool reliable = true);
|
||||
void sendSynchronousMessage(const NetworkString& message,
|
||||
bool reliable=true);
|
||||
void sendSynchronousMessage(STKPeer* peer, const NetworkString& message,
|
||||
bool reliable = true);
|
||||
void requestStart();
|
||||
void requestPause();
|
||||
void requestUnpause();
|
||||
|
||||
@@ -131,6 +131,14 @@ void ProtocolManager::propagateEvent(Event* event)
|
||||
Log::verbose("ProtocolManager", "Received event for protocols of type %d",
|
||||
searched_protocol);
|
||||
|
||||
bool is_synchronous = false;
|
||||
if(searched_protocol & PROTOCOL_SYNCHRONOUS)
|
||||
{
|
||||
is_synchronous = true;
|
||||
// Reset synchronous flag to restore original protocol id
|
||||
searched_protocol = ProtocolType(searched_protocol &
|
||||
~PROTOCOL_SYNCHRONOUS );
|
||||
}
|
||||
std::vector<unsigned int> protocols_ids;
|
||||
m_protocols.lock();
|
||||
for (unsigned int i = 0; i < m_protocols.getData().size() ; i++)
|
||||
@@ -155,9 +163,10 @@ void ProtocolManager::propagateEvent(Event* event)
|
||||
if (protocols_ids.size() != 0)
|
||||
{
|
||||
EventProcessingInfo epi;
|
||||
epi.m_arrival_time = (double)StkTime::getTimeSinceEpoch();
|
||||
epi.m_event = event;
|
||||
epi.m_protocols_ids = protocols_ids;
|
||||
epi.m_arrival_time = (double)StkTime::getTimeSinceEpoch();
|
||||
epi.m_is_synchronous = is_synchronous;
|
||||
epi.m_event = event;
|
||||
epi.m_protocols_ids = protocols_ids;
|
||||
// Add the event to the queue. After the event is handled
|
||||
// its memory will be freed.
|
||||
m_events_to_process.getData().push_back(epi);
|
||||
@@ -175,20 +184,29 @@ void ProtocolManager::propagateEvent(Event* event)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void ProtocolManager::sendMessage(Protocol* sender, const NetworkString& message,
|
||||
bool reliable)
|
||||
bool reliable, bool send_synchronously)
|
||||
{
|
||||
NetworkString new_message(1+message.size());
|
||||
new_message.ai8(sender->getProtocolType()); // add one byte to add protocol type
|
||||
ProtocolType type = sender->getProtocolType();
|
||||
// Set flag if the message must be handled synchronously on arrivat
|
||||
if(send_synchronously)
|
||||
type = ProtocolType(type | PROTOCOL_SYNCHRONOUS);
|
||||
new_message.ai8(type); // add one byte to add protocol type
|
||||
new_message += message;
|
||||
STKHost::get()->sendMessage(new_message, reliable);
|
||||
} // sendMessage
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void ProtocolManager::sendMessage(Protocol* sender, STKPeer* peer,
|
||||
const NetworkString& message, bool reliable)
|
||||
const NetworkString& message, bool reliable,
|
||||
bool send_synchronously)
|
||||
{
|
||||
NetworkString new_message(1+message.size());
|
||||
new_message.ai8(sender->getProtocolType()); // add one byte to add protocol type
|
||||
ProtocolType type = sender->getProtocolType();
|
||||
// Set flag if the message must be handled synchronously on arrivat
|
||||
if(send_synchronously)
|
||||
type = ProtocolType(type | PROTOCOL_SYNCHRONOUS);
|
||||
new_message.ai8(type); // add one byte to add protocol type
|
||||
new_message += message;
|
||||
peer->sendPacket(new_message, reliable);
|
||||
} // sendMessage
|
||||
@@ -418,6 +436,8 @@ void ProtocolManager::update()
|
||||
int offset = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
// Don't handle asynchronous events here.
|
||||
if(!m_events_to_process.getData()[i+offset].m_is_synchronous) continue;
|
||||
bool result = sendEvent(&m_events_to_process.getData()[i+offset], true);
|
||||
if (result)
|
||||
{
|
||||
@@ -455,6 +475,8 @@ void ProtocolManager::asynchronousUpdate()
|
||||
int offset = 0;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
// Don't handle synchronous events here.
|
||||
if(m_events_to_process.getData()[i+offset].m_is_synchronous) continue;
|
||||
bool result = sendEvent(&m_events_to_process.getData()[i+offset], false);
|
||||
if (result)
|
||||
{
|
||||
|
||||
@@ -95,7 +95,10 @@ struct EventProcessingInfo
|
||||
* sent to. */
|
||||
std::vector<unsigned int> m_protocols_ids;
|
||||
|
||||
} EventProcessingInfo;
|
||||
/** Indicates if this received message must be handled synchronously or
|
||||
* asynchronously. */
|
||||
bool m_is_synchronous;
|
||||
}; // EventProcessingInfo
|
||||
|
||||
// ============================================================================
|
||||
/** \class ProtocolManager
|
||||
@@ -120,10 +123,12 @@ class ProtocolManager : public AbstractSingleton<ProtocolManager>,
|
||||
virtual void propagateEvent(Event* event);
|
||||
virtual void sendMessage(Protocol* sender,
|
||||
const NetworkString& message,
|
||||
bool reliable = true);
|
||||
bool reliable = true,
|
||||
bool send_synchronously = false);
|
||||
virtual void sendMessage(Protocol* sender, STKPeer* peer,
|
||||
const NetworkString& message,
|
||||
bool reliable = true);
|
||||
bool reliable = true,
|
||||
bool send_synchronously = false);
|
||||
virtual void sendMessageExcept(Protocol* sender, STKPeer* peer,
|
||||
const NetworkString& message,
|
||||
bool reliable = true);
|
||||
|
||||
@@ -180,9 +180,6 @@ bool ClientLobbyRoomProtocol::notifyEventAsynchronous(Event* event)
|
||||
const NetworkString &data = event->data();
|
||||
assert(data.size()); // assert that data isn't empty
|
||||
uint8_t message_type = data[0];
|
||||
if (message_type == LE_KART_SELECTION_UPDATE ||
|
||||
message_type == LE_RACE_FINISHED )
|
||||
return false; // don't treat the event
|
||||
|
||||
event->removeFront(1);
|
||||
Log::info("ClientLobbyRoomProtocol", "Asynchronous message of type %d",
|
||||
|
||||
@@ -348,9 +348,9 @@ void ServerLobbyRoomProtocol::checkRaceFinished()
|
||||
for (unsigned int i = 0; i < peers.size(); i++)
|
||||
{
|
||||
NetworkString ns(6);
|
||||
ns.ai8(0x06).ai8(4).ai32(peers[i]->getClientServerToken());
|
||||
ns.ai8(LE_RACE_FINISHED).ai8(4).ai32(peers[i]->getClientServerToken());
|
||||
NetworkString total = ns + queue;
|
||||
sendMessage(peers[i], total, true);
|
||||
sendSynchronousMessage(peers[i], total, true);
|
||||
}
|
||||
Log::info("ServerLobbyRoomProtocol", "End of game message sent");
|
||||
m_in_race = false;
|
||||
@@ -563,7 +563,8 @@ void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event)
|
||||
uint8_t player_id = peer->getPlayerProfile()->getGlobalPlayerId();
|
||||
answer.ai8(LE_KART_SELECTION_UPDATE).ai8(1).ai8(player_id)
|
||||
.encodeString(kart_name);
|
||||
sendMessage(answer);
|
||||
// This message must be handled synchronously on the client.
|
||||
sendSynchronousMessage(answer);
|
||||
m_setup->setPlayerKart(player_id, kart_name);
|
||||
} // kartSelectionRequested
|
||||
|
||||
|
||||
Reference in New Issue
Block a user