CnC_Remastered_Collection

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

IPXCONN.CPP (34946B)


      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: /CounterStrike/IPXCONN.CPP 1     3/03/97 10:24a 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 
     47 #include "function.h"
     48 #include <stdio.h>
     49 //#include <mem.h>
     50 #include <string.h>
     51 #include "ipxconn.h"
     52 
     53 #ifdef WINSOCK_IPX
     54 #include "WSProto.h"
     55 
     56 #else
     57 
     58 #include "ipx95.h"
     59 #ifdef WIN32
     60 #include "tcpip.h"
     61 #else	//WIN32
     62 #include "fakesock.h"
     63 #endif	//WIN32
     64 #endif	//WINSOCK_IPX
     65 
     66 
     67 
     68 /*
     69 ********************************* Globals ***********************************
     70 */
     71 unsigned short 	IPXConnClass::Socket;
     72 int			 		IPXConnClass::ConnectionNum;
     73 ECBType *			IPXConnClass::ListenECB;
     74 IPXHeaderType *	IPXConnClass::ListenHeader;
     75 char *				IPXConnClass::ListenBuf;
     76 ECBType *			IPXConnClass::SendECB;
     77 IPXHeaderType *	IPXConnClass::SendHeader;
     78 char *				IPXConnClass::SendBuf;
     79 long 					IPXConnClass::Handler;
     80 int 					IPXConnClass::Configured = 0;
     81 int 					IPXConnClass::SocketOpen = 0;
     82 int 					IPXConnClass::Listening = 0;
     83 int					IPXConnClass::PacketLen;
     84 
     85 
     86 /***************************************************************************
     87  * IPXConnClass::IPXConnClass -- class constructor             				*
     88  *                                                                         *
     89  * INPUT:                                                                  *
     90  *		numsend			desired # of entries for the send queue					*
     91  *		numreceive		desired # of entries for the receive queue				*
     92  *		maxlen			max length of an application packet							*
     93  *		magicnum			the packet "magic number" for this connection			*
     94  *		address			address of destination (NULL = no address)				*
     95  *		id					connection's unique numerical ID								*
     96  *		name				connection's name													*
     97  *		extralen			max size of app-specific extra bytes (optional)			*
     98  *                                                                         *
     99  * OUTPUT:                                                                 *
    100  *		none.																						*
    101  *                                                                         *
    102  * WARNINGS:                                                               *
    103  *		none.																						*
    104  *                                                                         *
    105  * HISTORY:                                                                *
    106  *   12/20/1994 BR : Created.                                              *
    107  *=========================================================================*/
    108 IPXConnClass::IPXConnClass (int numsend, int numreceive, int maxlen,
    109 	unsigned short magicnum, IPXAddressClass *address, int id, char *name,
    110 	int extralen) :
    111 	ConnectionClass (numsend, numreceive, maxlen, magicnum,
    112 		2,			// retry delta
    113 		-1,		// max retries
    114 		60,		// timeout
    115 		extralen)	// (currently, this is only used by the Global Channel)
    116 {
    117 	NetNumType net;
    118 	NetNodeType node;
    119 
    120 	/*------------------------------------------------------------------------
    121 	Save the values passed in
    122 	------------------------------------------------------------------------*/
    123 	if (address)
    124 		Address = (*address);
    125 	ID = id;
    126 	strcpy (Name, name);
    127 
    128 #ifdef WINSOCK_IPX
    129 	Address.Get_Address(net,node);
    130 	memcpy(ImmediateAddress,node,6);
    131 	Immed_Set = 0;
    132 #else
    133 	if ( !Winsock.Get_Connected() ) {
    134 		/*------------------------------------------------------------------------
    135 		If our Address field is an actual address (ie NULL wasn't passed to the
    136 		constructor), pre-compute the ImmediateAddress value for the SendECB.
    137 		This allows pre-computing of the ImmediateAddress for all connections
    138 		created after Configure() is called.
    139 		------------------------------------------------------------------------*/
    140 		if (!Address.Is_Broadcast() && Configured==1) {
    141 			Address.Get_Address(net,node);
    142 
    143 			/*.....................................................................
    144 			If the user is logged in & has a valid Novell Connection Number, get
    145 			the bridge address the "official" way
    146 			.....................................................................*/
    147 			if (ConnectionNum != 0) {
    148 				if (IPX_Get_Local_Target (net, node, Socket, ImmediateAddress)!=0) {
    149 					memcpy(ImmediateAddress,node,6);
    150 				}
    151 			}
    152 			/*.....................................................................
    153 			Otherwise, use the destination node address as the ImmediateAddress,
    154 			and just hope there's no network bridge in the path.
    155 			.....................................................................*/
    156 			else {
    157 				memcpy(ImmediateAddress,node,6);
    158 			}
    159 
    160 			Immed_Set = 1;
    161 		}
    162 		else {
    163 			memset (ImmediateAddress, 0, 6);
    164 			Immed_Set = 0;
    165 		}
    166 	}
    167 #endif	//WINSOCK_IPX
    168 }	/* end of IPXConnClass */
    169 
    170 
    171 /***************************************************************************
    172  * IPXConnClass::Init -- hardware-specific initialization routine				*
    173  *                                                                         *
    174  * INPUT:                                                                  *
    175  *		none.																						*
    176  *                                                                         *
    177  * OUTPUT:                                                                 *
    178  *		none.																						*
    179  *                                                                         *
    180  * WARNINGS:                                                               *
    181  *		none.																						*
    182  *                                                                         *
    183  * HISTORY:                                                                *
    184  *   12/20/1994 BR : Created.                                              *
    185  *=========================================================================*/
    186 void IPXConnClass::Init (void)
    187 {
    188 	/*------------------------------------------------------------------------
    189 	Invoke the parent's Init routine
    190 	------------------------------------------------------------------------*/
    191 	ConnectionClass::Init();
    192 
    193 }	/* end of Init */
    194 
    195 
    196 /***************************************************************************
    197  * IPXConnClass::Configure -- One-time initialization routine					*
    198  *                                                                         *
    199  * This routine sets up static members that are shared by all IPX				*
    200  * connections (ie those variables used by the Send/Listen/Broadcast			*
    201  * routines).																					*
    202  *																									*
    203  * INPUT:                                                                  *
    204  *		socket				socket ID for sending & receiving						*
    205  *		conn_num				local IPX Connection Number (0 = not logged in)		*
    206  *		listen_ecb			ptr to ECBType for listening								*
    207  *		send_ecb				ptr to ECBType for sending									*
    208  *		listen_header		ptr to IPXHeaderType for listening						*
    209  *		send_header			ptr to IPXHeaderType for sending							*
    210  *		listen_buf			ptr to buffer for listening								*
    211  *		send_buf				ptr to buffer for sending									*
    212  *		handler_rm_ptr		REAL-MODE pointer to event service routine			*
    213  *								(high word = segment, low word = offset)				*
    214  *		maxpacketlen		max packet size to listen for								*
    215  *                                                                         *
    216  * OUTPUT:                                                                 *
    217  *		none.																						*
    218  *                                                                         *
    219  * WARNINGS:                                                               *
    220  *		- All pointers must be protected-mode pointers, but must point to		*
    221  *		  DOS real-mode memory (except the Handler segment/offset)				*
    222  *                                                                         *
    223  * HISTORY:                                                                *
    224  *   12/20/1994 BR : Created.                                              *
    225  *=========================================================================*/
    226 void IPXConnClass::Configure (unsigned short socket, int conn_num,
    227 	ECBType *listen_ecb, ECBType *send_ecb, IPXHeaderType *listen_header,
    228 	IPXHeaderType *send_header, char *listen_buf, char *send_buf,
    229 	long handler_rm_ptr, int maxpacketlen)
    230 {
    231 	/*------------------------------------------------------------------------
    232 	Save the values passed in
    233 	------------------------------------------------------------------------*/
    234 	Socket = socket;
    235 	ConnectionNum = conn_num;
    236 	ListenECB = listen_ecb;
    237 	SendECB = send_ecb;
    238 	ListenHeader = listen_header;
    239 	SendHeader = send_header;
    240 	ListenBuf = listen_buf;
    241 	SendBuf = send_buf;
    242 	Handler = handler_rm_ptr;
    243 	PacketLen = maxpacketlen;
    244 
    245 	Configured = 1;
    246 
    247 }	/* end of Configure */
    248 
    249 
    250 /***************************************************************************
    251  * IPXConnClass::Start_Listening -- commands IPX to listen                 *
    252  *                                                                         *
    253  * This routine may be used to start listening in polled mode (if the 		*
    254  * ECB's Event_Service_Routine is NULL), or in interrupt mode; it's			*
    255  * up to the caller to fill the ECB in.  If in polled mode, Listening		*
    256  * must be restarted every time a packet comes in.									*
    257  *                                                                         *
    258  * INPUT:                                                                  *
    259  *		none.																						*
    260  *                                                                         *
    261  * OUTPUT:                                                                 *
    262  *		none.																						*
    263  *                                                                         *
    264  * WARNINGS:                                                               *
    265  *		- The ListenECB must have been properly filled in by the IPX Manager.*
    266  *		- Configure must be called before calling this routine.					*
    267  *                                                                         *
    268  * HISTORY:                                                                *
    269  *   12/16/1994 BR : Created.                                              *
    270  *=========================================================================*/
    271 int IPXConnClass::Start_Listening(void)
    272 {
    273 #ifdef WIN32
    274 
    275 #ifdef WINSOCK_IPX
    276 	/*
    277 	** Open the socket.
    278 	*/
    279 	if (!Open_Socket(Socket))
    280 		return(false);
    281 
    282 	/*
    283 	** start listening on the socket.
    284 	*/
    285 	if ( PacketTransport->Start_Listening () ) {
    286 		Listening =1;
    287 		return (true);
    288 	} else {
    289 		Close_Socket(Socket);
    290 		return (false);
    291 	}
    292 
    293 #else
    294 	if (Winsock.Get_Connected ()) return (true);
    295 
    296 	/*------------------------------------------------------------------------
    297 	Open the Socket
    298 	------------------------------------------------------------------------*/
    299 	if (!Open_Socket(Socket))
    300 		return(false);
    301 
    302 	if (IPX_Start_Listening95()) {
    303 		Listening =1;
    304 		return (true);
    305 	} else {
    306 		Close_Socket(Socket);
    307 		return (false);
    308 	}
    309 #endif	//WINSOCK_IPX
    310 
    311 #else	//WIN32
    312 
    313 	void *hdr_ptr;
    314 	unsigned long hdr_val;
    315 	void *buf_ptr;
    316 	unsigned long buf_val;
    317 	int rc;
    318 
    319 	/*------------------------------------------------------------------------
    320 	Don't do a thing unless we've been configured, and we're not listening.
    321 	------------------------------------------------------------------------*/
    322 	if (Configured==0 || Listening==1) {
    323 		return(0);
    324 	}
    325 
    326 	/*------------------------------------------------------------------------
    327 	Open the Socket
    328 	------------------------------------------------------------------------*/
    329 	if (!Open_Socket(Socket)) {
    330 		return(0);
    331 	}
    332 
    333 	/*------------------------------------------------------------------------
    334 	Clear the ECB & header
    335 	------------------------------------------------------------------------*/
    336 	memset(ListenECB, 0, sizeof(ECBType));
    337 	memset(ListenHeader, 0, sizeof(IPXHeaderType));
    338 
    339 	/*------------------------------------------------------------------------
    340 	Convert protected-mode ptrs to real-mode ptrs
    341 	------------------------------------------------------------------------*/
    342 	hdr_val = (unsigned long)ListenHeader;
    343 	hdr_ptr = (void *)(((hdr_val & 0xffff0) << 12) | (hdr_val & 0x000f));
    344 
    345 	buf_val = (unsigned long)ListenBuf;
    346 	buf_ptr = (void *)(((buf_val & 0xffff0) << 12) | (buf_val & 0x000f));
    347 
    348 	/*------------------------------------------------------------------------
    349 	Fill in the ECB
    350 	------------------------------------------------------------------------*/
    351 	ListenECB->SocketNumber = Socket;
    352 	ListenECB->PacketCount = 2;
    353 	ListenECB->Packet[0].Address = hdr_ptr;
    354 	ListenECB->Packet[0].Length = sizeof(IPXHeaderType);
    355 	ListenECB->Packet[1].Address = buf_ptr;
    356 	ListenECB->Packet[1].Length = (unsigned short)PacketLen;
    357 
    358 	((long &)ListenECB->Event_Service_Routine) = Handler;
    359 
    360 	/*------------------------------------------------------------------------
    361 	Command IPX to listen
    362 	------------------------------------------------------------------------*/
    363 	rc = IPX_Listen_For_Packet(ListenECB);
    364 	if (rc!=0) {
    365 		Close_Socket(Socket);
    366 		return(0);
    367 	}
    368 	else {
    369 		Listening = 1;
    370 		return(1);
    371 	}
    372 
    373 #endif	//WIN32
    374 
    375 }	/* end of Start_Listening */
    376 
    377 
    378 /***************************************************************************
    379  * IPXConnClass::Stop_Listening -- commands IPX to stop  listen            *
    380  *                                                                         *
    381  * INPUT:                                                                  *
    382  *		none.																						*
    383  *                                                                         *
    384  * OUTPUT:                                                                 *
    385  *		none.																						*
    386  *                                                                         *
    387  * WARNINGS:                                                               *
    388  *		- This routine MUST NOT be called if IPX is not listening already!	*
    389  *                                                                         *
    390  * HISTORY:                                                                *
    391  *   12/16/1994 BR : Created.                                              *
    392  *=========================================================================*/
    393 int IPXConnClass::Stop_Listening(void)
    394 {
    395 #ifdef WINSOCK_IPX
    396 	if ( PacketTransport ) PacketTransport->Stop_Listening();
    397 	Listening = 0;
    398 
    399 	//	All done.
    400 	return(1);
    401 #else
    402 	/*------------------------------------------------------------------------
    403 	Don't do anything unless we're already Listening.
    404 	------------------------------------------------------------------------*/
    405 	if (Listening==0) {
    406 		return(0);
    407 	}
    408 
    409 #ifdef WIN32
    410 
    411 	if (Winsock.Get_Connected()) {
    412 		Listening = 0;
    413 		return (true);
    414 	} else {
    415 		IPX_Shut_Down95();
    416 		Close_Socket(Socket);
    417 	}
    418 
    419 #else	//WIN32
    420 
    421 	/*------------------------------------------------------------------------
    422 	Shut IPX down.
    423 	------------------------------------------------------------------------*/
    424 	IPX_Cancel_Event(ListenECB);
    425 	Close_Socket(Socket);
    426 
    427 #endif	//WIN32
    428 
    429 	Listening = 0;
    430 
    431 	/*------------------------------------------------------------------------
    432 	All done.
    433 	------------------------------------------------------------------------*/
    434 	return(1);
    435 #endif	//WINSOCK_IPX
    436 
    437 }	/* end of Stop_Listening */
    438 
    439 
    440 /***************************************************************************
    441  * IPXConnClass::Send -- sends a packet; invoked by SequencedConnection		*
    442  *                                                                         *
    443  * INPUT:                                                                  *
    444  *		buf			buffer to send															*
    445  *		buflen		length of buffer to send											*
    446  *		extrabuf		(not used by this class)											*
    447  *		extralen		(not used by this class)											*
    448  *                                                                         *
    449  * OUTPUT:                                                                 *
    450  *		1 = OK, 0 = error																		*
    451  *                                                                         *
    452  * WARNINGS:                                                               *
    453  *		none.																						*
    454  *                                                                         *
    455  * HISTORY:                                                                *
    456  *   12/16/1994 BR : Created.                                              *
    457  *=========================================================================*/
    458 int IPXConnClass::Send(char *buf, int buflen, void *, int)
    459 {
    460 	/*------------------------------------------------------------------------
    461 	Invoke our own Send_To routine, filling in our Address as the destination.
    462 	------------------------------------------------------------------------*/
    463 	if (Immed_Set) {
    464 		return(Send_To (buf, buflen, &Address, ImmediateAddress));
    465 	}
    466 	else {
    467 		return(Send_To (buf, buflen, &Address, NULL));
    468 	}
    469 
    470 }	/* end of Send */
    471 
    472 
    473 /***************************************************************************
    474  * IPXConnClass::Open_Socket -- opens communications socket    				*
    475  *                                                                         *
    476  * INPUT:                                                                  *
    477  *		socket		desired socket ID number											*
    478  *                                                                         *
    479  * OUTPUT:                                                                 *
    480  *		1 = OK, 0 = error																		*
    481  *                                                                         *
    482  * WARNINGS:                                                               *
    483  *		none.																						*
    484  *                                                                         *
    485  * HISTORY:                                                                *
    486  *   12/16/1994 BR : Created.                                              *
    487  *=========================================================================*/
    488 int IPXConnClass::Open_Socket(unsigned short socket)
    489 {
    490 	int rc;
    491 #ifdef WINSOCK_IPX
    492 	rc = PacketTransport->Open_Socket(socket);
    493 
    494 	SocketOpen = rc;
    495 	return ( rc );
    496 
    497 #else	//WINSOCK_IPX
    498 	if (Winsock.Get_Connected()) {
    499 		SocketOpen = 1;
    500 		return (true);
    501 	}
    502 
    503 	SocketOpen = 0;
    504 
    505 	/*------------------------------------------------------------------------
    506 	Try to open a listen socket.  The socket may have been left open by
    507 	a previously-crashed program, so ignore the state of the SocketOpen
    508 	flag for this call; use IPX to determine if the socket was already open.
    509 	------------------------------------------------------------------------*/
    510 	rc = IPX_Open_Socket(socket);
    511 	if (rc) {
    512 
    513 		/*.....................................................................
    514 		If already open, close & reopen it
    515 		.....................................................................*/
    516 		if (rc==IPXERR_SOCKET_ERROR) {
    517 #ifdef WIN32
    518 			WWDebugString ("Error -- Specified socket is already open");
    519 #endif	//WIN32
    520 			IPX_Close_Socket(socket);
    521 			rc = IPX_Open_Socket(socket);
    522 		}
    523 
    524 			/*..................................................................
    525 			Still can't open: return error
    526 			..................................................................*/
    527 		if (rc) {
    528 			return(0);
    529 		}
    530 	}
    531 
    532 	SocketOpen = 1;
    533 
    534 	return(1);
    535 #endif	//WINSOCK_IPX
    536 
    537 }	/* end of Open_Socket */
    538 
    539 
    540 /***************************************************************************
    541  * IPXConnClass::Close_Socket -- closes the socket 								*
    542  *                                                                         *
    543  * INPUT:                                                                  *
    544  *		socket		desired socket ID number											*
    545  *                                                                         *
    546  * OUTPUT:                                                                 *
    547  *		none.																						*
    548  *                                                                         *
    549  * WARNINGS:                                                               *
    550  *		Calling this routine when the sockets aren't open may crash!			*
    551  *                                                                         *
    552  * HISTORY:                                                                *
    553  *   12/16/1994 BR : Created.                                              *
    554  *=========================================================================*/
    555 void IPXConnClass::Close_Socket(unsigned short socket)
    556 {
    557 #ifdef WINSOCK_IPX
    558 	socket = socket;
    559 	PacketTransport->Close_Socket();
    560 	SocketOpen = 0;
    561 #else	//WINSOCK_IPX
    562 	if (Winsock.Get_Connected()) {
    563 		SocketOpen = 0;
    564 		return;
    565 	}
    566 
    567 	/*------------------------------------------------------------------------
    568 	Never, ever, ever, under any circumstances whatsoever, close a socket
    569 	that isn't open.  You'll regret it forever (or until at least until
    570 	you're through rebooting, which, if you're on a Pentium is the same
    571 	thing).
    572 	------------------------------------------------------------------------*/
    573 	if (SocketOpen==1) {
    574 		IPX_Close_Socket(socket);
    575 	}
    576 
    577 	SocketOpen = 0;
    578 #endif	//WINSOCK_IPX
    579 }	/* end of Close_Socket */
    580 
    581 
    582 /***************************************************************************
    583  * IPXConnClass::Send_To -- sends the packet to the given address				*
    584  *                                                                         *
    585  * The "ImmediateAddress" field of the SendECB must be filled in with the	*
    586  * address of a bridge, or the node address of the destination if there		*
    587  * is no bridge.  The NETX call to find this address will always crash		*
    588  * if NETX isn't loaded (ConnectionNum is 0), so this case is trapped &		*
    589  * prevented.																					*
    590  * Also, if the address of this IPX connection is known when the 				*
    591  * constructor is called, and Configure has been called, Get_Local_Target 	*
    592  * is called to precompute the ImmediateAddress; this case is detected & 	*
    593  * if the value is already computed, it's just memcpy'd over.					*
    594  *                                                                         *
    595  * INPUT:                                                                  *
    596  *		buf			buffer to send															*
    597  *		buflen		length of buffer														*
    598  *		address		Address to send to													*
    599  *		immed			ImmediateAddress value, NULL if none							*
    600  *                                                                         *
    601  * OUTPUT:                                                                 *
    602  *		1 = OK, 0 = error																		*
    603  *                                                                         *
    604  * WARNINGS:                                                               *
    605  *		none.																						*
    606  *                                                                         *
    607  * HISTORY:                                                                *
    608  *   12/16/1994 BR : Created.                                              *
    609  *=========================================================================*/
    610 int IPXConnClass::Send_To(char *buf, int buflen, IPXAddressClass *address,
    611 	NetNodeType immed)
    612 {
    613 #ifdef WINSOCK_IPX
    614 
    615 	immed = immed;
    616 	assert ( immed == NULL );
    617 	PacketTransport->WriteTo ( (void*)buf, buflen, (void*) address );
    618 	return (true);
    619 
    620 #else	//WINSOCK_IPX
    621 	NetNumType net;
    622 	NetNodeType node;
    623 	int rc;
    624 
    625 #ifdef WIN32
    626 
    627 	unsigned char	send_address[6];
    628 
    629 	if (Winsock.Get_Connected()) {
    630 		Winsock.Write((void*)buf, buflen);
    631 		return (true);
    632 	}
    633 
    634 	if (immed) {
    635 		memcpy(send_address, immed, 6);
    636 #ifdef FIXIT_DESTNET
    637 		// fixes DESTNET
    638 		address->Get_Address(net,node);
    639 #else
    640 		// breaks DESTNET
    641 		memcpy(node, immed, 6);
    642 		memset (net, 0, sizeof(net) );
    643 #endif
    644 	} else {
    645 		address->Get_Address(net,node);
    646 		/*.....................................................................
    647 		If the user is logged in & has a valid Novell Connection Number, get the
    648 		bridge address the "official" way
    649 		.....................................................................*/
    650 		if (ConnectionNum != 0) {
    651 			rc = IPX_Get_Local_Target (net, node, Socket, &send_address[0]);
    652 			if (rc!=0) {
    653 				return(false);
    654 			}
    655 		} else {
    656 			/*.....................................................................
    657 			Otherwise, use the destination node address as the ImmediateAddress, and
    658 			just hope there's no network bridge in the path.
    659 			.....................................................................*/
    660 			memcpy(send_address,node,6);
    661 		}
    662 	}
    663 
    664 	return (IPX_Send_Packet95(&send_address[0], (unsigned char*)buf, buflen, (unsigned char*)net, (unsigned char*)node));
    665 
    666 #else	//WIN32
    667 
    668 	void *hdr_ptr;
    669 	void *buf_ptr;
    670 	unsigned long hdr_val;
    671 	unsigned long buf_val;
    672 
    673 	/*------------------------------------------------------------------------
    674 	Clear the ECB & header
    675 	------------------------------------------------------------------------*/
    676 	memset(SendECB, 0, sizeof(ECBType));
    677 	memset(SendHeader, 0, sizeof(IPXHeaderType));
    678 
    679 	/*------------------------------------------------------------------------
    680 	Copy the message into the SendBuf
    681 	------------------------------------------------------------------------*/
    682 	memcpy (SendBuf,buf,buflen);
    683 
    684 	/*------------------------------------------------------------------------
    685 	Convert protected-mode ptrs to real-mode ptrs
    686 	------------------------------------------------------------------------*/
    687 	hdr_val = (unsigned long)SendHeader;
    688 	hdr_ptr = (void *)(((hdr_val & 0xffff0) << 12) | (hdr_val & 0x000f));
    689 	buf_val = (unsigned long)SendBuf;
    690 	buf_ptr = (void *)(((buf_val & 0xffff0) << 12) | (buf_val & 0x000f));
    691 
    692 	/*------------------------------------------------------------------------
    693 	Fill in ECB
    694 	------------------------------------------------------------------------*/
    695 	SendECB->SocketNumber = Socket;						// my output socket
    696 	SendECB->PacketCount = 2;								// 2 data areas
    697 	SendECB->Packet[0].Address = hdr_ptr;
    698 	SendECB->Packet[0].Length = sizeof(IPXHeaderType);
    699 	SendECB->Packet[1].Address = buf_ptr;
    700 	SendECB->Packet[1].Length = (unsigned short)buflen;
    701 
    702 	/*------------------------------------------------------------------------
    703 	Get the bridge address
    704 	------------------------------------------------------------------------*/
    705 	if (immed) {
    706 		memcpy(SendECB->ImmediateAddress, immed, 6);
    707 	}
    708 	else {
    709 		address->Get_Address(net,node);
    710 
    711 		/*.....................................................................
    712 		If the user is logged in & has a valid Novell Connection Number, get
    713 		the bridge address the "official" way
    714 		.....................................................................*/
    715 		if (ConnectionNum != 0) {
    716 			rc = IPX_Get_Local_Target (net, node, Socket,
    717 				SendECB->ImmediateAddress);
    718 			if (rc!=0) {
    719 				return(0);
    720 			}
    721 		}
    722 		/*.....................................................................
    723 		Otherwise, use the destination node address as the ImmediateAddress,
    724 		and just hope there's no network bridge in the path.
    725 		.....................................................................*/
    726 		else {
    727 			memcpy(SendECB->ImmediateAddress,node,6);
    728 		}
    729 	}
    730 
    731 	/*------------------------------------------------------------------------
    732 	Fill in outgoing header
    733 	------------------------------------------------------------------------*/
    734 	SendHeader->PacketType = 4;							// 4 = IPX packet
    735 	address->Get_Address(SendHeader);					// fill in header addresses
    736 	SendHeader->DestNetworkSocket = Socket;			// destination socket id
    737 
    738 	/*------------------------------------------------------------------------
    739 	Send the packet
    740 	------------------------------------------------------------------------*/
    741 	IPX_Send_Packet(SendECB);
    742 
    743 	/*------------------------------------------------------------------------
    744 	Wait for send to complete
    745 	------------------------------------------------------------------------*/
    746 	while (SendECB->InUse)
    747 		Let_IPX_Breath();
    748 
    749 	if (SendECB->CompletionCode!=0) {
    750 		return(0);
    751 	}
    752 	else {
    753 		return(1);
    754 	}
    755 
    756 #endif	//WIN32
    757 #endif	//WINSOCK_IPX
    758 
    759 }	/* end of Send_To */
    760 
    761 
    762 /***************************************************************************
    763  * IPXConnClass::Broadcast -- broadcasts the given packet						*
    764  *                                                                         *
    765  * INPUT:                                                                  *
    766  *		socket		desired socket ID number											*
    767  *                                                                         *
    768  * OUTPUT:                                                                 *
    769  *		1 = OK, 0 = error																		*
    770  *                                                                         *
    771  * WARNINGS:                                                               *
    772  *		none.																						*
    773  *                                                                         *
    774  * HISTORY:                                                                *
    775  *   12/16/1994 BR : Created.                                              *
    776  *=========================================================================*/
    777 int IPXConnClass::Broadcast(char *buf, int buflen)
    778 {
    779 #ifdef WINSOCK_IPX
    780 	PacketTransport->Broadcast (buf, buflen);
    781 	return (true);
    782 
    783 #else	//WINSOCK_IPX
    784 
    785 #ifdef WIN32
    786 
    787 	if (Winsock.Get_Connected()) {
    788 		Winsock.Write((void*)buf, buflen);
    789 		return(true);
    790 	} else {
    791 		return (IPX_Broadcast_Packet95((unsigned char*)buf, buflen));
    792 	}
    793 
    794 #else	//WIN32
    795 
    796 	void *hdr_ptr;
    797 	void *buf_ptr;
    798 	unsigned long hdr_val;
    799 	unsigned long buf_val;
    800 
    801 	/*------------------------------------------------------------------------
    802 	Clear the ECB & header
    803 	------------------------------------------------------------------------*/
    804 	memset(SendECB, 0, sizeof(ECBType));
    805 	memset(SendHeader, 0, sizeof(IPXHeaderType));
    806 
    807 	/*------------------------------------------------------------------------
    808 	Copy the message into the SendBuf
    809 	------------------------------------------------------------------------*/
    810 	memcpy (SendBuf,buf,buflen);
    811 
    812 	/*------------------------------------------------------------------------
    813 	Convert protected-mode ptrs to real-mode ptrs
    814 	------------------------------------------------------------------------*/
    815 	hdr_val = (unsigned long)SendHeader;
    816 	hdr_ptr = (void *)(((hdr_val & 0xffff0) << 12) | (hdr_val & 0x000f));
    817 	buf_val = (unsigned long)SendBuf;
    818 	buf_ptr = (void *)(((buf_val & 0xffff0) << 12) | (buf_val & 0x000f));
    819 
    820 	/*------------------------------------------------------------------------
    821 	Fill in ECB
    822 	------------------------------------------------------------------------*/
    823 	SendECB->SocketNumber = Socket;						// my output socket
    824 	SendECB->PacketCount = 2;								// 2 data areas
    825 	SendECB->Packet[0].Address = hdr_ptr;
    826 	SendECB->Packet[0].Length = sizeof(IPXHeaderType);
    827 	SendECB->Packet[1].Address = buf_ptr;
    828 	SendECB->Packet[1].Length = (unsigned short)buflen;
    829 	SendECB->ImmediateAddress[0] = 0xff;
    830 	SendECB->ImmediateAddress[1] = 0xff;
    831 	SendECB->ImmediateAddress[2] = 0xff;
    832 	SendECB->ImmediateAddress[3] = 0xff;
    833 	SendECB->ImmediateAddress[4] = 0xff;
    834 	SendECB->ImmediateAddress[5] = 0xff;
    835 
    836 	/*------------------------------------------------------------------------
    837 	Fill in outgoing header
    838 	------------------------------------------------------------------------*/
    839 	SendHeader->PacketType = 4;							// 4 = IPX packet
    840 	SendHeader->DestNetworkNumber[0] = 0xff;			// 0xff = broadcast
    841 	SendHeader->DestNetworkNumber[1] = 0xff;
    842 	SendHeader->DestNetworkNumber[2] = 0xff;
    843 	SendHeader->DestNetworkNumber[3] = 0xff;
    844 	SendHeader->DestNetworkNode[0] = 0xff;				// 0xff = broadcast
    845 	SendHeader->DestNetworkNode[1] = 0xff;
    846 	SendHeader->DestNetworkNode[2] = 0xff;
    847 	SendHeader->DestNetworkNode[3] = 0xff;
    848 	SendHeader->DestNetworkNode[4] = 0xff;
    849 	SendHeader->DestNetworkNode[5] = 0xff;
    850 	SendHeader->DestNetworkSocket = Socket;			// destination socket #
    851 
    852 	/*------------------------------------------------------------------------
    853 	Send the packet
    854 	------------------------------------------------------------------------*/
    855 	IPX_Send_Packet(SendECB);
    856 
    857 	/*------------------------------------------------------------------------
    858 	Wait for send to complete
    859 	------------------------------------------------------------------------*/
    860 	while (SendECB->InUse) {
    861 		Let_IPX_Breath();
    862 	}
    863 
    864 	if (SendECB->CompletionCode!=0) {
    865 		return(0);
    866 	}
    867 	else {
    868 		return(1);
    869 	}
    870 
    871 #endif	//WIN32
    872 #endif	//WINSOCK_IPX
    873 }	/* end of Broadcast */
    874 
    875 /************************** end of ipxconn.cpp *****************************/
    876