Commit 870977d2 authored by Pekka Pessi's avatar Pekka Pessi

Add helper functions to update or modify sdp attributes.

Feature request #1420698:
Added sdp_attribute_append(), sdp_attribute_replace(), and sdp_attribute_remove().

darcs-hash:20060201134415-65a35-e5286d2486210ec43b857bd43b092665e9dc1968.gz
parent d3b0f746
......@@ -1480,7 +1480,7 @@ int sdp_media_cmp(sdp_media_t const *a, sdp_media_t const *b)
/* ---------------------------------------------------------------------- */
sdp_connection_t *sdp_media_connections(sdp_media_t *m)
sdp_connection_t *sdp_media_connections(sdp_media_t const *m)
{
if (m) {
if (m->m_connections)
......@@ -1494,19 +1494,19 @@ sdp_connection_t *sdp_media_connections(sdp_media_t *m)
/* ---------------------------------------------------------------------- */
/** Find named attribute from given list. */
sdp_attribute_t *sdp_attribute_find(sdp_attribute_t *a, char const *name)
sdp_attribute_t *sdp_attribute_find(sdp_attribute_t const *a, char const *name)
{
for (; a; a = a->a_next) {
if (strcasecmp(a->a_name, name) == 0)
break;
}
return a;
return (sdp_attribute_t *)a;
}
/** Find named attribute from given lists (a or a2). */
sdp_attribute_t *sdp_attribute_find2(sdp_attribute_t *a,
sdp_attribute_t *a2,
sdp_attribute_t *sdp_attribute_find2(sdp_attribute_t const *a,
sdp_attribute_t const *a2,
char const *name)
{
for (; a; a = a->a_next) {
......@@ -1520,7 +1520,7 @@ sdp_attribute_t *sdp_attribute_find2(sdp_attribute_t *a,
break;
}
return a;
return (sdp_attribute_t *)a;
}
/** Get session mode from attribute list. */
......@@ -1566,36 +1566,133 @@ sdp_attribute_t *sdp_attribute_by_mode(su_home_t *home, sdp_mode_t mode)
/** Find a mapped attribute.
*
* A mapped attribute has form 'a=attribute:pt value'.
*
* A mapped attribute has form 'a=<name>:<pt> <value>' where pt is a RTP payload type,
* integer in range 0..127.
*
* result will point to value if it is found
* @return Pointer to a matching attribute structure, or NULL. If a matching
* attribute is found, @a return_result will point to part of the attribute
* after the payload type and whitespace.
*/
sdp_attribute_t *sdp_attribute_mapped_find(sdp_attribute_t *a,
sdp_attribute_t *sdp_attribute_mapped_find(sdp_attribute_t const *a,
char const *name,
int pt, char **result)
int pt, char **return_result)
{
*result = NULL;
char pt_value[4];
size_t pt_len;
if (return_result)
*return_result = NULL;
if (0 > pt || pt > 127)
return NULL;
snprintf(pt_value, sizeof(pt_value), "%u", (unsigned)pt);
pt_len = strlen(pt_value);
for (; (a = sdp_attribute_find(a, name)); a = a->a_next) {
char *value;
char const *value = a->a_value;
size_t wlen;
if (pt != (int)strtoul(a->a_value, &value, 10) || value == a->a_value)
if (strncmp(value, pt_value, pt_len))
continue;
value += strspn(value, " \t");
wlen = strspn(value + pt_len, " \t");
if (!value[0])
if (wlen == 0 || value[pt_len + wlen] == '\0')
continue;
*result = value;
if (return_result)
*return_result = (char *)value + pt_len + wlen;
return a;
return (sdp_attribute_t *)a;
}
return NULL;
}
/** Append a (list of) attribute(s) to a list of attributes. */
void sdp_attribute_append(sdp_attribute_t **list,
sdp_attribute_t const *a)
{
assert(list);
if (list == NULL || a == NULL)
return;
for (;*list; list = &(*list)->a_next)
;
*list = (sdp_attribute_t *)a;
}
/**Replace or append a attribute within a list of attributes.
*
* @retval 1 if replaced existing attribute
* @retval 0 if attribute was appended
* @retval -1 upon an error
*/
int sdp_attribute_replace(sdp_attribute_t **list,
sdp_attribute_t *a,
sdp_attribute_t **return_replaced)
{
sdp_attribute_t *replaced;
assert(list);
if (return_replaced)
*return_replaced = NULL;
if (list == NULL || a == NULL)
return -1;
assert(a->a_name != NULL); assert(a->a_next == NULL);
for (; *list; list = &(*list)->a_next) {
if (strcasecmp((*list)->a_name, a->a_name) == 0)
break;
}
replaced = *list, *list = a;
if (replaced) {
a->a_next = replaced->a_next;
replaced->a_next = NULL;
if (return_replaced)
*return_replaced = replaced;
return 1;
}
return 0;
}
/** Remove a named attribute from a list of attributes. */
sdp_attribute_t *sdp_attribute_remove(sdp_attribute_t **list,
char const *name)
{
sdp_attribute_t *a;
assert(list);
if (list == NULL)
return NULL;
if (name == NULL)
return NULL;
for (a = *list; a; list = &a->a_next, a = *list) {
if (strcasecmp(name, a->a_name) == 0)
break;
}
if (a) {
*list = a->a_next;
a->a_next = NULL;
}
return a;
}
/* Return 1 if m= line struct matches with given type and name */
unsigned sdp_media_match(sdp_media_t const *m,
sdp_media_e type,
......
......@@ -69,7 +69,7 @@ typedef struct sdp_list_s sdp_list_t;
typedef struct sdp_rtpmap_s sdp_rtpmap_t;
/** Message text */
typedef char const sdp_text_t;
typedef char const sdp_text_t;
#define SDP_MIME_TYPE "application/sdp"
......@@ -396,7 +396,7 @@ int sdp_rtpmap_cmp(sdp_rtpmap_t const *a, sdp_rtpmap_t const *b);
int sdp_list_cmp(sdp_list_t const *a, sdp_list_t const *b);
/** Get connections of a media description */
sdp_connection_t *sdp_media_connections(sdp_media_t *m);
sdp_connection_t *sdp_media_connections(sdp_media_t const *m);
/** Check if media uses RTP as its transport protocol */
int sdp_media_has_rtp(sdp_media_t const *m);
......@@ -408,11 +408,11 @@ void sdp_media_type(sdp_media_t *m, char const *s);
void sdp_media_transport(sdp_media_t *m, char const *s);
/** Find named attribute from given list. */
sdp_attribute_t *sdp_attribute_find(sdp_attribute_t *a, char const *name);
sdp_attribute_t *sdp_attribute_find(sdp_attribute_t const *a, char const *name);
/** Find named attribute from given lists. */
sdp_attribute_t *sdp_attribute_find2(sdp_attribute_t *a,
sdp_attribute_t *a2,
sdp_attribute_t *sdp_attribute_find2(sdp_attribute_t const *a,
sdp_attribute_t const *a2,
char const *name);
/** Get session mode from attribute list. */
......@@ -421,14 +421,26 @@ sdp_mode_t sdp_attribute_mode(sdp_attribute_t const *a, sdp_mode_t defmode);
/** Get session mode from attribute list. */
sdp_attribute_t *sdp_attribute_by_mode(su_home_t *, sdp_mode_t mode);
/** Find a mapped attribute of form 'a=attribute:pt value'
* result will point to value if it is found. */
sdp_attribute_t *sdp_attribute_mapped_find(sdp_attribute_t *a,
/** Find a mapped attribute. */
sdp_attribute_t *sdp_attribute_mapped_find(sdp_attribute_t const *a,
char const *name,
int pt, char **result);
int pt, char **return_result);
#define sdp_mapped_attribute_find sdp_attribute_mapped_find
/** Append a attribute to a list of attributes. */
void sdp_attribute_append(sdp_attribute_t **list,
sdp_attribute_t const *a);
/** Replace a attribute within a list of attributes. */
int sdp_attribute_replace(sdp_attribute_t **list,
sdp_attribute_t *a,
sdp_attribute_t **return_replaced);
/** Remove a named attribute from a list of attributes. */
sdp_attribute_t *sdp_attribute_remove(sdp_attribute_t **list,
char const *name);
/* Return 1 if m= line struct matches with given type and name */
unsigned sdp_media_match(sdp_media_t const *m,
sdp_media_e type,
......
......@@ -560,7 +560,7 @@ static sdp_attribute_t const a1[1] =
static int test_attribute(int flags)
{
su_home_t *home = su_home_create();
sdp_attribute_t *a;
sdp_attribute_t *a, *a_new, *list, *replaced;
BEGIN();
......@@ -587,6 +587,27 @@ static int test_attribute(int flags)
TEST_S(a->a_next->a_name, "foo");
TEST_S(a->a_next->a_value, "2");
list = a;
TEST(sdp_attribute_remove(&list, NULL), NULL);
TEST(sdp_attribute_remove(&list, "kuik"), NULL);
TEST(sdp_attribute_remove(&list, "barf"), NULL);
TEST(sdp_attribute_remove(&list, "bar"), a);
TEST_1(a_new = sdp_attribute_dup(home, a));
replaced = (void *)-1;
TEST(sdp_attribute_replace(&list, NULL, &replaced), -1);
TEST(replaced, NULL);
TEST(sdp_attribute_replace(&list, a, &replaced), 0);
TEST(replaced, NULL);
TEST(sdp_attribute_replace(&list, a_new, &replaced), 1);
TEST(replaced, a);
TEST_VOID(sdp_attribute_append(&list, a));
TEST(sdp_attribute_remove(&list, "bAr"), a_new);
TEST(sdp_attribute_remove(&list, "BAR"), a);
TEST(sdp_attribute_remove(&list, "bar"), NULL);
su_home_check(home);
su_home_destroy(home);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment