コード例 #1
0
ファイル: cl_net_chan.cpp プロジェクト: DerSaidin/OpenWolf
/*
==============
CL_Netchan_Decode

	// first four bytes of the data are always:
	long reliableAcknowledge;

==============
*/
static void CL_Netchan_Decode(msg_t * msg)
{
	long            reliableAcknowledge, i, index;
	byte            key, *string;
	int             srdc, sbit;
	qboolean        soob;

	srdc = msg->readcount;
	sbit = msg->bit;
	soob = msg->oob;

	msg->oob = qfalse;

	reliableAcknowledge = MSG_ReadLong(msg);

	msg->oob = soob;
	msg->bit = sbit;
	msg->readcount = srdc;

	string = (byte*)CL_GetReliableCommand( reliableAcknowledge );
	index = 0;
	// xor the client challenge with the netchan sequence number (need something that changes every message)
	key = (clc.challenge ^ LittleLong(*(unsigned *)msg->data)) & 0xFF;
	for(i = msg->readcount + CL_DECODE_START; i < msg->cursize; i++)
	{
		// modify the key with the last sent and with this message acknowledged client command
		if(!string[index])
		{
			index = 0;
		}
		if(string[index] > 127 || string[index] == '%')
		{
			key ^= '.' << (i & 1);
		}
		else
		{
			key ^= string[index] << (i & 1);
		}
		index++;
		// decode the data with this key
		*(msg->data + i) = *(msg->data + i) ^ key;
	}
}
コード例 #2
0
ファイル: cl_input.cpp プロジェクト: TheDushan/OpenWolf
/*
===================
CL_WritePacket

Create and send the command packet to the server
Including both the reliable commands and the usercmds

During normal gameplay, a client packet will contain something like:

4	sequence number
2	qport
4	serverid
4	acknowledged sequence number
4	clc.serverCommandSequence
<optional reliable commands>
1	clc_move or clc_moveNoDelta
1	command count
<count * usercmds>

===================
*/
void CL_WritePacket(void)
{
    msg_t           buf;
    byte            data[MAX_MSGLEN];
    int             i, j;
    usercmd_t      *cmd, *oldcmd;
    usercmd_t       nullcmd;
    int             packetNum;
    int             oldPacketNum;
    int             count, key;

    // don't send anything if playing back a demo
    if(clc.demoplaying || cls.state == CA_CINEMATIC)
    {
        return;
    }

    memset(&nullcmd, 0, sizeof(nullcmd));
    oldcmd = &nullcmd;

    MSG_Init(&buf, data, sizeof(data));

    MSG_Bitstream(&buf);
    // write the current serverId so the server
    // can tell if this is from the current gameState
    MSG_WriteLong(&buf, cl.serverId);

    // write the last message we received, which can
    // be used for delta compression, and is also used
    // to tell if we dropped a gamestate
    MSG_WriteLong(&buf, clc.serverMessageSequence);

    // write the last reliable message we received
    MSG_WriteLong(&buf, clc.serverCommandSequence);

    // write any unacknowledged clientCommands
    // NOTE TTimo: if you verbose this, you will see that there are quite a few duplicates
    // typically several unacknowledged cp or userinfo commands stacked up
    for(i = clc.reliableAcknowledge + 1; i <= clc.reliableSequence; i++)
    {
        MSG_WriteByte(&buf, clc_clientCommand);
        MSG_WriteLong(&buf, i);
        MSG_WriteString( &buf, CL_GetReliableCommand( i ) );
    }

    // we want to send all the usercmds that were generated in the last
    // few packet, so even if a couple packets are dropped in a row,
    // all the cmds will make it to the server
    if(cl_packetdup->integer < 0)
    {
        Cvar_Set("cl_packetdup", "0");
    }
    else if(cl_packetdup->integer > 5)
    {
        Cvar_Set("cl_packetdup", "5");
    }
    oldPacketNum = (clc.netchan.outgoingSequence - 1 - cl_packetdup->integer) & PACKET_MASK;
    count = cl.cmdNumber - cl.outPackets[oldPacketNum].p_cmdNumber;
    if(count > MAX_PACKET_USERCMDS)
    {
        count = MAX_PACKET_USERCMDS;
        Com_Printf("MAX_PACKET_USERCMDS\n");
    }

#ifdef USE_VOIP
    if (clc.voipOutgoingDataSize > 0)
    {
        if((clc.voipFlags & VOIP_SPATIAL) || Com_IsVoipTarget(clc.voipTargets, sizeof(clc.voipTargets), -1))
        {
            MSG_WriteByte (&buf, clc_voip);
            MSG_WriteByte (&buf, clc.voipOutgoingGeneration);
            MSG_WriteLong (&buf, clc.voipOutgoingSequence);
            MSG_WriteByte (&buf, clc.voipOutgoingDataFrames);
            MSG_WriteData (&buf, clc.voipTargets, sizeof(clc.voipTargets));
            MSG_WriteByte(&buf, clc.voipFlags);
            MSG_WriteShort (&buf, clc.voipOutgoingDataSize);
            MSG_WriteData (&buf, clc.voipOutgoingData, clc.voipOutgoingDataSize);

            // If we're recording a demo, we have to fake a server packet with
            //  this VoIP data so it gets to disk; the server doesn't send it
            //  back to us, and we might as well eliminate concerns about dropped
            //  and misordered packets here.
            if(clc.demorecording && !clc.demowaiting)
            {
                const int voipSize = clc.voipOutgoingDataSize;
                msg_t fakemsg;
                byte fakedata[MAX_MSGLEN];
                MSG_Init (&fakemsg, fakedata, sizeof (fakedata));
                MSG_Bitstream (&fakemsg);
                MSG_WriteLong (&fakemsg, clc.reliableAcknowledge);
                MSG_WriteByte (&fakemsg, svc_voip);
                MSG_WriteShort (&fakemsg, clc.clientNum);
                MSG_WriteByte (&fakemsg, clc.voipOutgoingGeneration);
                MSG_WriteLong (&fakemsg, clc.voipOutgoingSequence);
                MSG_WriteByte (&fakemsg, clc.voipOutgoingDataFrames);
                MSG_WriteShort (&fakemsg, clc.voipOutgoingDataSize );
                MSG_WriteData (&fakemsg, clc.voipOutgoingData, voipSize);
                MSG_WriteByte (&fakemsg, svc_EOF);
                CL_WriteDemoMessage (&fakemsg, 0);
            }

            clc.voipOutgoingSequence += clc.voipOutgoingDataFrames;
            clc.voipOutgoingDataSize = 0;
            clc.voipOutgoingDataFrames = 0;
        }
        else
        {
            // We have data, but no targets. Silently discard all data
            clc.voipOutgoingDataSize = 0;
            clc.voipOutgoingDataFrames = 0;
        }
    }
#endif

    if(count >= 1)
    {
        if(cl_showSend->integer)
        {
            Com_Printf("(%i)", count);
        }

        // begin a client move command
        if(cl_nodelta->integer || !cl.snap.valid || clc.demowaiting || clc.serverMessageSequence != cl.snap.messageNum)
        {
            MSG_WriteByte(&buf, clc_moveNoDelta);
        }
        else
        {
            MSG_WriteByte(&buf, clc_move);
        }

        // write the command count
        MSG_WriteByte(&buf, count);

        // use the checksum feed in the key
        key = clc.checksumFeed;
        // also use the message acknowledge
        key ^= clc.serverMessageSequence;
        // also use the last acknowledged server command in the key
        key ^= Com_HashKey( CL_GetReliableServerCommand( clc.serverCommandSequence ), 32);

        // write all the commands, including the predicted command
        for(i = 0; i < count; i++)
        {
            j = (cl.cmdNumber - count + i + 1) & CMD_MASK;
            cmd = &cl.cmds[j];
            MSG_WriteDeltaUsercmdKey(&buf, key, oldcmd, cmd);
            oldcmd = cmd;
        }
    }

    //
    // deliver the message
    //
    packetNum = clc.netchan.outgoingSequence & PACKET_MASK;
    cl.outPackets[packetNum].p_realtime = cls.realtime;
    cl.outPackets[packetNum].p_serverTime = oldcmd->serverTime;
    cl.outPackets[packetNum].p_cmdNumber = cl.cmdNumber;
    clc.lastPacketSentTime = cls.realtime;

    if(cl_showSend->integer)
    {
        Com_Printf("%i ", buf.cursize);
    }
    CL_Netchan_Transmit(&clc.netchan, &buf);

    // clients never really should have messages large enough
    // to fragment, but in case they do, fire them all off
    // at once
    // TTimo: this causes a packet burst, which is bad karma for winsock
    // added a WARNING message, we'll see if there are legit situations where this happens
    while(clc.netchan.unsentFragments)
    {
        if(cl_showSend->integer)
        {
            Com_Printf("WARNING: unsent fragments (not supposed to happen!)\n");
        }
        CL_Netchan_TransmitNextFragment(&clc.netchan);
    }
}