FreeBSD/sys/netgraph/ng_ksocket.c
/*
 * When incoming data is appended to the socket, we get notified here.
 * This is also called whenever a significant event occurs for the socket.
 * Our original caller may have queued this even some time ago and
 * we cannot trust that he even still exists. The node however is being
 * held with a reference by the queueing code and guarantied to be valid.
 */
When incoming data is appended to the socket, we get notified here.
This is also called whenever a significant event occurs for the socket.
Our original caller may have queued this even some time ago and
we cannot trust that he even still exists. The node however is being
held with a reference by the queueing code and guarantied to be valid.
When incoming data is appended to the socket we get notified here . This is also called whenever a significant event occurs for the socket . Our original caller may have queued this even some time ago and we cannot trust that he even still exists . The node however is being held with a reference by the queueing code and guarantied to be valid .
static void
ng_ksocket_incoming2(node_p node, hook_p hook, void *arg1, int arg2)
{
	struct socket *so = arg1;
	const priv_p priv = NG_NODE_PRIVATE(node);
	struct ng_mesg *response;
	int error;
	KASSERT(so == priv->so, ("%s: wrong socket", __func__));
	atomic_store_rel_int(&priv->fn_sent, 0);
	if (priv->flags & KSF_CONNECTING) {
		if ((error = so->so_error) != 0) {
			so->so_error = 0;
			so->so_state &= ~SS_ISCONNECTING;
		}
		if (!(so->so_state & SS_ISCONNECTING)) {
			NG_MKMESSAGE(response, NGM_KSOCKET_COOKIE,
			    NGM_KSOCKET_CONNECT, sizeof(int32_t), M_NOWAIT);
			if (response != NULL) {
				response->header.flags |= NGF_RESP;
				response->header.token = priv->response_token;
				*(int32_t *)response->data = error;
				NG_SEND_MSG_ID(error, node,
				    response, priv->response_addr, 0);
			}
			priv->flags &= ~KSF_CONNECTING;
		}
	}
	if (priv->flags & KSF_ACCEPTING) {
		error = ng_ksocket_check_accept(priv);
		if (error != EWOULDBLOCK)
			priv->flags &= ~KSF_ACCEPTING;
		if (error == 0)
			ng_ksocket_finish_accept(priv);
	}
	if (priv->hook == NULL)
		return;
	while (1) {
		struct uio uio;
		struct sockaddr *sa;
		struct mbuf *m;
		int flags;
		uio.uio_td = NULL;
		uio.uio_resid = IP_MAXPACKET;
		flags = MSG_DONTWAIT;
		sa = NULL;
		if ((error = soreceive(so, (so->so_state & SS_ISCONNECTED) ?
		    NULL : &sa, &uio, &m, NULL, &flags)) != 0)
			break;
		if (flags & MSG_TRUNC) {
			m_freem(m);
			m = NULL;
		}
		if (m == NULL) {
			if (sa != NULL)
				free(sa, M_SONAME);
			break;
		}
		KASSERT(m->m_nextpkt == NULL, ("%s: nextpkt", __func__));
		if (so->so_type == SOCK_STREAM) {
			struct mbuf *mh;
			mh = m_gethdr(M_NOWAIT, MT_DATA);
			if (mh == NULL) {
				m_freem(m);
				if (sa != NULL)
					free(sa, M_SONAME);
				break;
			}
			mh->m_next = m;
			for (; m; m = m->m_next)
				mh->m_pkthdr.len += m->m_len;
			m = mh;
		}
		if (sa != NULL) {
			struct sa_tag	*stag;
			stag = (struct sa_tag *)m_tag_alloc(NGM_KSOCKET_COOKIE,
			    NG_KSOCKET_TAG_SOCKADDR, sizeof(ng_ID_t) +
			    sa->sa_len, M_NOWAIT);
			if (stag == NULL) {
				free(sa, M_SONAME);
				goto sendit;
			}
			bcopy(sa, &stag->sa, sa->sa_len);
			free(sa, M_SONAME);
			stag->id = NG_NODE_ID(node);
			m_tag_prepend(m, &stag->tag);
		}
sendit:		
		NG_SEND_DATA_ONLY(error, priv->hook, m);
	}
	if (so->so_rcv.sb_state & SBS_CANTRCVMORE &&
	    !(priv->flags & KSF_EOFSEEN)) {
		struct mbuf *m;
		m = m_gethdr(M_NOWAIT, MT_DATA);
		if (m != NULL)
			NG_SEND_DATA_ONLY(error, priv->hook, m);
		priv->flags |= KSF_EOFSEEN;
	}
}
static void ng_ksocket_incoming2 ( node_p node , hook_p hook , void * arg1 , int arg2 ) { struct socket * so = arg1 ; const priv_p priv = NG_NODE_PRIVATE ( node ) ; struct ng_mesg * response ; int error ; KASSERT ( so == priv -> so , ( " " , __func__ ) ) ; atomic_store_rel_int ( & priv -> fn_sent , 0 ) ; if ( priv -> flags & KSF_CONNECTING ) { if ( ( error = so -> so_error ) != 0 ) { so -> so_error = 0 ; so -> so_state &= ~ SS_ISCONNECTING ; } if ( ! ( so -> so_state & SS_ISCONNECTING ) ) { NG_MKMESSAGE ( response , NGM_KSOCKET_COOKIE , NGM_KSOCKET_CONNECT , sizeof ( int32_t ) , M_NOWAIT ) ; if ( response != NULL ) { response -> header . flags |= NGF_RESP ; response -> header . token = priv -> response_token ; * ( int32_t * ) response -> data = error ; NG_SEND_MSG_ID ( error , node , response , priv -> response_addr , 0 ) ; } priv -> flags &= ~ KSF_CONNECTING ; } } if ( priv -> flags & KSF_ACCEPTING ) { error = ng_ksocket_check_accept ( priv ) ; if ( error != EWOULDBLOCK ) priv -> flags &= ~ KSF_ACCEPTING ; if ( error == 0 ) ng_ksocket_finish_accept ( priv ) ; } if ( priv -> hook == NULL ) return ; while ( 1 ) { struct uio uio ; struct sockaddr * sa ; struct mbuf * m ; int flags ; uio . uio_td = NULL ; uio . uio_resid = IP_MAXPACKET ; flags = MSG_DONTWAIT ; sa = NULL ; if ( ( error = soreceive ( so , ( so -> so_state & SS_ISCONNECTED ) ? NULL : & sa , & uio , & m , NULL , & flags ) ) != 0 ) break ; if ( flags & MSG_TRUNC ) { m_freem ( m ) ; m = NULL ; } if ( m == NULL ) { if ( sa != NULL ) free ( sa , M_SONAME ) ; break ; } KASSERT ( m -> m_nextpkt == NULL , ( " " , __func__ ) ) ; if ( so -> so_type == SOCK_STREAM ) { struct mbuf * mh ; mh = m_gethdr ( M_NOWAIT , MT_DATA ) ; if ( mh == NULL ) { m_freem ( m ) ; if ( sa != NULL ) free ( sa , M_SONAME ) ; break ; } mh -> m_next = m ; for ( ; m ; m = m -> m_next ) mh -> m_pkthdr . len += m -> m_len ; m = mh ; } if ( sa != NULL ) { struct sa_tag * stag ; stag = ( struct sa_tag * ) m_tag_alloc ( NGM_KSOCKET_COOKIE , NG_KSOCKET_TAG_SOCKADDR , sizeof ( ng_ID_t ) + sa -> sa_len , M_NOWAIT ) ; if ( stag == NULL ) { free ( sa , M_SONAME ) ; goto sendit ; } bcopy ( sa , & stag -> sa , sa -> sa_len ) ; free ( sa , M_SONAME ) ; stag -> id = NG_NODE_ID ( node ) ; m_tag_prepend ( m , & stag -> tag ) ; } sendit : NG_SEND_DATA_ONLY ( error , priv -> hook , m ) ; } if ( so -> so_rcv . sb_state & SBS_CANTRCVMORE && ! ( priv -> flags & KSF_EOFSEEN ) ) { struct mbuf * m ; m = m_gethdr ( M_NOWAIT , MT_DATA ) ; if ( m != NULL ) NG_SEND_DATA_ONLY ( error , priv -> hook , m ) ; priv -> flags |= KSF_EOFSEEN ; } }
When incoming data is appended to the socket, we get notified here.
When incoming data is appended to the socket we get notified here .
/* Allow next incoming event to be queued. */ /* Check whether a pending connect operation has completed */ /*
				 * send an async "response" message
				 * to the node that set us up
				 * (if it still exists)
				 */ /* Check whether a pending accept operation has completed */ /*
	 * If we don't have a hook, we must handle data events later.  When
	 * the hook gets created and is connected, this upcall function
	 * will be called again.
	 */ /* Read and forward available mbufs. */ /* Try to get next packet from socket. */ /* See if we got anything. */ /*
		 * Stream sockets do not have packet boundaries, so
		 * we have to allocate a header mbuf and attach the
		 * stream of data to it.
		 */ /* Put peer's socket address (if any) into a tag */ /* Forward data with optional peer sockaddr as packet tag */ /*
	 * If the peer has closed the connection, forward a 0-length mbuf
	 * to indicate end-of-file.
	 */