@@ -633,9 +633,6 @@ static srtp_err_status_t srtp_stream_clone(
633633 str -> enc_xtn_hdr = stream_template -> enc_xtn_hdr ;
634634 str -> enc_xtn_hdr_count = stream_template -> enc_xtn_hdr_count ;
635635
636- /* defensive coding */
637- str -> next = NULL ;
638- str -> prev = NULL ;
639636 return srtp_err_status_ok ;
640637}
641638
@@ -4829,11 +4826,17 @@ srtp_err_status_t srtp_stream_get_roc(srtp_t session,
48294826
48304827#ifndef SRTP_NO_STREAM_LIST
48314828
4832- /* in the default implementation, we have an intrusive doubly-linked list */
4829+ #define INITIAL_STREAM_INDEX_SIZE 2
4830+
4831+ typedef struct list_entry {
4832+ uint32_t ssrc ;
4833+ srtp_stream_t stream ;
4834+ } list_entry ;
4835+
48334836typedef struct srtp_stream_list_ctx_t_ {
4834- /* a stub stream that just holds pointers to the beginning and end of the
4835- * list */
4836- srtp_stream_ctx_t data ;
4837+ list_entry * entries ;
4838+ size_t size ;
4839+ size_t available ;
48374840} srtp_stream_list_ctx_t_ ;
48384841
48394842srtp_err_status_t srtp_stream_list_alloc (srtp_stream_list_t * list_ptr )
@@ -4844,73 +4847,137 @@ srtp_err_status_t srtp_stream_list_alloc(srtp_stream_list_t *list_ptr)
48444847 return srtp_err_status_alloc_fail ;
48454848 }
48464849
4847- list -> data .next = NULL ;
4848- list -> data .prev = NULL ;
4850+ list -> entries =
4851+ srtp_crypto_alloc (sizeof (list_entry ) * INITIAL_STREAM_INDEX_SIZE );
4852+ if (list -> entries == NULL ) {
4853+ srtp_crypto_free (list );
4854+ return srtp_err_status_alloc_fail ;
4855+ }
4856+
4857+ list -> size = INITIAL_STREAM_INDEX_SIZE ;
4858+ list -> available = INITIAL_STREAM_INDEX_SIZE ;
48494859
48504860 * list_ptr = list ;
4861+
48514862 return srtp_err_status_ok ;
48524863}
48534864
48544865srtp_err_status_t srtp_stream_list_dealloc (srtp_stream_list_t list )
48554866{
48564867 /* list must be empty */
4857- if (list -> data . next ) {
4868+ if (list -> available != list -> size ) {
48584869 return srtp_err_status_fail ;
48594870 }
4871+
4872+ srtp_crypto_free (list -> entries );
48604873 srtp_crypto_free (list );
4874+
48614875 return srtp_err_status_ok ;
48624876}
48634877
4878+ /*
4879+ * inserting a new entry in the list may require reallocating memory in order
4880+ * to keep all the items in a contiguous memory block.
4881+ */
48644882srtp_err_status_t srtp_stream_list_insert (srtp_stream_list_t list ,
48654883 srtp_stream_t stream )
48664884{
4867- /* insert at the head of the list */
4868- stream -> next = list -> data .next ;
4869- if (stream -> next != NULL ) {
4870- stream -> next -> prev = stream ;
4885+ /*
4886+ * there is no space to hold the new entry in the entries buffer,
4887+ * double the size of the buffer.
4888+ */
4889+ if (list -> available == 0 ) {
4890+ size_t new_size = list -> size * 2 ;
4891+ list_entry * new_entries =
4892+ srtp_crypto_alloc (sizeof (list_entry ) * new_size );
4893+ if (new_entries == NULL ) {
4894+ return srtp_err_status_alloc_fail ;
4895+ }
4896+
4897+ // copy previous entries into the new buffer
4898+ memcpy (new_entries , list -> entries , sizeof (list_entry ) * list -> size );
4899+ // release previous entries
4900+ srtp_crypto_free (list -> entries );
4901+ // assign new entries to the list
4902+ list -> entries = new_entries ;
4903+ // update list info
4904+ list -> size = new_size ;
4905+ list -> available = new_size / 2 ;
48714906 }
4872- list -> data .next = stream ;
4873- stream -> prev = & (list -> data );
4907+
4908+ // fill the first available entry
4909+ size_t next_index = list -> size - list -> available ;
4910+ list -> entries [next_index ].ssrc = stream -> ssrc ;
4911+ list -> entries [next_index ].stream = stream ;
4912+
4913+ // update available value
4914+ list -> available -- ;
48744915
48754916 return srtp_err_status_ok ;
48764917}
48774918
4878- srtp_stream_t srtp_stream_list_get (srtp_stream_list_t list , uint32_t ssrc )
4919+ /*
4920+ * removing an entry from the list performs a memory move of the following
4921+ * entries one possition back in order to keep all the entries in the buffer
4922+ * contiguous.
4923+ */
4924+ void srtp_stream_list_remove (srtp_stream_list_t list ,
4925+ srtp_stream_t stream_to_remove )
48794926{
4880- /* walk down list until ssrc is found */
4881- srtp_stream_t stream = list -> data .next ;
4882- while (stream != NULL ) {
4883- if (stream -> ssrc == ssrc ) {
4884- return stream ;
4927+ size_t end = list -> size - list -> available ;
4928+
4929+ for (unsigned int i = 0 ; i < end ; i ++ ) {
4930+ if (list -> entries [i ].ssrc == stream_to_remove -> ssrc ) {
4931+ size_t entries_to_move = list -> size - list -> available - i - 1 ;
4932+ memmove (& list -> entries [i ], & list -> entries [i + 1 ],
4933+ sizeof (list_entry ) * entries_to_move );
4934+ list -> available ++ ;
4935+
4936+ break ;
48854937 }
4886- stream = stream -> next ;
48874938 }
4888-
4889- /* we haven't found our ssrc, so return a null */
4890- return NULL ;
48914939}
48924940
4893- void srtp_stream_list_remove (srtp_stream_list_t list ,
4894- srtp_stream_t stream_to_remove )
4941+ srtp_stream_t srtp_stream_list_get (srtp_stream_list_t list , uint32_t ssrc )
48954942{
4896- ( void ) list ;
4943+ size_t end = list -> size - list -> available ;
48974944
4898- stream_to_remove -> prev -> next = stream_to_remove -> next ;
4899- if (stream_to_remove -> next != NULL ) {
4900- stream_to_remove -> next -> prev = stream_to_remove -> prev ;
4945+ list_entry * entries = list -> entries ;
4946+
4947+ for (unsigned int i = 0 ; i < end ; i ++ ) {
4948+ if (entries [i ].ssrc == ssrc ) {
4949+ return entries [i ].stream ;
4950+ }
49014951 }
4952+
4953+ return NULL ;
49024954}
49034955
49044956void srtp_stream_list_for_each (srtp_stream_list_t list ,
49054957 int (* callback )(srtp_stream_t , void * ),
49064958 void * data )
49074959{
4908- srtp_stream_t stream = list -> data .next ;
4909- while (stream != NULL ) {
4910- srtp_stream_t tmp = stream ;
4911- stream = stream -> next ;
4912- if (callback (tmp , data ))
4960+ list_entry * entries = list -> entries ;
4961+
4962+ size_t available = list -> available ;
4963+
4964+ /*
4965+ * the second statement of the expression needs to be recalculated on each
4966+ * iteration as the available number of entries may change within the given
4967+ * callback.
4968+ * Ie: in case the callback calls srtp_stream_list_remove().
4969+ */
4970+ for (unsigned int i = 0 ; i < list -> size - list -> available ;) {
4971+ if (callback (entries [i ].stream , data )) {
49134972 break ;
4973+ }
4974+
4975+ // the entry was not removed, increase the counter.
4976+ if (available == list -> available ) {
4977+ ++ i ;
4978+ }
4979+
4980+ available = list -> available ;
49144981 }
49154982}
49164983
0 commit comments