int AmSession::onSdpCompleted(const AmSdp& local_sdp, const AmSdp& remote_sdp) { DBG("AmSession::onSdpCompleted(...) ...\n"); if(local_sdp.media.empty() || remote_sdp.media.empty()) { ERROR("Invalid SDP"); string debug_str; local_sdp.print(debug_str); ERROR("Local SDP:\n%s", debug_str.empty() ? "<empty>" : debug_str.c_str()); remote_sdp.print(debug_str); ERROR("Remote SDP:\n%s", debug_str.empty() ? "<empty>" : debug_str.c_str()); return -1; } bool set_on_hold = false; if (!remote_sdp.media.empty()) { vector<SdpAttribute>::const_iterator pos = std::find(remote_sdp.media[0].attributes.begin(), remote_sdp.media[0].attributes.end(), SdpAttribute("sendonly")); set_on_hold = pos != remote_sdp.media[0].attributes.end(); } lockAudio(); // TODO: // - get the right media ID // - check if the stream coresponding to the media ID // should be created or updated // int ret = 0; try { ret = RTPStream()->init(local_sdp, remote_sdp, AmConfig::ForceSymmetricRtp); } catch (const string& s) { ERROR("Error while initializing RTP stream: '%s'\n", s.c_str()); ret = -1; } catch (...) { ERROR("Error while initializing RTP stream (unknown exception in AmRTPStream::init)\n"); ret = -1; } unlockAudio(); if (!isProcessingMedia()) { setInbandDetector(AmConfig::DefaultDTMFDetector); } return ret; }
int DSMCall::onSdpCompleted(const AmSdp& offer, const AmSdp& answer) { AmMimeBody* sdp_body = invite_req.body.hasContentType(SIP_APPLICATION_SDP); if(!sdp_body) { sdp_body = invite_req.body.addPart(SIP_APPLICATION_SDP); } if(sdp_body) { string sdp_buf; answer.print(sdp_buf); sdp_body->setPayload((const unsigned char*)sdp_buf.c_str(), sdp_buf.length()); } return AmB2BCallerSession::onSdpCompleted(offer,answer); }
int AmRtpStream::init(const AmSdp& local, const AmSdp& remote, bool force_passive_mode) { if((sdp_media_index < 0) || ((unsigned)sdp_media_index >= local.media.size()) || ((unsigned)sdp_media_index >= remote.media.size()) ) { ERROR("Media index %i is invalid, either within local or remote SDP (or both)",sdp_media_index); return -1; } const SdpMedia& local_media = local.media[sdp_media_index]; const SdpMedia& remote_media = remote.media[sdp_media_index]; payloads.clear(); pl_map.clear(); payloads.resize(local_media.payloads.size()); int i=0; vector<SdpPayload>::const_iterator sdp_it = local_media.payloads.begin(); vector<Payload>::iterator p_it = payloads.begin(); // first pass on local SDP - fill pl_map with intersection of codecs while(sdp_it != local_media.payloads.end()) { int int_pt = payload_provider->getDynPayload(sdp_it->encoding_name, sdp_it->clock_rate, sdp_it->encoding_param); amci_payload_t* a_pl = NULL; if(int_pt >= 0) a_pl = payload_provider->payload(int_pt); if(a_pl == NULL){ if (relay_payloads.get(sdp_it->payload_type)) { // this payload should be relayed, ignore ++sdp_it; continue; } else { ERROR("No internal payload corresponding to type %s/%i (ignoring)\n", sdp_it->encoding_name.c_str(), sdp_it->clock_rate); // ignore this payload ++sdp_it; continue; } }; p_it->pt = sdp_it->payload_type; p_it->name = sdp_it->encoding_name; p_it->codec_id = a_pl->codec_id; p_it->clock_rate = a_pl->sample_rate; p_it->advertised_clock_rate = sdp_it->clock_rate; pl_map[sdp_it->payload_type].index = i; pl_map[sdp_it->payload_type].remote_pt = -1; ++p_it; ++sdp_it; ++i; } // remove payloads which were not initialised (because of unknown payloads // which are to be relayed) if (p_it != payloads.end()) payloads.erase(p_it, payloads.end()); // second pass on remote SDP - initialize payload IDs used by remote (remote_pt) sdp_it = remote_media.payloads.begin(); while(sdp_it != remote_media.payloads.end()) { // TODO: match not only on encoding name // but also on parameters, if necessary // Some codecs define multiple payloads // with different encoding parameters PayloadMappingTable::iterator pmt_it = pl_map.end(); if(sdp_it->encoding_name.empty()){ // must be a static payload pmt_it = pl_map.find(sdp_it->payload_type); } else { for(p_it = payloads.begin(); p_it != payloads.end(); ++p_it){ if(!strcasecmp(p_it->name.c_str(),sdp_it->encoding_name.c_str()) && (p_it->advertised_clock_rate == (unsigned int)sdp_it->clock_rate)){ pmt_it = pl_map.find(p_it->pt); break; } } } // TODO: remove following code once proper // payload matching is implemented // // initialize remote_pt if not already there if(pmt_it != pl_map.end() && (pmt_it->second.remote_pt < 0)){ pmt_it->second.remote_pt = sdp_it->payload_type; } ++sdp_it; } if(!l_port){ // only if socket not yet bound: // set local address - media c-line having precedence over session c-line if (local_media.conn.address.empty()) setLocalIP(local.conn.address); else setLocalIP(local_media.conn.address); } setPassiveMode(remote_media.dir == SdpMedia::DirActive || force_passive_mode); // set remote address - media c-line having precedence over session c-line if (remote.conn.address.empty() && remote_media.conn.address.empty()) { WARN("no c= line given globally or in m= section in remote SDP\n"); return -1; } if (remote_media.conn.address.empty()) setRAddr(remote.conn.address, remote_media.port); else setRAddr(remote_media.conn.address, remote_media.port); if(local_media.payloads.empty()) { ERROR("local_media.payloads.empty()\n"); return -1; } payload = getDefaultPT(); if(payload < 0) { ERROR("could not set a default payload\n"); return -1; } DBG("default payload selected = %i\n",payload); last_payload = payload; remote_telephone_event_pt.reset(remote.telephoneEventPayload()); if (remote_telephone_event_pt.get()) { DBG("remote party supports telephone events (pt=%i)\n", remote_telephone_event_pt->payload_type); } else { DBG("remote party doesn't support telephone events\n"); } local_telephone_event_pt.reset(local.telephoneEventPayload()); if(local_media.recv) { resume(); } else { pause(); } if(local_media.send && !hold && (remote_media.port != 0) #ifndef SUPPORT_IPV6 && (r_saddr.sin_addr.s_addr != 0) #endif ) { mute = false; } else { mute = true; } #ifdef WITH_ZRTP if( session->zrtp_audio ) { DBG("now starting zrtp stream...\n"); zrtp_start_stream( session->zrtp_audio ); } #endif active = false; // mark as nothing received yet return 0; }