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

unix.superglobalmegacorp.com