@@ -1535,12 +1535,67 @@ handle_request(coap_context_t *context, coap_queue_t *node) {
15351535 assert (response == NULL );
15361536}
15371537
1538+ static inline int
1539+ is_separate (const coap_queue_t * node ) {
1540+ return node -> retransmit_cnt > COAP_DEFAULT_MAX_RETRANSMIT ;
1541+ }
1542+
1543+ static int
1544+ coap_remove_separate_from_queue (coap_context_t * context , const coap_address_t * dst ,
1545+ const unsigned char * token , size_t token_length , coap_queue_t * * sent ) {
1546+ coap_queue_t * p , * q ;
1547+ if (!context -> sendqueue )
1548+ return 0 ;
1549+
1550+ if (coap_address_equals (dst , & context -> sendqueue -> remote ) &&
1551+ token_match (token , token_length ,
1552+ context -> sendqueue -> pdu -> hdr -> token ,
1553+ context -> sendqueue -> pdu -> hdr -> token_length ) &&
1554+ is_separate (context -> sendqueue )) {
1555+ * sent = context -> sendqueue ;
1556+ context -> sendqueue = context -> sendqueue -> next ;
1557+ return 1 ;
1558+ }
1559+
1560+ p = context -> sendqueue ;
1561+ q = p -> next ;
1562+
1563+ /* when q is not NULL, it does not match (dst, token), so we can skip it */
1564+ while (q ) {
1565+ if (coap_address_equals (dst , & q -> remote ) &&
1566+ token_match (token , token_length ,
1567+ q -> pdu -> hdr -> token ,
1568+ q -> pdu -> hdr -> token_length ) &&
1569+ is_separate (q )) {
1570+ p -> next = q -> next ;
1571+ q -> next = NULL ;
1572+ * sent = q ;
1573+ return 1 ;
1574+ } else {
1575+ p = q ;
1576+ q = q -> next ;
1577+ }
1578+ }
1579+ return 0 ;
1580+ }
1581+
15381582static inline void
15391583handle_response (coap_context_t * context ,
15401584 coap_queue_t * sent , coap_queue_t * rcvd ) {
15411585
15421586 coap_send_ack (context , & rcvd -> local_if , & rcvd -> remote , rcvd -> pdu );
1543-
1587+
1588+ /* In case of separate response, the request cannot be matched with
1589+ * transaction id which is based on message id and remote address.
1590+ * Besides, excludes type Acknowledgement since separate response
1591+ * cannot be be of that type.
1592+ */
1593+ if (sent == NULL && rcvd -> pdu -> hdr -> type != COAP_MESSAGE_ACK ) {
1594+ coap_remove_separate_from_queue (context , & rcvd -> remote ,
1595+ rcvd -> pdu -> hdr -> token ,
1596+ rcvd -> pdu -> hdr -> token_length , & sent );
1597+ }
1598+
15441599 /* In a lossy context, the ACK of a separate response may have
15451600 * been lost, so we need to stop retransmitting requests with the
15461601 * same token.
@@ -1580,8 +1635,15 @@ coap_dispatch(coap_context_t *context, coap_queue_t *rcvd) {
15801635 /* find transaction in sendqueue to stop retransmission */
15811636 coap_remove_from_queue (& context -> sendqueue , rcvd -> id , & sent );
15821637
1583- if (rcvd -> pdu -> hdr -> code == 0 )
1638+ if (rcvd -> pdu -> hdr -> code == 0 ) {
1639+ if (sent != NULL ) {
1640+ sent -> retransmit_cnt = COAP_DEFAULT_MAX_RETRANSMIT + 1 ;
1641+ sent -> t = sent -> timeout << COAP_DEFAULT_MAX_RETRANSMIT ;
1642+ coap_insert_node (& context -> sendqueue , sent );
1643+ sent = NULL ;
1644+ }
15841645 goto cleanup ;
1646+ }
15851647
15861648 /* if sent code was >= 64 the message might have been a
15871649 * notification. Then, we must flag the observer to be alive
0 commit comments