diff --git a/examples/server-tls/main.go b/examples/server-tls/main.go index 8b2cf3e6..5271bbd7 100644 --- a/examples/server-tls/main.go +++ b/examples/server-tls/main.go @@ -93,12 +93,12 @@ func (sh *serverHandler) OnAnnounce(ctx *gortsplib.ServerHandlerOnAnnounceCtx) ( } // called after receiving a SETUP request. -func (sh *serverHandler) OnSetup(ctx *gortsplib.ServerHandlerOnSetupCtx) (*base.Response, error) { +func (sh *serverHandler) OnSetup(ctx *gortsplib.ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { log.Printf("setup request") return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil } // called after receiving a PLAY request. diff --git a/examples/server/main.go b/examples/server/main.go index b14b03cd..e5990101 100644 --- a/examples/server/main.go +++ b/examples/server/main.go @@ -92,12 +92,12 @@ func (sh *serverHandler) OnAnnounce(ctx *gortsplib.ServerHandlerOnAnnounceCtx) ( } // called after receiving a SETUP request. -func (sh *serverHandler) OnSetup(ctx *gortsplib.ServerHandlerOnSetupCtx) (*base.Response, error) { +func (sh *serverHandler) OnSetup(ctx *gortsplib.ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { log.Printf("setup request") return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil } // called after receiving a PLAY request. diff --git a/server_publish_test.go b/server_publish_test.go index 8d53bd04..b7178740 100644 --- a/server_publish_test.go +++ b/server_publish_test.go @@ -301,12 +301,12 @@ func TestServerPublishSetupPath(t *testing.T) { StatusCode: base.StatusOK, }, nil }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { require.Equal(t, ca.path, ctx.Path) require.Equal(t, ca.trackID, ctx.TrackID) return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, }, } @@ -398,10 +398,10 @@ func TestServerPublishErrorSetupDifferentPaths(t *testing.T) { StatusCode: base.StatusOK, }, nil }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, }, } @@ -480,10 +480,10 @@ func TestServerPublishErrorSetupTrackTwice(t *testing.T) { StatusCode: base.StatusOK, }, nil }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, }, } @@ -574,10 +574,10 @@ func TestServerPublishErrorRecordPartialTracks(t *testing.T) { StatusCode: base.StatusOK, }, nil }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, onRecord: func(ctx *ServerHandlerOnRecordCtx) (*base.Response, error) { return &base.Response{ @@ -694,10 +694,10 @@ func TestServerPublish(t *testing.T) { StatusCode: base.StatusOK, }, nil }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, onRecord: func(ctx *ServerHandlerOnRecordCtx) (*base.Response, error) { return &base.Response{ @@ -912,10 +912,10 @@ func TestServerPublishErrorWrongProtocol(t *testing.T) { StatusCode: base.StatusOK, }, nil }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, onRecord: func(ctx *ServerHandlerOnRecordCtx) (*base.Response, error) { return &base.Response{ @@ -1018,10 +1018,10 @@ func TestServerPublishRTCPReport(t *testing.T) { StatusCode: base.StatusOK, }, nil }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, onRecord: func(ctx *ServerHandlerOnRecordCtx) (*base.Response, error) { return &base.Response{ @@ -1174,10 +1174,10 @@ func TestServerPublishTimeout(t *testing.T) { StatusCode: base.StatusOK, }, nil }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, onRecord: func(ctx *ServerHandlerOnRecordCtx) (*base.Response, error) { return &base.Response{ @@ -1302,10 +1302,10 @@ func TestServerPublishWithoutTeardown(t *testing.T) { StatusCode: base.StatusOK, }, nil }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, onRecord: func(ctx *ServerHandlerOnRecordCtx) (*base.Response, error) { return &base.Response{ @@ -1414,10 +1414,10 @@ func TestServerPublishUDPChangeConn(t *testing.T) { StatusCode: base.StatusOK, }, nil }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, onRecord: func(ctx *ServerHandlerOnRecordCtx) (*base.Response, error) { return &base.Response{ diff --git a/server_read_test.go b/server_read_test.go index 1681f8a2..be626024 100644 --- a/server_read_test.go +++ b/server_read_test.go @@ -61,12 +61,12 @@ func TestServerReadSetupPath(t *testing.T) { t.Run(ca.name, func(t *testing.T) { s := &Server{ Handler: &testServerHandler{ - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { require.Equal(t, ca.path, ctx.Path) require.Equal(t, ca.trackID, ctx.TrackID) return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, }, } @@ -116,10 +116,10 @@ func TestServerReadErrorSetupDifferentPaths(t *testing.T) { require.Equal(t, "can't setup tracks with different paths", ctx.Error.Error()) close(connClosed) }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, }, } @@ -183,10 +183,10 @@ func TestServerReadErrorSetupTrackTwice(t *testing.T) { require.Equal(t, "track 0 has already been setup", ctx.Error.Error()) close(connClosed) }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, }, } @@ -268,10 +268,11 @@ func TestServerRead(t *testing.T) { onSessionClose: func(ctx *ServerHandlerOnSessionCloseCtx) { close(sessionClosed) }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { + v := uint32(123456) return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, &v, nil }, onPlay: func(ctx *ServerHandlerOnPlayCtx) (*base.Response, error) { ctx.Session.WriteFrame(0, StreamTypeRTP, []byte{0x01, 0x02, 0x03, 0x04}) @@ -356,6 +357,7 @@ func TestServerRead(t *testing.T) { var th headers.Transport err = th.Read(res.Header["Transport"]) require.NoError(t, err) + require.Equal(t, uint32(123456), *th.SSRC) <-sessionOpened @@ -483,10 +485,10 @@ func TestServerReadTCPResponseBeforeFrames(t *testing.T) { close(writerTerminate) <-writerDone }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, onPlay: func(ctx *ServerHandlerOnPlayCtx) (*base.Response, error) { go func() { @@ -567,10 +569,10 @@ func TestServerReadTCPResponseBeforeFrames(t *testing.T) { func TestServerReadPlayPlay(t *testing.T) { s := &Server{ Handler: &testServerHandler{ - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, onPlay: func(ctx *ServerHandlerOnPlayCtx) (*base.Response, error) { return &base.Response{ @@ -647,10 +649,10 @@ func TestServerReadPlayPausePlay(t *testing.T) { close(writerTerminate) <-writerDone }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, onPlay: func(ctx *ServerHandlerOnPlayCtx) (*base.Response, error) { if !writerStarted { @@ -759,10 +761,10 @@ func TestServerReadPlayPausePause(t *testing.T) { close(writerTerminate) <-writerDone }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, onPlay: func(ctx *ServerHandlerOnPlayCtx) (*base.Response, error) { go func() { @@ -882,10 +884,10 @@ func TestServerReadTimeout(t *testing.T) { StatusCode: base.StatusOK, }, nil }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, onPlay: func(ctx *ServerHandlerOnPlayCtx) (*base.Response, error) { return &base.Response{ @@ -972,10 +974,10 @@ func TestServerReadWithoutTeardown(t *testing.T) { StatusCode: base.StatusOK, }, nil }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, onPlay: func(ctx *ServerHandlerOnPlayCtx) (*base.Response, error) { return &base.Response{ @@ -1053,10 +1055,10 @@ func TestServerReadWithoutTeardown(t *testing.T) { func TestServerReadUDPChangeConn(t *testing.T) { s := &Server{ Handler: &testServerHandler{ - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, onPlay: func(ctx *ServerHandlerOnPlayCtx) (*base.Response, error) { return &base.Response{ diff --git a/server_test.go b/server_test.go index d1ce5305..8c02c5df 100644 --- a/server_test.go +++ b/server_test.go @@ -44,7 +44,7 @@ type testServerHandler struct { onSessionClose func(*ServerHandlerOnSessionCloseCtx) onDescribe func(*ServerHandlerOnDescribeCtx) (*base.Response, []byte, error) onAnnounce func(*ServerHandlerOnAnnounceCtx) (*base.Response, error) - onSetup func(*ServerHandlerOnSetupCtx) (*base.Response, error) + onSetup func(*ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) onPlay func(*ServerHandlerOnPlayCtx) (*base.Response, error) onRecord func(*ServerHandlerOnRecordCtx) (*base.Response, error) onPause func(*ServerHandlerOnPauseCtx) (*base.Response, error) @@ -91,11 +91,11 @@ func (sh *testServerHandler) OnAnnounce(ctx *ServerHandlerOnAnnounceCtx) (*base. return nil, fmt.Errorf("unimplemented") } -func (sh *testServerHandler) OnSetup(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { +func (sh *testServerHandler) OnSetup(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { if sh.onSetup != nil { return sh.onSetup(ctx) } - return nil, fmt.Errorf("unimplemented") + return nil, nil, fmt.Errorf("unimplemented") } func (sh *testServerHandler) OnPlay(ctx *ServerHandlerOnPlayCtx) (*base.Response, error) { @@ -327,11 +327,11 @@ func TestServerHighLevelPublishRead(t *testing.T) { }, }, nil }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { if ctx.Path != "teststream" { return &base.Response{ StatusCode: base.StatusBadRequest, - }, fmt.Errorf("invalid path (%s)", ctx.Req.URL) + }, nil, fmt.Errorf("invalid path (%s)", ctx.Req.URL) } return &base.Response{ @@ -339,7 +339,7 @@ func TestServerHighLevelPublishRead(t *testing.T) { Header: base.Header{ "Session": base.HeaderValue{"12345678"}, }, - }, nil + }, nil, nil }, onPlay: func(ctx *ServerHandlerOnPlayCtx) (*base.Response, error) { if ctx.Path != "teststream" { @@ -620,10 +620,10 @@ func TestServerErrorInvalidMethod(t *testing.T) { func TestServerErrorTCPTwoConnOneSession(t *testing.T) { s := &Server{ Handler: &testServerHandler{ - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, onPlay: func(ctx *ServerHandlerOnPlayCtx) (*base.Response, error) { return &base.Response{ @@ -712,10 +712,10 @@ func TestServerErrorTCPTwoConnOneSession(t *testing.T) { func TestServerErrorTCPOneConnTwoSessions(t *testing.T) { s := &Server{ Handler: &testServerHandler{ - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, onPlay: func(ctx *ServerHandlerOnPlayCtx) (*base.Response, error) { return &base.Response{ @@ -920,10 +920,10 @@ func TestServerSessionClose(t *testing.T) { onSessionClose: func(ctx *ServerHandlerOnSessionCloseCtx) { close(sessionClosed) }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, }, } @@ -969,10 +969,10 @@ func TestServerSessionAutoClose(t *testing.T) { onSessionClose: func(ctx *ServerHandlerOnSessionCloseCtx) { close(sessionClosed) }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, }, } @@ -1036,10 +1036,10 @@ func TestServerErrorInvalidPath(t *testing.T) { StatusCode: base.StatusOK, }, nil }, - onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, error) { + onSetup: func(ctx *ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) { return &base.Response{ StatusCode: base.StatusOK, - }, nil + }, nil, nil }, onPlay: func(ctx *ServerHandlerOnPlayCtx) (*base.Response, error) { return &base.Response{ diff --git a/serverhandler.go b/serverhandler.go index 2825cc0b..473d8355 100644 --- a/serverhandler.go +++ b/serverhandler.go @@ -103,7 +103,9 @@ type ServerHandlerOnSetupCtx struct { // ServerHandlerOnSetup can be implemented by a ServerHandler. type ServerHandlerOnSetup interface { - OnSetup(*ServerHandlerOnSetupCtx) (*base.Response, error) + // returns a Response and an optional SSRC that is + // inserted into the Transport header. + OnSetup(*ServerHandlerOnSetupCtx) (*base.Response, *uint32, error) } // ServerHandlerOnPlayCtx is the context of a PLAY request. diff --git a/serversession.go b/serversession.go index 9f47a61e..6eeb506f 100644 --- a/serversession.go +++ b/serversession.go @@ -503,21 +503,21 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base }, err } - var th headers.Transport - err = th.Read(req.Header["Transport"]) + var inTH headers.Transport + err = inTH.Read(req.Header["Transport"]) if err != nil { return &base.Response{ StatusCode: base.StatusBadRequest, }, liberrors.ErrServerTransportHeaderInvalid{Err: err} } - if th.Delivery != nil && *th.Delivery == base.StreamDeliveryMulticast { + if inTH.Delivery != nil && *inTH.Delivery == base.StreamDeliveryMulticast { return &base.Response{ StatusCode: base.StatusUnsupportedTransport, }, nil } - trackID, path, query, err := setupGetTrackIDPathQuery(req.URL, th.Mode, + trackID, path, query, err := setupGetTrackIDPathQuery(req.URL, inTH.Mode, ss.announcedTracks, ss.setupPath, ss.setupQuery) if err != nil { return &base.Response{ @@ -533,67 +533,67 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base switch ss.state { case ServerSessionStateInitial, ServerSessionStatePrePlay: // play - if th.Mode != nil && *th.Mode != headers.TransportModePlay { + if inTH.Mode != nil && *inTH.Mode != headers.TransportModePlay { return &base.Response{ StatusCode: base.StatusBadRequest, - }, liberrors.ErrServerTransportHeaderWrongMode{Mode: th.Mode} + }, liberrors.ErrServerTransportHeaderWrongMode{Mode: inTH.Mode} } default: // record - if th.Mode == nil || *th.Mode != headers.TransportModeRecord { + if inTH.Mode == nil || *inTH.Mode != headers.TransportModeRecord { return &base.Response{ StatusCode: base.StatusBadRequest, - }, liberrors.ErrServerTransportHeaderWrongMode{Mode: th.Mode} + }, liberrors.ErrServerTransportHeaderWrongMode{Mode: inTH.Mode} } } - if th.Protocol == StreamProtocolUDP { + if inTH.Protocol == StreamProtocolUDP { if ss.s.udpRTPListener == nil { return &base.Response{ StatusCode: base.StatusUnsupportedTransport, }, nil } - if th.ClientPorts == nil { + if inTH.ClientPorts == nil { return &base.Response{ StatusCode: base.StatusBadRequest, }, liberrors.ErrServerTransportHeaderNoClientPorts{} } } else { - if th.InterleavedIDs == nil { + if inTH.InterleavedIDs == nil { return &base.Response{ StatusCode: base.StatusBadRequest, }, liberrors.ErrServerTransportHeaderNoInterleavedIDs{} } - if th.InterleavedIDs[0] != (trackID*2) || - th.InterleavedIDs[1] != (1+trackID*2) { + if inTH.InterleavedIDs[0] != (trackID*2) || + inTH.InterleavedIDs[1] != (1+trackID*2) { return &base.Response{ StatusCode: base.StatusBadRequest, }, liberrors.ErrServerTransportHeaderWrongInterleavedIDs{ - Expected: [2]int{(trackID * 2), (1 + trackID*2)}, Value: *th.InterleavedIDs} + Expected: [2]int{(trackID * 2), (1 + trackID*2)}, Value: *inTH.InterleavedIDs} } } - if ss.setupProtocol != nil && *ss.setupProtocol != th.Protocol { + if ss.setupProtocol != nil && *ss.setupProtocol != inTH.Protocol { return &base.Response{ StatusCode: base.StatusBadRequest, }, liberrors.ErrServerTracksDifferentProtocols{} } - res, err := ss.s.Handler.(ServerHandlerOnSetup).OnSetup(&ServerHandlerOnSetupCtx{ + res, ssrc, err := ss.s.Handler.(ServerHandlerOnSetup).OnSetup(&ServerHandlerOnSetupCtx{ Session: ss, Conn: sc, Req: req, Path: path, Query: query, TrackID: trackID, - Transport: &th, + Transport: &inTH, }) if res.StatusCode == base.StatusOK { - ss.setupProtocol = &th.Protocol + ss.setupProtocol = &inTH.Protocol if ss.setuppedTracks == nil { ss.setuppedTracks = make(map[int]ServerSessionSetuppedTrack) @@ -603,30 +603,35 @@ func (ss *ServerSession) handleRequest(sc *ServerConn, req *base.Request) (*base res.Header = make(base.Header) } - if th.Protocol == StreamProtocolUDP { + th := headers.Transport{ + Delivery: func() *base.StreamDelivery { + v := base.StreamDeliveryUnicast + return &v + }(), + } + + if inTH.Protocol == StreamProtocolUDP { ss.setuppedTracks[trackID] = ServerSessionSetuppedTrack{ - udpRTPPort: th.ClientPorts[0], - udpRTCPPort: th.ClientPorts[1], + udpRTPPort: inTH.ClientPorts[0], + udpRTCPPort: inTH.ClientPorts[1], } - res.Header["Transport"] = headers.Transport{ - Protocol: StreamProtocolUDP, - Delivery: func() *base.StreamDelivery { - v := base.StreamDeliveryUnicast - return &v - }(), - ClientPorts: th.ClientPorts, - ServerPorts: &[2]int{sc.s.udpRTPListener.port(), sc.s.udpRTCPListener.port()}, - }.Write() + th.Protocol = StreamProtocolUDP + th.ClientPorts = inTH.ClientPorts + th.ServerPorts = &[2]int{sc.s.udpRTPListener.port(), sc.s.udpRTCPListener.port()} } else { ss.setuppedTracks[trackID] = ServerSessionSetuppedTrack{} - res.Header["Transport"] = headers.Transport{ - Protocol: StreamProtocolTCP, - InterleavedIDs: th.InterleavedIDs, - }.Write() + th.Protocol = StreamProtocolTCP + th.InterleavedIDs = inTH.InterleavedIDs } + + if ssrc != nil { + th.SSRC = ssrc + } + + res.Header["Transport"] = th.Write() } if ss.state == ServerSessionStateInitial {