⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bss_bio.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* crypto/bio/bss_bio.c  -*- Mode: C; c-file-style: "eay" -*- *//* ==================================================================== * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer.  * * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *    the documentation and/or other materials provided with the *    distribution. * * 3. All advertising materials mentioning features or use of this *    software must display the following acknowledgment: *    "This product includes software developed by the OpenSSL Project *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to *    endorse or promote products derived from this software without *    prior written permission. For written permission, please contact *    openssl-core@openssl.org. * * 5. Products derived from this software may not be called "OpenSSL" *    nor may "OpenSSL" appear in their names without prior written *    permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following *    acknowledgment: *    "This product includes software developed by the OpenSSL Project *    for use in the OpenSSL Toolkit (http://www.openssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This product includes cryptographic software written by Eric Young * (eay@cryptsoft.com).  This product includes software written by Tim * Hudson (tjh@cryptsoft.com). * *//* Special method for a BIO where the other endpoint is also a BIO * of this kind, handled by the same thread (i.e. the "peer" is actually * ourselves, wearing a different hat). * Such "BIO pairs" are mainly for using the SSL library with I/O interfaces * for which no specific BIO method is available. * See ssl/ssltest.c for some hints on how this can be used. *//* BIO_DEBUG implies BIO_PAIR_DEBUG */#ifdef BIO_DEBUG# ifndef BIO_PAIR_DEBUG#  define BIO_PAIR_DEBUG# endif#endif/* disable assert() unless BIO_PAIR_DEBUG has been defined */#ifndef BIO_PAIR_DEBUG# ifndef NDEBUG#  define NDEBUG# endif#endif#include <assert.h>#include <limits.h>#include <stdlib.h>#include <string.h>#include <openssl/bio.h>#include <openssl/err.h>#include <openssl/crypto.h>#include "e_os.h"/* VxWorks defines SSIZE_MAX with an empty value causing compile errors */#if defined(OPENSSL_SYS_VXWORKS)# undef SSIZE_MAX#endif#ifndef SSIZE_MAX# define SSIZE_MAX INT_MAX#endifstatic int bio_new(BIO *bio);static int bio_free(BIO *bio);static int bio_read(BIO *bio, char *buf, int size);static int bio_write(BIO *bio, const char *buf, int num);static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr);static int bio_puts(BIO *bio, const char *str);static int bio_make_pair(BIO *bio1, BIO *bio2);static void bio_destroy_pair(BIO *bio);static BIO_METHOD methods_biop ={	BIO_TYPE_BIO,	"BIO pair",	bio_write,	bio_read,	bio_puts,	NULL /* no bio_gets */,	bio_ctrl,	bio_new,	bio_free,	NULL /* no bio_callback_ctrl */};BIO_METHOD *BIO_s_bio(void)	{	return &methods_biop;	}struct bio_bio_st{	BIO *peer;     /* NULL if buf == NULL.	                * If peer != NULL, then peer->ptr is also a bio_bio_st,	                * and its "peer" member points back to us.	                * peer != NULL iff init != 0 in the BIO. */		/* This is for what we write (i.e. reading uses peer's struct): */	int closed;     /* valid iff peer != NULL */	size_t len;     /* valid iff buf != NULL; 0 if peer == NULL */	size_t offset;  /* valid iff buf != NULL; 0 if len == 0 */	size_t size;	char *buf;      /* "size" elements (if != NULL) */	size_t request; /* valid iff peer != NULL; 0 if len != 0,	                 * otherwise set by peer to number of bytes	                 * it (unsuccessfully) tried to read,	                 * never more than buffer space (size-len) warrants. */};static int bio_new(BIO *bio)	{	struct bio_bio_st *b;		b = OPENSSL_malloc(sizeof *b);	if (b == NULL)		return 0;	b->peer = NULL;	b->size = 17*1024; /* enough for one TLS record (just a default) */	b->buf = NULL;	bio->ptr = b;	return 1;	}static int bio_free(BIO *bio)	{	struct bio_bio_st *b;	if (bio == NULL)		return 0;	b = bio->ptr;	assert(b != NULL);	if (b->peer)		bio_destroy_pair(bio);		if (b->buf != NULL)		{		OPENSSL_free(b->buf);		}	OPENSSL_free(b);	return 1;	}static int bio_read(BIO *bio, char *buf, int size_)	{	size_t size = size_;	size_t rest;	struct bio_bio_st *b, *peer_b;	BIO_clear_retry_flags(bio);	if (!bio->init)		return 0;	b = bio->ptr;	assert(b != NULL);	assert(b->peer != NULL);	peer_b = b->peer->ptr;	assert(peer_b != NULL);	assert(peer_b->buf != NULL);	peer_b->request = 0; /* will be set in "retry_read" situation */	if (buf == NULL || size == 0)		return 0;	if (peer_b->len == 0)		{		if (peer_b->closed)			return 0; /* writer has closed, and no data is left */		else			{			BIO_set_retry_read(bio); /* buffer is empty */			if (size <= peer_b->size)				peer_b->request = size;			else				/* don't ask for more than the peer can				 * deliver in one write */				peer_b->request = peer_b->size;			return -1;			}		}	/* we can read */	if (peer_b->len < size)		size = peer_b->len;	/* now read "size" bytes */		rest = size;		assert(rest > 0);	do /* one or two iterations */		{		size_t chunk;				assert(rest <= peer_b->len);		if (peer_b->offset + rest <= peer_b->size)			chunk = rest;		else			/* wrap around ring buffer */			chunk = peer_b->size - peer_b->offset;		assert(peer_b->offset + chunk <= peer_b->size);				memcpy(buf, peer_b->buf + peer_b->offset, chunk);				peer_b->len -= chunk;		if (peer_b->len)			{			peer_b->offset += chunk;			assert(peer_b->offset <= peer_b->size);			if (peer_b->offset == peer_b->size)				peer_b->offset = 0;			buf += chunk;			}		else			{			/* buffer now empty, no need to advance "buf" */			assert(chunk == rest);			peer_b->offset = 0;			}		rest -= chunk;		}	while (rest);		return size;	}/* non-copying interface: provide pointer to available data in buffer *    bio_nread0:  return number of available bytes *    bio_nread:   also advance index * (example usage:  bio_nread0(), read from buffer, bio_nread() *  or just         bio_nread(), read from buffer) *//* WARNING: The non-copying interface is largely untested as of yet * and may contain bugs. */static ssize_t bio_nread0(BIO *bio, char **buf)	{	struct bio_bio_st *b, *peer_b;	ssize_t num;		BIO_clear_retry_flags(bio);	if (!bio->init)		return 0;		b = bio->ptr;	assert(b != NULL);	assert(b->peer != NULL);	peer_b = b->peer->ptr;	assert(peer_b != NULL);	assert(peer_b->buf != NULL);		peer_b->request = 0;		if (peer_b->len == 0)		{		char dummy;				/* avoid code duplication -- nothing available for reading */		return bio_read(bio, &dummy, 1); /* returns 0 or -1 */		}	num = peer_b->len;	if (peer_b->size < peer_b->offset + num)		/* no ring buffer wrap-around for non-copying interface */		num = peer_b->size - peer_b->offset;	assert(num > 0);	if (buf != NULL)		*buf = peer_b->buf + peer_b->offset;	return num;	}static ssize_t bio_nread(BIO *bio, char **buf, size_t num_)	{	struct bio_bio_st *b, *peer_b;	ssize_t num, available;	if (num_ > SSIZE_MAX)		num = SSIZE_MAX;	else		num = (ssize_t)num_;	available = bio_nread0(bio, buf);	if (num > available)		num = available;	if (num <= 0)		return num;	b = bio->ptr;	peer_b = b->peer->ptr;	peer_b->len -= num;	if (peer_b->len) 		{		peer_b->offset += num;		assert(peer_b->offset <= peer_b->size);		if (peer_b->offset == peer_b->size)			peer_b->offset = 0;		}	else		peer_b->offset = 0;	return num;	}static int bio_write(BIO *bio, const char *buf, int num_)	{	size_t num = num_;	size_t rest;	struct bio_bio_st *b;	BIO_clear_retry_flags(bio);	if (!bio->init || buf == NULL || num == 0)		return 0;	b = bio->ptr;			assert(b != NULL);	assert(b->peer != NULL);	assert(b->buf != NULL);	b->request = 0;	if (b->closed)		{		/* we already closed */		BIOerr(BIO_F_BIO_WRITE, BIO_R_BROKEN_PIPE);		return -1;		}	assert(b->len <= b->size);	if (b->len == b->size)		{		BIO_set_retry_write(bio); /* buffer is full */		return -1;		}	/* we can write */	if (num > b->size - b->len)		num = b->size - b->len;		/* now write "num" bytes */	rest = num;		assert(rest > 0);	do /* one or two iterations */		{		size_t write_offset;		size_t chunk;		assert(b->len + rest <= b->size);		write_offset = b->offset + b->len;		if (write_offset >= b->size)			write_offset -= b->size;		/* b->buf[write_offset] is the first byte we can write to. */		if (write_offset + rest <= b->size)			chunk = rest;		else			/* wrap around ring buffer */			chunk = b->size - write_offset;				memcpy(b->buf + write_offset, buf, chunk);				b->len += chunk;		assert(b->len <= b->size);				rest -= chunk;		buf += chunk;		}	while (rest);	return num;	}/* non-copying interface: provide pointer to region to write to *   bio_nwrite0:  check how much space is available *   bio_nwrite:   also increase length * (example usage:  bio_nwrite0(), write to buffer, bio_nwrite() *  or just         bio_nwrite(), write to buffer) */static ssize_t bio_nwrite0(BIO *bio, char **buf)	{	struct bio_bio_st *b;	size_t num;	size_t write_offset;	BIO_clear_retry_flags(bio);	if (!bio->init)		return 0;	b = bio->ptr;			assert(b != NULL);	assert(b->peer != NULL);	assert(b->buf != NULL);	b->request = 0;	if (b->closed)		{		BIOerr(BIO_F_BIO_NWRITE0, BIO_R_BROKEN_PIPE);		return -1;		}	assert(b->len <= b->size);	if (b->len == b->size)		{		BIO_set_retry_write(bio);		return -1;		}	num = b->size - b->len;	write_offset = b->offset + b->len;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -