diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2020-06-27 01:12:14 +0200 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2020-06-27 01:12:14 +0200 |
commit | b290be35e0717ad68d9a851974e7fcfedc88c448 (patch) | |
tree | 766fa0c27633c44d8c740b38daa7253f186daf85 /pflocal | |
parent | b95271e96190f0b854b46c8d5b8aab1a812d35a8 (diff) | |
download | hurd-b290be35e0717ad68d9a851974e7fcfedc88c448.tar.gz hurd-b290be35e0717ad68d9a851974e7fcfedc88c448.tar.bz2 hurd-b290be35e0717ad68d9a851974e7fcfedc88c448.zip |
pflocal: Add support for setsockopt(SO_{RECV,SND}BUF)
Thanks Svante Signell for the initial patch.
* libpipe/pipe.c (pipe_recv): Move writer wake code to...
(_pipe_wake_writers): ... new function.
* libpipe/pipe.h (_pipe_wake_writers): New prototype.
* pflocal/sock.h (PFLOCAL_WRITE_LIMIT_MAX): New macro.
* pflocal/socket.c (S_socket_setopt): Handle SO_RCVBUF and SO_SNDBUF cases.
Diffstat (limited to 'pflocal')
-rw-r--r-- | pflocal/sock.h | 3 | ||||
-rw-r--r-- | pflocal/socket.c | 84 |
2 files changed, 85 insertions, 2 deletions
diff --git a/pflocal/sock.h b/pflocal/sock.h index 011b91a3..dca16755 100644 --- a/pflocal/sock.h +++ b/pflocal/sock.h @@ -187,4 +187,7 @@ error_t sock_global_shutdown (); extern struct port_class *sock_user_port_class; extern struct port_class *addr_port_class; +/* Maximum allowed size for libpipe buffers */ +#define PFLOCAL_WRITE_LIMIT_MAX (1024*1024) + #endif /* __SOCK_H__ */ diff --git a/pflocal/socket.c b/pflocal/socket.c index 7a856bec..65503bc0 100644 --- a/pflocal/socket.c +++ b/pflocal/socket.c @@ -525,18 +525,98 @@ S_socket_setopt (struct sock_user *user, int level, int opt, data_t value, size_t value_len) { int ret = 0; + struct pipe *pipe; + struct sock *sock; if (!user) return EOPNOTSUPP; - pthread_mutex_lock (&user->sock->lock); + sock = user->sock; + + pthread_mutex_lock (&sock->lock); switch (level) { + case SOL_SOCKET: + switch (opt) + { + case SO_RCVBUF: + { + int new, old; + + if (value_len < sizeof (int)) + { + ret = EINVAL; + break; + } + new = *(int *)value; + if (new <= 0) + { + ret = EINVAL; + break; + } + if (new > PFLOCAL_WRITE_LIMIT_MAX) + new = PFLOCAL_WRITE_LIMIT_MAX; + + pipe = sock->read_pipe; + if (!pipe) + { + ret = EPIPE; + break; + } + + pthread_mutex_lock (&pipe->lock); + old = pipe->write_limit; + pipe->write_limit = new; + if (new > old) + _pipe_wake_writers (pipe); + pthread_mutex_unlock (&pipe->lock); + break; + } + + case SO_SNDBUF: + { + int new, old; + + if (value_len < sizeof (int)) + { + ret = EINVAL; + break; + } + new = *(int *)value; + if (new <= 0) + { + ret = EINVAL; + break; + } + if (new > PFLOCAL_WRITE_LIMIT_MAX) + new = PFLOCAL_WRITE_LIMIT_MAX; + + pipe = sock->read_pipe; + if (!pipe) + { + ret = EPIPE; + break; + } + + pthread_mutex_lock (&pipe->lock); + old = pipe->write_limit; + pipe->write_limit = new; + if (new > old) + _pipe_wake_writers (pipe); + pthread_mutex_unlock (&pipe->lock); + break; + } + + default: + ret = ENOPROTOOPT; + break; + } + break; default: ret = ENOPROTOOPT; break; } - pthread_mutex_unlock (&user->sock->lock); + pthread_mutex_unlock (&sock->lock); return ret; } |