Files
protocol/sdp/sdp.go
cnderrauber d791f31b6e Add playoutdelay to CreateRoomRequest (#439)
* Add playoutdelay to CreateRoomRequest

* generated protobuf

* Remove max from PlayoutDelay

* generated protobuf

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2023-08-03 16:11:22 +08:00

152 lines
4.2 KiB
Go

// Copyright 2023 LiveKit, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package sdp
import (
"strings"
"github.com/pion/sdp/v3"
"github.com/pion/webrtc/v3"
)
func GetMidValue(media *sdp.MediaDescription) string {
for _, attr := range media.Attributes {
if attr.Key == sdp.AttrKeyMID {
return attr.Value
}
}
return ""
}
func ExtractFingerprint(desc *sdp.SessionDescription) (string, string, error) {
fingerprints := make([]string, 0)
if fingerprint, haveFingerprint := desc.Attribute("fingerprint"); haveFingerprint {
fingerprints = append(fingerprints, fingerprint)
}
for _, m := range desc.MediaDescriptions {
if fingerprint, haveFingerprint := m.Attribute("fingerprint"); haveFingerprint {
fingerprints = append(fingerprints, fingerprint)
}
}
if len(fingerprints) < 1 {
return "", "", webrtc.ErrSessionDescriptionNoFingerprint
}
for _, m := range fingerprints {
if m != fingerprints[0] {
return "", "", webrtc.ErrSessionDescriptionConflictingFingerprints
}
}
parts := strings.Split(fingerprints[0], " ")
if len(parts) != 2 {
return "", "", webrtc.ErrSessionDescriptionInvalidFingerprint
}
return parts[1], parts[0], nil
}
func ExtractDTLSRole(desc *sdp.SessionDescription) webrtc.DTLSRole {
for _, md := range desc.MediaDescriptions {
setup, ok := md.Attribute(sdp.AttrKeyConnectionSetup)
if !ok {
continue
}
if setup == sdp.ConnectionRoleActive.String() {
return webrtc.DTLSRoleClient
}
if setup == sdp.ConnectionRolePassive.String() {
return webrtc.DTLSRoleServer
}
}
//
// If 'setup' attribute is not available, use client role
// as that is the default behaviour of answerers
//
// There seems to be some differences in how role is decided.
// libwebrtc (Chrome) code - (https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/pc/jsep_transport.cc;l=592;drc=369fb686729e7eb20d2bd09717cec14269a399d7)
// does not mention anything about ICE role when determining
// DTLS Role.
//
// But, ORTC has this - https://github.com/w3c/ortc/issues/167#issuecomment-69409953
// and pion/webrtc follows that (https://github.com/pion/webrtc/blob/e071a4eded1efd5d9b401bcfc4efacb3a2a5a53c/dtlstransport.go#L269)
//
// So if remote is ice-lite, pion will use DTLSRoleServer when answering
// while browsers pick DTLSRoleClient.
//
return webrtc.DTLSRoleClient
}
func ExtractICECredential(desc *sdp.SessionDescription) (string, string, error) {
remotePwds := []string{}
remoteUfrags := []string{}
if ufrag, haveUfrag := desc.Attribute("ice-ufrag"); haveUfrag {
remoteUfrags = append(remoteUfrags, ufrag)
}
if pwd, havePwd := desc.Attribute("ice-pwd"); havePwd {
remotePwds = append(remotePwds, pwd)
}
for _, m := range desc.MediaDescriptions {
if ufrag, haveUfrag := m.Attribute("ice-ufrag"); haveUfrag {
remoteUfrags = append(remoteUfrags, ufrag)
}
if pwd, havePwd := m.Attribute("ice-pwd"); havePwd {
remotePwds = append(remotePwds, pwd)
}
}
if len(remoteUfrags) == 0 {
return "", "", webrtc.ErrSessionDescriptionMissingIceUfrag
} else if len(remotePwds) == 0 {
return "", "", webrtc.ErrSessionDescriptionMissingIcePwd
}
for _, m := range remoteUfrags {
if m != remoteUfrags[0] {
return "", "", webrtc.ErrSessionDescriptionConflictingIceUfrag
}
}
for _, m := range remotePwds {
if m != remotePwds[0] {
return "", "", webrtc.ErrSessionDescriptionConflictingIcePwd
}
}
return remoteUfrags[0], remotePwds[0], nil
}
func ExtractStreamID(media *sdp.MediaDescription) (string, bool) {
var streamID string
msid, ok := media.Attribute(sdp.AttrKeyMsid)
if !ok {
return "", false
}
ids := strings.Split(msid, " ")
if len(ids) < 2 {
streamID = msid
} else {
streamID = ids[1]
}
return streamID, true
}