IPXLIB.C Comentada

André Moreira (andre@dei.isep.ipp.pt)
Professor Adjunto do Departamento de Engenharia Informática do ISEP
/*********** Funções IPX da shell Novell *************/
/*    OS COMENTARIOS AINDA NAO ESTAO COMPLETOS       */
/*****************************************************/
/*	Estas funções foram implementadas no DEI em 1994/95, para suporte das aulas práticas
	de Sistemas de Computação II, onde eram desenvolvidas pequenas aplicações em Turbo C 2.0,
	para as utilizar basta incluir o ficheiro IPXLIB.C:
	#include "path\ipxlib.c"
*/

#if     !defined(__IPX_DEF_)   /* verificar se este ficheiro ja foi incluido */
#define __IPX_DEF_

#include <dos.h>
#include <mem.h>
				/* tipos de socket */
#define TEMP_SOCKET_TYPE  0x00	/* socket temporario (válido até a aplicação terminar) */
#define PERM_SOCKET_TYPE  0xFF	/* socket permanente (usado para implementar programas TSR) */

#define DYNAMIC_SOCKET    0x0000 /* numero de porta para atribuição dinâmica */

typedef unsigned char BYTE;	/* definição de alguns identificadores de tipo */
typedef unsigned int  WORD;
typedef unsigned long LONG;

typedef struct { BYTE net[4], node[6], socket[2];} IPXaddress;  /* endereço IPX completo */

typedef struct				/* a estrutura do cabeçalho de um datagrama IPX */
	{
	WORD checkSum, length;		/* o checksum não é actualmente usado */
	BYTE tranportControl, type;	/* */
	IPXaddress destination, source; /* endereços de destino e origem */
	}
	IPXheader;

#define IPXpacket IPXheader	/* para manter as aplicações antigas que usavam este identificador*/


typedef struct	{ WORD address[2], size; } ECBfragment;

typedef struct
	{
	WORD link[2];
	BYTE far *ESRaddress;
	BYTE inUseFlag, compCode;
	BYTE ECBsocket[2];
	BYTE IPXworkSpace[4], driverWorkSpace[12], immediateAddress[6];
	WORD fragCount;
	ECBfragment fragDesc[2];
	}
	ECB;


BYTE IPXinit(BYTE exitFlag)	/* verificar se o driver IPX está instalado */
{
union REGS out,in;
in.x.ax=0x7A00;
int86(0x2F,&in,&out);
if(exitFlag && !out.h.al) {puts("\nIPX not Installed -> exiting...");exit(1);}
return(out.h.al);
}

BYTE IPXopenSocket(void *socket, BYTE type)	/* abrir um socket */
{						/* o socket (número de porta) é passado como apontador */
BYTE *sock=(BYTE *)socket;			/* o que permite que esta função defina uma porta livre */
union REGS out,in;				/* nesse caso a variável usada como parâmetro deve conter */
in.x.bx=0;					/* o valor DYNAMIC_SOCKET e a função encarrega-se de */
in.h.dl=sock[1];				/* encontrar uma porta livre. O número dessa porta é então */
in.h.dh=sock[0];				/* colocado na variavel 				*/
in.h.al=type;					/* o parâmetro type deverá ter o valor TEMP_SOCKET_TYPE */
int86(0x7A,&in,&out);				/* ou PERM_SOCKET_TYPE	*/
sock[1]=out.h.dl;
sock[0]=out.h.dh;
return(out.h.al);
}

void IPXcloseSocket(WORD socket)
{
BYTE *sock=(BYTE *)&socket;
union REGS out,in;
in.x.bx=1;
in.h.dl=sock[1];
in.h.dh=sock[0];
int86(0x7A,&in,&out);
}

BYTE IPXgetLocalTarget(IPXaddress *fullAddress, BYTE *imedAddress, WORD *transpTime)
{
union REGS out,in;
struct SREGS seg;
segread(&seg);
seg.es=seg.ds;
in.x.bx=2;
in.x.si=(WORD)fullAddress;
in.x.di=(WORD)imedAddress;
int86x(0x7A,&in,&out,&seg);
*transpTime=out.x.cx;
return(out.h.al);
}

void IPXsendPacket(ECB *ecb)
{
union REGS out,in;
struct SREGS seg;
segread(&seg);
seg.es=seg.ds;
in.x.bx=3;
in.x.si=(WORD)ecb;
int86x(0x7A,&in,&out,&seg);
}

#define IPXdoSendPacket(ecb) IPXsendPacket(&ecb);while(ecb.inUseFlag) IPXrelinquishControl()

void IPXlistenForPacket(ECB *ecb)
{
union REGS out,in;
struct SREGS seg;
segread(&seg);
seg.es=seg.ds;
in.x.bx=4;
in.x.si=(WORD)ecb;
int86x(0x7A,&in,&out,&seg);
}

void IPXsheduleIPXevent(WORD timeUnits, ECB *ecb)
{
union REGS out,in;
struct SREGS seg;
segread(&seg);
seg.es=seg.ds;
in.x.bx=5;
in.x.si=(WORD)ecb;
in.x.ax=timeUnits;
int86x(0x7A,&in,&out,&seg);
}

BYTE IPXcancelEvent(ECB *ecb)
{
union REGS out,in;
struct SREGS seg;
segread(&seg);
seg.es=seg.ds;
in.x.bx=6;
in.x.si=(WORD)ecb;
int86x(0x7A,&in,&out,&seg);
return(out.h.al);
}

BYTE IPXsheduleSpecialEvent(WORD timeUnits, ECB *ecb)
{
union REGS out,in;
struct SREGS seg;
segread(&seg);
seg.es=seg.ds;
in.x.bx=7;
in.x.si=(WORD)ecb;
in.x.ax=timeUnits;
int86x(0x7A,&in,&out,&seg);
return(out.h.al);
}

WORD IPXgetIntervalMarker(void)
{
union REGS in,out;
in.x.bx=8;
int86(0x7A,&in,&out);
return(out.x.ax);
}

void IPXgetInternetworkAddress(BYTE *address)
{
union REGS out,in;
struct SREGS seg;
segread(&seg);
seg.es=seg.ds;
in.x.bx=9;
in.x.si=(WORD)address;
int86x(0x7A,&in,&out,&seg);
}

void IPXrelinquishControl(void)
{
union REGS in,out;
in.x.bx=10;
int86(0x7A,&in,&out);
}

void IPXdisconnectFromTarget(BYTE *address)
{
union REGS out,in;
struct SREGS seg;
segread(&seg);
seg.es=seg.ds;
in.x.bx=11;
in.x.si=(WORD)address;
int86x(0x7A,&in,&out,&seg);
}

void IPXgetProcAddress(void (*proc)(),void *address)
{
WORD *addr=(WORD *)address;
struct SREGS seg;
segread(&seg);
seg.es=seg.ds;
addr[0]=(WORD)proc;
addr[1]=(WORD)seg.cs;
}

void IPXgetDataAddress(void *data,void *address)
{
WORD *addr=(WORD *)address;
struct SREGS seg;
segread(&seg);
seg.es=seg.ds;
addr[0]=(WORD)data;
addr[1]=(WORD)seg.ds;
}

/******************** Funções Auxiliares ***********************/

void swapWORD(WORD *data)
{
BYTE aux, *bp=(BYTE *)data;
aux=bp[0];bp[0]=bp[1];bp[1]=aux;
}

WORD getSwappedWORD(WORD data)
{
BYTE *arg=(BYTE *)&data, res[2];
res[0]=arg[1];res[1]=arg[0];
return(*((WORD *)res));
}

#define IPXgetDataSize(ipxh) (getSwappedWORD(ipxh.length)-30)



/*******************  ECB & IPX header setup ********************/

void IPXsetUpSend(ECB *ecb, IPXheader *ipx, BYTE *toNet, BYTE *toNode,
	WORD toSocket, WORD socket, void *buffer, WORD buffSize, void (*esr)())
{
WORD ttime;
BYTE *sock=(BYTE *)&socket;
BYTE *toSock=(BYTE *)&toSocket;

if(esr) IPXgetProcAddress(esr,&ecb->ESRaddress);
else memset(&ecb->ESRaddress,0,4);
ipx->destination.socket[0]=toSock[1];
ipx->destination.socket[1]=toSock[0];
ecb->inUseFlag=0;
ecb->ECBsocket[0]=sock[1];
ecb->ECBsocket[1]=sock[0];
ecb->fragCount=2;
IPXgetDataAddress(ipx,ecb->fragDesc[0].address);
ecb->fragDesc[0].size=30;
IPXgetDataAddress(buffer,ecb->fragDesc[1].address);
ecb->fragDesc[1].size=buffSize;
ipx->type=0;
movmem(toNet,ipx->destination.net,4);
movmem(toNode,ipx->destination.node,6);
IPXgetLocalTarget(&ipx->destination,ecb->immediateAddress, &ttime);
}

/*** Prepara a emissão em broadcast na rede corrente [00:00:00:00] ***/

void IPXsetUpSendBroadcast(ECB *ecb, IPXheader *ipx, WORD toSocket,
		WORD socket, void *buffer, WORD buffSize, void (*esr)())
{
BYTE *sock=(BYTE *)&socket;
BYTE *toSock=(BYTE *)&toSocket;

if(esr) IPXgetProcAddress(esr,&ecb->ESRaddress);
else memset(&ecb->ESRaddress,0,4);
ecb->ECBsocket[0]=sock[1];
ecb->ECBsocket[1]=sock[0];
ipx->destination.socket[0]=toSock[1];
ipx->destination.socket[1]=toSock[0];
ecb->inUseFlag=0;
ecb->fragCount=2;
IPXgetDataAddress(ipx,ecb->fragDesc[0].address);
ecb->fragDesc[0].size=30;
IPXgetDataAddress(buffer,ecb->fragDesc[1].address);
ecb->fragDesc[1].size=buffSize;
ipx->type=0;
memset(ecb->immediateAddress,0xFF,6);
memset(ipx->destination.net,0,4);
memset(ipx->destination.node,0xFF,6);
}


void IPXsetUpReceive(ECB *ecb, IPXheader *ipx, WORD socket, void *buffer,
			WORD buffSize, void (*esr)())
{
BYTE *sock=(BYTE *)&socket;

if(esr) IPXgetProcAddress(esr,&ecb->ESRaddress);
else memset(&ecb->ESRaddress,0,4);
ecb->inUseFlag=0;
ecb->ECBsocket[0]=sock[1];
ecb->ECBsocket[1]=sock[0];
ecb->fragCount=2;
IPXgetDataAddress(ipx,(WORD *)ecb->fragDesc[0].address);
ecb->fragDesc[0].size=30;
IPXgetDataAddress(buffer,(WORD *)ecb->fragDesc[1].address);
ecb->fragDesc[1].size=buffSize;
}

#endif