/* ============================== Netchan_CreateFragments_ ============================== */ void Netchan_CreateFragments_( qboolean server, netchan_t *chan, sizebuf_t *msg ) { fragbuf_t *buf; int chunksize; int send, pos; int remaining; int bufferid = 1; fragbufwaiting_t *wait, *p; if( BF_GetNumBytesWritten( msg ) == 0 ) return; chunksize = bound( 16, net_blocksize->integer, 1400 ); wait = (fragbufwaiting_t *)Mem_Alloc( net_mempool, sizeof( fragbufwaiting_t )); remaining = BF_GetNumBytesWritten( msg ); pos = 0; while( remaining > 0 ) { send = min( remaining, chunksize ); remaining -= send; buf = Netchan_AllocFragbuf(); buf->bufferid = bufferid++; // Copy in data BF_Clear( &buf->frag_message ); BF_WriteBits( &buf->frag_message, msg->pData + pos, send << 3 ); pos += send; Netchan_AddFragbufToTail( wait, buf ); } // now add waiting list item to end of buffer queue if( !chan->waitlist[FRAG_NORMAL_STREAM] ) { chan->waitlist[FRAG_NORMAL_STREAM] = wait; } else { p = chan->waitlist[FRAG_NORMAL_STREAM]; while( p->next ) { p = p->next; } p->next = wait; } }
fragbuf_t *Netchan_FindBufferById(fragbuf_t **pplist, int id, qboolean allocate) { fragbuf_t *list = *pplist; fragbuf_t *pnewbuf; while (list) { if (list->bufferid == id) return list; list = list->next; } if (!allocate) return nullptr; // Create new entry pnewbuf = Netchan_AllocFragbuf(); pnewbuf->bufferid = id; Netchan_AddBufferToList(pplist, pnewbuf); return pnewbuf; }
int Netchan_CreateFileFragments(qboolean server, netchan_t *chan, const char *filename) #ifdef REHLDS_FIXES { if (!server) return Netchan_CreateFileFragments_(server, chan, filename); if (!FS_FileExists(filename)) return FALSE; if (FS_FileSize(filename) > sv_filetransfermaxsize.value) return FALSE; auto wait = (fragbufwaiting_t *)Mem_ZeroMalloc(sizeof(fragbufwaiting_t)); auto buf = Netchan_AllocFragbuf(); buf->bufferid = 1; buf->isbuffer = false; buf->isfile = true; Q_strncpy(buf->filename, filename, sizeof(buf->filename)); buf->filename[sizeof(buf->filename) - 1] = '\0'; Netchan_AddFragbufToTail(wait, buf); if (!chan->waitlist[FRAG_FILE_STREAM]) { chan->waitlist[FRAG_FILE_STREAM] = wait; } else { auto p = chan->waitlist[FRAG_FILE_STREAM]; while (p->next) p = p->next; p->next = wait; } return TRUE; }
int Netchan_CreateFileFragments_(qboolean server, netchan_t *chan, const char *filename) #endif // REHLDS_FIXES { int chunksize; int compressedFileTime; FileHandle_t hfile; signed int filesize; int remaining; fragbufwaiting_t *p; int send; fragbuf_t *buf; char compressedfilename[MAX_PATH]; qboolean firstfragment; int bufferid; qboolean bCompressed; int pos; fragbufwaiting_t *wait; int uncompressed_size; bufferid = 1; firstfragment = TRUE; bCompressed = FALSE; chunksize = chan->pfnNetchan_Blocksize(chan->connection_status); Q_snprintf(compressedfilename, sizeof compressedfilename, "%s.ztmp", filename); compressedFileTime = FS_GetFileTime(compressedfilename); if (compressedFileTime >= FS_GetFileTime(filename) && (hfile = FS_Open(compressedfilename, "rb"))) { filesize = FS_Size(hfile); FS_Close(hfile); bCompressed = TRUE; hfile = FS_Open(filename, "rb"); if (!hfile) { Con_Printf("Warning: Unable to open %s for transfer\n", filename); return 0; } uncompressed_size = FS_Size(hfile); if (uncompressed_size > sv_filetransfermaxsize.value) { FS_Close(hfile); Con_Printf("Warning: File %s is too big to transfer from host %s\n", filename, NET_AdrToString(chan->remote_address)); return 0; } } else { hfile = FS_Open(filename, "rb"); if (!hfile) { Con_Printf("Warning: Unable to open %s for transfer\n", filename); return 0; } filesize = FS_Size(hfile); if (filesize > sv_filetransfermaxsize.value) { FS_Close(hfile); Con_Printf("Warning: File %s is too big to transfer from host %s\n", filename, NET_AdrToString(chan->remote_address)); return 0; } uncompressed_size = filesize; if (sv_filetransfercompression.value != 0.0) { unsigned char* uncompressed = (unsigned char*)Mem_Malloc(filesize); unsigned char* compressed = (unsigned char*)Mem_Malloc(filesize); unsigned int compressedSize = filesize; FS_Read(uncompressed, filesize, 1, hfile); if (BZ_OK == BZ2_bzBuffToBuffCompress((char*)compressed, &compressedSize, (char*)uncompressed, filesize, 9, 0, 30)) { FileHandle_t destFile = FS_Open(compressedfilename, "wb"); if (destFile) { Con_DPrintf("Creating compressed version of file %s (%d -> %d)\n", filename, filesize, compressedSize); FS_Write(compressed, compressedSize, 1, destFile); FS_Close(destFile); filesize = compressedSize; bCompressed = TRUE; } } Mem_Free(uncompressed); Mem_Free(compressed); } } FS_Close(hfile); wait = (fragbufwaiting_t *)Mem_ZeroMalloc(0xCu); remaining = filesize; pos = 0; while (remaining) { send = min(chunksize, remaining); buf = Netchan_AllocFragbuf(); if (!buf) { Con_Printf("Couldn't allocate fragbuf_t\n"); Mem_Free(wait); if (server) { #ifdef REHLDS_FIXES SV_DropClient(&g_psvs.clients[chan->player_slot - 1], 0, "Malloc problem"); #else // REHLDS_FIXES SV_DropClient(host_client, 0, "Malloc problem"); #endif // REHLDS_FIXES return 0; } else { rehlds_syserror("%s: Reverse clientside code", __func__); //return 0; } } buf->bufferid = bufferid++; SZ_Clear(&buf->frag_message); if (firstfragment) { firstfragment = FALSE; MSG_WriteString(&buf->frag_message, filename); MSG_WriteString(&buf->frag_message, bCompressed ? "bz2" : "uncompressed"); MSG_WriteLong(&buf->frag_message, uncompressed_size); send -= buf->frag_message.cursize; } buf->isfile = TRUE; buf->iscompressed = bCompressed; buf->size = send; buf->foffset = pos; Q_strncpy(buf->filename, filename, MAX_PATH - 1); buf->filename[MAX_PATH - 1] = 0; pos += send; remaining -= send; Netchan_AddFragbufToTail(wait, buf); } if (!chan->waitlist[FRAG_FILE_STREAM]) { chan->waitlist[FRAG_FILE_STREAM] = wait; } else { p = chan->waitlist[FRAG_FILE_STREAM]; while (p->next) p = p->next; p->next = wait; } return 1; }
void Netchan_CreateFileFragmentsFromBuffer(qboolean server, netchan_t *chan, const char *filename, unsigned char *uncompressed_pbuf, int uncompressed_size) { int chunksize; int send; fragbufwaiting_t *p; fragbuf_t *buf; unsigned char *pbuf; qboolean bCompressed; qboolean firstfragment; signed int bufferid; int remaining; int pos; unsigned int size; fragbufwaiting_t *wait; if (!uncompressed_size) return; bufferid = 1; firstfragment = TRUE; size = uncompressed_size; pbuf = (unsigned char *)Mem_Malloc(uncompressed_size); if (BZ2_bzBuffToBuffCompress((char*)pbuf, &size, (char*)uncompressed_pbuf, uncompressed_size, 9, 0, 30)) { bCompressed = FALSE; Mem_Free(pbuf); pbuf = uncompressed_pbuf; size = uncompressed_size; } else { bCompressed = TRUE; Con_DPrintf("Compressed %s for transmission (%d -> %d)\n", filename, uncompressed_size, size); } chunksize = chan->pfnNetchan_Blocksize(chan->connection_status); send = chunksize; wait = (fragbufwaiting_t *)Mem_ZeroMalloc(0xCu); remaining = size; pos = 0; while (remaining > 0) { send = min(remaining, chunksize); buf = (fragbuf_t *)Netchan_AllocFragbuf(); if (!buf) { Con_Printf("Couldn't allocate fragbuf_t\n"); Mem_Free(wait); if (server) SV_DropClient(host_client, 0, "Malloc problem"); else rehlds_syserror("%s:Reverse me: client-side code", __func__); #ifdef REHLDS_FIXES if (bCompressed) { Mem_Free(pbuf); } #endif return; } buf->bufferid = bufferid++; SZ_Clear(&buf->frag_message); if (firstfragment) { firstfragment = FALSE; MSG_WriteString(&buf->frag_message, filename); MSG_WriteString(&buf->frag_message, bCompressed ? "bz2" : "uncompressed"); MSG_WriteLong(&buf->frag_message, uncompressed_size); send -= buf->frag_message.cursize; } buf->isbuffer = TRUE; buf->isfile = TRUE; buf->size = send; buf->foffset = pos; MSG_WriteBuf(&buf->frag_message, send, &pbuf[pos]); pos += send; remaining -= send; Netchan_AddFragbufToTail(wait, buf); } if (!chan->waitlist[FRAG_FILE_STREAM]) { chan->waitlist[FRAG_FILE_STREAM] = wait; } else { p = chan->waitlist[FRAG_FILE_STREAM]; while (p->next) p = p->next; p->next = wait; } #ifdef REHLDS_FIXES if (bCompressed) { Mem_Free(pbuf); } #endif }
void Netchan_CreateFragments_(qboolean server, netchan_t *chan, sizebuf_t *msg) { fragbuf_t *buf; int chunksize; int send; int remaining; int pos; int bufferid = 1; fragbufwaiting_t *wait, *p; if (msg->cursize == 0) { return; } // Compress if not done already if (*(uint32 *)msg->data != MAKEID('B', 'Z', '2', '\0')) { unsigned char compressed[65536]; char hdr[4] = "BZ2"; unsigned int compressedSize = msg->cursize - sizeof(hdr); // we should fit in same data buffer minus 4 bytes for a header if (!BZ2_bzBuffToBuffCompress((char *)compressed, &compressedSize, (char *)msg->data, msg->cursize, 9, 0, 30)) { Con_DPrintf("Compressing split packet (%d -> %d bytes)\n", msg->cursize, compressedSize); Q_memcpy(msg->data, hdr, sizeof(hdr)); Q_memcpy(msg->data + sizeof(hdr), compressed, compressedSize); msg->cursize = compressedSize + sizeof(hdr); } } chunksize = chan->pfnNetchan_Blocksize(chan->connection_status); wait = (fragbufwaiting_t *)Mem_ZeroMalloc(sizeof(fragbufwaiting_t)); remaining = msg->cursize; pos = 0; while (remaining > 0) { send = min(remaining, chunksize); remaining -= send; buf = Netchan_AllocFragbuf(); if (!buf) { return; } buf->bufferid = bufferid++; // Copy in data SZ_Clear(&buf->frag_message); SZ_Write(&buf->frag_message, &msg->data[pos], send); pos += send; Netchan_AddFragbufToTail(wait, buf); } // Now add waiting list item to the end of buffer queue if (!chan->waitlist[FRAG_NORMAL_STREAM]) { chan->waitlist[FRAG_NORMAL_STREAM] = wait; } else { p = chan->waitlist[FRAG_NORMAL_STREAM]; while (p->next) { p = p->next; } p->next = wait; } }
/* ============================== Netchan_CreateFileFragments ============================== */ int Netchan_CreateFileFragments( qboolean server, netchan_t *chan, const char *filename ) { int chunksize; int send, pos; int remaining; int bufferid = 1; int filesize = 0; qboolean firstfragment = true; fragbufwaiting_t *wait, *p; fragbuf_t *buf; chunksize = bound( 16, net_blocksize->integer, 512 ); filesize = FS_FileSize( filename, false ); if( filesize <= 0 ) { MsgDev( D_WARN, "Unable to open %s for transfer\n", filename ); return 0; } wait = (fragbufwaiting_t *)Mem_Alloc( net_mempool, sizeof( fragbufwaiting_t )); remaining = filesize; pos = 0; while( remaining > 0 ) { send = min( remaining, chunksize ); buf = Netchan_AllocFragbuf(); buf->bufferid = bufferid++; // copy in data BF_Clear( &buf->frag_message ); if( firstfragment ) { firstfragment = false; // Write filename BF_WriteString( &buf->frag_message, filename ); // Send a bit less on first package send -= BF_GetNumBytesWritten( &buf->frag_message ); } buf->isfile = true; buf->size = send; buf->foffset = pos; Q_strncpy( buf->filename, filename, sizeof( buf->filename )); pos += send; remaining -= send; Netchan_AddFragbufToTail( wait, buf ); } // now add waiting list item to end of buffer queue if( !chan->waitlist[FRAG_FILE_STREAM] ) { chan->waitlist[FRAG_FILE_STREAM] = wait; } else { p = chan->waitlist[FRAG_FILE_STREAM]; while( p->next ) { p = p->next; } p->next = wait; } return 1; }
/* ============================== Netchan_CreateFileFragmentsFromBuffer ============================== */ void Netchan_CreateFileFragmentsFromBuffer( qboolean server, netchan_t *chan, char *filename, byte *pbuf, int size ) { int chunksize; int send, pos; int remaining; int bufferid = 1; qboolean firstfragment = true; fragbufwaiting_t *wait, *p; fragbuf_t *buf; if( !size ) return; chunksize = bound( 16, net_blocksize->integer, 512 ); wait = ( fragbufwaiting_t * )Mem_Alloc( net_mempool, sizeof( fragbufwaiting_t )); remaining = size; pos = 0; while( remaining > 0 ) { send = min( remaining, chunksize ); buf = Netchan_AllocFragbuf(); buf->bufferid = bufferid++; // copy in data BF_Clear( &buf->frag_message ); if( firstfragment ) { firstfragment = false; // write filename BF_WriteString( &buf->frag_message, filename ); // send a bit less on first package send -= BF_GetNumBytesWritten( &buf->frag_message ); } buf->isbuffer = true; buf->isfile = true; buf->size = send; buf->foffset = pos; BF_WriteBits( &buf->frag_message, pbuf + pos, send << 3 ); pos += send; remaining -= send; Netchan_AddFragbufToTail( wait, buf ); } // now add waiting list item to end of buffer queue if( !chan->waitlist[FRAG_FILE_STREAM] ) { chan->waitlist[FRAG_FILE_STREAM] = wait; } else { p = chan->waitlist[FRAG_FILE_STREAM]; while( p->next ) { p = p->next; } p->next = wait; } }