uses
  Crt,
  CoBase,
  CoDefs,
  CoIPv4,
  CoUDP,
  CoPktDrv;


{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
  );}

const

  Buff1     : array[0..100] of Char = 'Text posilany protokolem UDP'#0;

var
  Status   : TCoStatus;

  S        : String;

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

  RecvLen   : Word;

  Ovlp1     : TOverlapped;
  Ovlp2     : TOverlapped;

  UdpAddr   : TUdpAddress;

  TempSock  : PCoDevice;
  Sock      : PCoDevice;

  I         : Integer;

  H         : PCoPktHeap;

var
  P1, P2, P3, P4: Pointer;

begin
  ClrScr;

{  for I := Low(Buff1) to High(Buff1) do Buff1[I] := $CD;}

  if CoCreateDevice( 'PKTDRV', 'ETH_A', '',
       nil, TempSock ) <> CST_SUCCESS then
  begin
    WriteLn( 'Nelze vytorit instanci PktDrv' );
    Exit;
  end;


  if CoCreateDevice( 'IPV4', 'IP_A', 'IP="192.168.1.210"',
       CoOpenDevice( 'ETH_A' ), TempSock ) <> CST_SUCCESS then
  begin
    WriteLn( 'Nelze vytorit instanci IPV4' );
    Exit;
  end;


  if CoCreateDevice( 'UDPMUX', 'UDPMUX_A', '',
       CoOpenDevice( 'IP_A' ), TempSock ) <> CST_SUCCESS then
  begin
    WriteLn( 'Nelze vytorit instanci UDPMUX' );
    Exit;
  end;

  if CoCreateDevice( 'UDP', 'UDP_A', '',
       CoOpenDevice( 'UDPMUX_A' ), Sock ) <> CST_SUCCESS then
  begin
    WriteLn( 'Nelze vytorit instanci UDP' );
    Exit;
  end;


  Status := Sock^.CoGetOptionString( DEV_CLASS_IP, @S, SizeOf(S) - 1, nil);
  if Status <> CST_SUCCESS then
  begin
    WriteLn( 'CoGetOptionString() ', CoStatusToStr( Status ) );
    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;}


  UdpAddr.Size    := SizeOf( UdpAddr );
  UdpAddr.Address := IP_ADDR_ANY;
  UdpAddr.Port    := 4000;


  Status := Sock^.CoBind( @UdpAddr, COF_PROPAGATE, nil );
  if Status <> CST_SUCCESS then
  begin
    WriteLn( 'Bind, ', CoStatusToStr( Status ) );
  end;

{  Address.Size := SizeOf( Address );
  Address.Node := MakeIpAddr( 192, 168, 1, 8 );
  Address.Protocol := 255; { !! }


  UdpAddr.Size     := SizeOf( UdpAddr );
  UdpAddr.Address  := MakeIpAddr( 192, 168, 1, 1 );
  UdpAddr.Port     := 4000;

  Status := Sock^.CoSendBufferTo( @Buff1, SizeOf( Buff1 ), 0,
              PCoAddress(@UdpAddr), @Ovlp1 );



  Status := Sock^.CoGetIOResult( @Ovlp1, COF_WAIT );

  WriteLn( Status );

{  Status := Ip1^.CoSendBufferTo( @Buff1, SizeOf( Buff1 ), 0,
              PCoAddress(@Address), nil );
}

  repeat

    Status := Sock^.CoRecvBufferFrom( @Buff2, SizeOf( Buff2 ), @RecvLen, 0,
                PCoAddress(@UdpAddr), nil );


    if Status = CST_SUCCESS then
    begin
      WriteLn( 'Recv: ', RecvLen, 'B  :', Buff2 );
      Status := Sock^.CoSendBufferTo( @Buff2, RecvLen, 0, PCoAddress(@UdpAddr), nil );
    end;

  until KeyPressed;

  Status := Sock^.CoUnbind( COF_PROPAGATE, nil );

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

end.