Skip to content

Commit b4abac6

Browse files
committed
F Moved SetOnvifAuthentication method out of the SimpleOnvifClient
1 parent 03e8d66 commit b4abac6

File tree

3 files changed

+74
-101
lines changed

3 files changed

+74
-101
lines changed

README.md

Lines changed: 12 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Optionally, add Onvif discovery to make your service discoverable on the network
3838
```cs
3939
builder.Services.AddOnvifDiscovery();
4040
```
41-
Simple DeviceImpl just extends `SharpOnvifServer.DeviceMgmt.DeviceBase` and overrides a method you want to implement - for instance `GetDeviceInformation`:
41+
Simple `DeviceImpl` just extends `SharpOnvifServer.DeviceMgmt.DeviceBase` and overrides a method you want to implement - for instance `GetDeviceInformation`:
4242
```cs
4343
public class DeviceImpl : DeviceBase
4444
{
@@ -153,61 +153,23 @@ First add a reference to the DLL that implements the clients (e.g. `SharpOnvifCl
153153
```cs
154154
var auth = new DigestBehavior("admin", "password");
155155
```
156-
Create the Onvif client and set the authentication behavior before you use it:
156+
Create the Onvif client and set the authentication behavior using `SetOnvifAuthentication` extension method from `SharpOnvifClient.OnvifAuthenticationExtensions` before you use it:
157157
```cs
158-
using (var deviceClient = new DeviceClient(
159-
OnvifBindingFactory.CreateBinding(),
160-
new System.ServiceModel.EndpointAddress("http://192.168.1.10/onvif/device_service")))
161-
{
162-
SetAuthentication(deviceClient);
163-
164-
// use the client
165-
}
166-
```
167-
Where the `SetAuthentication` method might look like:
168-
```cs
169-
[Flags]
170-
public enum AuthenticationMethod
171-
{
172-
None = 0,
173-
WsUsernameToken = 1,
174-
HttpDigest = 2
175-
}
158+
using SharpOnvifClient;
176159

177-
private readonly System.Net.NetworkCredential _credentials;
178-
private readonly AuthenticationMethod _authentication = AuthenticationMethod.WsUsernameToken | AuthenticationMethod.HttpDigest;
179-
private readonly IEndpointBehavior _legacyAuth;
160+
System.Net.NetworkCredential credentials = new System.Net.NetworkCredential(userName, password);
161+
IEndpointBehavior legacyAuth = new WsUsernameTokenBehavior(_credentials);
180162

181-
// ctor
182-
...
183-
_credentials = new System.Net.NetworkCredential(userName, password);
184-
_legacyAuth = new WsUsernameTokenBehavior(_credentials);
185-
...
186-
187-
private void SetAuthentication<TChannel>(ClientBase<TChannel> channel) where TChannel : class
163+
using (var deviceClient = new DeviceClient(
164+
OnvifBindingFactory.CreateBinding(),
165+
new System.ServiceModel.EndpointAddress("http://192.168.1.10/onvif/device_service")))
188166
{
189-
if(_authentication == AuthenticationMethod.None)
190-
{
191-
return;
192-
}
193-
194-
if (_authentication.HasFlag(AuthenticationMethod.HttpDigest))
195-
{
196-
// HTTP Digest authentication is handled by WCF
197-
channel.ClientCredentials.HttpDigest.ClientCredential = _credentials;
198-
}
199-
200-
if (_authentication.HasFlag(AuthenticationMethod.WsUsernameToken))
201-
{
202-
// Legacy WsUsernameToken authentication must be handled using a custom behavior
203-
if (!channel.Endpoint.EndpointBehaviors.Contains(_legacyAuth))
204-
{
205-
channel.Endpoint.EndpointBehaviors.Add(_legacyAuth);
206-
}
207-
}
167+
deviceClient.SetOnvifAuthentication(OnvifAuthentication.WsUsernameToken | OnvifAuthentication.HttpDigest, credentials, legacyAuth);
168+
169+
// use the client
208170
}
209171
```
210-
Call any method on the client like:
172+
Call any method on the client, e.g.:
211173
```cs
212174
var deviceInfo = await deviceClient.GetDeviceInformationAsync(new GetDeviceInformationRequest());
213175
```
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System;
2+
using System.Diagnostics;
3+
using System.Net;
4+
using System.ServiceModel;
5+
6+
namespace SharpOnvifClient
7+
{
8+
[Flags]
9+
public enum OnvifAuthentication
10+
{
11+
None = 0,
12+
WsUsernameToken = 1,
13+
HttpDigest = 2
14+
}
15+
16+
public static class OnvifAuthenticationExtensions
17+
{
18+
public static void SetOnvifAuthentication<TChannel>(
19+
this ClientBase<TChannel> channel,
20+
OnvifAuthentication authentication,
21+
NetworkCredential credentials,
22+
System.ServiceModel.Description.IEndpointBehavior legacyAuth = null) where TChannel : class
23+
{
24+
if (authentication == OnvifAuthentication.None)
25+
{
26+
Debug.WriteLine("Authentication is disabled");
27+
return;
28+
}
29+
30+
if (authentication.HasFlag(OnvifAuthentication.HttpDigest))
31+
{
32+
// HTTP Digest authentication is handled by WCF
33+
channel.ClientCredentials.HttpDigest.ClientCredential = credentials;
34+
}
35+
36+
if (authentication.HasFlag(OnvifAuthentication.WsUsernameToken))
37+
{
38+
if(legacyAuth == null)
39+
throw new ArgumentNullException(nameof(legacyAuth));
40+
41+
// legacy WsUsernameToken authentication must be handled using a custom behavior
42+
if (!channel.Endpoint.EndpointBehaviors.Contains(legacyAuth))
43+
{
44+
channel.Endpoint.EndpointBehaviors.Add(legacyAuth);
45+
}
46+
}
47+
}
48+
}
49+
}

src/SharpOnvifClient/SimpleOnvifClient.cs

Lines changed: 13 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,13 @@
66
using SharpOnvifCommon;
77
using System;
88
using System.Collections.Generic;
9-
using System.Diagnostics;
109
using System.Linq;
1110
using System.ServiceModel;
1211
using System.ServiceModel.Description;
1312
using System.Threading.Tasks;
1413

1514
namespace SharpOnvifClient
1615
{
17-
[Flags]
18-
public enum AuthenticationMethod
19-
{
20-
None = 0,
21-
WsUsernameToken = 1,
22-
HttpDigest = 2
23-
}
24-
2516
public class SimpleOnvifClient : IDisposable
2617
{
2718
private bool _disposedValue;
@@ -32,27 +23,31 @@ public class SimpleOnvifClient : IDisposable
3223
private object _syncRoot = new object();
3324
private readonly Dictionary<string, ICommunicationObject> _clients = new Dictionary<string, ICommunicationObject>();
3425
private readonly System.Net.NetworkCredential _credentials;
35-
private readonly AuthenticationMethod _authentication;
26+
private readonly OnvifAuthentication _authentication;
3627
private readonly IEndpointBehavior _legacyAuth;
3728

38-
public SimpleOnvifClient(string onvifUri) : this(onvifUri, null, null, AuthenticationMethod.None)
29+
public SimpleOnvifClient(string onvifUri) : this(onvifUri, null, null, OnvifAuthentication.None)
3930
{ }
4031

41-
public SimpleOnvifClient(string onvifUri, string userName, string password) : this(onvifUri, userName, password, AuthenticationMethod.WsUsernameToken | AuthenticationMethod.HttpDigest)
32+
public SimpleOnvifClient(string onvifUri, string userName, string password) : this(onvifUri, userName, password, OnvifAuthentication.WsUsernameToken | OnvifAuthentication.HttpDigest)
4233
{ }
4334

44-
public SimpleOnvifClient(string onvifUri, string userName, string password, AuthenticationMethod authentication)
35+
public SimpleOnvifClient(string onvifUri, string userName, string password, OnvifAuthentication authentication)
4536
{
4637
if (string.IsNullOrWhiteSpace(onvifUri))
4738
throw new ArgumentNullException(nameof(onvifUri));
4839

49-
if(authentication != AuthenticationMethod.None)
40+
if(authentication != OnvifAuthentication.None)
5041
{
5142
if (string.IsNullOrWhiteSpace(userName) || string.IsNullOrWhiteSpace(password))
5243
throw new ArgumentNullException("User name or password must not be empty!");
5344

5445
_credentials = new System.Net.NetworkCredential(userName, password);
55-
_legacyAuth = new WsUsernameTokenBehavior(_credentials);
46+
47+
if (authentication.HasFlag(OnvifAuthentication.WsUsernameToken))
48+
{
49+
_legacyAuth = new WsUsernameTokenBehavior(_credentials);
50+
}
5651
}
5752

5853
_onvifUri = onvifUri;
@@ -61,45 +56,16 @@ public SimpleOnvifClient(string onvifUri, string userName, string password, Auth
6156

6257
public void SetCameraUtcNowOffset(TimeSpan utcNowOffset)
6358
{
64-
// used for WsUsernameToken authentication method
65-
if (_authentication.HasFlag(AuthenticationMethod.WsUsernameToken))
59+
if (_authentication.HasFlag(OnvifAuthentication.WsUsernameToken))
6660
{
67-
var utcOffsetBehavior = _legacyAuth as IHasUtcOffset;
68-
if (utcOffsetBehavior != null)
69-
{
70-
utcOffsetBehavior.UtcNowOffset = utcNowOffset;
71-
}
61+
((IHasUtcOffset)_legacyAuth).UtcNowOffset = utcNowOffset;
7262
}
7363
else
7464
{
7565
throw new NotSupportedException("Time offset is only supported for WsUsernameToken authentication");
7666
}
7767
}
7868

79-
private void SetAuthentication<TChannel>(ClientBase<TChannel> channel) where TChannel : class
80-
{
81-
if(_authentication == AuthenticationMethod.None)
82-
{
83-
Debug.WriteLine("Authentication is disabled");
84-
return;
85-
}
86-
87-
if (_authentication.HasFlag(AuthenticationMethod.HttpDigest))
88-
{
89-
// HTTP Digest authentication is handled by WCF
90-
channel.ClientCredentials.HttpDigest.ClientCredential = _credentials;
91-
}
92-
93-
if (_authentication.HasFlag(AuthenticationMethod.WsUsernameToken))
94-
{
95-
// Legacy WsUsernameToken authentication must be handled using a custom behavior
96-
if (!channel.Endpoint.EndpointBehaviors.Contains(_legacyAuth))
97-
{
98-
channel.Endpoint.EndpointBehaviors.Add(_legacyAuth);
99-
}
100-
}
101-
}
102-
10369
public TClient GetOrCreateClient<TClient, TChannel>(string uri, Func<string, TClient> creator) where TClient : ClientBase<TChannel> where TChannel : class
10470
{
10571
lock (_syncRoot)
@@ -111,7 +77,7 @@ public TClient GetOrCreateClient<TClient, TChannel>(string uri, Func<string, TCl
11177
else
11278
{
11379
var client = creator(uri);
114-
SetAuthentication(client);
80+
client.SetOnvifAuthentication(_authentication, _credentials, _legacyAuth);
11581
_clients.Add(uri, client);
11682
return client;
11783
}
@@ -189,9 +155,6 @@ public async Task<CreatePullPointSubscriptionResponse> PullPointSubscribeAsync(i
189155
{
190156
InitialTerminationTime = OnvifHelpers.GetTimeoutInMinutes(initialTerminationTimeInMinutes)
191157
}).ConfigureAwait(false);
192-
193-
Debug.WriteLine($"Pull Point subscription termination time: {subscribeResponse.TerminationTime}");
194-
195158
return subscribeResponse;
196159
}
197160

@@ -233,7 +196,6 @@ public async Task<SubscribeResponse1> BasicSubscribeAsync(string onvifEventListe
233196
}
234197
}
235198
}).ConfigureAwait(false);
236-
237199
return subscriptionResult;
238200
}
239201

0 commit comments

Comments
 (0)