Reading Xml over Socket c# - c#

Im trying to read/write xml from/to a server using a tcp socket connection. It gives me the error Root element is missing. I know there are xmpp/jabber libraries out there but I am looking for an easy custom solution how to do this in general and how to fix the error in my code.
I would greatly appreciate if someone could help me out :)
private void WritePreauthStreamInit(XmlWriter writer, string domain)
{
this.socketStream = new NetworkStream(this._socket);
XmlWriter writer1 = XmlWriter.Create(this.socketStream);
writer1.WriteStartElement("stream", "stream", "http://etherx.jabber.org/streams");
writer1.WriteAttributeString("to", domain);
writer1.WriteAttributeString("version", "1.0");
writer1.WriteStartElement("start-ack");
writer1.WriteEndElement();
writer1.Flush();
XmlReader reader1 = XmlReader.Create(this.socketStream);
while (reader1.Read()) //Exception: Root element is missing
{
string xml = reader1.Read().ToString();
}
}

My guess is that either XmlReader has false assumptions regarding buffer size of received data (I.E.: it expects to read either 4096 bytes or hit the end of the stream before it starts processing data) or the server is not sending what would be a valid document.
Either way, you could check by implementing a logging stream wrapper which dumps network traffic to disk or by using Wireshark or similar.
public class LoggingStreamWrapper : Stream
{
private Stream baseStream;
private TextWriter twLog;
private Encoding baseEncoding;
public LoggingStreamWrapper(Stream baseStream, TextWriter twLog)
: this(baseStream, twLog, Encoding.UTF8)
{
}
public LoggingStreamWrapper(Stream baseStream, TextWriter twLog, Encoding encoding)
{
if (baseStream == null)
throw new ArgumentNullException("baseStream");
if (twLog == null)
throw new ArgumentNullException("twLog");
this.baseStream = baseStream;
this.twLog = twLog;
this.baseEncoding = encoding;
}
public override bool CanRead
{
get { return baseStream.CanRead; }
}
public override bool CanSeek
{
get { return baseStream.CanSeek; }
}
public override bool CanWrite
{
get { return baseStream.CanWrite; }
}
public override void Flush()
{
baseStream.Flush();
twLog.WriteLine("Flushed stream");
twLog.Flush();
}
public override long Length
{
get { return baseStream.Length; }
}
public override long Position
{
get { return baseStream.Position; }
set
{
baseStream.Position = value;
twLog.WriteLine(string.Format("Set position to {0}", value));
twLog.Flush();
}
}
public override int Read(byte[] buffer, int offset, int count)
{
var bRead = baseStream.Read(buffer, offset, count);
if (bRead > 1)
{
twLog.WriteLine(string.Format("Read {0} bytes from stream: {1}\r\n{2}", bRead,
getText(buffer, offset, bRead),
Convert.ToBase64String(buffer, offset, bRead, Base64FormattingOptions.InsertLineBreaks)));
twLog.Flush();
}
else
{
twLog.WriteLine(string.Format("Read {0} bytes from stream", bRead));
twLog.Flush();
}
return bRead;
}
private string getText(byte[] buffer, int offset, int bRead)
{
try
{
return baseEncoding.GetString(buffer, offset, bRead);
}
catch
{
return "{ERROR: Could not convert to text}";
}
}
public override long Seek(long offset, SeekOrigin origin)
{
var newpos = baseStream.Seek(offset, origin);
twLog.WriteLine(string.Format("Seeked to {0} relative to {1}. New offset {2}", offset, origin, newpos));
twLog.Flush();
return newpos;
}
public override void SetLength(long value)
{
baseStream.SetLength(value);
twLog.WriteLine(string.Format("Set length to {0}", value));
twLog.Flush();
}
public override void Write(byte[] buffer, int offset, int count)
{
baseStream.Write(buffer, offset, count);
twLog.WriteLine(string.Format("Wrote {0} bytes to stream: {1}\r\n{2}", count,
getText(buffer, offset, count),
Convert.ToBase64String(buffer, offset, count, Base64FormattingOptions.InsertLineBreaks)));
twLog.Flush();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
twLog.Dispose();
baseStream.Dispose();
}
}
}

Related

Write only stream - get written bytes count with DataContractSerializer

Consider I have the following snippet:
public void Store(Stream s, object t)
{
var serializer = new DataContractSerializer(target.GetType(),
new DataContractSerializerSettings
{
PreserveObjectReferences = true
});
serializer.WriteObject(s, target);
}
where s is write-only and doesn't support seeking.
Is there any way to get bytes count that was written to stream by WriteObject? I know I can do it in the following way:
using (var memStream = new MemoryStream())
{
serializer.WriteObject(serializer, target);
Debug.WriteLine(memStream.Length);
memStream.CopyTo(s);
}
but I wonder wheter it is possible to avoid CopyTo - object is quite huge.
EDIT:
I've just came up with an idea: I can create a wrapper that counts bytes on write. It's the best solution so fat, but maybe there is another way.
DONE
I've implemented a wrapper: https://github.com/pwasiewicz/counted-stream - maybe it will be useful for someone.
Thanks!
Sample implementation of a wrapper I've made:
public class CountedStream : Stream
{
private readonly Stream stream;
public CountedStream(Stream stream)
{
if (stream == null) throw new ArgumentNullException("stream");
this.stream = stream;
}
public long WrittenBytes { get; private set; }
public override void Flush()
{
this.stream.Flush();
}
public override int Read(byte[] buffer, int offset, int count)
{
return this.stream.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
return this.stream.Seek(offset, origin);
}
public override void SetLength(long value)
{
this.stream.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
if (buffer.Length >= offset + count)
throw new ArgumentException("Count exceeds buffer size");
this.stream.Write(buffer, offset, count);
this.WrittenBytes += count;
}
public override bool CanRead
{
get { return this.stream.CanRead; }
}
public override bool CanSeek
{
get { return this.stream.CanSeek; }
}
public override bool CanWrite
{
get { return this.stream.CanWrite; }
}
public override long Length
{
get { return this.stream.Length; }
}
public override bool CanTimeout
{
get { return this.stream.CanTimeout; }
}
public override long Position
{
get { return this.stream.Position; }
set { this.stream.Position = value; }
}
}

NLayer MpegFile to SFML (.NET) Music

