XMPP BOSH strange behaviour in "meet.jit.si" but not in other jitsi servers

I am writing a proof of concept client for jitsi. The first step is to join XMPP. Trying with other community-run jitsi instances, my code seems to run fine, but when trying on “meet.jit.si”, I see this strange behaviour:

  1. Most of the time, when trying to authenticate ANONYMOUS, BOSH gives this error:

     <body condition='item-not-found' type='terminate' xmlns='http://jabber.org/protocol/httpbind'/>
    

Interestingly, trying a few times, with no changes at all, it succeeds with:

<body sid='d4ee2c37-fb0b-4e19-b909-20f82b3d0231' xmlns='http://jabber.org/protocol/httpbind' xmlns:stream='http://etherx.jabber.org/streams'><success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/></body>

There are no changes between requests. Most of the time, I get the error, but from time to time, it succeeds.

  1. When anonymous authentication is successful, next step fails always.

I send this, as documented in XEP-0206: XMPP Over BOSH :

<body rid='2068214881' sid='d4ee2c37-fb0b-4e19-b909-20f82b3d0231' to='meet.jit.si' xmpp:restart='true' xmlns:xmpp='urn:xmpp:xbosh' xml:lang='en' xmlns='http://jabber.org/protocol/httpbind'/>

But I always get an error:

<body condition='item-not-found' type='terminate' xmlns='http://jabber.org/protocol/httpbind'/>

Interestingly, trying the same code in other jitsi (community run) instances, my code works just fine: it connects to XMPP fine.

What am I missing?

Source code:

#!/usr/bin/env python3

import xml.etree.ElementTree as ET
import random

import requests
session = requests.Session()

server = 'meet.guifi.net'
bosh = 'https://meet.guifi.net/http-bind'

server = 'calls.disroot.org'
bosh = 'https://calls.disroot.org/http-bind'

server = 'jitsi.komun.org'
bosh = 'https://jitsi.komun.org/http-bind'

server = 'meet.jit.si'
bosh = 'https://meet.jit.si/http-bind'

def send(req):
    global rid
    rid += 1
    print(">", req)
    a = session.post(bosh, data=req)

    print(a.text)
    root = ET.fromstring(a.text)
    print(root.attrib)
    return root

jid = f'jcea{random.randrange(2**10)}@{server}'
rid = random.randrange(2**32)  # Futuros incrementos no deberían superar 2^53-1
req = ("<body "
       f"content='text/xml; charset=utf-8' from='{jid}' hold='1' "
       f"rid='{rid}' to='{server}' ver='1.6' wait='60' "
       "xmpp:version='1.0' xmlns:xmpp='urn:xmpp:xbosh' "
       "xml:lang='en' xmlns='http://jabber.org/protocol/httpbind'/>")

root = send(req)
sid = root.attrib['sid']

req = ("<body "
       f"rid='{rid}' sid='{sid}' "
       "xmlns='http://jabber.org/protocol/httpbind'>"
       "<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='ANONYMOUS'/>"
       "</body>")
send(req)

req = ("<body "
       f"rid='{rid}' sid='{sid}' to='{server}' "
       "xmpp:restart='true' xmlns:xmpp='urn:xmpp:xbosh' "
       "xml:lang='en' xmlns='http://jabber.org/protocol/httpbind'/>")
send(req)

req = ("<body "
       f"rid='{rid}' sid='{sid}' "
       "xmlns='http://jabber.org/protocol/httpbind'>"
       "<iq id='bind_0' type='set' xmlns='jabber:client'>"
       "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>"
       "<resource>JCEAJCEA</resource>"
       "</bind></iq></body>")
send(req)

for x in range(1):
    req = ("<body "
           f"rid='{rid}' sid='{sid}' "
           "xmlns='http://jabber.org/protocol/httpbind'/>")
    send(req)

Check how the web client is using it. You are missing the room parameter and you are moving between shards and item-not-found is normal in this case.
Check out the http://jitsi.org/meet-jit-si-terms-of-service/ for using meet.jit.si.

Hummm… I didn’t wrote the code to join a room yet because I am trying to login first :wink:

The sharding issue suggestion is interesting. I guess you are saying that “meet.jit.si” are actually several servers and that I could be connecting to a different server for each request. That is a good point I didn’t consider. I though that the Session ID (sid) would be enough to keep the “session” sticky somewhere in the backend. This is not the case, apparently.

The question now is… How can I be sure I am connecting to the same backend server?

The advice of studying the web client code is good but unworkable. How many thousand of lines of code is that?

I am aware of the terms of service and I obey them in the letter and in the spirit.

My plan is to write a jitsi participant able to join a room and record the audio of each participant in A SEPARATE AUDIO FILE. Podcasting recording, noise suppression, etc.

We do not advice to use custom client, you should use at least the lib-jitsi-meet version coming from the deployment. As backend changes, we may drop tomorrow xmpp or change the protocol in some other way.

The code base is big, that’s why there is the low level API such as lib-jitsi-meet. And in the web you have network tab you can be looking at …

This case is already implemented and is called localrecording and its main usecase is podcast, to ensure maximum quality the recording is done everywhere locally.

I am aware of the risk.

Checking the network tab, apparently, current meet.jit.si is using a websocket, not BOSH. That would solve the session sharding, because the websocket connection is persistent.

Oh, that is cool, but I can not use it as is because:

  1. I would need a jitsi instance that activates such a thing. Apparently meet.jit.si, my primary jitsi server, doesn’t.

  2. I have an open talk show. No fixed members, anyone can join anytime. If somebody forgets to enable this in their browser… bad luck!.

  3. There are people like myself that join the talk show via the smartphone app. No recording there.

I will check “lib-meet-jitsi” and will try websocket too. Checking around, some other jitsi instances have BOSH but no websocket enabled, so it seems I need to implement both.

Any advice welcomed