uses
  Crt,
  CoBase,
  CoIpx,
  CoEth01;


const
  Intf1Addr : TIpxAddress = (
    Size: SizeOf(TIpxAddress);
    Net:  (Long:0);
    Node: (Bytes:(0, 80, 252, 33, 19, 153));
    Sock: 5000
  );


  Intf2Addr : TIpxAddress = (
    Size: SizeOf(TIpxAddress);
    Net:  (Long:0);
    Node: (Bytes:(0, 80, 252, 33, 19, 154));
    Sock: 5001
  );

var
  Eth1     : PCoEth01;
  Ipxm1    : PCoIpxMux;
  Ipx1     : PCoIpx;

  Eth2     : PCoEth01;
  Ipxm2    : PCoIpxMux;
  Ipx2     : PCoIpx;

  Status   : TCoStatus;


  Buff1     : array[0..100] of Byte;

  Buff2     : array[0..1535] of Byte;

  FromAddr  : TEthAddress;
  RecvLen   : Word;

  Ovlp1     : TOverlapped;
  Ovlp2     : TOverlapped;

  Device    : PCoDevice;

  IoBase    : Word;

  S         : String;

begin
  ClrScr;

  if CoCreateDevice( 'ETH01', 'ETH_A', '',
       nil, PCoDevice(Eth1) ) <> CST_SUCCESS then
  begin
    WriteLn( 'Nelze vytorit instanci ETH01' );
    Exit;
  end;


  if CoCreateDevice( 'IPXMUX', 'IPXMUX_A', '',
       CoOpenDevice( 'ETH_A' ) , PCoDevice(Ipxm1) ) <> CST_SUCCESS then
  begin
    WriteLn( 'Nelze vytorit instanci ETH01' );
    Exit;
  end;


  if CoCreateDevice( 'IPX', '', '',
       CoOpenDevice( 'IPXMUX_A' ), PCoDevice(Ipx1) ) <> CST_SUCCESS then
  begin
    WriteLn( 'Nelze vytorit instanci IPX' );
    Exit;
  end;

{  Eth1 := New( PCoEth01, Init );
  Ipxm1 := New( PCoIpxMux, Init );
  Ipxm1^.CoAttachDevice( Eth1 );
  Ipx1 := New( PCoIpx, Init );
  Ipx1^.CoAttachDevice( Ipxm1 );}

  if CoCreateDevice( 'ETH01', 'ETH_B', '',
       nil, PCoDevice(Eth2) ) <> CST_SUCCESS then
  begin
    WriteLn( 'Nelze vytorit instanci ETH01' );
    Exit;
  end;


  if CoCreateDevice( 'IPXMUX', 'IPXMUX_B', '',
       CoOpenDevice( 'ETH_B' ) , PCoDevice(Ipxm2) ) <> CST_SUCCESS then
  begin
    WriteLn( 'Nelze vytorit instanci ETH01' );
    Exit;
  end;


  if CoCreateDevice( 'IPX', '', '',
       CoOpenDevice( 'IPXMUX_B' ), PCoDevice(Ipx2) ) <> CST_SUCCESS then
  begin
    WriteLn( 'Nelze vytorit instanci IPX' );
    Exit;
  end;

  IoBase := $310;

  Status := Ipx2^.CoSetOption( DEV_CLASS_ETH01, COPT_IOBASE,
       @IoBase, SizeOf( IoBase ), 0, nil );
  if Status <> CST_SUCCESS then
  begin
    WriteLn ('Nelze nastavit iobase' );
    Exit;
  end;

  Status := Ipx2^.CoGetOptionString( DEV_CLASS_ETH01, @S, SizeOf(S) - 1, nil);
  if Status <> CST_SUCCESS then
  begin
    WriteLn( 'nelze precist paramstr' );
    Exit;
  end
  else
    WriteLn( S );


  Status := Ipx2^.CoSetOptionString( DEV_CLASS_ETH01, 'IOBASE=$310', nil );
  if Status <> CST_SUCCESS then
  begin
    WriteLn( 'nelze nastavit paramstr' );
  end;


{ Eth2 := New( PCoEth01, Init );
  Eth2^.Eth_IoBase := $310;
  Ipxm2 := New( PCoIpxMux, Init );
  Ipxm2^.CoAttachDevice( Eth2 );
  Ipx2 := New( PCoIpx, Init );
  Ipx2^.CoAttachDevice( Ipxm2 );}


  Status := Ipx1^.CoBind( @Intf1Addr, COF_PROPAGATE, nil  );
  if Status <> CST_SUCCESS then
  begin
    WriteLn( '1_Bind, Error:', Status );
  end;


  Status := Ipx2^.CoBind( @Intf2Addr, COF_PROPAGATE, nil  );
  if Status <> CST_SUCCESS then
  begin
    WriteLn( '2_Bind, Error:', Status );
  end;


  Status := Ipx2^.CoRecvBufferFrom( @Buff2, SizeOf(Buff2), @RecvLen,
              0, @FromAddr, @Ovlp1 );

  Status := Ipx2^.CoRecvBufferFrom( @Buff2, SizeOf(Buff2), @RecvLen,
              0, @FromAddr, @Ovlp2 );


  if Status <> CST_PENDING then
  begin
    WriteLn('...');
    Exit;
  end;

  Status := Ipx2^.CoSendBufferTo( @Buff1, SizeOf(Buff1), 0, @Intf1Addr, nil );

  Ipx2^.CoCancelIO( @Ovlp1, 0 );

  if Status <> CST_SUCCESS then
  begin
    WriteLn( 'Send, Error:', Status );
  end;

  Status := Ipx2^.CoGetIoResult( @Ovlp1, COF_WAIT );
  if Status <> CST_SUCCESS then
  begin
    WriteLn( 'Recv, Error:', Status );
  end
  else begin
    WriteLn( 'Recvlen = ', RecvLen );
    WriteLn( 'FromAddr.Protocol = ', FromAddr.Protocol );
  end;

  Status := Ipx2^.CoGetIoResult( @Ovlp2, COF_WAIT );
  if Status <> CST_SUCCESS then
  begin
    WriteLn( 'Recv, Error:', Status );
  end
  else begin
    WriteLn( 'Recvlen = ', RecvLen );
    WriteLn( 'FromAddr.Protocol = ', FromAddr.Protocol );
  end;

  Status :=Ipx1^.CoUnbind( COF_PROPAGATE, nil );
  if Status <> CST_SUCCESS then
  begin
    WriteLn( '1_Unbind, Error:', Status );
  end;

  Status := Ipx2^.CoUnbind( COF_PROPAGATE, nil );
  if Status <> CST_SUCCESS then
  begin
    WriteLn( '2_Unbind, Error:', Status );
  end;

  CoDeleteDevice( Ipx1 );
  CoDeleteDevice( Ipxm1 );
  CoDeleteDevice( Eth1 );

end.