sbuf.c revision 8b23a6c7e1aee255004dd19098d4c2462b61b849
18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 1995 Danny Gasparovski.
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Please read the file COPYRIGHT for the
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * terms and conditions of the copyright.
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <slirp.h>
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsbuf_free(SBuf  sb)
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	free(sb->sb_data);
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsbuf_drop(SBuf  sb, int  num)
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * We can only drop how much we have
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * This should never succeed
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if(num > sb->sb_cc)
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		num = sb->sb_cc;
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	sb->sb_cc -= num;
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	sb->sb_rptr += num;
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen)
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sb->sb_rptr -= sb->sb_datalen;
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsbuf_reserve(SBuf  sb, int  size)
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sb->sb_datalen == size)
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)realloc(sb->sb_data, size);
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sb->sb_cc = 0;
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sb->sb_wptr)
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       sb->sb_datalen = size;
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       sb->sb_datalen = 0;
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Try and write() to the socket, whatever doesn't get written
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * append to the buffer... for a host with a fast net connection,
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * this prevents an unnecessary copy of the data
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (the socket is non-blocking, so we won't hang)
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsbuf_append(struct socket *so, MBuf  m)
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	int ret = 0;
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("sbuf_append");
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("so = %lx", (long)so);
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("m = %lx", (long)m);
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("m->m_len = %d", m->m_len);
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Shouldn't happen, but...  e.g. foreign host closes connection */
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (m->m_len <= 0) {
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		mbuf_free(m);
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return;
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * If there is urgent data, call sosendoob
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * if not all was sent, sowrite will take care of the rest
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * (The rest of this function is just an optimisation)
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (so->so_urgc) {
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sbuf_appendsb(&so->so_rcv, m);
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		mbuf_free(m);
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sosendoob(so);
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return;
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * We only write if there's nothing in the buffer,
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * ottherwise it'll arrive out of order, and hence corrupt
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (!so->so_rcv.sb_cc) {
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   ret = socket_send(so->s, m->m_data, m->m_len);
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (ret <= 0) {
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/*
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * Nothing was written
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * It's possible that the socket has closed, but
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * we don't need to check because if it has closed,
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * it will be detected in the normal way by soread()
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 */
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sbuf_appendsb(&so->so_rcv, m);
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else if (ret != m->m_len) {
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/*
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * Something was written, but not everything..
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * sbuf_appendsb the rest
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 */
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		m->m_len -= ret;
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		m->m_data += ret;
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sbuf_appendsb(&so->so_rcv, m);
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} /* else */
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Whatever happened, we free the mbuf */
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	mbuf_free(m);
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copy the data from m into sb
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The caller is responsible to make sure there's enough room
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsbuf_appendsb(SBuf  sb, MBuf  m)
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	int len, n,  nn;
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	len = m->m_len;
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (sb->sb_wptr < sb->sb_rptr) {
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		n = sb->sb_rptr - sb->sb_wptr;
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (n > len) n = len;
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		memcpy(sb->sb_wptr, m->m_data, n);
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else {
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/* Do the right edge first */
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		n = sb->sb_data + sb->sb_datalen - sb->sb_wptr;
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (n > len) n = len;
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		memcpy(sb->sb_wptr, m->m_data, n);
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		len -= n;
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (len) {
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			/* Now the left edge */
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			nn = sb->sb_rptr - sb->sb_data;
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			if (nn > len) nn = len;
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			memcpy(sb->sb_data,m->m_data+n,nn);
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n += nn;
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	sb->sb_cc   += n;
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	sb->sb_wptr += n;
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen)
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sb->sb_wptr -= sb->sb_datalen;
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copy data from sbuf to a normal, straight buffer
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Don't update the sbuf rptr, this will be
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * done in sbdrop when the data is acked
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsbuf_copy(SBuf  sb, int  off, int  len, char*  to)
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	char *from;
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	from = sb->sb_rptr + off;
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (from >= sb->sb_data + sb->sb_datalen)
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		from -= sb->sb_datalen;
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (from < sb->sb_wptr) {
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (len > sb->sb_cc) len = sb->sb_cc;
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		memcpy(to,from,len);
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else {
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/* re-use off */
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		off = (sb->sb_data + sb->sb_datalen) - from;
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (off > len) off = len;
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		memcpy(to,from,off);
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		len -= off;
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (len)
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		   memcpy(to+off,sb->sb_data,len);
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
173