tcpObject.cpp

Engine/source/app/net/tcpObject.cpp

More...

Public Variables

Public Functions

ConsoleDocClass(TCPObject , "@brief Allows communications between the game and <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> server using TCP/IP <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">protocols.\n\n</a>" "To use <a href="/coding/class/classtcpobject/">TCPObject</a> you set up <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> server, send data <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the server, and handle " "each line of the server 's response using <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> callback. Once you are done communicating with " "the server, you <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">disconnect.\n\n</a>" "<a href="/coding/class/classtcpobject/">TCPObject</a> is intended <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be used with text based protocols which means you 'll need <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " "delineate the server 's response with an end-of-line character. i.e. the newline " "character @\\n. You may optionally include the carriage return character @\\r prior <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the newline " "and <a href="/coding/class/classtcpobject/">TCPObject</a> will strip it out before sending the line <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the callback. If <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> newline " "character is not included in the server 's output, the received data will not be " "processed until you disconnect from the server(which flushes the internal buffer).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "<a href="/coding/class/classtcpobject/">TCPObject</a> may also be set up <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> listen <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> specific port, making Torque into <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> TCP server. " "When used in this manner, <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> callback is received when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> client connection is made. Following " "the outside connection, text may be sent and lines are processed in the usual <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">manner.\n\n</a>" "If you want <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> work with HTTP you may wish <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use <a href="/coding/class/classhttpobject/">HTTPObject</a> instead as it handles all of the " "HTTP header setup and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">parsing.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "//In this example we 'll retrieve the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> forum threads <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">RSS\n</a>" "//feed from garagegames.com. As we 're using TCPObject, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">the\n</a>" "//raw text response will be received from the server, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">including\n</a>" "//the HTTP <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">header.\n\n</a>" "//Define callbacks <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> our specific <a href="/coding/class/classtcpobject/">TCPObject</a> using our instance '<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">s\n</a>" "//name(RSSFeed) as the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">namespace.\n\n</a>" "//Handle an issue with resolving the server 's <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">name\n</a>" "function RSSFeed::onDNSFailed(%this)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Store this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">state\n</a>" " %this.lastState=\"DNSFailed\";\n\n" "   // Handle DNS <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">failure\n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "function RSSFeed::onConnectFailed(%this)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Store this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">state\n</a>" "   %this.lastState = \"ConnectFailed\";\n\n" "   // Handle connection <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">failure\n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "function RSSFeed::onDNSResolved(%this)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Store this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">state\n</a>" "   %this.lastState = \"DNSResolved\";\n\n" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "function RSSFeed::onConnected(%this)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Store this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">state\n</a>" "   %this.lastState = \"Connected\";\n\n" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "function RSSFeed::onDisconnect(%this)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Store this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">state\n</a>" "   %this.lastState = \"Disconnected\";\n\n" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "// Handle <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> line from the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server\n</a>" "function RSSFeed::onLine(%this, %line)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Print the line <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">console\n</a>" "   <a href="/coding/file/ggendoflinefix_8txt/#ggendoflinefix_8txt_1a7f8fee038817022b75b8865e5da4eba3">echo</a>( %line );\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "// Create the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">TCPObject\n</a>" "% rss)
DefineEngineMethod(TCPObject , connect , void , (const char *address) , "@brief Connect <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">address.\n\n</a>" "@param address Server address (including port) <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> connect <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to.\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// Set the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">address.\n</a>" "% address)
DefineEngineMethod(TCPObject , disconnect , void , () , "@brief Disconnect from whatever this <a href="/coding/class/classtcpobject/">TCPObject</a> is currently connected to, <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">anything.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "//Inform this <a href="/coding/class/classtcpobject/">TCPObject</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> disconnect from anything it is currently connected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to.\n</a>" "%thisTCPObj.disconnect();\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n</a>" )
DefineEngineMethod(TCPObject , finishLastLine , void , () , "@brief Eat the rest of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">lines.\n</a>" )
DefineEngineMethod(TCPObject , listen , void , (U32 port) , "@brief Start listening on the specified port <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">connections.\n\n</a>" "This method starts <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> listener which looks <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> incoming TCP connections <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> port. " "You must overload the onConnectionRequest callback <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> create <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classtcpobject/">TCPObject</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " " read, write , or reject the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">connection.\n\n</a>" " @param port Port <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> this <a href="/coding/class/classtcpobject/">TCPObject</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> start listening <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> connections <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">on.\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "//Create <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> listener on port 8080.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classtcpobject/">TCPObject</a>(TCPListener);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "TCPListener.listen(8080);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "function TCPListener::onConnectionRequest(%this, %address, %<a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a>)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Create <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> manage the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">connection.\n</a>" " <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classtcpobject/">TCPObject</a>(TCPClient, %<a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a>);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "function TCPClient::onLine(%this, %line)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Print the line of text from <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n</a>" " <a href="/coding/file/ggendoflinefix_8txt/#ggendoflinefix_8txt_1a7f8fee038817022b75b8865e5da4eba3">echo</a>(%line);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n</a>" )
DefineEngineMethod(TCPObject , send , void , (const char *data) , "@brief Transmits the data string <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the connected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">computer.\n\n</a>" "This method is used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> send text data <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the connected computer regardless <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> we initiated the " "connection using  connect, or listening <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> port using listen().\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @param data The data string <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">send.\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "//Set the command <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">data\n</a>" "% data)
DefineEngineMethod(TCPObject , sendFile , bool , (const char *fileName) , "@brief Transmits the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> in binary <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the connected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">computer.\n\n</a>" "@param fileName The filename of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">transfer.\n</a>" )
IMPLEMENT_CALLBACK(TCPObject , onConnected , void , () , () , "Called whenever <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> connection is established with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n</a>" )
IMPLEMENT_CALLBACK(TCPObject , onConnectFailed , void , () , () , "Called whenever <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> connection has failed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be established with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n</a>" )
IMPLEMENT_CALLBACK(TCPObject , onConnectionRequest , void , (const char *address, const char *ID) , (address, ID) , "@brief Called whenever <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> connection request is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">made.\n\n</a>" "This callback is used when the <a href="/coding/class/classtcpobject/">TCPObject</a> is listening <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> port and <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> client is attempting <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">connect.\n</a>" "@param address Server address connecting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">from.\n</a>" "@param ID Connection <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ID\n</a>" "@see listen()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" )
IMPLEMENT_CALLBACK(TCPObject , onDisconnect , void , () , () , "Called whenever the <a href="/coding/class/classtcpobject/">TCPObject</a> disconnects from whatever it is currently connected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to.\n</a>" )
IMPLEMENT_CALLBACK(TCPObject , onDNSFailed , void , () , () , "Called whenever the DNS has failed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">resolve.\n</a>" )
IMPLEMENT_CALLBACK(TCPObject , onDNSResolved , void , () , () , "Called whenever the DNS has been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">resolved.\n</a>" )
IMPLEMENT_CALLBACK(TCPObject , onEndReceive , void , () , () , "@brief Called when we are done reading all <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">lines.\n\n</a>" )
IMPLEMENT_CALLBACK(TCPObject , onLine , void , (const char *line) , (line) , "@brief Called whenever <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> line of data is sent <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">TCPObject.\n\n</a>" "This callback is called when the received data contains <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> newline @\\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a> character, or " "the connection has been disconnected and the <a href="/coding/class/classtcpobject/">TCPObject</a> 's buffer is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">flushed.\n</a>" " @param line Data sent from the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n</a>" )
IMPLEMENT_CALLBACK(TCPObject , onPacket , bool , (const char *data) , (data) , "@brief Called when we get <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> packet with no newlines or nulls (probably websocket).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "@param data Data sent from the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n</a>" "@return true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> script handled the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">packet.\n</a>" )
processConnectedAcceptEvent(NetSocket listeningPort, NetSocket newConnection, NetAddress originatingAddress)

Detailed Description

Public Variables

S32 gTCPCount 

Public Functions

ConsoleDocClass(TCPObject , "@brief Allows communications between the game and <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> server using TCP/IP <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">protocols.\n\n</a>" "To use <a href="/coding/class/classtcpobject/">TCPObject</a> you set up <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> connection <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> server, send data <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the server, and handle " "each line of the server 's response using <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> callback. Once you are done communicating with " "the server, you <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">disconnect.\n\n</a>" "<a href="/coding/class/classtcpobject/">TCPObject</a> is intended <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be used with text based protocols which means you 'll need <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " "delineate the server 's response with an end-of-line character. i.e. the newline " "character @\\n. You may optionally include the carriage return character @\\r prior <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the newline " "and <a href="/coding/class/classtcpobject/">TCPObject</a> will strip it out before sending the line <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the callback. If <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> newline " "character is not included in the server 's output, the received data will not be " "processed until you disconnect from the server(which flushes the internal buffer).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "<a href="/coding/class/classtcpobject/">TCPObject</a> may also be set up <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> listen <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> specific port, making Torque into <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> TCP server. " "When used in this manner, <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> callback is received when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> client connection is made. Following " "the outside connection, text may be sent and lines are processed in the usual <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">manner.\n\n</a>" "If you want <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> work with HTTP you may wish <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use <a href="/coding/class/classhttpobject/">HTTPObject</a> instead as it handles all of the " "HTTP header setup and <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">parsing.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "//In this example we 'll retrieve the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> forum threads <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">RSS\n</a>" "//feed from garagegames.com. As we 're using TCPObject, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">the\n</a>" "//raw text response will be received from the server, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">including\n</a>" "//the HTTP <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">header.\n\n</a>" "//Define callbacks <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> our specific <a href="/coding/class/classtcpobject/">TCPObject</a> using our instance '<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">s\n</a>" "//name(RSSFeed) as the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">namespace.\n\n</a>" "//Handle an issue with resolving the server 's <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">name\n</a>" "function RSSFeed::onDNSFailed(%this)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Store this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">state\n</a>" " %this.lastState=\"DNSFailed\";\n\n" "   // Handle DNS <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">failure\n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "function RSSFeed::onConnectFailed(%this)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Store this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">state\n</a>" "   %this.lastState = \"ConnectFailed\";\n\n" "   // Handle connection <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">failure\n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "function RSSFeed::onDNSResolved(%this)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Store this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">state\n</a>" "   %this.lastState = \"DNSResolved\";\n\n" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "function RSSFeed::onConnected(%this)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Store this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">state\n</a>" "   %this.lastState = \"Connected\";\n\n" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "function RSSFeed::onDisconnect(%this)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Store this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">state\n</a>" "   %this.lastState = \"Disconnected\";\n\n" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "// Handle <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> line from the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server\n</a>" "function RSSFeed::onLine(%this, %line)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   // Print the line <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">console\n</a>" "   <a href="/coding/file/ggendoflinefix_8txt/#ggendoflinefix_8txt_1a7f8fee038817022b75b8865e5da4eba3">echo</a>( %line );\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "// Create the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">TCPObject\n</a>" "% rss)

DefineEngineMethod(TCPObject , connect , void , (const char *address) , "@brief Connect <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">address.\n\n</a>" "@param address Server address (including port) <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> connect <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to.\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// Set the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">address.\n</a>" "% address)

DefineEngineMethod(TCPObject , disconnect , void , () , "@brief Disconnect from whatever this <a href="/coding/class/classtcpobject/">TCPObject</a> is currently connected to, <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">anything.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "//Inform this <a href="/coding/class/classtcpobject/">TCPObject</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> disconnect from anything it is currently connected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to.\n</a>" "%thisTCPObj.disconnect();\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n</a>" )

DefineEngineMethod(TCPObject , finishLastLine , void , () , "@brief Eat the rest of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">lines.\n</a>" )

DefineEngineMethod(TCPObject , listen , void , (U32 port) , "@brief Start listening on the specified port <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">connections.\n\n</a>" "This method starts <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> listener which looks <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> incoming TCP connections <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> port. " "You must overload the onConnectionRequest callback <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> create <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classtcpobject/">TCPObject</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " " read, write , or reject the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">connection.\n\n</a>" " @param port Port <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> this <a href="/coding/class/classtcpobject/">TCPObject</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> start listening <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> connections <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">on.\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "//Create <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> listener on port 8080.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classtcpobject/">TCPObject</a>(TCPListener);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "TCPListener.listen(8080);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "function TCPListener::onConnectionRequest(%this, %address, %<a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a>)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Create <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> manage the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">connection.\n</a>" " <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classtcpobject/">TCPObject</a>(TCPClient, %<a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a>);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "function TCPClient::onLine(%this, %line)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//Print the line of text from <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">client.\n</a>" " <a href="/coding/file/ggendoflinefix_8txt/#ggendoflinefix_8txt_1a7f8fee038817022b75b8865e5da4eba3">echo</a>(%line);\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n</a>" )

DefineEngineMethod(TCPObject , send , void , (const char *data) , "@brief Transmits the data string <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the connected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">computer.\n\n</a>" "This method is used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> send text data <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the connected computer regardless <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> we initiated the " "connection using  connect, or listening <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> port using listen().\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @param data The data string <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">send.\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "//Set the command <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">data\n</a>" "% data)

DefineEngineMethod(TCPObject , sendFile , bool , (const char *fileName) , "@brief Transmits the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> in binary <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the connected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">computer.\n\n</a>" "@param fileName The filename of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">transfer.\n</a>" )

IMPLEMENT_CALLBACK(TCPObject , onConnected , void , () , () , "Called whenever <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> connection is established with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n</a>" )

IMPLEMENT_CALLBACK(TCPObject , onConnectFailed , void , () , () , "Called whenever <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> connection has failed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be established with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n</a>" )

IMPLEMENT_CALLBACK(TCPObject , onConnectionRequest , void , (const char *address, const char *ID) , (address, ID) , "@brief Called whenever <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> connection request is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">made.\n\n</a>" "This callback is used when the <a href="/coding/class/classtcpobject/">TCPObject</a> is listening <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> port and <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> client is attempting <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">connect.\n</a>" "@param address Server address connecting <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">from.\n</a>" "@param ID Connection <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ID\n</a>" "@see listen()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" )

IMPLEMENT_CALLBACK(TCPObject , onDisconnect , void , () , () , "Called whenever the <a href="/coding/class/classtcpobject/">TCPObject</a> disconnects from whatever it is currently connected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to.\n</a>" )

IMPLEMENT_CALLBACK(TCPObject , onDNSFailed , void , () , () , "Called whenever the DNS has failed <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">resolve.\n</a>" )

IMPLEMENT_CALLBACK(TCPObject , onDNSResolved , void , () , () , "Called whenever the DNS has been <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">resolved.\n</a>" )

IMPLEMENT_CALLBACK(TCPObject , onEndReceive , void , () , () , "@brief Called when we are done reading all <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">lines.\n\n</a>" )

IMPLEMENT_CALLBACK(TCPObject , onLine , void , (const char *line) , (line) , "@brief Called whenever <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> line of data is sent <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">TCPObject.\n\n</a>" "This callback is called when the received data contains <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> newline @\\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a> character, or " "the connection has been disconnected and the <a href="/coding/class/classtcpobject/">TCPObject</a> 's buffer is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">flushed.\n</a>" " @param line Data sent from the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n</a>" )

IMPLEMENT_CALLBACK(TCPObject , onPacket , bool , (const char *data) , (data) , "@brief Called when we get <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> packet with no newlines or nulls (probably websocket).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "@param data Data sent from the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">server.\n</a>" "@return true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> script handled the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">packet.\n</a>" )

IMPLEMENT_CONOBJECT(TCPObject )

processConnectedAcceptEvent(NetSocket listeningPort, NetSocket newConnection, NetAddress originatingAddress)

processConnectedNotifyEvent(NetSocket sock, U32 state)

processConnectedReceiveEvent(NetSocket sock, RawData incomingData)

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "app/net/tcpObject.h"
 25
 26#include "platform/platform.h"
 27#include "console/simBase.h"
 28#include "console/consoleInternal.h"
 29#include "core/strings/stringUnit.h"
 30#include "console/engineAPI.h"
 31#include "core/stream/fileStream.h"
 32
 33TCPObject *TCPObject::table[TCPObject::TableSize] = {0, };
 34
 35IMPLEMENT_CONOBJECT(TCPObject);
 36
 37ConsoleDocClass( TCPObject,
 38   "@brief Allows communications between the game and a server using TCP/IP protocols.\n\n"
 39
 40   "To use TCPObject you set up a connection to a server, send data to the server, and handle "
 41   "each line of the server's response using a callback.  Once you are done communicating with "
 42   "the server, you disconnect.\n\n"
 43
 44   "TCPObject is intended to be used with text based protocols which means you'll need to "
 45   "delineate the server's response with an end-of-line character. i.e. the newline "
 46   "character @\\n.  You may optionally include the carriage return character @\\r prior to the newline "
 47   "and TCPObject will strip it out before sending the line to the callback.  If a newline "
 48   "character is not included in the server's output, the received data will not be "
 49   "processed until you disconnect from the server (which flushes the internal buffer).\n\n"
 50
 51   "TCPObject may also be set up to listen to a specific port, making Torque into a TCP server.  "
 52   "When used in this manner, a callback is received when a client connection is made.  Following "
 53   "the outside connection, text may be sent and lines are processed in the usual manner.\n\n"
 54
 55   "If you want to work with HTTP you may wish to use HTTPObject instead as it handles all of the "
 56   "HTTP header setup and parsing.\n\n"
 57   
 58   "@tsexample\n"
 59      "// In this example we'll retrieve the new forum threads RSS\n"
 60      "// feed from garagegames.com.  As we're using TCPObject, the\n"
 61      "// raw text response will be received from the server, including\n"
 62      "// the HTTP header.\n\n"
 63
 64      "// Define callbacks for our specific TCPObject using our instance's\n"
 65      "// name (RSSFeed) as the namespace.\n\n"
 66
 67      "// Handle an issue with resolving the server's name\n"
 68      "function RSSFeed::onDNSFailed(%this)\n"
 69      "{\n"
 70      "   // Store this state\n"
 71      "   %this.lastState = \"DNSFailed\";\n\n"
 72
 73      "   // Handle DNS failure\n"
 74      "}\n\n"
 75
 76      "function RSSFeed::onConnectFailed(%this)\n"
 77      "{\n"
 78      "   // Store this state\n"
 79      "   %this.lastState = \"ConnectFailed\";\n\n"
 80      "   // Handle connection failure\n"
 81      "}\n\n"
 82
 83      "function RSSFeed::onDNSResolved(%this)\n"
 84      "{\n"
 85      "   // Store this state\n"
 86      "   %this.lastState = \"DNSResolved\";\n\n"
 87      "}\n\n"
 88
 89      "function RSSFeed::onConnected(%this)\n"
 90      "{\n"
 91      "   // Store this state\n"
 92      "   %this.lastState = \"Connected\";\n\n"
 93      "}\n\n"
 94
 95      "function RSSFeed::onDisconnect(%this)\n"
 96      "{\n"
 97      "   // Store this state\n"
 98      "   %this.lastState = \"Disconnected\";\n\n"
 99      "}\n\n"
100
101      "// Handle a line from the server\n"
102      "function RSSFeed::onLine(%this, %line)\n"
103      "{\n"
104      "   // Print the line to the console\n"
105      "   echo( %line );\n"
106      "}\n\n"
107
108      "// Create the TCPObject\n"
109      "%rss = new TCPObject(RSSFeed);\n\n"
110
111      "// Define a dynamic field to store the last connection state\n"
112      "%rss.lastState = \"None\";\n\n"
113
114      "// Connect to the server\n"
115      "%rss.connect(\"www.garagegames.com:80\");\n\n"
116
117      "// Send the RSS feed request to the server.  Response will be\n"
118      "// handled in onLine() callback above\n"
119      "%rss.send(\"GET /feeds/rss/threads HTTP/1.1\\r\\nHost: www.garagegames.com\\r\\n\\r\\n\");\n"
120   "@endtsexample\n\n" 
121   
122   "@see HTTPObject\n"
123
124   "@ingroup Networking\n"
125);
126
127
128IMPLEMENT_CALLBACK(TCPObject, onConnectionRequest, void, (const char* address, const char* ID), (address, ID),
129   "@brief Called whenever a connection request is made.\n\n"
130   "This callback is used when the TCPObject is listening to a port and a client is attempting to connect.\n"
131   "@param address Server address connecting from.\n"
132   "@param ID Connection ID\n"
133   "@see listen()\n"
134   );
135
136IMPLEMENT_CALLBACK(TCPObject, onLine, void, (const char* line), (line),
137   "@brief Called whenever a line of data is sent to this TCPObject.\n\n"
138   "This callback is called when the received data contains a newline @\\n character, or "
139   "the connection has been disconnected and the TCPObject's buffer is flushed.\n"
140   "@param line Data sent from the server.\n"
141   );
142
143IMPLEMENT_CALLBACK(TCPObject, onPacket, bool, (const char* data), (data),
144   "@brief Called when we get a packet with no newlines or nulls (probably websocket).\n\n"
145   "@param data Data sent from the server.\n"
146   "@return true if script handled the packet.\n"
147   );
148IMPLEMENT_CALLBACK(TCPObject, onEndReceive, void, (), (),
149   "@brief Called when we are done reading all lines.\n\n"
150   );
151
152IMPLEMENT_CALLBACK(TCPObject, onDNSResolved, void, (),(),
153   "Called whenever the DNS has been resolved.\n"
154   );
155
156IMPLEMENT_CALLBACK(TCPObject, onDNSFailed, void, (),(),
157   "Called whenever the DNS has failed to resolve.\n"
158   );
159
160IMPLEMENT_CALLBACK(TCPObject, onConnected, void, (),(),
161   "Called whenever a connection is established with a server.\n"
162   );
163
164IMPLEMENT_CALLBACK(TCPObject, onConnectFailed, void, (),(),
165   "Called whenever a connection has failed to be established with a server.\n"
166   );
167
168IMPLEMENT_CALLBACK(TCPObject, onDisconnect, void, (),(),
169   "Called whenever the TCPObject disconnects from whatever it is currently connected to.\n"
170   );
171
172TCPObject *TCPObject::find(NetSocket tag)
173{
174   for(TCPObject *walk = table[tag.getHash() & TableMask]; walk; walk = walk->mNext)
175      if(walk->mTag.getHash() == tag.getHash())
176         return walk;
177   return NULL;
178}
179
180void TCPObject::addToTable(NetSocket newTag)
181{
182   removeFromTable();
183   mTag = newTag;
184   mNext = table[mTag.getHash() & TableMask];
185   table[mTag.getHash() & TableMask] = this;
186}
187
188void TCPObject::removeFromTable()
189{
190   for(TCPObject **walk = &table[mTag.getHash() & TableMask]; *walk; walk = &((*walk)->mNext))
191   {
192      if(*walk == this)
193      {
194         *walk = mNext;
195         return;
196      }
197   }
198}
199
200void processConnectedReceiveEvent(NetSocket sock, RawData incomingData);
201void processConnectedAcceptEvent(NetSocket listeningPort, NetSocket newConnection, NetAddress originatingAddress);
202void processConnectedNotifyEvent( NetSocket sock, U32 state );
203
204S32 gTCPCount = 0;
205
206TCPObject::TCPObject()
207{
208   mBuffer = NULL;
209   mBufferSize = 0;
210   mPort = 0;
211   mTag = NetSocket::INVALID;
212   mNext = NULL;
213   mState = Disconnected;
214
215   gTCPCount++;
216
217   if(gTCPCount == 1)
218   {
219      Net::getConnectionAcceptedEvent().notify(processConnectedAcceptEvent);
220      Net::getConnectionReceiveEvent().notify(processConnectedReceiveEvent);
221      Net::getConnectionNotifyEvent().notify(processConnectedNotifyEvent);
222   }
223}
224
225TCPObject::~TCPObject()
226{
227   disconnect();
228   dFree(mBuffer);
229
230   gTCPCount--;
231
232   if(gTCPCount == 0)
233   {
234      Net::getConnectionAcceptedEvent().remove(processConnectedAcceptEvent);
235      Net::getConnectionReceiveEvent().remove(processConnectedReceiveEvent);
236      Net::getConnectionNotifyEvent().remove(processConnectedNotifyEvent);
237   }
238}
239
240bool TCPObject::processArguments(S32 argc, ConsoleValueRef *argv)
241{
242   if(argc == 0)
243      return true;
244   else if(argc == 1)
245   {
246      addToTable(NetSocket::fromHandle(dAtoi(argv[0])));
247      return true;
248   }
249   return false;
250}
251
252bool TCPObject::onAdd()
253{
254   if(!Parent::onAdd())
255      return false;
256
257   const char *name = getName();
258
259   if(name && name[0] && getClassRep())
260   {
261      Namespace *parent = getClassRep()->getNameSpace();
262      Con::linkNamespaces(parent->mName, name);
263      mNameSpace = Con::lookupNamespace(name);
264
265   }
266
267   Sim::getTCPGroup()->addObject(this);
268
269   return true;
270}
271
272U32 TCPObject::onReceive(U8 *buffer, U32 bufferLen)
273{
274   // we got a raw buffer event
275   // default action is to split the buffer into lines of text
276   // and call processLine on each
277   // for any incomplete lines we have mBuffer
278   U32 start = 0;
279   parseLine(buffer, &start, bufferLen);
280   return start;
281}
282
283void TCPObject::parseLine(U8 *buffer, U32 *start, U32 bufferLen)
284{
285   // find the first \n in buffer
286   U32 i;
287   U8 *line = buffer + *start;
288
289   for(i = *start; i < bufferLen; i++)
290      if(buffer[i] == '\n' || buffer[i] == 0)
291         break;
292   U32 len = i - *start;
293
294   if(i == bufferLen || mBuffer)
295   {
296      // we've hit the end with no newline
297      mBuffer = (U8 *) dRealloc(mBuffer, mBufferSize + len + 1);
298      dMemcpy(mBuffer + mBufferSize, line, len);
299      mBufferSize += len;
300      *start = i;
301
302      // process the line
303      if(i != bufferLen)
304      {
305         mBuffer[mBufferSize] = 0;
306         if(mBufferSize && mBuffer[mBufferSize-1] == '\r')
307            mBuffer[mBufferSize - 1] = 0;
308         U8 *temp = mBuffer;
309         mBuffer = 0;
310         mBufferSize = 0;
311
312         processLine((UTF8*)temp);
313         dFree(temp);
314      }
315   }
316   else if(i != bufferLen)
317   {
318      line[len] = 0;
319      if(len && line[len-1] == '\r')
320         line[len-1] = 0;
321      processLine((UTF8*)line);
322   }
323   if(i != bufferLen)
324      *start = i + 1;
325}
326
327void TCPObject::onConnectionRequest(const NetAddress *addr, U32 connectId)
328{
329   char idBuf[16];
330   char addrBuf[256];
331   Net::addressToString(addr, addrBuf);
332   dSprintf(idBuf, sizeof(idBuf), "%d", connectId);
333   onConnectionRequest_callback(addrBuf,idBuf);
334}
335
336bool TCPObject::processLine(UTF8 *line)
337{
338   onLine_callback(line);
339   return true;
340}
341
342
343
344void TCPObject::onDNSResolved()
345{
346   mState = DNSResolved;
347   onDNSResolved_callback();
348}
349
350void TCPObject::onDNSFailed()
351{
352   mState = Disconnected;
353   onDNSFailed_callback();
354}
355
356
357void TCPObject::onConnected()
358{
359   mState = Connected;
360   onConnected_callback();
361}
362
363void TCPObject::onConnectFailed()
364{
365   mState = Disconnected;
366   onConnectFailed_callback();
367}
368
369bool TCPObject::finishLastLine()
370{
371   if(mBufferSize)
372   {
373      mBuffer[mBufferSize] = 0;
374      processLine((UTF8*)mBuffer);
375      dFree(mBuffer);
376      mBuffer = 0;
377      mBufferSize = 0;
378
379      return true;
380   }
381
382   return false;
383}
384
385bool TCPObject::isBufferEmpty()
386{
387   return (mBufferSize <= 0);
388}
389
390void TCPObject::emptyBuffer()
391{
392   if(mBufferSize)
393   {
394      dFree(mBuffer);
395      mBuffer = 0;
396      mBufferSize = 0;
397   }
398}
399
400void TCPObject::onDisconnect()
401{
402   finishLastLine();
403   mState = Disconnected;
404   onDisconnect_callback();
405}
406
407void TCPObject::listen(U16 port)
408{
409   mState = Listening;
410   NetSocket newTag = Net::openListenPort(port);
411   addToTable(newTag);
412}
413
414void TCPObject::connect(const char *address)
415{
416   NetSocket newTag = Net::openConnectTo(address);
417   addToTable(newTag);
418}
419
420void TCPObject::disconnect()
421{
422   if( mTag != NetSocket::INVALID ) {
423      Net::closeConnectTo(mTag);
424   }
425   removeFromTable();
426}
427
428void TCPObject::send(const U8 *buffer, U32 len)
429{
430   Net::sendtoSocket(mTag, buffer, S32(len));
431}
432
433bool TCPObject::sendFile(const char* fileName)
434{
435   //Open the file for reading
436   FileStream readFile;
437   if(!readFile.open(fileName, Torque::FS::File::Read))
438   {
439      return false;
440   }
441
442   //Read each byte into our buffer
443   Vector<U8> buffer(readFile.getStreamSize());
444   readFile.read(buffer.size(), &buffer);
445
446   //Send the buffer
447   send(buffer.address(), buffer.size());
448
449      return true;
450}
451
452DefineEngineMethod(TCPObject, send, void, (const char *data),, 
453   "@brief Transmits the data string to the connected computer.\n\n"
454
455   "This method is used to send text data to the connected computer regardless if we initiated the "
456   "connection using connect(), or listening to a port using listen().\n"
457
458   "@param data The data string to send.\n"
459
460   "@tsexample\n"
461      "// Set the command data\n"
462      "%data = \"GET \" @ $RSSFeed::serverURL @ \" HTTP/1.0\\r\\n\";\n"
463      "%data = %data @ \"Host: \" @ $RSSFeed::serverName @ \"\\r\\n\";\n"
464      "%data = %data @ \"User-Agent: \" @ $RSSFeed::userAgent @ \"\\r\\n\\r\\n\"\n\n"
465
466      "// Send the command to the connected server.\n"
467      "%thisTCPObj.send(%data);\n"
468   "@endtsexample\n")
469{
470   object->send( (const U8*)data, dStrlen(data) );
471}
472
473DefineEngineMethod(TCPObject, sendFile, bool, (const char *fileName),, 
474   "@brief Transmits the file in binary to the connected computer.\n\n"
475
476   "@param fileName The filename of the file to transfer.\n")
477{
478   return object->sendFile(fileName);
479}
480
481DefineEngineMethod(TCPObject, finishLastLine, void, (),, 
482   "@brief Eat the rest of the lines.\n")
483{
484   object->finishLastLine();
485}
486
487DefineEngineMethod(TCPObject, listen, void, (U32 port),, 
488   "@brief Start listening on the specified port for connections.\n\n"
489
490   "This method starts a listener which looks for incoming TCP connections to a port.  "
491   "You must overload the onConnectionRequest callback to create a new TCPObject to "
492   "read, write, or reject the new connection.\n\n"
493
494   "@param port Port for this TCPObject to start listening for connections on.\n"
495
496   "@tsexample\n"
497
498    "// Create a listener on port 8080.\n"
499    "new TCPObject( TCPListener );\n"
500    "TCPListener.listen( 8080 );\n\n"
501
502    "function TCPListener::onConnectionRequest( %this, %address, %id )\n"
503    "{\n"
504    "   // Create a new object to manage the connection.\n"
505    "   new TCPObject( TCPClient, %id );\n"
506    "}\n\n"
507
508    "function TCPClient::onLine( %this, %line )\n"
509    "{\n"
510    "   // Print the line of text from client.\n"
511    "   echo( %line );\n"
512    "}\n"
513
514   "@endtsexample\n")
515{
516   object->listen(U32(port));
517}
518
519DefineEngineMethod(TCPObject, connect, void, (const char* address),, 
520   "@brief Connect to the given address.\n\n"
521
522   "@param address Server address (including port) to connect to.\n"
523
524   "@tsexample\n"
525      "// Set the address.\n"
526      "%address = \"www.garagegames.com:80\";\n\n"
527
528      "// Inform this TCPObject to connect to the specified address.\n"
529      "%thisTCPObj.connect(%address);\n"
530   "@endtsexample\n")
531{
532   object->connect(address);
533}
534
535DefineEngineMethod(TCPObject, disconnect, void, (),, 
536   "@brief Disconnect from whatever this TCPObject is currently connected to, if anything.\n\n"
537
538   "@tsexample\n"
539      "// Inform this TCPObject to disconnect from anything it is currently connected to.\n"
540      "%thisTCPObj.disconnect();\n"
541   "@endtsexample\n")
542{
543   object->disconnect();
544}
545
546void processConnectedReceiveEvent(NetSocket sock, RawData incomingData)
547{
548   TCPObject *tcpo = TCPObject::find(sock);
549   if(!tcpo)
550   {
551      Con::printf("Got bad connected receive event.");
552      return;
553   }
554
555   U32 size = incomingData.size;
556   U8 *buffer = (U8*)incomingData.data;
557
558   while(size)
559   {
560      U32 ret = tcpo->onReceive(buffer, size);
561      AssertFatal(ret <= size, "Invalid return size");
562      size -= ret;
563      buffer += ret;
564   }
565
566   //If our buffer now has something in it then it's probably a web socket packet and lets handle it
567   if(!tcpo->isBufferEmpty())
568   {
569      //Copy all the data into a string (may be a quicker way of doing this)
570      U8 *data = (U8*)incomingData.data;
571      String temp;
572      for(S32 i = 0; i < incomingData.size; i++)
573      {
574         temp += data[i];
575      }
576
577      //Send the packet to script
578      bool handled = tcpo->onPacket_callback(temp);
579
580      //If the script did something with it, clear the buffer
581      if(handled)
582      {
583         tcpo->emptyBuffer();
584      }
585   }
586
587   tcpo->onEndReceive_callback();
588}
589
590void processConnectedAcceptEvent(NetSocket listeningPort, NetSocket newConnection, NetAddress originatingAddress)
591{
592   TCPObject *tcpo = TCPObject::find(listeningPort);
593   if(!tcpo)
594      return;
595
596   tcpo->onConnectionRequest(&originatingAddress, (U32)newConnection.getHandle());
597}
598
599void processConnectedNotifyEvent( NetSocket sock, U32 state )
600{
601   TCPObject *tcpo = TCPObject::find(sock);
602   if(!tcpo)
603      return;
604
605   switch(state)
606   {
607      case Net::DNSResolved:
608         tcpo->onDNSResolved();
609         break;
610      case Net::DNSFailed:
611         tcpo->onDNSFailed();
612         break;
613      case Net::Connected:
614         tcpo->onConnected();
615         break;
616      case Net::ConnectFailed:
617         tcpo->onConnectFailed();
618         break;
619      case Net::Disconnected:
620         tcpo->onDisconnect();
621         break;
622   }
623}
624