/// <summary> /// Creates a DumpWriter which writes rtpdump comptaible files. /// If <param name="modify" /> is true the StartTime and Source properties will be attempted to be copied from the source stream, if they are not present they will be used from the parameters given. /// /// Throws a <see cref="ArgumentNullException"/> if <paramref name="stream"/> or <paramref name="source"/> is null. /// Throws a <see cref="Common.Exception"/> with the Type `DumpWriter` if an unexpected error occurs, if the underlying exception is realted to reading any information being read from a stream being modified then it will be of type `DumpReader`. /// </summary> /// <param name="stream">The stream to write to</param> /// <param name="format">The format to write in</param> /// <param name="source">The source where packets came from in this dump</param> /// <param name="utcStart">The optional start of the file recording (used in the header)</param> /// <param name="modify">Optionally indicates if the file should be modified or created, by default it will not overwrite files if they exist.</param> /// <param name="leaveOpen">Indicates if the stream should be left open after calling Close or Dipose</param> public DumpWriter(System.IO.Stream stream, FileFormat format, System.Net.IPEndPoint defaultSource, DateTime?startTime = null, bool modify = false, bool leaveOpen = false, bool shouldDispose = true) : base(shouldDispose) { if (stream == null) { throw new ArgumentNullException("stream"); } if (defaultSource == null) { throw new ArgumentNullException("source"); } m_Format = format; m_Source = defaultSource; m_Start = startTime ?? DateTime.UtcNow; if (false == modify) // New file { //Create the writer m_Writer = new System.IO.BinaryWriter(stream, Encoding.ASCII, leaveOpen); } else//Modifying { //The stream should be the same format. FileFormat streamFormat = m_Format; try { //Header already written when modifying a file //Need to read the header and advance the stream to the end, indicate the header was already written so it is not again. using (DumpReader reader = new DumpReader(stream, m_WroteHeader = true)) { //Create the writer forcing ASCII Encoding, leave the stream open if indicated m_Writer = new System.IO.BinaryWriter(stream, Encoding.ASCII, leaveOpen); //Read to the end so packets can be added reader.ReadToEnd(); //Ensure the format of the writer matches the reader, if not throw an exception so it can be handled appropriately. //The exception will be of type `DumpReader` if (reader.m_Format != m_Format) { Media.Common.TaggedExceptionExtensions.RaiseTaggedException(reader, "Format of writer does not match reader, Expected: " + m_Format + " Found: " + reader.m_Format); } //Copy the file header from the reader if present, otherwise the file will have no header when written. m_FileHeader = reader.m_FileHeader; m_FileIdentifier = reader.m_FileIdentifier; //Check for the header to be present on existing files if the format has a header. (only Binary) //The exception will be of type `DumpReader` if (m_FileHeader == null && m_Format.HasFileHeader()) { Media.Common.TaggedExceptionExtensions.RaiseTaggedException(reader, "Did not find the expected Binary file header."); } //If not present use the start time indicated in the first entry... if (m_Start == null) { m_Start = startTime ?? reader.m_StartTime; } } } catch (Exception ex)//Only catch exceptions which are unexpected and raise a generic DumpWriter exception { Media.Common.TaggedExceptionExtensions.RaiseTaggedException(this, "An unexpected exception occured while reading the existing information present in the stream. See InnerException for more details.", ex); } } }