summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2020-06-27 01:12:14 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2020-06-27 01:12:14 +0200
commitb290be35e0717ad68d9a851974e7fcfedc88c448 (patch)
tree766fa0c27633c44d8c740b38daa7253f186daf85
parentb95271e96190f0b854b46c8d5b8aab1a812d35a8 (diff)
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.
-rw-r--r--libpipe/pipe.c31
-rw-r--r--libpipe/pipe.h4
-rw-r--r--pflocal/sock.h3
-rw-r--r--pflocal/socket.c84
4 files changed, 108 insertions, 14 deletions
diff --git a/libpipe/pipe.c b/libpipe/pipe.c
index 1d4f5cc0..8ffc56e9 100644
--- a/libpipe/pipe.c
+++ b/libpipe/pipe.c
@@ -200,6 +200,24 @@ void _pipe_no_writers (struct pipe *pipe)
pthread_mutex_unlock (&pipe->lock);
}
}
+
+/* Take any actions necessary when PIPE's writer can proceed.
+ PIPE should be locked. */
+void _pipe_wake_writers (struct pipe *pipe)
+{
+ pthread_cond_broadcast (&pipe->pending_writes);
+ pthread_mutex_unlock (&pipe->lock);
+
+ pthread_mutex_lock (&pipe->lock); /* Get back the lock on PIPE. */
+ /* Only wakeup selects if there's still writing space available. */
+ if (pipe_readable (pipe, 1) < pipe->write_limit)
+ {
+ pthread_cond_broadcast (&pipe->pending_write_selects);
+ pipe_select_cond_broadcast (pipe);
+ /* We leave PIPE locked here, assuming the caller will soon unlock
+ it and allow others access. */
+ }
+}
/* Return when either RPIPE is available for reading (if SELECT_READ is set
in *SELECT_TYPE), or WPIPE is available for writing (if select_write is
@@ -474,18 +492,7 @@ pipe_recv (struct pipe *pipe, int noblock, unsigned *flags, void **source,
timestamp (&pipe->read_time);
/* And wakeup anyone that might be interested in it. */
- pthread_cond_broadcast (&pipe->pending_writes);
- pthread_mutex_unlock (&pipe->lock);
-
- pthread_mutex_lock (&pipe->lock); /* Get back the lock on PIPE. */
- /* Only wakeup selects if there's still writing space available. */
- if (pipe_readable (pipe, 1) < pipe->write_limit)
- {
- pthread_cond_broadcast (&pipe->pending_write_selects);
- pipe_select_cond_broadcast (pipe);
- /* We leave PIPE locked here, assuming the caller will soon unlock
- it and allow others access. */
- }
+ _pipe_wake_writers (pipe);
}
return err;
diff --git a/libpipe/pipe.h b/libpipe/pipe.h
index 040204d5..eda38d24 100644
--- a/libpipe/pipe.h
+++ b/libpipe/pipe.h
@@ -263,6 +263,10 @@ void _pipe_no_readers (struct pipe *pipe);
should be locked. */
void _pipe_no_writers (struct pipe *pipe);
+/* Take any actions necessary when PIPE's writer can proceed.
+ PIPE should be locked. */
+void _pipe_wake_writers (struct pipe *pipe);
+
extern void pipe_acquire_reader (struct pipe *pipe);
extern void pipe_acquire_writer (struct pipe *pipe);
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;
}