ServiceChannel.cs 94 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Channels
  5. {
  6. using System.Collections.Generic;
  7. using System.Diagnostics;
  8. using System.Globalization;
  9. using System.Runtime;
  10. using System.Runtime.Diagnostics;
  11. using System.ServiceModel;
  12. using System.ServiceModel.Activation;
  13. using System.ServiceModel.Description;
  14. using System.ServiceModel.Diagnostics;
  15. using System.ServiceModel.Diagnostics.Application;
  16. using System.ServiceModel.Dispatcher;
  17. using System.ServiceModel.Security;
  18. using System.Threading;
  19. // This class is sealed because the constructor could call Abort, which is virtual
  20. sealed class ServiceChannel : CommunicationObject, IChannel, IClientChannel, IDuplexContextChannel, IOutputChannel, IRequestChannel, IServiceChannel
  21. {
  22. int activityCount = 0;
  23. bool allowInitializationUI = true;
  24. bool allowOutputBatching = false;
  25. bool autoClose = true;
  26. CallOnceManager autoDisplayUIManager;
  27. CallOnceManager autoOpenManager;
  28. readonly IChannelBinder binder;
  29. readonly ChannelDispatcher channelDispatcher;
  30. ClientRuntime clientRuntime;
  31. readonly bool closeBinder = true;
  32. bool closeFactory;
  33. bool didInteractiveInitialization;
  34. bool doneReceiving;
  35. EndpointDispatcher endpointDispatcher;
  36. bool explicitlyOpened;
  37. ExtensionCollection<IContextChannel> extensions;
  38. readonly ServiceChannelFactory factory;
  39. readonly bool hasSession;
  40. readonly SessionIdleManager idleManager;
  41. InstanceContext instanceContext;
  42. ServiceThrottle instanceContextServiceThrottle;
  43. bool isPending;
  44. readonly bool isReplyChannel;
  45. EndpointAddress localAddress;
  46. readonly MessageVersion messageVersion;
  47. readonly bool openBinder = false;
  48. TimeSpan operationTimeout;
  49. object proxy;
  50. ServiceThrottle serviceThrottle;
  51. string terminatingOperationName;
  52. InstanceContext wmiInstanceContext;
  53. bool hasChannelStartedAutoClosing;
  54. bool hasIncrementedBusyCount;
  55. bool hasCleanedUpChannelCollections;
  56. EventTraceActivity eventActivity;
  57. EventHandler<UnknownMessageReceivedEventArgs> unknownMessageReceived;
  58. ServiceChannel(IChannelBinder binder, MessageVersion messageVersion, IDefaultCommunicationTimeouts timeouts)
  59. {
  60. if (binder == null)
  61. {
  62. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("binder");
  63. }
  64. this.messageVersion = messageVersion;
  65. this.binder = binder;
  66. this.isReplyChannel = this.binder.Channel is IReplyChannel;
  67. IChannel innerChannel = binder.Channel;
  68. this.hasSession = (innerChannel is ISessionChannel<IDuplexSession>) ||
  69. (innerChannel is ISessionChannel<IInputSession>) ||
  70. (innerChannel is ISessionChannel<IOutputSession>);
  71. this.IncrementActivity();
  72. this.openBinder = (binder.Channel.State == CommunicationState.Created);
  73. this.operationTimeout = timeouts.SendTimeout;
  74. }
  75. internal ServiceChannel(ServiceChannelFactory factory, IChannelBinder binder)
  76. : this(binder, factory.MessageVersion, factory)
  77. {
  78. this.factory = factory;
  79. this.clientRuntime = factory.ClientRuntime;
  80. this.SetupInnerChannelFaultHandler();
  81. DispatchRuntime dispatch = factory.ClientRuntime.DispatchRuntime;
  82. if (dispatch != null)
  83. {
  84. this.autoClose = dispatch.AutomaticInputSessionShutdown;
  85. }
  86. factory.ChannelCreated(this);
  87. }
  88. internal ServiceChannel(IChannelBinder binder,
  89. EndpointDispatcher endpointDispatcher,
  90. ChannelDispatcher channelDispatcher,
  91. SessionIdleManager idleManager)
  92. : this(binder, channelDispatcher.MessageVersion, channelDispatcher.DefaultCommunicationTimeouts)
  93. {
  94. if (endpointDispatcher == null)
  95. {
  96. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointDispatcher");
  97. }
  98. this.channelDispatcher = channelDispatcher;
  99. this.endpointDispatcher = endpointDispatcher;
  100. this.clientRuntime = endpointDispatcher.DispatchRuntime.CallbackClientRuntime;
  101. this.SetupInnerChannelFaultHandler();
  102. this.autoClose = endpointDispatcher.DispatchRuntime.AutomaticInputSessionShutdown;
  103. this.isPending = true;
  104. IDefaultCommunicationTimeouts timeouts = channelDispatcher.DefaultCommunicationTimeouts;
  105. this.idleManager = idleManager;
  106. if (!binder.HasSession)
  107. this.closeBinder = false;
  108. if (this.idleManager != null)
  109. {
  110. bool didIdleAbort;
  111. this.idleManager.RegisterChannel(this, out didIdleAbort);
  112. if (didIdleAbort)
  113. {
  114. this.Abort();
  115. }
  116. }
  117. }
  118. CallOnceManager AutoOpenManager
  119. {
  120. get
  121. {
  122. if (!this.explicitlyOpened && (this.autoOpenManager == null))
  123. {
  124. this.EnsureAutoOpenManagers();
  125. }
  126. return this.autoOpenManager;
  127. }
  128. }
  129. CallOnceManager AutoDisplayUIManager
  130. {
  131. get
  132. {
  133. if (!this.explicitlyOpened && (this.autoDisplayUIManager == null))
  134. {
  135. this.EnsureAutoOpenManagers();
  136. }
  137. return this.autoDisplayUIManager;
  138. }
  139. }
  140. internal EventTraceActivity EventActivity
  141. {
  142. get
  143. {
  144. if (this.eventActivity == null)
  145. {
  146. //Take the id on the thread so that we know the initiating operation.
  147. this.eventActivity = EventTraceActivity.GetFromThreadOrCreate();
  148. }
  149. return this.eventActivity;
  150. }
  151. }
  152. internal bool CloseFactory
  153. {
  154. get { return this.closeFactory; }
  155. set { this.closeFactory = value; }
  156. }
  157. protected override TimeSpan DefaultCloseTimeout
  158. {
  159. get { return this.CloseTimeout; }
  160. }
  161. protected override TimeSpan DefaultOpenTimeout
  162. {
  163. get { return this.OpenTimeout; }
  164. }
  165. internal DispatchRuntime DispatchRuntime
  166. {
  167. get
  168. {
  169. if (this.endpointDispatcher != null)
  170. {
  171. return this.endpointDispatcher.DispatchRuntime;
  172. }
  173. if (this.clientRuntime != null)
  174. {
  175. return this.clientRuntime.DispatchRuntime;
  176. }
  177. return null;
  178. }
  179. }
  180. internal MessageVersion MessageVersion
  181. {
  182. get { return this.messageVersion; }
  183. }
  184. internal IChannelBinder Binder
  185. {
  186. get { return this.binder; }
  187. }
  188. internal TimeSpan CloseTimeout
  189. {
  190. get
  191. {
  192. if (this.IsClient)
  193. {
  194. return factory.InternalCloseTimeout;
  195. }
  196. else
  197. {
  198. return this.ChannelDispatcher.InternalCloseTimeout;
  199. }
  200. }
  201. }
  202. internal ChannelDispatcher ChannelDispatcher
  203. {
  204. get { return this.channelDispatcher; }
  205. }
  206. internal EndpointDispatcher EndpointDispatcher
  207. {
  208. get { return this.endpointDispatcher; }
  209. set
  210. {
  211. lock (this.ThisLock)
  212. {
  213. this.endpointDispatcher = value;
  214. this.clientRuntime = value.DispatchRuntime.CallbackClientRuntime;
  215. }
  216. }
  217. }
  218. internal ServiceChannelFactory Factory
  219. {
  220. get { return this.factory; }
  221. }
  222. internal IChannel InnerChannel
  223. {
  224. get { return this.binder.Channel; }
  225. }
  226. internal bool IsPending
  227. {
  228. get { return this.isPending; }
  229. set { this.isPending = value; }
  230. }
  231. internal bool HasSession
  232. {
  233. get { return hasSession; }
  234. }
  235. internal bool IsClient
  236. {
  237. get { return this.factory != null; }
  238. }
  239. internal bool IsReplyChannel
  240. {
  241. get { return this.isReplyChannel; }
  242. }
  243. public Uri ListenUri
  244. {
  245. get
  246. {
  247. return this.binder.ListenUri;
  248. }
  249. }
  250. public EndpointAddress LocalAddress
  251. {
  252. get
  253. {
  254. if (this.localAddress == null)
  255. {
  256. if (this.endpointDispatcher != null)
  257. {
  258. this.localAddress = this.endpointDispatcher.EndpointAddress;
  259. }
  260. else
  261. {
  262. this.localAddress = this.binder.LocalAddress;
  263. }
  264. }
  265. return this.localAddress;
  266. }
  267. }
  268. internal TimeSpan OpenTimeout
  269. {
  270. get
  271. {
  272. if (this.IsClient)
  273. {
  274. return factory.InternalOpenTimeout;
  275. }
  276. else
  277. {
  278. return this.ChannelDispatcher.InternalOpenTimeout;
  279. }
  280. }
  281. }
  282. public TimeSpan OperationTimeout
  283. {
  284. get { return this.operationTimeout; }
  285. set
  286. {
  287. if (value < TimeSpan.Zero)
  288. {
  289. string message = SR.GetString(SR.SFxTimeoutOutOfRange0);
  290. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value, message));
  291. }
  292. if (TimeoutHelper.IsTooLarge(value))
  293. {
  294. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value, SR.GetString(SR.SFxTimeoutOutOfRangeTooBig)));
  295. }
  296. this.operationTimeout = value;
  297. }
  298. }
  299. internal object Proxy
  300. {
  301. get
  302. {
  303. object proxy = this.proxy;
  304. if (proxy != null)
  305. return proxy;
  306. else
  307. return this;
  308. }
  309. set
  310. {
  311. this.proxy = value;
  312. base.EventSender = value; // need to use "proxy" as open/close event source
  313. }
  314. }
  315. internal ClientRuntime ClientRuntime
  316. {
  317. get { return this.clientRuntime; }
  318. }
  319. public EndpointAddress RemoteAddress
  320. {
  321. get
  322. {
  323. IOutputChannel outputChannel = this.InnerChannel as IOutputChannel;
  324. if (outputChannel != null)
  325. return outputChannel.RemoteAddress;
  326. IRequestChannel requestChannel = this.InnerChannel as IRequestChannel;
  327. if (requestChannel != null)
  328. return requestChannel.RemoteAddress;
  329. return null;
  330. }
  331. }
  332. ProxyOperationRuntime UnhandledProxyOperation
  333. {
  334. get { return this.ClientRuntime.GetRuntime().UnhandledProxyOperation; }
  335. }
  336. public Uri Via
  337. {
  338. get
  339. {
  340. IOutputChannel outputChannel = this.InnerChannel as IOutputChannel;
  341. if (outputChannel != null)
  342. return outputChannel.Via;
  343. IRequestChannel requestChannel = this.InnerChannel as IRequestChannel;
  344. if (requestChannel != null)
  345. return requestChannel.Via;
  346. return null;
  347. }
  348. }
  349. internal InstanceContext InstanceContext
  350. {
  351. get { return this.instanceContext; }
  352. set { this.instanceContext = value; }
  353. }
  354. internal ServiceThrottle InstanceContextServiceThrottle
  355. {
  356. get { return this.instanceContextServiceThrottle; }
  357. set { this.instanceContextServiceThrottle = value; }
  358. }
  359. internal ServiceThrottle ServiceThrottle
  360. {
  361. get { return this.serviceThrottle; }
  362. set
  363. {
  364. this.ThrowIfDisposed();
  365. this.serviceThrottle = value;
  366. }
  367. }
  368. internal InstanceContext WmiInstanceContext
  369. {
  370. get { return this.wmiInstanceContext; }
  371. set { this.wmiInstanceContext = value; }
  372. }
  373. void SetupInnerChannelFaultHandler()
  374. {
  375. // need to call this method after this.binder and this.clientRuntime are set to prevent a potential
  376. // NullReferenceException in this method or in the OnInnerChannelFaulted method;
  377. // because this method accesses this.binder and OnInnerChannelFaulted acesses this.clientRuntime.
  378. this.binder.Channel.Faulted += OnInnerChannelFaulted;
  379. }
  380. void BindDuplexCallbacks()
  381. {
  382. IDuplexChannel duplexChannel = this.InnerChannel as IDuplexChannel;
  383. if ((duplexChannel != null) && (this.factory != null) && (this.instanceContext != null))
  384. {
  385. if (this.binder is DuplexChannelBinder)
  386. ((DuplexChannelBinder)this.binder).EnsurePumping();
  387. }
  388. }
  389. internal bool CanCastTo(Type t)
  390. {
  391. if (t.IsAssignableFrom(typeof(IClientChannel)))
  392. return true;
  393. if (t.IsAssignableFrom(typeof(IDuplexContextChannel)))
  394. return this.InnerChannel is IDuplexChannel;
  395. if (t.IsAssignableFrom(typeof(IServiceChannel)))
  396. return true;
  397. return false;
  398. }
  399. internal void CompletedIOOperation()
  400. {
  401. if (this.idleManager != null)
  402. {
  403. this.idleManager.CompletedActivity();
  404. }
  405. }
  406. void EnsureAutoOpenManagers()
  407. {
  408. lock (this.ThisLock)
  409. {
  410. if (!this.explicitlyOpened)
  411. {
  412. if (this.autoOpenManager == null)
  413. {
  414. this.autoOpenManager = new CallOnceManager(this, CallOpenOnce.Instance);
  415. }
  416. if (this.autoDisplayUIManager == null)
  417. {
  418. this.autoDisplayUIManager = new CallOnceManager(this, CallDisplayUIOnce.Instance);
  419. }
  420. }
  421. }
  422. }
  423. void EnsureDisplayUI()
  424. {
  425. CallOnceManager manager = this.AutoDisplayUIManager;
  426. if (manager != null)
  427. {
  428. manager.CallOnce(TimeSpan.MaxValue, null);
  429. }
  430. this.ThrowIfInitializationUINotCalled();
  431. }
  432. IAsyncResult BeginEnsureDisplayUI(AsyncCallback callback, object state)
  433. {
  434. CallOnceManager manager = this.AutoDisplayUIManager;
  435. if (manager != null)
  436. {
  437. return manager.BeginCallOnce(TimeSpan.MaxValue, null, callback, state);
  438. }
  439. else
  440. {
  441. return new CallOnceCompletedAsyncResult(callback, state);
  442. }
  443. }
  444. void EndEnsureDisplayUI(IAsyncResult result)
  445. {
  446. CallOnceManager manager = this.AutoDisplayUIManager;
  447. if (manager != null)
  448. {
  449. manager.EndCallOnce(result);
  450. }
  451. else
  452. {
  453. CallOnceCompletedAsyncResult.End(result);
  454. }
  455. this.ThrowIfInitializationUINotCalled();
  456. }
  457. void EnsureOpened(TimeSpan timeout)
  458. {
  459. CallOnceManager manager = this.AutoOpenManager;
  460. if (manager != null)
  461. {
  462. manager.CallOnce(timeout, this.autoDisplayUIManager);
  463. }
  464. this.ThrowIfOpening();
  465. this.ThrowIfDisposedOrNotOpen();
  466. }
  467. IAsyncResult BeginEnsureOpened(TimeSpan timeout, AsyncCallback callback, object state)
  468. {
  469. CallOnceManager manager = this.AutoOpenManager;
  470. if (manager != null)
  471. {
  472. return manager.BeginCallOnce(timeout, this.autoDisplayUIManager, callback, state);
  473. }
  474. else
  475. {
  476. this.ThrowIfOpening();
  477. this.ThrowIfDisposedOrNotOpen();
  478. return new CallOnceCompletedAsyncResult(callback, state);
  479. }
  480. }
  481. void EndEnsureOpened(IAsyncResult result)
  482. {
  483. CallOnceManager manager = this.AutoOpenManager;
  484. if (manager != null)
  485. {
  486. manager.EndCallOnce(result);
  487. }
  488. else
  489. {
  490. CallOnceCompletedAsyncResult.End(result);
  491. }
  492. }
  493. public T GetProperty<T>() where T : class
  494. {
  495. IChannel innerChannel = this.InnerChannel;
  496. if (innerChannel != null)
  497. return innerChannel.GetProperty<T>();
  498. return null;
  499. }
  500. void PrepareCall(ProxyOperationRuntime operation, bool oneway, ref ProxyRpc rpc)
  501. {
  502. OperationContext context = OperationContext.Current;
  503. // Doing a request reply callback when dispatching in-order deadlocks.
  504. // We never receive the reply until we finish processing the current message.
  505. if (!oneway)
  506. {
  507. DispatchRuntime dispatchBehavior = this.ClientRuntime.DispatchRuntime;
  508. if ((dispatchBehavior != null) && (dispatchBehavior.ConcurrencyMode == ConcurrencyMode.Single))
  509. {
  510. if ((context != null) && (!context.IsUserContext) && (context.InternalServiceChannel == this))
  511. {
  512. if (dispatchBehavior.IsOnServer)
  513. {
  514. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCallbackRequestReplyInOrder1, typeof(ServiceBehaviorAttribute).Name)));
  515. }
  516. else
  517. {
  518. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCallbackRequestReplyInOrder1, typeof(CallbackBehaviorAttribute).Name)));
  519. }
  520. }
  521. }
  522. }
  523. if ((this.State == CommunicationState.Created) && !operation.IsInitiating)
  524. {
  525. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxNonInitiatingOperation1, operation.Name)));
  526. }
  527. if (this.terminatingOperationName != null)
  528. {
  529. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxTerminatingOperationAlreadyCalled1, this.terminatingOperationName)));
  530. }
  531. if (this.hasChannelStartedAutoClosing)
  532. {
  533. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(SR.GetString(SR.SFxClientOutputSessionAutoClosed)));
  534. }
  535. operation.BeforeRequest(ref rpc);
  536. AddMessageProperties(rpc.Request, context);
  537. if (!oneway && !this.ClientRuntime.ManualAddressing && rpc.Request.Version.Addressing != AddressingVersion.None)
  538. {
  539. RequestReplyCorrelator.PrepareRequest(rpc.Request);
  540. MessageHeaders headers = rpc.Request.Headers;
  541. EndpointAddress localAddress = this.LocalAddress;
  542. EndpointAddress replyTo = headers.ReplyTo;
  543. if (replyTo == null)
  544. {
  545. headers.ReplyTo = localAddress ?? EndpointAddress.AnonymousAddress;
  546. }
  547. if (this.IsClient && (localAddress != null) && !localAddress.IsAnonymous)
  548. {
  549. Uri localUri = localAddress.Uri;
  550. if ((replyTo != null) && !replyTo.IsAnonymous && (localUri != replyTo.Uri))
  551. {
  552. string text = SR.GetString(SR.SFxRequestHasInvalidReplyToOnClient, replyTo.Uri, localUri);
  553. Exception error = new InvalidOperationException(text);
  554. throw TraceUtility.ThrowHelperError(error, rpc.Request);
  555. }
  556. EndpointAddress faultTo = headers.FaultTo;
  557. if ((faultTo != null) && !faultTo.IsAnonymous && (localUri != faultTo.Uri))
  558. {
  559. string text = SR.GetString(SR.SFxRequestHasInvalidFaultToOnClient, faultTo.Uri, localUri);
  560. Exception error = new InvalidOperationException(text);
  561. throw TraceUtility.ThrowHelperError(error, rpc.Request);
  562. }
  563. if (this.messageVersion.Addressing == AddressingVersion.WSAddressingAugust2004)
  564. {
  565. EndpointAddress from = headers.From;
  566. if ((from != null) && !from.IsAnonymous && (localUri != from.Uri))
  567. {
  568. string text = SR.GetString(SR.SFxRequestHasInvalidFromOnClient, from.Uri, localUri);
  569. Exception error = new InvalidOperationException(text);
  570. throw TraceUtility.ThrowHelperError(error, rpc.Request);
  571. }
  572. }
  573. }
  574. }
  575. if (TraceUtility.MessageFlowTracingOnly)
  576. {
  577. //always set a new ID if none provided
  578. if (Trace.CorrelationManager.ActivityId == Guid.Empty)
  579. {
  580. rpc.ActivityId = Guid.NewGuid();
  581. FxTrace.Trace.SetAndTraceTransfer(rpc.ActivityId, true);
  582. }
  583. }
  584. if (rpc.Activity != null)
  585. {
  586. TraceUtility.SetActivity(rpc.Request, rpc.Activity);
  587. if (TraceUtility.ShouldPropagateActivity)
  588. {
  589. TraceUtility.AddActivityHeader(rpc.Request);
  590. }
  591. }
  592. else if (TraceUtility.PropagateUserActivity || TraceUtility.ShouldPropagateActivity)
  593. {
  594. TraceUtility.AddAmbientActivityToMessage(rpc.Request);
  595. }
  596. operation.Parent.BeforeSendRequest(ref rpc);
  597. //Attach and transfer Activity
  598. if (FxTrace.Trace.IsEnd2EndActivityTracingEnabled)
  599. {
  600. TraceClientOperationPrepared(ref rpc);
  601. }
  602. TraceUtility.MessageFlowAtMessageSent(rpc.Request, rpc.EventTraceActivity);
  603. if (MessageLogger.LogMessagesAtServiceLevel)
  604. {
  605. MessageLogger.LogMessage(ref rpc.Request, (oneway ? MessageLoggingSource.ServiceLevelSendDatagram : MessageLoggingSource.ServiceLevelSendRequest) | MessageLoggingSource.LastChance);
  606. }
  607. }
  608. private void TraceClientOperationPrepared(ref ProxyRpc rpc)
  609. {
  610. //Retrieve the old id on the RPC and attach the id on the message since we have a message id now.
  611. Guid previousId = rpc.EventTraceActivity != null ? rpc.EventTraceActivity.ActivityId : Guid.Empty;
  612. EventTraceActivity requestActivity = EventTraceActivityHelper.TryExtractActivity(rpc.Request);
  613. if (requestActivity == null)
  614. {
  615. requestActivity = EventTraceActivity.GetFromThreadOrCreate();
  616. EventTraceActivityHelper.TryAttachActivity(rpc.Request, requestActivity);
  617. }
  618. rpc.EventTraceActivity = requestActivity;
  619. if (TD.ClientOperationPreparedIsEnabled())
  620. {
  621. string remoteAddress = string.Empty;
  622. if (this.RemoteAddress != null && this.RemoteAddress.Uri != null)
  623. {
  624. remoteAddress = this.RemoteAddress.Uri.AbsoluteUri;
  625. }
  626. TD.ClientOperationPrepared(rpc.EventTraceActivity,
  627. rpc.Action,
  628. this.clientRuntime.ContractName,
  629. remoteAddress,
  630. previousId);
  631. }
  632. }
  633. internal static IAsyncResult BeginCall(ServiceChannel channel, ProxyOperationRuntime operation, object[] ins, AsyncCallback callback, object asyncState)
  634. {
  635. Fx.Assert(channel != null, "'channel' MUST NOT be NULL.");
  636. Fx.Assert(operation != null, "'operation' MUST NOT be NULL.");
  637. return channel.BeginCall(operation.Action, operation.IsOneWay, operation, ins, channel.operationTimeout, callback, asyncState);
  638. }
  639. internal IAsyncResult BeginCall(string action, bool oneway, ProxyOperationRuntime operation, object[] ins, AsyncCallback callback, object asyncState)
  640. {
  641. return this.BeginCall(action, oneway, operation, ins, this.operationTimeout, callback, asyncState);
  642. }
  643. internal IAsyncResult BeginCall(string action, bool oneway, ProxyOperationRuntime operation, object[] ins, TimeSpan timeout, AsyncCallback callback, object asyncState)
  644. {
  645. this.ThrowIfDisallowedInitializationUI();
  646. this.ThrowIfIdleAborted(operation);
  647. this.ThrowIfIsConnectionOpened(operation);
  648. ServiceModelActivity serviceModelActivity = null;
  649. if (DiagnosticUtility.ShouldUseActivity)
  650. {
  651. serviceModelActivity = ServiceModelActivity.CreateActivity(true);
  652. callback = TraceUtility.WrapExecuteUserCodeAsyncCallback(callback);
  653. }
  654. SendAsyncResult result;
  655. using (Activity boundOperation = ServiceModelActivity.BoundOperation(serviceModelActivity, true))
  656. {
  657. if (DiagnosticUtility.ShouldUseActivity)
  658. {
  659. ServiceModelActivity.Start(serviceModelActivity, SR.GetString(SR.ActivityProcessAction, action), ActivityType.ProcessAction);
  660. }
  661. result = new SendAsyncResult(this, operation, action, ins, oneway, timeout, callback, asyncState);
  662. if (DiagnosticUtility.ShouldUseActivity)
  663. {
  664. result.Rpc.Activity = serviceModelActivity;
  665. }
  666. TraceServiceChannelCallStart(result.Rpc.EventTraceActivity, false);
  667. result.Begin();
  668. }
  669. return result;
  670. }
  671. internal object Call(string action, bool oneway, ProxyOperationRuntime operation, object[] ins, object[] outs)
  672. {
  673. return this.Call(action, oneway, operation, ins, outs, this.operationTimeout);
  674. }
  675. internal object Call(string action, bool oneway, ProxyOperationRuntime operation, object[] ins, object[] outs, TimeSpan timeout)
  676. {
  677. this.ThrowIfDisallowedInitializationUI();
  678. this.ThrowIfIdleAborted(operation);
  679. this.ThrowIfIsConnectionOpened(operation);
  680. ProxyRpc rpc = new ProxyRpc(this, operation, action, ins, timeout);
  681. TraceServiceChannelCallStart(rpc.EventTraceActivity, true);
  682. using (rpc.Activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null)
  683. {
  684. if (DiagnosticUtility.ShouldUseActivity)
  685. {
  686. ServiceModelActivity.Start(rpc.Activity, SR.GetString(SR.ActivityProcessAction, action), ActivityType.ProcessAction);
  687. }
  688. this.PrepareCall(operation, oneway, ref rpc);
  689. if (!this.explicitlyOpened)
  690. {
  691. this.EnsureDisplayUI();
  692. this.EnsureOpened(rpc.TimeoutHelper.RemainingTime());
  693. }
  694. else
  695. {
  696. this.ThrowIfOpening();
  697. this.ThrowIfDisposedOrNotOpen();
  698. }
  699. try
  700. {
  701. ConcurrencyBehavior.UnlockInstanceBeforeCallout(OperationContext.Current);
  702. if (oneway)
  703. {
  704. this.binder.Send(rpc.Request, rpc.TimeoutHelper.RemainingTime());
  705. }
  706. else
  707. {
  708. rpc.Reply = this.binder.Request(rpc.Request, rpc.TimeoutHelper.RemainingTime());
  709. if (rpc.Reply == null)
  710. {
  711. this.ThrowIfFaulted();
  712. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.SFxServerDidNotReply)));
  713. }
  714. }
  715. }
  716. finally
  717. {
  718. this.CompletedIOOperation();
  719. CallOnceManager.SignalNextIfNonNull(this.autoOpenManager);
  720. ConcurrencyBehavior.LockInstanceAfterCallout(OperationContext.Current);
  721. }
  722. rpc.OutputParameters = outs;
  723. this.HandleReply(operation, ref rpc);
  724. }
  725. return rpc.ReturnValue;
  726. }
  727. internal object EndCall(string action, object[] outs, IAsyncResult result)
  728. {
  729. SendAsyncResult sendResult = result as SendAsyncResult;
  730. if (sendResult == null)
  731. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.SFxInvalidCallbackIAsyncResult)));
  732. using (ServiceModelActivity rpcActivity = sendResult.Rpc.Activity)
  733. {
  734. using (ServiceModelActivity.BoundOperation(rpcActivity, true))
  735. {
  736. if (sendResult.Rpc.Activity != null && DiagnosticUtility.ShouldUseActivity)
  737. {
  738. sendResult.Rpc.Activity.Resume();
  739. }
  740. if (sendResult.Rpc.Channel != this)
  741. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("result", SR.GetString(SR.AsyncEndCalledOnWrongChannel));
  742. if (action != MessageHeaders.WildcardAction && action != sendResult.Rpc.Action)
  743. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("result", SR.GetString(SR.AsyncEndCalledWithAnIAsyncResult));
  744. SendAsyncResult.End(sendResult);
  745. sendResult.Rpc.OutputParameters = outs;
  746. this.HandleReply(sendResult.Rpc.Operation, ref sendResult.Rpc);
  747. if (sendResult.Rpc.Activity != null)
  748. {
  749. sendResult.Rpc.Activity = null;
  750. }
  751. return sendResult.Rpc.ReturnValue;
  752. }
  753. }
  754. }
  755. internal void DecrementActivity()
  756. {
  757. int updatedActivityCount = Interlocked.Decrement(ref this.activityCount);
  758. if (!((updatedActivityCount >= 0)))
  759. {
  760. throw Fx.AssertAndThrowFatal("ServiceChannel.DecrementActivity: (updatedActivityCount >= 0)");
  761. }
  762. if (updatedActivityCount == 0 && this.autoClose)
  763. {
  764. try
  765. {
  766. if (this.State == CommunicationState.Opened)
  767. {
  768. if (this.IsClient)
  769. {
  770. ISessionChannel<IDuplexSession> duplexSessionChannel = this.InnerChannel as ISessionChannel<IDuplexSession>;
  771. if (duplexSessionChannel != null)
  772. {
  773. this.hasChannelStartedAutoClosing = true;
  774. duplexSessionChannel.Session.CloseOutputSession(this.CloseTimeout);
  775. }
  776. }
  777. else
  778. {
  779. this.Close(this.CloseTimeout);
  780. }
  781. }
  782. }
  783. catch (CommunicationException e)
  784. {
  785. DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
  786. }
  787. catch (TimeoutException e)
  788. {
  789. if (TD.CloseTimeoutIsEnabled())
  790. {
  791. TD.CloseTimeout(e.Message);
  792. }
  793. DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
  794. }
  795. catch (ObjectDisposedException e)
  796. {
  797. DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
  798. }
  799. catch (InvalidOperationException e)
  800. {
  801. DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
  802. }
  803. }
  804. }
  805. internal void FireUnknownMessageReceived(Message message)
  806. {
  807. EventHandler<UnknownMessageReceivedEventArgs> handler = this.unknownMessageReceived;
  808. if (handler != null)
  809. handler(this.proxy, new UnknownMessageReceivedEventArgs(message));
  810. }
  811. TimeoutException GetOpenTimeoutException(TimeSpan timeout)
  812. {
  813. EndpointAddress address = this.RemoteAddress ?? this.LocalAddress;
  814. if (address != null)
  815. {
  816. return new TimeoutException(SR.GetString(SR.TimeoutServiceChannelConcurrentOpen2, address, timeout));
  817. }
  818. else
  819. {
  820. return new TimeoutException(SR.GetString(SR.TimeoutServiceChannelConcurrentOpen1, timeout));
  821. }
  822. }
  823. internal void HandleReceiveComplete(RequestContext context)
  824. {
  825. if (context == null && HasSession)
  826. {
  827. bool first;
  828. lock (this.ThisLock)
  829. {
  830. first = !this.doneReceiving;
  831. this.doneReceiving = true;
  832. }
  833. if (first)
  834. {
  835. DispatchRuntime dispatchBehavior = this.ClientRuntime.DispatchRuntime;
  836. if (dispatchBehavior != null)
  837. dispatchBehavior.GetRuntime().InputSessionDoneReceiving(this);
  838. this.DecrementActivity();
  839. }
  840. }
  841. }
  842. void HandleReply(ProxyOperationRuntime operation, ref ProxyRpc rpc)
  843. {
  844. try
  845. {
  846. //set the ID after response
  847. if (TraceUtility.MessageFlowTracingOnly && rpc.ActivityId != Guid.Empty)
  848. {
  849. System.Runtime.Diagnostics.DiagnosticTraceBase.ActivityId = rpc.ActivityId;
  850. }
  851. if (rpc.Reply != null)
  852. {
  853. TraceUtility.MessageFlowAtMessageReceived(rpc.Reply, null, rpc.EventTraceActivity, false);
  854. if (MessageLogger.LogMessagesAtServiceLevel)
  855. {
  856. MessageLogger.LogMessage(ref rpc.Reply, MessageLoggingSource.ServiceLevelReceiveReply | MessageLoggingSource.LastChance);
  857. }
  858. operation.Parent.AfterReceiveReply(ref rpc);
  859. if ((operation.ReplyAction != MessageHeaders.WildcardAction) && !rpc.Reply.IsFault && rpc.Reply.Headers.Action != null)
  860. {
  861. if (String.CompareOrdinal(operation.ReplyAction, rpc.Reply.Headers.Action) != 0)
  862. {
  863. Exception error = new ProtocolException(SR.GetString(SR.SFxReplyActionMismatch3,
  864. operation.Name,
  865. rpc.Reply.Headers.Action,
  866. operation.ReplyAction));
  867. this.TerminateIfNecessary(ref rpc);
  868. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(error);
  869. }
  870. }
  871. if (operation.DeserializeReply && clientRuntime.IsFault(ref rpc.Reply))
  872. {
  873. MessageFault fault = MessageFault.CreateFault(rpc.Reply, this.clientRuntime.MaxFaultSize);
  874. string action = rpc.Reply.Headers.Action;
  875. if (action == rpc.Reply.Version.Addressing.DefaultFaultAction)
  876. {
  877. action = null;
  878. }
  879. ThrowIfFaultUnderstood(rpc.Reply, fault, action, rpc.Reply.Version, rpc.Channel.GetProperty<FaultConverter>());
  880. FaultException fe = rpc.Operation.FaultFormatter.Deserialize(fault, action);
  881. this.TerminateIfNecessary(ref rpc);
  882. throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(fe);
  883. }
  884. operation.AfterReply(ref rpc);
  885. }
  886. }
  887. finally
  888. {
  889. if (operation.SerializeRequest)
  890. {
  891. rpc.Request.Close();
  892. }
  893. OperationContext operationContext = OperationContext.Current;
  894. bool consumed = ((rpc.Reply != null) && (rpc.Reply.State != MessageState.Created));
  895. if ((operationContext != null) && operationContext.IsUserContext)
  896. {
  897. operationContext.SetClientReply(rpc.Reply, consumed);
  898. }
  899. else if (consumed)
  900. {
  901. rpc.Reply.Close();
  902. }
  903. if (TraceUtility.MessageFlowTracingOnly)
  904. {
  905. if (rpc.ActivityId != Guid.Empty)
  906. {
  907. //reset the ID as it was created internally - ensures each call is uniquely correlatable
  908. System.Runtime.Diagnostics.DiagnosticTraceBase.ActivityId = Guid.Empty;
  909. rpc.ActivityId = Guid.Empty;
  910. }
  911. }
  912. }
  913. this.TerminateIfNecessary(ref rpc);
  914. if (TD.ServiceChannelCallStopIsEnabled())
  915. {
  916. string remoteAddress = string.Empty;
  917. if (this.RemoteAddress != null && this.RemoteAddress.Uri != null)
  918. {
  919. remoteAddress = this.RemoteAddress.Uri.AbsoluteUri;
  920. }
  921. TD.ServiceChannelCallStop(rpc.EventTraceActivity, rpc.Action,
  922. this.clientRuntime.ContractName,
  923. remoteAddress);
  924. }
  925. }
  926. void TerminateIfNecessary(ref ProxyRpc rpc)
  927. {
  928. if (rpc.Operation.IsTerminating)
  929. {
  930. this.terminatingOperationName = rpc.Operation.Name;
  931. TerminatingOperationBehavior.AfterReply(ref rpc);
  932. }
  933. }
  934. void ThrowIfFaultUnderstood(Message reply, MessageFault fault, string action, MessageVersion version, FaultConverter faultConverter)
  935. {
  936. Exception exception;
  937. if (faultConverter != null && faultConverter.TryCreateException(reply, fault, out exception))
  938. {
  939. throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(exception);
  940. }
  941. bool checkSender;
  942. bool checkReceiver;
  943. FaultCode code;
  944. if (version.Envelope == EnvelopeVersion.Soap11)
  945. {
  946. checkSender = true;
  947. checkReceiver = true;
  948. code = fault.Code;
  949. }
  950. else
  951. {
  952. checkSender = fault.Code.IsSenderFault;
  953. checkReceiver = fault.Code.IsReceiverFault;
  954. code = fault.Code.SubCode;
  955. }
  956. if (code == null)
  957. {
  958. return;
  959. }
  960. if (code.Namespace == null)
  961. {
  962. return;
  963. }
  964. if (checkSender)
  965. {
  966. if (string.Compare(code.Namespace, FaultCodeConstants.Namespaces.NetDispatch, StringComparison.Ordinal) == 0)
  967. {
  968. if (string.Compare(code.Name, FaultCodeConstants.Codes.SessionTerminated, StringComparison.Ordinal) == 0)
  969. {
  970. throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new ChannelTerminatedException(fault.Reason.GetMatchingTranslation(CultureInfo.CurrentCulture).Text));
  971. }
  972. if (string.Compare(code.Name, FaultCodeConstants.Codes.TransactionAborted, StringComparison.Ordinal) == 0)
  973. {
  974. throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new ProtocolException(fault.Reason.GetMatchingTranslation(CultureInfo.CurrentCulture).Text));
  975. }
  976. }
  977. // throw SecurityAccessDeniedException explicitly
  978. if (string.Compare(code.Namespace, SecurityVersion.Default.HeaderNamespace.Value, StringComparison.Ordinal) == 0)
  979. {
  980. if (string.Compare(code.Name, SecurityVersion.Default.FailedAuthenticationFaultCode.Value, StringComparison.Ordinal) == 0)
  981. {
  982. throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new SecurityAccessDeniedException(fault.Reason.GetMatchingTranslation(CultureInfo.CurrentCulture).Text));
  983. }
  984. }
  985. }
  986. if (checkReceiver)
  987. {
  988. if (string.Compare(code.Namespace, FaultCodeConstants.Namespaces.NetDispatch, StringComparison.Ordinal) == 0)
  989. {
  990. if (string.Compare(code.Name, FaultCodeConstants.Codes.InternalServiceFault, StringComparison.Ordinal) == 0)
  991. {
  992. if (this.HasSession)
  993. {
  994. this.Fault();
  995. }
  996. if (fault.HasDetail)
  997. {
  998. ExceptionDetail detail = fault.GetDetail<ExceptionDetail>();
  999. throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new FaultException<ExceptionDetail>(detail, fault.Reason, fault.Code, action));
  1000. }
  1001. throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new FaultException(fault, action));
  1002. }
  1003. if (string.Compare(code.Name, FaultCodeConstants.Codes.DeserializationFailed, StringComparison.Ordinal) == 0)
  1004. {
  1005. throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new ProtocolException(
  1006. fault.Reason.GetMatchingTranslation(CultureInfo.CurrentCulture).Text));
  1007. }
  1008. }
  1009. }
  1010. }
  1011. void ThrowIfIdleAborted(ProxyOperationRuntime operation)
  1012. {
  1013. if (this.idleManager != null && this.idleManager.DidIdleAbort)
  1014. {
  1015. string text = SR.GetString(SR.SFxServiceChannelIdleAborted, operation.Name);
  1016. Exception error = new CommunicationObjectAbortedException(text);
  1017. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(error);
  1018. }
  1019. }
  1020. void ThrowIfIsConnectionOpened(ProxyOperationRuntime operation)
  1021. {
  1022. if (operation.IsSessionOpenNotificationEnabled)
  1023. {
  1024. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  1025. SR.GetString(SR.SFxServiceChannelCannotBeCalledBecauseIsSessionOpenNotificationEnabled, operation.Name, "Action", OperationDescription.SessionOpenedAction, "Open")));
  1026. }
  1027. }
  1028. void ThrowIfInitializationUINotCalled()
  1029. {
  1030. if (!this.didInteractiveInitialization && (this.ClientRuntime.InteractiveChannelInitializers.Count > 0))
  1031. {
  1032. IInteractiveChannelInitializer example = this.ClientRuntime.InteractiveChannelInitializers[0];
  1033. string text = SR.GetString(SR.SFxInitializationUINotCalled, example.GetType().ToString());
  1034. Exception error = new InvalidOperationException(text);
  1035. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(error);
  1036. }
  1037. }
  1038. void ThrowIfDisallowedInitializationUI()
  1039. {
  1040. if (!this.allowInitializationUI)
  1041. {
  1042. this.ThrowIfDisallowedInitializationUICore();
  1043. }
  1044. }
  1045. void ThrowIfDisallowedInitializationUICore()
  1046. {
  1047. if (this.ClientRuntime.InteractiveChannelInitializers.Count > 0)
  1048. {
  1049. IInteractiveChannelInitializer example = this.ClientRuntime.InteractiveChannelInitializers[0];
  1050. string text = SR.GetString(SR.SFxInitializationUIDisallowed, example.GetType().ToString());
  1051. Exception error = new InvalidOperationException(text);
  1052. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(error);
  1053. }
  1054. }
  1055. void ThrowIfOpening()
  1056. {
  1057. if (this.State == CommunicationState.Opening)
  1058. {
  1059. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCannotCallAutoOpenWhenExplicitOpenCalled)));
  1060. }
  1061. }
  1062. internal void IncrementActivity()
  1063. {
  1064. Interlocked.Increment(ref this.activityCount);
  1065. }
  1066. void OnInnerChannelFaulted(object sender, EventArgs e)
  1067. {
  1068. this.Fault();
  1069. if (this.HasSession)
  1070. {
  1071. DispatchRuntime dispatchRuntime = this.ClientRuntime.DispatchRuntime;
  1072. if (dispatchRuntime != null)
  1073. {
  1074. dispatchRuntime.GetRuntime().InputSessionFaulted(this);
  1075. }
  1076. }
  1077. if (this.autoClose && !this.IsClient)
  1078. {
  1079. this.Abort();
  1080. }
  1081. }
  1082. void AddMessageProperties(Message message, OperationContext context)
  1083. {
  1084. if (this.allowOutputBatching)
  1085. {
  1086. message.Properties.AllowOutputBatching = true;
  1087. }
  1088. if (context != null && context.InternalServiceChannel == this)
  1089. {
  1090. if (!context.OutgoingMessageVersion.IsMatch(message.Headers.MessageVersion))
  1091. {
  1092. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
  1093. SR.GetString(SR.SFxVersionMismatchInOperationContextAndMessage2, context.OutgoingMessageVersion, message.Headers.MessageVersion)
  1094. ));
  1095. }
  1096. if (context.HasOutgoingMessageHeaders)
  1097. {
  1098. message.Headers.CopyHeadersFrom(context.OutgoingMessageHeaders);
  1099. }
  1100. if (context.HasOutgoingMessageProperties)
  1101. {
  1102. message.Properties.CopyProperties(context.OutgoingMessageProperties);
  1103. }
  1104. }
  1105. }
  1106. #region IChannel Members
  1107. public void Send(Message message)
  1108. {
  1109. this.Send(message, this.OperationTimeout);
  1110. }
  1111. public void Send(Message message, TimeSpan timeout)
  1112. {
  1113. ProxyOperationRuntime operation = UnhandledProxyOperation;
  1114. this.Call(message.Headers.Action, true, operation, new object[] { message }, EmptyArray<object>.Instance, timeout);
  1115. }
  1116. public IAsyncResult BeginSend(Message message, AsyncCallback callback, object state)
  1117. {
  1118. return this.BeginSend(message, this.OperationTimeout, callback, state);
  1119. }
  1120. public IAsyncResult BeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state)
  1121. {
  1122. ProxyOperationRuntime operation = UnhandledProxyOperation;
  1123. return this.BeginCall(message.Headers.Action, true, operation, new object[] { message }, timeout, callback, state);
  1124. }
  1125. public void EndSend(IAsyncResult result)
  1126. {
  1127. this.EndCall(MessageHeaders.WildcardAction, EmptyArray<object>.Instance, result);
  1128. }
  1129. public Message Request(Message message)
  1130. {
  1131. return this.Request(message, this.OperationTimeout);
  1132. }
  1133. public Message Request(Message message, TimeSpan timeout)
  1134. {
  1135. ProxyOperationRuntime operation = UnhandledProxyOperation;
  1136. return (Message)this.Call(message.Headers.Action, false, operation, new object[] { message }, EmptyArray<object>.Instance, timeout);
  1137. }
  1138. public IAsyncResult BeginRequest(Message message, AsyncCallback callback, object state)
  1139. {
  1140. return this.BeginRequest(message, this.OperationTimeout, callback, state);
  1141. }
  1142. public IAsyncResult BeginRequest(Message message, TimeSpan timeout, AsyncCallback callback, object state)
  1143. {
  1144. ProxyOperationRuntime operation = this.UnhandledProxyOperation;
  1145. return this.BeginCall(message.Headers.Action, false, operation, new object[] { message }, timeout, callback, state);
  1146. }
  1147. public Message EndRequest(IAsyncResult result)
  1148. {
  1149. return (Message)this.EndCall(MessageHeaders.WildcardAction, EmptyArray<object>.Instance, result);
  1150. }
  1151. protected override void OnAbort()
  1152. {
  1153. if (this.idleManager != null)
  1154. {
  1155. this.idleManager.CancelTimer();
  1156. }
  1157. this.binder.Abort();
  1158. if (this.factory != null)
  1159. this.factory.ChannelDisposed(this);
  1160. if (this.closeFactory)
  1161. {
  1162. if (this.factory != null)
  1163. this.factory.Abort();
  1164. }
  1165. CleanupChannelCollections();
  1166. ServiceThrottle serviceThrottle = this.serviceThrottle;
  1167. if (serviceThrottle != null)
  1168. serviceThrottle.DeactivateChannel();
  1169. //rollback the attached transaction if one is present
  1170. if ((this.instanceContext != null) && this.HasSession)
  1171. {
  1172. if (instanceContext.HasTransaction)
  1173. {
  1174. instanceContext.Transaction.CompletePendingTransaction(instanceContext.Transaction.Attached, new Exception()); // error!=null forces Tx rollback
  1175. }
  1176. }
  1177. DecrementBusyCount();
  1178. }
  1179. protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
  1180. {
  1181. if (this.idleManager != null)
  1182. {
  1183. this.idleManager.CancelTimer();
  1184. }
  1185. if (this.factory != null)
  1186. {
  1187. this.factory.ChannelDisposed(this);
  1188. }
  1189. if (this.InstanceContext != null && this.InstanceContext.HasTransaction)
  1190. {
  1191. this.InstanceContext.CompleteAttachedTransaction();
  1192. }
  1193. if (this.closeBinder)
  1194. {
  1195. if (this.closeFactory)
  1196. {
  1197. return new ChainedAsyncResult(timeout, callback, state,
  1198. new ChainedBeginHandler(this.InnerChannel.BeginClose), new ChainedEndHandler(this.InnerChannel.EndClose),
  1199. new ChainedBeginHandler(this.factory.BeginClose), new ChainedEndHandler(this.factory.EndClose));
  1200. }
  1201. else
  1202. {
  1203. return this.InnerChannel.BeginClose(timeout, callback, state);
  1204. }
  1205. }
  1206. else
  1207. {
  1208. if (this.closeFactory)
  1209. return factory.BeginClose(timeout, callback, state);
  1210. else
  1211. return new CompletedAsyncResult(callback, state);
  1212. }
  1213. }
  1214. protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
  1215. {
  1216. this.ThrowIfDisallowedInitializationUI();
  1217. this.ThrowIfInitializationUINotCalled();
  1218. if (this.autoOpenManager == null)
  1219. {
  1220. this.explicitlyOpened = true;
  1221. }
  1222. if (this.HasSession && !this.IsClient)
  1223. {
  1224. IncrementBusyCount();
  1225. }
  1226. this.TraceChannelOpenStarted();
  1227. if (this.openBinder)
  1228. {
  1229. return this.InnerChannel.BeginOpen(timeout, callback, state);
  1230. }
  1231. else
  1232. {
  1233. return new CompletedAsyncResult(callback, state);
  1234. }
  1235. }
  1236. protected override void OnClose(TimeSpan timeout)
  1237. {
  1238. TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
  1239. if (this.idleManager != null)
  1240. {
  1241. this.idleManager.CancelTimer();
  1242. }
  1243. if (this.factory != null)
  1244. {
  1245. this.factory.ChannelDisposed(this);
  1246. }
  1247. if (this.InstanceContext != null && this.InstanceContext.HasTransaction)
  1248. {
  1249. this.InstanceContext.CompleteAttachedTransaction();
  1250. }
  1251. if (this.closeBinder)
  1252. this.InnerChannel.Close(timeoutHelper.RemainingTime());
  1253. if (this.closeFactory)
  1254. this.factory.Close(timeoutHelper.RemainingTime());
  1255. CleanupChannelCollections();
  1256. ServiceThrottle serviceThrottle = this.serviceThrottle;
  1257. if (serviceThrottle != null)
  1258. {
  1259. serviceThrottle.DeactivateChannel();
  1260. }
  1261. DecrementBusyCount();
  1262. }
  1263. protected override void OnEndClose(IAsyncResult result)
  1264. {
  1265. if (this.closeBinder)
  1266. {
  1267. if (this.closeFactory)
  1268. ChainedAsyncResult.End(result);
  1269. else
  1270. this.InnerChannel.EndClose(result);
  1271. }
  1272. else
  1273. {
  1274. if (this.closeFactory)
  1275. factory.EndClose(result);
  1276. else
  1277. CompletedAsyncResult.End(result);
  1278. }
  1279. CleanupChannelCollections();
  1280. ServiceThrottle serviceThrottle = this.serviceThrottle;
  1281. if (serviceThrottle != null)
  1282. {
  1283. serviceThrottle.DeactivateChannel();
  1284. }
  1285. DecrementBusyCount();
  1286. }
  1287. protected override void OnEndOpen(IAsyncResult result)
  1288. {
  1289. if (this.openBinder)
  1290. InnerChannel.EndOpen(result);
  1291. else
  1292. CompletedAsyncResult.End(result);
  1293. this.BindDuplexCallbacks();
  1294. this.CompletedIOOperation();
  1295. this.TraceChannelOpenCompleted();
  1296. }
  1297. protected override void OnOpen(TimeSpan timeout)
  1298. {
  1299. this.ThrowIfDisallowedInitializationUI();
  1300. this.ThrowIfInitializationUINotCalled();
  1301. if (this.autoOpenManager == null)
  1302. {
  1303. this.explicitlyOpened = true;
  1304. }
  1305. if (this.HasSession && !this.IsClient)
  1306. {
  1307. IncrementBusyCount();
  1308. }
  1309. this.TraceChannelOpenStarted();
  1310. if (this.openBinder)
  1311. {
  1312. this.InnerChannel.Open(timeout);
  1313. }
  1314. this.BindDuplexCallbacks();
  1315. this.CompletedIOOperation();
  1316. this.TraceChannelOpenCompleted();
  1317. }
  1318. void CleanupChannelCollections()
  1319. {
  1320. if (!this.hasCleanedUpChannelCollections)
  1321. {
  1322. lock (this.ThisLock)
  1323. {
  1324. if (!this.hasCleanedUpChannelCollections)
  1325. {
  1326. if (this.InstanceContext != null)
  1327. {
  1328. this.InstanceContext.OutgoingChannels.Remove((IChannel)this.proxy);
  1329. }
  1330. if (this.WmiInstanceContext != null)
  1331. {
  1332. this.WmiInstanceContext.WmiChannels.Remove((IChannel)this.proxy);
  1333. }
  1334. this.hasCleanedUpChannelCollections = true;
  1335. }
  1336. }
  1337. }
  1338. }
  1339. void IncrementBusyCount()
  1340. {
  1341. lock (this.ThisLock)
  1342. {
  1343. if (this.State == CommunicationState.Opening)
  1344. {
  1345. AspNetEnvironment.Current.IncrementBusyCount();
  1346. if (AspNetEnvironment.Current.TraceIncrementBusyCountIsEnabled())
  1347. {
  1348. AspNetEnvironment.Current.TraceIncrementBusyCount(this.GetType().FullName);
  1349. }
  1350. this.hasIncrementedBusyCount = true;
  1351. }
  1352. }
  1353. }
  1354. void DecrementBusyCount()
  1355. {
  1356. lock (this.ThisLock)
  1357. {
  1358. if (this.hasIncrementedBusyCount)
  1359. {
  1360. AspNetEnvironment.Current.DecrementBusyCount();
  1361. if (AspNetEnvironment.Current.TraceDecrementBusyCountIsEnabled())
  1362. {
  1363. AspNetEnvironment.Current.TraceDecrementBusyCount(this.GetType().FullName);
  1364. }
  1365. this.hasIncrementedBusyCount = false;
  1366. }
  1367. }
  1368. }
  1369. #endregion
  1370. #region IClientChannel Members
  1371. bool IDuplexContextChannel.AutomaticInputSessionShutdown
  1372. {
  1373. get { return this.autoClose; }
  1374. set { this.autoClose = value; }
  1375. }
  1376. bool IClientChannel.AllowInitializationUI
  1377. {
  1378. get { return this.allowInitializationUI; }
  1379. set
  1380. {
  1381. this.ThrowIfDisposedOrImmutable();
  1382. this.allowInitializationUI = value;
  1383. }
  1384. }
  1385. bool IContextChannel.AllowOutputBatching
  1386. {
  1387. get { return this.allowOutputBatching; }
  1388. set { this.allowOutputBatching = value; }
  1389. }
  1390. bool IClientChannel.DidInteractiveInitialization
  1391. {
  1392. get { return this.didInteractiveInitialization; }
  1393. }
  1394. IAsyncResult IDuplexContextChannel.BeginCloseOutputSession(TimeSpan timeout, AsyncCallback callback, object state)
  1395. {
  1396. return GetDuplexSessionOrThrow().BeginCloseOutputSession(timeout, callback, state);
  1397. }
  1398. void IDuplexContextChannel.EndCloseOutputSession(IAsyncResult result)
  1399. {
  1400. GetDuplexSessionOrThrow().EndCloseOutputSession(result);
  1401. }
  1402. void IDuplexContextChannel.CloseOutputSession(TimeSpan timeout)
  1403. {
  1404. GetDuplexSessionOrThrow().CloseOutputSession(timeout);
  1405. }
  1406. IDuplexSession GetDuplexSessionOrThrow()
  1407. {
  1408. if (this.InnerChannel == null)
  1409. {
  1410. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.channelIsNotAvailable0)));
  1411. }
  1412. ISessionChannel<IDuplexSession> duplexSessionChannel = this.InnerChannel as ISessionChannel<IDuplexSession>;
  1413. if (duplexSessionChannel == null)
  1414. {
  1415. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.channelDoesNotHaveADuplexSession0)));
  1416. }
  1417. return duplexSessionChannel.Session;
  1418. }
  1419. IExtensionCollection<IContextChannel> IExtensibleObject<IContextChannel>.Extensions
  1420. {
  1421. get
  1422. {
  1423. lock (this.ThisLock)
  1424. {
  1425. if (this.extensions == null)
  1426. this.extensions = new ExtensionCollection<IContextChannel>((IContextChannel)this.Proxy, this.ThisLock);
  1427. return this.extensions;
  1428. }
  1429. }
  1430. }
  1431. InstanceContext IDuplexContextChannel.CallbackInstance
  1432. {
  1433. get { return this.instanceContext; }
  1434. set
  1435. {
  1436. lock (this.ThisLock)
  1437. {
  1438. if (this.instanceContext != null)
  1439. {
  1440. this.instanceContext.OutgoingChannels.Remove((IChannel)this.proxy);
  1441. }
  1442. this.instanceContext = value;
  1443. if (this.instanceContext != null)
  1444. {
  1445. this.instanceContext.OutgoingChannels.Add((IChannel)this.proxy);
  1446. }
  1447. }
  1448. }
  1449. }
  1450. IInputSession IContextChannel.InputSession
  1451. {
  1452. get
  1453. {
  1454. if (this.InnerChannel != null)
  1455. {
  1456. ISessionChannel<IInputSession> inputSession = this.InnerChannel as ISessionChannel<IInputSession>;
  1457. if (inputSession != null)
  1458. return inputSession.Session;
  1459. ISessionChannel<IDuplexSession> duplexSession = this.InnerChannel as ISessionChannel<IDuplexSession>;
  1460. if (duplexSession != null)
  1461. return duplexSession.Session;
  1462. }
  1463. return null;
  1464. }
  1465. }
  1466. IOutputSession IContextChannel.OutputSession
  1467. {
  1468. get
  1469. {
  1470. if (this.InnerChannel != null)
  1471. {
  1472. ISessionChannel<IOutputSession> outputSession = this.InnerChannel as ISessionChannel<IOutputSession>;
  1473. if (outputSession != null)
  1474. return outputSession.Session;
  1475. ISessionChannel<IDuplexSession> duplexSession = this.InnerChannel as ISessionChannel<IDuplexSession>;
  1476. if (duplexSession != null)
  1477. return duplexSession.Session;
  1478. }
  1479. return null;
  1480. }
  1481. }
  1482. string IContextChannel.SessionId
  1483. {
  1484. get
  1485. {
  1486. if (this.InnerChannel != null)
  1487. {
  1488. ISessionChannel<IInputSession> inputSession = this.InnerChannel as ISessionChannel<IInputSession>;
  1489. if (inputSession != null)
  1490. return inputSession.Session.Id;
  1491. ISessionChannel<IOutputSession> outputSession = this.InnerChannel as ISessionChannel<IOutputSession>;
  1492. if (outputSession != null)
  1493. return outputSession.Session.Id;
  1494. ISessionChannel<IDuplexSession> duplexSession = this.InnerChannel as ISessionChannel<IDuplexSession>;
  1495. if (duplexSession != null)
  1496. return duplexSession.Session.Id;
  1497. }
  1498. return null;
  1499. }
  1500. }
  1501. event EventHandler<UnknownMessageReceivedEventArgs> IClientChannel.UnknownMessageReceived
  1502. {
  1503. add
  1504. {
  1505. lock (this.ThisLock)
  1506. {
  1507. this.unknownMessageReceived += value;
  1508. }
  1509. }
  1510. remove
  1511. {
  1512. lock (this.ThisLock)
  1513. {
  1514. this.unknownMessageReceived -= value;
  1515. }
  1516. }
  1517. }
  1518. public void DisplayInitializationUI()
  1519. {
  1520. this.ThrowIfDisallowedInitializationUI();
  1521. if (this.autoDisplayUIManager == null)
  1522. {
  1523. this.explicitlyOpened = true;
  1524. }
  1525. this.ClientRuntime.GetRuntime().DisplayInitializationUI(this);
  1526. this.didInteractiveInitialization = true;
  1527. }
  1528. public IAsyncResult BeginDisplayInitializationUI(AsyncCallback callback, object state)
  1529. {
  1530. this.ThrowIfDisallowedInitializationUI();
  1531. if (this.autoDisplayUIManager == null)
  1532. {
  1533. this.explicitlyOpened = true;
  1534. }
  1535. return this.ClientRuntime.GetRuntime().BeginDisplayInitializationUI(this, callback, state);
  1536. }
  1537. public void EndDisplayInitializationUI(IAsyncResult result)
  1538. {
  1539. this.ClientRuntime.GetRuntime().EndDisplayInitializationUI(result);
  1540. this.didInteractiveInitialization = true;
  1541. }
  1542. void IDisposable.Dispose()
  1543. {
  1544. this.Close();
  1545. }
  1546. #endregion
  1547. void TraceChannelOpenStarted()
  1548. {
  1549. if (TD.ClientChannelOpenStartIsEnabled() && this.endpointDispatcher == null)
  1550. {
  1551. TD.ClientChannelOpenStart(this.EventActivity);
  1552. }
  1553. else if (TD.ServiceChannelOpenStartIsEnabled())
  1554. {
  1555. TD.ServiceChannelOpenStart(this.EventActivity);
  1556. }
  1557. if (DiagnosticUtility.ShouldTraceInformation)
  1558. {
  1559. Dictionary<string, string> values = new Dictionary<string, string>(4);
  1560. bool traceNeeded = false;
  1561. DispatchRuntime behavior = this.DispatchRuntime;
  1562. if (behavior != null)
  1563. {
  1564. if (behavior.Type != null)
  1565. {
  1566. values["ServiceType"] = behavior.Type.AssemblyQualifiedName;
  1567. }
  1568. values["ContractNamespace"] = this.clientRuntime.ContractNamespace;
  1569. values["ContractName"] = this.clientRuntime.ContractName;
  1570. traceNeeded = true;
  1571. }
  1572. if ((this.endpointDispatcher != null) && (this.endpointDispatcher.ListenUri != null))
  1573. {
  1574. values["Uri"] = this.endpointDispatcher.ListenUri.ToString();
  1575. traceNeeded = true;
  1576. }
  1577. if (traceNeeded)
  1578. {
  1579. TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.ServiceChannelLifetime,
  1580. SR.GetString(SR.TraceCodeServiceChannelLifetime),
  1581. new DictionaryTraceRecord(values), this, null);
  1582. }
  1583. }
  1584. }
  1585. void TraceChannelOpenCompleted()
  1586. {
  1587. if (this.endpointDispatcher == null && TD.ClientChannelOpenStopIsEnabled())
  1588. {
  1589. TD.ClientChannelOpenStop(this.EventActivity);
  1590. }
  1591. else if (TD.ServiceChannelOpenStopIsEnabled())
  1592. {
  1593. TD.ServiceChannelOpenStop(this.EventActivity);
  1594. }
  1595. }
  1596. static void TraceServiceChannelCallStart(EventTraceActivity eventTraceActivity, bool isSynchronous)
  1597. {
  1598. if (TD.ServiceChannelCallStartIsEnabled())
  1599. {
  1600. if (isSynchronous)
  1601. {
  1602. TD.ServiceChannelCallStart(eventTraceActivity);
  1603. }
  1604. else
  1605. {
  1606. TD.ServiceChannelBeginCallStart(eventTraceActivity);
  1607. }
  1608. }
  1609. }
  1610. // Invariants for signalling the CallOnce manager.
  1611. //
  1612. // 1) If a Call, BeginCall, or EndCall on the channel throws,
  1613. // the manager will SignalNext itself.
  1614. // 2) If a Waiter times out, it will SignalNext its manager
  1615. // once it is both timed out and signalled.
  1616. // 3) Once Call or EndCall returns successfully, it guarantees
  1617. // that SignalNext will be called once the // next stage
  1618. // has sufficiently completed.
  1619. class SendAsyncResult : TraceAsyncResult
  1620. {
  1621. readonly bool isOneWay;
  1622. readonly ProxyOperationRuntime operation;
  1623. internal ProxyRpc Rpc;
  1624. OperationContext operationContext;
  1625. static AsyncCallback ensureInteractiveInitCallback = Fx.ThunkCallback(EnsureInteractiveInitCallback);
  1626. static AsyncCallback ensureOpenCallback = Fx.ThunkCallback(EnsureOpenCallback);
  1627. static AsyncCallback sendCallback = Fx.ThunkCallback(SendCallback);
  1628. internal SendAsyncResult(ServiceChannel channel, ProxyOperationRuntime operation,
  1629. string action, object[] inputParameters, bool isOneWay, TimeSpan timeout,
  1630. AsyncCallback userCallback, object userState)
  1631. : base(userCallback, userState)
  1632. {
  1633. this.Rpc = new ProxyRpc(channel, operation, action, inputParameters, timeout);
  1634. this.isOneWay = isOneWay;
  1635. this.operation = operation;
  1636. this.operationContext = OperationContext.Current;
  1637. }
  1638. internal void Begin()
  1639. {
  1640. this.Rpc.Channel.PrepareCall(this.operation, this.isOneWay, ref this.Rpc);
  1641. if (this.Rpc.Channel.explicitlyOpened)
  1642. {
  1643. this.Rpc.Channel.ThrowIfOpening();
  1644. this.Rpc.Channel.ThrowIfDisposedOrNotOpen();
  1645. this.StartSend(true);
  1646. }
  1647. else
  1648. {
  1649. this.StartEnsureInteractiveInit();
  1650. }
  1651. }
  1652. void StartEnsureInteractiveInit()
  1653. {
  1654. IAsyncResult result = this.Rpc.Channel.BeginEnsureDisplayUI(ensureInteractiveInitCallback, this);
  1655. if (result.CompletedSynchronously)
  1656. {
  1657. this.FinishEnsureInteractiveInit(result, true);
  1658. }
  1659. }
  1660. static void EnsureInteractiveInitCallback(IAsyncResult result)
  1661. {
  1662. if (!result.CompletedSynchronously)
  1663. {
  1664. ((SendAsyncResult)result.AsyncState).FinishEnsureInteractiveInit(result, false);
  1665. }
  1666. }
  1667. void FinishEnsureInteractiveInit(IAsyncResult result, bool completedSynchronously)
  1668. {
  1669. Exception exception = null;
  1670. try
  1671. {
  1672. this.Rpc.Channel.EndEnsureDisplayUI(result);
  1673. }
  1674. catch (Exception e)
  1675. {
  1676. if (Fx.IsFatal(e) || completedSynchronously)
  1677. {
  1678. throw;
  1679. }
  1680. exception = e;
  1681. }
  1682. if (exception != null)
  1683. {
  1684. this.CallComplete(completedSynchronously, exception);
  1685. }
  1686. else
  1687. {
  1688. this.StartEnsureOpen(completedSynchronously);
  1689. }
  1690. }
  1691. void StartEnsureOpen(bool completedSynchronously)
  1692. {
  1693. TimeSpan timeout = this.Rpc.TimeoutHelper.RemainingTime();
  1694. IAsyncResult result = null;
  1695. Exception exception = null;
  1696. try
  1697. {
  1698. result = this.Rpc.Channel.BeginEnsureOpened(timeout, ensureOpenCallback, this);
  1699. }
  1700. catch (Exception e)
  1701. {
  1702. if (Fx.IsFatal(e) || completedSynchronously)
  1703. {
  1704. throw;
  1705. }
  1706. exception = e;
  1707. }
  1708. if (exception != null)
  1709. {
  1710. this.CallComplete(completedSynchronously, exception);
  1711. }
  1712. else if (result.CompletedSynchronously)
  1713. {
  1714. this.FinishEnsureOpen(result, completedSynchronously);
  1715. }
  1716. }
  1717. static void EnsureOpenCallback(IAsyncResult result)
  1718. {
  1719. if (!result.CompletedSynchronously)
  1720. {
  1721. ((SendAsyncResult)result.AsyncState).FinishEnsureOpen(result, false);
  1722. }
  1723. }
  1724. void FinishEnsureOpen(IAsyncResult result, bool completedSynchronously)
  1725. {
  1726. Exception exception = null;
  1727. using (ServiceModelActivity.BoundOperation(this.Rpc.Activity))
  1728. {
  1729. try
  1730. {
  1731. this.Rpc.Channel.EndEnsureOpened(result);
  1732. }
  1733. catch (Exception e)
  1734. {
  1735. if (Fx.IsFatal(e) || completedSynchronously)
  1736. {
  1737. throw;
  1738. }
  1739. exception = e;
  1740. }
  1741. if (exception != null)
  1742. {
  1743. this.CallComplete(completedSynchronously, exception);
  1744. }
  1745. else
  1746. {
  1747. this.StartSend(completedSynchronously);
  1748. }
  1749. }
  1750. }
  1751. void StartSend(bool completedSynchronously)
  1752. {
  1753. TimeSpan timeout = this.Rpc.TimeoutHelper.RemainingTime();
  1754. IAsyncResult result = null;
  1755. Exception exception = null;
  1756. try
  1757. {
  1758. ConcurrencyBehavior.UnlockInstanceBeforeCallout(this.operationContext);
  1759. if (this.isOneWay)
  1760. {
  1761. result = this.Rpc.Channel.binder.BeginSend(this.Rpc.Request, timeout, sendCallback, this);
  1762. }
  1763. else
  1764. {
  1765. result = this.Rpc.Channel.binder.BeginRequest(this.Rpc.Request, timeout, sendCallback, this);
  1766. }
  1767. }
  1768. catch (Exception e)
  1769. {
  1770. if (Fx.IsFatal(e))
  1771. {
  1772. throw;
  1773. }
  1774. if (completedSynchronously)
  1775. {
  1776. ConcurrencyBehavior.LockInstanceAfterCallout(this.operationContext);
  1777. throw;
  1778. }
  1779. exception = e;
  1780. }
  1781. finally
  1782. {
  1783. CallOnceManager.SignalNextIfNonNull(this.Rpc.Channel.autoOpenManager);
  1784. }
  1785. if (exception != null)
  1786. {
  1787. this.CallComplete(completedSynchronously, exception);
  1788. }
  1789. else if (result.CompletedSynchronously)
  1790. {
  1791. this.FinishSend(result, completedSynchronously);
  1792. }
  1793. }
  1794. static void SendCallback(IAsyncResult result)
  1795. {
  1796. if (!result.CompletedSynchronously)
  1797. {
  1798. ((SendAsyncResult)result.AsyncState).FinishSend(result, false);
  1799. }
  1800. }
  1801. void FinishSend(IAsyncResult result, bool completedSynchronously)
  1802. {
  1803. Exception exception = null;
  1804. try
  1805. {
  1806. if (this.isOneWay)
  1807. {
  1808. this.Rpc.Channel.binder.EndSend(result);
  1809. }
  1810. else
  1811. {
  1812. this.Rpc.Reply = this.Rpc.Channel.binder.EndRequest(result);
  1813. if (this.Rpc.Reply == null)
  1814. {
  1815. this.Rpc.Channel.ThrowIfFaulted();
  1816. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.SFxServerDidNotReply)));
  1817. }
  1818. }
  1819. }
  1820. catch (Exception e)
  1821. {
  1822. if (Fx.IsFatal(e))
  1823. {
  1824. throw;
  1825. }
  1826. if (completedSynchronously)
  1827. {
  1828. ConcurrencyBehavior.LockInstanceAfterCallout(this.operationContext);
  1829. throw;
  1830. }
  1831. exception = e;
  1832. }
  1833. this.CallComplete(completedSynchronously, exception);
  1834. }
  1835. void CallComplete(bool completedSynchronously, Exception exception)
  1836. {
  1837. this.Rpc.Channel.CompletedIOOperation();
  1838. this.Complete(completedSynchronously, exception);
  1839. }
  1840. public static void End(SendAsyncResult result)
  1841. {
  1842. try
  1843. {
  1844. AsyncResult.End<SendAsyncResult>(result);
  1845. }
  1846. finally
  1847. {
  1848. ConcurrencyBehavior.LockInstanceAfterCallout(result.operationContext);
  1849. }
  1850. }
  1851. }
  1852. interface ICallOnce
  1853. {
  1854. void Call(ServiceChannel channel, TimeSpan timeout);
  1855. IAsyncResult BeginCall(ServiceChannel channel, TimeSpan timeout, AsyncCallback callback, object state);
  1856. void EndCall(ServiceChannel channel, IAsyncResult result);
  1857. }
  1858. class CallDisplayUIOnce : ICallOnce
  1859. {
  1860. static CallDisplayUIOnce instance;
  1861. internal static CallDisplayUIOnce Instance
  1862. {
  1863. get
  1864. {
  1865. if (CallDisplayUIOnce.instance == null)
  1866. {
  1867. CallDisplayUIOnce.instance = new CallDisplayUIOnce();
  1868. }
  1869. return CallDisplayUIOnce.instance;
  1870. }
  1871. }
  1872. [Conditional("DEBUG")]
  1873. void ValidateTimeoutIsMaxValue(TimeSpan timeout)
  1874. {
  1875. if (timeout != TimeSpan.MaxValue)
  1876. {
  1877. Fx.Assert("non-MaxValue timeout for displaying interactive initialization UI");
  1878. }
  1879. }
  1880. void ICallOnce.Call(ServiceChannel channel, TimeSpan timeout)
  1881. {
  1882. this.ValidateTimeoutIsMaxValue(timeout);
  1883. channel.DisplayInitializationUI();
  1884. }
  1885. IAsyncResult ICallOnce.BeginCall(ServiceChannel channel, TimeSpan timeout, AsyncCallback callback, object state)
  1886. {
  1887. this.ValidateTimeoutIsMaxValue(timeout);
  1888. return channel.BeginDisplayInitializationUI(callback, state);
  1889. }
  1890. void ICallOnce.EndCall(ServiceChannel channel, IAsyncResult result)
  1891. {
  1892. channel.EndDisplayInitializationUI(result);
  1893. }
  1894. }
  1895. class CallOpenOnce : ICallOnce
  1896. {
  1897. static CallOpenOnce instance;
  1898. internal static CallOpenOnce Instance
  1899. {
  1900. get
  1901. {
  1902. if (CallOpenOnce.instance == null)
  1903. {
  1904. CallOpenOnce.instance = new CallOpenOnce();
  1905. }
  1906. return CallOpenOnce.instance;
  1907. }
  1908. }
  1909. void ICallOnce.Call(ServiceChannel channel, TimeSpan timeout)
  1910. {
  1911. channel.Open(timeout);
  1912. }
  1913. IAsyncResult ICallOnce.BeginCall(ServiceChannel channel, TimeSpan timeout, AsyncCallback callback, object state)
  1914. {
  1915. return channel.BeginOpen(timeout, callback, state);
  1916. }
  1917. void ICallOnce.EndCall(ServiceChannel channel, IAsyncResult result)
  1918. {
  1919. channel.EndOpen(result);
  1920. }
  1921. }
  1922. class CallOnceManager
  1923. {
  1924. readonly ICallOnce callOnce;
  1925. readonly ServiceChannel channel;
  1926. bool isFirst = true;
  1927. Queue<IWaiter> queue;
  1928. static Action<object> signalWaiter = new Action<object>(CallOnceManager.SignalWaiter);
  1929. internal CallOnceManager(ServiceChannel channel, ICallOnce callOnce)
  1930. {
  1931. this.callOnce = callOnce;
  1932. this.channel = channel;
  1933. this.queue = new Queue<IWaiter>();
  1934. }
  1935. object ThisLock
  1936. {
  1937. get { return this; }
  1938. }
  1939. internal void CallOnce(TimeSpan timeout, CallOnceManager cascade)
  1940. {
  1941. SyncWaiter waiter = null;
  1942. bool first = false;
  1943. if (this.queue != null)
  1944. {
  1945. lock (this.ThisLock)
  1946. {
  1947. if (this.queue != null)
  1948. {
  1949. if (this.isFirst)
  1950. {
  1951. first = true;
  1952. this.isFirst = false;
  1953. }
  1954. else
  1955. {
  1956. waiter = new SyncWaiter(this);
  1957. this.queue.Enqueue(waiter);
  1958. }
  1959. }
  1960. }
  1961. }
  1962. CallOnceManager.SignalNextIfNonNull(cascade);
  1963. if (first)
  1964. {
  1965. bool throwing = true;
  1966. try
  1967. {
  1968. this.callOnce.Call(this.channel, timeout);
  1969. throwing = false;
  1970. }
  1971. finally
  1972. {
  1973. if (throwing)
  1974. {
  1975. this.SignalNext();
  1976. }
  1977. }
  1978. }
  1979. else if (waiter != null)
  1980. {
  1981. waiter.Wait(timeout);
  1982. }
  1983. }
  1984. internal IAsyncResult BeginCallOnce(TimeSpan timeout, CallOnceManager cascade,
  1985. AsyncCallback callback, object state)
  1986. {
  1987. AsyncWaiter waiter = null;
  1988. bool first = false;
  1989. if (this.queue != null)
  1990. {
  1991. lock (this.ThisLock)
  1992. {
  1993. if (this.queue != null)
  1994. {
  1995. if (this.isFirst)
  1996. {
  1997. first = true;
  1998. this.isFirst = false;
  1999. }
  2000. else
  2001. {
  2002. waiter = new AsyncWaiter(this, timeout, callback, state);
  2003. this.queue.Enqueue(waiter);
  2004. }
  2005. }
  2006. }
  2007. }
  2008. CallOnceManager.SignalNextIfNonNull(cascade);
  2009. if (first)
  2010. {
  2011. bool throwing = true;
  2012. try
  2013. {
  2014. IAsyncResult result = this.callOnce.BeginCall(this.channel, timeout, callback, state);
  2015. throwing = false;
  2016. return result;
  2017. }
  2018. finally
  2019. {
  2020. if (throwing)
  2021. {
  2022. this.SignalNext();
  2023. }
  2024. }
  2025. }
  2026. else if (waiter != null)
  2027. {
  2028. return waiter;
  2029. }
  2030. else
  2031. {
  2032. return new CallOnceCompletedAsyncResult(callback, state);
  2033. }
  2034. }
  2035. internal void EndCallOnce(IAsyncResult result)
  2036. {
  2037. if (result is CallOnceCompletedAsyncResult)
  2038. {
  2039. CallOnceCompletedAsyncResult.End(result);
  2040. }
  2041. else if (result is AsyncWaiter)
  2042. {
  2043. AsyncWaiter.End(result);
  2044. }
  2045. else
  2046. {
  2047. bool throwing = true;
  2048. try
  2049. {
  2050. this.callOnce.EndCall(this.channel, result);
  2051. throwing = false;
  2052. }
  2053. finally
  2054. {
  2055. if (throwing)
  2056. {
  2057. this.SignalNext();
  2058. }
  2059. }
  2060. }
  2061. }
  2062. static internal void SignalNextIfNonNull(CallOnceManager manager)
  2063. {
  2064. if (manager != null)
  2065. {
  2066. manager.SignalNext();
  2067. }
  2068. }
  2069. internal void SignalNext()
  2070. {
  2071. if (this.queue == null)
  2072. {
  2073. return;
  2074. }
  2075. IWaiter waiter = null;
  2076. lock (this.ThisLock)
  2077. {
  2078. if (this.queue != null)
  2079. {
  2080. if (this.queue.Count > 0)
  2081. {
  2082. waiter = this.queue.Dequeue();
  2083. }
  2084. else
  2085. {
  2086. this.queue = null;
  2087. }
  2088. }
  2089. }
  2090. if (waiter != null)
  2091. {
  2092. ActionItem.Schedule(CallOnceManager.signalWaiter, waiter);
  2093. }
  2094. }
  2095. static void SignalWaiter(object state)
  2096. {
  2097. ((IWaiter)state).Signal();
  2098. }
  2099. interface IWaiter
  2100. {
  2101. void Signal();
  2102. }
  2103. class SyncWaiter : IWaiter
  2104. {
  2105. ManualResetEvent wait = new ManualResetEvent(false);
  2106. CallOnceManager manager;
  2107. bool isTimedOut = false;
  2108. bool isSignaled = false;
  2109. int waitCount = 0;
  2110. internal SyncWaiter(CallOnceManager manager)
  2111. {
  2112. this.manager = manager;
  2113. }
  2114. bool ShouldSignalNext
  2115. {
  2116. get { return this.isTimedOut && this.isSignaled; }
  2117. }
  2118. void IWaiter.Signal()
  2119. {
  2120. wait.Set();
  2121. this.CloseWaitHandle();
  2122. bool signalNext;
  2123. lock (this.manager.ThisLock)
  2124. {
  2125. this.isSignaled = true;
  2126. signalNext = this.ShouldSignalNext;
  2127. }
  2128. if (signalNext)
  2129. {
  2130. this.manager.SignalNext();
  2131. }
  2132. }
  2133. internal bool Wait(TimeSpan timeout)
  2134. {
  2135. try
  2136. {
  2137. if (!TimeoutHelper.WaitOne(this.wait, timeout))
  2138. {
  2139. bool signalNext;
  2140. lock (this.manager.ThisLock)
  2141. {
  2142. this.isTimedOut = true;
  2143. signalNext = this.ShouldSignalNext;
  2144. }
  2145. if (signalNext)
  2146. {
  2147. this.manager.SignalNext();
  2148. }
  2149. }
  2150. }
  2151. finally
  2152. {
  2153. this.CloseWaitHandle();
  2154. }
  2155. return !this.isTimedOut;
  2156. }
  2157. void CloseWaitHandle()
  2158. {
  2159. if (Interlocked.Increment(ref this.waitCount) == 2)
  2160. {
  2161. this.wait.Close();
  2162. }
  2163. }
  2164. }
  2165. class AsyncWaiter : AsyncResult, IWaiter
  2166. {
  2167. static Action<object> timerCallback = new Action<object>(AsyncWaiter.TimerCallback);
  2168. CallOnceManager manager;
  2169. TimeSpan timeout;
  2170. IOThreadTimer timer;
  2171. internal AsyncWaiter(CallOnceManager manager, TimeSpan timeout,
  2172. AsyncCallback callback, object state)
  2173. : base(callback, state)
  2174. {
  2175. this.manager = manager;
  2176. this.timeout = timeout;
  2177. if (timeout != TimeSpan.MaxValue)
  2178. {
  2179. this.timer = new IOThreadTimer(timerCallback, this, false);
  2180. this.timer.Set(timeout);
  2181. }
  2182. }
  2183. internal static void End(IAsyncResult result)
  2184. {
  2185. AsyncResult.End<AsyncWaiter>(result);
  2186. }
  2187. void IWaiter.Signal()
  2188. {
  2189. if ((this.timer == null) || this.timer.Cancel())
  2190. {
  2191. this.Complete(false);
  2192. this.manager.channel.Closed -= this.OnClosed;
  2193. }
  2194. else
  2195. {
  2196. this.manager.SignalNext();
  2197. }
  2198. }
  2199. void OnClosed(object sender, EventArgs e)
  2200. {
  2201. if ((this.timer == null) || this.timer.Cancel())
  2202. {
  2203. this.Complete(false, this.manager.channel.CreateClosedException());
  2204. }
  2205. }
  2206. static void TimerCallback(object state)
  2207. {
  2208. AsyncWaiter _this = (AsyncWaiter)state;
  2209. _this.Complete(false, _this.manager.channel.GetOpenTimeoutException(_this.timeout));
  2210. }
  2211. }
  2212. }
  2213. class CallOnceCompletedAsyncResult : AsyncResult
  2214. {
  2215. internal CallOnceCompletedAsyncResult(AsyncCallback callback, object state)
  2216. : base(callback, state)
  2217. {
  2218. this.Complete(true);
  2219. }
  2220. static internal void End(IAsyncResult result)
  2221. {
  2222. AsyncResult.End<CallOnceCompletedAsyncResult>(result);
  2223. }
  2224. }
  2225. internal class SessionIdleManager
  2226. {
  2227. readonly IChannelBinder binder;
  2228. ServiceChannel channel;
  2229. readonly long idleTicks;
  2230. long lastActivity;
  2231. readonly IOThreadTimer timer;
  2232. static Action<object> timerCallback;
  2233. bool didIdleAbort;
  2234. bool isTimerCancelled;
  2235. object thisLock;
  2236. SessionIdleManager(IChannelBinder binder, TimeSpan idle)
  2237. {
  2238. this.binder = binder;
  2239. this.timer = new IOThreadTimer(GetTimerCallback(), this, false);
  2240. this.idleTicks = Ticks.FromTimeSpan(idle);
  2241. this.timer.SetAt(Ticks.Now + this.idleTicks);
  2242. this.thisLock = new Object();
  2243. }
  2244. internal static SessionIdleManager CreateIfNeeded(IChannelBinder binder, TimeSpan idle)
  2245. {
  2246. if (binder.HasSession && (idle != TimeSpan.MaxValue))
  2247. {
  2248. return new SessionIdleManager(binder, idle);
  2249. }
  2250. else
  2251. {
  2252. return null;
  2253. }
  2254. }
  2255. internal bool DidIdleAbort
  2256. {
  2257. get
  2258. {
  2259. lock (thisLock)
  2260. {
  2261. return this.didIdleAbort;
  2262. }
  2263. }
  2264. }
  2265. internal void CancelTimer()
  2266. {
  2267. lock (thisLock)
  2268. {
  2269. this.isTimerCancelled = true;
  2270. this.timer.Cancel();
  2271. }
  2272. }
  2273. internal void CompletedActivity()
  2274. {
  2275. Interlocked.Exchange(ref this.lastActivity, Ticks.Now);
  2276. }
  2277. internal void RegisterChannel(ServiceChannel channel, out bool didIdleAbort)
  2278. {
  2279. lock (thisLock)
  2280. {
  2281. this.channel = channel;
  2282. didIdleAbort = this.didIdleAbort;
  2283. }
  2284. }
  2285. static Action<object> GetTimerCallback()
  2286. {
  2287. if (SessionIdleManager.timerCallback == null)
  2288. {
  2289. SessionIdleManager.timerCallback = SessionIdleManager.TimerCallback;
  2290. }
  2291. return SessionIdleManager.timerCallback;
  2292. }
  2293. static void TimerCallback(object state)
  2294. {
  2295. ((SessionIdleManager)state).TimerCallback();
  2296. }
  2297. void TimerCallback()
  2298. {
  2299. // This reads lastActivity atomically without changing its value.
  2300. // (it only sets if it is zero, and then it sets it to zero).
  2301. long last = Interlocked.CompareExchange(ref this.lastActivity, 0, 0);
  2302. long abortTime = last + this.idleTicks;
  2303. lock (thisLock)
  2304. {
  2305. if (Ticks.Now > abortTime)
  2306. {
  2307. if (TD.SessionIdleTimeoutIsEnabled())
  2308. {
  2309. string listenUri = string.Empty;
  2310. if (this.binder.ListenUri != null)
  2311. {
  2312. listenUri = this.binder.ListenUri.AbsoluteUri;
  2313. }
  2314. TD.SessionIdleTimeout(listenUri);
  2315. }
  2316. this.didIdleAbort = true;
  2317. if (this.channel != null)
  2318. {
  2319. this.channel.Abort();
  2320. }
  2321. else
  2322. {
  2323. this.binder.Abort();
  2324. }
  2325. }
  2326. else
  2327. {
  2328. if (!this.isTimerCancelled && binder.Channel.State != CommunicationState.Faulted && binder.Channel.State != CommunicationState.Closed)
  2329. {
  2330. this.timer.SetAt(abortTime);
  2331. }
  2332. }
  2333. }
  2334. }
  2335. }
  2336. }
  2337. }