📄 sdp.c
字号:
{
pjmedia_sdp_attr *attr;
char tempbuf[128];
int len;
/* Check arguments. */
PJ_ASSERT_RETURN(pool && rtpmap && p_attr, PJ_EINVAL);
/* Check that mandatory attributes are specified. */
PJ_ASSERT_RETURN(rtpmap->enc_name.slen && rtpmap->clock_rate,
PJMEDIA_SDP_EINRTPMAP);
attr = pj_pool_alloc(pool, sizeof(pjmedia_sdp_attr));
PJ_ASSERT_RETURN(attr != NULL, PJ_ENOMEM);
attr->name.ptr = "rtpmap";
attr->name.slen = 6;
/* Format: ":pt enc_name/clock_rate[/param]" */
len = pj_ansi_snprintf(tempbuf, sizeof(tempbuf),
"%.*s %.*s/%u%s%.*s",
(int)rtpmap->pt.slen,
rtpmap->pt.ptr,
(int)rtpmap->enc_name.slen,
rtpmap->enc_name.ptr,
rtpmap->clock_rate,
(rtpmap->param.slen ? "/" : ""),
(int)rtpmap->param.slen,
rtpmap->param.ptr);
if (len < 1 || len > sizeof(tempbuf))
return PJMEDIA_SDP_ERTPMAPTOOLONG;
attr->value.slen = len;
attr->value.ptr = pj_pool_alloc(pool, attr->value.slen);
pj_memcpy(attr->value.ptr, tempbuf, attr->value.slen);
*p_attr = attr;
return PJ_SUCCESS;
}
static int print_connection_info( pjmedia_sdp_conn *c, char *buf, int len)
{
int printed;
printed = pj_ansi_snprintf(buf, len, "c=%.*s %.*s %.*s\r\n",
(int)c->net_type.slen,
c->net_type.ptr,
(int)c->addr_type.slen,
c->addr_type.ptr,
(int)c->addr.slen,
c->addr.ptr);
if (printed < 1 || printed > len)
return -1;
return printed;
}
PJ_DEF(pjmedia_sdp_conn*) pjmedia_sdp_conn_clone (pj_pool_t *pool,
const pjmedia_sdp_conn *rhs)
{
pjmedia_sdp_conn *c = pj_pool_alloc (pool, sizeof(pjmedia_sdp_conn));
if (!c) return NULL;
if (!pj_strdup (pool, &c->net_type, &rhs->net_type)) return NULL;
if (!pj_strdup (pool, &c->addr_type, &rhs->addr_type)) return NULL;
if (!pj_strdup (pool, &c->addr, &rhs->addr)) return NULL;
return c;
}
static pj_ssize_t print_attr(const pjmedia_sdp_attr *attr,
char *buf, pj_size_t len)
{
char *p = buf;
if ((int)len < attr->name.slen + attr->value.slen + 10)
return -1;
*p++ = 'a';
*p++ = '=';
pj_memcpy(p, attr->name.ptr, attr->name.slen);
p += attr->name.slen;
if (attr->value.slen) {
*p++ = ':';
pj_memcpy(p, attr->value.ptr, attr->value.slen);
p += attr->value.slen;
}
*p++ = '\r';
*p++ = '\n';
return p-buf;
}
static int print_media_desc( pjmedia_sdp_media *m, char *buf, int len)
{
char *p = buf;
char *end = buf+len;
unsigned i;
int printed;
/* check length for the "m=" line. */
if (len < m->desc.media.slen+m->desc.transport.slen+12+24) {
return -1;
}
*p++ = 'm'; /* m= */
*p++ = '=';
pj_memcpy(p, m->desc.media.ptr, m->desc.media.slen);
p += m->desc.media.slen;
*p++ = ' ';
printed = pj_utoa(m->desc.port, p);
p += printed;
if (m->desc.port_count > 1) {
*p++ = '/';
printed = pj_utoa(m->desc.port_count, p);
p += printed;
}
*p++ = ' ';
pj_memcpy(p, m->desc.transport.ptr, m->desc.transport.slen);
p += m->desc.transport.slen;
for (i=0; i<m->desc.fmt_count; ++i) {
*p++ = ' ';
pj_memcpy(p, m->desc.fmt[i].ptr, m->desc.fmt[i].slen);
p += m->desc.fmt[i].slen;
}
*p++ = '\r';
*p++ = '\n';
/* print connection info, if present. */
if (m->conn) {
printed = print_connection_info(m->conn, p, end-p);
if (printed < 0) {
return -1;
}
p += printed;
}
/* print attributes. */
for (i=0; i<m->attr_count; ++i) {
printed = print_attr(m->attr[i], p, end-p);
if (printed < 0) {
return -1;
}
p += printed;
}
return p-buf;
}
PJ_DEF(pjmedia_sdp_media*) pjmedia_sdp_media_clone(
pj_pool_t *pool,
const pjmedia_sdp_media *rhs)
{
unsigned int i;
pjmedia_sdp_media *m = pj_pool_alloc (pool, sizeof(pjmedia_sdp_media));
PJ_ASSERT_RETURN(m != NULL, NULL);
pj_strdup (pool, &m->desc.media, &rhs->desc.media);
m->desc.port = rhs->desc.port;
m->desc.port_count = rhs->desc.port_count;
pj_strdup (pool, &m->desc.transport, &rhs->desc.transport);
m->desc.fmt_count = rhs->desc.fmt_count;
for (i=0; i<rhs->desc.fmt_count; ++i)
pj_strdup(pool, &m->desc.fmt[i], &rhs->desc.fmt[i]);
if (rhs->conn) {
m->conn = pjmedia_sdp_conn_clone (pool, rhs->conn);
PJ_ASSERT_RETURN(m->conn != NULL, NULL);
} else {
m->conn = NULL;
}
m->attr_count = rhs->attr_count;
for (i=0; i < rhs->attr_count; ++i) {
m->attr[i] = pjmedia_sdp_attr_clone (pool, rhs->attr[i]);
PJ_ASSERT_RETURN(m->attr[i] != NULL, NULL);
}
return m;
}
PJ_DEF(pjmedia_sdp_attr*)
pjmedia_sdp_media_find_attr(const pjmedia_sdp_media *m,
const pj_str_t *name, const pj_str_t *fmt)
{
PJ_ASSERT_RETURN(m && name, NULL);
return pjmedia_sdp_attr_find(m->attr_count, m->attr, name, fmt);
}
PJ_DEF(pjmedia_sdp_attr*)
pjmedia_sdp_media_find_attr2(const pjmedia_sdp_media *m,
const char *name, const pj_str_t *fmt)
{
PJ_ASSERT_RETURN(m && name, NULL);
return pjmedia_sdp_attr_find2(m->attr_count, m->attr, name, fmt);
}
PJ_DEF(pj_status_t) pjmedia_sdp_media_add_attr( pjmedia_sdp_media *m,
pjmedia_sdp_attr *attr)
{
return pjmedia_sdp_attr_add(&m->attr_count, m->attr, attr);
}
PJ_DEF(unsigned)
pjmedia_sdp_media_remove_all_attr(pjmedia_sdp_media *m,
const char *name)
{
return pjmedia_sdp_attr_remove_all(&m->attr_count, m->attr, name);
}
PJ_DEF(pj_status_t)
pjmedia_sdp_media_remove_attr(pjmedia_sdp_media *m,
pjmedia_sdp_attr *attr)
{
return pjmedia_sdp_attr_remove(&m->attr_count, m->attr, attr);
}
static int print_session(const pjmedia_sdp_session *ses,
char *buf, pj_ssize_t len)
{
char *p = buf;
char *end = buf+len;
unsigned i;
int printed;
/* Check length for v= and o= lines. */
if (len < 5+
2+ses->origin.user.slen+18+
ses->origin.net_type.slen+ses->origin.addr.slen + 2)
{
return -1;
}
/* SDP version (v= line) */
pj_memcpy(p, "v=0\r\n", 5);
p += 5;
/* Owner (o=) line. */
*p++ = 'o';
*p++ = '=';
pj_memcpy(p, ses->origin.user.ptr, ses->origin.user.slen);
p += ses->origin.user.slen;
*p++ = ' ';
printed = pj_utoa(ses->origin.id, p);
p += printed;
*p++ = ' ';
printed = pj_utoa(ses->origin.version, p);
p += printed;
*p++ = ' ';
pj_memcpy(p, ses->origin.net_type.ptr, ses->origin.net_type.slen);
p += ses->origin.net_type.slen;
*p++ = ' ';
pj_memcpy(p, ses->origin.addr_type.ptr, ses->origin.addr_type.slen);
p += ses->origin.addr_type.slen;
*p++ = ' ';
pj_memcpy(p, ses->origin.addr.ptr, ses->origin.addr.slen);
p += ses->origin.addr.slen;
*p++ = '\r';
*p++ = '\n';
/* Session name (s=) line. */
if ((end-p) < 8+ses->name.slen) {
return -1;
}
*p++ = 's';
*p++ = '=';
pj_memcpy(p, ses->name.ptr, ses->name.slen);
p += ses->name.slen;
*p++ = '\r';
*p++ = '\n';
/* Connection line (c=) if exist. */
if (ses->conn) {
printed = print_connection_info(ses->conn, p, end-p);
if (printed < 1) {
return -1;
}
p += printed;
}
/* Time */
if ((end-p) < 24) {
return -1;
}
*p++ = 't';
*p++ = '=';
printed = pj_utoa(ses->time.start, p);
p += printed;
*p++ = ' ';
printed = pj_utoa(ses->time.stop, p);
p += printed;
*p++ = '\r';
*p++ = '\n';
/* Print all attribute (a=) lines. */
for (i=0; i<ses->attr_count; ++i) {
printed = print_attr(ses->attr[i], p, end-p);
if (printed < 0) {
return -1;
}
p += printed;
}
/* Print media (m=) lines. */
for (i=0; i<ses->media_count; ++i) {
printed = print_media_desc(ses->media[i], p, end-p);
if (printed < 0) {
return -1;
}
p += printed;
}
return p-buf;
}
/******************************************************************************
* PARSERS
*/
static void parse_version(pj_scanner *scanner, parse_context *ctx)
{
ctx->last_error = PJMEDIA_SDP_EINVER;
/* check equal sign */
if (*(scanner->curptr+1) != '=') {
on_scanner_error(scanner);
return;
}
/* check version is 0 */
if (*(scanner->curptr+2) != '0') {
on_scanner_error(scanner);
return;
}
/* We've got what we're looking for, skip anything until newline */
pj_scan_skip_line(scanner);
}
static void parse_origin(pj_scanner *scanner, pjmedia_sdp_session *ses,
parse_context *ctx)
{
pj_str_t str;
ctx->last_error = PJMEDIA_SDP_EINORIGIN;
/* check equal sign */
if (*(scanner->curptr+1) != '=') {
on_scanner_error(scanner);
return;
}
/* o= */
pj_scan_advance_n(scanner, 2, SKIP_WS);
/* username. */
pj_scan_get_until_ch(scanner, ' ', &ses->origin.user);
pj_scan_get_char(scanner);
/* id */
pj_scan_get_until_ch(scanner, ' ', &str);
ses->origin.id = pj_strtoul(&str);
pj_scan_get_char(scanner);
/* version */
pj_scan_get_until_ch(scanner, ' ', &str);
ses->origin.version = pj_strtoul(&str);
pj_scan_get_char(scanner);
/* network-type */
pj_scan_get_until_ch(scanner, ' ', &ses->origin.net_type);
pj_scan_get_char(scanner);
/* addr-type */
pj_scan_get_until_ch(scanner, ' ', &ses->origin.addr_type);
pj_scan_get_char(scanner);
/* address */
pj_scan_get_until_chr(scanner, " \t\r", &ses->origin.addr);
/* We've got what we're looking for, skip anything until newline */
pj_scan_skip_line(scanner);
}
static void parse_time(pj_scanner *scanner, pjmedia_sdp_session *ses,
parse_context *ctx)
{
pj_str_t str;
ctx->last_error = PJMEDIA_SDP_EINTIME;
/* check equal sign */
if (*(scanner->curptr+1) != '=') {
on_scanner_error(scanner);
return;
}
/* t= */
pj_scan_advance_n(scanner, 2, SKIP_WS);
/* start time */
pj_scan_get_until_ch(scanner, ' ', &str);
ses->time.start = pj_strtoul(&str);
pj_scan_get_char(scanner);
/* stop time */
pj_scan_get_until_chr(scanner, " \t\r", &str);
ses->time.stop = pj_strtoul(&str);
/* We've got what we're looking for, skip anything until newline */
pj_scan_skip_line(scanner);
}
static void parse_generic_line(pj_scanner *scanner, pj_str_t *str,
parse_context *ctx)
{
ctx->last_error = PJMEDIA_SDP_EINSDP;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -