Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Jun 2011 22:04:15 +0000 (UTC)
From:      Craig Rodrigues <rodrigc@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r223122 - head/lib/libstand
Message-ID:  <201106152204.p5FM4F4F000156@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rodrigc
Date: Wed Jun 15 22:04:14 2011
New Revision: 223122
URL: http://svn.freebsd.org/changeset/base/223122

Log:
  Added sendrecv_tftp function instead of sendrecv for use by tftp.
  In sendrecv_tftp:
      * Upon receving an unexpected block of data or error, resend the ACK
        immediately instead of waiting till the expiry of receive data timeout
        to resend the ACK.
      * change the receive timeout value between retries to be 2xMINTMO.
  
  Obtained from: Juniper Networks
  Fixed by: Santhanakrishnan Balraj <sbalraj at juniper dot net>

Modified:
  head/lib/libstand/tftp.c

Modified: head/lib/libstand/tftp.c
==============================================================================
--- head/lib/libstand/tftp.c	Wed Jun 15 21:58:01 2011	(r223121)
+++ head/lib/libstand/tftp.c	Wed Jun 15 22:04:14 2011	(r223122)
@@ -66,6 +66,7 @@ static int	tftp_read(struct open_file *f
 static int	tftp_write(struct open_file *f, void *buf, size_t size, size_t *resid);
 static off_t	tftp_seek(struct open_file *f, off_t offset, int where);
 static int	tftp_stat(struct open_file *f, struct stat *sb);
+static ssize_t sendrecv_tftp(d, sproc, sbuf, ssize, rproc, rbuf, rsize);
 
 struct fs_ops tftp_fsops = {
 	"tftp",
@@ -191,7 +192,7 @@ tftp_makereq(struct tftp_handle *h)
 	h->iodesc->destport = htons(IPPORT_TFTP);
 	h->iodesc->xid = 1;	/* expected block */
 
-	res = sendrecv(h->iodesc, sendudp, &wbuf.t, wtail - (char *) &wbuf.t,
+	res = sendrecv_tftp(h->iodesc, sendudp, &wbuf.t, wtail - (char *) &wbuf.t,
 		       recvtftp, t, sizeof(*t) + RSPACE);
 
 	if (res == -1)
@@ -226,7 +227,7 @@ tftp_getnextblock(struct tftp_handle *h)
 
 	h->iodesc->xid = h->currblock + 1;	/* expected block */
 
-	res = sendrecv(h->iodesc, sendudp, &wbuf.t, wtail - (char *) &wbuf.t,
+	res = sendrecv_tftp(h->iodesc, sendudp, &wbuf.t, wtail - (char *) &wbuf.t,
 		       recvtftp, t, sizeof(*t) + RSPACE);
 
 	if (res == -1)		/* 0 is OK! */
@@ -404,3 +405,55 @@ tftp_seek(struct open_file *f, off_t off
 	}
 	return (tftpfile->off);
 }
+
+static ssize_t
+sendrecv_tftp(d, sproc, sbuf, ssize, rproc, rbuf, rsize)
+	struct iodesc *d;
+	ssize_t (*sproc)(struct iodesc *, void *, size_t);
+	void *sbuf;
+	size_t ssize;
+	ssize_t (*rproc)(struct iodesc *, void *, size_t, time_t);
+	void *rbuf;
+	size_t rsize;
+{
+	ssize_t cc;
+	time_t t, t1, tleft;
+
+#ifdef TFTP_DEBUG
+	if (debug)
+		printf("sendrecv: called\n");
+#endif
+
+	tleft = MINTMO;
+	t = t1 = getsecs();
+	for (;;) {
+		if ((getsecs() - t) > MAXTMO) {
+			errno = ETIMEDOUT;
+			return -1;
+		}
+
+		cc = (*sproc)(d, sbuf, ssize);
+		if (cc != -1 && cc < ssize)
+			panic("sendrecv: short write! (%zd < %zu)",
+			    cc, ssize);
+
+		if (cc == -1) {
+			/* Error on transmit; wait before retrying */
+			while ((getsecs() - t1) < tleft);
+			continue;
+		}
+
+		/* Try to get a packet and process it. */
+		cc = (*rproc)(d, rbuf, rsize, tleft);
+		/* Return on data, EOF or real error. */
+		if (cc != -1 || errno != 0)
+			return (cc);
+
+		/* Timed out or didn't get the packet we're waiting for */
+		tleft += MINTMO;
+		if (tleft > (2 * MINTMO)) {
+			tleft = (2 * MINTMO);
+		}
+		t1 = getsecs();
+	}
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201106152204.p5FM4F4F000156>