Torque3D Documentation / _generateds / netDownload.cpp

netDownload.cpp

Engine/source/sim/netDownload.cpp

More...

Classes:

Public Functions

ConsoleDocClass(FileChunkEvent , "@brief Used by <a href="/coding/class/classnetconnection/">NetConnection</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> sending/receiving chunks of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">data.\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> editors or internal use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a> " " @internal" )
ConsoleDocClass(FileDownloadRequestEvent , "@brief Used by <a href="/coding/class/classnetconnection/">NetConnection</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> transmitting requests <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> obtain files from server during <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">loading.\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> editors or internal use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a> " " @internal" )

Detailed Description

Public Functions

ConsoleDocClass(FileChunkEvent , "@brief Used by <a href="/coding/class/classnetconnection/">NetConnection</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> sending/receiving chunks of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">data.\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> editors or internal use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a> " " @internal" )

ConsoleDocClass(FileDownloadRequestEvent , "@brief Used by <a href="/coding/class/classnetconnection/">NetConnection</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> transmitting requests <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> obtain files from server during <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">loading.\n\n</a>" "Not intended <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> game development, <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> editors or internal use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only.\n\n</a> " " @internal" )

IMPLEMENT_CO_NETEVENT_V1(FileChunkEvent )

IMPLEMENT_CO_NETEVENT_V1(FileDownloadRequestEvent )

  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/platform.h"
 25#include "core/dnet.h"
 26#include "console/simBase.h"
 27#include "console/engineAPI.h"
 28#include "sim/netConnection.h"
 29#include "core/stream/bitStream.h"
 30#include "core/stream/fileStream.h"
 31#include "sim/netObject.h"
 32
 33class FileDownloadRequestEvent : public NetEvent
 34{
 35public:
 36   typedef NetEvent Parent;
 37   enum 
 38   {
 39      MaxFileNames = 31,
 40   };
 41   
 42   U32 nameCount;
 43   char mFileNames[MaxFileNames][256];
 44
 45   FileDownloadRequestEvent(Vector<char*> *nameList = NULL)
 46   {
 47      nameCount = 0;
 48      if(nameList)
 49      {
 50         nameCount = nameList->size();
 51
 52         if(nameCount > MaxFileNames)
 53            nameCount = MaxFileNames;
 54
 55         for(U32 i = 0; i < nameCount; i++)
 56         {
 57            dStrcpy(mFileNames[i], (*nameList)[i], 256);
 58            //Con::printf("Sending request for file %s", mFileNames[i]);
 59         }
 60      }
 61   }
 62
 63   virtual void pack(NetConnection *, BitStream *bstream)
 64   {
 65      bstream->writeRangedU32(nameCount, 0, MaxFileNames);
 66      for(U32 i = 0; i < nameCount; i++)
 67         bstream->writeString(mFileNames[i]);
 68   }
 69
 70   virtual void write(NetConnection *, BitStream *bstream)
 71   {
 72      bstream->writeRangedU32(nameCount, 0, MaxFileNames);
 73      for(U32 i = 0; i < nameCount; i++)
 74         bstream->writeString(mFileNames[i]);
 75   }
 76
 77   virtual void unpack(NetConnection *, BitStream *bstream)
 78   {
 79      nameCount = bstream->readRangedU32(0, MaxFileNames);
 80      for(U32 i = 0; i < nameCount; i++)
 81         bstream->readString(mFileNames[i]);
 82   }
 83
 84   virtual void process(NetConnection *connection)
 85   {
 86      U32 i;
 87      for(i = 0; i < nameCount; i++)
 88         if(connection->startSendingFile(mFileNames[i]))
 89            break;
 90      if(i == nameCount)
 91         connection->startSendingFile(NULL);  // none of the files were sent
 92   }
 93
 94   DECLARE_CONOBJECT(FileDownloadRequestEvent);
 95
 96};
 97
 98IMPLEMENT_CO_NETEVENT_V1(FileDownloadRequestEvent);
 99
100ConsoleDocClass( FileDownloadRequestEvent,
101            "@brief Used by NetConnection for transmitting requests to obtain files from server during loading.\n\n"
102            "Not intended for game development, for editors or internal use only.\n\n "
103            "@internal");
104
105class FileChunkEvent : public NetEvent
106{
107public:
108   typedef NetEvent Parent;
109   enum
110   {
111      ChunkSize = 63,
112   };
113
114   U8 chunkData[ChunkSize];
115   U32 chunkLen;
116   
117   FileChunkEvent(U8 *data = NULL, U32 len = 0)
118   {
119      if(data)
120         dMemcpy(chunkData, data, len);
121      chunkLen = len;
122   }
123   
124   virtual void pack(NetConnection *, BitStream *bstream)
125   {
126      bstream->writeRangedU32(chunkLen, 0, ChunkSize);
127      bstream->write(chunkLen, chunkData);
128   }
129   
130   virtual void write(NetConnection *, BitStream *bstream)
131   {
132      bstream->writeRangedU32(chunkLen, 0, ChunkSize);
133      bstream->write(chunkLen, chunkData);
134   }
135   
136   virtual void unpack(NetConnection *, BitStream *bstream)
137   {
138      chunkLen = bstream->readRangedU32(0, ChunkSize);
139      bstream->read(chunkLen, chunkData);
140   }
141   
142   virtual void process(NetConnection *connection)
143   {
144      connection->chunkReceived(chunkData, chunkLen);
145   }
146   
147   virtual void notifyDelivered(NetConnection *nc, bool madeIt)
148   {
149      if(!nc->isRemoved())
150        nc->sendFileChunk();
151   }
152   
153   DECLARE_CONOBJECT(FileChunkEvent);
154};
155
156IMPLEMENT_CO_NETEVENT_V1(FileChunkEvent);
157
158ConsoleDocClass( FileChunkEvent,
159            "@brief Used by NetConnection for sending/receiving chunks of data.\n\n"
160            "Not intended for game development, for editors or internal use only.\n\n "
161            "@internal");
162
163void NetConnection::sendFileChunk()
164{
165   U8 buffer[FileChunkEvent::ChunkSize];
166   U32 len = FileChunkEvent::ChunkSize;
167   if(len + mCurrentFileBufferOffset > mCurrentFileBufferSize)
168      len = mCurrentFileBufferSize - mCurrentFileBufferOffset;
169
170   if(!len)
171   {
172      delete mCurrentDownloadingFile;
173      mCurrentDownloadingFile = NULL;
174      return;
175   }
176
177   mCurrentFileBufferOffset += len;
178   mCurrentDownloadingFile->read(len, buffer);
179   postNetEvent(new FileChunkEvent(buffer, len));
180}
181
182bool NetConnection::startSendingFile(const char *fileName)
183{
184   if(!fileName || Con::getBoolVariable("$NetConnection::neverUploadFiles"))
185   {
186      sendConnectionMessage(SendNextDownloadRequest);
187      return false;
188   }
189
190   mCurrentDownloadingFile = FileStream::createAndOpen( fileName, Torque::FS::File::Read );
191   if(!mCurrentDownloadingFile)
192   {
193      // the server didn't have the file, so send a 0 byte chunk:
194      Con::printf("No such file '%s'.", fileName);
195      postNetEvent(new FileChunkEvent(NULL, 0));
196      return false;
197   }
198
199   Con::printf("Sending file '%s'.", fileName);
200   mCurrentFileBufferSize = mCurrentDownloadingFile->getStreamSize();
201   mCurrentFileBufferOffset = 0;
202
203   // always have 32 file chunks (64 bytes each) in transit
204   sendConnectionMessage(FileDownloadSizeMessage, mCurrentFileBufferSize);
205   for(U32 i = 0; i < 32; i++)
206      sendFileChunk();
207   return true;
208}
209
210void NetConnection::sendNextFileDownloadRequest()
211{
212   // see if we've already downloaded this file...
213   while(mMissingFileList.size() && (Torque::FS::IsFile(mMissingFileList[0]) || Con::getBoolVariable("$NetConnection::neverDownloadFiles")))
214   {
215      dFree(mMissingFileList[0]);
216      mMissingFileList.pop_front();
217   }
218
219   if(mMissingFileList.size())
220   {
221      postNetEvent(new FileDownloadRequestEvent(&mMissingFileList));
222   }
223   else
224   {
225      fileDownloadSegmentComplete();
226   }
227}
228
229
230void NetConnection::chunkReceived(U8 *chunkData, U32 chunkLen)
231{
232   if(chunkLen == 0)
233   {
234      // the server didn't have the file... apparently it's one we don't need...
235      dFree(mCurrentFileBuffer);
236      mCurrentFileBuffer = NULL;
237      dFree(mMissingFileList[0]);
238      mMissingFileList.pop_front();
239      return;
240   }
241   if(chunkLen + mCurrentFileBufferOffset > mCurrentFileBufferSize)
242   {
243      setLastError("Invalid file chunk from server.");
244      return;
245   }
246   dMemcpy(((U8 *) mCurrentFileBuffer) + mCurrentFileBufferOffset, chunkData, chunkLen);
247   mCurrentFileBufferOffset += chunkLen;
248   if(mCurrentFileBufferOffset == mCurrentFileBufferSize)
249   {
250      // this file's done...
251      // save it to disk:
252      FileStream *stream;
253
254      Con::printf("Saving file %s.", mMissingFileList[0]);
255      if((stream = FileStream::createAndOpen( mMissingFileList[0], Torque::FS::File::Write )) == NULL)
256      {
257         setLastError("Couldn't open file downloaded by server.");
258         return;
259      }
260
261      dFree(mMissingFileList[0]);
262      mMissingFileList.pop_front();
263      stream->write(mCurrentFileBufferSize, mCurrentFileBuffer);
264      delete stream;
265      mNumDownloadedFiles++;
266      dFree(mCurrentFileBuffer);
267      mCurrentFileBuffer = NULL;
268      sendNextFileDownloadRequest();
269   }
270   else
271   {
272      Con::executef("onFileChunkReceived", mMissingFileList[0], Con::getIntArg(mCurrentFileBufferOffset), Con::getIntArg(mCurrentFileBufferSize));
273   }
274}
275
276