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
bio_ctx(BIO * b)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
buf_drain(unsigned char ** buf,size_t * bufsz,unsigned char * out,size_t outsz)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
buf_fill(unsigned char ** buf,size_t * bufsz,const unsigned char * in,size_t insz)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
test_new(BIO * b)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
test_free(BIO * b)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
test_write(BIO * b,const char * buf,int sz)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
test_read(BIO * b,char * buf,int sz)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
test_ctrl(BIO * b,int cmd,long num,void * ptr)107 long test_ctrl (BIO *b, int cmd, long num, void *ptr)
108 {
109 return 0;
110 }
111
test_callback_ctrl(BIO * b,int cmd,bio_info_cb fp)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
BIO_s_test()131 BIO_METHOD *BIO_s_test()
132 {
133 return &test_methods;
134 }
135
BIO_new_test()136 BIO API *BIO_new_test()
137 {
138 return BIO_new (BIO_s_test());
139 }
140
BIO_test_output_left(BIO * b)141 size_t API BIO_test_output_left (BIO *b)
142 {
143 return bio_ctx (b)->outsz;
144 }
145
BIO_test_get_output(BIO * b,unsigned char * buf,size_t bufsz)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
BIO_test_add_input(BIO * b,const unsigned char * buf,size_t bufsz)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