Ok this is fairly simple, but I don't know C++ so I am not sure the specifics here, hence why I am asking for help! I am fair with PERL and want this for a website, so PERL is perfect if anyone could help me with this...
This C / C++ code is from EveMON source code (
http://evemon.battleclinic.com/snaps/ ) file 2007-08-16_rev_1091.zip
All it does is connect to the EVE server to tell the server status and how many players are currently playing (should be simple right?)
I have tried this in PERL and have gotten to the point where I can connect to the server, but I am having trouble with the "encoding" and "decoding" of it all...
Here is the C / C++ snippet from path_to_local_source_/EVEM
on.Common/
EveServer.
cs:
/// <summary>
/// Called when we have data from TQ
/// </summary>
/// <param name="ar"></param>
private void ConnectCallback(IAsyncResu
lt ar)
{
TcpClient conn = (TcpClient)ar.AsyncState;
if (ar.IsCompleted && conn.Connected)
{
m_status = Status.Online;
try
{
NetworkStream stream = conn.GetStream();
byte[] data = {0x23, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00,
0x00, 0x14, 0x06, 0x04, 0xE8, 0x99, 0x02, 0x00,
0x05, 0x8B, 0x00, 0x08, 0x0A, 0xCD, 0xCC, 0xCC,
0xCC, 0xCC, 0xCC, 0x00, 0x40, 0x05, 0x49, 0x0F,
0x10, 0x05, 0x42, 0x6C, 0x6F, 0x6F, 0x64};
stream.Write(data, 0, data.Length);
byte[] response = new byte[256];
int bytes = stream.Read(response, 0, 256);
m_users = 0;
if (bytes > 21)
{
// Amended usercount checks, info from clef on iRC
// [16:01] <clef> BradStone: for the moment, take that byte[19] ... if it is 1, 8 or 9, the usercount is 0.
// [16:01] <clef> BradStone: if it is 4, the next 32bit are the usercount. 5 -> 16bit. 6 -> 8bit.
int usersBytes = 4 - (response[19]-3);
if (usersBytes > 0 && usersBytes < 5)
{
int multiplyer = 1;
for (int i=0;i<usersBytes;i++)
{
m_users = response[20+i] * multiplyer;
multiplyer *= 256;
}
}
}
string str = new System.Text.ASCIIEncoding(
).GetStrin
g(response
);
Match m = m_re.Match(str);
if (m.Success)
{
m_status = Status.Starting;
m_countdown = Convert.ToInt32(m.Groups[1
].Value) - 1;
m_tmrCountdown.Enabled = true;
}
conn.EndConnect(ar);
}
catch (Exception)
{
m_status = Status.Offline;
m_users = 0;
}
}
else
{
m_status = Status.Offline;
m_users = 0;
}
// Close the connection
conn.Close();
// Everything checked, lets see if we need to update something ...
setInformationText();
if (m_status != m_lastStatus)
{
if (ServerStatusChanged != null)
{
ServerStatusChanged(m_inst
ance, new EveServerEventArgs(m_ballo
onText, m_balloonIcon));
}
m_lastStatus = m_status;
}
if (ServerStatusUpdated != null)
{
ServerStatusUpdated(m_inst
ance, new EveServerEventArgs(m_statu
sText));
}
// switch off the semaphore
m_checkingServer = false;
}
private void checkServerStatus(object source, EventArgs e)
{
// Check the semaphore to see if we're mid check
if (m_checkingServer == true)
{
return;
}
// check to see if we are recovering from loss of connection (timer was set to 30 seconds)
if (m_tmrCheck.Interval == 30000)
{
// network is back - set timer to correct value.
m_tmrCheck.Interval = m_settings.StatusUpdateInt
erval * 60000;
}
// check that we have a network connection
if (!InternetCS.IsConnectedTo
Internet(m
_settings.
Connectivi
tyURL))
{
// switch on the semaphore
m_checkingServer = true;
// oops, we've lost the network - reset timer to 30 seconds
m_tmrCheck.Interval = 30000;
m_statusText = "// TQ Server Status Unknown";
if (ServerStatusUpdated != null)
{
ServerStatusUpdated(m_inst
ance, new EveServerEventArgs(m_statu
sText));
}
// switch off the semaphore
m_checkingServer = false;
return;
}
TcpClient conn = new TcpClient();
try
{
// Set default port and ip - also perform final validation
int serverPort = 26000;
System.Net.IPAddress serverAddress = System.Net.IPAddress.Parse
("87.237.3
8.200");
// If the user selected port is valid use that one, maybe they hand edited the xml file and bypassed input validation
if (int.TryParse(m_settings.C
ustomTQPor
t, out serverPort) && System.Net.IPAddress.TryPa
rse(m_sett
ings.Custo
mTQAddress
, out serverAddress))
{
if (System.Diagnostics.Debugg
er.IsAttac
hed)
{
System.Diagnostics.Debug.W
riteLine("
DEBUG: TQ check connecting to [" + serverAddress.ToString() + ":" + serverPort.ToString() + "]");
}
conn.BeginConnect(serverAd
dress.ToSt
ring(), serverPort, ConnectCallback, conn);
}
else
throw new Exception("Invalid TQ server IP or port"); // Shouldn't ever get here
}
catch (Exception)
{
conn.Close();
m_status = Status.Offline;
m_users = 0;
// switch off the semaphore - the check failed
m_checkingServer = false;
}
}
My test seems to be hanging after the ->send(); which is why the eval statement is in there. I am not very experienced with socket programming so I'm sure it's something I'm missing... My test code so far:
#!/usr/bin/perl
$host = "87.237.38.200";
$port = "26000";
$method = "tcp";
$|=1;
print "Connecting... \n\n";
@DATA = ("23", "00", "00", "00", "7E", "00", "00", "00",
"00", "14", "06", "04", "E8", "99", "02", "00",
"05", "8B", "00", "08", "0A", "CD", "CC", "CC",
"CC", "CC", "CC", "00", "40", "05", "49", "0F",
"10", "05", "42", "6C", "6F", "6F", "64");
use IO::Socket;
$remote = IO::Socket::INET->new(Prot
o => "tcp", PeerAddr => "$host", PeerPort => "$port");
if($remote)
{
$|=1;
print "Connected to $host on port $port.\n\n";
foreach $hex (@DATA)
{
chomp $hex;
$hex =~ s/([a-fA-F0-9]{2})/chr(hex
$1)/eg;
$send .= $hex;
}
eval {
$len = length($send);
$remote->recv($buffer, 1000);
$|=1;
print "RECEIVED: $buffer\n\n";
$remote->send($send, $len);
$|=1;
print "SENT: $send\n\n";
$remote->recv($buffer, 1000);
print "RECEIVED: $buffer\n\n";
}; print $@ if $@;
}
else
{
$|=1;
print "Unable to connect to $host on port $port\n\n";
}
close($remote) or die "Unable to close remote";
Start Free Trial