Deprecated: The behavior of unparenthesized expressions containing both '.' and '+'/'-' will change in PHP 8: '+'/'-' will take a higher precedence in /home/iano/public_html/tpforums-vb5/forum/includes/class_core.php on line 5842

PHP Warning: Use of undefined constant MYSQL_NUM - assumed 'MYSQL_NUM' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: Use of undefined constant MYSQL_ASSOC - assumed 'MYSQL_ASSOC' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: Use of undefined constant MYSQL_BOTH - assumed 'MYSQL_BOTH' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in ..../includes/functions_navigation.php on line 588

PHP Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in ..../includes/functions_navigation.php on line 612

PHP Warning: Use of undefined constant misc - assumed 'misc' (this will throw an Error in a future version of PHP) in ..../global.php(29) : eval()'d code(6) : eval()'d code on line 1

PHP Warning: Use of undefined constant index - assumed 'index' (this will throw an Error in a future version of PHP) in ..../global.php(29) : eval()'d code(6) : eval()'d code on line 1

PHP Warning: Use of undefined constant misc - assumed 'misc' (this will throw an Error in a future version of PHP) in ..../includes/class_bootstrap.php(1422) : eval()'d code(4) : eval()'d code on line 1

PHP Warning: Use of undefined constant index - assumed 'index' (this will throw an Error in a future version of PHP) in ..../includes/class_bootstrap.php(1422) : eval()'d code(4) : eval()'d code on line 1

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6
How to get Server Status and Motd?
Results 1 to 6 of 6

