877 lines
34 KiB
C++
877 lines
34 KiB
C++
//
|
|
// Copyright 2020 Electronic Arts Inc.
|
|
//
|
|
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
|
|
// software: you can redistribute it and/or modify it under the terms of
|
|
// the GNU General Public License as published by the Free Software Foundation,
|
|
// either version 3 of the License, or (at your option) any later version.
|
|
|
|
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
|
|
// in the hope that it will be useful, but with permitted additional restrictions
|
|
// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
|
|
// distributed with this program. You should have received a copy of the
|
|
// GNU General Public License along with permitted additional restrictions
|
|
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
|
|
|
|
/* $Header: /CounterStrike/IPXCONN.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
|
/***************************************************************************
|
|
** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
|
|
***************************************************************************
|
|
* *
|
|
* Project Name : Command & Conquer *
|
|
* *
|
|
* File Name : IPXCONN.CPP *
|
|
* *
|
|
* Programmer : Bill Randolph *
|
|
* *
|
|
* Start Date : December 20, 1994 *
|
|
* *
|
|
* Last Update : April 9, 1995 [BRR] *
|
|
* *
|
|
*-------------------------------------------------------------------------*
|
|
* Functions: *
|
|
* IPXConnClass::IPXConnClass -- class constructor *
|
|
* IPXConnClass::~IPXConnClass -- class destructor *
|
|
* IPXConnClass::Init -- hardware-specific initialization routine *
|
|
* IPXConnClass::Configure -- One-time initialization routine *
|
|
* IPXConnClass::Start_Listening -- commands IPX to listen *
|
|
* IPXConnClass::Stop_Listening -- commands IPX to stop listen *
|
|
* IPXConnClass::Send -- sends a packet; invoked by SequencedConnection *
|
|
* IPXConnClass::Open_Socket -- opens communications socket *
|
|
* IPXConnClass::Close_Socket -- closes the socket *
|
|
* IPXConnClass::Send_To -- sends the packet to the given address *
|
|
* IPXConnClass::Broadcast -- broadcasts the given packet *
|
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
|
|
#include "function.h"
|
|
#include <stdio.h>
|
|
//#include <mem.h>
|
|
#include <string.h>
|
|
#include "ipxconn.h"
|
|
|
|
#ifdef WINSOCK_IPX
|
|
#include "WSProto.h"
|
|
|
|
#else
|
|
|
|
#include "ipx95.h"
|
|
#ifdef WIN32
|
|
#include "tcpip.h"
|
|
#else //WIN32
|
|
#include "fakesock.h"
|
|
#endif //WIN32
|
|
#endif //WINSOCK_IPX
|
|
|
|
|
|
|
|
/*
|
|
********************************* Globals ***********************************
|
|
*/
|
|
unsigned short IPXConnClass::Socket;
|
|
int IPXConnClass::ConnectionNum;
|
|
ECBType * IPXConnClass::ListenECB;
|
|
IPXHeaderType * IPXConnClass::ListenHeader;
|
|
char * IPXConnClass::ListenBuf;
|
|
ECBType * IPXConnClass::SendECB;
|
|
IPXHeaderType * IPXConnClass::SendHeader;
|
|
char * IPXConnClass::SendBuf;
|
|
long IPXConnClass::Handler;
|
|
int IPXConnClass::Configured = 0;
|
|
int IPXConnClass::SocketOpen = 0;
|
|
int IPXConnClass::Listening = 0;
|
|
int IPXConnClass::PacketLen;
|
|
|
|
|
|
/***************************************************************************
|
|
* IPXConnClass::IPXConnClass -- class constructor *
|
|
* *
|
|
* INPUT: *
|
|
* numsend desired # of entries for the send queue *
|
|
* numreceive desired # of entries for the receive queue *
|
|
* maxlen max length of an application packet *
|
|
* magicnum the packet "magic number" for this connection *
|
|
* address address of destination (NULL = no address) *
|
|
* id connection's unique numerical ID *
|
|
* name connection's name *
|
|
* extralen max size of app-specific extra bytes (optional) *
|
|
* *
|
|
* OUTPUT: *
|
|
* none. *
|
|
* *
|
|
* WARNINGS: *
|
|
* none. *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/20/1994 BR : Created. *
|
|
*=========================================================================*/
|
|
IPXConnClass::IPXConnClass (int numsend, int numreceive, int maxlen,
|
|
unsigned short magicnum, IPXAddressClass *address, int id, char *name,
|
|
int extralen) :
|
|
ConnectionClass (numsend, numreceive, maxlen, magicnum,
|
|
2, // retry delta
|
|
-1, // max retries
|
|
60, // timeout
|
|
extralen) // (currently, this is only used by the Global Channel)
|
|
{
|
|
NetNumType net;
|
|
NetNodeType node;
|
|
|
|
/*------------------------------------------------------------------------
|
|
Save the values passed in
|
|
------------------------------------------------------------------------*/
|
|
if (address)
|
|
Address = (*address);
|
|
ID = id;
|
|
strcpy (Name, name);
|
|
|
|
#ifdef WINSOCK_IPX
|
|
Address.Get_Address(net,node);
|
|
memcpy(ImmediateAddress,node,6);
|
|
Immed_Set = 0;
|
|
#else
|
|
if ( !Winsock.Get_Connected() ) {
|
|
/*------------------------------------------------------------------------
|
|
If our Address field is an actual address (ie NULL wasn't passed to the
|
|
constructor), pre-compute the ImmediateAddress value for the SendECB.
|
|
This allows pre-computing of the ImmediateAddress for all connections
|
|
created after Configure() is called.
|
|
------------------------------------------------------------------------*/
|
|
if (!Address.Is_Broadcast() && Configured==1) {
|
|
Address.Get_Address(net,node);
|
|
|
|
/*.....................................................................
|
|
If the user is logged in & has a valid Novell Connection Number, get
|
|
the bridge address the "official" way
|
|
.....................................................................*/
|
|
if (ConnectionNum != 0) {
|
|
if (IPX_Get_Local_Target (net, node, Socket, ImmediateAddress)!=0) {
|
|
memcpy(ImmediateAddress,node,6);
|
|
}
|
|
}
|
|
/*.....................................................................
|
|
Otherwise, use the destination node address as the ImmediateAddress,
|
|
and just hope there's no network bridge in the path.
|
|
.....................................................................*/
|
|
else {
|
|
memcpy(ImmediateAddress,node,6);
|
|
}
|
|
|
|
Immed_Set = 1;
|
|
}
|
|
else {
|
|
memset (ImmediateAddress, 0, 6);
|
|
Immed_Set = 0;
|
|
}
|
|
}
|
|
#endif //WINSOCK_IPX
|
|
} /* end of IPXConnClass */
|
|
|
|
|
|
/***************************************************************************
|
|
* IPXConnClass::Init -- hardware-specific initialization routine *
|
|
* *
|
|
* INPUT: *
|
|
* none. *
|
|
* *
|
|
* OUTPUT: *
|
|
* none. *
|
|
* *
|
|
* WARNINGS: *
|
|
* none. *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/20/1994 BR : Created. *
|
|
*=========================================================================*/
|
|
void IPXConnClass::Init (void)
|
|
{
|
|
/*------------------------------------------------------------------------
|
|
Invoke the parent's Init routine
|
|
------------------------------------------------------------------------*/
|
|
ConnectionClass::Init();
|
|
|
|
} /* end of Init */
|
|
|
|
|
|
/***************************************************************************
|
|
* IPXConnClass::Configure -- One-time initialization routine *
|
|
* *
|
|
* This routine sets up static members that are shared by all IPX *
|
|
* connections (ie those variables used by the Send/Listen/Broadcast *
|
|
* routines). *
|
|
* *
|
|
* INPUT: *
|
|
* socket socket ID for sending & receiving *
|
|
* conn_num local IPX Connection Number (0 = not logged in) *
|
|
* listen_ecb ptr to ECBType for listening *
|
|
* send_ecb ptr to ECBType for sending *
|
|
* listen_header ptr to IPXHeaderType for listening *
|
|
* send_header ptr to IPXHeaderType for sending *
|
|
* listen_buf ptr to buffer for listening *
|
|
* send_buf ptr to buffer for sending *
|
|
* handler_rm_ptr REAL-MODE pointer to event service routine *
|
|
* (high word = segment, low word = offset) *
|
|
* maxpacketlen max packet size to listen for *
|
|
* *
|
|
* OUTPUT: *
|
|
* none. *
|
|
* *
|
|
* WARNINGS: *
|
|
* - All pointers must be protected-mode pointers, but must point to *
|
|
* DOS real-mode memory (except the Handler segment/offset) *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/20/1994 BR : Created. *
|
|
*=========================================================================*/
|
|
void IPXConnClass::Configure (unsigned short socket, int conn_num,
|
|
ECBType *listen_ecb, ECBType *send_ecb, IPXHeaderType *listen_header,
|
|
IPXHeaderType *send_header, char *listen_buf, char *send_buf,
|
|
long handler_rm_ptr, int maxpacketlen)
|
|
{
|
|
/*------------------------------------------------------------------------
|
|
Save the values passed in
|
|
------------------------------------------------------------------------*/
|
|
Socket = socket;
|
|
ConnectionNum = conn_num;
|
|
ListenECB = listen_ecb;
|
|
SendECB = send_ecb;
|
|
ListenHeader = listen_header;
|
|
SendHeader = send_header;
|
|
ListenBuf = listen_buf;
|
|
SendBuf = send_buf;
|
|
Handler = handler_rm_ptr;
|
|
PacketLen = maxpacketlen;
|
|
|
|
Configured = 1;
|
|
|
|
} /* end of Configure */
|
|
|
|
|
|
/***************************************************************************
|
|
* IPXConnClass::Start_Listening -- commands IPX to listen *
|
|
* *
|
|
* This routine may be used to start listening in polled mode (if the *
|
|
* ECB's Event_Service_Routine is NULL), or in interrupt mode; it's *
|
|
* up to the caller to fill the ECB in. If in polled mode, Listening *
|
|
* must be restarted every time a packet comes in. *
|
|
* *
|
|
* INPUT: *
|
|
* none. *
|
|
* *
|
|
* OUTPUT: *
|
|
* none. *
|
|
* *
|
|
* WARNINGS: *
|
|
* - The ListenECB must have been properly filled in by the IPX Manager.*
|
|
* - Configure must be called before calling this routine. *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/16/1994 BR : Created. *
|
|
*=========================================================================*/
|
|
int IPXConnClass::Start_Listening(void)
|
|
{
|
|
#ifdef WIN32
|
|
|
|
#ifdef WINSOCK_IPX
|
|
/*
|
|
** Open the socket.
|
|
*/
|
|
if (!Open_Socket(Socket))
|
|
return(false);
|
|
|
|
/*
|
|
** start listening on the socket.
|
|
*/
|
|
if ( PacketTransport->Start_Listening () ) {
|
|
Listening =1;
|
|
return (true);
|
|
} else {
|
|
Close_Socket(Socket);
|
|
return (false);
|
|
}
|
|
|
|
#else
|
|
if (Winsock.Get_Connected ()) return (true);
|
|
|
|
/*------------------------------------------------------------------------
|
|
Open the Socket
|
|
------------------------------------------------------------------------*/
|
|
if (!Open_Socket(Socket))
|
|
return(false);
|
|
|
|
if (IPX_Start_Listening95()) {
|
|
Listening =1;
|
|
return (true);
|
|
} else {
|
|
Close_Socket(Socket);
|
|
return (false);
|
|
}
|
|
#endif //WINSOCK_IPX
|
|
|
|
#else //WIN32
|
|
|
|
void *hdr_ptr;
|
|
unsigned long hdr_val;
|
|
void *buf_ptr;
|
|
unsigned long buf_val;
|
|
int rc;
|
|
|
|
/*------------------------------------------------------------------------
|
|
Don't do a thing unless we've been configured, and we're not listening.
|
|
------------------------------------------------------------------------*/
|
|
if (Configured==0 || Listening==1) {
|
|
return(0);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------
|
|
Open the Socket
|
|
------------------------------------------------------------------------*/
|
|
if (!Open_Socket(Socket)) {
|
|
return(0);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------
|
|
Clear the ECB & header
|
|
------------------------------------------------------------------------*/
|
|
memset(ListenECB, 0, sizeof(ECBType));
|
|
memset(ListenHeader, 0, sizeof(IPXHeaderType));
|
|
|
|
/*------------------------------------------------------------------------
|
|
Convert protected-mode ptrs to real-mode ptrs
|
|
------------------------------------------------------------------------*/
|
|
hdr_val = (unsigned long)ListenHeader;
|
|
hdr_ptr = (void *)(((hdr_val & 0xffff0) << 12) | (hdr_val & 0x000f));
|
|
|
|
buf_val = (unsigned long)ListenBuf;
|
|
buf_ptr = (void *)(((buf_val & 0xffff0) << 12) | (buf_val & 0x000f));
|
|
|
|
/*------------------------------------------------------------------------
|
|
Fill in the ECB
|
|
------------------------------------------------------------------------*/
|
|
ListenECB->SocketNumber = Socket;
|
|
ListenECB->PacketCount = 2;
|
|
ListenECB->Packet[0].Address = hdr_ptr;
|
|
ListenECB->Packet[0].Length = sizeof(IPXHeaderType);
|
|
ListenECB->Packet[1].Address = buf_ptr;
|
|
ListenECB->Packet[1].Length = (unsigned short)PacketLen;
|
|
|
|
((long &)ListenECB->Event_Service_Routine) = Handler;
|
|
|
|
/*------------------------------------------------------------------------
|
|
Command IPX to listen
|
|
------------------------------------------------------------------------*/
|
|
rc = IPX_Listen_For_Packet(ListenECB);
|
|
if (rc!=0) {
|
|
Close_Socket(Socket);
|
|
return(0);
|
|
}
|
|
else {
|
|
Listening = 1;
|
|
return(1);
|
|
}
|
|
|
|
#endif //WIN32
|
|
|
|
} /* end of Start_Listening */
|
|
|
|
|
|
/***************************************************************************
|
|
* IPXConnClass::Stop_Listening -- commands IPX to stop listen *
|
|
* *
|
|
* INPUT: *
|
|
* none. *
|
|
* *
|
|
* OUTPUT: *
|
|
* none. *
|
|
* *
|
|
* WARNINGS: *
|
|
* - This routine MUST NOT be called if IPX is not listening already! *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/16/1994 BR : Created. *
|
|
*=========================================================================*/
|
|
int IPXConnClass::Stop_Listening(void)
|
|
{
|
|
#ifdef WINSOCK_IPX
|
|
if ( PacketTransport ) PacketTransport->Stop_Listening();
|
|
Listening = 0;
|
|
|
|
// All done.
|
|
return(1);
|
|
#else
|
|
/*------------------------------------------------------------------------
|
|
Don't do anything unless we're already Listening.
|
|
------------------------------------------------------------------------*/
|
|
if (Listening==0) {
|
|
return(0);
|
|
}
|
|
|
|
#ifdef WIN32
|
|
|
|
if (Winsock.Get_Connected()) {
|
|
Listening = 0;
|
|
return (true);
|
|
} else {
|
|
IPX_Shut_Down95();
|
|
Close_Socket(Socket);
|
|
}
|
|
|
|
#else //WIN32
|
|
|
|
/*------------------------------------------------------------------------
|
|
Shut IPX down.
|
|
------------------------------------------------------------------------*/
|
|
IPX_Cancel_Event(ListenECB);
|
|
Close_Socket(Socket);
|
|
|
|
#endif //WIN32
|
|
|
|
Listening = 0;
|
|
|
|
/*------------------------------------------------------------------------
|
|
All done.
|
|
------------------------------------------------------------------------*/
|
|
return(1);
|
|
#endif //WINSOCK_IPX
|
|
|
|
} /* end of Stop_Listening */
|
|
|
|
|
|
/***************************************************************************
|
|
* IPXConnClass::Send -- sends a packet; invoked by SequencedConnection *
|
|
* *
|
|
* INPUT: *
|
|
* buf buffer to send *
|
|
* buflen length of buffer to send *
|
|
* extrabuf (not used by this class) *
|
|
* extralen (not used by this class) *
|
|
* *
|
|
* OUTPUT: *
|
|
* 1 = OK, 0 = error *
|
|
* *
|
|
* WARNINGS: *
|
|
* none. *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/16/1994 BR : Created. *
|
|
*=========================================================================*/
|
|
int IPXConnClass::Send(char *buf, int buflen, void *, int)
|
|
{
|
|
/*------------------------------------------------------------------------
|
|
Invoke our own Send_To routine, filling in our Address as the destination.
|
|
------------------------------------------------------------------------*/
|
|
if (Immed_Set) {
|
|
return(Send_To (buf, buflen, &Address, ImmediateAddress));
|
|
}
|
|
else {
|
|
return(Send_To (buf, buflen, &Address, NULL));
|
|
}
|
|
|
|
} /* end of Send */
|
|
|
|
|
|
/***************************************************************************
|
|
* IPXConnClass::Open_Socket -- opens communications socket *
|
|
* *
|
|
* INPUT: *
|
|
* socket desired socket ID number *
|
|
* *
|
|
* OUTPUT: *
|
|
* 1 = OK, 0 = error *
|
|
* *
|
|
* WARNINGS: *
|
|
* none. *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/16/1994 BR : Created. *
|
|
*=========================================================================*/
|
|
int IPXConnClass::Open_Socket(unsigned short socket)
|
|
{
|
|
int rc;
|
|
#ifdef WINSOCK_IPX
|
|
rc = PacketTransport->Open_Socket(socket);
|
|
|
|
SocketOpen = rc;
|
|
return ( rc );
|
|
|
|
#else //WINSOCK_IPX
|
|
if (Winsock.Get_Connected()) {
|
|
SocketOpen = 1;
|
|
return (true);
|
|
}
|
|
|
|
SocketOpen = 0;
|
|
|
|
/*------------------------------------------------------------------------
|
|
Try to open a listen socket. The socket may have been left open by
|
|
a previously-crashed program, so ignore the state of the SocketOpen
|
|
flag for this call; use IPX to determine if the socket was already open.
|
|
------------------------------------------------------------------------*/
|
|
rc = IPX_Open_Socket(socket);
|
|
if (rc) {
|
|
|
|
/*.....................................................................
|
|
If already open, close & reopen it
|
|
.....................................................................*/
|
|
if (rc==IPXERR_SOCKET_ERROR) {
|
|
#ifdef WIN32
|
|
WWDebugString ("Error -- Specified socket is already open");
|
|
#endif //WIN32
|
|
IPX_Close_Socket(socket);
|
|
rc = IPX_Open_Socket(socket);
|
|
}
|
|
|
|
/*..................................................................
|
|
Still can't open: return error
|
|
..................................................................*/
|
|
if (rc) {
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
SocketOpen = 1;
|
|
|
|
return(1);
|
|
#endif //WINSOCK_IPX
|
|
|
|
} /* end of Open_Socket */
|
|
|
|
|
|
/***************************************************************************
|
|
* IPXConnClass::Close_Socket -- closes the socket *
|
|
* *
|
|
* INPUT: *
|
|
* socket desired socket ID number *
|
|
* *
|
|
* OUTPUT: *
|
|
* none. *
|
|
* *
|
|
* WARNINGS: *
|
|
* Calling this routine when the sockets aren't open may crash! *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/16/1994 BR : Created. *
|
|
*=========================================================================*/
|
|
void IPXConnClass::Close_Socket(unsigned short socket)
|
|
{
|
|
#ifdef WINSOCK_IPX
|
|
socket = socket;
|
|
PacketTransport->Close_Socket();
|
|
SocketOpen = 0;
|
|
#else //WINSOCK_IPX
|
|
if (Winsock.Get_Connected()) {
|
|
SocketOpen = 0;
|
|
return;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------
|
|
Never, ever, ever, under any circumstances whatsoever, close a socket
|
|
that isn't open. You'll regret it forever (or until at least until
|
|
you're through rebooting, which, if you're on a Pentium is the same
|
|
thing).
|
|
------------------------------------------------------------------------*/
|
|
if (SocketOpen==1) {
|
|
IPX_Close_Socket(socket);
|
|
}
|
|
|
|
SocketOpen = 0;
|
|
#endif //WINSOCK_IPX
|
|
} /* end of Close_Socket */
|
|
|
|
|
|
/***************************************************************************
|
|
* IPXConnClass::Send_To -- sends the packet to the given address *
|
|
* *
|
|
* The "ImmediateAddress" field of the SendECB must be filled in with the *
|
|
* address of a bridge, or the node address of the destination if there *
|
|
* is no bridge. The NETX call to find this address will always crash *
|
|
* if NETX isn't loaded (ConnectionNum is 0), so this case is trapped & *
|
|
* prevented. *
|
|
* Also, if the address of this IPX connection is known when the *
|
|
* constructor is called, and Configure has been called, Get_Local_Target *
|
|
* is called to precompute the ImmediateAddress; this case is detected & *
|
|
* if the value is already computed, it's just memcpy'd over. *
|
|
* *
|
|
* INPUT: *
|
|
* buf buffer to send *
|
|
* buflen length of buffer *
|
|
* address Address to send to *
|
|
* immed ImmediateAddress value, NULL if none *
|
|
* *
|
|
* OUTPUT: *
|
|
* 1 = OK, 0 = error *
|
|
* *
|
|
* WARNINGS: *
|
|
* none. *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/16/1994 BR : Created. *
|
|
*=========================================================================*/
|
|
int IPXConnClass::Send_To(char *buf, int buflen, IPXAddressClass *address,
|
|
NetNodeType immed)
|
|
{
|
|
#ifdef WINSOCK_IPX
|
|
|
|
immed = immed;
|
|
assert ( immed == NULL );
|
|
PacketTransport->WriteTo ( (void*)buf, buflen, (void*) address );
|
|
return (true);
|
|
|
|
#else //WINSOCK_IPX
|
|
NetNumType net;
|
|
NetNodeType node;
|
|
int rc;
|
|
|
|
#ifdef WIN32
|
|
|
|
unsigned char send_address[6];
|
|
|
|
if (Winsock.Get_Connected()) {
|
|
Winsock.Write((void*)buf, buflen);
|
|
return (true);
|
|
}
|
|
|
|
if (immed) {
|
|
memcpy(send_address, immed, 6);
|
|
#ifdef FIXIT_DESTNET
|
|
// fixes DESTNET
|
|
address->Get_Address(net,node);
|
|
#else
|
|
// breaks DESTNET
|
|
memcpy(node, immed, 6);
|
|
memset (net, 0, sizeof(net) );
|
|
#endif
|
|
} else {
|
|
address->Get_Address(net,node);
|
|
/*.....................................................................
|
|
If the user is logged in & has a valid Novell Connection Number, get the
|
|
bridge address the "official" way
|
|
.....................................................................*/
|
|
if (ConnectionNum != 0) {
|
|
rc = IPX_Get_Local_Target (net, node, Socket, &send_address[0]);
|
|
if (rc!=0) {
|
|
return(false);
|
|
}
|
|
} else {
|
|
/*.....................................................................
|
|
Otherwise, use the destination node address as the ImmediateAddress, and
|
|
just hope there's no network bridge in the path.
|
|
.....................................................................*/
|
|
memcpy(send_address,node,6);
|
|
}
|
|
}
|
|
|
|
return (IPX_Send_Packet95(&send_address[0], (unsigned char*)buf, buflen, (unsigned char*)net, (unsigned char*)node));
|
|
|
|
#else //WIN32
|
|
|
|
void *hdr_ptr;
|
|
void *buf_ptr;
|
|
unsigned long hdr_val;
|
|
unsigned long buf_val;
|
|
|
|
/*------------------------------------------------------------------------
|
|
Clear the ECB & header
|
|
------------------------------------------------------------------------*/
|
|
memset(SendECB, 0, sizeof(ECBType));
|
|
memset(SendHeader, 0, sizeof(IPXHeaderType));
|
|
|
|
/*------------------------------------------------------------------------
|
|
Copy the message into the SendBuf
|
|
------------------------------------------------------------------------*/
|
|
memcpy (SendBuf,buf,buflen);
|
|
|
|
/*------------------------------------------------------------------------
|
|
Convert protected-mode ptrs to real-mode ptrs
|
|
------------------------------------------------------------------------*/
|
|
hdr_val = (unsigned long)SendHeader;
|
|
hdr_ptr = (void *)(((hdr_val & 0xffff0) << 12) | (hdr_val & 0x000f));
|
|
buf_val = (unsigned long)SendBuf;
|
|
buf_ptr = (void *)(((buf_val & 0xffff0) << 12) | (buf_val & 0x000f));
|
|
|
|
/*------------------------------------------------------------------------
|
|
Fill in ECB
|
|
------------------------------------------------------------------------*/
|
|
SendECB->SocketNumber = Socket; // my output socket
|
|
SendECB->PacketCount = 2; // 2 data areas
|
|
SendECB->Packet[0].Address = hdr_ptr;
|
|
SendECB->Packet[0].Length = sizeof(IPXHeaderType);
|
|
SendECB->Packet[1].Address = buf_ptr;
|
|
SendECB->Packet[1].Length = (unsigned short)buflen;
|
|
|
|
/*------------------------------------------------------------------------
|
|
Get the bridge address
|
|
------------------------------------------------------------------------*/
|
|
if (immed) {
|
|
memcpy(SendECB->ImmediateAddress, immed, 6);
|
|
}
|
|
else {
|
|
address->Get_Address(net,node);
|
|
|
|
/*.....................................................................
|
|
If the user is logged in & has a valid Novell Connection Number, get
|
|
the bridge address the "official" way
|
|
.....................................................................*/
|
|
if (ConnectionNum != 0) {
|
|
rc = IPX_Get_Local_Target (net, node, Socket,
|
|
SendECB->ImmediateAddress);
|
|
if (rc!=0) {
|
|
return(0);
|
|
}
|
|
}
|
|
/*.....................................................................
|
|
Otherwise, use the destination node address as the ImmediateAddress,
|
|
and just hope there's no network bridge in the path.
|
|
.....................................................................*/
|
|
else {
|
|
memcpy(SendECB->ImmediateAddress,node,6);
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------------------------------------
|
|
Fill in outgoing header
|
|
------------------------------------------------------------------------*/
|
|
SendHeader->PacketType = 4; // 4 = IPX packet
|
|
address->Get_Address(SendHeader); // fill in header addresses
|
|
SendHeader->DestNetworkSocket = Socket; // destination socket id
|
|
|
|
/*------------------------------------------------------------------------
|
|
Send the packet
|
|
------------------------------------------------------------------------*/
|
|
IPX_Send_Packet(SendECB);
|
|
|
|
/*------------------------------------------------------------------------
|
|
Wait for send to complete
|
|
------------------------------------------------------------------------*/
|
|
while (SendECB->InUse)
|
|
Let_IPX_Breath();
|
|
|
|
if (SendECB->CompletionCode!=0) {
|
|
return(0);
|
|
}
|
|
else {
|
|
return(1);
|
|
}
|
|
|
|
#endif //WIN32
|
|
#endif //WINSOCK_IPX
|
|
|
|
} /* end of Send_To */
|
|
|
|
|
|
/***************************************************************************
|
|
* IPXConnClass::Broadcast -- broadcasts the given packet *
|
|
* *
|
|
* INPUT: *
|
|
* socket desired socket ID number *
|
|
* *
|
|
* OUTPUT: *
|
|
* 1 = OK, 0 = error *
|
|
* *
|
|
* WARNINGS: *
|
|
* none. *
|
|
* *
|
|
* HISTORY: *
|
|
* 12/16/1994 BR : Created. *
|
|
*=========================================================================*/
|
|
int IPXConnClass::Broadcast(char *buf, int buflen)
|
|
{
|
|
#ifdef WINSOCK_IPX
|
|
PacketTransport->Broadcast (buf, buflen);
|
|
return (true);
|
|
|
|
#else //WINSOCK_IPX
|
|
|
|
#ifdef WIN32
|
|
|
|
if (Winsock.Get_Connected()) {
|
|
Winsock.Write((void*)buf, buflen);
|
|
return(true);
|
|
} else {
|
|
return (IPX_Broadcast_Packet95((unsigned char*)buf, buflen));
|
|
}
|
|
|
|
#else //WIN32
|
|
|
|
void *hdr_ptr;
|
|
void *buf_ptr;
|
|
unsigned long hdr_val;
|
|
unsigned long buf_val;
|
|
|
|
/*------------------------------------------------------------------------
|
|
Clear the ECB & header
|
|
------------------------------------------------------------------------*/
|
|
memset(SendECB, 0, sizeof(ECBType));
|
|
memset(SendHeader, 0, sizeof(IPXHeaderType));
|
|
|
|
/*------------------------------------------------------------------------
|
|
Copy the message into the SendBuf
|
|
------------------------------------------------------------------------*/
|
|
memcpy (SendBuf,buf,buflen);
|
|
|
|
/*------------------------------------------------------------------------
|
|
Convert protected-mode ptrs to real-mode ptrs
|
|
------------------------------------------------------------------------*/
|
|
hdr_val = (unsigned long)SendHeader;
|
|
hdr_ptr = (void *)(((hdr_val & 0xffff0) << 12) | (hdr_val & 0x000f));
|
|
buf_val = (unsigned long)SendBuf;
|
|
buf_ptr = (void *)(((buf_val & 0xffff0) << 12) | (buf_val & 0x000f));
|
|
|
|
/*------------------------------------------------------------------------
|
|
Fill in ECB
|
|
------------------------------------------------------------------------*/
|
|
SendECB->SocketNumber = Socket; // my output socket
|
|
SendECB->PacketCount = 2; // 2 data areas
|
|
SendECB->Packet[0].Address = hdr_ptr;
|
|
SendECB->Packet[0].Length = sizeof(IPXHeaderType);
|
|
SendECB->Packet[1].Address = buf_ptr;
|
|
SendECB->Packet[1].Length = (unsigned short)buflen;
|
|
SendECB->ImmediateAddress[0] = 0xff;
|
|
SendECB->ImmediateAddress[1] = 0xff;
|
|
SendECB->ImmediateAddress[2] = 0xff;
|
|
SendECB->ImmediateAddress[3] = 0xff;
|
|
SendECB->ImmediateAddress[4] = 0xff;
|
|
SendECB->ImmediateAddress[5] = 0xff;
|
|
|
|
/*------------------------------------------------------------------------
|
|
Fill in outgoing header
|
|
------------------------------------------------------------------------*/
|
|
SendHeader->PacketType = 4; // 4 = IPX packet
|
|
SendHeader->DestNetworkNumber[0] = 0xff; // 0xff = broadcast
|
|
SendHeader->DestNetworkNumber[1] = 0xff;
|
|
SendHeader->DestNetworkNumber[2] = 0xff;
|
|
SendHeader->DestNetworkNumber[3] = 0xff;
|
|
SendHeader->DestNetworkNode[0] = 0xff; // 0xff = broadcast
|
|
SendHeader->DestNetworkNode[1] = 0xff;
|
|
SendHeader->DestNetworkNode[2] = 0xff;
|
|
SendHeader->DestNetworkNode[3] = 0xff;
|
|
SendHeader->DestNetworkNode[4] = 0xff;
|
|
SendHeader->DestNetworkNode[5] = 0xff;
|
|
SendHeader->DestNetworkSocket = Socket; // destination socket #
|
|
|
|
/*------------------------------------------------------------------------
|
|
Send the packet
|
|
------------------------------------------------------------------------*/
|
|
IPX_Send_Packet(SendECB);
|
|
|
|
/*------------------------------------------------------------------------
|
|
Wait for send to complete
|
|
------------------------------------------------------------------------*/
|
|
while (SendECB->InUse) {
|
|
Let_IPX_Breath();
|
|
}
|
|
|
|
if (SendECB->CompletionCode!=0) {
|
|
return(0);
|
|
}
|
|
else {
|
|
return(1);
|
|
}
|
|
|
|
#endif //WIN32
|
|
#endif //WINSOCK_IPX
|
|
} /* end of Broadcast */
|
|
|
|
/************************** end of ipxconn.cpp *****************************/
|
|
|