⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdp_parse.c

📁 Sofia SIP is an open-source SIP User-Agent library, compliant with the IETF RFC3261 specification.
💻 C
📖 第 1 页 / 共 4 页
字号:
                         *(CRLF repeat-fields) CRLF)                         [zone-adjustments CRLF]   start-time =          time | "0"   stop-time =           time | "0"   time =                POS-DIGIT 9*(DIGIT)                         ;sufficient for 2 more centuries   */  PARSE_ALLOC(p, sdp_time_t, t);  *result = t;  if (parse_ul(p, &r, &t->t_start, 0) ||      parse_ul(p, &r, &t->t_stop, 0))    parsing_error(p, "invalid time");  else if (STRICT(p)) {    PARSE_CHECK_REST(p, r, "t");  }}/** * Parse an "r=" field * * The function parse_repeat() parses an SDP repeat field. * * @param p      pointer to SDP parser object * @param r      pointer to record data * @param result pointer to which parsed record is assigned *  */static void parse_repeat(sdp_parser_t *p, char *d, sdp_repeat_t **result){  /*   repeat-fields =       "r=" repeat-interval space typed-time                         1*(space typed-time)   repeat-interval =     typed-time   typed-time =          1*(DIGIT) [fixed-len-time-unit]   fixed-len-time-unit = "d" | "h" | "m" | "s"   */  unsigned long tt, *interval;  size_t i;  int n, N;  char *s;  sdp_repeat_t *r;  /** Count number of intervals */  for (N = 0, s = d; *s; ) {    if (!(is_posdigit(*s) || (!STRICT(p) && (*s) == '0')))      break;    do { s++; } while (is_digit(*s));    if (*s && strchr("dhms", *s))      s++;    N++;    if (!(i = STRICT(p) ? is_space(*s) : strspn(s, SPACE TAB)))      break;    s += i;  }  PARSE_CHECK_REST(p, s, "r");  if (N < 2) {    parsing_error(p, "invalid repeat");    return;  }  if (!(r = su_salloc(p->pr_home, offsetof(sdp_repeat_t, r_offsets[N - 1])))) {    parse_alloc_error(p, "sdp_repeat_t");     return;  }  r->r_number_of_offsets = N - 2;  r->r_offsets[N - 2] = 0;  for (n = 0, interval = &r->r_interval; n < N; n++) {    tt = strtoul(d, &d, 10);    switch (*d) {    case 'd': tt *= 24;    case 'h': tt *= 60;    case 'm': tt *= 60;    case 's': d++;      break;    }    interval[n] = tt;    while (is_space(*d))      d++;  }   *result = r;}/* ------------------------------------------------------------------------- * Function parse_zone() - parse an "z=" field * * Description: *   This function parses an SDP time zone field. * * Parameters: *   p      - pointer to SDP parser object *   r      - pointer to record data *   result - pointer to which parsed record is assigned * */static void parse_zone(sdp_parser_t *p, char *r, sdp_zone_t **result){  char *s;  size_t i;  int n, N;  sdp_zone_t *z;  /*   zone-adjustments =    time space ["-"] typed-time                         *(space time space ["-"] typed-time)   */  /** Count number of timezones, check syntax */  for (N = 0, s = r; *s;) {    if (!(is_posdigit(*s) || (!STRICT(p) && (*s) == '0')))      break;    do { s++; } while (is_digit(*s));    if (!(i = STRICT(p) ? is_space(*s) : strspn(s, SPACE TAB)))      break;    s += i;    if (!(*s == '-' || is_posdigit(*s) || (!STRICT(p) && (*s) == '0')))      break;    do { s++; } while (is_digit(*s));    if (*s && strchr("dhms", *s))      s++;    N++;    if (!(i = STRICT(p) ? is_space(*s) : strspn(s, SPACE TAB)))      break;    s += i;  }  PARSE_CHECK_REST(p, s, "z");  if (N < 1) {    parsing_error(p, "invalid timezone");    return;  }  if (!(z = su_salloc(p->pr_home, offsetof(sdp_zone_t, z_adjustments[N])))) {    parse_alloc_error(p, "sdp_zone_t");     return;  }  z->z_number_of_adjustments = N;  for (n = 0; n < N; n++) {    unsigned long at = strtoul(r, &r, 10);    long offset = strtol(r, &r, 10);    switch (*r) {    case 'd': offset *= 24;    case 'h': offset *= 60;    case 'm': offset *= 60;    case 's': r++;      break;    }    z->z_adjustments[n].z_at = at;    z->z_adjustments[n].z_offset = offset;  }   *result = z;}/* ------------------------------------------------------------------------- * Function parse_key() - parse an "k=" field * * Description: *   This function parses an SDP key field. * * Parameters: *   p      - pointer to SDP parser object *   r      - pointer to record data *   result - pointer to which parsed record is assigned * */static void parse_key(sdp_parser_t *p, char *r, sdp_key_t **result){  char *s;  /*   key-field =           ["k=" key-type CRLF]   key-type =            "prompt" |                         "clear:" key-data |                         "base64:" key-data |                         "uri:" uri   key-data =            email-safe | "~" | "   */  s = token(&r, ":", ALPHA DIGIT "-", SPACE TAB);  if (!s) {    parsing_error(p, "invalid key method");    return;  }  {    PARSE_ALLOC(p, sdp_key_t, k);    *result = k;    if (strcasecmp(s, "clear") == 0)      k->k_method = sdp_key_clear, k->k_method_name = "clear";    else if (strcasecmp(s, "base64") == 0)      k->k_method = sdp_key_base64, k->k_method_name = "base64";    else if (strcasecmp(s, "uri") == 0)      k->k_method = sdp_key_uri, k->k_method_name = "uri";    else if (strcasecmp(s, "prompt") == 0)      k->k_method = sdp_key_prompt, k->k_method_name = "prompt";    else      k->k_method = sdp_key_x, k->k_method_name = s;    k->k_material = r;  }}/* ------------------------------------------------------------------------- * Function parse_session_attr() - parse a session "a=" field * * Description: *   This function parses an SDP attribute field regarding whole session. * * Parameters: *   p      - pointer to SDP parser object *   r      - pointer to record data *   result - pointer to which parsed record is assigned */static void parse_session_attr(sdp_parser_t *p, char *r, sdp_attribute_t **result){  /*   attribute-fields =    *("a=" attribute CRLF)   attribute =           (att-field ":" att-value) | att-field   att-field =           1*(alpha-numeric)   att-value =           byte-string   */  char *name = NULL, *value = NULL;  if (!(name = token(&r, ":", ALPHA DIGIT "-", SPACE TAB))) {    parsing_error(p,"invalid attribute name");    return;  }  if (*r)    value = r;  else     PARSE_CHECK_REST(p, r, "a");  if (strcasecmp(name, "charset") == 0) {    p->pr_session->sdp_charset = value;    return;  }  if (p->pr_mode_manual)     ;  else if (strcasecmp(name, "inactive") == 0)    p->pr_session_mode = sdp_inactive;  else if (strcasecmp(name, "sendonly") == 0)    p->pr_session_mode = sdp_sendonly;  else if (strcasecmp(name, "recvonly") == 0)    p->pr_session_mode = sdp_recvonly;  else if (strcasecmp(name, "sendrecv") == 0)    p->pr_session_mode = sdp_sendrecv;  {    PARSE_ALLOC(p, sdp_attribute_t, a);    *result = a;    a->a_name  = name;    a->a_value = value;  }}/* ------------------------------------------------------------------------- * Function parse_media() - parse an "m=" field * * Description: *   This function parses an SDP media field. * * Parameters: *   p      - pointer to SDP parser object *   r      - pointer to record data *   result - pointer to which parsed record is assigned */static void parse_media(sdp_parser_t *p, char *r, sdp_media_t **result){  /*   media-descriptions =  *( media-field                         information-field                         *(connection-field)                         bandwidth-fields                         key-field                         attribute-fields )   media-field =         "m=" media space port ["/" integer]                         space proto 1*(space fmt) CRLF   media =               1*(alpha-numeric)                         ;typically "audio", "video", "application"                         ;or "data"   fmt =                 1*(alpha-numeric)                         ;typically an RTP payload type for audio                         ;and video media   proto =               1*(alpha-numeric)                         ;typically "RTP/AVP" or "udp" for IP4   port =                1*(DIGIT)                         ;should in the range "1024" to "65535" inclusive   */  char *s;  unsigned long value;  PARSE_ALLOC(p, sdp_media_t, m);  *result = m;  m->m_mode = sdp_sendrecv;  s = token(&r, SPACE, ALPHA DIGIT, NULL);  if (s == NULL && p->pr_config)    s = token(&r, SPACE, "*", NULL);  if (!s) {    parsing_error(p, "m= invalid media field");    return;  }  sdp_media_type(m, s);  /* Accept m=* in configuration file */  if (p->pr_config && m->m_type == sdp_media_any) {    r += strspn(r, SPACE TAB);    if (r[0] == '\0') {      m->m_proto = sdp_proto_any, m->m_proto_name = "*";      return;    }  }  if (parse_ul(p, &r, &value, 0)) {    parsing_error(p, "m= invalid port number");    return;  }  m->m_port = value;  if (*r == '/') {    r++;    if (parse_ul(p, &r, &value, 0)) {      parsing_error(p, "m= invalid port specification");      return;    }    m->m_number_of_ports = value;  }  /* alpha-numeric and "/" */  s = token(&r, SPACE, ALPHA DIGIT "/", SPACE);  if (s == NULL && p->pr_config)     s = token(&r, SPACE, "*", SPACE);  if (s == NULL) {    parsing_error(p, "m= missing protocol");    return;  }    if (!STRICT(p) && strcasecmp(s, "RTP") == 0)    m->m_proto = sdp_proto_rtp, m->m_proto_name = "RTP/AVP";  else     sdp_media_transport(m, s);  /* RTP format list */  if (*r && sdp_media_has_rtp(m)) {    parse_payload(p, r, &m->m_rtpmaps);    return;  }  /* "normal" format list */  if (*r) {    sdp_list_t **fmt = &m->m_format;        while (r && *r) {      PARSE_ALLOC(p, sdp_list_t, l);      *fmt = l;      l->l_text = next(&r, SPACE TAB, SPACE TAB);      fmt = &l->l_next;    }  }}/** Set media type */void sdp_media_type(sdp_media_t *m, char const *s){  if (strcmp(s, "*") == 0)    m->m_type = sdp_media_any, m->m_type_name = "*";  else if (strcasecmp(s, "audio") == 0)    m->m_type = sdp_media_audio, m->m_type_name = "audio";  else if (strcasecmp(s, "video") == 0)    m->m_type = sdp_media_video, m->m_type_name = "video";  else if (strcasecmp(s, "application") == 0)    m->m_type = sdp_media_application, m->m_type_name = "application";  else if (strcasecmp(s, "data") == 0)    m->m_type = sdp_media_data, m->m_type_name = "data";  else if (strcasecmp(s, "control") == 0)    m->m_type = sdp_media_control, m->m_type_name = "control";  else if (strcasecmp(s, "message") == 0)    m->m_type = sdp_media_message, m->m_type_name = "message";  else if (strcasecmp(s, "image") == 0)    m->m_type = sdp_media_image, m->m_type_name = "image";  else if (strcasecmp(s, "red") == 0)    m->m_type = sdp_media_red, m->m_type_name = "red";  else    m->m_type = sdp_media_x, m->m_type_name = s;}void sdp_media_transport(sdp_media_t *m, char const *s){  if (strcasecmp(s, "*") == 0)    m->m_proto = sdp_proto_any, m->m_proto_name = "*";  else if (strcasecmp(s, "RTP/AVP") == 0)    m->m_proto = sdp_proto_rtp, m->m_proto_name = "RTP/AVP";  else if (strcasecmp(s, "RTP/SAVP") == 0)    m->m_proto = sdp_proto_srtp, m->m_proto_name = "RTP/SAVP";  else if (strcasecmp(s, "UDPTL") == 0)    m->m_proto = sdp_proto_udptl, m->m_proto_name = "UDPTL";  else if (strcasecmp(s, "UDP") == 0)    m->m_proto = sdp_proto_udp, m->m_proto_name = "UDP";  else if (strcasecmp(s, "TCP") == 0)    m->m_proto = sdp_proto_tcp, m->m_proto_name = "TCP";  else if (strcasecmp(s, "TLS") == 0)    m->m_proto = sdp_proto_tls, m->m_proto_name = "TLS";  else     m->m_proto = sdp_proto_x, m->m_proto_name = s;}/** Check if media uses RTP as its transport protocol.  */int sdp_media_has_rtp(sdp_media_t const *m){  return m && (m->m_proto == sdp_proto_rtp || m->m_proto == sdp_proto_srtp);}#define RTPMAP(pt, encoding, rate, params) \  { sizeof(sdp_rtpmap_t), NULL, encoding, rate, (char *)params, NULL, 1, pt, 0 }/* rtpmaps for well-known codecs */static sdp_rtpmap_t const  sdp_rtpmap_pcmu = RTPMAP(0, "PCMU", 8000, 0),  sdp_rtpmap_1016 = RTPMAP(1, "1016", 8000, 0),  sdp_rtpmap_g721 = RTPMAP(2, "G721", 8000, 0),  sdp_rtpmap_gsm =  RTPMAP(3, "GSM",  8000, 0),  sdp_rtpmap_g723 = RTPMAP(4, "G723", 8000, 0),  sdp_rtpmap_dvi4_8000 = RTPMAP(5, "DVI4", 8000, 0),  sdp_rtpmap_dvi4_16000 = RTPMAP(6, "DVI4", 16000, 0),  sdp_rtpmap_lpc = RTPMAP(7, "LPC",  8000, 0),  sdp_rtpmap_pcma = RTPMAP(8, "PCMA", 8000, 0),  sdp_rtpmap_g722 = RTPMAP(9, "G722", 8000, 0),  sdp_rtpmap_l16_2 = RTPMAP(10, "L16", 44100, "2"),  sdp_rtpmap_l16 = RTPMAP(11, "L16", 44100, 0),  sdp_rtpmap_qcelp = RTPMAP(12, "QCELP", 8000, 0),  sdp_rtpmap_cn = RTPMAP(13, "CN", 8000, 0),  sdp_rtpmap_mpa = RTPMAP(14, "MPA", 90000, 0),  sdp_rtpmap_g728 = RTPMAP(15, "G728", 8000, 0),  sdp_rtpmap_dvi4_11025 = RTPMAP(16, "DVI4", 11025, 0),  sdp_rtpmap_dvi4_22050 = RTPMAP(17, "DVI4", 22050, 0),  sdp_rtpmap_g729 = RTPMAP(18, "G729", 8000, 0),  sdp_rtpmap_reserved_cn = RTPMAP(19, "CN", 8000, 0),  /* video codecs */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -