示例#1
0
文件: dosipx.cpp 项目: zlatkok/swospp
bool SendImportantPacket(const IPX_Address *dest, const char *destBuf, int destSize)
{
    if (!FindClientAckId(dest)) {
        WriteToLog("Trying to send important packet to a non-connected client [%#.12s]", dest);
        return false;
    }

    if (destSize <= (int)(m_maxPacketSize - sizeof(SWOSPP_Packet) + sizeof(ECB) - sizeof(dword))) {
        /* not fragmented */
        char *data;
        if (!(data = AddUnacknowledgedPacket(dest, GetClientNextSendingId(dest),
            IMPORTANT_PACKET_SIG, destBuf, destSize, 0)))
            return false;
        m_sendPacket->type = IMPORTANT_PACKET_SIG;
        SendPacket(dest, data, destSize + sizeof(dword));
    } else {
        /* fragmented */
        int bytesLeft = destSize, dataSpace, totalFragments, numFragmentedIds = 0;
        dword fragmentedIds[MAX_FRAGMENTS], groupId = GetClientNextSendingGroupId(dest);
        if (!groupId) {
            WriteToLog("Trying to send fragmented packet to a non-connected client");
            return false;
        }

        /* extra space for: dword id, dword group id, byte total */
        dataSpace = m_maxPacketSize - sizeof(SWOSPP_Packet) + sizeof(ECB) - 9;
        totalFragments = (destSize + dataSpace - 1) / dataSpace;
        if (totalFragments > MAX_FRAGMENTS) {
            WriteToLog("Trying to send too big packet, size = %d, %d fragments", destSize, totalFragments);
            return false;
        }

        while (bytesLeft > 0) {
            dword id = GetClientNextSendingId(dest);
            char *data = AddUnacknowledgedPacket(dest, id, PARTIAL_PACKET_SIG,
                destBuf + destSize - bytesLeft, min(bytesLeft, dataSpace), 5);

            if (!data) {
                int i;
                RollbackSendingId(dest);    /* or client will wait for this packet forever */
                /* cancel all fragments - entire group fails if one fails */
                WriteToLog("Out of memory while trying to send fragmented packet!");

                for (i = 0; i < numFragmentedIds; i++)
                    AcknowledgePacket(fragmentedIds[i], dest);

                m_sendPacket->type = CANCEL_PARTIAL_SIG;
                SendPacket(dest, (char *)groupId, sizeof(groupId));
                return false;
            }

            fragmentedIds[numFragmentedIds++] = id;
            *(dword *)(data + 4) = groupId;
            data[8] = totalFragments;
            m_sendPacket->type = PARTIAL_PACKET_SIG;
            SendPacket(dest, data, min(bytesLeft, dataSpace) + sizeof(dword) + 5);
            bytesLeft -= dataSpace;
        }
    }
    return true;
}
示例#2
0
文件: dosipx.cpp 项目: zlatkok/swospp
/** ReceivePacket

    destSize -> will contain the size of the packet after returning
    node     -> will contain sender's address after returning

    Return pointer to packet bytes allocated from the heap. Handle all incoming packet types.
    If there are no pending packets return nullptr. Also return nullptr if out of memory,
    differentiate that case by setting size to -1. Discard all invalid packets found.
*/
char *ReceivePacket(int *destSize, IPX_Address *node)
{
    dword id = 0, *currentId;
    int i, size;
    char *srcPtr, *destBuf = nullptr;

    /* ignoring malformed packets etc. */
    for (i = 0; i < MAX_RECV_PACKETS; i++)
        if (!m_packets[i]->ecb.inUseFlag && !m_packets[i]->ecb.completionCode)
            break;

    if (i >= MAX_RECV_PACKETS) {
        *destSize = 0;
        return nullptr;
    }

    size = htons(m_packets[i]->ipx.length) - sizeof(SWOSPP_Packet) + sizeof(ECB);
    /* our packets always have size limit */
    if (size < 0) {
        WriteToLog("Rejecting invalid size packet, with total size of %d bytes",
            htons(m_packets[i]->ipx.length));
        return ReceiveNextPacket(destSize, node, i);
    }

    srcPtr = m_packets[i]->data;
    /* get the sender's address and data */
    CopyAddress(node, &m_packets[i]->ipx.source);

    // can't have this if we're gonna let guys join the game
    //if (!FindClientAckId(node)) {
    //    WriteToLog("Rejecting packet from non-connected sender [%#.12s]", node);
    //    return ReceiveNextPacket(destSize, node, i);
    //}

    /* verify the stamp */
    if (m_packets[i]->verifyStamp != 'SWPP') {
        WriteToLog("Rejecting packet with invalid stamp: %08x:", m_packets[i]->verifyStamp);
        return ReceiveNextPacket(destSize, node, i);
    }

    /* this is probably overkill */
    if (m_packets[i]->adler32Checksum != Adler32((const byte *)m_packets[i]->data, size)) {
        WriteToLog("Rejecting packet with invalid Adler32 checksum (%d, expecting %d).",
            m_packets[i]->adler32Checksum, Adler32((const byte *)m_packets[i]->data, size));
        HexDumpToLog(m_packets[i]->data, size, "packet with failed checksum");
        return ReceiveNextPacket(destSize, node, i);
    }

    switch (m_packets[i]->type) {
    case UNIMPORTANT_PACKET_SIG:
        /* OK, with simple packet we're done already */
        break;

    case PARTIAL_PACKET_SIG:
    case IMPORTANT_PACKET_SIG:
        if (size < 4 + 5 * (m_packets[i]->type == PARTIAL_PACKET_SIG)) {
            WriteToLog("Malformed important/partial packet rejected, size = %d", size);
            return ReceiveNextPacket(destSize, node, i);
        }

        if (!(currentId = GetClientCurrentReceivingId(&m_packets[i]->ipx.source))) {
            WriteToLog("Rejecting important packet because client not connected.");
            HexDumpToLog(&m_packets[i]->ipx.source, sizeof(IPX_Address), "disconnected client address");
            /* maybe send them disconnect too for good measure? */
            DisconnectFrom(&m_packets[i]->ipx.source);
            return ReceiveNextPacket(destSize, node, i);
        }

        id = *(dword *)srcPtr;
        if (id > *currentId + 1) {
            /* OUT OF ORDER! YOU WILL OBEY! */
            //WriteToLog("Out of order packet detected, id = %d, expecting %d", id, *currentId + 1);
            return ReceiveNextPacket(destSize, node, i);
        }

        if (id == *currentId + 1) {
            /* cool, this is expected next packet, bump id and send it up there */
            size -= sizeof(dword);
            srcPtr += sizeof(dword);

            /* now process fragmented packet, if it is one */
            if (m_packets[i]->type == PARTIAL_PACKET_SIG) {
                byte total;
                dword fragId;

                if (size < 6) {
                    WriteToLog("Malformed partial packet rejected, size = %d.", size);
                    return ReceiveNextPacket(destSize, node, i);
                }

                fragId = *(dword *)srcPtr;
                total = srcPtr[4];

                if (total > MAX_FRAGMENTS) {
                    WriteToLog("Too many fragments for partial packet (%d).", total);
                    return ReceiveNextPacket(destSize, node, i);
                }

                size -= 5;
                srcPtr += 5;

                /* in case of memory exhaustion don't send ack, they'll send it again
                   and we'll hopefully have enough memory by then */
                if (!(destBuf = AddPacketFragment(destSize, srcPtr, size, node, fragId, total))) {
                    if (*destSize >= 0) {
                        ++*currentId;
                        SendAck(&m_packets[i]->ipx.source, id);
                    }

                    return ReceiveNextPacket(destSize, node, i);
                }

                /* we've got a fully assembled packet from fragments now */
                srcPtr = destBuf;
                size = *destSize;
            }
            ++*currentId;
            //WriteToLog("Increasing current id for node [%#.12s], id is %d now.", &m_packets[i]->ipx.source, *currentId);
        } else {
            /* we've already processed this one, get next */
            //WriteToLog("Discarding packet with ID %d (already processed, cur. id = %d)", id, *currentId);
            SendAck(&m_packets[i]->ipx.source, id);
            return ReceiveNextPacket(destSize, node, i);
        }
        break;

    case ACK_PACKET_SIG:
        if (size != 4)
            WriteToLog("Discarding ack packet with invalid size (%d)", size);
        else {
            AcknowledgePacket(*(dword *)srcPtr, &m_packets[i]->ipx.source);
        }

        return ReceiveNextPacket(destSize, node, i);

    case CANCEL_PARTIAL_SIG:
        if (size != sizeof(dword))
            WriteToLog("Received partial cancellation packet with invalid size: %d", size);
        else
            CancelFragmentedPacket(&m_packets[i]->ipx.source, *(dword *)srcPtr);
        return ReceiveNextPacket(destSize, node, i);
        break;

    default:
        WriteToLog("Invalid packet type: %#x", m_packets[i]->type);
        return ReceiveNextPacket(destSize, node, i);
    }

    if (!destBuf)
        destBuf = (char *)qAlloc(size);

    if (!destBuf) {
        *destSize = -1; /* signal memory exhaustion */
        return nullptr;
    }

    /* only ack if we're sure everything went well */
    if (m_packets[i]->type == PARTIAL_PACKET_SIG || m_packets[i]->type == IMPORTANT_PACKET_SIG)
        SendAck(&m_packets[i]->ipx.source, id);

    if (m_packets[i]->type != PARTIAL_PACKET_SIG) {
        *destSize = size;
        memcpy(destBuf, srcPtr, size);
    }

    //WriteToLog("Source address: [%#.12s]", node);
    //HexDumpToLog(m_packets[i], size + sizeof(SWOSPP_Packet), "received packet data");
    IPX_Listen((ECB *)m_packets[i]);
    return destBuf;
}
示例#3
0
TEST(Components, EncoderTest)
{
  RedBotEncoder leftEncoder(false);
  RedBotEncoder rightEncoder(true);

  Packet* packet0 = leftEncoder.getNextPacket();
  myPackets.push_back(packet0);

  CHECK(packet0 != NULL);
  CHECK(NULL != dynamic_cast<EncoderInputPacket*>(packet0));

  EncoderInputPacket* leftInputPacket = static_cast<EncoderInputPacket*>(packet0);

  CHECK_FALSE(leftInputPacket->isRight());

  Packet* packet1 = leftEncoder.getNextPacket();
  myPackets.push_back(packet1);

  CHECK_EQUAL((Packet*)NULL, packet1);

  Packet* packet2 = rightEncoder.getNextPacket();
  myPackets.push_back(packet2);

  CHECK(packet2 != NULL);
  CHECK(NULL != dynamic_cast<EncoderInputPacket*>(packet2));

  EncoderInputPacket* rightInputPacket = static_cast<EncoderInputPacket*>(packet2);

  CHECK(rightInputPacket->isRight());

  CHECK(leftEncoder.processPacket(EncoderCountPacket(false, 345)));
  CHECK_EQUAL(345, leftEncoder.Get());

  CHECK(leftEncoder.processPacket(EncoderCountPacket(false, 367)));
  CHECK_EQUAL(367, leftEncoder.Get());

  CHECK_FALSE(leftEncoder.processPacket(EncoderCountPacket(true, 203)));
  CHECK_EQUAL(367, leftEncoder.Get());

  CHECK_EQUAL(0, rightEncoder.Get());

  CHECK(rightEncoder.processPacket(EncoderCountPacket(true, -20)));
  CHECK_EQUAL(-20, rightEncoder.Get());

  CHECK_FALSE(rightEncoder.processPacket(AcknowledgePacket()));

  leftEncoder.Reset();

  Packet* packet3 = leftEncoder.getNextPacket();
  myPackets.push_back(packet3);

  CHECK(packet3 != NULL);
  CHECK(NULL != dynamic_cast<EncoderClearPacket*>(packet3));

  EncoderClearPacket* leftClearPacket = dynamic_cast<EncoderClearPacket*>(packet3);

  CHECK_FALSE(leftClearPacket->isRight());

  Packet* packet4 = leftEncoder.getNextPacket();
  myPackets.push_back(packet4);

  CHECK(packet4 != NULL);
  CHECK(NULL != dynamic_cast<EncoderInputPacket*>(packet4));

  rightEncoder.Reset();

  Packet* packet5 = rightEncoder.getNextPacket();
  myPackets.push_back(packet5);

  CHECK(packet5 != NULL);
  CHECK(NULL != dynamic_cast<EncoderClearPacket*>(packet5));

  EncoderClearPacket* rightClearPacket = dynamic_cast<EncoderClearPacket*>(packet5);

  CHECK(rightClearPacket->isRight());
}