bool
SipccSdpAttributeList::LoadGroups(sdp_t* sdp, uint16_t level,
                                  SdpErrorHolder& errorHolder)
{
  uint16_t attrCount = 0;
  if (sdp_attr_num_instances(sdp, level, 0, SDP_ATTR_GROUP, &attrCount) !=
      SDP_SUCCESS) {
    MOZ_ASSERT(false, "Could not get count of group attributes");
    errorHolder.AddParseError(0, "Could not get count of group attributes");
    return false;
  }

  UniquePtr<SdpGroupAttributeList> groups = MakeUnique<SdpGroupAttributeList>();
  for (uint16_t attr = 1; attr <= attrCount; ++attr) {
    SdpGroupAttributeList::Semantics semantics;
    std::vector<std::string> tags;

    switch (sdp_get_group_attr(sdp, level, 0, attr)) {
      case SDP_GROUP_ATTR_FID:
        semantics = SdpGroupAttributeList::kFid;
        break;
      case SDP_GROUP_ATTR_LS:
        semantics = SdpGroupAttributeList::kLs;
        break;
      case SDP_GROUP_ATTR_ANAT:
        semantics = SdpGroupAttributeList::kAnat;
        break;
      case SDP_GROUP_ATTR_BUNDLE:
        semantics = SdpGroupAttributeList::kBundle;
        break;
      default:
        continue;
    }

    uint16_t idCount = sdp_get_group_num_id(sdp, level, 0, attr);
    for (uint16_t id = 1; id <= idCount; ++id) {
      const char* idStr = sdp_get_group_id(sdp, level, 0, attr, id);
      if (!idStr) {
        std::ostringstream os;
        os << "bad a=group identifier at " << (attr - 1) << ", " << (id - 1);
        errorHolder.AddParseError(0, os.str());
        return false;
      }
      tags.push_back(std::string(idStr));
    }
    groups->PushEntry(semantics, tags);
  }

  if (!groups->mGroups.empty()) {
    SetAttribute(groups.release());
  }

  return true;
}
Example #2
0
nsresult
SdpHelper::AddCandidateToSdp(Sdp* sdp,
                             const std::string& candidateUntrimmed,
                             const std::string& mid,
                             uint16_t level)
{

  if (level >= sdp->GetMediaSectionCount()) {
    SDP_SET_ERROR("Index " << level << " out of range");
    return NS_ERROR_INVALID_ARG;
  }

  // Trim off '[a=]candidate:'
  size_t begin = candidateUntrimmed.find(':');
  if (begin == std::string::npos) {
    SDP_SET_ERROR("Invalid candidate, no ':' (" << candidateUntrimmed << ")");
    return NS_ERROR_INVALID_ARG;
  }
  ++begin;

  std::string candidate = candidateUntrimmed.substr(begin);

  // TODO(bug 1095793): mid

  SdpMediaSection& msection = sdp->GetMediaSection(level);
  SdpAttributeList& attrList = msection.GetAttributeList();

  UniquePtr<SdpMultiStringAttribute> candidates;
  if (!attrList.HasAttribute(SdpAttribute::kCandidateAttribute)) {
    // Create new
    candidates.reset(
        new SdpMultiStringAttribute(SdpAttribute::kCandidateAttribute));
  } else {
    // Copy existing
    candidates.reset(new SdpMultiStringAttribute(
        *static_cast<const SdpMultiStringAttribute*>(
            attrList.GetAttribute(SdpAttribute::kCandidateAttribute))));
  }
  candidates->PushEntry(candidate);
  attrList.SetAttribute(candidates.release());

  return NS_OK;
}
bool
SipccSdpAttributeList::LoadFingerprint(sdp_t* sdp, uint16_t level,
                                       SdpErrorHolder& errorHolder)
{
  char* value;
  UniquePtr<SdpFingerprintAttributeList> fingerprintAttrs;

  for (uint16_t i = 1; i < UINT16_MAX; ++i) {
    sdp_result_e result = sdp_attr_get_dtls_fingerprint_attribute(
        sdp, level, 0, SDP_ATTR_DTLS_FINGERPRINT, i, &value);

    if (result != SDP_SUCCESS) {
      break;
    }

    std::string fingerprintAttr(value);
    uint32_t lineNumber =
        sdp_attr_line_number(sdp, SDP_ATTR_DTLS_FINGERPRINT, level, 0, i);

    // sipcc does not expose parse code for this
    size_t start = fingerprintAttr.find_first_not_of(" \t");
    if (start == std::string::npos) {
      errorHolder.AddParseError(lineNumber, "Empty fingerprint attribute");
      return false;
    }

    size_t end = fingerprintAttr.find_first_of(" \t", start);
    if (end == std::string::npos) {
      // One token, no trailing ws
      errorHolder.AddParseError(lineNumber,
                                "Only one token in fingerprint attribute");
      return false;
    }

    std::string algorithmToken(fingerprintAttr.substr(start, end - start));

    start = fingerprintAttr.find_first_not_of(" \t", end);
    if (start == std::string::npos) {
      // One token, trailing ws
      errorHolder.AddParseError(lineNumber,
                                "Only one token in fingerprint attribute");
      return false;
    }

    std::string fingerprintToken(fingerprintAttr.substr(start));

    std::vector<uint8_t> fingerprint =
        SdpFingerprintAttributeList::ParseFingerprint(fingerprintToken);
    if (fingerprint.size() == 0) {
      errorHolder.AddParseError(lineNumber, "Malformed fingerprint token");
      return false;
    }

    if (!fingerprintAttrs) {
      fingerprintAttrs.reset(new SdpFingerprintAttributeList);
    }

    // Don't assert on unknown algorithm, just skip
    fingerprintAttrs->PushEntry(algorithmToken, fingerprint, false);
  }

  if (fingerprintAttrs) {
    SetAttribute(fingerprintAttrs.release());
  }

  return true;
}
Example #4
0
nsresult
SdpHelper::AddCandidateToSdp(Sdp* sdp,
                             const std::string& candidateUntrimmed,
                             const std::string& mid,
                             uint16_t level)
{

  if (level >= sdp->GetMediaSectionCount()) {
    SDP_SET_ERROR("Index " << level << " out of range");
    return NS_ERROR_INVALID_ARG;
  }

  // Trim off '[a=]candidate:'
  size_t begin = candidateUntrimmed.find(':');
  if (begin == std::string::npos) {
    SDP_SET_ERROR("Invalid candidate, no ':' (" << candidateUntrimmed << ")");
    return NS_ERROR_INVALID_ARG;
  }
  ++begin;

  std::string candidate = candidateUntrimmed.substr(begin);

  // https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-11#section-3.4.2.1
  // Implementations receiving an ICE Candidate object MUST use the MID if
  // present, or the m= line index, if not (as it could have come from a
  // non-JSEP endpoint). (bug 1095793)
  SdpMediaSection* msection = 0;
  if (!mid.empty()) {
    // FindMsectionByMid could return nullptr
    msection = FindMsectionByMid(*sdp, mid);

    // Check to make sure mid matches what we'd get by
    // looking up the m= line using the level. (mjf)
    std::string checkMid;
    nsresult rv = GetMidFromLevel(*sdp, level, &checkMid);
    if (NS_FAILED(rv)) {
      return rv;
    }
    if (mid != checkMid) {
      SDP_SET_ERROR("Mismatch between mid and level - \"" << mid
                     << "\" is not the mid for level " << level
                     << "; \"" << checkMid << "\" is");
      return NS_ERROR_INVALID_ARG;
    }
  }
  if (!msection) {
    msection = &(sdp->GetMediaSection(level));
  }

  SdpAttributeList& attrList = msection->GetAttributeList();

  UniquePtr<SdpMultiStringAttribute> candidates;
  if (!attrList.HasAttribute(SdpAttribute::kCandidateAttribute)) {
    // Create new
    candidates.reset(
        new SdpMultiStringAttribute(SdpAttribute::kCandidateAttribute));
  } else {
    // Copy existing
    candidates.reset(new SdpMultiStringAttribute(
        *static_cast<const SdpMultiStringAttribute*>(
            attrList.GetAttribute(SdpAttribute::kCandidateAttribute))));
  }
  candidates->PushEntry(candidate);
  attrList.SetAttribute(candidates.release());

  return NS_OK;
}