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
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; }
public X509Certificate ClientCertificate {
get { return clientCertificate; }
}
+
+ [MonoTODO]
+ public int ConnectionLeaseTimeout
+ {
+ get {
+ throw GetMustImplement ();
+ }
+ set {
+ throw GetMustImplement ();
+ }
+ }
public int ConnectionLimit {
get { return connectionLimit; }
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;
}
}
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 &&
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 {
{
protocolVersion = version;
}
-
+
+#if !TARGET_JVM
WebConnectionGroup GetConnectionGroup (string name)
{
if (name == null)
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 ()
{
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;
+ }
+ }
}
}
+