CONNECT.H (17916B)
1 // 2 // Copyright 2020 Electronic Arts Inc. 3 // 4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 5 // software: you can redistribute it and/or modify it under the terms of 6 // the GNU General Public License as published by the Free Software Foundation, 7 // either version 3 of the License, or (at your option) any later version. 8 9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 10 // in the hope that it will be useful, but with permitted additional restrictions 11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 // distributed with this program. You should have received a copy of the 13 // GNU General Public License along with permitted additional restrictions 14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection 15 16 /* $Header: F:\projects\c&c\vcs\code\connect.h_v 1.12 16 Oct 1995 16:46:04 JOE_BOSTIC $ */ 17 /*************************************************************************** 18 ** 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 ** 19 *************************************************************************** 20 * * 21 * Project Name : Command & Conquer * 22 * * 23 * File Name : CONNECT.H * 24 * * 25 * Programmer : Bill Randolph * 26 * * 27 * Start Date : December 19, 1994 * 28 * * 29 * Last Update : April 1, 1995 [BR] * 30 * * 31 *-------------------------------------------------------------------------* 32 * * 33 * DESCRIPTION: * 34 * This class represents a single "connection" with another system. It's * 35 * a pure virtual base class that acts as a framework for other classes. * 36 * * 37 * This class contains a CommQueueClass member, which stores received * 38 * & transmitted packets. The ConnectionClass has virtual functions to * 39 * handle adding packets to the queue, reading them from the queue, * 40 * a Send routine for actually sending data, and a Receive_Packet function * 41 * which is used to tell the connection that a new packet has come in. * 42 * * 43 * The virtual Service routine will handle all ACK & Retry logic for * 44 * communicating between this system & another. Thus, any class derived * 45 * from this class must provide the basic ACK/Retry logic. * 46 * * 47 * THE HEADER: * 48 * The Connection Classes prefix every packet sent with a header that's * 49 * local to this class. The header contains a "Magic Number" which should * 50 * be unique for each product, and Packet "Code", which will tell the * 51 * receiving end if this is DATA, or an ACK packet, and a packet ID, which * 52 * is a unique numerical ID for this packet (useful for detecting resends).* 53 * The header is stored with each packet in the send & receive Queues; * 54 * it's removed before it's passed back to the application, via * 55 * Get_Packet() * 56 * * 57 * THE CONNECTION MANAGER: * 58 * It is assumed that there will be a "Connection Manager" class which * 59 * will handle parsing incoming packets; it will then tell the connection * 60 * that new packets have come in, and the connection will process them in * 61 * whatever way it needs to for its protocol (check for resends, handle * 62 * ACK packets, etc). The job of the connection manager is to parse * 63 * incoming packets & distribute them to the connections that need to * 64 * store them (for multi-connection protocols). * 65 * * 66 * NOTES ON ACK/RETRY: * 67 * The packet's ID is used to check for re-sends. The ID is set to the * 68 * Queue's total Send Count; if the receiving system checks this value, * 69 * and it's less than that system's Receive Count, this is a resend. * 70 * (ie packet 0 will be the 1st packet sent, since the Send Queue's count * 71 * is 0 when it's sent; as soon as it's received, the Receive Count goes * 72 * up to 1, and an ID of 0 then means a resend.) This scheme keeps the * 73 * application from seeing the same packet twice. All the Connection * 74 * Manager has to do is mark the resent packet as non-ACK'd. Of course, * 75 * the Manager doesn't have to use this value at all. * 76 * * 77 * Both DATA_ACK packets and DATA_NOACK packets must go through the Send * 78 * Queue when "sent", so that the SendTotal value for this system * 79 * will still match the ReceiveTotal value for the other system; this is * 80 * why a NOACK packet can't just be sent immediately; it must go through * 81 * the queue. * 82 * * 83 * If the protocol being used already guarantees delivery of packets, * 84 * no ACK is required for the packets. In this case, the connection * 85 * class for this protocol can overload the Service routine to avoid * 86 * sending ACK packets, or the Connection Manager can just mark the * 87 * packet as ACK'd when it adds it to the Receive Queue for the connection.* 88 * * 89 * Derived classes must provide: * 90 * - Init a version of Init that gives the connection * 91 * access to any hardware-specific values it needs * 92 * Must chain to the parent's Init routine. * 93 * - Send_Packet adds the CommHeaderType header, adds the packet * 94 * to the out-going queue * 95 * - Receive_Packet processes incoming ACK packets, detects resends,* 96 * adds new packets to the in-coming queue * 97 * - Get_Packet reads the next-available packet from the * 98 * receive queue * 99 * - Send the hardware-dependent data-sending routine * 100 * - Service_Send_Queue services the send queue; handles re-sends, * 101 * detects when outgoing packets have been ACK'd; * 102 * cleans out the queue of old packets * 103 * - Service_Receive_Queue services the receive queue; handles sending * 104 * ACK's for new or re-sent packets; cleans out * 105 * the queue of old packets * 106 * * 107 * Any other routines can be overloaded as the derived class needs. * 108 * * 109 * CLASS HIERARCHY: * 110 * ConnectionClass * 111 * | * 112 * | * 113 * -------------------------------------- * 114 * | | * 115 * | | * 116 * SequencedConnClass NonSequencedConnClass * 117 * | | * 118 * | | * 119 * IPXConnClass ------------------------ * 120 * | | | * 121 * | | | * 122 * IPXGlobalConnClass NullModemConnClass ModemConnClass * 123 * * 124 * * 125 * ConnectionClass: * 126 * Abstract base class. * 127 * Provides: Queue for sent/recv'd packets * 128 * PacketBuf for preparing packets * 129 * Timeout variables * 130 * Service() routine * 131 * * 132 * SequencedConnClass: * 133 * Abstract base class * 134 * Provides: * "Sequenced" ACK/Retry logic, in Service_Send_Queue() & * 135 * Service_Receive_Queue() routines * 136 * * Send_Packet(): adds header to packet, adds it to Queue * 137 * * Receive_Packet(): adds incoming packet to receive Queue, * 138 * handles incoming ACK's & resends * 139 * * Get_Packet(): gets packet from the receive queue * 140 * * 141 * NonSequencedConnClass: * 142 * Abstract base class * 143 * Provides: * "Non-Sequenced" ACK/Retry logic, in Service_Send_Queue() * 144 * & Service_Receive_Queue() routines * 145 * * Send_Packet(): adds header to packet, adds it to Queue * 146 * * Receive_Packet(): adds incoming packet to receive Queue, * 147 * handles incoming ACK's & resends * 148 * * Get_Packet(): gets packet from the receive queue * 149 * * 150 * IPXConnClass: * 151 * Provides: * Hardware-dependent IPX interface routines, which allow * 152 * Service_Send_Queue() & Service_Receive_Queue() to do * 153 * their job * 154 * * Ability to associate an IPX Address, a numerical ID, and * 155 * a character-string Name with a connection * 156 * Inherits: * Sequenced ACK/Retry logic, Service routines, Queue & * 157 * PacketBuf, timeout variables * 158 * * 159 * IPXGlobalConnClass: * 160 * Special type of IPX Connection; supports receiving packets from * 161 * multiple systems at once, and sending packets via Broadcast or * 162 * to a specific address. * 163 * Provides: * Specialized Receive_Packet() routine, which handles * 164 * receiving packets from multiple systems * 165 * * Specialized Send_Packet() & Get_Packet() routines, * 166 * which pass IPX address of destination through to * 167 * the application, giving the application control over * 168 * whether the packet will be Broadcast or sent to a * 169 * specific destination (embeds destination address within * 170 * the packet itself) * 171 * * Specialized Send routine, which extracts the destination * 172 * address from the packet * 173 * Inherits: * Sequenced ACK/Retry logic, Service routines, Queue & * 174 * PacketBuf, timeout variables, IPX-specific routines * 175 * * 176 * NullModemConnClass: * 177 * Provides: * Hardware-dependent Serial-communication routines, which * 178 * allow Service_Send_Queue() & Service_Receive_Queue() to * 179 * do their job * 180 * Inherits: * Non-Sequenced ACK/Retry logic, Service routines, Queue & * 181 * PacketBuf, timeout variables * 182 * * 183 * ModemConnClass: * 184 * Provides: * Hardware-dependent Modem-communication routines, which * 185 * allow Service_Send_Queue() & Service_Receive_Queue() to * 186 * do their job * 187 * Inherits: * Non-Sequenced ACK/Retry logic, Service routines, Queue & * 188 * PacketBuf, timeout variables * 189 * * 190 * So, do ya think this header is long enough, or what? * 191 * * 192 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 193 194 #ifndef CONNECTION_H 195 #define CONNECTION_H 196 197 #define CONN_DEBUG 0 198 199 /* 200 ********************************** Defines ********************************** 201 */ 202 /*--------------------------------------------------------------------------- 203 This structure is the header prefixed to any packet sent by the application. 204 MagicNumber: This is a number unique to the application; it's up to the 205 Receive_Packet routine to check this value, to be sure we're 206 not getting data from some other product. This value should 207 be unique for each application. 208 Code: This will be one of the below-defined codes. 209 PacketID: This is a unique numerical ID for this packet. The Connection 210 sets this ID on all packets sent out. 211 ---------------------------------------------------------------------------*/ 212 typedef struct { 213 unsigned short MagicNumber; 214 unsigned char Code; 215 unsigned long PacketID; 216 } CommHeaderType; 217 218 219 /* 220 ***************************** Class Declaration ***************************** 221 */ 222 class ConnectionClass 223 { 224 /* 225 ---------------------------- Public Interface ---------------------------- 226 */ 227 public: 228 /*..................................................................... 229 These are the possible values for the Code field of the CommHeaderType: 230 .....................................................................*/ 231 enum ConnectionEnum { 232 PACKET_DATA_ACK, // this is a data packet requiring an ACK 233 PACKET_DATA_NOACK, // this is a data packet not requiring an ACK 234 PACKET_ACK, // this is an ACK for a packet 235 PACKET_COUNT, // for computational purposes 236 }; 237 238 /*..................................................................... 239 Constructor/destructor. 240 .....................................................................*/ 241 ConnectionClass (int maxlen, unsigned short magicnum, 242 unsigned long retry_delta, unsigned long max_retries, 243 unsigned long timeout); 244 virtual ~ConnectionClass (); 245 246 /*..................................................................... 247 Initialization. 248 .....................................................................*/ 249 virtual void Init (void) {}; 250 251 /*..................................................................... 252 Send/Receive routines. 253 .....................................................................*/ 254 virtual int Send_Packet (void * buf, int buflen, int ack_req) = 0; 255 virtual int Receive_Packet (void * buf, int buflen) = 0; 256 virtual int Get_Packet (void * buf, int * buflen) = 0; 257 258 /*..................................................................... 259 The main polling routine for the connection. Should be called as often 260 as possible. 261 .....................................................................*/ 262 virtual int Service (void); 263 264 /*..................................................................... 265 This routine is used by the retry logic; returns the current time in 266 60ths of a second. 267 .....................................................................*/ 268 static unsigned long Time (void); 269 270 /*..................................................................... 271 Utility routines. 272 .....................................................................*/ 273 unsigned short Magic_Num (void) { return (MagicNum); } 274 unsigned long Retry_Delta (void) { return (RetryDelta); } 275 void Set_Retry_Delta (unsigned long delta) { RetryDelta = delta;} 276 unsigned long Max_Retries (void) { return (MaxRetries); } 277 void Set_Max_Retries (unsigned long retries) { MaxRetries = retries;} 278 unsigned long Time_Out (void) { return (Timeout); } 279 void Set_TimeOut (unsigned long t) { Timeout = t;} 280 unsigned long Max_Packet_Len (void) { return (MaxPacketLen); } 281 static char * Command_Name(int command); 282 283 /* 284 -------------------------- Protected Interface --------------------------- 285 */ 286 protected: 287 /*..................................................................... 288 Routines to service the Send & Receive queues. 289 .....................................................................*/ 290 virtual int Service_Send_Queue(void) = 0; 291 virtual int Service_Receive_Queue(void) = 0; 292 293 /*..................................................................... 294 This routine actually performs a hardware-dependent data send. It's 295 pure virtual, so it >must< be defined by a derived class. 296 .....................................................................*/ 297 virtual int Send(char *buf, int buflen) = 0; 298 299 /*..................................................................... 300 This is the maximum packet length, including our own internal header. 301 .....................................................................*/ 302 int MaxPacketLen; 303 304 /*..................................................................... 305 Packet staging area; this is where the CommHeaderType gets tacked onto 306 the application's packet before it's sent. 307 .....................................................................*/ 308 char *PacketBuf; 309 310 /*..................................................................... 311 This is the magic number assigned to this connection. It is the first 312 few bytes of any transmission. 313 .....................................................................*/ 314 unsigned short MagicNum; 315 316 /*..................................................................... 317 This value determines the time delay before a packet is re-sent. 318 .....................................................................*/ 319 unsigned long RetryDelta; 320 321 /*..................................................................... 322 This is the maximum number of retries allowed for a packet; if this 323 value is exceeded, the connection is probably broken. 324 .....................................................................*/ 325 unsigned long MaxRetries; 326 327 /*..................................................................... 328 This is the total timeout for this connection; if this time is exceeded 329 on a packet, the connection is probably broken. 330 .....................................................................*/ 331 unsigned long Timeout; 332 333 /*..................................................................... 334 Names of all packet commands 335 .....................................................................*/ 336 static char *ConnectionClass::Commands[PACKET_COUNT]; 337 }; 338 339 #endif 340