/// <summary> /// Returns the next record to write in the DIME message. If the length of the payload data is not /// known upfront then use contentLength==-1 to specify chunked records. Otherwise the amount of data /// written to the record must match the content length specified. When the DimeWriter is closed then the /// message end flag is automatically set on the last record. If writing in non-chunked mode then /// an empty terminating record with TNF=TypeFormatEnum.None will be automatically sent when the /// DimeWriter is closed. /// </summary> /// <param name="id">The unique identifier of the record in the form of a URI.</param> /// <param name="type">The type of payload data in the record. The format of this type is /// specified by the typeFormat parameter. For example, if typeFormat is TypeFormatEnum.MediaType /// then a valid type is "plain/text; charset=utf-8"</param> /// <param name="typeFormat">The format of the type parameter.</param> /// <param name="contentLength">The count of bytes to be written to the DIME record, or -1 to specify /// writing a chunked payload record. /// </param> /// <returns>A write-only DimeRecord.</returns> private DimeRecord CreateRecord(Uri id, string type, TypeFormatEnum typeFormat, int contentLength) { if (type == null) { throw new ArgumentNullException("type"); } if (m_closed) { throw new InvalidOperationException("The writer is closed."); } // if a record currently exists, send it. if (m_currentRecord != null) { m_currentRecord.Close(false); } m_currentRecord = new DimeRecord(m_stream, id, type, typeFormat, m_firstRecord, contentLength, m_defaultChunkSize); m_firstRecord = false; if (m_lastRecord == true) { m_currentRecord.EndOfMessage = true; } return(m_currentRecord); }
/// <summary> /// Closes the DIME message. If writing chunked payloads then any buffered data is written to /// the underlying stream and the chunked record and message end flags are set. If writing /// non-chunked then a terminating empty record with TNF=TypeFormatEnum.None is written to /// end the DIME message.. /// </summary> public void Close() { if (m_closed) { return; } // if a record currently exists, send it. if (m_currentRecord != null) { m_currentRecord.Close(true); m_currentRecord = null; } m_closed = true; }
/// <summary> /// Returns the next record in the DIME message in read-only mode. If the DimeReader is closed then /// an InvalidOperationException will occur. When the end of /// the message is reached ReadRecord will return null. ReadRecord is a blocking i/o call in that the /// DIME record header is read before the method returns. /// </summary> /// <returns> /// A read-only DimeRecord, or null if it's the end of the DIME message. If the record has TNF=None /// and it is the last record in the message null is also returned. /// </returns> public DimeRecord ReadRecord() { if (m_closed) throw new InvalidOperationException("DimeReader is closed."); if (m_currentRecord != null) { if (m_currentRecord.EndOfMessage) return null; m_currentRecord.Close(); } m_currentRecord = new DimeRecord(m_stream); if (m_currentRecord.TypeFormat == TypeFormatEnum.None && m_currentRecord.EndOfMessage) { m_currentRecord.Close(); return null; } return m_currentRecord; }
/// <summary> /// Encapsulates the SOAP message into a DIME message. The stored attachments are added as DIME records. /// If an exception has been thrown, the soap message containing the exception is /// not encapsulated. /// </summary> private void AfterSerialize(SoapMessage message) { newStream.Position = 0; //if response only, then not on request if (dimeDir != DimeDir.Response && message.Exception == null) { DimeWriter dw = new DimeWriter(networkStream); int contentLength = (newStream.CanSeek && newStream.Length <= DefaultBufferSize) ? (int)newStream.Length : -1; DimeRecord record = null; if (outputAttachments.Count > 0) { record = dw.NewRecord(id, SoapContentType, TypeFormatEnum.AbsoluteUri, contentLength); } else { record = dw.LastRecord(id, SoapContentType, TypeFormatEnum.AbsoluteUri, contentLength); } BinaryCopy(newStream, record.BodyStream); //add attachments for (int i = 0; i < outputAttachments.Count; i++) { DimeAttachment attachment = (DimeAttachment)outputAttachments[i]; contentLength = attachment.Stream.CanSeek ? (int)attachment.Stream.Length : -1; if (i == (outputAttachments.Count - 1)) { record = dw.LastRecord(attachment.Id, attachment.Type, attachment.TypeFormat, contentLength); } else { record = dw.NewRecord(attachment.Id, attachment.Type, attachment.TypeFormat, contentLength); } BinaryCopy(attachment.Stream, record.BodyStream); } dw.Close(); } else { BinaryCopy(newStream, networkStream); } }
/// <summary> /// Returns the next record in the DIME message in read-only mode. If the DimeReader is closed then /// an InvalidOperationException will occur. When the end of /// the message is reached ReadRecord will return null. ReadRecord is a blocking i/o call in that the /// DIME record header is read before the method returns. /// </summary> /// <returns> /// A read-only DimeRecord, or null if it's the end of the DIME message. If the record has TNF=None /// and it is the last record in the message null is also returned. /// </returns> public DimeRecord ReadRecord() { if (m_closed) { throw new InvalidOperationException("DimeReader is closed."); } if (m_currentRecord != null) { if (m_currentRecord.EndOfMessage) { return(null); } m_currentRecord.Close(); } m_currentRecord = new DimeRecord(m_stream); if (m_currentRecord.TypeFormat == TypeFormatEnum.None && m_currentRecord.EndOfMessage) { m_currentRecord.Close(); return(null); } return(m_currentRecord); }
/// <summary> /// Retrieves the SOAP message from the DIME message. DIME attachments /// are removed from the stream and stored for future use by the AfterDeserialize /// method. /// </summary> private void BeforeDeserialize(SoapMessage message) { if (message.ContentType == DimeContentType) { contentType = message.ContentType; inputAttachments = new Hashtable(); DimeReader dr = new DimeReader(networkStream); DimeRecord record = dr.ReadRecord(); if (record.Type != SoapContentType) { throw new Exception(String.Format("Expected content type '{0}' in record containing SOAP payload.", SoapContentType)); } message.ContentType = "text/xml"; BinaryCopy(record.BodyStream, newStream); record.Close(); //get attachments while ((record = dr.ReadRecord()) != null) { //OutOfMemoryException Stream stream = new MemoryStream(record.Chunked ? DefaultBufferSize : record.ContentLength); BinaryCopy(record.BodyStream, stream); stream.Position = 0; DimeAttachment attachment = new DimeAttachment(record.Id.ToString(), record.Type, record.TypeFormat, stream); inputAttachments.Add(attachment.Id, attachment); record.Close(); } dr.Close(); } else { BinaryCopy(networkStream, newStream); } newStream.Position = 0; }
/// <summary> /// Creates a DimeStream object /// </summary> /// <param name="stream">Must be open</param> /// <param name="dimeRecord">A valid header for the DIME record.</param> /// <param name="streamType">Specifies if the stream is read-only or write-only.</param> internal DimeStream (DimeRecord dimeRecord) { m_dimeRecord = dimeRecord; }
/// <summary> /// Creates a DimeStream object /// </summary> /// <param name="dimeRecord">A valid header for the DIME record.</param> internal DimeStream(DimeRecord dimeRecord) { m_dimeRecord = dimeRecord; }
/// <summary> /// Returns the next record to write in the DIME message. If the length of the payload data is not /// known upfront then use contentLength==-1 to specify chunked records. Otherwise the amount of data /// written to the record must match the content length specified. When the DimeWriter is closed then the /// message end flag is automatically set on the last record. If writing in non-chunked mode then /// an empty terminating record with TNF=TypeFormatEnum.None will be automatically sent when the /// DimeWriter is closed. /// </summary> /// <param name="id">The unique identifier of the record in the form of a URI.</param> /// <param name="type">The type of payload data in the record. The format of this type is /// specified by the typeFormat parameter. For example, if typeFormat is TypeFormatEnum.MediaType /// then a valid type is "plain/text; charset=utf-8"</param> /// <param name="typeFormat">The format of the type parameter.</param> /// <param name="contentLength">The count of bytes to be written to the DIME record, or -1 to specify /// writing a chunked payload record. /// </param> /// <returns>A write-only DimeRecord.</returns> private DimeRecord CreateRecord(Uri id, string type, TypeFormatEnum typeFormat, int contentLength) { if (type == null) throw new ArgumentNullException("type"); if (m_closed) throw new InvalidOperationException("The writer is closed."); // if a record currently exists, send it. if (m_currentRecord != null) m_currentRecord.Close(false); m_currentRecord = new DimeRecord(m_stream, id, type, typeFormat, m_firstRecord, contentLength, m_defaultChunkSize); m_firstRecord = false; if(m_lastRecord == true) m_currentRecord.EndOfMessage = true; return m_currentRecord; }
/// <summary> /// Closes the DIME message. If writing chunked payloads then any buffered data is written to /// the underlying stream and the chunked record and message end flags are set. If writing /// non-chunked then a terminating empty record with TNF=TypeFormatEnum.None is written to /// end the DIME message.. /// </summary> public void Close() { if (m_closed) return; // if a record currently exists, send it. if (m_currentRecord != null) { m_currentRecord.Close(true); m_currentRecord = null; } m_closed = true; }