end:
int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count)	{	long cw_num = count, cr_num = count, sw_num = count, sr_num = count;	BIO *s_ssl_bio = NULL, *c_ssl_bio = NULL;	BIO *server = NULL, *server_io = NULL, *client = NULL, *client_io = NULL;	SSL_CIPHER *ciph;	int ret = 1;		size_t bufsiz = 256; /* small buffer for testing */	if (!BIO_new_bio_pair(&server, bufsiz, &server_io, bufsiz))		goto err;	if (!BIO_new_bio_pair(&client, bufsiz, &client_io, bufsiz))		goto err;		s_ssl_bio = BIO_new(BIO_f_ssl());	if (!s_ssl_bio)		goto err;	c_ssl_bio = BIO_new(BIO_f_ssl());	if (!c_ssl_bio)		goto err;	SSL_set_connect_state(c_ssl);	SSL_set_bio(c_ssl, client, client);	(void)BIO_set_ssl(c_ssl_bio, c_ssl, BIO_NOCLOSE);	SSL_set_accept_state(s_ssl);	SSL_set_bio(s_ssl, server, server);	(void)BIO_set_ssl(s_ssl_bio, s_ssl, BIO_NOCLOSE);	do		{		/* c_ssl_bio:          SSL filter BIO		 *		 * client:             pseudo-I/O for SSL library		 *		 * client_io:          client's SSL communication; usually to be		 *                     relayed over some I/O facility, but in this		 *                     test program, we're the server, too:		 *		 * server_io:          server's SSL communication		 *		 * server:             pseudo-I/O for SSL library		 *		 * s_ssl_bio:          SSL filter BIO		 *		 * The client and the server each employ a "BIO pair":		 * client + client_io, server + server_io.		 * BIO pairs are symmetric.  A BIO pair behaves similar		 * to a non-blocking socketpair (but both endpoints must		 * be handled by the same thread).		 *		 * Useful functions for querying the state of BIO pair endpoints:		 *		 * BIO_ctrl_pending(bio)              number of bytes we can read now		 * BIO_ctrl_get_read_request(bio)     number of bytes needed to fulfil		 *                                      other side's read attempt		 * BIO_ctrl_get_write_gurantee(bio)   number of bytes we can write now		 *		 * ..._read_request is never more than ..._write_guarantee;		 * it depends on the application which one you should use.		 */		/* We have non-blocking behaviour throughout this test program, but		 * can be sure that there is *some* progress in each iteration; so		 * we don't have to worry about ..._SHOULD_READ or ..._SHOULD_WRITE		 * -- we just try everything in each iteration		 */			{			/* CLIENT */					MS_STATIC char cbuf[1024*8];			int i, r;			if (debug)				if (SSL_in_init(c_ssl))					printf("client waiting in SSL_connect - %s\n",						SSL_state_string_long(c_ssl));			if (cw_num > 0)				{				/* Write to server. */								if (cw_num > (long)sizeof cbuf)					i = sizeof cbuf;				else					i = (int)cw_num;				r = BIO_write(c_ssl_bio, cbuf, i);				if (r == -1)					{					if (!BIO_should_retry(c_ssl_bio))						{						fprintf(stderr,"ERROR in CLIENT\n");						goto err;						}					/* BIO_should_retry(...) can just be ignored here.					 * The library expects us to call BIO_write with					 * the same arguments again, and that's what we will					 * do in the next iteration. */					}				else if (r == 0)					{					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");					goto err;					}				else					{					if (debug)						printf("client wrote %d\n", r);					cw_num -= r;									}				}			if (cr_num > 0)				{				/* Read from server. */				r = BIO_read(c_ssl_bio, cbuf, sizeof(cbuf));				if (r < 0)					{					if (!BIO_should_retry(c_ssl_bio))						{						fprintf(stderr,"ERROR in CLIENT\n");						goto err;						}					/* Again, "BIO_should_retry" can be ignored. */					}				else if (r == 0)					{					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");					goto err;					}				else					{					if (debug)						printf("client read %d\n", r);					cr_num -= r;					}				}			}			{			/* SERVER */					MS_STATIC char sbuf[1024*8];			int i, r;			if (debug)				if (SSL_in_init(s_ssl))					printf("server waiting in SSL_accept - %s\n",						SSL_state_string_long(s_ssl));			if (sw_num > 0)				{				/* Write to client. */								if (sw_num > (long)sizeof sbuf)					i = sizeof sbuf;				else					i = (int)sw_num;				r = BIO_write(s_ssl_bio, sbuf, i);				if (r == -1)					{					if (!BIO_should_retry(s_ssl_bio))						{						fprintf(stderr,"ERROR in SERVER\n");						goto err;						}					/* Ignore "BIO_should_retry". */					}				else if (r == 0)					{					fprintf(stderr,"SSL SERVER STARTUP FAILED\n");					goto err;					}				else					{					if (debug)						printf("server wrote %d\n", r);					sw_num -= r;									}				}			if (sr_num > 0)				{				/* Read from client. */				r = BIO_read(s_ssl_bio, sbuf, sizeof(sbuf));				if (r < 0)					{					if (!BIO_should_retry(s_ssl_bio))						{						fprintf(stderr,"ERROR in SERVER\n");						goto err;						}					/* blah, blah */					}				else if (r == 0)					{					fprintf(stderr,"SSL SERVER STARTUP FAILED\n");					goto err;					}				else					{					if (debug)						printf("server read %d\n", r);					sr_num -= r;					}				}			}						{			/* "I/O" BETWEEN CLIENT AND SERVER. */#define RELAYBUFSIZ 200			static char buf[RELAYBUFSIZ];			/* RELAYBUF is arbitrary.  When writing data over some real			 * network, use a buffer of the same size as in the BIO_pipe			 * and make that size large (for reading from the network			 * small buffers usually won't hurt).			 * Here sizes differ for testing. */			size_t r1, r2;			size_t num;			int r;			static int prev_progress = 1;			int progress = 0;						/* client to server */			do				{				r1 = BIO_ctrl_pending(client_io);				r2 = BIO_ctrl_get_write_guarantee(server_io);				num = r1;				if (r2 < num)					num = r2;				if (num)					{					if (sizeof buf < num)						num = sizeof buf;					if (INT_MAX < num) /* yeah, right */						num = INT_MAX;										r = BIO_read(client_io, buf, (int)num);					if (r != (int)num) /* can't happen */						{						fprintf(stderr, "ERROR: BIO_read could not read "							"BIO_ctrl_pending() bytes");						goto err;						}					r = BIO_write(server_io, buf, (int)num);					if (r != (int)num) /* can't happen */						{						fprintf(stderr, "ERROR: BIO_write could not write "							"BIO_ctrl_get_write_guarantee() bytes");						goto err;						}					progress = 1;					if (debug)						printf("C->S relaying: %d bytes\n", (int)num);					}				}			while (r1 && r2);			/* server to client */			do				{				r1 = BIO_ctrl_pending(server_io);				r2 = BIO_ctrl_get_write_guarantee(client_io);				num = r1;				if (r2 < num)					num = r2;				if (num)					{					if (sizeof buf < num)						num = sizeof buf;					if (INT_MAX < num)						num = INT_MAX;										r = BIO_read(server_io, buf, (int)num);					if (r != (int)num) /* can't happen */						{						fprintf(stderr, "ERROR: BIO_read could not read "							"BIO_ctrl_pending() bytes");						goto err;						}					r = BIO_write(client_io, buf, (int)num);					if (r != (int)num) /* can't happen */						{						fprintf(stderr, "ERROR: BIO_write could not write "							"BIO_ctrl_get_write_guarantee() bytes");						goto err;						}					progress = 1;					if (debug)						printf("S->C relaying: %d bytes\n", (int)num);					}				}			while (r1 && r2);			if (!progress && !prev_progress)				if (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0)					 /* can't happen */					{					fprintf(stderr, "ERROR: got stuck\n");					goto err;					}			prev_progress = progress;			}		}	while (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0);	ciph = SSL_get_current_cipher(c_ssl);	if (verbose)		fprintf(stdout,"DONE via BIO pair, protocol %s, cipher %s, %s\n",			SSL_get_version(c_ssl),			SSL_CIPHER_get_version(ciph),			SSL_CIPHER_get_name(ciph));	ret = 0; err:	ERR_print_errors(bio_err);		if (server)		BIO_free(server);	if (server_io)		BIO_free(server_io);	if (client)		BIO_free(client);	if (client_io)		BIO_free(client_io);	if (s_ssl_bio)		BIO_free(s_ssl_bio);	if (c_ssl_bio)		BIO_free(c_ssl_bio);	return ret;	}