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

📄 socket.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * 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_socket_t *sock, int accept_errno) {	isc_socketmgr_t *manager;	isc_socket_newconnev_t *dev;	isc_task_t *task;	ISC_SOCKADDR_LEN_T addrlen;	SOCKET fd;	isc_result_t result = ISC_R_SUCCESS;	char strbuf[ISC_STRERRORSIZE];	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->hEvent != NULL);	INSIST(sock->pending_accept == 1);	sock->pending_accept = 0;	/*	 * Check any possible error status from the event notification here.	 * Note that we don't take any action since it was only	 * Windows that was notifying about a network event, not the	 * application.	 * PDMXXX: Should we care about any of the possible event errors	 *	   signalled? The only possible valid errors are:	 *	   WSAENETDOWN, WSAECONNRESET, & WSAECONNABORTED	 */	if (accept_errno != 0) {		switch (accept_errno) {		case WSAENETDOWN:		case WSAECONNRESET:		case WSAECONNABORTED:			break;		/* Expected errors */		default:			isc__strerror(accept_errno, strbuf, sizeof(strbuf));			UNEXPECTED_ERROR(__FILE__, __LINE__,					 "internal_accept: from event wait: %s",					 strbuf);			break;		}		UNLOCK(&sock->lock);		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) {		isc_sockaddr_t from;		/*		 * This should only happen if WSAEventSelect() fails		 * below or in isc_socket_cancel().		 */		addrlen = sizeof(from.type);		fd = accept(sock->fd, &from.type.sa, &addrlen);		if (fd != INVALID_SOCKET) {			char addrbuf[ISC_SOCKADDR_FORMATSIZE];			isc_sockaddr_format(&from, addrbuf, sizeof(addrbuf));			UNEXPECTED_ERROR(__FILE__, __LINE__,					 "sock->accept_list empty: "					 "dropping TCP request from %s",					 addrbuf);			(void)closesocket(fd);		}		UNLOCK(&sock->lock);		return;	}	/*	 * Try to accept the new connection.  If the accept fails with	 * EAGAIN or EINTR, the event wait will be notified again since	 * the event will be reset on return to caller.	 */	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);	if (fd == INVALID_SOCKET) {		accept_errno = WSAGetLastError();		if (SOFT_ERROR(accept_errno) || accept_errno == WSAECONNRESET) {			goto soft_error;		} else {			isc__strerror(accept_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 = INVALID_SOCKET;			result = ISC_R_UNEXPECTED;		}	} else {		if (addrlen == 0) {			UNEXPECTED_ERROR(__FILE__, __LINE__,					 "internal_accept(): "					 "accept() failed to return "					 "remote address");			(void)closesocket(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)closesocket(fd);			goto soft_error;		}	}	if (fd != INVALID_SOCKET) {		dev->newsocket->address.length = addrlen;		dev->newsocket->pf = sock->pf;	}	/*	 * Pull off the done event.	 */	ISC_LIST_UNLINK(sock->accept_list, dev, ev_link);	/*	 * Stop listing for connects.	 */	if (ISC_LIST_EMPTY(sock->accept_list) &&	    WSAEventSelect(sock->fd, sock->hEvent, FD_CLOSE) != 0) {		int stat;		const char *msg;		stat = WSAGetLastError();		isc__strerror(stat, strbuf, sizeof(strbuf));		msg = isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,					     ISC_MSG_FAILED, "failed");		UNEXPECTED_ERROR(__FILE__, __LINE__, "WSAEventSelect: %s: %s",				 msg, strbuf);	}	UNLOCK(&sock->lock);	if (fd != INVALID_SOCKET) {		isc_result_t tresult;		tresult = make_nonblock(fd);		if (tresult != ISC_R_SUCCESS) {			closesocket(fd);			fd = INVALID_SOCKET;			result = tresult;		}	}	/*	 * INVALID_SOCKET means the new socket didn't happen.	 */	if (fd != INVALID_SOCKET) {		LOCK(&manager->lock);		ISC_LIST_APPEND(manager->socklist, dev->newsocket, link);		dev->newsocket->fd = fd;		dev->newsocket->bound = 1;		dev->newsocket->connected = 1;		/*		 * The accept socket inherits the listen socket's		 * selected events. Remove this socket from all events		 * as it is handled by IOCP. (Joe Quanaim, lucent.com)		 */		if (WSAEventSelect(dev->newsocket->fd, 0, 0) != 0) {			/* this is an unlikely but non-fatal error */			int stat;			const char *msg;			stat = WSAGetLastError();			isc__strerror(stat, strbuf, sizeof(strbuf));			msg = isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,						     ISC_MSG_FAILED, "failed");			UNEXPECTED_ERROR(__FILE__, __LINE__,					 "WSAEventSelect: %s: %s", msg, strbuf);		}		/*		 * Save away the remote address		 */		dev->address = dev->newsocket->address;		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_t **)&dev);	return; soft_error:	UNLOCK(&sock->lock);	return;}/* * Called when a socket with a pending connect() finishes. */static voidinternal_connect(isc_socket_t *sock, int connect_errno) {	isc_socket_connev_t *dev;	isc_task_t *task;	char strbuf[ISC_STRERRORSIZE];	INSIST(VALID_SOCKET(sock));	LOCK(&sock->lock);	/*	 * Has this event been canceled?	 */	dev = sock->connect_ev;	if (dev == NULL) {		INSIST(!sock->connecting);		UNLOCK(&sock->lock);		return;	}	INSIST(sock->connecting);	sock->connecting = 0;	/*	 * Check possible Windows network event error status here.	 */	if (connect_errno != 0) {		/*		 * If the error is EAGAIN, just try again on this		 * fd and pretend nothing strange happened.		 */		if (SOFT_ERROR(connect_errno) ||		    connect_errno == WSAEINPROGRESS)		{			sock->connecting = 1;			UNLOCK(&sock->lock);			return;		}		/*		 * Translate other errors into ISC_R_* flavors.		 */		switch (connect_errno) {#define ERROR_MATCH(a, b) case a: dev->result = b; break;			ERROR_MATCH(WSAEACCES, ISC_R_NOPERM);			ERROR_MATCH(WSAEADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);			ERROR_MATCH(WSAEAFNOSUPPORT, ISC_R_ADDRNOTAVAIL);			ERROR_MATCH(WSAECONNREFUSED, ISC_R_CONNREFUSED);			ERROR_MATCH(WSAEHOSTUNREACH, ISC_R_HOSTUNREACH);			ERROR_MATCH(WSAEHOSTDOWN, ISC_R_HOSTDOWN);			ERROR_MATCH(WSAENETUNREACH, ISC_R_NETUNREACH);			ERROR_MATCH(WSAENETDOWN, ISC_R_NETDOWN);			ERROR_MATCH(WSAENOBUFS, ISC_R_NORESOURCES);			ERROR_MATCH(WSAECONNRESET, ISC_R_CONNECTIONRESET);			ERROR_MATCH(WSAECONNABORTED, ISC_R_CONNECTIONRESET);			ERROR_MATCH(WSAETIMEDOUT, ISC_R_TIMEDOUT);#undef ERROR_MATCH		default:			dev->result = ISC_R_UNEXPECTED;			isc__strerror(connect_errno, strbuf, sizeof(strbuf));			UNEXPECTED_ERROR(__FILE__, __LINE__,					 "internal_connect: connect() %s",					 strbuf);		}	} else {		dev->result = ISC_R_SUCCESS;		sock->connected = 1;		sock->bound = 1;	}	sock->connect_ev = NULL;	UNLOCK(&sock->lock);	task = dev->ev_sender;	dev->ev_sender = sock;	isc_task_sendanddetach(&task, (isc_event_t **)&dev);}static voidinternal_recv(isc_socket_t *sock, isc_socketevent_t *dev,	      struct msghdr *messagehdr, int nbytes, int recv_errno){	isc_socketevent_t *ldev;	int io_state;	int cc;	INSIST(VALID_SOCKET(sock));	LOCK(&sock->lock);	socket_log(sock, NULL, IOEVENT,		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALRECV,		   "internal_recv: task got socket event %p", dev);	INSIST(sock->pending_recv > 0);	sock->pending_recv--;	/* If the event is no longer in the list we can just return */	ldev = ISC_LIST_HEAD(sock->recv_list);	while (ldev != NULL && ldev != dev) {		ldev = ISC_LIST_NEXT(ldev, ev_link);	}	if (ldev == NULL)		goto done;	/*	 * Try to do as much I/O as possible on this socket.  There are no	 * limits here, currently.	 */	switch (completeio_recv(sock, dev, messagehdr, nbytes, recv_errno)) {	case DOIO_SOFT:		cc = 0;		recv_errno = 0;		io_state = startio_recv(sock, dev, &cc, &recv_errno);		goto done;	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.		 */		dev->result = ISC_R_EOF;		send_recvdone_event(sock, &dev);		goto done;	case DOIO_SUCCESS:	case DOIO_HARD:		send_recvdone_event(sock, &dev);		break;	} done:	UNLOCK(&sock->lock);}static voidinternal_send(isc_socket_t *sock, isc_socketevent_t *dev,	      struct msghdr *messagehdr, int nbytes, int send_errno){	isc_socketevent_t *ldev;	int io_state;	int cc;	/*	 * Find out what socket this is and lock it.	 */	INSIST(VALID_SOCKET(sock));	LOCK(&sock->lock);	socket_log(sock, NULL, IOEVENT,		   isc_msgcat, ISC_MSGSET_SOCKET, ISC_MSG_INTERNALSEND,		   "internal_send: task got socket event %p", dev);	INSIST(sock->pending_send > 0);	sock->pending_send--;	/* If the event is no longer in the list we can just return */	ldev = ISC_LIST_HEAD(sock->send_list);	while (ldev != NULL && ldev != dev) {		ldev = ISC_LIST_NEXT(ldev, ev_link);	}	if (ldev == NULL)		goto done;	/*	 * Try to do as much I/O as possible on this socket.  There are no	 * limits here, currently.	 */	switch (completeio_send(sock, dev, messagehdr, nbytes, send_errno)) {	case DOIO_SOFT:		cc = 0;		send_errno = 0;		io_state = startio_send(sock, dev, &cc, &send_errno);		goto done;	case DOIO_HARD:	case DOIO_SUCCESS:		send_senddone_event(sock, &dev);		break;	} done:	UNLOCK(&sock->lock);}/* * This is the I/O Completion Port Worker Function. It loops forever * waiting for I/O to complete and then forwards them for further * processing. There are a number of these in separate threads. */static isc_threadresult_t WINAPISocketIoThread(LPVOID ThreadContext) {	isc_socketmgr_t *manager = ThreadContext;	BOOL bSuccess = FALSE;	DWORD nbytes;	IoCompletionInfo *lpo = NULL;	isc_socket_t *sock = NULL;	int request;	isc_socketevent_t *dev = NULL;	struct msghdr *messagehdr = NULL;	int errval;	char strbuf[ISC_STRERRORSIZE];	int errstatus;	REQUIRE(VALID_MANAGER(manager));	/*	Set the thread priority high enough so I/O will	 *	preempt normal recv packet processing, but not	 * 	higher than the timer sync thread.	 */	if (!SetThreadPriority(GetCurrentThre

⌨️ 快捷键说明

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