Sunteți pe pagina 1din 10

IIIIII II II II II II II II II II II IIIIII

PPPPPP PP PP PP PP PP PP PP PP PPPPPP PP PP PP PP PP PP

XX XX XX XX XX XX XX XX XX XX XXX XX XX XX XX XX XX XX XX XX XX XX XX

Por BLIND-EYE SeVeK Pablo_edt

Estas rutinas que van a poder ver estan echas en Turbo Pascal 6.0, pero son facilmente trasladables a otros lenguajes. Primero vamos a hablar un poco sobre el funcionamiento del protocolo en si. Ipx es un protocolo el cual contiene informacin para ser enviada por una red. Este contiene informacin que puede ser enviada de una mquina a otra o de una a todas las existentes en la red (nodos). Al enviar paquetes a todas las mquinas se le llama BROADCAST. La direccin broadcast generalmente esta confinada a la red local, aparte hay muchas otras maneras pero no son el centro de este texto. Estos paquetes tiene una estructura que esta demostrada en la Figura 1. Figura 1 El encabezado IPX. |Nombre |Check |Length |tc |pType |dest |src | | | | | | | Tamao (bytes) 2 bytes 2 bytes 1 byte 1 byte 12 bytes 12 bytes | | | | | | | Descripciones Bigendian check sum Bigendian largo del paquete Control de Transporte Tipo de paquete (usa siempre 0) Direccion del nodo destinatario Direccion del nodo principal

Sobre el camino, bigedians de ninguna manera el primer byte mantiene los valores mas significativos, esto es la manera opuesta al camino que generalmente se toma en una PC para realizar estas cosas. Por razones mejores para Novell, el valor del checksumm es siempre $ffff. El largo de del campo contiene el valor de los paquetes, incluyendo el encabezado IPX. El controlador de transporte mantiene un conteo de los numeros de paquetes que son enviados por los routers. La estructura de la direccin es mostrada en la figura 2. Figura 2 - La direccion del campo de red. |Nombre |red |nodo |socket | Tamao (bytes) | Descripciones | 4 bytes | Direccion de red | 6 bytes | Direccion del nodo | 2 byte | Numero de sockets

Los sockets son los dispositivos que permiten decidir al nodo si va a interactuar en el envio de un paquete. Este contiene infinidad de programas en la primera PC para poder mandar paquetes IPX con total transparencia para las otras. Esto significa que al el broadcast manda un paquete, solo va a poder ser recibido por la maquina que tenga abierto el

socket. Por esto los paquetes son ignorados por los nodos que no esten preparados para recibirlos. Pero hay que tener especial cuidado para estar seguro que dos programas no estan enviando paquetes de diferente tipo al mismo socket. La prxima orden a negociar es la que le dira a la PC que socket tiene que abrir. La figura 3 muestra la estructura del Event Control Block (ECB). |Nombre |Link |ESR |InUse |complete |socket |IPXwork |Dwork |immedAddr |fragCount |FragData |FragSize | | | | | | | | | | | | Tamao (bytes) 4 bytes | 4 bytes | 1 byte | 1 byte | 2 bytes | 4 bytes | 12 bytes | 12 bytes | 2 bytes | 4 bytes | 2 bytes | | Descripciones Extremo hacia el proximo ECB Extremo para la rutina de servicios Flag que comenta el estado del ECB Flag que comenta el codigo completado Bigendian numero de sockets para ECB Tamao de trabajo para IPX Tamao de trabajo para un controlador Direccion para enviarle Numbero de fragmentos. Extremos para fragmentos de datos Tamao de los fragmentos de datos

Todos los campos dentro de ECB deben resetearse a cero cada ves que se inicializa el ECB. La estructura ESR no es utilizada en nuestras rutinas que significa que el programa contiene un chequeo del ECB para estructurar la llegada de paquetes. Para enviar un paquete a un broadcast, tenemos que setear la direccion de los nodos a $ff. Esto esta echo automatico en todas nuestras rutinas. Fragdata tiene que estar inicializado para el punto en el que el encabezado IPX y la informacion se enviada mas directamente antes que este encabezado. Podran ver un ejemplo en el apendice B. Los procedimientos InitSendPacket y InitReceivePacket demuestran la inicializacion del both de ECB y el encabezado IPX. Una ves que todos los procesos se han inicializado, es necesario comentarle a IPX sobre el ECB. Esto estaria listo cuando abrimos el primer socket para usar. La interrupcin $7a es utilizada por Novell API, y es el camino mas viejo para seguir las rutinas. Esta manera generalmente es la mas facil. Las sub-funciones estan descriptas en la figura 1.
|FUNCION |NOMBRE | | | | | | | | | |REGISTROS |

$0000 |Socket abierto |AL=Longevity DX=Socket number (bigendian) | | |Returns:AL=Error code DX=Socket Number (bigendian) | $0001 |Socket cerrado |DX=Socket number $0003 |Paquete enviado|ES=Seg of ECB $0004 |Escucha del |paquete $0009 |Direccion |Loacl $000A |Im Idle (bigendian) | | | |

SI=Offset of ECB

|ES=Seg of ECB SI=Offset of ECB |Returns:AL=Error code |ES=Seg of address array | |Nulo

SI=Offset of address array | | |

NOTA: el numero de la funcion es guardado en BX.

Antes de abrir un socket se testea que el protocolo ipx este presente. Esto terminaria ejecutando int $2f con AX=$7F00. Si al volver AL no contiene $FF el protocolo ipx no esta instalado. Este es un buen punto

para tomar nuestra direccion local asi nuestro programa tendria que realizarklo una sola vez. Se puede ver un ejemplo en el procedimiento InitPX en el apendice A. Una vez abierto el socket y algunos retoques al ECBs y al encabezado IPX, vamos a comentarle al controlador de IPX sobre el. Primero chequeamos que ser reciban los paquetes ECB y los encabezamientos IPX, seguidos por un envio. Para un registro del recieve, el encabezado de IPX no necesita ser inicializado en absoluto. Sin embargo, yo pienso que es una buena idea poner a cero todos los campos, cuando estos esten en el lado seguro del procedimiento. El ECB sin embargo, necesita tener varios campos para configurar. Los flags inUse deben estar seteados a $1D (no me pregunten por qu, realmente funciona sin esto, pero alguno del resources que yo consult hicieron esto). El nmero del socket debe ser inicializado, y no hay que olvidarse que este es bigendian. Al terminar el fragCount, fragData y los campos del fragSize deben quedar completamente seteados. Por descarte todos los otros campos deben estar en cero. Una vez que todos estos campos estan seteados, hay que hacer correr el procedimiento "Escucha del Paquete" para comentarle al IPX controlador sobre el ECB. Esto devolver inmediatamente, pero si cualquier paquete llega para ese sockets esos paquetes se colocan en el registro. Para ver si un paquete a llegado, es necesario verificar que el InUse lo halla registrado en el ECB. Si ste es $00, entonces un paquete ha llegado y a sido procesado antes de que otro pueda ser aceptado. Si un paquete llega cuando hay un paquete que no se halla podido procesar, entonces ese paquete se perder. Esto significa que un paquete debe procesarse en el menor tiempo posible. El registro puede ser solicitado simplemente ejecutando el procedimiento "Escucha del Paquete" de nuevo. Nosotros tenemos un registro del recieve que espera un paquete. Ahora nosotros necesitamos un registro de send. Un registro de send necesita los mismos campos que un registro de receive, pero al comienzo necesita tener el encabezado IPX para ser registrado. El checksum se setea a $ffff y el tipo del paquete se setea a $00 (esto es un entrelazado de paquete a paquete). El prximo paso es setear la direccin del destino. Para utilizar una direccion broadcast se debe poner la direccion de la red y luego nuestra direccion local, el nodo debe ser el nodo broadcast ($ff,$ff,$ff,$ff,$ff,$ff) y el numero de sockets tiene que ser seteado. El programa debe setearse con la direccin de la fuente con la informacion del registro de la direccion local de red, y el socket por lo general nosostros lo seteamos como el de destino. Nosotros pusimos algunos datos dentros de los datos del registro asi llama a un proceso "Send Packet". El paquete se enviar entonces al nodo del destinatario de la red. Si el campo del nodo se pone a la direccin del broadcast, el paquete se enviar a todos los nodos en la red, incluso al nodo de la transmisor. BUENO AHORA EN TEORIA Y EN PRACTICA SE TIENEN QUE PODER MANDAR Y RECIBIR PAQUETES IPX. ///////////////////////////////APENDICE A////////////////////////////// ///////////////////////////////APENDICE A////////////////////////////// ///////////////////////////////APENDICE A//////////////////////////////

///////////////////////////////APENDICE A////////////////////////////// ///////////////////////////////APENDICE A////////////////////////////// unit ipx; interface uses dos; type netAddr = array[1..4] of byte; nodeAddr = array[1..6] of byte; } address 1=seg } = array[0..1] of word; { The address of a network } { The address of a node in a network { A pointer to the data 0=offset

netAddress = record Net : netAddr; Node : nodeAddr; Socket : word; end; localAddrT = record Net Node end; ECBType = record link ESR if none } inUse complete socket IPXwork Dwork immedAddr fragCount fragData fragSize end; IPXheader = record check length bytes } tc pType dest address } src end; : netAddr; : nodeAddr;

{ network address } { node address } { Big endian socket number}

{ my network address } { my node address }

: address; : address; : : : : : : : : :

{ Pointer to next ECB? } { Event Service Routine 00000000h

byte; { In use flag } byte; { Completeing flag } word; { Big endian socket number } array[1..4] of byte; { IPX work space } array[1..12] of byte; { Driver work space } nodeAddr; { Immediate local node address } word; { Fragment count } address; { Pointer to data fragment } word; { Size of data fragment }

: word; : word; : byte; : byte; : netAddress; : netAddress;

{ big endian checksum } { big endian length in { transport control } { packet type } { destination network { source network address }

const MYSOCKET : word = $869C; { This is the DOOM official socket number } BROADCAST : nodeAddr = ($ff,$ff,$ff,$ff,$ff,$ff); { Address for broadcast } var

localAddr function procedure procedure procedure function procedure procedure size,sock procedure size,sock procedure

: localAddrT;

IPXopenSocket(longevity : byte; var socketNumber : word):byte; IPXcloseSocket(socketNumber : word); GetLocalAddress; IPXsendPacket(var E : ECBtype); IPXlistenForPacket(var E : ECBtype):byte; ImIdle; InitSendPacket(var ecb : ecbType; var ipx : ipxHeader; : word); InitReceivePacket(var ecb : ecbType; var ipx : ipxHeader; : word); InitIPX;

implementation { Open a socket PARAMS: longevity = $00 for open till close or terminate = $ff for open till close use for TSR socketNumber = 0 for dynamic allocation = anything else RETURNS: completion code $00 = $fe = $ff = function IPXopenSocket(longevity var regs : registers; begin regs.bx:=$0000; regs.al:=longevity; regs.dx:=swap(socketNumber); intr($7A,regs); if socketNumber=$0000 then socketNumber:=swap(regs.dx); IPXopenSocket:=regs.al; end; { Close a socket PARMS: socketNumber = a socket to close } procedure IPXcloseSocket(socketNumber : word); var regs : registers; begin regs.bx:=$0001; regs.dx:=swap(socketNumber); intr($7A,regs); end; { Get my address and put it into the local address array! } procedure GetLocalAddress; var regs : registers; success socket table full socket already open } : byte; var socketNumber : word):byte;

begin regs.bx:=$0009; regs.es:=seg(localAddr); regs.si:=ofs(localAddr); intr($7A,regs); end; { Send an IPX packet PARAMS: var E = an initialized Event Control Block } procedure IPXsendPacket(var E : ECBtype); var regs : registers; begin regs.bx:=$0003; regs.es:=seg(E); regs.SI:=ofs(E); intr($7A,regs); end; { Listen for an IPX packet PARAMS: var E = an initialize Event Control Block RETURNS: 0 for OK, nonzero for an error ????} function IPXlistenForPacket(var E : ECBtype):byte; var regs : registers; begin regs.bx:=$0004; regs.es:=seg(E); regs.SI:=ofs(E); intr($7A,regs); IPXlistenForPacket:=regs.al; end; { Tell the IPX driver that we aren't doing anything at the moment } procedure ImIdle; var regs : registers; begin regs.bx:=$000A; intr($7A,regs); end; { Set up the fields in a send IPX record } procedure InitSendPacket(var ecb : ecbType; var ipx : ipxHeader; size,sock : word); begin fillChar(ecb,sizeOf(ecb),#0); fillChar(ipx,sizeOf(ipx),#0); with ecb do begin socket:=swap(sock); { Big endian socket number }

fragCount:=1; fragData[0]:=ofs(IPX); fragData[1]:=seg(IPX); fragSize:=sizeof(IPX)+size; immedAddr:=BROADCAST; end; with ipx do begin check:=$ffff; ptype:=0; dest.net:=localAddr.net; dest.node:=BROADCAST; dest.socket:=swap(sock); src.net:=localAddr.net; src.node:=localAddr.node; src.socket:=swap(sock); end; end;

{ Fragment count } { Pointer to data fragment } { Size of data fragment } { Needs to be BROADCAST?? }

{ { { { { { { {

NO CHECKSUM } Packet exchange packet } Send to this network } Send to everybody! } Send to my socket } From this net } From ME } From my socket }

{ Set up the fields in a recieve IPX record } procedure InitReceivePacket(var ecb : ecbType; var ipx : ipxHeader; size,sock : word); begin fillChar(ecb,sizeOf(ecb),#0); fillChar(ipx,sizeOf(ipx),#0); with ecb do begin inUse:=$1d; { ???? } socket:=swap(sock); { Big endian socket number } fragCount:=1; { Fragment count } fragData[0]:=ofs(IPX); { Pointer to data fragment } fragData[1]:=seg(IPX); fragSize:=sizeof(IPX)+size; { Size of data fragment } end; if IPXlistenForPacket(ecb)<>0 then ; end; { Set up IPX and get the local address } procedure InitIPX; var i : integer; regs : registers; begin regs.ax:=$7A00; intr($2f,regs); if regs.al<>255 then begin writeln('ERROR WHILE INITIALIZING IPX!'); halt(1); end; getLocalAddress; end; { Tell IPX to listen }

begin end. ///////////////////////////////APENDICE ///////////////////////////////APENDICE ///////////////////////////////APENDICE ///////////////////////////////APENDICE program CHAT; uses CRT,IPX; type Packet = record ecb : ECBType; IPX : IPXheader; data : string; end; var send,receive : Packet; procedure Main; var line y done k i handle : : : : : : string; integer; boolean; char; integer; string; B////////////////////////////// B////////////////////////////// B////////////////////////////// B//////////////////////////////

begin ClrScr; writeln('CHATER BOX v0.5 By Daniel Parnell writeln; write('Enter your handle :'); readln(handle); window(1,1,80,23); textBackground(Blue); textColor(Yellow); clrScr; window(1,24,80,25); textBackground(Red); textColor(Yellow); clrScr; y:=1; line:=''; done:=FALSE;

25th March 1994');

repeat repeat until KeyPressed or (receive.ecb.inuse=0); if receive.ecb.inuse=0 then begin window(1,1,80,23); gotoXY(1,y);

textBackground(Blue); textColor(Yellow); writeln(receive.data); y:=WhereY; if IPXlistenForPacket(receive.ecb)<>0 then begin writeln(#7,'ERROR TRYING TO receive A PACKET!'); halt(2); end; window(1,24,80,25); GotoXY(1,length(line)+1); end; if KeyPressed then begin k:=ReadKey; case k of #13 : if line<>'' then begin send.data:='<<'+handle+'>>'+line; with send.ecb do for i:=1 to 6 do ImmedAddr[i]:=$ff; repeat until send.ecb.inuse=0; IPXsendPacket(send.ecb); line:=''; end; #8 : if length(line)>0 then line:=copy(line,1,length(line)-1); #0 : k:=ReadKey; #27 : done:=TRUE; else if length(line)<79 then line:=line+k else begin sound(1000); delay(100); noSound; end; end; window(1,24,80,25); textBackground(Red); textColor(Yellow); GotoXY(1,1); clreol; write(line); end; until done; end; begin if IPXopenSocket(0,MYSOCKET)=0 then begin InitIPX;

with send do InitSendPacket(ecb,ipx,sizeof(String),MYSOCKET); with receive do InitReceivePacket(ecb,ipx,sizeof(String),MYSOCKET); Main; IPXcloseSocket(MYSOCKET); end; TextColor(LightGray); TextBackground(Black); window(1,1,80,25); clrScr; end.

S-ar putea să vă placă și