From aecc97ded33bbfd7e8e62aca333398a14b3c06d5 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 26 May 2017 13:39:54 +0100 Subject: [PATCH] PT_REQUESTFILE checking: * if you sent it to a client rather than the server, game over, your connection is closed * if files that don't exist or are too large are requested are listed, game over, your connection is closed (they should have been checked on YOUR side beforehand, silly) * if the server has downloading disabled anyway, ...yeah, you get the idea Don't worry, I made sure Got_RequestFilePak cleaned up the full file request list for the node in case of failure --- src/d_clisrv.c | 7 +++++- src/d_netfil.c | 64 +++++++++++++++++++++++++++++++++++++++++++++----- src/d_netfil.h | 2 +- 3 files changed, 65 insertions(+), 8 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index c095d38a..2fc895c2 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -3553,7 +3553,12 @@ static void HandlePacketFromAwayNode(SINT8 node) case PT_REQUESTFILE: if (server) - Got_RequestFilePak(node); + { + if (!cv_downloading.value || !Got_RequestFilePak(node)) + Net_CloseConnection(node); // close connection if one of the requested files could not be sent, or you disabled downloading anyway + } + else + Net_CloseConnection(node); // nope break; case PT_NODETIMEOUT: diff --git a/src/d_netfil.c b/src/d_netfil.c index bf4e5987..777814ce 100644 --- a/src/d_netfil.c +++ b/src/d_netfil.c @@ -62,7 +62,9 @@ #include -static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid); +// Prototypes +static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid); +static void SV_RemoveFileSendList(INT32 node); // Sender structure typedef struct filetx_s @@ -303,7 +305,8 @@ boolean CL_SendRequestFile(void) } // get request filepak and put it on the send queue -void Got_RequestFilePak(INT32 node) +// returns false if a requested file was not found or cannot be sent +boolean Got_RequestFilePak(INT32 node) { char wad[MAX_WADPATH+1]; UINT8 *p = netbuffer->u.textcmd; @@ -314,8 +317,13 @@ void Got_RequestFilePak(INT32 node) if (id == 0xFF) break; READSTRINGN(p, wad, MAX_WADPATH); - SV_SendFile(node, wad, id); + if (!SV_SendFile(node, wad, id)) + { + SV_RemoveFileSendList(node); + return false; // don't read the rest of the files + } } + return true; // no problems with any files } /** Checks if the files needed aren't already loaded or on the disk @@ -480,7 +488,7 @@ static INT32 filestosend = 0; * \sa SV_SendRam * */ -static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid) +static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid) { filetx_t **q; // A pointer to the "next" field of the last file in the list filetx_t *p; // The new file request @@ -537,7 +545,7 @@ static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid) free(p->id.filename); free(p); *q = NULL; - return; + return false; // cancel the rest of the requests } // Handle huge file requests (i.e. bigger than cv_maxsend.value KB) @@ -549,7 +557,7 @@ static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid) free(p->id.filename); free(p); *q = NULL; - return; + return false; // cancel the rest of the requests } DEBFILE(va("Sending file %s (id=%d) to %d\n", filename, fileid, node)); @@ -557,6 +565,7 @@ static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid) p->fileid = fileid; p->next = NULL; // End of list filestosend++; + return true; } /** Adds a memory block to the file list for a node @@ -598,6 +607,49 @@ void SV_SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod, UI filestosend++; } +/** Removes all file requests for a node + * This is needed only if a PT_REQUESTFILE's content gave you something that shouldn't be there + * + * \param node The destination + * \sa Got_RequestFilePak + * + */ +static void SV_RemoveFileSendList(INT32 node) +{ + filetx_t *p = transfer[node].txlist; + + if (p == NULL) + return; // ...well, that was easy + + while (p) + { + // Free the file request according to the freemethod parameter used with SV_SendFile/Ram + switch (p->ram) + { + case SF_FILE: // It's a file, close it and free its filename + if (cv_noticedownload.value) + CONS_Printf("Cancelling file transfer for node %d\n", node); + if (transfer[node].currentfile) + fclose(transfer[node].currentfile); + free(p->id.filename); + break; + case SF_Z_RAM: // It's a memory block allocated with Z_Alloc or the likes, use Z_Free + Z_Free(p->id.ram); + break; + case SF_RAM: // It's a memory block allocated with malloc, use free + free(p->id.ram); + case SF_NOFREERAM: // Nothing to free + break; + } + // Remove the file request from the list + transfer[node].txlist = p->next; + free(p); + // Indicate that the transmission is over (if for some reason it had started) + transfer[node].currentfile = NULL; + filestosend--; + } +} + /** Stops sending a file for a node, and removes the file request from the list, * either because the file has been fully sent or because the node was disconnected * diff --git a/src/d_netfil.h b/src/d_netfil.h index c9085a5b..b9b7b2f2 100644 --- a/src/d_netfil.h +++ b/src/d_netfil.h @@ -69,7 +69,7 @@ boolean SV_SendingFile(INT32 node); boolean CL_CheckDownloadable(void); boolean CL_SendRequestFile(void); -void Got_RequestFilePak(INT32 node); +boolean Got_RequestFilePak(INT32 node); void SV_AbortSendFiles(INT32 node); void CloseNetFile(void);