{-----------------------------------------------------------------}
{ Priklad na odesilani a prijem datagramu pomoci protokolu UDP    }
{ Tento priklad vyuziva knihovnu CoINET, ktera nebyla v praci     }
{ zminovana. Jejim ukolem je zjednoduseni vytvareni zarizeni      }
{ TCP/IP zasobniku                                                }
{-----------------------------------------------------------------}

program UdpSample;

uses
  CoBase,
  CoEth01,
  CoIPv4,
  CoUDP,
  CoINET;

const

  { Cilova adresa odesilaneho datagram }
  SAddress : TUdpAddress =
    (
      Size     : SizeOf( TUdpAddress );
      Address  : $FFFFFFFF; { Vseobecny obeznik }
      Port     : 5000
    );

var
  Status    : TCoStatus;              { Stav vysledku operace           }
  Sock      : PCoDevice;              { Ukazatel na instanci zarizeni   }
  Data      : array[0..1023] of Byte; { Data ramce                      }
  RecvLen   : Word;                   { Delka prijateho ramce           }
  RAddress  : TUdpAddress;            { Zdrojova adresa prijateho ramce }

  { Procedura pripravujici data odesilaneho ramce }
  procedure ProduceData;
  begin
    { ... }
  end;

  { Procedura zpracovavajici data prijateho ramce }
  procedure ConsumeData;
  begin
    { ... }
  end;

begin

  { Vytvoreni TCP/IP zasobniku nad zarizenim ETH01 s bazovou adresou  }
  { $2300. IP protokol bude nakonfigurovan na IP adresu 192.168.1.210 }
  { a masku 255.255.255.0                                             }

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

  if Status <> CST_SUCCESS then
  begin
    WriteLn( 'NetOpenStack() failed: ', CoStatusToStr( Status ) );
  end
  else begin
    { TCP/IP stack byl uspesne vytvoren }

    { Vytvorime UDP zasuvku naslouchajici na lokalni portu 5000 }
    Status := NetOpenSocket( 'UDP', 'LPORT=5000', '', Sock );

    if Status <> CST_SUCCESS then
    begin
    end
    else begin

      { Inicializace vsech vrstev TCP/IP zasobniku }
      Status := Sock^.CoBind( nil, COF_PROPAGATE, nil );

      if Status = CST_SUCCESS then
      begin

        { Naplneni dat urcenych k odvysilani }
        ProduceData;

        { Vyslani datagramu s daty Data na adresu SAddress }
        Status := Sock^.CoSendBufferTo( @Data, SizeOf( Data ), 0,
                    @SAddress, nil );

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

        { Prijem datagramu }

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

        if Status <> CST_SUCCESS then
        begin
          WriteLn( 'CoRecvBufferFrom() failed: ', Sock^.CoStatusToStr( Status ) );
        end
        else begin
          { Zpracovani prijatych dat }
          ConsumeData;
        end;

        { Deinicializace vsech vrstvev TCP/IP zasobniku }
        Status := Sock^.CoUnbind( COF_PROPAGATE, nil );
      end
      else
        WriteLn( 'CoBind() failed: ', Sock^.CoStatusToStr( Status ) );


      { Uvolneni zarizeni UDP zasuvku }
      NetCloseSocket( Sock );
    end;

    { Uvolneni vsech ostatnich zarizeni TCP/IP stacku }
    NetCloseStack( '' );
  end;

end.
