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

📄 socket.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
 */static intdoio_send(isc_socket_t *sock, isc_socketevent_t *dev) {	int cc;	struct iovec iov[MAXSCATTERGATHER_SEND];	size_t write_count;	struct msghdr msghdr;	char addrbuf[ISC_SOCKADDR_FORMATSIZE];	int attempts = 0;	int send_errno;	char strbuf[ISC_STRERRORSIZE];	build_msghdr_send(sock, dev, &msghdr, iov, &write_count); resend:	cc = sendmsg(sock->fd, &msghdr, 0);	send_errno = errno;	/*	 * Check for error or block condition.	 */	if (cc < 0) {		if (send_errno == EINTR && ++attempts < NRETRIES)			goto resend;		if (SOFT_ERROR(send_errno))			return (DOIO_SOFT);#define SOFT_OR_HARD(_system, _isc) \	if (send_errno == _system) { \		if (sock->connected) { \			dev->result = _isc; \			return (DOIO_HARD); \		} \		return (DOIO_SOFT); \	}#define ALWAYS_HARD(_system, _isc) \	if (send_errno == _system) { \		dev->result = _isc; \		return (DOIO_HARD); \	}		SOFT_OR_HARD(ECONNREFUSED, ISC_R_CONNREFUSED);		ALWAYS_HARD(EACCES, ISC_R_NOPERM);		ALWAYS_HARD(EAFNOSUPPORT, ISC_R_ADDRNOTAVAIL);		ALWAYS_HARD(EADDRNOTAVAIL, ISC_R_ADDRNOTAVAIL);		ALWAYS_HARD(EHOSTUNREACH, ISC_R_HOSTUNREACH);#ifdef EHOSTDOWN		ALWAYS_HARD(EHOSTDOWN, ISC_R_HOSTUNREACH);#endif		ALWAYS_HARD(ENETUNREACH, ISC_R_NETUNREACH);		ALWAYS_HARD(ENOBUFS, ISC_R_NORESOURCES);		ALWAYS_HARD(EPERM, ISC_R_HOSTUNREACH);		ALWAYS_HARD(EPIPE, ISC_R_NOTCONNECTED);		ALWAYS_HARD(ECONNRESET, ISC_R_CONNECTIONRESET);#undef SOFT_OR_HARD#undef ALWAYS_HARD		/*		 * The other error types depend on whether or not the		 * socket is UDP or TCP.  If it is UDP, some errors		 * that we expect to be fatal under TCP are merely		 * annoying, and are really soft errors.		 *		 * However, these soft errors are still returned as		 * a status.		 */		isc_sockaddr_format(&dev->address, addrbuf, sizeof(addrbuf));		isc__strerror(send_errno, strbuf, sizeof(strbuf));		UNEXPECTED_ERROR(__FILE__, __LINE__, "internal_send: %s: %s",				 addrbuf, strbuf);		dev->result = isc__errno2result(send_errno);		return (DOIO_HARD);	}	if (cc == 0)		UNEXPECTED_ERROR(__FILE__, __LINE__,				 "internal_send: send() %s 0",				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,						ISC_MSG_RETURNED, "returned"));	/*	 * If we write less than we expected, update counters, poke.	 */	dev->n += cc;	if ((size_t)cc != write_count)		return (DOIO_SOFT);	/*	 * Exactly what we wanted to write.  We're done with this	 * entry.  Post its completion event.	 */	dev->result = ISC_R_SUCCESS;	return (DOIO_SUCCESS);}/* * Kill. * * Caller must ensure that the socket is not locked and no external * references exist. */static voiddestroy(isc_socket_t **sockp) {	isc_socket_t *sock = *sockp;	isc_socketmgr_t *manager = sock->manager;	socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,		   ISC_MSG_DESTROYING, "destroying");	INSIST(ISC_LIST_EMPTY(sock->accept_list));	INSIST(ISC_LIST_EMPTY(sock->recv_list));	INSIST(ISC_LIST_EMPTY(sock->send_list));	INSIST(sock->connect_ev == NULL);	REQUIRE(sock->fd >= 0 && sock->fd < (int)FD_SETSIZE);	LOCK(&manager->lock);	/*	 * No one has this socket open, so the watcher doesn't have to be	 * poked, and the socket doesn't have to be locked.	 */	manager->fds[sock->fd] = NULL;	manager->fdstate[sock->fd] = CLOSE_PENDING;	select_poke(manager, sock->fd, SELECT_POKE_CLOSE);	ISC_LIST_UNLINK(manager->socklist, sock, link);#ifdef ISC_PLATFORM_USETHREADS	if (ISC_LIST_EMPTY(manager->socklist))		SIGNAL(&manager->shutdown_ok);#endif /* ISC_PLATFORM_USETHREADS */	/*	 * XXX should reset manager->maxfd here	 */	UNLOCK(&manager->lock);	free_socket(sockp);}static isc_result_tallocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,		isc_socket_t **socketp){	isc_socket_t *sock;	isc_result_t ret;	ISC_SOCKADDR_LEN_T cmsgbuflen;	sock = isc_mem_get(manager->mctx, sizeof(*sock));	if (sock == NULL)		return (ISC_R_NOMEMORY);	ret = ISC_R_UNEXPECTED;	sock->magic = 0;	sock->references = 0;	sock->manager = manager;	sock->type = type;	sock->fd = -1;	ISC_LINK_INIT(sock, link);	sock->recvcmsgbuf = NULL;	sock->sendcmsgbuf = NULL;	/*	 * set up cmsg buffers	 */	cmsgbuflen = 0;#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIPV6)	cmsgbuflen = cmsg_space(sizeof(struct in6_pktinfo));#endif#if defined(USE_CMSG) && defined(SO_TIMESTAMP)	cmsgbuflen += cmsg_space(sizeof(struct timeval));#endif	sock->recvcmsgbuflen = cmsgbuflen;	if (sock->recvcmsgbuflen != 0) {		sock->recvcmsgbuf = isc_mem_get(manager->mctx, cmsgbuflen);		if (sock->recvcmsgbuf == NULL)			goto error;	}	cmsgbuflen = 0;#if defined(USE_CMSG) && defined(ISC_PLATFORM_HAVEIPV6)	cmsgbuflen = cmsg_space(sizeof(struct in6_pktinfo));#endif	sock->sendcmsgbuflen = cmsgbuflen;	if (sock->sendcmsgbuflen != 0) {		sock->sendcmsgbuf = isc_mem_get(manager->mctx, cmsgbuflen);		if (sock->sendcmsgbuf == NULL)			goto error;	}	/*	 * set up list of readers and writers to be initially empty	 */	ISC_LIST_INIT(sock->recv_list);	ISC_LIST_INIT(sock->send_list);	ISC_LIST_INIT(sock->accept_list);	sock->connect_ev = NULL;	sock->pending_recv = 0;	sock->pending_send = 0;	sock->pending_accept = 0;	sock->listener = 0;	sock->connected = 0;	sock->connecting = 0;	sock->bound = 0;	/*	 * initialize the lock	 */	if (isc_mutex_init(&sock->lock) != ISC_R_SUCCESS) {		sock->magic = 0;		UNEXPECTED_ERROR(__FILE__, __LINE__,				 "isc_mutex_init() %s",				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,						ISC_MSG_FAILED, "failed"));		ret = ISC_R_UNEXPECTED;		goto error;	}	/*	 * Initialize readable and writable events	 */	ISC_EVENT_INIT(&sock->readable_ev, sizeof(intev_t),		       ISC_EVENTATTR_NOPURGE, NULL, ISC_SOCKEVENT_INTR,		       NULL, sock, sock, NULL, NULL);	ISC_EVENT_INIT(&sock->writable_ev, sizeof(intev_t),		       ISC_EVENTATTR_NOPURGE, NULL, ISC_SOCKEVENT_INTW,		       NULL, sock, sock, NULL, NULL);	sock->magic = SOCKET_MAGIC;	*socketp = sock;	return (ISC_R_SUCCESS); error:	if (sock->recvcmsgbuf != NULL)		isc_mem_put(manager->mctx, sock->recvcmsgbuf,			    sock->recvcmsgbuflen);	if (sock->sendcmsgbuf != NULL)		isc_mem_put(manager->mctx, sock->sendcmsgbuf,			    sock->sendcmsgbuflen);	isc_mem_put(manager->mctx, sock, sizeof(*sock));	return (ret);}/* * This event requires that the various lists be empty, that the reference * count be 1, and that the magic number is valid.  The other socket bits, * like the lock, must be initialized as well.  The fd associated must be * marked as closed, by setting it to -1 on close, or this routine will * also close the socket. */static voidfree_socket(isc_socket_t **socketp) {	isc_socket_t *sock = *socketp;	INSIST(sock->references == 0);	INSIST(VALID_SOCKET(sock));	INSIST(!sock->connecting);	INSIST(!sock->pending_recv);	INSIST(!sock->pending_send);	INSIST(!sock->pending_accept);	INSIST(ISC_LIST_EMPTY(sock->recv_list));	INSIST(ISC_LIST_EMPTY(sock->send_list));	INSIST(ISC_LIST_EMPTY(sock->accept_list));	INSIST(!ISC_LINK_LINKED(sock, link));	if (sock->recvcmsgbuf != NULL)		isc_mem_put(sock->manager->mctx, sock->recvcmsgbuf,			    sock->recvcmsgbuflen);	if (sock->sendcmsgbuf != NULL)		isc_mem_put(sock->manager->mctx, sock->sendcmsgbuf,			    sock->sendcmsgbuflen);	sock->magic = 0;	DESTROYLOCK(&sock->lock);	isc_mem_put(sock->manager->mctx, sock, sizeof(*sock));	*socketp = NULL;}/* * Create a new 'type' socket managed by 'manager'.  Events * will be posted to 'task' and when dispatched 'action' will be * called with 'arg' as the arg value.  The new socket is returned * in 'socketp'. */isc_result_tisc_socket_create(isc_socketmgr_t *manager, int pf, isc_sockettype_t type,		  isc_socket_t **socketp){	isc_socket_t *sock = NULL;	isc_result_t ret;#if defined(USE_CMSG) || defined(SO_BSDCOMPAT)	int on = 1;#endif	char strbuf[ISC_STRERRORSIZE];	REQUIRE(VALID_MANAGER(manager));	REQUIRE(socketp != NULL && *socketp == NULL);	ret = allocate_socket(manager, type, &sock);	if (ret != ISC_R_SUCCESS)		return (ret);	sock->pf = pf;	switch (type) {	case isc_sockettype_udp:		sock->fd = socket(pf, SOCK_DGRAM, IPPROTO_UDP);		break;	case isc_sockettype_tcp:		sock->fd = socket(pf, SOCK_STREAM, IPPROTO_TCP);		break;	}#ifdef F_DUPFD        /*         * Leave a space for stdio to work in.         */        if (sock->fd >= 0 && sock->fd < 20) {                int new, tmp;                new = fcntl(sock->fd, F_DUPFD, 20);                tmp = errno;                (void)close(sock->fd);                errno = tmp;                sock->fd = new;        }#endif	if (sock->fd >= (int)FD_SETSIZE) {		(void)close(sock->fd);		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", "socket");		free_socket(&sock);		return (ISC_R_NORESOURCES);	}		if (sock->fd < 0) {		free_socket(&sock);		switch (errno) {		case EMFILE:		case ENFILE:		case ENOBUFS:			return (ISC_R_NORESOURCES);		case EPROTONOSUPPORT:		case EPFNOSUPPORT:		case EAFNOSUPPORT:		/*		 * Linux 2.2 (and maybe others) return EINVAL instead of		 * EAFNOSUPPORT.		 */		case EINVAL:			return (ISC_R_FAMILYNOSUPPORT);		default:			isc__strerror(errno, strbuf, sizeof(strbuf));			UNEXPECTED_ERROR(__FILE__, __LINE__,					 "socket() %s: %s",					 isc_msgcat_get(isc_msgcat,							ISC_MSGSET_GENERAL,							ISC_MSG_FAILED,							"failed"),					 strbuf);			return (ISC_R_UNEXPECTED);		}	}	if (make_nonblock(sock->fd) != ISC_R_SUCCESS) {		(void)close(sock->fd);		free_socket(&sock);		return (ISC_R_UNEXPECTED);	}#ifdef SO_BSDCOMPAT	if (setsockopt(sock->fd, SOL_SOCKET, SO_BSDCOMPAT,		       (void *)&on, sizeof(on)) < 0) {		isc__strerror(errno, strbuf, sizeof(strbuf));		UNEXPECTED_ERROR(__FILE__, __LINE__,				 "setsockopt(%d, SO_BSDCOMPAT) %s: %s",				 sock->fd,				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,						ISC_MSG_FAILED, "failed"),				 strbuf);		/* Press on... */	}#endif#if defined(USE_CMSG)	if (type == isc_sockettype_udp) {#if defined(SO_TIMESTAMP)		if (setsockopt(sock->fd, SOL_SOCKET, SO_TIMESTAMP,			       (void *)&on, sizeof(on)) < 0		    && errno != ENOPROTOOPT) {			isc__strerror(errno, strbuf, sizeof(strbuf));			UNEXPECTED_ERROR(__FILE__, __LINE__,					 "setsockopt(%d, SO_TIMESTAMP) %s: %s",					 sock->fd, 					 isc_msgcat_get(isc_msgcat,							ISC_MSGSET_GENERAL,							ISC_MSG_FAILED,							"failed"),					 strbuf);			/* Press on... */		}#endif /* SO_TIMESTAMP */#if defined(ISC_PLATFORM_HAVEIPV6)		if (pf == AF_INET6 && sock->recvcmsgbuflen == 0) {			/*			 * Warn explicitly because this anomaly can be hidden			 * in usual operation (and unexpectedly appear later).			 */			UNEXPECTED_ERROR(__FILE__, __LINE__,					 "No buffer available to receive "					 "IPv6 destination");		}#ifdef IPV6_RECVPKTINFO		/* 2292bis */		if ((pf == AF_INET6)		    && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,				   (void *)&on, sizeof(on)) < 0)) {			isc__strerror(errno, strbuf, sizeof(strbuf));			UNEXPECTED_ERROR(__FILE__, __LINE__,					 "setsockopt(%d, IPV6_RECVPKTINFO) "					 "%s: %s", sock->fd,					 isc_msgcat_get(isc_msgcat,							ISC_MSGSET_GENERAL,							ISC_MSG_FAILED,							"failed"),					 strbuf);		}#else		/* 2292 */		if ((pf == AF_INET6)		    && (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_PKTINFO,				   (void *)&on, sizeof(on)) < 0)) {			isc__strerror(errno, strbuf, sizeof(strbuf));			UNEXPECTED_ERROR(__FILE__, __LINE__,					 "setsockopt(%d, IPV6_PKTINFO) %s: %s",					 sock->fd,					 isc_msgcat_get(isc_msgcat,							ISC_MSGSET_GENERAL,							ISC_MSG_FAILED,							"failed"),					 strbuf);		}#endif /* IPV6_RECVPKTINFO */#ifdef IPV6_USE_MIN_MTU        /*2292bis, not too common yet*/		/* use minimum MTU */		if (pf == AF_INET6) {			(void)setsockopt(sock->fd, IPPROTO_IPV6,					 IPV6_USE_MIN_MTU,					 (void *)&on, sizeof(on));		}#endif#endif /* ISC_PLATFORM_HAVEIPV6 */	}#endif /* USE_CMSG */	sock->references = 1;	*socketp = sock;	LOCK(&manager->lock);	/*	 * Note we don't have to lock the socket like we normally would because	 * there are no external references to it yet.	 */	manager->fds[sock->fd] = sock;	manager->fdstate[sock->fd] = MANAGED;	ISC_LIST_APPEND(manager->socklist, sock, link);	if (manager->maxfd < sock->fd)		manager->maxfd = sock->fd;	UNLOCK(&manager->lock);	socket_log(sock, NULL, CREATION, isc_msgcat, ISC_MSGSET_SOCKET,		   ISC_MSG_CREATED, "created");	return (ISC_R_SUCCESS);}/* * Attach to a socket.  Caller must explicitly detach when it is done. */voidisc_socket_attach(isc_socket_t *sock, isc_socket_t **socketp) {	REQUIRE(VALID_SOCKET(sock));	REQUIRE(socketp != NULL && *socketp == NULL);	LOCK(&sock->lock);	sock->references++;	UNLOCK(&sock->lock);	*socketp = sock;}/* * Dereference a socket.  If this is the last reference to it, clean things * up by destroying the socket. */voidisc_socket_detach(isc_socket_t **socketp) {	isc_socket_t *sock;	isc_boolean_t kill_socket = ISC_FALSE;	REQUIRE(socketp != NULL);

⌨️ 快捷键说明

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