struct RefCountable_ {
RefCountable_():count_(0) {}
- virtual ~RefCountable_() {}
+ virtual ~RefCountable_() { assert(RefCountCount() == 0); }
/* Not private, to allow class hierarchies */
void RefCountReference() const {
CommCommonCbParams::print(os);
if (nfd >= 0)
os << ", newFD " << nfd;
+ os << ", " << details;
}
CommConnectCbParams::print(std::ostream &os) const
{
CommCommonCbParams::print(os);
+ if (conn != NULL)
+ os << ", from my " << conn->local << " to " << conn->remote;
+ else if (paths && paths->size() > 0) {
+ // TODO: for each path. print the to => from path being attempted.
+ }
}
/* CommIoCbParams */
void print(std::ostream &os) const;
public:
- Comm::Connection *details;
+ Comm::Connection::Pointer details;
int nfd; // TODO: rename to fdNew or somesuch
};
void print(std::ostream &os) const;
public:
- Comm::Connection *conn;
- Vector<Comm::Connection *> *paths;
+ Comm::Connection::Pointer conn;
+ Vector<Comm::Connection::Pointer> *paths;
};
// read/write (I/O) parameters
class HttpRequest;
class StoreEntry;
-typedef void PSC(Vector<Comm::Connection*> *, void *);
+typedef void PSC(Vector<Comm::Connection::Pointer> *, void *);
-SQUIDCEXTERN void peerSelect(Vector<Comm::Connection*> *, HttpRequest *, StoreEntry *, PSC *, void *data);
+SQUIDCEXTERN void peerSelect(Vector<Comm::Connection::Pointer> *, HttpRequest *, StoreEntry *, PSC *, void *data);
SQUIDCEXTERN void peerSelectInit(void);
/**
PSC *callback;
void *callback_data;
- Vector<Comm::Connection*> *paths; ///< the callers paths array. to be filled with our final results.
+ Vector<Comm::Connection::Pointer> *paths; ///< the callers paths array. to be filled with our final results.
FwdServer *servers; ///< temporary linked list of peers we will pass back.
/*
disableRetries(); // we only retry pconn failures
- Comm::Connection *conn = new Comm::Connection;
+ Comm::Connection::Pointer conn = new Comm::Connection;
// TODO: where do we get the DNS info for the ICAP server host ??
// Ip::Address will do a BLOCKING lookup if s.cfg().host is a hostname
/** Handle a new connection on HTTP socket. */
void
-httpAccept(int sock, int newfd, Comm::Connection *details,
+httpAccept(int sock, int newfd, Comm::Connection::Pointer details,
comm_err_t flag, int xerrno, void *data)
{
http_port_list *s = (http_port_list *)data;
/** Create SSL connection structure and update fd_table */
static SSL *
-httpsCreate(int newfd, Comm::Connection *details, SSL_CTX *sslContext)
+httpsCreate(int newfd, Comm::Connection::Pointer details, SSL_CTX *sslContext)
{
SSL *ssl = SSL_new(sslContext);
/** handle a new HTTPS connection */
static void
-httpsAccept(int sock, int newfd, Comm::Connection *details,
+httpsAccept(int sock, int newfd, Comm::Connection::Pointer details,
comm_err_t flag, int xerrno, void *data)
{
https_port_list *s = (https_port_list *)data;
return new_socket;
}
-#if 0
-// AYJ: this API is dead. alter the caller which is using this to do its own DNS lookups
-// and generate a Vector<Comm::Connection*> of possible destinations.
-// do the rest of this itself...
-void
-commConnectStart(int fd, const char *host, u_short port, AsyncCall::Pointer &cb)
-{
- debugs(cb->debugSection, cb->debugLevel, "commConnectStart: FD " << fd <<
- ", cb " << cb << ", " << host << ":" << port); // TODO: just print *cb
-
- ConnectStateData *cs;
- cs = new ConnectStateData;
- cs->fd = fd;
- cs->host = xstrdup(host);
- cs->default_port = port;
- cs->callback = cb;
-
- comm_add_close_handler(fd, ConnectStateData::Free, cs);
- ipcache_nbgethostbyname(host, commConnectDnsHandle, cs);
-}
-#endif
-
-#if 0
-// TODO: Remove this and similar callback registration functions by replacing
-// (callback,data) parameters with an AsyncCall so that we do not have to use
-// a generic call name and debug level when creating an AsyncCall. This will
-// also cut the number of callback registration routines in half.
-void
-commConnectStart(int fd, const char *host, u_short port, CNCB * callback, void *data)
-{
- debugs(5, 5, "commConnectStart: FD " << fd << ", data " << data << ", " << host << ":" << port);
- AsyncCall::Pointer call = commCbCall(5,3,
- "SomeCommConnectHandler", CommConnectCbPtrFun(callback, data));
- commConnectStart(fd, host, port, call);
-}
-#endif
-
static void
copyFDFlags(int to, fde *F)
{
* Close the socket fd in use by a connection.
*/
void
-_comm_close(Comm::Connection *conn, char const *file, int line)
+_comm_close(Comm::Connection::Pointer conn, char const *file, int line)
{
_comm_close(conn->fd, file, line);
conn->fd = -1;
#define COMMIO_FD_READCB(fd) (&commfd_table[(fd)].readcb)
#define COMMIO_FD_WRITECB(fd) (&commfd_table[(fd)].writecb)
-typedef void CNCB(Comm::Connection *conn, Vector<Comm::Connection*> *paths, comm_err_t status, int xerrno, void *data);
+typedef void CNCB(Comm::Connection::Pointer conn, Vector<Comm::Connection::Pointer> *paths, comm_err_t status, int xerrno, void *data);
typedef void IOCB(int fd, char *, size_t size, comm_err_t flag, int xerrno, void *data);
SQUIDCEXTERN void commSetCloseOnExec(int fd);
SQUIDCEXTERN void commSetTcpKeepalive(int fd, int idle, int interval, int timeout);
extern void _comm_close(int fd, char const *file, int line);
-extern void _comm_close(Comm::Connection *conn, char const *file, int line);
+extern void _comm_close(Comm::Connection::Pointer conn, char const *file, int line);
#define comm_close(x) (_comm_close((x), __FILE__, __LINE__))
SQUIDCEXTERN void comm_reset_close(int fd);
#if LINGERING_CLOSE
SQUIDCEXTERN void comm_quick_poll_required(void);
#include "comm/Connection.h"
-typedef void IOACB(int fd, int nfd, Comm::Connection *details, comm_err_t flag, int xerrno, void *data);
+typedef void IOACB(int fd, int nfd, Comm::Connection::Pointer details, comm_err_t flag, int xerrno, void *data);
extern void comm_add_close_handler(int fd, PF *, void *);
extern void comm_add_close_handler(int fd, AsyncCall::Pointer &);
extern void comm_remove_close_handler(int fd, PF *, void *);
#include "comm/ConnectStateData.h"
#include "comm.h"
#include "CommCalls.h"
+#include "fde.h"
#include "icmp/net_db.h"
#include "SquidTime.h"
CBDATA_CLASS_INIT(ConnectStateData);
-ConnectStateData::ConnectStateData(Vector<Comm::Connection*> *paths, AsyncCall::Pointer handler) :
+ConnectStateData::ConnectStateData(Vector<Comm::Connection::Pointer> *paths, AsyncCall::Pointer handler) :
host(NULL),
connect_timeout(Config.Timeout.connect),
paths(paths),
connstart(0)
{}
-ConnectStateData::ConnectStateData(Comm::Connection *c, AsyncCall::Pointer handler) :
+ConnectStateData::ConnectStateData(Comm::Connection::Pointer c, AsyncCall::Pointer handler) :
host(NULL),
connect_timeout(Config.Timeout.connect),
paths(paths),
void
ConnectStateData::connect()
{
- Comm::Connection *active;
+ Comm::Connection::Pointer active;
/* handle connecting to one single path */
/* mainly used by components other than forwarding */
/* handle connecting to one of multiple paths */
/* mainly used by forwarding */
- if (solo) {
+ if (solo != NULL) {
active = solo;
} else if (paths) {
- Vector<Comm::Connection*>::iterator i = paths->begin();
+ Vector<Comm::Connection::Pointer>::iterator i = paths->begin();
if (connstart == 0) {
connstart = squid_curtime;
case COMM_OK:
debugs(5, 5, HERE << "FD " << active->fd << ": COMM_OK - connected");
- /*
- * stats.conn_open is used to account for the number of
- * connections that we have open to the peer, so we can limit
- * based on the max-conn option. We need to increment here,
- * even if the connection may fail.
- */
+ /*
+ * stats.conn_open is used to account for the number of
+ * connections that we have open to the peer, so we can limit
+ * based on the max-conn option. We need to increment here,
+ * even if the connection may fail.
+ */
if (active->_peer)
active->_peer->stats.conn_open++;
+ /* TODO: remove this fd_table access. But old code still depends on fd_table flags to
+ * indicate the state of a raw fd object being passed around.
+ */
+ fd_table[active->fd].flags.open = 1;
+
ipcacheMarkGoodAddr(host, active->remote);
callCallback(COMM_OK, 0);
break;
{
public:
/** open first working of a set of connections */
- ConnectStateData(Vector<Comm::Connection *> *paths, AsyncCall::Pointer handler);
+ ConnectStateData(Vector<Comm::Connection::Pointer> *paths, AsyncCall::Pointer handler);
/** attempt to open one connection. */
- ConnectStateData(Comm::Connection *, AsyncCall::Pointer handler);
+ ConnectStateData(Comm::Connection::Pointer, AsyncCall::Pointer handler);
void *operator new(size_t);
void operator delete(void *);
time_t connect_timeout;
private:
- Vector<Comm::Connection *> *paths; ///< forwarding paths to be tried. front of the list is the current being opened.
- Comm::Connection *solo; ///< single connection currently being opened.
- AsyncCall::Pointer callback; ///< handler to be called on connection completion.
+ Vector<Comm::Connection::Pointer> *paths; ///< forwarding paths to be tried. front of the list is the current being opened.
+ Comm::Connection::Pointer solo; ///< single connection currently being opened.
+ AsyncCall::Pointer callback; ///< handler to be called on connection completion.
int total_tries; ///< total number of connection attempts over all destinations so far.
int fail_retries; ///< number of retries current destination has been tried.
/*
* DEBUG: section 5 Socket Functions
+ * AUTHOR: Amos Jeffries
* AUTHOR: Robert Collins
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
*
*
* Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
+ * Copyright (c) 2010, Amos Jeffries <amosjeffries@squid-cache.org>
*/
#ifndef _SQUIDCONNECTIONDETAIL_H_
#include "hier_code.h"
#include "ip/Address.h"
+#include "RefCount.h"
class peer;
#define COMM_TRANSPARENT 0x08
#define COMM_DOBIND 0x10
-class Connection
+class Connection : public RefCountable
{
public:
+ typedef RefCount<Comm::Connection> Pointer;
+
Connection();
Connection(Connection &c);
~Connection();
}
void
-Comm::ListenStateData::notify(int newfd, comm_err_t errcode, int xerrno, Comm::Connection *connDetails)
+Comm::ListenStateData::notify(int newfd, comm_err_t errcode, int xerrno, Comm::Connection::Pointer connDetails)
{
// listener socket handlers just abandon the port with COMM_ERR_CLOSING
// it should only happen when this object is deleted...
void subscribe(AsyncCall::Pointer &call);
void acceptNext();
- void notify(int newfd, comm_err_t, int xerrno, Comm::Connection *);
+ void notify(int newfd, comm_err_t, int xerrno, Comm::Connection::Pointer);
int fd;
}
static void
-idnsInitVCConnected(Comm::Connection *conn, Vector<Comm::Connection *> *unused, comm_err_t status, int xerrno, void *data)
+idnsInitVCConnected(Comm::Connection::Pointer conn, Vector<Comm::Connection::Pointer> *unused, comm_err_t status, int xerrno, void *data)
{
nsvc * vc = (nsvc *)data;
if (status != COMM_OK || !conn) {
char buf[MAX_IPSTRLEN];
debugs(78, DBG_IMPORTANT, "Failed to connect to nameserver " << nameservers[vc->ns].S.NtoA(buf,MAX_IPSTRLEN) << " using TCP!");
- delete conn;
+ conn = NULL;
return;
}
static void
idnsInitVC(int ns)
{
- char buf[MAX_IPSTRLEN];
-
nsvc *vc = cbdataAlloc(nsvc);
nameservers[ns].vc = vc;
vc->ns = ns;
vc->msg = new MemBuf;
vc->busy = 1;
- Comm::Connection *conn = new Comm::Connection;
+ Comm::Connection::Pointer conn = new Comm::Connection;
if (!Config.Addrs.udp_outgoing.IsNoAddr())
conn->local = Config.Addrs.udp_outgoing;
/**** CALLBACK WRAPPERS ************************************************************/
static void
-fwdStartCompleteWrapper(Vector<Comm::Connection*> *unused, void *data)
+fwdStartCompleteWrapper(Vector<Comm::Connection::Pointer> *unused, void *data)
{
FwdState *fwd = (FwdState *) data;
fwd->startComplete();
#endif
void
-fwdConnectDoneWrapper(Comm::Connection *conn, Vector<Comm::Connection*> *paths, comm_err_t status, int xerrno, void *data)
+fwdConnectDoneWrapper(Comm::Connection::Pointer conn, Vector<Comm::Connection::Pointer> *paths, comm_err_t status, int xerrno, void *data)
{
FwdState *fwd = (FwdState *) data;
fwd->connectDone(conn, paths, status, xerrno);
#endif
void
-FwdState::connectDone(Comm::Connection *conn, Vector<Comm::Connection*> *result_paths, comm_err_t status, int xerrno)
+FwdState::connectDone(Comm::Connection::Pointer conn, Vector<Comm::Connection::Pointer> *result_paths, comm_err_t status, int xerrno)
{
assert(result_paths == &paths);
if (n_tries == 0) // first attempt
request->hier.first_conn_start = current_time;
- Comm::Connection *conn = paths[0];
+ Comm::Connection::Pointer conn = paths[0];
/* connection timeout */
int ctimeout;
debugs(17,2,HERE << " Pinned connection " << pinned_connection << " not valid. Releasing.");
request->releasePinnedConnection();
paths.shift();
- delete conn;
+ conn = NULL;
connectStart();
return;
}
// TODO: now that we are dealing with actual IP->IP links. should we still anchor pconn on hostname?
// or on the remote IP+port?
// that could reduce the pconns per virtual server a fair amount
-// and prevent crossover between servers hosting the one domain
+// but would prevent crossover between servers hosting the one domain
+// this currently opens the possibility that conn will lie about where the FD goes.
const char *host;
int port;
cs->connect();
}
-#if DEAD
-void
-FwdState::startFail()
-{
- debugs(17, 3, HERE << entry->url() );
- ErrorState *anErr = errorCon(ERR_CANNOT_FORWARD, HTTP_SERVICE_UNAVAILABLE, request);
- anErr->xerrno = errno;
- fail(anErr);
- self = NULL; // refcounted
-}
-#endif
-
void
FwdState::dispatch()
{
* - address of the client for which we made the connection
*/
void
-FwdState::pconnPush(int fd, const peer *_peer, const HttpRequest *req, const char *domain, Ip::Address &client_addr)
+FwdState::pconnPush(Comm::Connection::Pointer conn, const peer *_peer, const HttpRequest *req, const char *domain, Ip::Address &client_addr)
{
if (_peer) {
- fwdPconnPool->push(fd, _peer->name, _peer->http_port, domain, client_addr);
+ fwdPconnPool->push(conn->fd, _peer->name, _peer->http_port, domain, client_addr);
} else {
/* small performance improvement, using NULL for domain instead of listing it twice */
/* although this will leave a gap open for url-rewritten domains to share a link */
- fwdPconnPool->push(fd, req->GetHost(), req->port, NULL, client_addr);
+ fwdPconnPool->push(conn->fd, req->GetHost(), req->port, NULL, client_addr);
}
+
+ /* XXX: remove this when Comm::Connection are stored in the pool
+ * this only prevents the persistent FD being closed when the
+ * Comm::Connection currently using it is destroyed.
+ */
+ conn->fd = -1;
}
void
/**** PRIVATE NON-MEMBER FUNCTIONS ********************************************/
-#if DEAD
-static Ip::Address
-aclMapAddr(acl_address * head, ACLChecklist * ch)
-{
- acl_address *l;
-
- Ip::Address addr;
-
- for (l = head; l; l = l->next) {
- if (!l->aclList || ch->matchAclListFast(l->aclList))
- return l->addr;
- }
-
- addr.SetAnyAddr();
- return addr;
-}
-#endif
-
/*
* DPW 2007-05-19
* Formerly static, but now used by client_side_request.cc
}
void
-getOutgoingAddress(HttpRequest * request, Comm::Connection *conn)
+getOutgoingAddress(HttpRequest * request, Comm::Connection::Pointer conn)
{
/* skip if an outgoing address is already set. */
if (!conn->local.IsAnyAddr()) return;
#include "comm.h"
#include "comm/Connection.h"
-//#include "hier_code.h"
#include "ip/Address.h"
#include "Array.h"
-#if 0 // replaced by vector of extended Comm::Connection objects (paths)
-class FwdServer
-{
-public:
- peer *_peer; /* NULL --> origin server */
- hier_code code;
- FwdServer *next;
-};
-
-typedef void PSC(FwdServer *, void *);
-
-#endif
-
class FwdState : public RefCountable
{
public:
static void fwdStart(int fd, StoreEntry *, HttpRequest *);
void startComplete();
-// void startFail();
void fail(ErrorState *err);
void unregister(int fd);
void complete();
bool reforwardableStatus(http_status s);
void serverClosed(int fd);
void connectStart();
- void connectDone(Comm::Connection *conn, Vector<Comm::Connection*> *paths, comm_err_t status, int xerrno);
+ void connectDone(Comm::Connection::Pointer conn, Vector<Comm::Connection::Pointer> *paths, comm_err_t status, int xerrno);
void connectTimeout(int fd);
void initiateSSL();
void negotiateSSL(int fd);
bool checkRetry();
bool checkRetriable();
void dispatch();
- void pconnPush(int fd, const peer *_peer, const HttpRequest *req, const char *domain, Ip::Address &client_addr);
+ void pconnPush(Comm::Connection::Pointer conn, const peer *_peer, const HttpRequest *req, const char *domain, Ip::Address &client_addr);
bool dontRetry() { return flags.dont_retry; }
void ftpPasvFailed(bool val) { flags.ftp_pasv_failed = val; }
- Comm::Connection *conn() const { return paths[0]; };
+ Comm::Connection::Pointer conn() const { return paths[0]; };
private:
// hidden for safer management of self; use static fwdStart
} flags;
/** possible paths which may be tried (in sequence stored) */
- Vector<Comm::Connection*> paths;
+ Vector<Comm::Connection::Pointer> paths;
// NP: keep this last. It plays with private/public
CBDATA_CLASS2(FwdState);
debugs(9, 3, HERE << "connecting to " << ftpState->data.host << ", port " << ftpState->data.port);
- Comm::Connection *conn = new Comm::Connection;
+ Comm::Connection::Pointer conn = new Comm::Connection;
conn->remote = fd_table[ftpState->ctrl.fd].ipaddr; // TODO: do we have a better info source than fd_table?
conn->remote.SetPort(port);
conn->fd = fd;
debugs(9, 3, HERE << "connecting to " << ftpState->data.host << ", port " << ftpState->data.port);
- Comm::Connection *conn = new Comm::Connection;
+ Comm::Connection::Pointer conn = new Comm::Connection;
conn->remote = ipaddr;
conn->remote.SetPort(port);
conn->fd = ftpState->data.fd;
}
void
-FtpStateData::ftpPasvCallback(Comm::Connection *conn, Vector<Comm::Connection*> *unused, comm_err_t status, int xerrno, void *data)
+FtpStateData::ftpPasvCallback(Comm::Connection::Pointer conn, Vector<Comm::Connection::Pointer> *unused, comm_err_t status, int xerrno, void *data)
{
FtpStateData *ftpState = (FtpStateData *)data;
debugs(9, 3, HERE);
orig_request->hier.peer_http_request_sent.tv_sec = 0;
orig_request->hier.peer_http_request_sent.tv_usec = 0;
- if (fwd->conn())
+ if (fwd->conn() != NULL)
_peer = fwd->conn()->_peer; /* might be NULL */
if (_peer) {
orig_request->pinnedConnection()->pinConnection(fd, orig_request, _peer,
(request->flags.connection_auth != 0));
} else {
- fwd->pconnPush(fd, _peer, request, orig_request->GetHost(), client_addr);
+ fwd->pconnPush(fwd->conn(), _peer, request, orig_request->GetHost(), client_addr);
}
fd = -1;
}
void
-Ident::ConnectDone(Comm::Connection *conn, Vector<Comm::Connection*> *unused, comm_err_t status, int xerrno, void *data)
+Ident::ConnectDone(Comm::Connection::Pointer conn, Vector<Comm::Connection::Pointer> *unused, comm_err_t status, int xerrno, void *data)
{
IdentStateData *state = (IdentStateData *)data;
* start a TCP connection to the peer host on port 113
*/
void
-Ident::Start(Comm::Connection *conn, IDCB * callback, void *data)
+Ident::Start(Comm::Connection::Pointer conn, IDCB * callback, void *data)
{
IdentStateData *state;
char key1[IDENT_KEY_SZ];
* Self-registers with a global ident lookup manager,
* will call Ident::Init() itself if the manager has not been initialized already.
*/
-void Start(Comm::Connection *conn, IDCB * callback, void *cbdata);
+void Start(Comm::Connection::Pointer conn, IDCB * callback, void *cbdata);
/**
\ingroup IdentAPI
return ret;/* don't probe to often */
/* for each IP address of this peer. find one that we can connect to and probe it. */
- Vector<Comm::Connection *> *paths = new Vector<Comm::Connection *>;
+ Vector<Comm::Connection::Pointer> *paths = new Vector<Comm::Connection::Pointer>;
for (int i = 0; i < p->n_addresses; i++) {
- Comm::Connection *conn = new Comm::Connection;
+ Comm::Connection::Pointer conn = new Comm::Connection;
conn->remote = p->addresses[i];
conn->remote.SetPort(p->http_port);
getOutgoingAddress(NULL, conn);
}
static void
-peerProbeConnectDone(Comm::Connection *conn, Vector<Comm::Connection*> *unused, comm_err_t status, int xerrno, void *data)
+peerProbeConnectDone(Comm::Connection::Pointer conn, Vector<Comm::Connection::Pointer> *unused, comm_err_t status, int xerrno, void *data)
{
peer *p = (peer*)data;
void
-peerSelect(Vector<Comm::Connection*> *paths,
+peerSelect(Vector<Comm::Connection::Pointer> *paths,
HttpRequest * request,
StoreEntry * entry,
PSC * callback,
assert(ia->cur < ia->count);
// loop over each result address, adding to the possible destinations.
- Comm::Connection *p;
+ Comm::Connection::Pointer p;
int ip = ia->cur;
for (int n = 0; n < ia->count; n++, ip++) {
if (ip >= ia->count) ip = 0; // looped back to zero.
SQUIDCEXTERN void peerDigestStatsReport(const PeerDigest * pd, StoreEntry * e);
#include "comm/Connection.h"
-extern void getOutgoingAddress(HttpRequest * request, Comm::Connection *conn);
+extern void getOutgoingAddress(HttpRequest * request, Comm::Connection::Pointer conn);
unsigned long getOutgoingTOS(HttpRequest * request);
SQUIDCEXTERN void urnStart(HttpRequest *, StoreEntry *);
char *host; /* either request->host or proxy host */
u_short port;
HttpRequest *request;
- Vector<Comm::Connection*> *paths;
+ Vector<Comm::Connection::Pointer> *paths;
class Connection
{
static void
-tunnelConnectDone(Comm::Connection *unused, Vector<Comm::Connection*> *paths, comm_err_t status, int xerrno, void *data)
+tunnelConnectDone(Comm::Connection::Pointer unused, Vector<Comm::Connection::Pointer> *paths, comm_err_t status, int xerrno, void *data)
{
TunnelStateData *tunnelState = (TunnelStateData *)data;
HttpRequest *request = tunnelState->request;
ErrorState *err = NULL;
- Comm::Connection *conn = (*paths)[0];
+ Comm::Connection::Pointer conn = (*paths)[0];
assert(tunnelState->paths == paths);
}
static void
-tunnelPeerSelectComplete(Vector<Comm::Connection*> *peer_paths, void *data)
+tunnelPeerSelectComplete(Vector<Comm::Connection::Pointer> *peer_paths, void *data)
{
TunnelStateData *tunnelState = (TunnelStateData *)data;
HttpRequest *request = tunnelState->request;