bool useConnect;
object locker = new object ();
object hostE = new object ();
-#if NET_1_1
bool useNagle;
-#endif
-#if NET_2_0
BindIPEndPoint endPointCallback = null;
-#endif
+ bool tcp_keepalive;
+ int tcp_keepalive_time;
+ int tcp_keepalive_interval;
// Constructors
this.connectionLimit = connectionLimit;
this.maxIdleTime = maxIdleTime;
this.currentConnections = 0;
- this.idleSince = DateTime.Now;
+ this.idleSince = DateTime.UtcNow;
}
// Properties
get { return uri; }
}
-#if NET_2_0
static Exception GetMustImplement ()
{
return new NotImplementedException ();
get { return endPointCallback; }
set { endPointCallback = value; }
}
-#endif
public X509Certificate Certificate {
get { return certificate; }
get { return clientCertificate; }
}
-#if NET_2_0
[MonoTODO]
public int ConnectionLeaseTimeout
{
throw GetMustImplement ();
}
}
-#endif
public int ConnectionLimit {
get { return connectionLimit; }
public DateTime IdleSince {
get {
- return idleSince;
+ return idleSince.ToLocalTime ();
}
internal set {
lock (locker)
- idleSince = value;
+ idleSince = value.ToUniversalTime ();
}
}
get { return protocolVersion; }
}
-#if NET_2_0
[MonoTODO]
public int ReceiveBufferSize
{
throw GetMustImplement ();
}
}
-#endif
public bool SupportsPipelining {
get { return HttpVersion.Version11.Equals (protocolVersion); }
}
-#if NET_1_1
+
public bool Expect100Continue {
get { return SendContinue; }
set { SendContinue = value; }
get { return useNagle; }
set { useNagle = value; }
}
-#endif
internal bool SendContinue {
get { return sendContinue &&
set { sendContinue = value; }
}
// Methods
-
-#if !NET_2_0
- public override int GetHashCode()
+
+ public void SetTcpKeepAlive (bool enabled, int keepAliveTime, int keepAliveInterval)
{
- return base.GetHashCode ();
+ 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;
}
-#endif
-
+
+ internal void KeepAliveSetup (Socket socket)
+ {
+ 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 {
get {
return CurrentConnections == 0
&& maxIdleTime != Timeout.Infinite
- && DateTime.Now >= IdleSince.AddMilliseconds (maxIdleTime);
+ && DateTime.UtcNow >= IdleSince.AddMilliseconds (maxIdleTime);
}
}
return cnc.SendRequest (request);
}
#endif
-#if NET_2_0
public bool CloseConnectionGroup (string connectionGroupName)
{
lock (locker) {
return false;
}
-#endif
internal void IncrementConnection ()
{
lock (locker) {
currentConnections++;
- idleSince = DateTime.Now.AddMilliseconds (1000000);
+ idleSince = DateTime.UtcNow.AddMilliseconds (1000000);
}
}
lock (locker) {
currentConnections--;
if (currentConnections == 0)
- idleSince = DateTime.Now;
+ idleSince = DateTime.UtcNow;
}
}
clientCertificate = client;
}
-#if NET_2_0
internal bool CallEndPointDelegate (Socket sock, IPEndPoint remote)
{
if (endPointCallback == null)
return true;
}
}
-#endif
}
}