VirtualBox

source: vbox/trunk/src/VBox/Devices/Network/slirp/sbuf.c@ 1071

Last change on this file since 1071 was 1033, checked in by vboxsync, 18 years ago

Big change to make slirp fully instantiatable (replace all global
variables with local ones, passing a reference to the state/config
structure to all places which are interested). You can now have as many
cards in the guest configured for NAT networking as you want.

  • Property svn:eol-style set to native
File size: 4.3 KB
Line 
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
18void
19sbfree(sb)
20 struct sbuf *sb;
21{
22 free(sb->sb_data);
23}
24
25void
26sbdrop(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
43void
44sbreserve(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 */
74void
75#ifdef VBOX
76sbappend(PNATState pData, struct socket *so, struct mbuf *m)
77#else /* !VBOX */
78sbappend(so, m)
79 struct socket *so;
80 struct mbuf *m;
81#endif /* !VBOX */
82{
83 int ret = 0;
84
85 DEBUG_CALL("sbappend");
86 DEBUG_ARG("so = %lx", (long)so);
87 DEBUG_ARG("m = %lx", (long)m);
88 DEBUG_ARG("m->m_len = %d", m->m_len);
89
90 /* Shouldn't happen, but... e.g. foreign host closes connection */
91 if (m->m_len <= 0) {
92#ifdef VBOX
93 m_free(pData, m);
94#else /* !VBOX */
95 m_free(m);
96#endif /* !VBOX */
97 return;
98 }
99
100 /*
101 * If there is urgent data, call sosendoob
102 * if not all was sent, sowrite will take care of the rest
103 * (The rest of this function is just an optimisation)
104 */
105 if (so->so_urgc) {
106 sbappendsb(&so->so_rcv, m);
107#ifdef VBOX
108 m_free(pData, m);
109#else /* !VBOX */
110 m_free(m);
111#endif /* !VBOX */
112 sosendoob(so);
113 return;
114 }
115
116 /*
117 * We only write if there's nothing in the buffer,
118 * ottherwise it'll arrive out of order, and hence corrupt
119 */
120 if (!so->so_rcv.sb_cc)
121 ret = send(so->s, m->m_data, m->m_len, 0);
122
123 if (ret <= 0) {
124 /*
125 * Nothing was written
126 * It's possible that the socket has closed, but
127 * we don't need to check because if it has closed,
128 * it will be detected in the normal way by soread()
129 */
130 sbappendsb(&so->so_rcv, m);
131 } else if (ret != m->m_len) {
132 /*
133 * Something was written, but not everything..
134 * sbappendsb the rest
135 */
136 m->m_len -= ret;
137 m->m_data += ret;
138 sbappendsb(&so->so_rcv, m);
139 } /* else */
140 /* Whatever happened, we free the mbuf */
141#ifdef VBOX
142 m_free(pData, m);
143#else /* !VBOX */
144 m_free(m);
145#endif /* !VBOX */
146}
147
148/*
149 * Copy the data from m into sb
150 * The caller is responsible to make sure there's enough room
151 */
152void
153sbappendsb(sb, m)
154 struct sbuf *sb;
155 struct mbuf *m;
156{
157 int len, n, nn;
158
159 len = m->m_len;
160
161 if (sb->sb_wptr < sb->sb_rptr) {
162 n = sb->sb_rptr - sb->sb_wptr;
163 if (n > len) n = len;
164 memcpy(sb->sb_wptr, m->m_data, n);
165 } else {
166 /* Do the right edge first */
167 n = sb->sb_data + sb->sb_datalen - sb->sb_wptr;
168 if (n > len) n = len;
169 memcpy(sb->sb_wptr, m->m_data, n);
170 len -= n;
171 if (len) {
172 /* Now the left edge */
173 nn = sb->sb_rptr - sb->sb_data;
174 if (nn > len) nn = len;
175 memcpy(sb->sb_data,m->m_data+n,nn);
176 n += nn;
177 }
178 }
179
180 sb->sb_cc += n;
181 sb->sb_wptr += n;
182 if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen)
183 sb->sb_wptr -= sb->sb_datalen;
184}
185
186/*
187 * Copy data from sbuf to a normal, straight buffer
188 * Don't update the sbuf rptr, this will be
189 * done in sbdrop when the data is acked
190 */
191void
192sbcopy(sb, off, len, to)
193 struct sbuf *sb;
194 int off;
195 int len;
196 char *to;
197{
198 char *from;
199
200 from = sb->sb_rptr + off;
201 if (from >= sb->sb_data + sb->sb_datalen)
202 from -= sb->sb_datalen;
203
204 if (from < sb->sb_wptr) {
205 if (len > sb->sb_cc) len = sb->sb_cc;
206 memcpy(to,from,len);
207 } else {
208 /* re-use off */
209 off = (sb->sb_data + sb->sb_datalen) - from;
210 if (off > len) off = len;
211 memcpy(to,from,off);
212 len -= off;
213 if (len)
214 memcpy(to+off,sb->sb_data,len);
215 }
216}
217
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette