/*
 * test-bio.c - BIO layer for testing
 *
 * Copyright (c) 2012 The Chromium Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * This is a 'source/sink' BIO which supports synthetic inputs and outputs, and
 * can be used to drive filter BIOs through a state machine. It buffers all
 * output sent to it, which can be retrieved with BIO_test_get_output(), and
 * input sent to it, which is handed back in response to BIO_read() by the
 * filter BIO.
 */

#include <assert.h>
#include <string.h>

#include "src/test-bio.h"
#include "src/util.h"

int verbose;
int verbose_debug;

static const unsigned int kMagic = 0x5f8d3f15;

struct test_ctx
{
  unsigned int magic;
  unsigned char *out;
  size_t outsz;
  unsigned char *in;
  size_t insz;
};

static struct test_ctx *bio_ctx (BIO *b)
{
  struct test_ctx *ctx = b->ptr;
  assert (ctx->magic == kMagic);
  return ctx;
}

static size_t buf_drain (unsigned char **buf, size_t *bufsz,
                         unsigned char *out, size_t outsz)
{
  if (*bufsz < outsz)
    outsz = *bufsz;
  memcpy (out, *buf, outsz);
  if (*bufsz > outsz)
    memmove (*buf, *buf + outsz, *bufsz - outsz);
  *bufsz -= outsz;
  *buf = realloc (*buf, *bufsz);
  return outsz;
}

static void buf_fill (unsigned char **buf, size_t *bufsz,
                      const unsigned char *in, size_t insz)
{
  *buf = realloc (*buf, *bufsz + insz);
  memcpy (*buf + *bufsz, in, insz);
  *bufsz += insz;
}

int test_new (BIO *b)
{
  struct test_ctx *ctx = malloc (sizeof *ctx);
  if (!ctx)
    return 0;
  ctx->magic = kMagic;
  ctx->in = NULL;
  ctx->insz = 0;
  ctx->out = NULL;
  ctx->outsz = 0;
  b->init = 1;
  b->flags = 0;
  b->ptr = ctx;
  return 1;
}

int test_free (BIO *b)
{
  struct test_ctx *ctx;
  if (!b || !b->ptr)
    return 1;
  ctx = bio_ctx (b);
  free (ctx->in);
  free (ctx->out);
  return 1;
}

int test_write (BIO *b, const char *buf, int sz)
{
  struct test_ctx *ctx = bio_ctx (b);
  if (sz <= 0)
    return 0;
  buf_fill (&ctx->out, &ctx->outsz, (unsigned char *) buf, sz);
  return sz;
}

int test_read (BIO *b, char *buf, int sz)
{
  struct test_ctx *ctx = bio_ctx (b);
  if (sz <= 0)
    return 0;
  return buf_drain (&ctx->in, &ctx->insz, (unsigned char *) buf, sz);
}

long test_ctrl (BIO *b, int cmd, long num, void *ptr)
{
  return 0;
}

long test_callback_ctrl (BIO *b, int cmd, bio_info_cb fp)
{
  return 0;
}

BIO_METHOD test_methods =
{
  BIO_TYPE_SOCKET,
  "test",
  test_write,
  test_read,
  NULL,
  NULL,
  test_ctrl,
  test_new,
  test_free,
  test_callback_ctrl,
};

BIO_METHOD *BIO_s_test()
{
  return &test_methods;
}

BIO API *BIO_new_test()
{
  return BIO_new (BIO_s_test());
}

size_t API BIO_test_output_left (BIO *b)
{
  return bio_ctx (b)->outsz;
}

size_t API BIO_test_get_output (BIO *b, unsigned char *buf, size_t bufsz)
{
  struct test_ctx *c = bio_ctx (b);
  return buf_drain (&c->out, &c->outsz, buf, bufsz);
}

void API BIO_test_add_input (BIO *b, const unsigned char *buf, size_t bufsz)
{
  struct test_ctx *c = bio_ctx (b);
  return buf_fill (&c->in, &c->insz, buf, bufsz);
}
