MessageBuffer.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. //------------------------------------------------------------
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. //------------------------------------------------------------
  4. namespace System.ServiceModel.Channels
  5. {
  6. using System.Xml;
  7. using System.ServiceModel;
  8. using System.ServiceModel.Dispatcher;
  9. using System.Xml.XPath;
  10. using System.Diagnostics;
  11. using System.IO;
  12. using System.Collections.Generic;
  13. public abstract class MessageBuffer : IXPathNavigable, IDisposable
  14. {
  15. public abstract int BufferSize { get; }
  16. void IDisposable.Dispose()
  17. {
  18. Close();
  19. }
  20. public abstract void Close();
  21. public virtual void WriteMessage(Stream stream)
  22. {
  23. if (stream == null)
  24. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("stream"));
  25. Message message = CreateMessage();
  26. using (message)
  27. {
  28. XmlDictionaryWriter writer = XmlDictionaryWriter.CreateBinaryWriter(stream, XD.Dictionary, null, false);
  29. using (writer)
  30. {
  31. message.WriteMessage(writer);
  32. }
  33. }
  34. }
  35. public virtual string MessageContentType
  36. {
  37. get { return FramingEncodingString.Binary; }
  38. }
  39. public abstract Message CreateMessage();
  40. internal Exception CreateBufferDisposedException()
  41. {
  42. return new ObjectDisposedException("", SR.GetString(SR.MessageBufferIsClosed));
  43. }
  44. public XPathNavigator CreateNavigator()
  45. {
  46. return CreateNavigator(int.MaxValue, XmlSpace.None);
  47. }
  48. public XPathNavigator CreateNavigator(int nodeQuota)
  49. {
  50. return CreateNavigator(nodeQuota, XmlSpace.None);
  51. }
  52. public XPathNavigator CreateNavigator(XmlSpace space)
  53. {
  54. return CreateNavigator(int.MaxValue, space);
  55. }
  56. public XPathNavigator CreateNavigator(int nodeQuota, XmlSpace space)
  57. {
  58. if (nodeQuota <= 0)
  59. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("nodeQuota", SR.GetString(SR.FilterQuotaRange)));
  60. return new SeekableMessageNavigator(this.CreateMessage(), nodeQuota, space, true, true);
  61. }
  62. }
  63. class DefaultMessageBuffer : MessageBuffer
  64. {
  65. XmlBuffer msgBuffer;
  66. KeyValuePair<string, object>[] properties;
  67. bool[] understoodHeaders;
  68. bool closed;
  69. MessageVersion version;
  70. Uri to;
  71. string action;
  72. bool isNullMessage;
  73. public DefaultMessageBuffer(Message message, XmlBuffer msgBuffer)
  74. {
  75. this.msgBuffer = msgBuffer;
  76. this.version = message.Version;
  77. this.isNullMessage = message is NullMessage;
  78. properties = new KeyValuePair<string, object>[message.Properties.Count];
  79. ((ICollection<KeyValuePair<string, object>>)message.Properties).CopyTo(properties, 0);
  80. understoodHeaders = new bool[message.Headers.Count];
  81. for (int i = 0; i < understoodHeaders.Length; ++i)
  82. understoodHeaders[i] = message.Headers.IsUnderstood(i);
  83. //CSDMain 17837: CreateBufferedCopy should have code to copy over the To and Action headers
  84. if (version == MessageVersion.None)
  85. {
  86. this.to = message.Headers.To;
  87. this.action = message.Headers.Action;
  88. }
  89. }
  90. object ThisLock
  91. {
  92. get { return msgBuffer; }
  93. }
  94. public override int BufferSize
  95. {
  96. get { return msgBuffer.BufferSize; }
  97. }
  98. public override void Close()
  99. {
  100. lock (ThisLock)
  101. {
  102. if (closed)
  103. return;
  104. closed = true;
  105. for (int i = 0; i < this.properties.Length; i++)
  106. {
  107. IDisposable disposable = this.properties[i].Value as IDisposable;
  108. if (disposable != null)
  109. disposable.Dispose();
  110. }
  111. }
  112. }
  113. public override Message CreateMessage()
  114. {
  115. if (closed)
  116. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateBufferDisposedException());
  117. Message msg;
  118. if (this.isNullMessage)
  119. {
  120. msg = new NullMessage();
  121. }
  122. else
  123. {
  124. msg = Message.CreateMessage(msgBuffer.GetReader(0), int.MaxValue, this.version);
  125. }
  126. lock (ThisLock)
  127. {
  128. msg.Properties.CopyProperties(properties);
  129. }
  130. for (int i = 0; i < understoodHeaders.Length; ++i)
  131. {
  132. if (understoodHeaders[i])
  133. msg.Headers.AddUnderstood(i);
  134. }
  135. if (this.to != null)
  136. {
  137. msg.Headers.To = this.to;
  138. }
  139. if (this.action != null)
  140. {
  141. msg.Headers.Action = this.action;
  142. }
  143. return msg;
  144. }
  145. }
  146. class BufferedMessageBuffer : MessageBuffer
  147. {
  148. IBufferedMessageData messageData;
  149. KeyValuePair<string, object>[] properties;
  150. bool closed;
  151. object thisLock = new object();
  152. bool[] understoodHeaders;
  153. bool understoodHeadersModified;
  154. public BufferedMessageBuffer(IBufferedMessageData messageData,
  155. KeyValuePair<string, object>[] properties, bool[] understoodHeaders, bool understoodHeadersModified)
  156. {
  157. this.messageData = messageData;
  158. this.properties = properties;
  159. this.understoodHeaders = understoodHeaders;
  160. this.understoodHeadersModified = understoodHeadersModified;
  161. messageData.Open();
  162. }
  163. public override int BufferSize
  164. {
  165. get
  166. {
  167. lock (ThisLock)
  168. {
  169. if (closed)
  170. #pragma warning suppress 56503 // [....], Invalid State after dispose
  171. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateBufferDisposedException());
  172. return messageData.Buffer.Count;
  173. }
  174. }
  175. }
  176. public override void WriteMessage(Stream stream)
  177. {
  178. if (stream == null)
  179. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("stream"));
  180. lock (ThisLock)
  181. {
  182. if (closed)
  183. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateBufferDisposedException());
  184. ArraySegment<byte> buffer = messageData.Buffer;
  185. stream.Write(buffer.Array, buffer.Offset, buffer.Count);
  186. }
  187. }
  188. public override string MessageContentType
  189. {
  190. get
  191. {
  192. lock (ThisLock)
  193. {
  194. if (closed)
  195. #pragma warning suppress 56503 // [....], Invalid State after dispose
  196. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateBufferDisposedException());
  197. return messageData.MessageEncoder.ContentType;
  198. }
  199. }
  200. }
  201. object ThisLock
  202. {
  203. get { return thisLock; }
  204. }
  205. public override void Close()
  206. {
  207. lock (ThisLock)
  208. {
  209. if (!closed)
  210. {
  211. closed = true;
  212. messageData.Close();
  213. messageData = null;
  214. }
  215. }
  216. }
  217. public override Message CreateMessage()
  218. {
  219. lock (ThisLock)
  220. {
  221. if (closed)
  222. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateBufferDisposedException());
  223. RecycledMessageState recycledMessageState = messageData.TakeMessageState();
  224. if (recycledMessageState == null)
  225. recycledMessageState = new RecycledMessageState();
  226. BufferedMessage bufferedMessage = new BufferedMessage(messageData, recycledMessageState, this.understoodHeaders, this.understoodHeadersModified);
  227. bufferedMessage.Properties.CopyProperties(this.properties);
  228. messageData.Open();
  229. return bufferedMessage;
  230. }
  231. }
  232. }
  233. class BodyWriterMessageBuffer : MessageBuffer
  234. {
  235. BodyWriter bodyWriter;
  236. KeyValuePair<string, object>[] properties;
  237. MessageHeaders headers;
  238. bool closed;
  239. object thisLock = new object();
  240. public BodyWriterMessageBuffer(MessageHeaders headers,
  241. KeyValuePair<string, object>[] properties, BodyWriter bodyWriter)
  242. {
  243. this.bodyWriter = bodyWriter;
  244. this.headers = new MessageHeaders(headers);
  245. this.properties = properties;
  246. }
  247. protected object ThisLock
  248. {
  249. get { return thisLock; }
  250. }
  251. public override int BufferSize
  252. {
  253. get { return 0; }
  254. }
  255. public override void Close()
  256. {
  257. lock (ThisLock)
  258. {
  259. if (!closed)
  260. {
  261. closed = true;
  262. bodyWriter = null;
  263. headers = null;
  264. properties = null;
  265. }
  266. }
  267. }
  268. public override Message CreateMessage()
  269. {
  270. lock (ThisLock)
  271. {
  272. if (closed)
  273. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateBufferDisposedException());
  274. return new BodyWriterMessage(headers, properties, bodyWriter);
  275. }
  276. }
  277. protected BodyWriter BodyWriter
  278. {
  279. get { return bodyWriter; }
  280. }
  281. protected MessageHeaders Headers
  282. {
  283. get { return headers; }
  284. }
  285. protected KeyValuePair<string, object>[] Properties
  286. {
  287. get { return properties; }
  288. }
  289. protected bool Closed
  290. {
  291. get { return closed; }
  292. }
  293. }
  294. }