Commit 71092ea1 authored by Allan Stephens's avatar Allan Stephens Committed by Paul Gortmaker

tipc: Add support for SO_RCVTIMEO socket option

Adds support for the SO_RCVTIMEO socket option to TIPC's socket
receive routines.

Thanks go out to Raj Hegde <rajenhegde@yahoo.ca> for his contribution
to the development and testing this enhancement.
Signed-off-by: default avatarAllan Stephens <Allan.Stephens@windriver.com>
Signed-off-by: default avatarPaul Gortmaker <paul.gortmaker@windriver.com>
parent f1379173
...@@ -58,6 +58,9 @@ struct tipc_sock { ...@@ -58,6 +58,9 @@ struct tipc_sock {
#define tipc_sk(sk) ((struct tipc_sock *)(sk)) #define tipc_sk(sk) ((struct tipc_sock *)(sk))
#define tipc_sk_port(sk) ((struct tipc_port *)(tipc_sk(sk)->p)) #define tipc_sk_port(sk) ((struct tipc_port *)(tipc_sk(sk)->p))
#define tipc_rx_ready(sock) (!skb_queue_empty(&sock->sk->sk_receive_queue) || \
(sock->state == SS_DISCONNECTING))
static int backlog_rcv(struct sock *sk, struct sk_buff *skb); static int backlog_rcv(struct sock *sk, struct sk_buff *skb);
static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf); static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf);
static void wakeupdispatch(struct tipc_port *tport); static void wakeupdispatch(struct tipc_port *tport);
...@@ -911,6 +914,7 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, ...@@ -911,6 +914,7 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock,
struct tipc_port *tport = tipc_sk_port(sk); struct tipc_port *tport = tipc_sk_port(sk);
struct sk_buff *buf; struct sk_buff *buf;
struct tipc_msg *msg; struct tipc_msg *msg;
long timeout;
unsigned int sz; unsigned int sz;
u32 err; u32 err;
int res; int res;
...@@ -927,6 +931,7 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, ...@@ -927,6 +931,7 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock,
goto exit; goto exit;
} }
timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
restart: restart:
/* Look for a message in receive queue; wait if necessary */ /* Look for a message in receive queue; wait if necessary */
...@@ -936,17 +941,15 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, ...@@ -936,17 +941,15 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock,
res = -ENOTCONN; res = -ENOTCONN;
goto exit; goto exit;
} }
if (flags & MSG_DONTWAIT) { if (timeout <= 0L) {
res = -EWOULDBLOCK; res = timeout ? timeout : -EWOULDBLOCK;
goto exit; goto exit;
} }
release_sock(sk); release_sock(sk);
res = wait_event_interruptible(*sk_sleep(sk), timeout = wait_event_interruptible_timeout(*sk_sleep(sk),
(!skb_queue_empty(&sk->sk_receive_queue) || tipc_rx_ready(sock),
(sock->state == SS_DISCONNECTING))); timeout);
lock_sock(sk); lock_sock(sk);
if (res)
goto exit;
} }
/* Look at first message in receive queue */ /* Look at first message in receive queue */
...@@ -1034,6 +1037,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, ...@@ -1034,6 +1037,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
struct tipc_port *tport = tipc_sk_port(sk); struct tipc_port *tport = tipc_sk_port(sk);
struct sk_buff *buf; struct sk_buff *buf;
struct tipc_msg *msg; struct tipc_msg *msg;
long timeout;
unsigned int sz; unsigned int sz;
int sz_to_copy, target, needed; int sz_to_copy, target, needed;
int sz_copied = 0; int sz_copied = 0;
...@@ -1054,7 +1058,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, ...@@ -1054,7 +1058,7 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
} }
target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len);
timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
restart: restart:
/* Look for a message in receive queue; wait if necessary */ /* Look for a message in receive queue; wait if necessary */
...@@ -1064,17 +1068,15 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, ...@@ -1064,17 +1068,15 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock,
res = -ENOTCONN; res = -ENOTCONN;
goto exit; goto exit;
} }
if (flags & MSG_DONTWAIT) { if (timeout <= 0L) {
res = -EWOULDBLOCK; res = timeout ? timeout : -EWOULDBLOCK;
goto exit; goto exit;
} }
release_sock(sk); release_sock(sk);
res = wait_event_interruptible(*sk_sleep(sk), timeout = wait_event_interruptible_timeout(*sk_sleep(sk),
(!skb_queue_empty(&sk->sk_receive_queue) || tipc_rx_ready(sock),
(sock->state == SS_DISCONNECTING))); timeout);
lock_sock(sk); lock_sock(sk);
if (res)
goto exit;
} }
/* Look at first message in receive queue */ /* Look at first message in receive queue */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment