]> err.no Git - linux-2.6/commitdiff
[DCCP]: Rewrite dccp_sendmsg to be more like UDP
authorArnaldo Carvalho de Melo <acme@mandriva.com>
Sat, 13 Aug 2005 23:35:17 +0000 (20:35 -0300)
committerDavid S. Miller <davem@sunset.davemloft.net>
Mon, 29 Aug 2005 22:59:34 +0000 (15:59 -0700)
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>
net/dccp/proto.c

index 46dd489f66cf2f4de32a422943314c3be199d273..ed0bf58c8ae07d7911e454c34691677e4d3ed436 100644 (file)
@@ -214,197 +214,101 @@ out_discard:
        goto out_release;
 }
 
-EXPORT_SYMBOL(dccp_sendmsg);
-
 int dccp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                 size_t len, int nonblock, int flags, int *addr_len)
 {
        const struct dccp_hdr *dh;
-       int copied = 0;
-       unsigned long used;
-       int err;
-       int target;             /* Read at least this many bytes */
        long timeo;
 
        lock_sock(sk);
 
-       err = -ENOTCONN;
-       if (sk->sk_state == DCCP_LISTEN)
+       if (sk->sk_state == DCCP_LISTEN) {
+               len = -ENOTCONN;
                goto out;
-
-       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);
+       timeo = sock_rcvtimeo(sk, nonblock);
 
        do {
-               struct sk_buff *skb;
-               u32 offset;
+               struct sk_buff *skb = skb_peek(&sk->sk_receive_queue);
 
-       /* FIXME */
-#if 0
-               /*
-                * Are we at urgent data? Stop if we have read anything or
-                * have SIGURG pending.
-                */
-               if (tp->urg_data && tp->urg_seq == *seq) {
-                       if (copied)
-                               break;
-                       if (signal_pending(current)) {
-                               copied = timeo ? sock_intr_errno(timeo) :
-                                                -EAGAIN;
-                               break;
-                       }
-               }
-#endif
+               if (skb == NULL)
+                       goto verify_sock_status;
 
-               /* Next get a buffer. */
-
-               skb = skb_peek(&sk->sk_receive_queue);
-               do {
-                       if (!skb)
-                               break;
+               dh = dccp_hdr(skb);
 
-                       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_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)
+               if (dh->dccph_type == DCCP_PKT_RESET ||
+                   dh->dccph_type == DCCP_PKT_CLOSE) {
+                       dccp_pr_debug("found fin ok!\n");
+                       len = 0;
+                       goto found_fin_ok;
+               }
+               dccp_pr_debug("packet_type=%s\n",
+                             dccp_packet_name(dh->dccph_type));
+               sk_eat_skb(sk, skb);
+verify_sock_status:
+               if (sock_flag(sk, SOCK_DONE)) {
+                       len = 0;
                        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 (sk->sk_err) {
+                       len = sock_error(sk);
+                       break;
+               }
 
-                       if (!timeo) {
-                               copied = -EAGAIN;
-                               break;
-                       }
+               if (sk->sk_shutdown & RCV_SHUTDOWN) {
+                       len = 0;
+                       break;
+               }
 
-                       if (signal_pending(current)) {
-                               copied = sock_intr_errno(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;
                }
 
-               /* FIXME: cleanup_rbuf(sk, copied); */
+               if (!timeo) {
+                       len = -EAGAIN;
+                       break;
+               }
 
-               if (copied >= target) {
-                       /* Do not sleep, just process backlog. */
-                       release_sock(sk);
-                       lock_sock(sk);
-               } else
-                       sk_wait_data(sk, &timeo);
+               if (signal_pending(current)) {
+                       len = sock_intr_errno(timeo);
+                       break;
+               }
 
+               sk_wait_data(sk, &timeo);
                continue;
-
        found_ok_skb:
-               /* Ok so how much can we use? */
-               used = skb->len - offset;
-               if (len < used)
-                       used = len;
-
-               if (!(flags & MSG_TRUNC)) {
-                       err = skb_copy_datagram_iovec(skb, offset,
-                                                     msg->msg_iov, used);
-                       if (err) {
-                               /* Exception. Bailout! */
-                               if (!copied)
-                                       copied = -EFAULT;
-                               break;
-                       }
+               if (len > skb->len)
+                       len = skb->len;
+               else if (len < skb->len)
+                       msg->msg_flags |= MSG_TRUNC;
+
+               if (skb_copy_datagram_iovec(skb, 0, msg->msg_iov, len)) {
+                       /* Exception. Bailout! */
+                       len = -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:
                if (!(flags & MSG_PEEK))
                        sk_eat_skb(sk, skb);
                break;
-               
-       } 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;
-
+       } while (1);
 out:
        release_sock(sk);
-       return err;
-
-recv_urg:
-       /* FIXME: err = tcp_recv_urg(sk, timeo, msg, len, flags, addr_len); */
-       goto out;
+       return len;
 }
 
 static int inet_dccp_listen(struct socket *sock, int backlog)