@@ -60,16 +60,22 @@ public EventMeshClient(string url = Constants.DefaultUrl, int port = Constants.D
6060 }
6161 }
6262
63- public async Task < IEventMeshClientPubSession > CreatePubSession ( string vpn , string clientId , CancellationToken cancellationToken = default ( CancellationToken ) )
63+ public async Task < IEventMeshClientPubSession > CreatePubSession ( string vpn , string clientId , TimeSpan ? expirationTime = null , CancellationToken cancellationToken = default ( CancellationToken ) )
6464 {
65- var pubSession = await CreateSession ( vpn , clientId , UserAgentPurpose . PUB , cancellationToken ) ;
66- return new EventMeshClientPubSession ( pubSession , _ipAddr , _port ) ;
65+ var pubSession = await CreateSession ( vpn , clientId , UserAgentPurpose . PUB , expirationTime , false , cancellationToken ) ;
66+ return new EventMeshClientPubSession ( pubSession , clientId , _ipAddr , _port ) ;
6767 }
6868
69- public async Task < IEventMeshClientSubSession > CreateSubSession ( string vpn , string clientId , CancellationToken cancellationToken = default ( CancellationToken ) )
69+ public async Task < IEventMeshClientPubSession > CreatePubSession ( string vpn , string clientId , TimeSpan ? expirationTime = null , bool isInfinite = false , CancellationToken cancellationToken = default ( CancellationToken ) )
7070 {
71- var subSession = await CreateSession ( vpn , clientId , UserAgentPurpose . SUB , cancellationToken ) ;
72- return new EventMeshClientSubSession ( subSession , _ipAddr , _port ) ;
71+ var pubSession = await CreateSession ( vpn , clientId , UserAgentPurpose . PUB , expirationTime , isInfinite , cancellationToken ) ;
72+ return new EventMeshClientPubSession ( pubSession , clientId , _ipAddr , _port ) ;
73+ }
74+
75+ public async Task < IEventMeshClientSubSession > CreateSubSession ( string vpn , string clientId , TimeSpan ? expirationTime = null , CancellationToken cancellationToken = default ( CancellationToken ) )
76+ {
77+ var subSession = await CreateSession ( vpn , clientId , UserAgentPurpose . SUB , expirationTime , false , cancellationToken ) ;
78+ return new EventMeshClientSubSession ( subSession , clientId , _ipAddr , _port ) ;
7379 }
7480
7581 public async Task AddVpn ( string vpn , CancellationToken cancellationToken = default ( CancellationToken ) )
@@ -137,6 +143,22 @@ public EventMeshClient(string url = Constants.DefaultUrl, int port = Constants.D
137143 }
138144 }
139145
146+ public async Task Disconnect ( string clientId , string sessionId , CancellationToken cancellationToken = default ( CancellationToken ) )
147+ {
148+ using ( var udpClient = new UdpClient ( ) )
149+ {
150+ var writeCtx = new WriteBufferContext ( ) ;
151+ var package = PackageRequestBuilder . Disconnect ( clientId , sessionId ) ;
152+ package . Serialize ( writeCtx ) ;
153+ var payload = writeCtx . Buffer . ToArray ( ) ;
154+ await udpClient . SendAsync ( payload , payload . Count ( ) , new IPEndPoint ( _ipAddr , _port ) ) . WithCancellation ( cancellationToken ) ;
155+ var resultPayload = await udpClient . ReceiveAsync ( ) . WithCancellation ( cancellationToken ) ;
156+ var readCtx = new ReadBufferContext ( resultPayload . Buffer ) ;
157+ var packageResult = Package . Deserialize ( readCtx ) ;
158+ EnsureSuccessStatus ( package , packageResult ) ;
159+ }
160+ }
161+
140162 internal static void EnsureSuccessStatus ( Package packageRequest , Package packageResponse )
141163 {
142164 if ( packageResponse . Header . Status != HeaderStatus . SUCCESS )
@@ -150,9 +172,9 @@ internal static void EnsureSuccessStatus(Package packageRequest, Package package
150172 }
151173 }
152174
153- private async Task < HelloResponse > CreateSession ( string vpn , string clientId , UserAgentPurpose purpose , CancellationToken cancellationToken = default ( CancellationToken ) )
175+ private async Task < HelloResponse > CreateSession ( string vpn , string clientId , UserAgentPurpose purpose , TimeSpan ? expirationTime = null , bool isInfinite = false , CancellationToken cancellationToken = default ( CancellationToken ) )
154176 {
155- var userAgent = new UserAgent { ClientId = clientId , Vpn = vpn , Purpose = purpose } ;
177+ var userAgent = new UserAgent { ClientId = clientId , Vpn = vpn , Purpose = purpose , Expiration = expirationTime , IsSessionInfinite = isInfinite } ;
156178 using ( var udpClient = new UdpClient ( ) )
157179 {
158180 var writeCtx = new WriteBufferContext ( ) ;
@@ -174,38 +196,43 @@ public interface IEventMeshClientPubSession
174196 Task Publish ( string topicName , object obj , CancellationToken cancellationToken = default ( CancellationToken ) ) ;
175197 Task Publish ( string topicName , string str , CancellationToken cancellationToken = default ( CancellationToken ) ) ;
176198 Task Publish ( string topicName , CloudEvent cloudEvent , CancellationToken cancellationToken = default ( CancellationToken ) ) ;
199+ Task Disconnect ( CancellationToken cancellationToken = default ( CancellationToken ) ) ;
177200 }
178201
179202 public interface IEventMeshClientSubSession
180203 {
204+ string SessionId { get ; }
181205 Task < SubscriptionResult > PersistedSubscribe ( string topicFilter , string groupId , Action < CloudEvent > callback , CancellationToken cancellationToken ) ;
182206 SubscriptionResult DirectSubscribe ( string topicFilter , Action < CloudEvent > callback , CancellationToken cancellationToken ) ;
207+ Task Disconnect ( CancellationToken cancellationToken = default ( CancellationToken ) ) ;
183208 }
184209
185210 public class SubscriptionResult
186211 {
187- private readonly CancellationTokenSource _cancellationTokenSource ;
212+ private readonly Func < CancellationToken , Task > _disconnectCallback ;
188213
189- internal SubscriptionResult ( CancellationTokenSource cancellationTokenSource )
214+ internal SubscriptionResult ( Func < CancellationToken , Task > disconnectCallback )
190215 {
191- _cancellationTokenSource = cancellationTokenSource ;
216+ _disconnectCallback = disconnectCallback ;
192217 }
193218
194- public void Close ( )
219+ public async void Close ( )
195220 {
196- _cancellationTokenSource . Cancel ( ) ;
221+ await _disconnectCallback ( CancellationToken . None ) ;
197222 }
198223 }
199224
200225 internal class EventMeshClientPubSession : IEventMeshClientPubSession
201226 {
202227 private readonly HelloResponse _session ;
228+ private readonly string _clientId ;
203229 private readonly IPAddress _ipAddr ;
204230 private readonly int _port ;
205231
206- public EventMeshClientPubSession ( HelloResponse session , IPAddress ipAddr , int port )
232+ public EventMeshClientPubSession ( HelloResponse session , string clientId , IPAddress ipAddr , int port )
207233 {
208234 _session = session ;
235+ _clientId = clientId ;
209236 _ipAddr = ipAddr ;
210237 _port = port ;
211238 }
@@ -245,42 +272,83 @@ public EventMeshClientPubSession(HelloResponse session, IPAddress ipAddr, int po
245272 EventMeshClient . EnsureSuccessStatus ( package , packageResult ) ;
246273 }
247274 }
275+
276+ public async Task Disconnect ( CancellationToken cancellationToken = default )
277+ {
278+ using ( var udpClient = new UdpClient ( ) )
279+ {
280+ var writeCtx = new WriteBufferContext ( ) ;
281+ var package = PackageRequestBuilder . Disconnect ( _clientId , _session . SessionId ) ;
282+ package . Serialize ( writeCtx ) ;
283+ var payload = writeCtx . Buffer . ToArray ( ) ;
284+ await udpClient . SendAsync ( payload , payload . Count ( ) , new IPEndPoint ( _ipAddr , _port ) ) ;
285+ var resultPayload = await udpClient . ReceiveAsync ( ) ;
286+ var readCtx = new ReadBufferContext ( resultPayload . Buffer ) ;
287+ var packageResult = Package . Deserialize ( readCtx ) ;
288+ EventMeshClient . EnsureSuccessStatus ( package , packageResult ) ;
289+ }
290+ }
248291 }
249292
250293 internal class EventMeshClientSubSession : IEventMeshClientSubSession
251294 {
252295 private readonly HelloResponse _session ;
296+ private readonly string _clientId ;
253297 private readonly IPAddress _ipAddr ;
254298 private readonly int _port ;
255299 private int _offsetEvt ;
300+ private CancellationTokenSource _activeSubscriptionCancellationTokenSource = null ;
256301
257- public EventMeshClientSubSession ( HelloResponse session , IPAddress ipAddr , int port )
302+ public EventMeshClientSubSession ( HelloResponse session , string clientId , IPAddress ipAddr , int port )
258303 {
259304 _session = session ;
305+ _clientId = clientId ;
260306 _ipAddr = ipAddr ;
261307 _port = port ;
262308 }
263309
310+ public string SessionId => _session . SessionId ;
311+
264312 public async Task < SubscriptionResult > PersistedSubscribe ( string topicFilter , string groupId , Action < CloudEvent > callback , CancellationToken cancellationToken )
265313 {
266- var cancellationTokenSource = CancellationTokenSource . CreateLinkedTokenSource ( cancellationToken ) ;
267- var result = new SubscriptionResult ( cancellationTokenSource ) ;
314+ if ( _activeSubscriptionCancellationTokenSource != null ) throw new InvalidOperationException ( "There is already an active subscription" ) ;
315+ _activeSubscriptionCancellationTokenSource = CancellationTokenSource . CreateLinkedTokenSource ( cancellationToken ) ;
316+ var activeSubscription = new SubscriptionResult ( Disconnect ) ;
268317 await PersistedSubscribe ( topicFilter , groupId , cancellationToken ) ;
269318#pragma warning disable 4014
270- Task . Run ( async ( ) => await HandlePersistedSubscribe ( callback , groupId , cancellationTokenSource . Token ) ) ;
319+ Task . Run ( async ( ) => await HandlePersistedSubscribe ( callback , groupId , _activeSubscriptionCancellationTokenSource . Token ) ) ;
271320#pragma warning restore 4014
272- return result ;
321+ return activeSubscription ;
273322 }
274323
275324 public SubscriptionResult DirectSubscribe ( string topicName , Action < CloudEvent > callback , CancellationToken cancellationToken )
276325 {
326+ if ( _activeSubscriptionCancellationTokenSource != null ) throw new InvalidOperationException ( "There is already an active subscription" ) ;
277327 _offsetEvt = 1 ;
278- var cancellationTokenSource = CancellationTokenSource . CreateLinkedTokenSource ( cancellationToken ) ;
279- var result = new SubscriptionResult ( cancellationTokenSource ) ;
328+ _activeSubscriptionCancellationTokenSource = CancellationTokenSource . CreateLinkedTokenSource ( cancellationToken ) ;
329+ var activeSubscription = new SubscriptionResult ( Disconnect ) ;
280330#pragma warning disable 4014
281- Task . Run ( async ( ) => await HandleDirectSubscribe ( callback , topicName , cancellationTokenSource . Token ) ) ;
331+ Task . Run ( async ( ) => await HandleDirectSubscribe ( callback , topicName , _activeSubscriptionCancellationTokenSource . Token ) ) ;
282332#pragma warning restore 4014
283- return result ;
333+ return activeSubscription ;
334+ }
335+
336+ public async Task Disconnect ( CancellationToken cancellationToken = default )
337+ {
338+ using ( var udpClient = new UdpClient ( ) )
339+ {
340+ var writeCtx = new WriteBufferContext ( ) ;
341+ var package = PackageRequestBuilder . Disconnect ( _clientId , _session . SessionId ) ;
342+ package . Serialize ( writeCtx ) ;
343+ var payload = writeCtx . Buffer . ToArray ( ) ;
344+ await udpClient . SendAsync ( payload , payload . Count ( ) , new IPEndPoint ( _ipAddr , _port ) ) ;
345+ var resultPayload = await udpClient . ReceiveAsync ( ) ;
346+ var readCtx = new ReadBufferContext ( resultPayload . Buffer ) ;
347+ var packageResult = Package . Deserialize ( readCtx ) ;
348+ EventMeshClient . EnsureSuccessStatus ( package , packageResult ) ;
349+ }
350+
351+ if ( _activeSubscriptionCancellationTokenSource != null ) _activeSubscriptionCancellationTokenSource . Cancel ( ) ;
284352 }
285353
286354 private async Task PersistedSubscribe ( string topicFilter , string groupId , CancellationToken cancellationToken )
0 commit comments