BratokHR

Untitled

Jan 26th, 2021
744
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.     Немного принципа:
  3.    
  4.         При подключении к серверу(при отправки connectionless), сервер присылает
  5.     список файлов с хешами, которые нужны для сервера. Этот список записывается
  6.     в глобальную переменную g_localfiles.
  7.  
  8.         Ставится хук функции UI_DisplayDownloadInfo, она вызывается только тогда,
  9.     когда клиент начинает загрузку iwd файлов с сервера. В этом хуке ставится
  10.     флаг g_donwload, что приводит к началу загрузки файлов в потоке downloadThread,
  11.     и прерывается загрузка через стоковый протокол игры.
  12.  
  13.         После завершения загрузки, клиент переподключается к серверу и UI_DisplayDownloadInfo
  14.     уже не вызывается, что и збс...
  15.  
  16.  
  17.  
  18.     Поток загрузки. Он делает основную работу:
  19.     - Проверяет все файлы по md5-хешу, предварительно получив md5-хеши от сервера
  20.     - Скачивает файлы и заменяет их
  21. */
  22. void downloadThread()
  23. {
  24.     md5wrapper md5;
  25.  
  26.     for (;;)
  27.     {
  28.         if (!g_download)
  29.         {
  30.             Sleep(1000);
  31.             continue;
  32.         }
  33.  
  34. #ifdef DEBUG
  35.         printf("Host: %s\n", (char*)g_localfiles.host.c_str());
  36.         printf("Start download:\n");
  37. #endif
  38.  
  39.         g_dl_from = (char*)g_localfiles.host.c_str();
  40.         char *fs_game = GetCvar("fs_game")->string;
  41.         for (int i = 0; i < g_localfiles.files.size(); i++)
  42.         {
  43.             if (!g_download)
  44.                 break;
  45.  
  46. #ifdef DEBUG
  47.             printf("   - %s", (char*)g_localfiles.files[i].c_str());
  48. #endif
  49.             char file_path[MAX_PATH];
  50.             sprintf(file_path, "%s/%s", fs_game, (char*)g_localfiles.files[i].c_str());
  51.             g_dl_currentfile = (char*)g_localfiles.files[i].c_str();
  52.  
  53.             // check hash file
  54.             if (file_exists(file_path))
  55.             {
  56.                 std::string hash_path = md5.getHashFromFile(file_path);
  57.  
  58.                 if (hash_path == "-1")
  59.                 {
  60. #ifdef DEBUG
  61.                     printf(" (failed to read)\n");
  62. #endif
  63.                     game.Printf(0, "^3[COD2X] ^1failed to read file %s\n", file_path);
  64.                     continue;
  65.                 }
  66.  
  67.                 // get hash file from host
  68.                 char req[256], url[256];
  69.                 sprintf(req, "fs_game=%s&file=%s", fs_game, (char*)g_localfiles.files[i].c_str());
  70.                 sprintf(url, "%s/hash.php", (char*)g_localfiles.host.c_str());
  71.  
  72.                 char *hash_url = sendGetRequest(url, req);
  73.                 if (strcmp(hash_url, "-1") == 0)
  74.                 {
  75. #ifdef DEBUG
  76.                     printf(" (%s)\n", getCurlError());
  77. #endif
  78.                     game.Printf(0, "^3[COD2X] ^1failed to get hash file %s\n", getCurlError());
  79.                     continue;
  80.                 }
  81.  
  82.                 printf(" (%s)", hash_url);
  83.  
  84.                 if (strcmp((char*)hash_path.c_str(), hash_url) != 0)
  85.                 {
  86.                     g_localfiles.state[i] = 1; // need download
  87.                 }
  88. #ifdef DEBUG
  89.                 else printf(" not needed...\n");
  90. #endif
  91.             }
  92.             else g_localfiles.state[i] = 1;
  93.  
  94.             if (g_localfiles.state[i] != 1)
  95.                 continue;
  96.  
  97.             // download if needed
  98.             char file_url[MAX_PATH] = "\0";
  99.             sprintf(file_url, "%s/%s/%s", (char*)g_localfiles.host.c_str(), fs_game, (char*)g_localfiles.files[i].c_str());
  100.  
  101.             g_dl_size = getFileSizeByUrl(file_url);
  102.  
  103.             if (g_dl_size < 0)
  104.             {
  105. #ifdef DEBUG
  106.                 printf(" (%s)\n", getCurlError());
  107. #endif
  108.                 game.Printf(0, "^3[COD2X] ^1failed to get size file %s\n", getCurlError());
  109.                 continue;
  110.             }
  111.  
  112.             // сохранить в .tmp файле
  113.             char tmpfile[MAX_PATH];
  114.             sprintf(tmpfile, "%s.tmp", file_path);
  115.  
  116.             g_dl_bytes = 0;
  117.             g_dl_state = 1;
  118.             // загрузка файла
  119.             bool res = startDownload(file_url, tmpfile);
  120.  
  121.             if (!res)
  122.             {
  123.                 if (g_dl_size < 0)
  124.                 {
  125. #ifdef DEBUG
  126.                     printf(" (%s)\n", getCurlError());
  127. #endif
  128.                     game.Printf(0, "^3[COD2X] ^1failed to download file %s\n", getCurlError());
  129.                     continue;
  130.                 }
  131.             }
  132.  
  133. #ifdef DEBUG
  134.             printf("...OK\n");
  135. #endif
  136.            
  137.             // переименовать
  138.             if (rename(tmpfile, file_path))
  139.                 copy(tmpfile, file_path);
  140.             remove(tmpfile);
  141.         }
  142.  
  143.         g_dl_state = 0;
  144.         g_download = false;
  145.  
  146.         // переподключиться к серверу
  147.         game.Cmd_ExecuteText(1, "disconnect; wait 1; reconnect");
  148.     }
  149. }
  150.  
  151. /*
  152.     Хуки функций игры
  153. */
  154. bool MyDisplayDownload()
  155. {
  156.     traceLastFunc("MyDisplayDownload()");
  157.  
  158.     if (g_dl_init || getClientState() > CA_LOADING)
  159.         return false;
  160.    
  161.     if (g_download)
  162.         return true;
  163.  
  164.     if (g_localfiles.files.empty() || g_localfiles.host == "")
  165.         return false;
  166.  
  167.     // остановка загрузки файлов в игре
  168.     game.CL_AddReliableCommand("stopdl");
  169.     // флаг загрузки, в потоке загрузки он дает понять, что
  170.     // нужно что-то скачать
  171.     g_download = true;
  172.     // если при переподключении к серверу, игрок все равно что-то скачивает
  173.     // то этот флаг делает так, чтобы загрузка была через игру, а не CURL
  174.     g_dl_init = 1;
  175.  
  176.     return true;
  177. }
  178.  
  179. //        1.0          1.3
  180. // 0x00532830 : 0x00538AF0
  181. oUI_DisplayDownloadInfo pUI_DisplayDownloadInfo;
  182. void __declspec(naked) hUI_DisplayDownloadInfo(void)
  183. {
  184.     __asm pushad;
  185.  
  186.     if (!MyDisplayDownload())
  187.     {
  188.         __asm popad;
  189.         __asm jmp[pUI_DisplayDownloadInfo];
  190.     }
  191.     else
  192.     {
  193.         __asm popad;
  194.         __asm ret;
  195.     }
  196. }
RAW Paste Data