Home | History | Annotate | Download | only in src
      1 /*
      2  * test-bio.c - BIO layer for testing
      3  *
      4  * Copyright (c) 2012 The Chromium Authors. All rights reserved.
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  *
      8  * This is a 'source/sink' BIO which supports synthetic inputs and outputs, and
      9  * can be used to drive filter BIOs through a state machine. It buffers all
     10  * output sent to it, which can be retrieved with BIO_test_get_output(), and
     11  * input sent to it, which is handed back in response to BIO_read() by the
     12  * filter BIO.
     13  */
     14 
     15 #include <assert.h>
     16 #include <string.h>
     17 
     18 #include "src/test-bio.h"
     19 #include "src/util.h"
     20 
     21 int verbose;
     22 int verbose_debug;
     23 
     24 static const unsigned int kMagic = 0x5f8d3f15;
     25 
     26 struct test_ctx
     27 {
     28   unsigned int magic;
     29   unsigned char *out;
     30   size_t outsz;
     31   unsigned char *in;
     32   size_t insz;
     33 };
     34 
     35 static struct test_ctx *bio_ctx (BIO *b)
     36 {
     37   struct test_ctx *ctx = b->ptr;
     38   assert (ctx->magic == kMagic);
     39   return ctx;
     40 }
     41 
     42 static size_t buf_drain (unsigned char **buf, size_t *bufsz,
     43                          unsigned char *out, size_t outsz)
     44 {
     45   if (*bufsz < outsz)
     46     outsz = *bufsz;
     47   memcpy (out, *buf, outsz);
     48   if (*bufsz > outsz)
     49     memmove (*buf, *buf + outsz, *bufsz - outsz);
     50   *bufsz -= outsz;
     51   *buf = realloc (*buf, *bufsz);
     52   return outsz;
     53 }
     54 
     55 static void buf_fill (unsigned char **buf, size_t *bufsz,
     56                       const unsigned char *in, size_t insz)
     57 {
     58   *buf = realloc (*buf, *bufsz + insz);
     59   memcpy (*buf + *bufsz, in, insz);
     60   *bufsz += insz;
     61 }
     62 
     63 int test_new (BIO *b)
     64 {
     65   struct test_ctx *ctx = malloc (sizeof *ctx);
     66   if (!ctx)
     67     return 0;
     68   ctx->magic = kMagic;
     69   ctx->in = NULL;
     70   ctx->insz = 0;
     71   ctx->out = NULL;
     72   ctx->outsz = 0;
     73   b->init = 1;
     74   b->flags = 0;
     75   b->ptr = ctx;
     76   return 1;
     77 }
     78 
     79 int test_free (BIO *b)
     80 {
     81   struct test_ctx *ctx;
     82   if (!b || !b->ptr)
     83     return 1;
     84   ctx = bio_ctx (b);
     85   free (ctx->in);
     86   free (ctx->out);
     87   return 1;
     88 }
     89 
     90 int test_write (BIO *b, const char *buf, int sz)
     91 {
     92   struct test_ctx *ctx = bio_ctx (b);
     93   if (sz <= 0)
     94     return 0;
     95   buf_fill (&ctx->out, &ctx->outsz, (unsigned char *) buf, sz);
     96   return sz;
     97 }
     98 
     99 int test_read (BIO *b, char *buf, int sz)
    100 {
    101   struct test_ctx *ctx = bio_ctx (b);
    102   if (sz <= 0)
    103     return 0;
    104   return buf_drain (&ctx->in, &ctx->insz, (unsigned char *) buf, sz);
    105 }
    106 
    107 long test_ctrl (BIO *b, int cmd, long num, void *ptr)
    108 {
    109   return 0;
    110 }
    111 
    112 long test_callback_ctrl (BIO *b, int cmd, bio_info_cb fp)
    113 {
    114   return 0;
    115 }
    116 
    117 BIO_METHOD test_methods =
    118 {
    119   BIO_TYPE_SOCKET,
    120   "test",
    121   test_write,
    122   test_read,
    123   NULL,
    124   NULL,
    125   test_ctrl,
    126   test_new,
    127   test_free,
    128   test_callback_ctrl,
    129 };
    130 
    131 BIO_METHOD *BIO_s_test()
    132 {
    133   return &test_methods;
    134 }
    135 
    136 BIO API *BIO_new_test()
    137 {
    138   return BIO_new (BIO_s_test());
    139 }
    140 
    141 size_t API BIO_test_output_left (BIO *b)
    142 {
    143   return bio_ctx (b)->outsz;
    144 }
    145 
    146 size_t API BIO_test_get_output (BIO *b, unsigned char *buf, size_t bufsz)
    147 {
    148   struct test_ctx *c = bio_ctx (b);
    149   return buf_drain (&c->out, &c->outsz, buf, bufsz);
    150 }
    151 
    152 void API BIO_test_add_input (BIO *b, const unsigned char *buf, size_t bufsz)
    153 {
    154   struct test_ctx *c = bio_ctx (b);
    155   return buf_fill (&c->in, &c->insz, buf, bufsz);
    156 }
    157