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; }
// 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)); }
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); } }
void CachingChannel::log(const Poco::Message& msg) { Poco::FastMutex::ScopedLock lock(_mutex); _cache.push_front(msg); if (_size == _maxSize) { _cache.pop_back(); } else ++_size; }
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() ); } }
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; } }
// ------------------------------------------------------------------------------------------------ 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); }
//---------------------------------------------------------------------- // 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; }
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; }
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; }
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." )); }
/* ------------------------------------------------------------------------------------------------ * 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); }
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(); }
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")); }
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(); }
void Messages::vadd_msg(const char *msg, va_list ap) { player_messages.add_msg_string(vstring_format(msg, ap)); }
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; } } }
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)); } } }
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
void Messages::vadd_msg(game_message_type type, const char *msg, va_list ap) { player_messages.add_msg_string(vstring_format(msg, ap), type); }