ChannelReliableSession.cs 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208
  1. //----------------------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //--------------------------------------------------------------------------
  4. namespace System.ServiceModel.Channels
  5. {
  6. using System;
  7. using System.Runtime;
  8. using System.ServiceModel;
  9. using System.ServiceModel.Diagnostics.Application;
  10. using System.ServiceModel.Security;
  11. using System.Threading;
  12. using System.Xml;
  13. abstract class ChannelReliableSession : ISession
  14. {
  15. IReliableChannelBinder binder;
  16. bool canSendFault = true;
  17. ChannelBase channel;
  18. SessionFaultState faulted = SessionFaultState.NotFaulted;
  19. FaultHelper faultHelper;
  20. SequenceRangeCollection finalRanges;
  21. Guard guard = new Guard(int.MaxValue);
  22. InterruptibleTimer inactivityTimer;
  23. TimeSpan initiationTime;
  24. UniqueId inputID;
  25. bool isSessionClosed = false;
  26. UniqueId outputID;
  27. RequestContext replyFaultContext;
  28. IReliableFactorySettings settings;
  29. Message terminatingFault;
  30. object thisLock = new object();
  31. UnblockChannelCloseHandler unblockChannelCloseCallback;
  32. protected ChannelReliableSession(ChannelBase channel, IReliableFactorySettings settings, IReliableChannelBinder binder, FaultHelper faultHelper)
  33. {
  34. this.channel = channel;
  35. this.settings = settings;
  36. this.binder = binder;
  37. this.faultHelper = faultHelper;
  38. this.inactivityTimer = new InterruptibleTimer(this.settings.InactivityTimeout, new WaitCallback(this.OnInactivityElapsed), null);
  39. this.initiationTime = ReliableMessagingConstants.UnknownInitiationTime;
  40. }
  41. protected ChannelBase Channel
  42. {
  43. get
  44. {
  45. return this.channel;
  46. }
  47. }
  48. protected Guard Guard
  49. {
  50. get
  51. {
  52. return this.guard;
  53. }
  54. }
  55. public string Id
  56. {
  57. get
  58. {
  59. UniqueId sequenceId = this.SequenceID;
  60. if (sequenceId == null)
  61. return null;
  62. else
  63. return sequenceId.ToString();
  64. }
  65. }
  66. public TimeSpan InitiationTime
  67. {
  68. get
  69. {
  70. return this.initiationTime;
  71. }
  72. protected set
  73. {
  74. this.initiationTime = value;
  75. }
  76. }
  77. public UniqueId InputID
  78. {
  79. get
  80. {
  81. return this.inputID;
  82. }
  83. protected set
  84. {
  85. this.inputID = value;
  86. }
  87. }
  88. protected FaultHelper FaultHelper
  89. {
  90. get
  91. {
  92. return this.faultHelper;
  93. }
  94. }
  95. public UniqueId OutputID
  96. {
  97. get
  98. {
  99. return this.outputID;
  100. }
  101. protected set
  102. {
  103. this.outputID = value;
  104. }
  105. }
  106. public abstract UniqueId SequenceID
  107. {
  108. get;
  109. }
  110. public IReliableFactorySettings Settings
  111. {
  112. get
  113. {
  114. return this.settings;
  115. }
  116. }
  117. protected object ThisLock
  118. {
  119. get
  120. {
  121. return this.thisLock;
  122. }
  123. }
  124. public UnblockChannelCloseHandler UnblockChannelCloseCallback
  125. {
  126. set
  127. {
  128. this.unblockChannelCloseCallback = value;
  129. }
  130. }
  131. public virtual void Abort()
  132. {
  133. this.guard.Abort();
  134. this.inactivityTimer.Abort();
  135. // Try to send a fault.
  136. bool sendFault;
  137. lock (this.ThisLock)
  138. {
  139. // Faulted thread already cleaned up. No need to to anything more.
  140. if (this.faulted == SessionFaultState.CleanedUp)
  141. return;
  142. // Can only send a fault if the other side did not send one already.
  143. sendFault = this.canSendFault && (this.faulted != SessionFaultState.RemotelyFaulted); // NotFaulted || LocallyFaulted
  144. this.faulted = SessionFaultState.CleanedUp;
  145. }
  146. if (sendFault)
  147. {
  148. if ((this.binder.State == CommunicationState.Opened)
  149. && this.binder.Connected
  150. && (this.binder.CanSendAsynchronously || (this.replyFaultContext != null)))
  151. {
  152. if (this.terminatingFault == null)
  153. {
  154. UniqueId sequenceId = this.InputID ?? this.OutputID;
  155. if (sequenceId != null)
  156. {
  157. WsrmFault fault = SequenceTerminatedFault.CreateCommunicationFault(sequenceId, SR.GetString(SR.SequenceTerminatedOnAbort), null);
  158. this.terminatingFault = fault.CreateMessage(this.settings.MessageVersion,
  159. this.settings.ReliableMessagingVersion);
  160. }
  161. }
  162. if (this.terminatingFault != null)
  163. {
  164. this.AddFinalRanges();
  165. this.faultHelper.SendFaultAsync(this.binder, this.replyFaultContext, this.terminatingFault);
  166. return;
  167. }
  168. }
  169. }
  170. // Got here so the session did not actually send a fault, must clean up resources.
  171. if (this.terminatingFault != null)
  172. this.terminatingFault.Close();
  173. if (this.replyFaultContext != null)
  174. this.replyFaultContext.Abort();
  175. this.binder.Abort();
  176. }
  177. void AddFinalRanges()
  178. {
  179. // This relies on the assumption that acknowledgements can be piggybacked on sequence
  180. // faults for the converse sequence.
  181. if (this.finalRanges != null)
  182. {
  183. WsrmUtilities.AddAcknowledgementHeader(this.settings.ReliableMessagingVersion,
  184. this.terminatingFault, this.InputID, this.finalRanges, true);
  185. }
  186. }
  187. public virtual IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
  188. {
  189. return this.guard.BeginClose(timeout, callback, state);
  190. }
  191. public abstract IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state);
  192. public virtual void Close(TimeSpan timeout)
  193. {
  194. this.guard.Close(timeout);
  195. this.inactivityTimer.Abort();
  196. }
  197. // Corresponds to the state where the other side could have gone away already.
  198. public void CloseSession()
  199. {
  200. this.isSessionClosed = true;
  201. }
  202. public virtual void EndClose(IAsyncResult result)
  203. {
  204. this.guard.EndClose(result);
  205. this.inactivityTimer.Abort();
  206. }
  207. public abstract void EndOpen(IAsyncResult result);
  208. protected virtual void FaultCore()
  209. {
  210. if (TD.ReliableSessionChannelFaultedIsEnabled())
  211. {
  212. TD.ReliableSessionChannelFaulted(this.Id);
  213. }
  214. this.inactivityTimer.Abort();
  215. }
  216. public void OnLocalFault(Exception e, WsrmFault fault, RequestContext context)
  217. {
  218. Message faultMessage = (fault == null) ? null : fault.CreateMessage(this.settings.MessageVersion,
  219. this.settings.ReliableMessagingVersion);
  220. this.OnLocalFault(e, faultMessage, context);
  221. }
  222. public void OnLocalFault(Exception e, Message faultMessage, RequestContext context)
  223. {
  224. if (this.channel.Aborted ||
  225. this.channel.State == CommunicationState.Faulted ||
  226. this.channel.State == CommunicationState.Closed)
  227. {
  228. if (faultMessage != null)
  229. faultMessage.Close();
  230. if (context != null)
  231. context.Abort();
  232. return;
  233. }
  234. lock (this.ThisLock)
  235. {
  236. if (this.faulted != SessionFaultState.NotFaulted)
  237. return;
  238. this.faulted = SessionFaultState.LocallyFaulted;
  239. this.terminatingFault = faultMessage;
  240. this.replyFaultContext = context;
  241. }
  242. this.FaultCore();
  243. this.channel.Fault(e);
  244. this.UnblockChannelIfNecessary();
  245. }
  246. public void OnRemoteFault(WsrmFault fault)
  247. {
  248. this.OnRemoteFault(WsrmFault.CreateException(fault));
  249. }
  250. public void OnRemoteFault(Exception e)
  251. {
  252. if (this.channel.Aborted ||
  253. this.channel.State == CommunicationState.Faulted ||
  254. this.channel.State == CommunicationState.Closed)
  255. {
  256. return;
  257. }
  258. lock (this.ThisLock)
  259. {
  260. if (this.faulted != SessionFaultState.NotFaulted)
  261. return;
  262. this.faulted = SessionFaultState.RemotelyFaulted;
  263. }
  264. this.FaultCore();
  265. this.channel.Fault(e);
  266. this.UnblockChannelIfNecessary();
  267. }
  268. public virtual void OnFaulted()
  269. {
  270. this.FaultCore();
  271. // Try to send a fault.
  272. bool sendFault;
  273. lock (this.ThisLock)
  274. {
  275. // Channel was faulted without the session being told first (e.g. open throws).
  276. // The session does not know what fault to send so let abort send it if it can.
  277. if (this.faulted == SessionFaultState.NotFaulted)
  278. return;
  279. // Abort thread decided to clean up.
  280. if (this.faulted == SessionFaultState.CleanedUp)
  281. return;
  282. // Can only send a fault if the other side did not send one already.
  283. sendFault = this.canSendFault && (this.faulted != SessionFaultState.RemotelyFaulted); // LocallyFaulted
  284. this.faulted = SessionFaultState.CleanedUp;
  285. }
  286. if (sendFault)
  287. {
  288. if ((this.binder.State == CommunicationState.Opened)
  289. && this.binder.Connected
  290. && (this.binder.CanSendAsynchronously || (this.replyFaultContext != null))
  291. && (this.terminatingFault != null))
  292. {
  293. this.AddFinalRanges();
  294. this.faultHelper.SendFaultAsync(this.binder, this.replyFaultContext, this.terminatingFault);
  295. return;
  296. }
  297. }
  298. // Got here so the session did not actually send a fault, must clean up resources.
  299. if (this.terminatingFault != null)
  300. this.terminatingFault.Close();
  301. if (this.replyFaultContext != null)
  302. this.replyFaultContext.Abort();
  303. this.binder.Abort();
  304. }
  305. void OnInactivityElapsed(object state)
  306. {
  307. WsrmFault fault;
  308. Exception e;
  309. string exceptionMessage = SR.GetString(SR.SequenceTerminatedInactivityTimeoutExceeded, this.settings.InactivityTimeout);
  310. if (TD.InactivityTimeoutIsEnabled())
  311. {
  312. TD.InactivityTimeout(exceptionMessage);
  313. }
  314. if (this.SequenceID != null)
  315. {
  316. string faultReason = SR.GetString(SR.SequenceTerminatedInactivityTimeoutExceeded, this.settings.InactivityTimeout);
  317. fault = SequenceTerminatedFault.CreateCommunicationFault(this.SequenceID, faultReason, exceptionMessage);
  318. e = fault.CreateException();
  319. }
  320. else
  321. {
  322. fault = null;
  323. e = new CommunicationException(exceptionMessage);
  324. }
  325. OnLocalFault(e, fault, null);
  326. }
  327. public abstract void OnLocalActivity();
  328. public void OnUnknownException(Exception e)
  329. {
  330. this.canSendFault = false;
  331. this.OnLocalFault(e, (Message)null, null);
  332. }
  333. public abstract void Open(TimeSpan timeout);
  334. public virtual void OnRemoteActivity(bool fastPolling)
  335. {
  336. this.inactivityTimer.Set();
  337. }
  338. // returns true if the info does not fault the session.
  339. public bool ProcessInfo(WsrmMessageInfo info, RequestContext context)
  340. {
  341. return this.ProcessInfo(info, context, false);
  342. }
  343. public bool ProcessInfo(WsrmMessageInfo info, RequestContext context, bool throwException)
  344. {
  345. Exception e;
  346. if (info.ParsingException != null)
  347. {
  348. WsrmFault fault;
  349. if (this.SequenceID != null)
  350. {
  351. string reason = SR.GetString(SR.CouldNotParseWithAction, info.Action);
  352. fault = SequenceTerminatedFault.CreateProtocolFault(this.SequenceID, reason, null);
  353. }
  354. else
  355. {
  356. fault = null;
  357. }
  358. e = new ProtocolException(SR.GetString(SR.MessageExceptionOccurred), info.ParsingException);
  359. this.OnLocalFault(throwException ? null : e, fault, context);
  360. }
  361. else if (info.FaultReply != null)
  362. {
  363. e = info.FaultException;
  364. this.OnLocalFault(throwException ? null : e, info.FaultReply, context);
  365. }
  366. else if ((info.WsrmHeaderFault != null) && (info.WsrmHeaderFault.SequenceID != this.InputID)
  367. && (info.WsrmHeaderFault.SequenceID != this.OutputID))
  368. {
  369. e = new ProtocolException(SR.GetString(SR.WrongIdentifierFault, FaultException.GetSafeReasonText(info.WsrmHeaderFault.Reason)));
  370. this.OnLocalFault(throwException ? null : e, (Message)null, context);
  371. }
  372. else if (info.FaultInfo != null)
  373. {
  374. if (this.isSessionClosed)
  375. {
  376. UnknownSequenceFault unknownSequenceFault = info.FaultInfo as UnknownSequenceFault;
  377. if (unknownSequenceFault != null)
  378. {
  379. UniqueId sequenceId = unknownSequenceFault.SequenceID;
  380. if (((this.OutputID != null) && (this.OutputID == sequenceId))
  381. || ((this.InputID != null) && (this.InputID == sequenceId)))
  382. {
  383. if (this.settings.ReliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
  384. {
  385. info.Message.Close();
  386. return false;
  387. }
  388. else if (this.settings.ReliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11)
  389. {
  390. return true;
  391. }
  392. else
  393. {
  394. throw Fx.AssertAndThrow("Unknown version.");
  395. }
  396. }
  397. }
  398. }
  399. e = info.FaultException;
  400. if (context != null)
  401. context.Close();
  402. this.OnRemoteFault(throwException ? null : e);
  403. }
  404. else
  405. {
  406. return true;
  407. }
  408. info.Message.Close();
  409. if (throwException)
  410. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(e);
  411. else
  412. return false;
  413. }
  414. public void SetFinalAck(SequenceRangeCollection finalRanges)
  415. {
  416. this.finalRanges = finalRanges;
  417. }
  418. public virtual void StartInactivityTimer()
  419. {
  420. this.inactivityTimer.Set();
  421. }
  422. // RM channels fault out of band. During the Closing and Closed states CommunicationObjects
  423. // do not fault. In all other states the RM channel can and must unblock various methods
  424. // from the OnFaulted method. This method will ensure that anything that needs to unblock
  425. // in the Closing state will unblock if a fault occurs.
  426. void UnblockChannelIfNecessary()
  427. {
  428. lock (this.ThisLock)
  429. {
  430. if (this.faulted == SessionFaultState.NotFaulted)
  431. {
  432. throw Fx.AssertAndThrow("This method must be called from a fault thread.");
  433. }
  434. // Successfully faulted or aborted.
  435. else if (this.faulted == SessionFaultState.CleanedUp)
  436. {
  437. return;
  438. }
  439. }
  440. // Make sure the fault is sent then unblock the channel.
  441. this.OnFaulted();
  442. this.unblockChannelCloseCallback();
  443. }
  444. public bool VerifyDuplexProtocolElements(WsrmMessageInfo info, RequestContext context)
  445. {
  446. return this.VerifyDuplexProtocolElements(info, context, false);
  447. }
  448. public bool VerifyDuplexProtocolElements(WsrmMessageInfo info, RequestContext context, bool throwException)
  449. {
  450. WsrmFault fault = this.VerifyDuplexProtocolElements(info);
  451. if (fault == null)
  452. {
  453. return true;
  454. }
  455. if (throwException)
  456. {
  457. Exception e = fault.CreateException();
  458. this.OnLocalFault(null, fault, context);
  459. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(e);
  460. }
  461. else
  462. {
  463. this.OnLocalFault(fault.CreateException(), fault, context);
  464. return false;
  465. }
  466. }
  467. protected virtual WsrmFault VerifyDuplexProtocolElements(WsrmMessageInfo info)
  468. {
  469. if (info.AcknowledgementInfo != null && info.AcknowledgementInfo.SequenceID != this.OutputID)
  470. return new UnknownSequenceFault(info.AcknowledgementInfo.SequenceID);
  471. else if (info.AckRequestedInfo != null && info.AckRequestedInfo.SequenceID != this.InputID)
  472. return new UnknownSequenceFault(info.AckRequestedInfo.SequenceID);
  473. else if (info.SequencedMessageInfo != null && info.SequencedMessageInfo.SequenceID != this.InputID)
  474. return new UnknownSequenceFault(info.SequencedMessageInfo.SequenceID);
  475. else if (info.TerminateSequenceInfo != null && info.TerminateSequenceInfo.Identifier != this.InputID)
  476. {
  477. if (this.Settings.ReliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
  478. return SequenceTerminatedFault.CreateProtocolFault(this.OutputID, SR.GetString(SR.SequenceTerminatedUnexpectedTerminateSequence), SR.GetString(SR.UnexpectedTerminateSequence));
  479. else if (info.TerminateSequenceInfo.Identifier == this.OutputID)
  480. return null;
  481. else
  482. return new UnknownSequenceFault(info.TerminateSequenceInfo.Identifier);
  483. }
  484. else if (info.TerminateSequenceResponseInfo != null)
  485. {
  486. WsrmUtilities.AssertWsrm11(this.settings.ReliableMessagingVersion);
  487. if (info.TerminateSequenceResponseInfo.Identifier == this.OutputID)
  488. return null;
  489. else
  490. return new UnknownSequenceFault(info.TerminateSequenceResponseInfo.Identifier);
  491. }
  492. else if (info.CloseSequenceInfo != null)
  493. {
  494. WsrmUtilities.AssertWsrm11(this.settings.ReliableMessagingVersion);
  495. if (info.CloseSequenceInfo.Identifier == this.InputID)
  496. return null;
  497. else if (info.CloseSequenceInfo.Identifier == this.OutputID)
  498. // Spec allows RM-Destination close, but we do not.
  499. return SequenceTerminatedFault.CreateProtocolFault(this.OutputID, SR.GetString(SR.SequenceTerminatedUnsupportedClose), SR.GetString(SR.UnsupportedCloseExceptionString));
  500. else
  501. return new UnknownSequenceFault(info.CloseSequenceInfo.Identifier);
  502. }
  503. else if (info.CloseSequenceResponseInfo != null)
  504. {
  505. WsrmUtilities.AssertWsrm11(this.settings.ReliableMessagingVersion);
  506. if (info.CloseSequenceResponseInfo.Identifier == this.OutputID)
  507. return null;
  508. else if (info.CloseSequenceResponseInfo.Identifier == this.InputID)
  509. return SequenceTerminatedFault.CreateProtocolFault(this.InputID, SR.GetString(SR.SequenceTerminatedUnexpectedCloseSequenceResponse), SR.GetString(SR.UnexpectedCloseSequenceResponse));
  510. else
  511. return new UnknownSequenceFault(info.CloseSequenceResponseInfo.Identifier);
  512. }
  513. else
  514. return null;
  515. }
  516. public bool VerifySimplexProtocolElements(WsrmMessageInfo info, RequestContext context)
  517. {
  518. return this.VerifySimplexProtocolElements(info, context, false);
  519. }
  520. public bool VerifySimplexProtocolElements(WsrmMessageInfo info, RequestContext context, bool throwException)
  521. {
  522. WsrmFault fault = this.VerifySimplexProtocolElements(info);
  523. if (fault == null)
  524. {
  525. return true;
  526. }
  527. info.Message.Close();
  528. if (throwException)
  529. {
  530. Exception e = fault.CreateException();
  531. this.OnLocalFault(null, fault, context);
  532. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(e);
  533. }
  534. else
  535. {
  536. this.OnLocalFault(fault.CreateException(), fault, context);
  537. return false;
  538. }
  539. }
  540. protected abstract WsrmFault VerifySimplexProtocolElements(WsrmMessageInfo info);
  541. enum SessionFaultState
  542. {
  543. NotFaulted,
  544. LocallyFaulted,
  545. RemotelyFaulted,
  546. CleanedUp
  547. }
  548. public delegate void UnblockChannelCloseHandler();
  549. }
  550. class ClientReliableSession : ChannelReliableSession, IOutputSession
  551. {
  552. IClientReliableChannelBinder binder;
  553. PollingMode oldPollingMode;
  554. PollingHandler pollingHandler;
  555. PollingMode pollingMode;
  556. InterruptibleTimer pollingTimer;
  557. ReliableRequestor requestor;
  558. public delegate void PollingHandler();
  559. public ClientReliableSession(ChannelBase channel, IReliableFactorySettings factory, IClientReliableChannelBinder binder, FaultHelper faultHelper, UniqueId inputID) :
  560. base(channel, factory, binder, faultHelper)
  561. {
  562. this.binder = binder;
  563. this.InputID = inputID;
  564. this.pollingTimer = new InterruptibleTimer(this.GetPollingInterval(), this.OnPollingTimerElapsed, null);
  565. if (this.binder.Channel is IRequestChannel)
  566. {
  567. this.requestor = new RequestReliableRequestor();
  568. }
  569. else if (this.binder.Channel is IDuplexChannel)
  570. {
  571. SendReceiveReliableRequestor sendReceiveRequestor = new SendReceiveReliableRequestor();
  572. sendReceiveRequestor.TimeoutIsSafe = !this.ChannelSupportsOneCreateSequenceAttempt();
  573. this.requestor = sendReceiveRequestor;
  574. }
  575. else
  576. {
  577. Fx.Assert("This channel type is not supported");
  578. }
  579. MessageVersion messageVersion = this.Settings.MessageVersion;
  580. ReliableMessagingVersion reliableMessagingVersion = this.Settings.ReliableMessagingVersion;
  581. this.requestor.MessageVersion = messageVersion;
  582. this.requestor.Binder = this.binder;
  583. this.requestor.IsCreateSequence = true;
  584. this.requestor.TimeoutString1Index = SR.TimeoutOnOpen;
  585. this.requestor.MessageAction = WsrmIndex.GetCreateSequenceActionHeader(messageVersion.Addressing,
  586. reliableMessagingVersion);
  587. if ((reliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11)
  588. && (this.binder.GetInnerSession() is ISecureConversationSession))
  589. {
  590. this.requestor.MessageHeader = new WsrmUsesSequenceSTRHeader();
  591. }
  592. this.requestor.MessageBody = new CreateSequence(this.Settings.MessageVersion.Addressing,
  593. reliableMessagingVersion, this.Settings.Ordered, this.binder, this.InputID);
  594. this.requestor.SetRequestResponsePattern();
  595. }
  596. public PollingHandler PollingCallback
  597. {
  598. set
  599. {
  600. this.pollingHandler = value;
  601. }
  602. }
  603. public override UniqueId SequenceID
  604. {
  605. get
  606. {
  607. return this.OutputID;
  608. }
  609. }
  610. public override void Abort()
  611. {
  612. ReliableRequestor temp = this.requestor;
  613. if (temp != null)
  614. temp.Abort(this.Channel);
  615. pollingTimer.Abort();
  616. base.Abort();
  617. }
  618. public override IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
  619. {
  620. if (this.pollingHandler == null)
  621. {
  622. throw Fx.AssertAndThrow("The client reliable channel must set the polling handler prior to opening the client reliable session.");
  623. }
  624. return new OpenAsyncResult(this, timeout, callback, state);
  625. }
  626. bool ChannelSupportsOneCreateSequenceAttempt()
  627. {
  628. IDuplexSessionChannel channel = this.binder.Channel as IDuplexSessionChannel;
  629. if (channel == null)
  630. return false;
  631. return (channel.Session is ISecuritySession && !(channel.Session is ISecureConversationSession));
  632. }
  633. public override void Close(TimeSpan timeout)
  634. {
  635. base.Close(timeout);
  636. pollingTimer.Abort();
  637. }
  638. public override void EndClose(IAsyncResult result)
  639. {
  640. base.EndClose(result);
  641. pollingTimer.Abort();
  642. }
  643. public override void EndOpen(IAsyncResult result)
  644. {
  645. OpenAsyncResult.End(result);
  646. this.requestor = null;
  647. }
  648. protected override void FaultCore()
  649. {
  650. this.pollingTimer.Abort();
  651. base.FaultCore();
  652. }
  653. TimeSpan GetPollingInterval()
  654. {
  655. switch (this.pollingMode)
  656. {
  657. case PollingMode.Idle:
  658. return Ticks.ToTimeSpan(Ticks.FromTimeSpan(this.Settings.InactivityTimeout) / 2);
  659. case PollingMode.KeepAlive:
  660. return WsrmUtilities.CalculateKeepAliveInterval(this.Settings.InactivityTimeout, this.Settings.MaxRetryCount);
  661. case PollingMode.NotPolling:
  662. return TimeSpan.MaxValue;
  663. case PollingMode.FastPolling:
  664. TimeSpan keepAliveInterval = WsrmUtilities.CalculateKeepAliveInterval(this.Settings.InactivityTimeout, this.Settings.MaxRetryCount);
  665. TimeSpan fastPollingInterval = Ticks.ToTimeSpan(Ticks.FromTimeSpan(this.binder.DefaultSendTimeout) / 2);
  666. if (fastPollingInterval < keepAliveInterval)
  667. return fastPollingInterval;
  668. else
  669. return keepAliveInterval;
  670. default:
  671. throw Fx.AssertAndThrow("Unknown polling mode.");
  672. }
  673. }
  674. public override void OnFaulted()
  675. {
  676. base.OnFaulted();
  677. ReliableRequestor temp = this.requestor;
  678. if (temp != null)
  679. this.requestor.Fault(this.Channel);
  680. }
  681. void OnPollingTimerElapsed(object state)
  682. {
  683. if (this.Guard.Enter())
  684. {
  685. try
  686. {
  687. lock (this.ThisLock)
  688. {
  689. if (this.pollingMode == PollingMode.NotPolling)
  690. return;
  691. if (this.pollingMode == PollingMode.Idle)
  692. this.pollingMode = PollingMode.KeepAlive;
  693. }
  694. this.pollingHandler();
  695. this.pollingTimer.Set(this.GetPollingInterval());
  696. }
  697. finally
  698. {
  699. this.Guard.Exit();
  700. }
  701. }
  702. }
  703. public override void OnLocalActivity()
  704. {
  705. lock (this.ThisLock)
  706. {
  707. if (this.pollingMode == PollingMode.NotPolling)
  708. return;
  709. this.pollingTimer.Set(this.GetPollingInterval());
  710. }
  711. }
  712. public override void Open(TimeSpan timeout)
  713. {
  714. if (this.pollingHandler == null)
  715. {
  716. throw Fx.AssertAndThrow("The client reliable channel must set the polling handler prior to opening the client reliable session.");
  717. }
  718. DateTime start = DateTime.UtcNow;
  719. Message response = this.requestor.Request(timeout);
  720. this.ProcessCreateSequenceResponse(response, start);
  721. this.requestor = null;
  722. }
  723. public override void OnRemoteActivity(bool fastPolling)
  724. {
  725. base.OnRemoteActivity(fastPolling);
  726. lock (this.ThisLock)
  727. {
  728. if (this.pollingMode == PollingMode.NotPolling)
  729. return;
  730. if (fastPolling)
  731. this.pollingMode = PollingMode.FastPolling;
  732. else
  733. this.pollingMode = PollingMode.Idle;
  734. this.pollingTimer.Set(this.GetPollingInterval());
  735. }
  736. }
  737. void ProcessCreateSequenceResponse(Message response, DateTime start)
  738. {
  739. CreateSequenceResponseInfo createResponse = null;
  740. using (response)
  741. {
  742. if (response.IsFault)
  743. {
  744. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WsrmUtilities.CreateCSFaultException(
  745. this.Settings.MessageVersion, this.Settings.ReliableMessagingVersion, response,
  746. this.binder.Channel));
  747. }
  748. else
  749. {
  750. WsrmMessageInfo info = WsrmMessageInfo.Get(this.Settings.MessageVersion,
  751. this.Settings.ReliableMessagingVersion, this.binder.Channel, this.binder.GetInnerSession(),
  752. response, true);
  753. if (info.ParsingException != null)
  754. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(SR.GetString(SR.UnparsableCSResponse), info.ParsingException));
  755. // this throws and sends a fault if something is wrong with the info
  756. this.ProcessInfo(info, null, true);
  757. createResponse = info.CreateSequenceResponseInfo;
  758. string exceptionReason = null;
  759. string faultReason = null;
  760. if (createResponse == null)
  761. {
  762. exceptionReason = SR.GetString(SR.InvalidWsrmResponseChannelNotOpened,
  763. WsrmFeb2005Strings.CreateSequence, info.Action,
  764. WsrmIndex.GetCreateSequenceResponseActionString(this.Settings.ReliableMessagingVersion));
  765. }
  766. else if (!object.Equals(createResponse.RelatesTo, this.requestor.MessageId))
  767. {
  768. exceptionReason = SR.GetString(SR.WsrmMessageWithWrongRelatesToExceptionString, WsrmFeb2005Strings.CreateSequence);
  769. faultReason = SR.GetString(SR.WsrmMessageWithWrongRelatesToFaultString, WsrmFeb2005Strings.CreateSequence);
  770. }
  771. else if ((createResponse.AcceptAcksTo == null) && (this.InputID != null))
  772. {
  773. if (this.Settings.ReliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
  774. {
  775. exceptionReason = SR.GetString(SR.CSResponseWithoutOffer);
  776. faultReason = SR.GetString(SR.CSResponseWithoutOfferReason);
  777. }
  778. else if (this.Settings.ReliableMessagingVersion == ReliableMessagingVersion.WSReliableMessaging11)
  779. {
  780. exceptionReason = SR.GetString(SR.CSResponseOfferRejected);
  781. faultReason = SR.GetString(SR.CSResponseOfferRejectedReason);
  782. }
  783. else
  784. {
  785. throw Fx.AssertAndThrow("Reliable messaging version not supported.");
  786. }
  787. }
  788. else if ((createResponse.AcceptAcksTo != null) && (this.InputID == null))
  789. {
  790. exceptionReason = SR.GetString(SR.CSResponseWithOffer);
  791. faultReason = SR.GetString(SR.CSResponseWithOfferReason);
  792. }
  793. else if (createResponse.AcceptAcksTo != null && (createResponse.AcceptAcksTo.Uri != this.binder.RemoteAddress.Uri))
  794. {
  795. exceptionReason = SR.GetString(SR.AcksToMustBeSameAsRemoteAddress);
  796. faultReason = SR.GetString(SR.AcksToMustBeSameAsRemoteAddressReason);
  797. }
  798. if ((faultReason != null) && (createResponse != null))
  799. {
  800. UniqueId sequenceId = createResponse.Identifier;
  801. WsrmFault fault = SequenceTerminatedFault.CreateProtocolFault(sequenceId, faultReason, null);
  802. this.OnLocalFault(null, fault, null);
  803. }
  804. if (exceptionReason != null)
  805. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(exceptionReason));
  806. }
  807. }
  808. this.InitiationTime = DateTime.UtcNow - start;
  809. this.OutputID = createResponse.Identifier;
  810. this.pollingTimer.Set(this.GetPollingInterval());
  811. base.StartInactivityTimer();
  812. }
  813. public void ResumePolling(bool fastPolling)
  814. {
  815. lock (this.ThisLock)
  816. {
  817. if (this.pollingMode != PollingMode.NotPolling)
  818. {
  819. throw Fx.AssertAndThrow("Can't resume polling if pollingMode != PollingMode.NotPolling");
  820. }
  821. if (fastPolling)
  822. {
  823. this.pollingMode = PollingMode.FastPolling;
  824. }
  825. else
  826. {
  827. if (this.oldPollingMode == PollingMode.FastPolling)
  828. this.pollingMode = PollingMode.Idle;
  829. else
  830. this.pollingMode = this.oldPollingMode;
  831. }
  832. this.Guard.Exit();
  833. this.pollingTimer.Set(this.GetPollingInterval());
  834. }
  835. }
  836. // Returns true if caller should resume polling
  837. public bool StopPolling()
  838. {
  839. lock (this.ThisLock)
  840. {
  841. if (this.pollingMode == PollingMode.NotPolling)
  842. return false;
  843. this.oldPollingMode = pollingMode;
  844. this.pollingMode = PollingMode.NotPolling;
  845. this.pollingTimer.Cancel();
  846. return this.Guard.Enter();
  847. }
  848. }
  849. protected override WsrmFault VerifyDuplexProtocolElements(WsrmMessageInfo info)
  850. {
  851. WsrmFault fault = base.VerifyDuplexProtocolElements(info);
  852. if (fault != null)
  853. return fault;
  854. else if (info.CreateSequenceInfo != null)
  855. return SequenceTerminatedFault.CreateProtocolFault(this.OutputID, SR.GetString(SR.SequenceTerminatedUnexpectedCS), SR.GetString(SR.UnexpectedCS));
  856. else if (info.CreateSequenceResponseInfo != null && info.CreateSequenceResponseInfo.Identifier != this.OutputID)
  857. return SequenceTerminatedFault.CreateProtocolFault(this.OutputID, SR.GetString(SR.SequenceTerminatedUnexpectedCSROfferId), SR.GetString(SR.UnexpectedCSROfferId));
  858. else
  859. return null;
  860. }
  861. protected override WsrmFault VerifySimplexProtocolElements(WsrmMessageInfo info)
  862. {
  863. if (info.AcknowledgementInfo != null && info.AcknowledgementInfo.SequenceID != this.OutputID)
  864. return new UnknownSequenceFault(info.AcknowledgementInfo.SequenceID);
  865. else if (info.AckRequestedInfo != null)
  866. return SequenceTerminatedFault.CreateProtocolFault(this.OutputID, SR.GetString(SR.SequenceTerminatedUnexpectedAckRequested), SR.GetString(SR.UnexpectedAckRequested));
  867. else if (info.CreateSequenceInfo != null)
  868. return SequenceTerminatedFault.CreateProtocolFault(this.OutputID, SR.GetString(SR.SequenceTerminatedUnexpectedCS), SR.GetString(SR.UnexpectedCS));
  869. else if (info.SequencedMessageInfo != null)
  870. return new UnknownSequenceFault(info.SequencedMessageInfo.SequenceID);
  871. else if (info.TerminateSequenceInfo != null)
  872. {
  873. if (this.Settings.ReliableMessagingVersion == ReliableMessagingVersion.WSReliableMessagingFebruary2005)
  874. return SequenceTerminatedFault.CreateProtocolFault(this.OutputID, SR.GetString(SR.SequenceTerminatedUnexpectedTerminateSequence), SR.GetString(SR.UnexpectedTerminateSequence));
  875. else if (info.TerminateSequenceInfo.Identifier == this.OutputID)
  876. return null;
  877. else
  878. return new UnknownSequenceFault(info.TerminateSequenceInfo.Identifier);
  879. }
  880. else if (info.TerminateSequenceResponseInfo != null)
  881. {
  882. WsrmUtilities.AssertWsrm11(this.Settings.ReliableMessagingVersion);
  883. if (info.TerminateSequenceResponseInfo.Identifier == this.OutputID)
  884. return null;
  885. else
  886. return new UnknownSequenceFault(info.TerminateSequenceResponseInfo.Identifier);
  887. }
  888. else if (info.CloseSequenceInfo != null)
  889. {
  890. WsrmUtilities.AssertWsrm11(this.Settings.ReliableMessagingVersion);
  891. if (info.CloseSequenceInfo.Identifier == this.OutputID)
  892. return SequenceTerminatedFault.CreateProtocolFault(this.OutputID, SR.GetString(SR.SequenceTerminatedUnsupportedClose), SR.GetString(SR.UnsupportedCloseExceptionString));
  893. else
  894. return new UnknownSequenceFault(info.CloseSequenceInfo.Identifier);
  895. }
  896. else if (info.CloseSequenceResponseInfo != null)
  897. {
  898. WsrmUtilities.AssertWsrm11(this.Settings.ReliableMessagingVersion);
  899. if (info.CloseSequenceResponseInfo.Identifier == this.OutputID)
  900. return null;
  901. else
  902. return new UnknownSequenceFault(info.CloseSequenceResponseInfo.Identifier);
  903. }
  904. else
  905. return null;
  906. }
  907. class OpenAsyncResult : AsyncResult
  908. {
  909. static AsyncCallback onRequestComplete = Fx.ThunkCallback(new AsyncCallback(OnRequestCompleteStatic));
  910. ClientReliableSession session;
  911. DateTime start;
  912. public OpenAsyncResult(ClientReliableSession session, TimeSpan timeout, AsyncCallback callback, object state)
  913. : base(callback, state)
  914. {
  915. this.session = session;
  916. this.start = DateTime.UtcNow;
  917. IAsyncResult result = this.session.requestor.BeginRequest(timeout, onRequestComplete, this);
  918. if (result.CompletedSynchronously)
  919. {
  920. this.CompleteRequest(result);
  921. this.Complete(true);
  922. }
  923. }
  924. void CompleteRequest(IAsyncResult result)
  925. {
  926. Message response = this.session.requestor.EndRequest(result);
  927. this.session.ProcessCreateSequenceResponse(response, this.start);
  928. }
  929. public static void End(IAsyncResult result)
  930. {
  931. AsyncResult.End<OpenAsyncResult>(result);
  932. }
  933. static void OnRequestCompleteStatic(IAsyncResult result)
  934. {
  935. if (result.CompletedSynchronously)
  936. return;
  937. OpenAsyncResult openResult = (OpenAsyncResult)result.AsyncState;
  938. Exception exception = null;
  939. try
  940. {
  941. openResult.CompleteRequest(result);
  942. }
  943. catch (Exception e)
  944. {
  945. if (Fx.IsFatal(e))
  946. throw;
  947. exception = e;
  948. }
  949. openResult.Complete(false, exception);
  950. }
  951. }
  952. enum PollingMode
  953. {
  954. Idle,
  955. KeepAlive,
  956. FastPolling,
  957. NotPolling
  958. }
  959. }
  960. class ServerReliableSession : ChannelReliableSession, IInputSession
  961. {
  962. public ServerReliableSession(
  963. ChannelBase channel,
  964. IReliableFactorySettings listener,
  965. IServerReliableChannelBinder binder,
  966. FaultHelper faultHelper,
  967. UniqueId inputID,
  968. UniqueId outputID)
  969. : base(channel, listener, binder, faultHelper)
  970. {
  971. this.InputID = inputID;
  972. this.OutputID = outputID;
  973. }
  974. public override UniqueId SequenceID
  975. {
  976. get
  977. {
  978. return this.InputID;
  979. }
  980. }
  981. public override IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
  982. {
  983. return new CompletedAsyncResult(callback, state);
  984. }
  985. public override void EndOpen(IAsyncResult result)
  986. {
  987. CompletedAsyncResult.End(result);
  988. base.StartInactivityTimer();
  989. }
  990. public override void OnLocalActivity()
  991. {
  992. }
  993. public override void Open(TimeSpan timeout)
  994. {
  995. this.StartInactivityTimer();
  996. }
  997. protected override WsrmFault VerifyDuplexProtocolElements(WsrmMessageInfo info)
  998. {
  999. WsrmFault fault = base.VerifyDuplexProtocolElements(info);
  1000. if (fault != null)
  1001. return fault;
  1002. else if (info.CreateSequenceInfo != null && info.CreateSequenceInfo.OfferIdentifier != this.OutputID)
  1003. return SequenceTerminatedFault.CreateProtocolFault(this.OutputID, SR.GetString(SR.SequenceTerminatedUnexpectedCSOfferId), SR.GetString(SR.UnexpectedCSOfferId));
  1004. else if (info.CreateSequenceResponseInfo != null)
  1005. return SequenceTerminatedFault.CreateProtocolFault(this.OutputID, SR.GetString(SR.SequenceTerminatedUnexpectedCSR), SR.GetString(SR.UnexpectedCSR));
  1006. else
  1007. return null;
  1008. }
  1009. protected override WsrmFault VerifySimplexProtocolElements(WsrmMessageInfo info)
  1010. {
  1011. if (info.AcknowledgementInfo != null)
  1012. return SequenceTerminatedFault.CreateProtocolFault(this.InputID, SR.GetString(SR.SequenceTerminatedUnexpectedAcknowledgement), SR.GetString(SR.UnexpectedAcknowledgement));
  1013. else if (info.AckRequestedInfo != null && info.AckRequestedInfo.SequenceID != this.InputID)
  1014. return new UnknownSequenceFault(info.AckRequestedInfo.SequenceID);
  1015. else if (info.CreateSequenceResponseInfo != null)
  1016. return SequenceTerminatedFault.CreateProtocolFault(this.InputID, SR.GetString(SR.SequenceTerminatedUnexpectedCSR), SR.GetString(SR.UnexpectedCSR));
  1017. else if (info.SequencedMessageInfo != null && info.SequencedMessageInfo.SequenceID != this.InputID)
  1018. return new UnknownSequenceFault(info.SequencedMessageInfo.SequenceID);
  1019. else if (info.TerminateSequenceInfo != null && info.TerminateSequenceInfo.Identifier != this.InputID)
  1020. return new UnknownSequenceFault(info.TerminateSequenceInfo.Identifier);
  1021. else if (info.TerminateSequenceResponseInfo != null)
  1022. {
  1023. WsrmUtilities.AssertWsrm11(this.Settings.ReliableMessagingVersion);
  1024. if (info.TerminateSequenceResponseInfo.Identifier == this.InputID)
  1025. return SequenceTerminatedFault.CreateProtocolFault(this.InputID, SR.GetString(SR.SequenceTerminatedUnexpectedTerminateSequenceResponse), SR.GetString(SR.UnexpectedTerminateSequenceResponse));
  1026. else
  1027. return new UnknownSequenceFault(info.TerminateSequenceResponseInfo.Identifier);
  1028. }
  1029. else if (info.CloseSequenceInfo != null)
  1030. {
  1031. WsrmUtilities.AssertWsrm11(this.Settings.ReliableMessagingVersion);
  1032. if (info.CloseSequenceInfo.Identifier == this.InputID)
  1033. return null;
  1034. else
  1035. return new UnknownSequenceFault(info.CloseSequenceInfo.Identifier);
  1036. }
  1037. else if (info.CloseSequenceResponseInfo != null)
  1038. {
  1039. WsrmUtilities.AssertWsrm11(this.Settings.ReliableMessagingVersion);
  1040. if (info.CloseSequenceResponseInfo.Identifier == this.InputID)
  1041. return SequenceTerminatedFault.CreateProtocolFault(this.InputID, SR.GetString(SR.SequenceTerminatedUnexpectedCloseSequenceResponse), SR.GetString(SR.UnexpectedCloseSequenceResponse));
  1042. else
  1043. return new UnknownSequenceFault(info.CloseSequenceResponseInfo.Identifier);
  1044. }
  1045. else
  1046. return null;
  1047. }
  1048. }
  1049. }