
uses
  Crt,
  CoBase,
  CoIPV4,
  CoEthDef,
  CoEth01,
  CoINET,
  CoUDP,
  NumToStr;



procedure UdpSendTest;
var
  Sock     : PCoDevice;
  Status   : TCoStatus;
  SendBuff : array[0..4095] of Byte;
  SendLen  : Word;
  SrcAddr  : TUdpAddress;
  Counter  : Longint;
  Ovlp1    : TOverlapped;
  Ovlp2    : TOverlapped;
begin

  FillChar( Ovlp1, SizeOf( Ovlp1 ), 0 );
  FillChar( Ovlp2, SizeOf( Ovlp2 ), 0 );

  Status := NetOpenSocket( 'UDP', 'LPORT=5000', '', Sock );

  if Status <> CST_SUCCESS then
  begin
    WriteLn( 'NetOpenSocket() failed: ', CoStatusToStr( Status ) );
    Exit;
  end;

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

  if Status <> CST_SUCCESS then
  begin
    WriteLn( 'CoBind() failed: ', Sock^.CoStatusToStr( Status ) );
    NetCloseSocket( Sock );
    Exit;
  end;

  WriteLn( 'UDP port initialized' );

  SrcAddr.Size := SizeOf( SrcAddr );
  SrcAddr.Port := 5000;
  SrcAddr.Address := MakeIpAddr( 192, 168, 1, 9 );

  SendLen := 1400;

  Counter := 0;

  repeat

    if Counter mod 100 = 0 then
    begin
      gotoxy( 1, 1 );
      Write( Counter );
    end;
    Inc(Counter );

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

    Status := Sock^.CoSendBufferTo( @SendBuff, SendLen, 0, @SrcAddr, @Ovlp1 );

    Inc( Counter );

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

    Status := Sock^.CoSendBufferTo( @SendBuff, SendLen, 0, @SrcAddr, @Ovlp2 );
}

    Status := Sock^.CoSendBufferTo( @SendBuff, SendLen, 0, @SrcAddr, nil );

    if Status <> CST_SUCCESS then
    begin
      WriteLn( 'CoSendBufferTo() failed: ', Sock^.CoStatusToStr( Status ) );
    end;

  until False;

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

  if Status <> CST_SUCCESS then
  begin
    WriteLn( 'CoUnbind() failed: ', Sock^.CoStatusToStr( Status ) );
  end;

  NetCloseSocket( Sock );

end;

procedure UdpEchoTest;
var
  Sock     : PCoDevice;
  Status   : TCoStatus;
  RecvBuff : array[0..4095] of Byte;
  RecvLen  : Word;
  SrcAddr  : TUdpAddress;
  Ovlp     : TOverlapped;
begin


  FillChar( Ovlp, SizeOf( Ovlp ), 0);

  Status := NetOpenSocket( 'UDP', 'LPORT=5000', '', Sock );


  if Status <> CST_SUCCESS then
  begin
    WriteLn( 'NetOpenSocket() failed: ', CoStatusToStr( Status ) );
    Exit;
  end;

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

  if Status <> CST_SUCCESS then
  begin
    WriteLn( 'CoBind() failed: ', Sock^.CoStatusToStr( Status ) );
    NetCloseSocket( Sock );
    Exit;
  end;

  WriteLn( 'UDP port initialized' );

  repeat

    Status := Sock^.CoRecvBufferFrom( @RecvBuff, SizeOf( RecvBuff ),
                                        @RecvLen, 0, @SrcAddr, nil );

    case Status of

      CST_SUCCESS:
      begin

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

        if Status <> CST_SUCCESS then
        begin
          WriteLn( 'CoSendBufferTo() failed: ', Sock^.CoStatusToStr( Status ) );
        end;}

        Status := Sock^.CoSendBufferTo( @RecvBuff, RecvLen, 0,
                                          @SrcAddr, nil );

        if Status <> CST_SUCCESS then
        begin
          WriteLn( 'CoSendBufferTo() failed: ', Sock^.CoStatusToStr( Status ) );
        end;

      end;

      CST_ERR_TIMEOUT:
      begin
      end;

    else

      WriteLn( 'CoRecvBufferFrom() failed: ', Sock^.CoStatusToStr( Status ) );

    end;

  until False;


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

  if Status <> CST_SUCCESS then
  begin
    WriteLn( 'CoUnbind() failed: ', Sock^.CoStatusToStr( Status ) );
  end;

  NetCloseSocket( Sock );

