Path: blob/a-new-beginning/SharedDependencies/Sources/libslirp/sbuf.c
2 views
/* SPDX-License-Identifier: BSD-3-Clause */1/*2* Copyright (c) 1995 Danny Gasparovski.3*/45#include "slirp.h"67static void sbappendsb(struct sbuf *sb, struct mbuf *m);89void sbfree(struct sbuf *sb)10{11g_free(sb->sb_data);12}1314bool sbdrop(struct sbuf *sb, size_t num)15{16int limit = sb->sb_datalen / 2;1718g_warn_if_fail(num <= sb->sb_cc);19if (num > sb->sb_cc)20num = sb->sb_cc;2122sb->sb_cc -= num;23sb->sb_rptr += num;24if (sb->sb_rptr >= sb->sb_data + sb->sb_datalen)25sb->sb_rptr -= sb->sb_datalen;2627if (sb->sb_cc < limit && sb->sb_cc + num >= limit) {28return true;29}3031return false;32}3334void sbreserve(struct sbuf *sb, size_t size)35{36sb->sb_wptr = sb->sb_rptr = sb->sb_data = g_realloc(sb->sb_data, size);37sb->sb_cc = 0;38sb->sb_datalen = size;39}4041void sbappend(struct socket *so, struct mbuf *m)42{43int ret = 0;4445DEBUG_CALL("sbappend");46DEBUG_ARG("so = %p", so);47DEBUG_ARG("m = %p", m);48DEBUG_ARG("m->m_len = %d", m->m_len);4950/* Shouldn't happen, but... e.g. foreign host closes connection */51if (m->m_len <= 0) {52m_free(m);53return;54}5556/*57* If there is urgent data, call sosendoob58* if not all was sent, sowrite will take care of the rest59* (The rest of this function is just an optimisation)60*/61if (so->so_urgc) {62sbappendsb(&so->so_rcv, m);63m_free(m);64sosendoob(so);65return;66}6768/*69* We only write if there's nothing in the buffer,70* ottherwise it'll arrive out of order, and hence corrupt71*/72if (!so->so_rcv.sb_cc)73ret = slirp_send(so, m->m_data, m->m_len, 0);7475if (ret <= 0) {76/*77* Nothing was written78* It's possible that the socket has closed, but79* we don't need to check because if it has closed,80* it will be detected in the normal way by soread()81*/82sbappendsb(&so->so_rcv, m);83} else if (ret != m->m_len) {84/*85* Something was written, but not everything..86* sbappendsb the rest87*/88m->m_len -= ret;89m->m_data += ret;90sbappendsb(&so->so_rcv, m);91} /* else */92/* Whatever happened, we free the mbuf */93m_free(m);94}9596/*97* Copy the data from m into sb98* The caller is responsible to make sure there's enough room99*/100static void sbappendsb(struct sbuf *sb, struct mbuf *m)101{102int len, n, nn;103104len = m->m_len;105106if (sb->sb_wptr < sb->sb_rptr) {107n = sb->sb_rptr - sb->sb_wptr;108if (n > len)109n = len;110memcpy(sb->sb_wptr, m->m_data, n);111} else {112/* Do the right edge first */113n = sb->sb_data + sb->sb_datalen - sb->sb_wptr;114if (n > len)115n = len;116memcpy(sb->sb_wptr, m->m_data, n);117len -= n;118if (len) {119/* Now the left edge */120nn = sb->sb_rptr - sb->sb_data;121if (nn > len)122nn = len;123memcpy(sb->sb_data, m->m_data + n, nn);124n += nn;125}126}127128sb->sb_cc += n;129sb->sb_wptr += n;130if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen)131sb->sb_wptr -= sb->sb_datalen;132}133134void sbcopy(struct sbuf *sb, size_t off, size_t len, char *to)135{136char *from;137138g_assert(len + off <= sb->sb_cc);139140from = sb->sb_rptr + off;141if (from >= sb->sb_data + sb->sb_datalen)142from -= sb->sb_datalen;143144if (from < sb->sb_wptr) {145memcpy(to, from, len);146} else {147/* re-use off */148off = (sb->sb_data + sb->sb_datalen) - from;149if (off > len)150off = len;151memcpy(to, from, off);152len -= off;153if (len)154memcpy(to + off, sb->sb_data, len);155}156}157158159