Beispiel #1
0
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;
}