Annotation of qemu/slirp/sbuf.c, revision 1.1.1.5

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

unix.superglobalmegacorp.com