Пример #1
0
int
ofp_accept(int sockfd, struct ofp_sockaddr *addr, ofp_socklen_t *addrlen)
{
	struct ofp_sockaddr *sa = NULL;
	struct socket *so, *head = ofp_get_sock_by_fd(sockfd);
	if (!head) {
		ofp_errno = OFP_EBADF;
		return -1;
	}

	if ((head->so_options & OFP_SO_ACCEPTCONN) == 0) {
		ofp_errno = OFP_EINVAL;
		return -1;
	}

	ACCEPT_LOCK();
	if ((head->so_state & SS_NBIO) && OFP_TAILQ_EMPTY(&head->so_comp)) {
		ACCEPT_UNLOCK();
		ofp_errno = OFP_EWOULDBLOCK;
		return -1;
	}

	while (OFP_TAILQ_EMPTY(&head->so_comp) && head->so_error == 0) {
		if (head->so_rcv.sb_state & SBS_CANTRCVMORE) {
			head->so_error = OFP_ECONNABORTED;
			break;
		}
		if (ofp_msleep(&head->so_timeo, ofp_accept_mtx(), 0,
				 "accept", 0)) {
			ACCEPT_UNLOCK();
			return -1;
		}
	}

	if (head->so_error) {
		ofp_errno = head->so_error;
		head->so_error = 0;
		ACCEPT_UNLOCK();
		return -1;
	}
	so = OFP_TAILQ_FIRST(&head->so_comp);
	KASSERT(!(so->so_qstate & SQ_INCOMP), ("accept1: so SQ_INCOMP"));
	KASSERT(so->so_qstate & SQ_COMP, ("accept1: so not SQ_COMP"));

	/*
	 * Before changing the flags on the socket, we have to bump the
	 * reference count.  Otherwise, if the protocol calls ofp_sofree(),
	 * the socket will be released due to a zero refcount.
	 */
	OFP_SOCK_LOCK(so);			/* soref() and so_state update */
	soref(so);			/* file descriptor reference */

	OFP_TAILQ_REMOVE(&head->so_comp, so, so_list);
	head->so_qlen--;
	so->so_state |= (head->so_state & SS_NBIO);
	so->so_qstate &= ~SQ_COMP;
	so->so_head = NULL;

	OFP_SOCK_UNLOCK(so);
	ACCEPT_UNLOCK();

	/* connection has been removed from the listen queue */
	/*KNOTE_UNLOCKED(&head->so_rcv.sb_sel.si_note, 0);*/

	sa = 0;
	ofp_errno = ofp_soaccept(so, &sa);
	if (ofp_errno) {
		/*
		 * return a namelen of zero for older code which might
		 * ignore the return value from accept.
		 */
		if (addr)
			*addrlen = 0;
		return -1;
	}

	if (sa == NULL) {
		if (addr)
			*addrlen = 0;
		return so->so_number;
	}

	if (addr) {
		/* check sa_len before it is destroyed */
		if (*addrlen > sa->sa_len)
			*addrlen = sa->sa_len;
		memcpy(addr, sa, *addrlen);
	}

	free(sa);
	return so->so_number;
}
Пример #2
0
static inline int
is_accepting_socket_readable(struct socket *so)
{
	return !(OFP_TAILQ_EMPTY(&so->so_comp));
}