/** Saves a state using the GameProtocol function to combine several
 *  independent rewinders to write one state.
 */
void RewindManager::saveState()
{
    PROFILER_PUSH_CPU_MARKER("RewindManager - save state", 0x20, 0x7F, 0x20);
    auto gp = GameProtocol::lock();
    if (!gp)
        return;
    gp->startNewState();

    m_overall_state_size = 0;
    std::vector<std::string> rewinder_using;

    for (auto& p : m_all_rewinder)
    {
        // TODO: check if it's worth passing in a sufficiently large buffer from
        // GameProtocol - this would save the copy operation.
        BareNetworkString* buffer = NULL;
        if (auto r = p.second.lock())
            buffer = r->saveState(&rewinder_using);
        if (buffer != NULL)
        {
            m_overall_state_size += buffer->size();
            gp->addState(buffer);
        }
        delete buffer;    // buffer can be freed
    }
    gp->finalizeState(rewinder_using);
    PROFILER_POP_CPU_MARKER();
}   // saveState
/** Saves a local state using the GameProtocol function to combine several
 *  independent rewinders to write one state. Typically only the server needs
 *  to save a state (which is then send to the clients), except that each
 *  client needs one initial state (in case that it receives an event from
 *  a client before a state from the serer).
 *  \param allow_local_save Do a local save.
 */
void RewindManager::saveState(bool local_save)
{
    PROFILER_PUSH_CPU_MARKER("RewindManager - save state", 0x20, 0x7F, 0x20);
    GameProtocol::lock()->startNewState(local_save);
    AllRewinder::const_iterator rewinder;
    for (rewinder = m_all_rewinder.begin(); rewinder != m_all_rewinder.end(); ++rewinder)
    {
        // TODO: check if it's worth passing in a sufficiently large buffer from
        // GameProtocol - this would save the copy operation.
        BareNetworkString *buffer = (*rewinder)->saveState();
        if (buffer && buffer->size() >= 0)
        {
            m_overall_state_size += buffer->size();
            GameProtocol::lock()->addState(buffer);
        }   // size >= 0
        delete buffer;    // buffer can be freed
    }
    PROFILER_POP_CPU_MARKER();
}   // saveState
/** \brief Sends a packet whithout ENet adding its headers.
 *  This function is used in particular to achieve the STUN protocol.
 *  \param data : Data to send.
 *  \param dst : Destination of the packet.
 */
void Network::sendRawPacket(const BareNetworkString &buffer,
                            const TransportAddress& dst)
{
    struct sockaddr_in to;
    int to_len = sizeof(to);
    memset(&to,0,to_len);

    to.sin_family = AF_INET;
    to.sin_port = htons(dst.getPort());
    to.sin_addr.s_addr = htonl(dst.getIP());

    sendto(m_host->socket, buffer.getData(), buffer.size(), 0,
           (sockaddr*)&to, to_len);
    Log::verbose("Network", "Raw packet sent to %s",
                 dst.toString().c_str());
    Network::logPacket(buffer, false);
}   // sendRawPacket