slirp: replace qemu_notify_event() with a callback
[qemu/ar7.git] / slirp / sbuf.c
blob17f28e97a63d0742a5a1a8366dfa1a1f2a62a0a8
1 /*
2 * Copyright (c) 1995 Danny Gasparovski.
4 * Please read the file COPYRIGHT for the
5 * terms and conditions of the copyright.
6 */
8 #include "qemu/osdep.h"
9 #include "slirp.h"
10 #include "qemu/main-loop.h"
12 static void sbappendsb(struct sbuf *sb, struct mbuf *m);
14 void
15 sbfree(struct sbuf *sb)
17 free(sb->sb_data);
20 bool
21 sbdrop(struct sbuf *sb, int num)
23 int limit = sb->sb_datalen / 2;
26 * We can only drop how much we have
27 * This should never succeed
29 if(num > sb->sb_cc)
30 num = sb->sb_cc;
31 sb->sb_cc -= num;
32 sb->sb_rptr += num;
33 if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen)
34 sb->sb_rptr -= sb->sb_datalen;
36 if (sb->sb_cc < limit && sb->sb_cc + num >= limit) {
37 return true;
40 return false;
43 void
44 sbreserve(struct sbuf *sb, int size)
46 if (sb->sb_data) {
47 /* Already alloced, realloc if necessary */
48 if (sb->sb_datalen != size) {
49 sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)realloc(sb->sb_data, size);
50 sb->sb_cc = 0;
51 if (sb->sb_wptr)
52 sb->sb_datalen = size;
53 else
54 sb->sb_datalen = 0;
56 } else {
57 sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size);
58 sb->sb_cc = 0;
59 if (sb->sb_wptr)
60 sb->sb_datalen = size;
61 else
62 sb->sb_datalen = 0;
67 * Try and write() to the socket, whatever doesn't get written
68 * append to the buffer... for a host with a fast net connection,
69 * this prevents an unnecessary copy of the data
70 * (the socket is non-blocking, so we won't hang)
72 void
73 sbappend(struct socket *so, struct mbuf *m)
75 int ret = 0;
77 DEBUG_CALL("sbappend");
78 DEBUG_ARG("so = %p", so);
79 DEBUG_ARG("m = %p", m);
80 DEBUG_ARG("m->m_len = %d", m->m_len);
82 /* Shouldn't happen, but... e.g. foreign host closes connection */
83 if (m->m_len <= 0) {
84 m_free(m);
85 return;
89 * If there is urgent data, call sosendoob
90 * if not all was sent, sowrite will take care of the rest
91 * (The rest of this function is just an optimisation)
93 if (so->so_urgc) {
94 sbappendsb(&so->so_rcv, m);
95 m_free(m);
96 (void)sosendoob(so);
97 return;
101 * We only write if there's nothing in the buffer,
102 * ottherwise it'll arrive out of order, and hence corrupt
104 if (!so->so_rcv.sb_cc)
105 ret = slirp_send(so, m->m_data, m->m_len, 0);
107 if (ret <= 0) {
109 * Nothing was written
110 * It's possible that the socket has closed, but
111 * we don't need to check because if it has closed,
112 * it will be detected in the normal way by soread()
114 sbappendsb(&so->so_rcv, m);
115 } else if (ret != m->m_len) {
117 * Something was written, but not everything..
118 * sbappendsb the rest
120 m->m_len -= ret;
121 m->m_data += ret;
122 sbappendsb(&so->so_rcv, m);
123 } /* else */
124 /* Whatever happened, we free the mbuf */
125 m_free(m);
129 * Copy the data from m into sb
130 * The caller is responsible to make sure there's enough room
132 static void
133 sbappendsb(struct sbuf *sb, struct mbuf *m)
135 int len, n, nn;
137 len = m->m_len;
139 if (sb->sb_wptr < sb->sb_rptr) {
140 n = sb->sb_rptr - sb->sb_wptr;
141 if (n > len) n = len;
142 memcpy(sb->sb_wptr, m->m_data, n);
143 } else {
144 /* Do the right edge first */
145 n = sb->sb_data + sb->sb_datalen - sb->sb_wptr;
146 if (n > len) n = len;
147 memcpy(sb->sb_wptr, m->m_data, n);
148 len -= n;
149 if (len) {
150 /* Now the left edge */
151 nn = sb->sb_rptr - sb->sb_data;
152 if (nn > len) nn = len;
153 memcpy(sb->sb_data,m->m_data+n,nn);
154 n += nn;
158 sb->sb_cc += n;
159 sb->sb_wptr += n;
160 if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen)
161 sb->sb_wptr -= sb->sb_datalen;
165 * Copy data from sbuf to a normal, straight buffer
166 * Don't update the sbuf rptr, this will be
167 * done in sbdrop when the data is acked
169 void
170 sbcopy(struct sbuf *sb, int off, int len, char *to)
172 char *from;
174 from = sb->sb_rptr + off;
175 if (from >= sb->sb_data + sb->sb_datalen)
176 from -= sb->sb_datalen;
178 if (from < sb->sb_wptr) {
179 if (len > sb->sb_cc) len = sb->sb_cc;
180 memcpy(to,from,len);
181 } else {
182 /* re-use off */
183 off = (sb->sb_data + sb->sb_datalen) - from;
184 if (off > len) off = len;
185 memcpy(to,from,off);
186 len -= off;
187 if (len)
188 memcpy(to+off,sb->sb_data,len);