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