From 792d74e6efb918c455dae2b175daabdba86d9cd3 Mon Sep 17 00:00:00 2001 From: aler9 <46489434+aler9@users.noreply.github.com> Date: Sat, 13 Mar 2021 13:49:21 +0100 Subject: [PATCH] reduce usage of rtsp-simple-server in client tests --- clientconf_test.go | 440 ++++++++++++++++++++----- serverconf_test.go | 66 ++-- testimages/rtsp-simple-server/start.sh | 50 --- 3 files changed, 384 insertions(+), 172 deletions(-) diff --git a/clientconf_test.go b/clientconf_test.go index a9a6a263..40e12023 100644 --- a/clientconf_test.go +++ b/clientconf_test.go @@ -2,6 +2,7 @@ package gortsplib import ( "bufio" + "crypto/tls" "net" "os" "os/exec" @@ -63,7 +64,7 @@ func (c *container) wait() int { return int(code) } -func TestClientDialRead(t *testing.T) { +func TestClientRead(t *testing.T) { for _, ca := range []struct { encrypted bool proto string @@ -81,39 +82,142 @@ func TestClientDialRead(t *testing.T) { t.Run(encryptedStr+"_"+ca.proto, func(t *testing.T) { var scheme string - var port string - var serverConf string - if !ca.encrypted { - scheme = "rtsp" - port = "8554" - serverConf = "{}" - } else { + var l net.Listener + if ca.encrypted { scheme = "rtsps" - port = "8555" - serverConf = "readTimeout: 20s\n" + - "protocols: [tcp]\n" + - "encryption: yes\n" + + li, err := net.Listen("tcp", "localhost:8554") + require.NoError(t, err) + defer li.Close() + + cert, err := tls.X509KeyPair(serverCert, serverKey) + require.NoError(t, err) + + l = tls.NewListener(li, &tls.Config{Certificates: []tls.Certificate{cert}}) + + } else { + scheme = "rtsp" + + var err error + l, err = net.Listen("tcp", "localhost:8554") + require.NoError(t, err) + defer l.Close() } - cnt1, err := newContainer("rtsp-simple-server", "server", []string{serverConf}) - require.NoError(t, err) - defer cnt1.close() + serverDone := make(chan struct{}) + defer func() { <-serverDone }() + go func() { + defer close(serverDone) - time.Sleep(1 * time.Second) + conn, err := l.Accept() + require.NoError(t, err) + defer conn.Close() + bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)) - cnt2, err := newContainer("ffmpeg", "publish", []string{ - "-re", - "-stream_loop", "-1", - "-i", "emptyvideo.ts", - "-c", "copy", - "-f", "rtsp", - "-rtsp_transport", "udp", - scheme + "://localhost:" + port + "/teststream", - }) - require.NoError(t, err) - defer cnt2.close() + var req base.Request + err = req.Read(bconn.Reader) + require.NoError(t, err) + require.Equal(t, base.Options, req.Method) - time.Sleep(1 * time.Second) + err = base.Response{ + StatusCode: base.StatusOK, + Header: base.Header{ + "Public": base.HeaderValue{strings.Join([]string{ + string(base.Describe), + string(base.Setup), + string(base.Play), + }, ", ")}, + }, + }.Write(bconn.Writer) + require.NoError(t, err) + + err = req.Read(bconn.Reader) + require.NoError(t, err) + require.Equal(t, base.Describe, req.Method) + + track, err := NewTrackH264(96, []byte("123456"), []byte("123456")) + require.NoError(t, err) + sdp := Tracks{track}.Write() + + err = base.Response{ + StatusCode: base.StatusOK, + Header: base.Header{ + "Content-Type": base.HeaderValue{"application/sdp"}, + }, + Body: sdp, + }.Write(bconn.Writer) + require.NoError(t, err) + + err = req.Read(bconn.Reader) + require.NoError(t, err) + require.Equal(t, base.Setup, req.Method) + + th, err := headers.ReadTransport(req.Header["Transport"]) + require.NoError(t, err) + + if ca.proto == "udp" { + err = base.Response{ + StatusCode: base.StatusOK, + Header: base.Header{ + "Transport": headers.Transport{ + Protocol: StreamProtocolUDP, + Delivery: func() *base.StreamDelivery { + v := base.StreamDeliveryUnicast + return &v + }(), + ClientPorts: th.ClientPorts, + ServerPorts: &[2]int{34556, 34557}, + }.Write(), + }, + }.Write(bconn.Writer) + require.NoError(t, err) + + } else { + err = base.Response{ + StatusCode: base.StatusOK, + Header: base.Header{ + "Transport": headers.Transport{ + Protocol: StreamProtocolTCP, + Delivery: func() *base.StreamDelivery { + v := base.StreamDeliveryUnicast + return &v + }(), + ClientPorts: th.ClientPorts, + InterleavedIds: &[2]int{0, 1}, + }.Write(), + }, + }.Write(bconn.Writer) + require.NoError(t, err) + } + + err = req.Read(bconn.Reader) + require.NoError(t, err) + require.Equal(t, base.Play, req.Method) + + err = base.Response{ + StatusCode: base.StatusOK, + }.Write(bconn.Writer) + require.NoError(t, err) + + if ca.proto == "udp" { + l1, err := net.ListenPacket("udp", "localhost:34556") + require.NoError(t, err) + defer l1.Close() + + l1.WriteTo([]byte("\x00\x00\x00\x00"), &net.UDPAddr{ + IP: net.ParseIP("127.0.0.1"), + Port: th.ClientPorts[0], + }) + + } else { + err = base.InterleavedFrame{ + TrackID: 0, + StreamType: StreamTypeRTP, + Payload: []byte("\x00\x00\x00\x00"), + }.Write(bconn.Writer) + require.NoError(t, err) + } + }() conf := ClientConf{ StreamProtocol: func() *StreamProtocol { @@ -126,15 +230,12 @@ func TestClientDialRead(t *testing.T) { }(), } - conn, err := conf.DialRead(scheme + "://localhost:" + port + "/teststream") + conn, err := conf.DialRead(scheme + "://localhost:8554/teststream") require.NoError(t, err) - var firstFrame int32 frameRecv := make(chan struct{}) done := conn.ReadFrames(func(id int, typ StreamType, payload []byte) { - if atomic.SwapInt32(&firstFrame, 1) == 0 { - close(frameRecv) - } + close(frameRecv) }) <-frameRecv @@ -149,7 +250,7 @@ func TestClientDialRead(t *testing.T) { } } -func TestClientDialReadNoServerPorts(t *testing.T) { +func TestClientReadNoServerPorts(t *testing.T) { for _, ca := range []string{ "zero", "no", @@ -240,8 +341,6 @@ func TestClientDialReadNoServerPorts(t *testing.T) { }.Write(bconn.Writer) require.NoError(t, err) - time.Sleep(1 * time.Second) - l1, err := net.ListenPacket("udp", "localhost:0") require.NoError(t, err) defer l1.Close() @@ -271,40 +370,108 @@ func TestClientDialReadNoServerPorts(t *testing.T) { } } -func TestClientDialReadAutomaticProtocol(t *testing.T) { - cnt1, err := newContainer("rtsp-simple-server", "server", []string{ - "protocols: [tcp]\n", - }) +func TestClientReadAutomaticProtocol(t *testing.T) { + l, err := net.Listen("tcp", "localhost:8554") require.NoError(t, err) - defer cnt1.close() + defer l.Close() - time.Sleep(1 * time.Second) + serverDone := make(chan struct{}) + defer func() { <-serverDone }() + go func() { + defer close(serverDone) - cnt2, err := newContainer("ffmpeg", "publish", []string{ - "-re", - "-stream_loop", "-1", - "-i", "emptyvideo.ts", - "-c", "copy", - "-f", "rtsp", - "-rtsp_transport", "tcp", - "rtsp://localhost:8554/teststream", - }) - require.NoError(t, err) - defer cnt2.close() + conn, err := l.Accept() + require.NoError(t, err) + defer conn.Close() + bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)) - time.Sleep(1 * time.Second) + var req base.Request + err = req.Read(bconn.Reader) + require.NoError(t, err) + require.Equal(t, base.Options, req.Method) + + err = base.Response{ + StatusCode: base.StatusOK, + Header: base.Header{ + "Public": base.HeaderValue{strings.Join([]string{ + string(base.Describe), + string(base.Setup), + string(base.Play), + }, ", ")}, + }, + }.Write(bconn.Writer) + require.NoError(t, err) + + err = req.Read(bconn.Reader) + require.NoError(t, err) + require.Equal(t, base.Describe, req.Method) + + track, err := NewTrackH264(96, []byte("123456"), []byte("123456")) + require.NoError(t, err) + sdp := Tracks{track}.Write() + + err = base.Response{ + StatusCode: base.StatusOK, + Header: base.Header{ + "Content-Type": base.HeaderValue{"application/sdp"}, + }, + Body: sdp, + }.Write(bconn.Writer) + require.NoError(t, err) + + err = req.Read(bconn.Reader) + require.NoError(t, err) + require.Equal(t, base.Setup, req.Method) + + err = base.Response{ + StatusCode: base.StatusUnsupportedTransport, + }.Write(bconn.Writer) + require.NoError(t, err) + + err = req.Read(bconn.Reader) + require.NoError(t, err) + require.Equal(t, base.Setup, req.Method) + + err = base.Response{ + StatusCode: base.StatusOK, + Header: base.Header{ + "Transport": headers.Transport{ + Protocol: StreamProtocolTCP, + Delivery: func() *base.StreamDelivery { + v := base.StreamDeliveryUnicast + return &v + }(), + InterleavedIds: &[2]int{0, 1}, + }.Write(), + }, + }.Write(bconn.Writer) + require.NoError(t, err) + + err = req.Read(bconn.Reader) + require.NoError(t, err) + require.Equal(t, base.Play, req.Method) + + err = base.Response{ + StatusCode: base.StatusOK, + }.Write(bconn.Writer) + require.NoError(t, err) + + err = base.InterleavedFrame{ + TrackID: 0, + StreamType: StreamTypeRTP, + Payload: []byte("\x00\x00\x00\x00"), + }.Write(bconn.Writer) + require.NoError(t, err) + }() conf := ClientConf{StreamProtocol: nil} conn, err := conf.DialRead("rtsp://localhost:8554/teststream") require.NoError(t, err) - var firstFrame int32 frameRecv := make(chan struct{}) done := conn.ReadFrames(func(id int, typ StreamType, payload []byte) { - if atomic.SwapInt32(&firstFrame, 1) == 0 { - close(frameRecv) - } + close(frameRecv) }) <-frameRecv @@ -312,42 +479,137 @@ func TestClientDialReadAutomaticProtocol(t *testing.T) { <-done } -func TestClientDialReadRedirect(t *testing.T) { - cnt1, err := newContainer("rtsp-simple-server", "server", []string{ - "paths:\n" + - " path1:\n" + - " source: redirect\n" + - " sourceRedirect: rtsp://localhost:8554/path2\n" + - " path2:\n", - }) +func TestClientReadRedirect(t *testing.T) { + l, err := net.Listen("tcp", "localhost:8554") require.NoError(t, err) - defer cnt1.close() + defer l.Close() - time.Sleep(1 * time.Second) + serverDone := make(chan struct{}) + defer func() { <-serverDone }() + go func() { + defer close(serverDone) - cnt2, err := newContainer("ffmpeg", "publish", []string{ - "-re", - "-stream_loop", "-1", - "-i", "emptyvideo.ts", - "-c", "copy", - "-f", "rtsp", - "-rtsp_transport", "udp", - "rtsp://localhost:8554/path2", - }) - require.NoError(t, err) - defer cnt2.close() + conn, err := l.Accept() + require.NoError(t, err) + bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)) - time.Sleep(1 * time.Second) + var req base.Request + err = req.Read(bconn.Reader) + require.NoError(t, err) + require.Equal(t, base.Options, req.Method) + + err = base.Response{ + StatusCode: base.StatusOK, + Header: base.Header{ + "Public": base.HeaderValue{strings.Join([]string{ + string(base.Describe), + string(base.Setup), + string(base.Play), + }, ", ")}, + }, + }.Write(bconn.Writer) + require.NoError(t, err) + + err = req.Read(bconn.Reader) + require.NoError(t, err) + require.Equal(t, base.Describe, req.Method) + + err = base.Response{ + StatusCode: base.StatusMovedPermanently, + Header: base.Header{ + "Location": base.HeaderValue{"rtsp://localhost:8554/test"}, + }, + }.Write(bconn.Writer) + require.NoError(t, err) + + conn.Close() + + conn, err = l.Accept() + require.NoError(t, err) + defer conn.Close() + bconn = bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)) + + err = req.Read(bconn.Reader) + require.NoError(t, err) + require.Equal(t, base.Options, req.Method) + + err = base.Response{ + StatusCode: base.StatusOK, + Header: base.Header{ + "Public": base.HeaderValue{strings.Join([]string{ + string(base.Describe), + string(base.Setup), + string(base.Play), + }, ", ")}, + }, + }.Write(bconn.Writer) + require.NoError(t, err) + + err = req.Read(bconn.Reader) + require.NoError(t, err) + require.Equal(t, base.Describe, req.Method) + + track, err := NewTrackH264(96, []byte("123456"), []byte("123456")) + require.NoError(t, err) + sdp := Tracks{track}.Write() + + err = base.Response{ + StatusCode: base.StatusOK, + Header: base.Header{ + "Content-Type": base.HeaderValue{"application/sdp"}, + }, + Body: sdp, + }.Write(bconn.Writer) + require.NoError(t, err) + + err = req.Read(bconn.Reader) + require.NoError(t, err) + require.Equal(t, base.Setup, req.Method) + + th, err := headers.ReadTransport(req.Header["Transport"]) + require.NoError(t, err) + + err = base.Response{ + StatusCode: base.StatusOK, + Header: base.Header{ + "Transport": headers.Transport{ + Protocol: StreamProtocolUDP, + Delivery: func() *base.StreamDelivery { + v := base.StreamDeliveryUnicast + return &v + }(), + ClientPorts: th.ClientPorts, + ServerPorts: &[2]int{34556, 34557}, + }.Write(), + }, + }.Write(bconn.Writer) + require.NoError(t, err) + + err = req.Read(bconn.Reader) + require.NoError(t, err) + require.Equal(t, base.Play, req.Method) + + err = base.Response{ + StatusCode: base.StatusOK, + }.Write(bconn.Writer) + require.NoError(t, err) + + l1, err := net.ListenPacket("udp", "localhost:34556") + require.NoError(t, err) + defer l1.Close() + + l1.WriteTo([]byte("\x00\x00\x00\x00"), &net.UDPAddr{ + IP: net.ParseIP("127.0.0.1"), + Port: th.ClientPorts[0], + }) + }() conn, err := DialRead("rtsp://localhost:8554/path1") require.NoError(t, err) - var firstFrame int32 frameRecv := make(chan struct{}) done := conn.ReadFrames(func(id int, typ StreamType, payload []byte) { - if atomic.SwapInt32(&firstFrame, 1) == 0 { - close(frameRecv) - } + close(frameRecv) }) <-frameRecv @@ -355,7 +617,7 @@ func TestClientDialReadRedirect(t *testing.T) { <-done } -func TestClientDialReadPause(t *testing.T) { +func TestClientReadPause(t *testing.T) { for _, proto := range []string{ "udp", "tcp", @@ -426,7 +688,7 @@ func TestClientDialReadPause(t *testing.T) { } } -func TestClientDialPublishSerial(t *testing.T) { +func TestClientPublishSerial(t *testing.T) { for _, proto := range []string{ "udp", "tcp", @@ -487,7 +749,7 @@ func TestClientDialPublishSerial(t *testing.T) { } } -func TestClientDialPublishParallel(t *testing.T) { +func TestClientPublishParallel(t *testing.T) { for _, ca := range []struct { proto string server string @@ -600,7 +862,7 @@ func TestClientDialPublishParallel(t *testing.T) { } } -func TestClientDialPublishPauseSerial(t *testing.T) { +func TestClientPublishPauseSerial(t *testing.T) { for _, proto := range []string{ "udp", "tcp", @@ -672,7 +934,7 @@ func TestClientDialPublishPauseSerial(t *testing.T) { } } -func TestClientDialPublishPauseParallel(t *testing.T) { +func TestClientPublishPauseParallel(t *testing.T) { for _, proto := range []string{ "udp", "tcp", diff --git a/serverconf_test.go b/serverconf_test.go index b84cea5f..a1589e91 100644 --- a/serverconf_test.go +++ b/serverconf_test.go @@ -342,6 +342,35 @@ y++U32uuSFiXDcSLarfIsE992MEJLSAynbF1Rsgsr3gXbGiuToJRyxbIeVy7gwzD -----END RSA PRIVATE KEY----- `) +func TestServerTeardownResponse(t *testing.T) { + ts, err := newTestServ(nil) + require.NoError(t, err) + defer ts.close() + + conn, err := net.Dial("tcp", "localhost:8554") + require.NoError(t, err) + defer conn.Close() + bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)) + + err = base.Request{ + Method: base.Teardown, + URL: base.MustParseURL("rtsp://localhost:8554/"), + Header: base.Header{ + "CSeq": base.HeaderValue{"1"}, + }, + }.Write(bconn.Writer) + require.NoError(t, err) + + var res base.Response + err = res.Read(bconn.Reader) + require.NoError(t, err) + require.Equal(t, base.StatusOK, res.StatusCode) + + buf := make([]byte, 2048) + _, err = bconn.Read(buf) + require.Equal(t, io.EOF, err) +} + func TestServerPublishRead(t *testing.T) { for _, ca := range []struct { encrypted bool @@ -447,36 +476,7 @@ func TestServerPublishRead(t *testing.T) { } } -func TestServerTeardownResponse(t *testing.T) { - ts, err := newTestServ(nil) - require.NoError(t, err) - defer ts.close() - - conn, err := net.Dial("tcp", "localhost:8554") - require.NoError(t, err) - defer conn.Close() - bconn := bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)) - - err = base.Request{ - Method: base.Teardown, - URL: base.MustParseURL("rtsp://localhost:8554/"), - Header: base.Header{ - "CSeq": base.HeaderValue{"1"}, - }, - }.Write(bconn.Writer) - require.NoError(t, err) - - var res base.Response - err = res.Read(bconn.Reader) - require.NoError(t, err) - require.Equal(t, base.StatusOK, res.StatusCode) - - buf := make([]byte, 2048) - _, err = bconn.Read(buf) - require.Equal(t, io.EOF, err) -} - -func TestServerSetupWithoutTrackID(t *testing.T) { +func TestServerReadWithoutSetupTrackID(t *testing.T) { ts, err := newTestServ(nil) require.NoError(t, err) defer ts.close() @@ -545,7 +545,7 @@ func TestServerSetupWithoutTrackID(t *testing.T) { require.NoError(t, err) } -func TestServerResponseBeforeFrames(t *testing.T) { +func TestServerReadResponseBeforeFrames(t *testing.T) { ts, err := newTestServ(nil) require.NoError(t, err) defer ts.close() @@ -614,7 +614,7 @@ func TestServerResponseBeforeFrames(t *testing.T) { require.NoError(t, err) } -func TestServerPlayMultiple(t *testing.T) { +func TestServerReadPlayMultiple(t *testing.T) { ts, err := newTestServ(nil) require.NoError(t, err) defer ts.close() @@ -692,7 +692,7 @@ func TestServerPlayMultiple(t *testing.T) { require.Equal(t, base.StatusOK, res.StatusCode) } -func TestServerPauseMultiple(t *testing.T) { +func TestServerReadPauseMultiple(t *testing.T) { ts, err := newTestServ(nil) require.NoError(t, err) defer ts.close() diff --git a/testimages/rtsp-simple-server/start.sh b/testimages/rtsp-simple-server/start.sh index 295b2feb..9a93b80c 100644 --- a/testimages/rtsp-simple-server/start.sh +++ b/testimages/rtsp-simple-server/start.sh @@ -2,54 +2,4 @@ echo "$@" > /rtsp-simple-server.yml -echo "-----BEGIN CERTIFICATE----- -MIIDazCCAlOgAwIBAgIUXw1hEC3LFpTsllv7D3ARJyEq7sIwDQYJKoZIhvcNAQEL -BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM -GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDEyMTMxNzQ0NThaFw0zMDEy -MTExNzQ0NThaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw -HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB -AQUAA4IBDwAwggEKAoIBAQDG8DyyS51810GsGwgWr5rjJK7OE1kTTLSNEEKax8Bj -zOyiaz8rA2JGl2VUEpi2UjDr9Cm7nd+YIEVs91IIBOb7LGqObBh1kGF3u5aZxLkv -NJE+HrLVvUhaDobK2NU+Wibqc/EI3DfUkt1rSINvv9flwTFu1qHeuLWhoySzDKEp -OzYxpFhwjVSokZIjT4Red3OtFz7gl2E6OAWe2qoh5CwLYVdMWtKR0Xuw3BkDPk9I -qkQKx3fqv97LPEzhyZYjDT5WvGrgZ1WDAN3booxXF3oA1H3GHQc4m/vcLatOtb8e -nI59gMQLEbnp08cl873bAuNuM95EZieXTHNbwUnq5iybAgMBAAGjUzBRMB0GA1Ud -DgQWBBQBKhJh8eWu0a4au9X/2fKhkFX2vjAfBgNVHSMEGDAWgBQBKhJh8eWu0a4a -u9X/2fKhkFX2vjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBj -3aCW0YPKukYgVK9cwN0IbVy/D0C1UPT4nupJcy/E0iC7MXPZ9D/SZxYQoAkdptdO -xfI+RXkpQZLdODNx9uvV+cHyZHZyjtE5ENu/i5Rer2cWI/mSLZm5lUQyx+0KZ2Yu -tEI1bsebDK30msa8QSTn0WidW9XhFnl3gRi4wRdimcQapOWYVs7ih+nAlSvng7NI -XpAyRs8PIEbpDDBMWnldrX4TP6EWYUi49gCp8OUDRREKX3l6Ls1vZ02F34yHIt/7 -7IV/XSKG096bhW+icKBWV0IpcEsgTzPK1J1hMxgjhzIMxGboAeUU+kidthOob6Sd -XQxaORfgM//NzX9LhUPk ------END CERTIFICATE-----" > /server.crt - -echo "-----BEGIN RSA PRIVATE KEY----- -MIIEogIBAAKCAQEAxvA8skudfNdBrBsIFq+a4ySuzhNZE0y0jRBCmsfAY8zsoms/ -KwNiRpdlVBKYtlIw6/Qpu53fmCBFbPdSCATm+yxqjmwYdZBhd7uWmcS5LzSRPh6y -1b1IWg6GytjVPlom6nPxCNw31JLda0iDb7/X5cExbtah3ri1oaMkswyhKTs2MaRY -cI1UqJGSI0+EXndzrRc+4JdhOjgFntqqIeQsC2FXTFrSkdF7sNwZAz5PSKpECsd3 -6r/eyzxM4cmWIw0+Vrxq4GdVgwDd26KMVxd6ANR9xh0HOJv73C2rTrW/HpyOfYDE -CxG56dPHJfO92wLjbjPeRGYnl0xzW8FJ6uYsmwIDAQABAoIBACi0BKcyQ3HElSJC -kaAao+Uvnzh4yvPg8Nwf5JDIp/uDdTMyIEWLtrLczRWrjGVZYbsVROinP5VfnPTT -kYwkfKINj2u+gC6lsNuPnRuvHXikF8eO/mYvCTur1zZvsQnF5kp4GGwIqr+qoPUP -bB0UMndG1PdpoMryHe+JcrvTrLHDmCeH10TqOwMsQMLHYLkowvxwJWsmTY7/Qr5S -Wm3PPpOcW2i0uyPVuyuv4yD1368fqnqJ8QFsQp1K6QtYsNnJ71Hut1/IoxK/e6hj -5Z+byKtHVtmcLnABuoOT7BhleJNFBksX9sh83jid4tMBgci+zXNeGmgqo2EmaWAb -agQslkECgYEA8B1rzjOHVQx/vwSzDa4XOrpoHQRfyElrGNz9JVBvnoC7AorezBXQ -M9WTHQIFTGMjzD8pb+YJGi3gj93VN51r0SmJRxBaBRh1ZZI9kFiFzngYev8POgD3 -ygmlS3kTHCNxCK/CJkB+/jMBgtPj5ygDpCWVcTSuWlQFphePkW7jaaECgYEA1Blz -ulqgAyJHZaqgcbcCsI2q6m527hVr9pjzNjIVmkwu38yS9RTCgdlbEVVDnS0hoifl -+jVMEGXjF3xjyMvL50BKbQUH+KAa+V4n1WGlnZOxX9TMny8MBjEuSX2+362vQ3BX -4vOlX00gvoc+sY+lrzvfx/OdPCHQGVYzoKCxhLsCgYA07HcviuIAV/HsO2/vyvhp -xF5gTu+BqNUHNOZDDDid+ge+Jre2yfQLCL8VPLXIQW3Jff53IH/PGl+NtjphuLvj -7UDJvgvpZZuymIojP6+2c3gJ3CASC9aR3JBnUzdoE1O9s2eaoMqc4scpe+SWtZYf -3vzSZ+cqF6zrD/Rf/M35IQKBgHTU4E6ShPm09CcoaeC5sp2WK8OevZw/6IyZi78a -r5Oiy18zzO97U/k6xVMy6F+38ILl/2Rn31JZDVJujniY6eSkIVsUHmPxrWoXV1HO -y++U32uuSFiXDcSLarfIsE992MEJLSAynbF1Rsgsr3gXbGiuToJRyxbIeVy7gwzD -94TpAoGAY4/PejWQj9psZfAhyk5dRGra++gYRQ/gK1IIc1g+Dd2/BxbT/RHr05GK -6vwrfjsoRyMWteC1SsNs/CurjfQ/jqCfHNP5XPvxgd5Ec8sRJIiV7V5RTuWJsPu1 -+3K6cnKEyg+0ekYmLertRFIY6SwWmY1fyKgTvxudMcsBY7dC4xs= ------END RSA PRIVATE KEY-----" > /server.key - exec /rtsp-simple-server