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

📄 socket.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
	sock = *socketp;	REQUIRE(VALID_SOCKET(sock));	LOCK(&sock->lock);	REQUIRE(sock->references > 0);	sock->references--;	if (sock->references == 0)		kill_socket = ISC_TRUE;	UNLOCK(&sock->lock);	if (kill_socket)		destroy(&sock);	*socketp = NULL;}/* * I/O is possible on a given socket.  Schedule an event to this task that * will call an internal function to do the I/O.  This will charge the * task with the I/O operation and let our select loop handler get back * to doing something real as fast as possible. * * The socket and manager must be locked before calling this function. */static voiddispatch_recv(isc_socket_t *sock) {	intev_t *iev;	isc_socketevent_t *ev;	INSIST(!sock->pending_recv);	ev = ISC_LIST_HEAD(sock->recv_list);	if (ev == NULL)		return;	sock->pending_recv = 1;	iev = &sock->readable_ev;	socket_log(sock, NULL, EVENT, NULL, 0, 0,		   "dispatch_recv:  event %p -> task %p", ev, ev->ev_sender);	sock->references++;	iev->ev_sender = sock;	iev->ev_action = internal_recv;	iev->ev_arg = sock;	isc_task_send(ev->ev_sender, (isc_event_t **)&iev);}static voiddispatch_send(isc_socket_t *sock) {	intev_t *iev;	isc_socketevent_t *ev;	INSIST(!sock->pending_send);	ev = ISC_LIST_HEAD(sock->send_list);	if (ev == NULL)		return;	sock->pending_send = 1;	iev = &sock->writable_ev;	socket_log(sock, NULL, EVENT, NULL, 0, 0,		   "dispatch_send:  event %p -> task %p", ev, ev->ev_sender);	sock->references++;	iev->ev_sender = sock;	iev->ev_action = internal_send;	iev->ev_arg = sock;	isc_task_send(ev->ev_sender, (isc_event_t **)&iev);}/* * Dispatch an internal accept event. */static voiddispatch_accept(isc_socket_t *sock) {	intev_t *iev;	isc_socket_newconnev_t *ev;	INSIST(!sock->pending_accept);	/*	 * Are there any done events left, or were they all canceled	 * before the manager got the socket lock?	 */	ev = ISC_LIST_HEAD(sock->accept_list);	if (ev == NULL)		return;	sock->pending_accept = 1;	iev = &sock->readable_ev;	sock->references++;  /* keep socket around for this internal event */	iev->ev_sender = sock;	iev->ev_action = internal_accept;	iev->ev_arg = sock;	isc_task_send(ev->ev_sender, (isc_event_t **)&iev);}static voiddispatch_connect(isc_socket_t *sock) {	intev_t *iev;	isc_socket_connev_t *ev;	iev = &sock->writable_ev;	ev = sock->connect_ev;	INSIST(ev != NULL); /* XXX */	INSIST(sock->connecting);	sock->references++;  /* keep socket around for this internal event */	iev->ev_sender = sock;	iev->ev_action = internal_connect;	iev->ev_arg = sock;	isc_task_send(ev->ev_sender, (isc_event_t **)&iev);}/* * Dequeue an item off the given socket's read queue, set the result code * in the done event to the one provided, and send it to the task it was * destined for. * * If the event to be sent is on a list, remove it before sending.  If * asked to, send and detach from the socket as well. * * Caller must have the socket locked if the event is attached to the socket. */static voidsend_recvdone_event(isc_socket_t *sock, isc_socketevent_t **dev) {	isc_task_t *task;	task = (*dev)->ev_sender;	(*dev)->ev_sender = sock;	if (ISC_LINK_LINKED(*dev, ev_link))		ISC_LIST_DEQUEUE(sock->recv_list, *dev, ev_link);	if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED)	    == ISC_SOCKEVENTATTR_ATTACHED)		isc_task_sendanddetach(&task, (isc_event_t **)dev);	else		isc_task_send(task, (isc_event_t **)dev);}/* * See comments for send_recvdone_event() above. * * Caller must have the socket locked if the event is attached to the socket. */static voidsend_senddone_event(isc_socket_t *sock, isc_socketevent_t **dev) {	isc_task_t *task;	INSIST(dev != NULL && *dev != NULL);	task = (*dev)->ev_sender;	(*dev)->ev_sender = sock;	if (ISC_LINK_LINKED(*dev, ev_link))		ISC_LIST_DEQUEUE(sock->send_list, *dev, ev_link);	if (((*dev)->attributes & ISC_SOCKEVENTATTR_ATTACHED)	    == ISC_SOCKEVENTATTR_ATTACHED)		isc_task_sendanddetach(&task, (isc_event_t **)dev);	else		isc_task_send(task, (isc_event_t **)dev);}/* * Call accept() on a socket, to get the new file descriptor.  The listen * socket is used as a prototype to create a new isc_socket_t.  The new * socket has one outstanding reference.  The task receiving the event * will be detached from just after the event is delivered. * * On entry to this function, the event delivered is the internal * readable event, and the first item on the accept_list should be * the done event we want to send.  If the list is empty, this is a no-op, * so just unlock and return. */static voidinternal_accept(isc_task_t *me, isc_event_t *ev) {	isc_socket_t *sock;	isc_socketmgr_t *manager;	isc_socket_newconnev_t *dev;	isc_task_t *task;	ISC_SOCKADDR_LEN_T addrlen;	int fd;	isc_result_t result = ISC_R_SUCCESS;	char strbuf[ISC_STRERRORSIZE];	UNUSED(me);	sock = ev->ev_sender;	INSIST(VALID_SOCKET(sock));	LOCK(&sock->lock);	socket_log(sock, NULL, TRACE,		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTLOCK,		   "internal_accept called, locked socket");	manager = sock->manager;	INSIST(VALID_MANAGER(manager));	INSIST(sock->listener);	INSIST(sock->pending_accept == 1);	sock->pending_accept = 0;	INSIST(sock->references > 0);	sock->references--;  /* the internal event is done with this socket */	if (sock->references == 0) {		UNLOCK(&sock->lock);		destroy(&sock);		return;	}	/*	 * Get the first item off the accept list.	 * If it is empty, unlock the socket and return.	 */	dev = ISC_LIST_HEAD(sock->accept_list);	if (dev == NULL) {		UNLOCK(&sock->lock);		return;	}	/*	 * Try to accept the new connection.  If the accept fails with	 * EAGAIN or EINTR, simply poke the watcher to watch this socket	 * again.  Also ignore ECONNRESET, which has been reported to	 * be spuriously returned on Linux 2.2.19 although it is not	 * a documented error for accept().  ECONNABORTED has been	 * reported for Solaris 8.  The rest are thrown in not because	 * we have seen them but because they are ignored by other	 * deamons such as BIND 8 and Apache.	 */	addrlen = sizeof(dev->newsocket->address.type);	memset(&dev->newsocket->address.type.sa, 0, addrlen);	fd = accept(sock->fd, &dev->newsocket->address.type.sa,		    (void *)&addrlen);#ifdef F_DUPFD        /*         * Leave a space for stdio to work in.         */        if (fd >= 0 && fd < 20) {                int new, tmp;                new = fcntl(fd, F_DUPFD, 20);                tmp = errno;                (void)close(fd);                errno = tmp;                fd = new;        }#endif	if (fd < 0) {		if (SOFT_ERROR(errno))			goto soft_error;		switch (errno) {		case ENOBUFS:		case ENFILE:		case ENOMEM:		case ECONNRESET:		case ECONNABORTED:		case EHOSTUNREACH:		case EHOSTDOWN:		case ENETUNREACH:		case ENETDOWN:		case ECONNREFUSED:#ifdef EPROTO		case EPROTO:#endif#ifdef ENONET		case ENONET:#endif			goto soft_error;		default:			break;		}		isc__strerror(errno, strbuf, sizeof(strbuf));		UNEXPECTED_ERROR(__FILE__, __LINE__,				 "internal_accept: accept() %s: %s",				 isc_msgcat_get(isc_msgcat,						ISC_MSGSET_GENERAL,						ISC_MSG_FAILED,						"failed"),				 strbuf);		fd = -1;		result = ISC_R_UNEXPECTED;	} else {		if (addrlen == 0) {			UNEXPECTED_ERROR(__FILE__, __LINE__,					 "internal_accept(): "					 "accept() failed to return "					 "remote address");			(void)close(fd);			goto soft_error;		} else if (dev->newsocket->address.type.sa.sa_family !=			   sock->pf)		{			UNEXPECTED_ERROR(__FILE__, __LINE__,					 "internal_accept(): "					 "accept() returned peer address "					 "family %u (expected %u)", 					 dev->newsocket->address.					 type.sa.sa_family,					 sock->pf);			(void)close(fd);			goto soft_error;		} else if (fd >= (int)FD_SETSIZE) {			isc_log_iwrite(isc_lctx, ISC_LOGCATEGORY_GENERAL,				       ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,				       isc_msgcat, ISC_MSGSET_SOCKET,				       ISC_MSG_TOOMANYFDS,				       "%s: too many open file descriptors",				       "accept");			(void)close(fd);			goto soft_error;		}	}	if (fd != -1) {		dev->newsocket->address.length = addrlen;		dev->newsocket->pf = sock->pf;	}	/*	 * Pull off the done event.	 */	ISC_LIST_UNLINK(sock->accept_list, dev, ev_link);	/*	 * Poke watcher if there are more pending accepts.	 */	if (!ISC_LIST_EMPTY(sock->accept_list))		select_poke(sock->manager, sock->fd, SELECT_POKE_ACCEPT);	UNLOCK(&sock->lock);	if (fd != -1 && (make_nonblock(fd) != ISC_R_SUCCESS)) {		(void)close(fd);		fd = -1;		result = ISC_R_UNEXPECTED;	}	/*	 * -1 means the new socket didn't happen.	 */	if (fd != -1) {		LOCK(&manager->lock);		ISC_LIST_APPEND(manager->socklist, dev->newsocket, link);		dev->newsocket->fd = fd;		dev->newsocket->bound = 1;		dev->newsocket->connected = 1;		/*		 * Save away the remote address		 */		dev->address = dev->newsocket->address;		manager->fds[fd] = dev->newsocket;		manager->fdstate[fd] = MANAGED;		if (manager->maxfd < fd)			manager->maxfd = fd;		socket_log(sock, &dev->newsocket->address, CREATION,			   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_ACCEPTEDCXN,			   "accepted connection, new socket %p",			   dev->newsocket);		UNLOCK(&manager->lock);	} else {		dev->newsocket->references--;		free_socket(&dev->newsocket);	}		/*	 * Fill in the done event details and send it off.	 */	dev->result = result;	task = dev->ev_sender;	dev->ev_sender = sock;	isc_task_sendanddetach(&task, ISC_EVENT_PTR(&dev));	return; soft_error:	select_poke(sock->manager, sock->fd, SELECT_POKE_ACCEPT);	UNLOCK(&sock->lock);	return;}static voidinternal_recv(isc_task_t *me, isc_event_t *ev) {	isc_socketevent_t *dev;	isc_socket_t *sock;	INSIST(ev->ev_type == ISC_SOCKEVENT_INTR);	sock = ev->ev_sender;	INSIST(VALID_SOCKET(sock));	LOCK(&sock->lock);	socket_log(sock, NULL, IOEVENT,		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALRECV,		   "internal_recv: task %p got event %p", me, ev);	INSIST(sock->pending_recv == 1);	sock->pending_recv = 0;	INSIST(sock->references > 0);	sock->references--;  /* the internal event is done with this socket */	if (sock->references == 0) {		UNLOCK(&sock->lock);		destroy(&sock);		return;	}	/*	 * Try to do as much I/O as possible on this socket.  There are no	 * limits here, currently.	 */	dev = ISC_LIST_HEAD(sock->recv_list);	while (dev != NULL) {		switch (doio_recv(sock, dev)) {		case DOIO_SOFT:			goto poke;		case DOIO_EOF:			/*			 * read of 0 means the remote end was closed.			 * Run through the event queue and dispatch all			 * the events with an EOF result code.			 */			do {				dev->result = ISC_R_EOF;				send_recvdone_event(sock, &dev);				dev = ISC_LIST_HEAD(sock->recv_list);			} while (dev != NULL);			goto poke;		case DOIO_SUCCESS:		case DOIO_HARD:			send_recvdone_event(sock, &dev);			break;		}		dev = ISC_LIST_HEAD(sock->recv_list);	} poke:	if (!ISC_LIST_EMPTY(sock->recv_list))		select_poke(sock->manager, sock->fd, SELECT_POKE_READ);	UNLOCK(&sock->lock);}static voidinternal_send(isc_task_t *me, isc_event_t *ev) {	isc_socketevent_t *dev;	isc_socket_t *sock;	INSIST(ev->ev_type == ISC_SOCKEVENT_INTW);	/*	 * Find out what socket this is and lock it.	 */	sock = (isc_socket_t *)ev->ev_sender;	INSIST(VALID_SOCKET(sock));	LOCK(&sock->lock);	socket_log(sock, NULL, IOEVENT,		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND,		   "internal_send: task %p got event %p", me, ev);	INSIST(sock->pending_send == 1);	sock->pending_send = 0;	INSIST(sock->references > 0);	sock->references--;  /* the internal event is done with this socket */	if (sock->references == 0) {		UNLOCK(&sock->lock);		destroy(&sock);		return;	}	/*	 * Try to do as much I/O as possible on this socket.  There are no	 * limits here, currently.	 */	dev = ISC_LIST_HEAD(sock->send_list);	while (dev != NULL) {		switch (doio_send(sock, dev)) {		case DOIO_SOFT:			goto poke;		case DOIO_HARD:		case DOIO_SUCCESS:			send_senddone_event(sock, &dev);			break;		}		dev = ISC_LIST_HEAD(sock->send_list);	} poke:	if (!ISC_LIST_EMPTY(sock->send_list))		select_poke(sock->manager, sock->fd, SELECT_POKE_WRITE);	UNLOCK(&sock->lock);}static voidprocess_fds(isc_socketmgr_t *manager, int maxfd,	    fd_set *readfds, fd_set *writefds)

⌨️ 快捷键说明

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