PeterWaher / IoTGateway

New project
Other
227 stars 77 forks source link

XMPP BOSH HttpBinding fails on CreateSession ("Response acknowledgement invalid.") #14

Open andfussel opened 3 years ago

andfussel commented 3 years ago

hi sorry if i am wrong here... i'm new to github.

i try to create a windows-client app to connect with cisco finesse. its noti system is based on XMPP/BOSH. when i try to use the XmppClient with XmppCredentials including UriEndpoint it always ends up with a exception while connecting (in OnConnectionError-handler): "Response acknowledgement invalid."

i've had a closer look at https://github.com/PeterWaher/IoTGateway/blob/master/Networking/Waher.Networking.XMPP.BOSH/HttpBinding.cs: in CreateSession() when building the XML-body the rid is calculated like this: Xml.Append((this.rid++).ToString()); this will result in first reading rid and writing it to xml and then rid will be count up. so the local rid will be one bigger than the rid in xml-body. after responding th "ack"-flag is checked;

case "ack":
    if (!long.TryParse(Attr.Value, out long l) ||
        l != this.rid)
    {
        throw new Exception("Response acknowledgement invalid.");
    }

and its of cause not equal to rid :(

not sure if i am missing some thing, or its simply a typo (should be ++rid)

don't grill me if i completely misunderstood your code or XMPP/BOSH

PeterWaher commented 3 years ago

Hello andfussel.

Thanks for reaching out, and taking your time to troubleshoot this problem. Could you provide me with a connection URL, and test credentials to the broker you wish to connect to? You can do so over mail (peterwaher [at] hotmail.com), XMPP (peter [at] waher.se), or my feedback page (https://waher.se/Feedback.md)

Best regards, Peter

andfussel commented 3 years ago

hi peter

sorry, can't provide you any url. there is no way to access my environment from public. if you have a login to cisco devnet, maybe you could try to test it with their sandbox-environment: https://developer.cisco.com/docs/finesse/#!sandbox/finesse-sandbox (Packaged Contact Center Enterprise 12.5 or Unified Contact Center Express 12.5) docs to the APIs can be found their: https://developer.cisco.com/docs/finesse/#!finesse-overview and for my case the more interesting part: https://developer.cisco.com/docs/finesse/#!managing-notifications-in-third-party-applications/

my current code looks like this:

        sniffer = new InMemorySniffer();
        var cred = new XmppCredentials()
        {
                Account = [login],
                Password = "********",
                Host = [xmppDomain],
                UriEndpoint = $"https://[finesse-host]:7443/http-bind/",
                Port = 5223
        };

        var appAssembly = Assembly.GetExecutingAssembly();
        Waher.Runtime.Inventory.Types.Initialize(new[] { Assembly.GetAssembly(typeof(BOSH.HttpBinding)) });

        xmppClient = new XmppClient(cred, "en-US", appAssembly, new ISniffer[] { sniffer });
        xmppClient.OnConnectionError += XmppClient_OnConnectionError;
        xmppClient.Connect([xmppPubSubDomain]);

unfortunately that is the closest to my environment i could offer you.

meanwhile i downloaded the IoTGateway solution and changed the code of Waher.Networking.XMPP.BOSH.HttpBinding.CreateSession() on line 249 from

Xml.Append((this.rid++).ToString());

to

Xml.Append((++this.rid).ToString());

same for SendAsync line 560: Rid = this.rid++; to Rid = ++this.rid; still getting a error BUT now i receive a 401 unauthorized. this may be a issue with my server configuration or test client data.

i'm new to BOSH. tell me if i'm wrong: on server-side the rid from request is used to set the ack-flag in response, so each response belongs to the matching client-side rid? if so... the client-side rid will never match to any response cause the rid is changed after the request was generated and before the request was posted.

    long rid = 1;
    var request = (rid++).ToString();
    // now building XML, post it to the server, receive the response including the ack flag end parse it to long
    var ack = request; // if response ack-flag corresponds to rid of request
    if (long.TryParse(ack, out long response))
    {
        Console.WriteLine($"{response}");
        Console.WriteLine($"{rid}");
        Console.WriteLine($"{response == rid}");
    }

output will be

1
2
False