Thread: How to get Server Status and Motd?

  1. #1

    Question How to get Server Status and Motd?

    I was wondering if there is a specific port configured with OT and Live server where you can get the server status and MOTD.

    Is there one that accepts GET/POST. Also do the use of Geisor or any other CMS system offer additional endpoints?

  2. #2
    Senior Member
    Join Date
    Jan 2008
    Location
    Cambridge, England
    Posts
    725
    I remember making a system some time ago for OTs where it sent a request to 7171 using a PHP API, and could get a response from the server containing the MOTD and status of the server (open / closed, or timeout if offline), but it was a bit shit to run frequently, I ended up running it every 2 hours for each server I was watching.

    Edit: Some actual advice, try use Wireshark and log in to an OT, you should be able to make some sense of the packets sent and received.

  3. #3
    Senior Member
    Join Date
    Apr 2008
    Posts
    689
    There must be a way since otservlist queries that information from its registered servers. maybe try asking in a ot server specific forum?

  4. #4
    Senior Member
    Join Date
    Jan 2008
    Location
    Cambridge, England
    Posts
    725
    Quote Originally Posted by Farsa View Post
    There must be a way since otservlist queries that information from its registered servers. maybe try asking in a ot server specific forum?
    I think the method I was using is probably the correct one (to ping the login server infrequently) but I suspect my implementation was poor at best, it was my first and only attempt to date, so probably incredibly sloppy.

  5. #5
    I will do that thank you. That is kinda what i figured but I thought I would fish for some experience in the subject before diving right in.

    Thanks

  6. #6
    Not sure exactly what data you need to send, but this is OT's server.cpp (could give you a clue):

    Code:
    IpConnectMap ProtocolStatus::ipConnectMap;
    
    void ProtocolStatus::onRecvFirstMessage(NetworkMessage& msg)
    {
    	IpConnectMap::const_iterator it = ipConnectMap.find(getIP());
    	if(it != ipConnectMap.end() && OTSYS_TIME() < it->second + g_config.getNumber(ConfigManager::STATUSQUERY_TIMEOUT))
    	{
    		getConnection()->close();
    		return;
    	}
    
    	ipConnectMap[getIP()] = OTSYS_TIME();
    	uint8_t type = msg.get<char>();
    	switch(type)
    	{
    		case 0xFF:
    		{
    			if(msg.getString(false, 4) == "info")
    			{
    				if(OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false))
    				{
    					TRACK_MESSAGE(output);
    					if(Status* status = Status::getInstance())
    					{
    						bool sendPlayers = false;
    						if(msg.size() > msg.position())
    							sendPlayers = msg.get<char>() == 0x01;
    
    						output->putString(status->getStatusString(sendPlayers), false);
    					}
    
    					setRawMessages(true); // we dont want the size header, nor encryption
    					OutputMessagePool::getInstance()->send(output);
    				}
    			}
    
    			break;
    		}
    
    		case 0x01:
    		{
    			uint32_t requestedInfo = msg.get<uint16_t>(); //Only a Byte is necessary, though we could add new infos here
    			if(OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false))
    			{
    				TRACK_MESSAGE(output);
    				if(Status* status = Status::getInstance())
    					status->getInfo(requestedInfo, output, msg);
    
    				OutputMessagePool::getInstance()->send(output);
    			}
    
    			break;
    		}
    
    		default:
    			break;
    	}
    
    	getConnection()->close();
    }
    
    void ProtocolStatus::deleteProtocolTask()
    {
    #ifdef __DEBUG_NET_DETAIL__
    	std::clog << "Deleting ProtocolStatus" << std::endl;
    #endif
    	Protocol::deleteProtocolTask();
    }
    
    std::string Status::getStatusString(bool sendPlayers) const
    {
    	char buffer[90];
    	xmlDocPtr doc;
    	xmlNodePtr p, root;
    
    	doc = xmlNewDoc((const xmlChar*)"1.0");
    	doc->children = xmlNewDocNode(doc, NULL, (const xmlChar*)"tsqp", NULL);
    	root = doc->children;
    
    	xmlSetProp(root, (const xmlChar*)"version", (const xmlChar*)"1.0");
    
    	p = xmlNewNode(NULL,(const xmlChar*)"serverinfo");
    	sprintf(buffer, "%u", (uint32_t)getUptime());
    	xmlSetProp(p, (const xmlChar*)"uptime", (const xmlChar*)buffer);
    	xmlSetProp(p, (const xmlChar*)"ip", (const xmlChar*)g_config.getString(ConfigManager::IP).c_str());
    	xmlSetProp(p, (const xmlChar*)"servername", (const xmlChar*)g_config.getString(ConfigManager::SERVER_NAME).c_str());
    	sprintf(buffer, "%d", g_config.getNumber(ConfigManager::LOGIN_PORT));
    	xmlSetProp(p, (const xmlChar*)"port", (const xmlChar*)buffer);
    	xmlSetProp(p, (const xmlChar*)"location", (const xmlChar*)g_config.getString(ConfigManager::LOCATION).c_str());
    	xmlSetProp(p, (const xmlChar*)"url", (const xmlChar*)g_config.getString(ConfigManager::URL).c_str());
    	xmlSetProp(p, (const xmlChar*)"server", (const xmlChar*)SOFTWARE_NAME);
    	xmlSetProp(p, (const xmlChar*)"version", (const xmlChar*)SOFTWARE_VERSION);
    	xmlSetProp(p, (const xmlChar*)"client", (const xmlChar*)SOFTWARE_PROTOCOL);
    	xmlAddChild(root, p);
    
    	p = xmlNewNode(NULL,(const xmlChar*)"owner");
    	xmlSetProp(p, (const xmlChar*)"name", (const xmlChar*)g_config.getString(ConfigManager::OWNER_NAME).c_str());
    	xmlSetProp(p, (const xmlChar*)"email", (const xmlChar*)g_config.getString(ConfigManager::OWNER_EMAIL).c_str());
    	xmlAddChild(root, p);
    
    	p = xmlNewNode(NULL,(const xmlChar*)"players");
    	sprintf(buffer, "%d", g_game.getPlayersOnline());
    	xmlSetProp(p, (const xmlChar*)"online", (const xmlChar*)buffer);
    	sprintf(buffer, "%d", g_config.getNumber(ConfigManager::MAX_PLAYERS));
    	xmlSetProp(p, (const xmlChar*)"max", (const xmlChar*)buffer);
    	sprintf(buffer, "%d", g_game.getPlayersRecord());
    	xmlSetProp(p, (const xmlChar*)"peak", (const xmlChar*)buffer);
    	if(sendPlayers)
    	{
    		std::stringstream ss;
    		for(AutoList<Player>::iterator it = Player::autoList.begin(); it != Player::autoList.end(); ++it)
    		{
    			if(it->second->isRemoved() || it->second->isGhost())
    				continue;
    
    			if(!ss.str().empty())
    				ss << ";";
    
    			ss << it->second->getName() << "," << it->second->getVocationId() << "," << it->second->getLevel();
    		}
    
    		xmlNodeSetContent(p, (const xmlChar*)ss.str().c_str());
    	}
    
    	xmlAddChild(root, p);
    
    	p = xmlNewNode(NULL,(const xmlChar*)"monsters");
    	sprintf(buffer, "%d", g_game.getMonstersOnline());
    	xmlSetProp(p, (const xmlChar*)"total", (const xmlChar*)buffer);
    	xmlAddChild(root, p);
    
    	p = xmlNewNode(NULL,(const xmlChar*)"npcs");
    	sprintf(buffer, "%d", g_game.getNpcsOnline());
    	xmlSetProp(p, (const xmlChar*)"total", (const xmlChar*)buffer);
    	xmlAddChild(root, p);
    
    	p = xmlNewNode(NULL,(const xmlChar*)"map");
    	xmlSetProp(p, (const xmlChar*)"name", (const xmlChar*)g_config.getString(ConfigManager::MAP_NAME).c_str());
    	xmlSetProp(p, (const xmlChar*)"author", (const xmlChar*)g_config.getString(ConfigManager::MAP_AUTHOR).c_str());
    
    	uint32_t mapWidth, mapHeight;
    	g_game.getMapDimensions(mapWidth, mapHeight);
    	sprintf(buffer, "%u", mapWidth);
    	xmlSetProp(p, (const xmlChar*)"width", (const xmlChar*)buffer);
    	sprintf(buffer, "%u", mapHeight);
    
    	xmlSetProp(p, (const xmlChar*)"height", (const xmlChar*)buffer);
    	xmlAddChild(root, p);
    
    	xmlNewTextChild(root, NULL, (const xmlChar*)"motd", (const xmlChar*)g_config.getString(ConfigManager::MOTD).c_str());
    
    	xmlChar* s = NULL;
    	int32_t len = 0;
    	xmlDocDumpMemory(doc, (xmlChar**)&s, &len);
    
    	std::string xml;
    	if(s)
    		xml = std::string((char*)s, len);
    
    	xmlFree(s);
    	xmlFreeDoc(doc);
    	return xml;
    }
    
    void Status::getInfo(uint32_t requestedInfo, OutputMessage_ptr output, NetworkMessage& msg) const
    {
    	if(requestedInfo & REQUEST_BASIC_SERVER_INFO)
    	{
    		output->put<char>(0x10);
    		output->putString(g_config.getString(ConfigManager::SERVER_NAME).c_str());
    		output->putString(g_config.getString(ConfigManager::IP).c_str());
    
    		char buffer[10];
    		sprintf(buffer, "%d", g_config.getNumber(ConfigManager::LOGIN_PORT));
    		output->putString(buffer);
    	}
    
    	if(requestedInfo & REQUEST_SERVER_OWNER_INFO)
    	{
    		output->put<char>(0x11);
    		output->putString(g_config.getString(ConfigManager::OWNER_NAME).c_str());
    		output->putString(g_config.getString(ConfigManager::OWNER_EMAIL).c_str());
    	}
    
    	if(requestedInfo & REQUEST_MISC_SERVER_INFO)
    	{
    		output->put<char>(0x12);
    		output->putString(g_config.getString(ConfigManager::MOTD).c_str());
    		output->putString(g_config.getString(ConfigManager::LOCATION).c_str());
    		output->putString(g_config.getString(ConfigManager::URL).c_str());
    
    		uint64_t uptime = getUptime();
    		output->put<uint32_t>((uint32_t)(uptime >> 32));
    		output->put<uint32_t>((uint32_t)(uptime));
    	}
    
    	if(requestedInfo & REQUEST_PLAYERS_INFO)
    	{
    		output->put<char>(0x20);
    		output->put<uint32_t>(g_game.getPlayersOnline());
    		output->put<uint32_t>(g_config.getNumber(ConfigManager::MAX_PLAYERS));
    		output->put<uint32_t>(g_game.getPlayersRecord());
    	}
    
    	if(requestedInfo & REQUEST_SERVER_MAP_INFO)
    	{
    		output->put<char>(0x30);
    		output->putString(g_config.getString(ConfigManager::MAP_NAME).c_str());
    		output->putString(g_config.getString(ConfigManager::MAP_AUTHOR).c_str());
    
    		uint32_t mapWidth, mapHeight;
    		g_game.getMapDimensions(mapWidth, mapHeight);
    		output->put<uint16_t>(mapWidth);
    		output->put<uint16_t>(mapHeight);
    	}
    
    	if(requestedInfo & REQUEST_EXT_PLAYERS_INFO)
    	{
    		output->put<char>(0x21);
    		std::list<std::pair<std::string, uint32_t> > players;
    		for(AutoList<Player>::iterator it = Player::autoList.begin(); it != Player::autoList.end(); ++it)
    		{
    			if(!it->second->isRemoved() && !it->second->isGhost())
    				players.push_back(std::make_pair(it->second->getName(), it->second->getLevel()));
    		}
    
    		output->put<uint32_t>(players.size());
    		for(std::list<std::pair<std::string, uint32_t> >::iterator it = players.begin(); it != players.end(); ++it)
    		{
    			output->putString(it->first);
    			output->put<uint32_t>(it->second);
    		}
    	}
    
    	if(requestedInfo & REQUEST_PLAYER_STATUS_INFO)
    	{
    		output->put<char>(0x22);
    		const std::string name = msg.getString();
    
    		Player* p = NULL;
    		if(g_game.getPlayerByNameWildcard(name, p) == RET_NOERROR && !p->isGhost())
    			output->put<char>(0x01);
    		else
    			output->put<char>(0x00);
    	}
    
    	if(requestedInfo & REQUEST_SERVER_SOFTWARE_INFO)
    	{
    		output->put<char>(0x23);
    		output->putString(SOFTWARE_NAME);
    		output->putString(SOFTWARE_VERSION);
    		output->putString(SOFTWARE_PROTOCOL);
    	}
    }

    Some vars from .h file:
    Code:
    enum RequestedInfo_t
    {
    	REQUEST_BASIC_SERVER_INFO 	= 0x01,
    	REQUEST_SERVER_OWNER_INFO	= 0x02,
    	REQUEST_MISC_SERVER_INFO	= 0x04,
    	REQUEST_PLAYERS_INFO		= 0x08,
    	REQUEST_SERVER_MAP_INFO		= 0x10,
    	REQUEST_EXT_PLAYERS_INFO	= 0x20,
    	REQUEST_PLAYER_STATUS_INFO	= 0x40,
    	REQUEST_SERVER_SOFTWARE_INFO	= 0x80
    };

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •