]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/comm.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / comm.cc
index 9f19f1dbb4d5e8ad12a59517b27dd611b517ed78..1b62d7d19a37d0fcc1cbfd0ff7a4195e400c78c6 100644 (file)
@@ -1,37 +1,13 @@
 /*
- * DEBUG: section 05    Socket Functions
- * AUTHOR: Harvest Derived
+ * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
  *
- * SQUID Web Proxy Cache          http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- *  Squid is the result of efforts by numerous individuals from
- *  the Internet community; see the CONTRIBUTORS file for full
- *  details.   Many organizations have provided support for Squid's
- *  development; see the SPONSORS file for full details.  Squid is
- *  Copyrighted (C) 2001 by the Regents of the University of
- *  California; see the COPYRIGHT file for full details.  Squid
- *  incorporates software developed and/or copyrighted by other
- *  sources; see the CREDITS file for full details.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
- *
- *
- * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
+/* DEBUG: section 05    Socket Functions */
+
 #include "squid.h"
 #include "ClientInfo.h"
 #include "comm/AcceptLimiter.h"
@@ -39,6 +15,7 @@
 #include "comm/Connection.h"
 #include "comm/IoCallback.h"
 #include "comm/Loops.h"
+#include "comm/Read.h"
 #include "comm/TcpAcceptor.h"
 #include "comm/Write.h"
 #include "CommRead.h"
 #include "ip/tools.h"
 #include "pconn.h"
 #include "profiler/Profiler.h"
+#include "sbuf/SBuf.h"
 #include "SquidConfig.h"
 #include "StatCounters.h"
 #include "StoreIOBuffer.h"
 #include "tools.h"
 
-#if USE_SSL
+#if USE_OPENSSL
 #include "ssl/support.h"
 #endif
 
+#include <cerrno>
+#include <cmath>
 #if _SQUID_CYGWIN_
 #include <sys/ioctl.h>
 #endif
 #if HAVE_SYS_UN_H
 #include <sys/un.h>
 #endif
-#if HAVE_MATH_H
-#include <math.h>
-#endif
-#if HAVE_ERRNO_H
-#include <errno.h>
-#endif
 
 /*
  * New C-like simple comm code. This stuff is a mess and doesn't really buy us anything.
  */
 
-static void commStopHalfClosedMonitor(int fd);
 static IOCB commHalfClosedReader;
-static void comm_init_opened(const Comm::ConnectionPointer &conn, tos_t tos, nfmark_t nfmark, const char *note, struct addrinfo *AI);
+static void comm_init_opened(const Comm::ConnectionPointer &conn, const char *note, struct addrinfo *AI);
 static int comm_apply_flags(int new_socket, Ip::Address &addr, int flags, struct addrinfo *AI);
 
 #if USE_DELAY_POOLS
@@ -101,7 +74,7 @@ static bool WillCheckHalfClosed = false; /// true if check is scheduled
 static EVH commHalfClosedCheck;
 static void commPlanHalfClosedCheck();
 
-static comm_err_t commBind(int s, struct addrinfo &);
+static Comm::Flag commBind(int s, struct addrinfo &);
 static void commSetReuseAddr(int);
 static void commSetNoLinger(int);
 #ifdef TCP_NODELAY
@@ -117,75 +90,6 @@ isOpen(const int fd)
     return fd >= 0 && fd_table && fd_table[fd].flags.open != 0;
 }
 
-/**
- * Attempt a read
- *
- * If the read attempt succeeds or fails, call the callback.
- * Else, wait for another IO notification.
- */
-void
-commHandleRead(int fd, void *data)
-{
-    Comm::IoCallback *ccb = (Comm::IoCallback *) data;
-
-    assert(data == COMMIO_FD_READCB(fd));
-    assert(ccb->active());
-    /* Attempt a read */
-    ++ statCounter.syscalls.sock.reads;
-    errno = 0;
-    int retval;
-    retval = FD_READ_METHOD(fd, ccb->buf, ccb->size);
-    debugs(5, 3, "comm_read_try: FD " << fd << ", size " << ccb->size << ", retval " << retval << ", errno " << errno);
-
-    if (retval < 0 && !ignoreErrno(errno)) {
-        debugs(5, 3, "comm_read_try: scheduling COMM_ERROR");
-        ccb->offset = 0;
-        ccb->finish(COMM_ERROR, errno);
-        return;
-    };
-
-    /* See if we read anything */
-    /* Note - read 0 == socket EOF, which is a valid read */
-    if (retval >= 0) {
-        fd_bytes(fd, retval, FD_READ);
-        ccb->offset = retval;
-        ccb->finish(COMM_OK, errno);
-        return;
-    }
-
-    /* Nope, register for some more IO */
-    Comm::SetSelect(fd, COMM_SELECT_READ, commHandleRead, data, 0);
-}
-
-/**
- * Queue a read. handler/handler_data are called when the read
- * completes, on error, or on file descriptor close.
- */
-void
-comm_read(const Comm::ConnectionPointer &conn, char *buf, int size, AsyncCall::Pointer &callback)
-{
-    debugs(5, 5, "comm_read, queueing read for " << conn << "; asynCall " << callback);
-
-    /* Make sure we are open and not closing */
-    assert(Comm::IsConnOpen(conn));
-    assert(!fd_table[conn->fd].closing());
-    Comm::IoCallback *ccb = COMMIO_FD_READCB(conn->fd);
-
-    // Make sure we are either not reading or just passively monitoring.
-    // Active/passive conflicts are OK and simply cancel passive monitoring.
-    if (ccb->active()) {
-        // if the assertion below fails, we have an active comm_read conflict
-        assert(fd_table[conn->fd].halfClosedReader != NULL);
-        commStopHalfClosedMonitor(conn->fd);
-        assert(!ccb->active());
-    }
-    ccb->conn = conn;
-
-    /* Queue the read */
-    ccb->setCallback(Comm::IOCB_READ, callback, (char *)buf, NULL, size);
-    Comm::SetSelect(conn->fd, COMM_SELECT_READ, commHandleRead, ccb, 0);
-}
-
 /**
  * Empty the read buffers
  *
@@ -198,124 +102,20 @@ static void
 comm_empty_os_read_buffers(int fd)
 {
 #if _SQUID_LINUX_
+#if USE_OPENSSL
+    // Bug 4146: SSL-Bump BIO does not release sockets on close.
+    if (fd_table[fd].ssl)
+        return;
+#endif
+
     /* prevent those nasty RST packets */
     char buf[SQUID_TCP_SO_RCVBUF];
-
-    if (fd_table[fd].flags.nonblocking) {
+    if (fd_table[fd].flags.nonblocking && fd_table[fd].type != FD_MSGHDR) {
         while (FD_READ_METHOD(fd, buf, SQUID_TCP_SO_RCVBUF) > 0) {};
     }
 #endif
 }
 
-/**
- * Return whether the FD has a pending completed callback.
- * NP: does not work.
- */
-int
-comm_has_pending_read_callback(int fd)
-{
-    assert(isOpen(fd));
-    // XXX: We do not know whether there is a read callback scheduled.
-    // This is used for pconn management that should probably be more
-    // tightly integrated into comm to minimize the chance that a
-    // closing pconn socket will be used for a new transaction.
-    return false;
-}
-
-// Does comm check this fd for read readiness?
-// Note that when comm is not monitoring, there can be a pending callback
-// call, which may resume comm monitoring once fired.
-bool
-comm_monitors_read(int fd)
-{
-    assert(isOpen(fd) && COMMIO_FD_READCB(fd));
-    // Being active is usually the same as monitoring because we always
-    // start monitoring the FD when we configure Comm::IoCallback for I/O
-    // and we usually configure Comm::IoCallback for I/O when we starting
-    // monitoring a FD for reading.
-    return COMMIO_FD_READCB(fd)->active();
-}
-
-/**
- * Cancel a pending read. Assert that we have the right parameters,
- * and that there are no pending read events!
- *
- * XXX: We do not assert that there are no pending read events and
- * with async calls it becomes even more difficult.
- * The whole interface should be reworked to do callback->cancel()
- * instead of searching for places where the callback may be stored and
- * updating the state of those places.
- *
- * AHC Don't call the comm handlers?
- */
-void
-comm_read_cancel(int fd, IOCB *callback, void *data)
-{
-    if (!isOpen(fd)) {
-        debugs(5, 4, "comm_read_cancel fails: FD " << fd << " closed");
-        return;
-    }
-
-    Comm::IoCallback *cb = COMMIO_FD_READCB(fd);
-    // TODO: is "active" == "monitors FD"?
-    if (!cb->active()) {
-        debugs(5, 4, "comm_read_cancel fails: FD " << fd << " inactive");
-        return;
-    }
-
-    typedef CommCbFunPtrCallT<CommIoCbPtrFun> Call;
-    Call *call = dynamic_cast<Call*>(cb->callback.getRaw());
-    if (!call) {
-        debugs(5, 4, "comm_read_cancel fails: FD " << fd << " lacks callback");
-        return;
-    }
-
-    call->cancel("old comm_read_cancel");
-
-    typedef CommIoCbParams Params;
-    const Params &params = GetCommParams<Params>(cb->callback);
-
-    /* Ok, we can be reasonably sure we won't lose any data here! */
-    assert(call->dialer.handler == callback);
-    assert(params.data == data);
-
-    /* Delete the callback */
-    cb->cancel("old comm_read_cancel");
-
-    /* And the IO event */
-    Comm::SetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
-}
-
-void
-comm_read_cancel(int fd, AsyncCall::Pointer &callback)
-{
-    callback->cancel("comm_read_cancel");
-
-    if (!isOpen(fd)) {
-        debugs(5, 4, "comm_read_cancel fails: FD " << fd << " closed");
-        return;
-    }
-
-    Comm::IoCallback *cb = COMMIO_FD_READCB(fd);
-
-    if (!cb->active()) {
-        debugs(5, 4, "comm_read_cancel fails: FD " << fd << " inactive");
-        return;
-    }
-
-    AsyncCall::Pointer call = cb->callback;
-    assert(call != NULL); // XXX: should never fail (active() checks for callback==NULL)
-
-    /* Ok, we can be reasonably sure we won't lose any data here! */
-    assert(call == callback);
-
-    /* Delete the callback */
-    cb->cancel("comm_read_cancel");
-
-    /* And the IO event */
-    Comm::SetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
-}
-
 /**
  * synchronous wrapper around udp socket functions
  */
@@ -325,10 +125,10 @@ comm_udp_recvfrom(int fd, void *buf, size_t len, int flags, Ip::Address &from)
     ++ statCounter.syscalls.sock.recvfroms;
     debugs(5,8, "comm_udp_recvfrom: FD " << fd << " from " << from);
     struct addrinfo *AI = NULL;
-    Ip::Address::InitAddrInfo(AI);
+    Ip::Address::InitAddr(AI);
     int x = recvfrom(fd, buf, len, flags, AI->ai_addr, &AI->ai_addrlen);
     from = *AI;
-    Ip::Address::FreeAddrInfo(AI);
+    Ip::Address::FreeAddr(AI);
     return x;
 }
 
@@ -348,7 +148,7 @@ comm_udp_send(int s, const void *buf, size_t len, int flags)
 bool
 comm_has_incomplete_write(int fd)
 {
-    assert(isOpen(fd) && COMMIO_FD_WRITECB(fd));
+    assert(isOpen(fd) && COMMIO_FD_WRITECB(fd) != NULL);
     return COMMIO_FD_WRITECB(fd)->active();
 }
 
@@ -378,16 +178,17 @@ comm_local_port(int fd)
     if (F->sock_family == AF_INET)
         temp.setIPv4();
 
-    Ip::Address::InitAddrInfo(addr);
+    Ip::Address::InitAddr(addr);
 
     if (getsockname(fd, addr->ai_addr, &(addr->ai_addrlen)) ) {
-        debugs(50, DBG_IMPORTANT, "comm_local_port: Failed to retrieve TCP/UDP port number for socket: FD " << fd << ": " << xstrerror());
-        Ip::Address::FreeAddrInfo(addr);
+        int xerrno = errno;
+        debugs(50, DBG_IMPORTANT, MYNAME << "Failed to retrieve TCP/UDP port number for socket: FD " << fd << ": " << xstrerr(xerrno));
+        Ip::Address::FreeAddr(addr);
         return 0;
     }
     temp = *addr;
 
-    Ip::Address::FreeAddrInfo(addr);
+    Ip::Address::FreeAddr(addr);
 
     if (F->local_addr.isAnyAddr()) {
         /* save the whole local address, not just the port. */
@@ -400,19 +201,19 @@ comm_local_port(int fd)
     return F->local_addr.port();
 }
 
