2003-01-04 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System / System.Net.Sockets / UdpClient.cs
1 //\r
2 // System.Net.Sockets.UdpClient.cs\r
3 //\r
4 // Author:\r
5 //    Gonzalo Paniagua Javier <gonzalo@ximian.com>\r
6 //\r
7 // Copyright (C) Ximian, Inc. http://www.ximian.com\r
8 //\r
9 \r
10 using System;\r
11 using System.Net;\r
12 \r
13 namespace System.Net.Sockets\r
14 {\r
15         public class UdpClient : IDisposable\r
16         {\r
17                 private bool disposed = false;\r
18                 private bool active = false;\r
19                 private Socket socket;\r
20                 private IPEndPoint localEP;\r
21                 \r
22 #region Constructors\r
23                 public UdpClient ()\r
24                 {\r
25                         localEP = new IPEndPoint (IPAddress.Any, 0);\r
26                         InitSocket ();\r
27                 }\r
28 \r
29                 public UdpClient (int port)\r
30                 {\r
31                         // IPEndPoint throws ArgumentException when port is invalid\r
32                         localEP = new IPEndPoint (IPAddress.Any, port);\r
33                         InitSocket ();\r
34                 }\r
35 \r
36                 public UdpClient (IPEndPoint localEP)\r
37                 {\r
38                         if (localEP == null)\r
39                                 throw new ArgumentNullException ("IPEndPoint cannot be null");\r
40 \r
41                         this.localEP = localEP;\r
42                         InitSocket ();\r
43                 }\r
44 \r
45                 public UdpClient (string hostname, int port)\r
46                 {\r
47                         if (hostname == null)\r
48                                 throw new ArgumentNullException ("hostname cannot be null");\r
49 \r
50                         if (port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort)\r
51                                 throw new ArgumentException ("Invalid port");\r
52 \r
53                         localEP = new IPEndPoint (IPAddress.Any, 0);\r
54                         InitSocket ();\r
55                         Connect (hostname, port);\r
56                 }\r
57 \r
58                 private void InitSocket ()\r
59                 {\r
60                         active = false;\r
61                         socket = new Socket (AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);\r
62                         socket.Bind (localEP);\r
63                 }\r
64 \r
65 #endregion // Constructors\r
66 #region Public methods\r
67 #region Close\r
68                 public void Close ()\r
69                 {\r
70                         ((IDisposable) this).Dispose ();        \r
71                 }\r
72 #endregion\r
73 #region Connect\r
74                 public void Connect (IPEndPoint endPoint)\r
75                 {\r
76                         try {\r
77                                 socket.Connect (endPoint);\r
78                                 active = true;\r
79                         } finally {\r
80                                 CheckDisposed ();\r
81                         }\r
82                 }\r
83 \r
84                 public void Connect (IPAddress addr, int port)\r
85                 {\r
86                         Connect (new IPEndPoint (addr, port));\r
87                 }\r
88 \r
89                 public void Connect (string hostname, int port)\r
90                 {\r
91                         Connect (new IPEndPoint (Dns.Resolve (hostname).AddressList [0], port));\r
92                 }\r
93 #endregion\r
94 #region Multicast methods\r
95                 public void DropMulticastGroup (IPAddress multicastAddr)\r
96                 {\r
97                         try {\r
98                                 socket.SetSocketOption (SocketOptionLevel.IP, SocketOptionName.DropMembership,\r
99                                                         new MulticastOption (multicastAddr));\r
100                         } finally {\r
101                                 CheckDisposed ();\r
102                         }\r
103                 }\r
104 \r
105                 public void JoinMulticastGroup (IPAddress multicastAddr)\r
106                 {\r
107                         try {\r
108                                 socket.SetSocketOption (SocketOptionLevel.IP, SocketOptionName.AddMembership,\r
109                                                         new MulticastOption (multicastAddr));\r
110                         } finally {\r
111                                 CheckDisposed ();\r
112                         }\r
113                 }\r
114 \r
115                 public void JoinMulticastGroup (IPAddress multicastAddr, int timeToLive)\r
116                 {\r
117                         JoinMulticastGroup (multicastAddr);\r
118                         try {\r
119                                 socket.SetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive,\r
120                                                         timeToLive);\r
121                         } finally {\r
122                                 CheckDisposed ();\r
123                         }\r
124                 }\r
125 #endregion\r
126 #region Data I/O\r
127                 public byte [] Receive (ref IPEndPoint remoteEP)\r
128                 {\r
129                         try {\r
130                                 // Length of the array for receiving data??\r
131                                 byte [] recBuffer;\r
132                                 int available = socket.Available;\r
133                                 if (available < 512)\r
134                                         available = 512;\r
135 \r
136                                 recBuffer = new byte [available];\r
137                                 EndPoint endPoint = new IPEndPoint (IPAddress.Any, 0);\r
138                                 int dataRead = socket.ReceiveFrom (recBuffer, ref endPoint);\r
139                                 if (dataRead < recBuffer.Length)\r
140                                         recBuffer = CutArray (recBuffer, dataRead);\r
141 \r
142                                 remoteEP = (IPEndPoint) endPoint;\r
143                                 return recBuffer;\r
144                         } finally {\r
145                                 CheckDisposed ();\r
146                         }\r
147                 }\r
148 \r
149                 public int Send (byte [] dgram, int bytes)\r
150                 {\r
151                         try {\r
152                                 if (dgram == null)\r
153                                         throw new ArgumentNullException ("dgram is null");\r
154 \r
155                                 byte [] realDgram;\r
156                                 if (dgram.Length <= bytes)\r
157                                         realDgram = dgram;\r
158                                 else\r
159                                         realDgram = CutArray (dgram, (bytes >= dgram.Length) ? bytes : dgram.Length);\r
160 \r
161                                 // the socket should be connected already, so I use Send instead of SendTo\r
162                                 return socket.Send (realDgram);\r
163                         } finally {\r
164                                 CheckDisposed ();\r
165                         }\r
166                 }\r
167 \r
168                 public int Send (byte [] dgram, int bytes, IPEndPoint endPoint)\r
169                 {\r
170                         try {\r
171                                 if (dgram == null)\r
172                                         throw new ArgumentNullException ("dgram is null");\r
173 \r
174                                 byte [] realDgram;\r
175                                 if (dgram.Length <= bytes)\r
176                                         realDgram = dgram;\r
177                                 else\r
178                                         realDgram = CutArray (dgram, (bytes >= dgram.Length) ? bytes : dgram.Length);\r
179 \r
180                                 // the socket should not be connected\r
181                                 return socket.SendTo (realDgram, endPoint);\r
182                         } finally {\r
183                                 CheckDisposed ();\r
184                         }\r
185                 }\r
186 \r
187                 public int Send (byte [] dgram, int bytes, string hostname, int port)\r
188                 {\r
189                         return Send (dgram, bytes, \r
190                                      new IPEndPoint (Dns.Resolve (hostname).AddressList [0], port));\r
191                 }\r
192 \r
193                 private byte [] CutArray (byte [] orig, int length)\r
194                 {\r
195                         byte [] newArray = new byte [length];\r
196                         Array.Copy (orig, 0, newArray, 0, length);\r
197 \r
198                         return newArray;\r
199                 }\r
200 #endregion\r
201 #region Properties\r
202                 protected bool Active {\r
203                         get { return active; }\r
204                         set { active = value; }\r
205                 }\r
206 \r
207                 protected Socket Client {\r
208                         get { return socket; }\r
209                         set { socket = value; }\r
210                 }\r
211 #endregion\r
212 \r
213 /* \r
214 // commented because in the ms.net implementation these are not overriden. -- LP\r
215 #region Overrides\r
216                 public override bool Equals (object obj)\r
217                 {\r
218                         if (obj is UdpClient)\r
219                                 return (((UdpClient) obj).socket  == socket &&\r
220                                         ((UdpClient) obj).localEP == localEP);\r
221 \r
222                         return false;\r
223                 }\r
224 \r
225                 public override int GetHashCode ()\r
226                 {\r
227                         return (socket.GetHashCode () + localEP.GetHashCode () + (active ? 1 : 0));\r
228                 }\r
229 #endregion\r
230 */\r
231 \r
232 #region Disposing\r
233                 void IDisposable.Dispose ()\r
234                 {\r
235                         Dispose (true);\r
236                         GC.SuppressFinalize (this);\r
237                 }\r
238 \r
239                 void Dispose (bool disposing)\r
240                 {\r
241                         if (disposed) \r
242                                 return;\r
243                         disposed = true;\r
244                         if (disposing) {\r
245                                 // release managed resources\r
246                                 localEP = null;\r
247                         }                       \r
248                         // release unmanaged resources\r
249                         Socket s = socket;\r
250                         socket = null;\r
251                         if (s != null)\r
252                                 s.Close ();\r
253                 }\r
254                 \r
255                 ~UdpClient ()\r
256                 {\r
257                         Dispose (false);\r
258                 }\r
259                 \r
260                 private void CheckDisposed ()\r
261                 {\r
262                         if (disposed)\r
263                                 throw new ObjectDisposedException (GetType().FullName);\r
264                 }               \r
265 #endregion\r
266 #endregion\r
267         }\r
268 }\r
269 \r