| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531 |
- //
- // Copyright 2020 Electronic Arts Inc.
- //
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
- // software: you can redistribute it and/or modify it under the terms of
- // the GNU General Public License as published by the Free Software Foundation,
- // either version 3 of the License, or (at your option) any later version.
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
- // in the hope that it will be useful, but with permitted additional restrictions
- // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
- // distributed with this program. You should have received a copy of the
- // GNU General Public License along with permitted additional restrictions
- // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
- /* $Header: /CounterStrike/IPXGCONN.CPP 3 10/13/97 2:20p Steve_t $ */
- /***************************************************************************
- ** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
- ***************************************************************************
- * *
- * Project Name : Command & Conquer *
- * *
- * File Name : IPXGCONN.CPP *
- * *
- * Programmer : Bill Randolph *
- * *
- * Start Date : December 20, 1994 *
- * *
- * Last Update : July 6, 1995 [BRR] *
- *-------------------------------------------------------------------------*
- * Functions: *
- * IPXGlobalConnClass::IPXGlobalConnClass -- class constructor *
- * IPXGlobalConnClass::~IPXGlobalConnClass -- class destructor *
- * IPXGlobalConnClass::Send_Packet -- adds a packet to the send queue *
- * IPXGlobalConnClass::Receive_Packet -- adds packet to the receive queue*
- * IPXGlobalConnClass::Get_Packet -- gets a packet from the receive queue*
- * IPXGlobalConnClass::Send -- sends a packet *
- * IPXGlobalConnClass::Service_Receive_Queue -- services receive queue *
- * IPXGlobalConnClass::Set_Bridge -- Sets up connection to cross a bridge*
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "function.h"
- #include <stdio.h>
- //#include <mem.h>
- #include "ipxgconn.h"
- /***************************************************************************
- * IPXGlobalConnClass::IPXGlobalConnClass -- class constructor *
- * *
- * This routine chains to the parent constructor, but it adjusts the size *
- * of the packet by the added bytes in the GlobalHeaderType structure. *
- * This forces the parent classes to allocate the proper sized PacketBuf *
- * for outgoing packets, and to set MaxPacketLen to the proper value. *
- * *
- * INPUT: *
- * numsend desired # of entries for the send queue *
- * numreceive desired # of entries for the receive queue *
- * maxlen max length of an application packet *
- * product_id unique ID for this product *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 12/20/1994 BR : Created. *
- *=========================================================================*/
- IPXGlobalConnClass::IPXGlobalConnClass (int numsend, int numreceive,
- int maxlen, unsigned short product_id) :
- IPXConnClass (numsend, numreceive,
- maxlen + sizeof(GlobalHeaderType) - sizeof(CommHeaderType),
- GLOBAL_MAGICNUM, // magic number for this connection
- NULL, // IPX Address (none)
- 0, // Connection ID
- "", // Connection Name
- sizeof (IPXAddressClass)) // extra storage for the sender's address
- {
- int i;
- ProductID = product_id;
- IsBridge = 0;
- for (i = 0; i < 4; i++) {
- LastPacketID[i] = 0xffffffff;
- }
- LastRXIndex = 0;
- } /* end of IPXGlobalConnClass */
- /***************************************************************************
- * IPXGlobalConnClass::Send_Packet -- adds a packet to the send queue *
- * *
- * This routine prefixes the given buffer with a GlobalHeaderType and *
- * queues the resulting packet into the Send Queue. The packet's *
- * MagicNumber, Code, PacketID, destination Address and ProductID are set *
- * here. *
- * *
- * INPUT: *
- * buf buffer to send *
- * buflen length of buffer *
- * address address to send the packet to (NULL = Broadcast) *
- * ack_req 1 = ACK is required for this packet; 0 = isn't *
- * *
- * OUTPUT: *
- * 1 = OK, 0 = error *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 12/20/1994 BR : Created. *
- *=========================================================================*/
- int IPXGlobalConnClass::Send_Packet (void * buf, int buflen,
- IPXAddressClass *address, int ack_req)
- {
- IPXAddressClass dest_addr;
- /*------------------------------------------------------------------------
- Store the packet's Magic Number
- ------------------------------------------------------------------------*/
- ((GlobalHeaderType *)PacketBuf)->Header.MagicNumber = MagicNum;
- /*------------------------------------------------------------------------
- If this is a ACK-required packet, sent to a specific system, mark it as
- ACK-required; otherwise, mark as no-ACK-required.
- ------------------------------------------------------------------------*/
- if (ack_req && address != NULL) {
- ((GlobalHeaderType *)PacketBuf)->Header.Code = PACKET_DATA_ACK;
- }
- else {
- ((GlobalHeaderType *)PacketBuf)->Header.Code = PACKET_DATA_NOACK;
- }
- /*------------------------------------------------------------------------
- Fill in the packet ID. This will have very limited meaning; it only
- allows us to determine if an ACK packet we receive later goes with this
- packet; it doesn't let us detect re-sends of other systems' packets.
- ------------------------------------------------------------------------*/
- ((GlobalHeaderType *)PacketBuf)->Header.PacketID = Queue->Send_Total();
- /*------------------------------------------------------------------------
- Set the product ID for this packet.
- ------------------------------------------------------------------------*/
- ((GlobalHeaderType *)PacketBuf)->ProductID = ProductID;
- /*------------------------------------------------------------------------
- Set this packet's destination address. If no address is specified, use
- a Broadcast address (which IPXAddressClass's default constructor creates).
- ------------------------------------------------------------------------*/
- if (address != NULL) {
- dest_addr = (*address);
- }
- /*------------------------------------------------------------------------
- Copy the application's data
- ------------------------------------------------------------------------*/
- memcpy(PacketBuf + sizeof(GlobalHeaderType), buf, buflen);
- /*------------------------------------------------------------------------
- Queue it, along with the destination address
- ------------------------------------------------------------------------*/
- return(Queue->Queue_Send(PacketBuf,buflen + sizeof(GlobalHeaderType),
- &dest_addr, sizeof (IPXAddressClass)));
- } /* end of Send_Packet */
- /***************************************************************************
- * IPXGlobalConnClass::Receive_Packet -- adds packet to the receive queue *
- * *
- * INPUT: *
- * buf buffer to process (already includes GlobalHeaderType) *
- * buflen length of buffer to process *
- * address the address of the sender (the IPX Manager class must *
- * extract this from the IPX Header of the received packet.) *
- * *
- * OUTPUT: *
- * 1 = OK, 0 = error *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 12/20/1994 BR : Created. *
- *=========================================================================*/
- int IPXGlobalConnClass::Receive_Packet (void * buf, int buflen,
- IPXAddressClass *address)
- {
- GlobalHeaderType *packet; // ptr to this packet
- SendQueueType *send_entry; // ptr to send entry header
- GlobalHeaderType *entry_data; // ptr to queue entry data
- GlobalHeaderType ackpacket; // ACK packet to send
- int i;
- int resend;
- /*------------------------------------------------------------------------
- Check the magic #
- ------------------------------------------------------------------------*/
- packet = (GlobalHeaderType *)buf;
- if (packet->Header.MagicNumber!=MagicNum) {
- return(0);
- }
- /*------------------------------------------------------------------------
- Process the packet based on its Code
- ------------------------------------------------------------------------*/
- switch (packet->Header.Code) {
- //.....................................................................
- // DATA_ACK: Check for a resend by comparing the source address &
- // ID of this packet with our last 4 received packets.
- // Send an ACK for the packet, regardless of whether it's a resend
- // or not.
- //.....................................................................
- case PACKET_DATA_ACK:
- {
- //..................................................................
- // Check for a resend
- //..................................................................
- resend = 0;
- for (i = 0; i < 4; i++) {
- if ((unsigned int)i >= Queue->Receive_Total()) {
- break;
- }
- if ((*address)==LastAddress[i] &&
- packet->Header.PacketID==LastPacketID[i]) {
- resend = 1;
- break;
- }
- }
- bool send_ack = true;
- //..................................................................
- // If it's not a resend, queue it; then, record the sender's address
- // & the packet ID for future resend detection.
- //..................................................................
- if (!resend) {
- if (Queue->Queue_Receive (buf, buflen, address, sizeof(IPXAddressClass))) {
- LastAddress[LastRXIndex] = (*address);
- LastPacketID[LastRXIndex] = packet->Header.PacketID;
- LastRXIndex++;
- if (LastRXIndex >= 4) {
- LastRXIndex = 0;
- }
- }else{
- //..................................................................
- // Don't send an ack if we didn't have room to store the packet.
- //..................................................................
- send_ack = false;
- }
- }
- //..................................................................
- // Send an ACK for this packet
- //..................................................................
- if (send_ack) {
- ackpacket.Header.MagicNumber = MagicNum;
- ackpacket.Header.Code = PACKET_ACK;
- ackpacket.Header.PacketID = packet->Header.PacketID;
- ackpacket.ProductID = ProductID;
- Send ((char *)&ackpacket, sizeof(GlobalHeaderType),
- address, sizeof(IPXAddressClass));
- }
- break;
- }
- /*.....................................................................
- DATA_NOACK: Queue this message, along with the sender's address.
- Don't bother checking for a Re-Send, since the other system will only
- send this packet once.
- .....................................................................*/
- case PACKET_DATA_NOACK:
- Queue->Queue_Receive (buf, buflen, address, sizeof(IPXAddressClass));
- break;
- /*.....................................................................
- ACK: If this ACK is for any of my packets, mark that packet as
- acknowledged, then throw this packet away. Otherwise, ignore the ACK
- (if we re-sent before we received the other system's first ACK, this
- ACK will be a leftover)
- .....................................................................*/
- case PACKET_ACK:
- for (i = 0; i < Queue->Num_Send(); i++) {
- /*...............................................................
- Get queue entry ptr
- ...............................................................*/
- send_entry = Queue->Get_Send(i);
- /*...............................................................
- If ptr is valid, get ptr to its data
- ...............................................................*/
- entry_data = (GlobalHeaderType *)(send_entry->Buffer);
- /*...............................................................
- If ACK is for this entry, mark it
- ...............................................................*/
- if (packet->Header.PacketID==entry_data->Header.PacketID &&
- entry_data->Header.Code == PACKET_DATA_ACK) {
- send_entry->IsACK = 1;
- break;
- }
- }
- break;
- /*.....................................................................
- Default: ignore the packet
- .....................................................................*/
- default:
- break;
- }
- return(1);
- } /* end of Receive_Packet */
- /***************************************************************************
- * IPXGlobalConnClass::Get_Packet -- gets a packet from the receive queue *
- * *
- * INPUT: *
- * buf location to store buffer *
- * buflen filled in with length of 'buf' *
- * address filled in with sender's address *
- * product_id filled in with sender's ProductID *
- * *
- * OUTPUT: *
- * 1 = OK, 0 = error *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 12/20/1994 BR : Created. *
- *=========================================================================*/
- int IPXGlobalConnClass::Get_Packet (void * buf, int *buflen,
- IPXAddressClass *address, unsigned short *product_id)
- {
- ReceiveQueueType *rec_entry; // ptr to receive entry header
- GlobalHeaderType *packet;
- int packetlen; // size of received packet
- /*------------------------------------------------------------------------
- Return if nothing to do
- ------------------------------------------------------------------------*/
- if (Queue->Num_Receive() == 0) {
- return(0);
- }
- /*------------------------------------------------------------------------
- Get ptr to the next available entry
- ------------------------------------------------------------------------*/
- rec_entry = Queue->Get_Receive(0);
- /*------------------------------------------------------------------------
- Read it if it's un-read
- ------------------------------------------------------------------------*/
- if (rec_entry!=NULL && rec_entry->IsRead==0) {
- /*.....................................................................
- Mark as read
- .....................................................................*/
- rec_entry->IsRead = 1;
- /*.....................................................................
- Copy data packet
- .....................................................................*/
- packet = (GlobalHeaderType *)(rec_entry->Buffer);
- packetlen = rec_entry->BufLen - sizeof(GlobalHeaderType);
- if (packetlen > 0) {
- memcpy(buf, rec_entry->Buffer + sizeof(GlobalHeaderType), packetlen);
- }
- (*buflen) = packetlen;
- (*product_id) = packet->ProductID;
- (*address) = (*((IPXAddressClass *)(rec_entry->ExtraBuffer)));
- return(1);
- }
- return(0);
- } /* end of Get_Packet */
- /***************************************************************************
- * IPXGlobalConnClass::Send -- sends a packet *
- * *
- * This routine gets invoked by NonSequencedConn, when it's processing *
- * the Send & Receive Queues. The buffer provided will already have the *
- * GlobalHeaderType header embedded in it. *
- * *
- * INPUT: *
- * buf buffer to send *
- * buflen length of buffer *
- * extrabuf extra buffer to send *
- * extralen length of extra buffer *
- * *
- * OUTPUT: *
- * 1 = OK, 0 = error *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 12/20/1994 BR : Created. *
- *=========================================================================*/
- int IPXGlobalConnClass::Send(char *buf, int buflen, void *extrabuf, int )
- {
- IPXAddressClass *addr;
- int rc;
- /*------------------------------------------------------------------------
- Extract the packet's embedded IPX address
- ------------------------------------------------------------------------*/
- addr = (IPXAddressClass *)extrabuf;
- /*------------------------------------------------------------------------
- If it's a broadcast address, broadcast it
- ------------------------------------------------------------------------*/
- if (addr->Is_Broadcast()) {
- return(Broadcast (buf, buflen));
- }
- /*------------------------------------------------------------------------
- Otherwise, send it
- ------------------------------------------------------------------------*/
- else {
- if (IsBridge && !memcmp (addr, BridgeNet, 4)) {
- rc = Send_To (buf, buflen, addr, BridgeNode);
- }
- else {
- rc = Send_To (buf, buflen, addr, NULL);
- }
- return (rc);
- }
- } /* end of Send */
- /***************************************************************************
- * IPXGlobalConnClass::Service_Receive_Queue -- services the receive queue *
- * *
- * This routine is necessary because the regular ConnectionClass checks *
- * for sequential packet ID's before removing them from the receive queue; *
- * this class cannot do that. *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * 1 = OK, 0 = error *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 12/20/1994 BR : Created. *
- *=========================================================================*/
- int IPXGlobalConnClass::Service_Receive_Queue (void)
- {
- int i;
- ReceiveQueueType *rec_entry; // ptr to receive entry header
- //------------------------------------------------------------------------
- // Remove all dead packets: If a packet's been read, throw it away.
- //------------------------------------------------------------------------
- for (i = 0; i < Queue->Num_Receive(); i++) {
- rec_entry = Queue->Get_Receive(i);
- if (rec_entry->IsRead) {
- Queue->UnQueue_Receive(NULL,NULL,i,NULL,NULL);
- i--;
- }
- }
- return (1);
- } /* end of Service_Receive_Queue */
- /***************************************************************************
- * Set_Bridge -- Sets up connection to cross a bridge *
- * *
- * This routine is designed to prevent the connection from having to *
- * call Get_Local_Target, except the minimum number of times, since that *
- * routine is buggy & goes away for long periods sometimes. *
- * *
- * INPUT: *
- * bridge network number of the destination bridge *
- * *
- * OUTPUT: *
- * none *
- * *
- * WARNINGS: *
- * none *
- * *
- * HISTORY: *
- * 07/06/1995 BRR : Created. *
- *=========================================================================*/
- void IPXGlobalConnClass::Set_Bridge(NetNumType bridge)
- {
- #ifdef WINSOCK_IPX
- if (Configured) {
- bridge = bridge;
- IsBridge = 0;
- }
- #else //WINSOCK_IPX
- if (Configured) {
- memcpy (BridgeNet, bridge, 4);
- memset (BridgeNode, 0xff, 6);
- if (IPX_Get_Local_Target (BridgeNet, BridgeNode, Socket, BridgeNode)==0) {
- IsBridge = 1;
- }
- else {
- IsBridge = 0;
- }
- }
- #endif //WINSOCK_IPX
- } /* end of Set_Bridge */
- /************************** end of ipxgconn.cpp ****************************/
|