I'm currently searching for some way to extended SFML.Net to use MP3. Therefore ioctllr recommended NLayer, which I wanted to try. This is my approach:
namespace AudioCuesheetEditor.AudioBackend
{
public class SFMLMp3Stream : Stream
{
private static readonly Logfile log = Logfile.getLogfile(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private MpegFile file;
public SFMLMp3Stream(String _filename)
{
//TODO:Check file existence
file = new MpegFile(_filename);
log.debug("file = " + file.ToString());
}
#region implemented abstract members of Stream
public override void Flush()
{
file.Position = 0;
}
public override long Seek(long offset, SeekOrigin origin)
{
switch (origin)
{
case SeekOrigin.Begin:
file.Position = offset;
break;
case SeekOrigin.Current:
file.Position = file.Position + offset;
break;
case SeekOrigin.End:
break;
}
return file.Position;
}
public override void SetLength(long value)
{
//TODO?
int i = 1;
}
public override int Read(byte[] buffer, int offset, int count)
{
return file.ReadSamples(buffer, offset, count);
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotImplementedException();
}
public override bool CanRead
{
get
{
return true;
}
}
public override bool CanSeek
{
get
{
return file.CanSeek;
}
}
public override bool CanWrite
{
get
{
//Writing to stream is prohibited
return false;
}
}
public override long Length
{
get
{
return file.Length;
}
}
public override long Position
{
get
{
return file.Position;
}
set
{
file.Position = value;
}
}
#endregion
}
}
Used this way:
musicStream = new SFMLMp3Stream(this.objProgram.getObjCuesheet().getAudiofilePath(true));
try
{
music = new Music(musicStream);
}
catch(Exception ex)
{
log.fatal(ex.ToString());
}
I get the exception from SFML:
05.06.2014 10:34:28 AudioCuesheetEditor.AudioBackend.AudioManagerSFML: FATAL | SFML.LoadingFailedException: Failed to load music from memory
bei SFML.Audio.Music..ctor(Stream stream)
bei AudioCuesheetEditor.AudioBackend.AudioManagerSFML.setMusic() in d:\tmp\AudioCuesheetEditor\src\AudioCuesheetEditor\AudioBackend\AudioManagerSFML.cs:Zeile 50.
I read in SFML, that it needs PCM 16 Bit signed integers (http://en.sfml-dev.org/forums/index.php?topic=1406.0). Does NLayer support this? How do I need to change the code, that it works?
Thanks for your help.
Sven
Unhappiliy Music class doesn't offer reading an mp3 stream.

What are the possible causes for stream not writable exception?

What are the possible causes for Stream not Writable Exception when serializing custom object over TCP using Network Stream in C#.
I am Sending the Mp3 data in the form of Packets.The Frame consists of Byte[] Buffer.I am Using Binary Formatter to serialize the object.
BinaryFormatter.Serialize(NetworkStream,Packet);
The Mp3 Played at client with distortion and jitters end for few seconds and then The above mentioned exception raised.I m using NAudio Open Source library for it.
Before doing this modification I was using
NetworkStream.Write(Byte[] Buffer,0,EncodedSizeofMp3);
and it was writing it successfully before giving any exception
If you are writing to a NetworkStream, the stream/socket could be closed
If you are writing to a NetworkStream, it could have been created with FileAccess.Read
If I had to guess, though, it sounds like something is closing the stream - this can be the case if, say, a "writer" along the route assumes it owns the stream, so closes the stream prematurely. It is pretty common to have to write and use some kind of wrapper Stream that ignores Close() requests (I have one in front of me right now, in fact, since I'm writing some TCP code).
As a small aside; I generally advise against BinaryFormatter for comms (except remoting) - most importantly: it doesn't "version" in a very friendly way, but it also tends to be a bit verbose in most cases.
Here's the wrapper I'm using currently, in case it helps (the Reset() method spoofs resetting the position, so the caller can read a relative position):
class NonClosingNonSeekableStream : Stream
{
public NonClosingNonSeekableStream(Stream tail)
{
if(tail == null) throw new ArgumentNullException("tail");
this.tail = tail;
}
private long position;
private readonly Stream tail;
public override bool CanRead
{
get { return tail.CanRead; }
}
public override bool CanWrite
{
get { return tail.CanWrite; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanTimeout
{
get { return false; }
}
public override long Position
{
get { return position; }
set { throw new NotSupportedException(); }
}
public override void Flush()
{
tail.Flush();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override long Length
{
get { throw new NotSupportedException(); }
}
public override int Read(byte[] buffer, int offset, int count)
{
int read = tail.Read(buffer, offset, count);
if (read > 0) position += read;
return read;
}
public override void Write(byte[] buffer, int offset, int count)
{
tail.Write(buffer, offset, count);
if (count > 0) position += count;
}
public override int ReadByte()
{
int result = tail.ReadByte();
if (result >= 0) position++;
return result;
}
public override void WriteByte(byte value)
{
tail.WriteByte(value);
position++;
}
public void Reset()
{
position = 0;
}
}

Modify css file (minify) using HttpModule: GZip CRC check fails

i am using the following code to minify my css on the fly:
namespace MyCMS.Modules
{
public class CSSModule : IHttpModule
{
void IHttpModule.Dispose()
{
throw new NotImplementedException();
}
void IHttpModule.Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
HttpContext context = app.Context;
if (app.Request.RawUrl.Contains(".css"))
{
context.Response.Filter = new CSSFilter(app.Response.Filter);
}
}
private class CSSFilter : Stream
{
public CSSFilter(Stream sink) { _sink = sink; }
private Stream _sink;
public override bool CanRead { get { return true; } }
public override bool CanSeek { get { return true; } }
public override bool CanWrite { get { return true; } }
public override void Flush() { _sink.Flush(); }
public override long Length { get { return 0; } }
private long _position;
public override long Position
{
get { return _position; }
set { _position = value; }
}
public override int Read(byte[] buffer, int offset, int count) { return _sink.Read(buffer, offset, count); }
public override long Seek(long offset, SeekOrigin origin) { return _sink.Seek(offset, origin); }
public override void SetLength(long value) { _sink.SetLength(value); }
public override void Close() { _sink.Close(); }
public override void Write(byte[] buffer, int offset, int count)
{
byte[] data = new byte[count];
Buffer.BlockCopy(buffer, offset, data, 0, count);
string html = System.Text.Encoding.Default.GetString(buffer);
html = Yahoo.Yui.Compressor.CssCompressor.Compress(html,0, Yahoo.Yui.Compressor.CssCompressionType.Hybrid, true);
byte[] outdata = System.Text.Encoding.Default.GetBytes(html);
_sink.Write(outdata, 0, outdata.GetLength(0));
}
}
}
}
The problem is, the CRC of the GZip ( which is enabled on the server ) fails.
I do understand why it fails, since the file content was X and now its Y (minified),
and the original CRC was calculated for X, not Y.
what can i do to fix this?
I have created a sample MVC Application with CSSModule ,
With out module Site.css size was ~6kb.
Using module Site.css size ~1kb.
May be it will help you.
Link: http://www.mediafire.com/?a86fqg1zqy44ssc
http://www.sendspace.com/file/exxrj5

Stream to file while returning a WCF stream?

I have a WCF service that streams large files (100MB+) from a remote FTP server.
[ServiceContract]
public interface IStreamService
{
[OperationContract]
Stream GetDataFromFtp();
}
public class StreamService : IStreamService
{
public Stream GetDataFromFtp()
{
Stream ftpStream = Retr(...);
return ftpStream;
}
}
As WCF streams the file to the client, I want to stream it into a local cache, so that future requests don't need to go all the way back to the remote FTP - I can just serve them off disk.
I'm having problems achieving this without buffering the entire 100MB file stream in memory before returning it.
I tried using a simple capturing stream wrapper that does a write for each read:
public class CapturingStreamWrapper : Stream
{
private readonly Stream stream;
private readonly Stream captureStream;
public override int Read(byte[] buffer, int offset, int count)
{
int readBytes = stream.Read(buffer, offset, count);
captureStream.Write(buffer, offset, readBytes);
return readBytes;
}
}
public class StreamService : IStreamService
{
public Stream GetDataFromFtp()
{
Stream ftpStream = Retr(...);
Stream cacheStream = File.OpenWrite(...);
return new CapturingStreamWrapper(ftpStream, cacheStream);
}
}
But this didn't seem to work.
Additionally this doesn't provide any error handling - I need a catch block for the cache to delete any half-written file if the client transfer fails (i.e. transactional cache). I'm not sure how this would work because I don't know when streams are called/cleaned up in the WCF lifecycle.
Any ideas how I can stream into a file as I stream back to the client?
I ended up writing a couple of interconnected stream classes - one that pipes to the other as it reads. Apologies for the large code paste:
/// <summary>
/// A stream that, as it reads, makes those bytes available on an ouput
/// stream. Thread safe.
/// </summary>
public class CacheStream : Stream
{
private readonly Stream stream;
public CacheStream(Stream stream)
{
if (stream == null) throw new ArgumentNullException("stream");
this.stream = stream;
OutputStream = new CacheOutputStream(this);
}
public event EventHandler<BytesReadEventArgs> BytesRead = delegate { };
public event EventHandler Closing = delegate { };
public Stream OutputStream { get; private set; }
public override void Flush()
{
stream.Flush();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new InvalidOperationException("Cannot seek in CachingStream.");
}
public override void SetLength(long value)
{
stream.SetLength(value);
}
public override int Read(byte[] buffer, int offset, int count)
{
int numberOfBytesRead = stream.Read(buffer, offset, count);
if (numberOfBytesRead > 0)
PipeToOutputStream(buffer, offset, numberOfBytesRead);
return numberOfBytesRead;
}
private void PipeToOutputStream(byte[] buffer, int offset, int numberOfBytesRead)
{
var tmp = new byte[numberOfBytesRead];
Array.Copy(buffer, offset, tmp, 0, numberOfBytesRead);
BytesRead(this, new BytesReadEventArgs(tmp));
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new InvalidOperationException("Cannot write in CachingStream.");
}
public override bool CanRead
{
get { return stream.CanRead; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return false; }
}
public override long Length
{
get { return stream.Length; }
}
public override long Position
{
get { return stream.Position; }
set { throw new InvalidOperationException("Cannot set position in CachingStream."); }
}
public override void Close()
{
Closing(this, EventArgs.Empty);
base.Close();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
OutputStream.Dispose();
}
}
And
/// <summary>
/// Output portion of CacheStream. Streams bytes from a queue of buffers.
/// Thread safe.
/// </summary>
public class CacheOutputStream : Stream
{
private volatile int position;
private volatile int length;
private volatile bool sourceIsClosed;
// No Deque<T> in the BCL yet, but LinkedList is more or less the same.
private readonly LinkedList<byte[]> buffers = new LinkedList<byte[]>();
public CacheOutputStream(CacheStream stream)
{
if (stream == null) throw new ArgumentNullException("stream");
stream.BytesRead += (o, e) => AddToQueue(e.Buffer);
stream.Closing += (o, e) => sourceIsClosed = true;
}
private void AddToQueue(byte[] buffer)
{
if (buffer.Length == 0)
return;
lock (buffers)
{
buffers.AddLast(buffer);
length += buffer.Length;
}
}
public override int Read(byte[] buffer, int offset, int count)
{
if (buffer == null) throw new ArgumentNullException("buffer");
bool noMoreBuffersAvailable = HasNoMoreBuffersAvailable();
// Guard clause - closed and nothing more to write.
if (noMoreBuffersAvailable && sourceIsClosed)
return 0;
if (noMoreBuffersAvailable)
{
// Not closed yet! Block infinitely until we get closed or have some data.
while (HasNoMoreBuffersAvailable())
{
if (sourceIsClosed)
return 0;
Thread.Sleep(TimeSpan.FromMilliseconds(50));
}
}
byte[] currentBuffer = GetCurrentBuffer();
int numberOfBytesRead = DoRead(buffer, count, currentBuffer, offset);
PutLeftoverBytesAtFrontOfQueue(currentBuffer, numberOfBytesRead);
return numberOfBytesRead;
}
// Check if caller didn't have enough space to fit the buffer.
// Put the remaining bytes at the front of the queue.
private void PutLeftoverBytesAtFrontOfQueue(byte[] currentBuffer, int numberOfBytesRead)
{
if (currentBuffer == null) throw new ArgumentNullException("currentBuffer");
if (numberOfBytesRead == currentBuffer.Length)
return; // Clean read!
var remainingBuffer = new byte[currentBuffer.Length - numberOfBytesRead];
Array.Copy(currentBuffer, numberOfBytesRead, remainingBuffer, 0, remainingBuffer.Length);
lock (buffers)
buffers.AddFirst(remainingBuffer);
}
private int DoRead(byte[] buffer, int count, byte[] currentBuffer, int offset)
{
int maxNumberOfBytesWeCanWrite = Math.Min(count, currentBuffer.Length);
Array.Copy(currentBuffer, 0, buffer, offset, maxNumberOfBytesWeCanWrite);
position += maxNumberOfBytesWeCanWrite;
return maxNumberOfBytesWeCanWrite;
}
private byte[] GetCurrentBuffer()
{
byte[] currentBuffer;
lock (buffers)
{
currentBuffer = buffers.First.Value;
buffers.RemoveFirst();
}
return currentBuffer;
}
private bool HasNoMoreBuffersAvailable()
{
lock (buffers)
return buffers.Count == 0;
}
public override void Flush() { }
public override long Seek(long offset, SeekOrigin origin)
{
throw new InvalidOperationException("Cannot seek in CachingStream.");
}
public override void SetLength(long value)
{
throw new InvalidOperationException("Cannot set length in CachingStream.");
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new InvalidOperationException("Cannot write in a CachingStream.");
}
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return false; }
}
public override long Length
{
get { return length; }
}
public override long Position
{
get { return position; }
set { throw new InvalidOperationException("Cannot set position in CachingStream."); }
}
}

Categories

Resources