ng_ksocket: fix accept(2)

- Provide listen upcall and set it on NGM_KSOCKET_LISTEN
- Mask EWOULDBLOCK on NGM_KSOCKET_ACCEPT

Reviewed by:		afedorov
Differential Revision:	https://reviews.freebsd.org/D42637
PR:			272319
PR:			275106
Fixes:			779f106aa1
This commit is contained in:
Gleb Smirnoff 2023-11-17 09:24:30 -08:00
parent efad7cbfdc
commit 43f7e21668

View file

@ -152,6 +152,10 @@ static const struct ng_ksocket_alias ng_ksocket_protos[] = {
/* Helper functions */ /* Helper functions */
static int ng_ksocket_accept(priv_p); static int ng_ksocket_accept(priv_p);
static int ng_ksocket_listen_upcall(struct socket *so, void *arg,
int waitflag);
static void ng_ksocket_listen_upcall2(node_p node, hook_p hook,
void *arg1, int arg2);
static int ng_ksocket_incoming(struct socket *so, void *arg, int waitflag); static int ng_ksocket_incoming(struct socket *so, void *arg, int waitflag);
static int ng_ksocket_parse(const struct ng_ksocket_alias *aliases, static int ng_ksocket_parse(const struct ng_ksocket_alias *aliases,
const char *s, int family); const char *s, int family);
@ -695,6 +699,12 @@ ng_ksocket_rcvmsg(node_p node, item_p item, hook_p lasthook)
/* Listen */ /* Listen */
so->so_state |= SS_NBIO; so->so_state |= SS_NBIO;
error = solisten(so, *((int32_t *)msg->data), td); error = solisten(so, *((int32_t *)msg->data), td);
if (error == 0) {
SOLISTEN_LOCK(so);
solisten_upcall_set(so,
ng_ksocket_listen_upcall, priv);
SOLISTEN_UNLOCK(so);
}
break; break;
} }
@ -715,11 +725,15 @@ ng_ksocket_rcvmsg(node_p node, item_p item, hook_p lasthook)
/* /*
* If a connection is already complete, take it. * If a connection is already complete, take it.
* Otherwise let the upcall function deal with * Otherwise let the upcall function deal with
* the connection when it comes in. * the connection when it comes in. Don't return
* EWOULDBLOCK, per ng_ksocket(4) documentation.
*/ */
error = ng_ksocket_accept(priv); error = ng_ksocket_accept(priv);
if (error != 0 && error != EWOULDBLOCK) if (error == EWOULDBLOCK)
error = 0;
if (error != 0)
ERROUT(error); ERROUT(error);
priv->response_token = msg->header.token; priv->response_token = msg->header.token;
priv->response_addr = NGI_RETADDR(item); priv->response_addr = NGI_RETADDR(item);
break; break;
@ -1064,10 +1078,6 @@ ng_ksocket_incoming2(node_p node, hook_p hook, void *arg1, int arg2)
} }
} }
/* Check whether a pending accept operation has completed */
if (priv->flags & KSF_ACCEPTING)
(void )ng_ksocket_accept(priv);
/* /*
* If we don't have a hook, we must handle data events later. When * If we don't have a hook, we must handle data events later. When
* the hook gets created and is connected, this upcall function * the hook gets created and is connected, this upcall function
@ -1250,6 +1260,25 @@ ng_ksocket_accept(priv_p priv)
return (0); return (0);
} }
static int
ng_ksocket_listen_upcall(struct socket *so, void *arg, int waitflag)
{
priv_p priv = arg;
int wait = ((waitflag & M_WAITOK) ? NG_WAITOK : 0) | NG_QUEUE;
ng_send_fn1(priv->node, NULL, &ng_ksocket_listen_upcall2, priv, 0,
wait);
return (SU_OK);
}
static void
ng_ksocket_listen_upcall2(node_p node, hook_p hook, void *arg1, int arg2)
{
const priv_p priv = NG_NODE_PRIVATE(node);
(void )ng_ksocket_accept(priv);
}
/* /*
* Parse out either an integer value or an alias. * Parse out either an integer value or an alias.
*/ */