end;


procedure EthSendTest;
const

  Address : TEthAddress =
  ( Size     : SizeOf( TEthAddress );
    Mac      : (Bytes: ( 1, 2, 3, 4, 5, 6 )); { Adresa nekam do pryc... }
    Format   : ETH_FORMAT_ETHII;
    Protocol : $FFFF
  );
var
  Ovlp1, Ovlp2 : TOverlapped;

  Sock     : PCoDevice;
  Status   : TCoStatus;

  Frame    : array[0..1520] of Byte;
  FrameLen : Word;

  Counter  : Longint;

begin

  FillChar( Ovlp1, SizeOf( Ovlp1 ), 0 );
  FillChar( Ovlp2, SizeOf( Ovlp2 ), 0 );

  Status := CoCreateDevice( 'ETH01', '', 'IOBASE=$300', nil, Sock );

  if Status <> CST_SUCCESS then
  begin
    WriteLn( 'CoCreateDevice() failed: ', CoStatusToStr( Status ));
    Exit;
  end;

  Status := Sock^.CoBind( nil, 0, nil );

  if Status <> CST_SUCCESS then
  begin
    WriteLn( 'CoBind() failed: ', Sock^.CoStatusToStr( Status ) );
    CoReleaseDevicePtr( Sock );
    Exit;
  end;

  Counter := 0;
  FrameLen := 20;

  repeat

    if Counter mod 100 = 0 then
    begin
      GotoXY( 1, 1 );
      Write( Counter );
    end;

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

    Status := Sock^.CoSendBufferTo( @Frame, FrameLen, 0, @Address, @Ovlp1 );

    Inc(Counter );

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

    Status := Sock^.CoSendBufferTo( @Frame, FrameLen, 0, @Address, @Ovlp2 );

    Inc(Counter );

{    Status := Sock^.CoSendBufferTo( @Frame, FrameLen, 0, @Address, nil );



    if Status <> CST_SUCCESS then
    begin
      WriteLn( 'CoSendBufferTo() failed: ', Sock^.CoStatusToStr( Status ) );
      Break;
    end;}


  until False;

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

  if Status <> CST_SUCCESS then
  begin
    WriteLn( 'CoUnbind() failed: ', Sock^.CoStatusToStr( Status ) );
  end;


  CoReleaseDevicePtr( Sock );

end;



procedure PortToBuffer( PortIdx: Word; Buff: Pointer; Size: Word ); assembler;
asm
        MOV    CX, SIZE
        JCXZ   @@1
        LES    DI, Buff
        MOV    DX, PortIdx
        REP    INSB
  @@1:
end;

var
  Status: TCoStatus;


begin



{  EthSendTest;
end.}

  { Otevreni TCP/IP stacku }

  Status := NetOpenStack( 'ETH01', 'IOBASE=$300',
             'IPADDR="192.168.1.210" REASMTO=5', '' );

  if Status <> CST_SUCCESS then
  begin
    WriteLn( 'NetOpenStack() failed: ', CoStatusToStr( Status ) );
    Exit;
  end;

  WriteLn( 'TCP/IP stack initialized' );

  { Spusteni testu }

  UdpEchoTest;

{  UdpSendTest;}

  { Uzavreni TCP/IP stacku }

  NetCloseStack( '' );

end.