Game Development Community

dev|Pro Game Development Curriculum

TCP Query List

by Robert Fritzen · 12/10/2011 (9:43 pm) · 0 comments

For those who have been following my XXZ change list, this is one of those new key features that I have added, and I thought that it may be extremely useful to everyone, so.. Here we go.

Really easy to do here, create a new file, put it in the core/ folder, and exec it in core/main.cs, and add the following contents to it.

$Authentication::GenericServerPort = 80;

//Assemble a scriptContainer to hold the current connectivity details and queue list
$Authentication::ConnectionContainer = new ScriptObject(ConnectionContainer) {
   class = "TCPConnectionList";
   connectionStatus = 0;            //Current status indicated by object
   currentConnection = "";          //Current web address connected to
   currentSeparator = "";           //Used for FORM POST data separation
   currentTask = "";                //Current function being used by the container
   dropConnection = 1;              //Auto Drop after task completion
   dropTimer = 7500;                //time in MS until autoDrop is performed
   
   finishFunction = "";
   requestData = "";
   
   //create the inner TCP object for controlling the connections
   TCPConnection = new TCPObject(PGDConnection) {};
   TCPQueue[0] = "";
};
echo("* TCP Connection Container Activated.");

//control functions for the connection list
function TCPConnectionList::establishConnection(%this) {
   %this.currentTask = %this@".establishConnection();";
   if(%this.TCPQueue[0] $= "") {
      error("Task breakoff, queue slot 0 is empty but attempt to a connection?");
      return;
   }
   
   %request = %this.call(getField(%this.TCPQueue[0], 2), getField(%this.TCPQueue[0], 3));
   %this.requestData = %request;
   
   if(%this.requestData $= "NIL_REQUEST") {
      //task has been invalidated for some reason, push next one on the queue
      %this.performNextTask();
      return;
   }

   %this.TCPConnection.connect(getField(%this.TCPQueue[0], 0) @ ":" @ $Authentication::GenericServerPort);
   if(%this.dropConnection) {
      %this.autoDrop = %this.TCPConnection.schedule(%this.dropTimer, "disconnect");
   }
}

//generic TCPQueue data. TCPConnectionList.TCPQueue[0] = "www.phantomdev.net TAB /auth/TEDC/ TAB generateServerTest();";
function TCPConnectionList::addTaskToList(%this, %host, %location, %task, %args) {
   %this.currentTask = %this@".addTaskToList("@%host@", "@%location@", "@%task@", "@%args@");";
   echo("Adding TCP: "@%host@":"@%location@" === "@%task@" ("@%args@")");
   
   if(%this.TCPQueue[0] $= "") {
      //front of the list.
      %this.TCPQueue[0] = %host TAB %location TAB %task TAB %args;
      %this.establishConnection(); //connect now.
   }
   else {
      %check = 1;
      while(%this.TCPQueue[%check] !$= "") {
         %check++;
      }
      %this.TCPQueue[%check] = %host TAB %location TAB %task TAB %args;
   }
}

function TCPConnectionList::performNextTask(%this) {
   cancel(%this.autoDrop);
   %this.currentTask = %this@".performNextTask();";

   if(%this.TCPQueue[1] !$= "") {
      //there is another task in the list, update the list
      %this.TCPQueue[0] = ""; //this task is complete
      %check = 1;
      while(%this.TCPQueue[%check] !$= "") {
         %this.TCPQueue[%check-1] = %this.TCPQueue[%check];
         %this.TCPQueue[%check] = "";
         %check++;
      }
      echo("Performing next task");
      %this.establishConnection();
   }
   else {
     echo("No next task, completing");
     %this.TCPQueue[0] = "";
   }
}

function TCPConnectionList::getRandomSeperator(%this, %length) {
   %this.currentTask = %this@".getRandomSeperator("@%length@");";

   %alphanumeric = "abcdefghijklmnopqrstuvwxyz0123456789";
   for(%i = 0; %i < %length; %i++) {
      %index = getRandom(strLen(%alphanumeric));
      %letter = getSubStr(%alphanumeric, %index, 1);
      %UpperC = getRandom(0, 1);
      if(%UpperC) {
         %letter = strUpr(%letter);
      }
      else {
         %letter = strLwr(%letter);
      }
      %seq = %seq @ %letter;
   }

   %this.currentSeparator = %seq;
}

function TCPConnectionList::makeDisposition(%this, %_name, %_content, %_isEnd) {
   %this.currentTask = %this@".makeDisposition("@%_name@", "@%_content@", "@%_isEnd@");";

   if(%_isEnd) {
      %dispo = "--" @ %this.currentSeparator @ "\r\nContent-Disposition: form-data; name=""@%_name@""\r\n\r\n"@%_content@"\r\n--" @ %this.currentSeparator @ "--";
   }
   else {
      %dispo = "--" @ %this.currentSeparator @ "\r\nContent-Disposition: form-data; name=""@%_name@""\r\n\r\n"@%_content@"\r\n";
   }
   return %dispo;
}

