예제 #1
0
/*
==============================
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;
	}
}
예제 #2
0
파일: net_chan.cpp 프로젝트: Chuvi-w/rehlds
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;
}
예제 #3
0
파일: net_chan.cpp 프로젝트: Chuvi-w/rehlds
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;
}
예제 #4
0
파일: net_chan.cpp 프로젝트: Chuvi-w/rehlds
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;
}
예제 #5
0
파일: net_chan.cpp 프로젝트: Chuvi-w/rehlds
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
}
예제 #6
0
파일: net_chan.cpp 프로젝트: Chuvi-w/rehlds
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;
	}
}
예제 #7
0
/*
==============================
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;
}
예제 #8
0
/*
==============================
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;
	}
}