------------------------------------------------------------------------------ ------------------------------------------------------------------------------ -- This file is part of 'UDP', a datagram sockets library. -- -- -- -- (C) 2018 Stanislav Datskovskiy ( www.loper-os.org ) -- -- http://wot.deedbot.org/17215D118B7239507FAFED98B98228A001ABFFC7.html -- -- -- -- You do not have, nor can you ever acquire the right to use, copy or -- -- distribute this software ; Should you use this software for any purpose, -- -- or copy and distribute it to anyone or in any manner, you are breaking -- -- the laws of whatever soi-disant jurisdiction, and you promise to -- -- continue doing so for the indefinite future. In any case, please -- -- always : read and understand any software ; verify any PGP signatures -- -- that you use - for any purpose. -- -- -- -- See also http://trilema.com/2015/a-new-software-licensing-paradigm . -- ------------------------------------------------------------------------------ ------------------------------------------------------------------------------ package body UDP is -- Generate a human representation of a (local-endian) IP Address 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); return Text; end IP_To_String; -- Generate a (local-endian) IP Address from given human representation function IP_From_String(IP_Text : in String) return IP_Address is Text_With_Null : String(1 .. IP_Text'Length + 1); Result : Interfaces.C.Int := 0; IP : aliased IP_Address; begin -- We can't use To_C because malicious idiots demanded secondary stack. Text_With_Null(IP_Text'Range) := IP_Text; Text_With_Null(Text_With_Null'Last) := Character'Val(0); -- Let unix do the conversion Result := Unix_UDP_String_To_IP(Text_With_Null'Address, IP'Access); case Result is when -1 => raise UDP_Invalid_Text_IP; when others => return IP; end case; end IP_From_String; -- Open a UDP socket, with the given local endpoint for both TX and RX procedure Open_Socket(S : out Socket; Local_Endpoint : in Endpoint) is Result : constant Interfaces.C.Int := Unix_UDP_Socket_Open(Socket => S'Address, Local_IP => Local_Endpoint.Address, Local_Port => Local_Endpoint.Port); begin case Result is when -1 => raise UDP_Failed_Open; when -2 => raise UDP_Failed_SetOpt; when -3 => raise UDP_Failed_Bind; when others => null; end case; end Open_Socket; -- Permanently close the given open given socket procedure Close_Socket(S : in out Socket) is begin Unix_UDP_Socket_Close(Socket => S'Address); end Close_Socket; -- Transmit the Payload, via Socket, to given Destination procedure Transmit(S : in out Socket; Destination : in Endpoint; Payload_Buf : in Payload) is Result : constant Interfaces.C.Int := Unix_UDP_Socket_Transmit(Socket => S'Address, Remote_IP => Destination.Address, Remote_Port => Destination.Port, Payload_Buf => Payload_Buf'Address, Payload_Len => Payload'Length); begin case Result is when -1 => Close_Socket(S); raise UDP_Failed_Transmit; when others => -- No eggog null; end case; end Transmit; -- Wait (potentially forever!) for a Payload, via Socket; save its Origin procedure Receive(S : in out Socket; Origin : out Endpoint; Payload_Buf : out Payload; Valid : out Boolean) is -- Scratch pad (if not successful, the call has no outputs) Incoming_Payload : aliased Payload := (others => 0); Incoming_IP : aliased IP_Address; Incoming_Port : aliased IP_Port; Result : constant Interfaces.C.Int := Unix_UDP_Socket_Receive(Socket => S'Address, Origin_IP => Incoming_IP'Access, Origin_Port => Incoming_Port'Access, Payload_Buf => Incoming_Payload'Address, Payload_Len => Payload'Length); begin Valid := False; case Result is when -1 => Close_Socket(S); raise UDP_Failed_Receive; when others => -- No eggog: Origin.Address := Incoming_IP; Origin.Port := Incoming_Port; Payload_Buf := Incoming_Payload; -- Was a full-length payload? if (Result = Payload'Length) then Valid := True; end if; end case; end Receive; end UDP;