Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 531669a0 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by David S. Miller
Browse files

[DCCP]: Rewrite dccp_sendmsg to be more like UDP



Based on discussions with Nishida-san.

Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@mandriva.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7690af3f
Loading
Loading
Loading
Loading
+59 −155
Original line number Diff line number Diff line
@@ -214,70 +214,27 @@ int dccp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
	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

		/* Next get a buffer. */

		skb = skb_peek(&sk->sk_receive_queue);
		do {
			if (!skb)
				break;
		if (skb == NULL)
			goto verify_sock_status;

			offset = 0;
		dh = dccp_hdr(skb);

		if (dh->dccph_type == DCCP_PKT_DATA ||
@@ -287,124 +244,71 @@ int dccp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
		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));
			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;

		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))
		sk_eat_skb(sk, skb);
verify_sock_status:
		if (sock_flag(sk, SOCK_DONE)) {
			len = 0;
			break;
		}

		if (sk->sk_err) {
				copied = sock_error(sk);
			len = sock_error(sk);
			break;
		}

			if (sk->sk_shutdown & RCV_SHUTDOWN)
		if (sk->sk_shutdown & RCV_SHUTDOWN) {
			len = 0;
			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;
				len = -ENOTCONN;
				break;
			}
			len = 0;
			break;
		}

		if (!timeo) {
				copied = -EAGAIN;
			len = -EAGAIN;
			break;
		}

		if (signal_pending(current)) {
				copied = sock_intr_errno(timeo);
			len = sock_intr_errno(timeo);
			break;
		}
		}

		/* FIXME: cleanup_rbuf(sk, copied); */

		if (copied >= target) {
			/* Do not sleep, just process backlog. */
			release_sock(sk);
			lock_sock(sk);
		} else
		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) {
		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! */
				if (!copied)
					copied = -EFAULT;
			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)