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;
35 #if NET_2_0 && !NET_2_1
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.
97 public override bool CanTimeout
105 public override bool CanWrite {
107 return access == FileAccess.ReadWrite || access == FileAccess.Write;
111 public virtual bool DataAvailable {
114 return socket.Available > 0;
118 public override long Length {
120 // Network sockets always throw an exception
121 throw new NotSupportedException ();
125 public override long Position {
127 // Network sockets always throw an exception
128 throw new NotSupportedException ();
132 // Network sockets always throw an exception
133 throw new NotSupportedException ();
137 protected bool Readable {
147 #if NET_2_0 && !NET_2_1
149 [MonoNotSupported ("Not supported since Socket.ReceiveTimeout is not supported")]
151 public override int ReadTimeout
154 return(socket.ReceiveTimeout);
157 if (value <= 0 && value != Timeout.Infinite) {
158 throw new ArgumentOutOfRangeException ("value", "The value specified is less than or equal to zero and is not Infinite.");
161 socket.ReceiveTimeout = value;
166 protected Socket Socket {
172 protected bool Writeable {
182 #if NET_2_0 && !NET_2_1
184 [MonoNotSupported ("Not supported since Socket.SendTimeout is not supported")]
186 public override int WriteTimeout
189 return(socket.SendTimeout);
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");
270 public override void Close ()
272 ((IDisposable) this).Dispose ();
276 #if NET_2_0 && !NET_2_1
277 public void Close (int timeout)
280 throw new ArgumentOutOfRangeException ("timeout", "timeout is less than -1");
283 System.Timers.Timer close_timer = new System.Timers.Timer ();
284 close_timer.Elapsed += new ElapsedEventHandler (OnTimeoutClose);
285 /* NB timeout is in milliseconds here, cf
286 * seconds in Socket.Close(int)
288 close_timer.Interval = timeout;
289 close_timer.AutoReset = false;
290 close_timer.Enabled = true;
293 private void OnTimeoutClose (object source, ElapsedEventArgs e)
305 void Dispose (bool disposing)
320 GC.SuppressFinalize (this);
323 public override int EndRead (IAsyncResult ar)
329 throw new ArgumentNullException ("async result is null");
334 throw new IOException("Connection closed");
338 res = s.EndReceive (ar);
339 } catch (Exception e) {
340 throw new IOException ("EndRead failure", e);
345 public override void EndWrite (IAsyncResult ar)
349 throw new ArgumentNullException ("async result is null");
354 throw new IOException("Connection closed");
359 } catch (Exception e) {
360 throw new IOException ("EndWrite failure", e);
364 public override void Flush ()
366 // network streams are non-buffered, this is a no-op
370 void IDisposable.Dispose ()
376 public override int Read ([In,Out] byte [] buffer, int offset, int size)
382 throw new ArgumentNullException ("buffer is null");
383 if(offset<0 || offset>buffer.Length) {
384 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
386 if(size < 0 || offset+size>buffer.Length) {
387 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
393 throw new IOException("Connection closed");
397 res = s.Receive (buffer, offset, size, 0);
398 } catch (Exception e) {
399 throw new IOException ("Read failure", e);
405 public override long Seek (long offset, SeekOrigin origin)
407 // NetworkStream objects do not support seeking.
409 throw new NotSupportedException ();
412 public override void SetLength (long value)
414 // NetworkStream objects do not support SetLength
416 throw new NotSupportedException ();
419 public override void Write (byte [] buffer, int offset, int size)
423 throw new ArgumentNullException ("buffer");
425 if (offset < 0 || offset > buffer.Length)
426 throw new ArgumentOutOfRangeException("offset exceeds the size of buffer");
428 if (size < 0 || size > buffer.Length - offset)
429 throw new ArgumentOutOfRangeException("offset+size exceeds the size of buffer");
434 throw new IOException("Connection closed");
439 while (size - count > 0) {
440 count += s.Send (buffer, offset + count, size - count, 0);
442 } catch (Exception e) {
443 throw new IOException ("Write failure", e);
447 private void CheckDisposed ()
450 throw new ObjectDisposedException (GetType().FullName);
454 public void ChangeToSSLSocket()
456 socket.ChangeToSSL();