Beispiel #1
0
void Settings::on_mymessages_clicked()
{
    close();
    Messages sms;
    sms.setModal(true);
    sms.exec();
}
bool CommRemote::run(Messages & messages, Feedback & feedback) {
  // Delete all the previous remote messages to the robot
  messages.clearRemoteMessagesToRobot();

  pthread_mutex_lock(&dataMutex);

  // Add all the received remote messages to the robot
  std::vector<RemoteMessageToRobot const *>::iterator toIter;
  for (toIter = messagesToRobot.begin();
       toIter != messagesToRobot.end();
       toIter++) {
    messages.addRemoteMessageToRobot(*toIter);
  }
  messagesToRobot.clear();

  // Take ownership of all the remote messages to be sent from the robot
  messagesFromRobot.insert(messagesFromRobot.end(),
                           messages.getRemoteMessagesToSend().begin(),
                           messages.getRemoteMessagesToSend().end());
  messages.clearRemoteMessagesFromRobot();

  pthread_mutex_unlock(&dataMutex);

  // Are we connected to a client now?
  bool isConnectedToClient = (clientSocket >= 0);
  if (isConnectedToClient != wasConnectedToClient) {
    feedback.setConnectedToClient(isConnectedToClient);
    wasConnectedToClient = isConnectedToClient;
  }

  return false;
}
Beispiel #3
0
// dialogLoggingCallback is already used in debug.cpp
static void dialogLoggingCallback(const gchar */*log_domain*/,
                           GLogLevelFlags /*log_level*/,
                           const gchar *messageText,
                           gpointer user_data)
{
    Messages *dlg = static_cast<Messages *>(user_data);
    dlg->message(const_cast<char*>(messageText));

}
Beispiel #4
0
void check_datum(Messages &m, MatrixXi &y){
  for(int i=0; i<m.nnodes; i++)
    assert(y(i) >= -1 && y(i) < m.nvals(i));

    // do checks on m
  for(int c=0; c<m.cliques.size(); c++){
    assert(m.compute_nconfigs(c) > 0);
    assert(m.nconfigs(c) > 0);
  }
}
Beispiel #5
0
void CachingChannel::log(const Poco::Message& msg)
{
	Poco::FastMutex::ScopedLock lock(_mutex);
	_cache.push_front(msg);
	if (_size == _maxSize)
	{
		_cache.pop_back();
	}
	else
		++_size;
}
Beispiel #6
0
void DialogsProvider::OnMessages( wxCommandEvent& WXUNUSED(event) )
{
    /* Show/hide the log window */
    if( !p_messages_dialog )
        p_messages_dialog = new Messages( p_intf, this );

    if( p_messages_dialog )
    {
        p_messages_dialog->Show( !p_messages_dialog->IsShown() );
    }
}
Beispiel #7
0
void CachingChannel::getMessages(std::vector<Poco::Message>& msg, int offset, int numEntries) const
{
	msg.clear();
	Messages::const_iterator it = _cache.begin();

	while (offset > 0 && it != _cache.end())
		++it;

	while (numEntries > 0 && it != _cache.end())
	{
		msg.push_back(*it);
		++it;
	}
}
Beispiel #8
0
// ------------------------------------------------------------------------------------------------
static void QueueMtMsg(bool type, CCStr msg, va_list args)
{
    // Create a copy of the specified arguments list
    va_list args_cpy;
    va_copy(args_cpy, args);
    // Allocate a moderately large string
    String buffer(128, '\0');
    // Attempt to run the specified format
    Int32 size = vsnprintf(&buffer[0], buffer.size(), msg, args);
    // See if a larger buffer is necessary
    if (size > 0 && static_cast< unsigned >(size) > buffer.size())
    {
        // Resize the string buffer to the required size
        buffer.resize(static_cast< unsigned >(size+1), '\0');
        // Attempt to run the specified format
        size = vsnprintf(&buffer[0], buffer.size(), msg, args_cpy);
    }
    // Finalize the arguments list copy
    va_end(args_cpy);
    // See if the format failed
    if (size < 0)
    {
        return;
    }
    // Remove unwanted characters
    buffer.resize(size+1);
    // Acquire a global lock
    std::lock_guard< std::mutex > lock(g_Mutex);
    // Emplace the message into the message queue
    g_Messages.emplace(std::move(buffer), type);
}
Beispiel #9
0
//----------------------------------------------------------------------
// internal utility function
static int seqMessage(MessageType type, const char* format, va_list ap)
{
	char buff[SEQ_BUFFER_LENGTH];
	int ret = vsnprintf(buff, sizeof(buff), format, ap);
	Messages* messages = Messages::messages();

	// if the message object exists, use it, otherwise dump to stderr
	if (messages)
		messages->addMessage(type, buff);
#ifdef Q_OS_WIN
	OutputDebugStringA(buff);
	OutputDebugStringA("\n");
#else
		fprintf(stderr, "%s\n", buff);
#endif
	return ret;
}
Beispiel #10
0
void
Transaction::abort(Messages& messages)
{
    log->recordAbort(id);
    for (size_t i = 0; i < enrolledMessages.size(); ++i)
        messages.abort(enrolledMessages[i], shared_from_this());
    state = TRANS_ABORTED;
}
Beispiel #11
0
void
Transaction::commit(Messages& messages)
{
    log->recordCommit(id);
    for (size_t i = 0; i < enrolledMessages.size(); ++i)
        messages.commit(enrolledMessages[i], shared_from_this());
    state = TRANS_COMMITTED;
}
Beispiel #12
0
void CSMTools::BodyPartCheckStage::perform ( int stage, Messages &messages )
{
    const CSMWorld::Record<ESM::BodyPart> &record = mBodyParts.getRecord(stage);

    if ( record.isDeleted() )
        return;

    const ESM::BodyPart &bodyPart = record.get();

    CSMWorld::UniversalId id( CSMWorld::UniversalId::Type_BodyPart, bodyPart.mId );

    // Check BYDT
    if (bodyPart.mData.mPart > 14 )
        messages.push_back(std::make_pair( id, bodyPart.mId + " has out of range part value." ));

    if (bodyPart.mData.mFlags > 3 )
        messages.push_back(std::make_pair( id, bodyPart.mId + " has out of range flags value." ));

    if (bodyPart.mData.mType > 2 )
        messages.push_back(std::make_pair( id, bodyPart.mId + " has out of range type value." ));

    // Check MODL

    if ( bodyPart.mModel.empty() )
        messages.push_back(std::make_pair( id, bodyPart.mId + " has no model." ));
    else if ( mMeshes.searchId( bodyPart.mModel ) == -1 )
        messages.push_back(std::make_pair( id, bodyPart.mId + " has invalid model." ));

    // Check FNAM

    if ( bodyPart.mRace.empty() )
        messages.push_back(std::make_pair( id, bodyPart.mId + " has no race." ));
    else if ( mRaces.searchId( bodyPart.mRace ) == -1 )
        messages.push_back(std::make_pair( id, bodyPart.mId + " has invalid race." ));
}
Beispiel #13
0
/* ------------------------------------------------------------------------------------------------
 * Flush queued messages to the console output.
*/
void FlushMessages()
{
    // Acquire a global lock
    std::lock_guard< std::mutex > lock(g_Mutex);
    // Output any queued messages
    while (!g_Messages.empty())
    {
        // Identify the message type and send it
        if (g_Messages.front().second)
        {
            OutputMessage("%s", g_Messages.front().first.c_str());
        }
        else
        {
            OutputError("%s", g_Messages.front().first.c_str());
        }
        // Pop the message from the queue
        g_Messages.pop();
    }
}
void MemoryPacketModel::transformRequestFinished(QList<QByteArray> dataList, Messages messages)
{
    quintptr senderID = (quintptr)sender();
    if (transformRequests.contains(senderID)) {
        QPair<int,int> target = transformRequests.take(senderID);
        if (target.second > lastPredefinedColumn && target.second < columnNames.size()) {

            int size = dataList.size();
            if (size > packetsList.size() - target.first) {
                qWarning() << tr("[MemoryPacketModel::transformRequestFinished] data set size (%1) is too big")
                               .arg(dataList.size());
                size = packetsList.size() - target.first; // reducing the saice
            }

            QString colName = columnNames.at(target.second);
            OutputFormat format = userColumnsDef.value(colName).format;
            int j = 0;
            for (int i = target.first; i < target.first + size; i++) {
                Packet * pa = packetsList.at(i);
                QString data = QString::fromUtf8((format == Pip3lineConst::TEXTFORMAT) ? dataList.at(j) : dataList.at(j).toHex());
                pa->setAdditionalField(colName, data);
                j++;
            }
            emit dataChanged(createIndex(target.first, target.second), createIndex(target.first + size - 1, target.second));

            // loggin error messages

            for (int i = 0; i < messages.size(); i++) {
                emit log(messages.at(i).message,messages.at(i).source, messages.at(i).level);
            }

        } else {
            qCritical() << tr("[MemoryPacketModel::transformRequestFinished] Can't find the column %1 T_T").arg(target.second);
        }
    } else {
        qCritical() << tr("[MemoryPacketModel::transformRequestFinished] Can't find the request id T_T");
    }
    emit readOnlyStateChanged(false);
}
Beispiel #15
0
void DialogsProvider::OnIdle( wxIdleEvent& WXUNUSED(event) )
{
    /* Update the log window */
    if( p_messages_dialog )
        p_messages_dialog->UpdateLog();

    /* Update the playlist */
    if( p_playlist_dialog )
        p_playlist_dialog->UpdatePlaylist();

    /* Update the fileinfo windows */
    if( p_fileinfo_dialog )
        p_fileinfo_dialog->Update();
}
Beispiel #16
0
void CSMTools::SkillCheckStage::perform (int stage, Messages& messages)
{
    const CSMWorld::Record<ESM::Skill>& record = mSkills.getRecord (stage);

    if (record.isDeleted())
        return;

    const ESM::Skill& skill = record.get();

    CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Skill, skill.mId);

    for (int i=0; i<4; ++i)
        if (skill.mData.mUseValue[i]<0)
        {
            std::ostringstream stream;

            stream << "Use value #" << i << " of " << skill.mId << " is negative";

            messages.push_back (std::make_pair (id, stream.str()));
        }

    if (skill.mDescription.empty())
        messages.push_back (std::make_pair (id, skill.mId + " has an empty description"));
}
Beispiel #17
0
void CSMDoc::Operation::executeStage()
{
    Messages messages;

    while (mCurrentStage!=mStages.end())
    {
        if (mCurrentStep>=mCurrentStage->second)
        {
            mCurrentStep = 0;
            ++mCurrentStage;
        }
        else
        {
            try
            {
                mCurrentStage->first->perform (mCurrentStep++, messages);
            }
            catch (const std::exception& e)
            {
                emit reportMessage (CSMWorld::UniversalId(), e.what(), "", mType);
                abort();
            }

            ++mCurrentStepTotal;
            break;
        }
    }

    emit progress (mCurrentStepTotal, mTotalSteps ? mTotalSteps : 1, mType);

    for (Messages::Iterator iter (messages.begin()); iter!=messages.end(); ++iter)
        emit reportMessage (iter->mId, iter->mMessage, iter->mHint, mType);

    if (mCurrentStage==mStages.end())
        exit();
}
Beispiel #18
0
void Messages::vadd_msg(const char *msg, va_list ap)
{
    player_messages.add_msg_string(vstring_format(msg, ap));
}
Beispiel #19
0
  void Acknowledge::
  track ()
  {
    while (true)
    {
      Messages msgs;

      {
        Lock l (mutex_);

        if (stop_)
          break;

        if (hold_.current_size () != 0)
        {
          for (Map::iterator i (hold_.begin ()), e (hold_.end ());
               i != e;
               ++i)
          {
            Queue& q = (*i).int_id_;

            if (q.current_size () == 0) continue;

            track_queue ((*i).ext_id_, q, msgs);
          }
        }

        if (--nrtm_timer_ == 0)
        {
          nrtm_timer_ = params_.nrtm_timeout ();

          // Send NRTM.
          //
          unsigned short max_payload_size (
            params_.max_packet_size () - max_service_size);

          u32 max_elem (NRTM::max_count (max_payload_size));

          Profile_ptr nrtm (create_nrtm (max_elem));

          if (!nrtm.null ())
          {
            Message_ptr m (new Message);
            m->add (nrtm);
            msgs.push_back (m);

          }
        }
      }

      // Send stuff off.
      //
      for (Messages::Iterator i (msgs); !i.done (); i.advance ())
      {
        Message_ptr* ppm;
        i.next (ppm);

        //FUZZ: disable check_for_lack_ACE_OS
        send (*ppm);
        //FUZZ: enable check_for_lack_ACE_OS
      }

      // Go to sleep but watch for "manual cancellation" request.
      //
      {
        //FUZZ: disable check_for_lack_ACE_OS
        ACE_Time_Value time (ACE_OS::gettimeofday ());
        //FUZZ: enable check_for_lack_ACE_OS

        time += params_.tick ();

        Lock l (mutex_);

        while (!stop_)
        {
          if (cond_.wait (&time) == -1)
          {
            if (errno != ETIME)
              ACE_OS::abort ();
            else
              break;
          }
        }

        if (stop_)
          break;
      }
    }
  }
Beispiel #20
0
  void Acknowledge::
  track_queue (Address const& addr, Queue& q, Messages& msgs)
  {
    unsigned short max_payload_size (
      params_.max_packet_size () - max_service_size);

    u32 max_elem (NAK::max_count (max_payload_size));
    u32 count (0);

    Queue::iterator i (q.begin ()), e (q.end ());

    // Track existing losses.
    //
    while (i != e)
    {
      auto_ptr<NAK> nak (new NAK (addr));

      // Inner loop that fills NAK profile with up to max_elem elements.
      //
      for (; i != e && nak->count () < max_elem; ++i)
      {
        u64 sn ((*i).ext_id_);
        Descr& d = (*i).int_id_;

        if (d.lost ())
        {
          d.timer (d.timer () - 1);

          if (d.timer () == 0)
          {
            //@@ Need exp fallback.
            //
            d.nak_count (d.nak_count () + 1);
            d.timer ((d.nak_count () + 1) * params_.nak_timeout ());

            nak->add (sn);

            ++count;

            // cerr << 6 << "NAK # " << d.nak_count () << ": "
            // << addr << " " << sn << endl;
          }
        }
      }

      // Send this NAK.
      //
      if (nak->count ())
      {
        // cerr << 5 << "NAK: " << addr << " " << nak->count () << " sns"
        //     << endl;

        Message_ptr m (new Message);

        m->add (Profile_ptr (nak.release ()));

        msgs.push_back (m);
      }
    }

    // Detect and record new losses.
    //
    for (u64 sn (q.sn () + 1), end (q.max_sn ()); sn < end; ++sn)
    {
      if (q.find (sn) == -1)
      {
        q.bind (sn, Descr (1));
      }
    }
  }
Beispiel #21
0
namespace SMod {

// ------------------------------------------------------------------------------------------------
typedef ::std::string String;

// ------------------------------------------------------------------------------------------------
PluginFuncs*        _Func = nullptr;
PluginCallbacks*    _Clbk = nullptr;
PluginInfo*         _Info = nullptr;

// ------------------------------------------------------------------------------------------------
static ServerSettings       g_Settings;
static unsigned int         g_ServerVersion;

/* ------------------------------------------------------------------------------------------------
 * Output a message only if the _DEBUG was defined.
*/
void OutputDebug(CCStr msg, ...);

/* ------------------------------------------------------------------------------------------------
 * Output a formatted user message to the console.
*/
void OutputMessage(CCStr msg, ...);

/* ------------------------------------------------------------------------------------------------
 * Output a formatted error message to the console.
*/
void OutputError(CCStr msg, ...);

/* ------------------------------------------------------------------------------------------------
 * Output a formatted verbose user message to the console.
*/
void VerboseMessage(CCStr msg, ...);

/* ------------------------------------------------------------------------------------------------
 * Output a formatted verbose error message to the console.
*/
void VerboseError(CCStr msg, ...);

/* ------------------------------------------------------------------------------------------------
 * Output a formatted user message to the console in a thread safe manner.
*/
void MtOutputMessage(CCStr msg, ...);

/* ------------------------------------------------------------------------------------------------
 * Output a formatted error message to the console in a thread safe manner.
*/
void MtOutputError(CCStr msg, ...);

/* ------------------------------------------------------------------------------------------------
 * Output a formatted verbose user message to the console in a thread safe manner.
*/
void MtVerboseMessage(CCStr msg, ...);

/* ------------------------------------------------------------------------------------------------
 * Output a formatted verbose error message to the console in a thread safe manner.
*/
void MtVerboseError(CCStr msg, ...);

/* ------------------------------------------------------------------------------------------------
 * Simple parser that extracts URI information from a string.
*/
struct URI
{
    /* ---------------------------------------------------------------------------------------------
     * Base constructor.
    */
    URI(CCStr address)
        : mHost()
        , mPort()
        , mPath()
        , mFull()
        , mAddr()
    {
        // Is there even an address to parse?
        if (!address || strlen(address) <= 0)
        {
            return;
        }
        // Skip the protocol if it was specified
        if (strncmp(address, "http://", 7) == 0)
        {
            address += 7; // Skip the protocol
        }
        else if (strncmp(address, "https://", 8) == 0)
        {
            address += 8; // Skip the protocol
        }
        // Find where the port starts
        CCStr port = strchr(address, ':');
        // Find where the path starts
        CCStr path = strchr(port ? port : address, '/');
        // Did we find the port separator?
        if (port)
        {
            // Copy everything until the port separator
            mHost.assign(address, port - address);
        }
        // Did we find the path separator?
        else if(path)
        {
            // Copy everything until the path separator
            mHost.assign(address, path - address);
        }
        // The entire address is the host
        else
        {
            // Copy the entire address
            mHost.assign(address);
        }
        // Should we skip the port separator?
        if (port)
        {
            ++port;
        }
        // Did we find both a port and path?
        if (port && path)
        {
            // Copy everything between the port and path separators
            mPort.assign(port, path - port);
        }
        else if (port)
        {
            // Copy everything after the port separator
            mPort.assign(port);
        }
        // Assign the default port
        else
        {
            mPort.assign("80");
        }
        // Copy the path if necessary
        if (path)
        {
            mPath.assign(path);
        }
        // Assign a default path just in case
        else
        {
            mPath.assign("/");
        }
        // Generate the full URI
        mFull.assign("http://");
        mFull.append(mHost);
        mFull += ':';
        mFull.append(mPort);
        mFull.append(mPath);
        mAddr.append(mHost);
        // Generate the connect address
        mAddr += ':';
        mAddr.append(mPort);
    }

    /* ---------------------------------------------------------------------------------------------
     * Copy constructor.
    */
    URI(const URI & o)
        : mHost(o.mHost)
        , mPort(o.mPort)
        , mPath(o.mPath)
        , mFull(o.mFull)
        , mAddr(o.mAddr)
    {
        /* ... */
    }

    /* ---------------------------------------------------------------------------------------------
     * Move constructor.
    */
    URI(URI && o)
        : mHost(o.mHost)
        , mPort(o.mPort)
        , mPath(o.mPath)
        , mFull(o.mFull)
        , mAddr(o.mAddr)
    {
        /* ... */
    }

    /* ---------------------------------------------------------------------------------------------
     * Copy assignment operator.
    */
    URI & operator = (const URI & o)
    {
        if (this != &o)
        {
            mHost = o.mHost;
            mPort = o.mPort;
            mPath = o.mPath;
            mFull = o.mFull;
            mAddr = o.mAddr;
        }
        return *this;
    }

    /* ---------------------------------------------------------------------------------------------
     * Move assignment operator.
    */
    URI & operator = (URI && o)
    {
        if (this != &o)
        {
            mHost = o.mHost;
            mPort = o.mPort;
            mPath = o.mPath;
            mFull = o.mFull;
            mAddr = o.mAddr;
        }
        return *this;
    }

    /* ---------------------------------------------------------------------------------------------
     * Retrieve the protocol as a c string.
    */
    CCStr Protocol() const
    {
        return "http://";
    }

    /* ---------------------------------------------------------------------------------------------
     * Retrieve the host address as a c string.
    */
    CCStr Host() const
    {
        return mHost.c_str();
    }

    /* ---------------------------------------------------------------------------------------------
     * Retrieve the port number as a c string.
    */
    CCStr Port() const
    {
        return mPort.c_str();
    }

    /* ---------------------------------------------------------------------------------------------
     * Retrieve the request path as a c string.
    */
    CCStr Path() const
    {
        return mPath.c_str();
    }

    /* ---------------------------------------------------------------------------------------------
     * Retrieve the full address as a c string.
    */
    CCStr Full() const
    {
        return mFull.c_str();
    }

    /* ---------------------------------------------------------------------------------------------
     * Retrieve the connect address as a c string.
    */
    CCStr Addr() const
    {
        return mAddr.c_str();
    }

    // ---------------------------------------------------------------------------------------------
    String          mHost; // The host name.
    String          mPort; // The port number.
    String          mPath; // The request path.
    String          mFull; // The full address.
    String          mAddr; // The address used to connect to.
};

/* ------------------------------------------------------------------------------------------------
 * Manages a connection to a master-server.
*/
struct Server
{
    /* ---------------------------------------------------------------------------------------------
     * Base constructor.
    */
    Server(URI && addr)
        : m_Conn(nullptr)
        , m_Fails(0)
        , m_Valid(false)
        , m_Addr(addr)
        , m_Data()
    {
        /* ... */
    }

    /* ---------------------------------------------------------------------------------------------
     * Copy constructor. (disabled)
    */
    Server(const Server &) = delete;

    /* ---------------------------------------------------------------------------------------------
     * Move constructor.
    */
    Server(Server && o)
        : m_Conn(o.m_Conn)
        , m_Fails(o.m_Fails)
        , m_Valid(o.m_Valid)
        , m_Addr(o.m_Addr)
        , m_Data()
    {
        memcpy(m_Data, o.m_Data, sizeof(m_Data));
        // Take ownership of connection
        o.m_Conn = nullptr;
        // Re-associate the connection if necessary
        if (m_Conn)
        {
            m_Conn->user_data = this;
        }
    }

    /* ---------------------------------------------------------------------------------------------
     * Destructor.
    */
    ~Server()
    {
        // Disassociate this connection with this server, if necessary
        if (m_Conn)
        {
            m_Conn->user_data = nullptr;
        }
    }

    /* ---------------------------------------------------------------------------------------------
     * Copy assignment operator. (disabled)
    */
    Server & operator = (const Server &) = delete;

    /* ---------------------------------------------------------------------------------------------
     * Move assignment operator.
    */
    Server & operator = (Server && o)
    {
        if (this != &o)
        {
            m_Conn = o.m_Conn;
            m_Fails = o.m_Fails;
            m_Valid = o.m_Valid;
            m_Addr = o.m_Addr;
            memcpy(m_Data, o.m_Data, sizeof(m_Data));
            // Take ownership of connection
            o.m_Conn = nullptr;
            // Re-associate the connection if necessary
            if (m_Conn)
            {
                m_Conn->user_data = this;
            }
        }
        return *this;
    }

    /* ---------------------------------------------------------------------------------------------
     * Implicit conversion to boolean.
    */
    operator bool () const
    {
        return m_Valid;
    }

    /* ---------------------------------------------------------------------------------------------
     * Retrieve the associated master-server address.
    */
    const URI & GetURI() const
    {
        return m_Addr;
    }

    /* ---------------------------------------------------------------------------------------------
     * Retrieve the associated payload.
    */
    CCStr GetData() const
    {
        return m_Data;
    }

    /* ---------------------------------------------------------------------------------------------
     * Increase the failure count and see whether updates should stop being sent on this server.
    */
    void Failed()
    {
        // After one thousand failed attempts, there's no point in insisting
        if (++m_Fails >= 1000)
        {
            MtVerboseError("Master-server '%s' was marked as invalid after %u failures",
                            m_Addr.Addr(), m_Fails);
            // Block further updates
            m_Valid = false;
        }
    }

    /* ---------------------------------------------------------------------------------------------
     * Make the server valid again and continue to send updates.
    */
    void MakeValid()
    {
        // Reset the counter
        m_Fails = 0;
        // Allow further updates
        m_Valid = true;
    }

    /* ---------------------------------------------------------------------------------------------
     * Generate the payload message.
    */
    void Generate()
    {
        char body[32];
        // Generate the post data
        if (snprintf(body, sizeof(body), "port=%d", g_Settings.port) < 0)
        {
            VerboseError("Unable to generate the post data for '%s'", m_Addr.Host());
            // Make sure the data is null terminated
            m_Data[0] = '\0';
            // Make sure this is marked as invalid
            m_Valid = false;
        }
        // Generate the payload message sent with each message
        else if (snprintf(m_Data, sizeof(m_Data),
                    "POST %s HTTP/1.1\r\n"
                    "Host: %s\r\n"
                    "Connection: close\r\n"
                    "User-Agent: VCMP/0.4\r\n"
                    "VCMP-Version: %u\r\n"
                    "Content-Type: application/x-www-form-urlencoded\r\n"
                    "Content-Length: %u\r\n"
                    "\r\n" /* ... */ "%s"
                    , m_Addr.Path(), m_Addr.Host()
                    , g_ServerVersion, strlen(body), body) < 0)
        {
            VerboseError("Unable to generate the payload message for '%s'", m_Addr.Host());
            // Make sure the data is null terminated
            m_Data[0] = '\0';
            // Make sure this is marked as invalid
            m_Valid = false;
        }
        else
        {
            VerboseMessage("Payload for master-server '%s' is:\n%s", m_Addr.Host(), m_Data);
            // Make sure this is marked as valid
            MakeValid();
        }
    }

    /* ---------------------------------------------------------------------------------------------
     * Send the payload to the associated server to keep the server alive in the master-list.
    */
    void Update(mg_mgr * manager)
    {
        // Is there a connection already waiting response and are we allowed to update?
        if (m_Conn || !m_Valid)
        {
            return; // Keep waiting for a reply and ignore this request
        }
        // Attempt to create a connection to the associated master-server
        m_Conn = mg_connect(manager, m_Addr.Addr(), EventHandler);
        // Make sure that the connection could be created
        if (!m_Conn)
        {
            MtVerboseError("Unable to create connection for '%s'", m_Addr.Addr());
            // This operation failed
            Failed();
        }
        else
        {
            // Set associated connection user data to this instance
            m_Conn->user_data = this;
            // Attach the HTTP protocol component
            mg_set_protocol_http_websocket(m_Conn);
            // Send the payload data
            mg_printf(m_Conn, "%s", m_Data);
            // Verbose status
            MtVerboseMessage("Connection created for '%s'", m_Addr.Addr());
        }
    }

    /* ---------------------------------------------------------------------------------------------
     * Handle the dispatched connection events.
    */
    void HandleEvent(mg_connection * nc, int ev, void * ev_data)
    {
        // Identify the event type
        switch (ev)
        {
            case MG_EV_CONNECT:
            {
                const int status = *reinterpret_cast< int * >(ev_data);
                // Validate the connection status
                if (status != 0)
                {
                    MtVerboseError("Unable to connect to master-server '%s' because: %s",
                                    m_Addr.Host(), strerror(status));
                    // This operation failed
                    Failed();
                }
                // Specify that this connection is valid and should continue to be updated
                else
                {
                    MakeValid();
                }
            } break;
            case MG_EV_HTTP_REPLY:
            {
                // Close this connection immediately (explicit)
                nc->flags |= MG_F_CLOSE_IMMEDIATELY;
                // Disassociate this connection with this server
                m_Conn = nullptr;
                // Obtain the event data
                http_message * msg = reinterpret_cast< http_message * >(ev_data);
                // Output the received info
                MtVerboseMessage("Received data from '%s'\n%.*s",
                                    m_Addr.Host(),msg->message.len, msg->message.p);
                // Inspect response
                switch (msg->resp_code)
                {
                    case 400:
                    {
                        MtVerboseError("Master-server '%s' denied request due to malformed data", m_Addr.Host());
                        // This operation failed
                        Failed();
                    } break;
                    case 403:
                    {
                        MtVerboseError("Master-server '%s' denied request, server version may not have been accepted", m_Addr.Host());
                        // This operation failed
                        Failed();
                    } break;
                    case 405:
                    {
                        MtVerboseError("Master-server '%s' denied request, GET is not supported", m_Addr.Host());
                        // This operation failed
                        Failed();
                    } break;
                    case 408:
                    {
                        MtVerboseError("Master-server '%s' timed out while trying to reach your server; are your ports forwarded?", m_Addr.Host());
                        // This operation failed
                        Failed();
                    } break;
                    case 500:
                    {
                        MtVerboseError("Master-server '%s' had an unexpected error while processing your request", m_Addr.Host());
                        // This operation failed
                        Failed();
                    } break;
                    case 200:
                    {
                        MtVerboseMessage("Successfully announced on master-server '%s'", m_Addr.Host());
                        // This operation succeeded
                        MakeValid();
                    } break;
                    default: /* Unknown response */ break;
                }
            } break;
            case MG_EV_SEND:
            {
                MtVerboseMessage("Sent %d bytes to master-server '%s'",
                                    *reinterpret_cast< int * >(ev_data), m_Addr.Host());
            } break;
            case MG_EV_RECV:
            {
                MtVerboseMessage("Received %d bytes from master-server '%s'",
                                    *reinterpret_cast< int * >(ev_data), m_Addr.Host());
            } break;
            case MG_EV_CLOSE:
            {
                MtVerboseMessage("Closed connection to master-server '%s'", m_Addr.Host());
                // Disassociate this connection with this server
                m_Conn = nullptr;
            } break;
            default: /* Ignore event... */ break;
        }
    }

    /* ---------------------------------------------------------------------------------------------
     * Receive events from the connection manager.
    */
    static void EventHandler(mg_connection * nc, int ev, void * ev_data)
    {
        // Is there any user-data associated with this connection?
        if (nc->user_data)
        {
            static_cast< Server * >(nc->user_data)->HandleEvent(nc, ev, ev_data);
        }
        // Close this connection immediately and ignore it
        else
        {
            nc->flags |= MG_F_CLOSE_IMMEDIATELY;
        }
    }

private:

