-
+ 08D9E728F35338ACA8CBD7B2D0D1A124F731E286C15DF2E65C4D7C9BB6BF750CD44ACBB818ECA656BFD3402B77927C300693978576622E6E241C2F00824CC7FEudp/libudp/udp.adb(0 . 0)(1 . 139)
268 ------------------------------------------------------------------------------
269 ------------------------------------------------------------------------------
270 -- This file is part of 'UDP', a datagram sockets library. --
271 -- --
272 -- (C) 2018 Stanislav Datskovskiy ( www.loper-os.org ) --
273 -- http://wot.deedbot.org/17215D118B7239507FAFED98B98228A001ABFFC7.html --
274 -- --
275 -- You do not have, nor can you ever acquire the right to use, copy or --
276 -- distribute this software ; Should you use this software for any purpose, --
277 -- or copy and distribute it to anyone or in any manner, you are breaking --
278 -- the laws of whatever soi-disant jurisdiction, and you promise to --
279 -- continue doing so for the indefinite future. In any case, please --
280 -- always : read and understand any software ; verify any PGP signatures --
281 -- that you use - for any purpose. --
282 -- --
283 -- See also http://trilema.com/2015/a-new-software-licensing-paradigm . --
284 ------------------------------------------------------------------------------
285 ------------------------------------------------------------------------------
286
287 package body UDP is
288
289 -- Generate a human representation of a (local-endian) IP Address
290 function IP_To_String(IP : in IP_Address) return IP_Address_Text is
291 Text : IP_Address_Text := (others => ' ');
292 begin
293 Unix_UDP_IP_To_String(IP, Text'Address, Text'Length);
294 return Text;
295 end IP_To_String;
296
297
298 -- Generate a (local-endian) IP Address from given human representation
299 function IP_From_String(IP_Text : in String) return IP_Address is
300 Text_With_Null : String(1 .. IP_Text'Length + 1);
301 Result : Interfaces.C.Int := 0;
302 IP : aliased IP_Address;
303 begin
304 -- We can't use To_C because malicious idiots demanded secondary stack.
305 Text_With_Null(IP_Text'Range) := IP_Text;
306 Text_With_Null(Text_With_Null'Last) := Character'Val(0);
307
308 -- Let unix do the conversion
309 Result := Unix_UDP_String_To_IP(Text_With_Null'Address,
310 IP'Access);
311 case Result is
312 when -1 =>
313 raise UDP_Invalid_Text_IP;
314 when others =>
315 return IP;
316 end case;
317 end IP_From_String;
318
319
320 -- Open a UDP socket, with the given local endpoint for both TX and RX
321 procedure Open_Socket(S : out Socket;
322 Local_Endpoint : in Endpoint) is
323 Result : constant Interfaces.C.Int :=
324 Unix_UDP_Socket_Open(Socket => S'Address,
325 Local_IP => Local_Endpoint.Address,
326 Local_Port => Local_Endpoint.Port);
327 begin
328 case Result is
329 when -1 =>
330 raise UDP_Failed_Open;
331 when -2 =>
332 raise UDP_Failed_SetOpt;
333 when -3 =>
334 raise UDP_Failed_Bind;
335 when others =>
336 null;
337 end case;
338 end Open_Socket;
339
340
341 -- Permanently close the given open given socket
342 procedure Close_Socket(S : in out Socket) is
343 begin
344 Unix_UDP_Socket_Close(Socket => S'Address);
345 end Close_Socket;
346
347
348 -- Transmit the Payload, via Socket, to given Destination
349 procedure Transmit(S : in out Socket;
350 Destination : in Endpoint;
351 Payload_Buf : in Payload) is
352 Result : constant Interfaces.C.Int :=
353 Unix_UDP_Socket_Transmit(Socket => S'Address,
354 Remote_IP => Destination.Address,
355 Remote_Port => Destination.Port,
356 Payload_Buf => Payload_Buf'Address,
357 Payload_Len => Payload'Length);
358 begin
359 case Result is
360 when -1 =>
361 Close_Socket(S);
362 raise UDP_Failed_Transmit;
363 when others =>
364 -- No eggog
365 null;
366 end case;
367 end Transmit;
368
369
370 -- Wait (potentially forever!) for a Payload, via Socket; save its Origin
371 procedure Receive(S : in out Socket;
372 Origin : out Endpoint;
373 Payload_Buf : out Payload;
374 Valid : out Boolean) is
375
376 -- Scratch pad (if not successful, the call has no outputs)
377 Incoming_Payload : aliased Payload := (others => 0);
378 Incoming_IP : aliased IP_Address;
379 Incoming_Port : aliased IP_Port;
380
381 Result : constant Interfaces.C.Int :=
382 Unix_UDP_Socket_Receive(Socket => S'Address,
383 Origin_IP => Incoming_IP'Access,
384 Origin_Port => Incoming_Port'Access,
385 Payload_Buf => Incoming_Payload'Address,
386 Payload_Len => Payload'Length);
387 begin
388 Valid := False;
389 case Result is
390 when -1 =>
391 Close_Socket(S);
392 raise UDP_Failed_Receive;
393 when others =>
394 -- No eggog:
395 Origin.Address := Incoming_IP;
396 Origin.Port := Incoming_Port;
397 Payload_Buf := Incoming_Payload;
398
399 -- Was a full-length payload?
400 if (Result = Payload'Length) then
401 Valid := True;
402 end if;
403 end case;
404 end Receive;
405
406 end UDP;