TCP, UNIX sockets: allow multiple calls to listen

* Subsequent calls to listen on an already-listening socket can resize
  the backlog.
* While not explicitly spelled out by POSIX, this behaviour is
  consistent with FreeBSD and Linux.
This commit is contained in:
Hamish Morrison
2015-01-17 19:51:16 +00:00
parent ba483af7de
commit 64f6fcbccd
2 changed files with 27 additions and 22 deletions
@@ -728,9 +728,10 @@ TCPEndpoint::Listen(int count)
MutexLocker _(fLock); MutexLocker _(fLock);
if (fState != CLOSED) if (fState != CLOSED && fState != LISTEN)
return B_BAD_VALUE; return B_BAD_VALUE;
if (fState == CLOSED) {
fAcceptSemaphore = create_sem(0, "tcp accept"); fAcceptSemaphore = create_sem(0, "tcp accept");
if (fAcceptSemaphore < B_OK) if (fAcceptSemaphore < B_OK)
return ENOBUFS; return ENOBUFS;
@@ -741,6 +742,7 @@ TCPEndpoint::Listen(int count)
fAcceptSemaphore = -1; fAcceptSemaphore = -1;
return status; return status;
} }
}
gSocketModule->set_max_backlog(socket, count); gSocketModule->set_max_backlog(socket, count);
@@ -239,11 +239,13 @@ UnixEndpoint::Listen(int backlog)
if (!IsBound()) if (!IsBound())
RETURN_ERROR(EDESTADDRREQ); RETURN_ERROR(EDESTADDRREQ);
if (fState != UNIX_ENDPOINT_NOT_CONNECTED) if (fState != UNIX_ENDPOINT_NOT_CONNECTED
&& fState != UNIX_ENDPOINT_LISTENING)
RETURN_ERROR(EINVAL); RETURN_ERROR(EINVAL);
gSocketModule->set_max_backlog(socket, backlog); gSocketModule->set_max_backlog(socket, backlog);
if (fState == UNIX_ENDPOINT_NOT_CONNECTED) {
fAcceptSemaphore = create_sem(0, "unix accept"); fAcceptSemaphore = create_sem(0, "unix accept");
if (fAcceptSemaphore < 0) if (fAcceptSemaphore < 0)
RETURN_ERROR(ENOBUFS); RETURN_ERROR(ENOBUFS);
@@ -255,6 +257,7 @@ UnixEndpoint::Listen(int backlog)
fCredentials.gid = getegid(); fCredentials.gid = getegid();
fState = UNIX_ENDPOINT_LISTENING; fState = UNIX_ENDPOINT_LISTENING;
}
RETURN_ERROR(B_OK); RETURN_ERROR(B_OK);
} }