Skip to content

Commit 0330bbc

Browse files
committed
F Added TryReconnect()
1 parent a0b4e17 commit 0330bbc

2 files changed

Lines changed: 94 additions & 42 deletions

File tree

src/RTSPClientApp/Program.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
client.ReceivedVideoData += (sender, e) => Console.Write("*");
1414
client.NewAudioStream += (sender, e) => Console.WriteLine(e.ToString());
1515
client.ReceivedAudioData += (sender, e) => Console.Write("+");
16-
client.AuthenticationFailed += (sender, e) =>
16+
client.Stopped += (sender, e) =>
1717
{
1818
Console.WriteLine("Stopped");
19-
client.Connect(rtspUri, RTPTransport.TCP, userName, password, MediaRequest.VIDEO_AND_AUDIO, false, null, true);
19+
client.TryReconnect();
2020
};
2121

2222
client.Connect(rtspUri, RTPTransport.TCP, userName, password, MediaRequest.VIDEO_AND_AUDIO, false, null, true);

src/SharpRTSPClient/RTSPClient.cs

Lines changed: 92 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using System.IO;
1111
using System.Linq;
1212
using System.Net;
13+
using System.Net.Security;
1314
using System.Text;
1415

1516
namespace 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

Comments
 (0)