Statistics
| Branch: | Revision:

root / slirp / sbuf.c @ 5fafdf24

History | View | Annotate | Download (4 kB)

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
/* Done as a macro in socket.h */
11
/* int
12
 * sbspace(struct sockbuff *sb)
13
 * {
14
 *        return SB_DATALEN - sb->sb_cc;
15
 * }
16
 */
17

    
18
void
19
sbfree(sb)
20
        struct sbuf *sb;
21
{
22
        free(sb->sb_data);
23
}
24

    
25
void
26
sbdrop(sb, num)
27
        struct sbuf *sb;
28
        int num;
29
{
30
        /*
31
         * We can only drop how much we have
32
         * This should never succeed
33
         */
34
        if(num > sb->sb_cc)
35
                num = sb->sb_cc;
36
        sb->sb_cc -= num;
37
        sb->sb_rptr += num;
38
        if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen)
39
                sb->sb_rptr -= sb->sb_datalen;
40
  
41
}
42

    
43
void
44
sbreserve(sb, size)
45
        struct sbuf *sb;
46
        int size;
47
{
48
        if (sb->sb_data) {
49
                /* Already alloced, realloc if necessary */
50
                if (sb->sb_datalen != size) {
51
                        sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)realloc(sb->sb_data, size);
52
                        sb->sb_cc = 0;
53
                        if (sb->sb_wptr)
54
                           sb->sb_datalen = size;
55
                        else
56
                           sb->sb_datalen = 0;
57
                }
58
        } else {
59
                sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size);
60
                sb->sb_cc = 0;
61
                if (sb->sb_wptr)
62
                   sb->sb_datalen = size;
63
                else
64
                   sb->sb_datalen = 0;
65
        }
66
}
67

    
68
/*
69
 * Try and write() to the socket, whatever doesn't get written
70
 * append to the buffer... for a host with a fast net connection,
71
 * this prevents an unnecessary copy of the data
72
 * (the socket is non-blocking, so we won't hang)
73
 */
74
void
75
sbappend(so, m)
76
        struct socket *so;
77
        struct mbuf *m;
78
{
79
        int ret = 0;
80

    
81
        DEBUG_CALL("sbappend");
82
        DEBUG_ARG("so = %lx", (long)so);
83
        DEBUG_ARG("m = %lx", (long)m);
84
        DEBUG_ARG("m->m_len = %d", m->m_len);
85

    
86
        /* Shouldn't happen, but...  e.g. foreign host closes connection */
87
        if (m->m_len <= 0) {
88
                m_free(m);
89
                return;
90
        }
91

    
92
        /*
93
         * If there is urgent data, call sosendoob
94
         * if not all was sent, sowrite will take care of the rest
95
         * (The rest of this function is just an optimisation)
96
         */
97
        if (so->so_urgc) {
98
                sbappendsb(&so->so_rcv, m);
99
                m_free(m);
100
                sosendoob(so);
101
                return;
102
        }
103

    
104
        /*
105
         * We only write if there's nothing in the buffer,
106
         * ottherwise it'll arrive out of order, and hence corrupt
107
         */
108
        if (!so->so_rcv.sb_cc)
109
           ret = send(so->s, m->m_data, m->m_len, 0);
110

    
111
        if (ret <= 0) {
112
                /*
113
                 * Nothing was written
114
                 * It's possible that the socket has closed, but
115
                 * we don't need to check because if it has closed,
116
                 * it will be detected in the normal way by soread()
117
                 */
118
                sbappendsb(&so->so_rcv, m);
119
        } else if (ret != m->m_len) {
120
                /*
121
                 * Something was written, but not everything..
122
                 * sbappendsb the rest
123
                 */
124
                m->m_len -= ret;
125
                m->m_data += ret;
126
                sbappendsb(&so->so_rcv, m);
127
        } /* else */
128
        /* Whatever happened, we free the mbuf */
129
        m_free(m);
130
}
131

    
132
/*
133
 * Copy the data from m into sb
134
 * The caller is responsible to make sure there's enough room
135
 */
136
void
137
sbappendsb(sb, m)
138
         struct sbuf *sb;
139
         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
}
201