    // ---------------------------------------------------------------------------------------------
    mg_connection*  m_Conn; // The associated server connection.
    unsigned        m_Fails; // How many attempts to create a connection failed.
    bool            m_Valid; // Whether we should completely ignore this master-server.
    URI             m_Addr; // The master-server address information.
    char            m_Data[256]; // The payload to be sent with each update.
};

// ------------------------------------------------------------------------------------------------
typedef std::vector< Server >                       Servers;
typedef std::queue< std::pair< String, bool > >     Messages;

// ------------------------------------------------------------------------------------------------
static bool                 g_Verbose = false; // Enable or disable verbose messages
static bool                 g_Announce = false; // Allow the announce loop to continue
static std::thread          g_Thread; // Announce thread
static std::mutex           g_Mutex; // Global mutex

// ------------------------------------------------------------------------------------------------
static Servers              g_Servers; // List of servers to be updated
static Messages             g_Messages; // Messages queued from the announce thread

/* ------------------------------------------------------------------------------------------------
 * The main thread responsible for updating the specified master-servers.
*/
void AnnounceThread(Servers && servers)
{
    // The connection manager and connection options
    mg_mgr               manager;
    mg_serve_http_opts   options;
    // Initialize the manager and configuration structures to 0
    memset(&manager, 0, sizeof(mg_mgr));
    memset(&options, 0, sizeof(mg_serve_http_opts));
    // Initialize the connection manager
    mg_mgr_init(&manager, nullptr);
    // Send the initial update to all master-servers
    for (auto & server : servers)
    {
        server.Update(&manager);
    }
    // Used to know how many server updates were skipped
    unsigned count = 0;
    // Enter the announcement loop
    while (g_Announce)
    {
        // Pool for events from the connection manager
        mg_mgr_poll(&manager, 250);
        // See if we must issue any updates
        if (++count < 240)
        {
            continue;
        }
        // Reset the counter
        count = 0;
        // Process the specified servers
        for (auto & server : servers)
        {
            server.Update(&manager);
        }
    }
    // Release the connection manager resources
    mg_mgr_free(&manager);
}

/* ------------------------------------------------------------------------------------------------
 * Flush queued messages to the console output.
*/
void FlushMessages()
{
    // Acquire a global lock
    std::lock_guard< std::mutex > lock(g_Mutex);
    // Output any queued messages
    while (!g_Messages.empty())
    {
        // Identify the message type and send it
        if (g_Messages.front().second)
        {
            OutputMessage("%s", g_Messages.front().first.c_str());
        }
        else
        {
            OutputError("%s", g_Messages.front().first.c_str());
        }
        // Pop the message from the queue
        g_Messages.pop();
    }
}

/* ------------------------------------------------------------------------------------------------
 * The server was initialized and this plug-in must initialize as well.
*/
static uint8_t OnServerInitialise(void)
{
    // Obtain the server settings. We only need the port number
    _Func->GetServerSettings(&g_Settings);
    // Obtain the server version. This doesn't change much
    g_ServerVersion = _Func->GetServerVersion();
    // Attempt to generate the update payload
    for (unsigned n = 0; n < g_Servers.size();)
    {
        // Attempt to generate the payload
        g_Servers[n].Generate();
        // See if any failures occurred
        if (g_Servers[n].GetData()[0] == 0)
        {
            // Erase the server completely
            g_Servers.erase(g_Servers.begin() + n);
        }
        // Move to the next server
        else
        {
            ++n;
        }
    }
    // See if any servers are left
    if (g_Servers.empty())
    {
        // We don't want to receive events anymore
        _Clbk->OnServerInitialise       = nullptr;
        _Clbk->OnServerShutdown         = nullptr;
        _Clbk->OnServerFrame            = nullptr;
    }
    else
    {
        // Enable the announce thread to run if there are servers
        g_Announce = true;
        // Create the announce thread
        g_Thread = std::thread(AnnounceThread, std::move(g_Servers));
        // Notify that the plug-in was successfully initialized
        VerboseMessage("Announce plug-in was successfully initialized");
    }
    // Allow the server to continue
    return 1;
}

/* ------------------------------------------------------------------------------------------------
 * The server was shutdown and this plug-in must terminate as well.
*/
static void OnServerShutdown(void)
{
    // The server may still send callbacks
    _Clbk->OnServerInitialise       = nullptr;
    _Clbk->OnServerShutdown         = nullptr;
    _Clbk->OnServerFrame            = nullptr;
    // Tell the announce thread to stop
    g_Announce = false;
    // Wait for the announce thread to finish
    if (g_Thread.joinable())
    {
        g_Thread.join();
    }
    // Flush any remaining messages
    FlushMessages();
}

static void OnServerFrame(float /*delta*/)
{
    // Flush any queued messages
    FlushMessages();
}

// ------------------------------------------------------------------------------------------------
void OutputMessageImpl(CCStr msg, va_list args)
{
#if defined(WIN32) || defined(_WIN32)
    HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);

    CONSOLE_SCREEN_BUFFER_INFO csb_before;
    GetConsoleScreenBufferInfo( hstdout, &csb_before);
    SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN);
    printf("[ANNOUNCE] ");

    SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY);
    vprintf(msg, args);
    puts("");

    SetConsoleTextAttribute(hstdout, csb_before.wAttributes);
#else
    printf("%c[0;32m[ANNOUNCE]%c[0;37m", 27, 27);
    vprintf(msg, args);
    puts("");
#endif
}

// ------------------------------------------------------------------------------------------------
void OutputErrorImpl(CCStr msg, va_list args)
{
#if defined(WIN32) || defined(_WIN32)
    HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);

    CONSOLE_SCREEN_BUFFER_INFO csb_before;
    GetConsoleScreenBufferInfo( hstdout, &csb_before);
    SetConsoleTextAttribute(hstdout, FOREGROUND_RED | FOREGROUND_INTENSITY);
    printf("[ANNOUNCE] ");

    SetConsoleTextAttribute(hstdout, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY);
    vprintf(msg, args);
    puts("");

    SetConsoleTextAttribute(hstdout, csb_before.wAttributes);
#else
    printf("%c[0;32m[ANNOUNCE]%c[0;37m", 27, 27);
    vprintf(msg, args);
    puts("");
#endif
}

// ------------------------------------------------------------------------------------------------
void OutputDebug(CCStr msg, ...)
{
#ifdef _DEBUG
    // Initialize the arguments list
    va_list args;
    va_start(args, msg);
    // Call the output function
    OutputMessageImpl(msg, args);
    // Finalize the arguments list
    va_end(args);
#else
    SMOD_UNUSED_VAR(msg);
#endif
}

// ------------------------------------------------------------------------------------------------
void OutputMessage(CCStr msg, ...)
{
    // Initialize the arguments list
    va_list args;
    va_start(args, msg);
    // Call the output function
    OutputMessageImpl(msg, args);
    // Finalize the arguments list
    va_end(args);
}

// ------------------------------------------------------------------------------------------------
void OutputError(CCStr msg, ...)
{
    // Initialize the arguments list
    va_list args;
    va_start(args, msg);
    // Call the output function
    OutputErrorImpl(msg, args);
    // Finalize the arguments list
    va_end(args);
}

// ------------------------------------------------------------------------------------------------
void VerboseMessage(CCStr msg, ...)
{
    // Are verbose messages allowed?
    if (!g_Verbose)
    {
        return;
    }
    // Initialize the arguments list
    va_list args;
    va_start(args, msg);
    // Call the output function
    OutputMessageImpl(msg, args);
    // Finalize the arguments list
    va_end(args);
}

// ------------------------------------------------------------------------------------------------
void VerboseError(CCStr msg, ...)
{
    // Are verbose messages allowed?
    if (!g_Verbose)
    {
        return;
    }
    // Initialize the arguments list
    va_list args;
    va_start(args, msg);
    // Call the output function
    OutputErrorImpl(msg, args);
    // Finalize the arguments list
    va_end(args);
}

// ------------------------------------------------------------------------------------------------
static void QueueMtMsg(bool type, CCStr msg, va_list args)
{
    // Create a copy of the specified arguments list
    va_list args_cpy;
    va_copy(args_cpy, args);
    // Allocate a moderately large string
    String buffer(128, '\0');
    // Attempt to run the specified format
    Int32 size = vsnprintf(&buffer[0], buffer.size(), msg, args);
    // See if a larger buffer is necessary
    if (size > 0 && static_cast< unsigned >(size) > buffer.size())
    {
        // Resize the string buffer to the required size
        buffer.resize(static_cast< unsigned >(size+1), '\0');
        // Attempt to run the specified format
        size = vsnprintf(&buffer[0], buffer.size(), msg, args_cpy);
    }
    // Finalize the arguments list copy
    va_end(args_cpy);
    // See if the format failed
    if (size < 0)
    {
        return;
    }
    // Remove unwanted characters
    buffer.resize(size+1);
    // Acquire a global lock
    std::lock_guard< std::mutex > lock(g_Mutex);
    // Emplace the message into the message queue
    g_Messages.emplace(std::move(buffer), type);
}

// ------------------------------------------------------------------------------------------------
void MtOutputMessage(CCStr msg, ...)
{
    // Initialize the arguments list
    va_list args;
    va_start(args, msg);
    // Attempt to generate and queue the message
    QueueMtMsg(true, msg, args);
    // Finalize the arguments list
    va_end(args);
}

// ------------------------------------------------------------------------------------------------
void MtOutputError(CCStr msg, ...)
{
    // Initialize the arguments list
    va_list args;
    va_start(args, msg);
    // Attempt to generate and queue the message
    QueueMtMsg(false, msg, args);
    // Finalize the arguments list
    va_end(args);
}

// ------------------------------------------------------------------------------------------------
void MtVerboseMessage(CCStr msg, ...)
{
    // Are verbose messages allowed?
    if (!g_Verbose)
    {
        return;
    }
    // Initialize the arguments list
    va_list args;
    va_start(args, msg);
    // Attempt to generate and queue the message
    QueueMtMsg(true, msg, args);
    // Finalize the arguments list
    va_end(args);
}

// ------------------------------------------------------------------------------------------------
void MtVerboseError(CCStr msg, ...)
{
    // Are verbose messages allowed?
    if (!g_Verbose)
    {
        return;
    }
    // Initialize the arguments list
    va_list args;
    va_start(args, msg);
    // Attempt to generate and queue the message
    QueueMtMsg(false, msg, args);
    // Finalize the arguments list
    va_end(args);
}

} // Namespace:: SMod
Beispiel #22
0
void Messages::vadd_msg(game_message_type type, const char *msg, va_list ap)
{
    player_messages.add_msg_string(vstring_format(msg, ap), type);
}