📄 soa.c
字号:
}/* ======================================================================== */int soa_set_status(soa_session_t *ss, int status, char const *phrase){ if (ss) { ss->ss_status = status, ss->ss_phrase = phrase; ss->ss_wcode = 0, ss->ss_warning = NULL; } return -1;}int soa_set_warning(soa_session_t *ss, int code, char const *text){ if (ss) ss->ss_wcode = code, ss->ss_warning = text; return -1;}static inlineint soa_media_is_ready(soa_session_t const *ss){ XXX; return 0; /* return ss && ss->ss_session != NULL; */}void soa_set_activity(soa_session_t *ss, sdp_media_t const *m, int remote){ struct soa_media_activity *ma; sdp_connection_t const *c; int mode; int ma_audio = SOA_ACTIVE_DISABLED; int ma_video = SOA_ACTIVE_DISABLED; int ma_chat = SOA_ACTIVE_DISABLED; int ma_image = SOA_ACTIVE_DISABLED; int *p; remote = !!remote; ma = remote ? ss->ss_remote_activity : ss->ss_local_activity; for (; m; m = m->m_next) { if (m->m_type == sdp_media_audio) p = &ma_audio; else if (m->m_type == sdp_media_video) p = &ma_video; else if (m->m_type == sdp_media_image) p = &ma_image; else if (strcasecmp(m->m_type_name, "message") == 0) p = &ma_chat; else continue; if (m->m_rejected) { if (*p < 0) *p = SOA_ACTIVE_REJECTED; continue; } mode = m->m_mode; c = sdp_media_connections((sdp_media_t *)m); if (remote != (c && c->c_mcast)) mode = ((mode << 1) & 2) | ((mode >> 1) & 1); if (*p < 0) *p = mode; else *p |= mode; } ma->ma_audio = ma_audio; ma->ma_video = ma_video; ma->ma_image = ma_image; ma->ma_chat = ma_chat;}/* ----------------------------------------------------------------------*//* Handle SDP *//** * Parses and stores session description * * @param ss instance pointer * @param what caps, local or remote * @param sdp0 new sdp (parsed) * @param sdp_str new sdp (unparsed) * @param str_len length on unparsed data **/staticint soa_set_sdp(soa_session_t *ss, enum soa_sdp_kind what, sdp_session_t const *sdp0, char const *sdp_str, int str_len){ struct soa_description *ssd; int flags, new_version, retval; sdp_parser_t *parser = NULL; sdp_session_t sdp[1]; switch (what) { case soa_capability_sdp_kind: ssd = ss->ss_caps; flags = sdp_f_config; break; case soa_user_sdp_kind: ssd = ss->ss_user; flags = sdp_f_config; break; case soa_remote_sdp_kind: ssd = ss->ss_remote; flags = sdp_f_mode_0000; break; default: return -1; } if (sdp0) new_version = sdp_session_cmp(sdp0, ssd->ssd_sdp) != 0; else if (sdp_str) new_version = str0cmp(sdp_str, ssd->ssd_unparsed) != 0; else return (void)su_seterrno(EINVAL), -1; if (sdp_str && str_len == -1) str_len = strlen(sdp_str); if (!new_version) { if (what == soa_remote_sdp_kind) { *sdp = *ssd->ssd_sdp; /* XXX - should check changes by soa_set_remote_sdp */ return ss->ss_actions->soa_set_remote_sdp(ss, new_version, sdp, sdp_str, str_len); } return 0; } if (sdp0) { /* note: case 1 - src in parsed form */ *sdp = *sdp0; } else /* if (sdp_str) */ { /* note: case 2 - src in unparsed form */ parser = sdp_parse(ss->ss_home, sdp_str, str_len, flags | sdp_f_anynet); if (sdp_parsing_error(parser)) { sdp_parser_free(parser); return soa_set_status(ss, 400, "Bad Session Description"); } *sdp = *sdp_session(parser); } switch (what) { case soa_capability_sdp_kind: retval = ss->ss_actions->soa_set_capability_sdp(ss, sdp, sdp_str, str_len); break; case soa_user_sdp_kind: retval = ss->ss_actions->soa_set_user_sdp(ss, sdp, sdp_str, str_len); break; case soa_remote_sdp_kind: retval = ss->ss_actions->soa_set_remote_sdp(ss, 1, sdp, sdp_str, str_len); break; default: retval = soa_set_status(ss, 500, "Internal Error"); break; } if (parser) sdp_parser_free(parser); return retval;}/** Set session descriptions. */int soa_description_set(soa_session_t *ss, struct soa_description *ssd, sdp_session_t *sdp, char const *sdp_str, int str_len){ int retval = -1; sdp_printer_t *printer = NULL; sdp_session_t *sdp_new; char *sdp_str_new; char *sdp_str0_new; void *tbf1, *tbf2, *tbf3, *tbf4; /* Store description in three forms: unparsed, parsed and reprinted */ sdp_new = sdp_session_dup(ss->ss_home, sdp); printer = sdp_print(ss->ss_home, sdp, NULL, 0, 0); sdp_str_new = (char *)sdp_message(printer); if (sdp_str) sdp_str0_new = su_strndup(ss->ss_home, sdp_str, str_len); else sdp_str0_new = sdp_str_new; if (sdp_new && printer && sdp_str_new && sdp_str0_new) { tbf1 = ssd->ssd_sdp, tbf2 = ssd->ssd_printer; tbf3 = (void *)ssd->ssd_str, tbf4 = (void *)ssd->ssd_unparsed; ssd->ssd_sdp = sdp_new; ssd->ssd_printer = printer; ssd->ssd_str = sdp_str_new; ssd->ssd_unparsed = sdp_str0_new; retval = 1; } else { tbf1 = sdp_new, tbf2 = printer, tbf3 = sdp_str_new, tbf4 = sdp_str0_new; } su_free(ss->ss_home, tbf1); sdp_printer_free(tbf2); if (tbf3 != tbf4) su_free(ss->ss_home, tbf4); return retval;}/** Duplicate a session descriptions. */int soa_description_dup(su_home_t *home, struct soa_description *ssd, struct soa_description const *ssd0){ if (ssd0->ssd_sdp) { ssd->ssd_sdp = sdp_session_dup(home, ssd0->ssd_sdp); ssd->ssd_printer = sdp_print(home, ssd->ssd_sdp, NULL, 0, 0); ssd->ssd_str = (char *)sdp_message(ssd->ssd_printer); if (ssd0->ssd_str != ssd0->ssd_unparsed) ssd->ssd_unparsed = su_strdup(home, ssd0->ssd_unparsed); else ssd->ssd_unparsed = ssd->ssd_str; } return 0;}/** Free session descriptions. */void soa_description_free(soa_session_t *ss, struct soa_description *ssd){ void *tbf1, *tbf2, *tbf3, *tbf4; tbf1 = ssd->ssd_sdp, tbf2 = ssd->ssd_printer; tbf3 = (void *)ssd->ssd_str, tbf4 = (void *)ssd->ssd_unparsed; memset(ssd, 0, sizeof *ssd); su_free(ss->ss_home, tbf1); sdp_printer_free(tbf2); if (tbf3 != tbf4) su_free(ss->ss_home, tbf4);}/** Initialize SDP o= line */intsoa_init_sdp_origin(soa_session_t *ss, sdp_origin_t *o, char buffer[64]){ sdp_connection_t *c; if (ss == NULL || o == NULL) return su_seterrno(EFAULT), -1; assert(o->o_address); if (!o->o_username) o->o_username = "-"; if (o->o_id == 0) su_randmem(&o->o_id, sizeof o->o_id); o->o_id &= ((unsigned longlong)1 << 63) - 1; if (o->o_version == 0) su_randmem(&o->o_version, sizeof o->o_version); o->o_version &= ((unsigned longlong)1 << 63) - 1; c = o->o_address; if (!c->c_nettype || !c->c_address || strcmp(c->c_address, "") == 0 || strcmp(c->c_address, "0.0.0.0") == 0 || strcmp(c->c_address, "::") == 0 || !host_is_local(c->c_address)) { return soa_init_sdp_connection(ss, c, buffer); } return 0;}/** Search for an local address item from string provided by user */staticsu_localinfo_t *li_in_list(su_localinfo_t *li0, char const **llist){ char const *list = *llist; int n; if (!list) return NULL; while ((n = strcspn(list, ", "))) { su_localinfo_t *li; for (li = li0; li; li = li->li_next) { if (strncasecmp(li->li_canonname, list, n) == 0 && li->li_canonname[n] == '\0') break; } list += n; while (list[0] == ' ' || list[0] == ',') list++; *llist = list; if (li) return li; } return NULL;}/** Obtain a local address for SDP connection structure */intsoa_init_sdp_connection(soa_session_t *ss, sdp_connection_t *c, char buffer[64]){ su_localinfo_t *res, hints[1] = {{ LI_CANONNAME | LI_NUMERIC }}; su_localinfo_t *li, *li4, *li6; char const *address; int ip4, ip6, error; if (ss == NULL || c == NULL) return su_seterrno(EFAULT), -1; address = ss->ss_address; if (host_is_ip_address(address)) { /* Use the application-specified address - * do not check that it is found from the local address list */ c->c_nettype = sdp_net_in; if (host_is_ip4_address(address)) c->c_addrtype = sdp_addr_ip4; else c->c_addrtype = sdp_addr_ip6; if (!host_is_ip6_reference(address)) { c->c_address = strcpy(buffer, address); } else { /* Remove brackets [] around the reference */ size_t len = strlen(address + 1); c->c_address = memcpy(buffer, address + 1, len - 1); buffer[len - 1] = '\0'; } return 0; } /* XXX - using LI_SCOPE_LINK requires some tweaking */ hints->li_scope = LI_SCOPE_GLOBAL | LI_SCOPE_SITE /* | LI_SCOPE_LINK */; switch (ss->ss_af) { case SOA_AF_IP4_ONLY: hints->li_family = AF_INET, ip4 = 1, ip6 = 0; break;#if HAVE_SIN6 case SOA_AF_IP6_ONLY: hints->li_family = AF_INET6, ip6 = 1, ip4 = 0; break; case SOA_AF_IP4_IP6: ip4 = 2, ip6 = 1; break; case SOA_AF_IP6_IP4: ip4 = 1, ip6 = 2; break;#endif default: ip4 = ip6 = 1; } for (res = NULL; res == NULL;) { if ((error = su_getlocalinfo(hints, &res)) < 0 && error != ELI_NOADDRESS) { SU_DEBUG_1(("%s: su_localinfo: %s\n", __func__, su_gli_strerror(error))); return -1; } if (hints->li_scope & LI_SCOPE_HOST) break; hints->li_scope |= LI_SCOPE_HOST; } if (!(ip4 & ip6 && c->c_nettype == sdp_net_in)) /* Use ss_af preference */; else if (c->c_addrtype == sdp_addr_ip4) ip4 = 2, ip6 = 1; else if (c->c_addrtype == sdp_addr_ip6) ip6 = 2, ip4 = 1; if (address) SU_DEBUG_3(("%s: searching for %s from list \"%s\"\n", __func__, ip6 && !ip4 ? "IP6 " : !ip6 && ip4 ? "IP4 " : "", address)); li = res, li4 = NULL, li6 = NULL; for (;;) { if (address) li = li_in_list(li, &address); if (!li) break;#if HAVE_SIN6 else if (li->li_family == AF_INET6) { if (ip6 >= ip4) break; else if (!li6) li6 = li; /* Best IP6 address */ }#endif else if (li->li_family == AF_INET) { if (ip4 > ip6) break; else if (!li4) li4 = li; /* Best IP4 address */ } if (!address) li = li->li_next; } if (li == NULL) li = li4; if (li == NULL) li = li6; if (li == NULL) ; else if (li->li_family == AF_INET) c->c_nettype = sdp_net_in, c->c_addrtype = sdp_addr_ip4;#if HAVE_SIN6 else if (li->li_family == AF_INET6) c->c_nettype = sdp_net_in, c->c_addrtype = sdp_addr_ip6;#endif if (li) { assert(strlen(li->li_canonname) < 64); c->c_address = strcpy(buffer, li->li_canonname); } su_freelocalinfo(res); if (!li) return -1; else return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -