{$X+,V-,B-}
program RecHello1;

{ Simple IPX demonstration program, that uses one receive ESR.

  Run this program on 1 workstation, run S_HELLO or S1_HELLO on another.
  S_HELLO will send "hello world" messages,
  this workstation will receive them.  }

uses crt,nwMisc,nwIPX;

CONST IOSocket=$5678;

Var ReceiveEcb    :Tecb;
    IpxHdr        :TipxHeader;
    socket        :word;
    buf           :array[1..546] of byte;
    t             :byte;
    ReceivedBufLen:word;
    PacketReceived:boolean;

    NewStack:array[1..1024] of word;  { !! used by ESR }
    StackBottom:word;                 { !! used by ESR }


{$F+}
Procedure ListenESRhandler;
begin
PacketReceived:=true;
end;
{$F-}

{$F+}
Procedure ListenESR; assembler;
asm { ES:SI are the only valid registers when entering this procedure ! }
    mov dx, seg stackbottom
    mov ds, dx

    mov dx,ss  { setup of a new local stack }
    mov bx,sp  { ss:sp copied to dx:bx}
    mov ax,ds
    mov ss,ax
    mov sp,offset stackbottom
    push dx
    push bx

    CALL ListenEsrHandler

    pop bx
    pop dx
    mov sp,bx { restore stack }
    mov ss,dx
end;
{$F-}


begin
IF NOT IpxInitialize
 then begin
      writeln('Ipx needs to be installed.');
      halt(1);
      end;
socket:=IOSocket;
IF NOT IPXopenSocket(Socket,SHORT_LIVED_SOCKET)
 then begin
      writeln('IPXopenSocket returned error# ',nwIPX.result);
      halt(1);
      end;

Repeat
   PacketReceived:=False;
   { Empty receive buffer (ReceiveEcb.fragment[2].address^) }
   FillChar(buf,546,#0);

   { Setup ECB and IPX header }
   IPXsetupListenECB(Addr(ListenESR),IOsocket,@buf,546,
                     IpxHdr,ReceiveEcb);

   IPXListenForPacket(ReceiveECB);

  REPEAT

   delay(1000);
   Writeln('Packet received: ',PacketReceived);

   IF PacketReceived { ESR has signalled that a packet has been received }
    then begin
         Case ReceiveECB.CompletionCode OF
          $00:begin { Dump received bytes.. }
              Write('Data received  : ');
              ReceivedBufLen:=swap(IpxHdr.length)-SizeOf(TipxHeader);
              for t:=1 to ReceivedBufLen
               do write(chr(buf[t]));
              writeln;
              end;
          $FC:Writeln('The listen request has been canceled.');
              { impossible, as the cancelation has to be done by this program, and it doesn't }
          $FD:Writeln('Packet overflow error.');
              { 0 fragments, or receiving buffer too small. }
          $FF:Writeln('The socket is closed.');
              { Impossible. The socket is definitely open. See above. }
         end;

         { Now we're going to squeeze all information out of the IpxHdr }
         writeln('*IPX header info*');
         writeln('-total length  : ',swap(IpxHdr.length):0);
         writeln('-data length   : ',swap(IpxHdr.Length)-SizeOf(TipxHeader));
         writeln('-number of hops: ',(IpxHdr.TransportControl AND $0F):0);
         write('-sending adress: [');
         for t:=1 to 4
          do write(HexStr(IpxHdr.source.net[t],2));
         write('|');
         for t:=1 to 6
          do write(HexStr(IpxHdr.source.node[t],2));
         write('|');
         writeln(HexStr(swap(IpxHdr.source.socket),4),']');
         write('-destined for  : [');
         for t:=1 to 4
          do write(HexStr(IpxHdr.destination.net[t],2));
         write('|');
         for t:=1 to 6
          do write(HexStr(IpxHdr.destination.node[t],2));
         write('|');
         writeln(HexStr(swap(IpxHdr.destination.socket),4),']');

         writeln;
         end;

  UNTIL (KeyPressed or PacketReceived);

UNTIL keypressed;

IF NOT IPXcloseSocket(IOsocket)
 then writeln('IPXcloseSocket returned error# ',nwIPX.result);

end.