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