[DCCP]: Rewrite dccp_sendmsg to be more like UDP
Based on discussions with Nishida-san. Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
7690af3fff
commit
531669a0a9
226
net/dccp/proto.c
226
net/dccp/proto.c
@@ -214,197 +214,101 @@ out_discard:
|
|||||||
goto out_release;
|
goto out_release;
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(dccp_sendmsg);
|
|
||||||
|
|
||||||
int dccp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
int dccp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
|
||||||
size_t len, int nonblock, int flags, int *addr_len)
|
size_t len, int nonblock, int flags, int *addr_len)
|
||||||
{
|
{
|
||||||
const struct dccp_hdr *dh;
|
const struct dccp_hdr *dh;
|
||||||
int copied = 0;
|
|
||||||
unsigned long used;
|
|
||||||
int err;
|
|
||||||
int target; /* Read at least this many bytes */
|
|
||||||
long timeo;
|
long timeo;
|
||||||
|
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
|
|
||||||
err = -ENOTCONN;
|
if (sk->sk_state == DCCP_LISTEN) {
|
||||||
if (sk->sk_state == DCCP_LISTEN)
|
len = -ENOTCONN;
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
timeo = sock_rcvtimeo(sk, nonblock);
|
timeo = sock_rcvtimeo(sk, nonblock);
|
||||||
|
|
||||||
/* Urgent data needs to be handled specially. */
|
|
||||||
if (flags & MSG_OOB)
|
|
||||||
goto recv_urg;
|
|
||||||
|
|
||||||
/* FIXME */
|
|
||||||
#if 0
|
|
||||||
seq = &tp->copied_seq;
|
|
||||||
if (flags & MSG_PEEK) {
|
|
||||||
peek_seq = tp->copied_seq;
|
|
||||||
seq = &peek_seq;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb = skb_peek(&sk->sk_receive_queue);
|
||||||
u32 offset;
|
|
||||||
|
|
||||||
/* FIXME */
|
if (skb == NULL)
|
||||||
#if 0
|
goto verify_sock_status;
|
||||||
/*
|
|
||||||
* Are we at urgent data? Stop if we have read anything or
|
dh = dccp_hdr(skb);
|
||||||
* have SIGURG pending.
|
|
||||||
*/
|
if (dh->dccph_type == DCCP_PKT_DATA ||
|
||||||
if (tp->urg_data && tp->urg_seq == *seq) {
|
dh->dccph_type == DCCP_PKT_DATAACK)
|
||||||
if (copied)
|
goto found_ok_skb;
|
||||||
break;
|
|
||||||
if (signal_pending(current)) {
|
if (dh->dccph_type == DCCP_PKT_RESET ||
|
||||||
copied = timeo ? sock_intr_errno(timeo) :
|
dh->dccph_type == DCCP_PKT_CLOSE) {
|
||||||
-EAGAIN;
|
dccp_pr_debug("found fin ok!\n");
|
||||||
break;
|
len = 0;
|
||||||
}
|
goto found_fin_ok;
|
||||||
}
|
}
|
||||||
#endif
|
dccp_pr_debug("packet_type=%s\n",
|
||||||
|
dccp_packet_name(dh->dccph_type));
|
||||||
/* Next get a buffer. */
|
sk_eat_skb(sk, skb);
|
||||||
|
verify_sock_status:
|
||||||
skb = skb_peek(&sk->sk_receive_queue);
|
if (sock_flag(sk, SOCK_DONE)) {
|
||||||
do {
|
len = 0;
|
||||||
if (!skb)
|
|
||||||
break;
|
|
||||||
|
|
||||||
offset = 0;
|
|
||||||
dh = dccp_hdr(skb);
|
|
||||||
|
|
||||||
if (dh->dccph_type == DCCP_PKT_DATA ||
|
|
||||||
dh->dccph_type == DCCP_PKT_DATAACK)
|
|
||||||
goto found_ok_skb;
|
|
||||||
|
|
||||||
if (dh->dccph_type == DCCP_PKT_RESET ||
|
|
||||||
dh->dccph_type == DCCP_PKT_CLOSE) {
|
|
||||||
dccp_pr_debug("found fin ok!\n");
|
|
||||||
goto found_fin_ok;
|
|
||||||
}
|
|
||||||
dccp_pr_debug("packet_type=%s\n",
|
|
||||||
dccp_packet_name(dh->dccph_type));
|
|
||||||
BUG_TRAP(flags & MSG_PEEK);
|
|
||||||
skb = skb->next;
|
|
||||||
} while (skb != (struct sk_buff *)&sk->sk_receive_queue);
|
|
||||||
|
|
||||||
/* Well, if we have backlog, try to process it now yet. */
|
|
||||||
if (copied >= target && !sk->sk_backlog.tail)
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (copied) {
|
|
||||||
if (sk->sk_err ||
|
|
||||||
sk->sk_state == DCCP_CLOSED ||
|
|
||||||
(sk->sk_shutdown & RCV_SHUTDOWN) ||
|
|
||||||
!timeo ||
|
|
||||||
signal_pending(current) ||
|
|
||||||
(flags & MSG_PEEK))
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
if (sock_flag(sk, SOCK_DONE))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (sk->sk_err) {
|
|
||||||
copied = sock_error(sk);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sk->sk_shutdown & RCV_SHUTDOWN)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (sk->sk_state == DCCP_CLOSED) {
|
|
||||||
if (!sock_flag(sk, SOCK_DONE)) {
|
|
||||||
/* This occurs when user tries to read
|
|
||||||
* from never connected socket.
|
|
||||||
*/
|
|
||||||
copied = -ENOTCONN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!timeo) {
|
|
||||||
copied = -EAGAIN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (signal_pending(current)) {
|
|
||||||
copied = sock_intr_errno(timeo);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: cleanup_rbuf(sk, copied); */
|
if (sk->sk_err) {
|
||||||
|
len = sock_error(sk);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (copied >= target) {
|
if (sk->sk_shutdown & RCV_SHUTDOWN) {
|
||||||
/* Do not sleep, just process backlog. */
|
len = 0;
|
||||||
release_sock(sk);
|
break;
|
||||||
lock_sock(sk);
|
}
|
||||||
} else
|
|
||||||
sk_wait_data(sk, &timeo);
|
|
||||||
|
|
||||||
|
if (sk->sk_state == DCCP_CLOSED) {
|
||||||
|
if (!sock_flag(sk, SOCK_DONE)) {
|
||||||
|
/* This occurs when user tries to read
|
||||||
|
* from never connected socket.
|
||||||
|
*/
|
||||||
|
len = -ENOTCONN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
len = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!timeo) {
|
||||||
|
len = -EAGAIN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signal_pending(current)) {
|
||||||
|
len = sock_intr_errno(timeo);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sk_wait_data(sk, &timeo);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
found_ok_skb:
|
found_ok_skb:
|
||||||
/* Ok so how much can we use? */
|
if (len > skb->len)
|
||||||
used = skb->len - offset;
|
len = skb->len;
|
||||||
if (len < used)
|
else if (len < skb->len)
|
||||||
used = len;
|
msg->msg_flags |= MSG_TRUNC;
|
||||||
|
|
||||||
if (!(flags & MSG_TRUNC)) {
|
if (skb_copy_datagram_iovec(skb, 0, msg->msg_iov, len)) {
|
||||||
err = skb_copy_datagram_iovec(skb, offset,
|
/* Exception. Bailout! */
|
||||||
msg->msg_iov, used);
|
len = -EFAULT;
|
||||||
if (err) {
|
break;
|
||||||
/* Exception. Bailout! */
|
|
||||||
if (!copied)
|
|
||||||
copied = -EFAULT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
copied += used;
|
|
||||||
len -= used;
|
|
||||||
|
|
||||||
/* FIXME: tcp_rcv_space_adjust(sk); */
|
|
||||||
|
|
||||||
//skip_copy:
|
|
||||||
if (used + offset < skb->len)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!(flags & MSG_PEEK))
|
|
||||||
sk_eat_skb(sk, skb);
|
|
||||||
continue;
|
|
||||||
found_fin_ok:
|
found_fin_ok:
|
||||||
if (!(flags & MSG_PEEK))
|
if (!(flags & MSG_PEEK))
|
||||||
sk_eat_skb(sk, skb);
|
sk_eat_skb(sk, skb);
|
||||||
break;
|
break;
|
||||||
|
} while (1);
|
||||||
} while (len > 0);
|
|
||||||
|
|
||||||
/* According to UNIX98, msg_name/msg_namelen are ignored
|
|
||||||
* on connected socket. I was just happy when found this 8) --ANK
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Clean up data we have read: This will do ACK frames. */
|
|
||||||
/* FIXME: cleanup_rbuf(sk, copied); */
|
|
||||||
|
|
||||||
release_sock(sk);
|
|
||||||
return copied;
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
return err;
|
return len;
|
||||||
|
|
||||||
recv_urg:
|
|
||||||
/* FIXME: err = tcp_recv_urg(sk, timeo, msg, len, flags, addr_len); */
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int inet_dccp_listen(struct socket *sock, int backlog)
|
static int inet_dccp_listen(struct socket *sock, int backlog)
|
||||||
|
Reference in New Issue
Block a user