This seeks to add an async DNS lookup step to the ICAP connection setup process.

As a side effect it adds a little bit of tcp_outgoing_address support to ICAP. Its limited to "dst" ACL at present. So outgoing ACL selections depending on HTTP request details wont work. Which makes sense since this connection may be reused for multiple requests.

I've skipped the idea of using more than one IP result since there seems to be no sane place to store multiple IPs between connect attempts. It currently relies on ipcache MarkGood/MarkBad keeping a good usable IP at the top of the IP set.

Amos
=== modified file 'src/adaptation/icap/ServiceRep.cc'
--- src/adaptation/icap/ServiceRep.cc	2011-06-17 10:41:10 +0000
+++ src/adaptation/icap/ServiceRep.cc	2011-06-24 14:59:58 +0000
@@ -106,9 +106,7 @@
     else
         theIdleConns.closeN(1);
 
-    if (!(reused = Comm::IsConnOpen(connection)))
-        connection = new Comm::Connection;
-    else {
+    if ((reused = Comm::IsConnOpen(connection))) {
         debugs(93,3, HERE << "reused pconn " << connection);
         ++theBusyConns;
     }

=== modified file 'src/adaptation/icap/Xaction.cc'
--- src/adaptation/icap/Xaction.cc	2011-06-17 10:41:10 +0000
+++ src/adaptation/icap/Xaction.cc	2011-06-24 15:05:08 +0000
@@ -16,6 +16,7 @@
 #include "pconn.h"
 #include "HttpRequest.h"
 #include "HttpReply.h"
+#include "ipcache.h"
 #include "acl/FilledChecklist.h"
 #include "icap_log.h"
 #include "fde.h"
@@ -85,6 +86,13 @@
     Must(static_cast<size_t>(readBuf.potentialSpaceSize()) <= commBufSize);
 }
 
+static void
+icapLookupDnsResults(const ipcache_addrs *ia, const DnsLookupDetails &, void *data)
+{
+    Adaptation::Icap::Xaction *xa = static_cast<Adaptation::Icap::Xaction *>(data);
+    xa->dnsLookupDone(ia);
+}
+
 // TODO: obey service-specific, OPTIONS-reported connection limit
 void
 Adaptation::Icap::Xaction::openConnection()
@@ -124,9 +132,38 @@
     // Attempt to open a new connection...
     debugs(93,3, typeName << " opens connection to " << s.cfg().host.termedBuf() << ":" << s.cfg().port);
 
-    // TODO: find the IPs and attempt each one if this is a named service.
-    connection->remote = s.cfg().host.termedBuf();
+    // Locate the Service IP(s) to open
+    ipcache_nbgethostbyname(s.cfg().host.termedBuf(), icapLookupDnsResults, this);
+}
+
+void
+Adaptation::Icap::Xaction::dnsLookupDone(const ipcache_addrs *ia)
+{
+    if (ia == NULL) {
+        debugs(44, DBG_WARNING, "ICAP: Unknown service host: " << s.cfg().host);
+
+#if WHEN_IPCACHE_NBGETHOSTBYNAME_USES_ASYNC_CALLS
+        dieOnConnectionFailure(); // throws
+#else // take a step back into protected Async call dialing.
+        // fake the connect callback
+        typedef CommCbMemFunT<Adaptation::Icap::Xaction, CommConnectCbParams> Dialer;
+        CbcPointer<Xaction> self(this);
+        Dialer dialer(self, &Adaptation::Icap::Xaction::noteCommConnected);
+        dialer.params.conn = connection;
+        dialer.params.flag = COMM_ERR;
+        // fake other parameters by copying from the existing connection
+        connector = asyncCall(93,3, "Adaptation::Icap::Xaction::noteCommConnected", dialer);
+        ScheduleCallHere(connector);
+#endif
+        return;
+    }
+
+    assert(ia->cur < ia->count);
+
+    connection = new Comm::Connection;
+    connection->remote = ia->in_addrs[ia->cur];
     connection->remote.SetPort(s.cfg().port);
+    getOutgoingAddress(NULL, connection);
 
     // TODO: service bypass status may differ from that of a transaction
     typedef CommCbMemFunT<Adaptation::Icap::Xaction, CommTimeoutCbParams> TimeoutDialer;

=== modified file 'src/adaptation/icap/Xaction.h'
--- src/adaptation/icap/Xaction.h	2011-06-04 12:48:45 +0000
+++ src/adaptation/icap/Xaction.h	2011-06-24 15:04:50 +0000
@@ -43,6 +43,7 @@
 #include "HttpReply.h"
 
 class CommConnectCbParams;
+struct ipcache_addrs;
 
 namespace Adaptation
 {
@@ -100,6 +101,7 @@
     virtual void detailError(int errDetail) {}
 
     void openConnection();
+    void dnsLookupDone(const ipcache_addrs *ia);
     void closeConnection();
     void dieOnConnectionFailure();
     bool haveConnection() const;

Reply via email to