2 // System.Net.Sockets.NetworkStream.cs
5 // Miguel de Icaza (miguel@ximian.com)
6 // Sridhar Kulkarni <sridharkulkarni@gmail.com>
8 // (C) 2002 Ximian, Inc. http://www.ximian.com
9 // Copyright (C) 2002-2006 Novell, Inc. http://www.novell.com
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Runtime.InteropServices;
37 using System.Threading;
40 namespace System.Net.Sockets
42 public class NetworkStream : Stream, IDisposable {
46 bool readable, writeable;
47 bool disposed = false;
49 public NetworkStream (Socket socket)
50 : this (socket, FileAccess.ReadWrite, false)
54 public NetworkStream (Socket socket, bool owns_socket)
55 : this (socket, FileAccess.ReadWrite, owns_socket)
59 public NetworkStream (Socket socket, FileAccess access)
60 : this (socket, access, false)
64 public NetworkStream (Socket socket, FileAccess access, bool owns_socket)
67 throw new ArgumentNullException ("socket is null");
68 if (socket.SocketType != SocketType.Stream)
69 throw new ArgumentException ("Socket is not of type Stream", "socket");
70 if (!socket.Connected)
71 throw new IOException ("Not connected");
73 throw new IOException ("Operation not allowed on a non-blocking socket.");
76 this.owns_socket = owns_socket;
83 public override bool CanRead {
85 return access == FileAccess.ReadWrite || access == FileAccess.Read;
89 public override bool CanSeek {
91 // network sockets cant seek.
96 public override bool CanTimeout
103 public override bool CanWrite {
105 return access == FileAccess.ReadWrite || access == FileAccess.Write;
109 public virtual bool DataAvailable {
112 return socket.Available > 0;
116 public override long Length {
118 // Network sockets always throw an exception
119 throw new NotSupportedException ();
123 public override long Position {
125 // Network sockets always throw an exception
126 throw new NotSupportedException ();
130 // Network sockets always throw an exception
131 throw new NotSupportedException ();
135 protected bool Readable {
147 [MonoNotSupported ("Not supported since Socket.ReceiveTimeout is not supported")]
149 public override int ReadTimeout
152 int r = socket.ReceiveTimeout;
153 return (r <= 0) ? Timeout.Infinite : r;
156 if (value <= 0 && value != Timeout.Infinite) {
157 throw new ArgumentOutOfRangeException ("value", "The value specified is less than or equal to zero and is not Infinite.");
160 socket.ReceiveTimeout = value;
165 protected Socket Socket {
171 protected bool Writeable {
183 [MonoNotSupported ("Not supported since Socket.SendTimeout is not supported")]
185 public override int WriteTimeout
188 int r = socket.SendTimeout;
189 return (r <= 0) ? Timeout.Infinite : r;
192 if (value <= 0 && value != Timeout.Infinite) {
193 throw new ArgumentOutOfRangeException ("value", "The value specified is less than or equal to zero and is not Infinite");
196 socket.SendTimeout = value;
201 public override IAsyncResult BeginRead (byte [] buffer, int offset, int size,
202 AsyncCallback callback, object state)
208 throw new ArgumentNullException ("buffer is null");
209 int len = buffer.Length;
210 if(offset<0 || offset>len) {
211 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
213 if(size<0 || offset+size>len) {
214 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
220 throw new IOException("Connection closed");
224 retval = s.BeginReceive (buffer, offset, size, 0, callback, state);
225 } catch (Exception e) {
226 throw new IOException ("BeginReceive failure", e);
232 public override IAsyncResult BeginWrite (byte [] buffer, int offset, int size,
233 AsyncCallback callback, object state)
239 throw new ArgumentNullException ("buffer is null");
241 int len = buffer.Length;
242 if(offset<0 || offset>len) {
243 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
245 if(size<0 || offset+size>len) {
246 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
252 throw new IOException("Connection closed");
256 retval = s.BeginSend (buffer, offset, size, 0, callback, state);
258 throw new IOException ("BeginWrite failure");
271 public void Close (int timeout)
274 throw new ArgumentOutOfRangeException ("timeout", "timeout is less than -1");
277 System.Timers.Timer close_timer = new System.Timers.Timer ();
278 close_timer.Elapsed += new ElapsedEventHandler (OnTimeoutClose);
279 /* NB timeout is in milliseconds here, cf
280 * seconds in Socket.Close(int)
282 close_timer.Interval = timeout;
283 close_timer.AutoReset = false;
284 close_timer.Enabled = true;
287 private void OnTimeoutClose (object source, ElapsedEventArgs e)
293 protected override void Dispose (bool disposing)
308 GC.SuppressFinalize (this);
311 public override int EndRead (IAsyncResult ar)
317 throw new ArgumentNullException ("async result is null");
322 throw new IOException("Connection closed");
326 res = s.EndReceive (ar);
327 } catch (Exception e) {
328 throw new IOException ("EndRead failure", e);
333 public override void EndWrite (IAsyncResult ar)
337 throw new ArgumentNullException ("async result is null");
342 throw new IOException("Connection closed");
347 } catch (Exception e) {
348 throw new IOException ("EndWrite failure", e);
352 public override void Flush ()
354 // network streams are non-buffered, this is a no-op
357 public override int Read ([In,Out] byte [] buffer, int offset, int size)
363 throw new ArgumentNullException ("buffer is null");
364 if(offset<0 || offset>buffer.Length) {
365 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
367 if(size < 0 || offset+size>buffer.Length) {
368 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
374 throw new IOException("Connection closed");
378 res = s.Receive (buffer, offset, size, 0);
379 } catch (Exception e) {
380 throw new IOException ("Read failure", e);
386 public override long Seek (long offset, SeekOrigin origin)
388 // NetworkStream objects do not support seeking.
390 throw new NotSupportedException ();
393 public override void SetLength (long value)
395 // NetworkStream objects do not support SetLength
397 throw new NotSupportedException ();
400 public override void Write (byte [] buffer, int offset, int size)
404 throw new ArgumentNullException ("buffer");
406 if (offset < 0 || offset > buffer.Length)
407 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
409 if (size < 0 || size > buffer.Length - offset)
410 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
415 throw new IOException("Connection closed");
420 while (size - count > 0) {
421 count += s.Send (buffer, offset + count, size - count, 0);
423 } catch (Exception e) {
424 throw new IOException ("Write failure", e);
428 private void CheckDisposed ()
431 throw new ObjectDisposedException (GetType().FullName);
435 public void ChangeToSSLSocket()
437 socket.ChangeToSSL();