s->state=SSL_ST_BEFORE;
s->state=SSL_ST_BEFORE|(s->server) ?SSL_ST_ACCEPT :SSL_ST_CONNECT;
int ssl3_read_bytes(s,type,buf,len)SSL *s;int type;char *buf;int len;	{	int al,i,j,n,ret;	SSL3_RECORD *rr;	void (*cb)()=NULL;	BIO *bio;	if (s->s3->rbuf.buf == NULL) /* Not initialize yet */		if (!ssl3_setup_buffers(s))			return(-1);	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;	/* s->s3->rrec.type	- is the type of record	 * s->s3->rrec.data, 	- data	 * s->s3->rrec.off, 	- ofset into 'data' for next read	 * s->s3->rrec.length,	- number of bytes. */	rr= &(s->s3->rrec);	/* get new packet */	if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY))		{		ret=ssl3_get_record(s);		if (ret <= 0) return(ret);		}	/* we now have a packet which can be read and processed */	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 the other end has shutdown, throw anything we read away */	if (s->shutdown & SSL_RECEIVED_SHUTDOWN)		{		rr->length=0;		s->rwstate=SSL_NOTHING;		return(0);		}	/* Check for an incoming 'Client Request' message */	if ((rr->type == SSL3_RT_HANDSHAKE) && (rr->length == 4) &&		(rr->data[0] == SSL3_MT_CLIENT_REQUEST) &&		(s->session != NULL) && (s->session->cipher != NULL))		{		if ((rr->data[1] != 0) || (rr->data[2] != 0) ||			(rr->data[3] != 0))			{			al=SSL_AD_DECODE_ERROR;			SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_CLIENT_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);					}				}			}		rr->length=0;/* ZZZ */	goto start;		}	/* if it is not the type we want, or we have shutdown and want	 * the peer shutdown */	if ((rr->type != type) || (s->shutdown & SSL_SENT_SHUTDOWN))		{		if (rr->type == SSL3_RT_ALERT)			{			if ((rr->length != 2) || (rr->off != 0))				{				al=SSL_AD_DECODE_ERROR;				SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_ALERT_RECORD);				goto f_err;				}			i=rr->data[0];			n=rr->data[1];			/* clear from buffer */			rr->length=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;				}			rr->length=0;			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;			}		/* else we have a handshake */		if ((rr->type == SSL3_RT_HANDSHAKE) &&			!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->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);				}			/* In the case where we try to read application data			 * the first time, but we trigger an SSL handshake, we			 * return -1 with the retry option set.  I do this			 * otherwise renegotiation can cause nasty problems 			 * in the non-blocking world */			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			/* TLS just ignores unknown message types */			if (s->version == TLS1_VERSION)				{				goto start;				}#endif		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_UNEXPECTED_RECORD);			goto f_err;		case SSL3_RT_APPLICATION_DATA:			/* At this point, we were expecting something else,			 * but have application data.  What we do is set the			 * error, and return -1.  On the way out, if the			 * library was running inside ssl3_read() and it makes			 * sense to read application data at this point, we			 * will indulge it.  This will mostly happen during			 * session renegotiation.			 */			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;				}			}		}	/* make sure that we are not getting application data when we	 * are doing a handshake for the first time */	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,(unsigned char *)buf,n);	return(n);f_err:	ssl3_send_alert(s,SSL3_AL_FATAL,al);err:	return(-1);	}