📄 soa_static.c
字号:
cm = sdp_media_dup_all(home, caps->sdp_media, session); if (!s_media || !c_media || !u_media || !cm) return -1; for (i = 0, m = session->sdp_media; m && i < Ns; m = m->m_next) o_media[i++] = m; assert(i == Ns); for (i = 0, m = cm; m && i < Nc; m = m->m_next) c_media[i++] = m; assert(i == Nc); for (i = 0, m = upgrader->sdp_media; m && i < Nu; m = m->m_next) u_media[i++] = m; assert(i == Nu); if (caps != upgrader) { /* Update session according to remote */ for (i = 0; i < Nu; i++) { int common_codecs = 0; m = soa_sdp_matching(ss, c_media, u_media[i], &common_codecs); if (!m || u_media[i]->m_rejected) { m = soa_sdp_make_rejected_media(home, u_media[i], session, 0); } else if (sdp_media_uses_rtp(m)) { /* Process rtpmaps */ if (!common_codecs && !ss->ss_rtp_mismatch) m = soa_sdp_make_rejected_media(home, m, session, 1); soa_sdp_set_rtpmap_pt(m, u_media[i]); if (ss->ss_rtp_sort == SOA_RTP_SORT_REMOTE || (ss->ss_rtp_sort == SOA_RTP_SORT_DEFAULT && u_media[i]->m_mode == sdp_recvonly)) { soa_sdp_sort_rtpmap(&m->m_rtpmaps, u_media[i]->m_rtpmaps); } if (common_codecs && (ss->ss_rtp_select == SOA_RTP_SELECT_SINGLE || ss->ss_rtp_select == SOA_RTP_SELECT_COMMON)) { soa_sdp_select_rtpmap(&m->m_rtpmaps, u_media[i]->m_rtpmaps); if (ss->ss_rtp_select == SOA_RTP_SELECT_SINGLE) { if (m->m_rtpmaps) m->m_rtpmaps->rm_next = NULL; } } } s_media[i] = m; } } else { /* Update session according to local */ for (i = 0; i < Ns; i++) { m = soa_sdp_matching(ss, c_media, o_media[i], NULL); if (!m) m = soa_sdp_make_rejected_media(home, o_media[i], session, 0); s_media[i] = m; } /* Here we just append new media at the end */ for (j = 0; c_media[j]; j++) s_media[i++] = c_media[j]; assert(i <= size); } mm = &session->sdp_media; for (i = 0; s_media[i]; i++) { m = s_media[i]; *mm = m; mm = &m->m_next; } *mm = NULL; return 0;}/** Check if @a session contains media that are rejected by @a remote. */ int soa_sdp_reject_is_needed(sdp_session_t const *session, sdp_session_t const *remote){ sdp_media_t const *sm, *rm; if (!remote) return 1; if (!session) return 0; for (sm = session->sdp_media, rm = remote->sdp_media; sm && rm; sm = sm->m_next, rm = rm->m_next) { if (rm->m_rejected) { if (!sm->m_rejected) return 1; } else { sdp_mode_t send_mode = (rm->m_mode & sdp_recvonly) ? sdp_sendonly : 0; if (send_mode != (sm->m_mode & sdp_sendonly)) return 1; } } if (sm) return 1; return 0;}/** If m= line is rejected by, remote mark m= line rejected within session */ int soa_sdp_reject(su_home_t *home, sdp_session_t *session, sdp_session_t const *remote){ sdp_media_t *sm; sdp_media_t const *rm; if (!session || !session->sdp_media || !remote) return 0; rm = remote->sdp_media; for (sm = session->sdp_media; sm; sm = sm->m_next) { if (!rm || rm->m_rejected) { sm->m_rejected = 1; sm->m_mode = 0; sm->m_port = 0; sm->m_number_of_ports = 1; if (sm->m_format) sm->m_format->l_next = NULL; if (sm->m_rtpmaps) sm->m_rtpmaps->rm_next = NULL; sm->m_information = NULL; if (sm->m_connections) sm->m_connections->c_next = NULL; sm->m_bandwidths = NULL; sm->m_key = NULL; sm->m_attributes = NULL; sm->m_user = NULL; } if (rm) rm = rm->m_next; } return 0;}/** Check if @a session mode should be changed. */ int soa_sdp_mode_set_is_needed(sdp_session_t const *session, sdp_session_t const *remote, char const *hold){ sdp_media_t const *sm, *rm, *rm_next; int hold_all; sdp_mode_t send_mode, recv_mode; SU_DEBUG_7(("soa_sdp_mode_set_is_needed(%p, %p, \"%s\"): called\n", session, remote, hold ? hold : "")); if (!session ) return 0; hold_all = str0cmp(hold, "*") == 0; rm = remote ? remote->sdp_media : NULL, rm_next = NULL; for (sm = session->sdp_media; sm; sm = sm->m_next, rm = rm_next) { rm_next = rm ? rm->m_next : NULL; if (sm->m_rejected) continue; if (rm) { send_mode = (rm->m_mode & sdp_recvonly) ? sdp_sendonly : 0; if (send_mode != (sm->m_mode & sdp_sendonly)) return 1; } recv_mode = sm->m_mode & sdp_recvonly; if (recv_mode && hold && (hold_all || strcasestr(hold, sm->m_type_name))) return 1; } return 0;}/** Update mode within session */ int soa_sdp_mode_set(sdp_session_t *session, sdp_session_t const *remote, char const *hold){ sdp_media_t *sm; sdp_media_t const *rm, *rm_next; int hold_all; sdp_mode_t send_mode, recv_mode; SU_DEBUG_7(("soa_sdp_mode_set(%p, %p, \"%s\"): called\n", session, remote, hold ? hold : "")); if (!session || !session->sdp_media) return 0; rm = remote ? remote->sdp_media : NULL, rm_next = NULL; hold_all = str0cmp(hold, "*") == 0; for (sm = session->sdp_media; sm; sm = sm->m_next, rm = rm_next) { rm_next = rm ? rm->m_next : NULL; if (sm->m_rejected) continue; send_mode = sdp_sendonly; if (rm) send_mode = (rm->m_mode & sdp_recvonly) ? sdp_sendonly : 0; recv_mode = sm->m_mode & sdp_recvonly; if (recv_mode && hold && (hold_all || strcasestr(hold, sm->m_type_name))) recv_mode = 0; sm->m_mode = recv_mode | send_mode; } return 0;}enum offer_answer_action { generate_offer, generate_answer, process_answer};/** * Updates the modified copy of local SDP based * on application provided local SDP and remote SDP. */static int offer_answer_step(soa_session_t *ss, enum offer_answer_action action, char const *by){ char c_address[64]; sdp_session_t *local = ss->ss_local->ssd_sdp; sdp_session_t local0[1]; sdp_session_t *user = ss->ss_user->ssd_sdp; unsigned user_version = ss->ss_user_version; sdp_session_t *remote = ss->ss_remote->ssd_sdp; unsigned remote_version = ss->ss_remote_version; sdp_origin_t o[1] = {{ sizeof(o) }}; sdp_connection_t *c, c0[1] = {{ sizeof(c0) }}; sdp_time_t t[1] = {{ sizeof(t) }}; char const *phrase = "Internal Media Error"; su_home_t tmphome[SU_HOME_AUTO_SIZE(8192)]; su_home_auto(tmphome, sizeof tmphome); SU_DEBUG_7(("soa_static_offer_answer_action(%p, %s): called\n", ss, by)); if (user == NULL) return soa_set_status(ss, 500, "No session set by user"); if (action == generate_offer) remote = NULL; /* Pre-negotiation Step: Expand truncated remote SDP */ if (local && remote) switch (action) { case generate_answer: case process_answer: if (sdp_media_count(remote, sdp_media_any, "*", 0, 0) < sdp_media_count(local, sdp_media_any, "*", 0, 0)) { SU_DEBUG_5(("%s: remote %s is truncated: expanding\n", by, action == generate_answer ? "offer" : "answer")); remote = soa_sdp_expand_media(tmphome, remote, local); } default: break; } /* Step A: Create local SDP session (based on user-supplied SDP) */ if (local == NULL) switch (action) { case generate_offer: case generate_answer: SU_DEBUG_7(("soa_static(%p, %s): generating local description\n", ss, by)); local = local0; *local = *user, local->sdp_media = NULL; if (local->sdp_origin) { o->o_username = local->sdp_origin->o_username; /* o->o_address = local->sdp_origin->o_address; */ } if (!o->o_address) o->o_address = c0; local->sdp_origin = o; if (soa_init_sdp_origin(ss, o, c_address) < 0) { phrase = "Cannot Get IP Address for Media"; goto internal_error; } break; case process_answer: default: goto internal_error; } /* Step B: upgrade local SDP (add m= lines to it) */ switch (action) { case generate_offer: /* Upgrade local SDP based on user SDP */ if (local != local0 && ss->ss_local_user_version == user_version) break; if (local != local0) *local0 = *local, local = local0; SU_DEBUG_7(("soa_static(%p, %s): %s\n", ss, by, "upgrade with local description")); soa_sdp_upgrade(ss, tmphome, local, user, user); break; case generate_answer: /* Upgrade local SDP based on remote SDP */ if (ss->ss_local_user_version == user_version && ss->ss_local_remote_version == remote_version) break; if (ss->ss_local_user_version != user_version || soa_sdp_upgrade_is_needed(local, remote)) { if (local != local0) *local0 = *local, local = local0; SU_DEBUG_7(("soa_static(%p, %s): %s\n", ss, by, "upgrade with remote description")); soa_sdp_upgrade(ss, tmphome, local, user, remote); } break; case process_answer: default: break; } /* Step C: reject media */ switch (action) { case generate_offer: /* Local media is marked as rejected already in upgrade phase */ break; case generate_answer: case process_answer: if (ss->ss_local_remote_version == remote_version) break; if (soa_sdp_reject_is_needed(local, remote)) { if (local != local0) { *local0 = *local, local = local0;#define DUP_LOCAL(local) \ do { \ if (!local->sdp_media) break; \ local->sdp_media = \ sdp_media_dup_all(tmphome, local->sdp_media, local); \ if (!local->sdp_media) \ goto internal_error; \ } while (0) DUP_LOCAL(local); } SU_DEBUG_7(("soa_static(%p, %s): marking rejected media\n", ss, by)); soa_sdp_reject(tmphome, local, remote); } break; default: break; } /* Step D: Set media mode bits */ switch (action) { case generate_offer: case generate_answer: case process_answer: if (soa_sdp_mode_set_is_needed(local, remote, ss->ss_hold)) { if (local != local0) { *local = *local, local = local0; DUP_LOCAL(local); } soa_sdp_mode_set(local, remote, ss->ss_hold); } break; default: break; } /* Step E: Upgrade codecs */ switch (action) { case process_answer: /* Upgrade local SDP based on remote SDP */ if (ss->ss_local_remote_version == remote_version) break; if (1 /* We don't have good test for codecs */) { SU_DEBUG_7(("soa_static(%p, %s): %s\n", ss, by, "upgrade codecs with remote description")); if (local != local0) { *local0 = *local, local = local0; DUP_LOCAL(local); } soa_sdp_upgrade_rtpmaps(ss, local, remote); } break; case generate_offer: case generate_answer: default: break; } soa_description_free(ss, ss->ss_previous); if (local == local0) { /* We have modfied local session: update origin-line */ if (local->sdp_origin != o) *o = *local->sdp_origin, local->sdp_origin = o; o->o_version++; /* Do sanity checks for the created SDP */ if (!local->sdp_subject) /* s= is mandatory */ local->sdp_subject = "-"; if (!local->sdp_time) /* t= is mandatory */ local->sdp_time = t; /* Every m= line (even rejected one) must have a c= line * or there must be a c= line at session level */ c = local->sdp_origin->o_address; if (local->sdp_connection == NULL) { sdp_media_t *m; for (m = local->sdp_media; m; m = m->m_next) if (m->m_connections == NULL) break; if (m) local->sdp_connection = c; } if (action == generate_offer) { /* Keep a copy of previous session state */ *ss->ss_previous = *ss->ss_local; memset(ss->ss_local, 0, (sizeof *ss->ss_local)); ss->ss_previous_user_version = ss->ss_local_user_version; ss->ss_previous_remote_version = ss->ss_local_remote_version; } SU_DEBUG_7(("soa_static(%p, %s): storing local description\n", ss, by)); /* Update the unparsed and pretty-printed descriptions */ if (soa_description_set(ss, ss->ss_local, local, NULL, 0) < 0) { goto internal_error; } } /* Update version numbers */ switch (action) { case generate_offer: ss->ss_local_user_version = user_version; break; case generate_answer: ss->ss_local_user_version = user_version; ss->ss_local_remote_version = remote_version; break; case process_answer: ss->ss_local_remote_version = remote_version; default: break; } su_home_deinit(tmphome); return 0; internal_error: su_home_deinit(tmphome); return soa_set_status(ss, 500, phrase);}/** * Generates offer based on local SDP. */static int soa_static_generate_offer(soa_session_t *ss, soa_callback_f *completed){ if (!ss->ss_user->ssd_sdp) return soa_set_status(ss, 500, "No session set by user"); if (offer_answer_step(ss, generate_offer, "soa_generate_offer") < 0) return -1; return soa_base_generate_offer(ss, NULL);}static int soa_static_generate_answer(soa_session_t *ss, soa_callback_f *completed){ /* NOTE: * - local SDP might have changed * - remote SDP might have been updated */ if (offer_answer_step(ss, generate_answer, "soa_generate_answer") < 0) return -1; return soa_base_generate_answer(ss, NULL);}static int soa_static_process_answer(soa_session_t *ss, soa_callback_f *completed){ /* NOTE: * - both local and remote information is available * - local SDP might have changed * - remote SDP might have been updated */ if (offer_answer_step(ss, process_answer, "soa_process_answer") < 0) return -1; return soa_base_process_answer(ss, NULL);}/** Process rejected offer */static int soa_static_process_reject(soa_session_t *ss, soa_callback_f *completed){ struct soa_description d[1]; *d = *ss->ss_local; *ss->ss_local = *ss->ss_previous; ss->ss_local_user_version = ss->ss_previous_user_version; ss->ss_local_remote_version = ss->ss_previous_remote_version; memset(ss->ss_previous, 0, (sizeof *ss->ss_previous)); soa_description_free(ss, d); return soa_base_process_reject(ss, NULL);}static int soa_static_activate(soa_session_t *ss, char const *option){ return soa_base_activate(ss, option);}static int soa_static_deactivate(soa_session_t *ss, char const *option){ return soa_base_deactivate(ss, option);}static void soa_static_terminate(soa_session_t *ss, char const *option){ soa_description_free(ss, ss->ss_user); soa_base_terminate(ss, option);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -