TlsCipherSuite now inhers from TlsAbstractCipherSuite class, fixed problem with paddi...
[mono.git] / mcs / class / Mono.Security / Mono.Security.Protocol.Tls / TlsNetworkStream.cs
1 /* Transport Security Layer (TLS)\r
2  * Copyright (c) 2003 Carlos Guzmán Álvarez\r
3  * \r
4  * Permission is hereby granted, free of charge, to any person \r
5  * obtaining a copy of this software and associated documentation \r
6  * files (the "Software"), to deal in the Software without restriction, \r
7  * including without limitation the rights to use, copy, modify, merge, \r
8  * publish, distribute, sublicense, and/or sell copies of the Software, \r
9  * and to permit persons to whom the Software is furnished to do so, \r
10  * subject to the following conditions:\r
11  * \r
12  * The above copyright notice and this permission notice shall be included \r
13  * in all copies or substantial portions of the Software.\r
14  * \r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, \r
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES \r
17  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND \r
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT \r
19  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \r
20  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, \r
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \r
22  * DEALINGS IN THE SOFTWARE.\r
23  */\r
24 \r
25 using System;\r
26 using System.IO;\r
27 using System.Net;\r
28 using System.Net.Sockets;\r
29 \r
30 namespace Mono.Security.Protocol.Tls\r
31 {\r
32         public class TlsNetworkStream : Stream, IDisposable\r
33         {\r
34                 #region PROPERTIES\r
35 \r
36                 private TlsSocket       socket;\r
37                 private bool            ownsSocket;\r
38                 private bool            canRead;\r
39                 private bool            canWrite;\r
40                 private bool            disposed;\r
41 \r
42                 #endregion\r
43 \r
44                 #region PROPERTIES\r
45 \r
46                 public override bool CanRead\r
47                 {\r
48                         get { return canRead; }\r
49                 }\r
50 \r
51                 public override bool CanSeek\r
52                 {\r
53                         get { return false; }\r
54                 }\r
55 \r
56                 public override bool CanWrite\r
57                 {\r
58                         get { return canWrite; }\r
59                 }\r
60 \r
61                 public override long Length\r
62                 {\r
63                         get { throw new NotSupportedException(); }\r
64                 }\r
65 \r
66                 public override long Position\r
67                 {\r
68                         get { throw new NotSupportedException(); }\r
69                         set { throw new NotSupportedException(); }\r
70 \r
71                 }\r
72 \r
73                 public bool DataAvailable\r
74                 {\r
75                         get\r
76                         {\r
77                                 if (socket == null)\r
78                                 {\r
79                                         throw new IOException();\r
80                                 }\r
81 \r
82                                 if (this.socket.Session.IsSecure)\r
83                                 {\r
84                                         if ((this.socket.InputBuffer.Length - this.socket.InputBuffer.Position) > 0)\r
85                                         {\r
86                                                 return true;\r
87                                         }\r
88                                 }\r
89 \r
90                                 // If there are bytes in the socket buffer return true\r
91                                 // otherwise false\r
92                                 return this.socket.Available != 0;\r
93                         }\r
94                 }\r
95 \r
96                 #endregion\r
97 \r
98                 #region DESTRUCTOR\r
99 \r
100                 ~TlsNetworkStream()\r
101                 {\r
102                         this.Dispose(false);\r
103                 }\r
104 \r
105                 #endregion\r
106 \r
107         #region IDISPOSABLE\r
108 \r
109                 void IDisposable.Dispose()\r
110                 {\r
111                         this.Dispose(true);\r
112                         GC.SuppressFinalize(this);\r
113                 }\r
114 \r
115                 protected virtual void Dispose(bool disposing)\r
116                 {\r
117                         if (!disposed)\r
118                         {\r
119                                 if (disposing)\r
120                                 {\r
121                                         if (this.socket != null)\r
122                                         {\r
123                                                 if (this.ownsSocket)\r
124                                                 {\r
125                                                         try\r
126                                                         {\r
127                                                                 this.socket.Shutdown(SocketShutdown.Both);\r
128                                                         }\r
129                                                         catch{}\r
130                                                         finally\r
131                                                         {\r
132                                                                 this.socket.Close();\r
133                                                         }\r
134                                                 }\r
135                                         }\r
136                                         this.ownsSocket = false;\r
137                                         this.canRead    = false;\r
138                                         this.canWrite   = false;\r
139                                         this.socket             = null;\r
140                                 }\r
141 \r
142                                 disposed = true;\r
143                         }\r
144                 }\r
145 \r
146                 #endregion\r
147 \r
148                 #region PROTECTED_PROPERTIES\r
149 \r
150                 protected bool Readable \r
151                 {\r
152                         get { return this.canRead; }\r
153                         set { this.canRead = value;}\r
154                 }\r
155 \r
156                 protected TlsSocket Socket \r
157                 {\r
158                         get { return socket; }\r
159                 }\r
160 \r
161                 protected bool Writeable \r
162                 {\r
163                         get { return this.canWrite; }\r
164                         set { this.canWrite = value; }\r
165                 }\r
166 \r
167                 #endregion\r
168 \r
169                 #region CONSTRUCTORS\r
170                 \r
171                 public TlsNetworkStream(TlsSocket socket) \r
172                         : this(socket, FileAccess.ReadWrite, false)\r
173                 {\r
174                 }\r
175                 \r
176                 public TlsNetworkStream(TlsSocket socket, bool ownsSocket) \r
177                         : this(socket, FileAccess.ReadWrite, ownsSocket)\r
178                 {\r
179                 }\r
180                 \r
181                 public TlsNetworkStream(TlsSocket socket, FileAccess access)\r
182                         : this(socket, FileAccess.ReadWrite, false)\r
183                 {\r
184                 }\r
185                 \r
186                 public TlsNetworkStream(TlsSocket socket, FileAccess access, bool ownsSocket)\r
187                 {\r
188                         if (socket == null)\r
189                         {\r
190                                 throw new ArgumentNullException("socket is a null reference.");\r
191                         }\r
192                         if (!socket.Blocking)\r
193                         {\r
194                                 throw new IOException("socket is in a nonblocking state.");\r
195                         }\r
196                         if (socket.SocketType != SocketType.Stream)\r
197                         {\r
198                                 throw new IOException("The SocketType property of socket is not SocketType.Stream.");\r
199                         }\r
200                         if (!socket.Connected)\r
201                         {\r
202                                 throw new IOException("socket is not connected.");\r
203                         }\r
204 \r
205                         this.socket             = socket;\r
206                         this.ownsSocket = ownsSocket;\r
207                         switch (access)\r
208                         {\r
209                                 case FileAccess.Read:\r
210                                         this.canRead    = true;\r
211                                         break;\r
212 \r
213                                 case FileAccess.ReadWrite:\r
214                                         this.canRead    = true;\r
215                                         this.canWrite   = true;\r
216                                         break;\r
217 \r
218                                 case FileAccess.Write:\r
219                                         this.canWrite   = true;\r
220                                         break;\r
221                         }\r
222                 }\r
223 \r
224                 #endregion\r
225 \r
226                 #region METHODS\r
227 \r
228                 public override IAsyncResult BeginRead(\r
229                         byte[] buffer,\r
230                         int offset,\r
231                         int count,\r
232                         AsyncCallback callback,\r
233                         object state)\r
234                 {\r
235                         throw new NotSupportedException();\r
236                 }\r
237 \r
238                 public override IAsyncResult BeginWrite(\r
239                         byte[] buffer,\r
240                         int offset,\r
241                         int count,\r
242                         AsyncCallback callback,\r
243                         object state)\r
244                 {\r
245                         throw new NotSupportedException();\r
246                 }\r
247 \r
248                 public override int EndRead(IAsyncResult asyncResult)\r
249                 {\r
250                         throw new NotSupportedException();\r
251                 }\r
252 \r
253                 public override void EndWrite(IAsyncResult asyncResult)\r
254                 {\r
255                         throw new NotSupportedException();\r
256                 }\r
257 \r
258                 public override void Close()\r
259                 {\r
260                         ((IDisposable)this).Dispose();\r
261                 }\r
262 \r
263                 public override void Flush()\r
264                 {\r
265                 }\r
266 \r
267                 public override int Read(byte[] buffer, int offset, int size)\r
268                 {\r
269                         if (buffer == null)\r
270                         {\r
271                                 throw new ArgumentNullException("buffer is a null reference.");\r
272                         }\r
273                         if (offset < 0)\r
274                         {\r
275                                 throw new ArgumentOutOfRangeException("offset is less than 0.");\r
276                         }\r
277                         if (offset > buffer.Length)\r
278                         {\r
279                                 throw new ArgumentOutOfRangeException("offset is greater than the length of buffer.");\r
280                         }\r
281                         if (size < 0)\r
282                         {\r
283                                 throw new ArgumentOutOfRangeException("size is less than 0.");\r
284                         }\r
285                         if (size > (buffer.Length - offset))\r
286                         {\r
287                                 throw new ArgumentOutOfRangeException("size is less than the length of buffer minus the value of the offset parameter.");\r
288                         }\r
289                         if (disposed)\r
290                         {\r
291                                 throw new ObjectDisposedException("The NetworkStream is closed.");\r
292                         }\r
293                         if (!socket.Connected)\r
294                         {\r
295                                 throw new IOException("The underlying Socket is closed.");\r
296                         }\r
297         \r
298                         try\r
299                         {\r
300                                 return socket.Receive(buffer, offset, size, SocketFlags.None);\r
301                         }\r
302                         catch (TlsException ex)\r
303                         {\r
304                                 throw ex;\r
305                         }\r
306                         catch (Exception ex)\r
307                         {\r
308                                 throw new IOException("IO exception during read.", ex);\r
309                         }\r
310                 }\r
311 \r
312                 public override long Seek(long offset, SeekOrigin origin)\r
313                 {\r
314                         throw new NotSupportedException();\r
315                 }\r
316                 \r
317                 public override void SetLength(long value)\r
318                 {\r
319                         throw new NotSupportedException();\r
320                 }\r
321 \r
322                 public override void Write(byte[] buffer, int offset, int size)\r
323                 {\r
324                         if (buffer == null)\r
325                         {\r
326                                 throw new ArgumentNullException("buffer is a null reference.");\r
327                         }\r
328                         if (offset < 0)\r
329                         {\r
330                                 throw new ArgumentOutOfRangeException("offset is less than 0.");\r
331                         }\r
332                         if (offset > buffer.Length)\r
333                         {\r
334                                 throw new ArgumentOutOfRangeException("offset is greater than the length of buffer.");\r
335                         }\r
336                         if (size < 0)\r
337                         {\r
338                                 throw new ArgumentOutOfRangeException("size is less than 0.");\r
339                         }\r
340                         if (size > (buffer.Length - offset))\r
341                         {\r
342                                 throw new ArgumentOutOfRangeException("size is less than the length of buffer minus the value of the offset parameter.");\r
343                         }\r
344                         if (disposed)\r
345                         {\r
346                                 throw new ObjectDisposedException("The NetworkStream is closed.");\r
347                         }\r
348                         if (!socket.Connected)\r
349                         {\r
350                                 throw new IOException("The underlying Socket is closed.");\r
351                         }\r
352 \r
353                         try\r
354                         {\r
355                                 socket.Send(buffer, offset, size, SocketFlags.None);\r
356                         }\r
357                         catch (TlsException ex)\r
358                         {\r
359                                 throw ex;\r
360                         }\r
361                         catch (Exception ex)\r
362                         {\r
363                                 throw new IOException("IO exception during Write.", ex);\r
364                         }\r
365                 }\r
366 \r
367                 #endregion\r
368         }\r
369 }\r