//----------------------------------------------------------------------------- // Copyright (c) 2012 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- #include "platform/platformNetAsync.h" #include "core/strings/stringFunctions.h" #include "platform/threads/threadPool.h" #include "console/console.h" #if defined(TORQUE_OS_WIN) # include #else # include # include #endif #include NetAsync gNetAsync; //-------------------------------------------------------------------------- // NetAsync::NameLookupRequest. //-------------------------------------------------------------------------- // internal structure for storing information about a name lookup request struct NetAsync::NameLookupRequest { NetSocket sock; char remoteAddr[4096]; char out_h_addr[4096]; S32 out_h_length; bool complete; NameLookupRequest() { sock = NetSocket::INVALID; remoteAddr[0] = 0; out_h_addr[0] = 0; out_h_length = -1; complete = false; } }; //-------------------------------------------------------------------------- // NetAsync::NameLookupWorkItem. //-------------------------------------------------------------------------- /// Work item issued to the thread pool for each lookup request. struct NetAsync::NameLookupWorkItem : public ThreadPool::WorkItem { typedef ThreadPool::WorkItem Parent; NameLookupWorkItem( NameLookupRequest& request, ThreadPool::Context* context = 0 ) : Parent( context ), mRequest( request ) { } protected: virtual void execute() { NetAddress address; Net::Error error = Net::stringToAddress(mRequest.remoteAddr, &address, true); // do it if (error != Net::NoError) { // oh well! leave the lookup data unmodified (h_length) should // still be -1 from initialization mRequest.complete = true; } else { // copy the stuff we need from the hostent dMemset(mRequest.out_h_addr, 0, sizeof(mRequest.out_h_addr)); dMemcpy(mRequest.out_h_addr, &address, sizeof(address)); mRequest.out_h_length = sizeof(address); mRequest.complete = true; } } private: NameLookupRequest& mRequest; }; //-------------------------------------------------------------------------- // NetAsync. //-------------------------------------------------------------------------- NetAsync::NetAsync() { VECTOR_SET_ASSOCIATION( mLookupRequests ); } void NetAsync::queueLookup(const char* remoteAddr, NetSocket socket) { // do we have it already? U32 i = 0; for (i = 0; i < mLookupRequests.size(); ++i) { if (mLookupRequests[i].sock == socket) // found it. ignore more than one lookup at a time for a socket. return; } // not found, so add it mLookupRequests.increment(); NameLookupRequest& lookupRequest = mLookupRequests.last(); lookupRequest.sock = socket; dStrncpy(lookupRequest.remoteAddr, remoteAddr, sizeof(lookupRequest.remoteAddr)); ThreadSafeRef< NameLookupWorkItem > workItem( new NameLookupWorkItem( lookupRequest ) ); ThreadPool::GLOBAL().queueWorkItem( workItem ); } bool NetAsync::checkLookup(NetSocket socket, void* out_h_addr, S32* out_h_length, S32 out_h_addr_size) { bool found = false; // search for the socket RequestIterator iter; for (iter = mLookupRequests.begin(); iter != mLookupRequests.end(); ++iter) // if we found it and it is complete... if (socket == iter->sock && iter->complete) { // copy the lookup data to the callers parameters dMemcpy(out_h_addr, iter->out_h_addr, out_h_addr_size); *out_h_length = iter->out_h_length; found = true; break; } // we found the socket, so we are done with it. erase. if (found) mLookupRequests.erase(iter); return found; }