Unix.UDP.Mod 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. (* Aos, Copyright 2001, Pieter Muller, ETH Zurich *)
  2. MODULE UDP; (** AUTHOR "pjm, mvt, G.F."; PURPOSE "UDP protocol"; *)
  3. IMPORT IP, Sockets, Unix;
  4. CONST
  5. (** Error codes *)
  6. Ok* = 0; PortInUse* = 3501; Timeout* = 3502; BufferOverflow* = 3503; NoInterface* = 3504;
  7. Closed* = 3505; Error* = 9999;
  8. NilPort* = 0; anyport = 0;
  9. UDPHdrLen = 8;
  10. MaxUDPDataLen = 10000H - UDPHdrLen;
  11. VAR
  12. anyIP: IP.Adr;
  13. TYPE
  14. (** Socket. Stores the state of a UDP communication endpoint. *)
  15. Socket* = OBJECT
  16. VAR
  17. socket: LONGINT;
  18. lport: LONGINT; (* local port *)
  19. open: BOOLEAN;
  20. (** Constructor *)
  21. PROCEDURE & Open*( lport: LONGINT; VAR res: WORD );
  22. VAR laddr: Sockets.SocketAdr;
  23. BEGIN
  24. ASSERT( (lport >= 0) & (lport < 10000H) );
  25. SELF.lport := lport; res := Error;
  26. socket := Sockets.Socket( Unix.AFINET, Unix.SockDGram, Unix.IpProtoUDP );
  27. IF socket # 0 THEN
  28. IF lport # anyport THEN
  29. (* server *)
  30. laddr := Sockets.NewSocketAdr( anyIP, lport );
  31. IF Sockets.Bind( socket, laddr ) THEN
  32. res := Ok; open := TRUE
  33. ELSE
  34. Sockets.Close( socket )
  35. END
  36. ELSE
  37. (* client *)
  38. res := Ok; open := TRUE
  39. END
  40. END
  41. END Open;
  42. (** Send a UDP datagram to the foreign address specified by "fip" and "fport".
  43. The data is in "data[ofs..ofs+len-1]". In case of concurrent sends the datagrams are serialized.
  44. *)
  45. PROCEDURE Send*( fip: IP.Adr;
  46. fport: LONGINT;
  47. CONST data: ARRAY OF CHAR; ofs, len: LONGINT;
  48. VAR res: WORD );
  49. VAR addr: Sockets.SocketAdr;
  50. BEGIN {EXCLUSIVE}
  51. ASSERT( (fport >= 0) & (fport < 10000H) );
  52. ASSERT( (len >= 0) & (len <= MaxUDPDataLen) );
  53. addr := Sockets.NewSocketAdr( fip, fport );
  54. IF Sockets.SendTo( socket, addr, data, ofs, len ) THEN res := Ok ELSE res := Error END
  55. END Send;
  56. (** Send a broadcast UDP datagram via interface "int" to port "lport". Normally only used by DHCP.
  57. The data is in "data[ofs..ofs+len-1]". In case of concurrent sends the datagrams are serialized.
  58. *)
  59. PROCEDURE SendBroadcast*( int: IP.Interface; fport: LONGINT;
  60. CONST data: ARRAY OF CHAR; ofs, len: LONGINT );
  61. BEGIN (*{EXCLUSIVE}*)
  62. ASSERT( (fport >= 0) & (fport < 10000H) ); ASSERT( (len >= 0) & (len <= MaxUDPDataLen) );
  63. HALT( 99 ) (* not implemented yet *)
  64. END SendBroadcast;
  65. (** Receive a UDP datagram. If none is available, wait up to the specified timeout for one to arrive.
  66. "data[ofs..ofs+size-1]" is the data buffer to hold the returned datagram.
  67. "ms" is a wait timeout value in milliseconds, 0 means "don't wait", -1 means "infinite wait".
  68. On return, "fip" and "fport" hold the foreign address and port.
  69. "len" returns the actual datagram size and "data[ofs..ofs+len-1]" returns the data.
  70. "res" returns "Timeout" in case of a timeout and "BufferOverflow" if the received datagram was
  71. too big.
  72. *)
  73. PROCEDURE Receive*( VAR data: ARRAY OF CHAR; ofs, size, ms: LONGINT;
  74. VAR fip: IP.Adr; VAR fport, len: LONGINT; VAR res: WORD );
  75. VAR
  76. addr: Sockets.SocketAdr; i: LONGINT;
  77. BEGIN {EXCLUSIVE}
  78. IF ~open THEN res := Closed; RETURN END;
  79. IF (ms >= 0) & ~Sockets.AwaitPacket( socket, ms ) THEN
  80. res := Timeout; RETURN
  81. END;
  82. IF Sockets.RecvFrom( socket, addr, data, ofs, len ) THEN
  83. fport := Sockets.GetPortNumber( addr );
  84. IF addr IS Sockets.SocketAdrV4 THEN
  85. fip.usedProtocol := IP.IPv4;
  86. fip.ipv4Adr := addr(Sockets.SocketAdrV4).v4Adr;
  87. ELSE
  88. fip.usedProtocol := IP.IPv6;
  89. FOR i := 0 TO 15 DO
  90. fip.ipv6Adr[i] := addr(Sockets.SocketAdrV6).v6Adr[i]
  91. END
  92. END;
  93. res := Ok;
  94. ELSE
  95. res := Error
  96. END
  97. END Receive;
  98. (** Close the Socket, freeing its address for re-use. *)
  99. PROCEDURE Close*;
  100. BEGIN
  101. Sockets.Close( socket ); open := FALSE
  102. END Close;
  103. END Socket;
  104. BEGIN
  105. anyIP := IP.NilAdr;
  106. END UDP.