Ejemplo n.º 1
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++;
}
Ejemplo n.º 2
0
static void
icpHandleIcpV2(int fd, struct sockaddr_in from, char *buf, int len)
{
    icp_common_t header;
    StoreEntry *entry = NULL;
    char *url = NULL;
    const cache_key *key;
    request_t *icp_request = NULL;
    int allow = 0;
    aclCheck_t checklist;
    icp_common_t *reply;
    int src_rtt = 0;
    u_num32 flags = 0;
    int rtt = 0;
    int hops = 0;
    xmemcpy(&header, buf, sizeof(icp_common_t));
    /*
     * Only these fields need to be converted
     */
    header.length = ntohs(header.length);
    header.reqnum = ntohl(header.reqnum);
    header.flags = ntohl(header.flags);
    header.pad = ntohl(header.pad);
    /*
     * Length field should match the number of bytes read
     */
    if (len != header.length) {
	debug(12, 3) ("icpHandleIcpV2: ICP message is too small\n");
	return;
    }
    switch (header.opcode) {
    case ICP_QUERY:
	/* We have a valid packet */
	url = buf + sizeof(icp_common_t) + sizeof(u_num32);
	if (strpbrk(url, w_space)) {
	    url = rfc1738_escape(url);
	    reply = icpCreateMessage(ICP_ERR, 0, url, header.reqnum, 0);
	    icpUdpSend(fd, &from, reply, LOG_UDP_INVALID, 0);
	    break;
	}
	if ((icp_request = urlParse(METHOD_GET, url)) == NULL) {
	    reply = icpCreateMessage(ICP_ERR, 0, url, header.reqnum, 0);
	    icpUdpSend(fd, &from, reply, LOG_UDP_INVALID, 0);
	    break;
	}
	memset(&checklist, '\0', sizeof(checklist));
	checklist.src_addr = from.sin_addr;
	checklist.my_addr = no_addr;
	checklist.request = icp_request;
	allow = aclCheckFast(Config.accessList.icp, &checklist);
	if (!allow) {
	    debug(12, 2) ("icpHandleIcpV2: Access Denied for %s by %s.\n",
		inet_ntoa(from.sin_addr), AclMatchedName);
	    if (clientdbCutoffDenied(from.sin_addr)) {
		/*
		 * count this DENIED query in the clientdb, even though
		 * we're not sending an ICP reply...
		 */
		clientdbUpdate(from.sin_addr, LOG_UDP_DENIED, PROTO_ICP, 0);
	    } else {
		reply = icpCreateMessage(ICP_DENIED, 0, url, header.reqnum, 0);
		icpUdpSend(fd, &from, reply, LOG_UDP_DENIED, 0);
	    }
	    break;
	}
	if (header.flags & ICP_FLAG_SRC_RTT) {
	    rtt = netdbHostRtt(icp_request->host);
	    hops = netdbHostHops(icp_request->host);
	    src_rtt = ((hops & 0xFFFF) << 16) | (rtt & 0xFFFF);
	    if (rtt)
		flags |= ICP_FLAG_SRC_RTT;
	}
	/* The peer is allowed to use this cache */
	entry = storeGetPublic(url, METHOD_GET);
	debug(12, 5) ("icpHandleIcpV2: OPCODE %s\n", icp_opcode_str[header.opcode]);
	if (icpCheckUdpHit(entry, icp_request)) {
	    reply = icpCreateMessage(ICP_HIT, flags, url, header.reqnum, src_rtt);
	    icpUdpSend(fd, &from, reply, LOG_UDP_HIT, 0);
	    break;
	}
	if (Config.onoff.test_reachability && rtt == 0) {
	    if ((rtt = netdbHostRtt(icp_request->host)) == 0)
		netdbPingSite(icp_request->host);
	}
	/* if store is rebuilding, return a UDP_HIT, but not a MISS */
	if (store_dirs_rebuilding && opt_reload_hit_only) {
	    reply = icpCreateMessage(ICP_MISS_NOFETCH, flags, url, header.reqnum, src_rtt);
	    icpUdpSend(fd, &from, reply, LOG_UDP_MISS_NOFETCH, 0);
	} else if (hit_only_mode_until > squid_curtime) {
	    reply = icpCreateMessage(ICP_MISS_NOFETCH, flags, url, header.reqnum, src_rtt);
	    icpUdpSend(fd, &from, reply, LOG_UDP_MISS_NOFETCH, 0);
	} else if (Config.onoff.test_reachability && rtt == 0) {
	    reply = icpCreateMessage(ICP_MISS_NOFETCH, flags, url, header.reqnum, src_rtt);
	    icpUdpSend(fd, &from, reply, LOG_UDP_MISS_NOFETCH, 0);
	} else {
	    reply = icpCreateMessage(ICP_MISS, flags, url, header.reqnum, src_rtt);
	    icpUdpSend(fd, &from, reply, LOG_UDP_MISS, 0);
	}
	break;

    case ICP_HIT:
#if ALLOW_SOURCE_PING
    case ICP_SECHO:
#endif
    case ICP_DECHO:
    case ICP_MISS:
    case ICP_DENIED:
    case ICP_MISS_NOFETCH:
	if (neighbors_do_private_keys && header.reqnum == 0) {
	    debug(12, 0) ("icpHandleIcpV2: Neighbor %s returned reqnum = 0\n",
		inet_ntoa(from.sin_addr));
	    debug(12, 0) ("icpHandleIcpV2: Disabling use of private keys\n");
	    neighbors_do_private_keys = 0;
	}
	url = buf + sizeof(icp_common_t);
	debug(12, 3) ("icpHandleIcpV2: %s from %s for '%s'\n",
	    icp_opcode_str[header.opcode],
	    inet_ntoa(from.sin_addr),
	    url);
	key = icpGetCacheKey(url, (int) header.reqnum);
	/* call neighborsUdpAck even if ping_status != PING_WAITING */
	neighborsUdpAck(key, &header, &from);
	break;

    case ICP_INVALID:
    case ICP_ERR:
	break;

    default:
	debug(12, 0) ("icpHandleIcpV2: UNKNOWN OPCODE: %d from %s\n",
	    header.opcode, inet_ntoa(from.sin_addr));
	break;
    }
    if (icp_request)
	requestDestroy(icp_request);
}