⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comm.c

📁 -
💻 C
📖 第 1 页 / 共 2 页
字号:
	debug(5, 10) ("comm_connect_addr: FD %d connected to %s:%d\n",	    sock, F->ipaddr, F->remote_port);    } else if (status == COMM_INPROGRESS) {	debug(5, 10) ("comm_connect_addr: FD %d connection pending\n", sock);    }    return status;}/* Wait for an incoming connection on FD.  FD should be a socket returned * from comm_listen. */intcomm_accept(int fd, struct sockaddr_in *pn, struct sockaddr_in *me){    int sock;    struct sockaddr_in P;    struct sockaddr_in M;    socklen_t Slen;    fde *F = NULL;    Slen = sizeof(P);    Counter.syscalls.sock.accepts++;    if ((sock = accept(fd, (struct sockaddr *) &P, &Slen)) < 0) {	if (ignoreErrno(errno)) {	    debug(50, 5) ("comm_accept: FD %d: %s\n", fd, xstrerror());	    return COMM_NOMESSAGE;	} else if (ENFILE == errno || EMFILE == errno) {	    debug(50, 3) ("comm_accept: FD %d: %s\n", fd, xstrerror());	    return COMM_ERROR;	} else {	    debug(50, 1) ("comm_accept: FD %d: %s\n", fd, xstrerror());	    return COMM_ERROR;	}    }    if (pn)	*pn = P;    Slen = sizeof(M);    memset(&M, '\0', Slen);    getsockname(sock, (struct sockaddr *) &M, &Slen);    if (me)	*me = M;    commSetCloseOnExec(sock);    /* fdstat update */    fd_open(sock, FD_SOCKET, "HTTP Request");    F = &fd_table[sock];    xstrncpy(F->ipaddr, inet_ntoa(P.sin_addr), 16);    F->remote_port = htons(P.sin_port);    F->local_port = htons(M.sin_port);    commSetNonBlocking(sock);    return sock;}voidcommCallCloseHandlers(int fd){    fde *F = &fd_table[fd];    close_handler *ch;    debug(5, 5) ("commCallCloseHandlers: FD %d\n", fd);    while ((ch = F->close_handler) != NULL) {	F->close_handler = ch->next;	debug(5, 5) ("commCallCloseHandlers: ch->handler=%p\n", ch->handler);	if (cbdataValid(ch->data))	    ch->handler(fd, ch->data);	cbdataUnlock(ch->data);	safe_free(ch);    }}#if LINGERING_CLOSEstatic voidcommLingerClose(int fd, void *unused){    LOCAL_ARRAY(char, buf, 1024);    int n;    n = read(fd, buf, 1024);    if (n < 0)	debug(5, 3) ("commLingerClose: FD %d read: %s\n", fd, xstrerror());    comm_close(fd);}static voidcommLingerTimeout(int fd, void *unused){    debug(5, 3) ("commLingerTimeout: FD %d\n", fd);    comm_close(fd);}/* * Inspired by apache */voidcomm_lingering_close(int fd){    if (shutdown(fd, 1) < 0) {	comm_close(fd);	return;    }    fd_note(fd, "lingering close");    commSetTimeout(fd, 10, commLingerTimeout, NULL);    commSetSelect(fd, COMM_SELECT_READ, commLingerClose, NULL, 0);}#endifvoidcomm_close(int fd){    fde *F = NULL;#if USE_ASYNC_IO    int doaioclose = 1;#endif    debug(5, 5) ("comm_close: FD %d\n", fd);    assert(fd >= 0);    assert(fd < Squid_MaxFD);    F = &fd_table[fd];    if (F->flags.closing)	return;    if (shutting_down && (!F->flags.open || F->type == FD_FILE))	return;    assert(F->flags.open);    assert(F->type != FD_FILE);#ifdef USE_ASYNC_IO    if (F->flags.nolinger && F->flags.nonblocking)	doaioclose = 0;#endif    F->flags.closing = 1;    CommWriteStateCallbackAndFree(fd, COMM_ERR_CLOSING);    commCallCloseHandlers(fd);    if (F->uses)		/* assume persistent connect count */	pconnHistCount(1, F->uses);    fd_close(fd);		/* update fdstat */#if defined(_SQUID_LINUX_)    /*     * michael@metal.iinet.net.au sez close() on     * network sockets never blocks.     */    close(fd);#elif USE_ASYNC_IO    if (doaioclose)	aioClose(fd);    else	close(fd);#else    close(fd);#endif    Counter.syscalls.sock.closes++;}/* Send a udp datagram to specified TO_ADDR. */intcomm_udp_sendto(int fd,    const struct sockaddr_in *to_addr,    int addr_len,    const void *buf,    int len){    int x;    Counter.syscalls.sock.sendtos++;    x = sendto(fd, buf, len, 0, (struct sockaddr *) to_addr, addr_len);    if (x < 0) {#ifdef _SQUID_LINUX_	if (ECONNREFUSED != errno)#endif	    debug(50, 1) ("comm_udp_sendto: FD %d, %s, port %d: %s\n",		fd,		inet_ntoa(to_addr->sin_addr),		(int) htons(to_addr->sin_port),		xstrerror());	return COMM_ERROR;    }    return x;}voidcommSetDefer(int fd, DEFER * func, void *data){    fde *F = &fd_table[fd];    F->defer_check = func;    F->defer_data = data;}voidcommSetSelect(int fd, unsigned int type, PF * handler, void *client_data, time_t timeout){    fde *F = &fd_table[fd];    assert(fd >= 0);    assert(F->flags.open);    debug(5, 5) ("commSetSelect: FD %d type %d\n", fd, type);    if (type & COMM_SELECT_READ) {	F->read_handler = handler;	F->read_data = client_data;	commUpdateReadBits(fd, handler);    }    if (type & COMM_SELECT_WRITE) {	F->write_handler = handler;	F->write_data = client_data;	commUpdateWriteBits(fd, handler);    }    if (timeout)	F->timeout = squid_curtime + timeout;}voidcomm_add_close_handler(int fd, PF * handler, void *data){    close_handler *new = xmalloc(sizeof(*new));    close_handler *c;    debug(5, 5) ("comm_add_close_handler: FD %d, handler=%p, data=%p\n",	fd, handler, data);    for (c = fd_table[fd].close_handler; c; c = c->next)	assert(c->handler != handler || c->data != data);    new->handler = handler;    new->data = data;    new->next = fd_table[fd].close_handler;    fd_table[fd].close_handler = new;    cbdataLock(data);}voidcomm_remove_close_handler(int fd, PF * handler, void *data){    close_handler *p;    close_handler *last = NULL;    /* Find handler in list */    debug(5, 5) ("comm_remove_close_handler: FD %d, handler=%p, data=%p\n",	fd, handler, data);    for (p = fd_table[fd].close_handler; p != NULL; last = p, p = p->next)	if (p->handler == handler && p->data == data)	    break;		/* This is our handler */    assert(p != NULL);    /* Remove list entry */    if (last)	last->next = p->next;    else	fd_table[fd].close_handler = p->next;    cbdataUnlock(p->data);    safe_free(p);}static voidcommSetNoLinger(int fd){    struct linger L;    L.l_onoff = 0;		/* off */    L.l_linger = 0;    if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &L, sizeof(L)) < 0)	debug(50, 0) ("commSetNoLinger: FD %d: %s\n", fd, xstrerror());    fd_table[fd].flags.nolinger = 1;}static voidcommSetReuseAddr(int fd){    int on = 1;    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) < 0)	debug(50, 1) ("commSetReuseAddr: FD %d: %s\n", fd, xstrerror());}static voidcommSetTcpRcvbuf(int fd, int size){    if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *) &size, sizeof(size)) < 0)	debug(50, 1) ("commSetTcpRcvbuf: FD %d, SIZE %d: %s\n",	    fd, size, xstrerror());}intcommSetNonBlocking(int fd){    int flags;    int dummy = 0;    if ((flags = fcntl(fd, F_GETFL, dummy)) < 0) {	debug(50, 0) ("FD %d: fcntl F_GETFL: %s\n", fd, xstrerror());	return COMM_ERROR;    }    if (fcntl(fd, F_SETFL, flags | SQUID_NONBLOCK) < 0) {	debug(50, 0) ("commSetNonBlocking: FD %d: %s\n", fd, xstrerror());	return COMM_ERROR;    }    fd_table[fd].flags.nonblocking = 1;    return 0;}voidcommSetCloseOnExec(int fd){#ifdef FD_CLOEXEC    int flags;    int dummy = 0;    if ((flags = fcntl(fd, F_GETFL, dummy)) < 0) {	debug(50, 0) ("FD %d: fcntl F_GETFL: %s\n", fd, xstrerror());	return;    }    if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)	debug(50, 0) ("FD %d: set close-on-exec failed: %s\n", fd, xstrerror());#endif}#ifdef TCP_NODELAYstatic voidcommSetTcpNoDelay(int fd){    int on = 1;    if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on)) < 0)	debug(50, 1) ("commSetTcpNoDelay: FD %d: %s\n", fd, xstrerror());}#endifvoidcomm_init(void){    fd_table = xcalloc(Squid_MaxFD, sizeof(fde));    /* XXX account fd_table */    /* Keep a few file descriptors free so that we don't run out of FD's     * after accepting a client but before it opens a socket or a file.     * Since Squid_MaxFD can be as high as several thousand, don't waste them */    RESERVED_FD = XMIN(100, Squid_MaxFD / 4);}/* Write to FD. */static voidcommHandleWrite(int fd, void *data){    CommWriteStateData *state = data;    int len = 0;    int nleft;    debug(5, 5) ("commHandleWrite: FD %d: off %d, sz %d.\n",	fd, (int) state->offset, state->size);    nleft = state->size - state->offset;    len = write(fd, state->buf + state->offset, nleft);    debug(5, 5) ("commHandleWrite: write() returns %d\n", len);    fd_bytes(fd, len, FD_WRITE);    Counter.syscalls.sock.writes++;    if (len == 0) {	/* Note we even call write if nleft == 0 */	/* We're done */	if (nleft != 0)	    debug(5, 1) ("commHandleWrite: FD %d: write failure: connection closed with %d bytes remaining.\n", fd, nleft);	CommWriteStateCallbackAndFree(fd, nleft ? COMM_ERROR : COMM_OK);    } else if (len < 0) {	/* An error */	if (fd_table[fd].flags.socket_eof) {	    debug(50, 2) ("commHandleWrite: FD %d: write failure: %s.\n",		fd, xstrerror());	    CommWriteStateCallbackAndFree(fd, COMM_ERROR);	} else if (ignoreErrno(errno)) {	    debug(50, 10) ("commHandleWrite: FD %d: write failure: %s.\n",		fd, xstrerror());	    commSetSelect(fd,		COMM_SELECT_WRITE,		commHandleWrite,		state,		0);	} else {	    debug(50, 2) ("commHandleWrite: FD %d: write failure: %s.\n",		fd, xstrerror());	    CommWriteStateCallbackAndFree(fd, COMM_ERROR);	}    } else {	/* A successful write, continue */	state->offset += len;	if (state->offset < state->size) {	    /* Not done, reinstall the write handler and write some more */	    commSetSelect(fd,		COMM_SELECT_WRITE,		commHandleWrite,		state,		0);	} else {	    CommWriteStateCallbackAndFree(fd, COMM_OK);	}    }}/* Select for Writing on FD, until SIZE bytes are sent.  Call * * HANDLER when complete. */voidcomm_write(int fd, char *buf, int size, CWCB * handler, void *handler_data, FREE * free_func){    CommWriteStateData *state = fd_table[fd].rwstate;    debug(5, 5) ("comm_write: FD %d: sz %d: hndl %p: data %p.\n",	fd, size, handler, handler_data);    if (NULL != state) {	debug(5, 1) ("comm_write: fd_table[%d].rwstate != NULL\n", fd);	safe_free(state);	fd_table[fd].rwstate = NULL;    }    assert(state == NULL);    fd_table[fd].rwstate = state = xcalloc(1, sizeof(CommWriteStateData));    state->buf = buf;    state->size = size;    state->offset = 0;    state->handler = handler;    state->handler_data = handler_data;    state->free_func = free_func;    cbdataLock(handler_data);#ifdef OPTIMISTIC_IO    commHandleWrite(fd, state);#else    commSetSelect(fd, COMM_SELECT_WRITE, commHandleWrite, state, 0);#endif}/* a wrapper around comm_write to allow for MemBuf to be comm_written in a snap */voidcomm_write_mbuf(int fd, MemBuf mb, CWCB * handler, void *handler_data){    comm_write(fd, mb.buf, mb.size, handler, handler_data, memBufFreeFunc(&mb));}/* * hm, this might be too general-purpose for all the places we'd * like to use it. */intignoreErrno(int ierrno){    switch (ierrno) {    case EINPROGRESS:    case EWOULDBLOCK:#if EAGAIN != EWOULDBLOCK    case EAGAIN:#endif    case EALREADY:    case EINTR:#ifdef ERESTART    case ERESTART:#endif	return 1;    default:	return 0;    }    /* NOTREACHED */}voidcommCloseAllSockets(void){    int fd;    fde *F = NULL;    PF *callback;    for (fd = 0; fd <= Biggest_FD; fd++) {	F = &fd_table[fd];	if (!F->flags.open)	    continue;	if (F->type != FD_SOCKET)	    continue;	if (F->flags.ipc)	/* don't close inter-process sockets */	    continue;	if (F->timeout_handler) {	    debug(5, 5) ("commCloseAllSockets: FD %d: Calling timeout handler\n",		fd);	    callback = F->timeout_handler;	    F->timeout_handler = NULL;	    callback(fd, F->timeout_data);	} else {	    debug(5, 5) ("commCloseAllSockets: FD %d: calling comm_close()\n", fd);	    comm_close(fd);	}    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -