Socket_2_1.cs :  » 2.6.4-mono-.net-core » System.Net » System » Net » Sockets » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » 2.6.4 mono .net core » System.Net 
System.Net » System » Net » Sockets » Socket_2_1.cs
// System.Net.Sockets.Socket.cs
//
// Authors:
//  Phillip Pearson (pp@myelin.co.nz)
//  Dick Porter <dick@ximian.com>
//  Gonzalo Paniagua Javier (gonzalo@ximian.com)
//  Sridhar Kulkarni (sridharkulkarni@gmail.com)
//  Brian Nickel (brian.nickel@gmail.com)
//
// Copyright (C) 2001, 2002 Phillip Pearson and Ximian, Inc.
//    http://www.myelin.co.nz
// (c) 2004-2006 Novell, Inc. (http://www.novell.com)
//

//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

using System;
using System.Net;
using System.Collections;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using System.IO;
using System.Security;
using System.Text;

#if !NET_2_1
using System.Net.Configuration;
#endif

#if NET_2_0
using System.Collections.Generic;
#if !NET_2_1
using System.Net.NetworkInformation;
#endif
#endif

namespace System.Net.Sockets{

  public partial class Socket : IDisposable {

    /*
     *  These two fields are looked up by name by the runtime, don't change
     *  their name without also updating the runtime code.
     */
    private static int ipv4Supported = -1, ipv6Supported = -1;
    int linger_timeout;

    static Socket ()
    {
      // initialize ipv4Supported and ipv6Supported
      CheckProtocolSupport ();
    }

    internal static void CheckProtocolSupport ()
    {
      if(ipv4Supported == -1) {
        try {
          Socket tmp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
          tmp.Close();

          ipv4Supported = 1;
        } catch {
          ipv4Supported = 0;
        }
      }

      if (ipv6Supported == -1) {
#if !NET_2_1
#if NET_2_0 && CONFIGURATION_DEP
        SettingsSection config;
        config = (SettingsSection) System.Configuration.ConfigurationManager.GetSection ("system.net/settings");
        if (config != null)
          ipv6Supported = config.Ipv6.Enabled ? -1 : 0;
#else
        NetConfig config = System.Configuration.ConfigurationSettings.GetConfig("system.net/settings") as NetConfig;
        if (config != null)
          ipv6Supported = config.ipv6Enabled ? -1 : 0;
#endif
#endif
        if (ipv6Supported != 0) {
          try {
            Socket tmp = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
            tmp.Close();

            ipv6Supported = 1;
          } catch {
            ipv6Supported = 0;
          }
        }
      }
    }

    public static bool SupportsIPv4 {
      get {
        CheckProtocolSupport();
        return ipv4Supported == 1;
      }
    }

#if NET_2_0
    [ObsoleteAttribute ("Use OSSupportsIPv6 instead")]
#endif
    public static bool SupportsIPv6 {
      get {
        CheckProtocolSupport();
        return ipv6Supported == 1;
      }
    }
#if NET_2_1
    public static bool OSSupportsIPv4 {
      get {
        CheckProtocolSupport();
        return ipv4Supported == 1;
      }
    }
#endif
#if NET_2_1
    public static bool OSSupportsIPv6 {
      get {
        CheckProtocolSupport();
        return ipv6Supported == 1;
      }
    }
#elif NET_2_0
    public static bool OSSupportsIPv6 {
      get {
        NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces ();
        
        foreach (NetworkInterface adapter in nics) {
          if (adapter.Supports (NetworkInterfaceComponent.IPv6))
            return true;
        }
        return false;
      }
    }
#endif

    /* the field "socket" is looked up by name by the runtime */
    private IntPtr socket;
    private AddressFamily address_family;
    private SocketType socket_type;
    private ProtocolType protocol_type;
    internal bool blocking=true;
    Thread blocking_thread;
#if NET_2_0
    private bool isbound;
#endif
    /* When true, the socket was connected at the time of
     * the last IO operation
     */
    private bool connected;
    /* true if we called Close_internal */
    private bool closed;
    internal bool disposed;

    /*
     * This EndPoint is used when creating new endpoints. Because
     * there are many types of EndPoints possible,
     * seed_endpoint.Create(addr) is used for creating new ones.
     * As such, this value is set on Bind, SentTo, ReceiveFrom,
     * Connect, etc.
      */
    internal EndPoint seed_endpoint = null;

#if !TARGET_JVM
    // Creates a new system socket, returning the handle
    [MethodImplAttribute(MethodImplOptions.InternalCall)]
    private extern IntPtr Socket_internal(AddressFamily family,
                  SocketType type,
                  ProtocolType proto,
                  out int error);
#endif    
    
    public Socket(AddressFamily family, SocketType type, ProtocolType proto)
    {
#if NET_2_1
      if (family == AddressFamily.Unspecified)
        throw new ArgumentException ("family");
#endif
      address_family=family;
      socket_type=type;
      protocol_type=proto;
      
      int error;
      
      socket = Socket_internal (family, type, proto, out error);
      if (error != 0)
        throw new SocketException (error);
#if !NET_2_1
      SocketDefaults ();
#endif
    }

    ~Socket ()
    {
      Dispose (false);
    }


    public AddressFamily AddressFamily {
      get { return address_family; }
    }

#if !TARGET_JVM
    [MethodImplAttribute(MethodImplOptions.InternalCall)]
    private extern static void Blocking_internal(IntPtr socket,
                   bool block,
                   out int error);
#endif

    public bool Blocking {
      get {
        return(blocking);
      }
      set {
        if (disposed && closed)
          throw new ObjectDisposedException (GetType ().ToString ());

        int error;
        
        Blocking_internal (socket, value, out error);

        if (error != 0)
          throw new SocketException (error);
        
        blocking=value;
      }
    }

    public bool Connected {
      get { return connected; }
      internal set { connected = value; }
    }

    public ProtocolType ProtocolType {
      get { return protocol_type; }
    }
#if NET_2_0
    public bool NoDelay {
      get {
        if (disposed && closed)
          throw new ObjectDisposedException (GetType ().ToString ());

        ThrowIfUpd ();

        return (int)(GetSocketOption (
          SocketOptionLevel.Tcp,
          SocketOptionName.NoDelay)) != 0;
      }

      set {
        if (disposed && closed)
          throw new ObjectDisposedException (GetType ().ToString ());

        ThrowIfUpd ();

        SetSocketOption (
          SocketOptionLevel.Tcp,
          SocketOptionName.NoDelay, value ? 1 : 0);
      }
    }

    public int ReceiveBufferSize {
      get {
        if (disposed && closed) {
          throw new ObjectDisposedException (GetType ().ToString ());
        }
        return((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer));
      }
      set {
        if (disposed && closed) {
          throw new ObjectDisposedException (GetType ().ToString ());
        }
        if (value < 0) {
          throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
        }
        
        SetSocketOption (SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, value);
      }
    }

    public int SendBufferSize {
      get {
        if (disposed && closed) {
          throw new ObjectDisposedException (GetType ().ToString ());
        }
        return((int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.SendBuffer));
      }
      set {
        if (disposed && closed) {
          throw new ObjectDisposedException (GetType ().ToString ());
        }
        if (value < 0) {
          throw new ArgumentOutOfRangeException ("value", "The value specified for a set operation is less than zero");
        }
        
        SetSocketOption (SocketOptionLevel.Socket,
             SocketOptionName.SendBuffer,
             value);
      }
    }

    public short Ttl {
      get {
        if (disposed && closed) {
          throw new ObjectDisposedException (GetType ().ToString ());
        }
        
        short ttl_val;
        
        if (address_family == AddressFamily.InterNetwork) {
          ttl_val = (short)((int)GetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive));
        } else if (address_family == AddressFamily.InterNetworkV6) {
          ttl_val = (short)((int)GetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit));
        } else {
          throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
        }
        
        return(ttl_val);
      }
      set {
        if (disposed && closed) {
          throw new ObjectDisposedException (GetType ().ToString ());
        }
        
        if (address_family == AddressFamily.InterNetwork) {
          SetSocketOption (SocketOptionLevel.IP, SocketOptionName.IpTimeToLive, value);
        } else if (address_family == AddressFamily.InterNetworkV6) {
          SetSocketOption (SocketOptionLevel.IPv6, SocketOptionName.HopLimit, value);
        } else {
          throw new NotSupportedException ("This property is only valid for InterNetwork and InterNetworkV6 sockets");
        }
      }
    }
#endif
    // Returns the remote endpoint details in addr and port
    [MethodImplAttribute(MethodImplOptions.InternalCall)]
    private extern static SocketAddress RemoteEndPoint_internal(IntPtr socket, out int error);

    public EndPoint RemoteEndPoint {
      get {
        if (disposed && closed)
          throw new ObjectDisposedException (GetType ().ToString ());
        
        /*
         * If the seed EndPoint is null, Connect, Bind,
         * etc has not yet been called. MS returns null
         * in this case.
         */
        if (seed_endpoint == null)
          return null;
        
        SocketAddress sa;
        int error;
        
        sa=RemoteEndPoint_internal(socket, out error);

        if (error != 0)
          throw new SocketException (error);

        return seed_endpoint.Create (sa);
      }
    }

    void Linger (IntPtr handle)
    {
      if (!connected || linger_timeout <= 0)
        return;

      // We don't want to receive any more data
      int error;
      Shutdown_internal (handle, SocketShutdown.Receive, out error);
      if (error != 0)
        return;

      int seconds = linger_timeout / 1000;
      int ms = linger_timeout % 1000;
      if (ms > 0) {
        // If the other end closes, this will return 'true' with 'Available' == 0
        Poll_internal (handle, SelectMode.SelectRead, ms * 1000, out error);
        if (error != 0)
          return;

      }
      if (seconds > 0) {
        LingerOption linger = new LingerOption (true, seconds);
        SetSocketOption_internal (handle, SocketOptionLevel.Socket, SocketOptionName.Linger, linger, null, 0, out error);
        /* Not needed, we're closing upon return */
        /*if (error != 0)
          return; */
      }
    }

    protected virtual void Dispose (bool explicitDisposing)
    {
      if (disposed)
        return;

      disposed = true;
      bool was_connected = connected;
      connected = false;
      if ((int) socket != -1) {
        int error;
        closed = true;
        IntPtr x = socket;
        socket = (IntPtr) (-1);
        Thread th = blocking_thread;
        if (th != null) {
          th.Abort ();
          blocking_thread = null;
        }

        if (was_connected)
          Linger (x);
        //DateTime start = DateTime.UtcNow;
        Close_internal (x, out error);
        //Console.WriteLine ("Time spent in Close_internal: {0}ms", (DateTime.UtcNow - start).TotalMilliseconds);
        if (error != 0)
          throw new SocketException (error);
      }
    }

#if NET_2_1
    public void Dispose ()
#else
    void IDisposable.Dispose ()
#endif
    {
      Dispose (true);
      GC.SuppressFinalize (this);
    }

    // Closes the socket
    [MethodImplAttribute(MethodImplOptions.InternalCall)]
    private extern static void Close_internal(IntPtr socket, out int error);

    public void Close ()
    {
      linger_timeout = 0;
      ((IDisposable) this).Dispose ();
    }

#if NET_2_0
    public void Close (int timeout) 
    {
      linger_timeout = timeout;
      ((IDisposable) this).Dispose ();
    }
#endif

    // Connects to the remote address
    [MethodImplAttribute(MethodImplOptions.InternalCall)]
    private extern static void Connect_internal(IntPtr sock,
                  SocketAddress sa,
                  out int error);

    public void Connect (EndPoint remoteEP)
    {
      SocketAddress serial = null;

      if (disposed && closed)
        throw new ObjectDisposedException (GetType ().ToString ());

      if (remoteEP == null)
        throw new ArgumentNullException ("remoteEP");

      IPEndPoint ep = remoteEP as IPEndPoint;
      if (ep != null)
        if (ep.Address.Equals (IPAddress.Any) || ep.Address.Equals (IPAddress.IPv6Any))
          throw new SocketException ((int) SocketError.AddressNotAvailable);

#if MOONLIGHT
      if (protocol_type != ProtocolType.Tcp)
        throw new SocketException ((int) SocketError.AccessDenied);
#elif NET_2_0
      /* TODO: check this for the 1.1 profile too */
      if (islistening)
        throw new InvalidOperationException ();
#endif
      serial = remoteEP.Serialize ();

      int error = 0;

      blocking_thread = Thread.CurrentThread;
      try {
        Connect_internal (socket, serial, out error);
      } catch (ThreadAbortException) {
        if (disposed) {
          Thread.ResetAbort ();
          error = (int) SocketError.Interrupted;
        }
      } finally {
        blocking_thread = null;
      }

      if (error != 0)
        throw new SocketException (error);

      connected=true;

#if NET_2_0
      isbound = true;
#endif

      seed_endpoint = remoteEP;
    }

#if NET_2_0
    public bool ReceiveAsync (SocketAsyncEventArgs e)
    {
      // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
      //
      // LAME SPEC: the ArgumentException is never thrown, instead an NRE is
      // thrown when e.Buffer and e.BufferList are null (works fine when one is
      // set to a valid object)
      if (disposed && closed)
        throw new ObjectDisposedException (GetType ().ToString ());

      // We do not support recv into multiple buffers yet
      if (e.BufferList != null)
        throw new NotSupportedException ("Mono doesn't support using BufferList at this point.");
      
      e.DoOperation (SocketAsyncOperation.Receive, this);

      // We always return true for now
      return true;
    }

    public bool SendAsync (SocketAsyncEventArgs e)
    {
      // NO check is made whether e != null in MS.NET (NRE is thrown in such case)
      
      if (disposed && closed)
        throw new ObjectDisposedException (GetType ().ToString ());
      if (e.Buffer == null && e.BufferList == null)
        throw new ArgumentException ("Either e.Buffer or e.BufferList must be valid buffers.");

      e.DoOperation (SocketAsyncOperation.Send, this);

      // We always return true for now
      return true;
    }
#endif

    [MethodImplAttribute(MethodImplOptions.InternalCall)]
    extern static bool Poll_internal (IntPtr socket, SelectMode mode, int timeout, out int error);

    /* This overload is needed as the async Connect method
     * also needs to check the socket error status, but
     * getsockopt(..., SO_ERROR) clears the error.
     */
    internal bool Poll (int time_us, SelectMode mode, out int socket_error)
    {
      if (disposed && closed)
        throw new ObjectDisposedException (GetType ().ToString ());

      if (mode != SelectMode.SelectRead &&
          mode != SelectMode.SelectWrite &&
          mode != SelectMode.SelectError)
        throw new NotSupportedException ("'mode' parameter is not valid.");

      int error;
      bool result = Poll_internal (socket, mode, time_us, out error);
      if (error != 0)
        throw new SocketException (error);

      socket_error = (int)GetSocketOption (SocketOptionLevel.Socket, SocketOptionName.Error);
      
      if (mode == SelectMode.SelectWrite && result) {
        /* Update the connected state; for
         * non-blocking Connect()s this is
         * when we can find out that the
         * connect succeeded.
         */
        if (socket_error == 0) {
          connected = true;
        }
      }
      
      return result;
    }

    [MethodImplAttribute(MethodImplOptions.InternalCall)]
    private extern static int Receive_internal(IntPtr sock,
                 byte[] buffer,
                 int offset,
                 int count,
                 SocketFlags flags,
                 out int error);

    internal int Receive_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
    {
      int nativeError;
      int ret = Receive_internal (socket, buf, offset, size, flags, out nativeError);
      error = (SocketError) nativeError;
      if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress)
        connected = false;
      else
        connected = true;
      
      return ret;
    }

    [MethodImplAttribute(MethodImplOptions.InternalCall)]
    private extern static void GetSocketOption_obj_internal(IntPtr socket,
      SocketOptionLevel level, SocketOptionName name, out object obj_val,
      out int error);

    [MethodImplAttribute(MethodImplOptions.InternalCall)]
    private extern static int Send_internal(IntPtr sock,
              byte[] buf, int offset,
              int count,
              SocketFlags flags,
              out int error);

    internal int Send_nochecks (byte [] buf, int offset, int size, SocketFlags flags, out SocketError error)
    {
      if (size == 0) {
        error = SocketError.Success;
        return 0;
      }

      int nativeError;

      int ret = Send_internal (socket, buf, offset, size, flags, out nativeError);

      error = (SocketError)nativeError;

      if (error != SocketError.Success && error != SocketError.WouldBlock && error != SocketError.InProgress)
        connected = false;
      else
        connected = true;

      return ret;
    }

    public object GetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName)
    {
      if (disposed && closed)
        throw new ObjectDisposedException (GetType ().ToString ());

      object obj_val;
      int error;

      GetSocketOption_obj_internal (socket, optionLevel, optionName, out obj_val,
        out error);
      if (error != 0)
        throw new SocketException (error);

      if (optionName == SocketOptionName.Linger) {
        return((LingerOption)obj_val);
      } else if (optionName == SocketOptionName.AddMembership ||
           optionName == SocketOptionName.DropMembership) {
        return((MulticastOption)obj_val);
      } else if (obj_val is int) {
        return((int)obj_val);
      } else {
        return(obj_val);
      }
    }

    [MethodImplAttribute (MethodImplOptions.InternalCall)]
    private extern static void Shutdown_internal (IntPtr socket, SocketShutdown how, out int error);
    
    public void Shutdown (SocketShutdown how)
    {
      if (disposed && closed)
        throw new ObjectDisposedException (GetType ().ToString ());

      if (!connected)
        throw new SocketException (10057); // Not connected

      int error;
      
      Shutdown_internal (socket, how, out error);
      if (error != 0)
        throw new SocketException (error);
    }

    [MethodImplAttribute(MethodImplOptions.InternalCall)]
    private extern static void SetSocketOption_internal (IntPtr socket, SocketOptionLevel level,
                     SocketOptionName name, object obj_val,
                     byte [] byte_val, int int_val,
                     out int error);

    public void SetSocketOption (SocketOptionLevel optionLevel, SocketOptionName optionName, int optionValue)
    {
      if (disposed && closed)
        throw new ObjectDisposedException (GetType ().ToString ());

      int error;

      SetSocketOption_internal (socket, optionLevel, optionName, null,
             null, optionValue, out error);

      if (error != 0)
        throw new SocketException (error);
    }

    private void ThrowIfUpd ()
    {
#if !NET_2_1
      if (protocol_type == ProtocolType.Udp)
        throw new SocketException ((int)SocketError.ProtocolOption);
#endif
    }

#if MOONLIGHT
    static void CheckConnect (SocketAsyncEventArgs e)
    {
      // NO check is made whether e != null in MS.NET (NRE is thrown in such case)

      if (e.RemoteEndPoint == null)
        throw new ArgumentNullException ("remoteEP");
      if (e.BufferList != null)
        throw new ArgumentException ("Multiple buffers cannot be used with this method.");
    }

    public bool ConnectAsync (SocketAsyncEventArgs e)
    {
      if (disposed && closed)
        throw new ObjectDisposedException (GetType ().ToString ());

      CheckConnect (e);

      e.DoOperation (SocketAsyncOperation.Connect, this);

      // We always return true for now
      return true;
    }

    public static bool ConnectAsync (SocketType socketType, ProtocolType protocolType, SocketAsyncEventArgs e)
    {
      // exception ordering requires to check before creating the socket (good thing resource wise too)
      CheckConnect (e);

      Socket s = new Socket (AddressFamily.InterNetwork, socketType, protocolType);
      e.DoOperation (SocketAsyncOperation.Connect, s);

      // We always return true for now
      return true;
    }

    public static void CancelConnectAsync (SocketAsyncEventArgs e)
    {
      if (e == null)
        throw new ArgumentNullException ("e");

      Socket s = e.ConnectSocket;
      if ((s != null) && (s.blocking_thread != null))
        s.blocking_thread.Abort ();
    }
#endif
  }
}

www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.