Annotation of qemu/slirp/sbuf.c, revision 1.1.1.1
1.1 root 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:
unix.superglobalmegacorp.com