int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len)
	{
	int al,i,j,n,ret;
	SSL3_RECORD *rr;
	void (*cb)()=NULL;
	BIO *bio;
	if (s->s3->rbuf.buf == NULL)
		if (!ssl3_setup_buffers(s))
			return(-1);
	if ((type != SSL3_RT_APPLICATION_DATA) && (type != SSL3_RT_HANDSHAKE) && type)
		{
		SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_INTERNAL_ERROR);
		return -1;
		}
	if ((type == SSL3_RT_HANDSHAKE) && (s->s3->handshake_fragment_len > 0))
		{
		unsigned char *src = s->s3->handshake_fragment;
		unsigned char *dst = buf;
		n = 0;
		while ((len > 0) && (s->s3->handshake_fragment_len > 0))
			{
			*dst++ = *src++;
			len--; s->s3->handshake_fragment_len--;
			n++;
			}
		for (i = 0; i < s->s3->handshake_fragment_len; i++)
			s->s3->handshake_fragment[i] = *src++;
		ssl3_finish_mac(s, buf, n);
		return n;
	}
	if (!s->in_handshake && SSL_in_init(s))
		{
		i=s->handshake_func(s);
		if (i < 0) return(i);
		if (i == 0)
			{
			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
			return(-1);
			}
		}
start:
	s->rwstate=SSL_NOTHING;
	rr = &(s->s3->rrec);
	if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY))
		{
		ret=ssl3_get_record(s);
		if (ret <= 0) return(ret);
		}
	if (s->s3->change_cipher_spec
		&& (rr->type != SSL3_RT_HANDSHAKE))
		{
		al=SSL_AD_UNEXPECTED_MESSAGE;
		SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_DATA_BETWEEN_CCS_AND_FINISHED);
		goto err;
		}
	if (s->shutdown & SSL_RECEIVED_SHUTDOWN)
		{
		rr->length=0;
		s->rwstate=SSL_NOTHING;
		return(0);
		}
	if (type == rr->type)
		{
		if (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&
			(s->enc_read_ctx == NULL))
			{
			al=SSL_AD_UNEXPECTED_MESSAGE;
			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_APP_DATA_IN_HANDSHAKE);
			goto f_err;
			}
		if (len <= 0) return(len);
		if ((unsigned int)len > rr->length)
			n=rr->length;
		else
			n=len;
		memcpy(buf,&(rr->data[rr->off]),(unsigned int)n);
		rr->length-=n;
		rr->off+=n;
		if (rr->length == 0)
			{
			s->rstate=SSL_ST_READ_HEADER;
			rr->off=0;
			}
		if (type == SSL3_RT_HANDSHAKE)
			ssl3_finish_mac(s,buf,n);
		return(n);
		}
		{
		int dest_maxlen = 0;
		unsigned char *dest;
		int *dest_len;
		if (rr->type == SSL3_RT_HANDSHAKE)
			{
			dest_maxlen = sizeof s->s3->handshake_fragment;
			dest = s->s3->handshake_fragment;
			dest_len = &s->s3->handshake_fragment_len;
			}
		else if (rr->type == SSL3_RT_ALERT)
			{
			dest_maxlen = sizeof s->s3->alert_fragment;
			dest = s->s3->alert_fragment;
			dest_len = &s->s3->alert_fragment_len;
			}
		if (dest_maxlen > 0)
			{
			n = dest_maxlen - *dest_len;
			if (rr->length < n)
				n = rr->length;
			while (n-- > 0)
				{
				dest[(*dest_len)++] = rr->data[rr->off++];
				rr->length--;
				}
			if (*dest_len < dest_maxlen)
				goto start;
			}
		}
	if ((!s->server) &&
		(s->s3->handshake_fragment_len >= 4) &&
		(s->s3->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&
		(s->session != NULL) && (s->session->cipher != NULL))
		{
		s->s3->handshake_fragment_len = 0;
		if ((s->s3->handshake_fragment[1] != 0) ||
			(s->s3->handshake_fragment[2] != 0) ||
			(s->s3->handshake_fragment[3] != 0))
			{
			al=SSL_AD_DECODE_ERROR;
			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_HELLO_REQUEST);
			goto err;
			}
		if (SSL_is_init_finished(s) &&
			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
			!s->s3->renegotiate)
			{
			ssl3_renegotiate(s);
			if (ssl3_renegotiate_check(s))
				{
				n=s->handshake_func(s);
				if (n < 0) return(n);
				if (n == 0)
					{
					SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
					return(-1);
					}
				}
			}
		goto start;
		}
	if (s->s3->alert_fragment_len >= 2)
		{
		i = s->s3->alert_fragment[0];
		n = s->s3->alert_fragment[1];
		s->s3->alert_fragment_len = 0;
		if (s->info_callback != NULL)
			cb=s->info_callback;
		else if (s->ctx->info_callback != NULL)
			cb=s->ctx->info_callback;
		if (cb != NULL)
			{
			j=(i<<8)|n;
			cb(s,SSL_CB_READ_ALERT,j);
			}
		if (i == 1)
			{
			s->s3->warn_alert=n;
			if (n == SSL_AD_CLOSE_NOTIFY)
				{
				s->shutdown|=SSL_RECEIVED_SHUTDOWN;
				return(0);
				}
			}
		else if (i == 2)
			{
			char tmp[16];
			s->rwstate=SSL_NOTHING;
			s->s3->fatal_alert=n;
			SSLerr(SSL_F_SSL3_READ_BYTES,
				SSL_AD_REASON_OFFSET+n);
			sprintf(tmp,"%d",n);
			ERR_add_error_data(2,"SSL alert number ",tmp);
			s->shutdown|=SSL_RECEIVED_SHUTDOWN;
			SSL_CTX_remove_session(s->ctx,s->session);
			return(0);
			}
		else
			{
			al=SSL_AD_ILLEGAL_PARAMETER;
			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNKNOWN_ALERT_TYPE);
			goto f_err;
			}
		goto start;
		}
	if (s->shutdown & SSL_SENT_SHUTDOWN)
		{
		s->rwstate=SSL_NOTHING;
		rr->length=0;
		return(0);
		}
	if (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)
		{
		if (	(rr->length != 1) || (rr->off != 0) ||
			(rr->data[0] != SSL3_MT_CCS))
			{
			i=SSL_AD_ILLEGAL_PARAMETER;
			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);
			goto err;
			}
		rr->length=0;
		s->s3->change_cipher_spec=1;
		if (!do_change_cipher_spec(s))
			goto err;
		else
			goto start;
		}
	if ((s->s3->handshake_fragment_len >= 4) &&	!s->in_handshake)
		{
		if (((s->state&SSL_ST_MASK) == SSL_ST_OK) &&
			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS))
			{
			s->state=SSL_ST_BEFORE|(s->server)
				?SSL_ST_ACCEPT
				:SSL_ST_CONNECT;
			s->new_session=1;
			}
		n=s->handshake_func(s);
		if (n < 0) return(n);
		if (n == 0)
			{
			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);
			return(-1);
			}
		s->rwstate=SSL_READING;
		bio=SSL_get_rbio(s);
		BIO_clear_retry_flags(bio);
		BIO_set_retry_read(bio);
		return(-1);
		}
	switch (rr->type)
		{
	default:
#ifndef NO_TLS
		if (s->version == TLS1_VERSION)
			{
			goto start;
			}
#endif
		al=SSL_AD_UNEXPECTED_MESSAGE;
		SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
		goto f_err;
	case SSL3_RT_CHANGE_CIPHER_SPEC:
	case SSL3_RT_ALERT:
	case SSL3_RT_HANDSHAKE:
		al=SSL_AD_UNEXPECTED_MESSAGE;
		SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_INTERNAL_ERROR);
		goto f_err;
	case SSL3_RT_APPLICATION_DATA:
		if (s->s3->in_read_app_data &&
			(s->s3->total_renegotiations != 0) &&
			((
				(s->state & SSL_ST_CONNECT) &&
				(s->state >= SSL3_ST_CW_CLNT_HELLO_A) &&
				(s->state <= SSL3_ST_CR_SRVR_HELLO_A)
				) || (
					(s->state & SSL_ST_ACCEPT) &&
					(s->state <= SSL3_ST_SW_HELLO_REQ_A) &&
					(s->state >= SSL3_ST_SR_CLNT_HELLO_A)
					)
				))
			{
			s->s3->in_read_app_data=0;
			return(-1);
			}
		else
			{
			al=SSL_AD_UNEXPECTED_MESSAGE;
			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
			goto f_err;
			}
		}
f_err:
	ssl3_send_alert(s,SSL3_AL_FATAL,al);
err:
	return(-1);
	}
['int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len)\n\t{\n\tint al,i,j,n,ret;\n\tSSL3_RECORD *rr;\n\tvoid (*cb)()=NULL;\n\tBIO *bio;\n\tif (s->s3->rbuf.buf == NULL)\n\t\tif (!ssl3_setup_buffers(s))\n\t\t\treturn(-1);\n\tif ((type != SSL3_RT_APPLICATION_DATA) && (type != SSL3_RT_HANDSHAKE) && type)\n\t\t{\n\t\tSSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_INTERNAL_ERROR);\n\t\treturn -1;\n\t\t}\n\tif ((type == SSL3_RT_HANDSHAKE) && (s->s3->handshake_fragment_len > 0))\n\t\t{\n\t\tunsigned char *src = s->s3->handshake_fragment;\n\t\tunsigned char *dst = buf;\n\t\tn = 0;\n\t\twhile ((len > 0) && (s->s3->handshake_fragment_len > 0))\n\t\t\t{\n\t\t\t*dst++ = *src++;\n\t\t\tlen--; s->s3->handshake_fragment_len--;\n\t\t\tn++;\n\t\t\t}\n\t\tfor (i = 0; i < s->s3->handshake_fragment_len; i++)\n\t\t\ts->s3->handshake_fragment[i] = *src++;\n\t\tssl3_finish_mac(s, buf, n);\n\t\treturn n;\n\t}\n\tif (!s->in_handshake && SSL_in_init(s))\n\t\t{\n\t\ti=s->handshake_func(s);\n\t\tif (i < 0) return(i);\n\t\tif (i == 0)\n\t\t\t{\n\t\t\tSSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);\n\t\t\treturn(-1);\n\t\t\t}\n\t\t}\nstart:\n\ts->rwstate=SSL_NOTHING;\n\trr = &(s->s3->rrec);\n\tif ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY))\n\t\t{\n\t\tret=ssl3_get_record(s);\n\t\tif (ret <= 0) return(ret);\n\t\t}\n\tif (s->s3->change_cipher_spec\n\t\t&& (rr->type != SSL3_RT_HANDSHAKE))\n\t\t{\n\t\tal=SSL_AD_UNEXPECTED_MESSAGE;\n\t\tSSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_DATA_BETWEEN_CCS_AND_FINISHED);\n\t\tgoto err;\n\t\t}\n\tif (s->shutdown & SSL_RECEIVED_SHUTDOWN)\n\t\t{\n\t\trr->length=0;\n\t\ts->rwstate=SSL_NOTHING;\n\t\treturn(0);\n\t\t}\n\tif (type == rr->type)\n\t\t{\n\t\tif (SSL_in_init(s) && (type == SSL3_RT_APPLICATION_DATA) &&\n\t\t\t(s->enc_read_ctx == NULL))\n\t\t\t{\n\t\t\tal=SSL_AD_UNEXPECTED_MESSAGE;\n\t\t\tSSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_APP_DATA_IN_HANDSHAKE);\n\t\t\tgoto f_err;\n\t\t\t}\n\t\tif (len <= 0) return(len);\n\t\tif ((unsigned int)len > rr->length)\n\t\t\tn=rr->length;\n\t\telse\n\t\t\tn=len;\n\t\tmemcpy(buf,&(rr->data[rr->off]),(unsigned int)n);\n\t\trr->length-=n;\n\t\trr->off+=n;\n\t\tif (rr->length == 0)\n\t\t\t{\n\t\t\ts->rstate=SSL_ST_READ_HEADER;\n\t\t\trr->off=0;\n\t\t\t}\n\t\tif (type == SSL3_RT_HANDSHAKE)\n\t\t\tssl3_finish_mac(s,buf,n);\n\t\treturn(n);\n\t\t}\n\t\t{\n\t\tint dest_maxlen = 0;\n\t\tunsigned char *dest;\n\t\tint *dest_len;\n\t\tif (rr->type == SSL3_RT_HANDSHAKE)\n\t\t\t{\n\t\t\tdest_maxlen = sizeof s->s3->handshake_fragment;\n\t\t\tdest = s->s3->handshake_fragment;\n\t\t\tdest_len = &s->s3->handshake_fragment_len;\n\t\t\t}\n\t\telse if (rr->type == SSL3_RT_ALERT)\n\t\t\t{\n\t\t\tdest_maxlen = sizeof s->s3->alert_fragment;\n\t\t\tdest = s->s3->alert_fragment;\n\t\t\tdest_len = &s->s3->alert_fragment_len;\n\t\t\t}\n\t\tif (dest_maxlen > 0)\n\t\t\t{\n\t\t\tn = dest_maxlen - *dest_len;\n\t\t\tif (rr->length < n)\n\t\t\t\tn = rr->length;\n\t\t\twhile (n-- > 0)\n\t\t\t\t{\n\t\t\t\tdest[(*dest_len)++] = rr->data[rr->off++];\n\t\t\t\trr->length--;\n\t\t\t\t}\n\t\t\tif (*dest_len < dest_maxlen)\n\t\t\t\tgoto start;\n\t\t\t}\n\t\t}\n\tif ((!s->server) &&\n\t\t(s->s3->handshake_fragment_len >= 4) &&\n\t\t(s->s3->handshake_fragment[0] == SSL3_MT_HELLO_REQUEST) &&\n\t\t(s->session != NULL) && (s->session->cipher != NULL))\n\t\t{\n\t\ts->s3->handshake_fragment_len = 0;\n\t\tif ((s->s3->handshake_fragment[1] != 0) ||\n\t\t\t(s->s3->handshake_fragment[2] != 0) ||\n\t\t\t(s->s3->handshake_fragment[3] != 0))\n\t\t\t{\n\t\t\tal=SSL_AD_DECODE_ERROR;\n\t\t\tSSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_HELLO_REQUEST);\n\t\t\tgoto err;\n\t\t\t}\n\t\tif (SSL_is_init_finished(s) &&\n\t\t\t!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&\n\t\t\t!s->s3->renegotiate)\n\t\t\t{\n\t\t\tssl3_renegotiate(s);\n\t\t\tif (ssl3_renegotiate_check(s))\n\t\t\t\t{\n\t\t\t\tn=s->handshake_func(s);\n\t\t\t\tif (n < 0) return(n);\n\t\t\t\tif (n == 0)\n\t\t\t\t\t{\n\t\t\t\t\tSSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);\n\t\t\t\t\treturn(-1);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\tgoto start;\n\t\t}\n\tif (s->s3->alert_fragment_len >= 2)\n\t\t{\n\t\ti = s->s3->alert_fragment[0];\n\t\tn = s->s3->alert_fragment[1];\n\t\ts->s3->alert_fragment_len = 0;\n\t\tif (s->info_callback != NULL)\n\t\t\tcb=s->info_callback;\n\t\telse if (s->ctx->info_callback != NULL)\n\t\t\tcb=s->ctx->info_callback;\n\t\tif (cb != NULL)\n\t\t\t{\n\t\t\tj=(i<<8)|n;\n\t\t\tcb(s,SSL_CB_READ_ALERT,j);\n\t\t\t}\n\t\tif (i == 1)\n\t\t\t{\n\t\t\ts->s3->warn_alert=n;\n\t\t\tif (n == SSL_AD_CLOSE_NOTIFY)\n\t\t\t\t{\n\t\t\t\ts->shutdown|=SSL_RECEIVED_SHUTDOWN;\n\t\t\t\treturn(0);\n\t\t\t\t}\n\t\t\t}\n\t\telse if (i == 2)\n\t\t\t{\n\t\t\tchar tmp[16];\n\t\t\ts->rwstate=SSL_NOTHING;\n\t\t\ts->s3->fatal_alert=n;\n\t\t\tSSLerr(SSL_F_SSL3_READ_BYTES,\n\t\t\t\tSSL_AD_REASON_OFFSET+n);\n\t\t\tsprintf(tmp,"%d",n);\n\t\t\tERR_add_error_data(2,"SSL alert number ",tmp);\n\t\t\ts->shutdown|=SSL_RECEIVED_SHUTDOWN;\n\t\t\tSSL_CTX_remove_session(s->ctx,s->session);\n\t\t\treturn(0);\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tal=SSL_AD_ILLEGAL_PARAMETER;\n\t\t\tSSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNKNOWN_ALERT_TYPE);\n\t\t\tgoto f_err;\n\t\t\t}\n\t\tgoto start;\n\t\t}\n\tif (s->shutdown & SSL_SENT_SHUTDOWN)\n\t\t{\n\t\ts->rwstate=SSL_NOTHING;\n\t\trr->length=0;\n\t\treturn(0);\n\t\t}\n\tif (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC)\n\t\t{\n\t\tif (\t(rr->length != 1) || (rr->off != 0) ||\n\t\t\t(rr->data[0] != SSL3_MT_CCS))\n\t\t\t{\n\t\t\ti=SSL_AD_ILLEGAL_PARAMETER;\n\t\t\tSSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_CHANGE_CIPHER_SPEC);\n\t\t\tgoto err;\n\t\t\t}\n\t\trr->length=0;\n\t\ts->s3->change_cipher_spec=1;\n\t\tif (!do_change_cipher_spec(s))\n\t\t\tgoto err;\n\t\telse\n\t\t\tgoto start;\n\t\t}\n\tif ((s->s3->handshake_fragment_len >= 4) &&\t!s->in_handshake)\n\t\t{\n\t\tif (((s->state&SSL_ST_MASK) == SSL_ST_OK) &&\n\t\t\t!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS))\n\t\t\t{\n\t\t\ts->state=SSL_ST_BEFORE|(s->server)\n\t\t\t\t?SSL_ST_ACCEPT\n\t\t\t\t:SSL_ST_CONNECT;\n\t\t\ts->new_session=1;\n\t\t\t}\n\t\tn=s->handshake_func(s);\n\t\tif (n < 0) return(n);\n\t\tif (n == 0)\n\t\t\t{\n\t\t\tSSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_SSL_HANDSHAKE_FAILURE);\n\t\t\treturn(-1);\n\t\t\t}\n\t\ts->rwstate=SSL_READING;\n\t\tbio=SSL_get_rbio(s);\n\t\tBIO_clear_retry_flags(bio);\n\t\tBIO_set_retry_read(bio);\n\t\treturn(-1);\n\t\t}\n\tswitch (rr->type)\n\t\t{\n\tdefault:\n#ifndef NO_TLS\n\t\tif (s->version == TLS1_VERSION)\n\t\t\t{\n\t\t\tgoto start;\n\t\t\t}\n#endif\n\t\tal=SSL_AD_UNEXPECTED_MESSAGE;\n\t\tSSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD);\n\t\tgoto f_err;\n\tcase SSL3_RT_CHANGE_CIPHER_SPEC:\n\tcase SSL3_RT_ALERT:\n\tcase SSL3_RT_HANDSHAKE:\n\t\tal=SSL_AD_UNEXPECTED_MESSAGE;\n\t\tSSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_INTERNAL_ERROR);\n\t\tgoto f_err;\n\tcase SSL3_RT_APPLICATION_DATA:\n\t\tif (s->s3->in_read_app_data &&\n\t\t\t(s->s3->total_renegotiations != 0) &&\n\t\t\t((\n\t\t\t\t(s->state & SSL_ST_CONNECT) &&\n\t\t\t\t(s->state >= SSL3_ST_CW_CLNT_HELLO_A) &&\n\t\t\t\t(s->state <= SSL3_ST_CR_SRVR_HELLO_A)\n\t\t\t\t) || (\n\t\t\t\t\t(s->state & SSL_ST_ACCEPT) &&\n\t\t\t\t\t(s->state <= SSL3_ST_SW_HELLO_REQ_A) &&\n\t\t\t\t\t(s->state >= SSL3_ST_SR_CLNT_HELLO_A)\n\t\t\t\t\t)\n\t\t\t\t))\n\t\t\t{\n\t\t\ts->s3->in_read_app_data=0;\n\t\t\treturn(-1);\n\t\t\t}\n\t\telse\n\t\t\t{\n\t\t\tal=SSL_AD_UNEXPECTED_MESSAGE;\n\t\t\tSSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_UNEXPECTED_RECORD);\n\t\t\tgoto f_err;\n\t\t\t}\n\t\t}\nf_err:\n\tssl3_send_alert(s,SSL3_AL_FATAL,al);\nerr:\n\treturn(-1);\n\t}']