Merge branch 'no-multi-fopen' into 'master'

Prevent multiple nodes fopen-ing the same file

See merge request KartKrew/Kart-Public!326
This commit is contained in:
Sal 2022-12-20 10:06:14 +00:00
commit e8dee82341

View file

@ -94,10 +94,20 @@ typedef struct filetran_s
{ {
filetx_t *txlist; // Linked list of all files for the node filetx_t *txlist; // Linked list of all files for the node
UINT32 position; // The current position in the file UINT32 position; // The current position in the file
FILE *currentfile; // The file currently being sent/received boolean init; // false if we want to reset position / open a new file
} filetran_t; } filetran_t;
static filetran_t transfer[MAXNETNODES]; static filetran_t transfer[MAXNETNODES];
// The files currently being sent/received
typedef struct fileused_s
{
FILE *file;
UINT8 count;
UINT32 position;
} fileused_t;
static fileused_t transferFiles[UINT8_MAX + 1];
// Read time of file: stat _stmtime // Read time of file: stat _stmtime
// Write time of file: utime // Write time of file: utime
@ -760,8 +770,19 @@ static void SV_EndFileSend(INT32 node)
case SF_FILE: // It's a file, close it and free its filename case SF_FILE: // It's a file, close it and free its filename
if (cv_noticedownload.value) if (cv_noticedownload.value)
CONS_Printf("Ending file transfer (id %d) for node %d\n", p->fileid, node); CONS_Printf("Ending file transfer (id %d) for node %d\n", p->fileid, node);
if (transfer[node].currentfile) if (transferFiles[p->fileid].file)
fclose(transfer[node].currentfile); {
if (transferFiles[p->fileid].count > 0)
{
transferFiles[p->fileid].count--;
}
if (transferFiles[p->fileid].count == 0)
{
fclose(transferFiles[p->fileid].file);
transferFiles[p->fileid].file = NULL;
}
}
free(p->id.filename); free(p->id.filename);
break; break;
case SF_Z_RAM: // It's a memory block allocated with Z_Alloc or the likes, use Z_Free case SF_Z_RAM: // It's a memory block allocated with Z_Alloc or the likes, use Z_Free
@ -778,7 +799,7 @@ static void SV_EndFileSend(INT32 node)
free(p); free(p);
// Indicate that the transmission is over // Indicate that the transmission is over
transfer[node].currentfile = NULL; transfer[node].init = false;
filestosend--; filestosend--;
} }
@ -842,21 +863,31 @@ void SV_FileSendTicker(void)
ram = f->ram; ram = f->ram;
// Open the file if it isn't open yet, or // Open the file if it isn't open yet, or
if (!transfer[i].currentfile) if (transfer[i].init == false)
{ {
if (!ram) // Sending a file if (!ram) // Sending a file
{ {
long filesize; long filesize;
transfer[i].currentfile = if (transferFiles[f->fileid].count == 0)
{
// It needs opened.
transferFiles[f->fileid].file =
fopen(f->id.filename, "rb"); fopen(f->id.filename, "rb");
if (!transfer[i].currentfile) if (!transferFiles[f->fileid].file)
I_Error("File %s does not exist", {
f->id.filename); I_Error("Can't open file %s: %s",
f->id.filename, strerror(errno));
}
}
fseek(transfer[i].currentfile, 0, SEEK_END); // Increment number of nodes using this file.
filesize = ftell(transfer[i].currentfile); I_Assert(transferFiles[f->fileid].count < UINT8_MAX);
transferFiles[f->fileid].count++;
fseek(transferFiles[f->fileid].file, 0, SEEK_END);
filesize = ftell(transferFiles[f->fileid].file);
// Nobody wants to transfer a file bigger // Nobody wants to transfer a file bigger
// than 4GB! // than 4GB!
@ -865,23 +896,43 @@ void SV_FileSendTicker(void)
if (filesize == -1) if (filesize == -1)
I_Error("Error getting filesize of %s", f->id.filename); I_Error("Error getting filesize of %s", f->id.filename);
f->size = (UINT32)filesize; f->size = transferFiles[f->fileid].position = (UINT32)filesize;
fseek(transfer[i].currentfile, 0, SEEK_SET);
} }
else // Sending RAM
transfer[i].currentfile = (FILE *)1; // Set currentfile to a non-null value to indicate that it is open
transfer[i].position = 0; transfer[i].position = 0;
transfer[i].init = true; // Indicate that it is open
}
if (!ram)
{
// Seek to the right position if we aren't already there.
if (transferFiles[f->fileid].position != transfer[i].position)
{
fseek(transferFiles[f->fileid].file, transfer[i].position, SEEK_SET);
}
} }
// Build a packet containing a file fragment // Build a packet containing a file fragment
p = &netbuffer->u.filetxpak; p = &netbuffer->u.filetxpak;
size = software_MAXPACKETLENGTH - (FILETXHEADER + BASEPACKETSIZE); size = software_MAXPACKETLENGTH - (FILETXHEADER + BASEPACKETSIZE);
if (f->size-transfer[i].position < size)
size = f->size-transfer[i].position; if (f->size - transfer[i].position < size)
{
size = f->size - transfer[i].position;
}
if (ram) if (ram)
{
M_Memcpy(p->data, &f->id.ram[transfer[i].position], size); M_Memcpy(p->data, &f->id.ram[transfer[i].position], size);
else if (fread(p->data, 1, size, transfer[i].currentfile) != size) }
I_Error("SV_FileSendTicker: can't read %s byte on %s at %d because %s", sizeu1(size), f->id.filename, transfer[i].position, M_FileError(transfer[i].currentfile)); else if (fread(p->data, 1, size, transferFiles[f->fileid].file) != size)
{
I_Error("SV_FileSendTicker: can't read %s byte on %s at %d because %s",
sizeu1(size), f->id.filename, transfer[i].position, M_FileError(transferFiles[f->fileid].file));
transferFiles[f->fileid].position = (UINT32)(transferFiles[f->fileid].position + size);
}
p->position = LONG(transfer[i].position); p->position = LONG(transfer[i].position);
// Put flag so receiver knows the total size // Put flag so receiver knows the total size
if (transfer[i].position + size == f->size) if (transfer[i].position + size == f->size)
@ -891,15 +942,18 @@ void SV_FileSendTicker(void)
// Send the packet // Send the packet
if (HSendPacket(i, true, 0, FILETXHEADER + size)) // Reliable SEND if (HSendPacket(i, true, 0, FILETXHEADER + size)) // Reliable SEND
{ // Success {
// Success
transfer[i].position = (UINT32)(transfer[i].position + size); transfer[i].position = (UINT32)(transfer[i].position + size);
if (transfer[i].position == f->size) // Finish? if (transfer[i].position == f->size) // Finish?
{
SV_EndFileSend(i); SV_EndFileSend(i);
} }
}
else else
{ // Not sent for some odd reason, retry at next call {
if (!ram) // Not sent for some odd reason, retry at next call
fseek(transfer[i].currentfile,transfer[i].position, SEEK_SET);
// Exit the while (can't send this one so why should i send the next?) // Exit the while (can't send this one so why should i send the next?)
break; break;
} }