static void
private_fwdNegotiateSSL(int fd,void *data)
{
	SSL *ssl = fd_table[fd].ssl;
	int ret;

	server *s=(server *)data;

	//unsigned char key[22];
	errno = 0;
	ERR_clear_error();
	if ((ret = SSL_connect(ssl)) <= 0)
	{
		int ssl_error = SSL_get_error(ssl, ret);
		switch (ssl_error)
		{
			case SSL_ERROR_WANT_READ:
				commSetSelect(fd, COMM_SELECT_READ, private_fwdNegotiateSSL, s, 0);
				return;
			case SSL_ERROR_WANT_WRITE:
				commSetSelect(fd, COMM_SELECT_WRITE, private_fwdNegotiateSSL,s, 0);
				return;
			default:
				debug(153, 1) ("private_fwdNegotiateSSL: Error negotiating SSL connection on FD %d: %s (%d/%d/%d)\n", fd, ERR_error_string(ERR_get_error(), NULL), ssl_error, ret, errno);
			cbdataFree(s);
			comm_close(fd);
			return ;
		}
	}
	
	pconnPush(fd,s->ip_addr,s->port,NULL,NULL,0);
	commSetTimeout(fd,s->pconn_timeout,NULL,NULL);
	debug(153, 4) ("private_fwdNegotiateSSL: succeed negotiating SSL connection on FD:%d \n",fd);
	return;
}
void
icmpOpen(void)
{
#if USE_ICMP
    const char *args[2];
    int rfd;
    int wfd;
    args[0] = "(pinger)";
    args[1] = NULL;
    pid = ipcCreate(IPC_DGRAM,
	Config.Program.pinger,
	args,
	"Pinger Socket",
	&rfd,
	&wfd,
	&hIpc);
    if (pid < 0)
	return;
    assert(rfd == wfd);
    icmp_sock = rfd;
    fd_note(icmp_sock, "pinger");
    commSetSelect(icmp_sock, COMM_SELECT_READ, icmpRecv, NULL, 0);
    commSetTimeout(icmp_sock, -1, NULL, NULL);
    debug(37, 1) ("Pinger socket opened on FD %d\n", icmp_sock);
#endif
}
static void private_openAnIdleConn(char* server_ip,int server_port , struct in_addr outgoing , unsigned short tos, int ctimeout,FwdState *fwdState)
{

	int fd = comm_openex(SOCK_STREAM,IPPROTO_TCP,outgoing,0,COMM_NONBLOCKING,tos,server_ip);
	if (fd < 0)
	{
		debug(151, 4) ("private_openAnIdleConn: %s\n", xstrerror());
		return;
	}
//	debug(151,3)("mod_server_persist_connections-->private_openAnIdleConn: openIdleConn fd == %d,timeout:%d\n",fd,ctimeout);
	server *s = cbdataAlloc(server);
    s->ip_addr = xstrdup(server_ip);
	s->port = server_port;
	s->proto = fwdState->request->protocol; 
    s->pconn_timeout=ctimeout;

	commSetTimeout(fd,ctimeout,fwdConnectIdleTimeout,s);
/*	if(ctimeout>36000)
		commSetTcpKeepalive(fd, 3600, ctimeout/36000, ctimeout);
	else
		commSetTcpKeepalive(fd, 3600, 100, 360000);
*/
	commSetTcpKeepalive(fd, 1000, 10000, 360000);
	commConnectStart(fd, server_ip, server_port, private_openIdleConnDone, s);
}
Пример #4
0
static void
sslProxyConnected(int fd, void *data)
{
    SslStateData *sslState = data;
    MemBuf mb;
    HttpHeader hdr_out;
    Packer p;
    http_state_flags flags;
    debug(26, 3) ("sslProxyConnected: FD %d sslState=%p\n", fd, sslState);
    memset(&flags, '\0', sizeof(flags));
    memBufDefInit(&mb);
    memBufPrintf(&mb, "CONNECT %s HTTP/1.0\r\n", sslState->url);
    httpBuildRequestHeader(sslState->request,
	sslState->request,
	NULL,			/* StoreEntry */
	&hdr_out,
	sslState->client.fd,
	flags);			/* flags */
    packerToMemInit(&p, &mb);
    httpHeaderPackInto(&hdr_out, &p);
    httpHeaderClean(&hdr_out);
    packerClean(&p);
    memBufAppend(&mb, "\r\n", 2);
    xstrncpy(sslState->client.buf, mb.buf, SQUID_TCP_SO_RCVBUF);
    debug(26, 3) ("sslProxyConnected: Sending {%s}\n", sslState->client.buf);
    sslState->client.len = mb.size;
    memBufClean(&mb);
    commSetTimeout(sslState->server.fd,
	Config.Timeout.read,
	sslTimeout,
	sslState);
    sslSetSelect(sslState);
}
Пример #5
0
static void
identConnectDone(int fd, int status, void *data)
{
	IdentStateData *state = data;
	IdentClient *c;
	MemBuf mb;
	if (status != COMM_OK)
	{
		/* Failed to connect */
		comm_close(fd);
		return;
	}
	/*
	 * see if our clients still care
	 */
	for (c = state->clients; c; c = c->next)
	{
		if (cbdataValid(c->callback_data))
			break;
	}
	if (c == NULL)
	{
		/* no clients care */
		comm_close(fd);
		return;
	}
	memBufDefInit(&mb);
	memBufPrintf(&mb, "%d, %d\r\n",
				 ntohs(state->my_peer.sin_port),
				 ntohs(state->me.sin_port));
	comm_write_mbuf(fd, mb, NULL, state);
	commSetSelect(fd, COMM_SELECT_READ, identReadReply, state, 0);
	commSetTimeout(fd, Config.Timeout.ident, identTimeout, state);
}
Пример #6
0
void
icmpOpen(void)
{
#if USE_ICMP
    char *args[2];
    int x;
    int rfd;
    int wfd;
    args[0] = "(pinger)";
    args[1] = NULL;
    x = ipcCreate(IPC_UDP_SOCKET,
	Config.Program.pinger,
	args,
	"Pinger Socket",
	&rfd,
	&wfd);
    if (x < 0)
	return;
    assert(rfd == wfd);
    icmp_sock = rfd;
    commSetSelect(icmp_sock, COMM_SELECT_READ, icmpRecv, NULL, 0);
    commSetTimeout(icmp_sock, -1, NULL, NULL);
    debug(29, 1) ("Pinger socket opened on FD %d\n", icmp_sock);
#endif
}
Пример #7
0
/*
 * peerProbeConnect will be called on dead peers by neighborUp 
 */
static int
peerProbeConnect(peer * p)
{
    int fd;
    time_t ctimeout = p->connect_timeout > 0 ? p->connect_timeout
    : Config.Timeout.peer_connect;
    int ret = squid_curtime - p->stats.last_connect_failure > ctimeout * 10;
    if (p->test_fd != -1)
	return ret;		/* probe already running */
    if (squid_curtime - p->stats.last_connect_probe == 0)
	return ret;		/* don't probe to often */
    fd = comm_open(SOCK_STREAM, IPPROTO_TCP, getOutgoingAddr(NULL),
	0, COMM_NONBLOCKING, p->name);
    if (fd < 0)
	return ret;
    commSetTimeout(fd, ctimeout, peerProbeConnectTimeout, p);
    p->test_fd = fd;
    p->stats.last_connect_probe = squid_curtime;
    commConnectStart(p->test_fd,
	p->host,
	p->http_port,
	peerProbeConnectDone,
	p,
	NULL);
    return ret;
}
Пример #8
0
void
unlinkdInit(void)
{
#if USE_UNLINKD
    int x;
    char *args[2];
    struct timeval slp;
    args[0] = "(unlinkd)";
    args[1] = NULL;
#if HAVE_POLL && defined(_SQUID_OSF_)
    /* pipes and poll() don't get along on DUNIX -DW */
    x = ipcCreate(IPC_TCP_SOCKET,
#else
    x = ipcCreate(IPC_FIFO,
#endif
	Config.Program.unlinkd,
	args,
	"unlinkd",
	&unlinkd_rfd,
	&unlinkd_wfd);
    if (x < 0)
	fatal("Failed to create unlinkd subprocess");
    slp.tv_sec = 0;
    slp.tv_usec = 250000;
    select(0, NULL, NULL, NULL, &slp);
    fd_note(unlinkd_wfd, "squid -> unlinkd");
    fd_note(unlinkd_rfd, "unlinkd -> squid");
    commSetTimeout(unlinkd_rfd, -1, NULL, NULL);
    commSetTimeout(unlinkd_wfd, -1, NULL, NULL);
    /*
     * unlinkd_rfd should already be non-blocking because of
     * ipcCreate.  We change unlinkd_wfd to blocking mode because
     * we never want to lose an unlink request, and we don't have
     * code to retry if we get EWOULDBLOCK.  Unfortunately, we can
     * do this only for the IPC_FIFO case.
     */
    assert(fd_table[unlinkd_rfd].flags.nonblocking);
    if (FD_PIPE == fd_table[unlinkd_wfd].type)
	commUnsetNonBlocking(unlinkd_wfd);
    debug(12, 1) ("Unlinkd pipe opened on FD %d\n", unlinkd_wfd);
#else
    debug(12, 1) ("Unlinkd is disabled\n");
#endif
}
Пример #9
0
void
unlinkdInit(void)
{
    const char *args[2];
    struct timeval slp;
    args[0] = "(unlinkd)";
    args[1] = NULL;
#if (HAVE_POLL && defined(_SQUID_OSF_)) || defined(_SQUID_MSWIN_)
    /* pipes and poll() don't get along on DUNIX -DW */
    /* On Windows select() will fail on a pipe */
    pid = ipcCreate(IPC_STREAM,
#else
    /* We currently need to use FIFO.. see below */
    pid = ipcCreate(IPC_FIFO,
#endif
	Config.Program.unlinkd,
	args,
	"unlinkd",
	&unlinkd_rfd,
	&unlinkd_wfd,
	&hIpc);
    if (pid < 0)
	fatal("Failed to create unlinkd subprocess");
    slp.tv_sec = 0;
    slp.tv_usec = 250000;
    select(0, NULL, NULL, NULL, &slp);
    fd_note(unlinkd_wfd, "squid -> unlinkd");
    fd_note(unlinkd_rfd, "unlinkd -> squid");
    commSetTimeout(unlinkd_rfd, -1, NULL, NULL);
    commSetTimeout(unlinkd_wfd, -1, NULL, NULL);
    /*
     * unlinkd_rfd should already be non-blocking because of
     * ipcCreate.  We change unlinkd_wfd to blocking mode because
     * we never want to lose an unlink request, and we don't have
     * code to retry if we get EWOULDBLOCK.  Unfortunately, we can
     * do this only for the IPC_FIFO case.
     */
    assert(fd_table[unlinkd_rfd].flags.nonblocking);
    if (FD_PIPE == fd_table[unlinkd_wfd].type)
	commUnsetNonBlocking(unlinkd_wfd);
    debug(2, 1) ("Unlinkd pipe opened on FD %d\n", unlinkd_wfd);
}
Пример #10
0
static void set_upperlayer_persist_connection_timeout(FwdState *fwdState,int server_fd)
{

	persist_config *cfg = cc_get_mod_param(fwdState->client_fd,mod);
	fde *F=&fd_table[fwdState->server_fd];
	if(strstr(cfg->server_ips,F->ipaddr) && server_fd >0 )	
	{
		commSetTimeout(server_fd,cfg->time_out,NULL,NULL);
		debug(153, 4) ("set_upperlayer_persist_connection_timeout:update the upperlayer_timeout to %d\n",cfg->time_out);
	}
}
Пример #11
0
/*
 * copied from httpReadReply()
 *
 * by the time this is called, the ICAP headers have already
 * been read.
 */
void
icapReadReply(int fd, void *data)
{
    IcapStateData *icap = data;
    StoreEntry *entry = icap->respmod.entry;
    const request_t *request = icap->request;
    int len;
    debug(81, 5) ("icapReadReply: FD %d: icap %p.\n", fd, data);
    if (icap->flags.no_content && !icap->flags.http_server_eof) {	//AI

	return;
    }
    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
	comm_close(fd);
	return;
    }
    errno = 0;
    statCounter.syscalls.sock.reads++;
    len = memBufRead(fd, &icap->chunk_buf);
    debug(81, 5) ("icapReadReply: FD %d: len %d.\n", fd, len);
    if (len > 0) {
	fd_bytes(fd, len, FD_READ);
	kb_incr(&statCounter.icap.all.kbytes_in, len);
	commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap);
	if (icap->chunk_buf.size < icap->chunk_buf.capacity) {
	    *(icap->chunk_buf.buf + icap->chunk_buf.size) = '\0';
	    debug(81, 9) ("{%s}\n", icap->chunk_buf.buf);
	}
    }
    if (len <= 0) {
	debug(81, 2) ("icapReadReply: FD %d: read failure: %s.\n",
	    fd, xstrerror());
	if (ignoreErrno(errno)) {
	    debug(81, 2) ("icapReadReply: FD %d: ignored errno\n", fd);
	    commSetSelect(fd, COMM_SELECT_READ, icapReadReply, icap, 0);
	} else if (entry->mem_obj->inmem_hi == 0) {
	    ErrorState *err;
	    debug(81, 2) ("icapReadReply: FD %d: generating error page\n", fd);
	    err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
	    err->request = requestLink((request_t *) request);
	    err->xerrno = errno;
	    errorAppendEntry(entry, err);
	    comm_close(fd);
	} else {
	    debug(81, 2) ("icapReadReply: FD %d: just calling comm_close()\n",
		fd);
	    comm_close(fd);
	}
	return;
    }
    if (icapReadReply2(icap) < 0)
	comm_close(fd);
}
Пример #12
0
/*
 * start a TCP connection to the peer host on port 113
 */
void
identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer, IDCB * callback, void *data)
{
	IdentStateData *state;
	int fd;
	char key1[IDENT_KEY_SZ];
	char key2[IDENT_KEY_SZ];
	char key[IDENT_KEY_SZ];
	snprintf(key1, IDENT_KEY_SZ, "%s:%d",
			 inet_ntoa(me->sin_addr),
			 ntohs(me->sin_port));
	snprintf(key2, IDENT_KEY_SZ, "%s:%d",
			 inet_ntoa(my_peer->sin_addr),
			 ntohs(my_peer->sin_port));
	snprintf(key, IDENT_KEY_SZ, "%s,%s", key1, key2);
	if ((state = hash_lookup(ident_hash, key)) != NULL)
	{
		identClientAdd(state, callback, data);
		return;
	}
	fd = comm_open(SOCK_STREAM,
				   IPPROTO_TCP,
				   me->sin_addr,
				   0,
				   COMM_NONBLOCKING,
				   "ident");
	if (fd == COMM_ERROR)
	{
		/* Failed to get a local socket */
		callback(NULL, data);
		return;
	}
	CBDATA_INIT_TYPE(IdentStateData);
	state = cbdataAlloc(IdentStateData);
	state->hash.key = xstrdup(key);
	state->fd = fd;
	state->me = *me;
	state->my_peer = *my_peer;
	identClientAdd(state, callback, data);
	hash_join(ident_hash, &state->hash);
	comm_add_close_handler(fd,
						   identClose,
						   state);
	commSetTimeout(fd, Config.Timeout.ident, identTimeout, state);
	commConnectStart(fd,
					 inet_ntoa(state->my_peer.sin_addr),
					 IDENT_PORT,
					 identConnectDone,
					 state);
}
Пример #13
0
static void private_openIdleConnDone(int fd,int status, void* data)
{
	server* s = data;
	debug(151,3)("mod_server_persist_connections-->private_openIdleConnDone: ip_addr == %s \t port == %d, fd == %d\n",s->ip_addr, s->port,fd);
	if(fd>0)
	{
		if(s->proto == PROTO_HTTPS)
		{
			private_fwdInitiateSSL(fd,s); 
		}else{
			pconnPush(fd,s->ip_addr,s->port,NULL,NULL,0);
	        commSetTimeout(fd,s->pconn_timeout,NULL,NULL);
			cbdataFree(s); //Does fwdConnectIdleTimeOut will free!!!
		}
	}
}
Пример #14
0
/* This will be called when data is ready to be read from fd.  Read until
 * error or connection closed. */
static void
gopherReadReply(int fd, void *data)
{
    GopherStateData *gopherState = data;
    StoreEntry *entry = gopherState->entry;
    char *buf = NULL;
    int len;
    int clen;
    int bin;
    size_t read_sz;
#if DELAY_POOLS
    delay_id delay_id;
#endif
    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
	comm_close(fd);
	return;
    }
    errno = 0;
    buf = memAllocate(MEM_4K_BUF);
    read_sz = 4096 - 1;		/* leave room for termination */
#if DELAY_POOLS
    delay_id = delayMostBytesAllowed(entry->mem_obj, &read_sz);
#endif
    /* leave one space for \0 in gopherToHTML */
    statCounter.syscalls.sock.reads++;
    len = FD_READ_METHOD(fd, buf, read_sz);
    if (len > 0) {
	fd_bytes(fd, len, FD_READ);
#if DELAY_POOLS
	delayBytesIn(delay_id, len);
#endif
	kb_incr(&statCounter.server.all.kbytes_in, len);
	kb_incr(&statCounter.server.other.kbytes_in, len);
    }
    debug(10, 5) ("gopherReadReply: FD %d read len=%d\n", fd, len);
    if (len > 0) {
	commSetTimeout(fd, Config.Timeout.read, NULL, NULL);
	IOStats.Gopher.reads++;
	for (clen = len - 1, bin = 0; clen; bin++)
	    clen >>= 1;
	IOStats.Gopher.read_hist[bin]++;
    }
Пример #15
0
int
pconnPop(const char *host, u_short port, const char *domain, struct in_addr *client_address, u_short client_port, int *idle)
{
    struct _pconn *p;
    hash_link *hptr;
    int fd = -1;
    assert(table != NULL);
    hptr = pconnLookup(host, port, domain, client_address, client_port);
    if (hptr != NULL) {
	p = (struct _pconn *) hptr;
	assert(p->nfds > 0);
	fd = p->fds[p->nfds - 1];
	if (idle)
	    *idle = p->nfds - 1;
	pconnRemoveFD(p, fd);
	commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
	commSetTimeout(fd, -1, NULL, NULL);
    }
    return fd;
}
void
whoisStart(FwdState * fwd)
{
    WhoisState *p;
    int fd = fwd->server_fd;
    char *buf;
    size_t l;
    CBDATA_INIT_TYPE(WhoisState);
    p = cbdataAlloc(WhoisState);
    p->request = fwd->request;
    p->entry = fwd->entry;
    p->fwd = fwd;
    storeLockObject(p->entry);
    comm_add_close_handler(fd, whoisClose, p);
    l = strLen(p->request->urlpath) + 3;
    buf = xmalloc(l);
    snprintf(buf, l, "%s\r\n", strBuf(p->request->urlpath) + 1);
    comm_write(fd, buf, strlen(buf), NULL, p, xfree);
    commSetSelect(fd, COMM_SELECT_READ, whoisReadReply, p, 0);
    commSetTimeout(fd, Config.Timeout.read, whoisTimeout, p);
}
Пример #17
0
/* This will be called when data is ready to be read from fd.  Read until
 * error or connection closed. */
static void
waisReadReply(int fd, void *data)
{
    WaisStateData *waisState = data;
    LOCAL_ARRAY(char, buf, 4096);
    StoreEntry *entry = waisState->entry;
    int len;
    int clen;
    int bin;
    size_t read_sz;
#if DELAY_POOLS
    delay_id delay_id;
#endif
    if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
	comm_close(fd);
	return;
    }
    errno = 0;
    read_sz = 4096;
#if DELAY_POOLS
    delay_id = delayMostBytesAllowed(entry->mem_obj, &read_sz);
#endif
    statCounter.syscalls.sock.reads++;
    len = FD_READ_METHOD(fd, buf, read_sz);
    if (len > 0) {
	fd_bytes(fd, len, FD_READ);
#if DELAY_POOLS
	delayBytesIn(delay_id, len);
#endif
	kb_incr(&statCounter.server.all.kbytes_in, len);
	kb_incr(&statCounter.server.other.kbytes_in, len);
    }
    debug(24, 5) ("waisReadReply: FD %d read len:%d\n", fd, len);
    if (len > 0) {
	commSetTimeout(fd, Config.Timeout.read, NULL, NULL);
	IOStats.Wais.reads++;
	for (clen = len - 1, bin = 0; clen; bin++)
	    clen >>= 1;
	IOStats.Wais.read_hist[bin]++;
    }
Пример #18
0
/*
 * icapRespModKeepAliveOrClose
 *
 * Called when we are done reading from the ICAP server.
 * Either close the connection or keep it open for a future
 * transaction.
 */
static void
icapRespModKeepAliveOrClose(IcapStateData * icap)
{
    int fd = icap->icap_fd;
    if (fd < 0)
	return;
    if (!icap->flags.keep_alive) {
	debug(81, 3) ("%s:%d keep_alive not set, closing\n", __FILE__,
	    __LINE__);
	comm_close(fd);
	return;
    }
    debug(81, 3) ("%s:%d FD %d looks good, keeping alive\n", __FILE__, __LINE__,
	fd);
    commSetDefer(fd, NULL, NULL);
    commSetTimeout(fd, -1, NULL, NULL);
    commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
    comm_remove_close_handler(fd, icapStateFree, icap);
    pconnPush(fd, icap->current_service->hostname, icap->current_service->port);
    icap->icap_fd = -1;
    icapStateFree(-1, icap);
}
Пример #19
0
void
pconnPush(int fd, const char *host, u_short port, const char *domain, struct in_addr *client_address, u_short client_port)
{
    struct _pconn *p;
    int *old;
    LOCAL_ARRAY(char, desc, FD_DESC_SZ);
    LOCAL_ARRAY(char, key, PCONN_KEYLEN);
    if (fdUsageHigh()) {
	debug(48, 3) ("pconnPush: Not many unused FDs\n");
	comm_close(fd);
	return;
    } else if (shutting_down) {
	comm_close(fd);
	return;
    }
    assert(table != NULL);
    pconnKey(key, host, port, domain, client_address, client_port);
    p = (struct _pconn *) hash_lookup(table, key);
    if (p == NULL)
	p = pconnNew(key);
    if (p->nfds == p->nfds_alloc) {
	debug(48, 3) ("pconnPush: growing FD array\n");
	p->nfds_alloc <<= 1;
	old = p->fds;
	p->fds = xmalloc(p->nfds_alloc * sizeof(int));
	xmemcpy(p->fds, old, p->nfds * sizeof(int));
	if (p->nfds == PCONN_FDS_SZ)
	    memPoolFree(pconn_fds_pool, old);
	else
	    xfree(old);
    }
    p->fds[p->nfds++] = fd;
    commSetSelect(fd, COMM_SELECT_READ, pconnRead, p, 0);
    commSetTimeout(fd, Config.Timeout.pconn, pconnTimeout, p);
    snprintf(desc, FD_DESC_SZ, "%s idle connection", host);
    fd_note(fd, desc);
    debug(48, 3) ("pconnPush: pushed FD %d for %s\n", fd, key);
}
Пример #20
0
static void
sslConnectDone(int fdnotused, int status, void *data)
{
    SslStateData *sslState = data;
    request_t *request = sslState->request;
    ErrorState *err = NULL;
    if (status == COMM_ERR_DNS) {
	debug(26, 4) ("sslConnect: Unknown host: %s\n", sslState->host);
	err = errorCon(ERR_DNS_FAIL, HTTP_NOT_FOUND);
	err->request = requestLink(request);
	err->dnsserver_msg = xstrdup(dns_error_message);
	err->callback = sslErrorComplete;
	err->callback_data = sslState;
	errorSend(sslState->client.fd, err);
    } else if (status != COMM_OK) {
	err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE);
	err->xerrno = errno;
	err->host = xstrdup(sslState->host);
	err->port = sslState->port;
	err->request = requestLink(request);
	err->callback = sslErrorComplete;
	err->callback_data = sslState;
	errorSend(sslState->client.fd, err);
    } else {
	if (sslState->servers->peer)
	    sslProxyConnected(sslState->server.fd, sslState);
	else
	    sslConnected(sslState->server.fd, sslState);
	commSetTimeout(sslState->server.fd,
	    Config.Timeout.read,
	    sslTimeout,
	    sslState);
#if DELAY_POOLS
	commSetDefer(sslState->server.fd, sslDeferServerRead, sslState);
#endif
    }
}
Пример #21
0
void
icapSendRespMod(IcapStateData * icap, char *buf, int len, int theEnd)
{
    MemBuf mb;
#if ICAP_PREVIEW
    int size;
    const int preview_size = icap->preview_size;
#endif
    debug(81, 5) ("icapSendRespMod: FD %d, len %d, theEnd %d\n",
	icap->icap_fd, len, theEnd);

    if (icap->flags.no_content) {
	/*
	 * ICAP server said there are no modifications to make, so
	 * just append this data to the StoreEntry
	 */
	if (icap->respmod.resp_copy.size) {
	    /*
	     * first copy the data that we already sent to the ICAP server
	     */
	    memBufAppend(&icap->chunk_buf,
		icap->respmod.resp_copy.buf, icap->respmod.resp_copy.size);
	    icap->respmod.resp_copy.size = 0;
	}
	debug(81, 5) ("icapSendRepMod: len=%d theEnd=%d write_pending=%d\n",
	    len, theEnd, icap->flags.write_pending);
	if (len) {
	    /*
	     * also copy any new data from the HTTP side
	     */
	    memBufAppend(&icap->chunk_buf, buf, len);
	}
	(void) icapReadReply2(icap);
	return;
    }
    if (theEnd) {
	if (icap->respmod.res_body_sz)
	    icap->flags.send_zero_chunk = 1;
	icap->flags.http_server_eof = 1;
    }
    /*
     * httpReadReply is going to call us with a chunk and then
     * right away again with an EOF if httpPconnTransferDone() is true.
     * Since the first write is already dispatched, we'll have to 
     * hack this in somehow.
     */
    if (icap->flags.write_pending) {
	debug(81, 3) ("icapSendRespMod: oops, write_pending=1\n");
	assert(theEnd);
	assert(len == 0);
	return;
    }
    if (!cbdataValid(icap)) {
	debug(81, 3) ("icapSendRespMod: failed to establish connection?\n");
	return;
    }
    memBufDefInit(&mb);

#if SUPPORT_ICAP_204 || ICAP_PREVIEW
    /*
     * make a copy of the response in case ICAP server gives us a 204
     */
    /*
     * This piece of code is problematic for 204 responces outside preview.
     * The icap->respmod.resp_copy continues to filled until we had responce
     * If the icap server waits to gets all data before sends its responce 
     * then we are puting all downloading object to the main system memory.
     * My opinion is that 204 responces outside preview must be disabled .....
     * /chtsanti
     */

    if (len && icap->flags.copy_response) {
	 if (memBufIsNull(&icap->respmod.resp_copy))
	      memBufDefInit(&icap->respmod.resp_copy);
	 memBufAppend(&icap->respmod.resp_copy, buf, len);
    }

#endif

    if (icap->sc == 0) {
	/* No data sent yet. Start with headers */
	 if((icap->sc = buildRespModHeader(&mb, icap, buf, len, theEnd))>0){
	      buf += icap->sc;
	      len -= icap->sc;
	 }
	 /*
	  * Then we do not have http responce headers. All data (previous and those in buf)
	  * now are exist to icap->respmod.req_hdr_copy. Lets get them back.......
	  */
	 if(icap->sc <0){
	      memBufAppend(&icap->respmod.buffer,
			   icap->respmod.req_hdr_copy.buf,
			   icap->respmod.req_hdr_copy.size);
	      icap->sc=icap->respmod.req_hdr_copy.size;
	      icap->respmod.req_hdr_copy.size=0;
	      buf=NULL;
	      len=0;
	 }
    }
    if (0 == icap->sc) {
	/* check again; bail if we're not ready to send ICAP/HTTP hdrs */
	debug(81, 5) ("icapSendRespMod: dont have full HTTP response hdrs\n");
	memBufClean(&mb);
	return;
    }
#if ICAP_PREVIEW
    if (preview_size < 0 || !Config.icapcfg.preview_enable)	/* preview feature off */
	icap->flags.preview_done = 1;

    if (!icap->flags.preview_done) {
	/* preview not yet sent */
	if (icap->sc > 0 && icap->respmod.buffer.size <= preview_size
	    && len > 0) {
	    /* Try to collect at least preview_size+1 bytes */
	    /* By collecting one more byte than needed for preview we know best */
	    /* whether we have to send the ieof chunk extension */
	    size = icap->respmod.buffer.size + len;
	    if (size > preview_size + 1)
		size = preview_size + 1;
	    size -= icap->respmod.buffer.size;
	    debug(81,
		3)
		("icapSendRespMod: FD %d: copy %d more bytes to preview buffer.\n",
		icap->icap_fd, size);
	    memBufAppend(&icap->respmod.buffer, buf, size);
	    buf = ((char *) buf) + size;
	    len -= size;
	}
	if (icap->respmod.buffer.size > preview_size || theEnd) {
	    /* we got enough bytes for preview or this is the last call */
	    /* add preview preview now */
	    if (icap->respmod.buffer.size > 0) {
		size = icap->respmod.buffer.size;
		if (size > preview_size)
		    size = preview_size;
		memBufPrintf(&mb, "%x\r\n", size);
		memBufAppend(&mb, icap->respmod.buffer.buf, size);
		memBufAppend(&mb, crlf, 2);
		icap->sc += size;
	    }
	    if (icap->respmod.buffer.size <= preview_size) {
		/* content length is less than preview size+1 */
		if (icap->respmod.res_body_sz)
		    memBufAppend(&mb, "0; ieof\r\n\r\n", 11);
		memBufReset(&icap->respmod.buffer);	/* will now be used for other data */
	    } else {
		char ch;
		memBufAppend(&mb, "0\r\n\r\n", 5);
		/* end of preview, wait for continue or 204 signal */
		/* copy the extra byte and all other data to the icap buffer */
		/* so that it can be handled next time */
		ch = icap->respmod.buffer.buf[preview_size];
		memBufReset(&icap->respmod.buffer);	/* will now be used for other data */
		memBufAppend(&icap->respmod.buffer, &ch, 1);
		debug(81,
		    3)
		    ("icapSendRespMod: FD %d: sending preview and keeping %d bytes in internal buf.\n",
		    icap->icap_fd, len + 1);
		if (len > 0)
		    memBufAppend(&icap->respmod.buffer, buf, len);
	    }
	    icap->flags.preview_done = 1;
	    icap->flags.wait_for_preview_reply = 1;
	}
    } else if (icap->flags.wait_for_preview_reply) {
	/* received new data while waiting for preview response */
	/* add data to internal buffer and send later */
	debug(81,
	    3)
	    ("icapSendRespMod: FD %d: add %d more bytes to internal buf while waiting for preview-response.\n",
	    icap->icap_fd, len);
	if (len > 0)
	    memBufAppend(&icap->respmod.buffer, buf, len);
	/* do not send any data now while waiting for preview response */
	/* but prepare for read more data on the HTTP connection */
	memBufClean(&mb);
	return;
    } else
#endif
    {
	/* after preview completed and ICAP preview response received */
	/* there may still be some data in the buffer */
	if (icap->respmod.buffer.size > 0) {
	    memBufPrintf(&mb, "%x\r\n", icap->respmod.buffer.size);
	    memBufAppend(&mb, icap->respmod.buffer.buf,
		icap->respmod.buffer.size);
	    memBufAppend(&mb, crlf, 2);
	    icap->sc += icap->respmod.buffer.size;
	    memBufReset(&icap->respmod.buffer);
	}
	if (len > 0) {
	    memBufPrintf(&mb, "%x\r\n", len);
	    memBufAppend(&mb, buf, len);
	    memBufAppend(&mb, crlf, 2);
	    icap->sc += len;
	}
	if (icap->flags.send_zero_chunk) {
	    /* send zero end chunk */
	    icap->flags.send_zero_chunk = 0;
	    icap->flags.http_server_eof = 1;
	    memBufAppend(&mb, "0\r\n\r\n", 5);
	}
	/* wait for data coming from ICAP server as soon as we sent something */
	/* but of course only until we got the response header */
	if (!icap->flags.got_reply)
	    icap->flags.wait_for_reply = 1;
    }
    commSetTimeout(icap->icap_fd, -1, NULL, NULL);

    if (!mb.size) {
	memBufClean(&mb);
	return;
    }
    debug(81, 5) ("icapSendRespMod: FD %d writing {%s}\n", icap->icap_fd,
	mb.buf);
    icap->flags.write_pending = 1;
    comm_write_mbuf(icap->icap_fd, mb, icapSendRespModDone, icap);
}
Пример #22
0
static void
icapSendRespModDone(int fd, char *bufnotused, size_t size, int errflag,
    void *data)
{
    IcapStateData *icap = data;
    ErrorState *err;

    icap->flags.write_pending = 0;
    debug(81, 5) ("icapSendRespModDone: FD %d: size %d: errflag %d.\n",
	fd, size, errflag);
    if (size > 0) {
	fd_bytes(fd, size, FD_WRITE);
	kb_incr(&statCounter.icap.all.kbytes_out, size);
    }
    if (errflag == COMM_ERR_CLOSING)
	return;
    if (errflag) {
	err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
	err->xerrno = errno;
	if (cbdataValid(icap))
	    err->request = requestLink(icap->request);
	storeEntryReset(icap->respmod.entry);
	errorAppendEntry(icap->respmod.entry, err);
	comm_close(fd);
	return;
    }
    if (EBIT_TEST(icap->respmod.entry->flags, ENTRY_ABORTED)) {
        debug(81, 3) ("icapSendRespModDone: Entry Aborded\n");	
	comm_close(fd);
	return;
    }
    if (icap->flags.send_zero_chunk) {
	debug(81,
	    3) ("icapSendRespModDone: I'm supposed to send zero chunk now\n");
	icap->flags.send_zero_chunk = 0;
	icapSendRespMod(icap, NULL, 0, 1);
	return;
    }
    if (icap->flags.wait_for_preview_reply || icap->flags.wait_for_reply) {
	/* Schedule reading the ICAP response */
	debug(81,
	    3)
	    ("icapSendRespModDone: FD %d: commSetSelect on read icapRespModReadReply.\n",
	    fd);
	commSetSelect(fd, COMM_SELECT_READ, icapRespModReadReply, icap, 0);
#if 1
	commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap);
#else
	if (icap->flags.wait_for_preview_reply || icap->flags.http_server_eof) {
	    /*
	     * Set the read timeout only after all data has been sent
	     * or we are waiting for a preview response
	     * If the ICAP server does not return any data till all data
	     * has been sent, we are likely to hit the timeout for large
	     * HTTP bodies
	     */
	    commSetTimeout(fd, Config.Timeout.read, icapReadTimeout, icap);
	}
#endif
    }
}
Пример #23
0
int
ipcCreate(int type, const char *prog, char *const args[], const char *name, int *rfd, int *wfd)
{
    pid_t pid;
    struct sockaddr_in CS;
    struct sockaddr_in PS;
    int crfd = -1;
    int prfd = -1;
    int cwfd = -1;
    int pwfd = -1;
    int fd;
    int t1, t2, t3;
    socklen_t len;
    int tmp_s;
#if HAVE_PUTENV
    char *env_str;
#endif
    int x;

#if HAVE_POLL && defined(_SQUID_OSF_)
    assert(type != IPC_FIFO);
#endif

    if (rfd)
	*rfd = -1;
    if (wfd)
	*wfd = -1;
    if (type == IPC_TCP_SOCKET) {
	crfd = cwfd = comm_open(SOCK_STREAM,
	    0,
	    local_addr,
	    0,
	    COMM_NOCLOEXEC,
	    name);
	prfd = pwfd = comm_open(SOCK_STREAM,
	    0,			/* protocol */
	    local_addr,
	    0,			/* port */
	    0,			/* blocking */
	    name);
    } else if (type == IPC_UDP_SOCKET) {
	crfd = cwfd = comm_open(SOCK_DGRAM,
	    0,
	    local_addr,
	    0,
	    COMM_NOCLOEXEC,
	    name);
	prfd = pwfd = comm_open(SOCK_DGRAM,
	    0,
	    local_addr,
	    0,
	    0,
	    name);
    } else if (type == IPC_FIFO) {
	int p2c[2];
	int c2p[2];
	if (pipe(p2c) < 0) {
	    debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror());
	    return -1;
	}
	if (pipe(c2p) < 0) {
	    debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror());
	    return -1;
	}
	fd_open(prfd = p2c[0], FD_PIPE, "IPC FIFO Parent Read");
	fd_open(cwfd = p2c[1], FD_PIPE, "IPC FIFO Child Write");
	fd_open(crfd = c2p[0], FD_PIPE, "IPC FIFO Child Read");
	fd_open(pwfd = c2p[1], FD_PIPE, "IPC FIFO Parent Write");
    } else {
	assert(IPC_NONE);
    }
    debug(54, 3) ("ipcCreate: prfd FD %d\n", prfd);
    debug(54, 3) ("ipcCreate: pwfd FD %d\n", pwfd);
    debug(54, 3) ("ipcCreate: crfd FD %d\n", crfd);
    debug(54, 3) ("ipcCreate: cwfd FD %d\n", cwfd);

    if (crfd < 0) {
	debug(54, 0) ("ipcCreate: Failed to create child FD.\n");
	return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    }
    if (pwfd < 0) {
	debug(54, 0) ("ipcCreate: Failed to create server FD.\n");
	return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    }
    if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) {
	len = sizeof(PS);
	memset(&PS, '\0', len);
	if (getsockname(pwfd, (struct sockaddr *) &PS, &len) < 0) {
	    debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
	}
	debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
	    pwfd, inet_ntoa(PS.sin_addr), ntohs(PS.sin_port));
	len = sizeof(CS);
	memset(&CS, '\0', len);
	if (getsockname(crfd, (struct sockaddr *) &CS, &len) < 0) {
	    debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
	}
	debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
	    crfd, inet_ntoa(CS.sin_addr), ntohs(CS.sin_port));
    }
    if (type == IPC_TCP_SOCKET) {
	if (listen(crfd, 1) < 0) {
	    debug(50, 1) ("ipcCreate: listen FD %d: %s\n", crfd, xstrerror());
	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
	}
	debug(54, 3) ("ipcCreate: FD %d listening...\n", crfd);
    }
    /* flush or else we get dup data if unbuffered_logs is set */
    logsFlush();
    if ((pid = fork()) < 0) {
	debug(50, 1) ("ipcCreate: fork: %s\n", xstrerror());
	return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    }
    if (pid > 0) {		/* parent */
	/* close shared socket with child */
	comm_close(crfd);
	if (cwfd != crfd)
	    comm_close(cwfd);
	cwfd = crfd = -1;
	if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) {
	    if (comm_connect_addr(pwfd, &CS) == COMM_ERROR)
		return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
	}
	memset(hello_buf, '\0', HELLO_BUF_SZ);
	if (type == IPC_UDP_SOCKET)
	    x = recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0);
	else
	    x = read(prfd, hello_buf, HELLO_BUF_SZ - 1);
	if (x < 0) {
	    debug(50, 0) ("ipcCreate: PARENT: hello read test failed\n");
	    debug(50, 0) ("--> read: %s\n", xstrerror());
	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
	} else if (strcmp(hello_buf, hello_string)) {
	    debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n");
	    debug(54, 0) ("--> read returned %d\n", x);
	    debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf));
	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
	}
	commSetTimeout(prfd, -1, NULL, NULL);
	commSetNonBlocking(prfd);
	commSetNonBlocking(pwfd);
	if (rfd)
	    *rfd = prfd;
	if (wfd)
	    *wfd = pwfd;
	fd_table[prfd].flags.ipc = 1;
	fd_table[pwfd].flags.ipc = 1;
	return pwfd;
    }
    /* child */
    no_suid();			/* give up extra priviliges */
    /* close shared socket with parent */
    close(prfd);
    if (pwfd != prfd)
	close(pwfd);
    pwfd = prfd = -1;

    if (type == IPC_TCP_SOCKET) {
	debug(54, 3) ("ipcCreate: calling accept on FD %d\n", crfd);
	if ((fd = accept(crfd, NULL, NULL)) < 0) {
	    debug(50, 0) ("ipcCreate: FD %d accept: %s\n", crfd, xstrerror());
	    _exit(1);
	}
	debug(54, 3) ("ipcCreate: CHILD accepted new FD %d\n", fd);
	close(crfd);
	cwfd = crfd = fd;
    } else if (type == IPC_UDP_SOCKET) {
	if (comm_connect_addr(crfd, &PS) == COMM_ERROR)
	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    }
    if (type == IPC_UDP_SOCKET) {
	x = send(cwfd, hello_string, strlen(hello_string), 0);
	if (x < 0) {
	    debug(50, 0) ("sendto FD %d: %s\n", cwfd, xstrerror());
	    debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n");
	    _exit(1);
	}
    } else {
	if (write(cwfd, hello_string, strlen(hello_string)) < 0) {
	    debug(50, 0) ("write FD %d: %s\n", cwfd, xstrerror());
	    debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n");
	    _exit(1);
	}
    }
#if HAVE_PUTENV
    env_str = xcalloc((tmp_s = strlen(Config.debugOptions) + 32), 1);
    snprintf(env_str, tmp_s, "SQUID_DEBUG=%s", Config.debugOptions);
    putenv(env_str);
#endif
    /*
     * This double-dup stuff avoids problems when one of 
     *  crfd, cwfd, or debug_log are in the rage 0-2.
     */
    do {
	x = open(_PATH_DEVNULL, 0, 0444);
	if (x > -1)
	    commSetCloseOnExec(x);
    } while (x < 3);
    t1 = dup(crfd);
    t2 = dup(cwfd);
    t3 = dup(fileno(debug_log));
    assert(t1 > 2 && t2 > 2 && t3 > 2);
    close(crfd);
    close(cwfd);
    close(fileno(debug_log));
    dup2(t1, 0);
    dup2(t2, 1);
    dup2(t3, 2);
    close(t1);
    close(t2);
    close(t3);
#if HAVE_SETSID
    setsid();
#endif
    execvp(prog, args);
    debug(50, 0) ("ipcCreate: %s: %s\n", prog, xstrerror());
    _exit(1);
    return 0;
}
Пример #24
0
static void clientRecvFd(int sock, void *data)
{
	int retval;     
	struct msghdr msg;
	struct iovec vec;       
	char cmsgbuf[CMSG_SPACE(sizeof(int))];
	struct cmsghdr *p_cmsg;
	char iov_buf[CACHE_WATCH_RECV_MSG_LENGTH];

	vec.iov_base = iov_buf;
	vec.iov_len = CACHE_WATCH_RECV_MSG_LENGTH;
	msg.msg_name = NULL;    
	msg.msg_namelen = 0;
	msg.msg_iov = &vec; 
	msg.msg_iovlen = 1;
	msg.msg_control = cmsgbuf;
	msg.msg_controllen = sizeof(cmsgbuf);   
	msg.msg_flags = 0;      /* In case something goes wrong, set the fd to -1 before the syscall */
	retval = recvmsg(sock, &msg, 0);

	if( retval <= 0 )
	{       
		comm_close(sock);
		return; 
	}       

	if( (p_cmsg = CMSG_FIRSTHDR(&msg)) == NULL )
	{       
		comm_close(sock);
		return; 
	}       

    if (squidWatchReply(sock, &msg, iov_buf) != -1)
    {
        comm_close(sock);
        return;
    }

	int fd = *((int*)CMSG_DATA(p_cmsg));
	// for keep alive
	commSetSelect(sock, COMM_SELECT_READ, clientRecvFd, NULL, 0);
	// omm_close(sock);
	if(fd < 0)
	{
		return;
	}
	//comm_accept's jobs
	struct sockaddr_in peername;
	struct sockaddr_in sockname;
	socklen_t socklen;
	socklen = sizeof(struct sockaddr_in);
	memset(&peername, '\0', socklen);
	memset(&sockname, '\0', socklen);
	getpeername(fd, (struct sockaddr *)&peername, &socklen);
	getsockname(fd, (struct sockaddr *)&sockname, &socklen);
	commSetCloseOnExec(fd);
	fd_open(fd, FD_SOCKET, "HTTP Request");
	fde *F = &fd_table[fd];
	xstrncpy(F->ipaddr, xinet_ntoa(peername.sin_addr), 16);
	F->remote_port = htons(peername.sin_port);
	F->local_port = htons(sockname.sin_port);
	commSetNonBlocking(fd);
	//rest of httpAccept's jobs
    //
    //int on = 1;
    //if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on)) < 0)
    //    debug(191, 0) ("commSetTcpNoDelay: FD %d: %s\n", fd, xstrerror());
    //fd_table[fd].flags.nodelay = 1;
#ifdef TCP_NODELAY
	commSetTcpNoDelay(fd); /*Fix tcp use Negale bug while send packet*/
#endif

#ifdef CC_FRAMEWORK
	cc_call_hook_func_private_http_accept(fd);
#endif

	debug(191, 4) ("clientRecvFd: FD %d: accepted port %d client %s:%d\n", fd, F->local_port, F->ipaddr, F->remote_port);
	fd_note_static(fd, "client http connect");
	ConnStateData * connState = cbdataAlloc(ConnStateData);
	assert(Config.Sockaddr.http);
	connState->port = Config.Sockaddr.http;
	cbdataLock(connState->port);
	connState->peer = peername; 
	connState->log_addr = peername.sin_addr;
	connState->log_addr.s_addr &= Config.Addrs.client_netmask.s_addr;
	connState->me = sockname;
	connState->fd = fd;
	connState->pinning.fd = -1;
	connState->in.buf = memAllocBuf(CLIENT_REQ_BUF_SZ, &connState->in.size);
	comm_add_close_handler(fd, connStateFree, connState);
	if (Config.onoff.log_fqdn)
		fqdncache_gethostbyaddr(peername.sin_addr, FQDN_LOOKUP_IF_MISS);
	commSetTimeout(fd, Config.Timeout.request, requestTimeout, connState);
#if USE_IDENT
	static aclCheck_t identChecklist;
	identChecklist.src_addr = peername.sin_addr;
	identChecklist.my_addr = sockname.sin_addr;
	identChecklist.my_port = ntohs(sockname.sin_port);
	if (aclCheckFast(Config.accessList.identLookup, &identChecklist))
		identStart(&sockname, &peername, clientIdentDone, connState);
#endif
	commSetSelect(fd, COMM_SELECT_READ, clientReadRequest, connState, 0);
	commSetDefer(fd, clientReadDefer, connState);
	if (connState->port->tcp_keepalive.enabled)
	{       
		commSetTcpKeepalive(fd, connState->port->tcp_keepalive.idle, connState->port->tcp_keepalive.interval, connState->port->tcp_keepalive.timeout);
	}       

	clientdbEstablished(peername.sin_addr, 1);
	incoming_sockets_accepted++;
}
Пример #25
0
pid_t
ipcCreate(int type, const char *prog, const char *const args[], const char *name, int *rfd, int *wfd, void **hIpc)
{
    unsigned long thread;
    struct ipc_params params;
    int opt;
    int optlen = sizeof(opt);
    DWORD ecode = 0;
    pid_t pid;
    struct sockaddr_in CS;
    struct sockaddr_in PS;
    int crfd = -1;
    int prfd = -1;
    int cwfd = -1;
    int pwfd = -1;
    socklen_t len;
    int x;

    requirePathnameExists(name, prog);

    if (rfd)
	*rfd = -1;
    if (wfd)
	*wfd = -1;
    if (hIpc)
	*hIpc = NULL;

    if (WIN32_OS_version != _WIN_OS_WINNT) {
	getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, &optlen);
	opt = opt & ~(SO_SYNCHRONOUS_NONALERT | SO_SYNCHRONOUS_ALERT);
	setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, sizeof(opt));
    }
    if (type == IPC_TCP_SOCKET) {
	crfd = cwfd = comm_open(SOCK_STREAM,
	    IPPROTO_TCP,
	    local_addr,
	    0,
	    COMM_NOCLOEXEC,
	    name);
	prfd = pwfd = comm_open(SOCK_STREAM,
	    IPPROTO_TCP,	/* protocol */
	    local_addr,
	    0,			/* port */
	    0,			/* blocking */
	    name);
    } else if (type == IPC_UDP_SOCKET) {
	crfd = cwfd = comm_open(SOCK_DGRAM,
	    IPPROTO_UDP,
	    local_addr,
	    0,
	    COMM_NOCLOEXEC,
	    name);
	prfd = pwfd = comm_open(SOCK_DGRAM,
	    IPPROTO_UDP,
	    local_addr,
	    0,
	    0,
	    name);
    } else if (type == IPC_FIFO) {
	debug(54, 0)
	    ("ipcCreate: %s: use IPC_TCP_SOCKET instead of IP_FIFO on Windows\n",
	    prog);
	assert(0);
    } else {
	assert(IPC_NONE);
    }
    debug(54, 3) ("ipcCreate: prfd FD %d\n", prfd);
    debug(54, 3) ("ipcCreate: pwfd FD %d\n", pwfd);
    debug(54, 3) ("ipcCreate: crfd FD %d\n", crfd);
    debug(54, 3) ("ipcCreate: cwfd FD %d\n", cwfd);

    if (WIN32_OS_version != _WIN_OS_WINNT) {
	getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, &optlen);
	opt = opt | SO_SYNCHRONOUS_NONALERT;
	setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, optlen);
    }
    if (crfd < 0) {
	debug(54, 0) ("ipcCreate: Failed to create child FD.\n");
	return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    }
    if (pwfd < 0) {
	debug(54, 0) ("ipcCreate: Failed to create server FD.\n");
	return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    }
    if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) {
	len = sizeof(PS);
	memset(&PS, '\0', len);
	if (getsockname(pwfd, (struct sockaddr *) &PS, &len) < 0) {
	    debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
	}
	debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
	    pwfd, inet_ntoa(PS.sin_addr), ntohs(PS.sin_port));
	len = sizeof(CS);
	memset(&CS, '\0', len);
	if (getsockname(crfd, (struct sockaddr *) &CS, &len) < 0) {
	    debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror());
	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
	}
	debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n",
	    crfd, inet_ntoa(CS.sin_addr), ntohs(CS.sin_port));
    }
    if (type == IPC_TCP_SOCKET) {
	if (listen(crfd, 1) < 0) {
	    debug(54, 1) ("ipcCreate: listen FD %d: %s\n", crfd, xstrerror());
	    return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
	}
	debug(54, 3) ("ipcCreate: FD %d listening...\n", crfd);
    }
    /* flush or else we get dup data if unbuffered_logs is set */
    logsFlush();
    params.type = type;
    params.crfd = crfd;
    params.cwfd = cwfd;
    params.PS = PS;
    params.prog = prog;
    params.args = (char **) args;

    thread = _beginthreadex(NULL, 0, ipc_thread_1, &params, 0, NULL);

    if (thread == 0) {
	debug(54, 1) ("ipcCreate: _beginthread: %s\n", xstrerror());
	return ipcCloseAllFD(prfd, pwfd, crfd, cwfd);
    }
    if (comm_connect_addr(pwfd, &CS) == COMM_ERROR) {
	CloseHandle((HANDLE) thread);
	return ipcCloseAllFD(prfd, pwfd, -1, -1);
    }
    memset(hello_buf, '\0', HELLO_BUF_SZ);
    x = recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0);

    if (x < 0) {
	debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n");
	debug(54, 0) ("--> read: %s\n", xstrerror());
	CloseHandle((HANDLE) thread);
	return ipcCloseAllFD(prfd, pwfd, -1, -1);
    } else if (strcmp(hello_buf, hello_string)) {
	debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n");
	debug(54, 0) ("--> read returned %d\n", x);
	debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf));
	CloseHandle((HANDLE) thread);
	return ipcCloseAllFD(prfd, pwfd, -1, -1);
    }
    x = send(pwfd, ok_string, strlen(ok_string), 0);

    if (x < 0) {
	debug(54, 0) ("ipcCreate: PARENT: OK write test failed\n");
	debug(54, 0) ("--> read: %s\n", xstrerror());
	CloseHandle((HANDLE) thread);
	return ipcCloseAllFD(prfd, pwfd, -1, -1);
    }
    memset(hello_buf, '\0', HELLO_BUF_SZ);
    x = recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0);

    if (x < 0) {
	debug(54, 0) ("ipcCreate: PARENT: OK read test failed\n");
	debug(54, 0) ("--> read: %s\n", xstrerror());
	CloseHandle((HANDLE) thread);
	return ipcCloseAllFD(prfd, pwfd, -1, -1);
    } else if (!strcmp(hello_buf, err_string)) {
	debug(54, 0) ("ipcCreate: PARENT: OK read test failed\n");
	debug(54, 0) ("--> read returned %d\n", x);
	debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf));
	CloseHandle((HANDLE) thread);
	return ipcCloseAllFD(prfd, pwfd, -1, -1);
    }
    hello_buf[x] = '\0';
    pid = atol(hello_buf);
    commSetTimeout(prfd, -1, NULL, NULL);
    commSetNonBlocking(prfd);
    commSetNonBlocking(pwfd);
    commSetCloseOnExec(prfd);
    commSetCloseOnExec(pwfd);

    if (rfd)
	*rfd = prfd;
    if (wfd)
	*wfd = pwfd;

    fd_table[prfd].flags.ipc = 1;
    fd_table[pwfd].flags.ipc = 1;
    fd_table[crfd].flags.ipc = 1;
    fd_table[cwfd].flags.ipc = 1;

    if (Config.sleep_after_fork) {
	/* XXX emulation of usleep() */
	DWORD sl;
	sl = Config.sleep_after_fork / 1000;
	if (sl == 0)
	    sl = 1;
	Sleep(sl);
    }
    if (GetExitCodeThread((HANDLE) thread, &ecode) && ecode == STILL_ACTIVE) {
	if (hIpc)
	    *hIpc = (HANDLE) thread;
	return pid;
    } else {
	CloseHandle((HANDLE) thread);
	return ipcCloseAllFD(prfd, pwfd, -1, -1);
    }
}
Пример #26
0
void
sslStart(int fd, const char *url, request_t * request, size_t * size_ptr)
{
    /* Create state structure. */
    SslStateData *sslState = NULL;
    int sock;
    ErrorState *err = NULL;
    debug(26, 3) ("sslStart: '%s %s'\n",
	RequestMethodStr[request->method], url);
    Counter.server.all.requests++;
    Counter.server.other.requests++;
    /* Create socket. */
    sock = comm_open(SOCK_STREAM,
	0,
	Config.Addrs.tcp_outgoing,
	0,
	COMM_NONBLOCKING,
	url);
    if (sock == COMM_ERROR) {
	debug(26, 4) ("sslStart: Failed because we're out of sockets.\n");
	err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR);
	err->xerrno = errno;
	err->request = requestLink(request);
	errorSend(fd, err);
	return;
    }
    sslState = xcalloc(1, sizeof(SslStateData));
    cbdataAdd(sslState, cbdataXfree, 0);
#if DELAY_POOLS
    sslState->delay_id = delayClient(request);
    delayRegisterDelayIdPtr(&sslState->delay_id);
#endif
    sslState->url = xstrdup(url);
    sslState->request = requestLink(request);
    sslState->size_ptr = size_ptr;
    sslState->client.fd = fd;
    sslState->server.fd = sock;
    sslState->server.buf = xmalloc(SQUID_TCP_SO_RCVBUF);
    sslState->client.buf = xmalloc(SQUID_TCP_SO_RCVBUF);
    comm_add_close_handler(sslState->server.fd,
	sslServerClosed,
	sslState);
    comm_add_close_handler(sslState->client.fd,
	sslClientClosed,
	sslState);
    commSetTimeout(sslState->client.fd,
	Config.Timeout.lifetime,
	sslTimeout,
	sslState);
    commSetTimeout(sslState->server.fd,
	Config.Timeout.connect,
	sslTimeout,
	sslState);
    peerSelect(request,
	NULL,
	sslPeerSelectComplete,
	sslState);
    /*
     * Disable the client read handler until peer selection is complete
     * Take control away from client_side.c.
     */
    commSetSelect(sslState->client.fd, COMM_SELECT_READ, NULL, NULL, 0);
}