Revision: 14854
Author: adrian.chadd
Date: Fri Jul 1 23:41:29 2011
Log: Begin fleshing out replacement comm connect routines.
These will be v6 aware and minus the commResetFD() stuff.
http://code.google.com/p/lusca-cache/source/detail?r=14854
Added:
/playpen/LUSCA_HEAD_ipv6/src/comm2.c
Modified:
/playpen/LUSCA_HEAD_ipv6/src/protos.h
=======================================
--- /dev/null
+++ /playpen/LUSCA_HEAD_ipv6/src/comm2.c Fri Jul 1 23:41:29 2011
@@ -0,0 +1,305 @@
+
+/*
+ * $Id: comm.c 14853 2011-07-02 06:10:25Z adrian.chadd $
+ *
+ * DEBUG: section 5 Socket Functions - Replacement
+ * AUTHOR: Harvest Derived
+ *
+ * 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.
+ *
+ */
+
+/* On native Windows, squid_mswin.h needs to know when we are compiling
+ * comm.c for the correct handling of FD<=>socket magic
+ */
+#define COMM_C
+
+#include "squid.h"
+
+#if defined(_SQUID_CYGWIN_)
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+
+typedef struct {
+ char *host;
+ u_short port;
+ CNCB *callback;
+ void *data;
+ sqaddr_t in_addr6;
+ int fd;
+ int tries;
+ int addrcount;
+ int connstart;
+} ConnectStateDataNew;
+
+static PF commConnectFree;
+static PF commConnectHandle;
+static IPH commConnectDnsHandle;
+static void commConnectCallback(ConnectStateDataNew * cs, int status);
+static int commResetFD(ConnectStateDataNew * cs);
+static int commRetryConnect(ConnectStateDataNew * cs);
+CBDATA_TYPE(ConnectStateDataNew);
+
+void
+commConnectStartNew(int fd, const char *host, u_short port, CNCB *
callback,
+ void *data, sqaddr_t *addr6)
+{
+ ConnectStateDataNew *cs;
+ debug(5, 3) ("commConnectStart: FD %d, %s:%d\n", fd, host, (int) port);
+ /*
+ * XXX this wasn't ever here (it was in comm_init()) so its possible
this may slow things
+ * XXX down a little; eventually this should migrate to a
squid-specific comm_init()
+ * XXX (comm_local_init() ? comm_connect_init()? so its called once
like the old init
+ * XXX function was. -adrian
+ */
+ CBDATA_INIT_TYPE(ConnectStateDataNew);
+ cs = cbdataAlloc(ConnectStateDataNew);
+ cs->fd = fd;
+ cs->host = xstrdup(host);
+ cs->port = port;
+ cs->callback = callback;
+ cs->data = data;
+ sqinet_init(&cs->in_addr6);
+ if (addr6 != NULL) {
+ sqinet_init(&cs->in_addr6);
+ sqinet_copy(&cs->in_addr6, addr6);
+ cs->addrcount = 1;
+ } else {
+ cs->addrcount = 0;
+ }
+ cbdataLock(cs->data);
+ comm_add_close_handler(fd, commConnectFree, cs);
+ ipcache_nbgethostbyname(host, commConnectDnsHandle, cs);
+}
+
+static void
+commConnectDnsHandle(const ipcache_addrs * ia, void *data)
+{
+ ConnectStateDataNew *cs = data;
+ if (ia == NULL) {
+ /* If we've been given a default IP, use it */
+ if (cs->addrcount > 0) {
+ fd_table[cs->fd].flags.dnsfailed = 1;
+ cs->connstart = squid_curtime;
+ commConnectHandle(cs->fd, cs);
+ } else {
+ debug(5, 3) ("commConnectDnsHandle: Unknown host: %s\n", cs->host);
+ if (!dns_error_message) {
+ dns_error_message = "Unknown DNS error";
+ debug(5, 1) ("commConnectDnsHandle: Bad dns_error_message\n");
+ }
+ assert(dns_error_message != NULL);
+ commConnectCallback(cs, COMM_ERR_DNS);
+ }
+ return;
+ }
+ assert(ia->cur < ia->count);
+ sqinet_done(&cs->in_addr6);
+ sqinet_init(&cs->in_addr6);
+ (void) ipcacheGetAddr(ia, ia->cur, &cs->in_addr6);
+ if (Config.onoff.balance_on_multiple_ip)
+ ipcacheCycleAddr(cs->host, NULL);
+ cs->addrcount = ia->count;
+ cs->connstart = squid_curtime;
+ commConnectHandle(cs->fd, cs);
+}
+
+static void
+commConnectCallback(ConnectStateDataNew * cs, int status)
+{
+ CNCB *callback = cs->callback;
+ void *data = cs->data;
+ int fd = cs->fd;
+ comm_remove_close_handler(fd, commConnectFree, cs);
+ cs->callback = NULL;
+ cs->data = NULL;
+ commSetTimeout(fd, -1, NULL, NULL);
+ commConnectFree(fd, cs);
+ if (cbdataValid(data))
+ callback(fd, status, data);
+ cbdataUnlock(data);
+}
+
+static void
+commConnectFree(int fd, void *data)
+{
+ ConnectStateDataNew *cs = data;
+ debug(5, 3) ("commConnectFree: FD %d\n", fd);
+ if (cs->data)
+ cbdataUnlock(cs->data);
+ safe_free(cs->host);
+ sqinet_done(&cs->in_addr6);
+ cbdataFree(cs);
+}
+
+/* Reset FD so that we can connect() again */
+static int
+commResetFD(ConnectStateDataNew * cs)
+{
+ int fd2;
+ fde *F;
+ if (!cbdataValid(cs->data))
+ return 0;
+ fd2 = socket(AF_INET, SOCK_STREAM, 0);
+ CommStats.syscalls.sock.sockets++;
+ if (fd2 < 0) {
+ debug(5, 0) ("commResetFD: socket: %s\n", xstrerror());
+ if (ENFILE == errno || EMFILE == errno)
+ fdAdjustReserved();
+ return 0;
+ }
+ /* We are about to close the fd (dup2 over it). Unregister from the
event loop */
+ commSetEvents(cs->fd, 0, 0);
+#ifdef _SQUID_MSWIN_
+ /* On Windows dup2() can't work correctly on Sockets, the */
+ /* workaround is to close the destination Socket before call them. */
+ close(cs->fd);
+#endif
+ if (dup2(fd2, cs->fd) < 0) {
+ debug(5, 0) ("commResetFD: dup2: %s\n", xstrerror());
+ if (ENFILE == errno || EMFILE == errno)
+ fdAdjustReserved();
+ close(fd2);
+ return 0;
+ }
+ close(fd2);
+ F = &fd_table[cs->fd];
+ fd_table[cs->fd].flags.called_connect = 0;
+
+ /*
+ * The original code assumed the current local port equals the
previous local port
+ * Assume this for now and bite whatever occasional failure will
happen because commResetFD()
+ * results in some re-attempt to use a now-allocated local port.
+ *
+ * This should later on be modified to re-use the -original- socket
address (with or without
+ * an explicitly set port) rather than F->local_address and
F->local_port, which may have been
+ * updated after the initial local bind() and subsequent getsockname().
+ */
+
+ /*
+ * yuck, this has assumptions about comm_open() arguments for
+ * the original socket
+ */
+ assert(F->local_port == sqinet_get_port(&F->local_address));
+ if (F->flags.tproxy_rem) {
+ debug(5, 3) ("commResetFD: FD %d: re-starting a tproxy'ed upstream
connection\n", cs->fd);
+ if (comm_ips_bind_rem(cs->fd, &F->local_address) != COMM_OK) {
+ debug(5, 1) ("commResetFD: FD %d: TPROXY comm_ips_bind_rem()
failed? Why?\n", cs->fd);
+ return 0;
+ }
+ } else if (commBind(cs->fd, &F->local_address) != COMM_OK) {
+ debug(5, 0) ("commResetFD: bind: %s\n", xstrerror());
+ return 0;
+ }
+#ifdef IP_TOS
+ if (F->tos) {
+ int tos = F->tos;
+ if (setsockopt(cs->fd, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(int)) <
0)
+ debug(5, 1) ("commResetFD: setsockopt(IP_TOS) on FD %d: %s\n",
cs->fd, xstrerror());
+ }
+#endif
+ if (F->flags.close_on_exec)
+ commSetCloseOnExec(cs->fd);
+ if (F->flags.nonblocking)
+ commSetNonBlocking(cs->fd);
+#ifdef TCP_NODELAY
+ if (F->flags.nodelay)
+ commSetTcpNoDelay(cs->fd);
+#endif
+
+ /* Register the new FD with the event loop */
+ commUpdateEvents(cs->fd);
+ if (Config.tcpRcvBufsz > 0)
+ commSetTcpRcvbuf(cs->fd, Config.tcpRcvBufsz);
+ return 1;
+}
+
+static int
+commRetryConnect(ConnectStateDataNew * cs)
+{
+ assert(cs->addrcount > 0);
+ if (cs->addrcount == 1) {
+ if (cs->tries >= Config.retry.maxtries)
+ return 0;
+ if (squid_curtime - cs->connstart > Config.Timeout.connect)
+ return 0;
+ } else {
+ if (cs->tries > cs->addrcount)
+ return 0;
+ }
+ return commResetFD(cs);
+}
+
+static void
+commReconnect(void *data)
+{
+ ConnectStateDataNew *cs = data;
+ ipcache_nbgethostbyname(cs->host, commConnectDnsHandle, cs);
+}
+
+/* Connect SOCK to specified DEST_PORT at DEST_HOST. */
+static void
+commConnectHandle(int fd, void *data)
+{
+ int r;
+ sqaddr_t a;
+
+ ConnectStateDataNew *cs = data;
+
+ /* Create a temporary sqaddr_t which also contains the port we're
connecting to */
+ /* This should eventually just be folded into cs->in_addr6 -adrian */
+ sqinet_init(&a);
+ sqinet_copy(&a, &cs->in_addr6);
+ sqinet_set_port(&a, cs->port, SQADDR_NONE);
+ r = comm_connect_addr(fd, &a);
+ sqinet_done(&a);
+ switch(r) {
+ case COMM_INPROGRESS:
+ debug(5, 5) ("commConnectHandle: FD %d: COMM_INPROGRESS\n", fd);
+ commSetSelect(fd, COMM_SELECT_WRITE, commConnectHandle, cs, 0);
+ break;
+ case COMM_OK:
+ ipcacheMarkGoodAddr(cs->host, &cs->in_addr6);
+ commConnectCallback(cs, COMM_OK);
+ break;
+ default:
+ cs->tries++;
+ ipcacheMarkBadAddr(cs->host, &cs->in_addr6);
+ if (Config.onoff.test_reachability)
+ netdbDeleteAddrNetwork(&cs->in_addr6);
+ if (commRetryConnect(cs)) {
+ eventAdd("commReconnect", commReconnect, cs, cs->addrcount == 1 ?
0.05 : 0.0, 0);
+ } else {
+ commConnectCallback(cs, COMM_ERR_CONNECT);
+ }
+ break;
+ }
+}
+
=======================================
--- /playpen/LUSCA_HEAD_ipv6/src/protos.h Fri Jul 1 23:10:25 2011
+++ /playpen/LUSCA_HEAD_ipv6/src/protos.h Fri Jul 1 23:41:29 2011
@@ -1061,6 +1061,9 @@
/* comm.c */
extern void commConnectStart(int fd, const char *, u_short, CNCB *, void *,
sqaddr_t *addr6);
+extern void
+commConnectStartNew(int fd, const char *host, u_short port, CNCB *
callback,
+ void *data, sqaddr_t *addr6);
/* client_side_location_rewrite.c */
extern void clientHttpLocationRewriteCheck(clientHttpRequest * http);
--
You received this message because you are subscribed to the Google Groups
"lusca-commit" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/lusca-commit?hl=en.