diff --git a/sdp/offer.go b/sdp/offer.go index 492be90..ab8112d 100644 --- a/sdp/offer.go +++ b/sdp/offer.go @@ -571,8 +571,14 @@ func parseMKI(s string) ([]byte, error) { func parseSRTPProfile(val string) (*srtp.Profile, error) { val = strings.TrimSpace(val) - sub := strings.SplitN(val, " ", 3) + // Parses RFC 4568 crypto lines: a=crypto: [] + // Example: a=crypto:2 AES_CM_128_HMAC_SHA1_80 inline:j/...UX|2^48 UNENCRYPTED_SRTCP FEC_ORDER=FEC_SRTP_BEFORE_SRTCP + // + // We look at the space-separated fields after the tag. LiveKit only uses the first 3 parameters, + // but we need to split into 4 parts to isolate the trailing [] from the . + sub := strings.SplitN(val, " ", 4) if len(sub) != 3 { + // Livekit can not deal with the session-params, ignore return nil, nil // ignore } sind, prof, skey := sub[0], srtp.ProtectionProfile(sub[1]), sub[2] diff --git a/sdp/offer_test.go b/sdp/offer_test.go index 3a6fb64..53dcddb 100644 --- a/sdp/offer_test.go +++ b/sdp/offer_test.go @@ -462,6 +462,25 @@ a=sendrecv `, wantErr: true, }, + { + name: "crypto line with session-params", + sdp: `v=0 +o=Test 1 1 IN IP4 127.0.0.1 +s=Stream1 +t=0 0 +m=audio 59236 RTP/AVP 0 101 +c=IN IP4 127.0.0.1 +a=rtpmap:0 PCMU/8000 +a=rtpmap:101 telephone-event/8000 +a=sendrecv +a=rtcp:59237 +a=ptime:20 +a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:VmzmISmJO70Qntt3ZNqw4od6XHk6m9/kD/8Qeaum|2^48|66051:4 +a=crypto:2 AES_CM_128_HMAC_SHA1_80 inline:j/azhfJjX2cv+xwOOH8W7aks30PDRN7MzyRML7UX|2^48|66051:4 UNENCRYPTED_SRTCP +a=crypto:3 AES_CM_128_HMAC_SHA1_80 +`, + wantErr: false, + }, } for _, test := range tests { @@ -569,6 +588,37 @@ a=rtcp-fb:* ccm tmmbr require.NoError(t, err) require.Equal(t, vProfiles, v.CryptoProfiles) }) + t.Run( + "Ignore crypto line with session-params", func(t *testing.T) { + const sdpData = `v=0 +o=lin 3723 713 IN IP4 192.168.0.2 +s=Talk +c=IN IP4 192.168.0.2 +t=0 0 +a=rtcp-xr:rcvr-rtt=all:10000 stat-summary=loss,dup,jitt,TTL voip-metrics +a=record:off +m=audio 11200 RTP/SAVP 96 0 9 97 101 +a=rtpmap:96 opus/48000/2 +a=fmtp:96 useinbandfec=1 +a=rtpmap:97 telephone-event/48000 +a=rtpmap:101 telephone-event/8000 +a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:pMIPxjzYIG5TQuIWfkjTnaACVrzohhFfOGhSMgV1 +a=crypto:2 AES_CM_128_HMAC_SHA1_32 inline:ZKkTQfuCsliegVZtFSya3Z6oEVUtSwjGCfHlbrMf +a=crypto:3 AES_256_CM_HMAC_SHA1_80 inline:BvoLeRu5IcBkgNN14qtqaxi0r7ei2rwuBSodd0SANggS9JHsp5IU7lhEsyna1A +a=crypto:4 AES_256_CM_HMAC_SHA1_32 inline:j92SDyNTUe0BNGk4LeeCsPqX0qwPP/e9TLafvd7L9waM8r4arjzgUqs7uUERyg +a=crypto:5 AEAD_AES_128_GCM inline:gGetEkQgGk4NZIoKj/cbFpRkHdocmKlP0u3VMw +a=crypto:6 AEAD_AES_256_GCM inline:EFFzS2FMyNoYcVcaARU+nvk+JhHmVbvdFtRxZuRi9rDmLYpLms5ySv93iy0 +a=crypto:7 AES_CM_128_HMAC_SHA1_32 inline:ZKkTQfuCsliegVZtFSya3Z6oEVUtSwjGCfHlbrMf UNENCRYPTED_SRTCP +a=crypto:8 AES_256_CM_HMAC_SHA1_80 inline:BvoLeRu5IcBkgNN14qtqaxi0r7ei2rwuBSodd0SANggS9JHsp5IU7lhEsyna1A|66051:4 UNENCRYPTED_SRTCP +a=crypto:9 AEAD_AES_256_GCM inline:EFFzS2FMyNoYcVcaARU+nvk+JhHmVbvdFtRxZuRi9rDmLYpLms5ySv93iy0 UNAUTHENTICATED_SRTP UNENCRYPTED_SRTCP +a=rtcp-fb:* trr-int 5000 +a=rtcp-fb:* ccm tmmbr +` + v, err := ParseOfferWith(g, []byte(sdpData)) + require.NoError(t, err) + require.Equal(t, vProfiles, v.CryptoProfiles) + }, + ) } // TestParseOfferLifetimeAndMKI verifies that lifetime and MKI are correctly parsed from an SDP offer