Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stream_index #674

Merged
merged 16 commits into from
Jan 12, 2024
17 changes: 17 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,7 @@ ac_subst_files=''
ac_user_opts='
enable_option_checking
enable_debug_logging
enable_stream_index
enable_openssl
enable_nss
with_openssl_dir
Expand Down Expand Up @@ -5326,6 +5327,22 @@ fi
$as_echo "$enable_debug_logging" >&6; }


{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable stream index" >&5
$as_echo_n "checking whether to enable stream index... " >&6; }
# Check whether --enable-stream-index was given.
if test "${enable-stream-index+set}" = set; then :
enableval=$enable_stream_index;
else
enable_stream_index=no
fi

if test "$enable_stream_index" = "yes"; then

$as_echo "#define ENABLE_STREAM_INDEX 1" >>confdefs.h

fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_stream_index" >&5
$as_echo "$enable_stream_index" >&6; }



Expand Down
4 changes: 4 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ if get_option('debug-logging')
cdata.set('ENABLE_DEBUG_LOGGING', true)
endif

if get_option('stream-index')
cdata.set('ENABLE_STREAM_INDEX', true)
endif

use_openssl = false
use_nss = false
use_mbedtls = false
Expand Down
2 changes: 2 additions & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ option('crypto-library', type: 'combo', choices : ['none', 'openssl', 'nss', 'mb
description : 'What external crypto library to leverage, if any (OpenSSL, NSS, or mbedtls)')
option('crypto-library-kdf', type : 'feature', value : 'auto',
description : 'Use the external crypto library for Key Derivation Function support')
option('stream-index', type : 'boolean', value : 'false',
description : 'Enable stream index for fast stream retrieval')
option('fuzzer', type : 'feature', value : 'disabled',
description : 'Build libsrtp2 fuzzer (requires build with clang)')
option('tests', type : 'feature', value : 'auto', yield : true,
Expand Down
158 changes: 158 additions & 0 deletions srtp/srtp.c
Original file line number Diff line number Diff line change
Expand Up @@ -4841,6 +4841,7 @@ srtp_err_status_t srtp_get_stream_roc(srtp_t session,

#ifndef SRTP_NO_STREAM_LIST

#ifndef ENABLE_STREAM_INDEX
/* in the default implementation, we have an intrusive doubly-linked list */
typedef struct srtp_stream_list_ctx_t_ {
/* a stub stream that just holds pointers to the beginning and end of the
Expand Down Expand Up @@ -4926,4 +4927,161 @@ void srtp_stream_list_for_each(srtp_stream_list_t list,
}
}

#else

#define INITIAL_STREAM_INDEX_SIZE 2

typedef struct list_entry {
uint32_t ssrc;
srtp_stream_t stream;
} list_entry;

typedef struct srtp_stream_list_ctx_t_ {
list_entry *entries;
size_t size;
size_t available;
} srtp_stream_list_ctx_t_;

srtp_err_status_t srtp_stream_list_alloc(srtp_stream_list_t *list_ptr)
{
srtp_stream_list_t list =
srtp_crypto_alloc(sizeof(srtp_stream_list_ctx_t_));
if (list == NULL) {
return srtp_err_status_alloc_fail;
}

list->entries =
srtp_crypto_alloc(sizeof(list_entry) * INITIAL_STREAM_INDEX_SIZE);
if (list->entries == NULL) {
srtp_crypto_free(list);
return srtp_err_status_alloc_fail;
}

list->size = INITIAL_STREAM_INDEX_SIZE;
list->available = INITIAL_STREAM_INDEX_SIZE;

*list_ptr = list;

return srtp_err_status_ok;
}

srtp_err_status_t srtp_stream_list_dealloc(srtp_stream_list_t list)
{
/* list must be empty */
if (list->available != list->size) {
return srtp_err_status_fail;
}

srtp_crypto_free(list->entries);
srtp_crypto_free(list);

return srtp_err_status_ok;
}

/*
* inserting a new entry in the list may require reallocating memory in order
* to keep all the items in a contiguous memory block.
*/
srtp_err_status_t srtp_stream_list_insert(srtp_stream_list_t list,
srtp_stream_t stream)
{
/*
* there is no space to hold the new entry in the entries buffer,
* duplicate the size of the buffer.
jmillan marked this conversation as resolved.
Show resolved Hide resolved
*/
if (list->available == 0) {
size_t new_size = list->size * 2;
list_entry *new_entries =
srtp_crypto_alloc(sizeof(list_entry) * new_size);
if (new_entries == NULL) {
return srtp_err_status_alloc_fail;
}

// copy previous entries into the new buffer
memcpy(new_entries, list->entries, sizeof(list_entry) * list->size);
// release previous entries
srtp_crypto_free(list->entries);
// assign new entries to the list
list->entries = new_entries;
// update list info
list->size = new_size;
list->available = new_size / 2;
}

// fill the first available entry
size_t next_index = list->size - list->available;
list->entries[next_index].ssrc = stream->ssrc;
list->entries[next_index].stream = stream;

// update available value
list->available--;

return srtp_err_status_ok;
}

/*
* removing an entry from the list performs a memory move of the following
* entries one possition back in order to keep all the entries in the buffer
* contiguous.
*/
void srtp_stream_list_remove(srtp_stream_list_t list,
srtp_stream_t stream_to_remove)
{
unsigned int end = list->size - list->available;

for (unsigned int i = 0; i < end; i++) {
if (list->entries[i].ssrc == stream_to_remove->ssrc) {
size_t entries_to_move = list->size - list->available - i - 1;
memmove(&list->entries[i], &list->entries[i + 1],
entries_to_move * sizeof(list_entry));
list->available++;

break;
}
}
}

srtp_stream_t srtp_stream_list_get(srtp_stream_list_t list, uint32_t ssrc)
{
unsigned int end = list->size - list->available;

list_entry *entries = list->entries;

for (unsigned int i = 0; i < end; i++) {
if (entries[i].ssrc == ssrc) {
return entries[i].stream;
}
}

return NULL;
}

void srtp_stream_list_for_each(srtp_stream_list_t list,
int (*callback)(srtp_stream_t, void *),
void *data)
{
list_entry *entries = list->entries;

unsigned int ssrc;
jmillan marked this conversation as resolved.
Show resolved Hide resolved

/*
* the second statement of the expression needs to be recalculated on each
* iteration as the available number of entries may change within the given
* callback.
* Ie: in case the callback calls srtp_stream_list_remove().
*/
for (unsigned int i = 0; i < list->size - list->available;) {
ssrc = entries[i].ssrc;
if (callback(entries[i].stream, data)) {
break;
}

// the entry was not removed, increase the counter.
if (ssrc == entries[i].ssrc) {
++i;
}
}
}

#endif
#endif
Loading