src/HarmonyHub/Client.cs
/// <summary>
/// Listens for incoming XML stanzas and raises the appropriate events.
/// </summary>
/// <remarks>This runs in the context of a separate thread. In case of an
/// exception, the Error event is raised and the thread is shutdown.</remarks>
Listens for incoming XML stanzas and raises the appropriate events.
Listens for incoming XML stanzas and raises the appropriate events .
private void ReadXmlStream()
        {
            try
            {
                while (_parser != null && !_cancellationTokenSource.Token.IsCancellationRequested)
                {
                    XmlElement elem = _parser.NextElement("iq", "message", "presence");
                    MessageReceived?.Invoke(this, new MessageReceivedEventArgs(elem.OuterXml));
                    if (elem.Name == "iq" && elem.HasChildNodes)
                    {
                        var messageId = elem.Attributes["id"].Value;
                        if (messageId != null && _resultTaskCompletionSources.TryGetValue(messageId, out TaskCompletionSource<XmlElement> resultTaskCompletionSource))
                        {
                            var oaNode = elem.FirstChild;
                            if (oaNode != null && oaNode.Name == "oa")
                            {
                                switch (oaNode.Attributes["errorcode"].Value)
                                {
                                    case "200":
                                        resultTaskCompletionSource.TrySetResult(elem);
                                        _resultTaskCompletionSources.Remove(messageId);
                                        break;
                                    case "100":
                                        break;
                                    default:
                                        var errorMessage = oaNode.Attributes["errorstring"].Value;
                                        resultTaskCompletionSource.TrySetException(new Exception(errorMessage));
                                        _resultTaskCompletionSources.Remove(messageId);
                                        break;
                                }
                            }
                        }
                    }
                    else if (elem.Name == "message" && elem.HasChildNodes)
                    {
                        var eventNode = elem.FirstChild;
                        if (eventNode != null && eventNode.Name == "event" && eventNode.Attributes["type"] != null)
                        {
                            switch (eventNode.Attributes["type"].Value)
                            {
                                case HarmonyEventTypes.StartActivityFinished:
                                    var messageParams = eventNode.InnerText.ToParamDictionary();
                                    int activityId;
                                    if (int.TryParse(messageParams["activityId"], out activityId))
                                    {
                                        CurrentActivityUpdated?.Invoke(this, new ActivityUpdatedEventArgs(activityId));
                                    }
                                    break;
                                case HarmonyEventTypes.StateDigest:
                                    break;
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                if (e is IOException)
                {
                    Authenticated = false;
                    Connected = false;
                }
                if (!_disposed)
                {
                    Error?.Invoke(this, new ErrorEventArgs(e));
                }
            }
        }
private void ReadXmlStream ( ) { try { while ( _parser != null && ! _cancellationTokenSource . Token . IsCancellationRequested ) { XmlElement elem = _parser . NextElement ( " " , " " , " " ) ; MessageReceived ? . Invoke ( this , new MessageReceivedEventArgs ( elem . OuterXml ) ) ; if ( elem . Name == " " && elem . HasChildNodes ) { var messageId = elem . Attributes [ " " ] . Value ; if ( messageId != null && _resultTaskCompletionSources . TryGetValue ( messageId , out TaskCompletionSource < XmlElement > resultTaskCompletionSource ) ) { var oaNode = elem . FirstChild ; if ( oaNode != null && oaNode . Name == " " ) { switch ( oaNode . Attributes [ " " ] . Value ) { case " " : resultTaskCompletionSource . TrySetResult ( elem ) ; _resultTaskCompletionSources . Remove ( messageId ) ; break ; case " " : break ; default : var errorMessage = oaNode . Attributes [ " " ] . Value ; resultTaskCompletionSource . TrySetException ( new Exception ( errorMessage ) ) ; _resultTaskCompletionSources . Remove ( messageId ) ; break ; } } } } else if ( elem . Name == " " && elem . HasChildNodes ) { var eventNode = elem . FirstChild ; if ( eventNode != null && eventNode . Name == " " && eventNode . Attributes [ " " ] != null ) { switch ( eventNode . Attributes [ " " ] . Value ) { case HarmonyEventTypes . StartActivityFinished : var messageParams = eventNode . InnerText . ToParamDictionary ( ) ; int activityId ; if ( int . TryParse ( messageParams [ " " ] , out activityId ) ) { CurrentActivityUpdated ? . Invoke ( this , new ActivityUpdatedEventArgs ( activityId ) ) ; } break ; case HarmonyEventTypes . StateDigest : break ; } } } } } catch ( Exception e ) { if ( e is IOException ) { Authenticated = false ; Connected = false ; } if ( ! _disposed ) { Error ? . Invoke ( this , new ErrorEventArgs ( e ) ) ; } } }
Listens for incoming XML stanzas and raises the appropriate events.
Listens for incoming XML stanzas and raises the appropriate events .
// Ignore continuation messages // Find the activityId // TODO: What to do with this? // It seems that these are purely informational, currently comments out to avoid the serialization hit // but left in, for the case that this becomes useful later on // var notify = JsonSerializer<HarmonyNotify>.Deserialize(eventNode.InnerText); // Stream has dropped, this happens naturally on Dispose // An exception outside of Dispose should be raised to the caller to handle
remarks
This runs in the context of a separate thread. In case of an
exception, the Error event is raised and the thread is shutdown.
This runs in the context of a separate thread . In case of an exception the Error event is raised and the thread is shutdown .