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

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>
                      9: 
1.1.1.2   root       10: static void sbappendsb(struct sbuf *sb, struct mbuf *m);
                     11: 
1.1       root       12: void
1.1.1.4 ! root       13: sbfree(struct sbuf *sb)
1.1       root       14: {
                     15:        free(sb->sb_data);
                     16: }
                     17: 
                     18: void
1.1.1.4 ! root       19: sbdrop(struct sbuf *sb, int num)
1.1       root       20: {
1.1.1.2   root       21:        /*
1.1       root       22:         * We can only drop how much we have
1.1.1.2   root       23:         * This should never succeed
1.1       root       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;
1.1.1.2   root       31: 
1.1       root       32: }
                     33: 
                     34: void
1.1.1.4 ! root       35: sbreserve(struct sbuf *sb, int size)
1.1       root       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
1.1.1.4 ! root       64: sbappend(struct socket *so, struct mbuf *m)
1.1       root       65: {
                     66:        int ret = 0;
1.1.1.2   root       67: 
1.1       root       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);
1.1.1.2   root       72: 
1.1       root       73:        /* Shouldn't happen, but...  e.g. foreign host closes connection */
                     74:        if (m->m_len <= 0) {
                     75:                m_free(m);
                     76:                return;
                     77:        }
1.1.1.2   root       78: 
1.1       root       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:        }
1.1.1.2   root       90: 
1.1       root       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)
1.1.1.3   root       96:           ret = slirp_send(so, m->m_data, m->m_len, 0);
1.1.1.2   root       97: 
1.1       root       98:        if (ret <= 0) {
1.1.1.2   root       99:                /*
1.1       root      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:  */
1.1.1.2   root      123: static void
                    124: sbappendsb(struct sbuf *sb, struct mbuf *m)
1.1       root      125: {
                    126:        int len, n,  nn;
1.1.1.2   root      127: 
1.1       root      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
1.1.1.4 ! root      161: sbcopy(struct sbuf *sb, int off, int len, char *to)
1.1       root      162: {
                    163:        char *from;
1.1.1.2   root      164: 
1.1       root      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