diff -uNr a/udp/libudp/restrict.adc b/udp/libudp/restrict.adc --- a/udp/libudp/restrict.adc 0ce47e877e69cdc718556d94802736a36d5289bac7d5c58f4faffc75f0fe8f461f4799705e9b29f89e071c51141bd88b2d73917271170f7fd771ed288ad07215 +++ b/udp/libudp/restrict.adc 7feb3510444d5888f8cd5566f7beb042274f44e6535c9cc2b3fe05b922d8778e5940911b56ca064490dc67c985476c769acf23cd25ac62bbfa57ef652d7d7a05 @@ -27,10 +27,10 @@ pragma Restrictions(No_Access_Parameter_Allocators); pragma Restrictions(No_Allocators); pragma Restrictions(No_Asynchronous_Control); -pragma Restrictions(No_Calendar); +--pragma Restrictions(No_Calendar); pragma Restrictions(No_Coextensions); pragma Restrictions(No_Default_Stream_Attributes); -pragma Restrictions(No_Delay); +--pragma Restrictions(No_Delay); pragma Restrictions(No_Dispatch); pragma Restrictions(No_Dispatching_Calls); pragma Restrictions(No_Dynamic_Attachment); @@ -45,7 +45,6 @@ pragma Restrictions(No_Floating_Point); pragma Restrictions(No_Implementation_Aspect_Specifications); pragma Restrictions(No_Implementation_Units); -pragma Restrictions(No_Implicit_Conditionals); pragma Restrictions(No_Implicit_Dynamic_Code); pragma Restrictions(No_Implicit_Heap_Allocations); pragma Restrictions(No_Implicit_Protected_Object_Allocations); @@ -57,7 +56,7 @@ pragma Restrictions(No_Nested_Finalization); pragma Restrictions(No_Protected_Type_Allocators); pragma Restrictions(No_Protected_Types); -pragma Restrictions(No_Relative_Delay); +--pragma Restrictions(No_Relative_Delay); pragma Restrictions(No_Requeue_Statements); pragma Restrictions(No_Secondary_Stack); pragma Restrictions(No_Select_Statements); @@ -80,4 +79,5 @@ pragma Restrictions(Simple_Barriers); pragma Restrictions(Static_Priorities); pragma Restrictions(Static_Storage_Size); + --pragma Restrictions(No_Implicit_Conditionals); pragma Validity_Checks(ALL_CHECKS); diff -uNr a/udp/libudp/udp.adb b/udp/libudp/udp.adb --- a/udp/libudp/udp.adb de0cec9ced66f9d083e9c7dd1f2e02586e36481701f3b8c988f500f521454dc8ca51797961e1e773edffb7a96ad6d9b4f277b47aab056b7e313c23b8677baff3 +++ b/udp/libudp/udp.adb 84814d47643f564f51fe5a03835b373812ee8902fa209175522de3b447c11916c8457b747fee05b87f05bd9c2c172000717b1621a22999e457e7bc5c4250a1b4 @@ -18,9 +18,29 @@ ------------------------------------------------------------------------------ package body UDP is + + -- Bit-level compare of 2 payloads, returns number of different bits + function Bit_Compare(A: in Payload; B: in Payload) return Natural is + V : Unsigned_8; + Count : Natural := 0; + begin + for I in Payload'Range loop + -- obtain bits that are different + V := A(I) xor B(I); + -- count the bits that are 1, if any + Counting_Loop: + while V /= 0 loop + Count := Count + Natural((V and Unsigned_8(1))); + V := Shift_Right(V, 1); + end loop Counting_Loop; + end loop; + + return Count; + end Bit_Compare; -- Generate a human representation of a (local-endian) IP Address - function IP_To_String(IP : in IP_Address) return IP_Address_Text is + function IP_To_String(IP : in IP_Address) + return IP_Address_Text is Text : IP_Address_Text := (others => ' '); begin Unix_UDP_IP_To_String(IP, Text'Address, Text'Length); @@ -94,10 +114,10 @@ Close_Socket(S); raise UDP_Failed_Transmit; when others => - -- No eggog, but must check if sent all bytes: - if (Result /= Payload'Length) then - Close_Socket(S); - raise UDP_Truncated_Send; + if Result /= Payload'Length then + -- fail as message was truncated/not sent in full + Close_Socket(S); + raise UDP_Truncated_Send; end if; end case; end Transmit; @@ -107,7 +127,7 @@ procedure Receive(S : in out Socket; Origin : out Endpoint; Payload_Buf : out Payload; - Valid : out Boolean) is + Recv_Len : out Unsigned_32) is -- Scratch pad (if not successful, the call has no outputs) Incoming_Payload : aliased Payload := (others => 0); @@ -121,7 +141,8 @@ Payload_Buf => Incoming_Payload'Address, Payload_Len => Payload'Length); begin - Valid := False; + -- Valid := False; + Recv_Len := 0; case Result is when -1 => Close_Socket(S); @@ -133,9 +154,10 @@ Payload_Buf := Incoming_Payload; -- Was a full-length payload? - if (Result = Payload'Length) then - Valid := True; - end if; + --if (Result = Payload'Length) then + -- Valid := True; + --end if; + Recv_Len := Unsigned_32( Result ); end case; end Receive; diff -uNr a/udp/libudp/udp.ads b/udp/libudp/udp.ads --- a/udp/libudp/udp.ads 41d0512d8759cbcb10d753a22a86b6bdaf96fccf779e2bbdabf4a1c7efca7a4f8f9047984d6cc2350b7625715aac26c0ccd49c7baca765811e0c0bcc0ababf22 +++ b/udp/libudp/udp.ads a7e2a069125e5476d4eafa10c4b674a1776325568da5700b2e8adf626f9bb3aa07c28b1435dff4be3c085aef3c963dd90a22c91f3d47abf4a5b205b0b84ab842 @@ -20,14 +20,13 @@ with Interfaces, Interfaces.C; use Interfaces, Interfaces.C; with System; use System; +generic + Payload_Size : in Positive; -- to allow for diff sizes at runtime package UDP is pragma Preelaborate; - - -- This is subject to debate: - Payload_Size : constant Positive := 512; - + type Payload is array(1 .. Payload_Size) of Unsigned_8; subtype IP_Address is Unsigned_32; @@ -35,6 +34,9 @@ -- Magic that puts emitter on 'any' local interface INADDR_ANY : constant Unsigned_32 := 0; + + -- Bit-level compare of 2 payloads, returns number of different bits + function Bit_Compare(A: in Payload; B: in Payload) return Natural; -- An local or remote address:port type Endpoint is @@ -72,10 +74,11 @@ -- Wait (potentially forever!) for a Payload, via Socket; save its Origin, -- and whether the received Payload was valid (i.e. expected length): + -- replaced Valid with actual received length for testing purpose procedure Receive(S : in out Socket; Origin : out Endpoint; Payload_Buf : out Payload; - Valid : out Boolean); + Recv_Len : out Unsigned_32); -- Eggogology: UDP_Invalid_Text_IP : exception; diff -uNr a/udp/manifest b/udp/manifest --- a/udp/manifest 6b46c9cc494c5f0ecce1c653d6f34ad30d366b0d4a1d9ab169e94ffbc17be09cac3dbf85f5b571516161712fd201e50581cd2c247aa5b7442f94b69cfdc907eb +++ b/udp/manifest 7ae4ec290548713f623a1cae18025750324170d9b22a618be1d2a1a95c02c1b10f605ebc109a7983bd14b23b01a497567d5a7796db212b9f76d209cb4ff5ca14 @@ -2,3 +2,4 @@ 543081 udp_errata_asciilifeform diana_coman Regrind of asciilifeform's errata on his UDP lib: adds closing socket calls, corrects and adds to comments. 543082 udp_fix_nullchars diana_coman Fix for issue in unix_udp.c that returns null characters at end of IPs shorter than 16 characters in length. 543083 mt_prng diana_coman Ada implementation of Mersenne Twister pseudorandom number generator + automated tests for it. +543084 udp_tester diana_coman Sender and Receiver for testing UDP communication over a range of packet sizes. NB: this makes some changes to UDP lib for *testing* purposes - those changes are NOT required in production. diff -uNr a/udp/udp_tester/bin/README b/udp/udp_tester/bin/README --- a/udp/udp_tester/bin/README false +++ b/udp/udp_tester/bin/README 5fdbae897eb301a711bf95707f329517db540e34c182a5beec96e93d5d0d856cec2ed6b01c1191f865e8d1c45709a462c70c3005d4aa3676eb445d1479edf2e5 @@ -0,0 +1 @@ +Placeholder. diff -uNr a/udp/udp_tester/obj/README b/udp/udp_tester/obj/README --- a/udp/udp_tester/obj/README false +++ b/udp/udp_tester/obj/README 50f9b127e6ae2019779520d8998bea7f559496b1847c7c66b6ce6a6f3fc20db67d45f1fbf7a9318c86ebba0694db73de168f409d8328a751f3104c1474a83a0d @@ -0,0 +1 @@ +obj diff -uNr a/udp/udp_tester/tester.gpr b/udp/udp_tester/tester.gpr --- a/udp/udp_tester/tester.gpr false +++ b/udp/udp_tester/tester.gpr 6b510bcd314548708ef8d5c03595599e1a65a31882876c9ed538c0c92fdb6dc6f5854f35bfc6ad7f569eb225bbcb3ed990830ca21483c4de37bc527372d78862 @@ -0,0 +1,54 @@ + -- S.MG, 2018 + -- Sender for testing UDP transmissions + +with "../libudp/udp.gpr"; -- UDP lib +with "../libmt/mt.gpr"; -- mersenne twister prng + +project Tester is + + for Object_Dir use "obj"; + + type Mode_Type is ("debug", "release"); + Mode : Mode_Type := external ("mode", "release"); + + for Languages use ("Ada"); + for Source_Dirs use ("."); + for Exec_Dir use "bin"; + for Main use ("udp_sender.adb", "udp_receiver.adb"); + + package Compiler is + case Mode is + when "debug" => + for Switches ("Ada") + use ("-g"); + when "release" => + for Switches ("Ada") + use ("-O2", "-fdump-scos", "-gnata", "-fstack-check", + "-gnatyd", "-gnatym", + "-fdata-sections", "-ffunction-sections"); + end case; + end Compiler; + + package Binder is + case Mode is + when "debug" => + for Switches ("Ada") + use (); + when "release" => + for Switches ("Ada") + use ("-static"); + end case; + end Binder; + + package Linker is + case Mode is + when "debug" => + for Switches ("Ada") + use (); + when "release" => + for Switches ("Ada") + use ("-Wl,--gc-sections", "-static"); + end case; + end Linker; + +end Tester; diff -uNr a/udp/udp_tester/udp_receiver.adb b/udp/udp_tester/udp_receiver.adb --- a/udp/udp_tester/udp_receiver.adb false +++ b/udp/udp_tester/udp_receiver.adb 951bdccfb137311e6cdcfdcdebd1c8af3edb598ae2a28278765bf439f4f6ea497a2592a15c70fcffd3f11f42b693867ed1a612633907d8c85a3eb1c08d0f2fe1 @@ -0,0 +1,12 @@ + -- S.MG, 2018 + +with UDP_Tester; + +procedure UDP_Receiver is + -- Port to listen on + Receiver_Port : constant := 9000; +begin + + UDP_Tester.Receiver( Receiver_Port ); + +end UDP_Receiver; diff -uNr a/udp/udp_tester/udp_sender.adb b/udp/udp_tester/udp_sender.adb --- a/udp/udp_tester/udp_sender.adb false +++ b/udp/udp_tester/udp_sender.adb 72774e64a2e5fbee5f5865e2ec24244fbde193c530203e1b8ce49f1df80491f03b7df3f5b728069c07b9656a2ebb39b5ac9e863e75371715ec937579f322ea43 @@ -0,0 +1,16 @@ + -- S.MG, 2018 + +with UDP_Tester; + +procedure UDP_Sender is + -- Sender and Receiver addresses + ports + Receiver_IP : constant String := "127.0.0.1"; --SET THIS to your address! + Receiver_Port : constant := 9000; + + Sender_Port : constant := 8000; + +begin + + UDP_Tester.Sender( Receiver_IP, Receiver_Port, Sender_Port) ; + +end UDP_Sender; diff -uNr a/udp/udp_tester/udp_tester.adb b/udp/udp_tester/udp_tester.adb --- a/udp/udp_tester/udp_tester.adb false +++ b/udp/udp_tester/udp_tester.adb b7560776b05822024c15f66648c6ea0777a6ef23b817df4418a8c52d1319f62f3348db65e4ee905d4730ecbc2bca800628f3fec21d5e9ac62fdd5b293d1e9973 @@ -0,0 +1,310 @@ + -- UDP transmissions tester for the libUDP + -- S.MG, 2018 + +with Ada.Text_IO; use Ada.Text_IO; +with Ada.Calendar; use Ada.Calendar; -- for local time +with Ada.Calendar.Time_Zones; use Ada.Calendar.Time_Zones; -- UTC_Time_Offset +with Ada.Calendar.Formatting; use Ada.Calendar.Formatting; -- for unix-like +with Ada.Directories; use Ada.Directories; -- for log files checks +with Interfaces; use Interfaces; --Unsigned_8 for payload + +with UDP; +with MT; + +package body UDP_Tester is + + procedure Create_If_Not_Exists( Filename: in String; Header: in String) is + F : File_Type; + begin + begin + Open(File => F, Mode => Append_File, Name => Filename); + Close(File => F); + exception + when Ada.Text_IO.Name_Error => + Create( File => F, Mode => Out_File, Name => Filename); + Put_Line(F, Header); + Close(F); + Put_Line("Created file " & Filename); + end; + end Create_If_Not_Exists; + + procedure Sender( Receiver_IP: in String; + Receiver_Port: in Unsigned_16; + Sender_Port: in Unsigned_16 ) is + + -- payload sizes to choose from + Sizes : array(1..Max_Len-Header_Len+1) of Natural; + Len_Sizes : Natural := Sizes'Length; + Packet_Size : Positive; + Pos : Natural; + + -- log file for sender + OutFile : File_Type; + OutFileName : constant String := "sender_udp_log.txt"; + HeaderOutFile : constant String := + "SizeSent" & + ",TimeSent" & + ",DestinationIP" & + ",DestinationPort" & + ",Seed"; + + -- seed for initialising the MT PRNG + Seed : constant MT.U32 := MT.U32(Ada.Calendar.Clock - Epoch); + begin + -- create log file and add header to it if it doesn't exist already + Create_If_Not_Exists( OutFileName, HeaderOutFile); + + -- initialize MT rpng + MT.Init_Genrand(Seed); + + -- initialize payload sizes to choose from + for I in Sizes'Range loop + Sizes(I) := I - 1; + end loop; + + -- send packages in a loop + Sending_Loop: + while Len_Sizes > 0 loop + + --a delay of 1 sec to avoid saturating the link with burst-mode + delay 1.0; + + -- pick randomly one of the available sizes for payload + Pos := Natural(MT.Gen_U32 mod MT.U32(Len_Sizes)) + 1; + Packet_Size := Sizes( Pos ) + Header_Len; + + -- shift available sizes to exclude the latest pick + if PosSizes'First then + Sizes(Pos..Len_Sizes-1) := Sizes(Pos+1..Len_Sizes); + end if; + -- decrease length of available sizes + Len_Sizes := Len_Sizes - 1; + + -- instantiate UDP sender of picked size and send packet + declare + K : constant Positive := Packet_Size; + -- sender will have *current* size of UDP packet + package UDP_Sdr is new UDP( Payload_Size => K ); + + -- socket, addr, port + Socket : UDP_Sdr.Socket; + + Local_Endpoint : UDP_Sdr.Endpoint := + (Address => UDP_Sdr.INADDR_ANY, + Port => Sender_Port); + + Remote_Endpoint : UDP_Sdr.Endpoint := + (Address => UDP_Sdr.IP_From_String(Receiver_IP), + Port => Receiver_Port); + + Sent_Payload : UDP_Sdr.Payload; + + TimeUTC : Ada.Calendar.Time; + TimeUnix : Interfaces.Unsigned_32; + + begin + -- message to console + Put_Line("Sending packet Len_Sizes= " & Integer'Image(Len_Sizes) & + " with length " & Positive'Image(Sent_Payload'Length)); + + -- fill the payload, so starting after header octets + for I in (Sent_Payload'First + Header_Len) .. Sent_Payload'Last loop + Sent_Payload(I) := Interfaces.Unsigned_8(I mod 256); + end loop; + + -- fill the header part + -- time (UTC): year, month, day, seconds since midnight (2 octets) + TimeUTC := Ada.Calendar.Clock; + TimeUnix := Interfaces.Unsigned_32(TimeUTC - Epoch); + + Sent_Payload(Sent_Payload'First+3) := Interfaces.Unsigned_8( + TimeUnix mod 256 ); + TimeUnix := Shift_Right(TimeUnix, 8); + + Sent_Payload(Sent_Payload'First+2) := Interfaces.Unsigned_8( + TimeUnix mod 256 ); + TimeUnix := Shift_Right(TimeUnix, 8); + + Sent_Payload(Sent_Payload'First+1) := Interfaces.Unsigned_8( + TimeUnix mod 256 ); + TimeUnix := Shift_Right(TimeUnix, 8); + Sent_Payload(Sent_Payload'First) := Interfaces.Unsigned_8( + TimeUnix mod 256 ); + + + -- size of message (full, payload+header) + Sent_Payload(Sent_Payload'First + 4) := Interfaces.Unsigned_8( + Sent_Payload'Length / 256); + + Sent_Payload(Sent_Payload'First + 5) := Interfaces.Unsigned_8( + Sent_Payload'Length mod 256); + + -- send packet + UDP_Sdr.Open_Socket(Socket, Local_Endpoint); + UDP_Sdr.Transmit(Socket, Remote_Endpoint, Sent_Payload); + UDP_Sdr.Close_Socket(Socket); + + -- log the packet + TimeUnix := Interfaces.Unsigned_32(TimeUTC - Epoch); + + Open(File => OutFile, + Mode => Append_File, + Name => OutFileName); + Put(OutFile, Integer'Image(Sent_Payload'Length)); + Put(OutFile, "," & Unsigned_32'Image(TimeUnix)); + Put(OutFile, "," & Receiver_IP); + Put(OutFile, "," & Unsigned_16'Image(Receiver_Port)); + Put_Line(OutFile, "," & MT.U32'Image(Seed)); + + Close(File => OutFile); + end; + end loop Sending_Loop; + end Sender; + + procedure Receiver( Receiver_Port: in Unsigned_16 ) is + -- receiver HAS to have max len for UDP size; it doesn't know it in advance + package UDP_Rcv is new UDP( Payload_Size => Max_Len ); + + -- socket and local endpoint to receive on + Socket : UDP_Rcv.Socket; + Local_Endpoint : UDP_Rcv.Endpoint := (Address => UDP_Rcv.INADDR_ANY, + Port => Receiver_Port); + + -- received payload and source information + Received_Payload : UDP_Rcv.Payload; + Received_Origin : UDP_Rcv.Endpoint; + Received_Len : Unsigned_32; + + -- for logging + TimeUTC : Ada.Calendar.Time; + TimeUnix : Interfaces.Unsigned_32; + TimeSent : Interfaces.Unsigned_32; + SizeSent : Interfaces.Unsigned_32; + Expected : Interfaces.Unsigned_8; --one octet of payload + ErrCount : Natural; + + -- log file + OutFile : File_Type; + ErrFile : File_Type; + OutFileName : constant String := "receiver_udp_log.txt"; + ErrFileName : constant String := "receiver_udp_err_log.txt"; + HeaderOutFile : constant String := + "SizeSent" & + ",TimeSent" & + ",SourceIP" & + ",SourcePort" & + ",SizeReceived" & + ",TimeReceived" & + ",ErrorOctetsCount"; + HeaderErrFile : constant String := + "SizeSent" & + ",TimeSent" & + ",SourceIP" & + ",SourcePort" & + ",SizeReceived" & + ",TimeReceived" & + "(,Position" & --position in payload of err octet + ",ValueReceived" & + ",ValueExpected)*"; + + begin + -- create log files and add headers to them if they don't exist already + Create_If_Not_Exists( OutFileName, HeaderOutFile); + Create_If_Not_Exists( ErrFileName, HeaderErrFile); + + Put_Line("Opening socket on local endpoint " & + UDP_Rcv.IP_To_String(Local_Endpoint.Address) & + " :" & UDP_Rcv.IP_Port'Image(Local_Endpoint.Port) & "..."); + + UDP_Rcv.Open_Socket(Socket, Local_Endpoint); + + Put_Line("Waiting for payloads..."); + +-- endless, receiving loop + Receiving_Loop: + loop + -- receive a payload + UDP_Rcv.Receive(Socket, Received_Origin, Received_Payload, Received_Len); + + -- log the received payload + -- -- get local, arrival time + TimeUTC := Ada.Calendar.Clock; + TimeUnix := Unsigned_32(TimeUTC - Epoch); -- local, arrival time + + -- -- append to log file(s) + Open(File => OutFile, -- main log + Mode => Append_File, + Name => OutFileName); + + Open(File => ErrFile, -- error log + Mode => Append_File, + Name => ErrFileName); + + -- -- info from the received package itself + TimeSent := 0; + for I in 1..4 loop + TimeSent := Shift_Left(TimeSent, 8); + TimeSent := TimeSent + Unsigned_32(Received_Payload(I)); + end loop; + + SizeSent := Shift_Left(Unsigned_32(Received_Payload(5)), 8) + + Unsigned_32(Received_Payload(6)); + + Put(OutFile, Unsigned_32'Image(SizeSent)); + Put(OutFile, "," & Unsigned_32'Image(TimeSent)); + + -- -- info from receiver end + Put(OutFile, "," & UDP_Rcv.IP_To_String(Received_Origin.Address)); + Put(OutFile, "," & UDP_Rcv.IP_Port'Image(Received_Origin.Port)); + Put(OutFile, "," & Unsigned_32'Image(Received_Len)); + Put(OutFile, "," & Unsigned_32'Image(TimeUnix)); + + -- any octets that are different from expected (i.e. errors) + ErrCount := 0; + for I in Header_Len+1 .. Natural(Received_Len) loop + Expected := Unsigned_8(I mod 256); + if Received_Payload(I) /= Expected then + ErrCount := ErrCount + 1; + + -- first time *only*, add all the package info as well + if ErrCount = 1 then + Put(ErrFile, Unsigned_32'Image(SizeSent)); + Put(ErrFile, "," & Unsigned_32'Image(TimeSent)); + Put(ErrFile, "," & UDP_Rcv.IP_To_String(Received_Origin.Address)); + Put(ErrFile, "," & UDP_Rcv.IP_Port'Image(Received_Origin.Port)); + Put(ErrFile, "," & Unsigned_32'Image(Received_Len)); + Put(ErrFile, "," & Unsigned_32'Image(TimeUnix)); + end if; + + -- at all times: add the error details - position, received, expected + Put(ErrFile, "," & Natural'Image(I) & "," & + Unsigned_8'Image( Received_Payload(I) ) & "," & + Unsigned_8'Image( Expected ) + ); + end if; + end loop; + -- if there was at least an error, move to next line in error log + if ErrCount > 0 then + New_Line(File => ErrFile); + end if; + + -- in all cases, record ErrCount in main log file too + Put_Line(OutFile, "," & Natural'Image(ErrCount)); + + -- logging done for this entry, close the log files + Close(File => OutFile); + Close(File => ErrFile); + + Put_Line("Received payload from " & + UDP_Rcv.IP_To_String(Received_Origin.Address) & + " :" & UDP_Rcv.IP_Port'Image(Received_Origin.Port) & + " with length " & Unsigned_32'Image(Received_Len)); + + end loop Receiving_Loop; -- infinite, receiving loop + + -- close the socket and tidy up + UDP_Rcv.Close_Socket(Socket); + + end Receiver; + +end UDP_Tester; diff -uNr a/udp/udp_tester/udp_tester.ads b/udp/udp_tester/udp_tester.ads --- a/udp/udp_tester/udp_tester.ads false +++ b/udp/udp_tester/udp_tester.ads 1dd063e7677409e44fa53db1551400f6c3256b47b925dd789a8af51c2bebd15ad1f9418f372fcf7d0dddd33908336178c734e69358f88a0ad03f57bae2367196 @@ -0,0 +1,48 @@ + -- S.MG, 2018 + -- Tester for UDP communications relying on libudp and libmt + +with Ada.Calendar; use Ada.Calendar; -- for local time +with Ada.Calendar.Time_Zones; use Ada.Calendar.Time_Zones; -- UTC_Time_Offset +with Ada.Calendar.Formatting; use Ada.Calendar.Formatting; -- for unix-like +with Interfaces; use Interfaces; + +with UDP; +with MT; + +package UDP_Tester is + + -- knobs for Tester, change as required + + -- used for obtaining Unix-like time from value ret by Ada.Calendar.Clock + Epoch : constant Time := Formatting.Time_Of(1970, 1, 1, 0.0); + + -- Header of each packet is: + -- 4 octets local time unix format; + -- 2 octets total length of message (header+payload) + Header_Len : constant Positive := 6; + -- packages sent will be between Header_Len and Max_Len + Max_Len : constant Positive := 2048; + + -- helper methods + procedure Create_If_Not_Exists( Filename: in String; Header: in String); + + -- will send messages with lengths between Header_Len and Max_Len + -- messages are sent at 1 second intervals (i.e. 1 second between 2 messages) + -- sizes are chosen based on MT prng with seed = unixtime when sender starts + -- payloads are simply I mod 256 where I is position of octet in message + -- data for all sent messages is logged in a .txt file in current dir + -- if the log files exist, new content will be APPENDED to it + -- if the log file does not exist, it will be created + procedure Sender( Receiver_IP: in String; + Receiver_Port: in Unsigned_16; + Sender_Port: in Unsigned_16 ); + + -- receiver method with endless loop, receiving UDP messages on given port + -- data for all received messages is logged in a .txt file in current dir + -- an additional err log contains any octets that are different from expected + -- if the log files exist, new content will be APPENDED to it + -- if the log file does not exist, it will be created + procedure Receiver( Receiver_Port: in Unsigned_16 ); + + +end UDP_Tester;