Initial commit

master
Robert Arkenin 2013-03-07 18:41:55 -05:00
parent cdf753c912
commit 8623ecc4a0
12 changed files with 417 additions and 38 deletions

View File

@ -1,27 +1,62 @@
<?php
$nodes=array();
ini_set('memory_limit', '1024M');
$nodes[0][0][0]="CONTENT_IGNORE";//Initialize array, overwritten later anyway.
require_once 'servercommands.php';
require_once 'miscdefines.php';
require_once 'hardwiredContentTypes.php';
define("CMDTOSERVER", 1); //Otherwise to client
define("CMDSENDRELIABLE", 2);
define("CMDACKNEEDED", 4);
define("CMDACTIONRELIABLE", 8);
require_once 'network.php';
require_once 'processCommunication.php';
require_once 'packet.php';
require_once 'serialize.php';
require_once 'lowLevelNet.php';
require_once 'networkMaintenance.php';
require_once 'sendComm.php';
var_dump(unpack("n",serializeU16(65500)));
var_dump(unpack('n', "\xff\xdc"));
require_once 'knownMap.php';
//define("CMDTOSERVER", 1); //Otherwise to client
//define("CMDSENDRELIABLE", 2);
//define("CMDACKNEEDED", 4);
//define("CMDACTIONRELIABLE", 8);
if (PHP_SAPI != "cli") {
die("Main [FATAL]:Must be run in CLI mode!");
}
if ($argc != 3) {
die("Main [FATAL]:Improper arguments!\r\n Usage: minetestbot.php host port controlfile");
if ($argc != 6) {
var_dump($argv);
var_dump($argc);
die("Main [FATAL]:Improper arguments!\r\n Usage: minetestbot.php <host> <port> <username> <pass> <controlfile>");
}
$serverIp = $argv[1];
$serverPort = $argv[2];
$controlFile = $argv[3];
$username = $argv[3];
$password = $argv[4];
$controlFile = $argv[5];
$serverSocket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
if (false == (@socket_connect($serverSocket, $serverIp, $serverPort))) {
die("Connect [FATAL]:Connect failed: reason: " . socket_strerror(socket_last_error($serverSocket)) . "\n");
if (false == (socket_connect($serverSocket, $serverIp, $serverPort))) {
die("Connect [FATAL]:Connect failed: reason: " . socket_strerror(socket_last_error($serverSocket)) . "\n");
}
$controlHandle = fopen($controlFile, "rb");
$fileReadBuffer = fread($controlHandle, 8);
if (strcasecmp($fileReadBuffer, "mtbotpurephp")!=0){
die("File [FATAL]:Impropper file header, perhaps not a MTBot control file?");
socket_set_nonblock($serverSocket);
//socket_write($serverSocket, "FOOBARFOOBAR");
require_once $controlFile;
//$controlHandle = fopen($controlFile, "rb");
//$fileReadBuffer = fread($controlHandle, 8);
//if (strcasecmp($fileReadBuffer, "mtbotpurephp")!=0){
// die("File [FATAL]:Impropper file header, perhaps not a MTBot control file?");
//}
////TODO: Get password from file
sendTOSERVER_INIT($username, $password);
//$connectSeqNum = sendPacket(FormReliablePacket(FormOriginalPacket("")));
//blockingLoopWaitPacketAck($connectSeqNum);
//while($ourPeerId==0){
// readNetworkPacket($serverSocket);
//}
while(true){
usleep(100);
readNetworkPacket($serverSocket);
}
?>

5
src/knownMap.php Normal file
View File

@ -0,0 +1,5 @@
<?php
?>

7
src/lowLevelNet.php Normal file
View File

@ -0,0 +1,7 @@
<?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
?>

164
src/network.php Normal file
View File

@ -0,0 +1,164 @@
<?php
$packetBuffer = array();
//require_once 'index.php';
define("BASE_HEADER_SIZE", 7);
define("PEER_ID_INEXISTENT", 0);
define("PEER_ID_SERVER", 1);
define("CHANNEL_COUNT", 3);
define("TYPE_CONTROL", 0);
define("CONTROLTYPE_ACK", 0);
define("CONTROLTYPE_SET_PEER_ID", 1);
define("CONTROLTYPE_PING", 2);
define("CONTROLTYPE_DISCO", 3);
define("TYPE_SPLIT", 2);
define("TYPE_RELIABLE", 3);
define("RELIABLE_HEADER_SIZE", 3);
define("SEQNUM_INITIAL", 65500);
$seqnumOut = SEQNUM_INITIAL;
$seqnumIn = SEQNUM_INITIAL;
$ourPeerId = PEER_ID_INEXISTENT;
$serverPeerId = PEER_ID_SERVER;
$bufferedPackets = array();
function readNetworkPacket($socket) {
global $seqnumIn;
global $seqnumOut;
global $ourPeerId;
global $serverPeerId;
global $bufferedPackets;
global $packetsAwaitingSend;
$packet = socket_read($socket, 4096, PHP_BINARY_READ);
if (strlen($packet) > 0) {
echo 'Got packet!';
$protocolId = substr($packet, 0, 4);
$senderPeerId = deserializeU16(substr($packet, 4, 2));
$channel = ord(substr($packet, 6, 1));
$packetType = ord(substr($packet, 7, 1));
switch ($packetType) {
case TYPE_CONTROL:
$controlType = ord(substr($packet, 8, 1));
switch ($controlType) {
case CONTROLTYPE_ACK:
$seqnumAckd = deserializeU16(substr($packet, 9, 2));
unset($packetsAwaitingSend[$seqnumAckd]);
break;
case CONTROLTYPE_SET_PEER_ID:
$peerId = deserializeU16(substr($packet, 9, 1));
$ourPeerId = $peerId;
echo "Got our peer id!";
return true;
break;
case CONTROLTYPE_DISCO:
exit("Disconnected.");
break;
}
break;
case TYPE_RELIABLE:
$incomingSeqnum = deserializeU16(substr($packet, 8, 1));
sendAck($incomingSeqnum);
$packetPayload = substr($packet, 10);
if (isset($bufferedPackets[$seqnumIn])) {
$seqnumIn++;
$seqnumIn = $seqnumIn % 65536;
readNetworkPacket($bufferedPackets[$seqnumIn]);
}
break;
case TYPE_ORIGINAL:
processCommandToClient(substr($packet, 8));
break;
case TYPE_SPLIT:
//TODO Split packet
break;
default:
return false;
break;
}
}
}
function readNetworkPacketNested($packIn) {
global $seqnumIn;
global $seqnumOut;
global $ourPeerId;
global $serverPeerId;
global $packetsAwaitingSend;
global $bufferedPackets;
$packetType = ord(substr($packet, 0, 1));
switch ($packetType) {
case TYPE_CONTROL:
$controlType = ord(substr($packet, 1, 1));
switch ($controlType) {
case CONTROLTYPE_ACK:
$seqnumAckd = deserializeU16(substr($packet, 2, 2));
unset($packetsAwaitingSend[$seqnumAckd]);
case CONTROLTYPE_SET_PEER_ID:
$peerId = deserializeU16(substr($packet, 2, 2));
$ourPeerId = $peerId;
echo "Got our peer ID!";
return true;
break;
case CONTROLTYPE_DISCO:
exit("Disconnected.");
break;
}
break;
case TYPE_RELIABLE:
$incomingSeqnum = deserializeU16(substr($packet, 1, 1));
sendAck($incomingSeqnum);
$packetPayload = substr($packet, 3);
if (isset($bufferedPackets[$seqnumIn])) {
$seqnumIn++;
$seqnumIn = $seqnumIn % 65536;
readNetworkPacketNested($bufferedPackets[$seqnumIn]);
}
break;
case TYPE_ORIGINAL:
processCommandToClient(substr($packet, 1));
break;
case TYPE_SPLIT:
//TODO Split packet
break;
default:
return false;
break;
}
}
function sendPacket($packet) {
global $serverSocket;
socket_write($serverSocket, "\x4f\x45\x74\x03\x00\x01\x00" . $packet);
}
function formReliablePacket($packet) {
global $seqnumOut;
$packetOut = chr(3) . serializeU16($seqnumOut) . $packet;
$seqnumOut++;
return $packetOut;
}
function formOriginalPacket($packet) {
if(strlen($packet)!=0){
return chr(1) . chr(0) . $packet;
}
else{
return chr(1);
}
}
function sendPing() {
global $serverSocket;
$pingPacket = "\x4f\x45\x74\x03\x00\x01\x00" . chr(TYPE_CONTROL) . chr(CONTROLTYPE_PING);
socket_write($serverSocket, $pingPacket);
}
function sendAck($seqnumToAck) {
global $serverSocket;
$ackpacket = "\x4f\x45\x74\x03\x00\x01\x00" . chr(TYPE_CONTROL) . chr(CONTROLTYPE_ACK) . serializeU16($seqnumToAck);
socket_write($serverSocket, $ackPacket);
}
?>

View File

@ -0,0 +1,15 @@
<?php
$packetsAwaitingSend=array();
$lastSend=microtime(true);
function FiveSecPoll(){
global $lastSend;
global $packetsAwaitingSend;
foreach ($packetsAwaitingSend as $seqnumToSend => $data) {
FormReliablePacketWithSeqnum($seqnum, $data);
}
if ((microtime(true)-$lastSend)>=4){
SendPing();
}
}
//function
?>

17
src/packet.php Normal file
View File

@ -0,0 +1,17 @@
<?php
//require_once 'index.php';
//require_once 'network.php';
//class BufferedPacket{
// global $seqnum;
// global $ourPeerId;
// global $serverPeerId;
// public $isControl;
// public $isFrag;
// public $totalFrags;
// public $fragsReady;
// function __construct($seqnum, $t){}
// function isReady(){
// return $totalFrags==$fragsReady;
// }
//}
?>

View File

@ -1,41 +1,105 @@
<?php
require_once 'servercommands.php';
//$testPacket="\x4f\x45\x74\x03\x00\x00\x00\x01\x00\x10\x19\x72\x61\x72\x6b\x65\x6e\x69\x6e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x55\x62\x2b\x48\x57\x64\x71\x4a\x34\x38\x36\x47\x49\x73\x32\x47\x4e\x74\x6e\x47\x31\x4c\x64\x4a\x48\x4e\x4d\x00\x00\x0d\x00\x10";
function processCommandToClient($packet) {
$magicNum=substr($packet,0,4);
$senderPeerId=substr($packet, 4,2);
$packetChannel=substr($packet,6,1);
$payload=substr($packet, 9);
require_once 'servercommands.php';
$testPacket = "\x4f\x45\x74\x03\x00\x00\x00\x01\x00\x10\x19\x72\x61\x72\x6b\x65\x6e\x69\x6e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x55\x62\x2b\x48\x57\x64\x71\x4a\x34\x38\x36\x47\x49\x73\x32\x47\x4e\x74\x6e\x47\x31\x4c\x64\x4a\x48\x4e\x4d\x00\x00\x0d\x00\x10";
function processCommandToClient($packet) {
global $recommended_send_interval;
global $privsarray;
global $mapseed;
global $playerpos;
global $knownMap;
$headerByte = ord(substr($payload, 0, 1));
$datasize = strlen($payload);
print $headerByte;
print "\n";
$headerByte = ord(substr($packet, 0, 1));
$datasize = strlen($packet);
//print $headerByte . "\n";
//print ord(substr($packet, 0, 1));
//print "\n";
print CLIENT_INIT;
switch ($headerByte) {
case CLIENT_INIT:
//var_dump(($magicNum),($senderPeerId), ($packetChannel), $payload);
// print("DUMMY!");
/*sendCmd(SERVER_INIT2); TODO: Implement sending SERVER_INIT2*/
switch ($datasize){
case 2+1+6+8+4:
/*TODO: Unpack codes for data... */
var_dump(($magicNum), ($senderPeerId), ($packetChannel), $packet);
print("DUMMY!");
sendCmd(SERVER_INIT2, array());
/* TODO: CRITICAL Implement sending SERVER_INIT2 */
switch ($datasize) {
case 2 + 1 + 6 + 8 + 4:
/* TODO: Unpack codes for data... */
}
break;
case CLIENT_ACCESS_DENIED:
die("Connect [FATAL]:Connect failed reason: Access denied");
break;
case CLIENT_REMOVENODE:
$nodepos=deserializeNodePos(substr($payload,2));
$nodepos = deserializeNodePos(substr($packet, 1, 6));
removeNode($nodepos);
break;
case CLIENT_ADDNODE:
$nodepos = deserializeNodePos(substr($packet, 1, 6));
$node = deserializeNode(substr($packet, 7));
addNode($nodepos, $node);
break;
case CLIENT_BLOCKDATA:
/* TODO: CRITICAL FIGURE OUT MapNode::deSerialize in mapNode.cpp, as well as deserialize bulk. */
print("Packet Handling [TODO]: CLIENT_BLOCKDATA received but not processed.\n");
break;
case CLIENT_INVENTORY:
/* TODO: MEDIUM Figure out Inventory serialization!!!
* * void InventoryList::deSerialize(std::istream &is) in inventory.cpp
* void Inventory::deSerialize(std::istream &is) in inventory.cpp */
print("Packet Handling [TODO]: CLIENT_INVENTORY received but not processed.\n");
break;
case CLIENT_CHAT_MESSAGE:
$length = deserializeU16(substr($packet, 1, 2));
$message = minetestWideToNarrow(substr($packet));
processChatMsg($message);
break;
case CLIENT_MOVE_PLAYER:
$playerpos = readV3F100(substr($packet, 1, 12));
break;
case CLIENT_DEATHSCREEN:
print("Player [INFO]: Player died at " . $playerpos . toString() . ".\n");
sendCmd(SERVER_RESPAWN, array());
break;
case CLIENT_PRIVILEGES:
$numPrivs = deserializeU16(substr($packet, 1, 2));
$privsarray = array();
$packetPos = 3;
for ($i = 1; $i <= numPrivs; $i++) {
$thisIterationLength = deserializeU16(substr($packet, $packetPos, 2));
$packetPos+=2;
array_push($privsarray, substr($packet, $packetpos, $thisIterationLength));
$packetPos+=$thisIterationLength;
}
$privs = implode(", ", $privsarray);
print("Player [INFO]: Got privs: $privs\n");
break;
case CLIENT_INVENTORY_FORMSPEC:
$length = deserializeU32(substr($packet, 1, 4));
$invSpec = substr($packet, 5, $length);
break;
case CLIENT_DETACHED_INVENTORY:
$nameLength=deserializeU16(substr($packet, 1, 2));
$invName=substr($packet,3, $nameLength);
$invBody=substr($packet,3+$nameLength);
$detachedInvs[$invName]=deserializeInv($invBody); /* TODO: MEDUIM Deserialize Invs. Doesn't look that hard.
* void InventoryList::deSerialize(std::istream &is) in inventory.cpp
* void Inventory::deSerialize(std::istream &is) in inventory.cpp
*/
break;
case CLIENT_SHOW_FORMSPEC:
print("ServerAction [INFO]: Not showing formspec, ignored.");
break;
}
}
function deserializeNodePos($string){
/*TODO: IMPLEMENT*/
function processChatMsg($message) {
print "received chat message: ".$message . "\n";
}
//processCommandToClient($testPacket);
?>

24
src/sendComm.php Normal file
View File

@ -0,0 +1,24 @@
<?php
require_once 'servercommands.php';
function sendTOSERVER_INIT($username, $passphrase) {
$packetToSend = chr(SERVER_INIT);
$packetToSend.=chr(25);
$packetToSend.=str_pad($username, 20, chr(0), STR_PAD_RIGHT);
if (preg_match("/^[A-Za-z0-9]{27}$/", $passphrase) != 1) {
die("The passphrase must be 27 characters, which may be alphanumeric, with case sensitivity.");
}
$packetToSend.=$passphrase . chr(0) . serializeU16(13) . serializeU16(25);
sendPacket(formReliablePacket(formOriginalPacket("")));
sendPacket(formOriginalPacket($packetToSend));
}
function sendTOSERVER_PLAYERPOS() {
$packet = chr(SERVER_PLAYERPOS);
$packet.=$knownmap->player->pos->getAsV3F100();
}
?>

50
src/serialize.php Normal file
View File

@ -0,0 +1,50 @@
<?php
define("POINTEDTHING_NOTHING", 0);
define("POINTEDTHING_NODE", 1);
define("POINTEDTHING_OBJECT", 2);
function deserializeNodePos($in) {
}
function deserializeNode($in) {
global $knownNodes;
}
function deserializeU16($in) {
$retval = unpack("nout", $in);
return $retval[out];
}
function minetestWideToNarrow($in) {
$out = "";
$length = strlen($in);
for ($i = 1; $i < $length; $i+=2) {
$out = $out . $in[$i];
}
return $out;
}
function serializePointedThing($abovesurface, $undersurface, $type) {
/*
* Undersurface gets punched
* Abovesurface is target for node place
*/
$out = "";
$out = $out . chr(0);
$out.=chr($type);
if ($type == POINTEDTHING_NODE) {
$out = $out . serializeNodePos($undersurface);
$out = $out . serializeNodePos($abovesurface);
}return $out;
}
function serializeU16($in){
$retval=pack("n", $in);
//echo("Serialized $in to $retval");
return $retval;
}
?>

View File

@ -18,7 +18,7 @@
explicitly sent afterwards
*/
define("CLIENT_BLOCKDATA",0x20); //TODO: Multiple blocks
define("CLIENT_BLOCKDATA",0x20);
define("CLIENT_ADDNODE",0x21);
define("CLIENT_REMOVENODE",0x22);

View File

@ -1,5 +1,3 @@
<?php
$string="\x04\x00\xa0\x00";
$array=unpack("cchars/nint/nint2/nint3/nint4/nint5/nint6", $string);
var_dump($array);
var_dump(preg_match("/^[A-Za-z0-9]{27}$/", "aaaaaaaaaaaaa6!aaaaaaaaaaaa"));
?>