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

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: /* Done as a macro in socket.h */
                     13: /* int
1.1.1.2   root       14:  * sbspace(struct sockbuff *sb)
1.1       root       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;
1.1.1.2   root       30:        int num;
1.1       root       31: {
1.1.1.2   root       32:        /*
1.1       root       33:         * We can only drop how much we have
1.1.1.2   root       34:         * This should never succeed
1.1       root       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;
1.1.1.2   root       42: 
1.1       root       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;
1.1.1.2   root       82: 
1.1       root       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);
1.1.1.2   root       87: 
1.1       root       88:        /* Shouldn't happen, but...  e.g. foreign host closes connection */
                     89:        if (m->m_len <= 0) {
                     90:                m_free(m);
                     91:                return;
                     92:        }
1.1.1.2   root       93: 
1.1       root       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:        }
1.1.1.2   root      105: 
1.1       root      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)
1.1.1.3 ! root      111:           ret = slirp_send(so, m->m_data, m->m_len, 0);
1.1.1.2   root      112: 
1.1       root      113:        if (ret <= 0) {
1.1.1.2   root      114:                /*
1.1       root      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:  */
1.1.1.2   root      138: static void
                    139: sbappendsb(struct sbuf *sb, struct mbuf *m)
1.1       root      140: {
                    141:        int len, n,  nn;
1.1.1.2   root      142: 
1.1       root      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;
1.1.1.2   root      183: 
1.1       root      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