MODULE UDP;
IMPORT IP, Sockets, Unix;
CONST
Ok* = 0; PortInUse* = 3501; Timeout* = 3502; BufferOverflow* = 3503; NoInterface* = 3504;
Closed* = 3505; Error* = 9999;
NilPort* = 0; anyport = 0;
UDPHdrLen = 8;
MaxUDPDataLen = 10000H - UDPHdrLen;
VAR
anyIP: IP.Adr;
TYPE
Socket* = OBJECT
VAR
socket: LONGINT;
lport: LONGINT;
open: BOOLEAN;
PROCEDURE & Open*( lport: LONGINT; VAR res: LONGINT );
VAR laddr: Sockets.SocketAdr;
BEGIN
ASSERT( (lport >= 0) & (lport < 10000H) );
SELF.lport := lport; res := Error;
socket := Sockets.Socket( Unix.AFINET, Unix.SockDGram, Unix.IpProtoUDP );
IF socket # 0 THEN
IF lport # anyport THEN
laddr := Sockets.NewSocketAdr( anyIP, lport );
IF Sockets.Bind( socket, laddr ) THEN
res := Ok; open := TRUE
ELSE
Sockets.Close( socket )
END
ELSE
res := Ok; open := TRUE
END
END
END Open;
PROCEDURE Send*( fip: IP.Adr;
fport: LONGINT;
CONST data: ARRAY OF CHAR; ofs, len: LONGINT;
VAR res: LONGINT );
VAR addr: Sockets.SocketAdr;
BEGIN {EXCLUSIVE}
ASSERT( (fport >= 0) & (fport < 10000H) );
ASSERT( (len >= 0) & (len <= MaxUDPDataLen) );
addr := Sockets.NewSocketAdr( fip, fport );
IF Sockets.SendTo( socket, addr, data, ofs, len ) THEN res := Ok ELSE res := Error END
END Send;
PROCEDURE SendBroadcast*( int: IP.Interface; fport: LONGINT;
CONST data: ARRAY OF CHAR; ofs, len: LONGINT );
BEGIN
ASSERT( (fport >= 0) & (fport < 10000H) ); ASSERT( (len >= 0) & (len <= MaxUDPDataLen) );
HALT( 99 )
END SendBroadcast;
PROCEDURE Receive*( VAR data: ARRAY OF CHAR; ofs, size, ms: LONGINT;
VAR fip: IP.Adr; VAR fport, len, res: LONGINT );
VAR
addr: Sockets.SocketAdr; i: LONGINT;
BEGIN {EXCLUSIVE}
IF ~open THEN res := Closed; RETURN END;
IF (ms >= 0) & ~Sockets.AwaitPacket( socket, ms ) THEN
res := Timeout; RETURN
END;
IF Sockets.RecvFrom( socket, addr, data, ofs, len ) THEN
fport := Sockets.GetPortNumber( addr );
IF addr IS Sockets.SocketAdrV4 THEN
fip.usedProtocol := IP.IPv4;
fip.ipv4Adr := addr(Sockets.SocketAdrV4).v4Adr;
ELSE
fip.usedProtocol := IP.IPv6;
FOR i := 0 TO 15 DO
fip.ipv6Adr[i] := addr(Sockets.SocketAdrV6).v6Adr[i]
END
END;
res := Ok;
ELSE
res := Error
END
END Receive;
PROCEDURE Close*;
BEGIN
Sockets.Close( socket )
END Close;
END Socket;
BEGIN
anyIP := IP.NilAdr;
END UDP.
(*
History:
27.10.2003 mvt Complete internal redesign for new interfaces of Network and IP.
22.11.2003 mvt Changed SocketPool to work with a hash table.
02.05.2005 eb Works with fragmented packets & IPv6 ready (WritePseudoHdr)
*)