1 /* Transport Security Layer (TLS)
\r
2 * Copyright (c) 2003 Carlos Guzmán Álvarez
\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
12 * The above copyright notice and this permission notice shall be included
\r
13 * in all copies or substantial portions of the Software.
\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
28 using System.Net.Sockets;
\r
30 namespace Mono.Security.Protocol.Tls
\r
32 public class TlsNetworkStream : Stream, IDisposable
\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
46 public override bool CanRead
\r
48 get { return canRead; }
\r
51 public override bool CanSeek
\r
53 get { return false; }
\r
56 public override bool CanWrite
\r
58 get { return canWrite; }
\r
61 public override long Length
\r
63 get { throw new NotSupportedException(); }
\r
66 public override long Position
\r
68 get { throw new NotSupportedException(); }
\r
69 set { throw new NotSupportedException(); }
\r
73 public bool DataAvailable
\r
79 throw new IOException();
\r
82 if (this.socket.Session.IsSecure)
\r
84 if ((this.socket.InputBuffer.Length - this.socket.InputBuffer.Position) > 0)
\r
90 // If there are bytes in the socket buffer return true
\r
92 return this.socket.Available != 0;
\r
100 ~TlsNetworkStream()
\r
102 this.Dispose(false);
\r
107 #region IDISPOSABLE
\r
109 void IDisposable.Dispose()
\r
111 this.Dispose(true);
\r
112 GC.SuppressFinalize(this);
\r
115 protected virtual void Dispose(bool disposing)
\r
121 if (this.socket != null)
\r
123 if (this.ownsSocket)
\r
127 this.socket.Shutdown(SocketShutdown.Both);
\r
132 this.socket.Close();
\r
136 this.ownsSocket = false;
\r
137 this.canRead = false;
\r
138 this.canWrite = false;
\r
139 this.socket = null;
\r
148 #region PROTECTED_PROPERTIES
\r
150 protected bool Readable
\r
152 get { return this.canRead; }
\r
153 set { this.canRead = value;}
\r
156 protected TlsSocket Socket
\r
158 get { return socket; }
\r
161 protected bool Writeable
\r
163 get { return this.canWrite; }
\r
164 set { this.canWrite = value; }
\r
169 #region CONSTRUCTORS
\r
171 public TlsNetworkStream(TlsSocket socket)
\r
172 : this(socket, FileAccess.ReadWrite, false)
\r
176 public TlsNetworkStream(TlsSocket socket, bool ownsSocket)
\r
177 : this(socket, FileAccess.ReadWrite, ownsSocket)
\r
181 public TlsNetworkStream(TlsSocket socket, FileAccess access)
\r
182 : this(socket, FileAccess.ReadWrite, false)
\r
186 public TlsNetworkStream(TlsSocket socket, FileAccess access, bool ownsSocket)
\r
188 if (socket == null)
\r
190 throw new ArgumentNullException("socket is a null reference.");
\r
192 if (!socket.Blocking)
\r
194 throw new IOException("socket is in a nonblocking state.");
\r
196 if (socket.SocketType != SocketType.Stream)
\r
198 throw new IOException("The SocketType property of socket is not SocketType.Stream.");
\r
200 if (!socket.Connected)
\r
202 throw new IOException("socket is not connected.");
\r
205 this.socket = socket;
\r
206 this.ownsSocket = ownsSocket;
\r
209 case FileAccess.Read:
\r
210 this.canRead = true;
\r
213 case FileAccess.ReadWrite:
\r
214 this.canRead = true;
\r
215 this.canWrite = true;
\r
218 case FileAccess.Write:
\r
219 this.canWrite = true;
\r
228 public override IAsyncResult BeginRead(
\r
232 AsyncCallback callback,
\r
235 throw new NotSupportedException();
\r
238 public override IAsyncResult BeginWrite(
\r
242 AsyncCallback callback,
\r
245 throw new NotSupportedException();
\r
248 public override int EndRead(IAsyncResult asyncResult)
\r
250 throw new NotSupportedException();
\r
253 public override void EndWrite(IAsyncResult asyncResult)
\r
255 throw new NotSupportedException();
\r
258 public override void Close()
\r
260 ((IDisposable)this).Dispose();
\r
263 public override void Flush()
\r
267 public override int Read(byte[] buffer, int offset, int size)
\r
269 if (buffer == null)
\r
271 throw new ArgumentNullException("buffer is a null reference.");
\r
275 throw new ArgumentOutOfRangeException("offset is less than 0.");
\r
277 if (offset > buffer.Length)
\r
279 throw new ArgumentOutOfRangeException("offset is greater than the length of buffer.");
\r
283 throw new ArgumentOutOfRangeException("size is less than 0.");
\r
285 if (size > (buffer.Length - offset))
\r
287 throw new ArgumentOutOfRangeException("size is less than the length of buffer minus the value of the offset parameter.");
\r
291 throw new ObjectDisposedException("The NetworkStream is closed.");
\r
293 if (!socket.Connected)
\r
295 throw new IOException("The underlying Socket is closed.");
\r
300 return socket.Receive(buffer, offset, size, SocketFlags.None);
\r
302 catch (TlsException ex)
\r
306 catch (Exception ex)
\r
308 throw new IOException("IO exception during read.", ex);
\r
312 public override long Seek(long offset, SeekOrigin origin)
\r
314 throw new NotSupportedException();
\r
317 public override void SetLength(long value)
\r
319 throw new NotSupportedException();
\r
322 public override void Write(byte[] buffer, int offset, int size)
\r
324 if (buffer == null)
\r
326 throw new ArgumentNullException("buffer is a null reference.");
\r
330 throw new ArgumentOutOfRangeException("offset is less than 0.");
\r
332 if (offset > buffer.Length)
\r
334 throw new ArgumentOutOfRangeException("offset is greater than the length of buffer.");
\r
338 throw new ArgumentOutOfRangeException("size is less than 0.");
\r
340 if (size > (buffer.Length - offset))
\r
342 throw new ArgumentOutOfRangeException("size is less than the length of buffer minus the value of the offset parameter.");
\r
346 throw new ObjectDisposedException("The NetworkStream is closed.");
\r
348 if (!socket.Connected)
\r
350 throw new IOException("The underlying Socket is closed.");
\r
355 socket.Send(buffer, offset, size, SocketFlags.None);
\r
357 catch (TlsException ex)
\r
361 catch (Exception ex)
\r
363 throw new IOException("IO exception during Write.", ex);
\r