2002-04-24 Dick Porter <dick@ximian.com>
[mono.git] / mcs / class / System / System.Net.Sockets / Socket.cs
1 // System.Net.Sockets.Socket.cs
2 //
3 // Authors:
4 //    Phillip Pearson (pp@myelin.co.nz)
5 //    Dick Porter <dick@ximian.com>
6 //
7 // Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
8 //    http://www.myelin.co.nz
9 //
10
11 using System;
12 using System.Net;
13 using System.Collections;
14 using System.Runtime.CompilerServices;
15 using System.Threading;
16
17 namespace System.Net.Sockets 
18 {
19         public class Socket : IDisposable 
20         {
21                 private sealed class SocketAsyncResult: IAsyncResult 
22                 {
23                         private object state;
24                         private WaitHandle waithandle;
25                         private bool completed_sync, completed;
26                         private Worker worker;
27
28                         public SocketAsyncResult(object state) {
29                                 this.state=state;
30                                 waithandle=new ManualResetEvent(false);
31                                 completed_sync=completed=false;
32                         }
33
34                         public object AsyncState {
35                                 get {
36                                         return(state);
37                                 }
38                         }
39
40                         public WaitHandle AsyncWaitHandle {
41                                 get {
42                                         return(waithandle);
43                                 }
44                                 set {
45                                         waithandle=value;
46                                 }
47                         }
48
49                         public bool CompletedSynchronously {
50                                 get {
51                                         return(completed_sync);
52                                 }
53                         }
54
55                         public bool IsCompleted {
56                                 get {
57                                         return(completed);
58                                 }
59                                 set {
60                                         completed=value;
61                                 }
62                         }
63                         
64                         public Worker Worker {
65                                 get {
66                                         return(worker);
67                                 }
68                                 set {
69                                         worker=value;
70                                 }
71                         }
72                 }
73
74                 private sealed class Worker 
75                 {
76                         private AsyncCallback callback;
77                         private SocketAsyncResult result;
78                         private Socket socket;
79
80                         // Parameters
81                         private EndPoint endpoint;      // Connect,ReceiveFrom,SendTo
82                         private byte[] buffer;          // Receive,ReceiveFrom,Send,SendTo
83                         private int offset;             // Receive,ReceiveFrom,Send,SendTo
84                         private int size;               // Receive,ReceiveFrom,Send,SendTo
85                         private SocketFlags sockflags;  // Receive,ReceiveFrom,Send,SendTo
86
87                         // Return values
88                         private Socket acc_socket;
89                         private int total;
90                         
91
92                         // For Accept
93                         public Worker(Socket req_sock,
94                                       AsyncCallback req_callback,
95                                       SocketAsyncResult req_result)
96                                 : this(req_sock, null, 0, 0, SocketFlags.None,
97                                        null, req_callback, req_result) {}
98
99                         // For Connect
100                         public Worker(Socket req_sock, EndPoint req_endpoint,
101                                       AsyncCallback req_callback,
102                                       SocketAsyncResult req_result)
103                                 : this(req_sock, null, 0, 0, SocketFlags.None,
104                                        req_endpoint, req_callback,
105                                        req_result) {}
106
107                         // For Receive and Send
108                         public Worker(Socket req_sock, byte[] req_buffer,
109                                       int req_offset, int req_size,
110                                       SocketFlags req_sockflags,
111                                       AsyncCallback req_callback,
112                                       SocketAsyncResult req_result)
113                                 : this(req_sock, req_buffer, req_offset,
114                                        req_size, req_sockflags, null,
115                                        req_callback, req_result) {}
116
117                         // For ReceiveFrom and SendTo
118                         public Worker(Socket req_sock, byte[] req_buffer,
119                                       int req_offset, int req_size,
120                                       SocketFlags req_sockflags,
121                                       EndPoint req_endpoint,
122                                       AsyncCallback req_callback,
123                                       SocketAsyncResult req_result) {
124                                 socket=req_sock;
125                                 buffer=req_buffer;
126                                 offset=req_offset;
127                                 size=req_size;
128                                 sockflags=req_sockflags;
129                                 endpoint=req_endpoint;
130                                 callback=req_callback;
131                                 result=req_result;
132                         }
133
134                         private void End() {
135                                 callback(result);
136                                 ((ManualResetEvent)result.AsyncWaitHandle).Set();
137                                 result.IsCompleted=true;
138                         }
139                         
140                         public void Accept() {
141                                 lock(result) {
142                                         acc_socket=socket.Accept();
143                                         End();
144                                 }
145                         }
146
147                         public void Connect() {
148                                 lock(result) {
149                                         socket.Connect(endpoint);
150                                         End();
151                                 }
152                         }
153
154                         public void Receive() {
155                                 lock(result) {
156                                         total=socket.Receive(buffer, offset,
157                                                              size, sockflags);
158                                         End();
159                                 }
160                         }
161
162                         public void ReceiveFrom() {
163                                 lock(result) {
164                                         total=socket.ReceiveFrom(buffer,
165                                                                  offset, size,
166                                                                  sockflags,
167                                                                  ref endpoint);
168                                         End();
169                                 }
170                         }
171
172                         public void Send() {
173                                 lock(result) {
174                                         total=socket.Send(buffer, offset, size,
175                                                           sockflags);
176                                         End();
177                                 }
178                         }
179
180                         public void SendTo() {
181                                 lock(result) {
182                                         total=socket.SendTo(buffer, offset,
183                                                             size, sockflags,
184                                                             endpoint);
185                                         End();
186                                 }
187                         }
188
189                         public EndPoint EndPoint {
190                                 get {
191                                         return(endpoint);
192                                 }
193                         }
194
195                         public Socket Socket {
196                                 get {
197                                         return(acc_socket);
198                                 }
199                         }
200
201                         public int Total {
202                                 get {
203                                         return(total);
204                                 }
205                         }
206                 }
207                         
208                 /* the field "socket" is looked up by name by the runtime */
209                 private IntPtr socket;
210                 private AddressFamily address_family;
211                 private SocketType socket_type;
212                 private ProtocolType protocol_type;
213                 private bool blocking=true;
214
215                 /* When true, the socket was connected at the time of
216                  * the last IO operation
217                  */
218                 private bool connected=false;
219                 
220                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
221                 private extern static void Select_internal(ref Socket[] read,
222                                                            ref Socket[] write,
223                                                            ref Socket[] err,
224                                                            int timeout);
225
226                 public static void Select(IList read_list, IList write_list,
227                                           IList err_list, int time_us) {
228                         if(read_list==null &&
229                            write_list==null &&
230                            err_list==null) {
231                                 throw new ArgumentNullException();
232                         }
233
234                         int read_count, write_count, err_count;
235
236                         if(read_list!=null) {
237                                 read_count=read_list.Count;
238                         } else {
239                                 read_count=0;
240                         }
241
242                         if(write_list!=null) {
243                                 write_count=write_list.Count;
244                         } else {
245                                 write_count=0;
246                         }
247
248                         if(err_list!=null) {
249                                 err_count=err_list.Count;
250                         } else {
251                                 err_count=0;
252                         }
253                         
254                         Socket[] read_arr=new Socket[read_count];
255                         Socket[] write_arr=new Socket[write_count];
256                         Socket[] err_arr=new Socket[err_count];
257
258                         int i;
259
260                         if(read_list!=null) {
261                                 i=0;
262                                 
263                                 foreach (Socket s in read_list) {
264                                         read_arr[i]=s;
265                                         i++;
266                                 }
267                         }
268
269                         if(write_list!=null) {
270                                 i=0;
271                                 foreach (Socket s in write_list) {
272                                         write_arr[i]=s;
273                                         i++;
274                                 }
275                         }
276                         
277                         if(err_list!=null) {
278                                 i=0;
279                                 foreach (Socket s in err_list) {
280                                         err_arr[i]=s;
281                                         i++;
282                                 }
283                         }
284
285                         Select_internal(ref read_arr, ref write_arr,
286                                         ref err_arr, time_us);
287
288                         if(read_list!=null) {
289                                 read_list.Clear();
290                                 for(i=0; i<read_arr.Length; i++) {
291                                         read_list.Add(read_arr[i]);
292                                 }
293                         }
294                         
295                         if(write_list!=null) {
296                                 write_list.Clear();
297                                 for(i=0; i<write_arr.Length; i++) {
298                                         write_list.Add(write_arr[i]);
299                                 }
300                         }
301                         
302                         if(err_list!=null) {
303                                 err_list.Clear();
304                                 for(i=0; i<err_arr.Length; i++) {
305                                         err_list.Add(err_arr[i]);
306                                 }
307                         }
308                 }
309
310                 // private constructor used by Accept, which already
311                 // has a socket handle to use
312                 private Socket(AddressFamily family, SocketType type,
313                                ProtocolType proto, IntPtr sock) {
314                         address_family=family;
315                         socket_type=type;
316                         protocol_type=proto;
317                         
318                         socket=sock;
319                         connected=true;
320                 }
321                 
322                 // Creates a new system socket, returning the handle
323                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
324                 private extern IntPtr Socket_internal(AddressFamily family,
325                                                       SocketType type,
326                                                       ProtocolType proto);
327                 
328                 public Socket(AddressFamily family, SocketType type,
329                               ProtocolType proto) {
330                         address_family=family;
331                         socket_type=type;
332                         protocol_type=proto;
333                         
334                         socket=Socket_internal(family, type, proto);
335                 }
336
337                 public AddressFamily AddressFamily {
338                         get {
339                                 return(address_family);
340                         }
341                 }
342
343                 // Returns the amount of data waiting to be read on socket
344                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
345                 private extern static int Available_internal(IntPtr socket);
346                 
347                 public int Available {
348                         get {
349                                 return(Available_internal(socket));
350                         }
351                 }
352
353                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
354                 private extern static void Blocking_internal(IntPtr socket,
355                                                             bool block);
356
357                 public bool Blocking {
358                         get {
359                                 return(blocking);
360                         }
361                         set {
362                                 Blocking_internal(socket, value);
363                                 blocking=value;
364                         }
365                 }
366
367                 public bool Connected {
368                         get {
369                                 return(connected);
370                         }
371                 }
372
373                 public IntPtr Handle {
374                         get {
375                                 return(socket);
376                         }
377                 }
378
379                 // Returns the local endpoint details in addr and port
380                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
381                 private extern static SocketAddress LocalEndPoint_internal(IntPtr socket);
382
383                 [MonoTODO("Support non-IP endpoints")]
384                 public EndPoint LocalEndPoint {
385                         get {
386                                 SocketAddress sa;
387                                 
388                                 sa=LocalEndPoint_internal(socket);
389
390                                 if(sa.Family==AddressFamily.InterNetwork) {
391                                         // Stupidly, EndPoint.Create() is an
392                                         // instance method
393                                         return new IPEndPoint(0, 0).Create(sa);
394                                 } else {
395                                         throw new NotImplementedException();
396                                 }
397                         }
398                 }
399
400                 public ProtocolType ProtocolType {
401                         get {
402                                 return(protocol_type);
403                         }
404                 }
405
406                 // Returns the remote endpoint details in addr and port
407                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
408                 private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket);
409
410                 [MonoTODO("Support non-IP endpoints")]
411                 public EndPoint RemoteEndPoint {
412                         get {
413                                 SocketAddress sa;
414                                 
415                                 sa=RemoteEndPoint_internal(socket);
416
417                                 if(sa.Family==AddressFamily.InterNetwork) {
418                                         // Stupidly, EndPoint.Create() is an
419                                         // instance method
420                                         return new IPEndPoint(0, 0).Create(sa);
421                                 } else {
422                                         throw new NotImplementedException();
423                                 }
424                         }
425                 }
426
427                 public SocketType SocketType {
428                         get {
429                                 return(socket_type);
430                         }
431                 }
432
433                 // Creates a new system socket, returning the handle
434                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
435                 private extern static IntPtr Accept_internal(IntPtr sock);
436                 
437                 public Socket Accept() {
438                         IntPtr sock=Accept_internal(socket);
439                         
440                         return(new Socket(this.AddressFamily, this.SocketType,
441                                           this.ProtocolType, sock));
442                 }
443
444                 public IAsyncResult BeginAccept(AsyncCallback callback,
445                                                 object state) {
446                         SocketAsyncResult req=new SocketAsyncResult(state);
447                         Worker worker=new Worker(this, callback, req);
448                         Thread child=new Thread(new ThreadStart(worker.Accept));
449                         child.Start();
450                         return(req);
451                 }
452
453                 public IAsyncResult BeginConnect(EndPoint end_point,
454                                                  AsyncCallback callback,
455                                                  object state) {
456                         SocketAsyncResult req=new SocketAsyncResult(state);
457                         Worker worker=new Worker(this, end_point, callback,
458                                                  req);
459                         Thread child=new Thread(new ThreadStart(worker.Connect));
460                         child.Start();
461                         return(req);
462                 }
463
464                 public IAsyncResult BeginReceive(byte[] buffer, int offset,
465                                                  int size,
466                                                  SocketFlags socket_flags,
467                                                  AsyncCallback callback,
468                                                  object state) {
469                         SocketAsyncResult req=new SocketAsyncResult(state);
470                         Worker worker=new Worker(this, buffer, offset, size,
471                                                  socket_flags, callback, req);
472                         Thread child=new Thread(new ThreadStart(worker.Receive));
473                         child.Start();
474                         return(req);
475                 }
476
477                 public IAsyncResult BeginReceiveFrom(byte[] buffer, int offset,
478                                                      int size,
479                                                      SocketFlags socket_flags,
480                                                      ref EndPoint remote_end,
481                                                      AsyncCallback callback,
482                                                      object state) {
483                         SocketAsyncResult req=new SocketAsyncResult(state);
484                         Worker worker=new Worker(this, buffer, offset, size,
485                                                  socket_flags, remote_end,
486                                                  callback, req);
487                         Thread child=new Thread(new ThreadStart(worker.ReceiveFrom));
488                         child.Start();
489                         return(req);
490                 }
491
492                 public IAsyncResult BeginSend(byte[] buffer, int offset,
493                                               int size,
494                                               SocketFlags socket_flags,
495                                               AsyncCallback callback,
496                                               object state) {
497                         SocketAsyncResult req=new SocketAsyncResult(state);
498                         Worker worker=new Worker(this, buffer, offset, size,
499                                                  socket_flags, callback, req);
500                         Thread child=new Thread(new ThreadStart(worker.Send));
501                         child.Start();
502                         return(req);
503                 }
504
505                 public IAsyncResult BeginSendTo(byte[] buffer, int offset,
506                                                 int size,
507                                                 SocketFlags socket_flags,
508                                                 EndPoint remote_end,
509                                                 AsyncCallback callback,
510                                                 object state) {
511                         SocketAsyncResult req=new SocketAsyncResult(state);
512                         Worker worker=new Worker(this, buffer, offset, size,
513                                                  socket_flags, remote_end,
514                                                  callback, req);
515                         Thread child=new Thread(new ThreadStart(worker.SendTo));
516                         child.Start();
517                         return(req);
518                 }
519
520                 // Creates a new system socket, returning the handle
521                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
522                 private extern static void Bind_internal(IntPtr sock,
523                                                          SocketAddress sa);
524
525                 public void Bind(EndPoint local_end) {
526                         if(local_end==null) {
527                                 throw new ArgumentNullException();
528                         }
529                         
530                         Bind_internal(socket, local_end.Serialize());
531                 }
532
533                 // Closes the socket
534                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
535                 private extern static void Close_internal(IntPtr socket);
536                 
537                 public void Close() {
538                         connected=false;
539                         Close_internal(socket);
540                 }
541
542                 // Connects to the remote address
543                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
544                 private extern static void Connect_internal(IntPtr sock,
545                                                             SocketAddress sa);
546
547                 public void Connect(EndPoint remote_end) {
548                         if(remote_end==null) {
549                                 throw new ArgumentNullException();
550                         }
551                         
552                         Connect_internal(socket, remote_end.Serialize());
553                         connected=true;
554                 }
555                 
556                 public Socket EndAccept(IAsyncResult result) {
557                         SocketAsyncResult req=(SocketAsyncResult)result;
558
559                         result.AsyncWaitHandle.WaitOne();
560                         return(req.Worker.Socket);
561                 }
562
563                 public void EndConnect(IAsyncResult result) {
564                         SocketAsyncResult req=(SocketAsyncResult)result;
565
566                         result.AsyncWaitHandle.WaitOne();
567                 }
568
569                 public int EndReceive(IAsyncResult result) {
570                         SocketAsyncResult req=(SocketAsyncResult)result;
571
572                         result.AsyncWaitHandle.WaitOne();
573                         return(req.Worker.Total);
574                 }
575
576                 public int EndReceiveFrom(IAsyncResult result,
577                                           ref EndPoint end_point) {
578                         SocketAsyncResult req=(SocketAsyncResult)result;
579
580                         result.AsyncWaitHandle.WaitOne();
581                         end_point=req.Worker.EndPoint;
582                         return(req.Worker.Total);
583                 }
584
585                 public int EndSend(IAsyncResult result) {
586                         SocketAsyncResult req=(SocketAsyncResult)result;
587
588                         result.AsyncWaitHandle.WaitOne();
589                         return(req.Worker.Total);
590                 }
591
592                 public int EndSendTo(IAsyncResult result) {
593                         SocketAsyncResult req=(SocketAsyncResult)result;
594
595                         result.AsyncWaitHandle.WaitOne();
596                         return(req.Worker.Total);
597                 }
598
599                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
600                 private extern static void GetSocketOption_obj_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, out object obj_val);
601                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
602                 private extern static void GetSocketOption_arr_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, ref byte[] byte_val);
603
604                 public object GetSocketOption(SocketOptionLevel level,
605                                               SocketOptionName name) {
606                         object obj_val;
607                         
608                         GetSocketOption_obj_internal(socket, level, name,
609                                                      out obj_val);
610                         
611                         if(name==SocketOptionName.Linger) {
612                                 return((LingerOption)obj_val);
613                         } else if (name==SocketOptionName.AddMembership ||
614                                    name==SocketOptionName.DropMembership) {
615                                 return((MulticastOption)obj_val);
616                         } else {
617                                 return((int)obj_val);
618                         }
619                 }
620
621                 public void GetSocketOption(SocketOptionLevel level,
622                                             SocketOptionName name,
623                                             byte[] opt_value) {
624                         int opt_value_len=opt_value.Length;
625                         
626                         GetSocketOption_arr_internal(socket, level, name,
627                                                      ref opt_value);
628                 }
629
630                 public byte[] GetSocketOption(SocketOptionLevel level,
631                                               SocketOptionName name,
632                                               int length) {
633                         byte[] byte_val=new byte[length];
634                         
635                         GetSocketOption_arr_internal(socket, level, name,
636                                                      ref byte_val);
637
638                         return(byte_val);
639                 }
640
641                 [MonoTODO("Totally undocumented")]
642                 public int IOControl(int ioctl_code, byte[] in_value,
643                                      byte[] out_value) {
644                         throw new NotImplementedException();
645                 }
646
647                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
648                 private extern static void Listen_internal(IntPtr sock,
649                                                            int backlog);
650
651                 public void Listen(int backlog) {
652                         Listen_internal(socket, backlog);
653                 }
654
655                 /* The docs for Poll() are a bit lightweight too, but
656                  * it seems to be just a simple wrapper around Select.
657                  */
658                 public bool Poll(int time_us, SelectMode mode) {
659                         ArrayList socketlist=new ArrayList(1);
660
661                         socketlist.Add(this);
662                         
663                         switch(mode) {
664                         case SelectMode.SelectError:
665                                 Select(null, null, socketlist, time_us);
666                                 break;
667                         case SelectMode.SelectRead:
668                                 Select(socketlist, null, null, time_us);
669                                 break;
670                         case SelectMode.SelectWrite:
671                                 Select(null, socketlist, null, time_us);
672                                 break;
673                         default:
674                                 throw new NotSupportedException();
675                         }
676
677                         if(socketlist.Contains(this)) {
678                                 return(true);
679                         } else {
680                                 return(false);
681                         }
682                 }
683                 
684                 public int Receive(byte[] buf) {
685                         return(Receive(buf, 0, buf.Length, SocketFlags.None));
686                 }
687
688                 public int Receive(byte[] buf, SocketFlags flags) {
689                         return(Receive(buf, 0, buf.Length, flags));
690                 }
691
692                 public int Receive(byte[] buf, int size, SocketFlags flags) {
693                         return(Receive(buf, 0, size, flags));
694                 }
695
696                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
697                 private extern static int Receive_internal(IntPtr sock,
698                                                            byte[] buffer,
699                                                            int offset,
700                                                            int count,
701                                                            SocketFlags flags);
702
703                 public int Receive(byte[] buf, int offset, int size,
704                                    SocketFlags flags) {
705                         if(buf==null) {
706                                 throw new ArgumentNullException();
707                         }
708                         if(offset+size>buf.Length) {
709                                 throw new ArgumentException();
710                         }
711                         
712                         int ret;
713                         
714                         try {
715                                 ret=Receive_internal(socket, buf, offset,
716                                                      size, flags);
717                         } catch(SocketException) {
718                                 connected=false;
719                                 throw;
720                         }
721                         connected=true;
722
723                         return(ret);
724                 }
725                 
726                 public int ReceiveFrom(byte[] buf, ref EndPoint remote_end) {
727                         return(ReceiveFrom(buf, 0, buf.Length,
728                                            SocketFlags.None, ref remote_end));
729                 }
730
731                 public int ReceiveFrom(byte[] buf, SocketFlags flags,
732                                        ref EndPoint remote_end) {
733                         return(ReceiveFrom(buf, 0, buf.Length, flags,
734                                            ref remote_end));
735                 }
736
737                 public int ReceiveFrom(byte[] buf, int size, SocketFlags flags,
738                                        ref EndPoint remote_end) {
739                         return(ReceiveFrom(buf, 0, size, flags,
740                                            ref remote_end));
741                 }
742
743
744                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
745                 private extern static int RecvFrom_internal(IntPtr sock,
746                                                             byte[] buffer,
747                                                             int offset,
748                                                             int count,
749                                                             SocketFlags flags,
750                                                             ref SocketAddress sockaddr);
751
752                 public int ReceiveFrom(byte[] buf, int offset, int size,
753                                        SocketFlags flags,
754                                        ref EndPoint remote_end) {
755                         if(buf==null || remote_end==null) {
756                                 throw new ArgumentNullException();
757                         }
758                         if(offset+size>buf.Length) {
759                                 throw new ArgumentException();
760                         }
761
762                         SocketAddress sockaddr=remote_end.Serialize();
763                         int count;
764
765                         try {
766                                 count=RecvFrom_internal(socket, buf, offset,
767                                                         size, flags,
768                                                         ref sockaddr);
769                         } catch(SocketException) {
770                                 connected=false;
771                                 throw;
772                         }
773                         connected=true;
774                         
775                         // Stupidly, EndPoint.Create() is an
776                         // instance method
777                         remote_end=remote_end.Create(sockaddr);
778
779                         return(count);
780                 }
781
782                 public int Send(byte[] buf) {
783                         return(Send(buf, 0, buf.Length, SocketFlags.None));
784                 }
785
786                 public int Send(byte[] buf, SocketFlags flags) {
787                         return(Send(buf, 0, buf.Length, flags));
788                 }
789
790                 public int Send(byte[] buf, int size, SocketFlags flags) {
791                         return(Send(buf, 0, size, flags));
792                 }
793
794                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
795                 private extern static int Send_internal(IntPtr sock,
796                                                         byte[] buf, int offset,
797                                                         int count,
798                                                         SocketFlags flags);
799
800                 public int Send(byte[] buf, int offset, int size,
801                                 SocketFlags flags) {
802                         if(buf==null) {
803                                 throw new ArgumentNullException();
804                         }
805                         if(offset+size>buf.Length) {
806                                 throw new ArgumentException();
807                         }
808
809                         int ret;
810
811                         try {
812                                 ret=Send_internal(socket, buf, offset, size,
813                                                   flags);
814                         } catch(SocketException) {
815                                 connected=false;
816                                 throw;
817                         }
818                         connected=true;
819
820                         return(ret);
821                 }
822
823                 public int SendTo(byte[] buffer, EndPoint remote_end) {
824                         return(SendTo(buffer, 0, buffer.Length,
825                                       SocketFlags.None, remote_end));
826                 }
827
828                 public int SendTo(byte[] buffer, SocketFlags flags,
829                                   EndPoint remote_end) {
830                         return(SendTo(buffer, 0, buffer.Length, flags,
831                                       remote_end));
832                 }
833
834                 public int SendTo(byte[] buffer, int size, SocketFlags flags,
835                                   EndPoint remote_end) {
836                         return(SendTo(buffer, size, buffer.Length, flags,
837                                       remote_end));
838                 }
839
840
841                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
842                 private extern static int SendTo_internal(IntPtr sock,
843                                                           byte[] buffer,
844                                                           int offset,
845                                                           int count,
846                                                           SocketFlags flags,
847                                                           SocketAddress sa);
848
849                 public int SendTo(byte[] buffer, int offset, int size,
850                                   SocketFlags flags, EndPoint remote_end) {
851                         if(buffer==null || remote_end==null) {
852                                 throw new ArgumentNullException();
853                         }
854                         if(offset+size>buffer.Length) {
855                                 throw new ArgumentException();
856                         }
857
858                         SocketAddress sockaddr=remote_end.Serialize();
859
860                         int ret;
861
862                         try {
863                                 ret=SendTo_internal(socket, buffer, offset,
864                                                     size, flags, sockaddr);
865                         }
866                         catch(SocketException) {
867                                 connected=false;
868                                 throw;
869                         }
870                         connected=true;
871
872                         return(ret);
873                 }
874
875                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
876                 private extern static void SetSocketOption_internal(IntPtr socket, SocketOptionLevel level, SocketOptionName name, object obj_val, byte[] byte_val, int int_val);
877
878                 public void SetSocketOption(SocketOptionLevel level,
879                                             SocketOptionName name,
880                                             byte[] opt_value) {
881                         SetSocketOption_internal(socket, level, name, null,
882                                                  opt_value, 0);
883                 }
884
885                 public void SetSocketOption(SocketOptionLevel level,
886                                             SocketOptionName name,
887                                             int opt_value) {
888                         SetSocketOption_internal(socket, level, name, null,
889                                                  null, opt_value);
890                 }
891
892                 public void SetSocketOption(SocketOptionLevel level,
893                                             SocketOptionName name,
894                                             object opt_value) {
895                         if(opt_value==null) {
896                                 throw new ArgumentNullException();
897                         }
898                         
899                         SetSocketOption_internal(socket, level, name,
900                                                  opt_value, null, 0);
901                 }
902
903                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
904                 private extern static void Shutdown_internal(IntPtr socket, SocketShutdown how);
905                 
906                 public void Shutdown(SocketShutdown how) {
907                         Shutdown_internal(socket, how);
908                 }
909
910                 private bool disposed = false;
911                 
912                 protected virtual void Dispose(bool explicitDisposing) {
913                         // Check to see if Dispose has already been called
914                         if(!this.disposed) {
915                                 // If this is a call to Dispose,
916                                 // dispose all managed resources.
917                                 if(explicitDisposing) {
918                                         // Free up stuff here
919                                 }
920
921                                 // Release unmanaged resources
922                                 this.disposed=true;
923                                 this.Close();
924                         }
925                 }
926
927                 public void Dispose() {
928                         Dispose(true);
929                         // Take yourself off the Finalization queue
930                         GC.SuppressFinalize(this);
931                 }
932
933                 ~Socket () {
934                         Dispose(false);
935                 }
936         }
937 }