Game Development Community

Possible bug in TCPObject--discussion

by Stephen Zepp · in Torque Game Engine · 10/02/2005 (7:42 am) · 6 replies

I'm not 100% sure this is a bug, so I want to give the background before i jump right in with the code I'm questioning...

I was working on a project that requires using a TCP/IP socket between a java server and a torque server this past week, and part of my development phases was to have a Torque to Torque socket on a single computer between two instantiations of Torque (debug mode) for testing purposes.

I re-implemented TCPObject (call it XXXObject, I can't talk about what the project itself is unfortunately) to give it non-socket related functionality, and modify the onLine() member method extensively. I fully admit I was sloppy in the reimplementation, but as far as I can tell what I reimplemented had nothing to do with the issue I was seeing.

I would start up one Torque server in listen mode on port 29000, and see the port showing as LISTENING via netstat. I would then start up the second Torque server in connect mode, and see the socket ESTABLISHED...everything is dandy so far. The problem came when I tried to send data across the socket--on the receiving side I was getting the following error:

"Got bad connected receive event."

Which when traced in the source points to DemoGame::onConnectedReceiveEvent(), indicating that it cannot find the TCPObject within the object table that is associated with the socket the data came across.

By adding some debugging code I was able to prove to myself that the socket that the OS handed the listen server during the socket handshake (event->tag) was in fact different from the socket that the data was coming across (event->connectionTag), and I confirmed with a general TCP/IP networking expert that this was correct: winSock assigns a final socket to the application once the handshake is complete that is different from what socket the handshake was performed with...but TCPObject never does anything with this.

In general, the TCPObject that was setting up the handshake on the server in listen mode was never able to use the socket once it was set up, either to receive or send data. I was able to fix this by adding the following:

In void DemoGame::processConnectedAcceptEvent( ConnectedAcceptEvent* event ), after:

tcpo->onConnectionRequest(&event->address, event->connectionTag);

I added:

tcpo->addToTable(event->connectionTag);

And this fixed my problem completely.

Now, the reason why I call this a possible bug: Obviously, TCPObject has been used by quite a few people for a variety of reasons, and the script hook is there to allow you to do a similar resolution in script...but I haven't seen an example of completing the connection on this side of the equation in script, and wasn't quite sure how to finish it off...and in my case wanted to do it in code anyway.

So if any of the experts with TCPObject have come across this and would be willing to discuss how they resolved the issue, and if they think it's a bug at all, I'd love to hear your thoughts!

Tom B, I know you've messed with it a bunch, as well as LabRat...any comments?

#1
10/02/2005 (9:11 pm)
I've been thinking about this from a more generic perspective, and after realizing that many users of TCPObject would want the ability to keep a "listener" up and running but not connected so it can continue to marshall new connections, I took a different look at the code.

Sure enough, it is a trivial task to have this happen in script. The function onConnectionRequest() simply hands off the event to the script:

Con::executef(this, 3, "onConnectRequest", addrBuf, idBuf);

This allows you to (in your script TCPObject::onConnectRequest() ) spawn a new TCPObject, give it the name (in the arguments section) of idBuf, and it will automatically be linked to that already established socket. It would look like:

%connectedListener = new TCPObject(%NewObjectName, %idBuf);

TCPObject::processArguments() will take the %idBuf and add this new TCPObject directly to the table using that %idBuf as it's link. Since %idBuf is the event->connectionTag from my post above, next data to come across that socket is linked to your %connectedListener TCPObject.

So long story short, it isn't a bug, just isn't documented well to know how to use it via script. I'll leave this post here in case anyone in the future comes up with a similar question.
#2
10/02/2005 (10:03 pm)
(Remember, first arg is name, so for stuff to get to process args...)

Anyway, sounds like a good solution/analysis. Good to have this discussion out where people can find it!
#3
10/02/2005 (10:08 pm)
Good point..edited!
#4
04/26/2006 (9:20 am)
@ Stephen

Can you direct me to some detailed information on how the TCP/HTTP objects work?
I'm trying to understand how to use them.

I am also confused about what the "CharLogin" block is supposed to do. Since I can't find any forum data on this.
#5
05/03/2006 (8:54 am)
Ive done this!!! =D -- Before I saw teh post....

I have MMOTCPObject: which is a stripped TCPObject for BINARY data...

I.E. WriteU32, WriteU16... Etc...

But I did something like:

%dave = new mmoTCPObject();
%dave.someFunction(%id);

It works, mmm?

(The best part is that I made it for T2D and it works w/o editing! =.o )

You do:

function TCPObject:onConnectionRequest(%addr, %id)

and the code is in there?
#6
07/27/2007 (6:26 am)
I set up a winsock to talk to this tcpobject:listen() and there is a huge lag here huge meaning couple seconds from time of transmit to time of receive. Any way to make this a bit faster?