platformNetAsync.cpp
Engine/source/platform/platformNetAsync.cpp
Classes:
class
Work item issued to the thread pool for each lookup request.
Detailed Description
Public Variables
NetAsync gNetAsync
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 "platform/platformNetAsync.h" 25#include "core/strings/stringFunctions.h" 26#include "platform/threads/threadPool.h" 27#include "console/console.h" 28 29#if defined(TORQUE_OS_WIN) 30# include <winsock.h> 31#elif defined(TORQUE_OS_XENON) 32# include <Xtl.h> 33#else 34# include <netdb.h> 35# include <unistd.h> 36#endif 37 38#include <errno.h> 39 40NetAsync gNetAsync; 41 42//-------------------------------------------------------------------------- 43// NetAsync::NameLookupRequest. 44//-------------------------------------------------------------------------- 45 46// internal structure for storing information about a name lookup request 47struct NetAsync::NameLookupRequest 48{ 49 NetSocket sock; 50 char remoteAddr[4096]; 51 char out_h_addr[4096]; 52 S32 out_h_length; 53 bool complete; 54 55 NameLookupRequest() 56 { 57 sock = NetSocket::INVALID; 58 remoteAddr[0] = 0; 59 out_h_addr[0] = 0; 60 out_h_length = -1; 61 complete = false; 62 } 63}; 64 65//-------------------------------------------------------------------------- 66// NetAsync::NameLookupWorkItem. 67//-------------------------------------------------------------------------- 68 69/// Work item issued to the thread pool for each lookup request. 70 71struct NetAsync::NameLookupWorkItem : public ThreadPool::WorkItem 72{ 73 typedef ThreadPool::WorkItem Parent; 74 75 NameLookupWorkItem( NameLookupRequest& request, ThreadPool::Context* context = 0 ) 76 : Parent( context ), 77 mRequest( request ) 78 { 79 } 80 81protected: 82 virtual void execute() 83 { 84#ifndef TORQUE_OS_XENON 85 86 NetAddress address; 87 Net::Error error = Net::stringToAddress(mRequest.remoteAddr, &address, true); 88 89 // do it 90 if (error != Net::NoError) 91 { 92 // oh well! leave the lookup data unmodified (h_length) should 93 // still be -1 from initialization 94 mRequest.complete = true; 95 } 96 else 97 { 98 // copy the stuff we need from the hostent 99 dMemset(mRequest.out_h_addr, 0, 100 sizeof(mRequest.out_h_addr)); 101 dMemcpy(mRequest.out_h_addr, &address, sizeof(address)); 102 103 mRequest.out_h_length = sizeof(address); 104 mRequest.complete = true; 105 } 106#else 107 XNDNS *pxndns = NULL; 108 HANDLE hEvent = CreateEvent(NULL, false, false, NULL); 109 XNetDnsLookup(mRequest.remoteAddr, hEvent, &pxndns); 110 111 while(pxndns->iStatus == WSAEINPROGRESS) 112 WaitForSingleObject(hEvent, INFINITE); 113 114 if(pxndns->iStatus == 0 && pxndns->cina > 0) 115 { 116 dMemset(mRequest.out_h_addr, 0, sizeof(mRequest.out_h_addr)); 117 118 // This is a suspect section. I need to revisit. [2/22/2010 Pat] 119 dMemcpy(mRequest.out_h_addr, pxndns->aina, sizeof(IN_ADDR)); 120 mRequest.out_h_length = sizeof(IN_ADDR); 121 } 122 123 mRequest.complete = true; 124 125 XNetDnsRelease(pxndns); 126 CloseHandle(hEvent); 127#endif 128 } 129 130private: 131 NameLookupRequest& mRequest; 132}; 133 134//-------------------------------------------------------------------------- 135// NetAsync. 136//-------------------------------------------------------------------------- 137 138NetAsync::NetAsync() 139{ 140 VECTOR_SET_ASSOCIATION( mLookupRequests ); 141} 142 143void NetAsync::queueLookup(const char* remoteAddr, NetSocket socket) 144{ 145 // do we have it already? 146 147 U32 i = 0; 148 for (i = 0; i < mLookupRequests.size(); ++i) 149 { 150 if (mLookupRequests[i].sock == socket) 151 // found it. ignore more than one lookup at a time for a socket. 152 return; 153 } 154 155 // not found, so add it 156 157 mLookupRequests.increment(); 158 NameLookupRequest& lookupRequest = mLookupRequests.last(); 159 lookupRequest.sock = socket; 160 dStrncpy(lookupRequest.remoteAddr, remoteAddr, sizeof(lookupRequest.remoteAddr)); 161 162 ThreadSafeRef< NameLookupWorkItem> workItem( new NameLookupWorkItem( lookupRequest ) ); 163 ThreadPool::GLOBAL().queueWorkItem( workItem ); 164} 165 166bool NetAsync::checkLookup(NetSocket socket, void* out_h_addr, 167 S32* out_h_length, S32 out_h_addr_size) 168{ 169 bool found = false; 170 171 // search for the socket 172 RequestIterator iter; 173 for (iter = mLookupRequests.begin(); 174 iter != mLookupRequests.end(); 175 ++iter) 176 // if we found it and it is complete... 177 if (socket == iter->sock && iter->complete) 178 { 179 // copy the lookup data to the callers parameters 180 dMemcpy(out_h_addr, iter->out_h_addr, out_h_addr_size); 181 *out_h_length = iter->out_h_length; 182 found = true; 183 break; 184 } 185 186 // we found the socket, so we are done with it. erase. 187 if (found) 188 mLookupRequests.erase(iter); 189 190 return found; 191} 192
