SingletonConnectionReader.cs 77 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Channels
  5. {
  6. using System;
  7. using System.Diagnostics;
  8. using System.IO;
  9. using System.Net;
  10. using System.Runtime;
  11. using System.Runtime.CompilerServices;
  12. using System.Security.Authentication.ExtendedProtection;
  13. using System.ServiceModel;
  14. using System.ServiceModel.Activation;
  15. using System.ServiceModel.Description;
  16. using System.ServiceModel.Diagnostics;
  17. using System.ServiceModel.Dispatcher;
  18. using System.ServiceModel.Security;
  19. using System.Threading;
  20. using System.Xml;
  21. using System.ServiceModel.Diagnostics.Application;
  22. delegate void ServerSingletonPreambleCallback(ServerSingletonPreambleConnectionReader serverSingletonPreambleReader);
  23. delegate ISingletonChannelListener SingletonPreambleDemuxCallback(ServerSingletonPreambleConnectionReader serverSingletonPreambleReader);
  24. interface ISingletonChannelListener
  25. {
  26. TimeSpan ReceiveTimeout { get; }
  27. void ReceiveRequest(RequestContext requestContext, Action callback, bool canDispatchOnThisThread);
  28. }
  29. class ServerSingletonPreambleConnectionReader : InitialServerConnectionReader
  30. {
  31. ServerSingletonDecoder decoder;
  32. ServerSingletonPreambleCallback callback;
  33. WaitCallback onAsyncReadComplete;
  34. IConnectionOrientedTransportFactorySettings transportSettings;
  35. TransportSettingsCallback transportSettingsCallback;
  36. SecurityMessageProperty security;
  37. Uri via;
  38. IConnection rawConnection;
  39. byte[] connectionBuffer;
  40. bool isReadPending;
  41. int offset;
  42. int size;
  43. TimeoutHelper receiveTimeoutHelper;
  44. Action<Uri> viaDelegate;
  45. ChannelBinding channelBindingToken;
  46. static AsyncCallback onValidate;
  47. public ServerSingletonPreambleConnectionReader(IConnection connection, Action connectionDequeuedCallback,
  48. long streamPosition, int offset, int size, TransportSettingsCallback transportSettingsCallback,
  49. ConnectionClosedCallback closedCallback, ServerSingletonPreambleCallback callback)
  50. : base(connection, closedCallback)
  51. {
  52. this.decoder = new ServerSingletonDecoder(streamPosition, MaxViaSize, MaxContentTypeSize);
  53. this.offset = offset;
  54. this.size = size;
  55. this.callback = callback;
  56. this.transportSettingsCallback = transportSettingsCallback;
  57. this.rawConnection = connection;
  58. this.ConnectionDequeuedCallback = connectionDequeuedCallback;
  59. }
  60. public ChannelBinding ChannelBinding
  61. {
  62. get
  63. {
  64. return this.channelBindingToken;
  65. }
  66. }
  67. public int BufferOffset
  68. {
  69. get { return this.offset; }
  70. }
  71. public int BufferSize
  72. {
  73. get { return this.size; }
  74. }
  75. public ServerSingletonDecoder Decoder
  76. {
  77. get { return this.decoder; }
  78. }
  79. public IConnection RawConnection
  80. {
  81. get { return this.rawConnection; }
  82. }
  83. public Uri Via
  84. {
  85. get { return this.via; }
  86. }
  87. public IConnectionOrientedTransportFactorySettings TransportSettings
  88. {
  89. get { return this.transportSettings; }
  90. }
  91. public SecurityMessageProperty Security
  92. {
  93. get { return this.security; }
  94. }
  95. TimeSpan GetRemainingTimeout()
  96. {
  97. return this.receiveTimeoutHelper.RemainingTime();
  98. }
  99. void ReadAndDispatch()
  100. {
  101. bool success = false;
  102. try
  103. {
  104. while ((size > 0 || !isReadPending) && !IsClosed)
  105. {
  106. if (size == 0)
  107. {
  108. isReadPending = true;
  109. if (onAsyncReadComplete == null)
  110. {
  111. onAsyncReadComplete = new WaitCallback(OnAsyncReadComplete);
  112. }
  113. if (Connection.BeginRead(0, connectionBuffer.Length, GetRemainingTimeout(),
  114. onAsyncReadComplete, null) == AsyncCompletionResult.Queued)
  115. {
  116. break;
  117. }
  118. HandleReadComplete();
  119. }
  120. int bytesRead = decoder.Decode(connectionBuffer, offset, size);
  121. if (bytesRead > 0)
  122. {
  123. offset += bytesRead;
  124. size -= bytesRead;
  125. }
  126. if (decoder.CurrentState == ServerSingletonDecoder.State.PreUpgradeStart)
  127. {
  128. if (onValidate == null)
  129. {
  130. onValidate = Fx.ThunkCallback(new AsyncCallback(OnValidate));
  131. }
  132. this.via = decoder.Via;
  133. IAsyncResult result = this.Connection.BeginValidate(this.via, onValidate, this);
  134. if (result.CompletedSynchronously)
  135. {
  136. if (!VerifyValidationResult(result))
  137. {
  138. // This goes through the failure path (Abort) even though it doesn't throw.
  139. return;
  140. }
  141. }
  142. break; //exit loop, set success=true;
  143. }
  144. }
  145. success = true;
  146. }
  147. catch (CommunicationException exception)
  148. {
  149. DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information);
  150. }
  151. catch (TimeoutException exception)
  152. {
  153. if (TD.ReceiveTimeoutIsEnabled())
  154. {
  155. TD.ReceiveTimeout(exception.Message);
  156. }
  157. DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information);
  158. }
  159. catch (Exception e)
  160. {
  161. if (Fx.IsFatal(e))
  162. {
  163. throw;
  164. }
  165. if (!ExceptionHandler.HandleTransportExceptionHelper(e))
  166. {
  167. throw;
  168. }
  169. // containment -- we abort ourselves for any error, no extra containment needed
  170. }
  171. finally
  172. {
  173. if (!success)
  174. {
  175. Abort();
  176. }
  177. }
  178. }
  179. //returns true if validation was successful
  180. bool VerifyValidationResult(IAsyncResult result)
  181. {
  182. return this.Connection.EndValidate(result) && this.ContinuePostValidationProcessing();
  183. }
  184. static void OnValidate(IAsyncResult result)
  185. {
  186. bool success = false;
  187. ServerSingletonPreambleConnectionReader thisPtr = (ServerSingletonPreambleConnectionReader)result.AsyncState;
  188. try
  189. {
  190. if (!result.CompletedSynchronously)
  191. {
  192. if (!thisPtr.VerifyValidationResult(result))
  193. {
  194. // This goes through the failure path (Abort) even though it doesn't throw.
  195. return;
  196. }
  197. }
  198. success = true;
  199. }
  200. catch (CommunicationException exception)
  201. {
  202. DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information);
  203. }
  204. catch (TimeoutException exception)
  205. {
  206. if (TD.ReceiveTimeoutIsEnabled())
  207. {
  208. TD.ReceiveTimeout(exception.Message);
  209. }
  210. DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information);
  211. }
  212. catch (Exception e)
  213. {
  214. if (Fx.IsFatal(e))
  215. {
  216. throw;
  217. }
  218. DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
  219. }
  220. finally
  221. {
  222. if (!success)
  223. {
  224. thisPtr.Abort();
  225. }
  226. }
  227. }
  228. //returns false if the connection should be aborted
  229. bool ContinuePostValidationProcessing()
  230. {
  231. if (viaDelegate != null)
  232. {
  233. try
  234. {
  235. viaDelegate(via);
  236. }
  237. catch (ServiceActivationException e)
  238. {
  239. DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
  240. // return fault and close connection
  241. SendFault(FramingEncodingString.ServiceActivationFailedFault);
  242. return true;
  243. }
  244. }
  245. this.transportSettings = transportSettingsCallback(via);
  246. if (transportSettings == null)
  247. {
  248. EndpointNotFoundException e = new EndpointNotFoundException(SR.GetString(SR.EndpointNotFound, decoder.Via));
  249. DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
  250. // return fault and close connection
  251. SendFault(FramingEncodingString.EndpointNotFoundFault);
  252. return false;
  253. }
  254. // we have enough information to hand off to a channel. Our job is done
  255. callback(this);
  256. return true;
  257. }
  258. public void SendFault(string faultString)
  259. {
  260. SendFault(faultString, ref this.receiveTimeoutHelper);
  261. }
  262. void SendFault(string faultString, ref TimeoutHelper timeoutHelper)
  263. {
  264. InitialServerConnectionReader.SendFault(Connection, faultString,
  265. connectionBuffer, timeoutHelper.RemainingTime(), TransportDefaults.MaxDrainSize);
  266. }
  267. public IAsyncResult BeginCompletePreamble(TimeSpan timeout, AsyncCallback callback, object state)
  268. {
  269. return new CompletePreambleAsyncResult(timeout, this, callback, state);
  270. }
  271. public IConnection EndCompletePreamble(IAsyncResult result)
  272. {
  273. return CompletePreambleAsyncResult.End(result);
  274. }
  275. class CompletePreambleAsyncResult : TypedAsyncResult<IConnection>
  276. {
  277. static WaitCallback onReadCompleted = new WaitCallback(OnReadCompleted);
  278. static WaitCallback onWriteCompleted = new WaitCallback(OnWriteCompleted);
  279. static AsyncCallback onUpgradeComplete = Fx.ThunkCallback(OnUpgradeComplete);
  280. TimeoutHelper timeoutHelper;
  281. ServerSingletonPreambleConnectionReader parent;
  282. StreamUpgradeAcceptor upgradeAcceptor;
  283. StreamUpgradeProvider upgrade;
  284. IStreamUpgradeChannelBindingProvider channelBindingProvider;
  285. IConnection currentConnection;
  286. UpgradeState upgradeState = UpgradeState.None;
  287. public CompletePreambleAsyncResult(TimeSpan timeout, ServerSingletonPreambleConnectionReader parent, AsyncCallback callback, object state)
  288. : base(callback, state)
  289. {
  290. this.timeoutHelper = new TimeoutHelper(timeout);
  291. this.parent = parent;
  292. Initialize();
  293. if (ContinueWork(null))
  294. {
  295. Complete(this.currentConnection, true);
  296. }
  297. }
  298. byte[] ConnectionBuffer
  299. {
  300. get
  301. {
  302. return this.parent.connectionBuffer;
  303. }
  304. set
  305. {
  306. this.parent.connectionBuffer = value;
  307. }
  308. }
  309. int Offset
  310. {
  311. get
  312. {
  313. return this.parent.offset;
  314. }
  315. set
  316. {
  317. this.parent.offset = value;
  318. }
  319. }
  320. int Size
  321. {
  322. get
  323. {
  324. return this.parent.size;
  325. }
  326. set
  327. {
  328. this.parent.size = value;
  329. }
  330. }
  331. bool CanReadAndDecode
  332. {
  333. get
  334. {
  335. //ok to read/decode before we start the upgrade
  336. //and between UpgradeComplete/WritingPreambleAck
  337. return this.upgradeState == UpgradeState.None
  338. || this.upgradeState == UpgradeState.UpgradeComplete;
  339. }
  340. }
  341. ServerSingletonDecoder Decoder
  342. {
  343. get
  344. {
  345. return this.parent.decoder;
  346. }
  347. }
  348. void Initialize()
  349. {
  350. if (!this.parent.transportSettings.MessageEncoderFactory.Encoder.IsContentTypeSupported(Decoder.ContentType))
  351. {
  352. SendFault(FramingEncodingString.ContentTypeInvalidFault, ref timeoutHelper);
  353. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(SR.GetString(
  354. SR.ContentTypeMismatch, Decoder.ContentType, parent.transportSettings.MessageEncoderFactory.Encoder.ContentType)));
  355. }
  356. upgrade = this.parent.transportSettings.Upgrade;
  357. if (upgrade != null)
  358. {
  359. channelBindingProvider = upgrade.GetProperty<IStreamUpgradeChannelBindingProvider>();
  360. upgradeAcceptor = upgrade.CreateUpgradeAcceptor();
  361. }
  362. this.currentConnection = this.parent.Connection;
  363. }
  364. void SendFault(string faultString, ref TimeoutHelper timeoutHelper)
  365. {
  366. this.parent.SendFault(faultString, ref timeoutHelper);
  367. }
  368. bool BeginRead()
  369. {
  370. this.Offset = 0;
  371. return this.currentConnection.BeginRead(0, this.ConnectionBuffer.Length, timeoutHelper.RemainingTime(), onReadCompleted, this) == AsyncCompletionResult.Completed;
  372. }
  373. void EndRead()
  374. {
  375. this.Size = currentConnection.EndRead();
  376. if (this.Size == 0)
  377. {
  378. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(this.Decoder.CreatePrematureEOFException());
  379. }
  380. }
  381. bool ContinueWork(IAsyncResult upgradeAsyncResult)
  382. {
  383. if (upgradeAsyncResult != null)
  384. {
  385. Fx.AssertAndThrow(this.upgradeState == UpgradeState.EndUpgrade, "upgradeAsyncResult should only be passed in from OnUpgradeComplete callback");
  386. }
  387. for (;;)
  388. {
  389. if (Size == 0 && this.CanReadAndDecode)
  390. {
  391. if (BeginRead())
  392. {
  393. EndRead();
  394. }
  395. else
  396. {
  397. //when read completes, we will re-enter this loop.
  398. break;
  399. }
  400. }
  401. for (;;)
  402. {
  403. if (this.CanReadAndDecode)
  404. {
  405. int bytesRead = Decoder.Decode(ConnectionBuffer, Offset, Size);
  406. if (bytesRead > 0)
  407. {
  408. Offset += bytesRead;
  409. Size -= bytesRead;
  410. }
  411. }
  412. switch (Decoder.CurrentState)
  413. {
  414. case ServerSingletonDecoder.State.UpgradeRequest:
  415. switch (this.upgradeState)
  416. {
  417. case UpgradeState.None:
  418. //change the state so that we don't read/decode until it is safe
  419. ChangeUpgradeState(UpgradeState.VerifyingUpgradeRequest);
  420. break;
  421. case UpgradeState.VerifyingUpgradeRequest:
  422. if (this.upgradeAcceptor == null)
  423. {
  424. SendFault(FramingEncodingString.UpgradeInvalidFault, ref timeoutHelper);
  425. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  426. new ProtocolException(SR.GetString(SR.UpgradeRequestToNonupgradableService, Decoder.Upgrade)));
  427. }
  428. if (!this.upgradeAcceptor.CanUpgrade(Decoder.Upgrade))
  429. {
  430. SendFault(FramingEncodingString.UpgradeInvalidFault, ref timeoutHelper);
  431. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(SR.GetString(SR.UpgradeProtocolNotSupported, Decoder.Upgrade)));
  432. }
  433. ChangeUpgradeState(UpgradeState.WritingUpgradeAck);
  434. // accept upgrade
  435. if (this.currentConnection.BeginWrite(ServerSingletonEncoder.UpgradeResponseBytes, 0, ServerSingletonEncoder.UpgradeResponseBytes.Length,
  436. true, timeoutHelper.RemainingTime(), onWriteCompleted, this) == AsyncCompletionResult.Queued)
  437. {
  438. //OnWriteCompleted will:
  439. // 1) set upgradeState to UpgradeAckSent
  440. // 2) call EndWrite
  441. return false;
  442. }
  443. else
  444. {
  445. this.currentConnection.EndWrite();
  446. }
  447. ChangeUpgradeState(UpgradeState.UpgradeAckSent);
  448. break;
  449. case UpgradeState.UpgradeAckSent:
  450. IConnection connectionToUpgrade = this.currentConnection;
  451. if (Size > 0)
  452. {
  453. connectionToUpgrade = new PreReadConnection(connectionToUpgrade, ConnectionBuffer, Offset, Size);
  454. }
  455. ChangeUpgradeState(UpgradeState.BeginUpgrade);
  456. break;
  457. case UpgradeState.BeginUpgrade:
  458. try
  459. {
  460. if (!BeginUpgrade(out upgradeAsyncResult))
  461. {
  462. //OnUpgradeComplete will set upgradeState to EndUpgrade
  463. return false;
  464. }
  465. ChangeUpgradeState(UpgradeState.EndUpgrade);
  466. }
  467. catch (Exception exception)
  468. {
  469. if (Fx.IsFatal(exception))
  470. throw;
  471. this.parent.WriteAuditFailure(upgradeAcceptor as StreamSecurityUpgradeAcceptor, exception);
  472. throw;
  473. }
  474. break;
  475. case UpgradeState.EndUpgrade://Must be a different state here than UpgradeComplete so that we don't try to read from the connection
  476. try
  477. {
  478. EndUpgrade(upgradeAsyncResult);
  479. ChangeUpgradeState(UpgradeState.UpgradeComplete);
  480. }
  481. catch (Exception exception)
  482. {
  483. if (Fx.IsFatal(exception))
  484. throw;
  485. this.parent.WriteAuditFailure(upgradeAcceptor as StreamSecurityUpgradeAcceptor, exception);
  486. throw;
  487. }
  488. break;
  489. case UpgradeState.UpgradeComplete:
  490. //Client is doing more than one upgrade, reset the state
  491. ChangeUpgradeState(UpgradeState.VerifyingUpgradeRequest);
  492. break;
  493. }
  494. break;
  495. case ServerSingletonDecoder.State.Start:
  496. this.parent.SetupSecurityIfNecessary(upgradeAcceptor);
  497. if (this.upgradeState == UpgradeState.UpgradeComplete //We have done at least one upgrade, but we are now done.
  498. || this.upgradeState == UpgradeState.None)//no upgrade, just send the preample end bytes
  499. {
  500. ChangeUpgradeState(UpgradeState.WritingPreambleEnd);
  501. // we've finished the preamble. Ack and return.
  502. if (this.currentConnection.BeginWrite(ServerSessionEncoder.AckResponseBytes, 0, ServerSessionEncoder.AckResponseBytes.Length,
  503. true, timeoutHelper.RemainingTime(), onWriteCompleted, this) == AsyncCompletionResult.Queued)
  504. {
  505. //OnWriteCompleted will:
  506. // 1) set upgradeState to PreambleEndSent
  507. // 2) call EndWrite
  508. return false;
  509. }
  510. else
  511. {
  512. this.currentConnection.EndWrite();
  513. }
  514. //terminal state
  515. ChangeUpgradeState(UpgradeState.PreambleEndSent);
  516. }
  517. //we are done, this.currentConnection is the upgraded connection
  518. return true;
  519. }
  520. if (Size == 0)
  521. {
  522. break;
  523. }
  524. }
  525. }
  526. return false;
  527. }
  528. bool BeginUpgrade(out IAsyncResult upgradeAsyncResult)
  529. {
  530. upgradeAsyncResult = InitialServerConnectionReader.BeginUpgradeConnection(this.currentConnection, upgradeAcceptor, this.parent.transportSettings, onUpgradeComplete, this);
  531. if (!upgradeAsyncResult.CompletedSynchronously)
  532. {
  533. upgradeAsyncResult = null; //caller shouldn't use this out param unless completed [....].
  534. return false;
  535. }
  536. return true;
  537. }
  538. void EndUpgrade(IAsyncResult upgradeAsyncResult)
  539. {
  540. this.currentConnection = InitialServerConnectionReader.EndUpgradeConnection(upgradeAsyncResult);
  541. this.ConnectionBuffer = this.currentConnection.AsyncReadBuffer;
  542. if (this.channelBindingProvider != null
  543. && this.channelBindingProvider.IsChannelBindingSupportEnabled
  544. && this.parent.channelBindingToken == null)//first one wins in the case of multiple upgrades.
  545. {
  546. this.parent.channelBindingToken = channelBindingProvider.GetChannelBinding(this.upgradeAcceptor, ChannelBindingKind.Endpoint);
  547. }
  548. }
  549. void ChangeUpgradeState(UpgradeState newState)
  550. {
  551. switch (newState)
  552. {
  553. case UpgradeState.None:
  554. throw Fx.AssertAndThrow("Invalid State Transition: currentState=" + this.upgradeState + ", newState=" + newState);
  555. case UpgradeState.VerifyingUpgradeRequest:
  556. if (this.upgradeState != UpgradeState.None //starting first upgrade
  557. && this.upgradeState != UpgradeState.UpgradeComplete)//completing one upgrade and starting another
  558. {
  559. throw Fx.AssertAndThrow("Invalid State Transition: currentState=" + this.upgradeState + ", newState=" + newState);
  560. }
  561. break;
  562. case UpgradeState.WritingUpgradeAck:
  563. if (this.upgradeState != UpgradeState.VerifyingUpgradeRequest)
  564. {
  565. throw Fx.AssertAndThrow("Invalid State Transition: currentState=" + this.upgradeState + ", newState=" + newState);
  566. }
  567. break;
  568. case UpgradeState.UpgradeAckSent:
  569. if (this.upgradeState != UpgradeState.WritingUpgradeAck)
  570. {
  571. throw Fx.AssertAndThrow("Invalid State Transition: currentState=" + this.upgradeState + ", newState=" + newState);
  572. }
  573. break;
  574. case UpgradeState.BeginUpgrade:
  575. if (this.upgradeState != UpgradeState.UpgradeAckSent)
  576. {
  577. throw Fx.AssertAndThrow("Invalid State Transition: currentState=" + this.upgradeState + ", newState=" + newState);
  578. }
  579. break;
  580. case UpgradeState.EndUpgrade:
  581. if (this.upgradeState != UpgradeState.BeginUpgrade)
  582. {
  583. throw Fx.AssertAndThrow("Invalid State Transition: currentState=" + this.upgradeState + ", newState=" + newState);
  584. }
  585. break;
  586. case UpgradeState.UpgradeComplete:
  587. if (this.upgradeState != UpgradeState.EndUpgrade)
  588. {
  589. throw Fx.AssertAndThrow("Invalid State Transition: currentState=" + this.upgradeState + ", newState=" + newState);
  590. }
  591. break;
  592. case UpgradeState.WritingPreambleEnd:
  593. if (this.upgradeState != UpgradeState.None //no upgrade being used
  594. && this.upgradeState != UpgradeState.UpgradeComplete)//upgrades are now complete, end the preamble handshake.
  595. {
  596. throw Fx.AssertAndThrow("Invalid State Transition: currentState=" + this.upgradeState + ", newState=" + newState);
  597. }
  598. break;
  599. case UpgradeState.PreambleEndSent:
  600. if (this.upgradeState != UpgradeState.WritingPreambleEnd)
  601. {
  602. throw Fx.AssertAndThrow("Invalid State Transition: currentState=" + this.upgradeState + ", newState=" + newState);
  603. }
  604. break;
  605. default:
  606. throw Fx.AssertAndThrow("Unexpected Upgrade State: " + newState);
  607. }
  608. this.upgradeState = newState;
  609. }
  610. static void OnReadCompleted(object state)
  611. {
  612. CompletePreambleAsyncResult thisPtr = (CompletePreambleAsyncResult)state;
  613. Exception completionException = null;
  614. bool completeSelf = false;
  615. try
  616. {
  617. thisPtr.EndRead();
  618. completeSelf = thisPtr.ContinueWork(null);
  619. }
  620. catch (Exception ex)
  621. {
  622. if (Fx.IsFatal(ex))
  623. {
  624. throw;
  625. }
  626. completionException = ex;
  627. completeSelf = true;
  628. }
  629. if (completeSelf)
  630. {
  631. if (completionException != null)
  632. {
  633. thisPtr.Complete(false, completionException);
  634. }
  635. else
  636. {
  637. thisPtr.Complete(thisPtr.currentConnection, false);
  638. }
  639. }
  640. }
  641. static void OnWriteCompleted(object state)
  642. {
  643. CompletePreambleAsyncResult thisPtr = (CompletePreambleAsyncResult)state;
  644. Exception completionException = null;
  645. bool completeSelf = false;
  646. try
  647. {
  648. thisPtr.currentConnection.EndWrite();
  649. switch (thisPtr.upgradeState)
  650. {
  651. case UpgradeState.WritingUpgradeAck:
  652. thisPtr.ChangeUpgradeState(UpgradeState.UpgradeAckSent);
  653. break;
  654. case UpgradeState.WritingPreambleEnd:
  655. thisPtr.ChangeUpgradeState(UpgradeState.PreambleEndSent);
  656. break;
  657. }
  658. completeSelf = thisPtr.ContinueWork(null);
  659. }
  660. catch (Exception ex)
  661. {
  662. if (Fx.IsFatal(ex))
  663. {
  664. throw;
  665. }
  666. completionException = ex;
  667. completeSelf = true;
  668. }
  669. if (completeSelf)
  670. {
  671. if (completionException != null)
  672. {
  673. thisPtr.Complete(false, completionException);
  674. }
  675. else
  676. {
  677. thisPtr.Complete(thisPtr.currentConnection, false);
  678. }
  679. }
  680. }
  681. static void OnUpgradeComplete(IAsyncResult result)
  682. {
  683. if (result.CompletedSynchronously)
  684. {
  685. return;
  686. }
  687. CompletePreambleAsyncResult thisPtr = (CompletePreambleAsyncResult)result.AsyncState;
  688. Exception completionException = null;
  689. bool completeSelf = false;
  690. try
  691. {
  692. thisPtr.ChangeUpgradeState(UpgradeState.EndUpgrade);
  693. completeSelf = thisPtr.ContinueWork(result);
  694. }
  695. catch (Exception ex)
  696. {
  697. if (Fx.IsFatal(ex))
  698. {
  699. throw;
  700. }
  701. completionException = ex;
  702. completeSelf = true;
  703. }
  704. if (completeSelf)
  705. {
  706. if (completionException != null)
  707. {
  708. thisPtr.Complete(false, completionException);
  709. }
  710. else
  711. {
  712. thisPtr.Complete(thisPtr.currentConnection, false);
  713. }
  714. }
  715. }
  716. enum UpgradeState
  717. {
  718. None,
  719. VerifyingUpgradeRequest,
  720. WritingUpgradeAck,
  721. UpgradeAckSent,
  722. BeginUpgrade,
  723. EndUpgrade,
  724. UpgradeComplete,
  725. WritingPreambleEnd,
  726. PreambleEndSent,
  727. }
  728. }
  729. void SetupSecurityIfNecessary(StreamUpgradeAcceptor upgradeAcceptor)
  730. {
  731. StreamSecurityUpgradeAcceptor securityUpgradeAcceptor = upgradeAcceptor as StreamSecurityUpgradeAcceptor;
  732. if (securityUpgradeAcceptor != null)
  733. {
  734. this.security = securityUpgradeAcceptor.GetRemoteSecurity();
  735. if (this.security == null)
  736. {
  737. Exception securityFailedException = new ProtocolException(
  738. SR.GetString(SR.RemoteSecurityNotNegotiatedOnStreamUpgrade, this.Via));
  739. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(securityFailedException);
  740. }
  741. // Audit Authentication Success
  742. WriteAuditEvent(securityUpgradeAcceptor, AuditLevel.Success, null);
  743. }
  744. }
  745. #region Transport Security Auditing
  746. void WriteAuditFailure(StreamSecurityUpgradeAcceptor securityUpgradeAcceptor, Exception exception)
  747. {
  748. try
  749. {
  750. WriteAuditEvent(securityUpgradeAcceptor, AuditLevel.Failure, exception);
  751. }
  752. #pragma warning suppress 56500 // covered by FxCop
  753. catch (Exception auditException)
  754. {
  755. if (Fx.IsFatal(auditException))
  756. {
  757. throw;
  758. }
  759. DiagnosticUtility.TraceHandledException(auditException, TraceEventType.Error);
  760. }
  761. }
  762. void WriteAuditEvent(StreamSecurityUpgradeAcceptor securityUpgradeAcceptor, AuditLevel auditLevel, Exception exception)
  763. {
  764. if ((this.transportSettings.AuditBehavior.MessageAuthenticationAuditLevel & auditLevel) != auditLevel)
  765. {
  766. return;
  767. }
  768. if (securityUpgradeAcceptor == null)
  769. {
  770. return;
  771. }
  772. String primaryIdentity = String.Empty;
  773. SecurityMessageProperty clientSecurity = securityUpgradeAcceptor.GetRemoteSecurity();
  774. if (clientSecurity != null)
  775. {
  776. primaryIdentity = GetIdentityNameFromContext(clientSecurity);
  777. }
  778. ServiceSecurityAuditBehavior auditBehavior = this.transportSettings.AuditBehavior;
  779. if (auditLevel == AuditLevel.Success)
  780. {
  781. SecurityAuditHelper.WriteTransportAuthenticationSuccessEvent(auditBehavior.AuditLogLocation,
  782. auditBehavior.SuppressAuditFailure, null, this.Via, primaryIdentity);
  783. }
  784. else
  785. {
  786. SecurityAuditHelper.WriteTransportAuthenticationFailureEvent(auditBehavior.AuditLogLocation,
  787. auditBehavior.SuppressAuditFailure, null, this.Via, primaryIdentity, exception);
  788. }
  789. }
  790. [MethodImpl(MethodImplOptions.NoInlining)]
  791. static string GetIdentityNameFromContext(SecurityMessageProperty clientSecurity)
  792. {
  793. return SecurityUtils.GetIdentityNamesFromContext(
  794. clientSecurity.ServiceSecurityContext.AuthorizationContext);
  795. }
  796. #endregion
  797. void HandleReadComplete()
  798. {
  799. offset = 0;
  800. size = Connection.EndRead();
  801. isReadPending = false;
  802. if (size == 0)
  803. {
  804. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(decoder.CreatePrematureEOFException());
  805. }
  806. }
  807. void OnAsyncReadComplete(object state)
  808. {
  809. bool success = false;
  810. try
  811. {
  812. HandleReadComplete();
  813. ReadAndDispatch();
  814. success = true;
  815. }
  816. catch (CommunicationException exception)
  817. {
  818. DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information);
  819. }
  820. catch (TimeoutException exception)
  821. {
  822. if (TD.ReceiveTimeoutIsEnabled())
  823. {
  824. TD.ReceiveTimeout(exception.Message);
  825. }
  826. DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information);
  827. }
  828. catch (Exception e)
  829. {
  830. if (Fx.IsFatal(e))
  831. {
  832. throw;
  833. }
  834. if (!ExceptionHandler.HandleTransportExceptionHelper(e))
  835. {
  836. throw;
  837. }
  838. // containment -- we abort ourselves for any error, no extra containment needed
  839. }
  840. finally
  841. {
  842. if (!success)
  843. {
  844. Abort();
  845. }
  846. }
  847. }
  848. public void StartReading(Action<Uri> viaDelegate, TimeSpan timeout)
  849. {
  850. this.viaDelegate = viaDelegate;
  851. this.receiveTimeoutHelper = new TimeoutHelper(timeout);
  852. this.connectionBuffer = Connection.AsyncReadBuffer;
  853. ReadAndDispatch();
  854. }
  855. }
  856. class ServerSingletonConnectionReader : SingletonConnectionReader
  857. {
  858. ConnectionDemuxer connectionDemuxer;
  859. ServerSingletonDecoder decoder;
  860. IConnection rawConnection;
  861. string contentType;
  862. ChannelBinding channelBindingToken;
  863. public ServerSingletonConnectionReader(ServerSingletonPreambleConnectionReader preambleReader,
  864. IConnection upgradedConnection, ConnectionDemuxer connectionDemuxer)
  865. : base(upgradedConnection, preambleReader.BufferOffset, preambleReader.BufferSize,
  866. preambleReader.Security, preambleReader.TransportSettings, preambleReader.Via)
  867. {
  868. this.decoder = preambleReader.Decoder;
  869. this.contentType = this.decoder.ContentType;
  870. this.connectionDemuxer = connectionDemuxer;
  871. this.rawConnection = preambleReader.RawConnection;
  872. this.channelBindingToken = preambleReader.ChannelBinding;
  873. }
  874. protected override string ContentType
  875. {
  876. get { return this.contentType; }
  877. }
  878. protected override long StreamPosition
  879. {
  880. get { return this.decoder.StreamPosition; }
  881. }
  882. protected override bool DecodeBytes(byte[] buffer, ref int offset, ref int size, ref bool isAtEof)
  883. {
  884. while (size > 0)
  885. {
  886. int bytesRead = decoder.Decode(buffer, offset, size);
  887. if (bytesRead > 0)
  888. {
  889. offset += bytesRead;
  890. size -= bytesRead;
  891. }
  892. switch (decoder.CurrentState)
  893. {
  894. case ServerSingletonDecoder.State.EnvelopeStart:
  895. // we're at the envelope
  896. return true;
  897. case ServerSingletonDecoder.State.End:
  898. isAtEof = true;
  899. return false;
  900. }
  901. }
  902. return false;
  903. }
  904. protected override void OnClose(TimeSpan timeout)
  905. {
  906. TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
  907. // send back EOF and then recycle the connection
  908. this.Connection.Write(SingletonEncoder.EndBytes, 0, SingletonEncoder.EndBytes.Length, true, timeoutHelper.RemainingTime());
  909. this.connectionDemuxer.ReuseConnection(this.rawConnection, timeoutHelper.RemainingTime());
  910. ChannelBindingUtility.Dispose(ref this.channelBindingToken);
  911. }
  912. protected override void PrepareMessage(Message message)
  913. {
  914. base.PrepareMessage(message);
  915. IPEndPoint remoteEndPoint = this.rawConnection.RemoteIPEndPoint;
  916. // pipes will return null
  917. if (remoteEndPoint != null)
  918. {
  919. RemoteEndpointMessageProperty remoteEndpointProperty = new RemoteEndpointMessageProperty(remoteEndPoint);
  920. message.Properties.Add(RemoteEndpointMessageProperty.Name, remoteEndpointProperty);
  921. }
  922. if (this.channelBindingToken != null)
  923. {
  924. ChannelBindingMessageProperty property = new ChannelBindingMessageProperty(this.channelBindingToken, false);
  925. property.AddTo(message);
  926. property.Dispose(); //message.Properties.Add() creates a copy...
  927. }
  928. }
  929. }
  930. abstract class SingletonConnectionReader
  931. {
  932. IConnection connection;
  933. bool doneReceiving;
  934. bool doneSending;
  935. bool isAtEof;
  936. bool isClosed;
  937. SecurityMessageProperty security;
  938. object thisLock = new object();
  939. int offset;
  940. int size;
  941. IConnectionOrientedTransportFactorySettings transportSettings;
  942. Uri via;
  943. Stream inputStream;
  944. protected SingletonConnectionReader(IConnection connection, int offset, int size, SecurityMessageProperty security,
  945. IConnectionOrientedTransportFactorySettings transportSettings, Uri via)
  946. {
  947. this.connection = connection;
  948. this.offset = offset;
  949. this.size = size;
  950. this.security = security;
  951. this.transportSettings = transportSettings;
  952. this.via = via;
  953. }
  954. protected IConnection Connection
  955. {
  956. get
  957. {
  958. return this.connection;
  959. }
  960. }
  961. protected object ThisLock
  962. {
  963. get
  964. {
  965. return this.thisLock;
  966. }
  967. }
  968. protected virtual string ContentType
  969. {
  970. get { return null; }
  971. }
  972. protected abstract long StreamPosition { get; }
  973. public void Abort()
  974. {
  975. this.connection.Abort();
  976. }
  977. public void DoneReceiving(bool atEof)
  978. {
  979. DoneReceiving(atEof, this.transportSettings.CloseTimeout);
  980. }
  981. void DoneReceiving(bool atEof, TimeSpan timeout)
  982. {
  983. if (!this.doneReceiving)
  984. {
  985. this.isAtEof = atEof;
  986. this.doneReceiving = true;
  987. if (this.doneSending)
  988. {
  989. this.Close(timeout);
  990. }
  991. }
  992. }
  993. public void Close(TimeSpan timeout)
  994. {
  995. lock (ThisLock)
  996. {
  997. if (this.isClosed)
  998. {
  999. return;
  1000. }
  1001. this.isClosed = true;
  1002. }
  1003. TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
  1004. bool success = false;
  1005. try
  1006. {
  1007. // first drain our stream if necessary
  1008. if (this.inputStream != null)
  1009. {
  1010. byte[] dummy = DiagnosticUtility.Utility.AllocateByteArray(transportSettings.ConnectionBufferSize);
  1011. while (!this.isAtEof)
  1012. {
  1013. this.inputStream.ReadTimeout = TimeoutHelper.ToMilliseconds(timeoutHelper.RemainingTime());
  1014. int bytesRead = this.inputStream.Read(dummy, 0, dummy.Length);
  1015. if (bytesRead == 0)
  1016. {
  1017. this.isAtEof = true;
  1018. }
  1019. }
  1020. }
  1021. OnClose(timeoutHelper.RemainingTime());
  1022. success = true;
  1023. }
  1024. finally
  1025. {
  1026. if (!success)
  1027. {
  1028. this.Abort();
  1029. }
  1030. }
  1031. }
  1032. protected abstract void OnClose(TimeSpan timeout);
  1033. public void DoneSending(TimeSpan timeout)
  1034. {
  1035. this.doneSending = true;
  1036. if (this.doneReceiving)
  1037. {
  1038. this.Close(timeout);
  1039. }
  1040. }
  1041. protected abstract bool DecodeBytes(byte[] buffer, ref int offset, ref int size, ref bool isAtEof);
  1042. protected virtual void PrepareMessage(Message message)
  1043. {
  1044. message.Properties.Via = this.via;
  1045. message.Properties.Security = (this.security != null) ? (SecurityMessageProperty)this.security.CreateCopy() : null;
  1046. }
  1047. public RequestContext ReceiveRequest(TimeSpan timeout)
  1048. {
  1049. Message requestMessage = Receive(timeout);
  1050. return new StreamedFramingRequestContext(this, requestMessage);
  1051. }
  1052. public IAsyncResult BeginReceive(TimeSpan timeout, AsyncCallback callback, object state)
  1053. {
  1054. return new ReceiveAsyncResult(this, timeout, callback, state);
  1055. }
  1056. public virtual Message EndReceive(IAsyncResult result)
  1057. {
  1058. return ReceiveAsyncResult.End(result);
  1059. }
  1060. public Message Receive(TimeSpan timeout)
  1061. {
  1062. byte[] buffer = DiagnosticUtility.Utility.AllocateByteArray(connection.AsyncReadBufferSize);
  1063. if (size > 0)
  1064. {
  1065. Buffer.BlockCopy(connection.AsyncReadBuffer, offset, buffer, offset, size);
  1066. }
  1067. TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
  1068. for (;;)
  1069. {
  1070. if (DecodeBytes(buffer, ref offset, ref size, ref isAtEof))
  1071. {
  1072. break;
  1073. }
  1074. if (this.isAtEof)
  1075. {
  1076. DoneReceiving(true, timeoutHelper.RemainingTime());
  1077. return null;
  1078. }
  1079. if (size == 0)
  1080. {
  1081. offset = 0;
  1082. size = connection.Read(buffer, 0, buffer.Length, timeoutHelper.RemainingTime());
  1083. if (size == 0)
  1084. {
  1085. DoneReceiving(true, timeoutHelper.RemainingTime());
  1086. return null;
  1087. }
  1088. }
  1089. }
  1090. // we're ready to read a message
  1091. IConnection singletonConnection = this.connection;
  1092. if (size > 0)
  1093. {
  1094. byte[] initialData = DiagnosticUtility.Utility.AllocateByteArray(size);
  1095. Buffer.BlockCopy(buffer, offset, initialData, 0, size);
  1096. singletonConnection = new PreReadConnection(singletonConnection, initialData);
  1097. }
  1098. Stream connectionStream = new SingletonInputConnectionStream(this, singletonConnection, this.transportSettings);
  1099. this.inputStream = new MaxMessageSizeStream(connectionStream, transportSettings.MaxReceivedMessageSize);
  1100. using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity(true) : null)
  1101. {
  1102. if (DiagnosticUtility.ShouldUseActivity)
  1103. {
  1104. ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityProcessingMessage, TraceUtility.RetrieveMessageNumber()), ActivityType.ProcessMessage);
  1105. }
  1106. Message message = null;
  1107. try
  1108. {
  1109. message = transportSettings.MessageEncoderFactory.Encoder.ReadMessage(
  1110. this.inputStream, transportSettings.MaxBufferSize, this.ContentType);
  1111. }
  1112. catch (XmlException xmlException)
  1113. {
  1114. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
  1115. new ProtocolException(SR.GetString(SR.MessageXmlProtocolError), xmlException));
  1116. }
  1117. if (DiagnosticUtility.ShouldUseActivity)
  1118. {
  1119. TraceUtility.TransferFromTransport(message);
  1120. }
  1121. PrepareMessage(message);
  1122. return message;
  1123. }
  1124. }
  1125. class ReceiveAsyncResult : AsyncResult
  1126. {
  1127. static Action<object> onReceiveScheduled = new Action<object>(OnReceiveScheduled);
  1128. Message message;
  1129. SingletonConnectionReader parent;
  1130. TimeSpan timeout;
  1131. public ReceiveAsyncResult(SingletonConnectionReader parent, TimeSpan timeout, AsyncCallback callback,
  1132. object state)
  1133. : base(callback, state)
  1134. {
  1135. this.parent = parent;
  1136. this.timeout = timeout;
  1137. //
  1138. ActionItem.Schedule(onReceiveScheduled, this);
  1139. }
  1140. public static Message End(IAsyncResult result)
  1141. {
  1142. ReceiveAsyncResult receiveAsyncResult = AsyncResult.End<ReceiveAsyncResult>(result);
  1143. return receiveAsyncResult.message;
  1144. }
  1145. static void OnReceiveScheduled(object state)
  1146. {
  1147. ReceiveAsyncResult thisPtr = (ReceiveAsyncResult)state;
  1148. Exception completionException = null;
  1149. try
  1150. {
  1151. thisPtr.message = thisPtr.parent.Receive(thisPtr.timeout);
  1152. }
  1153. #pragma warning suppress 56500 // [....], transferring exception to another thread
  1154. catch (Exception exception)
  1155. {
  1156. if (Fx.IsFatal(exception))
  1157. {
  1158. throw;
  1159. }
  1160. completionException = exception;
  1161. }
  1162. thisPtr.Complete(false, completionException);
  1163. }
  1164. }
  1165. class StreamedFramingRequestContext : RequestContextBase
  1166. {
  1167. IConnection connection;
  1168. SingletonConnectionReader parent;
  1169. IConnectionOrientedTransportFactorySettings settings;
  1170. TimeoutHelper timeoutHelper;
  1171. public StreamedFramingRequestContext(SingletonConnectionReader parent, Message requestMessage)
  1172. : base(requestMessage, parent.transportSettings.CloseTimeout, parent.transportSettings.SendTimeout)
  1173. {
  1174. this.parent = parent;
  1175. this.connection = parent.connection;
  1176. this.settings = parent.transportSettings;
  1177. }
  1178. protected override void OnAbort()
  1179. {
  1180. this.parent.Abort();
  1181. }
  1182. protected override void OnClose(TimeSpan timeout)
  1183. {
  1184. this.parent.Close(timeout);
  1185. }
  1186. protected override void OnReply(Message message, TimeSpan timeout)
  1187. {
  1188. ICompressedMessageEncoder compressedMessageEncoder = this.settings.MessageEncoderFactory.Encoder as ICompressedMessageEncoder;
  1189. if (compressedMessageEncoder != null && compressedMessageEncoder.CompressionEnabled)
  1190. {
  1191. compressedMessageEncoder.AddCompressedMessageProperties(message, this.parent.ContentType);
  1192. }
  1193. timeoutHelper = new TimeoutHelper(timeout);
  1194. StreamingConnectionHelper.WriteMessage(message, this.connection, false, this.settings, ref timeoutHelper);
  1195. parent.DoneSending(timeoutHelper.RemainingTime());
  1196. }
  1197. protected override IAsyncResult OnBeginReply(Message message, TimeSpan timeout, AsyncCallback callback, object state)
  1198. {
  1199. ICompressedMessageEncoder compressedMessageEncoder = this.settings.MessageEncoderFactory.Encoder as ICompressedMessageEncoder;
  1200. if (compressedMessageEncoder != null && compressedMessageEncoder.CompressionEnabled)
  1201. {
  1202. compressedMessageEncoder.AddCompressedMessageProperties(message, this.parent.ContentType);
  1203. }
  1204. timeoutHelper = new TimeoutHelper(timeout);
  1205. return StreamingConnectionHelper.BeginWriteMessage(message, this.connection, false, this.settings,
  1206. ref timeoutHelper, callback, state);
  1207. }
  1208. protected override void OnEndReply(IAsyncResult result)
  1209. {
  1210. StreamingConnectionHelper.EndWriteMessage(result);
  1211. parent.DoneSending(timeoutHelper.RemainingTime());
  1212. }
  1213. }
  1214. // ensures that the reader is notified at end-of-stream, and takes care of the framing chunk headers
  1215. class SingletonInputConnectionStream : ConnectionStream
  1216. {
  1217. SingletonMessageDecoder decoder;
  1218. SingletonConnectionReader reader;
  1219. bool atEof;
  1220. byte[] chunkBuffer; // used for when we have overflow
  1221. int chunkBufferOffset;
  1222. int chunkBufferSize;
  1223. int chunkBytesRemaining;
  1224. public SingletonInputConnectionStream(SingletonConnectionReader reader, IConnection connection,
  1225. IDefaultCommunicationTimeouts defaultTimeouts)
  1226. : base(connection, defaultTimeouts)
  1227. {
  1228. this.reader = reader;
  1229. this.decoder = new SingletonMessageDecoder(reader.StreamPosition);
  1230. this.chunkBytesRemaining = 0;
  1231. this.chunkBuffer = new byte[IntEncoder.MaxEncodedSize];
  1232. }
  1233. void AbortReader()
  1234. {
  1235. this.reader.Abort();
  1236. }
  1237. public override void Close()
  1238. {
  1239. this.reader.DoneReceiving(this.atEof);
  1240. }
  1241. // run chunk data through the decoder
  1242. void DecodeData(byte[] buffer, int offset, int size)
  1243. {
  1244. while (size > 0)
  1245. {
  1246. int bytesRead = decoder.Decode(buffer, offset, size);
  1247. offset += bytesRead;
  1248. size -= bytesRead;
  1249. Fx.Assert(decoder.CurrentState == SingletonMessageDecoder.State.ReadingEnvelopeBytes || decoder.CurrentState == SingletonMessageDecoder.State.ChunkEnd, "");
  1250. }
  1251. }
  1252. // run the current data through the decoder to get valid message bytes
  1253. void DecodeSize(byte[] buffer, ref int offset, ref int size)
  1254. {
  1255. while (size > 0)
  1256. {
  1257. int bytesRead = decoder.Decode(buffer, offset, size);
  1258. if (bytesRead > 0)
  1259. {
  1260. offset += bytesRead;
  1261. size -= bytesRead;
  1262. }
  1263. switch (decoder.CurrentState)
  1264. {
  1265. case SingletonMessageDecoder.State.ChunkStart:
  1266. this.chunkBytesRemaining = decoder.ChunkSize;
  1267. // if we have overflow and we're not decoding out of our buffer, copy over
  1268. if (size > 0 && !object.ReferenceEquals(buffer, this.chunkBuffer))
  1269. {
  1270. Fx.Assert(size <= this.chunkBuffer.Length, "");
  1271. Buffer.BlockCopy(buffer, offset, this.chunkBuffer, 0, size);
  1272. this.chunkBufferOffset = 0;
  1273. this.chunkBufferSize = size;
  1274. }
  1275. return;
  1276. case SingletonMessageDecoder.State.End:
  1277. ProcessEof();
  1278. return;
  1279. }
  1280. }
  1281. }
  1282. int ReadCore(byte[] buffer, int offset, int count)
  1283. {
  1284. int bytesRead = -1;
  1285. try
  1286. {
  1287. bytesRead = base.Read(buffer, offset, count);
  1288. if (bytesRead == 0)
  1289. {
  1290. ProcessEof();
  1291. }
  1292. }
  1293. finally
  1294. {
  1295. if (bytesRead == -1) // there was an exception
  1296. {
  1297. AbortReader();
  1298. }
  1299. }
  1300. return bytesRead;
  1301. }
  1302. public override int Read(byte[] buffer, int offset, int count)
  1303. {
  1304. int result = 0;
  1305. while (true)
  1306. {
  1307. if (count == 0)
  1308. {
  1309. return result;
  1310. }
  1311. if (this.atEof)
  1312. {
  1313. return result;
  1314. }
  1315. // first deal with any residual carryover
  1316. if (this.chunkBufferSize > 0)
  1317. {
  1318. int bytesToCopy = Math.Min(chunkBytesRemaining,
  1319. Math.Min(this.chunkBufferSize, count));
  1320. Buffer.BlockCopy(this.chunkBuffer, this.chunkBufferOffset, buffer, offset, bytesToCopy);
  1321. // keep decoder up to date
  1322. DecodeData(this.chunkBuffer, this.chunkBufferOffset, bytesToCopy);
  1323. this.chunkBufferOffset += bytesToCopy;
  1324. this.chunkBufferSize -= bytesToCopy;
  1325. this.chunkBytesRemaining -= bytesToCopy;
  1326. if (this.chunkBytesRemaining == 0 && this.chunkBufferSize > 0)
  1327. {
  1328. DecodeSize(this.chunkBuffer, ref this.chunkBufferOffset, ref this.chunkBufferSize);
  1329. }
  1330. result += bytesToCopy;
  1331. offset += bytesToCopy;
  1332. count -= bytesToCopy;
  1333. }
  1334. else if (chunkBytesRemaining > 0)
  1335. {
  1336. // We're in the middle of a chunk. Try and include the next chunk size as well
  1337. int bytesToRead = count;
  1338. if (int.MaxValue - chunkBytesRemaining >= IntEncoder.MaxEncodedSize)
  1339. {
  1340. bytesToRead = Math.Min(count, chunkBytesRemaining + IntEncoder.MaxEncodedSize);
  1341. }
  1342. int bytesRead = ReadCore(buffer, offset, bytesToRead);
  1343. // keep decoder up to date
  1344. DecodeData(buffer, offset, Math.Min(bytesRead, this.chunkBytesRemaining));
  1345. if (bytesRead > chunkBytesRemaining)
  1346. {
  1347. result += this.chunkBytesRemaining;
  1348. int overflowCount = bytesRead - chunkBytesRemaining;
  1349. int overflowOffset = offset + chunkBytesRemaining;
  1350. this.chunkBytesRemaining = 0;
  1351. // read at least part of the next chunk, and put any overflow in this.chunkBuffer
  1352. DecodeSize(buffer, ref overflowOffset, ref overflowCount);
  1353. }
  1354. else
  1355. {
  1356. result += bytesRead;
  1357. this.chunkBytesRemaining -= bytesRead;
  1358. }
  1359. return result;
  1360. }
  1361. else
  1362. {
  1363. // Final case: we have a new chunk. Read the size, and loop around again
  1364. if (count < IntEncoder.MaxEncodedSize)
  1365. {
  1366. // we don't have space for MaxEncodedSize, so it's worth the copy cost to read into a temp buffer
  1367. this.chunkBufferOffset = 0;
  1368. this.chunkBufferSize = ReadCore(this.chunkBuffer, 0, this.chunkBuffer.Length);
  1369. DecodeSize(this.chunkBuffer, ref this.chunkBufferOffset, ref this.chunkBufferSize);
  1370. }
  1371. else
  1372. {
  1373. int bytesRead = ReadCore(buffer, offset, IntEncoder.MaxEncodedSize);
  1374. int sizeOffset = offset;
  1375. DecodeSize(buffer, ref sizeOffset, ref bytesRead);
  1376. }
  1377. }
  1378. }
  1379. }
  1380. void ProcessEof()
  1381. {
  1382. if (!this.atEof)
  1383. {
  1384. this.atEof = true;
  1385. if (this.chunkBufferSize > 0 || this.chunkBytesRemaining > 0
  1386. || decoder.CurrentState != SingletonMessageDecoder.State.End)
  1387. {
  1388. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(decoder.CreatePrematureEOFException());
  1389. }
  1390. this.reader.DoneReceiving(true);
  1391. }
  1392. }
  1393. public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
  1394. {
  1395. return new ReadAsyncResult(this, buffer, offset, count, callback, state);
  1396. }
  1397. public override int EndRead(IAsyncResult result)
  1398. {
  1399. return ReadAsyncResult.End(result);
  1400. }
  1401. public class ReadAsyncResult : AsyncResult
  1402. {
  1403. SingletonInputConnectionStream parent;
  1404. int result;
  1405. public ReadAsyncResult(SingletonInputConnectionStream parent,
  1406. byte[] buffer, int offset, int count, AsyncCallback callback, object state)
  1407. : base(callback, state)
  1408. {
  1409. this.parent = parent;
  1410. //
  1411. this.result = this.parent.Read(buffer, offset, count);
  1412. base.Complete(true);
  1413. }
  1414. public static int End(IAsyncResult result)
  1415. {
  1416. ReadAsyncResult thisPtr = AsyncResult.End<ReadAsyncResult>(result);
  1417. return thisPtr.result;
  1418. }
  1419. }
  1420. }
  1421. }
  1422. static class StreamingConnectionHelper
  1423. {
  1424. public static void WriteMessage(Message message, IConnection connection, bool isRequest,
  1425. IConnectionOrientedTransportFactorySettings settings, ref TimeoutHelper timeoutHelper)
  1426. {
  1427. byte[] endBytes = null;
  1428. if (message != null)
  1429. {
  1430. MessageEncoder messageEncoder = settings.MessageEncoderFactory.Encoder;
  1431. byte[] envelopeStartBytes = SingletonEncoder.EnvelopeStartBytes;
  1432. bool writeStreamed;
  1433. if (isRequest)
  1434. {
  1435. endBytes = SingletonEncoder.EnvelopeEndFramingEndBytes;
  1436. writeStreamed = TransferModeHelper.IsRequestStreamed(settings.TransferMode);
  1437. }
  1438. else
  1439. {
  1440. endBytes = SingletonEncoder.EnvelopeEndBytes;
  1441. writeStreamed = TransferModeHelper.IsResponseStreamed(settings.TransferMode);
  1442. }
  1443. if (writeStreamed)
  1444. {
  1445. connection.Write(envelopeStartBytes, 0, envelopeStartBytes.Length, false, timeoutHelper.RemainingTime());
  1446. Stream connectionStream = new StreamingOutputConnectionStream(connection, settings);
  1447. Stream writeTimeoutStream = new TimeoutStream(connectionStream, ref timeoutHelper);
  1448. messageEncoder.WriteMessage(message, writeTimeoutStream);
  1449. }
  1450. else
  1451. {
  1452. ArraySegment<byte> messageData = messageEncoder.WriteMessage(message,
  1453. int.MaxValue, settings.BufferManager, envelopeStartBytes.Length + IntEncoder.MaxEncodedSize);
  1454. messageData = SingletonEncoder.EncodeMessageFrame(messageData);
  1455. Buffer.BlockCopy(envelopeStartBytes, 0, messageData.Array, messageData.Offset - envelopeStartBytes.Length,
  1456. envelopeStartBytes.Length);
  1457. connection.Write(messageData.Array, messageData.Offset - envelopeStartBytes.Length,
  1458. messageData.Count + envelopeStartBytes.Length, true, timeoutHelper.RemainingTime(), settings.BufferManager);
  1459. }
  1460. }
  1461. else if (isRequest) // context handles response end bytes
  1462. {
  1463. endBytes = SingletonEncoder.EndBytes;
  1464. }
  1465. if (endBytes != null)
  1466. {
  1467. connection.Write(endBytes, 0, endBytes.Length,
  1468. true, timeoutHelper.RemainingTime());
  1469. }
  1470. }
  1471. public static IAsyncResult BeginWriteMessage(Message message, IConnection connection, bool isRequest,
  1472. IConnectionOrientedTransportFactorySettings settings, ref TimeoutHelper timeoutHelper,
  1473. AsyncCallback callback, object state)
  1474. {
  1475. return new WriteMessageAsyncResult(message, connection, isRequest, settings, ref timeoutHelper, callback, state);
  1476. }
  1477. public static void EndWriteMessage(IAsyncResult result)
  1478. {
  1479. WriteMessageAsyncResult.End(result);
  1480. }
  1481. // overrides ConnectionStream to add a Framing int at the beginning of each record
  1482. class StreamingOutputConnectionStream : ConnectionStream
  1483. {
  1484. byte[] encodedSize;
  1485. public StreamingOutputConnectionStream(IConnection connection, IDefaultCommunicationTimeouts timeouts)
  1486. : base(connection, timeouts)
  1487. {
  1488. this.encodedSize = new byte[IntEncoder.MaxEncodedSize];
  1489. }
  1490. void WriteChunkSize(int size)
  1491. {
  1492. if (size > 0)
  1493. {
  1494. int bytesEncoded = IntEncoder.Encode(size, encodedSize, 0);
  1495. base.Connection.Write(encodedSize, 0, bytesEncoded, false, TimeSpan.FromMilliseconds(this.WriteTimeout));
  1496. }
  1497. }
  1498. public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
  1499. {
  1500. WriteChunkSize(count);
  1501. return base.BeginWrite(buffer, offset, count, callback, state);
  1502. }
  1503. public override void WriteByte(byte value)
  1504. {
  1505. WriteChunkSize(1);
  1506. base.WriteByte(value);
  1507. }
  1508. public override void Write(byte[] buffer, int offset, int count)
  1509. {
  1510. WriteChunkSize(count);
  1511. base.Write(buffer, offset, count);
  1512. }
  1513. }
  1514. class WriteMessageAsyncResult : AsyncResult
  1515. {
  1516. IConnection connection;
  1517. MessageEncoder encoder;
  1518. BufferManager bufferManager;
  1519. Message message;
  1520. static WaitCallback onWriteBufferedMessage;
  1521. static WaitCallback onWriteStartBytes;
  1522. static Action<object> onWriteStartBytesScheduled;
  1523. static WaitCallback onWriteEndBytes =
  1524. Fx.ThunkCallback(new WaitCallback(OnWriteEndBytes));
  1525. byte[] bufferToFree;
  1526. IConnectionOrientedTransportFactorySettings settings;
  1527. TimeoutHelper timeoutHelper;
  1528. byte[] endBytes;
  1529. public WriteMessageAsyncResult(Message message, IConnection connection, bool isRequest,
  1530. IConnectionOrientedTransportFactorySettings settings, ref TimeoutHelper timeoutHelper,
  1531. AsyncCallback callback, object state)
  1532. : base(callback, state)
  1533. {
  1534. this.connection = connection;
  1535. this.encoder = settings.MessageEncoderFactory.Encoder;
  1536. this.bufferManager = settings.BufferManager;
  1537. this.timeoutHelper = timeoutHelper;
  1538. this.message = message;
  1539. this.settings = settings;
  1540. bool throwing = true;
  1541. bool completeSelf = false;
  1542. if (message == null)
  1543. {
  1544. if (isRequest) // context takes care of the end bytes on Close/reader.EOF
  1545. {
  1546. this.endBytes = SingletonEncoder.EndBytes;
  1547. }
  1548. completeSelf = WriteEndBytes();
  1549. }
  1550. else
  1551. {
  1552. try
  1553. {
  1554. byte[] envelopeStartBytes = SingletonEncoder.EnvelopeStartBytes;
  1555. bool writeStreamed;
  1556. if (isRequest)
  1557. {
  1558. this.endBytes = SingletonEncoder.EnvelopeEndFramingEndBytes;
  1559. writeStreamed = TransferModeHelper.IsRequestStreamed(settings.TransferMode);
  1560. }
  1561. else
  1562. {
  1563. this.endBytes = SingletonEncoder.EnvelopeEndBytes;
  1564. writeStreamed = TransferModeHelper.IsResponseStreamed(settings.TransferMode);
  1565. }
  1566. if (writeStreamed)
  1567. {
  1568. if (onWriteStartBytes == null)
  1569. {
  1570. onWriteStartBytes = Fx.ThunkCallback(new WaitCallback(OnWriteStartBytes));
  1571. }
  1572. AsyncCompletionResult writeStartBytesResult = connection.BeginWrite(envelopeStartBytes, 0, envelopeStartBytes.Length, true,
  1573. timeoutHelper.RemainingTime(), onWriteStartBytes, this);
  1574. if (writeStartBytesResult == AsyncCompletionResult.Completed)
  1575. {
  1576. if (onWriteStartBytesScheduled == null)
  1577. {
  1578. onWriteStartBytesScheduled = new Action<object>(OnWriteStartBytes);
  1579. }
  1580. ActionItem.Schedule(onWriteStartBytesScheduled, this);
  1581. }
  1582. }
  1583. else
  1584. {
  1585. ArraySegment<byte> messageData = settings.MessageEncoderFactory.Encoder.WriteMessage(message,
  1586. int.MaxValue, this.bufferManager, envelopeStartBytes.Length + IntEncoder.MaxEncodedSize);
  1587. messageData = SingletonEncoder.EncodeMessageFrame(messageData);
  1588. this.bufferToFree = messageData.Array;
  1589. Buffer.BlockCopy(envelopeStartBytes, 0, messageData.Array, messageData.Offset - envelopeStartBytes.Length,
  1590. envelopeStartBytes.Length);
  1591. if (onWriteBufferedMessage == null)
  1592. {
  1593. onWriteBufferedMessage = Fx.ThunkCallback(new WaitCallback(OnWriteBufferedMessage));
  1594. }
  1595. AsyncCompletionResult writeBufferedResult =
  1596. connection.BeginWrite(messageData.Array, messageData.Offset - envelopeStartBytes.Length,
  1597. messageData.Count + envelopeStartBytes.Length, true, timeoutHelper.RemainingTime(),
  1598. onWriteBufferedMessage, this);
  1599. if (writeBufferedResult == AsyncCompletionResult.Completed)
  1600. {
  1601. completeSelf = HandleWriteBufferedMessage();
  1602. }
  1603. }
  1604. throwing = false;
  1605. }
  1606. finally
  1607. {
  1608. if (throwing)
  1609. {
  1610. Cleanup();
  1611. }
  1612. }
  1613. }
  1614. if (completeSelf)
  1615. {
  1616. base.Complete(true);
  1617. }
  1618. }
  1619. public static void End(IAsyncResult result)
  1620. {
  1621. AsyncResult.End<WriteMessageAsyncResult>(result);
  1622. }
  1623. void Cleanup()
  1624. {
  1625. if (bufferToFree != null)
  1626. {
  1627. this.bufferManager.ReturnBuffer(bufferToFree);
  1628. }
  1629. }
  1630. bool HandleWriteStartBytes()
  1631. {
  1632. connection.EndWrite();
  1633. Stream connectionStream = new StreamingOutputConnectionStream(connection, settings);
  1634. Stream writeTimeoutStream = new TimeoutStream(connectionStream, ref timeoutHelper);
  1635. this.encoder.WriteMessage(message, writeTimeoutStream);
  1636. return WriteEndBytes();
  1637. }
  1638. bool HandleWriteBufferedMessage()
  1639. {
  1640. this.connection.EndWrite();
  1641. return WriteEndBytes();
  1642. }
  1643. bool WriteEndBytes()
  1644. {
  1645. if (this.endBytes == null)
  1646. {
  1647. Cleanup();
  1648. return true;
  1649. }
  1650. AsyncCompletionResult result = connection.BeginWrite(endBytes, 0,
  1651. endBytes.Length, true, timeoutHelper.RemainingTime(), onWriteEndBytes, this);
  1652. if (result == AsyncCompletionResult.Queued)
  1653. {
  1654. return false;
  1655. }
  1656. return HandleWriteEndBytes();
  1657. }
  1658. bool HandleWriteEndBytes()
  1659. {
  1660. this.connection.EndWrite();
  1661. Cleanup();
  1662. return true;
  1663. }
  1664. static void OnWriteStartBytes(object asyncState)
  1665. {
  1666. OnWriteStartBytesCallbackHelper(asyncState);
  1667. }
  1668. static void OnWriteStartBytesCallbackHelper(object asyncState)
  1669. {
  1670. WriteMessageAsyncResult thisPtr = (WriteMessageAsyncResult)asyncState;
  1671. Exception completionException = null;
  1672. bool completeSelf = false;
  1673. bool throwing = true;
  1674. try
  1675. {
  1676. completeSelf = thisPtr.HandleWriteStartBytes();
  1677. throwing = false;
  1678. }
  1679. #pragma warning suppress 56500 // [....], transferring exception to another thread
  1680. catch (Exception e)
  1681. {
  1682. if (Fx.IsFatal(e))
  1683. {
  1684. throw;
  1685. }
  1686. completeSelf = true;
  1687. completionException = e;
  1688. }
  1689. finally
  1690. {
  1691. if (throwing)
  1692. {
  1693. thisPtr.Cleanup();
  1694. }
  1695. }
  1696. if (completeSelf)
  1697. {
  1698. thisPtr.Complete(false, completionException);
  1699. }
  1700. }
  1701. static void OnWriteBufferedMessage(object asyncState)
  1702. {
  1703. WriteMessageAsyncResult thisPtr = (WriteMessageAsyncResult)asyncState;
  1704. Exception completionException = null;
  1705. bool completeSelf = false;
  1706. bool throwing = true;
  1707. try
  1708. {
  1709. completeSelf = thisPtr.HandleWriteBufferedMessage();
  1710. throwing = false;
  1711. }
  1712. #pragma warning suppress 56500 // [....], transferring exception to another thread
  1713. catch (Exception e)
  1714. {
  1715. if (Fx.IsFatal(e))
  1716. {
  1717. throw;
  1718. }
  1719. completeSelf = true;
  1720. completionException = e;
  1721. }
  1722. finally
  1723. {
  1724. if (throwing)
  1725. {
  1726. thisPtr.Cleanup();
  1727. }
  1728. }
  1729. if (completeSelf)
  1730. {
  1731. thisPtr.Complete(false, completionException);
  1732. }
  1733. }
  1734. static void OnWriteEndBytes(object asyncState)
  1735. {
  1736. WriteMessageAsyncResult thisPtr = (WriteMessageAsyncResult)asyncState;
  1737. Exception completionException = null;
  1738. bool completeSelf = false;
  1739. bool success = false;
  1740. try
  1741. {
  1742. completeSelf = thisPtr.HandleWriteEndBytes();
  1743. success = true;
  1744. }
  1745. #pragma warning suppress 56500 // [....], transferring exception to another thread
  1746. catch (Exception e)
  1747. {
  1748. if (Fx.IsFatal(e))
  1749. {
  1750. throw;
  1751. }
  1752. completeSelf = true;
  1753. completionException = e;
  1754. }
  1755. finally
  1756. {
  1757. if (!success)
  1758. {
  1759. thisPtr.Cleanup();
  1760. }
  1761. }
  1762. if (completeSelf)
  1763. {
  1764. thisPtr.Complete(false, completionException);
  1765. }
  1766. }
  1767. }
  1768. }
  1769. }