PageRenderTime 8ms CodeModel.GetById 15ms app.highlight 72ms RepoModel.GetById 1ms app.codeStats 1ms

/mcs/class/System/System.Net.Sockets/Socket.cs

https://bitbucket.org/steenlund/mono-2.6.7-for-amiga
C# | 3145 lines | 2361 code | 579 blank | 205 comment | 773 complexity | 4c24ed54c4c8bbbf6480a4f139b7baaa MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1// System.Net.Sockets.Socket.cs
   2//
   3// Authors:
   4//	Phillip Pearson (pp@myelin.co.nz)
   5//	Dick Porter <dick@ximian.com>
   6//	Gonzalo Paniagua Javier (gonzalo@ximian.com)
   7//	Sridhar Kulkarni (sridharkulkarni@gmail.com)
   8//	Brian Nickel (brian.nickel@gmail.com)
   9//
  10// Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
  11//    http://www.myelin.co.nz
  12// (c) 2004-2006 Novell, Inc. (http://www.novell.com)
  13//
  14
  15//
  16// Permission is hereby granted, free of charge, to any person obtaining
  17// a copy of this software and associated documentation files (the
  18// "Software"), to deal in the Software without restriction, including
  19// without limitation the rights to use, copy, modify, merge, publish,
  20// distribute, sublicense, and/or sell copies of the Software, and to
  21// permit persons to whom the Software is furnished to do so, subject to
  22// the following conditions:
  23// 
  24// The above copyright notice and this permission notice shall be
  25// included in all copies or substantial portions of the Software.
  26// 
  27// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  28// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  29// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  30// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  31// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  32// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  33// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  34//
  35
  36using System;
  37using System.Net;
  38using System.Collections;
  39using System.Runtime.CompilerServices;
  40using System.Runtime.InteropServices;
  41using System.Threading;
  42using System.Reflection;
  43using System.IO;
  44using System.Net.Configuration;
  45using System.Text;
  46
  47#if NET_2_0
  48using System.Collections.Generic;
  49using System.Net.NetworkInformation;
  50using System.Timers;
  51#endif
  52
  53namespace System.Net.Sockets 
  54{
  55	public partial class Socket : IDisposable
  56	{
  57		enum SocketOperation {
  58			Accept,
  59			Connect,
  60			Receive,
  61			ReceiveFrom,
  62			Send,
  63			SendTo,
  64			UsedInManaged1,
  65			UsedInManaged2,
  66			UsedInProcess,
  67			UsedInConsole2,
  68			Disconnect,
  69			AcceptReceive,
  70			ReceiveGeneric,
  71			SendGeneric
  72		}
  73
  74		[StructLayout (LayoutKind.Sequential)]
  75		struct WSABUF 
  76		{
  77			public int len;
  78			public IntPtr buf;
  79		};
  80
  81		[StructLayout (LayoutKind.Sequential)]
  82		private sealed class SocketAsyncResult: IAsyncResult
  83		{
  84			/* Same structure in the runtime */
  85			/*
  86			  Keep this in sync with MonoSocketAsyncResult in
  87  			  metadata/socket-io.h and ProcessAsyncReader
  88  			  in System.Diagnostics/Process.cs.
  89			*/
  90
  91			public Socket Sock;
  92			public IntPtr handle;
  93			object state;
  94			AsyncCallback callback;
  95			WaitHandle waithandle;
  96
  97			Exception delayedException;
  98
  99			public EndPoint EndPoint;	// Connect,ReceiveFrom,SendTo
 100			public byte [] Buffer;		// Receive,ReceiveFrom,Send,SendTo
 101			public int Offset;		// Receive,ReceiveFrom,Send,SendTo
 102			public int Size;		// Receive,ReceiveFrom,Send,SendTo
 103			public SocketFlags SockFlags;	// Receive,ReceiveFrom,Send,SendTo
 104			public Socket AcceptSocket;	// AcceptReceive
 105			public IPAddress[] Addresses;	// Connect
 106			public int Port;		// Connect
 107#if NET_2_0
 108			public IList<ArraySegment<byte>> Buffers;	// Receive, Send
 109#else
 110			public object Buffers;		// Reserve this slot in older profiles
 111#endif
 112			public bool ReuseSocket;	// Disconnect
 113
 114			// Return values
 115			Socket acc_socket;
 116			int total;
 117
 118			bool completed_sync;
 119			bool completed;
 120			public bool blocking;
 121			internal int error;
 122			SocketOperation operation;
 123			public object ares;
 124			public int EndCalled;
 125
 126			public SocketAsyncResult (Socket sock, object state, AsyncCallback callback, SocketOperation operation)
 127			{
 128				this.Sock = sock;
 129				this.blocking = sock.blocking;
 130				this.handle = sock.socket;
 131				this.state = state;
 132				this.callback = callback;
 133				this.operation = operation;
 134				SockFlags = SocketFlags.None;
 135			}
 136
 137			public void CheckIfThrowDelayedException ()
 138			{
 139				if (delayedException != null) {
 140					Sock.connected = false;
 141					throw delayedException;
 142				}
 143
 144				if (error != 0) {
 145					Sock.connected = false;
 146					throw new SocketException (error);
 147				}
 148			}
 149
 150			void CompleteAllOnDispose (Queue queue)
 151			{
 152				object [] pending = queue.ToArray ();
 153				queue.Clear ();
 154
 155				WaitCallback cb;
 156				for (int i = 0; i < pending.Length; i++) {
 157					SocketAsyncResult ares = (SocketAsyncResult) pending [i];
 158					cb = new WaitCallback (ares.CompleteDisposed);
 159					ThreadPool.QueueUserWorkItem (cb, null);
 160				}
 161				if (pending.Length == 0)
 162					Buffer = null;
 163			}
 164
 165			void CompleteDisposed (object unused)
 166			{
 167				Complete ();
 168			}
 169
 170			public void Complete ()
 171			{
 172				if (operation != SocketOperation.Receive && Sock.disposed)
 173					delayedException = new ObjectDisposedException (Sock.GetType ().ToString ());
 174
 175				IsCompleted = true;
 176
 177				Queue queue = null;
 178				if (operation == SocketOperation.Receive || operation == SocketOperation.ReceiveFrom) {
 179					queue = Sock.readQ;
 180				} else if (operation == SocketOperation.Send || operation == SocketOperation.SendTo) {
 181					queue = Sock.writeQ;
 182				}
 183
 184				if (queue != null) {
 185					SocketAsyncCall sac = null;
 186					SocketAsyncResult req = null;
 187					lock (queue) {
 188						queue.Dequeue (); // remove ourselves
 189						if (queue.Count > 0) {
 190							req = (SocketAsyncResult) queue.Peek ();
 191							if (!Sock.disposed) {
 192								Worker worker = new Worker (req);
 193								sac = GetDelegate (worker, req.operation);
 194							} else {
 195								CompleteAllOnDispose (queue);
 196							}
 197						}
 198					}
 199
 200					if (sac != null)
 201						sac.BeginInvoke (null, req);
 202				}
 203
 204				if (callback != null)
 205					callback (this);
 206				Buffer = null;
 207			}
 208
 209			SocketAsyncCall GetDelegate (Worker worker, SocketOperation op)
 210			{
 211				switch (op) {
 212				case SocketOperation.Receive:
 213					return new SocketAsyncCall (worker.Receive);
 214				case SocketOperation.ReceiveFrom:
 215					return new SocketAsyncCall (worker.ReceiveFrom);
 216				case SocketOperation.Send:
 217					return new SocketAsyncCall (worker.Send);
 218				case SocketOperation.SendTo:
 219					return new SocketAsyncCall (worker.SendTo);
 220				default:
 221					return null; // never happens
 222				}
 223			}
 224
 225			public void Complete (bool synch)
 226			{
 227				completed_sync = synch;
 228				Complete ();
 229			}
 230
 231			public void Complete (int total)
 232			{
 233				this.total = total;
 234				Complete ();
 235			}
 236
 237			public void Complete (Exception e, bool synch)
 238			{
 239				completed_sync = synch;
 240				delayedException = e;
 241				Complete ();
 242			}
 243
 244			public void Complete (Exception e)
 245			{
 246				delayedException = e;
 247				Complete ();
 248			}
 249
 250			public void Complete (Socket s)
 251			{
 252				acc_socket = s;
 253				Complete ();
 254			}
 255
 256			public void Complete (Socket s, int total)
 257			{
 258				acc_socket = s;
 259				this.total = total;
 260				Complete ();
 261			}
 262
 263			public object AsyncState {
 264				get {
 265					return state;
 266				}
 267			}
 268
 269			public WaitHandle AsyncWaitHandle {
 270				get {
 271					lock (this) {
 272						if (waithandle == null)
 273							waithandle = new ManualResetEvent (completed);
 274					}
 275
 276					return waithandle;
 277				}
 278				set {
 279					waithandle=value;
 280				}
 281			}
 282
 283			public bool CompletedSynchronously {
 284				get {
 285					return(completed_sync);
 286				}
 287			}
 288
 289			public bool IsCompleted {
 290				get {
 291					return(completed);
 292				}
 293				set {
 294					completed=value;
 295					lock (this) {
 296						if (waithandle != null && value) {
 297							((ManualResetEvent) waithandle).Set ();
 298						}
 299					}
 300				}
 301			}
 302			
 303			public Socket Socket {
 304				get {
 305					return acc_socket;
 306				}
 307			}
 308
 309			public int Total {
 310				get { return total; }
 311				set { total = value; }
 312			}
 313
 314			public SocketError ErrorCode
 315			{
 316				get {
 317#if NET_2_0
 318					SocketException ex = delayedException as SocketException;
 319					
 320					if (ex != null)
 321						return(ex.SocketErrorCode);
 322
 323					if (error != 0)
 324						return((SocketError)error);
 325#endif
 326					return(SocketError.Success);
 327				}
 328			}
 329		}
 330
 331		private sealed class Worker 
 332		{
 333			SocketAsyncResult result;
 334
 335			public Worker (SocketAsyncResult ares)
 336			{
 337				this.result = ares;
 338			}
 339
 340			public void Accept ()
 341			{
 342				Socket acc_socket = null;
 343				try {
 344					acc_socket = result.Sock.Accept ();
 345				} catch (Exception e) {
 346					result.Complete (e);
 347					return;
 348				}
 349
 350				result.Complete (acc_socket);
 351			}
 352
 353			/* only used in 2.0 profile and newer, but
 354			 * leave in older profiles to keep interface
 355			 * to runtime consistent
 356			 */
 357			public void AcceptReceive ()
 358			{
 359				Socket acc_socket = null;
 360				
 361				try {
 362					if (result.AcceptSocket == null) {
 363						acc_socket = result.Sock.Accept ();
 364					} else {
 365						acc_socket = result.AcceptSocket;
 366						result.Sock.Accept (acc_socket);
 367					}
 368				} catch (Exception e) {
 369					result.Complete (e);
 370					return;
 371				}
 372
 373				/* It seems the MS runtime
 374				 * special-cases 0-length requested
 375				 * receive data.  See bug 464201.
 376				 */
 377				int total = 0;
 378				if (result.Size > 0) {
 379					try {
 380						SocketError error;
 381					
 382						total = acc_socket.Receive_nochecks (result.Buffer,
 383										     result.Offset,
 384										     result.Size,
 385										     result.SockFlags,
 386										     out error);
 387					} catch (Exception e) {
 388						result.Complete (e);
 389						return;
 390					}
 391				}
 392
 393				result.Complete (acc_socket, total);
 394			}
 395
 396			public void Connect ()
 397			{
 398				/* If result.EndPoint is non-null,
 399				 * this is the standard one-address
 400				 * connect attempt.  Otherwise
 401				 * Addresses must be non-null and
 402				 * contain a list of addresses to try
 403				 * to connect to; the first one to
 404				 * succeed causes the rest of the list
 405				 * to be ignored.
 406				 */
 407				if (result.EndPoint != null) {
 408					try {
 409						if (!result.Sock.Blocking) {
 410							int success;
 411							result.Sock.Poll (-1, SelectMode.SelectWrite, out success);
 412							if (success == 0) {
 413								result.Sock.connected = true;
 414							} else {
 415								result.Complete (new SocketException (success));
 416								return;
 417							}
 418						} else {
 419							result.Sock.seed_endpoint = result.EndPoint;
 420							result.Sock.Connect (result.EndPoint);
 421							result.Sock.connected = true;
 422						}
 423					} catch (Exception e) {
 424						result.Complete (e);
 425						return;
 426					}
 427
 428					result.Complete ();
 429				} else if (result.Addresses != null) {
 430					int error = (int) SocketError.InProgress; // why?
 431					foreach(IPAddress address in result.Addresses) {
 432						IPEndPoint iep = new IPEndPoint (address, result.Port);
 433						SocketAddress serial = iep.Serialize ();
 434						
 435						Socket.Connect_internal (result.Sock.socket, serial, out error);
 436						if (error == 0) {
 437							result.Sock.connected = true;
 438							result.Sock.seed_endpoint = iep;
 439							result.Complete ();
 440							return;
 441						} else if (error != (int)SocketError.InProgress &&
 442							   error != (int)SocketError.WouldBlock) {
 443							continue;
 444						}
 445
 446						if (!result.Sock.Blocking) {
 447							int success;
 448							result.Sock.Poll (-1, SelectMode.SelectWrite, out success);
 449							if (success == 0) {
 450								result.Sock.connected = true;
 451								result.Sock.seed_endpoint = iep;
 452								result.Complete ();
 453								return;
 454							}
 455						}
 456					}
 457					
 458					result.Complete (new SocketException (error));
 459				} else {
 460					result.Complete (new SocketException ((int)SocketError.AddressNotAvailable));
 461				}
 462			}
 463
 464			/* Also only used in 2.0 profile and newer */
 465			public void Disconnect ()
 466			{
 467#if NET_2_0
 468				try {
 469					result.Sock.Disconnect (result.ReuseSocket);
 470				} catch (Exception e) {
 471					result.Complete (e);
 472					return;
 473				}
 474				result.Complete ();
 475#else
 476				result.Complete (new SocketException ((int)SocketError.Fault));
 477#endif
 478			}
 479
 480			public void Receive ()
 481			{
 482				// Actual recv() done in the runtime
 483				result.Complete ();
 484			}
 485
 486			public void ReceiveFrom ()
 487			{
 488				int total = 0;
 489				try {
 490					total = result.Sock.ReceiveFrom_nochecks (result.Buffer,
 491									 result.Offset,
 492									 result.Size,
 493									 result.SockFlags,
 494									 ref result.EndPoint);
 495				} catch (Exception e) {
 496					result.Complete (e);
 497					return;
 498				}
 499
 500				result.Complete (total);
 501			}
 502
 503			public void ReceiveGeneric ()
 504			{
 505#if NET_2_0
 506				int total = 0;
 507				try {
 508					SocketError error;
 509					
 510					total = result.Sock.Receive (result.Buffers, result.SockFlags, out error);
 511				} catch (Exception e) {
 512					result.Complete (e);
 513					return;
 514				}
 515				
 516				result.Complete (total);
 517#else
 518				result.Complete (new SocketException ((int)SocketError.Fault));
 519#endif
 520			}
 521
 522			int send_so_far;
 523
 524			void UpdateSendValues (int last_sent)
 525			{
 526				if (result.error == 0) {
 527					send_so_far += last_sent;
 528					result.Offset += last_sent;
 529					result.Size -= last_sent;
 530				}
 531			}
 532
 533			public void Send ()
 534			{
 535				// Actual send() done in the runtime
 536				if (result.error == 0) {
 537					UpdateSendValues (result.Total);
 538					if (result.Sock.disposed) {
 539						result.Complete ();
 540						return;
 541					}
 542
 543					if (result.Size > 0) {
 544						SocketAsyncCall sac = new SocketAsyncCall (this.Send);
 545						sac.BeginInvoke (null, result);
 546						return; // Have to finish writing everything. See bug #74475.
 547					}
 548					result.Total = send_so_far;
 549				}
 550				result.Complete ();
 551			}
 552
 553			public void SendTo ()
 554			{
 555				int total = 0;
 556				try {
 557					total = result.Sock.SendTo_nochecks (result.Buffer,
 558								    result.Offset,
 559								    result.Size,
 560								    result.SockFlags,
 561								    result.EndPoint);
 562
 563					UpdateSendValues (total);
 564					if (result.Size > 0) {
 565						SocketAsyncCall sac = new SocketAsyncCall (this.SendTo);
 566						sac.BeginInvoke (null, result);
 567						return; // Have to finish writing everything. See bug #74475.
 568					}
 569					result.Total = send_so_far;
 570				} catch (Exception e) {
 571					result.Complete (e);
 572					return;
 573				}
 574
 575				result.Complete ();
 576			}
 577
 578			public void SendGeneric ()
 579			{
 580#if NET_2_0
 581				int total = 0;
 582				try {
 583					SocketError error;
 584					
 585					total = result.Sock.Send (result.Buffers, result.SockFlags, out error);
 586				} catch (Exception e) {
 587					result.Complete (e);
 588					return;
 589				}
 590				
 591				result.Complete (total);
 592#else
 593				result.Complete (new SocketException ((int)SocketError.Fault));
 594#endif
 595			}
 596		}
 597			
 598
 599		private Queue readQ = new Queue (2);
 600		private Queue writeQ = new Queue (2);
 601
 602		delegate void SocketAsyncCall ();
 603
 604#if NET_2_0
 605		private bool islistening;
 606		private bool useoverlappedIO;
 607#endif
 608		
 609
 610		static void AddSockets (ArrayList sockets, IList list, string name)
 611		{
 612			if (list != null) {
 613				foreach (Socket sock in list) {
 614					if (sock == null) // MS throws a NullRef
 615						throw new ArgumentNullException ("name", "Contains a null element");
 616					sockets.Add (sock);
 617				}
 618			}
 619
 620			sockets.Add (null);
 621		}
 622#if !TARGET_JVM
 623		[MethodImplAttribute(MethodImplOptions.InternalCall)]
 624		private extern static void Select_internal (ref Socket [] sockets,
 625							int microSeconds,
 626							out int error);
 627#endif
 628		public static void Select (IList checkRead, IList checkWrite, IList checkError, int microSeconds)
 629		{
 630			ArrayList list = new ArrayList ();
 631			AddSockets (list, checkRead, "checkRead");
 632			AddSockets (list, checkWrite, "checkWrite");
 633			AddSockets (list, checkError, "checkError");
 634
 635			if (list.Count == 3) {
 636				throw new ArgumentNullException ("checkRead, checkWrite, checkError",
 637								 "All the lists are null or empty.");
 638			}
 639
 640			int error;
 641			/*
 642			 * The 'sockets' array contains: READ socket 0-n, null,
 643			 * 				 WRITE socket 0-n, null,
 644			 *				 ERROR socket 0-n, null
 645			 */
 646			Socket [] sockets = (Socket []) list.ToArray (typeof (Socket));
 647			Select_internal (ref sockets, microSeconds, out error);
 648
 649			if (error != 0)
 650				throw new SocketException (error);
 651
 652			if (sockets == null) {
 653				if (checkRead != null)
 654					checkRead.Clear ();
 655				if (checkWrite != null)
 656					checkWrite.Clear ();
 657				if (checkError != null)
 658					checkError.Clear ();
 659				return;
 660			}
 661
 662			int mode = 0;
 663			int count = sockets.Length;
 664			IList currentList = checkRead;
 665			int currentIdx = 0;
 666			for (int i = 0; i < count; i++) {
 667				Socket cur_sock;
 668				Socket sock = sockets [i];
 669				if (sock == null) { // separator
 670					if (currentList != null) {
 671						// Remove non-signaled sockets after the current one
 672						int to_remove = currentList.Count - currentIdx;
 673						for (int k = 0; k < to_remove; k++)
 674							currentList.RemoveAt (currentIdx);
 675					}
 676					currentList = (mode == 0) ? checkWrite : checkError;
 677					currentIdx = 0;
 678					mode++;
 679					continue;
 680				}
 681
 682				if (mode == 1 && currentList == checkWrite && !sock.connected) {
 683					if ((int) sock.GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error) == 0)
 684						sock.connected = true;
 685				}
 686
 687				// Remove non-signaled sockets before the current one
 688				int max = currentList.Count;
 689				while ((cur_sock = (Socket) currentList [currentIdx]) != sock) {
 690					currentList.RemoveAt (currentIdx);
 691				}
 692				currentIdx++;
 693			}
 694		}
 695
 696		// private constructor used by Accept, which already
 697		// has a socket handle to use
 698		private Socket(AddressFamily family, SocketType type,
 699			       ProtocolType proto, IntPtr sock)
 700		{
 701			address_family=family;
 702			socket_type=type;
 703			protocol_type=proto;
 704			
 705			socket=sock;
 706			connected=true;
 707		}
 708
 709		private void SocketDefaults ()
 710		{
 711#if NET_2_0
 712			try {
 713				if (address_family == AddressFamily.InterNetwork /* Need to test IPv6 further ||
 714										   address_family == AddressFamily.InterNetworkV6 */) {
 715					/* This is the default, but it
 716					 * probably has nasty side
 717					 * effects on Linux, as the
 718					 * socket option is kludged by
 719					 * turning on or off PMTU
 720					 * discovery...
 721					 */
 722					this.DontFragment = false;
 723				}
 724
 725				//
 726				// Microsoft sets these to 8192, but we are going to keep them
 727				// both to the OS defaults as these have a big performance impact.
 728				// on WebClient performance.
 729				//
 730				//this.ReceiveBufferSize = 8192;
 731				//this.SendBufferSize = 8192;
 732			} catch (SocketException) {
 733			}
 734#endif
 735		}
 736
 737
 738#if NET_2_0
 739		[MonoTODO]
 740		public Socket (SocketInformation socketInformation)
 741		{
 742			throw new NotImplementedException ("SocketInformation not figured out yet");
 743
 744			// ifdef to avoid the warnings.
 745#if false
 746			//address_family = socketInformation.address_family;
 747			//socket_type = socketInformation.socket_type;
 748			//protocol_type = socketInformation.protocol_type;
 749			address_family = AddressFamily.InterNetwork;
 750			socket_type = SocketType.Stream;
 751			protocol_type = ProtocolType.IP;
 752			
 753			int error;
 754			socket = Socket_internal (address_family, socket_type, protocol_type, out error);
 755			if (error != 0)
 756				throw new SocketException (error);
 757
 758			SocketDefaults ();
 759#endif
 760		}
 761#endif
 762
 763#if !TARGET_JVM
 764		// Returns the amount of data waiting to be read on socket
 765		[MethodImplAttribute(MethodImplOptions.InternalCall)]
 766		private extern static int Available_internal(IntPtr socket, out int error);
 767#endif
 768
 769		public int Available {
 770			get {
 771				if (disposed && closed)
 772					throw new ObjectDisposedException (GetType ().ToString ());
 773
 774				int ret, error;
 775				
 776				ret = Available_internal(socket, out error);
 777
 778				if (error != 0)
 779					throw new SocketException (error);
 780
 781				return(ret);
 782			}
 783		}
 784
 785
 786#if NET_2_0
 787		public bool DontFragment {
 788			get {
 789				if (disposed && closed) {
 790					throw new ObjectDisposedException (GetType ().ToString ());
 791				}
 792
 793				bool dontfragment;
 794				
 795				if (address_family == AddressFamily.InterNetwork) {
 796					dontfragment = (int)(GetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment)) != 0;
 797				} else if (address_family == AddressFamily.InterNetworkV6) {
 798					dontfragment = (int)(GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment)) != 0;
 799				} else {
 800					throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
 801				}
 802				
 803				return(dontfragment);
 804			}
 805			set {
 806				if (disposed && closed) {
 807					throw new ObjectDisposedException (GetType ().ToString ());
 808				}
 809
 810				if (address_family == AddressFamily.InterNetwork) {
 811					SetSocketOption (SocketOptionLevel.IP, SocketOptionName.DontFragment, value?1:0);
 812				} else if (address_family == AddressFamily.InterNetworkV6) {
 813					SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.DontFragment, value?1:0);
 814				} else {
 815					throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
 816				}
 817			}
 818		}
 819
 820		public bool EnableBroadcast {
 821			get {
 822				if (disposed && closed) {
 823					throw new ObjectDisposedException (GetType ().ToString ());
 824				}
 825
 826				if (protocol_type != ProtocolType.Udp) {
 827					throw new SocketException ((int)SocketError.ProtocolOption);
 828				}
 829				
 830				return((int)(GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast)) != 0);
 831			}
 832			set {
 833				if (disposed && closed) {
 834					throw new ObjectDisposedException (GetType ().ToString ());
 835				}
 836
 837				if (protocol_type != ProtocolType.Udp) {
 838					throw new SocketException ((int)SocketError.ProtocolOption);
 839				}
 840
 841				SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Broadcast, value?1:0);
 842			}
 843		}
 844		
 845		public bool ExclusiveAddressUse {
 846			get {
 847				if (disposed && closed) {
 848					throw new ObjectDisposedException (GetType ().ToString ());
 849				}
 850
 851				return((int)(GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse)) != 0);
 852			}
 853			set {
 854				if (disposed && closed) {
 855					throw new ObjectDisposedException (GetType ().ToString ());
 856				}
 857				if (isbound) {
 858					throw new InvalidOperationException ("Bind has already been called for this socket");
 859				}
 860				
 861				SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ExclusiveAddressUse, value?1:0);
 862			}
 863		}
 864		
 865		public bool IsBound {
 866			get {
 867				return(isbound);
 868			}
 869		}
 870		
 871		public LingerOption LingerState {
 872			get {
 873				if (disposed && closed) {
 874					throw new ObjectDisposedException (GetType ().ToString ());
 875				}
 876
 877				return((LingerOption)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Linger));
 878			}
 879			set {
 880				if (disposed && closed) {
 881					throw new ObjectDisposedException (GetType ().ToString ());
 882				}
 883				
 884				SetSocketOption (SocketOptionLevel.Socket,
 885						 SocketOptionName.Linger,
 886						 value);
 887			}
 888		}
 889		
 890		public bool MulticastLoopback {
 891			get {
 892				if (disposed && closed) {
 893					throw new ObjectDisposedException (GetType ().ToString ());
 894				}
 895
 896				/* Even though this option can be set
 897				 * for TCP sockets on Linux, throw
 898				 * this exception anyway to be
 899				 * compatible (the MSDN docs say
 900				 * "Setting this property on a
 901				 * Transmission Control Protocol (TCP)
 902				 * socket will have no effect." but
 903				 * the MS runtime throws the
 904				 * exception...)
 905				 */
 906				if (protocol_type == ProtocolType.Tcp) {
 907					throw new SocketException ((int)SocketError.ProtocolOption);
 908				}
 909				
 910				bool multicastloopback;
 911				
 912				if (address_family == AddressFamily.InterNetwork) {
 913					multicastloopback = (int)(GetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback)) != 0;
 914				} else if (address_family == AddressFamily.InterNetworkV6) {
 915					multicastloopback = (int)(GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback)) != 0;
 916				} else {
 917					throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
 918				}
 919				
 920				return(multicastloopback);
 921			}
 922			set {
 923				if (disposed && closed) {
 924					throw new ObjectDisposedException (GetType ().ToString ());
 925				}
 926
 927				/* Even though this option can be set
 928				 * for TCP sockets on Linux, throw
 929				 * this exception anyway to be
 930				 * compatible (the MSDN docs say
 931				 * "Setting this property on a
 932				 * Transmission Control Protocol (TCP)
 933				 * socket will have no effect." but
 934				 * the MS runtime throws the
 935				 * exception...)
 936				 */
 937				if (protocol_type == ProtocolType.Tcp) {
 938					throw new SocketException ((int)SocketError.ProtocolOption);
 939				}
 940				
 941				if (address_family == AddressFamily.InterNetwork) {
 942					SetSocketOption (SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, value?1:0);
 943				} else if (address_family == AddressFamily.InterNetworkV6) {
 944					SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.MulticastLoopback, value?1:0);
 945				} else {
 946					throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
 947				}
 948			}
 949		}
 950		
 951		
 952		[MonoTODO ("This doesn't do anything on Mono yet")]
 953		public bool UseOnlyOverlappedIO {
 954			get {
 955				return(useoverlappedIO);
 956			}
 957			set {
 958				useoverlappedIO = value;
 959			}
 960		}
 961#endif
 962
 963		public IntPtr Handle {
 964			get {
 965				return(socket);
 966			}
 967		}
 968
 969#if !TARGET_JVM
 970		// Returns the local endpoint details in addr and port
 971		[MethodImplAttribute(MethodImplOptions.InternalCall)]
 972		private extern static SocketAddress LocalEndPoint_internal(IntPtr socket, out int error);
 973#endif
 974
 975		// Wish:  support non-IP endpoints.
 976		public EndPoint LocalEndPoint {
 977			get {
 978				if (disposed && closed)
 979					throw new ObjectDisposedException (GetType ().ToString ());
 980				
 981				/*
 982				 * If the seed EndPoint is null, Connect, Bind,
 983				 * etc has not yet been called. MS returns null
 984				 * in this case.
 985				 */
 986				if (seed_endpoint == null)
 987					return null;
 988				
 989				SocketAddress sa;
 990				int error;
 991				
 992				sa=LocalEndPoint_internal(socket, out error);
 993
 994				if (error != 0)
 995					throw new SocketException (error);
 996
 997				return seed_endpoint.Create (sa);
 998			}
 999		}
1000
1001		public SocketType SocketType {
1002			get {
1003				return(socket_type);
1004			}
1005		}
1006
1007#if NET_2_0
1008		public int SendTimeout {
1009			get {
1010				if (disposed && closed)
1011					throw new ObjectDisposedException (GetType ().ToString ());
1012
1013				return (int)GetSocketOption(
1014					SocketOptionLevel.Socket,
1015					SocketOptionName.SendTimeout);
1016			}
1017			set {
1018				if (disposed && closed)
1019					throw new ObjectDisposedException (GetType ().ToString ());
1020
1021				if (value < -1)
1022					throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
1023
1024				/* According to the MSDN docs we
1025				 * should adjust values between 1 and
1026				 * 499 to 500, but the MS runtime
1027				 * doesn't do this.
1028				 */
1029				if (value == -1)
1030					value = 0;
1031
1032				SetSocketOption(
1033					SocketOptionLevel.Socket,
1034					SocketOptionName.SendTimeout, value);
1035			}
1036		}
1037
1038		public int ReceiveTimeout {
1039			get {
1040				if (disposed && closed)
1041					throw new ObjectDisposedException (GetType ().ToString ());
1042
1043				return (int)GetSocketOption(
1044					SocketOptionLevel.Socket,
1045					SocketOptionName.ReceiveTimeout);
1046			}
1047			set {
1048				if (disposed && closed)
1049					throw new ObjectDisposedException (GetType ().ToString ());
1050
1051				if (value < -1)
1052					throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than -1");
1053
1054				if (value == -1) {
1055					value = 0;
1056				}
1057				
1058				SetSocketOption(
1059					SocketOptionLevel.Socket,
1060					SocketOptionName.ReceiveTimeout, value);
1061			}
1062		}
1063
1064		public bool AcceptAsync (SocketAsyncEventArgs e)
1065		{
1066			// NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1067			
1068			if (disposed && closed)
1069				throw new ObjectDisposedException (GetType ().ToString ());
1070			if (!IsBound)
1071				throw new InvalidOperationException ("You must call the Bind method before performing this operation.");
1072			if (!islistening)
1073				throw new InvalidOperationException ("You must call the Listen method before performing this operation.");
1074			if (e.BufferList != null)
1075				throw new ArgumentException ("Multiple buffers cannot be used with this method.");
1076			if (e.Count < 0)
1077				throw new ArgumentOutOfRangeException ("e.Count");
1078			
1079			Socket acceptSocket = e.AcceptSocket;
1080			if (acceptSocket != null) {
1081				if (acceptSocket.IsBound || acceptSocket.Connected)
1082					throw new InvalidOperationException ("AcceptSocket: The socket must not be bound or connected.");
1083			} else
1084				e.AcceptSocket = new Socket (AddressFamily, SocketType, ProtocolType);
1085
1086			try {
1087				e.DoOperation (SocketAsyncOperation.Accept, this);
1088			} catch {
1089				((IDisposable)e).Dispose ();
1090				throw;
1091			}
1092
1093			// We always return true for now
1094			return true;
1095		}
1096#endif
1097		
1098		// Creates a new system socket, returning the handle
1099		[MethodImplAttribute(MethodImplOptions.InternalCall)]
1100		private extern static IntPtr Accept_internal(IntPtr sock, out int error, bool blocking);
1101
1102		public Socket Accept() {
1103			if (disposed && closed)
1104				throw new ObjectDisposedException (GetType ().ToString ());
1105
1106			int error = 0;
1107			IntPtr sock = (IntPtr) (-1);
1108			blocking_thread = Thread.CurrentThread;
1109			try {
1110				sock = Accept_internal(socket, out error, blocking);
1111			} catch (ThreadAbortException) {
1112				if (disposed) {
1113					Thread.ResetAbort ();
1114					error = (int) SocketError.Interrupted;
1115				}
1116			} finally {
1117				blocking_thread = null;
1118			}
1119
1120			if (error != 0)
1121				throw new SocketException (error);
1122			
1123			Socket accepted = new Socket(this.AddressFamily, this.SocketType,
1124				this.ProtocolType, sock);
1125
1126			accepted.seed_endpoint = this.seed_endpoint;
1127			accepted.Blocking = this.Blocking;
1128			return(accepted);
1129		}
1130
1131		internal void Accept (Socket acceptSocket)
1132		{
1133			if (disposed && closed)
1134				throw new ObjectDisposedException (GetType ().ToString ());
1135			
1136			int error = 0;
1137			IntPtr sock = (IntPtr)(-1);
1138			blocking_thread = Thread.CurrentThread;
1139			
1140			try {
1141				sock = Accept_internal (socket, out error, blocking);
1142			} catch (ThreadAbortException) {
1143				if (disposed) {
1144					Thread.ResetAbort ();
1145					error = (int)SocketError.Interrupted;
1146				}
1147			} finally {
1148				blocking_thread = null;
1149			}
1150			
1151			if (error != 0)
1152				throw new SocketException (error);
1153			
1154			acceptSocket.address_family = this.AddressFamily;
1155			acceptSocket.socket_type = this.SocketType;
1156			acceptSocket.protocol_type = this.ProtocolType;
1157			acceptSocket.socket = sock;
1158			acceptSocket.connected = true;
1159			acceptSocket.seed_endpoint = this.seed_endpoint;
1160			acceptSocket.Blocking = this.Blocking;
1161
1162			/* FIXME: figure out what if anything else
1163			 * needs to be reset
1164			 */
1165		}
1166
1167		public IAsyncResult BeginAccept(AsyncCallback callback,
1168						object state)
1169		{
1170			if (disposed && closed)
1171				throw new ObjectDisposedException (GetType ().ToString ());
1172
1173#if NET_2_0
1174			/* FIXME: check the 1.1 docs for this too */
1175			if (!isbound || !islistening)
1176				throw new InvalidOperationException ();
1177#endif
1178
1179			SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Accept);
1180			Worker worker = new Worker (req);
1181			SocketAsyncCall sac = new SocketAsyncCall (worker.Accept);
1182			sac.BeginInvoke (null, req);
1183			return(req);
1184		}
1185
1186#if NET_2_0
1187		public IAsyncResult BeginAccept (int receiveSize,
1188						 AsyncCallback callback,
1189						 object state)
1190		{
1191			if (disposed && closed)
1192				throw new ObjectDisposedException (GetType ().ToString ());
1193
1194			if (receiveSize < 0)
1195				throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
1196
1197			SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive);
1198			Worker worker = new Worker (req);
1199			SocketAsyncCall sac = new SocketAsyncCall (worker.AcceptReceive);
1200			
1201			req.Buffer = new byte[receiveSize];
1202			req.Offset = 0;
1203			req.Size = receiveSize;
1204			req.SockFlags = SocketFlags.None;
1205
1206			sac.BeginInvoke (null, req);
1207			return(req);
1208		}
1209
1210		public IAsyncResult BeginAccept (Socket acceptSocket,
1211						 int receiveSize,
1212						 AsyncCallback callback,
1213						 object state)
1214		{
1215			if (disposed && closed)
1216				throw new ObjectDisposedException (GetType ().ToString ());
1217
1218			if (receiveSize < 0)
1219				throw new ArgumentOutOfRangeException ("receiveSize", "receiveSize is less than zero");
1220
1221			if (acceptSocket != null) {
1222				if (acceptSocket.disposed && acceptSocket.closed)
1223					throw new ObjectDisposedException (acceptSocket.GetType ().ToString ());
1224
1225				if (acceptSocket.IsBound)
1226					throw new InvalidOperationException ();
1227
1228				/* For some reason the MS runtime
1229				 * barfs if the new socket is not TCP,
1230				 * even though it's just about to blow
1231				 * away all those parameters
1232				 */
1233				if (acceptSocket.ProtocolType != ProtocolType.Tcp)
1234					throw new SocketException ((int)SocketError.InvalidArgument);
1235			}
1236			
1237			SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.AcceptReceive);
1238			Worker worker = new Worker (req);
1239			SocketAsyncCall sac = new SocketAsyncCall (worker.AcceptReceive);
1240			
1241			req.Buffer = new byte[receiveSize];
1242			req.Offset = 0;
1243			req.Size = receiveSize;
1244			req.SockFlags = SocketFlags.None;
1245			req.AcceptSocket = acceptSocket;
1246
1247			sac.BeginInvoke (null, req);
1248			return(req);
1249		}
1250#endif
1251
1252		public IAsyncResult BeginConnect(EndPoint end_point,
1253						 AsyncCallback callback,
1254						 object state) {
1255
1256			if (disposed && closed)
1257				throw new ObjectDisposedException (GetType ().ToString ());
1258
1259			if (end_point == null)
1260				throw new ArgumentNullException ("end_point");
1261
1262			SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
1263			req.EndPoint = end_point;
1264
1265			// Bug #75154: Connect() should not succeed for .Any addresses.
1266			if (end_point is IPEndPoint) {
1267				IPEndPoint ep = (IPEndPoint) end_point;
1268				if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any)) {
1269					req.Complete (new SocketException ((int) SocketError.AddressNotAvailable), true);
1270					return req;
1271				}
1272			}
1273
1274			int error = 0;
1275			if (!blocking) {
1276				SocketAddress serial = end_point.Serialize ();
1277				Connect_internal (socket, serial, out error);
1278				if (error == 0) {
1279					// succeeded synch
1280					connected = true;
1281					req.Complete (true);
1282				} else if (error != (int) SocketError.InProgress && error != (int) SocketError.WouldBlock) {
1283					// error synch
1284					connected = false;
1285					req.Complete (new SocketException (error), true);
1286				}
1287			}
1288
1289			if (blocking || error == (int) SocketError.InProgress || error == (int) SocketError.WouldBlock) {
1290				// continue asynch
1291				connected = false;
1292				Worker worker = new Worker (req);
1293				SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
1294				sac.BeginInvoke (null, req);
1295			}
1296
1297			return(req);
1298		}
1299
1300#if NET_2_0
1301		public IAsyncResult BeginConnect (IPAddress address, int port,
1302						  AsyncCallback callback,
1303						  object state)
1304		{
1305			if (disposed && closed)
1306				throw new ObjectDisposedException (GetType ().ToString ());
1307
1308			if (address == null)
1309				throw new ArgumentNullException ("address");
1310
1311			if (address.ToString ().Length == 0)
1312				throw new ArgumentException ("The length of the IP address is zero");
1313
1314			if (islistening)
1315				throw new InvalidOperationException ();
1316
1317			IPEndPoint iep = new IPEndPoint (address, port);
1318			return(BeginConnect (iep, callback, state));
1319		}
1320
1321		public IAsyncResult BeginConnect (IPAddress[] addresses,
1322						  int port,
1323						  AsyncCallback callback,
1324						  object state)
1325		{
1326			if (disposed && closed)
1327				throw new ObjectDisposedException (GetType ().ToString ());
1328
1329			if (addresses == null)
1330				throw new ArgumentNullException ("addresses");
1331
1332			if (this.AddressFamily != AddressFamily.InterNetwork &&
1333				this.AddressFamily != AddressFamily.InterNetworkV6)
1334				throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
1335
1336			if (islistening)
1337				throw new InvalidOperationException ();
1338
1339			SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Connect);
1340			req.Addresses = addresses;
1341			req.Port = port;
1342			
1343			connected = false;
1344			Worker worker = new Worker (req);
1345			SocketAsyncCall sac = new SocketAsyncCall (worker.Connect);
1346			sac.BeginInvoke (null, req);
1347			
1348			return(req);
1349		}
1350
1351		public IAsyncResult BeginConnect (string host, int port,
1352						  AsyncCallback callback,
1353						  object state)
1354		{
1355			if (disposed && closed)
1356				throw new ObjectDisposedException (GetType ().ToString ());
1357
1358			if (host == null)
1359				throw new ArgumentNullException ("host");
1360
1361			if (address_family != AddressFamily.InterNetwork &&
1362				address_family != AddressFamily.InterNetworkV6)
1363				throw new NotSupportedException ("This method is valid only for sockets in the InterNetwork and InterNetworkV6 families");
1364
1365			if (islistening)
1366				throw new InvalidOperationException ();
1367
1368			IPAddress [] addresses = Dns.GetHostAddresses (host);
1369			return (BeginConnect (addresses, port, callback, state));
1370		}
1371
1372		public IAsyncResult BeginDisconnect (bool reuseSocket,
1373						     AsyncCallback callback,
1374						     object state)
1375		{
1376			if (disposed && closed)
1377				throw new ObjectDisposedException (GetType ().ToString ());
1378
1379			SocketAsyncResult req = new SocketAsyncResult (this, state, callback, SocketOperation.Disconnect);
1380			req.ReuseSocket = reuseSocket;
1381			
1382			Worker worker = new Worker (req);
1383			SocketAsyncCall sac = new SocketAsyncCall (worker.Disconnect);
1384			sac.BeginInvoke (null, req);
1385			
1386			return(req);
1387		}
1388#endif
1389		
1390		public IAsyncResult BeginReceive(byte[] buffer, int offset,
1391						 int size,
1392						 SocketFlags socket_flags,
1393						 AsyncCallback callback,
1394						 object state) {
1395
1396			if (disposed && closed)
1397				throw new ObjectDisposedException (GetType ().ToString ());
1398
1399			if (buffer == null)
1400				throw new ArgumentNullException ("buffer");
1401
1402			if (offset < 0 || offset > buffer.Length)
1403				throw new ArgumentOutOfRangeException ("offset");
1404
1405			if (size < 0 || offset + size > buffer.Length)
1406				throw new ArgumentOutOfRangeException ("size");
1407
1408			SocketAsyncResult req;
1409			lock (readQ) {
1410				req = new SocketAsyncResult (this, state, callback, SocketOperation.Receive);
1411				req.Buffer = buffer;
1412				req.Offset = offset;
1413				req.Size = size;
1414				req.SockFlags = socket_flags;
1415				readQ.Enqueue (req);
1416				if (readQ.Count == 1) {
1417					Worker worker = new Worker (req);
1418					SocketAsyncCall sac = new SocketAsyncCall (worker.Receive);
1419					sac.BeginInvoke (null, req);
1420				}
1421			}
1422
1423			return req;
1424		}
1425#if NET_2_0
1426		public IAsyncResult BeginReceive (byte[] buffer, int offset,
1427						  int size, SocketFlags flags,
1428						  out SocketError error,
1429						  AsyncCallback callback,
1430						  object state)
1431		{
1432			/* As far as I can tell from the docs and from
1433			 * experimentation, a pointer to the
1434			 * SocketError parameter is not supposed to be
1435			 * saved for the async parts.  And as we don't
1436			 * set any socket errors in the setup code, we
1437			 * just have to set it to Success.
1438			 */
1439			error = SocketError.Success;
1440			return (BeginReceive (buffer, offset, size, flags, callback, state));
1441		}
1442
1443		[CLSCompliant (false)]
1444		public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers,
1445						  SocketFlags socketFlags,
1446						  AsyncCallback callback,
1447						  object state)
1448		{
1449			if (disposed && closed)
1450				throw new ObjectDisposedException (GetType ().ToString ());
1451
1452			if (buffers == null)
1453				throw new ArgumentNullException ("buffers");
1454
1455			SocketAsyncResult req;
1456			lock(readQ) {
1457				req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveGeneric);
1458				req.Buffers = buffers;
1459				req.SockFlags = socketFlags;
1460				readQ.Enqueue (req);
1461				if (readQ.Count == 1) {
1462					Worker worker = new Worker (req);
1463					SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveGeneric);
1464					sac.BeginInvoke (null, req);
1465				}
1466			}
1467			
1468			return(req);
1469		}
1470		
1471		[CLSCompliant (false)]
1472		public IAsyncResult BeginReceive (IList<ArraySegment<byte>> buffers,
1473						  SocketFlags socketFlags,
1474						  out SocketError errorCode,
1475						  AsyncCallback callback,
1476						  object state)
1477		{
1478			/* I assume the same SocketError semantics as
1479			 * above
1480			 */
1481			errorCode = SocketError.Success;
1482			return (BeginReceive (buffers, socketFlags, callback, state));
1483		}
1484#endif
1485
1486		public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
1487						     int size,
1488						     SocketFlags socket_flags,
1489						     ref EndPoint remote_end,
1490						     AsyncCallback callback,
1491						     object state) {
1492			if (disposed && closed)
1493				throw new ObjectDisposedException (GetType ().ToString ());
1494
1495			if (buffer == null)
1496				throw new ArgumentNullException ("buffer");
1497
1498			if (offset < 0)
1499				throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
1500
1501			if (size < 0)
1502				throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
1503
1504			if (offset + size > buffer.Length)
1505				throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
1506
1507			SocketAsyncResult req;
1508			lock (readQ) {
1509				req = new SocketAsyncResult (this, state, callback, SocketOperation.ReceiveFrom);
1510				req.Buffer = buffer;
1511				req.Offset = offset;
1512				req.Size = size;
1513				req.SockFlags = socket_flags;
1514				req.EndPoint = remote_end;
1515				readQ.Enqueue (req);
1516				if (readQ.Count == 1) {
1517					Worker worker = new Worker (req);
1518					SocketAsyncCall sac = new SocketAsyncCall (worker.ReceiveFrom);
1519					sac.BeginInvoke (null, req);
1520				}
1521			}
1522			return req;
1523		}
1524
1525#if NET_2_0
1526		[MonoTODO]
1527		public IAsyncResult BeginReceiveMessageFrom (
1528			byte[] buffer, int offset, int size,
1529			SocketFlags socketFlags, ref EndPoint remoteEP,
1530			AsyncCallback callback, object state)
1531		{
1532			if (disposed && closed)
1533				throw new ObjectDisposedException (GetType ().ToString ());
1534
1535			if (buffer == null)
1536				throw new ArgumentNullException ("buffer");
1537
1538			if (remoteEP == null)
1539				throw new ArgumentNullException ("remoteEP");
1540
1541			if (offset < 0 || offset > buffer.Length)
1542				throw new ArgumentOutOfRangeException ("offset");
1543
1544			if (size < 0 || offset + size > buffer.Length)
1545				throw new ArgumentOutOfRangeException ("size");
1546
1547			throw new NotImplementedException ();
1548		}
1549#endif
1550
1551		public IAsyncResult BeginSend (byte[] buffer, int offset, int size, SocketFlags socket_flags,
1552					       AsyncCallback callback, object state)
1553		{
1554			if (disposed && closed)
1555				throw new ObjectDisposedException (GetType ().ToString ());
1556
1557			if (buffer == null)
1558				throw new ArgumentNullException ("buffer");
1559
1560			if (offset < 0)
1561				throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
1562
1563			if (size < 0)
1564				throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
1565
1566			if (offset + size > buffer.Length)
1567				throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
1568
1569#if NET_2_0
1570			/* TODO: Check this exception in the 1.1 profile */
1571			if (!connected)
1572				throw new SocketException ((int)SocketError.NotConnected);
1573#endif
1574
1575			SocketAsyncResult req;
1576			lock (writeQ) {
1577				req = new SocketAsyncResult (this, state, callback, SocketOperation.Send);
1578				req.Buffer = buffer;
1579				req.Offset = offset;
1580				req.Size = size;
1581				req.SockFlags = socket_flags;
1582				writeQ.Enqueue (req);
1583				if (writeQ.Count == 1) {
1584					Worker worker = new Worker (req);
1585					SocketAsyncCall sac = new SocketAsyncCall (worker.Send);
1586					sac.BeginInvoke (null, req);
1587				}
1588			}
1589			return req;
1590		}
1591
1592#if NET_2_0
1593		public IAsyncResult BeginSend (byte[] buffer, int offset,
1594					       int size,
1595					       SocketFlags socketFlags,
1596					       out SocketError errorCode,
1597					       AsyncCallback callback,
1598					       object state)
1599		{
1600			if (!connected) {
1601				errorCode = SocketError.NotConnected;
1602				throw new SocketException ((int)errorCode);
1603			}
1604			
1605			errorCode = SocketError.Success;
1606			
1607			return (BeginSend (buffer, offset, size, socketFlags, callback,
1608				state));
1609		}
1610
1611		public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers,
1612					       SocketFlags socketFlags,
1613					       AsyncCallback callback,
1614					       object state)
1615		{
1616			if (disposed && closed)
1617				throw new ObjectDisposedException (GetType ().ToString ());
1618
1619			if (buffers == null)
1620				throw new ArgumentNullException ("buffers");
1621
1622			if (!connected)
1623				throw new SocketException ((int)SocketError.NotConnected);
1624
1625			SocketAsyncResult req;
1626			lock (writeQ) {
1627				req = new SocketAsyncResult (this, state, callback, SocketOperation.SendGeneric);
1628				req.Buffers = buffers;
1629				req.SockFlags = socketFlags;
1630				writeQ.Enqueue (req);
1631				if (writeQ.Count == 1) {
1632					Worker worker = new Worker (req);
1633					SocketAsyncCall sac = new SocketAsyncCall (worker.SendGeneric);
1634					sac.BeginInvoke (null, req);
1635				}
1636			}
1637			
1638			return(req);
1639		}
1640
1641		[CLSCompliant (false)]
1642		public IAsyncResult BeginSend (IList<ArraySegment<byte>> buffers,
1643					       SocketFlags socketFlags,
1644					       out SocketError errorCode,
1645					       AsyncCallback callback,
1646					       object state)
1647		{
1648			if (!connected) {
1649				errorCode = SocketError.NotConnected;
1650				throw new SocketException ((int)errorCode);
1651			}
1652			
1653			errorCode = SocketError.Success;
1654			return (BeginSend (buffers, socketFlags, callback, state));
1655		}
1656
1657		delegate void SendFileHandler (string fileName, byte [] preBuffer, byte [] postBuffer, TransmitFileOptions flags);
1658
1659		sealed class SendFileAsyncResult : IAsyncResult {
1660			IAsyncResult ares;
1661			SendFileHandler d;
1662
1663			public SendFileAsyncResult (SendFileHandler d, IAsyncResult ares)
1664			{
1665				this.d = d;
1666				this.ares = ares;
1667			}
1668
1669			public object AsyncState {
1670				get { return ares.AsyncState; }
1671			}
1672
1673			public WaitHandle AsyncWaitHandle {
1674				get { return ares.AsyncWaitHandle; }
1675			}
1676
1677			public bool CompletedSynchronously {
1678				get { return ares.CompletedSynchronously; }
1679			}
1680
1681			public bool IsCompleted {
1682				get { return ares.IsCompleted; }
1683			}
1684
1685			public SendFileHandler Delegate {
1686				get { return d; }
1687			}
1688
1689			public IAsyncResult Original {
1690				get { return ares; }
1691			}
1692		}
1693
1694		public IAsyncResult BeginSendFile (string fileName,
1695						   AsyncCallback callback,
1696						   object state)
1697		{
1698			if (disposed && closed)
1699				throw new ObjectDisposedException (GetType ().ToString ());
1700
1701			if (!connected)
1702				throw new NotSupportedException ();
1703
1704			if (!File.Exists (fileName))
1705				throw new FileNotFoundException ();
1706
1707			return BeginSendFile (fileName, null, null, 0, callback, state);
1708		}
1709
1710		public IAsyncResult BeginSendFile (string fileName,
1711						   byte[] preBuffer,
1712						   byte[] postBuffer,
1713						   TransmitFileOptions flags,
1714						   AsyncCallback callback,
1715						   object state)
1716		{
1717			if (disposed && closed)
1718				throw new ObjectDisposedException (GetType ().ToString ());
1719
1720			if (!connected)
1721				throw new NotSupportedException ();
1722
1723			if (!File.Exists (fileName))
1724				throw new FileNotFoundException ();
1725
1726			SendFileHandler d = new SendFileHandler (SendFile);
1727			return new SendFileAsyncResult (d, d.BeginInvoke (fileName, preBuffer, postBuffer, flags, callback, state));
1728		}
1729#endif
1730
1731		public IAsyncResult BeginSendTo(byte[] buffer, int offset,
1732						int size,
1733						SocketFlags socket_flags,
1734						EndPoint remote_end,
1735						AsyncCallback callback,
1736						object state) {
1737			if (disposed && closed)
1738				throw new ObjectDisposedException (GetType ().ToString ());
1739
1740			if (buffer == null)
1741				throw new ArgumentNullException ("buffer");
1742
1743			if (offset < 0)
1744				throw new ArgumentOutOfRangeException ("offset", "offset must be >= 0");
1745
1746			if (size < 0)
1747				throw new ArgumentOutOfRangeException ("size", "size must be >= 0");
1748
1749			if (offset + size > buffer.Length)
1750				throw new ArgumentOutOfRangeException ("offset, size", "offset + size exceeds the buffer length");
1751
1752			SocketAsyncResult req;
1753			lock (writeQ) {
1754				req = new SocketAsyncResult (this, state, callback, SocketOperation.SendTo);
1755				req.Buffer = buffer;
1756				req.Offset = offset;
1757				req.Size = size;
1758				req.SockFlags = socket_flags;
1759				req.EndPoint = remote_end;
1760				writeQ.Enqueue (req);
1761				if (writeQ.Count == 1) {
1762					Worker worker = new Worker (req);
1763					SocketAsyncCall sac = new SocketAsyncCall (worker.SendTo);
1764					sac.BeginInvoke (null, req);
1765				}
1766			}
1767			return req;
1768		}
1769
1770		// Creates a new system socket, returning the handle
1771		[MethodImplAttribute(MethodImplOptions.InternalCall)]
1772		private extern static void Bind_internal(IntPtr sock,
1773							 SocketAddress sa,
1774							 out int error);
1775
1776		public void Bind(EndPoint local_end) {
1777			if (disposed && closed)
1778				throw new ObjectDisposedException (GetType ().ToString ());
1779
1780			if (local_end == null)
1781				throw new ArgumentNullException("local_end");
1782			
1783			int error;
1784			
1785			Bind_internal(socket, local_end.Serialize(), out error);
1786			if (error != 0)
1787				throw new SocketException (error);
1788#if NET_2_0
1789			if (error == 0)
1790				isbound = true;
1791#endif
1792			
1793			seed_endpoint = local_end;
1794		}
1795
1796#if NET_2_0
1797		public bool ConnectAsync (SocketAsyncEventArgs e)
1798		{
1799			// NO check is made whether e != null in MS.NET (NRE is thrown in such case)
1800			
1801			if (disposed && closed)
1802				throw new ObjectDisposedException (GetType ().ToString ());
1803			if (islistening)
1804				throw new InvalidOperationException ("You may not perform this operation after calling the Listen method.");
1805			if (e.RemoteEndPoint == null)
1806				throw new ArgumentNullException ("remoteEP", "Value cannot be null.");
1807			if (e.BufferList != null)
1808				throw new ArgumentException ("Multiple buffers cannot be used with this method.");
1809
1810			e.DoOperation (SocketAsyncOperation.Connect, this);
1811
1812			// We always return true for now
1813			return true;
1814		}
1815#endif
1816		
1817#if NET_2_0
1818		public void Connect (IPAddress address, int port)
1819		{
1820			Connect (new IPEndPoint (address, port));
1821		}
1822		
1823		public void Connect (IPAddress[] addresses, int port)
1824		{
1825			if (disposed && closed)
1826				throw new ObjectDisposedException (GetType ().ToString ());
1827
1828			if (addresses == null)
1829				throw new ArgumentNullException ("addresses");
1830
1831			if (this.AddressFamily != AddressFamily.InterNetwork &&
1832				this.AddressFamily != AddressFamily.InterNetworkV6)
1833				throw new NotSupportedException ("This method is only valid for addresses in the InterNetwork or InterNetworkV6 families");
1834
1835			if (islistening)
1836				throw new InvalidOperationException ();
1837
1838			/* FIXME: do non-blocking sockets Poll here? */
1839			int error = 0;
1840			foreach (IPAddress address in addresses) {
1841				IPEndPoint iep = new IPEndPoint (address, port);
1842				SocketAddress serial = iep.Serialize ();
1843				
1844				Connect_internal (socket, serial, out error);
1845				if (error == 0) {
1846					connected = true;
1847					seed_endpoint = iep;
1848					return;
1849				} else if (error != (int)SocketError.InProgress &&
1850					   error != (int)SocketError.WouldBlock) {
1851					continue;
1852				}
1853				
1854				if (!blocking) {
1855					Poll (-1, SelectMod

Large files files are truncated, but you can click here to view the full file