Noux: add recvfrom()

Add SYSTEMCALL_RECVFROM to noux/net and the corresponding libc function.

Fixes #290.
This commit is contained in:
Josef Söntgen 2012-06-08 14:24:38 +02:00 committed by Norman Feske
parent d28465cb3a
commit 7e26c79455
6 changed files with 77 additions and 2 deletions

View File

@ -66,6 +66,7 @@ namespace Noux {
SYSCALL_SEND,
SYSCALL_SENDTO,
SYSCALL_RECV,
SYSCALL_RECVFROM,
SYSCALL_GETPEERNAME,
SYSCALL_SHUTDOWN,
SYSCALL_CONNECT,
@ -108,6 +109,7 @@ namespace Noux {
NOUX_DECL_SYSCALL_NAME(SEND)
NOUX_DECL_SYSCALL_NAME(SENDTO)
NOUX_DECL_SYSCALL_NAME(RECV)
NOUX_DECL_SYSCALL_NAME(RECVFROM)
NOUX_DECL_SYSCALL_NAME(GETPEERNAME)
NOUX_DECL_SYSCALL_NAME(SHUTDOWN)
NOUX_DECL_SYSCALL_NAME(CONNECT)

View File

@ -380,6 +380,10 @@ namespace Noux {
SYSIO_DECL(recv, { int fd; Chunk buf; size_t len; int flags; },
{ size_t len; });
SYSIO_DECL(recvfrom, { int fd; Chunk buf; size_t len; int flags;
struct sockaddr src_addr; socklen_t addrlen; },
{ size_t len; });
SYSIO_DECL(shutdown, { int fd; int how; }, { });
SYSIO_DECL(connect, { int fd; struct sockaddr addr; socklen_t addrlen; },

View File

@ -583,6 +583,8 @@ namespace {
ssize_t sendto(Libc::File_descriptor *, const void *, size_t, int,
const struct sockaddr *, socklen_t);
ssize_t recv(Libc::File_descriptor *, void *, ::size_t, int);
ssize_t recvfrom(Libc::File_descriptor *, void *, ::size_t, int,
struct sockaddr *, socklen_t*);
int getsockopt(Libc::File_descriptor *, int, int, void *,
socklen_t *);
int setsockopt(Libc::File_descriptor *, int , int , const void *,
@ -1324,9 +1326,9 @@ namespace {
return -1;
}
Genode::memcpy(buf, sysio()->recv_in.buf, sysio()->recv_in.len);
Genode::memcpy(buf, sysio()->recv_in.buf, sysio()->recv_out.len);
sum_recv_count += sysio()->recv_in.len;
sum_recv_count += sysio()->recv_out.len;
if (sysio()->recv_out.len < sysio()->recv_in.len)
break;
@ -1341,6 +1343,50 @@ namespace {
}
ssize_t Plugin::recvfrom(Libc::File_descriptor *fd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen)
{
Genode::size_t sum_recvfrom_count = 0;
while (len) {
Genode::size_t curr_len = Genode::min(len, sizeof(sysio()->recvfrom_in.buf));
sysio()->recv_in.fd = noux_fd(fd->context);
sysio()->recv_in.len = curr_len;
if (addrlen == NULL)
sysio()->recvfrom_in.addrlen = 0;
else
sysio()->recvfrom_in.addrlen = *addrlen;
if (!noux()->syscall(Noux::Session::SYSCALL_RECVFROM)) {
/* XXX set errno */
return -1;
}
if (src_addr != NULL && addrlen != NULL)
Genode::memcpy(src_addr, &sysio()->recvfrom_in.src_addr,
sysio()->recvfrom_in.addrlen);
Genode::memcpy(buf, sysio()->recvfrom_in.buf, sysio()->recvfrom_out.len);
sum_recvfrom_count += sysio()->recvfrom_out.len;
if (sysio()->recvfrom_out.len < sysio()->recvfrom_in.len)
break;
if (sysio()->recvfrom_out.len <= len)
len -= sysio()->recvfrom_out.len;
else
break;
}
return sum_recvfrom_count;
}
ssize_t Plugin::send(Libc::File_descriptor *fd, const void *buf, ::size_t len, int flags)
{
/* remember original len for the return value */

View File

@ -483,6 +483,7 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
case SYSCALL_SEND:
case SYSCALL_SENDTO:
case SYSCALL_RECV:
case SYSCALL_RECVFROM:
case SYSCALL_GETPEERNAME:
case SYSCALL_SHUTDOWN:
case SYSCALL_CONNECT:

View File

@ -267,6 +267,19 @@ bool Noux::Child::_syscall_net(Noux::Session::Syscall sc)
_sysio->recv_out.len = len;
return true;
}
case SYSCALL_RECVFROM:
{
GET_SOCKET_IO_CHANNEL(_sysio->recvfrom_in.fd, socket_io_channel)
ssize_t len = socket_io_channel->recvfrom(_sysio);
if (len == -1)
return false;
_sysio->recvfrom_out.len = len;
return true;
}
case SYSCALL_GETPEERNAME:

View File

@ -241,6 +241,15 @@ namespace Noux {
sysio->recv_in.flags);
}
ssize_t recvfrom(Sysio *sysio)
{
ssize_t result = ::recvfrom(_socket, sysio->recv_in.buf, sysio->recv_in.len,
sysio->recv_in.flags, (struct sockaddr *)&sysio->recvfrom_in.src_addr,
&sysio->recvfrom_in.addrlen);
return result;
}
ssize_t send(Sysio *sysio)
{
return ::send(_socket, sysio->send_in.buf, sysio->send_in.len,