buffer.c revision 296465
1139743Simp#include "tunala.h"
239212Sgibbs
339212Sgibbs#ifndef NO_BUFFER
439212Sgibbs
539212Sgibbsvoid buffer_init(buffer_t * buf)
639212Sgibbs{
739212Sgibbs    buf->used = 0;
839212Sgibbs    buf->total_in = buf->total_out = 0;
939212Sgibbs}
1039212Sgibbs
1139212Sgibbsvoid buffer_close(buffer_t * buf)
1239212Sgibbs{
1339212Sgibbs    /* Our data is static - nothing needs "release", just reset it */
1439212Sgibbs    buf->used = 0;
1539212Sgibbs}
1639212Sgibbs
1739212Sgibbs/* Code these simple ones in compact form */
1839212Sgibbsunsigned int buffer_used(buffer_t * buf)
1939212Sgibbs{
2039212Sgibbs    return buf->used;
2139212Sgibbs}
2239212Sgibbs
2339212Sgibbsunsigned int buffer_unused(buffer_t * buf)
2439212Sgibbs{
2539212Sgibbs    return (MAX_DATA_SIZE - buf->used);
2639212Sgibbs}
2739212Sgibbs
2850477Speterint buffer_full(buffer_t * buf)
2939212Sgibbs{
3039212Sgibbs    return (buf->used == MAX_DATA_SIZE ? 1 : 0);
3139212Sgibbs}
3239212Sgibbs
3339212Sgibbsint buffer_notfull(buffer_t * buf)
3455206Speter{
3539212Sgibbs    return (buf->used < MAX_DATA_SIZE ? 1 : 0);
3639212Sgibbs}
3739212Sgibbs
3839212Sgibbsint buffer_empty(buffer_t * buf)
3939212Sgibbs{
4039212Sgibbs    return (buf->used == 0 ? 1 : 0);
4139212Sgibbs}
4239212Sgibbs
4339212Sgibbsint buffer_notempty(buffer_t * buf)
4439212Sgibbs{
4539212Sgibbs    return (buf->used > 0 ? 1 : 0);
4639212Sgibbs}
4739212Sgibbs
4839212Sgibbsunsigned long buffer_total_in(buffer_t * buf)
4939212Sgibbs{
5039212Sgibbs    return buf->total_in;
5139212Sgibbs}
5239212Sgibbs
5360938Sjakeunsigned long buffer_total_out(buffer_t * buf)
5460938Sjake{
5560938Sjake    return buf->total_out;
5639212Sgibbs}
5739212Sgibbs
5839212Sgibbs/*
5939212Sgibbs * These 3 static (internal) functions don't adjust the "total" variables as
6039212Sgibbs * it's not sure when they're called how it should be interpreted. Only the
6139212Sgibbs * higher-level "buffer_[to|from]_[fd|SSL|BIO]" functions should alter these
6239212Sgibbs * values.
6341813Sgibbs */
6439212Sgibbs# if 0                          /* To avoid "unused" warnings */
6539212Sgibbsstatic unsigned int buffer_adddata(buffer_t * buf, const unsigned char *ptr,
6639212Sgibbs                                   unsigned int size)
6739212Sgibbs{
6839212Sgibbs    unsigned int added = MAX_DATA_SIZE - buf->used;
6939212Sgibbs    if (added > size)
7039212Sgibbs        added = size;
7139212Sgibbs    if (added == 0)
7239212Sgibbs        return 0;
7339212Sgibbs    memcpy(buf->data + buf->used, ptr, added);
7439212Sgibbs    buf->used += added;
7539212Sgibbs    buf->total_in += added;
7639212Sgibbs    return added;
7739212Sgibbs}
7839212Sgibbs
7939212Sgibbsstatic unsigned int buffer_tobuffer(buffer_t * to, buffer_t * from, int cap)
8039212Sgibbs{
8139212Sgibbs    unsigned int moved, tomove = from->used;
8239212Sgibbs    if ((int)tomove > cap)
8339212Sgibbs        tomove = cap;
8439212Sgibbs    if (tomove == 0)
8539212Sgibbs        return 0;
8639212Sgibbs    moved = buffer_adddata(to, from->data, tomove);
8739212Sgibbs    if (moved == 0)
8839212Sgibbs        return 0;
8939212Sgibbs    buffer_takedata(from, NULL, moved);
9039212Sgibbs    return moved;
9139212Sgibbs}
9239212Sgibbs# endif
9339212Sgibbs
9439212Sgibbsstatic unsigned int buffer_takedata(buffer_t * buf, unsigned char *ptr,
9539212Sgibbs                                    unsigned int size)
9639212Sgibbs{
9739212Sgibbs    unsigned int taken = buf->used;
9839212Sgibbs    if (taken > size)
9939212Sgibbs        taken = size;
10039212Sgibbs    if (taken == 0)
10139212Sgibbs        return 0;
10239212Sgibbs    if (ptr)
10339212Sgibbs        memcpy(ptr, buf->data, taken);
10439212Sgibbs    buf->used -= taken;
10539212Sgibbs    /* Do we have to scroll? */
10639212Sgibbs    if (buf->used > 0)
10739212Sgibbs        memmove(buf->data, buf->data + taken, buf->used);
10839212Sgibbs    return taken;
10939212Sgibbs}
11039212Sgibbs
11139212Sgibbs# ifndef NO_IP
11239212Sgibbs
11339212Sgibbsint buffer_from_fd(buffer_t * buf, int fd)
11439212Sgibbs{
11539212Sgibbs    int toread = buffer_unused(buf);
11639212Sgibbs    if (toread == 0)
11739212Sgibbs        /* Shouldn't be called in this case! */
11839212Sgibbs        abort();
11939212Sgibbs    toread = read(fd, buf->data + buf->used, toread);
12039212Sgibbs    if (toread > 0) {
12139212Sgibbs        buf->used += toread;
12239212Sgibbs        buf->total_in += toread;
12339212Sgibbs    }
12439212Sgibbs    return toread;
12539212Sgibbs}
12639212Sgibbs
12739212Sgibbsint buffer_to_fd(buffer_t * buf, int fd)
12839212Sgibbs{
12939212Sgibbs    int towrite = buffer_used(buf);
13039212Sgibbs    if (towrite == 0)
13139212Sgibbs        /* Shouldn't be called in this case! */
13239212Sgibbs        abort();
13339212Sgibbs    towrite = write(fd, buf->data, towrite);
13439212Sgibbs    if (towrite > 0) {
13539212Sgibbs        buffer_takedata(buf, NULL, towrite);
13639212Sgibbs        buf->total_out += towrite;
13739212Sgibbs    }
13839212Sgibbs    return towrite;
13945844Sgibbs}
14039212Sgibbs
14145844Sgibbs# endif                         /* !defined(NO_IP) */
14245844Sgibbs
14345844Sgibbs# ifndef NO_OPENSSL
14439212Sgibbs
14539212Sgibbsstatic void int_ssl_check(SSL *s, int ret)
14639212Sgibbs{
14739212Sgibbs    int e = SSL_get_error(s, ret);
14839212Sgibbs    switch (e) {
14939212Sgibbs        /*
15039212Sgibbs         * These seem to be harmless and already "dealt with" by our
15139212Sgibbs         * non-blocking environment. NB: "ZERO_RETURN" is the clean "error"
15239212Sgibbs         * indicating a successfully closed SSL tunnel. We let this happen
15339212Sgibbs         * because our IO loop should not appear to have broken on this
15439212Sgibbs         * condition - and outside the IO loop, the "shutdown" state is
15539212Sgibbs         * checked.
15639212Sgibbs         */
15739212Sgibbs    case SSL_ERROR_NONE:
15839212Sgibbs    case SSL_ERROR_WANT_READ:
15939212Sgibbs    case SSL_ERROR_WANT_WRITE:
16039212Sgibbs    case SSL_ERROR_WANT_X509_LOOKUP:
16139212Sgibbs    case SSL_ERROR_ZERO_RETURN:
16239212Sgibbs        return;
16339212Sgibbs        /*
16439212Sgibbs         * These seem to be indications of a genuine error that should result
16539212Sgibbs         * in the SSL tunnel being regarded as "dead".
16639212Sgibbs         */
16739212Sgibbs    case SSL_ERROR_SYSCALL:
16839212Sgibbs    case SSL_ERROR_SSL:
16939212Sgibbs        SSL_set_app_data(s, (char *)1);
17039212Sgibbs        return;
17139212Sgibbs    default:
17239212Sgibbs        break;
17339212Sgibbs    }
17439212Sgibbs    /*
17539212Sgibbs     * For any other errors that (a) exist, and (b) crop up - we need to
17639212Sgibbs     * interpret what to do with them - so "politely inform" the caller that
17739212Sgibbs     * the code needs updating here.
17839212Sgibbs     */
17939212Sgibbs    abort();
18039212Sgibbs}
18139212Sgibbs
18239212Sgibbsvoid buffer_from_SSL(buffer_t * buf, SSL *ssl)
18339212Sgibbs{
18439212Sgibbs    int ret;
18539212Sgibbs    if (!ssl || buffer_full(buf))
18639212Sgibbs        return;
18739212Sgibbs    ret = SSL_read(ssl, buf->data + buf->used, buffer_unused(buf));
18839212Sgibbs    if (ret > 0) {
18939212Sgibbs        buf->used += ret;
19039212Sgibbs        buf->total_in += ret;
19139212Sgibbs    }
19239212Sgibbs    if (ret < 0)
19339212Sgibbs        int_ssl_check(ssl, ret);
19439212Sgibbs}
19539212Sgibbs
19639212Sgibbsvoid buffer_to_SSL(buffer_t * buf, SSL *ssl)
19739212Sgibbs{
19839212Sgibbs    int ret;
19939212Sgibbs    if (!ssl || buffer_empty(buf))
20039212Sgibbs        return;
20139212Sgibbs    ret = SSL_write(ssl, buf->data, buf->used);
20239212Sgibbs    if (ret > 0) {
20339212Sgibbs        buffer_takedata(buf, NULL, ret);
20439212Sgibbs        buf->total_out += ret;
20539212Sgibbs    }
20639212Sgibbs    if (ret < 0)
20739212Sgibbs        int_ssl_check(ssl, ret);
20839212Sgibbs}
20939212Sgibbs
21039212Sgibbsvoid buffer_from_BIO(buffer_t * buf, BIO *bio)
21139212Sgibbs{
21239212Sgibbs    int ret;
21339212Sgibbs    if (!bio || buffer_full(buf))
21439212Sgibbs        return;
21539212Sgibbs    ret = BIO_read(bio, buf->data + buf->used, buffer_unused(buf));
21639212Sgibbs    if (ret > 0) {
21739212Sgibbs        buf->used += ret;
21839212Sgibbs        buf->total_in += ret;
21939212Sgibbs    }
22039212Sgibbs}
22139212Sgibbs
22239212Sgibbsvoid buffer_to_BIO(buffer_t * buf, BIO *bio)
22339212Sgibbs{
22439212Sgibbs    int ret;
22539212Sgibbs    if (!bio || buffer_empty(buf))
22639212Sgibbs        return;
22739212Sgibbs    ret = BIO_write(bio, buf->data, buf->used);
22839212Sgibbs    if (ret > 0) {
22939212Sgibbs        buffer_takedata(buf, NULL, ret);
23039212Sgibbs        buf->total_out += ret;
23139212Sgibbs    }
23239212Sgibbs}
23339212Sgibbs
23439212Sgibbs# endif                         /* !defined(NO_OPENSSL) */
23539212Sgibbs
23639212Sgibbs#endif                          /* !defined(NO_BUFFER) */
23755206Speter