6

I'm trying to implement a XMPP client for UWP in C# and to achieve this I'm using StreamSocket for TCP connection.

The problem is that for handshake and SASL auth I need a sequence of "writing and reading" from the client by the server and without a delay I can't read all data sent by server; I want to remove the delay part.

This is my code:

// Start handshake
await XmppWrite("<?xml version='1.0'?><stream:stream to='" + serverHostName.Domain + "' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>");
var responseStream = await XmppRead();

SaslPlain saslPlain = new SaslPlain(Username, Password);
responseStream = null;
String xml = null;
while (!saslPlain.IsCompleted && (xml = saslPlain.GetNextXml(responseStream)) != null)
{
    await XmppWrite(xml);
    responseStream = await XmppRead();
}
if (!saslPlain.IsSuccess) return;

// Request bind
await XmppWrite("<?xml version='1.0'?><stream:stream to='" + serverHostName.Domain + "' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>");
responseStream = await XmppRead();

// Bind
await XmppWrite("<iq id='" + GenerateId() + "' type='set'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/></iq>");
responseStream = await XmppRead();
if (responseStream.Jid == null) return;

Jid = responseStream.Jid;

// Open session
await XmppWrite("<iq id='" + GenerateId() + "' type='set'><session xmlns='urn:ietf:params:xml:ns:xmpp-session'/></iq>");
responseStream = await XmppRead();

The XmppRead() method is this:

private async Task<XmppStream> XmppRead()
{
    await Task.Delay(100); // Things don't works without this...
    var x = await dataReader.LoadAsync(BUFFER_SIZE);
    if (dataReader.UnconsumedBufferLength > 0)
    {
        Debug.WriteLine(x + ", " + dataReader.UnconsumedBufferLength);
        var stream = new XmppStream(dataReader.ReadString(dataReader.UnconsumedBufferLength));
        if (stream.IsError)
        {
            if (Error != null)
            {
                Error(this, new XmppClientEventArgs(stream));
            }
            throw new Exception(stream.Error);
        }
        return stream;
    }
    return new XmppStream();
}

So, I think the problem is that i try to read before the server has finished to send all its data, so I can read only a partial message. How can i check if there are some other data without block?

Thanks.

StepUp
  • 36,391
  • 15
  • 88
  • 148
blow
  • 12,811
  • 24
  • 75
  • 112

1 Answers1

0

(I was searching for something else and saw this question)

What happens when you set the DataReader.InputOptions to Partial? Right now the LoadAsync (AFAICT) won't return it's got all BUFFER_SIZE bytes. By setting the input stream options to partial, you'll get whatever is available.

DataReader docs are here and InputStreamOptions value are here

PESMITH_MSFT
  • 350
  • 1
  • 9