Message.cs 74 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118
  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.IO;
  10. using System.Runtime;
  11. using System.Runtime.Serialization;
  12. using System.ServiceModel;
  13. using System.ServiceModel.Diagnostics;
  14. using System.ServiceModel.Dispatcher;
  15. using System.Threading;
  16. using System.Xml;
  17. public abstract class Message : IDisposable
  18. {
  19. MessageState state;
  20. SeekableMessageNavigator messageNavigator;
  21. internal const int InitialBufferSize = 1024;
  22. public abstract MessageHeaders Headers { get; } // must never return null
  23. protected bool IsDisposed
  24. {
  25. get { return state == MessageState.Closed; }
  26. }
  27. public virtual bool IsFault
  28. {
  29. get
  30. {
  31. if (IsDisposed)
  32. #pragma warning suppress 56503 // [....], Invalid State after dispose
  33. throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
  34. return false;
  35. }
  36. }
  37. public virtual bool IsEmpty
  38. {
  39. get
  40. {
  41. if (IsDisposed)
  42. #pragma warning suppress 56503 // [....], Invalid State after dispose
  43. throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
  44. return false;
  45. }
  46. }
  47. public abstract MessageProperties Properties { get; }
  48. public abstract MessageVersion Version { get; } // must never return null
  49. internal virtual RecycledMessageState RecycledMessageState
  50. {
  51. get { return null; }
  52. }
  53. public MessageState State
  54. {
  55. get { return state; }
  56. }
  57. internal void BodyToString(XmlDictionaryWriter writer)
  58. {
  59. OnBodyToString(writer);
  60. }
  61. public void Close()
  62. {
  63. if (state != MessageState.Closed)
  64. {
  65. state = MessageState.Closed;
  66. OnClose();
  67. if (DiagnosticUtility.ShouldTraceVerbose)
  68. {
  69. TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageClosed,
  70. SR.GetString(SR.TraceCodeMessageClosed), this);
  71. }
  72. }
  73. else
  74. {
  75. if (DiagnosticUtility.ShouldTraceVerbose)
  76. {
  77. TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageClosedAgain,
  78. SR.GetString(SR.TraceCodeMessageClosedAgain), this);
  79. }
  80. }
  81. }
  82. public MessageBuffer CreateBufferedCopy(int maxBufferSize)
  83. {
  84. if (maxBufferSize < 0)
  85. throw TraceUtility.ThrowHelperError(new ArgumentOutOfRangeException("maxBufferSize", maxBufferSize,
  86. SR.GetString(SR.ValueMustBeNonNegative)), this);
  87. switch (state)
  88. {
  89. case MessageState.Created:
  90. state = MessageState.Copied;
  91. if (DiagnosticUtility.ShouldTraceVerbose)
  92. {
  93. TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageCopied,
  94. SR.GetString(SR.TraceCodeMessageCopied), this, this);
  95. }
  96. break;
  97. case MessageState.Closed:
  98. throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
  99. case MessageState.Copied:
  100. throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenCopied)), this);
  101. case MessageState.Read:
  102. throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenRead)), this);
  103. case MessageState.Written:
  104. throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenWritten)), this);
  105. default:
  106. Fx.Assert(SR.GetString(SR.InvalidMessageState));
  107. throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidMessageState)), this);
  108. }
  109. return OnCreateBufferedCopy(maxBufferSize);
  110. }
  111. static Type GetObjectType(object value)
  112. {
  113. return (value == null) ? typeof(object) : value.GetType();
  114. }
  115. static public Message CreateMessage(MessageVersion version, string action, object body)
  116. {
  117. return CreateMessage(version, action, body, DataContractSerializerDefaults.CreateSerializer(GetObjectType(body), int.MaxValue/*maxItems*/));
  118. }
  119. static public Message CreateMessage(MessageVersion version, string action, object body, XmlObjectSerializer serializer)
  120. {
  121. if (version == null)
  122. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
  123. if (serializer == null)
  124. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serializer"));
  125. return new BodyWriterMessage(version, action, new XmlObjectSerializerBodyWriter(body, serializer));
  126. }
  127. static public Message CreateMessage(MessageVersion version, string action, XmlReader body)
  128. {
  129. return CreateMessage(version, action, XmlDictionaryReader.CreateDictionaryReader(body));
  130. }
  131. static public Message CreateMessage(MessageVersion version, string action, XmlDictionaryReader body)
  132. {
  133. if (body == null)
  134. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("body");
  135. if (version == null)
  136. throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("version");
  137. return CreateMessage(version, action, new XmlReaderBodyWriter(body, version.Envelope));
  138. }
  139. static public Message CreateMessage(MessageVersion version, string action, BodyWriter body)
  140. {
  141. if (version == null)
  142. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
  143. if (body == null)
  144. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("body"));
  145. return new BodyWriterMessage(version, action, body);
  146. }
  147. static internal Message CreateMessage(MessageVersion version, ActionHeader actionHeader, BodyWriter body)
  148. {
  149. if (version == null)
  150. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
  151. if (body == null)
  152. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("body"));
  153. return new BodyWriterMessage(version, actionHeader, body);
  154. }
  155. static public Message CreateMessage(MessageVersion version, string action)
  156. {
  157. if (version == null)
  158. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
  159. return new BodyWriterMessage(version, action, EmptyBodyWriter.Value);
  160. }
  161. static internal Message CreateMessage(MessageVersion version, ActionHeader actionHeader)
  162. {
  163. if (version == null)
  164. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
  165. return new BodyWriterMessage(version, actionHeader, EmptyBodyWriter.Value);
  166. }
  167. static public Message CreateMessage(XmlReader envelopeReader, int maxSizeOfHeaders, MessageVersion version)
  168. {
  169. return CreateMessage(XmlDictionaryReader.CreateDictionaryReader(envelopeReader), maxSizeOfHeaders, version);
  170. }
  171. static public Message CreateMessage(XmlDictionaryReader envelopeReader, int maxSizeOfHeaders, MessageVersion version)
  172. {
  173. if (envelopeReader == null)
  174. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("envelopeReader"));
  175. if (version == null)
  176. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
  177. Message message = new StreamedMessage(envelopeReader, maxSizeOfHeaders, version);
  178. return message;
  179. }
  180. static public Message CreateMessage(MessageVersion version, FaultCode faultCode, string reason, string action)
  181. {
  182. if (version == null)
  183. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
  184. if (faultCode == null)
  185. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("faultCode"));
  186. if (reason == null)
  187. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("reason"));
  188. return CreateMessage(version, MessageFault.CreateFault(faultCode, reason), action);
  189. }
  190. static public Message CreateMessage(MessageVersion version, FaultCode faultCode, string reason, object detail, string action)
  191. {
  192. if (version == null)
  193. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
  194. if (faultCode == null)
  195. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("faultCode"));
  196. if (reason == null)
  197. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("reason"));
  198. return CreateMessage(version, MessageFault.CreateFault(faultCode, new FaultReason(reason), detail), action);
  199. }
  200. static public Message CreateMessage(MessageVersion version, MessageFault fault, string action)
  201. {
  202. if (fault == null)
  203. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("fault"));
  204. if (version == null)
  205. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("version"));
  206. return new BodyWriterMessage(version, action, new FaultBodyWriter(fault, version.Envelope));
  207. }
  208. internal Exception CreateMessageDisposedException()
  209. {
  210. return new ObjectDisposedException("", SR.GetString(SR.MessageClosed));
  211. }
  212. void IDisposable.Dispose()
  213. {
  214. Close();
  215. }
  216. public T GetBody<T>()
  217. {
  218. XmlDictionaryReader reader = GetReaderAtBodyContents(); // This call will change the message state to Read.
  219. return OnGetBody<T>(reader);
  220. }
  221. protected virtual T OnGetBody<T>(XmlDictionaryReader reader)
  222. {
  223. return this.GetBodyCore<T>(reader, DataContractSerializerDefaults.CreateSerializer(typeof(T), int.MaxValue/*maxItems*/));
  224. }
  225. public T GetBody<T>(XmlObjectSerializer serializer)
  226. {
  227. if (serializer == null)
  228. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serializer"));
  229. return this.GetBodyCore<T>(GetReaderAtBodyContents(), serializer);
  230. }
  231. T GetBodyCore<T>(XmlDictionaryReader reader, XmlObjectSerializer serializer)
  232. {
  233. T value;
  234. using (reader)
  235. {
  236. value = (T)serializer.ReadObject(reader);
  237. this.ReadFromBodyContentsToEnd(reader);
  238. }
  239. return value;
  240. }
  241. internal virtual XmlDictionaryReader GetReaderAtHeader()
  242. {
  243. XmlBuffer buffer = new XmlBuffer(int.MaxValue);
  244. XmlDictionaryWriter writer = buffer.OpenSection(XmlDictionaryReaderQuotas.Max);
  245. WriteStartEnvelope(writer);
  246. MessageHeaders headers = this.Headers;
  247. for (int i = 0; i < headers.Count; i++)
  248. headers.WriteHeader(i, writer);
  249. writer.WriteEndElement();
  250. writer.WriteEndElement();
  251. buffer.CloseSection();
  252. buffer.Close();
  253. XmlDictionaryReader reader = buffer.GetReader(0);
  254. reader.ReadStartElement();
  255. reader.MoveToStartElement();
  256. return reader;
  257. }
  258. public XmlDictionaryReader GetReaderAtBodyContents()
  259. {
  260. EnsureReadMessageState();
  261. if (IsEmpty)
  262. throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageIsEmpty)), this);
  263. return OnGetReaderAtBodyContents();
  264. }
  265. internal void EnsureReadMessageState()
  266. {
  267. switch (state)
  268. {
  269. case MessageState.Created:
  270. state = MessageState.Read;
  271. if (DiagnosticUtility.ShouldTraceVerbose)
  272. {
  273. TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageRead, SR.GetString(SR.TraceCodeMessageRead), this);
  274. }
  275. break;
  276. case MessageState.Copied:
  277. throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenCopied)), this);
  278. case MessageState.Read:
  279. throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenRead)), this);
  280. case MessageState.Written:
  281. throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenWritten)), this);
  282. case MessageState.Closed:
  283. throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
  284. default:
  285. Fx.Assert(SR.GetString(SR.InvalidMessageState));
  286. throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidMessageState)), this);
  287. }
  288. }
  289. internal SeekableMessageNavigator GetNavigator(bool navigateBody, int maxNodes)
  290. {
  291. if (IsDisposed)
  292. throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
  293. if (null == this.messageNavigator)
  294. {
  295. this.messageNavigator = new SeekableMessageNavigator(this, maxNodes, XmlSpace.Default, navigateBody, false);
  296. }
  297. else
  298. {
  299. this.messageNavigator.ForkNodeCount(maxNodes);
  300. }
  301. return this.messageNavigator;
  302. }
  303. internal void InitializeReply(Message request)
  304. {
  305. UniqueId requestMessageID = request.Headers.MessageId;
  306. if (requestMessageID == null)
  307. throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.RequestMessageDoesNotHaveAMessageID)), request);
  308. Headers.RelatesTo = requestMessageID;
  309. }
  310. static internal bool IsFaultStartElement(XmlDictionaryReader reader, EnvelopeVersion version)
  311. {
  312. return reader.IsStartElement(XD.MessageDictionary.Fault, version.DictionaryNamespace);
  313. }
  314. protected virtual void OnBodyToString(XmlDictionaryWriter writer)
  315. {
  316. writer.WriteString(SR.GetString(SR.MessageBodyIsUnknown));
  317. }
  318. protected virtual MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
  319. {
  320. return OnCreateBufferedCopy(maxBufferSize, XmlDictionaryReaderQuotas.Max);
  321. }
  322. internal MessageBuffer OnCreateBufferedCopy(int maxBufferSize, XmlDictionaryReaderQuotas quotas)
  323. {
  324. XmlBuffer msgBuffer = new XmlBuffer(maxBufferSize);
  325. XmlDictionaryWriter writer = msgBuffer.OpenSection(quotas);
  326. OnWriteMessage(writer);
  327. msgBuffer.CloseSection();
  328. msgBuffer.Close();
  329. return new DefaultMessageBuffer(this, msgBuffer);
  330. }
  331. protected virtual void OnClose()
  332. {
  333. }
  334. protected virtual XmlDictionaryReader OnGetReaderAtBodyContents()
  335. {
  336. XmlBuffer bodyBuffer = new XmlBuffer(int.MaxValue);
  337. XmlDictionaryWriter writer = bodyBuffer.OpenSection(XmlDictionaryReaderQuotas.Max);
  338. if (this.Version.Envelope != EnvelopeVersion.None)
  339. {
  340. OnWriteStartEnvelope(writer);
  341. OnWriteStartBody(writer);
  342. }
  343. OnWriteBodyContents(writer);
  344. if (this.Version.Envelope != EnvelopeVersion.None)
  345. {
  346. writer.WriteEndElement();
  347. writer.WriteEndElement();
  348. }
  349. bodyBuffer.CloseSection();
  350. bodyBuffer.Close();
  351. XmlDictionaryReader reader = bodyBuffer.GetReader(0);
  352. if (this.Version.Envelope != EnvelopeVersion.None)
  353. {
  354. reader.ReadStartElement();
  355. reader.ReadStartElement();
  356. }
  357. reader.MoveToContent();
  358. return reader;
  359. }
  360. protected virtual void OnWriteStartBody(XmlDictionaryWriter writer)
  361. {
  362. MessageDictionary messageDictionary = XD.MessageDictionary;
  363. writer.WriteStartElement(messageDictionary.Prefix.Value, messageDictionary.Body, Version.Envelope.DictionaryNamespace);
  364. }
  365. public void WriteBodyContents(XmlDictionaryWriter writer)
  366. {
  367. EnsureWriteMessageState(writer);
  368. OnWriteBodyContents(writer);
  369. }
  370. public IAsyncResult BeginWriteBodyContents(XmlDictionaryWriter writer, AsyncCallback callback, object state)
  371. {
  372. EnsureWriteMessageState(writer);
  373. return this.OnBeginWriteBodyContents(writer, callback, state);
  374. }
  375. public void EndWriteBodyContents(IAsyncResult result)
  376. {
  377. this.OnEndWriteBodyContents(result);
  378. }
  379. protected abstract void OnWriteBodyContents(XmlDictionaryWriter writer);
  380. protected virtual IAsyncResult OnBeginWriteBodyContents(XmlDictionaryWriter writer, AsyncCallback callback, object state)
  381. {
  382. return new OnWriteBodyContentsAsyncResult(writer, this, callback, state);
  383. }
  384. protected virtual void OnEndWriteBodyContents(IAsyncResult result)
  385. {
  386. OnWriteBodyContentsAsyncResult.End(result);
  387. }
  388. public void WriteStartEnvelope(XmlDictionaryWriter writer)
  389. {
  390. if (writer == null)
  391. throw TraceUtility.ThrowHelperError(new ArgumentNullException("writer"), this);
  392. OnWriteStartEnvelope(writer);
  393. }
  394. protected virtual void OnWriteStartEnvelope(XmlDictionaryWriter writer)
  395. {
  396. EnvelopeVersion envelopeVersion = Version.Envelope;
  397. if (envelopeVersion != EnvelopeVersion.None)
  398. {
  399. MessageDictionary messageDictionary = XD.MessageDictionary;
  400. writer.WriteStartElement(messageDictionary.Prefix.Value, messageDictionary.Envelope, envelopeVersion.DictionaryNamespace);
  401. WriteSharedHeaderPrefixes(writer);
  402. }
  403. }
  404. protected virtual void OnWriteStartHeaders(XmlDictionaryWriter writer)
  405. {
  406. EnvelopeVersion envelopeVersion = Version.Envelope;
  407. if (envelopeVersion != EnvelopeVersion.None)
  408. {
  409. MessageDictionary messageDictionary = XD.MessageDictionary;
  410. writer.WriteStartElement(messageDictionary.Prefix.Value, messageDictionary.Header, envelopeVersion.DictionaryNamespace);
  411. }
  412. }
  413. public override string ToString()
  414. {
  415. if (IsDisposed)
  416. {
  417. return base.ToString();
  418. }
  419. StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture);
  420. EncodingFallbackAwareXmlTextWriter textWriter = new EncodingFallbackAwareXmlTextWriter(stringWriter);
  421. textWriter.Formatting = Formatting.Indented;
  422. XmlDictionaryWriter writer = XmlDictionaryWriter.CreateDictionaryWriter(textWriter);
  423. try
  424. {
  425. ToString(writer);
  426. writer.Flush();
  427. return stringWriter.ToString();
  428. }
  429. catch (XmlException e)
  430. {
  431. return SR.GetString(SR.MessageBodyToStringError, e.GetType().ToString(), e.Message);
  432. }
  433. }
  434. internal void ToString(XmlDictionaryWriter writer)
  435. {
  436. if (IsDisposed)
  437. {
  438. throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
  439. }
  440. if (this.Version.Envelope != EnvelopeVersion.None)
  441. {
  442. WriteStartEnvelope(writer);
  443. WriteStartHeaders(writer);
  444. MessageHeaders headers = this.Headers;
  445. for (int i = 0; i < headers.Count; i++)
  446. {
  447. headers.WriteHeader(i, writer);
  448. }
  449. writer.WriteEndElement();
  450. MessageDictionary messageDictionary = XD.MessageDictionary;
  451. WriteStartBody(writer);
  452. }
  453. BodyToString(writer);
  454. if (this.Version.Envelope != EnvelopeVersion.None)
  455. {
  456. writer.WriteEndElement();
  457. writer.WriteEndElement();
  458. }
  459. }
  460. public string GetBodyAttribute(string localName, string ns)
  461. {
  462. if (localName == null)
  463. throw TraceUtility.ThrowHelperError(new ArgumentNullException("localName"), this);
  464. if (ns == null)
  465. throw TraceUtility.ThrowHelperError(new ArgumentNullException("ns"), this);
  466. switch (state)
  467. {
  468. case MessageState.Created:
  469. break;
  470. case MessageState.Copied:
  471. throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenCopied)), this);
  472. case MessageState.Read:
  473. throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenRead)), this);
  474. case MessageState.Written:
  475. throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenWritten)), this);
  476. case MessageState.Closed:
  477. throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
  478. default:
  479. Fx.Assert(SR.GetString(SR.InvalidMessageState));
  480. throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidMessageState)), this);
  481. }
  482. return OnGetBodyAttribute(localName, ns);
  483. }
  484. protected virtual string OnGetBodyAttribute(string localName, string ns)
  485. {
  486. return null;
  487. }
  488. internal void ReadFromBodyContentsToEnd(XmlDictionaryReader reader)
  489. {
  490. Message.ReadFromBodyContentsToEnd(reader, this.Version.Envelope);
  491. }
  492. static void ReadFromBodyContentsToEnd(XmlDictionaryReader reader, EnvelopeVersion envelopeVersion)
  493. {
  494. if (envelopeVersion != EnvelopeVersion.None)
  495. {
  496. reader.ReadEndElement(); // </Body>
  497. reader.ReadEndElement(); // </Envelope>
  498. }
  499. reader.MoveToContent();
  500. }
  501. internal static bool ReadStartBody(XmlDictionaryReader reader, EnvelopeVersion envelopeVersion, out bool isFault, out bool isEmpty)
  502. {
  503. if (reader.IsEmptyElement)
  504. {
  505. reader.Read();
  506. isEmpty = true;
  507. isFault = false;
  508. reader.ReadEndElement();
  509. return false;
  510. }
  511. else
  512. {
  513. reader.Read();
  514. if (reader.NodeType != XmlNodeType.Element)
  515. reader.MoveToContent();
  516. if (reader.NodeType == XmlNodeType.Element)
  517. {
  518. isFault = IsFaultStartElement(reader, envelopeVersion);
  519. isEmpty = false;
  520. }
  521. else if (reader.NodeType == XmlNodeType.EndElement)
  522. {
  523. isEmpty = true;
  524. isFault = false;
  525. Message.ReadFromBodyContentsToEnd(reader, envelopeVersion);
  526. return false;
  527. }
  528. else
  529. {
  530. isEmpty = false;
  531. isFault = false;
  532. }
  533. return true;
  534. }
  535. }
  536. public void WriteBody(XmlWriter writer)
  537. {
  538. WriteBody(XmlDictionaryWriter.CreateDictionaryWriter(writer));
  539. }
  540. public void WriteBody(XmlDictionaryWriter writer)
  541. {
  542. WriteStartBody(writer);
  543. WriteBodyContents(writer);
  544. writer.WriteEndElement();
  545. }
  546. public void WriteStartBody(XmlWriter writer)
  547. {
  548. WriteStartBody(XmlDictionaryWriter.CreateDictionaryWriter(writer));
  549. }
  550. public void WriteStartBody(XmlDictionaryWriter writer)
  551. {
  552. if (writer == null)
  553. throw TraceUtility.ThrowHelperError(new ArgumentNullException("writer"), this);
  554. OnWriteStartBody(writer);
  555. }
  556. internal void WriteStartHeaders(XmlDictionaryWriter writer)
  557. {
  558. OnWriteStartHeaders(writer);
  559. }
  560. public void WriteMessage(XmlWriter writer)
  561. {
  562. WriteMessage(XmlDictionaryWriter.CreateDictionaryWriter(writer));
  563. }
  564. public void WriteMessage(XmlDictionaryWriter writer)
  565. {
  566. EnsureWriteMessageState(writer);
  567. OnWriteMessage(writer);
  568. }
  569. void EnsureWriteMessageState(XmlDictionaryWriter writer)
  570. {
  571. if (writer == null)
  572. throw TraceUtility.ThrowHelperError(new ArgumentNullException("writer"), this);
  573. switch (state)
  574. {
  575. case MessageState.Created:
  576. state = MessageState.Written;
  577. if (DiagnosticUtility.ShouldTraceVerbose)
  578. {
  579. TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.MessageWritten, SR.GetString(SR.TraceCodeMessageWritten), this);
  580. }
  581. break;
  582. case MessageState.Copied:
  583. throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenCopied)), this);
  584. case MessageState.Read:
  585. throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenRead)), this);
  586. case MessageState.Written:
  587. throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageHasBeenWritten)), this);
  588. case MessageState.Closed:
  589. throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
  590. default:
  591. Fx.Assert(SR.GetString(SR.InvalidMessageState));
  592. throw TraceUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.InvalidMessageState)), this);
  593. }
  594. }
  595. public IAsyncResult BeginWriteMessage(XmlDictionaryWriter writer, AsyncCallback callback, object state)
  596. {
  597. EnsureWriteMessageState(writer);
  598. return OnBeginWriteMessage(writer, callback, state);
  599. }
  600. public void EndWriteMessage(IAsyncResult result)
  601. {
  602. OnEndWriteMessage(result);
  603. }
  604. protected virtual void OnWriteMessage(XmlDictionaryWriter writer)
  605. {
  606. WriteMessagePreamble(writer);
  607. OnWriteBodyContents(writer);
  608. WriteMessagePostamble(writer);
  609. }
  610. internal void WriteMessagePreamble(XmlDictionaryWriter writer)
  611. {
  612. if (this.Version.Envelope != EnvelopeVersion.None)
  613. {
  614. OnWriteStartEnvelope(writer);
  615. MessageHeaders headers = this.Headers;
  616. int headersCount = headers.Count;
  617. if (headersCount > 0)
  618. {
  619. OnWriteStartHeaders(writer);
  620. for (int i = 0; i < headersCount; i++)
  621. {
  622. headers.WriteHeader(i, writer);
  623. }
  624. writer.WriteEndElement();
  625. }
  626. OnWriteStartBody(writer);
  627. }
  628. }
  629. internal void WriteMessagePostamble(XmlDictionaryWriter writer)
  630. {
  631. if (this.Version.Envelope != EnvelopeVersion.None)
  632. {
  633. writer.WriteEndElement();
  634. writer.WriteEndElement();
  635. }
  636. }
  637. protected virtual IAsyncResult OnBeginWriteMessage(XmlDictionaryWriter writer, AsyncCallback callback, object state)
  638. {
  639. return new OnWriteMessageAsyncResult(writer, this, callback, state);
  640. }
  641. protected virtual void OnEndWriteMessage(IAsyncResult result)
  642. {
  643. OnWriteMessageAsyncResult.End(result);
  644. }
  645. void WriteSharedHeaderPrefixes(XmlDictionaryWriter writer)
  646. {
  647. MessageHeaders headers = Headers;
  648. int count = headers.Count;
  649. int prefixesWritten = 0;
  650. for (int i = 0; i < count; i++)
  651. {
  652. if (this.Version.Addressing == AddressingVersion.None && headers[i].Namespace == AddressingVersion.None.Namespace)
  653. {
  654. continue;
  655. }
  656. IMessageHeaderWithSharedNamespace headerWithSharedNamespace = headers[i] as IMessageHeaderWithSharedNamespace;
  657. if (headerWithSharedNamespace != null)
  658. {
  659. XmlDictionaryString prefix = headerWithSharedNamespace.SharedPrefix;
  660. string prefixString = prefix.Value;
  661. if (!((prefixString.Length == 1)))
  662. {
  663. Fx.Assert("Message.WriteSharedHeaderPrefixes: (prefixString.Length == 1) -- IMessageHeaderWithSharedNamespace must use a single lowercase letter prefix.");
  664. throw TraceUtility.ThrowHelperError(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "IMessageHeaderWithSharedNamespace must use a single lowercase letter prefix.")), this);
  665. }
  666. int prefixIndex = prefixString[0] - 'a';
  667. if (!((prefixIndex >= 0 && prefixIndex < 26)))
  668. {
  669. Fx.Assert("Message.WriteSharedHeaderPrefixes: (prefixIndex >= 0 && prefixIndex < 26) -- IMessageHeaderWithSharedNamespace must use a single lowercase letter prefix.");
  670. throw TraceUtility.ThrowHelperError(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "IMessageHeaderWithSharedNamespace must use a single lowercase letter prefix.")), this);
  671. }
  672. int prefixBit = 1 << prefixIndex;
  673. if ((prefixesWritten & prefixBit) == 0)
  674. {
  675. writer.WriteXmlnsAttribute(prefixString, headerWithSharedNamespace.SharedNamespace);
  676. prefixesWritten |= prefixBit;
  677. }
  678. }
  679. }
  680. }
  681. class OnWriteBodyContentsAsyncResult : ScheduleActionItemAsyncResult
  682. {
  683. Message message;
  684. XmlDictionaryWriter writer;
  685. public OnWriteBodyContentsAsyncResult(XmlDictionaryWriter writer, Message message, AsyncCallback callback, object state)
  686. : base(callback, state)
  687. {
  688. Fx.Assert(message != null, "message should never be null");
  689. this.message = message;
  690. this.writer = writer;
  691. Schedule();
  692. }
  693. protected override void OnDoWork()
  694. {
  695. this.message.OnWriteBodyContents(this.writer);
  696. }
  697. }
  698. class OnWriteMessageAsyncResult : ScheduleActionItemAsyncResult
  699. {
  700. Message message;
  701. XmlDictionaryWriter writer;
  702. public OnWriteMessageAsyncResult(XmlDictionaryWriter writer, Message message, AsyncCallback callback, object state)
  703. : base(callback, state)
  704. {
  705. Fx.Assert(message != null, "message should never be null");
  706. this.message = message;
  707. this.writer = writer;
  708. Schedule();
  709. }
  710. protected override void OnDoWork()
  711. {
  712. this.message.OnWriteMessage(this.writer);
  713. }
  714. }
  715. }
  716. class EmptyBodyWriter : BodyWriter
  717. {
  718. static EmptyBodyWriter value;
  719. EmptyBodyWriter()
  720. : base(true)
  721. {
  722. }
  723. public static EmptyBodyWriter Value
  724. {
  725. get
  726. {
  727. if (value == null)
  728. value = new EmptyBodyWriter();
  729. return value;
  730. }
  731. }
  732. internal override bool IsEmpty
  733. {
  734. get { return true; }
  735. }
  736. protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
  737. {
  738. }
  739. }
  740. class FaultBodyWriter : BodyWriter
  741. {
  742. MessageFault fault;
  743. EnvelopeVersion version;
  744. public FaultBodyWriter(MessageFault fault, EnvelopeVersion version)
  745. : base(true)
  746. {
  747. this.fault = fault;
  748. this.version = version;
  749. }
  750. internal override bool IsFault
  751. {
  752. get { return true; }
  753. }
  754. protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
  755. {
  756. fault.WriteTo(writer, version);
  757. }
  758. }
  759. class XmlObjectSerializerBodyWriter : BodyWriter
  760. {
  761. object body;
  762. XmlObjectSerializer serializer;
  763. public XmlObjectSerializerBodyWriter(object body, XmlObjectSerializer serializer)
  764. : base(true)
  765. {
  766. this.body = body;
  767. this.serializer = serializer;
  768. }
  769. object ThisLock
  770. {
  771. get { return this; }
  772. }
  773. protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
  774. {
  775. lock (ThisLock)
  776. {
  777. serializer.WriteObject(writer, body);
  778. }
  779. }
  780. }
  781. class XmlReaderBodyWriter : BodyWriter
  782. {
  783. XmlDictionaryReader reader;
  784. bool isFault;
  785. public XmlReaderBodyWriter(XmlDictionaryReader reader, EnvelopeVersion version)
  786. : base(false)
  787. {
  788. this.reader = reader;
  789. if (reader.MoveToContent() != XmlNodeType.Element)
  790. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.InvalidReaderPositionOnCreateMessage), "reader"));
  791. this.isFault = Message.IsFaultStartElement(reader, version);
  792. }
  793. internal override bool IsFault
  794. {
  795. get
  796. {
  797. return this.isFault;
  798. }
  799. }
  800. protected override BodyWriter OnCreateBufferedCopy(int maxBufferSize)
  801. {
  802. return OnCreateBufferedCopy(maxBufferSize, this.reader.Quotas);
  803. }
  804. protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
  805. {
  806. using (reader)
  807. {
  808. XmlNodeType type = reader.MoveToContent();
  809. while (!reader.EOF && type != XmlNodeType.EndElement)
  810. {
  811. if (type != XmlNodeType.Element)
  812. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.InvalidReaderPositionOnCreateMessage), "reader"));
  813. writer.WriteNode(reader, false);
  814. type = reader.MoveToContent();
  815. }
  816. }
  817. }
  818. }
  819. class BodyWriterMessage : Message
  820. {
  821. MessageProperties properties;
  822. MessageHeaders headers;
  823. BodyWriter bodyWriter;
  824. BodyWriterMessage(BodyWriter bodyWriter)
  825. {
  826. this.bodyWriter = bodyWriter;
  827. }
  828. public BodyWriterMessage(MessageVersion version, string action, BodyWriter bodyWriter)
  829. : this(bodyWriter)
  830. {
  831. this.headers = new MessageHeaders(version);
  832. this.headers.Action = action;
  833. }
  834. public BodyWriterMessage(MessageVersion version, ActionHeader actionHeader, BodyWriter bodyWriter)
  835. : this(bodyWriter)
  836. {
  837. this.headers = new MessageHeaders(version);
  838. this.headers.SetActionHeader(actionHeader);
  839. }
  840. public BodyWriterMessage(MessageHeaders headers, KeyValuePair<string, object>[] properties, BodyWriter bodyWriter)
  841. : this(bodyWriter)
  842. {
  843. this.headers = new MessageHeaders(headers);
  844. this.properties = new MessageProperties(properties);
  845. }
  846. public override bool IsFault
  847. {
  848. get
  849. {
  850. if (IsDisposed)
  851. #pragma warning suppress 56503 // [....], Invalid State after dispose
  852. throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
  853. return bodyWriter.IsFault;
  854. }
  855. }
  856. public override bool IsEmpty
  857. {
  858. get
  859. {
  860. if (IsDisposed)
  861. #pragma warning suppress 56503 // [....], Invalid State after dispose
  862. throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
  863. return bodyWriter.IsEmpty;
  864. }
  865. }
  866. public override MessageHeaders Headers
  867. {
  868. get
  869. {
  870. if (IsDisposed)
  871. #pragma warning suppress 56503 // [....], Invalid State after dispose
  872. throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
  873. return headers;
  874. }
  875. }
  876. public override MessageProperties Properties
  877. {
  878. get
  879. {
  880. if (IsDisposed)
  881. #pragma warning suppress 56503 // [....], Invalid State after dispose
  882. throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
  883. if (properties == null)
  884. properties = new MessageProperties();
  885. return properties;
  886. }
  887. }
  888. public override MessageVersion Version
  889. {
  890. get
  891. {
  892. if (IsDisposed)
  893. #pragma warning suppress 56503 // [....], Invalid State after dispose
  894. throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
  895. return headers.MessageVersion;
  896. }
  897. }
  898. protected override MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
  899. {
  900. BodyWriter bufferedBodyWriter;
  901. if (bodyWriter.IsBuffered)
  902. {
  903. bufferedBodyWriter = bodyWriter;
  904. }
  905. else
  906. {
  907. bufferedBodyWriter = bodyWriter.CreateBufferedCopy(maxBufferSize);
  908. }
  909. KeyValuePair<string, object>[] properties = new KeyValuePair<string, object>[Properties.Count];
  910. ((ICollection<KeyValuePair<string, object>>)Properties).CopyTo(properties, 0);
  911. return new BodyWriterMessageBuffer(headers, properties, bufferedBodyWriter);
  912. }
  913. protected override void OnClose()
  914. {
  915. Exception ex = null;
  916. try
  917. {
  918. base.OnClose();
  919. }
  920. catch (Exception e)
  921. {
  922. if (Fx.IsFatal(e))
  923. throw;
  924. ex = e;
  925. }
  926. try
  927. {
  928. if (properties != null)
  929. properties.Dispose();
  930. }
  931. catch (Exception e)
  932. {
  933. if (Fx.IsFatal(e))
  934. throw;
  935. if (ex == null)
  936. ex = e;
  937. }
  938. if (ex != null)
  939. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ex);
  940. bodyWriter = null;
  941. }
  942. protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
  943. {
  944. bodyWriter.WriteBodyContents(writer);
  945. }
  946. protected override IAsyncResult OnBeginWriteMessage(XmlDictionaryWriter writer, AsyncCallback callback, object state)
  947. {
  948. WriteMessagePreamble(writer);
  949. return new OnWriteMessageAsyncResult(writer, this, callback, state);
  950. }
  951. protected override void OnEndWriteMessage(IAsyncResult result)
  952. {
  953. OnWriteMessageAsyncResult.End(result);
  954. }
  955. protected override IAsyncResult OnBeginWriteBodyContents(XmlDictionaryWriter writer, AsyncCallback callback, object state)
  956. {
  957. return bodyWriter.BeginWriteBodyContents(writer, callback, state);
  958. }
  959. protected override void OnEndWriteBodyContents(IAsyncResult result)
  960. {
  961. bodyWriter.EndWriteBodyContents(result);
  962. }
  963. protected override void OnBodyToString(XmlDictionaryWriter writer)
  964. {
  965. if (bodyWriter.IsBuffered)
  966. {
  967. bodyWriter.WriteBodyContents(writer);
  968. }
  969. else
  970. {
  971. writer.WriteString(SR.GetString(SR.MessageBodyIsStream));
  972. }
  973. }
  974. protected internal BodyWriter BodyWriter
  975. {
  976. get
  977. {
  978. return bodyWriter;
  979. }
  980. }
  981. class OnWriteMessageAsyncResult : AsyncResult
  982. {
  983. BodyWriterMessage message;
  984. XmlDictionaryWriter writer;
  985. public OnWriteMessageAsyncResult(XmlDictionaryWriter writer, BodyWriterMessage message, AsyncCallback callback, object state)
  986. : base(callback, state)
  987. {
  988. this.message = message;
  989. this.writer = writer;
  990. if (HandleWriteBodyContents(null))
  991. {
  992. this.Complete(true);
  993. }
  994. }
  995. bool HandleWriteBodyContents(IAsyncResult result)
  996. {
  997. if (result == null)
  998. {
  999. result = this.message.OnBeginWriteBodyContents(this.writer, PrepareAsyncCompletion(HandleWriteBodyContents), this);
  1000. if (!result.CompletedSynchronously)
  1001. {
  1002. return false;
  1003. }
  1004. }
  1005. this.message.OnEndWriteBodyContents(result);
  1006. this.message.WriteMessagePostamble(this.writer);
  1007. return true;
  1008. }
  1009. public static void End(IAsyncResult result)
  1010. {
  1011. AsyncResult.End<OnWriteMessageAsyncResult>(result);
  1012. }
  1013. }
  1014. }
  1015. abstract class ReceivedMessage : Message
  1016. {
  1017. bool isFault;
  1018. bool isEmpty;
  1019. public override bool IsEmpty
  1020. {
  1021. get { return isEmpty; }
  1022. }
  1023. public override bool IsFault
  1024. {
  1025. get { return isFault; }
  1026. }
  1027. protected static bool HasHeaderElement(XmlDictionaryReader reader, EnvelopeVersion envelopeVersion)
  1028. {
  1029. return reader.IsStartElement(XD.MessageDictionary.Header, envelopeVersion.DictionaryNamespace);
  1030. }
  1031. protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
  1032. {
  1033. if (!isEmpty)
  1034. {
  1035. using (XmlDictionaryReader bodyReader = OnGetReaderAtBodyContents())
  1036. {
  1037. if (bodyReader.ReadState == ReadState.Error || bodyReader.ReadState == ReadState.Closed)
  1038. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MessageBodyReaderInvalidReadState, bodyReader.ReadState.ToString())));
  1039. while (bodyReader.NodeType != XmlNodeType.EndElement && !bodyReader.EOF)
  1040. {
  1041. writer.WriteNode(bodyReader, false);
  1042. }
  1043. this.ReadFromBodyContentsToEnd(bodyReader);
  1044. }
  1045. }
  1046. }
  1047. protected bool ReadStartBody(XmlDictionaryReader reader)
  1048. {
  1049. return Message.ReadStartBody(reader, this.Version.Envelope, out this.isFault, out this.isEmpty);
  1050. }
  1051. protected static EnvelopeVersion ReadStartEnvelope(XmlDictionaryReader reader)
  1052. {
  1053. EnvelopeVersion envelopeVersion;
  1054. if (reader.IsStartElement(XD.MessageDictionary.Envelope, XD.Message12Dictionary.Namespace))
  1055. envelopeVersion = EnvelopeVersion.Soap12;
  1056. else if (reader.IsStartElement(XD.MessageDictionary.Envelope, XD.Message11Dictionary.Namespace))
  1057. envelopeVersion = EnvelopeVersion.Soap11;
  1058. else
  1059. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.MessageVersionUnknown)));
  1060. if (reader.IsEmptyElement)
  1061. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.MessageBodyMissing)));
  1062. reader.Read();
  1063. return envelopeVersion;
  1064. }
  1065. protected static void VerifyStartBody(XmlDictionaryReader reader, EnvelopeVersion version)
  1066. {
  1067. if (!reader.IsStartElement(XD.MessageDictionary.Body, version.DictionaryNamespace))
  1068. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.MessageBodyMissing)));
  1069. }
  1070. }
  1071. sealed class StreamedMessage : ReceivedMessage
  1072. {
  1073. MessageHeaders headers;
  1074. XmlAttributeHolder[] envelopeAttributes;
  1075. XmlAttributeHolder[] headerAttributes;
  1076. XmlAttributeHolder[] bodyAttributes;
  1077. string envelopePrefix;
  1078. string headerPrefix;
  1079. string bodyPrefix;
  1080. MessageProperties properties;
  1081. XmlDictionaryReader reader;
  1082. XmlDictionaryReaderQuotas quotas;
  1083. public StreamedMessage(XmlDictionaryReader reader, int maxSizeOfHeaders, MessageVersion desiredVersion)
  1084. {
  1085. properties = new MessageProperties();
  1086. if (reader.NodeType != XmlNodeType.Element)
  1087. reader.MoveToContent();
  1088. if (desiredVersion.Envelope == EnvelopeVersion.None)
  1089. {
  1090. this.reader = reader;
  1091. this.headerAttributes = XmlAttributeHolder.emptyArray;
  1092. this.headers = new MessageHeaders(desiredVersion);
  1093. }
  1094. else
  1095. {
  1096. envelopeAttributes = XmlAttributeHolder.ReadAttributes(reader, ref maxSizeOfHeaders);
  1097. envelopePrefix = reader.Prefix;
  1098. EnvelopeVersion envelopeVersion = ReadStartEnvelope(reader);
  1099. if (desiredVersion.Envelope != envelopeVersion)
  1100. {
  1101. Exception versionMismatchException = new ArgumentException(SR.GetString(SR.EncoderEnvelopeVersionMismatch, envelopeVersion, desiredVersion.Envelope), "reader");
  1102. throw TraceUtility.ThrowHelperError(
  1103. new CommunicationException(versionMismatchException.Message, versionMismatchException),
  1104. this);
  1105. }
  1106. if (HasHeaderElement(reader, envelopeVersion))
  1107. {
  1108. headerPrefix = reader.Prefix;
  1109. headerAttributes = XmlAttributeHolder.ReadAttributes(reader, ref maxSizeOfHeaders);
  1110. headers = new MessageHeaders(desiredVersion, reader, envelopeAttributes, headerAttributes, ref maxSizeOfHeaders);
  1111. }
  1112. else
  1113. {
  1114. headerAttributes = XmlAttributeHolder.emptyArray;
  1115. headers = new MessageHeaders(desiredVersion);
  1116. }
  1117. if (reader.NodeType != XmlNodeType.Element)
  1118. reader.MoveToContent();
  1119. bodyPrefix = reader.Prefix;
  1120. VerifyStartBody(reader, envelopeVersion);
  1121. bodyAttributes = XmlAttributeHolder.ReadAttributes(reader, ref maxSizeOfHeaders);
  1122. if (ReadStartBody(reader))
  1123. {
  1124. this.reader = reader;
  1125. }
  1126. else
  1127. {
  1128. this.quotas = new XmlDictionaryReaderQuotas();
  1129. reader.Quotas.CopyTo(this.quotas);
  1130. reader.Close();
  1131. }
  1132. }
  1133. }
  1134. public override MessageHeaders Headers
  1135. {
  1136. get
  1137. {
  1138. if (IsDisposed)
  1139. #pragma warning suppress 56503 // [....], Invalid State after dispose
  1140. throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
  1141. return headers;
  1142. }
  1143. }
  1144. public override MessageVersion Version
  1145. {
  1146. get
  1147. {
  1148. return headers.MessageVersion;
  1149. }
  1150. }
  1151. public override MessageProperties Properties
  1152. {
  1153. get
  1154. {
  1155. return properties;
  1156. }
  1157. }
  1158. protected override void OnBodyToString(XmlDictionaryWriter writer)
  1159. {
  1160. writer.WriteString(SR.GetString(SR.MessageBodyIsStream));
  1161. }
  1162. protected override void OnClose()
  1163. {
  1164. Exception ex = null;
  1165. try
  1166. {
  1167. base.OnClose();
  1168. }
  1169. catch (Exception e)
  1170. {
  1171. if (Fx.IsFatal(e))
  1172. throw;
  1173. ex = e;
  1174. }
  1175. try
  1176. {
  1177. properties.Dispose();
  1178. }
  1179. catch (Exception e)
  1180. {
  1181. if (Fx.IsFatal(e))
  1182. throw;
  1183. if (ex == null)
  1184. ex = e;
  1185. }
  1186. try
  1187. {
  1188. if (reader != null)
  1189. {
  1190. reader.Close();
  1191. }
  1192. }
  1193. catch (Exception e)
  1194. {
  1195. if (Fx.IsFatal(e))
  1196. throw;
  1197. if (ex == null)
  1198. ex = e;
  1199. }
  1200. if (ex != null)
  1201. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ex);
  1202. }
  1203. protected override XmlDictionaryReader OnGetReaderAtBodyContents()
  1204. {
  1205. XmlDictionaryReader reader = this.reader;
  1206. this.reader = null;
  1207. return reader;
  1208. }
  1209. protected override MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
  1210. {
  1211. if (this.reader != null)
  1212. return OnCreateBufferedCopy(maxBufferSize, this.reader.Quotas);
  1213. return OnCreateBufferedCopy(maxBufferSize, this.quotas);
  1214. }
  1215. protected override void OnWriteStartBody(XmlDictionaryWriter writer)
  1216. {
  1217. writer.WriteStartElement(bodyPrefix, MessageStrings.Body, Version.Envelope.Namespace);
  1218. XmlAttributeHolder.WriteAttributes(bodyAttributes, writer);
  1219. }
  1220. protected override void OnWriteStartEnvelope(XmlDictionaryWriter writer)
  1221. {
  1222. EnvelopeVersion envelopeVersion = Version.Envelope;
  1223. writer.WriteStartElement(envelopePrefix, MessageStrings.Envelope, envelopeVersion.Namespace);
  1224. XmlAttributeHolder.WriteAttributes(envelopeAttributes, writer);
  1225. }
  1226. protected override void OnWriteStartHeaders(XmlDictionaryWriter writer)
  1227. {
  1228. EnvelopeVersion envelopeVersion = Version.Envelope;
  1229. writer.WriteStartElement(headerPrefix, MessageStrings.Header, envelopeVersion.Namespace);
  1230. XmlAttributeHolder.WriteAttributes(headerAttributes, writer);
  1231. }
  1232. protected override string OnGetBodyAttribute(string localName, string ns)
  1233. {
  1234. return XmlAttributeHolder.GetAttribute(bodyAttributes, localName, ns);
  1235. }
  1236. }
  1237. interface IBufferedMessageData
  1238. {
  1239. MessageEncoder MessageEncoder { get; }
  1240. ArraySegment<byte> Buffer { get; }
  1241. XmlDictionaryReaderQuotas Quotas { get; }
  1242. void Close();
  1243. void EnableMultipleUsers();
  1244. XmlDictionaryReader GetMessageReader();
  1245. void Open();
  1246. void ReturnMessageState(RecycledMessageState messageState);
  1247. RecycledMessageState TakeMessageState();
  1248. }
  1249. sealed class BufferedMessage : ReceivedMessage
  1250. {
  1251. MessageHeaders headers;
  1252. MessageProperties properties;
  1253. IBufferedMessageData messageData;
  1254. RecycledMessageState recycledMessageState;
  1255. XmlDictionaryReader reader;
  1256. XmlAttributeHolder[] bodyAttributes;
  1257. public BufferedMessage(IBufferedMessageData messageData, RecycledMessageState recycledMessageState)
  1258. : this(messageData, recycledMessageState, null, false)
  1259. {
  1260. }
  1261. public BufferedMessage(IBufferedMessageData messageData, RecycledMessageState recycledMessageState, bool[] understoodHeaders, bool understoodHeadersModified)
  1262. {
  1263. bool throwing = true;
  1264. try
  1265. {
  1266. this.recycledMessageState = recycledMessageState;
  1267. this.messageData = messageData;
  1268. properties = recycledMessageState.TakeProperties();
  1269. if (properties == null)
  1270. this.properties = new MessageProperties();
  1271. XmlDictionaryReader reader = messageData.GetMessageReader();
  1272. MessageVersion desiredVersion = messageData.MessageEncoder.MessageVersion;
  1273. if (desiredVersion.Envelope == EnvelopeVersion.None)
  1274. {
  1275. this.reader = reader;
  1276. this.headers = new MessageHeaders(desiredVersion);
  1277. }
  1278. else
  1279. {
  1280. EnvelopeVersion envelopeVersion = ReadStartEnvelope(reader);
  1281. if (desiredVersion.Envelope != envelopeVersion)
  1282. {
  1283. Exception versionMismatchException = new ArgumentException(SR.GetString(SR.EncoderEnvelopeVersionMismatch, envelopeVersion, desiredVersion.Envelope), "reader");
  1284. throw TraceUtility.ThrowHelperError(
  1285. new CommunicationException(versionMismatchException.Message, versionMismatchException),
  1286. this);
  1287. }
  1288. if (HasHeaderElement(reader, envelopeVersion))
  1289. {
  1290. headers = recycledMessageState.TakeHeaders();
  1291. if (headers == null)
  1292. {
  1293. headers = new MessageHeaders(desiredVersion, reader, messageData, recycledMessageState, understoodHeaders, understoodHeadersModified);
  1294. }
  1295. else
  1296. {
  1297. headers.Init(desiredVersion, reader, messageData, recycledMessageState, understoodHeaders, understoodHeadersModified);
  1298. }
  1299. }
  1300. else
  1301. {
  1302. headers = new MessageHeaders(desiredVersion);
  1303. }
  1304. VerifyStartBody(reader, envelopeVersion);
  1305. int maxSizeOfAttributes = int.MaxValue;
  1306. bodyAttributes = XmlAttributeHolder.ReadAttributes(reader, ref maxSizeOfAttributes);
  1307. if (maxSizeOfAttributes < int.MaxValue - 4096)
  1308. bodyAttributes = null;
  1309. if (ReadStartBody(reader))
  1310. {
  1311. this.reader = reader;
  1312. }
  1313. else
  1314. {
  1315. reader.Close();
  1316. }
  1317. }
  1318. throwing = false;
  1319. }
  1320. finally
  1321. {
  1322. if (throwing && MessageLogger.LoggingEnabled)
  1323. {
  1324. MessageLogger.LogMessage(messageData.Buffer, MessageLoggingSource.Malformed);
  1325. }
  1326. }
  1327. }
  1328. public override MessageHeaders Headers
  1329. {
  1330. get
  1331. {
  1332. if (IsDisposed)
  1333. #pragma warning suppress 56503 // [....], Invalid State after dispose
  1334. throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
  1335. return headers;
  1336. }
  1337. }
  1338. internal IBufferedMessageData MessageData
  1339. {
  1340. get
  1341. {
  1342. return messageData;
  1343. }
  1344. }
  1345. public override MessageProperties Properties
  1346. {
  1347. get
  1348. {
  1349. if (IsDisposed)
  1350. #pragma warning suppress 56503 // [....], Invalid State after dispose
  1351. throw TraceUtility.ThrowHelperError(CreateMessageDisposedException(), this);
  1352. return properties;
  1353. }
  1354. }
  1355. internal override RecycledMessageState RecycledMessageState
  1356. {
  1357. get { return recycledMessageState; }
  1358. }
  1359. public override MessageVersion Version
  1360. {
  1361. get
  1362. {
  1363. return headers.MessageVersion;
  1364. }
  1365. }
  1366. protected override XmlDictionaryReader OnGetReaderAtBodyContents()
  1367. {
  1368. XmlDictionaryReader reader = this.reader;
  1369. this.reader = null;
  1370. return reader;
  1371. }
  1372. internal override XmlDictionaryReader GetReaderAtHeader()
  1373. {
  1374. if (!headers.ContainsOnlyBufferedMessageHeaders)
  1375. return base.GetReaderAtHeader();
  1376. XmlDictionaryReader reader = messageData.GetMessageReader();
  1377. if (reader.NodeType != XmlNodeType.Element)
  1378. reader.MoveToContent();
  1379. reader.Read();
  1380. if (HasHeaderElement(reader, headers.MessageVersion.Envelope))
  1381. return reader;
  1382. return base.GetReaderAtHeader();
  1383. }
  1384. public XmlDictionaryReader GetBufferedReaderAtBody()
  1385. {
  1386. XmlDictionaryReader reader = messageData.GetMessageReader();
  1387. if (reader.NodeType != XmlNodeType.Element)
  1388. reader.MoveToContent();
  1389. if (this.Version.Envelope != EnvelopeVersion.None)
  1390. {
  1391. reader.Read();
  1392. if (HasHeaderElement(reader, headers.MessageVersion.Envelope))
  1393. reader.Skip();
  1394. if (reader.NodeType != XmlNodeType.Element)
  1395. reader.MoveToContent();
  1396. }
  1397. return reader;
  1398. }
  1399. public XmlDictionaryReader GetMessageReader()
  1400. {
  1401. return messageData.GetMessageReader();
  1402. }
  1403. protected override void OnBodyToString(XmlDictionaryWriter writer)
  1404. {
  1405. using (XmlDictionaryReader reader = GetBufferedReaderAtBody())
  1406. {
  1407. if (this.Version == MessageVersion.None)
  1408. {
  1409. writer.WriteNode(reader, false);
  1410. }
  1411. else
  1412. {
  1413. if (!reader.IsEmptyElement)
  1414. {
  1415. reader.ReadStartElement();
  1416. while (reader.NodeType != XmlNodeType.EndElement)
  1417. writer.WriteNode(reader, false);
  1418. }
  1419. }
  1420. }
  1421. }
  1422. protected override void OnClose()
  1423. {
  1424. Exception ex = null;
  1425. try
  1426. {
  1427. base.OnClose();
  1428. }
  1429. catch (Exception e)
  1430. {
  1431. if (Fx.IsFatal(e))
  1432. throw;
  1433. ex = e;
  1434. }
  1435. try
  1436. {
  1437. properties.Dispose();
  1438. }
  1439. catch (Exception e)
  1440. {
  1441. if (Fx.IsFatal(e))
  1442. throw;
  1443. if (ex == null)
  1444. ex = e;
  1445. }
  1446. try
  1447. {
  1448. if (reader != null)
  1449. {
  1450. reader.Close();
  1451. }
  1452. }
  1453. catch (Exception e)
  1454. {
  1455. if (Fx.IsFatal(e))
  1456. throw;
  1457. if (ex == null)
  1458. ex = e;
  1459. }
  1460. try
  1461. {
  1462. recycledMessageState.ReturnHeaders(headers);
  1463. recycledMessageState.ReturnProperties(properties);
  1464. messageData.ReturnMessageState(recycledMessageState);
  1465. recycledMessageState = null;
  1466. messageData.Close();
  1467. messageData = null;
  1468. }
  1469. catch (Exception e)
  1470. {
  1471. if (Fx.IsFatal(e))
  1472. throw;
  1473. if (ex == null)
  1474. ex = e;
  1475. }
  1476. if (ex != null)
  1477. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ex);
  1478. }
  1479. protected override void OnWriteStartEnvelope(XmlDictionaryWriter writer)
  1480. {
  1481. using (XmlDictionaryReader reader = GetMessageReader())
  1482. {
  1483. reader.MoveToContent();
  1484. EnvelopeVersion envelopeVersion = Version.Envelope;
  1485. writer.WriteStartElement(reader.Prefix, MessageStrings.Envelope, envelopeVersion.Namespace);
  1486. writer.WriteAttributes(reader, false);
  1487. }
  1488. }
  1489. protected override void OnWriteStartHeaders(XmlDictionaryWriter writer)
  1490. {
  1491. using (XmlDictionaryReader reader = GetMessageReader())
  1492. {
  1493. reader.MoveToContent();
  1494. EnvelopeVersion envelopeVersion = Version.Envelope;
  1495. reader.Read();
  1496. if (HasHeaderElement(reader, envelopeVersion))
  1497. {
  1498. writer.WriteStartElement(reader.Prefix, MessageStrings.Header, envelopeVersion.Namespace);
  1499. writer.WriteAttributes(reader, false);
  1500. }
  1501. else
  1502. {
  1503. writer.WriteStartElement(MessageStrings.Prefix, MessageStrings.Header, envelopeVersion.Namespace);
  1504. }
  1505. }
  1506. }
  1507. protected override void OnWriteStartBody(XmlDictionaryWriter writer)
  1508. {
  1509. using (XmlDictionaryReader reader = GetBufferedReaderAtBody())
  1510. {
  1511. writer.WriteStartElement(reader.Prefix, MessageStrings.Body, Version.Envelope.Namespace);
  1512. writer.WriteAttributes(reader, false);
  1513. }
  1514. }
  1515. protected override MessageBuffer OnCreateBufferedCopy(int maxBufferSize)
  1516. {
  1517. if (headers.ContainsOnlyBufferedMessageHeaders)
  1518. {
  1519. KeyValuePair<string, object>[] properties = new KeyValuePair<string, object>[Properties.Count];
  1520. ((ICollection<KeyValuePair<string, object>>)Properties).CopyTo(properties, 0);
  1521. messageData.EnableMultipleUsers();
  1522. bool[] understoodHeaders = null;
  1523. if (headers.HasMustUnderstandBeenModified)
  1524. {
  1525. understoodHeaders = new bool[headers.Count];
  1526. for (int i = 0; i < headers.Count; i++)
  1527. {
  1528. understoodHeaders[i] = headers.IsUnderstood(i);
  1529. }
  1530. }
  1531. return new BufferedMessageBuffer(messageData, properties, understoodHeaders, headers.HasMustUnderstandBeenModified);
  1532. }
  1533. else
  1534. {
  1535. if (this.reader != null)
  1536. return OnCreateBufferedCopy(maxBufferSize, this.reader.Quotas);
  1537. return OnCreateBufferedCopy(maxBufferSize, XmlDictionaryReaderQuotas.Max);
  1538. }
  1539. }
  1540. protected override string OnGetBodyAttribute(string localName, string ns)
  1541. {
  1542. if (this.bodyAttributes != null)
  1543. return XmlAttributeHolder.GetAttribute(this.bodyAttributes, localName, ns);
  1544. using (XmlDictionaryReader reader = GetBufferedReaderAtBody())
  1545. {
  1546. return reader.GetAttribute(localName, ns);
  1547. }
  1548. }
  1549. }
  1550. struct XmlAttributeHolder
  1551. {
  1552. string prefix;
  1553. string ns;
  1554. string localName;
  1555. string value;
  1556. public static XmlAttributeHolder[] emptyArray = new XmlAttributeHolder[0];
  1557. public XmlAttributeHolder(string prefix, string localName, string ns, string value)
  1558. {
  1559. this.prefix = prefix;
  1560. this.localName = localName;
  1561. this.ns = ns;
  1562. this.value = value;
  1563. }
  1564. public string Prefix
  1565. {
  1566. get { return prefix; }
  1567. }
  1568. public string NamespaceUri
  1569. {
  1570. get { return ns; }
  1571. }
  1572. public string LocalName
  1573. {
  1574. get { return localName; }
  1575. }
  1576. public string Value
  1577. {
  1578. get { return value; }
  1579. }
  1580. public void WriteTo(XmlWriter writer)
  1581. {
  1582. writer.WriteStartAttribute(prefix, localName, ns);
  1583. writer.WriteString(value);
  1584. writer.WriteEndAttribute();
  1585. }
  1586. public static void WriteAttributes(XmlAttributeHolder[] attributes, XmlWriter writer)
  1587. {
  1588. for (int i = 0; i < attributes.Length; i++)
  1589. attributes[i].WriteTo(writer);
  1590. }
  1591. public static XmlAttributeHolder[] ReadAttributes(XmlDictionaryReader reader)
  1592. {
  1593. int maxSizeOfHeaders = int.MaxValue;
  1594. return ReadAttributes(reader, ref maxSizeOfHeaders);
  1595. }
  1596. public static XmlAttributeHolder[] ReadAttributes(XmlDictionaryReader reader, ref int maxSizeOfHeaders)
  1597. {
  1598. if (reader.AttributeCount == 0)
  1599. return emptyArray;
  1600. XmlAttributeHolder[] attributes = new XmlAttributeHolder[reader.AttributeCount];
  1601. reader.MoveToFirstAttribute();
  1602. for (int i = 0; i < attributes.Length; i++)
  1603. {
  1604. string ns = reader.NamespaceURI;
  1605. string localName = reader.LocalName;
  1606. string prefix = reader.Prefix;
  1607. string value = string.Empty;
  1608. while (reader.ReadAttributeValue())
  1609. {
  1610. if (value.Length == 0)
  1611. value = reader.Value;
  1612. else
  1613. value += reader.Value;
  1614. }
  1615. Deduct(prefix, ref maxSizeOfHeaders);
  1616. Deduct(localName, ref maxSizeOfHeaders);
  1617. Deduct(ns, ref maxSizeOfHeaders);
  1618. Deduct(value, ref maxSizeOfHeaders);
  1619. attributes[i] = new XmlAttributeHolder(prefix, localName, ns, value);
  1620. reader.MoveToNextAttribute();
  1621. }
  1622. reader.MoveToElement();
  1623. return attributes;
  1624. }
  1625. static void Deduct(string s, ref int maxSizeOfHeaders)
  1626. {
  1627. int byteCount = s.Length * sizeof(char);
  1628. if (byteCount > maxSizeOfHeaders)
  1629. {
  1630. string message = SR.GetString(SR.XmlBufferQuotaExceeded);
  1631. Exception inner = new QuotaExceededException(message);
  1632. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(message, inner));
  1633. }
  1634. maxSizeOfHeaders -= byteCount;
  1635. }
  1636. public static string GetAttribute(XmlAttributeHolder[] attributes, string localName, string ns)
  1637. {
  1638. for (int i = 0; i < attributes.Length; i++)
  1639. if (attributes[i].LocalName == localName && attributes[i].NamespaceUri == ns)
  1640. return attributes[i].Value;
  1641. return null;
  1642. }
  1643. }
  1644. class RecycledMessageState
  1645. {
  1646. MessageHeaders recycledHeaders;
  1647. MessageProperties recycledProperties;
  1648. UriCache uriCache;
  1649. HeaderInfoCache headerInfoCache;
  1650. public HeaderInfoCache HeaderInfoCache
  1651. {
  1652. get
  1653. {
  1654. if (headerInfoCache == null)
  1655. {
  1656. headerInfoCache = new HeaderInfoCache();
  1657. }
  1658. return headerInfoCache;
  1659. }
  1660. }
  1661. public UriCache UriCache
  1662. {
  1663. get
  1664. {
  1665. if (uriCache == null)
  1666. uriCache = new UriCache();
  1667. return uriCache;
  1668. }
  1669. }
  1670. public MessageProperties TakeProperties()
  1671. {
  1672. MessageProperties taken = recycledProperties;
  1673. recycledProperties = null;
  1674. return taken;
  1675. }
  1676. public void ReturnProperties(MessageProperties properties)
  1677. {
  1678. if (properties.CanRecycle)
  1679. {
  1680. properties.Recycle();
  1681. this.recycledProperties = properties;
  1682. }
  1683. }
  1684. public MessageHeaders TakeHeaders()
  1685. {
  1686. MessageHeaders taken = recycledHeaders;
  1687. recycledHeaders = null;
  1688. return taken;
  1689. }
  1690. public void ReturnHeaders(MessageHeaders headers)
  1691. {
  1692. if (headers.CanRecycle)
  1693. {
  1694. headers.Recycle(this.HeaderInfoCache);
  1695. this.recycledHeaders = headers;
  1696. }
  1697. }
  1698. }
  1699. class HeaderInfoCache
  1700. {
  1701. const int maxHeaderInfos = 4;
  1702. HeaderInfo[] headerInfos;
  1703. int index;
  1704. public MessageHeaderInfo TakeHeaderInfo(XmlDictionaryReader reader, string actor, bool mustUnderstand, bool relay, bool isRefParam)
  1705. {
  1706. if (this.headerInfos != null)
  1707. {
  1708. int i = this.index;
  1709. for (;;)
  1710. {
  1711. HeaderInfo headerInfo = this.headerInfos[i];
  1712. if (headerInfo != null)
  1713. {
  1714. if (headerInfo.Matches(reader, actor, mustUnderstand, relay, isRefParam))
  1715. {
  1716. this.headerInfos[i] = null;
  1717. this.index = (i + 1) % maxHeaderInfos;
  1718. return headerInfo;
  1719. }
  1720. }
  1721. i = (i + 1) % maxHeaderInfos;
  1722. if (i == this.index)
  1723. {
  1724. break;
  1725. }
  1726. }
  1727. }
  1728. return new HeaderInfo(reader, actor, mustUnderstand, relay, isRefParam);
  1729. }
  1730. public void ReturnHeaderInfo(MessageHeaderInfo headerInfo)
  1731. {
  1732. HeaderInfo headerInfoToReturn = headerInfo as HeaderInfo;
  1733. if (headerInfoToReturn != null)
  1734. {
  1735. if (this.headerInfos == null)
  1736. {
  1737. this.headerInfos = new HeaderInfo[maxHeaderInfos];
  1738. }
  1739. int i = this.index;
  1740. for (;;)
  1741. {
  1742. if (this.headerInfos[i] == null)
  1743. {
  1744. break;
  1745. }
  1746. i = (i + 1) % maxHeaderInfos;
  1747. if (i == this.index)
  1748. {
  1749. break;
  1750. }
  1751. }
  1752. this.headerInfos[i] = headerInfoToReturn;
  1753. this.index = (i + 1) % maxHeaderInfos;
  1754. }
  1755. }
  1756. class HeaderInfo : MessageHeaderInfo
  1757. {
  1758. string name;
  1759. string ns;
  1760. string actor;
  1761. bool isReferenceParameter;
  1762. bool mustUnderstand;
  1763. bool relay;
  1764. public HeaderInfo(XmlDictionaryReader reader, string actor, bool mustUnderstand, bool relay, bool isReferenceParameter)
  1765. {
  1766. this.actor = actor;
  1767. this.mustUnderstand = mustUnderstand;
  1768. this.relay = relay;
  1769. this.isReferenceParameter = isReferenceParameter;
  1770. reader.GetNonAtomizedNames(out name, out ns);
  1771. }
  1772. public override string Name
  1773. {
  1774. get { return name; }
  1775. }
  1776. public override string Namespace
  1777. {
  1778. get { return ns; }
  1779. }
  1780. public override bool IsReferenceParameter
  1781. {
  1782. get { return isReferenceParameter; }
  1783. }
  1784. public override string Actor
  1785. {
  1786. get { return actor; }
  1787. }
  1788. public override bool MustUnderstand
  1789. {
  1790. get { return mustUnderstand; }
  1791. }
  1792. public override bool Relay
  1793. {
  1794. get { return relay; }
  1795. }
  1796. public bool Matches(XmlDictionaryReader reader, string actor, bool mustUnderstand, bool relay, bool isRefParam)
  1797. {
  1798. return reader.IsStartElement(this.name, this.ns) &&
  1799. this.actor == actor && this.mustUnderstand == mustUnderstand && this.relay == relay && this.isReferenceParameter == isRefParam;
  1800. }
  1801. }
  1802. }
  1803. class UriCache
  1804. {
  1805. const int MaxKeyLength = 128;
  1806. const int MaxEntries = 8;
  1807. Entry[] entries;
  1808. int count;
  1809. public UriCache()
  1810. {
  1811. entries = new Entry[MaxEntries];
  1812. }
  1813. public Uri CreateUri(string uriString)
  1814. {
  1815. Uri uri = Get(uriString);
  1816. if (uri == null)
  1817. {
  1818. uri = new Uri(uriString);
  1819. Set(uriString, uri);
  1820. }
  1821. return uri;
  1822. }
  1823. Uri Get(string key)
  1824. {
  1825. if (key.Length > MaxKeyLength)
  1826. return null;
  1827. for (int i = count - 1; i >= 0; i--)
  1828. if (entries[i].Key == key)
  1829. return entries[i].Value;
  1830. return null;
  1831. }
  1832. void Set(string key, Uri value)
  1833. {
  1834. if (key.Length > MaxKeyLength)
  1835. return;
  1836. if (count < entries.Length)
  1837. {
  1838. entries[count++] = new Entry(key, value);
  1839. }
  1840. else
  1841. {
  1842. Array.Copy(entries, 1, entries, 0, entries.Length - 1);
  1843. entries[count - 1] = new Entry(key, value);
  1844. }
  1845. }
  1846. struct Entry
  1847. {
  1848. string key;
  1849. Uri value;
  1850. public Entry(string key, Uri value)
  1851. {
  1852. this.key = key;
  1853. this.value = value;
  1854. }
  1855. public string Key
  1856. {
  1857. get { return key; }
  1858. }
  1859. public Uri Value
  1860. {
  1861. get { return value; }
  1862. }
  1863. }
  1864. }
  1865. }