File:  [Qemu by Fabrice Bellard] / qemu / slirp / sbuf.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:25:39 2018 UTC (2 years, 11 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu1001, qemu1000, qemu0151, qemu0150, qemu0141, qemu0140, qemu0130, qemu0125, qemu0124, qemu0123, qemu0122, qemu0121, qemu0120, qemu0111, qemu0110, HEAD
qemu 0.11.0

    1: /*
    2:  * Copyright (c) 1995 Danny Gasparovski.
    3:  *
    4:  * Please read the file COPYRIGHT for the
    5:  * terms and conditions of the copyright.
    6:  */
    7: 
    8: #include <slirp.h>
    9: 
   10: static void sbappendsb(struct sbuf *sb, struct mbuf *m);
   11: 
   12: void
   13: sbfree(struct sbuf *sb)
   14: {
   15: 	free(sb->sb_data);
   16: }
   17: 
   18: void
   19: sbdrop(struct sbuf *sb, int num)
   20: {
   21: 	/*
   22: 	 * We can only drop how much we have
   23: 	 * This should never succeed
   24: 	 */
   25: 	if(num > sb->sb_cc)
   26: 		num = sb->sb_cc;
   27: 	sb->sb_cc -= num;
   28: 	sb->sb_rptr += num;
   29: 	if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen)
   30: 		sb->sb_rptr -= sb->sb_datalen;
   31: 
   32: }
   33: 
   34: void
   35: sbreserve(struct sbuf *sb, int size)
   36: {
   37: 	if (sb->sb_data) {
   38: 		/* Already alloced, realloc if necessary */
   39: 		if (sb->sb_datalen != size) {
   40: 			sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)realloc(sb->sb_data, size);
   41: 			sb->sb_cc = 0;
   42: 			if (sb->sb_wptr)
   43: 			   sb->sb_datalen = size;
   44: 			else
   45: 			   sb->sb_datalen = 0;
   46: 		}
   47: 	} else {
   48: 		sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size);
   49: 		sb->sb_cc = 0;
   50: 		if (sb->sb_wptr)
   51: 		   sb->sb_datalen = size;
   52: 		else
   53: 		   sb->sb_datalen = 0;
   54: 	}
   55: }
   56: 
   57: /*
   58:  * Try and write() to the socket, whatever doesn't get written
   59:  * append to the buffer... for a host with a fast net connection,
   60:  * this prevents an unnecessary copy of the data
   61:  * (the socket is non-blocking, so we won't hang)
   62:  */
   63: void
   64: sbappend(struct socket *so, struct mbuf *m)
   65: {
   66: 	int ret = 0;
   67: 
   68: 	DEBUG_CALL("sbappend");
   69: 	DEBUG_ARG("so = %lx", (long)so);
   70: 	DEBUG_ARG("m = %lx", (long)m);
   71: 	DEBUG_ARG("m->m_len = %d", m->m_len);
   72: 
   73: 	/* Shouldn't happen, but...  e.g. foreign host closes connection */
   74: 	if (m->m_len <= 0) {
   75: 		m_free(m);
   76: 		return;
   77: 	}
   78: 
   79: 	/*
   80: 	 * If there is urgent data, call sosendoob
   81: 	 * if not all was sent, sowrite will take care of the rest
   82: 	 * (The rest of this function is just an optimisation)
   83: 	 */
   84: 	if (so->so_urgc) {
   85: 		sbappendsb(&so->so_rcv, m);
   86: 		m_free(m);
   87: 		sosendoob(so);
   88: 		return;
   89: 	}
   90: 
   91: 	/*
   92: 	 * We only write if there's nothing in the buffer,
   93: 	 * ottherwise it'll arrive out of order, and hence corrupt
   94: 	 */
   95: 	if (!so->so_rcv.sb_cc)
   96: 	   ret = slirp_send(so, m->m_data, m->m_len, 0);
   97: 
   98: 	if (ret <= 0) {
   99: 		/*
  100: 		 * Nothing was written
  101: 		 * It's possible that the socket has closed, but
  102: 		 * we don't need to check because if it has closed,
  103: 		 * it will be detected in the normal way by soread()
  104: 		 */
  105: 		sbappendsb(&so->so_rcv, m);
  106: 	} else if (ret != m->m_len) {
  107: 		/*
  108: 		 * Something was written, but not everything..
  109: 		 * sbappendsb the rest
  110: 		 */
  111: 		m->m_len -= ret;
  112: 		m->m_data += ret;
  113: 		sbappendsb(&so->so_rcv, m);
  114: 	} /* else */
  115: 	/* Whatever happened, we free the mbuf */
  116: 	m_free(m);
  117: }
  118: 
  119: /*
  120:  * Copy the data from m into sb
  121:  * The caller is responsible to make sure there's enough room
  122:  */
  123: static void
  124: sbappendsb(struct sbuf *sb, struct mbuf *m)
  125: {
  126: 	int len, n,  nn;
  127: 
  128: 	len = m->m_len;
  129: 
  130: 	if (sb->sb_wptr < sb->sb_rptr) {
  131: 		n = sb->sb_rptr - sb->sb_wptr;
  132: 		if (n > len) n = len;
  133: 		memcpy(sb->sb_wptr, m->m_data, n);
  134: 	} else {
  135: 		/* Do the right edge first */
  136: 		n = sb->sb_data + sb->sb_datalen - sb->sb_wptr;
  137: 		if (n > len) n = len;
  138: 		memcpy(sb->sb_wptr, m->m_data, n);
  139: 		len -= n;
  140: 		if (len) {
  141: 			/* Now the left edge */
  142: 			nn = sb->sb_rptr - sb->sb_data;
  143: 			if (nn > len) nn = len;
  144: 			memcpy(sb->sb_data,m->m_data+n,nn);
  145: 			n += nn;
  146: 		}
  147: 	}
  148: 
  149: 	sb->sb_cc += n;
  150: 	sb->sb_wptr += n;
  151: 	if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen)
  152: 		sb->sb_wptr -= sb->sb_datalen;
  153: }
  154: 
  155: /*
  156:  * Copy data from sbuf to a normal, straight buffer
  157:  * Don't update the sbuf rptr, this will be
  158:  * done in sbdrop when the data is acked
  159:  */
  160: void
  161: sbcopy(struct sbuf *sb, int off, int len, char *to)
  162: {
  163: 	char *from;
  164: 
  165: 	from = sb->sb_rptr + off;
  166: 	if (from >= sb->sb_data + sb->sb_datalen)
  167: 		from -= sb->sb_datalen;
  168: 
  169: 	if (from < sb->sb_wptr) {
  170: 		if (len > sb->sb_cc) len = sb->sb_cc;
  171: 		memcpy(to,from,len);
  172: 	} else {
  173: 		/* re-use off */
  174: 		off = (sb->sb_data + sb->sb_datalen) - from;
  175: 		if (off > len) off = len;
  176: 		memcpy(to,from,off);
  177: 		len -= off;
  178: 		if (len)
  179: 		   memcpy(to+off,sb->sb_data,len);
  180: 	}
  181: }

unix.superglobalmegacorp.com