Torque3D Documentation / _generateds / platformNetAsync.cpp

platformNetAsync.cpp

Engine/source/platform/platformNetAsync.cpp

More...

Classes:

class

Work item issued to the thread pool for each lookup request.

Public Variables

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