Exemplo n.º 1
0
/*
 * Sv_ReadPackets
 */
static void Sv_ReadPackets(void) {
	int i;
	sv_client_t *cl;
	byte qport;

	while (Net_GetPacket(NS_SERVER, &net_from, &net_message)) {

		// check for connectionless packet(0xffffffff) first
		if (*(int *) net_message.data == -1) {
			Sv_ConnectionlessPacket();
			continue;
		}

		// read the qport out of the message so we can fix up
		// stupid address translating routers
		Msg_BeginReading(&net_message);

		Msg_ReadLong(&net_message); // sequence number
		Msg_ReadLong(&net_message); // sequence number

		qport = Msg_ReadByte(&net_message) & 0xff;

		// check for packets from connected clients
		for (i = 0, cl = svs.clients; i < sv_max_clients->integer; i++, cl++) {

			if (cl->state == SV_CLIENT_FREE)
				continue;

			if (!Net_CompareClientNetaddr(net_from, cl->netchan.remote_address))
				continue;

			if (cl->netchan.qport != qport)
				continue;

			if (cl->netchan.remote_address.port != net_from.port) {
				Com_Warn("Sv_ReadPackets: Fixing up a translated port.\n");
				cl->netchan.remote_address.port = net_from.port;
			}

			// this is a valid, sequenced packet, so process it
			if (Netchan_Process(&cl->netchan, &net_message)) {
				cl->last_message = svs.real_time; // nudge timeout
				Sv_ParseClientMessage(cl);
			}

			// we've processed the packet for the correct client, so break
			break;
		}
	}
}
Exemplo n.º 2
0
/*
 * Read a sound delta from the message buffer and play it.
 * Only used with psv_frame2 packets.
 */
void Cl_ReadSoundDelta2(deltatype_t type, boolean skip)
{
	int     sound = 0, soundFlags = 0;
	byte    flags = 0;
	clmobj_t *cmo = NULL;
	thid_t  mobjId = 0;
	sector_t *sector = NULL;
	polyobj_t *poly = NULL;
	mobj_t *emitter = NULL;
	float   volume = 1;

	if(type == DT_SOUND)
	{
		// Delta ID is the sound ID.
		sound = Msg_ReadShort();
	}
	else if(type == DT_MOBJ_SOUND)
	{
		if((cmo = Cl_FindMobj(mobjId = Msg_ReadShort())) != NULL)
		{
			if(cmo->flags & CLMF_HIDDEN)
			{
				// We can't play sounds from hidden mobjs, because we 
				// aren't sure exactly where they are located.
				cmo = NULL;
			}
			else
			{
				emitter = &cmo->mo;
			}
		}
	}
	else if(type == DT_SECTOR_SOUND)
	{
		int     index = (ushort) Msg_ReadShort();

		if(index < numsectors)
		{
			sector = SECTOR_PTR(index);
			emitter = (mobj_t *) &sector->soundorg;
		}
	}
	else						/* DT_POLY_SOUND */
	{
		int     index = (ushort) Msg_ReadShort();

		if(index < po_NumPolyobjs)
		{
			poly = PO_PTR(index);
			emitter = (mobj_t *) &poly->startSpot;
		}
	}

	flags = Msg_ReadByte();

	if(type != DT_SOUND)
	{
		// The sound ID.
		sound = Msg_ReadShort();
	}

	if(flags & SNDDF_VOLUME)
	{
		byte    b = Msg_ReadByte();

		if(b == 255)
		{
			// Full volume, no attenuation.
			soundFlags |= DDSF_NO_ATTENUATION;
		}
		else
		{
			volume = b / 127.0f;
		}
	}

	if(flags & SNDDF_REPEAT)
	{
		soundFlags |= DDSF_REPEAT;
	}

	// The delta has been read. Are we skipping?
	if(skip)
		return;

	// Now the entire delta has been read.
	// Should we start or stop a sound?
	if(volume > 0 && sound > 0)
	{
		// Do we need to queue this sound?
		if(type == DT_MOBJ_SOUND && !cmo)
		{
			// Create a new Hidden clmobj.
			cmo = Cl_CreateMobj(mobjId);
			cmo->flags |= CLMF_HIDDEN | CLMF_SOUND;
			cmo->sound = sound;
			cmo->volume = volume;
			/*#ifdef _DEBUG
			   Con_Printf("Cl_ReadSoundDelta2(%i): Queueing: id=%i snd=%i vol=%.2f\n",
			   type, mobjId, sound, volume);
			   #endif */
			// The sound will be started when the clmobj is unhidden.
			return;
		}

		// We will start a sound.
		if(type != DT_SOUND && !emitter)
		{
			// Not enough information.
#ifdef _DEBUG
			Con_Printf("Cl_ReadSoundDelta2(%i): Insufficient data, snd=%i\n",
					   type, sound);
#endif
			return;
		}

		// Sounds originating from the viewmobj should really originate 
		// from the real player mobj.
		if(cmo && cmo == playerstate[consoleplayer].cmo)
		{
			/*#ifdef _DEBUG
			   Con_Printf("Cl_ReadSoundDelta2(%i): ViewMobj sound...\n", type);
			   #endif */
			emitter = players[consoleplayer].mo;
		}

		// First stop any sounds originating from the same emitter.
		// We allow only one sound per emitter.
		if(type != DT_SOUND && emitter)
		{
			S_StopSound(0, emitter);
		}

		S_LocalSoundAtVolume(sound | soundFlags, emitter, volume);

		/*#ifdef _DEBUG
		   Con_Printf("Cl_ReadSoundDelta2(%i): Start snd=%i [%x] vol=%.2f", 
		   type, sound, flags, volume);
		   if(cmo)  Con_Printf(", mo=%i\n", cmo->mo.thinker.id);
		   else if(sector) Con_Printf(", sector=%i\n", GET_SECTOR_IDX(sector));
		   else if(poly) Con_Printf(", poly=%i\n", GET_POLYOBJ_IDX(poly));
		   else Con_Printf("\n");
		   #endif */
	}
	else if(sound >= 0)
	{
		// We must stop a sound. We'll only stop sounds from 
		// specific sources.
		if(emitter)
		{
			S_StopSound(sound, emitter);

			/*#ifdef _DEBUG
			   Con_Printf("Cl_ReadSoundDelta2(%i): Stop sound %i", 
			   type, sound);
			   if(cmo)  Con_Printf(", mo=%i\n", cmo->mo.thinker.id);
			   else if(sector) Con_Printf(", sector=%i\n", 
			   GET_SECTOR_IDX(sector));
			   else if(poly) Con_Printf(", poly=%i\n", GET_POLYOBJ_IDX(poly));
			   else Con_Printf("\n");
			   #endif */
		}
	}
}
Exemplo n.º 3
0
/*
 * Called when a psv_frame sound packet is received.
 */
void Cl_Sound(void)
{
	int     sound, volume = 127;
	float   pos[3];
	byte    flags;
	int     num;
	mobj_t *mo = NULL;

	flags = Msg_ReadByte();

	// Sound ID.
	if(flags & SNDF_SHORT_SOUND_ID)
	{
		sound = Msg_ReadShort();
	}
	else
	{
		sound = Msg_ReadByte();
	}

	// Is the ID valid?
	if(sound < 1 || sound >= defs.count.sounds.num)
	{
		Con_Message("Cl_Sound: Out of bounds ID %i.\n", sound);
		return;					// Bad sound ID!
	}
#ifdef _DEBUG
	Con_Printf("Cl_Sound: %i\n", sound);
#endif

	if(flags & SNDF_VOLUME)
	{
		volume = Msg_ReadByte();
		if(volume > 127)
		{
			volume = 127;
			sound |= DDSF_NO_ATTENUATION;
		}
	}
	if(flags & SNDF_ID)
	{
		thid_t  sourceId = Msg_ReadShort();
		clmobj_t *cmo = Cl_FindMobj(sourceId);

		if(cmo)
		{
			S_LocalSoundAtVolume(sound, &cmo->mo, volume / 127.0f);
		}
	}
	else if(flags & SNDF_SECTOR)
	{
		num = Msg_ReadPackedShort();
		if(num < 0 || num >= numsectors)
		{
			Con_Message("Cl_Sound: Invalid sector number %i.\n", num);
			return;
		}
		mo = (mobj_t *) &SECTOR_PTR(num)->soundorg;
		//S_StopSound(0, mo);
		S_LocalSoundAtVolume(sound, mo, volume / 127.0f);
	}
	else if(flags & SNDF_ORIGIN)
	{
		pos[VX] = Msg_ReadShort();
		pos[VY] = Msg_ReadShort();
		pos[VZ] = Msg_ReadShort();
		S_LocalSoundAtVolumeFrom(sound, NULL, pos, volume / 127.0f);
	}
	else if(flags & SNDF_PLAYER)
	{
		S_LocalSoundAtVolume(sound, players[(flags & 0xf0) >> 4].mo,
							 volume / 127.0f);
	}
Exemplo n.º 4
0
/*
 * Sv_ParseClientMessage
 *
 * The current net_message is parsed for the given client.
 */
void Sv_ParseClientMessage(sv_client_t *cl) {
	user_cmd_t null_cmd, oldest_cmd, old_cmd, new_cmd;
	int net_drop;
	int strings_issued;
	int moves_issued;
	int last_frame;
	int c;
	char *s;

	sv_client = cl;
	sv_player = sv_client->edict;

	// allow a finite number of moves and strings
	moves_issued = strings_issued = 0;

	while (true) {

		if (net_message.read > net_message.size) {
			Com_Warn("Sv_ParseClientMessage: Bad read from %s\n",
					Sv_NetaddrToString(sv_client));
			Sv_DropClient(cl);
			return;
		}

		c = Msg_ReadByte(&net_message);
		if (c == -1)
			break;

		switch (c) {

		case CL_CMD_USER_INFO:
			strncpy(cl->user_info, Msg_ReadString(&net_message), sizeof(cl->user_info) - 1);
			Sv_UserInfoChanged(cl);
			break;

		case CL_CMD_MOVE:
			if (++moves_issued > CMD_MAX_MOVES) {
				return; // someone is trying to cheat
			}

			last_frame = Msg_ReadLong(&net_message);
			if (last_frame != cl->last_frame) {
				cl->last_frame = last_frame;
				if (cl->last_frame > -1) {
					cl->frame_latency[cl->last_frame & (CLIENT_LATENCY_COUNTS
							- 1)] = svs.real_time - cl->frames[cl->last_frame
							& UPDATE_MASK].sent_time;
				}
			}

			memset(&null_cmd, 0, sizeof(null_cmd));
			Msg_ReadDeltaUsercmd(&net_message, &null_cmd, &oldest_cmd);
			Msg_ReadDeltaUsercmd(&net_message, &oldest_cmd, &old_cmd);
			Msg_ReadDeltaUsercmd(&net_message, &old_cmd, &new_cmd);

			// don't start delta compression until the client is spawned
			// TODO: should this be a little higher up?
			if (cl->state != SV_CLIENT_ACTIVE) {
				cl->last_frame = -1;
				break;
			}

			// catch extremely high msec movements
			if (null_cmd.msec > CMD_MAX_MSEC || oldest_cmd.msec > CMD_MAX_MSEC
					|| old_cmd.msec > CMD_MAX_MSEC || new_cmd.msec
					> CMD_MAX_MSEC) {
				Com_Warn("Sv_ParseClientMessage: Illegal msec from %s\n",
						Sv_NetaddrToString(cl));
				Sv_KickClient(cl, "Illegal movement");
				return;
			}

			net_drop = cl->netchan.dropped;
			if (net_drop < 20) {
				while (net_drop > 2) {
					Sv_ClientThink(cl, &cl->last_cmd);
					net_drop--;
				}
				if (net_drop > 1)
					Sv_ClientThink(cl, &oldest_cmd);
				if (net_drop > 0)
					Sv_ClientThink(cl, &old_cmd);
			}
			Sv_ClientThink(cl, &new_cmd);
			cl->last_cmd = new_cmd;
			break;

		case CL_CMD_STRING:
			s = Msg_ReadString(&net_message);

			// malicious users may try using too many string commands
			if (++strings_issued < CMD_MAX_STRINGS)
				Sv_UserStringCommand(s);
			else {
				Com_Warn(
						"Sv_ParseClientMessage: CMD_MAX_STRINGS exceeded for %s\n",
						Sv_NetaddrToString(cl));
				Sv_KickClient(cl, "Too many commands.");
				return;
			}

			if (cl->state == SV_CLIENT_FREE)
				return; // disconnect command
			break;

		default:
			Com_Print("Sv_ParseClientMessage: unknown command %d\n", c);
			Sv_DropClient(cl);
			return;
		}
	}
}