#include <sofia-sip/su_alloc.h>
#include <sofia-sip/su_types.h>
+#include <sofia-sip/su_string.h>
#include "sofia-sip/sdp.h"
/* ---------------------------------------------------------------------- */
-/* Compare two string pointers */
-su_inline
-int str0cmp(char const *a, char const *b)
-{
- if (a == NULL) a = "";
- if (b == NULL) b = "";
- return strcmp(a, b);
-}
-
-/* Compare two string pointers ignoring case. */
-su_inline
-int str0casecmp(char const *a, char const *b)
-{
- if (a == NULL) a = "";
- if (b == NULL) b = "";
- return strcasecmp(a, b);
-}
-
/** Compare two session descriptions
*/
int sdp_session_cmp(sdp_session_t const *a, sdp_session_t const *b)
return rv;
if ((rv = sdp_origin_cmp(a->sdp_origin, b->sdp_origin)))
return rv;
- if ((rv = str0cmp(a->sdp_subject, b->sdp_subject)))
+ if ((rv = su_strcmp(a->sdp_subject, b->sdp_subject)))
return rv;
- if ((rv = str0cmp(a->sdp_information, b->sdp_information)))
+ if ((rv = su_strcmp(a->sdp_information, b->sdp_information)))
return rv;
- if ((rv = str0cmp(a->sdp_uri, b->sdp_uri)))
+ if ((rv = su_strcmp(a->sdp_uri, b->sdp_uri)))
return rv;
if ((rv = sdp_list_cmp(a->sdp_emails, b->sdp_emails)))
return rv;
return a->o_version < b->o_version ? -1 : 1;
if (a->o_id != b->o_id)
return a->o_id < b->o_id ? -1 : 1;
- if ((rv = strcasecmp(a->o_username, b->o_username)))
+ if ((rv = su_strcasecmp(a->o_username, b->o_username)))
return rv;
- if ((rv = strcasecmp(a->o_address->c_address, b->o_address->c_address)))
+ if ((rv = su_strcasecmp(a->o_address->c_address, b->o_address->c_address)))
return rv;
return 0;
if (a->k_method != b->k_method)
return a->k_method < b->k_method ? -1 : 1;
if (a->k_method == sdp_key_x &&
- (rv = str0cmp(a->k_method_name, b->k_method_name)))
+ (rv = su_strcmp(a->k_method_name, b->k_method_name)))
return rv;
- return str0cmp(a->k_material, b->k_material);
+ return su_strcmp(a->k_material, b->k_material);
}
/** Compare two attribute (a=) fields */
if ((a != NULL) != (b != NULL))
return (a != NULL) < (b != NULL) ? -1 : 1;
- if ((rv = str0cmp(a->a_name, b->a_name)))
+ if ((rv = su_strcmp(a->a_name, b->a_name)))
return rv;
- return str0cmp(a->a_value, b->a_value);
+ return su_strcmp(a->a_value, b->a_value);
}
/** Compare two rtpmap structures. */
return a->rm_pt < b->rm_pt ? -1 : 1;
/* Case insensitive encoding */
- if ((rv = str0cmp(a->rm_encoding, b->rm_encoding)))
+ if ((rv = su_strcmp(a->rm_encoding, b->rm_encoding)))
return rv;
/* Rate */
if (a->rm_rate != b->rm_rate)
if (b->rm_params)
b_param = b->rm_params;
- rv = strcasecmp(a_param, b_param);
+ rv = su_strcasecmp(a_param, b_param);
if (rv)
return rv;
}
- return str0casecmp(a->rm_fmtp, b->rm_fmtp);
+ return su_strcasecmp(a->rm_fmtp, b->rm_fmtp);
}
/** Compare two lists. */
return 0;
if ((a != NULL) != (b != NULL))
return (a != NULL) < (b != NULL) ? -1 : 1;
- if ((rv = str0cmp(a->l_text, b->l_text)))
+ if ((rv = su_strcmp(a->l_text, b->l_text)))
return rv;
}
if (a->m_type != b->m_type)
return a->m_type < b->m_type ? -1 : 1;
if (a->m_type == sdp_media_x)
- if ((rv = str0cmp(a->m_type_name, b->m_type_name)))
+ if ((rv = su_strcmp(a->m_type_name, b->m_type_name)))
return rv;
if (a->m_port != b->m_port)
return a->m_port < b->m_port ? -1 : 1;
if (a->m_proto != b->m_proto)
return a->m_proto < b->m_proto ? -1 : 1;
if (a->m_proto == sdp_media_x)
- if ((rv = str0cmp(a->m_proto_name, b->m_proto_name)))
+ if ((rv = su_strcmp(a->m_proto_name, b->m_proto_name)))
return rv;
if (a->m_mode != b->m_mode)
if ((rv = sdp_list_cmp(a->m_format, b->m_format)))
return rv;
- if ((rv = str0cmp(a->m_information, b->m_information)))
+ if ((rv = su_strcmp(a->m_information, b->m_information)))
return rv;
for (ac = a->m_connections, bc = b->m_connections;
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)
+ if (su_casematch(a->a_name, name))
break;
}
char const *name)
{
for (; a; a = a->a_next) {
- if (strcasecmp(a->a_name, name) == 0)
+ if (su_casematch(a->a_name, name))
break;
}
if (a == 0)
for (a = a2; a; a = a->a_next) {
- if (strcasecmp(a->a_name, name) == 0)
+ if (su_casematch(a->a_name, name))
break;
}
sdp_mode_t sdp_attribute_mode(sdp_attribute_t const *a, sdp_mode_t defmode)
{
for (; a; a = a->a_next) {
- if (strcasecmp(a->a_name, "sendrecv") == 0)
+ if (su_casematch(a->a_name, "sendrecv"))
return sdp_sendrecv;
- if (strcasecmp(a->a_name, "inactive") == 0)
+ if (su_casematch(a->a_name, "inactive"))
return sdp_inactive;
- if (strcasecmp(a->a_name, "recvonly") == 0)
+ if (su_casematch(a->a_name, "recvonly"))
return sdp_recvonly;
- if (strcasecmp(a->a_name, "sendonly") == 0)
+ if (su_casematch(a->a_name, "sendonly"))
return sdp_sendonly;
}
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)
+ if (su_casematch((*list)->a_name, a->a_name))
break;
}
return NULL;
for (a = *list; a; list = &a->a_next, a = *list) {
- if (strcasecmp(name, a->a_name) == 0)
+ if (su_casematch(name, a->a_name))
break;
}
type_name = "";
if (type != m->m_type ||
- (type == sdp_media_x && strcasecmp(m->m_type_name, type_name)))
+ (type == sdp_media_x && !su_casematch(m->m_type_name, type_name)))
return 0;
if (proto == sdp_proto_any || m->m_proto == sdp_proto_any)
proto_name = "";
if (proto != m->m_proto ||
- (proto == sdp_proto_x && strcasecmp(m->m_proto_name, proto_name)))
+ (proto == sdp_proto_x && !su_casematch(m->m_proto_name, proto_name)))
return 0;
return 1;
return 1;
if (a->m_type != b->m_type ||
- (a->m_type == sdp_media_x &&
- strcasecmp(b->m_type_name, a->m_type_name)))
+ (a->m_type == sdp_media_x
+ && !su_casematch(b->m_type_name, a->m_type_name)))
return 0;
if (a->m_proto == sdp_proto_any || b->m_proto == sdp_proto_any)
return 1;
if (a->m_proto != b->m_proto ||
- (a->m_proto == sdp_proto_x &&
- strcasecmp(b->m_proto_name, a->m_proto_name)))
+ (a->m_proto == sdp_proto_x
+ && !su_casematch(b->m_proto_name, a->m_proto_name)))
return 0;
return 1;
(m->m_proto == sdp_proto_rtp ||
m->m_proto == sdp_proto_srtp ||
(m->m_proto == sdp_proto_x && m->m_proto_name &&
- strncasecmp(m->m_proto_name, "RTP/", 4) == 0));
+ su_casenmatch(m->m_proto_name, "RTP/", 4)));
}
/** Check if payload type, rtp rate and parameters match in rtpmaps*/
if (a->rm_rate != b->rm_rate)
return 0;
- if (strcasecmp(a->rm_encoding, b->rm_encoding))
+ if (!su_casematch(a->rm_encoding, b->rm_encoding))
return 0;
aparam = a->rm_params; bparam = b->rm_params;
if (!aparam) aparam = "1"; if (!bparam) bparam = "1";
- if (strcasecmp(aparam, bparam))
+ if (!su_casematch(aparam, bparam))
return 0;
return 1;
if (rm->rm_rate != list->rm_rate)
continue;
- if (strcasecmp(rm->rm_encoding, list->rm_encoding) != 0)
+ if (!su_casematch(rm->rm_encoding, list->rm_encoding))
continue;
lparam = rm->rm_params; rparam = list->rm_params;
break;
if (!lparam) lparam = "1"; if (!rparam) rparam = "1";
- if (strcasecmp(lparam, rparam))
+ if (!su_casematch(lparam, rparam))
continue;
break;
* @author Kai Vehmanen <kai.vehmanen@nokia.com>
*
* @date Created: Fri Feb 18 10:25:08 2000 ppessi
+ *
+ * @sa @RFC4566, @RFC2327.
*/
#include "config.h"
#include <sofia-sip/su_alloc.h>
+#include <sofia-sip/su_string.h>
#include "sofia-sip/sdp.h"
*
* SDP parser handle.
*
- * The SDP parser handle is returned by sdp_parse(). It contains either
- * successfully parse SDP session #sdp_session_t or an error message.
+ * The SDP parser handle returned by sdp_parse() contains either
+ * a successfully parsed SDP session #sdp_session_t or an error message.
* If sdp_session() returns non-NULL, parsing was successful.
*
* @sa #sdp_session_t, sdp_parse(), sdp_session(), sdp_parsing_error(),
- * sdp_sanity_check(), sdp_parser_home(), sdp_parser_free().
+ * sdp_sanity_check(), sdp_parser_home(), sdp_parser_free(), @RFC4566,
+ * @RFC2327.
*/
struct sdp_parser_s {
* Always a valid parser handle.
*
* @todo Parser accepts some non-conforming SDP even with #sdp_f_strict.
+ *
+ * @sa sdp_session(), sdp_parsing_error(), sdp_sanity_check(),
+ * sdp_parser_home(), sdp_parser_free(), @RFC4566, @RFC2327.
*/
sdp_parser_t *
sdp_parse(su_home_t *home, char const msg[], issize_t msgsize, int flags)
/* Require that version comes first */
record = next(&message, CRLF, strip);
- if (!record || strcmp(record, "v=0")) {
+ if (!su_strmatch(record, "v=0")) {
if (!p->pr_config || !record || record[1] != '=') {
parsing_error(p, "bad SDP message");
return;
return
c &&
c->c_nettype == sdp_net_in &&
- ((c->c_addrtype == sdp_addr_ip4 && strcmp(c->c_address, "0.0.0.0")) ||
- (c->c_addrtype == sdp_addr_ip6 && strcmp(c->c_address, "::")));
+ ((c->c_addrtype == sdp_addr_ip4 && su_strmatch(c->c_address, "0.0.0.0")) ||
+ (c->c_addrtype == sdp_addr_ip6 && su_strmatch(c->c_address, "::")));
}
/**Postprocess session description.
*
- * The function post_session() postprocesses the session description. The
- * postprocessing includes setting the session backpointer for each media.
+ * Postprocessing includes setting the session backpointer for each media,
+ * doing sanity checks and setting rejected and mode flags.
*/
static void post_session(sdp_parser_t *p, sdp_session_t *sdp)
{
c = sdp_media_connections(m);
- if (p->pr_mode_0000 && c) {
- if (c->c_nettype == sdp_net_in &&
- c->c_addrtype == sdp_addr_ip4 &&
- strcmp(c->c_address, "0.0.0.0") == 0)
- /* Reset recvonly flag */
- m->m_mode &= ~sdp_recvonly;
+ if (p->pr_mode_0000 && sdp_connection_is_inaddr_any(c)) {
+ /* Reset recvonly flag */
+ m->m_mode &= ~sdp_recvonly;
}
}
*result = c;
- if (strncasecmp(r, "IN", 2) == 0) {
+ if (su_casenmatch(r, "IN", 2)) {
char *s;
/* nettype is internet */
/* addrtype */
s = token(&r, SPACE TAB, NULL, NULL);
- if (s && strcasecmp(s, "IP4") == 0)
+ if (su_casematch(s, "IP4"))
c->c_addrtype = sdp_addr_ip4;
- else if (s && strcasecmp(s, "IP6") == 0)
+ else if (su_casematch(s, "IP6"))
c->c_addrtype = sdp_addr_ip6;
else {
parsing_error(p, "unknown IN address type: %s", s);
return;
}
- if (strcmp(name, "CT") == 0)
+ if (su_casematch(name, "CT"))
modifier = sdp_bw_ct, name = NULL;
- else if (strcmp(name, "AS") == 0)
+ else if (su_casematch(name, "AS") == 0)
modifier = sdp_bw_as, name = NULL;
else
modifier = sdp_bw_x;
int n, N;
char *s;
sdp_repeat_t *r;
+ int strict = STRICT(p);
/** Count number of intervals */
for (N = 0, s = d; *s; ) {
- if (!(is_posdigit(*s) || (!STRICT(p) && (*s) == '0')))
+ if (!(is_posdigit(*s) || (!strict && (*s) == '0')))
break;
do { s++; } while (is_digit(*s));
- if (*s && strchr("dhms", *s))
+ if (*s && strchr(strict ? "dhms" : "dhmsDHMS", *s))
s++;
N++;
- if (!(i = STRICT(p) ? is_space(*s) : strspn(s, SPACE TAB)))
+ if (!(i = strict ? is_space(*s) : strspn(s, SPACE TAB)))
break;
s += i;
}
tt = strtoul(d, &d, 10);
switch (*d) {
- case 'd': tt *= 24;
- case 'h': tt *= 60;
- case 'm': tt *= 60;
- case 's': d++;
+ case 'd': case 'D': tt *= 24;
+ case 'h': case 'H': tt *= 60;
+ case 'm': case 'M': tt *= 60;
+ case 's': case 'S': d++;
break;
}
/* These are defined as key-sensitive in RFC 4566 */
#define MATCH(s, tok) \
- (STRICT(p) ? strcmp((s), (tok)) == 0 : strcasecmp((s), (tok)) == 0)
+ (STRICT(p) ? su_strmatch((s), (tok)) : su_casematch((s), (tok)))
if (MATCH(s, "clear"))
k->k_method = sdp_key_clear, k->k_method_name = "clear";
else
PARSE_CHECK_REST(p, r, "a");
- if (strcasecmp(name, "charset") == 0) {
+ if (su_casematch(name, "charset")) {
p->pr_session->sdp_charset = value;
return;
}
if (p->pr_mode_manual)
;
- else if (strcasecmp(name, "inactive") == 0)
+ else if (su_casematch(name, "inactive"))
p->pr_session_mode = sdp_inactive;
- else if (strcasecmp(name, "sendonly") == 0)
+ else if (su_casematch(name, "sendonly"))
p->pr_session_mode = sdp_sendonly;
- else if (strcasecmp(name, "recvonly") == 0)
+ else if (su_casematch(name, "recvonly"))
p->pr_session_mode = sdp_recvonly;
- else if (strcasecmp(name, "sendrecv") == 0)
+ else if (su_casematch(name, "sendrecv"))
p->pr_session_mode = sdp_sendrecv;
{
return;
}
- if (!STRICT(p) && strcasecmp(s, "RTP") == 0)
+ if (!STRICT(p) && su_casematch(s, "RTP"))
m->m_proto = sdp_proto_rtp, m->m_proto_name = "RTP/AVP";
else
sdp_media_transport(m, s);
/** Set media type */
void sdp_media_type(sdp_media_t *m, char const *s)
{
- if (strcmp(s, "*") == 0)
+ if (su_strmatch(s, "*"))
m->m_type = sdp_media_any, m->m_type_name = "*";
- else if (strcasecmp(s, "audio") == 0)
+ else if (su_casematch(s, "audio"))
m->m_type = sdp_media_audio, m->m_type_name = "audio";
- else if (strcasecmp(s, "video") == 0)
+ else if (su_casematch(s, "video"))
m->m_type = sdp_media_video, m->m_type_name = "video";
- else if (strcasecmp(s, "application") == 0)
+ else if (su_casematch(s, "application"))
m->m_type = sdp_media_application, m->m_type_name = "application";
- else if (strcasecmp(s, "data") == 0)
+ else if (su_casematch(s, "data"))
m->m_type = sdp_media_data, m->m_type_name = "data";
- else if (strcasecmp(s, "control") == 0)
+ else if (su_casematch(s, "control"))
m->m_type = sdp_media_control, m->m_type_name = "control";
- else if (strcasecmp(s, "message") == 0)
+ else if (su_casematch(s, "message"))
m->m_type = sdp_media_message, m->m_type_name = "message";
- else if (strcasecmp(s, "image") == 0)
+ else if (su_casematch(s, "image"))
m->m_type = sdp_media_image, m->m_type_name = "image";
- else if (strcasecmp(s, "red") == 0)
+ else if (su_casematch(s, "red"))
m->m_type = sdp_media_red, m->m_type_name = "red";
else
m->m_type = sdp_media_x, m->m_type_name = s;
}
+/** Set transport protocol.
+ *
+ * Set the @m->m_proto to a well-known protocol type as
+ * well as canonize case of @a m_proto_name.
+ */
void sdp_media_transport(sdp_media_t *m, char const *s)
{
- if (strcasecmp(s, "*") == 0)
+ if (m == NULL || s == NULL)
+ ;
+ else if (su_strmatch(s, "*"))
m->m_proto = sdp_proto_any, m->m_proto_name = "*";
- else if (strcasecmp(s, "RTP/AVP") == 0)
+ else if (su_casematch(s, "RTP/AVP"))
m->m_proto = sdp_proto_rtp, m->m_proto_name = "RTP/AVP";
- else if (strcasecmp(s, "RTP/SAVP") == 0)
+ else if (su_casematch(s, "RTP/SAVP"))
m->m_proto = sdp_proto_srtp, m->m_proto_name = "RTP/SAVP";
- else if (strcasecmp(s, "udptl") == 0)
+ else if (su_casematch(s, "udptl"))
/* Lower case - be compatible with people living by T.38 examples */
m->m_proto = sdp_proto_udptl, m->m_proto_name = "udptl";
- else if (strcasecmp(s, "UDP") == 0)
+ else if (su_casematch(s, "UDP"))
m->m_proto = sdp_proto_udp, m->m_proto_name = "UDP";
- else if (strcasecmp(s, "TCP") == 0)
+ else if (su_casematch(s, "TCP"))
m->m_proto = sdp_proto_tcp, m->m_proto_name = "TCP";
- else if (strcasecmp(s, "TLS") == 0)
+ else if (su_casematch(s, "TLS"))
m->m_proto = sdp_proto_tls, m->m_proto_name = "TLS";
else
m->m_proto = sdp_proto_x, m->m_proto_name = s;
if (p->pr_mode_manual)
;
- else if (strcasecmp(name, "inactive") == 0) {
+ else if (su_casematch(name, "inactive")) {
m->m_mode = sdp_inactive;
return;
}
- else if (strcasecmp(name, "sendonly") == 0) {
+ else if (su_casematch(name, "sendonly")) {
m->m_mode = sdp_sendonly;
return;
}
- else if (strcasecmp(name, "recvonly") == 0) {
+ else if (su_casematch(name, "recvonly")) {
m->m_mode = sdp_recvonly;
return;
}
- else if (strcasecmp(name, "sendrecv") == 0) {
+ else if (su_casematch(name, "sendrecv")) {
m->m_mode = sdp_sendrecv;
return;
}
- if (rtp && strcasecmp(name, "rtpmap") == 0) {
+ if (rtp && su_casematch(name, "rtpmap")) {
if ((n = parse_rtpmap(p, r, m)) == 0 || n < -1)
return;
}
- else if (rtp && strcasecmp(name, "fmtp") == 0) {
+ else if (rtp && su_casematch(name, "fmtp")) {
if ((n = parse_fmtp(p, r, m)) == 0 || n < -1)
return;
}