Q2PRO Shitfuck Netchan
This thing sucks, lol, Q2 "PRO" my ass, suck my dick and lick my hairy balls.unknown
c_cpp
4 years ago
11 kB
8
Indexable
/*
===============
Netchan_TransmitNextFragment
================
*/
size_t Netchan_TransmitNextFragment(netchan_t *netchan)
{
sizebuf_t send;
byte send_buf[MAX_PACKETLEN];
qboolean send_reliable;
uint32_t w1, w2;
uint16_t offset;
size_t fragment_length;
qboolean more_fragments;
// Should we send a reliable message, or not?
send_reliable = netchan->reliableLength ? true : false;
// Write the packet header
w1 = (netchan->outgoingSequence & 0x3FFFFFFF) | (1 << 30) |
(send_reliable << 31);
w2 = (netchan->incomingSequence & 0x3FFFFFFF) | (0 << 30) |
(netchan->incomingReliableSequence << 31);
SZ_TagInit(&send, send_buf, sizeof(send_buf), SZ_NC_SEND_FRG);
SZ_WriteLong(&send, w1);
SZ_WriteLong(&send, w2);
#if USE_CLIENT
// Send the qport if we are a client
if (netchan->sock == NS_CLIENT && netchan->qport) {
SZ_WriteByte(&send, netchan->qport);
}
#endif
// Calculate Fragment length based on how much has been read so far.
// Ensure we do not exceed the max packet length.
fragment_length = netchan->outFragment.cursize - netchan->outFragment.readcount;
if (fragment_length > netchan->maxpacketlen) {
fragment_length = netchan->maxpacketlen;
}
// More
more_fragments = true;
if (netchan->outFragment.readcount + fragment_length ==
netchan->outFragment.cursize) {
more_fragments = false;
}
// Write fragment offset
offset = (netchan->outFragment.readcount & 0x7FFF) |
(more_fragments << 15);
SZ_WriteShort(&send, offset);
// Write fragment contents
SZ_Write(&send, netchan->outFragment.data + netchan->outFragment.readcount,
fragment_length);
SHOWPACKET("send %4" PRIz " : s=%d ack=%d rack=%d "
"fragment_offset=%" PRIz " more_fragments=%d",
send.cursize,
netchan->outgoingSequence,
netchan->incomingSequence,
netchan->incomingReliableSequence,
netchan->outFragment.readcount,
more_fragments);
if (send_reliable) {
SHOWPACKET(" reliable=%i ", netchan->reliableSequence);
}
SHOWPACKET("\n");
// Increment read count with fragment length and store whether one more is pending or not.
netchan->outFragment.readcount += fragment_length;
netchan->fragmentPending = more_fragments;
// If the message has been sent completely, clear the fragment buffer
if (!netchan->fragmentPending) {
netchan->outgoingSequence++;
netchan->lastSent = com_localTime;
SZ_Clear(&netchan->outFragment);
}
// Send the datagram
NET_SendPacket(netchan->sock, send.data, send.cursize,
&netchan->remoteAddress);
return send.cursize;
}
/*
===============
Netchan_Transmit
================
*/
size_t Netchan_Transmit(netchan_t *netchan, size_t length, const void *data, int numpackets)
{
sizebuf_t send;
byte send_buf[MAX_PACKETLEN];
qboolean send_reliable;
uint32_t w1, w2;
int i;
// check for message overflow
if (netchan->message.overflowed) {
netchan->fatal_error = true;
Com_WPrintf("%s: outgoing message overflow\n",
NET_AdrToString(&netchan->remoteAddress));
return 0;
}
if (netchan->fragmentPending) {
return Netchan_TransmitNextFragment(netchan);
}
send_reliable = false;
// if the remote side dropped the last reliable message, resend it
if (netchan->incomingAcknowledged > netchan->lastReliableSequence &&
netchan->incomingReliableAcknowledged != netchan->reliableSequence) {
send_reliable = true;
}
// if the reliable transmit buffer is empty, copy the current message out
if (!netchan->reliableLength && netchan->message.cursize) {
send_reliable = true;
memcpy(netchan->reliableBuffer, netchan->messageBuffer,
netchan->message.cursize);
netchan->reliableLength = netchan->message.cursize;
netchan->message.cursize = 0;
netchan->reliableSequence ^= 1;
}
if (length > netchan->maxpacketlen || (send_reliable &&
(netchan->reliableLength + length > netchan->maxpacketlen))) {
if (send_reliable) {
netchan->lastReliableSequence = netchan->outgoingSequence;
SZ_Write(&netchan->outFragment, netchan->reliableBuffer,
netchan->reliableLength);
}
// add the unreliable part if space is available
if (netchan->outFragment.maxsize - netchan->outFragment.cursize >= length)
SZ_Write(&netchan->outFragment, data, length);
else
Com_WPrintf("%s: dumped unreliable\n",
NET_AdrToString(&netchan->remoteAddress));
return Netchan_TransmitNextFragment(netchan);
}
// write the packet header
w1 = (netchan->outgoingSequence & 0x3FFFFFFF) | (send_reliable << 31);
w2 = (netchan->incomingSequence & 0x3FFFFFFF) |
(netchan->incomingReliableSequence << 31);
SZ_TagInit(&send, send_buf, sizeof(send_buf), SZ_NC_SEND_NEW);
SZ_WriteLong(&send, w1);
SZ_WriteLong(&send, w2);
#if USE_CLIENT
// send the qport if we are a client
if (netchan->sock == NS_CLIENT && netchan->qport) {
SZ_WriteByte(&send, netchan->qport);
}
#endif
// copy the reliable message to the packet first
if (send_reliable) {
netchan->lastReliableSequence = netchan->outgoingSequence;
SZ_Write(&send, netchan->reliableBuffer, netchan->reliableLength);
}
// add the unreliable part
SZ_Write(&send, data, length);
SHOWPACKET("send %4" PRIz " : s=%d ack=%d rack=%d",
send.cursize,
netchan->outgoingSequence,
netchan->incomingSequence,
netchan->incomingReliableSequence);
if (send_reliable) {
SHOWPACKET(" reliable=%d", netchan->reliableSequence);
}
SHOWPACKET("\n");
// send the datagram
for (i = 0; i < numpackets; i++) {
NET_SendPacket(netchan->sock, send.data, send.cursize,
&netchan->remoteAddress);
}
netchan->outgoingSequence++;
netchan->reliableAckPending = false;
netchan->lastSent = com_localTime;
return send.cursize * numpackets;
}
/*
=================
Netchan_Process
=================
*/
qboolean Netchan_Process(netchan_t *netchan)
{
uint32_t sequence, sequence_ack, reliable_ack;
qboolean reliable_message, fragmented_message, more_fragments;
uint16_t fragment_offset;
size_t length;
// get sequence numbers
MSG_BeginReading();
sequence = MSG_ReadLong();
sequence_ack = MSG_ReadLong();
// read the qport if we are a server
#if USE_CLIENT
if (netchan->sock == NS_SERVER)
#endif
if (netchan->qport) {
MSG_ReadByte();
}
reliable_message = sequence >> 31;
reliable_ack = sequence_ack >> 31;
fragmented_message = (sequence >> 30) & 1;
sequence &= 0x3FFFFFFF;
sequence_ack &= 0x3FFFFFFF;
fragment_offset = 0;
more_fragments = false;
if (fragmented_message) {
fragment_offset = MSG_ReadShort();
more_fragments = fragment_offset >> 15;
fragment_offset &= 0x7FFF;
}
SHOWPACKET("recv %4" PRIz " : s=%d ack=%d rack=%d",
msg_read.cursize, sequence, sequence_ack, reliable_ack);
if (fragmented_message) {
SHOWPACKET(" fragment_offset=%d more_fragments=%d",
fragment_offset, more_fragments);
}
if (reliable_message) {
SHOWPACKET(" reliable=%d", netchan->incomingReliableSequence ^ 1);
}
SHOWPACKET("\n");
//
// discard stale or duplicated packets
//
if (sequence <= netchan->incomingSequence) {
SHOWDROP("%s: out of order packet %i at %i\n",
NET_AdrToString(&netchan->remoteAddress),
sequence, netchan->incomingSequence);
return false;
}
//
// dropped packets don't keep the message from being used
//
netchan->dropped = sequence - (netchan->incomingSequence + 1);
if (netchan->dropped > 0) {
SHOWDROP("%s: dropped %i packets at %i\n",
NET_AdrToString(&netchan->remoteAddress),
netchan->dropped, sequence);
}
//
// if the current outgoing reliable message has been acknowledged
// clear the buffer to make way for the next
//
netchan->incomingReliableAcknowledged = reliable_ack;
if (reliable_ack == netchan->reliableSequence) {
netchan->reliableLength = 0; // it has been received
}
//
// parse fragment header, if any
//
if (fragmented_message) {
if (netchan->fragmentSequence != sequence) {
// start new receive sequence
netchan->fragmentSequence = sequence;
SZ_Clear(&netchan->inFragment);
}
if (fragment_offset < netchan->inFragment.cursize) {
SHOWDROP("%s: out of order fragment at %i\n",
NET_AdrToString(&netchan->remoteAddress), sequence);
return false;
}
if (fragment_offset > netchan->inFragment.cursize) {
SHOWDROP("%s: dropped fragment(s) at %i\n",
NET_AdrToString(&netchan->remoteAddress), sequence);
return false;
}
length = msg_read.cursize - msg_read.readcount;
if (netchan->inFragment.cursize + length > netchan->inFragment.maxsize) {
SHOWDROP("%s: oversize fragment at %i\n",
NET_AdrToString(&netchan->remoteAddress), sequence);
return false;
}
SZ_Write(&netchan->inFragment, msg_read.data +
msg_read.readcount, length);
if (more_fragments) {
return false;
}
// message has been sucessfully assembled
SZ_Clear(&msg_read);
SZ_Write(&msg_read, netchan->inFragment.data,
netchan->inFragment.cursize);
SZ_Clear(&netchan->inFragment);
}
netchan->incomingSequence = sequence;
netchan->incomingAcknowledged = sequence_ack;
//
// if this message contains a reliable message, bump incomingReliableSequence
//
if (reliable_message) {
netchan->reliableAckPending = true;
netchan->incomingReliableSequence ^= 1;
}
//
// the message can now be read from the current message pointer
//
netchan->lastReceived = com_localTime;
netchan->totalDropped += netchan->dropped;
netchan->totalReceived += netchan->dropped + 1;
return true;
}Editor is loading...