/*
 * Copyright (c) 1995 Danny Gasparovski.
 *
 * Please read the file COPYRIGHT for the
 * terms and conditions of the copyright.
 */

#include "qemu/osdep.h"
#include "slirp.h"
#include "qemu/main-loop.h"

static void sbappendsb(struct sbuf *sb, struct mbuf *m);

void sbfree(struct sbuf *sb)
{
    free(sb->sb_data);
}

void sbdrop(struct sbuf *sb, int num)
{
    int limit = sb->sb_datalen / 2;

    /*
     * We can only drop how much we have
     * This should never succeed
     */
    if (num > sb->sb_cc)
        num = sb->sb_cc;
    sb->sb_cc -= num;
    sb->sb_rptr += num;
    if (sb->sb_rptr >= sb->sb_data + sb->sb_datalen)
        sb->sb_rptr -= sb->sb_datalen;

    if (sb->sb_cc < limit && sb->sb_cc + num >= limit) {
        qemu_notify_event();
    }
}

void sbreserve(struct sbuf *sb, int size)
{
    if (sb->sb_data) {
        /* Already alloced, realloc if necessary */
        if (sb->sb_datalen != size) {
            sb->sb_wptr = sb->sb_rptr = sb->sb_data =
                (char *)realloc(sb->sb_data, size);
            sb->sb_cc = 0;
            if (sb->sb_wptr)
                sb->sb_datalen = size;
            else
                sb->sb_datalen = 0;
        }
    } else {
        sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size);
        sb->sb_cc = 0;
        if (sb->sb_wptr)
            sb->sb_datalen = size;
        else
            sb->sb_datalen = 0;
    }
}

/*
 * Try and write() to the socket, whatever doesn't get written
 * append to the buffer... for a host with a fast net connection,
 * this prevents an unnecessary copy of the data
 * (the socket is non-blocking, so we won't hang)
 */
void sbappend(struct socket *so, struct mbuf *m)
{
    int ret = 0;

    DEBUG_CALL("sbappend");
    DEBUG_ARG("so = %p", so);
    DEBUG_ARG("m = %p", m);
    DEBUG_ARG("m->m_len = %d", m->m_len);

    /* Shouldn't happen, but...  e.g. foreign host closes connection */
    if (m->m_len <= 0) {
        m_free(m);
        return;
    }

    /*
     * If there is urgent data, call sosendoob
     * if not all was sent, sowrite will take care of the rest
     * (The rest of this function is just an optimisation)
     */
    if (so->so_urgc) {
        sbappendsb(&so->so_rcv, m);
        m_free(m);
        (void)sosendoob(so);
        return;
    }

    /*
     * We only write if there's nothing in the buffer,
     * ottherwise it'll arrive out of order, and hence corrupt
     */
    if (!so->so_rcv.sb_cc)
        ret = slirp_send(so, m->m_data, m->m_len, 0);

    if (ret <= 0) {
        /*
         * Nothing was written
         * It's possible that the socket has closed, but
         * we don't need to check because if it has closed,
         * it will be detected in the normal way by soread()
         */
        sbappendsb(&so->so_rcv, m);
    } else if (ret != m->m_len) {
        /*
         * Something was written, but not everything..
         * sbappendsb the rest
         */
        m->m_len -= ret;
        m->m_data += ret;
        sbappendsb(&so->so_rcv, m);
    } /* else */
    /* Whatever happened, we free the mbuf */
    m_free(m);
}

/*
 * Copy the data from m into sb
 * The caller is responsible to make sure there's enough room
 */
static void sbappendsb(struct sbuf *sb, struct mbuf *m)
{
    int len, n, nn;

    len = m->m_len;

    if (sb->sb_wptr < sb->sb_rptr) {
        n = sb->sb_rptr - sb->sb_wptr;
        if (n > len)
            n = len;
        memcpy(sb->sb_wptr, m->m_data, n);
    } else {
        /* Do the right edge first */
        n = sb->sb_data + sb->sb_datalen - sb->sb_wptr;
        if (n > len)
            n = len;
        memcpy(sb->sb_wptr, m->m_data, n);
        len -= n;
        if (len) {
            /* Now the left edge */
            nn = sb->sb_rptr - sb->sb_data;
            if (nn > len)
                nn = len;
            memcpy(sb->sb_data, m->m_data + n, nn);
            n += nn;
        }
    }

    sb->sb_cc += n;
    sb->sb_wptr += n;
    if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen)
        sb->sb_wptr -= sb->sb_datalen;
}

/*
 * Copy data from sbuf to a normal, straight buffer
 * Don't update the sbuf rptr, this will be
 * done in sbdrop when the data is acked
 */
void sbcopy(struct sbuf *sb, int off, int len, char *to)
{
    char *from;

    from = sb->sb_rptr + off;
    if (from >= sb->sb_data + sb->sb_datalen)
        from -= sb->sb_datalen;

    if (from < sb->sb_wptr) {
        if (len > sb->sb_cc)
            len = sb->sb_cc;
        memcpy(to, from, len);
    } else {
        /* re-use off */
        off = (sb->sb_data + sb->sb_datalen) - from;
        if (off > len)
            off = len;
        memcpy(to, from, off);
        len -= off;
        if (len)
            memcpy(to + off, sb->sb_data, len);
    }
}
