/* crypto/bio/bf_nbio.c */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
 * All rights reserved.
 *
 * This package is an SSL implementation written
 * by Eric Young (eay@cryptsoft.com).
 * The implementation was written so as to conform with Netscapes SSL.
 * 
 * This library is free for commercial and non-commercial use as long as
 * the following conditions are aheared to.  The following conditions
 * apply to all code found in this distribution, be it the RC4, RSA,
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
 * included with this distribution is covered by the same copyright terms
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
 * 
 * Copyright remains Eric Young's, and as such any Copyright notices in
 * the code are not to be removed.
 * If this package is used in a product, Eric Young should be given attribution
 * as the author of the parts of the library used.
 * This can be in the form of a textual message at program startup or
 * in documentation (online or textual) provided with the package.
 * 
 * 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 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 acknowledgement:
 *    "This product includes cryptographic software written by
 *     Eric Young (eay@cryptsoft.com)"
 *    The word 'cryptographic' can be left out if the rouines from the library
 *    being used are not cryptographic related :-).
 * 4. If you include any Windows specific code (or a derivative thereof) from 
 *    the apps directory (application code) you must include an acknowledgement:
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
 * 
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
 * ANY EXPRESS 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 AUTHOR OR 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.
 * 
 * The licence and distribution terms for any publically available version or
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
 * copied and put under another distribution licence
 * [including the GNU Public Licence.]
 */

#include <stdio.h>
#include <errno.h>
#include "cryptlib.h"
#include <openssl/rand.h>
#include <openssl/bio.h>

/* BIO_put and BIO_get both add to the digest,
 * BIO_gets returns the digest */

static int nbiof_write(BIO *h,const char *buf,int num);
static int nbiof_read(BIO *h,char *buf,int size);
static int nbiof_puts(BIO *h,const char *str);
static int nbiof_gets(BIO *h,char *str,int size);
static long nbiof_ctrl(BIO *h,int cmd,long arg1,void *arg2);
static int nbiof_new(BIO *h);
static int nbiof_free(BIO *data);
static long nbiof_callback_ctrl(BIO *h,int cmd,bio_info_cb *fp);
typedef struct nbio_test_st
	{
	/* only set if we sent a 'should retry' error */
	int lrn;
	int lwn;
	} NBIO_TEST;

static BIO_METHOD methods_nbiof=
	{
	BIO_TYPE_NBIO_TEST,
	"non-blocking IO test filter",
	nbiof_write,
	nbiof_read,
	nbiof_puts,
	nbiof_gets,
	nbiof_ctrl,
	nbiof_new,
	nbiof_free,
	nbiof_callback_ctrl,
	};

BIO_METHOD *BIO_f_nbio_test(void)
	{
	return(&methods_nbiof);
	}

static int nbiof_new(BIO *bi)
	{
	NBIO_TEST *nt;

	if (!(nt=(NBIO_TEST *)OPENSSL_malloc(sizeof(NBIO_TEST)))) return(0);
	nt->lrn= -1;
	nt->lwn= -1;
	bi->ptr=(char *)nt;
	bi->init=1;
	bi->flags=0;
	return(1);
	}

static int nbiof_free(BIO *a)
	{
	if (a == NULL) return(0);
	if (a->ptr != NULL)
		OPENSSL_free(a->ptr);
	a->ptr=NULL;
	a->init=0;
	a->flags=0;
	return(1);
	}
	
static int nbiof_read(BIO *b, char *out, int outl)
	{
	NBIO_TEST *nt;
	int ret=0;
#if 1
	int num;
	unsigned char n;
#endif

	if (out == NULL) return(0);
	if (b->next_bio == NULL) return(0);
	nt=(NBIO_TEST *)b->ptr;

	BIO_clear_retry_flags(b);
#if 1
	RAND_pseudo_bytes(&n,1);
	num=(n&0x07);

	if (outl > num) outl=num;

	if (num == 0)
		{
		ret= -1;
		BIO_set_retry_read(b);
		}
	else
#endif
		{
		ret=BIO_read(b->next_bio,out,outl);
		if (ret < 0)
			BIO_copy_next_retry(b);
		}
	return(ret);
	}

static int nbiof_write(BIO *b, const char *in, int inl)
	{
	NBIO_TEST *nt;
	int ret=0;
	int num;
	unsigned char n;

	if ((in == NULL) || (inl <= 0)) return(0);
	if (b->next_bio == NULL) return(0);
	nt=(NBIO_TEST *)b->ptr;

	BIO_clear_retry_flags(b);

#if 1
	if (nt->lwn > 0)
		{
		num=nt->lwn;
		nt->lwn=0;
		}
	else
		{
		RAND_pseudo_bytes(&n,1);
		num=(n&7);
		}

	if (inl > num) inl=num;

	if (num == 0)
		{
		ret= -1;
		BIO_set_retry_write(b);
		}
	else
#endif
		{
		ret=BIO_write(b->next_bio,in,inl);
		if (ret < 0)
			{
			BIO_copy_next_retry(b);
			nt->lwn=inl;
			}
		}
	return(ret);
	}

static long nbiof_ctrl(BIO *b, int cmd, long num, void *ptr)
	{
	long ret;

	if (b->next_bio == NULL) return(0);
	switch (cmd)
		{
        case BIO_C_DO_STATE_MACHINE:
		BIO_clear_retry_flags(b);
		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
		BIO_copy_next_retry(b);
		break;
	case BIO_CTRL_DUP:
		ret=0L;
		break;
	default:
		ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
		break;
		}
	return(ret);
	}

static long nbiof_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
	{
	long ret=1;

	if (b->next_bio == NULL) return(0);
	switch (cmd)
		{
	default:
		ret=BIO_callback_ctrl(b->next_bio,cmd,fp);
		break;
		}
	return(ret);
	}

static int nbiof_gets(BIO *bp, char *buf, int size)
	{
	if (bp->next_bio == NULL) return(0);
	return(BIO_gets(bp->next_bio,buf,size));
	}


static int nbiof_puts(BIO *bp, const char *str)
	{
	if (bp->next_bio == NULL) return(0);
	return(BIO_puts(bp->next_bio,str));
	}


