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

📄 sdp.cxx

📁 sloedgy open sip stack source code
💻 CXX
📖 第 1 页 / 共 2 页
字号:
  RTP_DataFrame::PayloadTypes pt = (RTP_DataFrame::PayloadTypes)str.Left(pos).AsUnsigned();

  // find the format that matches the payload type
  PINDEX fmt = 0;
  while (formats[fmt].GetPayloadType() != pt) {
    fmt++;
    if (fmt >= formats.GetSize()) {
      PTRACE(2, "SDP\tMedia attribute " << attr << " found for unknown RTP type " << pt);
      return;
    }
  }
  SDPMediaFormat & format = formats[fmt];

  // extract the attribute argument
  str = str.Mid(pos+1).Trim();

  // handle rtpmap attribute
  if (attr *= "rtpmap") {

    PStringArray tokens = str.Tokenise('/');
    if (tokens.GetSize() < 2) {
      PTRACE(2, "SDP\tMalformed rtpmap attribute for " << pt);
      return;
    }

    format.SetEncodingName(tokens[0]);
    format.SetClockRate(tokens[1].AsUnsigned());
    if (tokens.GetSize() > 2)
      format.SetParameters(tokens[2]);

    return;
  }

  // handle fmtp attributes
  if (attr *= "fmtp") {
    format.SetFMTP(str);
    return;
  }

  // unknown attriutes
  PTRACE(2, "SDP\tUnknown media attribute " << ostr);
  return;
}


void SDPMediaDescription::PrintOn(const OpalTransportAddress & commonAddr, ostream & str) const
{
  PIPSocket::Address commonIP;
  commonAddr.GetIpAddress(commonIP);

  PIPSocket::Address transportIP;
  transportAddress.GetIpAddress(transportIP);

  PString connectString;
  if (commonIP != transportIP)
    connectString = GetConnectAddressString(transportAddress);

  PrintOn(str, connectString);
}

void SDPMediaDescription::PrintOn(ostream & str) const
{
  PIPSocket::Address ip;
  transportAddress.GetIpAddress(ip);
  PrintOn(str, GetConnectAddressString(transportAddress));
}

void SDPMediaDescription::PrintOn(ostream & str, const PString & connectString) const
{
  //
  // if no media formats, then do not output the media header
  // this avoids displaying an empty media header with no payload types
  // when (for example) video has been disabled
  //
  if (formats.GetSize() == 0)
    return;

  PIPSocket::Address ip;
  WORD port;
  transportAddress.GetIpAndPort(ip, port);

  // output media header
  str << "m=" 
      << media << " "
      << port << " "
      << transport;

  if (transport == SDP_MEDIA_TRANSPORT) {

    // output RTP payload types
    PINDEX i;
    for (i = 0; i < formats.GetSize(); i++)
      str << ' ' << (int)formats[i].GetPayloadType();
    str << "\r\n";

    // output attributes for each payload type
    for (i = 0; i < formats.GetSize(); i++)
      str << formats[i];

    if (packetTime)
      str << "a=ptime:" << packetTime << "\r\n";

    // media format direction
    switch (direction) {
      case SDPMediaDescription::RecvOnly:
        str << "a=recvonly" << "\r\n";
        break;
      case SDPMediaDescription::SendOnly:
        str << "a=sendonly" << "\r\n";
        break;
      case SDPMediaDescription::SendRecv:
        str << "a=sendrecv" << "\r\n";
        break;
      case SDPMediaDescription::Inactive:
        str << "a=inactive" << "\r\n";
        break;
      default:
        break;
    }
  }

  else {
    PINDEX i;
    for (i = 0; i < formats.GetSize(); i++)
      str << ' ' << formats[i].GetEncodingName();
    str << "\r\n";
  }

  if (!connectString.IsEmpty())
    str << "c=" << connectString << "\r\n";
}


