home *** CD-ROM | disk | FTP | other *** search
-
- /***************************************************/
- /***************************************************/
- /* IPX LIBRARY ROUTINES */
- /* (c) 1992 by R. Kvinnesland */
- /***************************************************/
- /***************************************************/
-
- /* ------- */
- /* ------- */
- /* headers */
- /* ------- */
- /* ------- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <dos.h>
- #include <time.h>
- #include <string.h>
- #include <conio.h>
- #include <io.h>
- #include <fcntl.h>
- #include <sys\stat.h>
-
- #include "rkipx.h"
-
- /* ------------------------------------- */
- /* ------------------------------------- */
- /* global variables */
- /* ------------------------------------- */
- /* ------------------------------------- */
-
- unsigned IPXerrno; // latest IPX error
- time_t IPXto = IPX_TIMEOUT; // secs to wait for IPX command
- unsigned IPXtries = IPX_TRIES; // # times to retry RX/TX
- unsigned IPXdatalen = MINIPXDATALEN; // size of IPX packet data buffer
-
- /* -------------------------------- */
- /* ---- I N T E R N A L U S E ---- */
- /* -------------------------------- */
-
- static void (*IPXAPI)(void);
-
- /************************************************************************/
- /************************************************************************/
- /* IPX LOW-LEVEL FUNCTIONS */
- /************************************************************************/
- /************************************************************************/
-
- unsigned IPXInstalled( void )
- {
- union REGS regs;
- struct SREGS sregs;
-
- regs.x.ax = IPX_MULTIPLEX;
- int86x( DOS_MULTIPLEX_VECTOR, ®s, ®s, &sregs );
- IPXAPI = MK_FP( sregs.es, regs.x.di );
- return( regs.h.al );
- }
-
- /************************************************************************/
- /************************************************************************/
-
- unsigned IPXSocketOpen( BYTE *socket, BYTE longevity )
- {
- _DL = socket[0];
- _DH = socket[1];
- _AL = longevity;
- _BX = SOCKET_OPEN;
- IPXAPI();
- socket[0] = _DL;
- socket[1] = _DH;
- _AH = 0;
- return( _AX );
- }
-
- /**************************************************************************/
- /**************************************************************************/
-
- void IPXSocketClose( BYTE *socket )
- {
- _DL = socket[0];
- _DH = socket[1];
- _BX = SOCKET_CLOSE;
- IPXAPI();
- return;
- }
-
- /**************************************************************************/
- /**************************************************************************/
-
- unsigned IPXGetLocalTarget( LOCALTARGET *lt )
- {
- _ES = FP_SEG( (void far *)lt );
- _SI = FP_OFF( (void far *)lt->INA.Network );
- _DI = FP_OFF( (void far *)lt->ImmediateAddr );
- _BX = GET_LOCAL_TARGET;
- IPXAPI();
- _AH = 0;
-
- return( _AX );
- }
-
- /**************************************************************************/
- /**************************************************************************/
-
- void IPXSendPacket( EVENTCONTROLBLOCK *ecb )
- {
-
- _ES = FP_SEG( (void far *)ecb );
- _SI = FP_OFF( (void far *)ecb );
- _BX = SEND_PACKET;
- IPXAPI();
- return;
- }
-
- /**************************************************************************/
- /**************************************************************************/
-
- void IPXListenForPacket( EVENTCONTROLBLOCK *ecb )
- {
-
- _ES = FP_SEG( (void far *)ecb );
- _SI = FP_OFF( (void far *)ecb );
- _BX = LISTEN_FOR_PACKET;
- IPXAPI();
- return;
- }
-
- /**************************************************************************/
- /**************************************************************************/
-
- void IPXGetInternetworkAddress( INTNETADDR *ina )
- {
- _ES = FP_SEG( (void far *)ina );
- _SI = FP_OFF( (void far *)ina );
- _BX = GET_INTERNETWORK_ADDR;
- IPXAPI();
- return;
- }
-
- /**************************************************************************/
- /**************************************************************************/
-
- void IPXRelinquishControl( void )
- {
- _BX = RELINQUISH_CONTROL;
- IPXAPI();
- return;
- }
-
- /**************************************************************************/
- /**************************************************************************/
-
- void IPXDisconnectFromTarget( NETADDR *naddr )
- {
- _ES = FP_SEG( (void far *)naddr );
- _SI = FP_OFF( (void far *)naddr );
- _BX = DISCONNECT_FROM_TARGET;
- IPXAPI();
- return;
- }
-
- /**************************************************************************/
- /**************************************************************************/
-
- unsigned IPXCancelEvent( EVENTCONTROLBLOCK *ecb )
- {
- _ES = FP_SEG( (void far *)ecb );
- _SI = FP_OFF( (void far *)ecb );
- _BX = CANCEL_EVENT;
- IPXAPI();
- _AH = 0;
- return( _AX );
- }
-
- /**************************************************************************/
- /**************************************************************************/
-
- unsigned IPXGetIntervalMarker( void )
- {
- _BX = GET_INTERVAL_MARKER;
- IPXAPI();
- return( _AX );
- }
-
- /**************************************************************************/
- /**************************************************************************/
-
- void IPXScheduleEvent( EVENTCONTROLBLOCK *ecb, unsigned delay )
- {
-
- _ES = FP_SEG( (void far *)ecb );
- _SI = FP_OFF( (void far *)ecb );
- _AX = delay;
- _BX = SCHEDULE_EVENT;
- IPXAPI();
- return;
- }
-
- /**************************************************************************/
- /**************************************************************************/
- /* INTERNAL UTILITY FUNCTIONS */
- /**************************************************************************/
- /**************************************************************************/
-
- int IPXTimeOutRT( EVENTCONTROLBLOCK *ecb,
- time_t delay,
- void (*RTfunc)(void) )
- {
- time_t start_time;
-
- start_time = time( NULL );
- while ( ecb->InUse )
- {
- IPXRelinquishControl();
- if ( RTfunc != NULL )
- {
- RTfunc();
- }
- if ( (time( NULL ) - start_time) > delay ) // next FULL second!
- {
- IPXCancelEvent( ecb );
- return( TRUE );
- }
- }
- return( !TRUE );
- }
-
- /*************************/
- /*************************/
-
- /* returns TRUE if characters in string are legal hex digits */
-
- int xatoxb( BYTE *d, char *s )
- {
- while( *s )
- {
- if ( !isxdigit( *s ) )
- {
- return( !TRUE );
- }
- *d = (isdigit(*s) ? *s++ - '0' : toupper(*s++) - '7') << 4;
- if ( !isxdigit( *s ) )
- {
- return( !TRUE );
- }
- *d++ += (isdigit(*s) ? *s++ - '0' : toupper(*s++) - '7');
- }
- return( TRUE );
- }
-
- /* ======================================================= */
-
- /* allows/ignores non-hex ASCII delimiters in string */
-
- void xantoxb( BYTE *d, char *s, unsigned len )
- {
- while( len-- )
- {
- while( !isxdigit( *s ) )
- s++;
- *d = (isdigit(*s) ? *s++ - '0' : toupper(*s++) - '7') << 4;
- while( !isxdigit( *s ) )
- s++;
- *d++ += (isdigit(*s) ? *s++ - '0' : toupper(*s++) - '7');
- }
- return;
- }
-
- /*************************************************************************/
- /*************************************************************************/
-
- void ShowECB( EVENTCONTROLBLOCK *ecb )
- {
- unsigned i;
-
- printf( "\n" );
- printf( "LINK ADDR: %04X:%04X\n",
- (unsigned)((long)ecb->LinkAddr / SEGSIZE ),
- (unsigned)((long)ecb->LinkAddr % SEGSIZE) );
-
- printf( " ESR: %04X:%04X\n",
- (unsigned)((long)ecb->ESR / SEGSIZE),
- (unsigned)((long)ecb->ESR % SEGSIZE) );
-
- printf( " IN USE: %02X\n",
- ecb->InUse );
-
- printf( "COMP CODE: %02X\n",
- ecb->CompletionCode );
-
- printf( " SOCKET: %02X %02X\n",
- ecb->Socket[0],
- ecb->Socket[1] );
-
- printf( "IPX WrkSp: %02X %02X %02X %02X\n",
- ecb->IPXWorkspace[0],
- ecb->IPXWorkspace[1],
- ecb->IPXWorkspace[2],
- ecb->IPXWorkspace[3] );
-
- printf( "Drv WrkSp: %02X %02X %02X %02X",
- ecb->DriverWorkspace[0],
- ecb->DriverWorkspace[1],
- ecb->DriverWorkspace[2],
- ecb->DriverWorkspace[3] );
- printf( " %02X %02X %02X %02X",
- ecb->DriverWorkspace[4],
- ecb->DriverWorkspace[5],
- ecb->DriverWorkspace[6],
- ecb->DriverWorkspace[7] );
- printf( " %02X %02X %02X %02X\n",
- ecb->DriverWorkspace[8],
- ecb->DriverWorkspace[9],
- ecb->DriverWorkspace[10],
- ecb->DriverWorkspace[11] );
-
- printf( "Immd Addr: %02X %02X %02X %02X %02X %02X\n",
- ecb->ImmediateAddr[0],
- ecb->ImmediateAddr[1],
- ecb->ImmediateAddr[2],
- ecb->ImmediateAddr[3],
- ecb->ImmediateAddr[4],
- ecb->ImmediateAddr[5] );
-
- printf( " FRAG CNT: %u\n", ecb->FragmentCnt );
-
- for( i = 0; i < ecb->FragmentCnt; i++ )
- {
- printf( " FRAG %03u - @BUFR: %04X:%04X LEN: %u\n",
- i+1,
- (unsigned)((long)ecb->Fragment[i].BufAddr / SEGSIZE),
- (unsigned)((long)ecb->Fragment[i].BufAddr % SEGSIZE),
- ecb->Fragment[i].Len );
- }
-
- return;
- }
-
- /*************************************************************************/
- /*************************************************************************/
-
- void ShowIPXPacket( IPXHEADER *ipxhdr )
- {
- unsigned i;
-
- printf( "\n" );
- printf( " Checksum: %04X\n", HILOSWAP( ipxhdr->Chksum ) );
- printf( " IPX Pkt Len: %u\n", HILOSWAP( ipxhdr->Len ) );
- printf( " RX Data Len: %u\n", HILOSWAP( ipxhdr->Len ) - sizeof(IPXHEADER) );
- printf( "TransprtCtrl: %02X\n", ipxhdr->TransportCtrl );
- printf( " PacketType: %02X\n", ipxhdr->PacketType );
-
- printf( " DestNetwork: %02X %02X %02X %02X\n",
- ipxhdr->DestAddr.INA.Network[0],
- ipxhdr->DestAddr.INA.Network[1],
- ipxhdr->DestAddr.INA.Network[2],
- ipxhdr->DestAddr.INA.Network[3] );
-
- printf( " DestNode: %02X %02X %02X %02X %02X %02X\n",
- ipxhdr->DestAddr.INA.Node[0],
- ipxhdr->DestAddr.INA.Node[1],
- ipxhdr->DestAddr.INA.Node[2],
- ipxhdr->DestAddr.INA.Node[3],
- ipxhdr->DestAddr.INA.Node[4],
- ipxhdr->DestAddr.INA.Node[5] );
-
- printf( " DestSocket: %02X %02X\n",
- ipxhdr->DestAddr.Socket[0],
- ipxhdr->DestAddr.Socket[1] );
-
- printf( " SrceNetwork: %02X %02X %02X %02X\n",
- ipxhdr->SrceAddr.INA.Network[0],
- ipxhdr->SrceAddr.INA.Network[1],
- ipxhdr->SrceAddr.INA.Network[2],
- ipxhdr->SrceAddr.INA.Network[3] );
-
- printf( " SrceNode: %02X %02X %02X %02X %02X %02X\n",
- ipxhdr->SrceAddr.INA.Node[0],
- ipxhdr->SrceAddr.INA.Node[1],
- ipxhdr->SrceAddr.INA.Node[2],
- ipxhdr->SrceAddr.INA.Node[3],
- ipxhdr->SrceAddr.INA.Node[4],
- ipxhdr->SrceAddr.INA.Node[5] );
-
- printf( " SrceSocket: %02X %02X\n",
- ipxhdr->SrceAddr.Socket[0],
- ipxhdr->SrceAddr.Socket[1] );
-
- return;
- }
-
- /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
- /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
- /* HIGH-LEVEL APPLICATION PROGRAMMING IPX INTERFACE FUNCTIONS */
- /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
- /*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
-
-
- /*******************************************************************/
- /*******************************************************************/
- /*
- ------------------------
- ------------------------
- FUNCTION: IPXReceiveRT()
- ------------------------
- ------------------------
-
- Receive data into a buffer or file from a non-specified sender.
-
- NOTE:
- The sender must know the internetwork address and socket of the
- machine that is to receive its transmission(s), but the receiver
- merely has to issue a LISTEN & can then receive from any sender.
-
- ----------
- ----------
- PROTOTYPE:
- ----------
- ----------
-
- unsigned IPXReceiveRT( long *BfrLen,
- BYTE *FileOrBfr,
- char *SocketStr,
- void (*RTfunc)(void) );
-
- ---------
- ---------
- INPUT(S):
- ---------
- ---------
-
- BfrLen = 0 if receiving a file
- OR
- the maximum # of bytes that can be stored in a given buffer
-
- FileOrBfr = (string) name of file (path optional) into which to write
- the data that is received
- OR
- pointer to given byte buffer into which to store the data
- that is received
-
- SocketStr = 4 character hex-ASCII string of IPX Socket to
- use for receiving. Note that certain NOVELL sockets
- are reserved, and the caller is cautioned to use
- socket numbers "40xx", e.g., "4010", "40A1", etc.
-
- RTfunc = pointer to a function which is to be called during
- time out loops when IPX command is pending. Set
- to NULL if you don't need this "real time" capability.
-
- ----------
- ----------
- RETURN(S):
- ----------
- ----------
-
- 0x00 - GOOD_IPX_RETURN - all went well.
-
-
- 0x10 - BAD_LOCAL_TARGET - the internal IPX call to find the sender's
- local target failed. Check the global variable IPXerrno for the
- specific reason, e.g.:
-
- 0xFA - DEST_NODE_PATH_NOT_FND - the 6-byte node address
- specified in the received IPX packet parameter SrceAddr
- could not be found. Either the packet was corrupted,
- or the sending machine with that node has died.
-
-
- 0x11 - BAD_SOCKET_PARAM - the SocketStr parameter did not consist of
- a string of four hex-ascii digits.
-
-
- 0x12 - BAD_SOCKET_OPEN - the attempt to open the socket specified in
- SocketStr parameter failed. The global variable IPXerrno will contain
- return code received from IPX. It can be one of the following:
-
- 0xFE - SOCKET_TABLE_FULL - each machine gets 20 sockets, so
- this error should never occur unless other non-"well
- behaved" IPX applications are running on the machine.
-
- 0xFF - SOCKET_ALREADY_OPEN - it will be closed upon return,
- so try again. It is not ignored because at the point
- of call the socket shouldn't have been open, and all
- discrepancies will be caught and reported!
-
-
- 0x20 - BAD_TX_TRY - an attempt to send a packet failed, due to
- failure of either the network or the configuration of the receiving
- machine. Check the global IPXerrno to discern the problem.
- It should be one of the following:
-
- 0xFC - EVENT_CANCELED - send request was canceled by
- application due to timeout.
-
- 0xFD - FRAGMENT_SIZE_ERROR - malformed packet size, either
- less than 30 bytes or greater than 576 bytes, or
- the event control block's Fragment Count field was 0.
-
- 0xFE - DESTINATION_NOT_FOUND - the destination machine,
- specified in the NETADDR parameter, is not on the
- network or not powered up.
-
- 0xFF - NETWORK_FAILURE - network or hardware failure.
-
-
- 0x21 - BAD_RETRIES - the receiver, while awaiting data from the
- sending machine, has exhausted its retry number & count series.
- Check IPXerrno for:
-
- 0xFC - EVENT_CANCELED - listen request was canceled by
- application due to timeout.
-
- 0xFD - FRAGMENT_SIZE_ERROR - either the event control block's
- Fragment Count field was 0, or the receiver's buffer
- space was too small to hold the incoming data.
-
- 0xFF - ECB_SOCKET_NOT_OPEN - Socket for listening has not
- been opened by the application.
-
-
- 0x22 - BAD_RX_SEQ_NUM - the receiving machine has received a block
- of data whose sequence number is unexpected. If this has occured,
- a network failure has caused the transmission to become garbled,
- or the sending machine had aborted the current send/received sequence
- and restarted anew within the retry number & timeout series of the
- receiving machine. Both scenarios are highly unlikely.
-
-
- 0x30 - BAD_FILE_OPEN - the file to be received, specified by
- the FileOrBfr parameter, could not be opened. Check syntax of
- ASCIIZ string to make sure path and filename are correct, and
- don't forget to use double slashes in the string when specifying
- a path! For example, "D:\MYPATH\MYFILE.DAT" is not a valid C
- string. You must pass it as "D:\\MYPATH\\MYFILE.DAT".
-
-
- 0x31 - BAD_FILE_WRITE - problem writing to the file specified in the
- parameter FileOrBfr, even though the file was successfully opened.
- This should never occur, barring disk failure or some strange
- interaction between the caller's program and other programs running
- as background processes or TSR's.
-
-
- 0xBB - USER_TERMINATED - the user has chosen to abort the application
- by hitting the two SHIFT keys & an ALT key during a send/receive sequence.
-
-
- 0xDD - IPX_NOT_PRESENT - IPX API interface was not detected. Make
- sure NOVELL's IPX.COM or equivalent has been run before attempting to
- access IPX functions.
-
-
- -------------------------
- -------------------------
- APPLICATION CODE EXAMPLE:
- -------------------------
- -------------------------
-
- #include "ipx.h"
- #define RXSOCKET "4050"
- #define RXBFRSIZE 8192
-
- int main( void )
- {
- unsigned rc;
- long len;
- BYTE *RxBfr;
-
- // receiving a file
- len = 0;
- rc = IPXReceiveRT( &len, "RXDATA.DAT", RXSOCKET, NULL );
- if ( rc != GOOD_IPX_RETURN )
- {
- printf( "FUNCTION ERROR: %02X IPX ERROR: %02X", rc, IPXerrno );
- // take appropriate error action here
- return( -1 );
- }
-
- // receiving a buffer
- RxBfr = calloc( 1, RXBFRSIZE );
- if ( !RxBfr )
- {
- printf( "MEMORY ALLOCATION FAILURE!" );
- return( -1 );
- }
-
- len = RXBFRSIZE;
- rc = IPXReceiveRT( &len, RxBfr, RXSOCKET, NULL );
- if ( rc != GOOD_IPX_RETURN )
- {
- printf( "FUNCTION ERROR: %02X IPX ERROR: %02X", rc, IPXerrno );
- // take appropriate error action here
- return( -1 );
- }
-
- return( 0 );
- }
-
- */
- /*******************************************************************/
- /*******************************************************************/
-
- unsigned IPXReceiveRT( long *BfrLen,
- BYTE *FileOrBfr,
- char *SocketStr,
- void (*RTfunc)(void) )
- {
-
- int fhandle;
- long totRX;
- BYTE *RXptr;
- unsigned rc, lenRX, retries;
- int TXflg, fileflg;
- BYTE Socket[2];
- BYTE expected_seq;
- NETADDR TXna;
-
- BYTE *pIPXbfrRX, *pIPXbfrTX;
- IPXHEADER *pIPXpktRX, *pIPXpktTX;
- EVENTCONTROLBLOCK *pIPXecbRX, *pIPXecbTX;
- LOCALTARGET *pLocalTarget;
-
- /* -------------------------------------------------------------- */
- /* check that IPX API has been installed or attempt to install it */
- /* -------------------------------------------------------------- */
-
- if (
- !(IPXAPI)
- &&
- (IPXInstalled() != IPX_PRESENT)
- )
- {
- return( IPX_NOT_PRESENT );
- }
-
- /* ------------------------------------------- */
- /* open socket for peer-to-peer communications */
- /* ------------------------------------------- */
-
- if (
- (strlen( SocketStr ) != (sizeof(Socket)*2)) // 2 ASCII chars per byte
- ||
- !(xatoxb( Socket, SocketStr ))
- )
- {
- return( BAD_SOCKET_PARAM );
- }
-
- IPXerrno = IPXSocketOpen( Socket, SOCKET_SHORT_LIVED );
- if ( IPXerrno != IPX_SUCCESS )
- {
- if ( IPXerrno == SOCKET_ALREADY_OPEN )
- /*
- sure, we could just go ahead,
- but the socket really shouldn't have been open at this point,
- and until this library has been thoroughly shaken out,
- (hopefully) ALL discrepancies will be caught & reported!
- */
- {
- IPXSocketClose( Socket );
- }
- return( BAD_SOCKET_OPEN );
- }
-
- /* -------------------- */
- /* set the receive mode */
- /* -------------------- */
-
- fileflg = TRUE;
- if ( *BfrLen )
- {
- RXptr = FileOrBfr;
- fileflg = !TRUE;
- }
-
- /* ----------------------- */
- /* attempt to open RX file */
- /* ----------------------- */
-
- if ( fileflg )
- {
- fhandle = open( FileOrBfr,
- O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
- S_IREAD | S_IWRITE );
- if ( fhandle == FILE_PROBLEM )
- {
- IPXSocketClose( Socket );
- return( BAD_FILE_OPEN );
- }
- }
-
- /* ------------------------- */
- /* allocate necessary memory */
- /* ------------------------- */
-
- pIPXbfrRX = (BYTE *)calloc( 1, SEQLEN+IPXdatalen );
- pIPXbfrTX = (BYTE *)calloc( 1, SEQLEN+IPXdatalen );
- pIPXpktRX = (IPXHEADER *)calloc( 1, sizeof(IPXHEADER) );
- pIPXpktTX = (IPXHEADER *)calloc( 1, sizeof(IPXHEADER) );
- pIPXecbRX = (EVENTCONTROLBLOCK *)calloc( 1, sizeof(EVENTCONTROLBLOCK) );
- pIPXecbTX = (EVENTCONTROLBLOCK *)calloc( 1, sizeof(EVENTCONTROLBLOCK) );
- pLocalTarget = (LOCALTARGET *)calloc( 1, sizeof(LOCALTARGET) );
-
- if (
- pIPXbfrRX == NULL ||
- pIPXbfrTX == NULL ||
- pIPXpktRX == NULL ||
- pIPXpktTX == NULL ||
- pIPXecbRX == NULL ||
- pIPXecbTX == NULL ||
- pLocalTarget == NULL
- )
- {
- IPXSocketClose( Socket );
- *BfrLen = 0;
- if ( fileflg )
- {
- close( fhandle );
- unlink( FileOrBfr );
- }
- if ( pIPXbfrRX )
- free( pIPXbfrRX );
- if ( pIPXbfrTX )
- free( pIPXbfrTX );
- if ( pIPXpktRX )
- free( pIPXpktRX );
- if ( pIPXpktTX )
- free( pIPXpktTX );
- if ( pIPXecbRX )
- free( pIPXecbRX );
- if ( pIPXecbTX )
- free( pIPXecbTX );
- if ( pLocalTarget )
- free( pLocalTarget );
- return( BAD_MEMORY_ALLOC );
- }
-
- /* --------------------------- */
- /* initialize ECBs/IPX packets */
- /* --------------------------- */
-
- memcpy( pIPXecbRX->Socket, Socket, sizeof(pIPXecbRX->Socket) );
- pIPXpktRX->PacketType = IPX_PACKET_TYPE;
- pIPXecbRX->FragmentCnt = 2;
- pIPXecbRX->Fragment[0].BufAddr = (void *)pIPXpktRX;
- pIPXecbRX->Fragment[0].Len = sizeof(IPXHEADER);
- pIPXecbRX->Fragment[1].BufAddr = (void *)pIPXbfrRX;
- pIPXecbRX->Fragment[1].Len = SEQLEN+IPXdatalen;
-
- memcpy( pIPXecbTX->Socket, Socket, sizeof(pIPXecbTX->Socket) );
- pIPXpktTX->PacketType = IPX_PACKET_TYPE;
- pIPXecbTX->FragmentCnt = 2;
- pIPXecbTX->Fragment[0].BufAddr = (void *)pIPXpktTX;
- pIPXecbTX->Fragment[0].Len = sizeof(IPXHEADER);
- pIPXecbTX->Fragment[1].BufAddr = (void *)pIPXbfrTX;
- pIPXecbTX->Fragment[1].Len = SEQLEN+strlen( ACKSTR );
- strcpy( pIPXbfrTX+SEQLEN, ACKSTR );
-
- /* =================== */
- /* DATA RX/ACK TX LOOP */
- /* =================== */
-
- expected_seq = FIRST_SEQ_NUM;
- TXflg = !TRUE;
- retries = 0;
- totRX = 0;
- while ( TRUE )
- {
-
- /* if user decides to break it off, then quit */
- if ( USERBREAK )
- {
- rc = USER_TERMINATED;
- break;
- }
-
- /* issue LISTEN for pending RX of data */
- IPXListenForPacket( pIPXecbRX );
-
- /* ----------------------------- */
- /* issue SEND to ACK previous RX */
- /* ----------------------------- */
-
- if ( TXflg )
- {
-
- /* RX source address = TX destination address */
- memcpy( &pIPXpktTX->DestAddr, &TXna, sizeof(NETADDR) );
-
- /* must also fill immediate address of ECB */
- memcpy( pLocalTarget, &TXna, sizeof(NETADDR) );
-
- IPXerrno = IPXGetLocalTarget( pLocalTarget );
- if ( IPXerrno != IPX_SUCCESS )
- {
- IPXCancelEvent( pIPXecbRX );
- rc = BAD_LOCAL_TARGET;
- break;
- }
-
- memcpy( pIPXecbTX->ImmediateAddr,
- pLocalTarget->ImmediateAddr,
- sizeof(pIPXecbTX->ImmediateAddr) );
-
- /* retain RX seq # for ACK */
- *pIPXbfrTX = *pIPXbfrRX;
-
- /* send the ACK & check result of TX */
- IPXSendPacket( pIPXecbTX );
- IPXTimeOutRT( pIPXecbTX, IPXto, RTfunc );
- IPXerrno = pIPXecbTX->CompletionCode;
- if ( IPXerrno != IPX_SUCCESS )
- {
- IPXCancelEvent( pIPXecbRX );
- rc = BAD_TX_TRY;
- break;
- }
-
- /* ------------------------ */
- /* TX was successfully sent */
- /* ------------------------ */
-
- /* if the previous RX data that we are now ACKing */
- /* did not fill the RX buffer, consider it EOT */
- if ( lenRX < IPXdatalen )
- {
- IPXCancelEvent( pIPXecbRX );
- rc = GOOD_IPX_RETURN;
- break;
- }
-
- } // end of if ( TXflg )
-
- /* -------------- */
- /* monitor LISTEN */
- /* -------------- */
-
- /* monitor result of pending LISTEN */
- IPXTimeOutRT( pIPXecbRX, IPXto, RTfunc );
- IPXerrno = pIPXecbRX->CompletionCode;
-
- /* ----------------- */
- /* RX was successful */
- /* ----------------- */
-
- if ( IPXerrno == IPX_SUCCESS )
- {
-
- /* if first RX then save Sender's address */
- if ( !totRX )
- {
- memcpy( &TXna, &pIPXpktRX->SrceAddr, sizeof(NETADDR) );
- }
-
- /* ignore all but latest Sender */
- if ( memcmp( &TXna, &pIPXpktRX->SrceAddr, sizeof(NETADDR) ) )
- {
- TXflg = !TRUE;
- continue;
- }
-
- /* check sequence number */
- if ( expected_seq != *pIPXbfrRX )
- {
- rc = BAD_RX_SEQ_NUM;
- break;
- }
-
- /* if any data was received, then save it */
- lenRX = HILOSWAP( pIPXpktRX->Len ) - (sizeof(IPXHEADER)+SEQLEN);
- if ( lenRX )
- {
-
- /* data to be written to file */
- if ( fileflg )
- {
- rc = write( fhandle, pIPXbfrRX+SEQLEN, lenRX );
- if ( lenRX != rc )
- {
- rc = BAD_FILE_WRITE;
- break;
- }
- }
-
- /* data to be copied into buffer */
- if ( !fileflg )
- {
- totRX += lenRX;
- if ( *BfrLen < totRX )
- {
- rc = BAD_RX_BFR_LEN;
- break;
- }
- memcpy( RXptr, pIPXbfrRX+SEQLEN, lenRX );
- RXptr += lenRX;
- }
-
- } // end of if ( lenRX )
-
- /* ACK is now owed to sender; clear retry cnts & bump seq # */
- TXflg = TRUE;
- retries = 0;
- expected_seq++;
-
- } // end of if ( IPXerrno == IPX_SUCCESS )
-
- /* --------------------- */
- /* RX was NOT successful */
- /* --------------------- */
-
- if ( IPXerrno != IPX_SUCCESS )
- {
-
- /* if maximum retries have been exhausted, then quit */
- if ( retries++ >= IPXtries )
- {
- rc = BAD_RETRIES;
- break;
- }
-
- } // end of if ( IPXerrno != IPX_SUCCESS )
-
- } // end of while ( TRUE )
-
- /* ---------------- */
- /* bring it on home */
- /* ---------------- */
-
- IPXSocketClose( Socket );
-
- /* if file mode, close it & delete it if something went wrong */
- if ( fileflg )
- {
- close( fhandle );
- if ( rc != GOOD_IPX_RETURN )
- {
- unlink( FileOrBfr );
- }
- }
-
- /* if buffer mode, set number of bytes read into buffer */
- if ( !fileflg )
- {
- *BfrLen = totRX;
- if ( rc != GOOD_IPX_RETURN )
- {
- *BfrLen = 0;
- }
- }
-
- /* free that mem! */
- free( pIPXbfrRX );
- free( pIPXbfrTX );
- free( pIPXpktRX );
- free( pIPXpktTX );
- free( pIPXecbRX );
- free( pIPXecbTX );
- free( pLocalTarget );
-
- return( rc );
- }
-
- /*******************************************************************/
- /*******************************************************************/
- /*
- ---------------------
- ---------------------
- FUNCTION: IPXSendRT()
- ---------------------
- ---------------------
-
- Send a file or buffer to specified destination machine
-
- ----------
- ----------
- PROTOTYPE:
- ----------
- ----------
-
- unsigned IPXSendRT( long *BfrLen,
- BYTE *FileOrBfr,
- char *SocketStr,
- NETADDR *Destination,
- void (*RTfunc)(void) );
-
- ---------
- ---------
- INPUT(S):
- ---------
- ---------
-
- BfrLen = 0 if sending a file
- OR
- the # of bytes to send from a given byte buffer
-
- FileOrBfr = (string) name of file (path optional) to send
- OR
- pointer to given byte buffer from which to send data
-
- SocketStr = 4 character hex-ASCII string of IPX Socket to
- use for sending. Note that certain NOVELL sockets
- are reserved, and the caller is cautioned to use
- socket numbers "40xx", e.g., "4010", "40A1", etc.
-
- Destination = structure containing Network Address, Node
- Address, and receiving socket number of the
- machine that is to receive the file/buffer data.
- See IPX.H for structure layout; if needed, use
- function xatoxb() for converting hex-ascii
- strings to hex-binary bytes.
-
- RTfunc = pointer to a function which is to be called during
- time out loops when IPX command is pending. Set
- to NULL if you don't need this "real time" capability.
-
- ----------
- ----------
- RETURN(S):
- ----------
- ----------
-
- 0x00 - GOOD_IPX_RETURN - all went well.
-
-
- 0x10 - BAD_LOCAL_TARGET - the internal IPX call to find the receiver's
- local target failed. Check the global variable IPXerrno for the
- specific reason, e.g.:
-
- 0xFA - DEST_NODE_PATH_NOT_FND - the 6-byte node address
- specified in the passed parameter Destination.INA.Node
- could not be found. Either the node is non-extant, or
- the machine with that node is not powered on.
-
-
- 0x11 - BAD_SOCKET_PARAM - the SocketStr parameter did not consist of
- a string of four hex-ascii digits.
-
-
- 0x12 - BAD_SOCKET_OPEN - the attempt to open the socket specified in
- SocketStr parameter failed. The global variable IPXerrno will contain
- return code received from IPX. It can be one of the following:
-
- 0xFE - SOCKET_TABLE_FULL - each machine gets 20 sockets, so
- this error should never occur unless other non-"well
- behaved" IPX applications are running on the machine.
-
- 0xFF - SOCKET_ALREADY_OPEN - it will be closed upon return,
- so try again. It is not ignored because at the point
- of call the socket shouldn't have been open, and all
- discrepancies will be caught and reported!
-
-
- 0x20 - BAD_TX_TRY - the attempt to send an IPX packet failed due to
- a problem of either the network or the configuration of the sending
- machine. Check the global IPXerrno to discern the problem. It should
- be one of the following:
-
- 0xFC - EVENT_CANCELED - send request was canceled by
- application due to timeout.
-
- 0xFD - FRAGMENT_SIZE_ERROR - malformed packet size, either
- less than 30 bytes or greater than 576 bytes, or
- the event control block's Fragment Count field was 0.
-
- 0xFE - DESTINATION_NOT_FOUND - the destination machine,
- specified in the NETADDR parameter, is not on the
- network or not powered up.
-
- 0xFF - NETWORK_FAILURE - network or hardware failure.
-
-
- 0x21 - BAD_RETRIES - the sender has been awaiting an acknowledgement
- from the receiver for most recently sent data, and has exhausted its
- retry number & count series. Check IPXerrno for:
-
- 0xFC - EVENT_CANCELED - listen request was canceled by
- application due to timeout.
-
- 0xFD - FRAGMENT_SIZE_ERROR - either the event control block's
- Fragment Count field was 0, or the receiver's buffer
- space was too small to hold the incoming data.
-
- 0xFF - ECB_SOCKET_NOT_OPEN - Socket for listening has not
- been opened by the application.
-
-
- 0x22 - BAD_RX_SEQ_NUM - the destination machine has transmitted an
- acknowledgement to received data, but the sequence number does not
- match the sequence number of the data that the sender transmitted.
- If this problem occurs, either a network failure has caused the
- transmission to become garbled, or the destination machine had
- aborted the current send/received sequence and restarted anew
- within the retry number & timeout series of the sender.
- Both scenarios are highly unlikely.
-
- 0x23 - BAD_RX_SRCE_ADDR - the sending machine received a transmission
- from a machine other than the expected receiver of the original trans-
- mission. This should never occur, due to the fact that the sender
- socket should be known at this point only to the receiver of the
- message that the sender transmitted. If other machines transmitting
- on the network are getting through to another sender unexpectedly, then
- some application software debugging is in order, or special TSR programs
- are running, the behavior of which should be monitored more stringently.
-
-
- 0x30 - BAD_FILE_OPEN - the file to be transmitted, specified by
- the FileOrBfr parameter, could not be opened. Check syntax of
- ASCIIZ string to make sure path and filename are correct, and
- don't forget to use double slashes in the string when specifying
- a path! For example, "D:\MYPATH\MYFILE.DAT" is not a valid C
- string. You must pass it as "D:\\MYPATH\\MYFILE.DAT".
-
-
- 0x32 - BAD_FILE_READ - problem reading the file specified in the
- parameter FileOrBfr, even though the file was successfully opened.
- This should never occur, barring disk failure or some strange
- interaction between the caller's program and other programs running
- as background processes or TSR's.
-
-
- 0xBB - USER_TERMINATED - the user has chosen to abort the application
- by hitting the two SHIFT keys & an ALT key during a send/receive sequence.
-
-
- 0xDD - IPX_NOT_PRESENT - IPX API interface was not detected. Make
- sure NOVELL's IPX.COM or equivalent has been run before attempting to
- access IPX functions.
-
-
- -------------------------
- -------------------------
- APPLICATION CODE EXAMPLE:
- -------------------------
- -------------------------
-
- #define TXSOCKET "4050"
- #define TXBFRSIZE 8192
-
- int main( void )
- {
- NETADDR na;
- unsigned rc;
- long len;
- BYTE *TxBfr;
-
- // hard-coded example of internetwork address of destination machine
- xatoxb( na.INA.Network, "01234567" );
- xatoxb( na.INA.Node, "0123456789AB" );
- xatoxb( na.Socket, "4010" );
-
- // sending a file
- len = 0;
- rc = IPXSendRT( &len, "TXDATA.DAT", TXSOCKET, &na, NULL );
- if ( rc != GOOD_IPX_RETURN )
- {
- // take appropriate error action here
- return( -1 );
- }
-
- // sending a buffer
- TxBfr = calloc( 1, TXBFRSIZE );
- if ( !TxBfr )
- {
- printf( "MEMORY ALLOCATION FAILURE!" );
- return( -1 );
- }
-
- len = TXBFRSIZE;
- rc = IPXSendRT( &len, TxBfr, TXSOCKET, &na, NULL );
- if ( rc != GOOD_IPX_RETURN )
- {
- printf( "FUNCTION ERROR: %02X IPX ERROR: %02X", rc, IPXerrno );
- // take appropriate error action here
- return( -1 );
- }
-
- return( 0 );
- }
-
- */
- /*******************************************************************/
- /*******************************************************************/
-
- unsigned IPXSendRT( long *BfrLen,
- BYTE *FileOrBfr,
- char *SocketStr,
- NETADDR *Destination,
- void (*RTfunc)(void) )
- {
- int fhandle;
- unsigned rc, lenTX, retries;
- BYTE *TXptr;
- int retryTXflg, fileflg;
- BYTE Socket[2];
- BYTE expected_seq;
-
- BYTE *pIPXbfrRX, *pIPXbfrTX;
- IPXHEADER *pIPXpktRX, *pIPXpktTX;
- EVENTCONTROLBLOCK *pIPXecbRX, *pIPXecbTX;
- LOCALTARGET *pLocalTarget;
-
- /* ----------------------------------------------------------- */
- /* check that IPX API has been installed or attempt to install */
- /* ----------------------------------------------------------- */
-
- if (
- !(IPXAPI)
- &&
- (IPXInstalled() != IPX_PRESENT)
- )
- {
- return( IPX_NOT_PRESENT );
- }
-
- /* ------------------------------------------- */
- /* open socket for peer-to-peer communications */
- /* ------------------------------------------- */
-
- if (
- (strlen( SocketStr ) != (sizeof(Socket)*2))
- ||
- !(xatoxb( Socket, SocketStr ))
- )
- {
- return( BAD_SOCKET_PARAM );
- }
-
- IPXerrno = IPXSocketOpen( Socket, SOCKET_SHORT_LIVED );
- if ( IPXerrno != IPX_SUCCESS )
- {
- if ( IPXerrno == SOCKET_ALREADY_OPEN )
- {
- IPXSocketClose( Socket );
- }
- return( BAD_SOCKET_OPEN );
- }
-
- /* --------------------- */
- /* set the transfer mode */
- /* --------------------- */
-
- fileflg = TRUE;
- if ( *BfrLen )
- {
- TXptr = FileOrBfr;
- fileflg = !TRUE;
- }
-
- /* ------------------------------- */
- /* check that TX file is available */
- /* ------------------------------- */
-
- if ( fileflg )
- {
- fhandle = open( FileOrBfr, O_RDONLY | O_BINARY );
- if ( fhandle == FILE_PROBLEM )
- {
- IPXSocketClose( Socket );
- return( BAD_FILE_OPEN );
- }
- }
-
- /* ------------------------- */
- /* allocate necessary memory */
- /* ------------------------- */
-
- pIPXbfrRX = (BYTE *)calloc( 1, SEQLEN+IPXdatalen );
- pIPXbfrTX = (BYTE *)calloc( 1, SEQLEN+IPXdatalen );
- pIPXpktRX = (IPXHEADER *)calloc( 1, sizeof(IPXHEADER) );
- pIPXpktTX = (IPXHEADER *)calloc( 1, sizeof(IPXHEADER) );
- pIPXecbRX = (EVENTCONTROLBLOCK *)calloc( 1, sizeof(EVENTCONTROLBLOCK) );
- pIPXecbTX = (EVENTCONTROLBLOCK *)calloc( 1, sizeof(EVENTCONTROLBLOCK) );
- pLocalTarget = (LOCALTARGET *)calloc( 1, sizeof(LOCALTARGET) );
-
- if (
- pIPXbfrRX == NULL ||
- pIPXbfrTX == NULL ||
- pIPXpktRX == NULL ||
- pIPXpktTX == NULL ||
- pIPXecbRX == NULL ||
- pIPXecbTX == NULL ||
- pLocalTarget == NULL
- )
- {
- IPXSocketClose( Socket );
- if ( fileflg )
- close( fhandle );
- if ( pIPXbfrRX )
- free( pIPXbfrRX );
- if ( pIPXbfrTX )
- free( pIPXbfrTX );
- if ( pIPXpktRX )
- free( pIPXpktRX );
- if ( pIPXpktTX )
- free( pIPXpktTX );
- if ( pIPXecbRX )
- free( pIPXecbRX );
- if ( pIPXecbTX )
- free( pIPXecbTX );
- if ( pLocalTarget )
- free( pLocalTarget );
- return( BAD_MEMORY_ALLOC );
- }
-
- /* --------------------------- */
- /* initialize ECBs/IPX packets */
- /* --------------------------- */
-
- memcpy( pIPXecbRX->Socket, Socket, sizeof(pIPXecbRX->Socket) );
- pIPXpktRX->PacketType = IPX_PACKET_TYPE;
- pIPXecbRX->FragmentCnt = 2;
- pIPXecbRX->Fragment[0].BufAddr = (void *)pIPXpktRX;
- pIPXecbRX->Fragment[0].Len = sizeof(IPXHEADER);
- pIPXecbRX->Fragment[1].BufAddr = (void *)pIPXbfrRX;
- pIPXecbRX->Fragment[1].Len = SEQLEN+IPXdatalen;
-
- memcpy( pIPXecbTX->Socket, Socket, sizeof(pIPXecbTX->Socket) );
- pIPXpktTX->PacketType = IPX_PACKET_TYPE;
- pIPXecbTX->FragmentCnt = 2;
- pIPXecbTX->Fragment[0].BufAddr = (void *)pIPXpktTX;
- pIPXecbTX->Fragment[0].Len = sizeof(IPXHEADER);
- pIPXecbTX->Fragment[1].BufAddr = (void *)pIPXbfrTX;
-
- memcpy( &pIPXpktTX->DestAddr, Destination, sizeof(NETADDR) );
- memcpy( pLocalTarget, Destination, sizeof(INTNETADDR) );
- IPXerrno = IPXGetLocalTarget( pLocalTarget );
- if ( IPXerrno != IPX_SUCCESS )
- {
- IPXSocketClose( Socket );
- if ( fileflg )
- close( fhandle );
- free( pIPXbfrRX );
- free( pIPXbfrTX );
- free( pIPXpktRX );
- free( pIPXpktTX );
- free( pIPXecbRX );
- free( pIPXecbTX );
- free( pLocalTarget );
- return( BAD_LOCAL_TARGET );
- }
-
- memcpy( pIPXecbTX->ImmediateAddr,
- pLocalTarget->ImmediateAddr,
- sizeof(pIPXecbTX->ImmediateAddr) );
-
- /* =================== */
- /* DATA TX/ACK RX LOOP */
- /* =================== */
-
- expected_seq = FIRST_SEQ_NUM;
- retryTXflg = !TRUE;
- retries = 0;
- while( TRUE )
- {
-
- /* if user chose to break things off, then quit */
- if ( USERBREAK )
- {
- rc = USER_TERMINATED;
- break;
- }
-
- /* get ready for expected ACK of imminent TX */
- IPXListenForPacket( pIPXecbRX );
-
- /* if TX retry is not active, prepare TX buffer */
- if ( !retryTXflg )
- {
-
- /* fill TX buffer with data from file */
- if ( fileflg )
- {
- lenTX = read( fhandle, pIPXbfrTX+SEQLEN, IPXdatalen );
- if ( lenTX == (unsigned)FILE_PROBLEM )
- {
- IPXCancelEvent( pIPXecbRX );
- rc = BAD_FILE_READ;
- break;
- }
- }
-
- /* fill TX buffer with data from buffer */
- if ( !fileflg )
- {
- lenTX = ((*BfrLen < IPXdatalen) ? *BfrLen : IPXdatalen);
- memcpy( pIPXbfrTX+SEQLEN, TXptr, lenTX );
- TXptr += lenTX;
- *BfrLen -= IPXdatalen;
- }
-
- /* set sequence number & buffer length */
- *pIPXbfrTX = expected_seq;
- pIPXecbTX->Fragment[1].Len = SEQLEN+lenTX;
-
- } // end of if ( !retryTXflg )
-
- /* send the data & check result of TX */
- IPXSendPacket( pIPXecbTX );
- IPXTimeOutRT( pIPXecbTX, IPXto, RTfunc );
- IPXerrno = pIPXecbTX->CompletionCode;
- if ( IPXerrno != IPX_SUCCESS )
- {
- /* cancel the pending LISTEN */
- IPXCancelEvent( pIPXecbRX );
- rc = BAD_TX_TRY;
- break;
- }
-
- /* ---------------------------------- */
- /* RX (ACK to previous TX) is pending */
- /* ---------------------------------- */
-
- /* wait for RX to complete, then check result */
- IPXTimeOutRT( pIPXecbRX, IPXto, RTfunc );
- IPXerrno = pIPXecbRX->CompletionCode;
-
- /* ----------------------------- */
- /* ACK was received successfully */
- /* ----------------------------- */
-
- if ( IPXerrno == IPX_SUCCESS )
- {
- /* check that RX was from expected Destination */
- if ( memcmp( Destination, &pIPXpktRX->SrceAddr, sizeof(NETADDR) ) )
- {
- rc = BAD_RX_SRCE_ADDR;
- break;
- }
-
- /* check that TX/RX sequence in sync */
- if ( expected_seq != *pIPXbfrRX )
- {
- rc = BAD_RX_SEQ_NUM;
- break;
- }
-
- /* if last TX was EOT, then all done! */
- if ( lenTX < IPXdatalen )
- {
- rc = GOOD_IPX_RETURN;
- break;
- }
-
- /* otherwise, do next TX */
- expected_seq++;
- retries = 0;
- retryTXflg = !TRUE;
-
- } // end of if ( IPXerrno == IPX_SUCCESS )
-
- /* ------------------- */
- /* no ACK was received */
- /* ------------------- */
-
- if ( IPXerrno != IPX_SUCCESS )
- {
-
- /* if maximum retries have been exhausted, then quit */
- if ( retries++ >= IPXtries )
- {
- rc = BAD_RETRIES;
- break;
- }
-
- /* otherwise, try RX again */
- retryTXflg = TRUE;
-
- } // end of if ( IPXerrno != IPX_SUCCESS )
-
-
- } // end of while ( TRUE )
-
- /* --------------------------------- */
- /* close socket and bring it on home */
- /* --------------------------------- */
-
- IPXSocketClose( Socket );
-
- if ( fileflg )
- close( fhandle );
-
- free( pIPXbfrRX );
- free( pIPXbfrTX );
- free( pIPXpktRX );
- free( pIPXpktTX );
- free( pIPXecbRX );
- free( pIPXecbTX );
- free( pLocalTarget );
-
- return( rc );
- }
-
- /************************************************************************/
- /* EOF EOF EOF EOF EOF EOF EOF EOF EOF EOF EOF EOF EOF EOF */
- /************************************************************************/
-