Updates from 1.0.0-stable.
diff --git a/ssl/d1_both.c b/ssl/d1_both.c
index 87c8c93..9130983 100644
--- a/ssl/d1_both.c
+++ b/ssl/d1_both.c
@@ -136,7 +136,6 @@
 static void dtls1_set_message_header_int(SSL *s, unsigned char mt,
 	unsigned long len, unsigned short seq_num, unsigned long frag_off, 
 	unsigned long frag_len);
-static int dtls1_retransmit_buffered_messages(SSL *s);
 static long dtls1_get_message_fragment(SSL *s, int st1, int stn, 
 	long max, int *ok);
 
@@ -574,30 +573,31 @@
 			}
 		}
 
-	frag = dtls1_hm_fragment_new(frag_len);
-	if ( frag == NULL)
-		goto err;
-
-	memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
-
 	if (frag_len)
 		{
+		frag = dtls1_hm_fragment_new(frag_len);
+		if ( frag == NULL)
+			goto err;
+
+		memcpy(&(frag->msg_header), msg_hdr, sizeof(*msg_hdr));
+
 		/* read the body of the fragment (header has already been read */
 		i = s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE,
 			frag->fragment,frag_len,0);
 		if (i<=0 || (unsigned long)i!=frag_len)
 			goto err;
+
+		memset(seq64be,0,sizeof(seq64be));
+		seq64be[6] = (unsigned char)(msg_hdr->seq>>8);
+		seq64be[7] = (unsigned char)(msg_hdr->seq);
+
+		item = pitem_new(seq64be, frag);
+		if ( item == NULL)
+			goto err;
+
+		pqueue_insert(s->d1->buffered_messages, item);
 		}
 
-	memset(seq64be,0,sizeof(seq64be));
-	seq64be[6] = (unsigned char)(msg_hdr->seq>>8);
-	seq64be[7] = (unsigned char)(msg_hdr->seq);
-
-	item = pitem_new(seq64be, frag);
-	if ( item == NULL)
-		goto err;
-
-	pqueue_insert(s->d1->buffered_messages, item);
 	return DTLS1_HM_FRAGMENT_RETRY;
 
 err:
@@ -931,8 +931,21 @@
 	return dtls1_retransmit_buffered_messages(s) ;
 	}
 
+int
+dtls1_get_queue_priority(unsigned short seq, int is_ccs)
+	{
+	/* The index of the retransmission queue actually is the message sequence number,
+	 * since the queue only contains messages of a single handshake. However, the
+	 * ChangeCipherSpec has no message sequence number and so using only the sequence
+	 * will result in the CCS and Finished having the same index. To prevent this,
+	 * the sequence number is multiplied by 2. In case of a CCS 1 is subtracted.
+	 * This does not only differ CSS and Finished, it also maintains the order of the
+	 * index (important for priority queues) and fits in the unsigned short variable.
+	 */	
+	return seq * 2 - is_ccs;
+	}
 
