2 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
13 #include "internal/cryptlib.h"
15 static int buffer_write(BIO
*h
, const char *buf
, int num
);
16 static int buffer_read(BIO
*h
, char *buf
, int size
);
17 static int buffer_puts(BIO
*h
, const char *str
);
18 static int buffer_gets(BIO
*h
, char *str
, int size
);
19 static long buffer_ctrl(BIO
*h
, int cmd
, long arg1
, void *arg2
);
20 static int buffer_new(BIO
*h
);
21 static int buffer_free(BIO
*data
);
22 static long buffer_callback_ctrl(BIO
*h
, int cmd
, BIO_info_cb
*fp
);
23 #define DEFAULT_BUFFER_SIZE 4096
25 static const BIO_METHOD methods_buffer
= {
28 /* TODO: Convert to new style write function */
31 /* TODO: Convert to new style read function */
42 const BIO_METHOD
*BIO_f_buffer(void)
44 return &methods_buffer
;
47 static int buffer_new(BIO
*bi
)
49 BIO_F_BUFFER_CTX
*ctx
= OPENSSL_zalloc(sizeof(*ctx
));
53 ctx
->ibuf_size
= DEFAULT_BUFFER_SIZE
;
54 ctx
->ibuf
= OPENSSL_malloc(DEFAULT_BUFFER_SIZE
);
55 if (ctx
->ibuf
== NULL
) {
59 ctx
->obuf_size
= DEFAULT_BUFFER_SIZE
;
60 ctx
->obuf
= OPENSSL_malloc(DEFAULT_BUFFER_SIZE
);
61 if (ctx
->obuf
== NULL
) {
62 OPENSSL_free(ctx
->ibuf
);
68 bi
->ptr
= (char *)ctx
;
73 static int buffer_free(BIO
*a
)
79 b
= (BIO_F_BUFFER_CTX
*)a
->ptr
;
80 OPENSSL_free(b
->ibuf
);
81 OPENSSL_free(b
->obuf
);
89 static int buffer_read(BIO
*b
, char *out
, int outl
)
92 BIO_F_BUFFER_CTX
*ctx
;
96 ctx
= (BIO_F_BUFFER_CTX
*)b
->ptr
;
98 if ((ctx
== NULL
) || (b
->next_bio
== NULL
))
101 BIO_clear_retry_flags(b
);
105 /* If there is stuff left over, grab it */
109 memcpy(out
, &(ctx
->ibuf
[ctx
->ibuf_off
]), i
);
120 * We may have done a partial read. try to do more. We have nothing in
121 * the buffer. If we get an error and have read some data, just return it
122 * and let them retry to get the error again. copy direct to parent
125 if (outl
> ctx
->ibuf_size
) {
127 i
= BIO_read(b
->next_bio
, out
, outl
);
129 BIO_copy_next_retry(b
);
131 return ((num
> 0) ? num
: i
);
144 /* we are going to be doing some buffering */
145 i
= BIO_read(b
->next_bio
, ctx
->ibuf
, ctx
->ibuf_size
);
147 BIO_copy_next_retry(b
);
149 return ((num
> 0) ? num
: i
);
156 /* Lets re-read using ourselves :-) */
160 static int buffer_write(BIO
*b
, const char *in
, int inl
)
163 BIO_F_BUFFER_CTX
*ctx
;
165 if ((in
== NULL
) || (inl
<= 0))
167 ctx
= (BIO_F_BUFFER_CTX
*)b
->ptr
;
168 if ((ctx
== NULL
) || (b
->next_bio
== NULL
))
171 BIO_clear_retry_flags(b
);
173 i
= ctx
->obuf_size
- (ctx
->obuf_len
+ ctx
->obuf_off
);
174 /* add to buffer and return */
176 memcpy(&(ctx
->obuf
[ctx
->obuf_off
+ ctx
->obuf_len
]), in
, inl
);
177 ctx
->obuf_len
+= inl
;
181 /* stuff already in buffer, so add to it first, then flush */
182 if (ctx
->obuf_len
!= 0) {
183 if (i
> 0) { /* lets fill it up if we can */
184 memcpy(&(ctx
->obuf
[ctx
->obuf_off
+ ctx
->obuf_len
]), in
, i
);
190 /* we now have a full buffer needing flushing */
192 i
= BIO_write(b
->next_bio
, &(ctx
->obuf
[ctx
->obuf_off
]),
195 BIO_copy_next_retry(b
);
198 return ((num
> 0) ? num
: i
);
204 if (ctx
->obuf_len
== 0)
209 * we only get here if the buffer has been flushed and we still have
214 /* we now have inl bytes to write */
215 while (inl
>= ctx
->obuf_size
) {
216 i
= BIO_write(b
->next_bio
, in
, inl
);
218 BIO_copy_next_retry(b
);
220 return ((num
> 0) ? num
: i
);
232 * copy the rest into the buffer since we have only a small amount left
237 static long buffer_ctrl(BIO
*b
, int cmd
, long num
, void *ptr
)
240 BIO_F_BUFFER_CTX
*ctx
;
246 ctx
= (BIO_F_BUFFER_CTX
*)b
->ptr
;
254 if (b
->next_bio
== NULL
)
256 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
259 if (ctx
->ibuf_len
> 0)
261 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
264 ret
= (long)ctx
->obuf_len
;
266 case BIO_C_GET_BUFF_NUM_LINES
:
269 for (i
= 0; i
< ctx
->ibuf_len
; i
++) {
270 if (p1
[ctx
->ibuf_off
+ i
] == '\n')
274 case BIO_CTRL_WPENDING
:
275 ret
= (long)ctx
->obuf_len
;
277 if (b
->next_bio
== NULL
)
279 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
282 case BIO_CTRL_PENDING
:
283 ret
= (long)ctx
->ibuf_len
;
285 if (b
->next_bio
== NULL
)
287 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
290 case BIO_C_SET_BUFF_READ_DATA
:
291 if (num
> ctx
->ibuf_size
) {
292 p1
= OPENSSL_malloc((int)num
);
295 OPENSSL_free(ctx
->ibuf
);
299 ctx
->ibuf_len
= (int)num
;
300 memcpy(ctx
->ibuf
, ptr
, (int)num
);
303 case BIO_C_SET_BUFF_SIZE
:
308 obs
= ctx
->obuf_size
;
309 } else { /* if (*ip == 1) */
311 ibs
= ctx
->ibuf_size
;
320 if ((ibs
> DEFAULT_BUFFER_SIZE
) && (ibs
!= ctx
->ibuf_size
)) {
321 p1
= OPENSSL_malloc((int)num
);
325 if ((obs
> DEFAULT_BUFFER_SIZE
) && (obs
!= ctx
->obuf_size
)) {
326 p2
= OPENSSL_malloc((int)num
);
333 if (ctx
->ibuf
!= p1
) {
334 OPENSSL_free(ctx
->ibuf
);
338 ctx
->ibuf_size
= ibs
;
340 if (ctx
->obuf
!= p2
) {
341 OPENSSL_free(ctx
->obuf
);
345 ctx
->obuf_size
= obs
;
348 case BIO_C_DO_STATE_MACHINE
:
349 if (b
->next_bio
== NULL
)
351 BIO_clear_retry_flags(b
);
352 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
353 BIO_copy_next_retry(b
);
357 if (b
->next_bio
== NULL
)
359 if (ctx
->obuf_len
<= 0) {
360 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
365 BIO_clear_retry_flags(b
);
366 if (ctx
->obuf_len
> 0) {
367 r
= BIO_write(b
->next_bio
,
368 &(ctx
->obuf
[ctx
->obuf_off
]), ctx
->obuf_len
);
369 BIO_copy_next_retry(b
);
380 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
384 if (!BIO_set_read_buffer_size(dbio
, ctx
->ibuf_size
) ||
385 !BIO_set_write_buffer_size(dbio
, ctx
->obuf_size
))
389 /* Ensure there's stuff in the input buffer */
392 (void)buffer_read(b
, fake_buf
, 0);
394 if (num
> ctx
->ibuf_len
)
396 memcpy(ptr
, &(ctx
->ibuf
[ctx
->ibuf_off
]), num
);
400 if (b
->next_bio
== NULL
)
402 ret
= BIO_ctrl(b
->next_bio
, cmd
, num
, ptr
);
407 BIOerr(BIO_F_BUFFER_CTRL
, ERR_R_MALLOC_FAILURE
);
411 static long buffer_callback_ctrl(BIO
*b
, int cmd
, BIO_info_cb
*fp
)
415 if (b
->next_bio
== NULL
)
419 ret
= BIO_callback_ctrl(b
->next_bio
, cmd
, fp
);
425 static int buffer_gets(BIO
*b
, char *buf
, int size
)
427 BIO_F_BUFFER_CTX
*ctx
;
428 int num
= 0, i
, flag
;
431 ctx
= (BIO_F_BUFFER_CTX
*)b
->ptr
;
432 size
--; /* reserve space for a '\0' */
433 BIO_clear_retry_flags(b
);
436 if (ctx
->ibuf_len
> 0) {
437 p
= &(ctx
->ibuf
[ctx
->ibuf_off
]);
439 for (i
= 0; (i
< ctx
->ibuf_len
) && (i
< size
); i
++) {
451 if (flag
|| size
== 0) {
455 } else { /* read another chunk */
457 i
= BIO_read(b
->next_bio
, ctx
->ibuf
, ctx
->ibuf_size
);
459 BIO_copy_next_retry(b
);
462 return ((num
> 0) ? num
: i
);
472 static int buffer_puts(BIO
*b
, const char *str
)
474 return buffer_write(b
, str
, strlen(str
));