mirror of
https://github.com/aler9/gortsplib
synced 2025-10-25 08:10:34 +08:00
134
server_conn.go
134
server_conn.go
@@ -2,6 +2,7 @@ package gortsplib
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net"
|
||||
@@ -17,6 +18,7 @@ import (
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/description"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/headers"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/liberrors"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/mikey"
|
||||
)
|
||||
|
||||
func getSessionID(header base.Header) string {
|
||||
@@ -51,7 +53,97 @@ func checkBackChannelsEnabled(header base.Header) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func prepareForDescribe(d *description.Session, multicast bool, backChannels bool) *description.Session {
|
||||
func mikeyGenerate(ctx *wrappedSRTPContext) (*mikey.Message, error) {
|
||||
csbID, err := randUint32()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
msg := &mikey.Message{
|
||||
Header: mikey.Header{
|
||||
Version: 1,
|
||||
CSBID: csbID,
|
||||
},
|
||||
}
|
||||
|
||||
msg.Header.CSIDMapInfo = make([]mikey.SRTPIDEntry, len(ctx.ssrcs))
|
||||
|
||||
n := 0
|
||||
for _, ssrc := range ctx.ssrcs {
|
||||
msg.Header.CSIDMapInfo[n] = mikey.SRTPIDEntry{
|
||||
PolicyNo: 0,
|
||||
SSRC: ssrc,
|
||||
ROC: ctx.roc(ssrc),
|
||||
}
|
||||
n++
|
||||
}
|
||||
|
||||
randData := make([]byte, 16)
|
||||
_, err = rand.Read(randData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
msg.Payloads = []mikey.Payload{
|
||||
&mikey.PayloadT{
|
||||
TSType: 0,
|
||||
TSValue: mikeyEncodeTime(time.Now()),
|
||||
},
|
||||
&mikey.PayloadRAND{
|
||||
Data: randData,
|
||||
},
|
||||
&mikey.PayloadSP{
|
||||
PolicyParams: []mikey.PayloadSPPolicyParam{
|
||||
{
|
||||
Type: mikey.PayloadSPPolicyParamTypeEncrAlg,
|
||||
Value: []byte{1},
|
||||
},
|
||||
{
|
||||
Type: mikey.PayloadSPPolicyParamTypeSessionEncrKeyLen,
|
||||
Value: []byte{0x10},
|
||||
},
|
||||
{
|
||||
Type: mikey.PayloadSPPolicyParamTypeAuthAlg,
|
||||
Value: []byte{1},
|
||||
},
|
||||
{
|
||||
Type: mikey.PayloadSPPolicyParamTypeSessionAuthKeyLen,
|
||||
Value: []byte{0x0a},
|
||||
},
|
||||
{
|
||||
Type: mikey.PayloadSPPolicyParamTypeSRTPEncrOffOn,
|
||||
Value: []byte{1},
|
||||
},
|
||||
{
|
||||
Type: mikey.PayloadSPPolicyParamTypeSRTCPEncrOffOn,
|
||||
Value: []byte{1},
|
||||
},
|
||||
{
|
||||
Type: mikey.PayloadSPPolicyParamTypeSRTPAuthOffOn,
|
||||
Value: []byte{1},
|
||||
},
|
||||
},
|
||||
},
|
||||
&mikey.PayloadKEMAC{
|
||||
SubPayloads: []*mikey.SubPayloadKeyData{
|
||||
{
|
||||
Type: mikey.SubPayloadKeyDataKeyTypeTEK,
|
||||
KeyData: ctx.key,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
func prepareForDescribe(
|
||||
d *description.Session,
|
||||
multicast bool,
|
||||
backChannels bool,
|
||||
secure bool,
|
||||
medias map[*description.Media]*serverStreamMedia,
|
||||
) (*description.Session, error) {
|
||||
out := &description.Session{
|
||||
Title: d.Title,
|
||||
Multicast: multicast,
|
||||
@@ -60,19 +152,32 @@ func prepareForDescribe(d *description.Session, multicast bool, backChannels boo
|
||||
|
||||
for i, medi := range d.Medias {
|
||||
if !medi.IsBackChannel || backChannels {
|
||||
var keyMgmtMikey *mikey.Message
|
||||
if secure {
|
||||
sm := medias[medi]
|
||||
|
||||
var err error
|
||||
keyMgmtMikey, err = mikeyGenerate(sm.srtpOutCtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
out.Medias = append(out.Medias, &description.Media{
|
||||
Type: medi.Type,
|
||||
ID: medi.ID,
|
||||
IsBackChannel: medi.IsBackChannel,
|
||||
// we have to use trackID=number in order to support clients
|
||||
// like the Grandstream GXV3500.
|
||||
Control: "trackID=" + strconv.FormatInt(int64(i), 10),
|
||||
Formats: medi.Formats,
|
||||
Control: "trackID=" + strconv.FormatInt(int64(i), 10),
|
||||
Secure: secure,
|
||||
KeyMgmtMikey: keyMgmtMikey,
|
||||
Formats: medi.Formats,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func credentialsProvided(req *base.Request) bool {
|
||||
@@ -160,7 +265,7 @@ func (sc *ServerConn) UserData() interface{} {
|
||||
return sc.userData
|
||||
}
|
||||
|
||||
// Session returns associated session.
|
||||
// Session returns the associated session.
|
||||
func (sc *ServerConn) Session() *ServerSession {
|
||||
return sc.session
|
||||
}
|
||||
@@ -370,13 +475,28 @@ func (sc *ServerConn) handleRequestInner(req *base.Request) (*base.Response, err
|
||||
return res, err
|
||||
}
|
||||
|
||||
desc := prepareForDescribe(
|
||||
var desc *description.Session
|
||||
desc, err = prepareForDescribe(
|
||||
stream.Desc,
|
||||
checkMulticastEnabled(sc.s.MulticastIPRange, query),
|
||||
checkBackChannelsEnabled(req.Header),
|
||||
sc.s.TLSConfig != nil,
|
||||
stream.medias,
|
||||
)
|
||||
if err != nil {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusInternalServerError,
|
||||
}, err
|
||||
}
|
||||
|
||||
var byts []byte
|
||||
byts, err = desc.Marshal(false)
|
||||
if err != nil {
|
||||
return &base.Response{
|
||||
StatusCode: base.StatusInternalServerError,
|
||||
}, err
|
||||
}
|
||||
|
||||
byts, _ := desc.Marshal(false)
|
||||
res.Body = byts
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user