Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/SharedDependencies/Sources/libslirp/sbuf.c
2 views
1
/* SPDX-License-Identifier: BSD-3-Clause */
2
/*
3
* Copyright (c) 1995 Danny Gasparovski.
4
*/
5
6
#include "slirp.h"
7
8
static void sbappendsb(struct sbuf *sb, struct mbuf *m);
9
10
void sbfree(struct sbuf *sb)
11
{
12
g_free(sb->sb_data);
13
}
14
15
bool sbdrop(struct sbuf *sb, size_t num)
16
{
17
int limit = sb->sb_datalen / 2;
18
19
g_warn_if_fail(num <= sb->sb_cc);
20
if (num > sb->sb_cc)
21
num = sb->sb_cc;
22
23
sb->sb_cc -= num;
24
sb->sb_rptr += num;
25
if (sb->sb_rptr >= sb->sb_data + sb->sb_datalen)
26
sb->sb_rptr -= sb->sb_datalen;
27
28
if (sb->sb_cc < limit && sb->sb_cc + num >= limit) {
29
return true;
30
}
31
32
return false;
33
}
34
35
void sbreserve(struct sbuf *sb, size_t size)
36
{
37
sb->sb_wptr = sb->sb_rptr = sb->sb_data = g_realloc(sb->sb_data, size);
38
sb->sb_cc = 0;
39
sb->sb_datalen = size;
40
}
41
42
void sbappend(struct socket *so, struct mbuf *m)
43
{
44
int ret = 0;
45
46
DEBUG_CALL("sbappend");
47
DEBUG_ARG("so = %p", so);
48
DEBUG_ARG("m = %p", m);
49
DEBUG_ARG("m->m_len = %d", m->m_len);
50
51
/* Shouldn't happen, but... e.g. foreign host closes connection */
52
if (m->m_len <= 0) {
53
m_free(m);
54
return;
55
}
56
57
/*
58
* If there is urgent data, call sosendoob
59
* if not all was sent, sowrite will take care of the rest
60
* (The rest of this function is just an optimisation)
61
*/
62
if (so->so_urgc) {
63
sbappendsb(&so->so_rcv, m);
64
m_free(m);
65
sosendoob(so);
66
return;
67
}
68
69
/*
70
* We only write if there's nothing in the buffer,
71
* ottherwise it'll arrive out of order, and hence corrupt
72
*/
73
if (!so->so_rcv.sb_cc)
74
ret = slirp_send(so, m->m_data, m->m_len, 0);
75
76
if (ret <= 0) {
77
/*
78
* Nothing was written
79
* It's possible that the socket has closed, but
80
* we don't need to check because if it has closed,
81
* it will be detected in the normal way by soread()
82
*/
83
sbappendsb(&so->so_rcv, m);
84
} else if (ret != m->m_len) {
85
/*
86
* Something was written, but not everything..
87
* sbappendsb the rest
88
*/
89
m->m_len -= ret;
90
m->m_data += ret;
91
sbappendsb(&so->so_rcv, m);
92
} /* else */
93
/* Whatever happened, we free the mbuf */
94
m_free(m);
95
}
96
97
/*
98
* Copy the data from m into sb
99
* The caller is responsible to make sure there's enough room
100
*/
101
static void sbappendsb(struct sbuf *sb, struct mbuf *m)
102
{
103
int len, n, nn;
104
105
len = m->m_len;
106
107
if (sb->sb_wptr < sb->sb_rptr) {
108
n = sb->sb_rptr - sb->sb_wptr;
109
if (n > len)
110
n = len;
111
memcpy(sb->sb_wptr, m->m_data, n);
112
} else {
113
/* Do the right edge first */
114
n = sb->sb_data + sb->sb_datalen - sb->sb_wptr;
115
if (n > len)
116
n = len;
117
memcpy(sb->sb_wptr, m->m_data, n);
118
len -= n;
119
if (len) {
120
/* Now the left edge */
121
nn = sb->sb_rptr - sb->sb_data;
122
if (nn > len)
123
nn = len;
124
memcpy(sb->sb_data, m->m_data + n, nn);
125
n += nn;
126
}
127
}
128
129
sb->sb_cc += n;
130
sb->sb_wptr += n;
131
if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen)
132
sb->sb_wptr -= sb->sb_datalen;
133
}
134
135
void sbcopy(struct sbuf *sb, size_t off, size_t len, char *to)
136
{
137
char *from;
138
139
g_assert(len + off <= sb->sb_cc);
140
141
from = sb->sb_rptr + off;
142
if (from >= sb->sb_data + sb->sb_datalen)
143
from -= sb->sb_datalen;
144
145
if (from < sb->sb_wptr) {
146
memcpy(to, from, len);
147
} else {
148
/* re-use off */
149
off = (sb->sb_data + sb->sb_datalen) - from;
150
if (off > len)
151
off = len;
152
memcpy(to, from, off);
153
len -= off;
154
if (len)
155
memcpy(to + off, sb->sb_data, len);
156
}
157
}
158
159