-static int
+int
 dtls1_retransmit_buffered_messages(SSL *s)
 	{
 	pqueue sent = s->d1->sent_messages;
@@ -946,8 +959,9 @@
 	for ( item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter))
 		{
 		frag = (hm_fragment *)item->data;
-		if ( dtls1_retransmit_message(s, frag->msg_header.seq, 0, &found) <= 0 &&
-			found)
+			if ( dtls1_retransmit_message(s,
+				dtls1_get_queue_priority(frag->msg_header.seq, frag->msg_header.is_ccs),
+				0, &found) <= 0 && found)
 			{
 			fprintf(stderr, "dtls1_retransmit_message() failed\n");
 			return -1;
@@ -963,7 +977,6 @@
 	pitem *item;
 	hm_fragment *frag;
 	unsigned char seq64be[8];
-	unsigned int epoch = s->d1->w_epoch;
 
 	/* this function is called immediately after a message has 
 	 * been serialized */
@@ -977,7 +990,6 @@
 		{
 		OPENSSL_assert(s->d1->w_msg_hdr.msg_len + 
 			DTLS1_CCS_HEADER_LENGTH == (unsigned int)s->init_num);
-		epoch++;
 		}
 	else
 		{
@@ -992,11 +1004,18 @@
 	frag->msg_header.frag_len = s->d1->w_msg_hdr.msg_len;
 	frag->msg_header.is_ccs = is_ccs;
 
+	/* save current state*/
+	frag->msg_header.saved_retransmit_state.enc_write_ctx = s->enc_write_ctx;
+	frag->msg_header.saved_retransmit_state.write_hash = s->write_hash;
+	frag->msg_header.saved_retransmit_state.compress = s->compress;
+	frag->msg_header.saved_retransmit_state.session = s->session;
+	frag->msg_header.saved_retransmit_state.epoch = s->d1->w_epoch;
+	
 	memset(seq64be,0,sizeof(seq64be));
-	seq64be[0] = (unsigned char)(epoch>>8);
-	seq64be[1] = (unsigned char)(epoch);
-	seq64be[6] = (unsigned char)(frag->msg_header.seq>>8);
-	seq64be[7] = (unsigned char)(frag->msg_header.seq);
+	seq64be[6] = (unsigned char)(dtls1_get_queue_priority(frag->msg_header.seq,
+														  frag->msg_header.is_ccs)>>8);
+	seq64be[7] = (unsigned char)(dtls1_get_queue_priority(frag->msg_header.seq,
+														  frag->msg_header.is_ccs));
 
 	item = pitem_new(seq64be, frag);
 	if ( item == NULL)
@@ -1025,6 +1044,8 @@
 	hm_fragment *frag ;
 	unsigned long header_length;
 	unsigned char seq64be[8];
+	struct dtls1_retransmit_state saved_state;
+	unsigned char save_write_sequence[8];
 
 	/*
 	  OPENSSL_assert(s->init_num == 0);
@@ -1060,9 +1081,45 @@
 		frag->msg_header.msg_len, frag->msg_header.seq, 0, 
 		frag->msg_header.frag_len);
 
+	/* save current state */
+	saved_state.enc_write_ctx = s->enc_write_ctx;
+	saved_state.write_hash = s->write_hash;
+	saved_state.compress = s->compress;
+	saved_state.session = s->session;
+	saved_state.epoch = s->d1->w_epoch;
+	saved_state.epoch = s->d1->w_epoch;
+	
 	s->d1->retransmitting = 1;
+	
+	/* restore state in which the message was originally sent */
+	s->enc_write_ctx = frag->msg_header.saved_retransmit_state.enc_write_ctx;
+	s->write_hash = frag->msg_header.saved_retransmit_state.write_hash;
+	s->compress = frag->msg_header.saved_retransmit_state.compress;
+	s->session = frag->msg_header.saved_retransmit_state.session;
+	s->d1->w_epoch = frag->msg_header.saved_retransmit_state.epoch;
+	
+	if (frag->msg_header.saved_retransmit_state.epoch == saved_state.epoch - 1)
+	{
+		memcpy(save_write_sequence, s->s3->write_sequence, sizeof(s->s3->write_sequence));
+		memcpy(s->s3->write_sequence, s->d1->last_write_sequence, sizeof(s->s3->write_sequence));
+	}
+	
 	ret = dtls1_do_write(s, frag->msg_header.is_ccs ? 
-		SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
+						 SSL3_RT_CHANGE_CIPHER_SPEC : SSL3_RT_HANDSHAKE);
+	
+	/* restore current state */
+	s->enc_write_ctx = saved_state.enc_write_ctx;
+	s->write_hash = saved_state.write_hash;
+	s->compress = saved_state.compress;
+	s->session = saved_state.session;
+	s->d1->w_epoch = saved_state.epoch;
+	
+	if (frag->msg_header.saved_retransmit_state.epoch == saved_state.epoch - 1)
+	{
+		memcpy(s->d1->last_write_sequence, s->s3->write_sequence, sizeof(s->s3->write_sequence));
+		memcpy(s->s3->write_sequence, save_write_sequence, sizeof(s->s3->write_sequence));
+	}
+
 	s->d1->retransmitting = 0;
 
 	(void)BIO_flush(SSL_get_wbio(s));
diff --git a/ssl/d1_clnt.c b/ssl/d1_clnt.c
index f569d4b..c151264 100644
--- a/ssl/d1_clnt.c
+++ b/ssl/d1_clnt.c
@@ -229,6 +229,7 @@
 			/* every DTLS ClientHello resets Finished MAC */
 			ssl3_init_finished_mac(s);
 
+			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
 			ret=dtls1_client_hello(s);
 			if (ret <= 0) goto end;
 
@@ -254,6 +255,7 @@
 			if (ret <= 0) goto end;
 			else
 				{
+				BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
 				if (s->hit)
 					s->state=SSL3_ST_CR_FINISHED_A;
 				else
@@ -268,6 +270,7 @@
 			ret = dtls1_get_hello_verify(s);
 			if ( ret <= 0)
 				goto end;
+			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
 			if ( s->d1->send_cookie) /* start again, with a cookie */
 				s->state=SSL3_ST_CW_CLNT_HELLO_A;
 			else
@@ -329,6 +332,7 @@
 		case SSL3_ST_CW_CERT_B:
 		case SSL3_ST_CW_CERT_C:
 		case SSL3_ST_CW_CERT_D:
+			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
 			ret=dtls1_send_client_certificate(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CW_KEY_EXCH_A;
@@ -337,6 +341,7 @@
 
 		case SSL3_ST_CW_KEY_EXCH_A:
 		case SSL3_ST_CW_KEY_EXCH_B:
+			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
 			ret=dtls1_send_client_key_exchange(s);
 			if (ret <= 0) goto end;
 			/* EAY EAY EAY need to check for DH fix cert
@@ -358,6 +363,7 @@
 
 		case SSL3_ST_CW_CERT_VRFY_A:
 		case SSL3_ST_CW_CERT_VRFY_B:
+			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
 			ret=dtls1_send_client_verify(s);
 			if (ret <= 0) goto end;
 			s->state=SSL3_ST_CW_CHANGE_A;
@@ -367,6 +373,7 @@
 
 		case SSL3_ST_CW_CHANGE_A:
 		case SSL3_ST_CW_CHANGE_B:
+			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
 			ret=dtls1_send_change_cipher_spec(s,
 				SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
 			if (ret <= 0) goto end;
@@ -401,6 +408,7 @@
 
 		case SSL3_ST_CW_FINISHED_A:
 		case SSL3_ST_CW_FINISHED_B:
+			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
 			ret=dtls1_send_finished(s,
 				SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B,
 				s->method->ssl3_enc->client_finished_label,
@@ -433,6 +441,7 @@
 			ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
 				SSL3_ST_CR_FINISHED_B);
 			if (ret <= 0) goto end;
+			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
 
 			if (s->hit)
 				s->state=SSL3_ST_CW_CHANGE_A;
@@ -488,6 +497,7 @@
 
 			/* done with handshaking */
 			s->d1->handshake_read_seq  = 0;
+			s->d1->next_handshake_write_seq = 0;
 			goto end;
 			/* break; */
 			
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index bd28b75..be47541 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -98,6 +98,7 @@
 	d1->processed_rcds.q=pqueue_new();
 	d1->buffered_messages = pqueue_new();
 	d1->sent_messages=pqueue_new();
+	d1->buffered_app_data.q=pqueue_new();
 
 	if ( s->server)
 		{
@@ -105,12 +106,13 @@
 		}
 
 	if( ! d1->unprocessed_rcds.q || ! d1->processed_rcds.q 
-        || ! d1->buffered_messages || ! d1->sent_messages)
+        || ! d1->buffered_messages || ! d1->sent_messages || ! d1->buffered_app_data.q)
 		{
         if ( d1->unprocessed_rcds.q) pqueue_free(d1->unprocessed_rcds.q);
         if ( d1->processed_rcds.q) pqueue_free(d1->processed_rcds.q);
         if ( d1->buffered_messages) pqueue_free(d1->buffered_messages);
 		if ( d1->sent_messages) pqueue_free(d1->sent_messages);
+		if ( d1->buffered_app_data.q) pqueue_free(d1->buffered_app_data.q);
 		OPENSSL_free(d1);
 		return (0);
 		}
@@ -159,6 +161,15 @@
         }
 	pqueue_free(s->d1->sent_messages);
 
+	while ( (item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL)
+		{
+		frag = (hm_fragment *)item->data;
+		OPENSSL_free(frag->fragment);
+		OPENSSL_free(frag);
+		pitem_free(item);
+		}
+	pqueue_free(s->d1->buffered_app_data.q);
+
 	OPENSSL_free(s->d1);
 	}
 
diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c
index dea63d6..2e9d545 100644
--- a/ssl/d1_pkt.c
+++ b/ssl/d1_pkt.c
@@ -746,6 +746,23 @@
 	 * s->s3->rrec.length,  - number of bytes. */
 	rr = &(s->s3->rrec);
 
+	/* We are not handshaking and have no data yet,
+	 * so process data buffered during the last handshake
+	 * in advance, if any.
+	 */
+	if (s->state == SSL_ST_OK && rr->length == 0)
+		{
+		pitem *item;
+		item = pqueue_pop(s->d1->buffered_app_data.q);
+		if (item)
+			{
+			dtls1_copy_record(s, item);
+
+			OPENSSL_free(item->data);
+			pitem_free(item);
+			}
+		}
+		
 	/* get new packet if necessary */
 	if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY))
 		{
@@ -767,9 +784,14 @@
 	                               * reset by ssl3_get_finished */
 		&& (rr->type != SSL3_RT_HANDSHAKE))
 		{
-		al=SSL_AD_UNEXPECTED_MESSAGE;
-		SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_DATA_BETWEEN_CCS_AND_FINISHED);
-		goto err;
+		/* We now have application data between CCS and Finished.
+		 * Most likely the packets were reordered on their way, so
+		 * buffer the application data for later processing rather
+		 * than dropping the connection.
+		 */
+		dtls1_buffer_record(s, &(s->d1->buffered_app_data), 0);
+		rr->length = 0;
+		goto start;
 		}
 
 	/* If the other end has shut down, throw anything we read away
@@ -839,15 +861,28 @@
 			dest = s->d1->alert_fragment;
 			dest_len = &s->d1->alert_fragment_len;
 			}
-                /* else it's a CCS message, or it's wrong */
-                else if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC)
-                        {
-                          /* Not certain if this is the right error handling */
-                          al=SSL_AD_UNEXPECTED_MESSAGE;
-                          SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
-                          goto f_err;
-                        }
+		/* else it's a CCS message, or application data or wrong */
+		else if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC)
+			{
+			/* Application data while renegotiating
+			 * is allowed. Try again reading.
+			 */
+			if (rr->type == SSL3_RT_APPLICATION_DATA)
+				{
+				BIO *bio;
+				s->s3->in_read_app_data=2;
+				bio=SSL_get_rbio(s);
+				s->rwstate=SSL_READING;
+				BIO_clear_retry_flags(bio);
+				BIO_set_retry_read(bio);
+				return(-1);
+				}
 
+			/* Not certain if this is the right error handling */
+			al=SSL_AD_UNEXPECTED_MESSAGE;
+			SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_UNEXPECTED_RECORD);
+			goto f_err;
+			}
 
 		if (dest_maxlen > 0)
 			{
@@ -985,7 +1020,9 @@
 				n2s(p, seq);
 				n2l3(p, frag_off);
 
-				dtls1_retransmit_message(s, seq, frag_off, &found);
+				dtls1_retransmit_message(s,
+										 dtls1_get_queue_priority(frag->msg_header.seq, 0),
+										 frag_off, &found);
 				if ( ! found  && SSL_in_init(s))
 					{
 					/* fprintf( stderr,"in init = %d\n", SSL_in_init(s)); */
@@ -1074,6 +1111,16 @@
 			goto start;
 			}
 
+		/* If we are server, we may have a repeated FINISHED of the
+		 * client here, then retransmit our CCS and FINISHED.
+		 */
+		if (msg_hdr.type == SSL3_MT_FINISHED)
+			{
+			dtls1_retransmit_buffered_messages(s);
+			rr->length = 0;
+			goto start;
+			}
+
 		if (((s->state&SSL_ST_MASK) == SSL_ST_OK) &&
 			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS))
 			{
@@ -1728,6 +1775,7 @@
 	else
 		{
 		seq = s->s3->write_sequence;
+		memcpy(s->d1->last_write_sequence, seq, sizeof(s->s3->write_sequence));
 		s->d1->w_epoch++;
 		}
 
diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c
index 1ded18d..ebd35c7 100644
--- a/ssl/d1_srvr.c
+++ b/ssl/d1_srvr.c
@@ -249,6 +249,7 @@
 		case SSL3_ST_SW_HELLO_REQ_B:
 
 			s->shutdown=0;
+			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
 			ret=dtls1_send_hello_request(s);
 			if (ret <= 0) goto end;
 			s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C;
@@ -269,6 +270,7 @@
 			s->shutdown=0;
 			ret=ssl3_get_client_hello(s);
 			if (ret <= 0) goto end;
+			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
 			s->new_session = 2;
 
 			if (s->d1->send_cookie)
@@ -282,6 +284,7 @@
 		case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A:
 		case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B:
 
+			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
 			ret = dtls1_send_hello_verify_request(s);
 			if ( ret <= 0) goto end;
 			s->d1->send_cookie = 0;
@@ -294,6 +297,7 @@
 			
 		case SSL3_ST_SW_SRVR_HELLO_A:
 		case SSL3_ST_SW_SRVR_HELLO_B:
+			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
 			ret=dtls1_send_server_hello(s);
 			if (ret <= 0) goto end;
 
@@ -309,6 +313,7 @@
 			/* Check if it is anon DH */
 			if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL))
 				{
+				BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
 				ret=dtls1_send_server_certificate(s);
 				if (ret <= 0) goto end;
 				}
@@ -350,6 +355,7 @@
 				)
 			    )
 				{
+				BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
 				ret=dtls1_send_server_key_exchange(s);
 				if (ret <= 0) goto end;
 				}
@@ -386,6 +392,7 @@
 			else
 				{
 				s->s3->tmp.cert_request=1;
+				BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
 				ret=dtls1_send_certificate_request(s);
 				if (ret <= 0) goto end;
 #ifndef NETSCAPE_HANG_BUG
@@ -400,6 +407,7 @@
 
 		case SSL3_ST_SW_SRVR_DONE_A:
 		case SSL3_ST_SW_SRVR_DONE_B:
+			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
 			ret=dtls1_send_server_done(s);
 			if (ret <= 0) goto end;
 			s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
@@ -427,6 +435,7 @@
 			ret = ssl3_check_client_hello(s);
 			if (ret <= 0)
 				goto end;
+			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
 			if (ret == 2)
 				s->state = SSL3_ST_SR_CLNT_HELLO_C;
 			else {
@@ -434,6 +443,7 @@
 				 * have not asked for it :-) */
 				ret=ssl3_get_client_certificate(s);
 				if (ret <= 0) goto end;
+				BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
 				s->init_num=0;
 				s->state=SSL3_ST_SR_KEY_EXCH_A;
 			}
@@ -443,6 +453,7 @@
 		case SSL3_ST_SR_KEY_EXCH_B:
 			ret=ssl3_get_client_key_exchange(s);
 			if (ret <= 0) goto end;
+			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
 			s->state=SSL3_ST_SR_CERT_VRFY_A;
 			s->init_num=0;
 
@@ -463,6 +474,7 @@
 			/* we should decide if we expected this one */
 			ret=ssl3_get_cert_verify(s);
 			if (ret <= 0) goto end;
+			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
 
 			s->state=SSL3_ST_SR_FINISHED_A;
 			s->init_num=0;
@@ -473,6 +485,7 @@
 			ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
 				SSL3_ST_SR_FINISHED_B);
 			if (ret <= 0) goto end;
+			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
 			if (s->hit)
 				s->state=SSL_ST_OK;
 			else
@@ -555,6 +568,7 @@
 			s->d1->handshake_read_seq = 0;
 			/* next message is server hello */
 			s->d1->handshake_write_seq = 0;
+			s->d1->next_handshake_write_seq = 0;
 			goto end;
 			/* break; */
 
diff --git a/ssl/dtls1.h b/ssl/dtls1.h
index 6548a98..cb8bd7c 100644
--- a/ssl/dtls1.h
+++ b/ssl/dtls1.h
@@ -102,6 +102,19 @@
 					   encoding */
 	} DTLS1_BITMAP;
 
+struct dtls1_retransmit_state
+	{
+	EVP_CIPHER_CTX *enc_write_ctx;	/* cryptographic state */
+	EVP_MD_CTX *write_hash;			/* used for mac generation */
+#ifndef OPENSSL_NO_COMP
+	COMP_CTX *compress;				/* compression */
+#else
+	char *compress;	
+#endif
+	SSL_SESSION *session;
+	unsigned short epoch;
+	};
+
 struct hm_header_st
 	{
 	unsigned char type;
@@ -110,6 +123,7 @@
 	unsigned long frag_off;
 	unsigned long frag_len;
 	unsigned int is_ccs;
+	struct dtls1_retransmit_state saved_retransmit_state;
 	};
 
 struct ccs_header_st
@@ -169,6 +183,9 @@
 
 	unsigned short handshake_read_seq;
 
+	/* save last sequence number for retransmissions */
+	unsigned char last_write_sequence[8];
+
 	/* Received handshake records (processed and unprocessed) */
 	record_pqueue unprocessed_rcds;
 	record_pqueue processed_rcds;
@@ -179,6 +196,13 @@
 	/* Buffered (sent) handshake records */
 	pqueue sent_messages;
 
+	/* Buffered application records.
+	 * Only for records between CCS and Finished
+	 * to prevent either protocol violation or
+	 * unnecessary message loss.
+	 */
+	record_pqueue buffered_app_data;
+
 	unsigned int mtu; /* max wire packet size */
 
 	struct hm_header_st w_msg_hdr;
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 9b6aadd..dd9fa87 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -935,6 +935,8 @@
 int dtls1_buffer_message(SSL *s, int ccs);
 int dtls1_retransmit_message(SSL *s, unsigned short seq, 
 	unsigned long frag_off, int *found);
+int dtls1_get_queue_priority(unsigned short seq, int is_ccs);
+int dtls1_retransmit_buffered_messages(SSL *s);
 void dtls1_clear_record_buffer(SSL *s);
 void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr);
 void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr);