1010using System . IO ;
1111using System . Linq ;
1212using System . Net ;
13+ using System . Net . Security ;
1314using System . Text ;
1415
1516namespace SharpRTSPClient
@@ -42,7 +43,7 @@ public class RTSPClient : IDisposable
4243 public event EventHandler < NewStreamEventArgs > NewAudioStream ;
4344 public event EventHandler < SimpleDataEventArgs > ReceivedVideoData ;
4445 public event EventHandler < SimpleDataEventArgs > ReceivedAudioData ;
45- public event EventHandler < EventArgs > AuthenticationFailed ;
46+ public event EventHandler < EventArgs > Stopped ;
4647
4748 public bool ProcessRTCP { get ; set ; } = true ; // answer RTCP
4849 public event EventHandler < RawRtcpDataEventArgs > ReceivedRawVideoRTCP ;
@@ -66,13 +67,13 @@ private enum RtspStatus { WaitingToConnect, Connecting, ConnectFailed, Connected
6667 private IRtpTransport _videoRtpTransport ;
6768 private IRtpTransport _audioRtpTransport ;
6869
69- private Uri _uri ; // RTSP URI (username & password will be stripped out)
70+ private Uri _uri = null ; // RTSP URI (username & password will be stripped out)
7071 private string _session = "" ; // RTSP Session
7172 private Authentication _authentication ;
7273 private NetworkCredential _credentials = new NetworkCredential ( ) ;
73- private bool _clientWantsVideo = false ; // Client wants to receive Video
74- private bool _clientWantsAudio = false ; // Client wants to receive Audio
75-
74+ private MediaRequest _mediaRequest = MediaRequest . VIDEO_AND_AUDIO ;
75+ private RemoteCertificateValidationCallback _userCertificateSelectionCallback = null ;
76+ private bool _autoReconnect = false ;
7677 private Uri _videoUri = null ; // URI used for the Video Track
7778 private int _videoPayload = - 1 ; // Payload Type for the Video. (often 96 which is the first dynamic payload value. Bosch use 35)
7879
@@ -150,8 +151,19 @@ public RTSPClient(ILoggerFactory loggerFactory)
150151 /// <param name="playbackSession">Playback session.</param>
151152 /// <param name="userCertificateSelectionCallback">Callback for user certificate selection.</param>
152153 /// <param name="autoReconnect">Automatically try to reconnect after losing the connection.</param>
153- public void Connect ( string url , RTPTransport rtpTransport , string username = null , string password = null , MediaRequest mediaRequest = MediaRequest . VIDEO_AND_AUDIO , bool playbackSession = false , System . Net . Security . RemoteCertificateValidationCallback userCertificateSelectionCallback = null , bool autoReconnect = false )
154+ public void Connect (
155+ string url ,
156+ RTPTransport rtpTransport ,
157+ string username = null ,
158+ string password = null ,
159+ MediaRequest mediaRequest = MediaRequest . VIDEO_AND_AUDIO ,
160+ bool playbackSession = false ,
161+ RemoteCertificateValidationCallback userCertificateSelectionCallback = null ,
162+ bool autoReconnect = false )
154163 {
164+ if ( string . IsNullOrEmpty ( url ) )
165+ throw new ArgumentNullException ( nameof ( url ) ) ;
166+
155167 Connect ( new Uri ( url ) , rtpTransport , username , password , mediaRequest , playbackSession , userCertificateSelectionCallback , autoReconnect ) ;
156168 }
157169
@@ -166,40 +178,74 @@ public void Connect(string url, RTPTransport rtpTransport, string username = nul
166178 /// <param name="playbackSession">Playback session.</param>
167179 /// <param name="userCertificateSelectionCallback">Callback for user certificate selection.</param>
168180 /// <param name="autoReconnect">Automatically try to reconnect after losing the connection.</param>
169- public void Connect ( Uri uri , RTPTransport rtpTransport , string username = null , string password = null , MediaRequest mediaRequest = MediaRequest . VIDEO_AND_AUDIO , bool playbackSession = false , System . Net . Security . RemoteCertificateValidationCallback userCertificateSelectionCallback = null , bool autoReconnect = false )
181+ public void Connect (
182+ Uri uri ,
183+ RTPTransport rtpTransport ,
184+ string username = null ,
185+ string password = null ,
186+ MediaRequest mediaRequest = MediaRequest . VIDEO_AND_AUDIO ,
187+ bool playbackSession = false ,
188+ RemoteCertificateValidationCallback userCertificateSelectionCallback = null ,
189+ bool autoReconnect = false )
170190 {
171- _logger . LogDebug ( "Connecting to {url} " , uri ) ;
172-
173- _uri = uri ;
174-
175- _playbackSession = playbackSession ;
191+ if ( uri == null )
192+ throw new ArgumentNullException ( nameof ( uri ) ) ;
176193
177194 // Use URI to extract username and password and to make a new URL without the username and password
178- var hostname = _uri . Host ;
179- var port = _uri . Port ;
180- try
195+ var hostname = uri . Host ;
196+ var port = uri . Port ;
197+ NetworkCredential credentials = null ;
198+
199+ if ( uri . UserInfo . Length > 0 )
181200 {
182- if ( _uri . UserInfo . Length > 0 )
183- {
184- _credentials = new NetworkCredential ( _uri . UserInfo . Split ( ':' ) [ 0 ] , _uri . UserInfo . Split ( ':' ) [ 1 ] ) ;
185- _uri = new Uri ( _uri . GetComponents ( UriComponents . AbsoluteUri & ~ UriComponents . UserInfo , UriFormat . UriEscaped ) ) ;
186- }
187- else
188- {
189- _credentials = new NetworkCredential ( username , password ) ;
190- }
201+ credentials = new NetworkCredential ( uri . UserInfo . Split ( ':' ) [ 0 ] , uri . UserInfo . Split ( ':' ) [ 1 ] ) ;
202+ uri = new Uri ( uri . GetComponents ( UriComponents . AbsoluteUri & ~ UriComponents . UserInfo , UriFormat . UriEscaped ) ) ;
191203 }
192- catch
204+ else
193205 {
194- _credentials = new NetworkCredential ( ) ;
206+ credentials = new NetworkCredential ( username , password ) ;
195207 }
196208
209+ Connect ( uri , rtpTransport , credentials , mediaRequest , playbackSession , userCertificateSelectionCallback , autoReconnect ) ;
210+ }
211+
212+ /// <summary>
213+ /// Connects to the specified RTSP server.
214+ /// </summary>
215+ /// <param name="uri">The URI of the RTSP server.</param>
216+ /// <param name="rtpTransport">Type of the RTP transport <see cref="RTPTransport"/>.</param>
217+ /// <param name="credentials">Network credentials.</param>
218+ /// <param name="mediaRequest">Media request type <see cref="MediaRequest>."/></param>
219+ /// <param name="playbackSession">Playback session.</param>
220+ /// <param name="userCertificateSelectionCallback">Callback for user certificate selection.</param>
221+ /// <param name="autoReconnect">Automatically try to reconnect after losing the connection.</param>
222+ public void Connect (
223+ Uri uri ,
224+ RTPTransport rtpTransport ,
225+ NetworkCredential credentials = null ,
226+ MediaRequest mediaRequest = MediaRequest . VIDEO_AND_AUDIO ,
227+ bool playbackSession = false ,
228+ RemoteCertificateValidationCallback userCertificateSelectionCallback = null ,
229+ bool autoReconnect = false )
230+ {
231+ _logger . LogDebug ( "Connecting to {url} " , uri ) ;
232+
233+ this . _uri = uri ;
234+ // Check the RTP Transport
235+ // If the RTP transport is TCP then we interleave the RTP packets in the RTSP stream
236+ // If the RTP transport is UDP, we initialise two UDP sockets (one for video, one for RTCP status messages)
237+ // If the RTP transport is MULTICAST, we have to wait for the SETUP message to get the Multicast Address from the RTSP server
238+ this . _rtpTransport = rtpTransport ;
239+ this . _credentials = credentials ?? new NetworkCredential ( ) ;
197240 // We can ask the RTSP server for Video, Audio or both. If we don't want audio we don't need to SETUP the audio channel or receive it
198- _clientWantsVideo = ( mediaRequest is MediaRequest . VIDEO_ONLY || mediaRequest is MediaRequest . VIDEO_AND_AUDIO ) ;
199- _clientWantsAudio = ( mediaRequest is MediaRequest . AUDIO_ONLY || mediaRequest is MediaRequest . VIDEO_AND_AUDIO ) ;
241+ this . _mediaRequest = mediaRequest ;
242+ this . _playbackSession = playbackSession ;
243+ this . _userCertificateSelectionCallback = userCertificateSelectionCallback ;
244+ this . _autoReconnect = autoReconnect ;
200245
201246 // Connect to a RTSP Server. The RTSP session is a TCP connection
202247 _rtspSocketStatus = RtspStatus . Connecting ;
248+
203249 try
204250 {
205251 switch ( _uri . Scheme )
@@ -213,7 +259,7 @@ public void Connect(Uri uri, RTPTransport rtpTransport, string username = null,
213259
214260 default :
215261 {
216- _rtspSocket = Rtsp . RtspUtils . CreateRtspTransportFromUrl ( _uri , userCertificateSelectionCallback ) ;
262+ _rtspSocket = Rtsp . RtspUtils . CreateRtspTransportFromUrl ( _uri , _userCertificateSelectionCallback ) ;
217263 }
218264 break ;
219265 }
@@ -237,22 +283,16 @@ public void Connect(Uri uri, RTPTransport rtpTransport, string username = null,
237283 // Connect a RTSP Listener to the RTSP Socket (or other Stream) to send RTSP messages and listen for RTSP replies
238284 _rtspClient = new RtspListener ( _rtspSocket , _loggerFactory . CreateLogger < RtspListener > ( ) )
239285 {
240- AutoReconnect = autoReconnect
286+ AutoReconnect = _autoReconnect
241287 } ;
242288
243289 _rtspClient . MessageReceived += RtspMessageReceived ;
244290 _rtspClient . Start ( ) ; // start listening for messages from the server (messages fire the MessageReceived event)
245291
246- // Check the RTP Transport
247- // If the RTP transport is TCP then we interleave the RTP packets in the RTSP stream
248- // If the RTP transport is UDP, we initialise two UDP sockets (one for video, one for RTCP status messages)
249- // If the RTP transport is MULTICAST, we have to wait for the SETUP message to get the Multicast Address from the RTSP server
250- this . _rtpTransport = rtpTransport ;
251-
252292 if ( rtpTransport == RTPTransport . UDP )
253293 {
254294 // give a range of 500 pairs (1000 addresses) to try incase some address are in use
255- _videoRtpTransport = new UDPSocket ( 50000 , 51000 ) ;
295+ _videoRtpTransport = new UDPSocket ( 50000 , 51000 ) ;
256296 _audioRtpTransport = new UDPSocket ( 50000 , 51000 ) ;
257297 }
258298
@@ -288,6 +328,18 @@ public void Connect(Uri uri, RTPTransport rtpTransport, string username = null,
288328 _rtspClient . SendMessage ( optionsMessage ) ;
289329 }
290330
331+ /// <summary>
332+ /// Attempt to reconnect when a connection to the server is lost.
333+ /// </summary>
334+ /// <exception cref="InvalidOperationException">Reconnect can only be called after calling Connect.</exception>
335+ public void TryReconnect ( )
336+ {
337+ if ( _uri == null )
338+ throw new InvalidOperationException ( "Reconnect can only be called after calling Connect!" ) ;
339+
340+ Connect ( _uri , _rtpTransport , _credentials , _mediaRequest , _playbackSession , _userCertificateSelectionCallback , _autoReconnect ) ;
341+ }
342+
291343 /// <summary>
292344 /// Returns true if this connection failed, or if it connected but is no longer connected.
293345 /// </summary>
@@ -742,7 +794,7 @@ private void RtspMessageReceived(object sender, RtspChunkEventArgs e)
742794 {
743795 _logger . LogError ( "Fail to authenticate stopping here" ) ;
744796 StopClient ( ) ;
745- AuthenticationFailed ? . Invoke ( this , EventArgs . Empty ) ;
797+ Stopped ? . Invoke ( this , EventArgs . Empty ) ;
746798 return ;
747799 }
748800
@@ -947,7 +999,7 @@ private void HandleDescribeResponse(RtspResponse message)
947999
9481000 // Process each 'Media' Attribute in the SDP (each sub-stream)
9491001 // to look for first supported video substream
950- if ( _clientWantsVideo )
1002+ if ( _mediaRequest is MediaRequest . VIDEO_ONLY || _mediaRequest is MediaRequest . VIDEO_AND_AUDIO )
9511003 {
9521004 foreach ( Media media in sdpData . Medias . Where ( m => m . MediaType == Media . MediaTypes . video ) )
9531005 {
@@ -1093,7 +1145,7 @@ private void HandleDescribeResponse(RtspResponse message)
10931145 }
10941146 }
10951147
1096- if ( _clientWantsAudio )
1148+ if ( _mediaRequest is MediaRequest . AUDIO_ONLY || _mediaRequest is MediaRequest . VIDEO_AND_AUDIO )
10971149 {
10981150 foreach ( Media media in sdpData . Medias . Where ( m => m . MediaType == Media . MediaTypes . audio ) )
10991151 {
0 commit comments