[Mono-bugs] [Bug 31877][Nor] New - Bug in bounds checking on NetworkStream buffer
bugzilla-daemon@rocky.ximian.com
bugzilla-daemon@rocky.ximian.com
7 Oct 2002 16:11:29 -0000
Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.
Changed by timothyjmills@hotmail.com.
http://bugzilla.ximian.com/show_bug.cgi?id=31877
--- shadow/31877 Mon Oct 7 12:11:29 2002
+++ shadow/31877.tmp.2324 Mon Oct 7 12:11:29 2002
@@ -0,0 +1,1483 @@
+Bug#: 31877
+Product: Mono/Class Libraries
+Version: unspecified
+OS: Red Hat 7.2
+OS Details:
+Status: NEW
+Resolution:
+Severity:
+Priority: Normal
+Component: System
+AssignedTo: mono-bugs@ximian.com
+ReportedBy: timothyjmills@hotmail.com
+QAContact: mono-bugs@ximian.com
+TargetMilestone: ---
+URL:
+Cc:
+Summary: Bug in bounds checking on NetworkStream buffer
+
+Description of Problem:
+Bug in bounds checking on NetworkStream buffer in BeginRead and BeginWrite.
+
+
+Steps to reproduce the problem:
+1. byte[] buffer = new buffer[1024];
+2. NetworkStream stream = new NetworkStream(connectedSocket);
+3. stream.BeginRead(buffer, 512, 512);
+
+Actual Results:
+ArgumentsException
+
+Expected Results:
+success
+
+
+How often does this happen?
+Always
+
+Additional Information:
+
+To fix:
+
+mcs-0.16/class/System/System.Net.Sockets/NetworkStream.cs
+//
+// System.Net.Sockets.NetworkStream.cs
+//
+// Author:
+// Miguel de Icaza (miguel@ximian.com)
+//
+// (C) 2002 Ximian, Inc. http://www.ximian.com
+//
+
+using System.IO;
+
+namespace System.Net.Sockets
+{
+ public class NetworkStream : Stream, IDisposable {
+ FileAccess access;
+ Socket socket;
+ bool owns_socket;
+ bool readable, writeable;
+ bool disposed = false;
+
+ public NetworkStream (Socket socket)
+ : this (socket, FileAccess.ReadWrite, false)
+ {
+ }
+
+ public NetworkStream (Socket socket, bool owns_socket)
+ : this (socket, FileAccess.ReadWrite, owns_socket)
+ {
+ }
+
+ public NetworkStream (Socket socket, FileAccess access)
+ : this (socket, access, false)
+ {
+ }
+
+ public NetworkStream (Socket socket, FileAccess access,
+bool owns_socket)
+ {
+ if (socket == null)
+ throw new ArgumentNullException
+("Parameter name: socket");
+ if (!socket.Connected)
+ throw new ArgumentException ("Not
+connected", "socket");
+ if (socket.SocketType != SocketType.Stream)
+ throw new ArgumentException ("Socket is
+not of type Stream", "socket");
+ if (!socket.Blocking)
+ throw new IOException ();
+
+ this.socket = socket;
+ this.owns_socket = owns_socket;
+ this.access = access;
+
+ readable = CanRead;
+ writeable = CanWrite;
+ }
+
+ public override bool CanRead {
+ get {
+ return access == FileAccess.ReadWrite ||
+access == FileAccess.Read;
+ }
+ }
+
+ public override bool CanSeek {
+ get {
+ // network sockets cant seek.
+ return false;
+ }
+ }
+
+ public override bool CanWrite {
+ get {
+ return access == FileAccess.ReadWrite ||
+access == FileAccess.Write;
+ }
+ }
+
+ public virtual bool DataAvailable {
+ get {
+ try {
+ return socket.Available > 0;
+ } finally {
+ CheckDisposed ();
+ }
+ }
+ }
+
+ public override long Length {
+ get {
+ // Network sockets always throw an
+exception
+ throw new NotSupportedException ();
+ }
+ }
+
+ public override long Position {
+ get {
+ // Network sockets always throw an
+exception
+ throw new NotSupportedException ();
+ }
+
+ set {
+ // Network sockets always throw an
+exception
+ throw new NotSupportedException ();
+ }
+ }
+
+ protected bool Readable {
+ get {
+ return readable;
+ }
+
+ set {
+ readable = value;
+ }
+ }
+
+ protected Socket Socket {
+ get {
+ return socket;
+ }
+ }
+
+ protected bool Writeable {
+ get {
+ return writeable;
+ }
+
+ set {
+ writeable = value;
+ }
+ }
+
+ public override IAsyncResult BeginRead (byte [] buffer,
+int offset, int size,
+ AsyncCallback
+callback, object state)
+ {
+ try {
+ IAsyncResult retval;
+
+ if (buffer == null)
+ throw new ArgumentNullException
+("Parameter name: buffer");
+ int len = buffer.Length;
+ if ((offset < 0) || (offset >= len))
+ throw new
+ArgumentOutOfRangeException ("Parameter name: offset");
+ if ((offset + size < 0) || (offset + size
+> len))
+ throw new
+ArgumentOutOfRangeException ("Paramter name: size");
+
+ try {
+ retval = socket.BeginReceive
+(buffer, offset, size, 0, callback, state);
+ } catch {
+ throw new IOException
+("BeginReceive failure");
+ }
+
+ return retval;
+ } finally {
+ CheckDisposed ();
+
+ }
+ }
+
+ public override IAsyncResult BeginWrite (byte [] buffer,
+int offset, int size,
+ AsyncCallback
+callback, object state)
+ {
+ try {
+ IAsyncResult retval;
+
+ if (buffer == null)
+ throw new ArgumentNullException
+("Parameter name: buffer");
+
+ int len = buffer.Length;
+ if ((offset < 0) || (offset >= len))
+ throw new
+ArgumentOutOfRangeException ("Parameter name: offset");
+ if ((offset + size < 0) || (offset + size
+> len))
+ throw new
+ArgumentOutOfRangeException ("Paramter name: size");
+
+ try {
+ retval = socket.BeginSend (buffer,
+offset, size, 0, callback, state);
+ } catch {
+ throw new IOException ("BeginWrite
+failure");
+ }
+
+ return retval;
+ } finally {
+ CheckDisposed ();
+ }
+ }
+
+ ~NetworkStream ()
+ {
+ Dispose (false);
+ }
+
+ public override void Close ()
+ {
+ ((IDisposable) this).Dispose ();
+ }
+
+ protected virtual void Dispose (bool disposing)
+ {
+ if (disposed)
+ return;
+ disposed = true;
+
+ if (owns_socket) {
+ Socket s = socket;
+ if (s != null)
+ s.Close ();
+ }
+ socket = null;
+ }
+
+ public override int EndRead (IAsyncResult asyncResult)
+ {
+ try {
+ int res;
+
+ if (asyncResult == null)
+ throw new ArgumentNullException
+("Parameter: asyncResult");
+
+ try {
+ res = socket.EndReceive
+(asyncResult);
+ } catch {
+ throw new IOException ("EndRead
+failure");
+ }
+ return res;
+ } finally {
+ CheckDisposed ();
+ }
+ }
+
+ public override void EndWrite (IAsyncResult asyncResult)
+ {
+ try {
+ if (asyncResult == null)
+ throw new ArgumentNullException
+("Parameter: asyncResult");
+
+ try {
+ socket.EndSend (asyncResult);
+ } catch {
+ throw new IOException ("EndWrite
+failure");
+ }
+ } finally {
+ CheckDisposed ();
+ }
+ }
+
+ public override void Flush ()
+ {
+ // network streams are non-buffered, this is a no-
+op
+ }
+
+ void IDisposable.Dispose ()
+ {
+ Dispose (true);
+ GC.SuppressFinalize (this);
+ }
+
+ public override int Read (byte [] buffer, int offset, int
+size)
+ {
+ try {
+ int res;
+
+ if (buffer == null)
+ throw new ArgumentNullException
+("Parameter name: buffer");
+
+ int len = buffer.Length;
+ if ((offset < 0) || (offset >= len))
+ throw new
+ArgumentOutOfRangeException ("Parameter name: offset");
+ if ((offset + size < 0) || (offset + size
+> len))
+ throw new
+ArgumentOutOfRangeException ("Paramter name: size");
+ try {
+ res = socket.Receive (buffer,
+offset, size, 0);
+ } catch {
+ throw new IOException ("Read
+failure");
+ }
+ return res;
+ } finally {
+ CheckDisposed ();
+ }
+ }
+
+ public override long Seek (long offset, SeekOrigin origin)
+ {
+ // NetworkStream objects do not support seeking.
+
+ throw new NotSupportedException ();
+ }
+
+ public override void SetLength (long value)
+ {
+ // NetworkStream objects do not support SetLength
+
+ throw new NotSupportedException ();
+ }
+
+ public override void Write (byte [] buffer, int offset,
+int size)
+ {
+ try {
+ if (buffer == null)
+ throw new ArgumentNullException
+("Parameter name: buffer");
+ int len = buffer.Length;
+ if ((offset < 0) || (offset >= len))
+ throw new
+ArgumentOutOfRangeException ("Parameter name: offset");
+ if ((offset + size < 0) || (offset + size
+> len))
+ throw new
+ArgumentOutOfRangeException ("Paramter name: size");
+
+ try {
+ socket.Send (buffer, offset, size,
+0);
+ } catch {
+ throw new IOException ("Write
+failure");
+ }
+ } finally {
+ CheckDisposed ();
+ }
+ }
+
+ private void CheckDisposed ()
+ {
+ if (disposed)
+ throw new ObjectDisposedException (GetType
+().FullName);
+ }
+
+ }
+}
+
+
+
+mcs-0.16/class/System/System.Net.Sockets/Socket.cs
+// System.Net.Sockets.Socket.cs
+//
+// Authors:
+// Phillip Pearson (pp@myelin.co.nz)
+// Dick Porter <dick@ximian.com>
+//
+// Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
+// http://www.myelin.co.nz
+//
+
+using System;
+using System.Net;
+using System.Collections;
+using System.Runtime.CompilerServices;
+using System.Threading;
+
+namespace System.Net.Sockets
+{
+ public class Socket : IDisposable
+ {
+ private sealed class SocketAsyncResult: IAsyncResult
+ {
+ private object state;
+ private WaitHandle waithandle;
+ private bool completed_sync, completed;
+ private Worker worker;
+
+ public SocketAsyncResult(object state) {
+ this.state=state;
+ waithandle=new ManualResetEvent(false);
+ completed_sync=completed=false;
+ }
+
+ public object AsyncState {
+ get {
+ return(state);
+ }
+ }
+
+ public WaitHandle AsyncWaitHandle {
+ get {
+ return(waithandle);
+ }
+ set {
+ waithandle=value;
+ }
+ }
+
+ public bool CompletedSynchronously {
+ get {
+ return(completed_sync);
+ }
+ }
+
+ public bool IsCompleted {
+ get {
+ return(completed);
+ }
+ set {
+ completed=value;
+ }
+ }
+
+ public Worker Worker {
+ get {
+ return(worker);
+ }
+ set {
+ worker=value;
+ }
+ }
+ }
+
+ private sealed class Worker
+ {
+ private AsyncCallback callback;
+ private SocketAsyncResult result;
+ private Socket socket;
+
+ // Parameters
+ private EndPoint endpoint; //
+Connect,ReceiveFrom,SendTo
+ private byte[] buffer; //
+Receive,ReceiveFrom,Send,SendTo
+ private int offset; //
+Receive,ReceiveFrom,Send,SendTo
+ private int size; //
+Receive,ReceiveFrom,Send,SendTo
+ private SocketFlags sockflags; //
+Receive,ReceiveFrom,Send,SendTo
+
+ // Return values
+ private Socket acc_socket;
+ private int total;
+
+
+ // For Accept
+ public Worker(Socket req_sock,
+ AsyncCallback req_callback,
+ SocketAsyncResult req_result)
+ : this(req_sock, null, 0, 0,
+SocketFlags.None,
+ null, req_callback, req_result) {}
+
+ // For Connect
+ public Worker(Socket req_sock, EndPoint
+req_endpoint,
+ AsyncCallback req_callback,
+ SocketAsyncResult req_result)
+ : this(req_sock, null, 0, 0,
+SocketFlags.None,
+ req_endpoint, req_callback,
+ req_result) {}
+
+ // For Receive and Send
+ public Worker(Socket req_sock, byte[] req_buffer,
+ int req_offset, int req_size,
+ SocketFlags req_sockflags,
+ AsyncCallback req_callback,
+ SocketAsyncResult req_result)
+ : this(req_sock, req_buffer, req_offset,
+ req_size, req_sockflags, null,
+ req_callback, req_result) {}
+
+ // For ReceiveFrom and SendTo
+ public Worker(Socket req_sock, byte[] req_buffer,
+ int req_offset, int req_size,
+ SocketFlags req_sockflags,
+ EndPoint req_endpoint,
+ AsyncCallback req_callback,
+ SocketAsyncResult req_result) {
+ socket=req_sock;
+ buffer=req_buffer;
+ offset=req_offset;
+ size=req_size;
+ sockflags=req_sockflags;
+ endpoint=req_endpoint;
+ callback=req_callback;
+ result=req_result;
+ }
+
+ private void End() {
+ ((ManualResetEvent)
+result.AsyncWaitHandle).Set();
+ callback(result);
+ result.IsCompleted=true;
+ }
+
+ public void Accept() {
+ lock(result) {
+ acc_socket=socket.Accept();
+ End();
+ }
+ }
+
+ public void Connect() {
+ lock(result) {
+ socket.Connect(endpoint);
+ End();
+ }
+ }
+
+ public void Receive() {
+ lock(result) {
+ total=socket.Receive(buffer,
+offset,
+ size,
+sockflags);
+ End();
+ }
+ }
+
+ public void ReceiveFrom() {
+ lock(result) {
+ total=socket.ReceiveFrom(buffer,
+ offset,
+size,
+ sockflags,
+ ref
+endpoint);
+ End();
+ }
+ }
+
+ public void Send() {
+ lock(result) {
+ total=socket.Send(buffer, offset,
+size,
+ sockflags);
+ End();
+ }
+ }
+
+ public void SendTo() {
+ lock(result) {
+ total=socket.SendTo(buffer, offset,
+ size,
+sockflags,
+ endpoint);
+ End();
+ }
+ }
+
+ public EndPoint EndPoint {
+ get {
+ return(endpoint);
+ }
+ }
+
+ public Socket Socket {
+ get {
+ return(acc_socket);
+ }
+ }
+
+ public int Total {
+ get {
+ return(total);
+ }
+ }
+ }
+
+ /* the field "socket" is looked up by name by the runtime
+*/
+ private IntPtr socket;
+ private AddressFamily address_family;
+ private SocketType socket_type;
+ private ProtocolType protocol_type;
+ private bool blocking=true;
+
+ /* When true, the socket was connected at the time of
+ * the last IO operation
+ */
+ private bool connected=false;
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static void Select_internal(ref Socket[]
+read,
+ ref Socket[]
+write,
+ ref Socket[]
+err,
+ int timeout);
+
+ public static void Select(IList read_list, IList
+write_list,
+ IList err_list, int time_us) {
+ if(read_list==null &&
+ write_list==null &&
+ err_list==null) {
+ throw new ArgumentNullException();
+ }
+
+ int read_count, write_count, err_count;
+
+ if(read_list!=null) {
+ read_count=read_list.Count;
+ } else {
+ read_count=0;
+ }
+
+ if(write_list!=null) {
+ write_count=write_list.Count;
+ } else {
+ write_count=0;
+ }
+
+ if(err_list!=null) {
+ err_count=err_list.Count;
+ } else {
+ err_count=0;
+ }
+
+ Socket[] read_arr=new Socket[read_count];
+ Socket[] write_arr=new Socket[write_count];
+ Socket[] err_arr=new Socket[err_count];
+
+ int i;
+
+ if(read_list!=null) {
+ i=0;
+
+ foreach (Socket s in read_list) {
+ read_arr[i]=s;
+ i++;
+ }
+ }
+
+ if(write_list!=null) {
+ i=0;
+ foreach (Socket s in write_list) {
+ write_arr[i]=s;
+ i++;
+ }
+ }
+
+ if(err_list!=null) {
+ i=0;
+ foreach (Socket s in err_list) {
+ err_arr[i]=s;
+ i++;
+ }
+ }
+
+ Select_internal(ref read_arr, ref write_arr,
+ ref err_arr, time_us);
+
+ if(read_list!=null) {
+ read_list.Clear();
+ for(i=0; i<read_arr.Length; i++) {
+ read_list.Add(read_arr[i]);
+ }
+ }
+
+ if(write_list!=null) {
+ write_list.Clear();
+ for(i=0; i<write_arr.Length; i++) {
+ write_list.Add(write_arr[i]);
+ }
+ }
+
+ if(err_list!=null) {
+ err_list.Clear();
+ for(i=0; i<err_arr.Length; i++) {
+ err_list.Add(err_arr[i]);
+ }
+ }
+ }
+
+ // private constructor used by Accept, which already
+ // has a socket handle to use
+ private Socket(AddressFamily family, SocketType type,
+ ProtocolType proto, IntPtr sock) {
+ address_family=family;
+ socket_type=type;
+ protocol_type=proto;
+
+ socket=sock;
+ connected=true;
+ }
+
+ // Creates a new system socket, returning the handle
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern IntPtr Socket_internal(AddressFamily family,
+ SocketType type,
+ ProtocolType proto);
+
+ public Socket(AddressFamily family, SocketType type,
+ ProtocolType proto) {
+ address_family=family;
+ socket_type=type;
+ protocol_type=proto;
+
+ socket=Socket_internal(family, type, proto);
+ }
+
+ public AddressFamily AddressFamily {
+ get {
+ return(address_family);
+ }
+ }
+
+ // Returns the amount of data waiting to be read on socket
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static int Available_internal(IntPtr
+socket);
+
+ public int Available {
+ get {
+ return(Available_internal(socket));
+ }
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static void Blocking_internal(IntPtr socket,
+ bool block);
+
+ public bool Blocking {
+ get {
+ return(blocking);
+ }
+ set {
+ Blocking_internal(socket, value);
+ blocking=value;
+ }
+ }
+
+ public bool Connected {
+ get {
+ return(connected);
+ }
+ }
+
+ public IntPtr Handle {
+ get {
+ return(socket);
+ }
+ }
+
+ // Returns the local endpoint details in addr and port
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static SocketAddress LocalEndPoint_internal
+(IntPtr socket);
+
+ [MonoTODO("Support non-IP endpoints")]
+ public EndPoint LocalEndPoint {
+ get {
+ SocketAddress sa;
+
+ sa=LocalEndPoint_internal(socket);
+
+ if(sa.Family==AddressFamily.InterNetwork) {
+ // Stupidly, EndPoint.Create() is
+an
+ // instance method
+ return new IPEndPoint(0, 0).Create
+(sa);
+ } else {
+ throw new NotImplementedException
+();
+ }
+ }
+ }
+
+ public ProtocolType ProtocolType {
+ get {
+ return(protocol_type);
+ }
+ }
+
+ // Returns the remote endpoint details in addr and port
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static SocketAddress RemoteEndPoint_internal
+(IntPtr socket);
+
+ [MonoTODO("Support non-IP endpoints")]
+ public EndPoint RemoteEndPoint {
+ get {
+ SocketAddress sa;
+
+ sa=RemoteEndPoint_internal(socket);
+
+ if(sa.Family==AddressFamily.InterNetwork) {
+ // Stupidly, EndPoint.Create() is
+an
+ // instance method
+ return new IPEndPoint(0, 0).Create
+(sa);
+ } else {
+ throw new NotImplementedException
+();
+ }
+ }
+ }
+
+ public SocketType SocketType {
+ get {
+ return(socket_type);
+ }
+ }
+
+ // Creates a new system socket, returning the handle
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static IntPtr Accept_internal(IntPtr sock);
+
+ public Socket Accept() {
+ IntPtr sock=Accept_internal(socket);
+
+ return(new Socket(this.AddressFamily,
+this.SocketType,
+ this.ProtocolType, sock));
+ }
+
+ public IAsyncResult BeginAccept(AsyncCallback callback,
+ object state) {
+ SocketAsyncResult req=new SocketAsyncResult(state);
+ Worker worker=new Worker(this, callback, req);
+ req.Worker=worker;
+ Thread child=new Thread(new ThreadStart
+(worker.Accept));
+ child.Start();
+ return(req);
+ }
+
+ public IAsyncResult BeginConnect(EndPoint end_point,
+ AsyncCallback callback,
+ object state) {
+ SocketAsyncResult req=new SocketAsyncResult(state);
+ Worker worker=new Worker(this, end_point, callback,
+ req);
+ req.Worker=worker;
+ Thread child=new Thread(new ThreadStart
+(worker.Connect));
+ child.Start();
+ return(req);
+ }
+
+ public IAsyncResult BeginReceive(byte[] buffer, int offset,
+ int size,
+ SocketFlags socket_flags,
+ AsyncCallback callback,
+ object state) {
+ SocketAsyncResult req=new SocketAsyncResult(state);
+ Worker worker=new Worker(this, buffer, offset,
+size,
+ socket_flags, callback,
+req);
+ req.Worker=worker;
+ Thread child=new Thread(new ThreadStart
+(worker.Receive));
+ child.Start();
+ return(req);
+ }
+
+ public IAsyncResult BeginReceiveFrom(byte[] buffer, int
+offset,
+ int size,
+ SocketFlags
+socket_flags,
+ ref EndPoint
+remote_end,
+ AsyncCallback
+callback,
+ object state) {
+ SocketAsyncResult req=new SocketAsyncResult(state);
+ Worker worker=new Worker(this, buffer, offset,
+size,
+ socket_flags, remote_end,
+ callback, req);
+ req.Worker=worker;
+ Thread child=new Thread(new ThreadStart
+(worker.ReceiveFrom));
+ child.Start();
+ return(req);
+ }
+
+ public IAsyncResult BeginSend(byte[] buffer, int offset,
+ int size,
+ SocketFlags socket_flags,
+ AsyncCallback callback,
+ object state) {
+ SocketAsyncResult req=new SocketAsyncResult(state);
+ Worker worker=new Worker(this, buffer, offset,
+size,
+ socket_flags, callback,
+req);
+ req.Worker=worker;
+ Thread child=new Thread(new ThreadStart
+(worker.Send));
+ child.Start();
+ return(req);
+ }
+
+ public IAsyncResult BeginSendTo(byte[] buffer, int offset,
+ int size,
+ SocketFlags socket_flags,
+ EndPoint remote_end,
+ AsyncCallback callback,
+ object state) {
+ SocketAsyncResult req=new SocketAsyncResult(state);
+ Worker worker=new Worker(this, buffer, offset,
+size,
+ socket_flags, remote_end,
+ callback, req);
+ req.Worker=worker;
+ Thread child=new Thread(new ThreadStart
+(worker.SendTo));
+ child.Start();
+ return(req);
+ }
+
+ // Creates a new system socket, returning the handle
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static void Bind_internal(IntPtr sock,
+ SocketAddress sa);
+
+ public void Bind(EndPoint local_end) {
+ if(local_end==null) {
+ throw new ArgumentNullException();
+ }
+
+ Bind_internal(socket, local_end.Serialize());
+ }
+
+ // Closes the socket
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static void Close_internal(IntPtr socket);
+
+ public void Close() {
+ connected=false;
+ Close_internal(socket);
+ }
+
+ // Connects to the remote address
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static void Connect_internal(IntPtr sock,
+ SocketAddress
+sa);
+
+ public void Connect(EndPoint remote_end) {
+ if(remote_end==null) {
+ throw new ArgumentNullException();
+ }
+
+ Connect_internal(socket, remote_end.Serialize());
+ connected=true;
+ }
+
+ public Socket EndAccept(IAsyncResult result) {
+ SocketAsyncResult req=(SocketAsyncResult)result;
+
+ result.AsyncWaitHandle.WaitOne();
+ return(req.Worker.Socket);
+ }
+
+ public void EndConnect(IAsyncResult result) {
+ SocketAsyncResult req=(SocketAsyncResult)result;
+
+ result.AsyncWaitHandle.WaitOne();
+ }
+
+ public int EndReceive(IAsyncResult result) {
+ SocketAsyncResult req=(SocketAsyncResult)result;
+
+ result.AsyncWaitHandle.WaitOne();
+ return(req.Worker.Total);
+ }
+
+ public int EndReceiveFrom(IAsyncResult result,
+ ref EndPoint end_point) {
+ SocketAsyncResult req=(SocketAsyncResult)result;
+
+ result.AsyncWaitHandle.WaitOne();
+ end_point=req.Worker.EndPoint;
+ return(req.Worker.Total);
+ }
+
+ public int EndSend(IAsyncResult result) {
+ SocketAsyncResult req=(SocketAsyncResult)result;
+
+ result.AsyncWaitHandle.WaitOne();
+ return(req.Worker.Total);
+ }
+
+ public int EndSendTo(IAsyncResult result) {
+ SocketAsyncResult req=(SocketAsyncResult)result;
+
+ result.AsyncWaitHandle.WaitOne();
+ return(req.Worker.Total);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static void GetSocketOption_obj_internal
+(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object
+obj_val);
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static void GetSocketOption_arr_internal
+(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[]
+byte_val);
+
+ public object GetSocketOption(SocketOptionLevel level,
+ SocketOptionName name) {
+ object obj_val;
+
+ GetSocketOption_obj_internal(socket, level, name,
+ out obj_val);
+
+ if(name==SocketOptionName.Linger) {
+ return((LingerOption)obj_val);
+ } else if (name==SocketOptionName.AddMembership ||
+ name==SocketOptionName.DropMembership) {
+ return((MulticastOption)obj_val);
+ } else {
+ return((int)obj_val);
+ }
+ }
+
+ public void GetSocketOption(SocketOptionLevel level,
+ SocketOptionName name,
+ byte[] opt_value) {
+ int opt_value_len=opt_value.Length;
+
+ GetSocketOption_arr_internal(socket, level, name,
+ ref opt_value);
+ }
+
+ public byte[] GetSocketOption(SocketOptionLevel level,
+ SocketOptionName name,
+ int length) {
+ byte[] byte_val=new byte[length];
+
+ GetSocketOption_arr_internal(socket, level, name,
+ ref byte_val);
+
+ return(byte_val);
+ }
+
+ [MonoTODO("Totally undocumented")]
+ public int IOControl(int ioctl_code, byte[] in_value,
+ byte[] out_value) {
+ throw new NotImplementedException();
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static void Listen_internal(IntPtr sock,
+ int backlog);
+
+ public void Listen(int backlog) {
+ Listen_internal(socket, backlog);
+ }
+
+ /* The docs for Poll() are a bit lightweight too, but
+ * it seems to be just a simple wrapper around Select.
+ */
+ public bool Poll(int time_us, SelectMode mode) {
+ ArrayList socketlist=new ArrayList(1);
+
+ socketlist.Add(this);
+
+ switch(mode) {
+ case SelectMode.SelectError:
+ Select(null, null, socketlist, time_us);
+ break;
+ case SelectMode.SelectRead:
+ Select(socketlist, null, null, time_us);
+ break;
+ case SelectMode.SelectWrite:
+ Select(null, socketlist, null, time_us);
+ break;
+ default:
+ throw new NotSupportedException();
+ }
+
+ if(socketlist.Contains(this)) {
+ return(true);
+ } else {
+ return(false);
+ }
+ }
+
+ public int Receive(byte[] buffer) {
+ return(Receive(buffer, 0, buffer.Length,
+SocketFlags.None));
+ }
+
+ public int Receive(byte[] buffer, SocketFlags flags) {
+ return(Receive(buffer, 0, buffer.Length, flags));
+ }
+
+ public int Receive(byte[] buffer, int size, SocketFlags
+flags) {
+ return(Receive(buffer, 0, size, flags));
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static int Receive_internal(IntPtr sock,
+ byte[] buffer,
+ int offset,
+ int count,
+ SocketFlags
+flags);
+
+ public int Receive(byte[] buffer, int offset, int size,
+ SocketFlags flags) {
+ if (buffer == null)
+ throw new ArgumentNullException
+("Parameter name: buffer");
+ int len = buffer.Length;
+ if ((offset < 0) || (offset >= len))
+ throw new ArgumentOutOfRangeException
+("Parameter name: offset");
+ if ((offset + size < 0) || (offset + size > len))
+ throw new ArgumentOutOfRangeException
+("Paramter name: size");
+ int ret;
+
+ try {
+ ret=Receive_internal(socket, buffer,
+offset,
+ size, flags);
+ } catch(SocketException) {
+ connected=false;
+ throw;
+ }
+ connected=true;
+
+ return(ret);
+ }
+
+ public int ReceiveFrom(byte[] buffer, ref EndPoint
+remote_end) {
+ return(ReceiveFrom(buffer, 0, buffer.Length,
+ SocketFlags.None, ref
+remote_end));
+ }
+
+ public int ReceiveFrom(byte[] buffer, SocketFlags flags,
+ ref EndPoint remote_end) {
+ return(ReceiveFrom(buffer, 0, buffer.Length, flags,
+ ref remote_end));
+ }
+
+ public int ReceiveFrom(byte[] buffer, int size,
+SocketFlags flags,
+ ref EndPoint remote_end) {
+ return(ReceiveFrom(buffer, 0, size, flags,
+ ref remote_end));
+ }
+
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static int RecvFrom_internal(IntPtr sock,
+ byte[] buffer,
+ int offset,
+ int count,
+ SocketFlags
+flags,
+ ref
+SocketAddress sockaddr);
+
+ public int ReceiveFrom(byte[] buffer, int offset, int size,
+ SocketFlags flags,
+ ref EndPoint remote_end) {
+ if (buffer == null)
+ throw new ArgumentNullException
+("Parameter name: buffer");
+ if (remote_end == null)
+ throw new ArgumentNullException
+("Parameter name: remote_end");
+ int len = buffer.Length;
+ if ((offset < 0) || (offset >= len))
+ throw new ArgumentOutOfRangeException
+("Parameter name: offset");
+ if ((offset + size < 0) || (offset + size > len))
+ throw new ArgumentOutOfRangeException
+("Paramter name: size");
+
+ SocketAddress sockaddr=remote_end.Serialize();
+ int count;
+
+ try {
+ count=RecvFrom_internal(socket, buffer,
+offset,
+ size, flags,
+ ref sockaddr);
+ } catch(SocketException) {
+ connected=false;
+ throw;
+ }
+ connected=true;
+
+ // Stupidly, EndPoint.Create() is an
+ // instance method
+ remote_end=remote_end.Create(sockaddr);
+
+ return(count);
+ }
+
+ public int Send(byte[] buffer) {
+ return(Send(buffer, 0, buffer.Length,
+SocketFlags.None));
+ }
+
+ public int Send(byte[] buffer, SocketFlags flags) {
+ return(Send(buffer, 0, buffer.Length, flags));
+ }
+
+ public int Send(byte[] buffer, int size, SocketFlags
+flags) {
+ return(Send(buffer, 0, size, flags));
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static int Send_internal(IntPtr sock,
+ byte[] buffer, int
+offset,
+ int count,
+ SocketFlags flags);
+
+ public int Send(byte[] buffer, int offset, int size,
+ SocketFlags flags) {
+ if (buffer == null)
+ throw new ArgumentNullException
+("Parameter name: buffer");
+ int len = buffer.Length;
+ if ((offset < 0) || (offset >= len))
+ throw new ArgumentOutOfRangeException
+("Parameter name: offset");
+ if ((offset + size < 0) || (offset + size > len))
+ throw new ArgumentOutOfRangeException
+("Paramter name: size");
+ int ret;
+
+ try {
+ ret=Send_internal(socket, buffer, offset,
+size,
+ flags);
+ } catch(SocketException) {
+ connected=false;
+ throw;
+ }
+ connected=true;
+
+ return(ret);
+ }
+
+ public int SendTo(byte[] buffer, EndPoint remote_end) {
+ return(SendTo(buffer, 0, buffer.Length,
+ SocketFlags.None, remote_end));
+ }
+
+ public int SendTo(byte[] buffer, SocketFlags flags,
+ EndPoint remote_end) {
+ return(SendTo(buffer, 0, buffer.Length, flags,
+ remote_end));
+ }
+
+ public int SendTo(byte[] buffer, int size, SocketFlags
+flags,
+ EndPoint remote_end) {
+ return(SendTo(buffer, size, buffer.Length, flags,
+ remote_end));
+ }
+
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static int SendTo_internal(IntPtr sock,
+ byte[] buffer,
+ int offset,
+ int count,
+ SocketFlags
+flags,
+ SocketAddress
+sa);
+
+ public int SendTo(byte[] buffer, int offset, int size,
+ SocketFlags flags, EndPoint remote_end) {
+ if (buffer == null)
+ throw new ArgumentNullException
+("Parameter name: buffer");
+ if (remote_end == null)
+ throw new ArgumentNullException
+("Parameter name: remote_end");
+ int len = buffer.Length;
+ if ((offset < 0) || (offset >= len))
+ throw new ArgumentOutOfRangeException
+("Parameter name: offset");
+ if ((offset + size < 0) || (offset + size > len))
+ throw new ArgumentOutOfRangeException
+("Paramter name: size");
+
+ SocketAddress sockaddr=remote_end.Serialize();
+
+ int ret;
+
+ try {
+ ret=SendTo_internal(socket, buffer, offset,
+ size, flags, sockaddr);
+ }
+ catch(SocketException) {
+ connected=false;
+ throw;
+ }
+ connected=true;
+
+ return(ret);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static void SetSocketOption_internal(IntPtr
+socket, SocketOptionLevel level, SocketOptionName name, object obj_val,
+byte[] byte_val, int int_val);
+
+ public void SetSocketOption(SocketOptionLevel level,
+ SocketOptionName name,
+ byte[] opt_value) {
+ SetSocketOption_internal(socket, level, name, null,
+ opt_value, 0);
+ }
+
+ public void SetSocketOption(SocketOptionLevel level,
+ SocketOptionName name,
+ int opt_value) {
+ SetSocketOption_internal(socket, level, name, null,
+ null, opt_value);
+ }
+
+ public void SetSocketOption(SocketOptionLevel level,
+ SocketOptionName name,
+ object opt_value) {
+ if(opt_value==null) {
+ throw new ArgumentNullException();
+ }
+
+ /* Passing a bool as the third parameter to
+ * SetSocketOption causes this overload to be
+ * used when in fact we want to pass the value
+ * to the runtime as an int.
+ */
+ if(opt_value is System.Boolean) {
+ bool bool_val=(bool)opt_value;
+
+ /* Stupid casting rules :-( */
+ if(bool_val==true) {
+ SetSocketOption_internal(socket,
+level,
+ name,
+null,
+ null, 1);
+ } else {
+ SetSocketOption_internal(socket,
+level,
+ name,
+null,
+ null, 0);
+ }
+ } else {
+ SetSocketOption_internal(socket, level,
+name,
+ opt_value, null,
+0);
+ }
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static void Shutdown_internal(IntPtr
+socket, SocketShutdown how);
+
+ public void Shutdown(SocketShutdown how) {
+ Shutdown_internal(socket, how);
+ }
+
+ private bool disposed = false;
+
+ protected virtual void Dispose(bool explicitDisposing) {
+ // Check to see if Dispose has already been called
+ if(!this.disposed) {
+ // If this is a call to Dispose,
+ // dispose all managed resources.
+ if(explicitDisposing) {
+ // Free up stuff here
+ }
+
+ // Release unmanaged resources
+ this.disposed=true;
+ this.Close();
+ }
+ }
+
+ public void Dispose() {
+ Dispose(true);
+ // Take yourself off the Finalization queue
+ GC.SuppressFinalize(this);
+ }
+
+ ~Socket () {
+ Dispose(false);
+ }
+ }
+}
+
+
+
+mcs-0.16/class/System/System.Net.Sockets/ChangeLog:
+
+2002-10-07 Tim Mills <timothyjmills@hotmail.com>
+
+ * Socket.cs: Improved bounds checking on buffer argument
+ for a number of methods.
+
+ * NetworkStream.cs: Fixed bug in BeginRead, BeginWrite which
+ made an incorrect bounds check on buffer.