From 116f2403d0af2d1e3f1804244ec86089e3f18396 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 19 Feb 2013 12:51:02 -0800 Subject: [PATCH] updated the list for storing out of order messages --- cyassl/internal.h | 16 ++++--- src/internal.c | 103 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 99 insertions(+), 20 deletions(-) diff --git a/cyassl/internal.h b/cyassl/internal.h index 9a68f0faf..517035cbc 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -1387,9 +1387,10 @@ typedef struct DtlsPool { typedef struct DtlsMsg { struct DtlsMsg* next; - word32 seq; - word32 sz; - byte msg[1500]; + word32 seq; /* Handshake sequence number */ + word32 sz; /* Length of whole mesage */ + word32 fragSz; /* Length of fragments received */ + byte* msg; } DtlsMsg; @@ -1685,9 +1686,14 @@ CYASSL_LOCAL int GrowInputBuffer(CYASSL* ssl, int size, int usedLength); CYASSL_LOCAL int DtlsPoolTimeout(CYASSL*); CYASSL_LOCAL int DtlsPoolSend(CYASSL*); CYASSL_LOCAL void DtlsPoolReset(CYASSL*); - CYASSL_LOCAL DtlsMsg* DtlsMsgNew(word32, byte*, word32, void*); + + CYASSL_LOCAL DtlsMsg* DtlsMsgNew(word32, void*); CYASSL_LOCAL void DtlsMsgDelete(DtlsMsg*, void*); - CYASSL_LOCAL void DtlsMsgListFree(DtlsMsg*, void*); + CYASSL_LOCAL void DtlsMsgListDelete(DtlsMsg*, void*); + CYASSL_LOCAL void DtlsMsgSet(DtlsMsg*, word32, const byte*, word32, word32); + CYASSL_LOCAL DtlsMsg* DtlsMsgFind(DtlsMsg*, word32); + CYASSL_LOCAL DtlsMsg* DtlsMsgStore(DtlsMsg*, word32, const byte*, word32, + word32, word32, void*); CYASSL_LOCAL DtlsMsg* DtlsMsgInsert(DtlsMsg*, DtlsMsg*); #endif /* CYASSL_DTLS */ diff --git a/src/internal.c b/src/internal.c index ad596254d..0a9078863 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1414,7 +1414,7 @@ void SSL_ResourceFree(CYASSL* ssl) XFREE(ssl->dtls_pool, ssl->heap, DYNAMIC_TYPE_NONE); } if (ssl->dtls_msg_list != NULL) { - DtlsMsgListFree(ssl->dtls_msg_list, ssl->heap); + DtlsMsgListDelete(ssl->dtls_msg_list, ssl->heap); ssl->dtls_msg_list = NULL; } XFREE(ssl->buffers.dtlsCtx.peer.sa, ssl->heap, DYNAMIC_TYPE_SOCKADDR); @@ -1652,33 +1652,43 @@ int DtlsPoolSend(CYASSL* ssl) /* functions for managing DTLS datagram reordering */ -DtlsMsg* DtlsMsgNew(word32 dataSz, byte* data, word32 seq, void* heap) +DtlsMsg* DtlsMsgNew(word32 sz, void* heap) { DtlsMsg* msg = NULL; - if (dataSz > 0) + if (sz > 0) msg = (DtlsMsg*)XMALLOC(sizeof(DtlsMsg), heap, DYNAMIC_TYPE_DTLS_MSG); if (msg != NULL) { - msg->next = NULL; - msg->seq = seq; - msg->sz = dataSz; - XMEMCPY(msg->msg, data, dataSz); + msg->msg = (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_NONE); + if (msg->msg != NULL) { + msg->next = NULL; + msg->seq = 0; + msg->sz = sz; + msg->fragSz = 0; + } + else { + XFREE(msg, heap, DYNAMIC_TYPE_DTLS_MSG); + msg = NULL; + } } return msg; } - -void DtlsMsgDelete(DtlsMsg* msg, void* heap) +void DtlsMsgDelete(DtlsMsg* item, void* heap) { (void)heap; - if (msg != NULL) - XFREE(msg, heap, DYNAMIC_TYPE_DTLS_MSG); + + if (item != NULL) { + if (item->msg != NULL) + XFREE(item->msg, heap, DYNAMIC_TYPE_NONE); + XFREE(item, heap, DYNAMIC_TYPE_DTLS_MSG); + } } -void DtlsMsgListFree(DtlsMsg* head, void* heap) +void DtlsMsgListDelete(DtlsMsg* head, void* heap) { DtlsMsg* next; while (head) { @@ -1689,6 +1699,66 @@ void DtlsMsgListFree(DtlsMsg* head, void* heap) } +void DtlsMsgSet(DtlsMsg* msg, word32 seq, const byte* data, + word32 fragOffset, word32 fragSz) +{ + if (msg != NULL && data != NULL && msg->fragSz <= msg->sz) { + msg->seq = seq; + msg->fragSz += fragSz; + XMEMCPY(&msg->msg[fragOffset], data, fragSz); + } +} + + +DtlsMsg* DtlsMsgFind(DtlsMsg* head, word32 seq) +{ + while (head != NULL && head->seq != seq) { + head = head->next; + } + return head; +} + + +DtlsMsg* DtlsMsgStore(DtlsMsg* head, word32 seq, const byte* data, word32 dataSz, + word32 fragOffset, word32 fragSz, void* heap) +{ + + /* See if seq exists in the list. If it isn't in the list, make + * a new item of size dataSz, copy fragSz bytes from data to msg->msg + * starting at offset fragOffset, and add fragSz to msg->fragSz. If + * the seq is in the list and it isn't full, copy fragSz bytes from + * data to msg->msg starting at offset fragOffset, and add fragSz to + * msg->fragSz. The new item should be inserted into the list in its + * proper position. + * + * 1. Find seq in list, or where seq should go in list. If seq not in + * list, create new item and insert into list. Either case, keep + * pointer to item. + * 2. If msg->fragSz + fragSz < sz, copy data to msg->msg at offset + * fragOffset. Add fragSz to msg->fragSz. + */ + + if (head != NULL) { + DtlsMsg* cur = DtlsMsgFind(head, seq); + if (cur == NULL) { + cur = DtlsMsgNew(dataSz, heap); + DtlsMsgSet(cur, seq, data, fragOffset, fragSz); + head = DtlsMsgInsert(head, cur); + } + else { + DtlsMsgSet(cur, seq, data, fragOffset, fragSz); + } + } + else { + head = DtlsMsgNew(dataSz, heap); + DtlsMsgSet(head, seq, data, fragOffset, fragSz); + } + + return head; +} + + +/* DtlsMsgInsert() is an in-order insert. */ DtlsMsg* DtlsMsgInsert(DtlsMsg* head, DtlsMsg* item) { if (head == NULL || item->seq < head->seq) { @@ -2201,7 +2271,9 @@ static int GetRecordHeader(CYASSL* ssl, const byte* input, word32* inOutIdx, return VERSION_ERROR; /* only use requested version */ } } - +#if 0 + /* Instead of this, check the datagram against the sliding window of + * received datagram goodness. */ #ifdef CYASSL_DTLS /* If DTLS, check the sequence number against expected. If out of * order, drop the record. Allows newer records in and resets the @@ -2219,7 +2291,7 @@ static int GetRecordHeader(CYASSL* ssl, const byte* input, word32* inOutIdx, } } #endif - +#endif /* record layer length check */ if (*size > (MAX_RECORD_SIZE + MAX_COMP_EXTRA + MAX_MSG_EXTRA)) return LENGTH_ERROR; @@ -4044,7 +4116,8 @@ int ProcessReply(CYASSL* ssl) &ssl->curRL, &ssl->curSize); #ifdef CYASSL_DTLS if (ssl->options.dtls && ret == SEQUENCE_ERROR) { - /* This message is out of order. Forget it ever happened. */ + /* This message is out of order. If we are handshaking, save + *it for later. Otherwise go ahead and process it. */ ssl->options.processReply = doProcessInit; ssl->buffers.inputBuffer.length = 0; ssl->buffers.inputBuffer.idx = 0;