mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-03-24 03:32:22 +00:00
HTTP downloader port
This commit is contained in:
parent
fd92193f7e
commit
b4beaa9f43
9 changed files with 872 additions and 271 deletions
|
@ -1,7 +1,7 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2023 by Sonic Team Junior.
|
||||
// Copyright (C) 1999-2024 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
|
@ -43,11 +43,45 @@ tic_t firstconnectattempttime = 0;
|
|||
UINT8 mynode;
|
||||
static void *snake = NULL;
|
||||
|
||||
static void CL_DrawConnectionStatusBox(void)
|
||||
static boolean IsDownloadingFile(void)
|
||||
{
|
||||
if (cl_mode == CL_DOWNLOADFILES || cl_mode == CL_DOWNLOADHTTPFILES)
|
||||
return filedownload.current != -1;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void DrawConnectionStatusBox(void)
|
||||
{
|
||||
M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-16-8, 32, 1);
|
||||
if (cl_mode != CL_CONFIRMCONNECT)
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort");
|
||||
|
||||
if (cl_mode == CL_CONFIRMCONNECT || IsDownloadingFile())
|
||||
return;
|
||||
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_YELLOWMAP, "Press ESC to abort");
|
||||
}
|
||||
|
||||
static void DrawFileProgress(fileneeded_t *file, int y)
|
||||
{
|
||||
Net_GetNetStat();
|
||||
|
||||
INT32 dldlength = (INT32)((file->currentsize/(double)file->totalsize) * 256);
|
||||
if (dldlength > 256)
|
||||
dldlength = 256;
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, y, 256, 8, 111);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, y, dldlength, 8, 96);
|
||||
|
||||
const char *progress_str;
|
||||
if (file->totalsize >= 1024*1024)
|
||||
progress_str = va(" %.2fMiB/%.2fMiB", (double)file->currentsize / (1024*1024), (double)file->totalsize / (1024*1024));
|
||||
else if (file->totalsize < 1024)
|
||||
progress_str = va(" %4uB/%4uB", file->currentsize, file->totalsize);
|
||||
else
|
||||
progress_str = va(" %.2fKiB/%.2fKiB", (double)file->currentsize / 1024, (double)file->totalsize / 1024);
|
||||
|
||||
V_DrawString(BASEVIDWIDTH/2-128, y, V_20TRANS|V_ALLOWLOWERCASE, progress_str);
|
||||
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH/2+128, y, V_20TRANS|V_MONOSPACE, va("%3.1fK/s ", ((double)getbps)/1024));
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -55,21 +89,21 @@ static void CL_DrawConnectionStatusBox(void)
|
|||
//
|
||||
// Keep the local client informed of our status.
|
||||
//
|
||||
static inline void CL_DrawConnectionStatus(void)
|
||||
static void CL_DrawConnectionStatus(void)
|
||||
{
|
||||
INT32 ccstime = I_GetTime();
|
||||
|
||||
// Draw background fade
|
||||
V_DrawFadeScreen(0xFF00, 16); // force default
|
||||
|
||||
if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_LOADFILES)
|
||||
if (cl_mode != CL_DOWNLOADFILES && cl_mode != CL_DOWNLOADHTTPFILES && cl_mode != CL_LOADFILES)
|
||||
{
|
||||
INT32 animtime = ((ccstime / 4) & 15) + 16;
|
||||
UINT8 palstart;
|
||||
const char *cltext;
|
||||
|
||||
// Draw the bottom box.
|
||||
CL_DrawConnectionStatusBox();
|
||||
DrawConnectionStatusBox();
|
||||
|
||||
if (cl_mode == CL_SEARCHING)
|
||||
palstart = 32; // Red
|
||||
|
@ -78,33 +112,20 @@ static inline void CL_DrawConnectionStatus(void)
|
|||
else
|
||||
palstart = 96; // Green
|
||||
|
||||
if (!(cl_mode == CL_DOWNLOADSAVEGAME && lastfilenum != -1))
|
||||
if (!(cl_mode == CL_DOWNLOADSAVEGAME && filedownload.current != -1))
|
||||
for (INT32 i = 0; i < 16; ++i) // 15 pal entries total.
|
||||
V_DrawFill((BASEVIDWIDTH/2-128) + (i * 16), BASEVIDHEIGHT-16, 16, 8, palstart + ((animtime - i) & 15));
|
||||
|
||||
switch (cl_mode)
|
||||
{
|
||||
case CL_DOWNLOADSAVEGAME:
|
||||
if (fileneeded && lastfilenum != -1)
|
||||
if (fileneeded && filedownload.current != -1)
|
||||
{
|
||||
UINT32 currentsize = fileneeded[lastfilenum].currentsize;
|
||||
UINT32 totalsize = fileneeded[lastfilenum].totalsize;
|
||||
INT32 dldlength;
|
||||
fileneeded_t *file = &fileneeded[filedownload.current];
|
||||
|
||||
cltext = M_GetText("Downloading game state...");
|
||||
Net_GetNetStat();
|
||||
|
||||
dldlength = (INT32)((currentsize/(double)totalsize) * 256);
|
||||
if (dldlength > 256)
|
||||
dldlength = 256;
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, 256, 8, 111);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, dldlength, 8, 96);
|
||||
|
||||
V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE,
|
||||
va(" %4uK/%4uK",currentsize>>10,totalsize>>10));
|
||||
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE,
|
||||
va("%3.1fK/s ", ((double)getbps)/1024));
|
||||
DrawFileProgress(file, BASEVIDHEIGHT-16);
|
||||
}
|
||||
else
|
||||
cltext = M_GetText("Waiting to download game state...");
|
||||
|
@ -156,12 +177,11 @@ static inline void CL_DrawConnectionStatus(void)
|
|||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, 256, 8, 111);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, totalfileslength, 8, 96);
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE,
|
||||
va(" %2u/%2u Files",loadcompletednum,fileneedednum));
|
||||
va(" %2u/%2u files",loadcompletednum,fileneedednum));
|
||||
}
|
||||
else if (lastfilenum != -1)
|
||||
else if (filedownload.current != -1)
|
||||
{
|
||||
INT32 dldlength;
|
||||
static char tempname[28];
|
||||
char tempname[28];
|
||||
fileneeded_t *file;
|
||||
char *filename;
|
||||
|
||||
|
@ -169,24 +189,16 @@ static inline void CL_DrawConnectionStatus(void)
|
|||
Snake_Draw(snake);
|
||||
|
||||
// Draw the bottom box.
|
||||
CL_DrawConnectionStatusBox();
|
||||
DrawConnectionStatusBox();
|
||||
|
||||
if (fileneeded)
|
||||
{
|
||||
file = &fileneeded[lastfilenum];
|
||||
file = &fileneeded[filedownload.current];
|
||||
filename = file->filename;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
Net_GetNetStat();
|
||||
dldlength = (INT32)((file->currentsize/(double)file->totalsize) * 256);
|
||||
if (dldlength > 256)
|
||||
dldlength = 256;
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, 256, 8, 111);
|
||||
V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, dldlength, 8, 96);
|
||||
|
||||
memset(tempname, 0, sizeof(tempname));
|
||||
// offset filename to just the name only part
|
||||
filename += strlen(filename) - nameonlylength(filename);
|
||||
|
||||
|
@ -199,22 +211,56 @@ static inline void CL_DrawConnectionStatus(void)
|
|||
}
|
||||
else // we can copy the whole thing in safely
|
||||
{
|
||||
strncpy(tempname, filename, sizeof(tempname)-1);
|
||||
strlcpy(tempname, filename, sizeof(tempname));
|
||||
}
|
||||
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP,
|
||||
va(M_GetText("Downloading \"%s\""), tempname));
|
||||
V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE,
|
||||
va(" %4uK/%4uK",fileneeded[lastfilenum].currentsize>>10,file->totalsize>>10));
|
||||
V_DrawRightAlignedString(BASEVIDWIDTH/2+128, BASEVIDHEIGHT-16, V_20TRANS|V_MONOSPACE,
|
||||
va("%3.1fK/s ", ((double)getbps)/1024));
|
||||
// Lactozilla: Disabled, see below change
|
||||
// (also it doesn't really fit on a typical SRB2 screen)
|
||||
#if 0
|
||||
const char *download_str = cl_mode == CL_DOWNLOADHTTPFILES
|
||||
? M_GetText("HTTP downloading \"%s\"")
|
||||
: M_GetText("Downloading \"%s\"");
|
||||
#else
|
||||
const char *download_str = M_GetText("Downloading \"%s\"");
|
||||
#endif
|
||||
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_ALLOWLOWERCASE|V_YELLOWMAP,
|
||||
va(download_str, tempname));
|
||||
|
||||
// Rusty: actually lets do this instead
|
||||
if (cl_mode == CL_DOWNLOADHTTPFILES)
|
||||
{
|
||||
const char *http_source = filedownload.http_source;
|
||||
|
||||
if (strlen(http_source) > sizeof(tempname)-1) // too long to display fully
|
||||
{
|
||||
size_t endhalfpos = strlen(http_source)-10;
|
||||
// display as first 14 chars + ... + last 10 chars
|
||||
// which should add up to 27 if our math(s) is correct
|
||||
snprintf(tempname, sizeof(tempname), "%.14s...%.10s", http_source, http_source+endhalfpos);
|
||||
}
|
||||
else // we can copy the whole thing in safely
|
||||
{
|
||||
strlcpy(tempname, http_source, sizeof(tempname));
|
||||
}
|
||||
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_ALLOWLOWERCASE|V_YELLOWMAP,
|
||||
va(M_GetText("from %s"), tempname));
|
||||
}
|
||||
else
|
||||
{
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-16, V_ALLOWLOWERCASE|V_YELLOWMAP,
|
||||
M_GetText("from the server"));
|
||||
}
|
||||
|
||||
DrawFileProgress(file, BASEVIDHEIGHT-16);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (snake)
|
||||
Snake_Draw(snake);
|
||||
|
||||
CL_DrawConnectionStatusBox();
|
||||
DrawConnectionStatusBox();
|
||||
V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-16-24, V_YELLOWMAP,
|
||||
M_GetText("Waiting to download files..."));
|
||||
}
|
||||
|
@ -479,23 +525,98 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room)
|
|||
#endif // MASTERSERVER
|
||||
}
|
||||
|
||||
static boolean IsFileDownloadable(fileneeded_t *file)
|
||||
{
|
||||
return file->status == FS_NOTFOUND || file->status == FS_MD5SUMBAD;
|
||||
}
|
||||
|
||||
static boolean UseDirectDownloader(void)
|
||||
{
|
||||
return filedownload.http_source[0] == '\0' || filedownload.http_failed;
|
||||
}
|
||||
|
||||
static void DoLoadFiles(void)
|
||||
{
|
||||
Snake_Free(&snake);
|
||||
|
||||
cl_mode = CL_LOADFILES;
|
||||
}
|
||||
|
||||
static void AbortConnection(void)
|
||||
{
|
||||
Snake_Free(&snake);
|
||||
|
||||
D_QuitNetGame();
|
||||
CL_Reset();
|
||||
D_StartTitle();
|
||||
|
||||
// Will be reset by caller. Signals refusal.
|
||||
cl_mode = CL_ABORTED;
|
||||
}
|
||||
|
||||
static void BeginDownload(boolean direct)
|
||||
{
|
||||
filedownload.current = 0;
|
||||
filedownload.remaining = 0;
|
||||
|
||||
for (int i = 0; i < fileneedednum; i++)
|
||||
{
|
||||
// Lactozilla: Rusty had fixed this SLIGHTLY incorrectly.
|
||||
// Since [redacted] doesn't HAVE its own file transmission code - it spins an HTTP server - it wasn't
|
||||
// instantly obvious to us where to do this, and we didn't want to check the original implementation.
|
||||
if (fileneeded[i].status == FS_FALLBACK)
|
||||
fileneeded[i].status = FS_NOTFOUND;
|
||||
|
||||
if (IsFileDownloadable(&fileneeded[i]))
|
||||
filedownload.remaining++;
|
||||
}
|
||||
|
||||
if (!filedownload.remaining)
|
||||
{
|
||||
DoLoadFiles();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!direct)
|
||||
{
|
||||
cl_mode = CL_DOWNLOADHTTPFILES;
|
||||
Snake_Allocate(&snake);
|
||||
|
||||
// Discard any paused downloads
|
||||
CL_AbortDownloadResume();
|
||||
}
|
||||
else
|
||||
{
|
||||
// do old LEGACY request
|
||||
if (CL_SendFileRequest())
|
||||
{
|
||||
cl_mode = CL_DOWNLOADFILES;
|
||||
|
||||
// don't alloc snake if already alloced
|
||||
if (!snake)
|
||||
Snake_Allocate(&snake);
|
||||
}
|
||||
else
|
||||
{
|
||||
AbortConnection();
|
||||
|
||||
// why was this its own cl_mode_t?
|
||||
M_StartMessage(M_GetText(
|
||||
"The direct downloader encountered an error.\n"
|
||||
"See the logfile for more info.\n\n"
|
||||
"Press ESC\n"
|
||||
), NULL, MM_NOTHING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void M_ConfirmConnect(event_t *ev)
|
||||
{
|
||||
if (ev->type == ev_keydown)
|
||||
{
|
||||
if (ev->key == ' ' || ev->key == 'y' || ev->key == KEY_ENTER || ev->key == KEY_JOY1)
|
||||
{
|
||||
if (totalfilesrequestednum > 0)
|
||||
{
|
||||
if (CL_SendFileRequest())
|
||||
{
|
||||
cl_mode = CL_DOWNLOADFILES;
|
||||
Snake_Allocate(&snake);
|
||||
}
|
||||
}
|
||||
else
|
||||
cl_mode = CL_LOADFILES;
|
||||
|
||||
BeginDownload(UseDirectDownloader());
|
||||
M_ClearMenus(true);
|
||||
}
|
||||
else if (ev->key == 'n' || ev->key == KEY_ESCAPE || ev->key == KEY_JOY1 + 3)
|
||||
|
@ -506,22 +627,122 @@ static void M_ConfirmConnect(event_t *ev)
|
|||
}
|
||||
}
|
||||
|
||||
static const char *GetPrintableFileSize(UINT64 filesize)
|
||||
{
|
||||
static char downloadsize[32];
|
||||
|
||||
if (filesize >= 1024*1024)
|
||||
snprintf(downloadsize, sizeof(downloadsize), "%.2fMiB", (double)filesize / (1024*1024));
|
||||
else if (filesize < 1024)
|
||||
snprintf(downloadsize, sizeof(downloadsize), "%luB", filesize);
|
||||
else
|
||||
snprintf(downloadsize, sizeof(downloadsize), "%.2fKiB", (double)filesize / 1024);
|
||||
|
||||
return downloadsize;
|
||||
}
|
||||
|
||||
static void ShowDownloadConsentMessage(void)
|
||||
{
|
||||
UINT64 totalsize = 0;
|
||||
|
||||
filedownload.completednum = 0;
|
||||
filedownload.completedsize = 0;
|
||||
|
||||
if (fileneeded == NULL)
|
||||
I_Error("CL_FinishedFileList: fileneeded == NULL");
|
||||
|
||||
for (int i = 0; i < fileneedednum; i++)
|
||||
{
|
||||
if (IsFileDownloadable(&fileneeded[i]))
|
||||
totalsize += fileneeded[i].totalsize;
|
||||
}
|
||||
|
||||
const char *downloadsize = GetPrintableFileSize(totalsize);
|
||||
|
||||
if (serverisfull)
|
||||
M_StartMessage(va(M_GetText(
|
||||
"This server is full!\n"
|
||||
"Download of %s of additional\ncontent is required to join.\n"
|
||||
"\n"
|
||||
"You may download server addons,\nand wait for a slot.\n"
|
||||
"\n"
|
||||
"Press ENTER to continue\nor ESC to cancel.\n"
|
||||
), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER);
|
||||
else
|
||||
M_StartMessage(va(M_GetText(
|
||||
"Download of %s of additional\ncontent is required to join.\n"
|
||||
"\n"
|
||||
"Press ENTER to continue\nor ESC to cancel.\n"
|
||||
), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER);
|
||||
|
||||
cl_mode = CL_CONFIRMCONNECT;
|
||||
curfadevalue = 0;
|
||||
}
|
||||
|
||||
static const char *GetDirectDownloadFailReason(UINT8 dlstatus)
|
||||
{
|
||||
switch (dlstatus)
|
||||
{
|
||||
case DLSTATUS_TOOLARGE:
|
||||
return M_GetText("Some addons are larger than the server is willing to send.");
|
||||
case DLSTATUS_WONTSEND:
|
||||
return M_GetText("The server is not allowing download requests.");
|
||||
case DLSTATUS_NODOWNLOAD:
|
||||
return M_GetText("All addons downloadable, but you have chosen to disable addon downloading.");
|
||||
case DLSTATUS_FOLDER:
|
||||
return M_GetText("One or more addons were added as a folder, which the server cannot send.");
|
||||
}
|
||||
|
||||
return "Unknown reason";
|
||||
}
|
||||
|
||||
static void HandleDirectDownloadFail(UINT8 dlstatus)
|
||||
{
|
||||
// not downloadable, put reason in console
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You need additional addons to connect to this server:\n"));
|
||||
|
||||
for (UINT8 i = 0; i < fileneedednum; i++)
|
||||
{
|
||||
if (fileneeded[i].folder || (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN))
|
||||
{
|
||||
CONS_Printf(" * \"%s\" ", fileneeded[i].filename);
|
||||
|
||||
if (fileneeded[i].folder)
|
||||
{
|
||||
CONS_Printf("(folder)");
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf("(%s)", GetPrintableFileSize(fileneeded[i].totalsize));
|
||||
|
||||
if (fileneeded[i].status == FS_NOTFOUND)
|
||||
CONS_Printf(M_GetText(" not found, md5: "));
|
||||
else if (fileneeded[i].status == FS_MD5SUMBAD)
|
||||
CONS_Printf(M_GetText(" wrong version, md5: "));
|
||||
|
||||
char md5tmp[33];
|
||||
for (INT32 j = 0; j < 16; j++)
|
||||
sprintf(&md5tmp[j*2], "%02x", fileneeded[i].md5sum[j]);
|
||||
CONS_Printf("%s", md5tmp);
|
||||
}
|
||||
|
||||
CONS_Printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
CONS_Printf("%s\n", GetDirectDownloadFailReason(dlstatus));
|
||||
}
|
||||
|
||||
static boolean CL_FinishedFileList(void)
|
||||
{
|
||||
INT32 i;
|
||||
char *downloadsize = NULL;
|
||||
|
||||
//CONS_Printf(M_GetText("Checking files...\n"));
|
||||
i = CL_CheckFiles();
|
||||
INT32 i = CL_CheckFiles();
|
||||
if (i == 4) // still checking ...
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (i == 3) // too many files
|
||||
{
|
||||
D_QuitNetGame();
|
||||
CL_Reset();
|
||||
D_StartTitle();
|
||||
AbortConnection();
|
||||
M_StartMessage(M_GetText(
|
||||
"You have too many WAD files loaded\n"
|
||||
"to add ones the server is using.\n"
|
||||
|
@ -532,15 +753,15 @@ static boolean CL_FinishedFileList(void)
|
|||
}
|
||||
else if (i == 2) // cannot join for some reason
|
||||
{
|
||||
D_QuitNetGame();
|
||||
CL_Reset();
|
||||
D_StartTitle();
|
||||
AbortConnection();
|
||||
M_StartMessage(M_GetText(
|
||||
"You have the wrong addons loaded.\n\n"
|
||||
"You have the wrong addons loaded.\n"
|
||||
"\n"
|
||||
"To play on this server, restart\n"
|
||||
"the game and don't load any addons.\n"
|
||||
"SRB2 will automatically add\n"
|
||||
"everything you need when you join.\n\n"
|
||||
"everything you need when you join.\n"
|
||||
"\n"
|
||||
"Press ESC\n"
|
||||
), NULL, MM_NOTHING);
|
||||
return false;
|
||||
|
@ -566,63 +787,38 @@ static boolean CL_FinishedFileList(void)
|
|||
{
|
||||
// must download something
|
||||
// can we, though?
|
||||
if (!CL_CheckDownloadable()) // nope!
|
||||
// Rusty: always check downloadable
|
||||
UINT8 status = CL_CheckDownloadable(UseDirectDownloader());
|
||||
if (status != DLSTATUS_OK)
|
||||
{
|
||||
D_QuitNetGame();
|
||||
CL_Reset();
|
||||
D_StartTitle();
|
||||
HandleDirectDownloadFail(status);
|
||||
AbortConnection();
|
||||
M_StartMessage(M_GetText(
|
||||
"An error occurred when trying to\n"
|
||||
"download missing addons.\n"
|
||||
"(This is almost always a problem\n"
|
||||
"with the server, not your game.)\n\n"
|
||||
"with the server, not your game.)\n"
|
||||
"\n"
|
||||
"See the console or log file\n"
|
||||
"for additional details.\n\n"
|
||||
"for additional details.\n"
|
||||
"\n"
|
||||
"Press ESC\n"
|
||||
), NULL, MM_NOTHING);
|
||||
return false;
|
||||
}
|
||||
|
||||
downloadcompletednum = 0;
|
||||
downloadcompletedsize = 0;
|
||||
totalfilesrequestednum = 0;
|
||||
totalfilesrequestedsize = 0;
|
||||
|
||||
if (fileneeded == NULL)
|
||||
I_Error("CL_FinishedFileList: fileneeded == NULL");
|
||||
|
||||
for (i = 0; i < fileneedednum; i++)
|
||||
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)
|
||||
{
|
||||
totalfilesrequestednum++;
|
||||
totalfilesrequestedsize += fileneeded[i].totalsize;
|
||||
}
|
||||
|
||||
if (totalfilesrequestedsize>>20 >= 100)
|
||||
downloadsize = Z_StrDup(va("%uM",totalfilesrequestedsize>>20));
|
||||
if (!filedownload.http_failed)
|
||||
{
|
||||
// show download consent modal ONCE!
|
||||
ShowDownloadConsentMessage();
|
||||
}
|
||||
else
|
||||
downloadsize = Z_StrDup(va("%uK",totalfilesrequestedsize>>10));
|
||||
|
||||
if (serverisfull)
|
||||
M_StartMessage(va(M_GetText(
|
||||
"This server is full!\n"
|
||||
"Download of %s additional content\nis required to join.\n"
|
||||
"\n"
|
||||
"You may download, load server addons,\nand wait for a slot.\n"
|
||||
"\n"
|
||||
"Press ENTER to continue\nor ESC to cancel.\n"
|
||||
), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER);
|
||||
else
|
||||
M_StartMessage(va(M_GetText(
|
||||
"Download of %s additional content\nis required to join.\n"
|
||||
"\n"
|
||||
"Press ENTER to continue\nor ESC to cancel.\n"
|
||||
), downloadsize), M_ConfirmConnect, MM_EVENTHANDLER);
|
||||
|
||||
Z_Free(downloadsize);
|
||||
cl_mode = CL_CONFIRMCONNECT;
|
||||
curfadevalue = 0;
|
||||
{
|
||||
// do a direct download
|
||||
BeginDownload(true);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -734,15 +930,18 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent)
|
|||
if (reason)
|
||||
{
|
||||
char *message = Z_StrDup(reason);
|
||||
D_QuitNetGame();
|
||||
CL_Reset();
|
||||
D_StartTitle();
|
||||
AbortConnection();
|
||||
M_StartMessage(message, NULL, MM_NOTHING);
|
||||
Z_Free(message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (serverlist[i].info.httpsource[0])
|
||||
strlcpy(filedownload.http_source, serverlist[i].info.httpsource, MAX_MIRROR_LENGTH);
|
||||
else
|
||||
filedownload.http_source[0] = '\0';
|
||||
|
||||
D_ParseFileneeded(info->fileneedednum, info->fileneeded, 0);
|
||||
|
||||
if (info->flags & SV_LOTSOFADDONS)
|
||||
|
@ -773,6 +972,42 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void HandleHTTPDownloadFail(void)
|
||||
{
|
||||
char filename[MAX_WADPATH];
|
||||
|
||||
CONS_Alert(CONS_WARNING, M_GetText("One or more addons failed to download:\n"));
|
||||
|
||||
for (int i = 0; i < fileneedednum; i++)
|
||||
{
|
||||
if (fileneeded[i].failed == FDOWNLOAD_FAIL_NONE)
|
||||
continue;
|
||||
|
||||
strlcpy(filename, fileneeded[i].filename, sizeof filename);
|
||||
nameonly(filename);
|
||||
|
||||
CONS_Printf(" * \"%s\" (%s)", filename, GetPrintableFileSize(fileneeded[i].totalsize));
|
||||
|
||||
if (fileneeded[i].failed == FDOWNLOAD_FAIL_NOTFOUND)
|
||||
CONS_Printf(M_GetText(" not found, md5: "));
|
||||
else if (fileneeded[i].failed == FDOWNLOAD_FAIL_MD5SUMBAD)
|
||||
CONS_Printf(M_GetText(" wrong version, md5: "));
|
||||
else
|
||||
CONS_Printf(M_GetText(" other error, md5: "));
|
||||
|
||||
char md5tmp[33];
|
||||
for (INT32 j = 0; j < 16; j++)
|
||||
snprintf(&md5tmp[j*2], sizeof(md5tmp), "%02x", fileneeded[i].md5sum[j]);
|
||||
CONS_Printf("%s\n", md5tmp);
|
||||
|
||||
fileneeded[i].failed = FDOWNLOAD_FAIL_NONE;
|
||||
}
|
||||
|
||||
CONS_Printf(M_GetText("Falling back to direct downloader.\n"));
|
||||
|
||||
cl_mode = CL_CHECKFILES;
|
||||
}
|
||||
|
||||
/** Called by CL_ConnectToServer
|
||||
*
|
||||
* \param tmpsave The name of the gamestate file???
|
||||
|
@ -810,21 +1045,43 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
|
|||
if (!CL_FinishedFileList())
|
||||
return false;
|
||||
break;
|
||||
case CL_DOWNLOADFILES:
|
||||
|
||||
case CL_DOWNLOADHTTPFILES:
|
||||
waitmore = false;
|
||||
for (INT32 i = 0; i < fileneedednum; i++)
|
||||
if (fileneeded[i].status == FS_DOWNLOADING
|
||||
|| fileneeded[i].status == FS_REQUESTED)
|
||||
for (int i = filedownload.current; i < fileneedednum; i++)
|
||||
{
|
||||
if (IsFileDownloadable(&fileneeded[i]))
|
||||
{
|
||||
if (!filedownload.http_running)
|
||||
{
|
||||
if (!CURLPrepareFile(filedownload.http_source, i))
|
||||
HandleHTTPDownloadFail();
|
||||
}
|
||||
waitmore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Rusty TODO: multithread
|
||||
if (filedownload.http_running)
|
||||
CURLGetFile();
|
||||
|
||||
if (waitmore)
|
||||
break; // exit the case
|
||||
|
||||
Snake_Free(&snake);
|
||||
|
||||
cl_mode = CL_LOADFILES;
|
||||
// Done downloading files
|
||||
if (!filedownload.remaining)
|
||||
{
|
||||
if (filedownload.http_failed)
|
||||
HandleHTTPDownloadFail();
|
||||
else
|
||||
DoLoadFiles();
|
||||
}
|
||||
break;
|
||||
case CL_DOWNLOADFILES:
|
||||
// Done downloading files
|
||||
if (!filedownload.remaining)
|
||||
DoLoadFiles();
|
||||
break;
|
||||
case CL_LOADFILES:
|
||||
if (CL_LoadServerFiles())
|
||||
|
@ -839,10 +1096,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
|
|||
if (firstconnectattempttime + NEWTICRATE*300 < I_GetTime() && !server)
|
||||
{
|
||||
CONS_Printf(M_GetText("5 minute wait time exceeded.\n"));
|
||||
CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
|
||||
D_QuitNetGame();
|
||||
CL_Reset();
|
||||
D_StartTitle();
|
||||
AbortConnection();
|
||||
M_StartMessage(M_GetText(
|
||||
"5 minute wait time exceeded.\n"
|
||||
"You may retry connection.\n"
|
||||
|
@ -914,15 +1168,12 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
|
|||
CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
|
||||
M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING);
|
||||
|
||||
Snake_Free(&snake);
|
||||
AbortConnection();
|
||||
|
||||
D_QuitNetGame();
|
||||
CL_Reset();
|
||||
D_StartTitle();
|
||||
memset(gamekeydown, 0, NUMKEYS);
|
||||
return false;
|
||||
}
|
||||
else if (cl_mode == CL_DOWNLOADFILES && snake)
|
||||
else if ((cl_mode == CL_DOWNLOADFILES || cl_mode == CL_DOWNLOADHTTPFILES) && snake)
|
||||
Snake_Update(snake);
|
||||
|
||||
if (client && (cl_mode == CL_DOWNLOADFILES || cl_mode == CL_DOWNLOADSAVEGAME))
|
||||
|
@ -973,7 +1224,7 @@ void CL_ConnectToServer(void)
|
|||
|
||||
sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
|
||||
|
||||
lastfilenum = -1;
|
||||
filedownload.current = -1;
|
||||
|
||||
cl_mode = CL_SEARCHING;
|
||||
|
||||
|
@ -1121,14 +1372,9 @@ void PT_ServerRefuse(SINT8 node)
|
|||
M_StartMessage(va(M_GetText("Server refuses connection\n\nReason:\n%s"),
|
||||
reason), NULL, MM_NOTHING);
|
||||
|
||||
D_QuitNetGame();
|
||||
CL_Reset();
|
||||
D_StartTitle();
|
||||
AbortConnection();
|
||||
|
||||
free(reason);
|
||||
|
||||
// Will be reset by caller. Signals refusal.
|
||||
cl_mode = CL_ABORTED;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2023 by Sonic Team Junior.
|
||||
// Copyright (C) 1999-2024 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
|
@ -36,7 +36,8 @@ typedef enum
|
|||
CL_CONNECTED,
|
||||
CL_ABORTED,
|
||||
CL_ASKFULLFILELIST,
|
||||
CL_CONFIRMCONNECT
|
||||
CL_CONFIRMCONNECT,
|
||||
CL_DOWNLOADHTTPFILES
|
||||
} cl_mode_t;
|
||||
|
||||
extern serverelem_t serverlist[MAXSERVERLIST];
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2023 by Sonic Team Junior.
|
||||
// Copyright (C) 1999-2024 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
|
@ -116,6 +116,8 @@ consvar_t cv_playbackspeed = CVAR_INIT ("playbackspeed", "1", 0, playbackspeed_c
|
|||
consvar_t cv_idletime = CVAR_INIT ("idletime", "0", CV_SAVE, CV_Unsigned, NULL);
|
||||
consvar_t cv_dedicatedidletime = CVAR_INIT ("dedicatedidletime", "10", CV_SAVE, CV_Unsigned, NULL);
|
||||
|
||||
consvar_t cv_httpsource = CVAR_INIT ("http_source", "", CV_SAVE, NULL, NULL);
|
||||
|
||||
void ResetNode(INT32 node)
|
||||
{
|
||||
memset(&netnodes[node], 0, sizeof(*netnodes));
|
||||
|
@ -153,12 +155,15 @@ void CL_Reset(void)
|
|||
FreeFileNeeded();
|
||||
fileneedednum = 0;
|
||||
|
||||
totalfilesrequestednum = 0;
|
||||
totalfilesrequestedsize = 0;
|
||||
firstconnectattempttime = 0;
|
||||
serverisfull = false;
|
||||
connectiontimeout = (tic_t)cv_nettimeout.value; //reset this temporary hack
|
||||
|
||||
filedownload.remaining = 0;
|
||||
filedownload.http_failed = false;
|
||||
filedownload.http_running = false;
|
||||
filedownload.http_source[0] = '\0';
|
||||
|
||||
// D_StartTitle should get done now, but the calling function will handle it
|
||||
}
|
||||
|
||||
|
@ -892,6 +897,74 @@ static void PT_Login(SINT8 node, INT32 netconsole)
|
|||
#endif
|
||||
}
|
||||
|
||||
/** Add a login for HTTP downloads. If the
|
||||
* user/password is missing, remove it.
|
||||
*
|
||||
* \sa Command_list_http_logins
|
||||
*/
|
||||
static void Command_set_http_login (void)
|
||||
{
|
||||
HTTP_login *login;
|
||||
HTTP_login **prev_next;
|
||||
|
||||
if (COM_Argc() < 2)
|
||||
{
|
||||
CONS_Printf(
|
||||
"set_http_login <URL> [user:password]: Set or remove a login to "
|
||||
"authenticate HTTP downloads.\n"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
login = CURLGetLogin(COM_Argv(1), &prev_next);
|
||||
|
||||
if (COM_Argc() == 2)
|
||||
{
|
||||
if (login)
|
||||
{
|
||||
(*prev_next) = login->next;
|
||||
CONS_Printf("Login for '%s' removed.\n", login->url);
|
||||
Z_Free(login);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (login)
|
||||
Z_Free(login->auth);
|
||||
else
|
||||
{
|
||||
login = ZZ_Alloc(sizeof *login);
|
||||
login->url = Z_StrDup(COM_Argv(1));
|
||||
}
|
||||
|
||||
login->auth = Z_StrDup(COM_Argv(2));
|
||||
|
||||
login->next = curl_logins;
|
||||
curl_logins = login;
|
||||
}
|
||||
}
|
||||
|
||||
/** List logins for HTTP downloads.
|
||||
*
|
||||
* \sa Command_set_http_login
|
||||
*/
|
||||
static void Command_list_http_logins (void)
|
||||
{
|
||||
HTTP_login *login;
|
||||
|
||||
for (
|
||||
login = curl_logins;
|
||||
login;
|
||||
login = login->next
|
||||
){
|
||||
CONS_Printf(
|
||||
"'%s' -> '%s'\n",
|
||||
login->url,
|
||||
login->auth
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void PT_AskLuaFile(SINT8 node)
|
||||
{
|
||||
if (server && luafiletransfers && luafiletransfers->nodestatus[node] == LFTNS_ASKED)
|
||||
|
@ -1568,6 +1641,8 @@ void D_ClientServerInit(void)
|
|||
COM_AddCommand("reloadbans", Command_ReloadBan, COM_LUA);
|
||||
COM_AddCommand("connect", Command_connect, COM_LUA);
|
||||
COM_AddCommand("nodes", Command_Nodes, COM_LUA);
|
||||
COM_AddCommand("set_http_login", Command_set_http_login, 0);
|
||||
COM_AddCommand("list_http_logins", Command_list_http_logins, 0);
|
||||
COM_AddCommand("resendgamestate", Command_ResendGamestate, COM_LUA);
|
||||
#ifdef PACKETDROP
|
||||
COM_AddCommand("drop", Command_Drop, COM_LUA);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2023 by Sonic Team Junior.
|
||||
// Copyright (C) 1999-2024 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
|
@ -74,6 +74,7 @@ extern UINT32 playerpingtable[MAXPLAYERS];
|
|||
extern tic_t servermaxping;
|
||||
|
||||
extern consvar_t cv_netticbuffer, cv_resynchattempts, cv_blamecfail, cv_playbackspeed, cv_idletime, cv_dedicatedidletime;
|
||||
extern consvar_t cv_httpsource;
|
||||
|
||||
// Used in d_net, the only dependence
|
||||
void D_ClientServerInit(void);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2023 by Sonic Team Junior.
|
||||
// Copyright (C) 1999-2024 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
|
@ -606,6 +606,7 @@ void D_RegisterServerCommands(void)
|
|||
CV_RegisterVar(&cv_blamecfail);
|
||||
CV_RegisterVar(&cv_dedicatedidletime);
|
||||
CV_RegisterVar(&cv_idletime);
|
||||
CV_RegisterVar(&cv_httpsource);
|
||||
|
||||
COM_AddCommand("ping", Command_Ping_f, COM_LUA);
|
||||
CV_RegisterVar(&cv_nettimeout);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2023 by Sonic Team Junior.
|
||||
// Copyright (C) 1999-2024 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
|
@ -53,6 +53,10 @@
|
|||
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef HAVE_CURL
|
||||
#include <curl/curl.h>
|
||||
#endif
|
||||
|
||||
// Prototypes
|
||||
static boolean AddFileToSendQueue(INT32 node, UINT8 fileid);
|
||||
|
||||
|
@ -104,12 +108,19 @@ typedef struct
|
|||
} pauseddownload_t;
|
||||
static pauseddownload_t *pauseddownload = NULL;
|
||||
|
||||
// for cl loading screen
|
||||
INT32 lastfilenum = -1;
|
||||
INT32 downloadcompletednum = 0;
|
||||
UINT32 downloadcompletedsize = 0;
|
||||
INT32 totalfilesrequestednum = 0;
|
||||
UINT32 totalfilesrequestedsize = 0;
|
||||
file_download_t filedownload;
|
||||
|
||||
static CURL *http_handle;
|
||||
static CURLM *multi_handle;
|
||||
static UINT32 curl_dlnow;
|
||||
static UINT32 curl_dltotal;
|
||||
static time_t curl_starttime;
|
||||
static int curl_runninghandles = 0;
|
||||
static UINT32 curl_origfilesize;
|
||||
static UINT32 curl_origtotalfilesize;
|
||||
static char *curl_realname = NULL;
|
||||
static fileneeded_t *curl_curfile = NULL;
|
||||
HTTP_login *curl_logins;
|
||||
|
||||
luafiletransfer_t *luafiletransfers = NULL;
|
||||
boolean waitingforluafiletransfer = false;
|
||||
|
@ -140,6 +151,13 @@ static UINT16 GetWadNumFromFileNeededId(UINT8 id)
|
|||
return UINT16_MAX;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
WILLSEND_YES,
|
||||
WILLSEND_NO,
|
||||
WILLSEND_TOOLARGE
|
||||
};
|
||||
|
||||
/** Fills a serverinfo packet with information about wad files loaded.
|
||||
*
|
||||
* \todo Give this function a better name since it is in global scope.
|
||||
|
@ -186,9 +204,9 @@ UINT8 *PutFileNeeded(UINT16 firstfile)
|
|||
{
|
||||
// Store in the upper four bits
|
||||
if (!cv_downloading.value)
|
||||
filestatus += (2 << 4); // Won't send
|
||||
filestatus += (WILLSEND_NO << 4); // Won't send
|
||||
else if (wadfiles[i]->filesize <= (UINT32)cv_maxsend.value * 1024)
|
||||
filestatus += (1 << 4); // Will send if requested
|
||||
filestatus += (WILLSEND_YES << 4); // Will send if requested
|
||||
// else
|
||||
// filestatus += (0 << 4); -- Won't send, too big
|
||||
}
|
||||
|
@ -250,6 +268,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 fi
|
|||
fileneeded[i].willsend = (UINT8)(filestatus >> 4);
|
||||
fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size
|
||||
fileneeded[i].file = NULL; // The file isn't open yet
|
||||
fileneeded[i].failed = FDOWNLOAD_FAIL_NONE;
|
||||
READSTRINGN(p, fileneeded[i].filename, MAX_WADPATH); // The next bytes are the file name
|
||||
READMEM(p, fileneeded[i].md5sum, 16); // The last 16 bytes are the file checksum
|
||||
}
|
||||
|
@ -257,7 +276,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 fi
|
|||
|
||||
void CL_PrepareDownloadSaveGame(const char *tmpsave)
|
||||
{
|
||||
lastfilenum = -1;
|
||||
filedownload.current = -1;
|
||||
|
||||
FreeFileNeeded();
|
||||
AllocFileNeeded(1);
|
||||
|
@ -275,86 +294,37 @@ void CL_PrepareDownloadSaveGame(const char *tmpsave)
|
|||
/** Checks the server to see if we CAN download all the files,
|
||||
* before starting to create them and requesting.
|
||||
*
|
||||
* \param direct Game will do a direct download
|
||||
* \return True if we can download all the files
|
||||
*
|
||||
*/
|
||||
boolean CL_CheckDownloadable(void)
|
||||
UINT8 CL_CheckDownloadable(boolean direct)
|
||||
{
|
||||
UINT8 dlstatus = 0;
|
||||
UINT8 dlstatus = DLSTATUS_OK;
|
||||
|
||||
for (UINT8 i = 0; i < fileneedednum; i++)
|
||||
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN)
|
||||
{
|
||||
if (fileneeded[i].folder)
|
||||
{
|
||||
dlstatus = 4;
|
||||
dlstatus = DLSTATUS_FOLDER;
|
||||
break;
|
||||
}
|
||||
|
||||
if (fileneeded[i].willsend == 1)
|
||||
if (!direct || fileneeded[i].willsend == WILLSEND_YES)
|
||||
continue;
|
||||
|
||||
if (fileneeded[i].willsend == 0)
|
||||
dlstatus = 1;
|
||||
else //if (fileneeded[i].willsend == 2)
|
||||
dlstatus = 2;
|
||||
if (fileneeded[i].willsend == WILLSEND_TOOLARGE)
|
||||
dlstatus = DLSTATUS_TOOLARGE;
|
||||
else //if (fileneeded[i].willsend == WILLSEND_NO)
|
||||
dlstatus = DLSTATUS_WONTSEND;
|
||||
}
|
||||
|
||||
// Downloading locally disabled
|
||||
if (!dlstatus && M_CheckParm("-nodownload"))
|
||||
dlstatus = 3;
|
||||
if (direct && !dlstatus && M_CheckParm("-nodownload"))
|
||||
dlstatus = DLSTATUS_NODOWNLOAD;
|
||||
|
||||
if (!dlstatus)
|
||||
return true;
|
||||
|
||||
// not downloadable, put reason in console
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You need additional addons to connect to this server:\n"));
|
||||
|
||||
for (UINT8 i = 0; i < fileneedednum; i++)
|
||||
{
|
||||
if (fileneeded[i].folder || (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN))
|
||||
{
|
||||
CONS_Printf(" * \"%s\" ", fileneeded[i].filename);
|
||||
|
||||
if (fileneeded[i].folder)
|
||||
{
|
||||
CONS_Printf("(folder)");
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf("(%dK)", fileneeded[i].totalsize >> 10);
|
||||
|
||||
if (fileneeded[i].status == FS_NOTFOUND)
|
||||
CONS_Printf(M_GetText(" not found, md5: "));
|
||||
else if (fileneeded[i].status == FS_MD5SUMBAD)
|
||||
CONS_Printf(M_GetText(" wrong version, md5: "));
|
||||
|
||||
char md5tmp[33];
|
||||
for (INT32 j = 0; j < 16; j++)
|
||||
sprintf(&md5tmp[j*2], "%02x", fileneeded[i].md5sum[j]);
|
||||
CONS_Printf("%s", md5tmp);
|
||||
}
|
||||
|
||||
CONS_Printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
switch (dlstatus)
|
||||
{
|
||||
case 1:
|
||||
CONS_Printf(M_GetText("Some addons are larger than the server is willing to send.\n"));
|
||||
break;
|
||||
case 2:
|
||||
CONS_Printf(M_GetText("The server is not allowing download requests.\n"));
|
||||
break;
|
||||
case 3:
|
||||
CONS_Printf(M_GetText("All addons downloadable, but you have chosen to disable addon downloading.\n"));
|
||||
break;
|
||||
case 4:
|
||||
CONS_Printf(M_GetText("One or more addons were added as a folder, which the server cannot send.\n"));
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
return dlstatus;
|
||||
}
|
||||
|
||||
/** Returns true if a needed file transfer can be resumed
|
||||
|
@ -396,23 +366,42 @@ boolean CL_SendFileRequest(void)
|
|||
|
||||
#ifdef PARANOIA
|
||||
if (M_CheckParm("-nodownload"))
|
||||
I_Error("Attempted to download files in -nodownload mode");
|
||||
{
|
||||
CONS_Printf("Attempted to download files in -nodownload mode");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (INT32 i = 0; i < fileneedednum; i++)
|
||||
{
|
||||
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN
|
||||
&& (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2))
|
||||
&& (fileneeded[i].willsend == WILLSEND_TOOLARGE || fileneeded[i].willsend == WILLSEND_NO || fileneeded[i].folder))
|
||||
{
|
||||
I_Error("Attempted to download files that were not sendable");
|
||||
CONS_Printf("Attempted to download files that were not sendable");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)
|
||||
{
|
||||
// Error check for the first time around.
|
||||
totalfreespaceneeded += fileneeded[i].totalsize;
|
||||
}
|
||||
}
|
||||
|
||||
I_GetDiskFreeSpace(&availablefreespace);
|
||||
if (totalfreespaceneeded > availablefreespace)
|
||||
{
|
||||
CONS_Printf("To play on this server you must download %s KB,\n"
|
||||
"but you have only %s KB free space on your device\n",
|
||||
sizeu1((size_t)(totalfreespaceneeded>>10)), sizeu2((size_t)(availablefreespace>>10)));
|
||||
return false;
|
||||
}
|
||||
|
||||
netbuffer->packettype = PT_REQUESTFILE;
|
||||
p = (char *)netbuffer->u.textcmd;
|
||||
for (INT32 i = 0; i < fileneedednum; i++)
|
||||
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)
|
||||
{
|
||||
totalfreespaceneeded += fileneeded[i].totalsize;
|
||||
|
||||
WRITEUINT8(p, i); // fileid
|
||||
|
||||
// put it in download dir
|
||||
|
@ -424,15 +413,16 @@ boolean CL_SendFileRequest(void)
|
|||
|
||||
WRITEUINT8(p, 0xFF);
|
||||
|
||||
I_GetDiskFreeSpace(&availablefreespace);
|
||||
if (totalfreespaceneeded > availablefreespace)
|
||||
I_Error("To play on this server you must download %s KB,\n"
|
||||
"but you have only %s KB free space on this drive\n",
|
||||
sizeu1((size_t)(totalfreespaceneeded>>10)), sizeu2((size_t)(availablefreespace>>10)));
|
||||
if (!HSendPacket(servernode, true, 0, p - (char *)netbuffer->u.textcmd))
|
||||
{
|
||||
CONS_Printf("Could not send download request packet to server\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// prepare to download
|
||||
I_mkdir(downloaddir, 0755);
|
||||
return HSendPacket(servernode, true, 0, p - (char *)netbuffer->u.textcmd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// get request filepak and put it on the send queue
|
||||
|
@ -514,7 +504,7 @@ INT32 CL_CheckFiles(void)
|
|||
|
||||
for (i = 0; i < fileneedednum; i++)
|
||||
{
|
||||
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)
|
||||
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD || fileneeded[i].status == FS_FALLBACK)
|
||||
downloadrequired = true;
|
||||
|
||||
if (fileneeded[i].status != FS_OPEN)
|
||||
|
@ -932,8 +922,6 @@ boolean AddLuaFileToSendQueue(INT32 node, const char *filename)
|
|||
{
|
||||
filetx_t **q; // A pointer to the "next" field of the last file in the list
|
||||
filetx_t *p; // The new file request
|
||||
//INT32 i;
|
||||
//char wadfilename[MAX_WADPATH];
|
||||
|
||||
luafiletransfers->nodestatus[node] = LFTNS_SENDING;
|
||||
|
||||
|
@ -1306,6 +1294,21 @@ void FileReceiveTicker(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void OpenNewFileForDownload(fileneeded_t *file, const char *filename)
|
||||
{
|
||||
file->file = fopen(filename, "wb");
|
||||
if (!file->file)
|
||||
I_Error("Can't create file %s: %s", filename, strerror(errno));
|
||||
|
||||
file->currentsize = 0;
|
||||
file->totalsize = LONG(netbuffer->u.filetxpak.filesize);
|
||||
file->ackresendposition = UINT32_MAX; // Only used for resumed downloads
|
||||
|
||||
file->receivedfragments = calloc(file->totalsize / file->fragmentsize + 1, sizeof(*file->receivedfragments));
|
||||
if (!file->receivedfragments)
|
||||
I_Error("FileSendTicker: No more memory\n");
|
||||
}
|
||||
|
||||
void PT_FileFragment(SINT8 node, INT32 netconsole)
|
||||
{
|
||||
if (netnodes[node].ingame)
|
||||
|
@ -1348,8 +1351,6 @@ void PT_FileFragment(SINT8 node, INT32 netconsole)
|
|||
))
|
||||
I_Error("Tried to download \"%s\"", filename);
|
||||
|
||||
filename = file->filename;
|
||||
|
||||
if (filenum >= fileneedednum)
|
||||
{
|
||||
DEBFILE(va("fileframent not needed %d>%d\n", filenum, fileneedednum));
|
||||
|
@ -1372,15 +1373,24 @@ void PT_FileFragment(SINT8 node, INT32 netconsole)
|
|||
|
||||
if (CL_CanResumeDownload(file))
|
||||
{
|
||||
file->file = fopen(filename, "r+b");
|
||||
file->file = fopen(file->filename, "r+b");
|
||||
if (!file->file)
|
||||
I_Error("Can't reopen file %s: %s", filename, strerror(errno));
|
||||
CONS_Printf("\r%s...\n", filename);
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Couldn't reopen file %s: %s\n", file->filename, strerror(errno));
|
||||
|
||||
CONS_Printf("Resuming download...\n");
|
||||
file->currentsize = pauseddownload->currentsize;
|
||||
file->receivedfragments = pauseddownload->receivedfragments;
|
||||
file->ackresendposition = 0;
|
||||
free(pauseddownload->receivedfragments);
|
||||
|
||||
CONS_Printf("Restarting download of addon \"%s\"...\n", filename);
|
||||
|
||||
OpenNewFileForDownload(file, file->filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf("Resuming download of addon \"%s\"...\n", filename);
|
||||
file->currentsize = pauseddownload->currentsize;
|
||||
file->receivedfragments = pauseddownload->receivedfragments;
|
||||
file->ackresendposition = 0;
|
||||
}
|
||||
|
||||
free(pauseddownload);
|
||||
pauseddownload = NULL;
|
||||
|
@ -1388,20 +1398,8 @@ void PT_FileFragment(SINT8 node, INT32 netconsole)
|
|||
else
|
||||
{
|
||||
CL_AbortDownloadResume();
|
||||
|
||||
file->file = fopen(filename, "wb");
|
||||
if (!file->file)
|
||||
I_Error("Can't create file %s: %s", filename, strerror(errno));
|
||||
|
||||
CONS_Printf("\r%s...\n",filename);
|
||||
|
||||
file->currentsize = 0;
|
||||
file->totalsize = LONG(netbuffer->u.filetxpak.filesize);
|
||||
file->ackresendposition = UINT32_MAX; // Only used for resumed downloads
|
||||
|
||||
file->receivedfragments = calloc(file->totalsize / fragmentsize + 1, sizeof(*file->receivedfragments));
|
||||
if (!file->receivedfragments)
|
||||
I_Error("FileSendTicker: No more memory\n");
|
||||
OpenNewFileForDownload(file, file->filename);
|
||||
CONS_Printf("Downloading addon \"%s\" from the server...\n", filename);
|
||||
}
|
||||
|
||||
lasttimeackpacketsent = I_GetTime();
|
||||
|
@ -1421,7 +1419,7 @@ void PT_FileFragment(SINT8 node, INT32 netconsole)
|
|||
// We can receive packets in the wrong order, anyway all OSes support gaped files
|
||||
fseek(file->file, fragmentpos, SEEK_SET);
|
||||
if (fragmentsize && fwrite(netbuffer->u.filetxpak.data, boundedfragmentsize, 1, file->file) != 1)
|
||||
I_Error("Can't write to %s: %s\n",filename, M_FileError(file->file));
|
||||
I_Error("Can't write to %s: %s\n",file->filename, M_FileError(file->file));
|
||||
file->currentsize += boundedfragmentsize;
|
||||
|
||||
AddFragmentToAckPacket(file->ackpacket, file->iteration, fragmentpos / fragmentsize, filenum);
|
||||
|
@ -1435,8 +1433,6 @@ void PT_FileFragment(SINT8 node, INT32 netconsole)
|
|||
free(file->ackpacket);
|
||||
file->status = FS_FOUND;
|
||||
file->justdownloaded = true;
|
||||
CONS_Printf(M_GetText("Downloading %s...(done)\n"),
|
||||
filename);
|
||||
|
||||
// Tell the server we have received the file
|
||||
netbuffer->packettype = PT_FILERECEIVED;
|
||||
|
@ -1449,6 +1445,16 @@ void PT_FileFragment(SINT8 node, INT32 netconsole)
|
|||
netbuffer->packettype = PT_HASLUAFILE;
|
||||
HSendPacket(servernode, true, 0, 0);
|
||||
FreeFileNeeded();
|
||||
|
||||
CONS_Printf(M_GetText("Downloaded \"%s\"\n"), filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
filedownload.completednum++;
|
||||
filedownload.completedsize += file->totalsize;
|
||||
filedownload.remaining--;
|
||||
|
||||
CONS_Printf(M_GetText("Finished download of addon \"%s\"\n"), filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1483,7 +1489,7 @@ void PT_FileFragment(SINT8 node, INT32 netconsole)
|
|||
I_Error("Received a file not requested (file id: %d, file status: %s)\n", filenum, s);
|
||||
}
|
||||
|
||||
lastfilenum = filenum;
|
||||
filedownload.current = filenum;
|
||||
}
|
||||
|
||||
/** \brief Checks if a node is downloading a file
|
||||
|
@ -1581,6 +1587,220 @@ void Command_Downloads_f(void)
|
|||
}
|
||||
}
|
||||
|
||||
static size_t curlwrite_data(void *ptr, size_t size, size_t nmemb, FILE *stream)
|
||||
{
|
||||
return fwrite(ptr, size, nmemb, stream);
|
||||
}
|
||||
|
||||
static int curlprogress_callback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
|
||||
{
|
||||
(void)clientp;
|
||||
(void)ultotal;
|
||||
(void)ulnow; // Function prototype requires these but we won't use, so just discard
|
||||
curl_dlnow = (UINT32)dlnow;
|
||||
curl_dltotal = (UINT32)dltotal;
|
||||
getbytes = ((double)dlnow) / (time(NULL) - curl_starttime); // To-do: Make this more accurate???
|
||||
return 0;
|
||||
}
|
||||
|
||||
boolean CURLPrepareFile(const char* url, int dfilenum)
|
||||
{
|
||||
HTTP_login *login;
|
||||
|
||||
#ifdef PARANOIA
|
||||
if (M_CheckParm("-nodownload"))
|
||||
I_Error("Attempted to download files in -nodownload mode");
|
||||
#endif
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
http_handle = curl_easy_init();
|
||||
multi_handle = curl_multi_init();
|
||||
|
||||
if (http_handle && multi_handle)
|
||||
{
|
||||
I_mkdir(downloaddir, 0755);
|
||||
|
||||
curl_curfile = &fileneeded[dfilenum];
|
||||
curl_realname = curl_curfile->filename;
|
||||
nameonly(curl_realname);
|
||||
|
||||
curl_origfilesize = curl_curfile->currentsize;
|
||||
curl_origtotalfilesize = curl_curfile->totalsize;
|
||||
|
||||
char md5tmp[33];
|
||||
for (INT32 j = 0; j < 16; j++)
|
||||
sprintf(&md5tmp[j*2], "%02x", curl_curfile->md5sum[j]);
|
||||
|
||||
curl_easy_setopt(http_handle, CURLOPT_URL, va("%s/%s?md5=%s", url, curl_realname, md5tmp));
|
||||
|
||||
// Only allow HTTP and HTTPS
|
||||
curl_easy_setopt(http_handle, CURLOPT_PROTOCOLS_STR, "http,https");
|
||||
|
||||
// Set user agent, as some servers won't accept invalid user agents.
|
||||
curl_easy_setopt(http_handle, CURLOPT_USERAGENT, va("Sonic Robo Blast 2/v%d.%d", VERSION, SUBVERSION));
|
||||
|
||||
// Authenticate if the user so wishes
|
||||
login = CURLGetLogin(url, NULL);
|
||||
|
||||
if (login)
|
||||
{
|
||||
curl_easy_setopt(http_handle, CURLOPT_USERPWD, login->auth);
|
||||
}
|
||||
|
||||
// Follow a redirect request, if sent by the server.
|
||||
curl_easy_setopt(http_handle, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
|
||||
curl_easy_setopt(http_handle, CURLOPT_FAILONERROR, 1L);
|
||||
|
||||
CONS_Printf("Downloading addon \"%s\" from %s\n", curl_realname, url);
|
||||
|
||||
strcatbf(curl_curfile->filename, downloaddir, "/");
|
||||
curl_curfile->file = fopen(curl_curfile->filename, "wb");
|
||||
curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, curl_curfile->file);
|
||||
curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, curlwrite_data);
|
||||
curl_easy_setopt(http_handle, CURLOPT_NOPROGRESS, 0L);
|
||||
curl_easy_setopt(http_handle, CURLOPT_XFERINFOFUNCTION, curlprogress_callback);
|
||||
|
||||
curl_curfile->status = FS_DOWNLOADING;
|
||||
curl_multi_add_handle(multi_handle, http_handle);
|
||||
|
||||
curl_multi_perform(multi_handle, &curl_runninghandles);
|
||||
curl_starttime = time(NULL);
|
||||
|
||||
filedownload.current = dfilenum;
|
||||
filedownload.http_running = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
filedownload.http_running = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CURLGetFile(void)
|
||||
{
|
||||
CURLMcode mc; /* return code used by curl_multi_wait() */
|
||||
CURLcode easyres; /* Return from easy interface */
|
||||
int numfds;
|
||||
CURLMsg *m; /* for picking up messages with the transfer status */
|
||||
CURL *e;
|
||||
int msgs_left; /* how many messages are left */
|
||||
const char *easy_handle_error;
|
||||
|
||||
if (curl_runninghandles)
|
||||
{
|
||||
curl_multi_perform(multi_handle, &curl_runninghandles);
|
||||
|
||||
/* wait for activity, timeout or "nothing" */
|
||||
mc = curl_multi_wait(multi_handle, NULL, 0, 1000, &numfds);
|
||||
|
||||
if (mc != CURLM_OK)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "curl_multi_wait() failed, code %d.\n", mc);
|
||||
return;
|
||||
}
|
||||
curl_curfile->currentsize = curl_dlnow;
|
||||
curl_curfile->totalsize = curl_dltotal;
|
||||
}
|
||||
|
||||
/* See how the transfers went */
|
||||
while ((m = curl_multi_info_read(multi_handle, &msgs_left)))
|
||||
{
|
||||
if (m && (m->msg == CURLMSG_DONE))
|
||||
{
|
||||
e = m->easy_handle;
|
||||
easyres = m->data.result;
|
||||
|
||||
char *filename = Z_StrDup(curl_realname);
|
||||
nameonly(filename);
|
||||
|
||||
if (easyres != CURLE_OK)
|
||||
{
|
||||
long response_code = 0;
|
||||
|
||||
if (easyres == CURLE_HTTP_RETURNED_ERROR)
|
||||
curl_easy_getinfo(e, CURLINFO_RESPONSE_CODE, &response_code);
|
||||
|
||||
if (response_code == 404)
|
||||
curl_curfile->failed = FDOWNLOAD_FAIL_NOTFOUND;
|
||||
else
|
||||
curl_curfile->failed = FDOWNLOAD_FAIL_OTHER;
|
||||
|
||||
easy_handle_error = (response_code) ? va("HTTP response code %ld", response_code) : curl_easy_strerror(easyres);
|
||||
curl_curfile->status = FS_FALLBACK;
|
||||
curl_curfile->currentsize = curl_origfilesize;
|
||||
curl_curfile->totalsize = curl_origtotalfilesize;
|
||||
filedownload.http_failed = true;
|
||||
fclose(curl_curfile->file);
|
||||
remove(curl_curfile->filename);
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Failed to download addon \"%s\" (%s)\n"), filename, easy_handle_error);
|
||||
}
|
||||
else
|
||||
{
|
||||
fclose(curl_curfile->file);
|
||||
|
||||
CONS_Printf(M_GetText("Finished download of addon \"%s\"\n"), filename);
|
||||
|
||||
if (checkfilemd5(curl_curfile->filename, curl_curfile->md5sum) == FS_MD5SUMBAD)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("File \"%s\" does not match the version used by the server\n"), filename);
|
||||
curl_curfile->status = FS_FALLBACK;
|
||||
curl_curfile->failed = FDOWNLOAD_FAIL_MD5SUMBAD;
|
||||
filedownload.http_failed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
filedownload.completednum++;
|
||||
filedownload.completedsize += curl_curfile->totalsize;
|
||||
curl_curfile->status = FS_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
Z_Free(filename);
|
||||
|
||||
curl_curfile->file = NULL;
|
||||
filedownload.http_running = false;
|
||||
filedownload.remaining--;
|
||||
curl_multi_remove_handle(multi_handle, e);
|
||||
curl_easy_cleanup(e);
|
||||
|
||||
if (!filedownload.remaining)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!filedownload.remaining)
|
||||
{
|
||||
curl_multi_cleanup(multi_handle);
|
||||
curl_global_cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
HTTP_login *
|
||||
CURLGetLogin (const char *url, HTTP_login ***return_prev_next)
|
||||
{
|
||||
HTTP_login * login;
|
||||
HTTP_login ** prev_next;
|
||||
|
||||
for (
|
||||
prev_next = &curl_logins;
|
||||
( login = (*prev_next));
|
||||
prev_next = &login->next
|
||||
){
|
||||
if (strcmp(login->url, url) == 0)
|
||||
{
|
||||
if (return_prev_next)
|
||||
(*return_prev_next) = prev_next;
|
||||
|
||||
return login;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Functions cut and pasted from Doomatic :)
|
||||
|
||||
void nameonly(char *s)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2023 by Sonic Team Junior.
|
||||
// Copyright (C) 1999-2024 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
|
@ -25,6 +25,23 @@ typedef enum
|
|||
SF_NOFREERAM
|
||||
} freemethod_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DLSTATUS_OK,
|
||||
DLSTATUS_TOOLARGE,
|
||||
DLSTATUS_WONTSEND,
|
||||
DLSTATUS_NODOWNLOAD,
|
||||
DLSTATUS_FOLDER
|
||||
} dlstatus_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FDOWNLOAD_FAIL_NONE,
|
||||
FDOWNLOAD_FAIL_NOTFOUND,
|
||||
FDOWNLOAD_FAIL_MD5SUMBAD,
|
||||
FDOWNLOAD_FAIL_OTHER
|
||||
} filedownloadfail_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FS_NOTCHECKED,
|
||||
|
@ -33,7 +50,8 @@ typedef enum
|
|||
FS_REQUESTED,
|
||||
FS_DOWNLOADING,
|
||||
FS_OPEN, // Is opened and used in w_wad
|
||||
FS_MD5SUMBAD
|
||||
FS_MD5SUMBAD,
|
||||
FS_FALLBACK
|
||||
} filestatus_t;
|
||||
|
||||
typedef enum
|
||||
|
@ -51,6 +69,7 @@ typedef struct
|
|||
UINT8 willsend; // Is the server willing to send it?
|
||||
UINT8 folder; // File is a folder
|
||||
fileneededtype_t type;
|
||||
filedownloadfail_t failed;
|
||||
boolean justdownloaded; // To prevent late fragments from causing an I_Error
|
||||
|
||||
// Used only for download
|
||||
|
@ -70,11 +89,30 @@ extern INT32 fileneedednum;
|
|||
extern fileneeded_t *fileneeded;
|
||||
extern char downloaddir[512];
|
||||
|
||||
extern INT32 lastfilenum;
|
||||
extern INT32 downloadcompletednum;
|
||||
extern UINT32 downloadcompletedsize;
|
||||
extern INT32 totalfilesrequestednum;
|
||||
extern UINT32 totalfilesrequestedsize;
|
||||
typedef struct
|
||||
{
|
||||
INT32 current;
|
||||
INT32 remaining;
|
||||
INT32 completednum;
|
||||
UINT32 completedsize;
|
||||
|
||||
boolean http_failed;
|
||||
boolean http_running;
|
||||
|
||||
char http_source[MAX_MIRROR_LENGTH];
|
||||
} file_download_t;
|
||||
|
||||
extern file_download_t filedownload;
|
||||
|
||||
typedef struct HTTP_login HTTP_login;
|
||||
|
||||
extern struct HTTP_login
|
||||
{
|
||||
char * url;
|
||||
char * auth;
|
||||
HTTP_login * next;
|
||||
}
|
||||
*curl_logins;
|
||||
|
||||
extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed;
|
||||
|
||||
|
@ -97,10 +135,14 @@ boolean SendingFile(INT32 node);
|
|||
void FileReceiveTicker(void);
|
||||
void PT_FileFragment(SINT8 node, INT32 netconsole);
|
||||
|
||||
boolean CL_CheckDownloadable(void);
|
||||
UINT8 CL_CheckDownloadable(boolean direct);
|
||||
boolean CL_SendFileRequest(void);
|
||||
void PT_RequestFile(SINT8 node);
|
||||
|
||||
boolean CURLPrepareFile(const char* url, int dfilenum);
|
||||
void CURLGetFile(void);
|
||||
HTTP_login * CURLGetLogin (const char *url, HTTP_login ***return_prev_next);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LFTNS_NONE, // This node is not connected
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2023 by Sonic Team Junior.
|
||||
// Copyright (C) 1999-2024 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
|
@ -26,7 +26,7 @@ packet versions.
|
|||
If you change the struct or the meaning of a field
|
||||
therein, increment this number.
|
||||
*/
|
||||
#define PACKETVERSION 4
|
||||
#define PACKETVERSION 5
|
||||
|
||||
// Network play related stuff.
|
||||
// There is a data struct that stores network
|
||||
|
@ -200,6 +200,7 @@ enum {
|
|||
|
||||
#define MAXSERVERNAME 32
|
||||
#define MAXFILENEEDED 915
|
||||
#define MAX_MIRROR_LENGTH 256
|
||||
|
||||
// This packet is too large
|
||||
typedef struct
|
||||
|
@ -230,6 +231,7 @@ typedef struct
|
|||
unsigned char mapmd5[16];
|
||||
UINT8 actnum;
|
||||
UINT8 iszone;
|
||||
char httpsource[MAX_MIRROR_LENGTH];
|
||||
UINT8 fileneeded[MAXFILENEEDED]; // is filled with writexxx (byteptr.h)
|
||||
} ATTRPACK serverinfo_pak;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2023 by Sonic Team Junior.
|
||||
// Copyright (C) 1999-2024 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
|
@ -127,6 +127,8 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
|
|||
|
||||
memset(netbuffer->u.serverinfo.maptitle, 0, sizeof netbuffer->u.serverinfo.maptitle);
|
||||
|
||||
memset(netbuffer->u.serverinfo.httpsource, 0, MAX_MIRROR_LENGTH);
|
||||
|
||||
if (mapheaderinfo[gamemap-1] && *mapheaderinfo[gamemap-1]->lvlttl)
|
||||
{
|
||||
char *read = mapheaderinfo[gamemap-1]->lvlttl, *writ = netbuffer->u.serverinfo.maptitle;
|
||||
|
@ -153,6 +155,17 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
|
|||
if (mapheaderinfo[gamemap-1])
|
||||
netbuffer->u.serverinfo.actnum = mapheaderinfo[gamemap-1]->actnum;
|
||||
|
||||
const char *httpurl = cv_httpsource.string;
|
||||
size_t mirror_length = strlen(httpurl);
|
||||
if (mirror_length > MAX_MIRROR_LENGTH)
|
||||
mirror_length = MAX_MIRROR_LENGTH;
|
||||
|
||||
if (snprintf(netbuffer->u.serverinfo.httpsource, mirror_length+1, "%s", httpurl) < 0)
|
||||
// If there's an encoding error, send nothing, we accept that the above may be truncated
|
||||
strncpy(netbuffer->u.serverinfo.httpsource, "", mirror_length);
|
||||
|
||||
netbuffer->u.serverinfo.httpsource[MAX_MIRROR_LENGTH-1] = '\0';
|
||||
|
||||
p = PutFileNeeded(0);
|
||||
|
||||
HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u));
|
||||
|
|
Loading…
Reference in a new issue