How can unrealscript halt event handler execution after an arbitrary number of lines with no return or error?
- by Dan Cowell
I have created a class that extends TcpLink and is instantiated in a custom Kismet Sequence Action. It is being instantiated correctly and is making the GET HTTP request that I need it to (I have checked my access log in apache) and Apache is responding to the request with the appropriate content.
The problem I have is that I'm using the event receive mode and it appears that somehow the handler for the Opened event is halted after a specific number of lines of code have executed.
Here is my code for the Opened event:
event Opened()
{
// A connection was established
WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] event opened");
WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] Sending simple HTTP query");
//The HTTP GET request
//char(13) and char(10) are carrage returns and new lines
requesttext = "userId="$userId$"&apartmentId="$apartmentId;
SendText("GET /"$path$"?"$requesttext$" HTTP/1.0");
SendText(chr(13)$chr(10));
SendText("Host: "$TargetHost);
SendText(chr(13)$chr(10));
SendText("Connection: Close");
SendText(chr(13)$chr(10)$chr(13)$chr(10));
//WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] Sent request: "$requesttext);
//WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] end HTTP query");
//WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] LinkState: "$LinkState);
//WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] LinkMode: "$LinkMode);
WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] ReceiveMode: "$ReceiveMode);
WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] Error: "$string(GetLastError()));
}
As you can see, a number of the Broadcast calls have been commented out. Initially, only the lines up to the Broadcast containing "[DNomad_TcpLinkClient] Sent request: " were being executed and none of the Broadcasts were commented out. After commenting out that line, the next Broadcast was successful and so on and so forth.
As a test, I commented out the very first Broadcast to see if the connection closing had any effect:
// A connection was established
//WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] event opened");
WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] Sending simple HTTP query");
Upon doing that, an additional Broadcast at the end of the function executed. Thus the inference that there is an upper limit to the number of lines executed.
Additionally, my ReceivedText handler is never called, despite Apache returning the correct HTTP 200 response with a body.
My working hypothesis is that somehow after the Sequence Action finishes executing the garbage collector cleans up the TcpLinkClient instance. My biggest source of confusion with that is how on earth it does it during the execution of an event handler.
Has anyone ever seen anything like this before? My full TcpLinkClient class is below:
/*
* TcpLinkClient based on an example usage of the TcpLink class by Michiel 'elmuerte' Hendriks for Epic Games, Inc.
*
*/
class DNomad_TcpLinkClient extends TcpLink;
var PlayerController PC;
var string TargetHost;
var int TargetPort;
var string path;
var string requesttext;
var string userId;
var string apartmentId;
var string statusCode;
var string responseData;
event PostBeginPlay()
{
super.PostBeginPlay();
}
function DoTcpLinkRequest(string uid, string id) //removes having to send a host
{
userId = uid;
apartmentId = id;
Resolve(targethost);
}
function string GetStatus() {
return statusCode;
}
event Resolved( IpAddr Addr )
{
// The hostname was resolved succefully
WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] "$TargetHost$" resolved to "$ IpAddrToString(Addr));
// Make sure the correct remote port is set, resolving doesn't set
// the port value of the IpAddr structure
Addr.Port = TargetPort;
//dont comment out this log because it rungs the function bindport
WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] Bound to port: "$ BindPort() );
if (!Open(Addr))
{
WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] Open failed");
}
}
event ResolveFailed()
{
WorldInfo.Game.Broadcast(self, "[TcpLinkClient] Unable to resolve "$TargetHost);
// You could retry resolving here if you have an alternative
// remote host.
//send failed message to scaleform UI
//JunHud(JunPlayerController(PC).myHUD).JunMovie.CallSetHTML("Failed");
}
event Opened()
{
// A connection was established
//WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] event opened");
WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] Sending simple HTTP query");
//The HTTP GET request
//char(13) and char(10) are carrage returns and new lines
requesttext = "userId="$userId$"&apartmentId="$apartmentId;
SendText("GET /"$path$"?"$requesttext$" HTTP/1.0");
SendText(chr(13)$chr(10));
SendText("Host: "$TargetHost);
SendText(chr(13)$chr(10));
SendText("Connection: Close");
SendText(chr(13)$chr(10)$chr(13)$chr(10));
//WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] Sent request: "$requesttext);
//WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] end HTTP query");
//WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] LinkState: "$LinkState);
//WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] LinkMode: "$LinkMode);
WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] ReceiveMode: "$ReceiveMode);
WorldInfo.Game.Broadcast(self, "[DNomad_TcpLinkClient] Error: "$string(GetLastError()));
}
event Closed()
{
// In this case the remote client should have automatically closed
// the connection, because we requested it in the HTTP request.
WorldInfo.Game.Broadcast(self, "Connection closed.");
// After the connection was closed we could establish a new
// connection using the same TcpLink instance.
}
event ReceivedText( string Text )
{
WorldInfo.Game.Broadcast(self, "Received Text: "$Text);
//we dont want the header info, so we split the string after two new lines
Text = Split(Text, chr(13)$chr(10)$chr(13)$chr(10), true);
WorldInfo.Game.Broadcast(self, "Split Text: "$Text);
statusCode = Text;
}
event ReceivedLine( string Line ) {
WorldInfo.Game.Broadcast(self, "Received Line: "$Line);
}
event ReceivedBinary( int Count, byte B[255] ) {
WorldInfo.Game.Broadcast(self, "Received Binary of length: "$Count);
}
defaultproperties
{
TargetHost="127.0.0.1"
TargetPort=80 //default for HTTP
LinkMode=MODE_Text
ReceiveMode=RMODE_Event
path = "dnomad/datafeed.php"
userId = "0";
apartmentId = "0";
statusCode = "";
send = false;
}