tcpObject.cpp
Engine/source/app/net/tcpObject.cpp
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)
processConnectedNotifyEvent(NetSocket sock, U32 state)
processConnectedReceiveEvent(NetSocket sock, RawData incomingData)
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