Skip to content

Commit 37d88ec

Browse files
authored
Merge pull request #674 from jmillan/stream_index
stream_index
2 parents 4c74586 + 1828b47 commit 37d88ec

File tree

3 files changed

+105
-47
lines changed

3 files changed

+105
-47
lines changed

include/srtp_priv.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,14 +144,6 @@ typedef struct srtp_stream_ctx_t_ {
144144
int *enc_xtn_hdr;
145145
int enc_xtn_hdr_count;
146146
uint32_t pending_roc;
147-
/*
148-
The next and prev pointers are here to allow for a stream list to be
149-
implemented as an intrusive doubly-linked list (the former being the
150-
default). Other stream list implementations can ignore these fields or use
151-
them for some other purpose specific to the stream list implementation.
152-
*/
153-
struct srtp_stream_ctx_t_ *next;
154-
struct srtp_stream_ctx_t_ *prev;
155147
} strp_stream_ctx_t_;
156148

157149
/*

include/stream_list_priv.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@ extern "C" {
5858
* the API was extracted to allow downstreams to override its
5959
* implementation by defining the `SRTP_NO_STREAM_LIST` preprocessor
6060
* directive, which removes the default implementation of these
61-
* functions. if this is done, the `next` & `prev` fields are free for
62-
* the implementation to use.
61+
* functions.
6362
*
6463
* this is still an internal interface; there is no stability
6564
* guarantee--downstreams should watch this file for changes in

srtp/srtp.c

Lines changed: 104 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
48334836
typedef 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

48394842
srtp_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

48544865
srtp_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+
*/
48644882
srtp_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

49044956
void 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

Comments
 (0)