1 #include "AutopatcherClient.h"
2 #include "DirectoryDeltaTransfer.h"
3 #include "FileList.h"
4 #include "StringCompressor.h"
5 #include "RakPeerInterface.h"
6 #include "FileListTransfer.h"
7 #include "FileListTransferCBInterface.h"
8 #include "BitStream.h"
9 #include "MessageIdentifiers.h"
10 #include "AutopatcherPatchContext.h"
11 #include "ApplyPatch.h"
12 #include "FileOperations.h"
13 //#include "SHA1.h"
14 #include <stdio.h>
15 #include "FileOperations.h"
16 #include "RakAssert.h"
17 #include "ThreadPool.h"
18
19 #ifdef _MSC_VER
20 #pragma warning( push )
21 #endif
22
23 #include "SuperFastHash.h"
24 static const unsigned HASH_LENGTH=sizeof(unsigned int);
25
26 #define COPY_ON_RESTART_EXTENSION ".patched.tmp"
27
28 struct AutopatcherClientThreadInfo
29 {
30 FileListTransferCBInterface::OnFileStruct onFileStruct;
31 char applicationDirectory[512];
32 PatchContext result;
33 unsigned prePatchLength, postPatchLength;
34 char *prePatchFile, *postPatchFile;
35 };
36 // -----------------------------------------------------------------
AutopatcherClientWorkerThread(AutopatcherClientThreadInfo * input,bool * returnOutput,void * perThreadData)37 AutopatcherClientThreadInfo* AutopatcherClientWorkerThread(AutopatcherClientThreadInfo* input, bool *returnOutput, void* perThreadData)
38 {
39 char fullPathToDir[1024];
40 *returnOutput=true;
41
42 strcpy(fullPathToDir, input->applicationDirectory);
43 strcat(fullPathToDir, input->onFileStruct.fileName);
44 if (input->onFileStruct.context.op==PC_WRITE_FILE)
45 {
46 if (WriteFileWithDirectories(fullPathToDir, (char*)input->onFileStruct.fileData, input->onFileStruct.byteLengthOfThisFile)==false)
47 {
48 char newDir[1024];
49 strcpy(newDir, fullPathToDir);
50 strcat(newDir, COPY_ON_RESTART_EXTENSION);
51 if (WriteFileWithDirectories(newDir, (char*)input->onFileStruct.fileData, input->onFileStruct.byteLengthOfThisFile))
52 {
53 input->result=PC_NOTICE_WILL_COPY_ON_RESTART;
54 }
55 else
56 {
57 input->result=PC_ERROR_FILE_WRITE_FAILURE;
58 }
59 }
60 else
61 {
62 input->result=(PatchContext) input->onFileStruct.context.op;
63 }
64 }
65 else
66 {
67 RakAssert(input->onFileStruct.context.op==PC_HASH_WITH_PATCH);
68
69 // CSHA1 sha1;
70 FILE *fp;
71
72 fp=fopen(fullPathToDir, "rb");
73 if (fp==0)
74 {
75 input->result=PC_ERROR_PATCH_TARGET_MISSING;
76 return input;
77 }
78 fseek(fp, 0, SEEK_END);
79 input->prePatchLength = ftell(fp);
80 fseek(fp, 0, SEEK_SET);
81 input->postPatchFile=0;
82 input->prePatchFile= (char*) rakMalloc_Ex(input->prePatchLength, __FILE__, __LINE__);
83 fread(input->prePatchFile, input->prePatchLength, 1, fp);
84 fclose(fp);
85
86 // printf("apply patch %i bytes\n", byteLengthOfThisFile-SHA1_LENGTH);
87 // for (int i=0; i < byteLengthOfThisFile-SHA1_LENGTH; i++)
88 // printf("%i ", fileData[SHA1_LENGTH+i]);
89 // printf("\n");
90 if (ApplyPatch((char*)input->prePatchFile, input->prePatchLength, &input->postPatchFile, &input->postPatchLength, (char*)input->onFileStruct.fileData+HASH_LENGTH, input->onFileStruct.byteLengthOfThisFile-HASH_LENGTH)==false)
91 {
92
93 input->result=PC_ERROR_PATCH_APPLICATION_FAILURE;
94 return input;
95 }
96
97 // sha1.Reset();
98 // sha1.Update((unsigned char*) input->postPatchFile, input->postPatchLength);
99 // sha1.Final();
100
101 unsigned int hash = SuperFastHash(input->postPatchFile, input->postPatchLength);
102 if (RakNet::BitStream::DoEndianSwap())
103 RakNet::BitStream::ReverseBytesInPlace((unsigned char*) &hash, sizeof(hash));
104
105 //if (memcmp(sha1.GetHash(), input->onFileStruct.fileData, HASH_LENGTH)!=0)
106 if (memcmp(&hash, input->onFileStruct.fileData, HASH_LENGTH)!=0)
107 {
108 input->result=PC_ERROR_PATCH_RESULT_CHECKSUM_FAILURE;
109 }
110
111 // Write postPatchFile over the existing file
112 if (WriteFileWithDirectories(fullPathToDir, (char*)input->postPatchFile, input->postPatchLength)==false)
113 {
114 char newDir[1024];
115 strcpy(newDir, fullPathToDir);
116 strcat(newDir, COPY_ON_RESTART_EXTENSION);
117 if (WriteFileWithDirectories(newDir, (char*)input->postPatchFile, input->postPatchLength))
118 {
119 input->result=PC_NOTICE_WILL_COPY_ON_RESTART;
120 }
121 else
122 {
123 input->result=PC_ERROR_FILE_WRITE_FAILURE;
124 }
125 }
126 else
127 {
128 input->result=(PatchContext)input->onFileStruct.context.op;
129 }
130 }
131
132 return input;
133 }
134 // -----------------------------------------------------------------
135 class AutopatcherClientCallback : public FileListTransferCBInterface
136 {
137 public:
138 ThreadPool<AutopatcherClientThreadInfo*,AutopatcherClientThreadInfo*> threadPool;
139 char applicationDirectory[512];
140 FileListTransferCBInterface *onFileCallback;
141 AutopatcherClient *client;
142 bool downloadComplete;
143 bool canDeleteUser;
144
AutopatcherClientCallback(void)145 AutopatcherClientCallback(void)
146 {
147 threadPool.StartThreads(1,0);
148 canDeleteUser=false;
149 downloadComplete=false;
150 }
~AutopatcherClientCallback(void)151 virtual ~AutopatcherClientCallback(void)
152 {
153 StopThreads();
154 }
StopThreads(void)155 void StopThreads(void)
156 {
157 threadPool.StopThreads();
158 RakAssert(threadPool.NumThreadsWorking()==0);
159
160 unsigned i;
161 AutopatcherClientThreadInfo* info;
162 for (i=0; i < threadPool.InputSize(); i++)
163 {
164 info = threadPool.GetInputAtIndex(i);
165 if (info->prePatchFile)
166 rakFree_Ex(info->prePatchFile, __FILE__, __LINE__ );
167 if (info->postPatchFile)
168 rakFree_Ex(info->postPatchFile, __FILE__, __LINE__ );
169 if (info->onFileStruct.fileData)
170 rakFree_Ex(info->onFileStruct.fileData, __FILE__, __LINE__ );
171 RakNet::OP_DELETE(info, __FILE__, __LINE__);
172 }
173 threadPool.ClearInput();
174 for (i=0; i < threadPool.OutputSize(); i++)
175 {
176 info = threadPool.GetOutputAtIndex(i);
177 if (info->prePatchFile)
178 rakFree_Ex(info->prePatchFile, __FILE__, __LINE__ );
179 if (info->postPatchFile)
180 rakFree_Ex(info->postPatchFile, __FILE__, __LINE__ );
181 if (info->onFileStruct.fileData)
182 rakFree_Ex(info->onFileStruct.fileData, __FILE__, __LINE__ );
183 RakNet::OP_DELETE(info, __FILE__, __LINE__);
184 }
185 threadPool.ClearOutput();
186 }
Update(void)187 virtual bool Update(void)
188 {
189 if (threadPool.HasOutputFast() && threadPool.HasOutput())
190 {
191 AutopatcherClientThreadInfo *threadInfo = threadPool.GetOutput();
192 threadInfo->onFileStruct.context.op=threadInfo->result;
193 switch (threadInfo->result)
194 {
195 case PC_NOTICE_WILL_COPY_ON_RESTART:
196 {
197 client->CopyAndRestart(threadInfo->onFileStruct.fileName);
198 if (threadInfo->onFileStruct.context.op==PC_WRITE_FILE)
199 {
200 // Regular file in use but we can write the temporary file. Restart and copy it over the existing
201 onFileCallback->OnFile(&threadInfo->onFileStruct);
202 }
203 else
204 {
205 // Regular file in use but we can write the temporary file. Restart and copy it over the existing
206 rakFree_Ex(threadInfo->onFileStruct.fileData, __FILE__, __LINE__ );
207 threadInfo->onFileStruct.fileData=threadInfo->postPatchFile;
208 onFileCallback->OnFile(&threadInfo->onFileStruct);
209 threadInfo->onFileStruct.fileData=0;
210 }
211 }
212 break;
213 case PC_ERROR_FILE_WRITE_FAILURE:
214 {
215 if (threadInfo->onFileStruct.context.op==PC_WRITE_FILE)
216 {
217 onFileCallback->OnFile(&threadInfo->onFileStruct);
218 }
219 else
220 {
221 rakFree_Ex(threadInfo->onFileStruct.fileData, __FILE__, __LINE__ );
222 threadInfo->onFileStruct.fileData=threadInfo->postPatchFile;
223 threadInfo->onFileStruct.byteLengthOfThisFile=threadInfo->postPatchLength;
224 onFileCallback->OnFile(&threadInfo->onFileStruct);
225 threadInfo->onFileStruct.fileData=0;
226 }
227 }
228 break;
229 case PC_ERROR_PATCH_TARGET_MISSING:
230 {
231 onFileCallback->OnFile(&threadInfo->onFileStruct);
232 client->Redownload(threadInfo->onFileStruct.fileName);
233 }
234 break;
235 case PC_ERROR_PATCH_APPLICATION_FAILURE:
236 {
237 // Failure - signal class and download this file.
238 onFileCallback->OnFile(&threadInfo->onFileStruct);
239 client->Redownload(threadInfo->onFileStruct.fileName);
240 }
241 break;
242 case PC_ERROR_PATCH_RESULT_CHECKSUM_FAILURE:
243 {
244 // Failure - signal class and download this file.
245 onFileCallback->OnFile(&threadInfo->onFileStruct);
246 client->Redownload(threadInfo->onFileStruct.fileName);
247 }
248 break;
249 default:
250 {
251 if (threadInfo->onFileStruct.context.op==PC_WRITE_FILE)
252 {
253 onFileCallback->OnFile(&threadInfo->onFileStruct);
254 }
255 else
256 {
257 rakFree_Ex(threadInfo->onFileStruct.fileData, __FILE__, __LINE__ );
258 threadInfo->onFileStruct.fileData=threadInfo->postPatchFile;
259 onFileCallback->OnFile(&threadInfo->onFileStruct);
260 threadInfo->onFileStruct.fileData=0;
261 }
262 }
263 break;
264 }
265
266 if (threadInfo->prePatchFile)
267 rakFree_Ex(threadInfo->prePatchFile, __FILE__, __LINE__ );
268 if (threadInfo->postPatchFile)
269 rakFree_Ex(threadInfo->postPatchFile, __FILE__, __LINE__ );
270 if (threadInfo->onFileStruct.fileData)
271 rakFree_Ex(threadInfo->onFileStruct.fileData, __FILE__, __LINE__ );
272 RakNet::OP_DELETE(threadInfo, __FILE__, __LINE__);
273 }
274
275 // If both input and output are empty, we are done.
276 if (onFileCallback->Update()==false)
277 canDeleteUser=true;
278
279 if ( downloadComplete &&
280 canDeleteUser &&
281 threadPool.IsWorking()==false)
282 {
283 // Stop threads before calling OnThreadCompletion, in case the other thread starts a new instance of this thread.
284 StopThreads();
285 client->OnThreadCompletion();
286 return false;
287 }
288
289 return true;
290 }
OnDownloadComplete(DownloadCompleteStruct * dcs)291 virtual bool OnDownloadComplete(DownloadCompleteStruct *dcs)
292 {
293 downloadComplete=true;
294 if (onFileCallback->OnDownloadComplete(dcs)==false)
295 {
296 canDeleteUser=true;
297 }
298 return true;
299 };
OnDereference(void)300 virtual void OnDereference(void)
301 {
302 onFileCallback->OnDereference();
303 StopThreads();
304 }
OnFile(OnFileStruct * onFileStruct)305 virtual bool OnFile(OnFileStruct *onFileStruct)
306 {
307 AutopatcherClientThreadInfo *inStruct = RakNet::OP_NEW<AutopatcherClientThreadInfo>( __FILE__, __LINE__ );
308 inStruct->prePatchFile=0;
309 inStruct->postPatchFile=0;
310 memcpy(&(inStruct->onFileStruct), onFileStruct, sizeof(OnFileStruct));
311 memcpy(inStruct->applicationDirectory,applicationDirectory,sizeof(applicationDirectory));
312 if (onFileStruct->context.op==PC_HASH_WITH_PATCH)
313 onFileStruct->context.op=PC_NOTICE_FILE_DOWNLOADED_PATCH;
314 else
315 onFileStruct->context.op=PC_NOTICE_FILE_DOWNLOADED;
316 onFileCallback->OnFile(onFileStruct);
317 threadPool.AddInput(AutopatcherClientWorkerThread, inStruct);
318
319 // Return false means don't delete OnFileStruct::data
320 return false;
321 }
OnFileProgress(FileProgressStruct * fps)322 virtual void OnFileProgress(FileProgressStruct *fps)
323 {
324 char fullPathToDir[1024];
325
326 if (fps->onFileStruct->fileName)
327 {
328 strcpy(fullPathToDir, applicationDirectory);
329 strcat(fullPathToDir, fps->onFileStruct->fileName);
330 onFileCallback->OnFileProgress(fps);
331 }
332 }
333 };
AutopatcherClient()334 AutopatcherClient::AutopatcherClient()
335 {
336 serverId=UNASSIGNED_SYSTEM_ADDRESS;
337 serverIdIndex=-1;
338 applicationDirectory[0]=0;
339 fileListTransfer=0;
340 priority=HIGH_PRIORITY;
341 orderingChannel=0;
342 serverDate[0]=0;
343 userCB=0;
344 processThreadCompletion=false;
345 }
~AutopatcherClient()346 AutopatcherClient::~AutopatcherClient()
347 {
348 Clear();
349 }
Clear(void)350 void AutopatcherClient::Clear(void)
351 {
352 if (fileListTransfer)
353 fileListTransfer->RemoveReceiver(serverId);
354 serverId=UNASSIGNED_SYSTEM_ADDRESS;
355 setId=(unsigned short)-1;
356 redownloadList.Clear();
357 copyAndRestartList.Clear();
358 }
SetUploadSendParameters(PacketPriority _priority,char _orderingChannel)359 void AutopatcherClient::SetUploadSendParameters(PacketPriority _priority, char _orderingChannel)
360 {
361 priority=_priority;
362 orderingChannel=_orderingChannel;
363 }
SetFileListTransferPlugin(FileListTransfer * flt)364 void AutopatcherClient::SetFileListTransferPlugin(FileListTransfer *flt)
365 {
366 fileListTransfer=flt;
367 }
GetServerDate(void) const368 char* AutopatcherClient::GetServerDate(void) const
369 {
370 return (char*)serverDate;
371 }
CancelDownload(void)372 void AutopatcherClient::CancelDownload(void)
373 {
374 fileListTransfer->CancelReceive(setId);
375 Clear();
376 }
OnThreadCompletion(void)377 void AutopatcherClient::OnThreadCompletion(void)
378 {
379 processThreadCompletion=true;
380 }
IsPatching(void) const381 bool AutopatcherClient::IsPatching(void) const
382 {
383 return fileListTransfer->IsHandlerActive(setId);
384 }
PatchApplication(const char * _applicationName,const char * _applicationDirectory,const char * lastUpdateDate,SystemAddress host,FileListTransferCBInterface * onFileCallback,const char * restartOutputFilename,const char * pathToRestartExe)385 bool AutopatcherClient::PatchApplication(const char *_applicationName, const char *_applicationDirectory, const char *lastUpdateDate, SystemAddress host, FileListTransferCBInterface *onFileCallback, const char *restartOutputFilename, const char *pathToRestartExe)
386 {
387 RakAssert(applicationName);
388 RakAssert(applicationDirectory);
389 RakAssert(pathToRestartExe);
390 RakAssert(restartOutputFilename);
391
392 // if (rakPeerInterface->GetIndexFromSystemAddress(host)==-1)
393 // return false;
394 if (IsPatching())
395 return false; // Already in the middle of patching.
396
397 strcpy(applicationDirectory, _applicationDirectory);
398 FileList::FixEndingSlash(applicationDirectory);
399 strcpy(applicationName, _applicationName);
400 serverId=host;
401 patchComplete=false;
402 userCB=onFileCallback;
403 strcpy(copyOnRestartOut, restartOutputFilename);
404 strcpy(restartExe, pathToRestartExe);
405 processThreadCompletion=false;
406
407 RakNet::BitStream outBitStream;
408 outBitStream.Write((unsigned char)ID_AUTOPATCHER_GET_CHANGELIST_SINCE_DATE);
409 stringCompressor->EncodeString(applicationName, 512, &outBitStream);
410 stringCompressor->EncodeString(lastUpdateDate, 64, &outBitStream);
411 SendUnified(&outBitStream, priority, RELIABLE_ORDERED, orderingChannel, host, false);
412 return true;
413 }
414 #ifdef _MSC_VER
415 #pragma warning( disable : 4100 ) // warning C4100: <variable name> : unreferenced formal parameter
416 #endif
Update(void)417 void AutopatcherClient::Update(void)
418 {
419 if (processThreadCompletion)
420 {
421 processThreadCompletion=false;
422 fileListTransfer->RemoveReceiver(serverId);
423
424 // If redownload list, process it
425 if (redownloadList.fileList.Size())
426 {
427 RakNet::BitStream outBitStream;
428 AutopatcherClientCallback *transferCallback;
429 transferCallback = RakNet::OP_NEW<AutopatcherClientCallback>( __FILE__, __LINE__ );
430 strcpy(transferCallback->applicationDirectory, applicationDirectory);
431 transferCallback->onFileCallback=userCB;
432 transferCallback->client=this;
433 setId = fileListTransfer->SetupReceive(transferCallback, true, serverId);
434
435 // Ask for patches for the files in the list that are different from what we have.
436 outBitStream.Write((unsigned char)ID_AUTOPATCHER_GET_PATCH);
437 outBitStream.Write(setId);
438 stringCompressor->EncodeString(applicationName, 512, &outBitStream);
439 redownloadList.Serialize(&outBitStream);
440 SendUnified(&outBitStream, priority, RELIABLE_ORDERED, orderingChannel, serverId, false);
441 redownloadList.Clear();
442 }
443 else if (copyAndRestartList.fileList.Size())
444 {
445 Packet *p = AllocatePacketUnified(1);
446 p->bitSize=p->length*8;
447 p->data[0]=ID_AUTOPATCHER_RESTART_APPLICATION;
448 p->systemAddress=serverId;
449 p->systemAddress.systemIndex=serverIdIndex;
450 PushBackPacketUnified(p,false);
451
452 FILE *fp;
453 fp = fopen(copyOnRestartOut, "wt");
454 RakAssert(fp);
455 if (fp)
456 {
457 fprintf(fp, "#Sleep 1000\n");
458 unsigned i;
459 for (i=0; i < copyAndRestartList.fileList.Size(); i++)
460 {
461 #ifdef _WIN32
462 fprintf(fp, "del /q \"%s%s\"\n", applicationDirectory, copyAndRestartList.fileList[i].filename.C_String());
463 fprintf(fp, "rename \"%s%s%s\" \"%s\"\n", applicationDirectory, copyAndRestartList.fileList[i].filename.C_String(), COPY_ON_RESTART_EXTENSION, copyAndRestartList.fileList[i].filename.C_String());
464 #else
465 fprintf(fp, "rm -f \"%s%s\"\n", applicationDirectory, copyAndRestartList.fileList[i].filename.C_String());
466 fprintf(fp, "mv \"%s%s%s\" \"%s\"\n", applicationDirectory, copyAndRestartList.fileList[i].filename.C_String(), COPY_ON_RESTART_EXTENSION, copyAndRestartList.fileList[i].filename.C_String());
467 #endif
468 }
469 #ifdef _WIN32
470 fprintf(fp, "#CreateProcess \"%s\"\n", restartExe);
471 #else
472 fprintf(fp, "chmod +x \"%s\"\n", restartExe);
473 fprintf(fp, "#CreateProcess \"%s\" &\n", restartExe);
474 #endif
475 fprintf(fp, "#DeleteThisFile\n");
476 fclose(fp);
477 }
478 }
479 else
480 {
481 Packet *p = AllocatePacketUnified(1);
482 p->bitSize=p->length*8;
483 p->data[0]=ID_AUTOPATCHER_FINISHED;
484 p->systemAddress=serverId;
485 p->systemAddress.systemIndex=serverIdIndex;
486 PushBackPacketUnified(p,false);
487 }
488 }
489 }
OnClosedConnection(SystemAddress systemAddress,RakNetGUID rakNetGUID,PI2_LostConnectionReason lostConnectionReason)490 void AutopatcherClient::OnClosedConnection(SystemAddress systemAddress, RakNetGUID rakNetGUID, PI2_LostConnectionReason lostConnectionReason )
491 {
492 if (systemAddress==serverId)
493 Clear();
494 }
OnReceive(Packet * packet)495 PluginReceiveResult AutopatcherClient::OnReceive(Packet *packet)
496 {
497 switch (packet->data[0])
498 {
499 case ID_AUTOPATCHER_CREATION_LIST:
500 return OnCreationList(packet);
501 case ID_AUTOPATCHER_DELETION_LIST:
502 OnDeletionList(packet);
503 return RR_STOP_PROCESSING_AND_DEALLOCATE;
504 case ID_AUTOPATCHER_REPOSITORY_FATAL_ERROR:
505 fileListTransfer->RemoveReceiver(serverId);
506 Clear();
507 return RR_CONTINUE_PROCESSING;
508 case ID_AUTOPATCHER_FINISHED_INTERNAL:
509 return OnDownloadFinishedInternal(packet);
510 case ID_AUTOPATCHER_FINISHED:
511 return OnDownloadFinished(packet);
512 }
513 return RR_CONTINUE_PROCESSING;
514 }
515 #ifdef _MSC_VER
516 #pragma warning( disable : 4100 ) // warning C4100: <variable name> : unreferenced formal parameter
517 #endif
OnShutdown(void)518 void AutopatcherClient::OnShutdown(void)
519 {
520 // TODO
521 }
522
OnCreationList(Packet * packet)523 PluginReceiveResult AutopatcherClient::OnCreationList(Packet *packet)
524 {
525 RakAssert(fileListTransfer);
526 if (packet->systemAddress!=serverId)
527 return RR_STOP_PROCESSING_AND_DEALLOCATE;
528
529 RakNet::BitStream inBitStream(packet->data, packet->length, false);
530 RakNet::BitStream outBitStream;
531 FileList remoteFileList, missingOrChanged;
532 inBitStream.IgnoreBits(8);
533 if (remoteFileList.Deserialize(&inBitStream)==false)
534 return RR_STOP_PROCESSING_AND_DEALLOCATE;
535
536 stringCompressor->DecodeString(serverDate, 128, &inBitStream);
537 RakAssert(serverDate[0]);
538
539 // Go through the list of hashes. For each file we already have, remove it from the list.
540 remoteFileList.ListMissingOrChangedFiles(applicationDirectory, &missingOrChanged, true, false);
541
542 if (missingOrChanged.fileList.Size()==0)
543 {
544 packet->data[0]=ID_AUTOPATCHER_FINISHED;
545 return RR_CONTINUE_PROCESSING; // Pass to user
546 }
547
548 // Prepare the transfer plugin to get a file list.
549 AutopatcherClientCallback *transferCallback;
550 transferCallback = RakNet::OP_NEW<AutopatcherClientCallback>( __FILE__, __LINE__ );
551 strcpy(transferCallback->applicationDirectory, applicationDirectory);
552 transferCallback->onFileCallback=userCB;
553 transferCallback->client=this;
554 setId = fileListTransfer->SetupReceive(transferCallback, true, packet->systemAddress);
555
556 // Ask for patches for the files in the list that are different from what we have.
557 outBitStream.Write((unsigned char)ID_AUTOPATCHER_GET_PATCH);
558 outBitStream.Write(setId);
559 stringCompressor->EncodeString(applicationName, 512, &outBitStream);
560 missingOrChanged.Serialize(&outBitStream);
561 SendUnified(&outBitStream, priority, RELIABLE_ORDERED, orderingChannel, packet->systemAddress, false);
562
563 return RR_STOP_PROCESSING_AND_DEALLOCATE; // Absorb this message
564 }
OnDeletionList(Packet * packet)565 void AutopatcherClient::OnDeletionList(Packet *packet)
566 {
567 if (packet->systemAddress!=serverId)
568 return;
569
570 RakNet::BitStream inBitStream(packet->data, packet->length, false);
571 RakNet::BitStream outBitStream;
572 inBitStream.IgnoreBits(8);
573 FileList fileList;
574 if (fileList.Deserialize(&inBitStream)==false)
575 return;
576 fileList.DeleteFiles(applicationDirectory);
577 }
OnDownloadFinished(Packet * packet)578 PluginReceiveResult AutopatcherClient::OnDownloadFinished(Packet *packet)
579 {
580 RakNet::BitStream inBitStream(packet->data, packet->length, false);
581 inBitStream.IgnoreBits(8);
582 // This may have been created internally, with no serverDate written (line 469 or so)
583 if (inBitStream.GetNumberOfUnreadBits()>7)
584 stringCompressor->DecodeString(serverDate, 128, &inBitStream);
585 RakAssert(serverDate[0]);
586 serverId=packet->systemAddress;
587 serverIdIndex=packet->systemAddress.systemIndex;
588
589 return RR_CONTINUE_PROCESSING;
590 }
OnDownloadFinishedInternal(Packet * packet)591 PluginReceiveResult AutopatcherClient::OnDownloadFinishedInternal(Packet *packet)
592 {
593 RakNet::BitStream inBitStream(packet->data, packet->length, false);
594 inBitStream.IgnoreBits(8);
595 serverId=packet->systemAddress;
596 serverIdIndex=packet->systemAddress.systemIndex;
597 stringCompressor->DecodeString(serverDate, 128, &inBitStream);
598 RakAssert(serverDate[0]);
599
600 return RR_STOP_PROCESSING_AND_DEALLOCATE;
601 }
CopyAndRestart(const char * filePath)602 void AutopatcherClient::CopyAndRestart(const char *filePath)
603 {
604 // We weren't able to write applicationDirectory + filePath so we wrote applicationDirectory + filePath + COPY_ON_RESTART_EXTENSION instead
605 copyAndRestartList.AddFile(filePath,filePath, 0, 0, 0, FileListNodeContext(0,0));
606 }
Redownload(const char * filePath)607 void AutopatcherClient::Redownload(const char *filePath)
608 {
609 redownloadList.AddFile(filePath,filePath, 0, 0, 0, FileListNodeContext(0,0));
610 }
611
612 #ifdef _MSC_VER
613 #pragma warning( pop )
614 #endif
615