CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

IPXCONN.CPP (29007B)


      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\ipxconn.cpv   1.9   16 Oct 1995 16:50:52   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 : IPXCONN.CPP                              *
     24  *                                                                         *
     25  *                   Programmer : Bill Randolph                            *
     26  *                                                                         *
     27  *                   Start Date : December 20, 1994                        *
     28  *                                                                         *
     29  *                  Last Update : April 9, 1995 [BRR]								*
     30  *                                                                         *
     31  *-------------------------------------------------------------------------*
     32  * Functions:    			                                                   *
     33  *   IPXConnClass::IPXConnClass -- class constructor           				*
     34  *   IPXConnClass::~IPXConnClass -- class destructor           				*
     35  *   IPXConnClass::Init -- hardware-specific initialization routine			*
     36  *   IPXConnClass::Configure -- One-time initialization routine				*
     37  *   IPXConnClass::Start_Listening -- commands IPX to listen               *
     38  *   IPXConnClass::Stop_Listening -- commands IPX to stop  listen          *
     39  *   IPXConnClass::Send -- sends a packet; invoked by SequencedConnection	*
     40  *   IPXConnClass::Open_Socket -- opens communications socket    				*
     41  *   IPXConnClass::Close_Socket -- closes the socket 								*
     42  *   IPXConnClass::Send_To -- sends the packet to the given address			*
     43  *   IPXConnClass::Broadcast -- broadcasts the given packet						*
     44  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     45 
     46 #include "function.h"
     47 #include "ipx95.h"
     48 #include "tcpip.h"
     49 
     50 /*
     51 ********************************* Globals ***********************************
     52 */
     53 unsigned short 	IPXConnClass::Socket;
     54 int			 		IPXConnClass::ConnectionNum;
     55 ECBType *			IPXConnClass::ListenECB;
     56 IPXHeaderType *	IPXConnClass::ListenHeader;
     57 char *				IPXConnClass::ListenBuf;
     58 ECBType *			IPXConnClass::SendECB;
     59 IPXHeaderType *	IPXConnClass::SendHeader;
     60 char *				IPXConnClass::SendBuf;
     61 long 					IPXConnClass::Handler;
     62 int 					IPXConnClass::Configured = 0;
     63 int 					IPXConnClass::SocketOpen = 0;
     64 int 					IPXConnClass::Listening = 0;
     65 int					IPXConnClass::PacketLen;
     66 
     67 
     68 /***************************************************************************
     69  * IPXConnClass::IPXConnClass -- class constructor             				*
     70  *                                                                         *
     71  * INPUT:                                                                  *
     72  *		numsend			desired # of entries for the send queue					*
     73  *		numreceive		desired # of entries for the recieve queue				*
     74  *		maxlen			max length of an application packet							*
     75  *		magicnum			the packet "magic number" for this connection			*
     76  *		address			address of destination (NULL = no address)				*
     77  *		id					connection's unique numerical ID								*
     78  *		name				connection's name													*
     79  *                                                                         *
     80  * OUTPUT:                                                                 *
     81  *		none.																						*
     82  *                                                                         *
     83  * WARNINGS:                                                               *
     84  *		none.																						*
     85  *                                                                         *
     86  * HISTORY:                                                                *
     87  *   12/20/1994 BR : Created.                                              *
     88  *=========================================================================*/
     89 IPXConnClass::IPXConnClass (int numsend, int numreceive, int maxlen,
     90 	unsigned short magicnum, IPXAddressClass *address, int id, char *name) :
     91 #ifdef SEQ_NET
     92 	SequencedConnClass (numsend, numreceive, maxlen, magicnum,
     93 #else
     94 	NonSequencedConnClass (numsend, numreceive, maxlen, magicnum,
     95 #endif
     96 		2,			// retry delta
     97 		-1,		// max retries
     98 		60)		// timeout
     99 {
    100 	NetNumType net;
    101 	NetNodeType node;
    102 
    103 	/*------------------------------------------------------------------------
    104 	Save the values passed in
    105 	------------------------------------------------------------------------*/
    106 	if (address)
    107 		Address = (*address);
    108 	ID = id;
    109 	strcpy (Name, name);
    110 
    111 	if (!Winsock.Get_Connected()){
    112 		/*------------------------------------------------------------------------
    113 		If our Address field is an actual address (ie NULL wasn't passed to the
    114 		constructor), pre-compute the ImmediateAddress value for the SendECB.
    115 		This allows pre-computing of the ImmediateAddress for all connections
    116 		created after Configure() is called.
    117 		------------------------------------------------------------------------*/
    118 		if (!Address.Is_Broadcast() && Configured==1) {
    119 			Address.Get_Address(net,node);
    120 			/*.....................................................................
    121 			If the user is logged in & has a valid Novell Connection Number, get the
    122 			bridge address the "official" way
    123 			.....................................................................*/
    124 			if (ConnectionNum != 0) {
    125 				if (IPX_Get_Local_Target (net, node, Socket, ImmediateAddress)!=0)
    126 					memcpy(ImmediateAddress,node,6);
    127 			} else {
    128 
    129 				/*.....................................................................
    130 				Otherwise, use the destination node address as the ImmediateAddress, and
    131 				just hope there's no network bridge in the path.
    132 				.....................................................................*/
    133 				memcpy(ImmediateAddress,node,6);
    134 			}
    135 
    136 			Immed_Set = 1;
    137 		} else {
    138 			memset (ImmediateAddress, 0, 6);
    139 			Immed_Set = 0;
    140 		}
    141 	}
    142 
    143 }	/* end of IPXConnClass */
    144 
    145 
    146 /***************************************************************************
    147  * IPXConnClass::Init -- hardware-specific initialization routine				*
    148  *                                                                         *
    149  * INPUT:                                                                  *
    150  *		none.																						*
    151  *                                                                         *
    152  * OUTPUT:                                                                 *
    153  *		none.																						*
    154  *                                                                         *
    155  * WARNINGS:                                                               *
    156  *		none.																						*
    157  *                                                                         *
    158  * HISTORY:                                                                *
    159  *   12/20/1994 BR : Created.                                              *
    160  *=========================================================================*/
    161 void IPXConnClass::Init (void)
    162 {
    163 	/*------------------------------------------------------------------------
    164 	Invoke the parent's Init routine
    165 	------------------------------------------------------------------------*/
    166 #ifdef SEQ_NET
    167 	SequencedConnClass::Init();
    168 #else
    169 	NonSequencedConnClass::Init();
    170 #endif
    171 }
    172 
    173 
    174 /***************************************************************************
    175  * IPXConnClass::Configure -- One-time initialization routine					*
    176  *                                                                         *
    177  * This routine sets up static members that are shared by all IPX				*
    178  * connections (ie those variables used by the Send/Listen/Broadcast			*
    179  * routines).																					*
    180  *																									*
    181  * INPUT:                                                                  *
    182  *		socket				socket ID for sending & receiving						*
    183  *		conn_num				local IPX Connection Number (0 = not logged in)		*
    184  *		listen_ecb			ptr to ECBType for listening								*
    185  *		send_ecb				ptr to ECBType for sending									*
    186  *		listen_header		ptr to IPXHeaderType for listening						*
    187  *		send_header			ptr to IPXHeaderType for sending							*
    188  *		listen_buf			ptr to buffer for listening								*
    189  *		send_buf				ptr to buffer for sending									*
    190  *		handler_rm_ptr		REAL-MODE pointer to event service routine			*
    191  *								(high word = segment, low word = offset)				*
    192  *		maxpacketlen		max packet size to listen for								*
    193  *                                                                         *
    194  * OUTPUT:                                                                 *
    195  *		none.																						*
    196  *                                                                         *
    197  * WARNINGS:                                                               *
    198  *		- All pointers must be protected-mode pointers, but must point to		*
    199  *		  DOS real-mode memory (except the Handler segment/offset)				*
    200  *                                                                         *
    201  * HISTORY:                                                                *
    202  *   12/20/1994 BR : Created.                                              *
    203  *=========================================================================*/
    204 void IPXConnClass::Configure (unsigned short socket, int conn_num,
    205 	ECBType *listen_ecb, ECBType *send_ecb, IPXHeaderType *listen_header,
    206 	IPXHeaderType *send_header, char *listen_buf, char *send_buf,
    207 	long handler_rm_ptr, int maxpacketlen)
    208 {
    209 	/*------------------------------------------------------------------------
    210 	Save the values passed in
    211 	------------------------------------------------------------------------*/
    212 	Socket = socket;
    213 	ConnectionNum = conn_num;
    214 	ListenECB = listen_ecb;
    215 	SendECB = send_ecb;
    216 	ListenHeader = listen_header;
    217 	SendHeader = send_header;
    218 	ListenBuf = listen_buf;
    219 	SendBuf = send_buf;
    220 	Handler = handler_rm_ptr;
    221 	PacketLen = maxpacketlen;
    222 
    223 	Configured = 1;
    224 
    225 }	/* end of Configure */
    226 
    227 
    228 /***************************************************************************
    229  * IPXConnClass::Start_Listening -- commands IPX to listen                 *
    230  *                                                                         *
    231  * This routine may be used to start listening in polled mode (if the 		*
    232  * ECB's Event_Service_Routine is NULL), or in interrupt mode; it's			*
    233  * up to the caller to fill the ECB in.  If in polled mode, Listening		*
    234  * must be restarted every time a packet comes in.									*
    235  *                                                                         *
    236  * INPUT:                                                                  *
    237  *		none.																						*
    238  *                                                                         *
    239  * OUTPUT:                                                                 *
    240  *		none.																						*
    241  *                                                                         *
    242  * WARNINGS:                                                               *
    243  *		- The ListenECB must have been properly filled in by the IPX Manager.*
    244  *		- Configure must be called before calling this routine.					*
    245  *                                                                         *
    246  * HISTORY:                                                                *
    247  *   12/16/1994 BR : Created.                                              *
    248  *=========================================================================*/
    249 bool IPXConnClass::Start_Listening(void)
    250 {
    251 
    252 #ifndef NOT_FOR_WIN95
    253 
    254 	if (Winsock.Get_Connected()) return (true);
    255 
    256 	/*------------------------------------------------------------------------
    257 	Open the Socket
    258 	------------------------------------------------------------------------*/
    259 	if (!Open_Socket(Socket))
    260 		return(false);
    261 
    262 	if (IPX_Start_Listening95()){
    263 		Listening =1;
    264 		return (TRUE);
    265 	}else{
    266 		return (FALSE);
    267 	}
    268 
    269 #else
    270 
    271 	void *hdr_ptr;
    272 	unsigned long hdr_val;
    273 	void *buf_ptr;
    274 	unsigned long buf_val;
    275 	int rc;
    276 
    277 	/*------------------------------------------------------------------------
    278 	Don't do a thing unless we've been configured, and we're not listening.
    279 	------------------------------------------------------------------------*/
    280 	if (Configured==0 || Listening==1)
    281 		return(false);
    282 
    283 	/*------------------------------------------------------------------------
    284 	Open the Socket
    285 	------------------------------------------------------------------------*/
    286 	if (!Open_Socket(Socket))
    287 		return(false);
    288 
    289 	/*------------------------------------------------------------------------
    290 	Clear the ECB & header
    291 	------------------------------------------------------------------------*/
    292 	memset(ListenECB, 0, sizeof(ECBType));
    293 	memset(ListenHeader, 0, sizeof(IPXHeaderType));
    294 
    295 	/*------------------------------------------------------------------------
    296 	Convert protected-mode ptrs to real-mode ptrs
    297 	------------------------------------------------------------------------*/
    298 	hdr_val = (unsigned long)ListenHeader;
    299 	hdr_ptr = (void *)(((hdr_val & 0xffff0) << 12) | (hdr_val & 0x000f));
    300 
    301 	buf_val = (unsigned long)ListenBuf;
    302 	buf_ptr = (void *)(((buf_val & 0xffff0) << 12) | (buf_val & 0x000f));
    303 
    304 	/*------------------------------------------------------------------------
    305 	Fill in the ECB
    306 	------------------------------------------------------------------------*/
    307 	ListenECB->SocketNumber = Socket;
    308 	ListenECB->PacketCount = 2;
    309 	ListenECB->Packet[0].Address = hdr_ptr;
    310 	ListenECB->Packet[0].Length = sizeof(IPXHeaderType);
    311 	ListenECB->Packet[1].Address = buf_ptr;
    312 	ListenECB->Packet[1].Length = (unsigned short)PacketLen;
    313 
    314 	((long &)ListenECB->Event_Service_Routine) = Handler;
    315 
    316 	/*------------------------------------------------------------------------
    317 	Command IPX to listen
    318 	------------------------------------------------------------------------*/
    319 	rc = IPX_Listen_For_Packet(ListenECB);
    320 	if (rc!=0) {
    321 		Close_Socket(Socket);
    322 		return(false);
    323 	} else {
    324 		Listening = 1;
    325 		return(true);
    326 	}
    327 
    328 #endif	//NOT_FOR_WIN95
    329 }	/* end of Start_Listening */
    330 
    331 
    332 /***************************************************************************
    333  * IPXConnClass::Stop_Listening -- commands IPX to stop  listen            *
    334  *                                                                         *
    335  * INPUT:                                                                  *
    336  *		none.																						*
    337  *                                                                         *
    338  * OUTPUT:                                                                 *
    339  *		none.																						*
    340  *                                                                         *
    341  * WARNINGS:                                                               *
    342  *		- This routine MUST NOT be called if IPX is not listening already!	*
    343  *                                                                         *
    344  * HISTORY:                                                                *
    345  *   12/16/1994 BR : Created.                                              *
    346  *=========================================================================*/
    347 bool IPXConnClass::Stop_Listening(void)
    348 {
    349 	/*------------------------------------------------------------------------
    350 	Don't do anything unless we're already Listening.
    351 	------------------------------------------------------------------------*/
    352 	if (Listening==0)
    353 		return(false);
    354 
    355 #ifndef NOT_FOR_WIN95
    356 
    357 	if (Winsock.Get_Connected()){
    358 		Listening = 0;
    359 		return (true);
    360 	}else{
    361 		IPX_Shut_Down95();
    362 		Close_Socket(Socket);
    363 	}
    364 
    365 #else	//NOT_FOR_WIN95
    366 
    367 	/*------------------------------------------------------------------------
    368 	Shut IPX down.
    369 	------------------------------------------------------------------------*/
    370 	IPX_Cancel_Event(ListenECB);
    371 	Close_Socket(Socket);
    372 
    373 #endif	//NOT_FOR_WIN95
    374 
    375 	Listening = 0;
    376 
    377 	/*------------------------------------------------------------------------
    378 	All done.
    379 	------------------------------------------------------------------------*/
    380 	return(true);
    381 
    382 }	/* end of Stop_Listening */
    383 
    384 
    385 /***************************************************************************
    386  * IPXConnClass::Send -- sends a packet; invoked by SequencedConnection		*
    387  *                                                                         *
    388  * INPUT:                                                                  *
    389  *		socket		desired socket ID number											*
    390  *                                                                         *
    391  * OUTPUT:                                                                 *
    392  *		1 = OK, 0 = error																		*
    393  *                                                                         *
    394  * WARNINGS:                                                               *
    395  *		none.																						*
    396  *                                                                         *
    397  * HISTORY:                                                                *
    398  *   12/16/1994 BR : Created.                                              *
    399  *=========================================================================*/
    400 int IPXConnClass::Send(char *buf, int buflen)
    401 {
    402 	/*------------------------------------------------------------------------
    403 	Invoke our own Send_To routine, filling in our Address as the destination.
    404 	------------------------------------------------------------------------*/
    405 	if (Immed_Set) {
    406 		return(Send_To (buf, buflen, &Address, ImmediateAddress));
    407 	} else {
    408 		return(Send_To (buf, buflen, &Address, NULL));
    409 	}
    410 
    411 }	/* end of Send */
    412 
    413 
    414 /***************************************************************************
    415  * IPXConnClass::Open_Socket -- opens communications socket    				*
    416  *                                                                         *
    417  * INPUT:                                                                  *
    418  *		socket		desired socket ID number											*
    419  *                                                                         *
    420  * OUTPUT:                                                                 *
    421  *		1 = OK, 0 = error																		*
    422  *                                                                         *
    423  * WARNINGS:                                                               *
    424  *		none.																						*
    425  *                                                                         *
    426  * HISTORY:                                                                *
    427  *   12/16/1994 BR : Created.                                              *
    428  *=========================================================================*/
    429 int IPXConnClass::Open_Socket(unsigned short socket)
    430 {
    431 	int rc;
    432 
    433 	if (Winsock.Get_Connected()){
    434 		SocketOpen = 1;
    435 		return (true);
    436 	}
    437 
    438 	SocketOpen = 0;
    439 
    440 	/*------------------------------------------------------------------------
    441 	Try to open a listen socket.  The socket may have been left open by
    442 	a previously-crashed program, so ignore the state of the SocketOpen
    443 	flag for this call; use IPX to determine if the socket was already open.
    444 	------------------------------------------------------------------------*/
    445 	rc = IPX_Open_Socket(socket);
    446 	if (rc) {
    447 		/*
    448 		................. If already open, close & reopen it ..................
    449 		*/
    450 		if (rc==IPXERR_SOCKET_ERROR) {
    451 			IPX_Close_Socket(socket);
    452 			rc = IPX_Open_Socket(socket);
    453 			/*
    454 			.................. Still can't open: return error ..................
    455 			*/
    456 			if (rc) {
    457 				return(false);
    458 			}
    459 		}
    460 	}
    461 
    462 	SocketOpen = 1;
    463 
    464 	return(true);
    465 }
    466 
    467 
    468 /***************************************************************************
    469  * IPXConnClass::Close_Socket -- closes the socket 								*
    470  *                                                                         *
    471  * INPUT:                                                                  *
    472  *		socket		desired socket ID number											*
    473  *                                                                         *
    474  * OUTPUT:                                                                 *
    475  *		none.																						*
    476  *                                                                         *
    477  * WARNINGS:                                                               *
    478  *		Calling this routine when the sockets aren't open may crash!			*
    479  *                                                                         *
    480  * HISTORY:                                                                *
    481  *   12/16/1994 BR : Created.                                              *
    482  *=========================================================================*/
    483 void IPXConnClass::Close_Socket(unsigned short socket)
    484 {
    485 	if (Winsock.Get_Connected()){
    486 		SocketOpen = 0;
    487 		return;
    488 	}
    489 	/*------------------------------------------------------------------------
    490 	Never, ever, ever, under any circumstances whatsoever, close a socket
    491 	that isn't open.  You'll regret it forever (or until at least until you're
    492 	through rebooting, which, if you're on a Pentium is the same thing).
    493 	------------------------------------------------------------------------*/
    494 	if (SocketOpen==1)
    495 		IPX_Close_Socket(socket);
    496 
    497 	SocketOpen = 0;
    498 
    499 }	/* end of Close_Socket */
    500 
    501 
    502 /***************************************************************************
    503  * IPXConnClass::Send_To -- sends the packet to the given address				*
    504  *                                                                         *
    505  * The "ImmediateAddress" field of the SendECB must be filled in with the	*
    506  * address of a bridge, or the node address of the destination if there		*
    507  * is no bridge.  The NETX call to find this address will always crash		*
    508  * if NETX isn't loaded (ConnectionNum is 0), so this case is trapped &		*
    509  * prevented.																					*
    510  * Also, if the address of this IPX connection is known when the 				*
    511  * constructor is called, and Configure has been called, Get_Local_Target 	*
    512  * is called to precompute the ImmediateAddress; this case is detected & 	*
    513  * if the value is already computed, it's just memcpy'd over.					*
    514  *                                                                         *
    515  * INPUT:                                                                  *
    516  *		buf			buffer to send															*
    517  *		buflen		length of buffer														*
    518  *		address		Address to send to													*
    519  *		immed			ImmediateAddress value, NULL if none							*
    520  *                                                                         *
    521  * OUTPUT:                                                                 *
    522  *		1 = OK, 0 = error																		*
    523  *                                                                         *
    524  * WARNINGS:                                                               *
    525  *		none.																						*
    526  *                                                                         *
    527  * HISTORY:                                                                *
    528  *   12/16/1994 BR : Created.                                              *
    529  *=========================================================================*/
    530 //#pragma off (unreferenced)
    531 int IPXConnClass::Send_To(char *buf, int buflen, IPXAddressClass *address,
    532 	NetNodeType immed)
    533 {
    534 
    535 	//void *hdr_ptr;
    536 	//void *buf_ptr;
    537 	//unsigned long hdr_val;
    538 	//unsigned long buf_val;
    539 	NetNumType net;
    540 	NetNodeType node;
    541 	int rc;
    542 
    543 	//unsigned short target_mask;
    544 
    545 	unsigned char	send_address[6];
    546 
    547 	if (Winsock.Get_Connected()){
    548 
    549 #ifdef VIRTUAL_SUBNET_SERVER
    550 		if (immed){
    551 			memcpy(send_address, immed, 6);
    552 		}else{
    553 			address->Get_Address(net,node);
    554 			memcpy (send_address, node, 6);
    555 		}
    556 		/*
    557 		** Use first two bytes of ipx address as target mask
    558 		*/
    559 		unsigned short *maskptr = (unsigned short*)&send_address[0];
    560 		target_mask = *maskptr;
    561 
    562 		char *tempsend = new char [buflen + sizeof (target_mask)];
    563 
    564 		*(unsigned short*)tempsend = htons(target_mask);
    565 		memcpy (tempsend+2, buf, buflen);
    566 #if (0)
    567 char tempbuf[256];
    568 CommHeaderType *packet = (CommHeaderType *)(&tempsend[2]);
    569 static char pcode [4][18]={
    570 	"PACKET_DATA_ACK",			// this is a data packet requiring an ACK
    571 	"PACKET_DATA_NOACK",		// this is a data packet not requiring an ACK
    572 	"PACKET_ACK",					// this is an ACK for a packet
    573 	"PACKET_COUNT"				// for computational purposes
    574 };
    575 
    576 sprintf (tempbuf, "Sending unicast packet type %d, ID=%d, code=%s, length=%d\n", tempsend[sizeof(CommHeaderType)+2],
    577 																						packet->PacketID,
    578 																						pcode[packet->Code],
    579 																						buflen + sizeof (target_mask));
    580 CCDebugString (tempbuf);
    581 #endif	//(0)
    582 
    583 		Winsock.Write((void*)tempsend, buflen + sizeof (target_mask));
    584 		delete [] tempsend;
    585 #else	// VIRTUAL_SUBNET_SERVER
    586 		Winsock.Write((void*)buf, buflen);
    587 #endif	// VIRTUAL_SUBNET_SERVER
    588 
    589 		return (true);
    590 	}
    591 
    592 
    593 
    594 	if (immed) {
    595 		memcpy(send_address, immed, 6);
    596 		//memcpy(node, immed, 6);
    597 		//memset (net, 0, sizeof(net) );
    598 		address->Get_Address(net,node);
    599 	} else {
    600 		address->Get_Address(net,node);
    601 		/*.....................................................................
    602 		If the user is logged in & has a valid Novell Connection Number, get the
    603 		bridge address the "official" way
    604 		.....................................................................*/
    605 		if (ConnectionNum != 0) {
    606 			rc = IPX_Get_Local_Target (net, node, Socket, &send_address[0]);
    607 			if (rc!=0) {
    608 				return(false);
    609 			}
    610 		} else {
    611 			/*.....................................................................
    612 			Otherwise, use the destination node address as the ImmediateAddress, and
    613 			just hope there's no network bridge in the path.
    614 			.....................................................................*/
    615 			memcpy(send_address,node,6);
    616 		}
    617 	}
    618 
    619 	return (IPX_Send_Packet95(&send_address[0], (unsigned char*)buf, buflen, (unsigned char*)net, (unsigned char*)node));
    620 
    621 
    622 }
    623 //#pragma on (unreferenced)
    624 
    625 /***************************************************************************
    626  * IPXConnClass::Broadcast -- broadcasts the given packet						*
    627  *                                                                         *
    628  * INPUT:                                                                  *
    629  *		socket		desired socket ID number											*
    630  *                                                                         *
    631  * OUTPUT:                                                                 *
    632  *		1 = OK, 0 = error																		*
    633  *                                                                         *
    634  * WARNINGS:                                                               *
    635  *		none.																						*
    636  *                                                                         *
    637  * HISTORY:                                                                *
    638  *   12/16/1994 BR : Created.                                              *
    639  *=========================================================================*/
    640 int IPXConnClass::Broadcast(char *buf, int buflen)
    641 {
    642 
    643 	if (Winsock.Get_Connected()){
    644 #ifdef VIRTUAL_SUBNET_SERVER
    645 		char *tempsend = new char [buflen + sizeof (unsigned short)];
    646 		memcpy (tempsend+2, buf, buflen);
    647 		*tempsend = 0;
    648 		*(tempsend+1) = 0;
    649 #if (0)
    650 char tempbuf[256];
    651 CommHeaderType *packet = (CommHeaderType *)(&tempsend[2]);
    652 static char pcode [4][18]={
    653 	"PACKET_DATA_ACK",			// this is a data packet requiring an ACK
    654 	"PACKET_DATA_NOACK",		// this is a data packet not requiring an ACK
    655 	"PACKET_ACK",					// this is an ACK for a packet
    656 	"PACKET_COUNT"				// for computational purposes
    657 };
    658 
    659 sprintf (tempbuf, "Sending multicast packet type %d, ID=%d, code=%s, length=%d\n", tempsend[sizeof(CommHeaderType)+2],
    660 																						packet->PacketID,
    661 																						pcode[packet->Code],
    662 																						buflen + sizeof (unsigned short));
    663 CCDebugString (tempbuf);
    664 #endif	//(0)
    665 
    666 		Winsock.Write((void*)tempsend, buflen + sizeof (unsigned short));
    667 		delete [] tempsend;
    668 #else	// VIRTUAL_SUBNET_SERVER
    669 		Winsock.Write((void*)buf, buflen);
    670 #endif	// VIRTUAL_SUBNET_SERVER
    671 		return(true);
    672 	}else{
    673 		return (IPX_Broadcast_Packet95((unsigned char*)buf, buflen));
    674 	}
    675 
    676 }
    677