Exemplo n.º 1
0
/*
 * When an attempt at a new connection is noted on a socket
 * which accepts connections, sonewconn is called.  If the
 * connection is possible (subject to space constraints, etc.)
 * then we allocate a new structure, propoerly linked into the
 * data structure of the original socket, and return this.
 * Connstatus may be 0, SS_ISCONFIRMING, or SS_ISCONNECTED.
 */
struct socket *
sonewconn(struct socket *head, int connstatus)
{
	struct socket	*so;
	int		soqueue, error;

	KASSERT(connstatus == 0 || connstatus == SS_ISCONFIRMING ||
	    connstatus == SS_ISCONNECTED);
	KASSERT(solocked(head));

	if ((head->so_options & SO_ACCEPTFILTER) != 0)
		connstatus = 0;
	soqueue = connstatus ? 1 : 0;
	if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2)
		return NULL;
	so = soget(false);
	if (so == NULL)
		return NULL;
	mutex_obj_hold(head->so_lock);
//	so->so_lock = head->so_lock;
	so->so_type = head->so_type;
	so->so_options = head->so_options &~ SO_ACCEPTCONN;
	so->so_linger = head->so_linger;
	so->so_state = head->so_state | SS_NOFDREF;
	so->so_proto = head->so_proto;
	so->so_timeo = head->so_timeo;
#if 0 /* VADIM */
	so->so_pgid = head->so_pgid;
	so->so_send = head->so_send;
	so->so_receive = head->so_receive;
	so->so_uidinfo = head->so_uidinfo;
	so->so_cpid = head->so_cpid;
#else
	so->glueing_block = NULL;
#endif
#ifdef MBUFTRACE
	so->so_mowner = head->so_mowner;
	so->so_rcv.sb_mowner = head->so_rcv.sb_mowner;
	so->so_snd.sb_mowner = head->so_snd.sb_mowner;
#endif
	if (soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat) != 0)
		goto out;
	so->so_snd.sb_lowat = head->so_snd.sb_lowat;
	so->so_rcv.sb_lowat = head->so_rcv.sb_lowat;
	so->so_rcv.sb_timeo = head->so_rcv.sb_timeo;
	so->so_snd.sb_timeo = head->so_snd.sb_timeo;
	so->so_rcv.sb_flags |= head->so_rcv.sb_flags & (SB_AUTOSIZE | SB_ASYNC);
	so->so_snd.sb_flags |= head->so_snd.sb_flags & (SB_AUTOSIZE | SB_ASYNC);
	soqinsque(head, so, soqueue);
	error = (*so->so_proto->pr_usrreq)(so, PRU_ATTACH, NULL, NULL,
	    NULL);
	KASSERT(solocked(so));
	if (error != 0) {
		(void) soqremque(so, soqueue);
out:
		/*
		 * Remove acccept filter if one is present.
		 * XXX Is this really needed?
		 */
#if 0 /*VADIM*/
		if (so->so_accf != NULL)
			(void)accept_filt_clear(so);
#endif
		soput(so);
		return NULL;
	}
	if (connstatus) {
		sorwakeup(head);
#if 0
		cv_broadcast(&head->so_cv);
#endif
		so->so_state |= connstatus;
	}
	return so;
}
Exemplo n.º 2
0
/*
 * sonewconn: accept a new connection.
 *
 * When an attempt at a new connection is noted on a socket which accepts
 * connections, sonewconn(9) is called.  If the connection is possible
 * (subject to space constraints, etc) then we allocate a new structure,
 * properly linked into the data structure of the original socket.
 *
 * => If 'soready' is true, then socket will become ready for accept() i.e.
 *    inserted into the so_q queue, SS_ISCONNECTED set and waiters awoken.
 * => May be called from soft-interrupt context.
 * => Listening socket should be locked.
 * => Returns the new socket locked.
 */
struct socket *
sonewconn(struct socket *head, bool soready)
{
	struct socket *so;
	int soqueue, error;

	KASSERT(solocked(head));

	if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2) {
		/* Listen queue overflow. */
		return NULL;
	}
	if ((head->so_options & SO_ACCEPTFILTER) != 0) {
		soready = false;
	}
	soqueue = soready ? 1 : 0;

	if ((so = soget(false)) == NULL) {
		return NULL;
	}
	so->so_type = head->so_type;
	so->so_options = head->so_options & ~SO_ACCEPTCONN;
	so->so_linger = head->so_linger;
	so->so_state = head->so_state | SS_NOFDREF;
	so->so_proto = head->so_proto;
	so->so_timeo = head->so_timeo;
	so->so_pgid = head->so_pgid;
	so->so_send = head->so_send;
	so->so_receive = head->so_receive;
	so->so_uidinfo = head->so_uidinfo;
	so->so_cpid = head->so_cpid;

	/*
	 * Share the lock with the listening-socket, it may get unshared
	 * once the connection is complete.
	 */
	mutex_obj_hold(head->so_lock);
	so->so_lock = head->so_lock;

	/*
	 * Reserve the space for socket buffers.
	 */
#ifdef MBUFTRACE
	so->so_mowner = head->so_mowner;
	so->so_rcv.sb_mowner = head->so_rcv.sb_mowner;
	so->so_snd.sb_mowner = head->so_snd.sb_mowner;
#endif
	if (soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat)) {
		goto out;
	}
	so->so_snd.sb_lowat = head->so_snd.sb_lowat;
	so->so_rcv.sb_lowat = head->so_rcv.sb_lowat;
	so->so_rcv.sb_timeo = head->so_rcv.sb_timeo;
	so->so_snd.sb_timeo = head->so_snd.sb_timeo;
	so->so_rcv.sb_flags |= head->so_rcv.sb_flags & (SB_AUTOSIZE | SB_ASYNC);
	so->so_snd.sb_flags |= head->so_snd.sb_flags & (SB_AUTOSIZE | SB_ASYNC);

	/*
	 * Finally, perform the protocol attach.  Note: a new socket
	 * lock may be assigned at this point (if so, it will be held).
	 */
	error = (*so->so_proto->pr_usrreqs->pr_attach)(so, 0);
	if (error) {
out:
		KASSERT(solocked(so));
		KASSERT(so->so_accf == NULL);
		soput(so);

		/* Note: the listening socket shall stay locked. */
		KASSERT(solocked(head));
		return NULL;
	}
	KASSERT(solocked2(head, so));

	/*
	 * Insert into the queue.  If ready, update the connection status
	 * and wake up any waiters, e.g. processes blocking on accept().
	 */
	soqinsque(head, so, soqueue);
	if (soready) {
		so->so_state |= SS_ISCONNECTED;
		sorwakeup(head);
		cv_broadcast(&head->so_cv);
	}
	return so;
}