function TCPConnectionList::assembleHTTP1_1Header(%this, %_command, %_userAgent, %_extra) {
   %this.currentTask = %this@".assembleHTTP1_1Header("@%_command@", "@%_userAgent@", "@%_extra@");";
   %header = %_command SPC getField(%this.TCPQueue[0], 1) SPC "HTTP/1.1\r\n" @
                    "Host: "@getField(%this.TCPQueue[0], 0)@"\r\n" @
                    "User-Agent: "@%_userAgent@"rnConnection: close\r\n" @
                    %_extra;
   return %header;
}

function TCPConnectionList::dropConnection(%this) {
   %this.currentTask = %this@".dropConnection();";
   %this.TCPConnection.disconnect();
}

//functions for the TCP object alone
function PGDConnection::onConnected(%this) {
   //--$PGDConnection::Connected = true;
   if($DebugMode) {
      echo("DEBUG: "@$Authentication::ConnectionContainer.requestData);
   }
   if(%this.callOnConnect !$= "") {
      eval(%this.callOnConnect);
   }
   $Authentication::ConnectionContainer.connectionStatus = 0;
   %this.doingSomething = true;
   %this.send($Authentication::ConnectionContainer.requestData);
   %this.response = "";
   %this.allData = "";
}

function PGDConnection::onConnectFailed( %this ) {
   //--$PGDConnection::Connected = false;
   $Authentication::ConnectionContainer.connectionStatus = 1;
   %this.response = "CERROR_CONNECTFAILED";
   if(%this.callOnDisconnect !$= "") {
      eval(%this.callOnDisconnect);
   }
   //
   %this.callOnConnect = "";
   %this.callOnDisconnect = "";
   //
   CloseMessagePopup();
   MessageBoxOK("Connection Error", "Unable to connect to a server nPlease try again later.");
   //move up the task list
   $Authentication::ConnectionContainer.currentConnection = "";
   $Authentication::ConnectionContainer.currentTask = "";
   $Authentication::ConnectionContainer.performNextTask();
}

function PGDConnection::onDNSFailed( %this ) {
   //--$PGDConnection::Connected = false;
   $Authentication::ConnectionContainer.connectionStatus = 2;
   %this.response = "CERROR_DNSFAIL";
   if(%this.callOnDisconnect !$= "") {
      eval(%this.callOnDisconnect);
   }
   //
   %this.callOnConnect = "";
   %this.callOnDisconnect = "";
   //
   CloseMessagePopup();
   MessageBoxOK("DNS Error", "Your DNS server was unable to resolve a host name nPlease try again later.");
   //move up the task list
   $Authentication::ConnectionContainer.currentConnection = "";
   $Authentication::ConnectionContainer.currentTask = "";
   $Authentication::ConnectionContainer.performNextTask();
}

function PGDConnection::onLine(%this, %line) {
   //all of PGD's responses start with the $ line
   if($debugMode) {
      echo(%line);
   }
   if(strstr(%line, "$") != -1) {
      //strip PGD
      %line = strReplace(%line, "$", "");
      %line = strReplace(%line, "PGD", "");
      if(%this.doSingleLineEval) {
         %this.call($Authentication::ConnectionContainer.finishFunction, %line);
      }
      else {
         %this.response = %this.response NL %line;
      }
   }

   %this.allData = %this.allData NL %line;
}

function PGDConnection::onDisconnect(%this) {
   if(strstr(%this.response, "CERROR") != -1) {
      CloseMessagePopup();
      messageBoxOk("Connection Error", "Your client failed to connect. n Error Code:"@%this.response@"");
      //$Authentication::ConnectionContainer.attemptTaskRetry();  establishConnection(); //will add this later...
      return;
   }
   if(%this.callOnDisconnect !$= "") {
      eval(%this.callOnDisconnect);
   }
   
   $Authentication::ConnectionContainer.connectionStatus = 0;
   $Authentication::ConnectionContainer.currentConnection = "";
   $Authentication::ConnectionContainer.currentTask = "";
   %this.call($Authentication::ConnectionContainer.finishFunction, %this.response);
   //
   %this.callOnConnect = "";
   %this.callOnDisconnect = "";
   //
   $Authentication::ConnectionContainer.performNextTask();
}

Basically what this tool does is allows you to establish a list of TCP tasks you want to do, and then have then return data with a very useful process.

So, how to use it, well, let's look at a simple example, like pulling some raw TCP data right off of this page.

function getGGPage() {
   if($WeGotGGPage) {
      return "yes";
   }         

   $Authentication::ConnectionContainer.addTaskToList("www.garagegames.com",
                                                   "/community/resources/view/21401",
                                                   "generateRCFResourceChallenge", 2719);
}

function TCPConnectionList::generateRCFResourceChallenge(%this, %numbeh) {
   echo(%numbeh); //prints 2719
   if($WeGotGGPage) {
      return "NIL_REQUEST"; //NIL_REQUEST removes the task from the query
   }
   //%this.getRandomSeperator(16); //when using POST
   %header = %this.assembleHTTP1_1Header("GET", "My Godly Game Client");

   %this.finishFunction = "depleteData";
   return %header;
}

function PGDConnection::depleteData(%this, %response) {
   echo(%this.allData);
}

If you need a POST example, I can provide one later. Other than that, enjoy. I find great use out of this tool for my own projects, so I'm sure someone will as well.