-static comm_err_t
+static Comm::Flag
 commBind(int s, struct addrinfo &inaddr)
 {
     ++ statCounter.syscalls.sock.binds;
 
     if (bind(s, inaddr.ai_addr, inaddr.ai_addrlen) == 0) {
-        debugs(50, 6, "commBind: bind socket FD " << s << " to " << fd_table[s].local_addr);
-        return COMM_OK;
+        debugs(50, 6, "bind socket FD " << s << " to " << fd_table[s].local_addr);
+        return Comm::OK;
     }
+    int xerrno = errno;
+    debugs(50, DBG_CRITICAL, MYNAME << "Cannot bind socket FD " << s << " to " << fd_table[s].local_addr << ": " << xstrerr(xerrno));
 
-    debugs(50, 0, "commBind: Cannot bind socket FD " << s << " to " << fd_table[s].local_addr << ": " << xstrerror());
-
-    return COMM_ERROR;
+    return Comm::COMM_ERROR;
 }
 
 /**
@@ -426,7 +227,7 @@ comm_open(int sock_type,
           int flags,
           const char *note)
 {
-    return comm_openex(sock_type, proto, addr, flags, 0, 0, note);
+    return comm_openex(sock_type, proto, addr, flags, note);
 }
 
 void
@@ -439,7 +240,7 @@ comm_open_listener(int sock_type,
     conn->flags |= COMM_DOBIND;
 
     /* attempt native enabled port. */
-    conn->fd = comm_openex(sock_type, proto, conn->local, conn->flags, 0, 0, note);
+    conn->fd = comm_openex(sock_type, proto, conn->local, conn->flags, note);
 }
 
 int
@@ -455,7 +256,7 @@ comm_open_listener(int sock_type,
     flags |= COMM_DOBIND;
 
     /* attempt native enabled port. */
-    sock = comm_openex(sock_type, proto, addr, flags, 0, 0, note);
+    sock = comm_openex(sock_type, proto, addr, flags, note);
 
     return sock;
 }
@@ -471,10 +272,11 @@ comm_set_v6only(int fd, int tos)
 {
 #ifdef IPV6_V6ONLY
     if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &tos, sizeof(int)) < 0) {
-        debugs(50, DBG_IMPORTANT, "comm_open: setsockopt(IPV6_V6ONLY) " << (tos?"ON":"OFF") << " for FD " << fd << ": " << xstrerror());
+        int xerrno = errno;
+        debugs(50, DBG_IMPORTANT, MYNAME << "setsockopt(IPV6_V6ONLY) " << (tos?"ON":"OFF") << " for FD " << fd << ": " << xstrerr(xerrno));
     }
 #else
-    debugs(50, 0, "WARNING: comm_open: setsockopt(IPV6_V6ONLY) not supported on this platform");
+    debugs(50, DBG_CRITICAL, MYNAME << "WARNING: setsockopt(IPV6_V6ONLY) not supported on this platform");
 #endif /* sockopt */
 }
 
@@ -511,7 +313,8 @@ comm_set_transparent(int fd)
 #if defined(soLevel) && defined(soFlag)
     int tos = 1;
     if (setsockopt(fd, soLevel, soFlag, (char *) &tos, sizeof(int)) < 0) {
-        debugs(50, DBG_IMPORTANT, "comm_open: setsockopt(TPROXY) on FD " << fd << ": " << xstrerror());
+        int xerrno = errno;
+        debugs(50, DBG_IMPORTANT, MYNAME << "setsockopt(TPROXY) on FD " << fd << ": " << xstrerr(xerrno));
     } else {
         /* mark the socket as having transparent options */
         fd_table[fd].flags.transparent = true;
@@ -530,8 +333,6 @@ comm_openex(int sock_type,
             int proto,
             Ip::Address &addr,
             int flags,
-            tos_t tos,
-            nfmark_t nfmark,
             const char *note)
 {
     int new_socket;
@@ -549,19 +350,20 @@ comm_openex(int sock_type,
     debugs(50, 3, "comm_openex: Attempt open socket for: " << addr );
 
     new_socket = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol);
+    int xerrno = errno;
 
     /* under IPv6 there is the possibility IPv6 is present but disabled. */
     /* try again as IPv4-native if possible */
     if ( new_socket < 0 && Ip::EnableIpv6 && addr.isIPv6() && addr.setIPv4() ) {
         /* attempt to open this IPv4-only. */
-        Ip::Address::FreeAddrInfo(AI);
+        Ip::Address::FreeAddr(AI);
         /* Setup the socket addrinfo details for use */
         addr.getAddrInfo(AI);
         AI->ai_socktype = sock_type;
         AI->ai_protocol = proto;
-        debugs(50, 3, "comm_openex: Attempt fallback open socket for: " << addr );
+        debugs(50, 3, "Attempt fallback open socket for: " << addr );
         new_socket = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol);
-        debugs(50, 2, HERE << "attempt open " << note << " socket on: " << addr);
+        debugs(50, 2, "attempt open " << note << " socket on: " << addr);
     }
 
     if (new_socket < 0) {
@@ -570,15 +372,16 @@ comm_openex(int sock_type,
          * limits the number of simultaneous clients */
 
         if (limitError(errno)) {
-            debugs(50, DBG_IMPORTANT, "comm_open: socket failure: " << xstrerror());
+            debugs(50, DBG_IMPORTANT, MYNAME << "socket failure: " << xstrerr(xerrno));
             fdAdjustReserved();
         } else {
-            debugs(50, DBG_CRITICAL, "comm_open: socket failure: " << xstrerror());
+            debugs(50, DBG_CRITICAL, MYNAME << "socket failure: " << xstrerr(xerrno));
         }
 
-        Ip::Address::FreeAddrInfo(AI);
+        Ip::Address::FreeAddr(AI);
 
         PROF_stop(comm_open);
+        errno = xerrno; // restore for caller
         return -1;
     }
 
@@ -589,14 +392,6 @@ comm_openex(int sock_type,
 
     debugs(50, 3, "comm_openex: Opened socket " << conn << " : family=" << AI->ai_family << ", type=" << AI->ai_socktype << ", protocol=" << AI->ai_protocol );
 
-    /* set TOS if needed */
-    if (tos)
-        Ip::Qos::setSockTos(conn, tos);
-
-    /* set netfilter mark if needed */
-    if (nfmark)
-        Ip::Qos::setSockNfmark(conn, nfmark);
-
     if ( Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && addr.isIPv6() )
         comm_set_v6only(conn->fd, 1);
 
@@ -605,23 +400,22 @@ comm_openex(int sock_type,
     if ( Ip::EnableIpv6&IPV6_SPECIAL_V4MAPPING && addr.isIPv6() )
         comm_set_v6only(conn->fd, 0);
 
-    comm_init_opened(conn, tos, nfmark, note, AI);
+    comm_init_opened(conn, note, AI);
     new_socket = comm_apply_flags(conn->fd, addr, flags, AI);
 
-    Ip::Address::FreeAddrInfo(AI);
+    Ip::Address::FreeAddr(AI);
 
     PROF_stop(comm_open);
 
     // XXX transition only. prevent conn from closing the new FD on function exit.
     conn->fd = -1;
+    errno = xerrno; // restore for caller
     return new_socket;
 }
 
 /// update FD tables after a local or remote (IPC) comm_openex();
 void
 comm_init_opened(const Comm::ConnectionPointer &conn,
-                 tos_t tos,
-                 nfmark_t nfmark,
                  const char *note,
                  struct addrinfo *AI)
 {
@@ -639,9 +433,6 @@ comm_init_opened(const Comm::ConnectionPointer &conn,
 
     fde *F = &fd_table[conn->fd];
     F->local_addr = conn->local;
-    F->tosToServer = tos;
-
-    F->nfmarkToServer = nfmark;
 
     F->sock_family = AI->ai_family;
 }
@@ -685,14 +476,14 @@ comm_apply_flags(int new_socket,
         if ( addr.isNoAddr() )
             debugs(5,0,"CRITICAL: Squid is attempting to bind() port " << addr << "!!");
 
-        if (commBind(new_socket, *AI) != COMM_OK) {
+        if (commBind(new_socket, *AI) != Comm::OK) {
             comm_close(new_socket);
             return -1;
         }
     }
 
     if (flags & COMM_NONBLOCKING)
-        if (commSetNonBlocking(new_socket) == COMM_ERROR) {
+        if (commSetNonBlocking(new_socket) == Comm::COMM_ERROR) {
             comm_close(new_socket);
             return -1;
         }
@@ -718,7 +509,7 @@ comm_import_opened(const Comm::ConnectionPointer &conn,
     assert(Comm::IsConnOpen(conn));
     assert(AI);
 
-    comm_init_opened(conn, 0, 0, note, AI);
+    comm_init_opened(conn, note, AI);
 
     if (!(conn->flags & COMM_NOCLOEXEC))
         fd_table[conn->fd].flags.close_on_exec = true;
@@ -796,10 +587,15 @@ commUnsetConnTimeout(const Comm::ConnectionPointer &conn)
     return commSetConnTimeout(conn, -1, nil);
 }
 
+/**
+ * Connect socket FD to given remote address.
+ * If return value is an error flag (COMM_ERROR, ERR_CONNECT, ERR_PROTOCOL, etc.),
+ * then error code will also be returned in errno.
+ */
 int
 comm_connect_addr(int sock, const Ip::Address &address)
 {
-    comm_err_t status = COMM_OK;
+    Comm::Flag status = Comm::OK;
     fde *F = &fd_table[sock];
     int x = 0;
     int err = 0;
@@ -818,7 +614,7 @@ comm_connect_addr(int sock, const Ip::Address &address)
      */
     if (F->sock_family == AF_INET && !address.isIPv4()) {
         errno = ENETUNREACH;
-        return COMM_ERR_PROTOCOL;
+        return Comm::ERR_PROTOCOL;
     }
 
     /* Handle IPv4 over IPv6-only socket case.
@@ -830,60 +626,56 @@ comm_connect_addr(int sock, const Ip::Address &address)
      */
     if (!F->local_addr.isIPv4() && address.isIPv4()) {
         errno = ENETUNREACH;
-        return COMM_ERR_PROTOCOL;
+        return Comm::ERR_PROTOCOL;
     }
 
     address.getAddrInfo(AI, F->sock_family);
 
     /* Establish connection. */
-    errno = 0;
+    int xerrno = 0;
 
     if (!F->flags.called_connect) {
         F->flags.called_connect = true;
         ++ statCounter.syscalls.sock.connects;
 
-        x = connect(sock, AI->ai_addr, AI->ai_addrlen);
-
-        // XXX: ICAP code refuses callbacks during a pending comm_ call
-        // Async calls development will fix this.
-        if (x == 0) {
-            x = -1;
-            errno = EINPROGRESS;
-        }
-
-        if (x < 0) {
-            debugs(5,5, "comm_connect_addr: sock=" << sock << ", addrinfo( " <<
+        errno = 0;
+        if ((x = connect(sock, AI->ai_addr, AI->ai_addrlen)) < 0) {
+            xerrno = errno;
+            debugs(5,5, "sock=" << sock << ", addrinfo(" <<
                    " flags=" << AI->ai_flags <<
                    ", family=" << AI->ai_family <<
                    ", socktype=" << AI->ai_socktype <<
                    ", protocol=" << AI->ai_protocol <<
                    ", &addr=" << AI->ai_addr <<
-                   ", addrlen=" << AI->ai_addrlen <<
-                   " )" );
-            debugs(5, 9, "connect FD " << sock << ": (" << x << ") " << xstrerror());
-            debugs(14,9, "connecting to: " << address );
+                   ", addrlen=" << AI->ai_addrlen << " )");
+            debugs(5, 9, "connect FD " << sock << ": (" << x << ") " << xstrerr(xerrno));
+            debugs(14,9, "connecting to: " << address);
+
+        } else if (x == 0) {
+            // XXX: ICAP code refuses callbacks during a pending comm_ call
+            // Async calls development will fix this.
+            x = -1;
+            xerrno = EINPROGRESS;
         }
+
     } else {
+        errno = 0;
 #if _SQUID_NEWSOS6_
         /* Makoto MATSUSHITA <matusita@ics.es.osaka-u.ac.jp> */
+        if (connect(sock, AI->ai_addr, AI->ai_addrlen) < 0)
+            xerrno = errno;
 
-        connect(sock, AI->ai_addr, AI->ai_addrlen);
-
-        if (errno == EINVAL) {
+        if (xerrno == EINVAL) {
             errlen = sizeof(err);
             x = getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &errlen);
-
             if (x >= 0)
-                errno = x;
+                xerrno = x;
         }
-
 #else
         errlen = sizeof(err);
-
         x = getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &errlen);
-
         if (x == 0)
-            errno = err;
+            xerrno = err;
 
 #if _SQUID_SOLARIS_
         /*
@@ -892,37 +684,39 @@ comm_connect_addr(int sock, const Ip::Address &address)
         * connect and just returns EPIPE.  Create a fake
         * error message for connect.   -- fenner@parc.xerox.com
         */
-        if (x < 0 && errno == EPIPE)
-            errno = ENOTCONN;
-
+        if (x < 0 && xerrno == EPIPE)
+            xerrno = ENOTCONN;
+        else
+            xerrno = errno;
 #endif
 #endif
-
     }
 
-    Ip::Address::FreeAddrInfo(AI);
+    Ip::Address::FreeAddr(AI);
 
     PROF_stop(comm_connect_addr);
 
-    if (errno == 0 || errno == EISCONN)
-        status = COMM_OK;
-    else if (ignoreErrno(errno))
-        status = COMM_INPROGRESS;
-    else if (errno == EAFNOSUPPORT || errno == EINVAL)
-        return COMM_ERR_PROTOCOL;
+    errno = xerrno;
+    if (xerrno == 0 || xerrno == EISCONN)
+        status = Comm::OK;
+    else if (ignoreErrno(xerrno))
+        status = Comm::INPROGRESS;
+    else if (xerrno == EAFNOSUPPORT || xerrno == EINVAL)
+        return Comm::ERR_PROTOCOL;
     else
-        return COMM_ERROR;
+        return Comm::COMM_ERROR;
 
     address.toStr(F->ipaddr, MAX_IPSTRLEN);
 
     F->remote_port = address.port(); /* remote_port is HS */
 
-    if (status == COMM_OK) {
+    if (status == Comm::OK) {
         debugs(5, DBG_DATA, "comm_connect_addr: FD " << sock << " connected to " << address);
-    } else if (status == COMM_INPROGRESS) {
+    } else if (status == Comm::INPROGRESS) {
         debugs(5, DBG_DATA, "comm_connect_addr: FD " << sock << " connection pending");
     }
 
+    errno = xerrno;
     return status;
 }
 
@@ -949,12 +743,11 @@ static void
 commLingerClose(int fd, void *unused)
 {
     LOCAL_ARRAY(char, buf, 1024);
-    int n;
-    n = FD_READ_METHOD(fd, buf, 1024);
-
-    if (n < 0)
-        debugs(5, 3, "commLingerClose: FD " << fd << " read: " << xstrerror());
-
+    int n = FD_READ_METHOD(fd, buf, 1024);
+    if (n < 0) {
+        int xerrno = errno;
+        debugs(5, 3, "FD " << fd << " read: " << xstrerr(xerrno));
+    }
     comm_close(fd);
 }
 
@@ -971,7 +764,7 @@ commLingerTimeout(const FdeCbParams &params)
 void
 comm_lingering_close(int fd)
 {
-#if USE_SSL
+#if USE_OPENSSL
     if (fd_table[fd].ssl)
         ssl_shutdown_method(fd_table[fd].ssl);
 #endif
@@ -1010,9 +803,10 @@ comm_reset_close(const Comm::ConnectionPointer &conn)
     L.l_onoff = 1;
     L.l_linger = 0;
 
-    if (setsockopt(conn->fd, SOL_SOCKET, SO_LINGER, (char *) &L, sizeof(L)) < 0)
-        debugs(50, DBG_CRITICAL, "ERROR: Closing " << conn << " with TCP RST: " << xstrerror());
-
+    if (setsockopt(conn->fd, SOL_SOCKET, SO_LINGER, (char *) &L, sizeof(L)) < 0) {
+        int xerrno = errno;
+        debugs(50, DBG_CRITICAL, "ERROR: Closing " << conn << " with TCP RST: " << xstrerr(xerrno));
+    }
     conn->close();
 }
 
@@ -1024,38 +818,29 @@ old_comm_reset_close(int fd)
     L.l_onoff = 1;
     L.l_linger = 0;
 
-    if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &L, sizeof(L)) < 0)
-        debugs(50, DBG_CRITICAL, "ERROR: Closing FD " << fd << " with TCP RST: " << xstrerror());
-
+    if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &L, sizeof(L)) < 0) {
+        int xerrno = errno;
+        debugs(50, DBG_CRITICAL, "ERROR: Closing FD " << fd << " with TCP RST: " << xstrerr(xerrno));
+    }
     comm_close(fd);
 }
 
-#if USE_SSL
+#if USE_OPENSSL
 void
 commStartSslClose(const FdeCbParams &params)
 {
-    assert(&fd_table[params.fd].ssl);
-    ssl_shutdown_method(fd_table[params.fd].ssl);
+    assert(fd_table[params.fd].ssl);
+    ssl_shutdown_method(fd_table[params.fd].ssl.get());
 }
 #endif
 
 void
 comm_close_complete(const FdeCbParams &params)
 {
-#if USE_SSL
     fde *F = &fd_table[params.fd];
-
-    if (F->ssl) {
-        SSL_free(F->ssl);
-        F->ssl = NULL;
-    }
-
-    if (F->dynamicSslContext) {
-        SSL_CTX_free(F->dynamicSslContext);
-        F->dynamicSslContext = NULL;
-    }
-#endif
-    fd_close(params.fd);               /* update fdstat */
+    F->ssl.reset();
+    F->dynamicTlsContext.reset();
+    fd_close(params.fd);        /* update fdstat */
     close(params.fd);
 
     ++ statCounter.syscalls.sock.closes;
@@ -1071,7 +856,7 @@ comm_close_complete(const FdeCbParams &params)
  * + call read handlers with ERR_CLOSING
  * + call closing handlers
  *
- * NOTE: COMM_ERR_CLOSING will NOT be called for CommReads' sitting in a
+ * NOTE: Comm::ERR_CLOSING will NOT be called for CommReads' sitting in a
  * DeferredReadManager.
  */
 void
@@ -1105,7 +890,7 @@ _comm_close(int fd, char const *file, int line)
 
     F->flags.close_request = true;
 
-#if USE_SSL
+#if USE_OPENSSL
     if (F->ssl) {
         AsyncCall::Pointer startCall=commCbCall(5,4, "commStartSslClose",
                                                 FdeCbPtrFun(commStartSslClose, NULL));
@@ -1123,11 +908,11 @@ _comm_close(int fd, char const *file, int line)
     // notify read/write handlers after canceling select reservations, if any
     if (COMMIO_FD_WRITECB(fd)->active()) {
         Comm::SetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
-        COMMIO_FD_WRITECB(fd)->finish(COMM_ERR_CLOSING, errno);
+        COMMIO_FD_WRITECB(fd)->finish(Comm::ERR_CLOSING, errno);
     }
     if (COMMIO_FD_READCB(fd)->active()) {
         Comm::SetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
-        COMMIO_FD_READCB(fd)->finish(COMM_ERR_CLOSING, errno);
+        COMMIO_FD_READCB(fd)->finish(Comm::ERR_CLOSING, errno);
     }
 
 #if USE_DELAY_POOLS
@@ -1142,9 +927,6 @@ _comm_close(int fd, char const *file, int line)
 
     commCallCloseHandlers(fd);
 
-    if (F->pconn.uses && F->pconn.pool)
-        F->pconn.pool->noteUses(F->pconn.uses);
-
     comm_empty_os_read_buffers(fd);
 
     AsyncCall::Pointer completeCall=commCbCall(5,4, "comm_close_complete",
@@ -1174,24 +956,26 @@ comm_udp_sendto(int fd,
     struct addrinfo *AI = NULL;
     to_addr.getAddrInfo(AI, fd_table[fd].sock_family);
     int x = sendto(fd, buf, len, 0, AI->ai_addr, AI->ai_addrlen);
-    Ip::Address::FreeAddrInfo(AI);
+    int xerrno = errno;
+    Ip::Address::FreeAddr(AI);
 
     PROF_stop(comm_udp_sendto);
 
-    if (x >= 0)
+    if (x >= 0) {
+        errno = xerrno; // restore for caller to use
         return x;
+    }
 
 #if _SQUID_LINUX_
-
-    if (ECONNREFUSED != errno)
+    if (ECONNREFUSED != xerrno)
 #endif
+        debugs(50, DBG_IMPORTANT, MYNAME << "FD " << fd << ", (family=" << fd_table[fd].sock_family << ") " << to_addr << ": " << xstrerr(xerrno));
 
-        debugs(50, DBG_IMPORTANT, "comm_udp_sendto: FD " << fd << ", (family=" << fd_table[fd].sock_family << ") " << to_addr << ": " << xstrerror());
-
-    return COMM_ERROR;
+    errno = xerrno; // restore for caller to use
+    return Comm::COMM_ERROR;
 }
 
-void
+AsyncCall::Pointer
 comm_add_close_handler(int fd, CLCB * handler, void *data)
 {
     debugs(5, 5, "comm_add_close_handler: FD " << fd << ", handler=" <<
@@ -1200,6 +984,7 @@ comm_add_close_handler(int fd, CLCB * handler, void *data)
     AsyncCall::Pointer call=commCbCall(5,4, "SomeCloseHandler",
                                        CommCloseCbPtrFun(handler, data));
     comm_add_close_handler(fd, call);
+    return call;
 }
 
 void
@@ -1235,7 +1020,7 @@ comm_remove_close_handler(int fd, CLCB * handler, void *data)
         typedef CommCloseCbParams Params;
         const Params &params = GetCommParams<Params>(p);
         if (call->dialer.handler == handler && params.data == data)
-            break;             /* This is our handler */
+            break;      /* This is our handler */
     }
 
     // comm_close removes all close handlers so our handler may be gone
@@ -1266,12 +1051,13 @@ commSetNoLinger(int fd)
 {
 
     struct linger L;
-    L.l_onoff = 0;             /* off */
+    L.l_onoff = 0;      /* off */
     L.l_linger = 0;
 
-    if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &L, sizeof(L)) < 0)
-        debugs(50, 0, "commSetNoLinger: FD " << fd << ": " << xstrerror());
-
+    if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &L, sizeof(L)) < 0) {
+        int xerrno = errno;
+        debugs(50, DBG_CRITICAL, MYNAME << "FD " << fd << ": " << xstrerr(xerrno));
+    }
     fd_table[fd].flags.nolinger = true;
 }
 
@@ -1279,65 +1065,61 @@ static void
 commSetReuseAddr(int fd)
 {
     int on = 1;
-
-    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) < 0)
-        debugs(50, DBG_IMPORTANT, "commSetReuseAddr: FD " << fd << ": " << xstrerror());
+    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) < 0) {
+        int xerrno = errno;
+        debugs(50, DBG_IMPORTANT, MYNAME << "FD " << fd << ": " << xstrerr(xerrno));
+    }
 }
 
 static void
 commSetTcpRcvbuf(int fd, int size)
 {
-    if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *) &size, sizeof(size)) < 0)
-        debugs(50, DBG_IMPORTANT, "commSetTcpRcvbuf: FD " << fd << ", SIZE " << size << ": " << xstrerror());
-    if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &size, sizeof(size)) < 0)
-        debugs(50, DBG_IMPORTANT, "commSetTcpRcvbuf: FD " << fd << ", SIZE " << size << ": " << xstrerror());
+    if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *) &size, sizeof(size)) < 0) {
+        int xerrno = errno;
+        debugs(50, DBG_IMPORTANT, MYNAME << "FD " << fd << ", SIZE " << size << ": " << xstrerr(xerrno));
+    }
+    if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *) &size, sizeof(size)) < 0) {
+        int xerrno = errno;
+        debugs(50, DBG_IMPORTANT, MYNAME << "FD " << fd << ", SIZE " << size << ": " << xstrerr(xerrno));
+    }
 #ifdef TCP_WINDOW_CLAMP
-    if (setsockopt(fd, SOL_TCP, TCP_WINDOW_CLAMP, (char *) &size, sizeof(size)) < 0)
-        debugs(50, DBG_IMPORTANT, "commSetTcpRcvbuf: FD " << fd << ", SIZE " << size << ": " << xstrerror());
+    if (setsockopt(fd, SOL_TCP, TCP_WINDOW_CLAMP, (char *) &size, sizeof(size)) < 0) {
+        int xerrno = errno;
+        debugs(50, DBG_IMPORTANT, MYNAME << "FD " << fd << ", SIZE " << size << ": " << xstrerr(xerrno));
+    }
 #endif
 }
 
 int
 commSetNonBlocking(int fd)
 {
-#if !_SQUID_WINDOWS_
-    int flags;
-    int dummy = 0;
-#endif
 #if _SQUID_WINDOWS_
     int nonblocking = TRUE;
 
-#if _SQUID_CYGWIN_
-    if (fd_table[fd].type != FD_PIPE) {
-#endif
-
-        if (ioctl(fd, FIONBIO, &nonblocking) < 0) {
-            debugs(50, 0, "commSetNonBlocking: FD " << fd << ": " << xstrerror() << " " << fd_table[fd].type);
-            return COMM_ERROR;
-        }
-
-#if _SQUID_CYGWIN_
-    } else {
-#endif
-#endif
-#if !_SQUID_WINDOWS_
+    if (ioctl(fd, FIONBIO, &nonblocking) < 0) {
+        int xerrno = errno;
+        debugs(50, DBG_CRITICAL, MYNAME << "FD " << fd << ": " << xstrerr(xerrno) << " " << fd_table[fd].type);
+        return Comm::COMM_ERROR;
+    }
 
-        if ((flags = fcntl(fd, F_GETFL, dummy)) < 0) {
-            debugs(50, 0, "FD " << fd << ": fcntl F_GETFL: " << xstrerror());
-            return COMM_ERROR;
-        }
+#else
+    int flags;
+    int dummy = 0;
 
-        if (fcntl(fd, F_SETFL, flags | SQUID_NONBLOCK) < 0) {
-            debugs(50, 0, "commSetNonBlocking: FD " << fd << ": " << xstrerror());
-            return COMM_ERROR;
-        }
+    if ((flags = fcntl(fd, F_GETFL, dummy)) < 0) {
+        int xerrno = errno;
+        debugs(50, DBG_CRITICAL, MYNAME << "FD " << fd << ": fcntl F_GETFL: " << xstrerr(xerrno));
+        return Comm::COMM_ERROR;
+    }
 
-#endif
-#if _SQUID_CYGWIN_
+    if (fcntl(fd, F_SETFL, flags | SQUID_NONBLOCK) < 0) {
+        int xerrno = errno;
+        debugs(50, DBG_CRITICAL, MYNAME << "FD " << fd << ": " << xstrerr(xerrno));
+        return Comm::COMM_ERROR;
     }
 #endif
-    fd_table[fd].flags.nonblocking = true;
 
+    fd_table[fd].flags.nonblocking = true;
     return 0;
 }
 
@@ -1353,14 +1135,16 @@ commUnsetNonBlocking(int fd)
     int dummy = 0;
 
     if ((flags = fcntl(fd, F_GETFL, dummy)) < 0) {
-        debugs(50, 0, "FD " << fd << ": fcntl F_GETFL: " << xstrerror());
-        return COMM_ERROR;
+        int xerrno = errno;
+        debugs(50, DBG_CRITICAL, MYNAME << "FD " << fd << ": fcntl F_GETFL: " << xstrerr(xerrno));
+        return Comm::COMM_ERROR;
     }
 
     if (fcntl(fd, F_SETFL, flags & (~SQUID_NONBLOCK)) < 0) {
 #endif
-        debugs(50, 0, "commUnsetNonBlocking: FD " << fd << ": " << xstrerror());
-        return COMM_ERROR;
+        int xerrno = errno;
+        debugs(50, DBG_CRITICAL, MYNAME << "FD " << fd << ": " << xstrerr(xerrno));
+        return Comm::COMM_ERROR;
     }
 
     fd_table[fd].flags.nonblocking = false;
@@ -1375,12 +1159,15 @@ commSetCloseOnExec(int fd)
     int dummy = 0;
 
     if ((flags = fcntl(fd, F_GETFD, dummy)) < 0) {
-        debugs(50, 0, "FD " << fd << ": fcntl F_GETFD: " << xstrerror());
+        int xerrno = errno;
+        debugs(50, DBG_CRITICAL, MYNAME << "FD " << fd << ": fcntl F_GETFD: " << xstrerr(xerrno));
         return;
     }
 
-    if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
-        debugs(50, 0, "FD " << fd << ": set close-on-exec failed: " << xstrerror());
+    if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
+        int xerrno = errno;
+        debugs(50, DBG_CRITICAL, MYNAME << "FD " << fd << ": set close-on-exec failed: " << xstrerr(xerrno));
+    }
 
     fd_table[fd].flags.close_on_exec = true;
 
@@ -1393,8 +1180,10 @@ commSetTcpNoDelay(int fd)
 {
     int on = 1;
 
-    if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on)) < 0)
-        debugs(50, DBG_IMPORTANT, "commSetTcpNoDelay: FD " << fd << ": " << xstrerror());
+    if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on)) < 0) {
+        int xerrno = errno;
+        debugs(50, DBG_IMPORTANT, MYNAME << "FD " << fd << ": " << xstrerr(xerrno));
+    }
 
     fd_table[fd].flags.nodelay = true;
 }
@@ -1408,24 +1197,32 @@ commSetTcpKeepalive(int fd, int idle, int interval, int timeout)
 #ifdef TCP_KEEPCNT
     if (timeout && interval) {
         int count = (timeout + interval - 1) / interval;
-        if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &count, sizeof(on)) < 0)
-            debugs(5, DBG_IMPORTANT, "commSetKeepalive: FD " << fd << ": " << xstrerror());
+        if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &count, sizeof(on)) < 0) {
+            int xerrno = errno;
+            debugs(5, DBG_IMPORTANT, MYNAME << "FD " << fd << ": " << xstrerr(xerrno));
+        }
     }
 #endif
 #ifdef TCP_KEEPIDLE
     if (idle) {
-        if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(on)) < 0)
-            debugs(5, DBG_IMPORTANT, "commSetKeepalive: FD " << fd << ": " << xstrerror());
+        if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &idle, sizeof(on)) < 0) {
+            int xerrno = errno;
+            debugs(5, DBG_IMPORTANT, MYNAME << "FD " << fd << ": " << xstrerr(xerrno));
+        }
     }
 #endif
 #ifdef TCP_KEEPINTVL
     if (interval) {
-        if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(on)) < 0)
-            debugs(5, DBG_IMPORTANT, "commSetKeepalive: FD " << fd << ": " << xstrerror());
+        if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(on)) < 0) {
+            int xerrno = errno;
+            debugs(5, DBG_IMPORTANT, MYNAME << "FD " << fd << ": " << xstrerr(xerrno));
+        }
     }
 #endif
-    if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on)) < 0)
-        debugs(5, DBG_IMPORTANT, "commSetKeepalive: FD " << fd << ": " << xstrerror());
+    if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on)) < 0) {
+        int xerrno = errno;
+        debugs(5, DBG_IMPORTANT, MYNAME << "FD " << fd << ": " << xstrerr(xerrno));
+    }
 }
 
 void
@@ -1657,7 +1454,7 @@ ClientInfo::setWriteLimiter(const int aWriteSpeedLimit, const double anInitialBu
 }
 
 CommQuotaQueue::CommQuotaQueue(ClientInfo *info): clientInfo(info),
-        ins(0), outs(0)
+    ins(0), outs(0)
 {
     assert(clientInfo);
 }
@@ -1739,7 +1536,7 @@ commCloseAllSockets(void)
         if (F->type != FD_SOCKET)
             continue;
 
-        if (F->flags.ipc)      /* don't close inter-process sockets */
+        if (F->flags.ipc)   /* don't close inter-process sockets */
             continue;
 
         if (F->timeoutHandler != NULL) {
@@ -1795,7 +1592,7 @@ checkTimeouts(void)
             // We have an active write callback and we are timed out
             debugs(5, 5, "checkTimeouts: FD " << fd << " auto write timeout");
             Comm::SetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
-            COMMIO_FD_WRITECB(fd)->finish(COMM_ERROR, ETIMEDOUT);
+            COMMIO_FD_WRITECB(fd)->finish(Comm::COMM_ERROR, ETIMEDOUT);
         } else if (AlreadyTimedOut(F))
             continue;
 
@@ -1851,7 +1648,7 @@ commHalfClosedCheck(void *)
         if (!fd_table[c->fd].halfClosedReader) { // not reading already
             AsyncCall::Pointer call = commCbCall(5,4, "commHalfClosedReader",
                                                  CommIoCbPtrFun(&commHalfClosedReader, NULL));
-            comm_read(c, NULL, 0, call);
+            Comm::Read(c, call);
             fd_table[c->fd].halfClosedReader = call;
         } else
             c->fd = -1; // XXX: temporary. prevent c replacement erase closing listed FD
@@ -1870,7 +1667,7 @@ commHasHalfClosedMonitor(int fd)
 }
 
 /// stop waiting for possibly half-closed connection to close
-static void
+void
 commStopHalfClosedMonitor(int const fd)
 {
     debugs(5, 5, HERE << "removing FD " << fd << " from " << *TheHalfClosed);
@@ -1878,7 +1675,7 @@ commStopHalfClosedMonitor(int const fd)
     // cancel the read if one was scheduled
     AsyncCall::Pointer reader = fd_table[fd].halfClosedReader;
     if (reader != NULL)
-        comm_read_cancel(fd, reader);
+        Comm::ReadCancel(fd, reader);
     fd_table[fd].halfClosedReader = NULL;
 
     TheHalfClosed->del(fd);
@@ -1886,7 +1683,7 @@ commStopHalfClosedMonitor(int const fd)
 
 /// I/O handler for the possibly half-closed connection monitoring code
 static void
-commHalfClosedReader(const Comm::ConnectionPointer &conn, char *, size_t size, comm_err_t flag, int, void *)
+commHalfClosedReader(const Comm::ConnectionPointer &conn, char *, size_t size, Comm::Flag flag, int, void *)
 {
     // there cannot be more data coming in on half-closed connections
     assert(size == 0);
@@ -1896,11 +1693,11 @@ commHalfClosedReader(const Comm::ConnectionPointer &conn, char *, size_t size, c
     fd_table[conn->fd].halfClosedReader = NULL; // done reading, for now
 
     // nothing to do if fd is being closed
-    if (flag == COMM_ERR_CLOSING)
+    if (flag == Comm::ERR_CLOSING)
         return;
 
     // if read failed, close the connection
-    if (flag != COMM_OK) {
+    if (flag != Comm::OK) {
         debugs(5, 3, HERE << "closing " << conn);
         conn->close();
         return;
@@ -1913,7 +1710,7 @@ commHalfClosedReader(const Comm::ConnectionPointer &conn, char *, size_t size, c
 CommRead::CommRead() : conn(NULL), buf(NULL), len(0), callback(NULL) {}
 
 CommRead::CommRead(const Comm::ConnectionPointer &c, char *buf_, int len_, AsyncCall::Pointer &callback_)
-        : conn(c), buf(buf_), len(len_), callback(callback_) {}
+    : conn(c), buf(buf_), len(len_), callback(callback_) {}
 
 DeferredRead::DeferredRead () : theReader(NULL), theContext(NULL), theRead(), cancelled(false) {}
 
@@ -1971,7 +1768,7 @@ DeferredReadManager::popHead(CbDataListContainer<DeferredRead> &deferredReads)
     //       amount of time. We must re-validate that it is active and usable.
 
     // If the connection has been closed already. Cancel this read.
-    if (!Comm::IsConnOpen(read.theRead.conn)) {
+    if (!fd_table || !Comm::IsConnOpen(read.theRead.conn)) {
         if (read.closer != NULL) {
             read.closer->cancel("Connection closed before.");
             read.closer = NULL;
@@ -2057,17 +1854,17 @@ CommSelectEngine::checkEvents(int timeout)
 
     switch (Comm::DoSelect(timeout)) {
 
-    case COMM_OK:
+    case Comm::OK:
 
-    case COMM_TIMEOUT:
+    case Comm::TIMEOUT:
         return 0;
 
-    case COMM_IDLE:
+    case Comm::IDLE:
 
-    case COMM_SHUTDOWN:
+    case Comm::SHUTDOWN:
         return EVENT_IDLE;
 
-    case COMM_ERROR:
+    case Comm::COMM_ERROR:
         return EVENT_ERROR;
 
     default:
@@ -2105,15 +1902,16 @@ comm_open_uds(int sock_type,
     debugs(50, 3, HERE << "Attempt open socket for: " << addr->sun_path);
 
     if ((new_socket = socket(AI.ai_family, AI.ai_socktype, AI.ai_protocol)) < 0) {
+        int xerrno = errno;
         /* Increase the number of reserved fd's if calls to socket()
          * are failing because the open file table is full.  This
          * limits the number of simultaneous clients */
 
-        if (limitError(errno)) {
-            debugs(50, DBG_IMPORTANT, HERE << "socket failure: " << xstrerror());
+        if (limitError(xerrno)) {
+            debugs(50, DBG_IMPORTANT, MYNAME << "socket failure: " << xstrerr(xerrno));
             fdAdjustReserved();
         } else {
-            debugs(50, DBG_CRITICAL, HERE << "socket failure: " << xstrerror());
+            debugs(50, DBG_CRITICAL, MYNAME << "socket failure: " << xstrerr(xerrno));
         }
 
         PROF_stop(comm_open);
@@ -2126,7 +1924,7 @@ comm_open_uds(int sock_type,
     debugs(50, 5, HERE << "FD " << new_socket << " is a new socket");
 
     assert(!isOpen(new_socket));
-    fd_open(new_socket, FD_MSGHDR, NULL);
+    fd_open(new_socket, FD_MSGHDR, addr->sun_path);
 
     fdd_table[new_socket].close_file = NULL;
 
@@ -2141,7 +1939,7 @@ comm_open_uds(int sock_type,
         commSetReuseAddr(new_socket);
 
     if (flags & COMM_NONBLOCKING) {
-        if (commSetNonBlocking(new_socket) != COMM_OK) {
+        if (commSetNonBlocking(new_socket) != Comm::OK) {
             comm_close(new_socket);
             PROF_stop(comm_open);
             return -1;
@@ -2149,7 +1947,7 @@ comm_open_uds(int sock_type,
     }
 
     if (flags & COMM_DOBIND) {
-        if (commBind(new_socket, AI) != COMM_OK) {
+        if (commBind(new_socket, AI) != Comm::OK) {
             comm_close(new_socket);
             PROF_stop(comm_open);
             return -1;
@@ -2169,3 +1967,4 @@ comm_open_uds(int sock_type,
 
     return new_socket;
 }
+