Updated rcon protocol for BC2?

Post Reply
User avatar
merc248
A semi-regular
A semi-regular
Posts: 27
https://www.youtube.com/channel/UC40BgXanDqOYoVCYFDSTfHA
Joined: Sun Apr 04, 2010 9:54 pm
Location: Seattle, WA
Contact:

Updated rcon protocol for BC2?

Post by merc248 »

Hi guys,

I'm wondering if anyone knows if there's an updated document describing the rcon protocol for BC2? I saw one for R3, but I wasn't sure if that's missing a ton of info ever since the servers have been upgraded to R8 (and soon R9).
Image
Image
User avatar
Edge100x
Founder
Founder
Posts: 12945
Joined: Thu Apr 18, 2002 11:04 pm
Location: Seattle
Contact:

Re: Updated rcon protocol for BC2?

Post by Edge100x »

Aye, there's a link to one in the "R9 is coming" post here: http://www.nfoservers.com/forums/viewto ... f=4&t=4434
User avatar
merc248
A semi-regular
A semi-regular
Posts: 27
Joined: Sun Apr 04, 2010 9:54 pm
Location: Seattle, WA
Contact:

Re: Updated rcon protocol for BC2?

Post by merc248 »

Sweet, thanks.

If anyone's interested: I'm trying to code up a simple script that polls the server for server population info; if the server population is above a certain threshold, then it will email me every hour (this could be improved upon by only emailing me if the previously measured average jumps up in a significant way.)

Right now, I just use "wget" or "ftp" on my GameTracker page, then cut away all of the extra HTML to get the server population number.

If anyone's interested in the script I've cooked up so far, let me know. It's a UNIX shell script, so you'd have to throw it on a UNIX box for it to work.
Image
Image
User avatar
Chenzo
A semi-regular
A semi-regular
Posts: 27
Joined: Mon Mar 15, 2010 8:40 am
Location: PA, USA
Contact:

Re: Updated rcon protocol for BC2?

Post by Chenzo »

What are you writing this in?

I had found/ganked/tweaked a script from a BC2 forum somewhere and made this page:

http://firstdigital.site.nfoservers.com/

which pulls my server's current data (i.e. # of players, current map, player names, etc...) It's in PHP and uses a socket connection to the server itself to gather the info (as opposed to a 3rd party site, like gametracker...)
Image
User avatar
Chenzo
A semi-regular
A semi-regular
Posts: 27
Joined: Mon Mar 15, 2010 8:40 am
Location: PA, USA
Contact:

Re: Updated rcon protocol for BC2?

Post by Chenzo »

reading fail... I see yer writing it in UNIX shell script... I guess PHP isn't going to help you much. (Plus, I'm not sure how you could run a PHP script as a reoccurring task.)
Image
User avatar
Mike Rowe
A regular
A regular
Posts: 41
Joined: Fri Dec 04, 2009 10:12 pm

Re: Updated rcon protocol for BC2?

Post by Mike Rowe »

mind sharing your script? the squad part is pretty cool
Its a Dirty Job
User avatar
Chenzo
A semi-regular
A semi-regular
Posts: 27
Joined: Mon Mar 15, 2010 8:40 am
Location: PA, USA
Contact:

Re: Updated rcon protocol for BC2?

Post by Chenzo »

Sure...

copy and paste the code below into a .php file. Change the 4 variables at the top of the PHP code to match your server ip, port, rcon port, and rcon password.

The rcon password is required to get the player list. But if you just wanted server name, mode, map, and player count, you can remove that part and not use your rcon pw.

(Obviously you'll have to change the banner to your own, and adjust the title/links and whatnot, but... this should be good enough to get you going...)

PHP CODE:

Code: Select all

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>1st Digital Infantry's BF:BC2 Server Info</title>
<style type="text/css">
<!--
body {
	background-color: #333;
}
body,td,th {
	font-family: Verdana, Geneva, sans-serif;
	font-size: 10px;
	color: #FFF;
}
.serverTitle {
	font-size: 12px;
}
-->
</style></head>

<body text="#FFFFFF" link="#CCCCCC" vlink="#CCCCCC" alink="#CCCCCC">


<?php

// This code is a port of the functions from http://static.cdn.ea.com/dice/u/f/bfbc2/Static/BFBC2_PC_Server_R3_519901_RemoteAdministration.zip

$ip = '216.52.143.157'; //Server IP
$game_port = 19567; //Server Port (only for display purposes)
$query_port = 48888; // rcon query port
$rCpw = "xxxxxxx"; //rcon password

$clientSequenceNr = 0;

function EncodeClientRequest($words)
{
    $packet = EncodePacket(False, False, $clientSequenceNr, $words);
    $clientSequenceNr++;
    return $packet;
}

function EncodeHeader($isFromServer, $isResponse, $sequence)
{
    $header = $sequence & 0x3fffffff;
    if ($isFromServer)
        $header += 0x80000000;
    if ($isResponse)
        $header += 0x40000000;

    // Not tested this bit
        
    return pack('I', $header);
}

function DecodeHeader($data)
{
    $header = unpack('I', $data);    
    return array($header & 0x80000000, $header & 0x40000000, $header & 0x3fffffff);
}


function EncodeInt32($size)
{
    return pack('I', $size);
}

function DecodeInt32($data)
{
    $decode = unpack('I', $data);
    return $decode[1];
}
    

function EncodeWords($words)
{
    $size = 0;
    $encodedWords = '';
    foreach ($words as $word)
    {
        $strWord = $word;
        $encodedWords .= EncodeInt32(strlen($strWord));
        $encodedWords .= $strWord;
        $encodedWords .= "\x00";
        $size += strlen($strWord) + 5;
    }
    return array($size, $encodedWords);
}
    
function DecodeWords($size, $data)
{
    $numWords = DecodeInt32($data);        
    $offset = 0;    
    while ($offset < $size)
    {
        $wordLen = DecodeInt32(substr($data,$offset,4));
        $word = substr($data,$offset+4,$wordLen);
        $words[] = $word;
        $offset += $wordLen + 5;        
    }

    return $words;
}

function EncodePacket($isFromServer, $isResponse, $sequence, $words)
{
    $words = explode(' ',$words);
    $encodedHeader = EncodeHeader($isFromServer, $isResponse, $sequence);        
    $encodedNumWords = EncodeInt32(count($words));    
    list($wordsSize, $encodedWords) = EncodeWords($words);
    $encodedSize = EncodeInt32($wordsSize + 12);    
    return $encodedHeader . $encodedSize . $encodedNumWords . $encodedWords;
}

function DecodePacket($data)
{
    list($isFromServer, $isResponse, $sequence) = DecodeHeader($data);
    $wordsSize = DecodeInt32(substr($data,4,4)) - 12;
    $words = DecodeWords($wordsSize, substr($data,12));
    return array($isFromServer, $isResponse, $sequence, $words);

}


function squadName($sID) {
	$sName = "";
	switch ($sID) {
		case 1:
			$sName = "Alpha";
			break;
		case 2:
			$sName = "Bravo";
			break;
		case 3:
			$sName = "Charlie";
			break;
		case 4:
			$sName = "Delta";
			break;
		case 5:
			$sName = "Echo";
			break;
		case 6:
			$sName = "Foxtrot";
			break;
		case 7:
			$sName = "Golf";
			break;
		case 8:
			$sName = "Hotel";
			break;
		default:
			$sName = "No Squad";
	}	
	
	return ($sName);
}



function getMapName($fileName) {
	
	$theMapName = "";
	$pN = split('_', $fileName) ;

	$partName = substr($pN[1], 0, 3);

	switch ($partName) {
		case "001":
			$theMapName = "Panama Canal";
			break;
		case "002":
			$theMapName = "Valparaíso";
			break;
		case "003":
			$theMapName = "Laguna Alta";
			break;
		case "004":
			$theMapName = "Isla Inocentes";
			break;
		case "005":
			$theMapName = "Atacama Desert";
			break;
		case "006":
			$theMapName = "Arica Harbor";
			break;
		case "007":
			$theMapName = "White Pass";
			break;
		case "008":
			$theMapName = "Nelson Bay";
			break;
		case "009":
			$theMapName = "Laguna Presa";
			break;
		case "012":
			$theMapName = "Port Valdez";
			break;
		default:
			$theMapName = $fileName;
	}
	return ($theMapName);
}


function getMapImage($fileName) {
	$theMapName = "";
	$pN = split('_', $fileName) ;

	$partName = substr($pN[1], 0, 3);
	$theMapName = "MP_" . $partName . ".jpg";
	return ($theMapName);
}




$sock = fsockopen( "tcp://" . $ip, $query_port);
if($sock != false)
{
    socket_set_timeout($sock, 0, 500000);
    fwrite($sock,EncodeClientRequest("serverInfo")); // OK, serverName, current playercount, max playercount , gamemode, map    
    list($isFromServer, $isResponse, $sequence, $words) = DecodePacket(fread($sock, 4096));
$elements = count($words)-1;
for($i=0;$i<$elements;$i=$i+5)
{
	$sName = $words[1+$i];
	$scPlayers = $words[2+$i];
	$stPlayers = $words[3+$i];
	$sMode = $words[4+$i];
	$sMap = $words[5+$i];
}
    $tempS = "login.plainText " . $rCpw;
	fwrite($sock,EncodeClientRequest($tempS ));
    list($isFromServer, $isResponse, $sequence, $words) = DecodePacket(fread($sock, 4096));
       
    fwrite($sock,EncodeClientRequest("admin.listPlayers all"));
    list($isFromServer, $isResponse, $sequence, $words) = DecodePacket(fread($sock, 4096)); // clantag, player name, squadID, teamID

$attackArray = array();
$defendArray = array();
$aCount = 0;
$dCount = 0;

for ($sq=1; $sq<10; $sq++) {
	$attackArray[sq] = array();
	$defendArray[sq] = array();
}


$theCount = count($words);
$pa = 1;
$userCount = 1;


$tempTag = "";
$tempName = "";
$tempSquadID = 50;
$tempTeamID = 50;

for ($q=0; $q<$theCount; $q++) {
	//This is getting everything... in one long array...
	
	if ($q > 0) {
		if ($pa == 1) {
			$tempTag = $words[$q];
		}
		if ($pa == 2) {
			$tempName = $words[$q];
		}
		if ($pa == 3) {
			$tempSquadID = $words[$q]  + 1;
			if ($tempSquadID == 25) {
				$tempSquadID = 9;
			}
		}
		if ($pa == 4) {
			$tempTeamID = $words[$q];
		}
		$pa++;
		if ($pa > 4) {
			if ($tempTeamID == 1) {
				//echo"attack";
				$attackArray[$tempSquadID][] = array($tempTag, $tempName);
				$aCount++;
			} else {
				//echo"defend";
				$defendArray[$tempSquadID][] = array($tempTag, $tempName);
				$dCount++;
			}
			$pa = 1;	
			$userCount++;
		}
	}
}



    fwrite($sock,EncodeClientRequest("quit"));
    list($isFromServer, $isResponse, $sequence, $words) =  DecodePacket(fread($sock, 4096));  
    fclose($sock);
}



?>

<div align="center">
  <p><a href="http://www.1stdigitalinfantry.com/forums"><img src="1di_serverban_01.png" alt="1st Digital Infantry Battlegrounds" width="512" height="64" border="1" /></a></p>
  <p><font class="serverTitle"><strong><?php echo $sName;?></strong></font><br />
  <?php echo $ip . ":" . $game_port;?><br />
  Join Us: <a href="http://www.1stdigitalinfantry.com/forums" title="1st Digital Infantry" target="_blank">www.1stdigitalinfantry.com/forums</a> </p>
  <p><br />
    Mode: <strong><?php echo $sMode;?></strong><br />
    Current Players: <strong><?php echo $scPlayers . "/" . $stPlayers;?></strong>    <br />
    Current Map: <strong><?php echo getMapName($sMap);?></strong><br />
  <?php echo'<img src="images/' . getMapImage($sMap) . '" width="178" height="100" />' ?>
  </p>
  <table width="900" border="0" align="center" cellpadding="6" cellspacing="6">
    <tr>
      <td width="429" bgcolor="#666666"><div align="center"><strong>ATTACKERS</strong> (<?php echo $aCount; ?>)</div></td>
      <td width="429" bgcolor="#666666"><div align="center"><strong>DEFENDERS</strong> (<?php echo $dCount; ?>)</div></td>
    </tr>
    <tr>
      <td valign="top" bgcolor="#666666">
      <?php 
	  
	  for ($e=1; $e<10; $e++) {
	$squadMemberCount = count($attackArray[$e]);
	 if ($squadMemberCount > 0) {
	?>
      
      <table width="300" border="0" align="center" cellpadding="0" cellspacing="0">
        <tr bgcolor="#333333">
          <td><table width="300" border="0" cellpadding="3" align="center">
            <tr>
              <td colspan="2" bgcolor="#000000"><strong><?php echo squadName($e); ?></strong></td>
            </tr>
            <?php 
			
			for ($f=0; $f<$squadMemberCount; $f++) {
				
				?>
            <tr>
              <td width="82"><font color="#999999"><?php echo $attackArray[$e][$f][0]; ?></font></td>
              <td width="208"><?php echo $attackArray[$e][$f][1]; ?></td>
            </tr>
            
            <?php } ?>
            
          </table></td>
        </tr>
      </table>
      <br />
      <?php
		}
	  
	  }?>
      
      </td>
      <td valign="top" bgcolor="#666666">
      
      <?php 
	  
	  for ($e=1; $e<10; $e++) {
	$squadMemberCount = count($defendArray[$e]);
	 if ($squadMemberCount > 0) {
	?>
      
      <table width="300" border="0" align="center" cellpadding="0" cellspacing="0">
        <tr bgcolor="#333333">
          <td><table width="300" border="0" cellpadding="3" align="center">
            <tr>
              <td colspan="2" bgcolor="#000000"><strong><?php echo squadName($e); ?></strong></td>
            </tr>
            <?php 
			
			for ($f=0; $f<$squadMemberCount; $f++) {
				
				?>
            <tr>
              <td width="82"><font color="#999999"><?php echo $defendArray[$e][$f][0]; ?></font></td>
              <td width="208"><?php echo $defendArray[$e][$f][1]; ?></td>
            </tr>
            
            <?php } ?>
            
          </table></td>
        </tr>
      </table>
      <br />
      <?php
		}
	  
	  }?>
      
      
      </td>
    </tr>
</table>
</div>
</body>
</html>
Image
User avatar
Mike Rowe
A regular
A regular
Posts: 41
Joined: Fri Dec 04, 2009 10:12 pm

Re: Updated rcon protocol for BC2?

Post by Mike Rowe »

nice thanks
Its a Dirty Job
User avatar
merc248
A semi-regular
A semi-regular
Posts: 27
Joined: Sun Apr 04, 2010 9:54 pm
Location: Seattle, WA
Contact:

Re: Updated rcon protocol for BC2?

Post by merc248 »

Chenzo:

It's possible to run php code with cron with the "php" command line interpreter.

I'll check out your code when I'm at work today. :)
Image
Image
User avatar
merc248
A semi-regular
A semi-regular
Posts: 27
Joined: Sun Apr 04, 2010 9:54 pm
Location: Seattle, WA
Contact:

Re: Updated rcon protocol for BC2?

Post by merc248 »

Here's what I've cooked up so far (I'll likely switch over to the PHP version soon, or just cook up my own version in Perl or something.)

http://redbluemagenta.com/programs/check_bc2_pop.sh
Image
Image
User avatar
Chenzo
A semi-regular
A semi-regular
Posts: 27
Joined: Mon Mar 15, 2010 8:40 am
Location: PA, USA
Contact:

Re: Updated rcon protocol for BC2?

Post by Chenzo »

ah... nice. (Don't have a perl box to run it on... heh.)

I'm reworking the script to produce a xml output for importing into flash... (or anything...)

just got the structure together, I think:

http://firstdigital.site.nfoservers.com ... yerXML.php
Image
Sim
This is my homepage
This is my homepage
Posts: 179
Joined: Thu Jul 30, 2009 9:02 am

Re: Updated rcon protocol for BC2?

Post by Sim »

Would it be possible to keep a log of who connects to our BC2 servers?
That way we can see connection numbers and use it to verify if someone played during an event.
User avatar
Edge100x
Founder
Founder
Posts: 12945
Joined: Thu Apr 18, 2002 11:04 pm
Location: Seattle
Contact:

Re: Updated rcon protocol for BC2?

Post by Edge100x »

PB is a good way to see these connections (and it will be required soon for ranked servers). Right now the logs would need to be downloaded individually through the File manager page in our control panel, but I can look into ways of bundling them together to make it easier to download more than one at once.
Sim
This is my homepage
This is my homepage
Posts: 179
Joined: Thu Jul 30, 2009 9:02 am

Re: Updated rcon protocol for BC2?

Post by Sim »

We have PB enabled and streaming to pbbans on both servers :D.
I did notice the pb logs having this info, but i have no clue how to make a basic problem to skim through the logs and pull out each time someone connects.
Post Reply