OpalMediaFormatList SDPMediaDescription::GetMediaFormats(unsigned sessionID) const
{
  OpalMediaFormatList list;

  PINDEX i;
  for (i = 0; i < formats.GetSize(); i++) {
    OpalMediaFormat opalFormat = formats[i].GetMediaFormat();
    if (opalFormat.IsEmpty())
      PTRACE(2, "SIP\tRTP payload type " << formats[i].GetPayloadType() << " not matched to audio codec");
    else {
      if (opalFormat.GetDefaultSessionID() == sessionID) {
        PTRACE(2, "SIP\tRTP payload type " << formats[i].GetPayloadType() << " matched to codec " << opalFormat);
	      list += opalFormat;
      }
    }
  }

  return list;
}

void SDPMediaDescription::CreateRTPMap(unsigned sessionID, RTP_DataFrame::PayloadMapType & map) const
{
  OpalMediaFormatList list;

  PINDEX i;
  for (i = 0; i < formats.GetSize(); i++) {
    OpalMediaFormat opalFormat = formats[i].GetMediaFormat();
    if (!opalFormat.IsEmpty() && 
         opalFormat.GetDefaultSessionID() == sessionID &&
         opalFormat.GetPayloadType() != formats[i].GetPayloadType()) {
      map.insert(RTP_DataFrame::PayloadMapType::value_type(opalFormat.GetPayloadType(), formats[i].GetPayloadType()));
      PTRACE(2, "SIP\tAdding RTP translation from " << opalFormat.GetPayloadType() << " to " << formats[i].GetPayloadType());
    }
  }
}

void SDPMediaDescription::AddSDPMediaFormat(SDPMediaFormat * sdpMediaFormat)
{
  formats.Append(sdpMediaFormat);
}


void SDPMediaDescription::AddMediaFormat(const OpalMediaFormat & mediaFormat, const RTP_DataFrame::PayloadMapType & map)
{
  RTP_DataFrame::PayloadTypes payloadType = mediaFormat.GetPayloadType();
  const char * encodingName = mediaFormat.GetEncodingName();
  unsigned clockRate = mediaFormat.GetClockRate();

  RTP_DataFrame::PayloadMapType payloadTypeMap = map;
  if (payloadTypeMap.size() != 0) {
    RTP_DataFrame::PayloadMapType::iterator r = payloadTypeMap.find(payloadType);
    if (r != payloadTypeMap.end())
      payloadType = r->second;
  }
      
  if (payloadType >= RTP_DataFrame::MaxPayloadType || encodingName == NULL || *encodingName == '\0')
    return;

  PINDEX i;
  for (i = 0; i < formats.GetSize(); i++) {
    if (formats[i].GetPayloadType() == payloadType ||
        (strcasecmp(formats[i].GetEncodingName(), encodingName) == 0 
	 && formats[i].GetClockRate() == clockRate))
      return;
  }

  AddSDPMediaFormat(new SDPMediaFormat(payloadType, encodingName, mediaFormat.GetClockRate()));
}


void SDPMediaDescription::AddMediaFormats(const OpalMediaFormatList & mediaFormats, unsigned session, const RTP_DataFrame::PayloadMapType & map)
{
  for (PINDEX i = 0; i < mediaFormats.GetSize(); i++) {
    OpalMediaFormat mediaFormat = mediaFormats[i];
    if (mediaFormat.GetDefaultSessionID() == session &&
        mediaFormat.GetPayloadType() != RTP_DataFrame::IllegalPayloadType)
      AddMediaFormat(mediaFormat, map);
  }
}


//////////////////////////////////////////////////////////////////////////////

const char * const SDPSessionDescription::ConferenceTotalBandwidthModifier = "CT";
const char * const SDPSessionDescription::ApplicationSpecificBandwidthModifier = "AS";

SDPSessionDescription::SDPSessionDescription(const OpalTransportAddress & address)
  : sessionName(SIP_DEFAULT_SESSION_NAME),
    ownerUsername('-'),
    ownerAddress(address),
    defaultConnectAddress(address)
{
  protocolVersion  = 0;
  ownerSessionId  = ownerVersion = PTime().GetTimeInSeconds();
  direction = SDPMediaDescription::Undefined;
  
  bandwidthModifier = "";
  bandwidthValue = 0;
}


void SDPSessionDescription::PrintOn(ostream & str) const
{
  OpalTransportAddress connectionAddress(defaultConnectAddress);
  BOOL useCommonConnect = TRUE;

  // see common connect address is needed
  {
    OpalTransportAddress descrAddress;
    PINDEX matched = 0;
    PINDEX descrMatched = 0;
    PINDEX i;
    for (i = 0; i < mediaDescriptions.GetSize(); i++) {
      if (i == 0)
        descrAddress = mediaDescriptions[i].GetTransportAddress();
      if (mediaDescriptions[i].GetTransportAddress() == connectionAddress)
        ++matched;
      if (mediaDescriptions[i].GetTransportAddress() == descrAddress)
        ++descrMatched;
    }
    if (connectionAddress != descrAddress) {
      if ((descrMatched > matched))
        connectionAddress = descrAddress;
      else
        useCommonConnect = FALSE;
    }
  }

  // encode mandatory session information
  str << "v=" << protocolVersion << "\r\n"
         "o=" << ownerUsername << ' '
	      << ownerSessionId << ' '
	      << ownerVersion << ' '
              << GetConnectAddressString(ownerAddress)
              << "\r\n"
         "s=" << sessionName << "\r\n";

  // make sure the "c=" line (if required) is before the "t=" otherwise the proxy
  // used by FWD will reject the call with an SDP parse error. This does not seem to be 
  // required by the RFC so it is probably a bug in the proxy
  if (useCommonConnect)
    str << "c=" << GetConnectAddressString(connectionAddress) << "\r\n";
  
  if(bandwidthModifier != "" && bandwidthValue != 0) {
	  str << "b=" << bandwidthModifier << ":" << bandwidthValue << "\r\n";
  }
  
  str << "t=" << "0 0" << "\r\n";

  switch (direction) {

  case SDPMediaDescription::RecvOnly:
    str << "a=recvonly" << "\r\n";
    break;
  case SDPMediaDescription::SendOnly:
    str << "a=sendonly" << "\r\n";
    break;
  case SDPMediaDescription::SendRecv:
    str << "a=sendrecv" << "\r\n";
    break;
  case SDPMediaDescription::Inactive:
    str << "a=inactive" << "\r\n";
    break;
  default:
    break;
  }
  
  // encode media session information
  PINDEX i;
  for (i = 0; i < mediaDescriptions.GetSize(); i++) {
    if (useCommonConnect) 
      mediaDescriptions[i].PrintOn(connectionAddress, str);
    else
      str << mediaDescriptions[i];
  }
}


PString SDPSessionDescription::Encode() const
{
  PStringStream str;
  PrintOn(str);
  return str;
}


BOOL SDPSessionDescription::Decode(const PString & str)
{
  // break string into lines
  PStringArray lines = str.Lines();

  // parse keyvalue pairs
  SDPMediaDescription * currentMedia = NULL;
  PINDEX i;
  for (i = 0; i < lines.GetSize(); i++) {
    PString & line = lines[i];
    PINDEX pos = line.Find('=');
    if (pos != P_MAX_INDEX) {
      PString key   = line.Left(pos).Trim();
      PString value = line.Mid(pos+1).Trim();
      if (key.GetLength() == 1) {

      	// media name and transport address (mandatory)
        if (key[0] == 'm') {
          currentMedia = new SDPMediaDescription(defaultConnectAddress);
          if (currentMedia->Decode(value)) {
            mediaDescriptions.Append(currentMedia);
            PTRACE(3, "SDP\tAdding media session with " << currentMedia->GetSDPMediaFormats().GetSize() << " formats");
          }
          else
            delete currentMedia;
        }
	
        /////////////////////////////////
        //
        // Session description
        //
        /////////////////////////////////
	  
        else if (currentMedia == NULL) {
	  PINDEX thePos;
          switch (key[0]) {
            case 'v' : // protocol version (mandatory)
              protocolVersion = value.AsInteger();
              break;

            case 'o' : // owner/creator and session identifier (mandatory)
              ParseOwner(value);
              break;

            case 's' : // session name (mandatory)
              sessionName = value;
              break;

            case 'c' : // connection information - not required if included in all media
              defaultConnectAddress = ParseConnectAddress(value);
              break;

            case 't' : // time the session is active (mandatory)
            case 'i' : // session information
            case 'u' : // URI of description
            case 'e' : // email address
            case 'p' : // phone number
	      break;
            case 'b' : // bandwidth information
	      thePos = value.Find(':');
	      if (thePos != P_MAX_INDEX) {
		bandwidthModifier = value.Left(thePos);
		bandwidthValue = value.Mid(thePos+1).AsInteger();
	      }
	      break;
            case 'z' : // time zone adjustments
            case 'k' : // encryption key
            case 'r' : // zero or more repeat times
              break;
            case 'a' : // zero or more session attribute lines
	      if (value *= "sendonly")
		SetDirection (SDPMediaDescription::SendOnly);
	      else if (value *= "recvonly")
		SetDirection (SDPMediaDescription::RecvOnly);
	      else if (value *= "sendrecv")
		SetDirection (SDPMediaDescription::SendRecv);
	      else if (value *= "inactive")
		SetDirection (SDPMediaDescription::Inactive);
	      break;

            default:
              PTRACE(1, "SDP\tUnknown session information key " << key[0]);
          }
        }

        /////////////////////////////////
        //
        // media information
        //
        /////////////////////////////////
	  
        else {
          switch (key[0]) {
            case 'i' : // media title
            case 'b' : // bandwidth information
            case 'k' : // encryption key
              break;

            case 'c' : // connection information - optional if included at session-level
              break;

            case 'a' : // zero or more media attribute lines
	      currentMedia->SetAttribute(value);
              break;

            default:
              PTRACE(1, "SDP\tUnknown mediainformation key " << key[0]);
          }
        }
      }
    }
  }

  return TRUE;
}


void SDPSessionDescription::ParseOwner(const PString & str)
{
  PStringArray tokens = str.Tokenise(" ");

  if (tokens.GetSize() != 6) {
    PTRACE(1, "SDP\tOrigin has " << tokens.GetSize() << " elements");
  }
  else {
    ownerUsername    = tokens[0];
    ownerSessionId   = tokens[1].AsUnsigned();
    ownerVersion     = tokens[2].AsUnsigned();
    ownerAddress = defaultConnectAddress = ParseConnectAddress(tokens, 3);
  }
}


SDPMediaDescription * SDPSessionDescription::GetMediaDescription(
                                    SDPMediaDescription::MediaType rtpMediaType) const
{
  // look for matching media type
  PINDEX i;
  for (i = 0; i < mediaDescriptions.GetSize(); i++) {
    if (mediaDescriptions[i].GetMediaType() == rtpMediaType)
      return &mediaDescriptions[i];
  }

  return NULL;
}


SDPMediaDescription::Direction SDPSessionDescription::GetDirection(unsigned sessionID) const
{
  PINDEX i;
  for (i = 0; i < mediaDescriptions.GetSize(); i++) {
    if ((mediaDescriptions[i].GetMediaType() == SDPMediaDescription::Video && sessionID == OpalMediaFormat::DefaultVideoSessionID) || (mediaDescriptions[i].GetMediaType() == SDPMediaDescription::Audio && sessionID == OpalMediaFormat::DefaultAudioSessionID)) {
      if (mediaDescriptions[i].GetDirection() != SDPMediaDescription::Undefined)
	return mediaDescriptions[i].GetDirection();
      else
	return direction;
    }
  }
  
  return direction;
}

// End of file ////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

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