Merge pull request #347 from JamesB7/master
[mono.git] / mcs / class / System / System.Net / ServicePoint.cs
index 956998e112b07201e62dea33dbd00c269277f163..12895c441dcb8ceeb8cfbca93b096aa9f3efbf2a 100644 (file)
@@ -55,9 +55,11 @@ namespace System.Net
                bool useConnect;
                object locker = new object ();
                object hostE = new object ();
-#if NET_1_1
                bool useNagle;
-#endif
+               BindIPEndPoint endPointCallback = null;
+               bool tcp_keepalive;
+               int tcp_keepalive_time;
+               int tcp_keepalive_interval;
                
                // Constructors
 
@@ -75,6 +77,17 @@ namespace System.Net
                public Uri Address {
                        get { return uri; }
                }
+
+               static Exception GetMustImplement ()
+               {
+                       return new NotImplementedException ();
+               }
+
+               public BindIPEndPoint BindIPEndPointDelegate
+               {
+                       get { return endPointCallback; }
+                       set { endPointCallback = value; }
+               }
                
                public X509Certificate Certificate {
                        get { return certificate; }
@@ -83,6 +96,17 @@ namespace System.Net
                public X509Certificate ClientCertificate {
                        get { return clientCertificate; }
                }
+
+               [MonoTODO]
+               public int ConnectionLeaseTimeout
+               {
+                       get {
+                               throw GetMustImplement ();
+                       }
+                       set {
+                               throw GetMustImplement ();
+                       }
+               }
                
                public int ConnectionLimit {
                        get { return connectionLimit; }
@@ -100,17 +124,17 @@ namespace System.Net
 
                public int CurrentConnections {
                        get {
-                               lock (locker) {
-                                       return currentConnections;
-                               }
+                               return currentConnections;
                        }
                }
 
                public DateTime IdleSince {
                        get {
-                               lock (locker) {
-                                       return idleSince;
-                               }
+                               return idleSince;
+                       }
+                       internal set {
+                               lock (locker)
+                                       idleSince = value;
                        }
                }
                
@@ -126,23 +150,32 @@ namespace System.Net
                public virtual Version ProtocolVersion {
                        get { return protocolVersion; }
                }
+
+               [MonoTODO]
+               public int ReceiveBufferSize
+               {
+                       get {
+                               throw GetMustImplement ();
+                       }
+                       set {
+                               throw GetMustImplement ();
+                       }
+               }
                
                public bool SupportsPipelining {
                        get { return HttpVersion.Version11.Equals (protocolVersion); }
                }
 
-#if NET_1_1
+
                public bool Expect100Continue {
                        get { return SendContinue; }
                        set { SendContinue = value; }
                }
 
-               [MonoTODO ("Use me")]
                public bool UseNagleAlgorithm {
                        get { return useNagle; }
                        set { useNagle = value; }
                }
-#endif
 
                internal bool SendContinue {
                        get { return sendContinue &&
@@ -150,12 +183,48 @@ namespace System.Net
                        set { sendContinue = value; }
                }
                // Methods
-               
-               public override int GetHashCode() 
+
+               public void SetTcpKeepAlive (bool enabled, int keepAliveTime, int keepAliveInterval)
+               {
+                       if (enabled) {
+                               if (keepAliveTime <= 0)
+                                       throw new ArgumentOutOfRangeException ("keepAliveTime", "Must be greater than 0");
+                               if (keepAliveInterval <= 0)
+                                       throw new ArgumentOutOfRangeException ("keepAliveInterval", "Must be greater than 0");
+                       }
+
+                       tcp_keepalive = enabled;
+                       tcp_keepalive_time = keepAliveTime;
+                       tcp_keepalive_interval = keepAliveInterval;
+               }
+
+               internal void KeepAliveSetup (Socket socket)
                {
-                       return base.GetHashCode ();
+                       if (!tcp_keepalive)
+                               return;
+
+                       byte [] bytes = new byte [12];
+                       PutBytes (bytes, (uint) (tcp_keepalive ? 1 : 0), 0);
+                       PutBytes (bytes, (uint) tcp_keepalive_time, 4);
+                       PutBytes (bytes, (uint) tcp_keepalive_interval, 8);
+                       socket.IOControl (IOControlCode.KeepAliveValues, bytes, null);
                }
-               
+
+               static void PutBytes (byte [] bytes, uint v, int offset)
+               {
+                       if (BitConverter.IsLittleEndian) {
+                               bytes [offset] = (byte) (v & 0x000000ff);
+                               bytes [offset + 1] = (byte) ((v & 0x0000ff00) >> 8);
+                               bytes [offset + 2] = (byte) ((v & 0x00ff0000) >> 16);
+                               bytes [offset + 3] = (byte) ((v & 0xff000000) >> 24);
+                       } else {
+                               bytes [offset + 3] = (byte) (v & 0x000000ff);
+                               bytes [offset + 2] = (byte) ((v & 0x0000ff00) >> 8);
+                               bytes [offset + 1] = (byte) ((v & 0x00ff0000) >> 16);
+                               bytes [offset] = (byte) ((v & 0xff000000) >> 24);
+                       }
+               }
+
                // Internal Methods
 
                internal bool UsesProxy {
@@ -227,7 +296,8 @@ namespace System.Net
                {
                        protocolVersion = version;
                }
-               
+
+#if !TARGET_JVM
                WebConnectionGroup GetConnectionGroup (string name)
                {
                        if (name == null)
@@ -248,11 +318,24 @@ namespace System.Net
                        
                        lock (locker) {
                                WebConnectionGroup cncGroup = GetConnectionGroup (groupName);
-                               cnc = cncGroup.GetConnection ();
+                               cnc = cncGroup.GetConnection (request);
                        }
                        
                        return cnc.SendRequest (request);
                }
+#endif
+               public bool CloseConnectionGroup (string connectionGroupName)
+               {
+                       lock (locker) {
+                               WebConnectionGroup cncGroup = GetConnectionGroup (connectionGroupName);
+                               if (cncGroup != null) {
+                                       cncGroup.Close ();
+                                       return true;
+                               }
+                       }
+
+                       return false;
+               }
 
                internal void IncrementConnection ()
                {
@@ -276,6 +359,43 @@ namespace System.Net
                        certificate = server;
                        clientCertificate = client;
                }
+
+               internal bool CallEndPointDelegate (Socket sock, IPEndPoint remote)
+               {
+                       if (endPointCallback == null)
+                               return true;
+
+                       int count = 0;
+                       for (;;) {
+                               IPEndPoint local = null;
+                               try {
+                                       local = endPointCallback (this,
+                                               remote, count);
+                               } catch {
+                                       // This is to differentiate from an
+                                       // OverflowException, which should propagate.
+                                       return false;
+                               }
+
+                               if (local == null)
+                                       return true;
+
+                               try {
+                                       sock.Bind (local);
+                               } catch (SocketException) {
+                                       // This is intentional; the docs say
+                                       // that if the Bind fails, we keep
+                                       // going until there is an
+                                       // OverflowException on the retry
+                                       // count.
+                                       checked { ++count; }
+                                       continue;
+                               }
+
+                               return true;
+                       }
+               }
        }
 }
 
+