Project

General

Profile

Roster Management

Corey Wilson
Added over 5 years ago

I've been trying to add a friend to a roster & send a <pres type="subscribe" but I am receiving a "Not Supported" error, I have read on your Server Features list that Tigase does in fact support RFC-3291 so I am not 100% sure why this is happening. Below is the stanza's sent & received.

//Add to Roster (Call)
<body rid="69177779301" xmlns="http://jabber.org/protocol/httpbind" sid="dc38943a-3c7e-4a30-91a1-bb5e4a28e88f">
  <iq xmlns="jabber:client" type="set">
    <query xmlns="jabber:iq:roster">
      <item jid="friend@localhost" name="My Friend">
        <group>friends</group>
      </item>
    </query>
  </iq>
</body>
//Roster Add (Response - successful)
<body xmlns="http://jabber.org/protocol/httpbind" secure="true" xmlns:xmpp="urn:xmpp:xbosh" xmlns:stream="http://etherx.jabber.org/streams" ack="69177779301" from="localhost" xmpp:version="1.0">
  <iq xmlns="jabber:client" type="set" to="me@localhost/1381435511979079689" id="rsttig6">
    <query xmlns="jabber:iq:roster" ver="ec4856da5e5f02199a88f8a9cd9b789d">
      <item subscription="none" name="My Friend" jid="friend@localhost">
        <group>friends</group>
      </item>
    </query>
  </iq>
  <iq xmlns="jabber:client" type="result" to="me@localhost/1381435511979079689"/>
</body>
//Subscribe to User
<body rid="69177779302" xmlns="http://jabber.org/protocol/httpbind" sid="dc38943a-3c7e-4a30-91a1-bb5e4a28e88f">
  <pres to="friend@localhost" type="subscribe"/>
</body>
//Subscribe (Response - failed)
<body xmlns="http://jabber.org/protocol/httpbind" secure="true" xmlns:xmpp="urn:xmpp:xbosh" xmlns:stream="http://etherx.jabber.org/streams" ack="69177779302" from="localhost" xmpp:version="1.0">
  <pres xmlns="jabber:client" type="error" to="me@localhost/1381435511979079689" from="friend@localhost">
    <error code="501" type="cancel"><feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
      <text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas" xml:lang="en">The feature is not supported yet.</text>
    </error>
  </pres>
</body>

If I try to send the presence with a "from" <presence from="me@localhost" to="friend@localhost" type="subscribe" /> I get an empty response.

Both users exist and I am logged on both accounts trying to pass data back and forth.

Possibly I have to use the Dynamic Roster setup?


Replies (15)

Added by Wojciech Kapcia TigaseTeam over 5 years ago

First of all, if you use pres instead of presence you will get <feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/> as it's not correct stanza. Second of all - which version of Tigase are you using with what configuration options? I've tried suggested scenario with latest revision and it worked without any problem. Dynamic roster should not cause such problems.

Added by Corey Wilson over 5 years ago

That would make sense - sorry I knew I was doing something stupid lol I'm copying code from Strophe that uses $pres and wrote it into PHP as <pres instead of @<presence@.

This worked, sorry about my dumb question :)

Added by Corey Wilson over 5 years ago

I have a new question about the Roster / Subscription requests. I am trying to implement a friend request / confirm procedure essentially the same as any social networking website.

A Sends B a friend Request
B Accepts A's Friend Request
They're Friends.

I'm a little stuck on how I should go about settings up the XMPP Subscriptions to support this type of setup.

Currently (As far as I can tell) You must do this:

A sends B a Subscription Request.
B Accepts A's Subscription Request

B sends A a Subscription Request
A Accepts B's Subscription Request

This adds 2 more steps to the standard process with B accepting A's friend request, now B also has to send ANOTHER request to make it work (as XMPP has it set up).

This is how I have it so far:

*A sends B a Friend Request*
- Add B to Roster, Send B a Subscription

*B accepts A's Friend Request*
- Add A to Roster, Accept A's Subscription Request, Send A a Subscription Request

I have been sitting here trying to figure out now how I can get A to accept *B*s final Subscription request. Through the system there are no more buttons they need to press to finalize the friend request since the friend has already be accepted.

I've been able to get this to work currently by loading a script on each page to receive incoming subscription="to" and responding with a subscribed presence, and also checking to see on the users login for any outstanding subscription requests.

This seems like a recipe for disaster tho - I am wondering if anyone has any recommendations on how to get around this. Maybe there is a way with Tigase to automatically send a subscribed presence if the user already has a subscription to them?

Added by Wojciech Kapcia TigaseTeam over 5 years ago

I think that this may interest you: 3.4.1. Client Generation of Subscription Pre-Approval - basically you send "subscribed" while sending "subscribe". There is a matter of eventually cancelling of pre-approval within some time after not receiving response.

Added by Corey Wilson over 5 years ago

I had tried this before but I can't seem to get it to work. I send both a "Subscribe" and a "Subscribed" initially, but when the (friend) sends "Subscribe" and "Subscribed" I only receive a "From" subscription.

Here are the Stanzas, maybe you can see what I am doing wrong?:

(I am working with: 5.2.0-SNAPSHOT-b3312/d1149826)

    //CALL:
    <body rid="705924250022" xmlns="http://jabber.org/protocol/httpbind" sid="9b271c72-6f16-4f83-8693-1d66c7eb01f6">
        <iq xmlns="jabber:client" type="set">
          <query xmlns="jabber:iq:roster">
                <item jid="friend@localhost" name="Friends Name">
                    <group>friends</group>
                </item>
            </query>
        </iq>
    </body>

    //RESULT: (705924250022) 
    <body xmlns="http://jabber.org/protocol/httpbind" secure="true" xmlns:xmpp="urn:xmpp:xbosh" xmlns:stream="http://etherx.jabber.org/streams" ack="705924250006" from="localhost" xmpp:version="1.0">
        <iq xmlns="jabber:client" type="set" to="me@localhost/13816138651938348194" id="rsttig29">
            <query xmlns="jabber:iq:roster" ver="83488f23f451b248f094a03dfac354d5">
                <item subscription="none" name="Friends Name" jid="friend@localhost">
                    <group>friends</group>
                </item>
            </query>
        </iq>
        <iq xmlns="jabber:client" type="result" to="me@localhost/13816138651938348194" />
    </body>


    //CALL:
    <body rid="705924250023" xmlns="http://jabber.org/protocol/httpbind" sid="9b271c72-6f16-4f83-8693-1d66c7eb01f6">
        <presence from="me@localhost" to="friend@localhost" type="subscribe"/>
    </body>

    //RESULT: (705924250023) 
    <body xmlns="http://jabber.org/protocol/httpbind" secure="true" xmlns:xmpp="urn:xmpp:xbosh" xmlns:stream="http://etherx.jabber.org/streams" ack="705924250007" from="localhost" xmpp:version="1.0">
        <iq xmlns="jabber:client" type="set" to="me@localhost/13816138651938348194" id="rsttig30">
            <query xmlns="jabber:iq:roster" ver="83488f23f451b248f094a03dfac354d5">
                <item subscription="none" ask="subscribe" name="Friends Name" jid="friend@localhost">
                    <group>friends</group>
                </item>
            </query>
        </iq>
    </body>


    //CALL:
    <body rid="705924250024" xmlns="http://jabber.org/protocol/httpbind" sid="9b271c72-6f16-4f83-8693-1d66c7eb01f6">
        <presence from="me@localhost" to="friend@localhost" type="subscribed"/>
    </body>


    //RESULT: (705924250024)
    //Empty
    //CALL:
    <body rid="209191709088" xmlns="http://jabber.org/protocol/httpbind" sid="624018a4-d61e-44dd-bc0d-58eedc56f9d8">
        <iq xmlns="jabber:client" type="set">
          <query xmlns="jabber:iq:roster">
            <item jid="me@localhost" name="My Name">
              <group>friends</group>
            </item>
          </query>
        </iq>
    </body>


    //RESULT: (209191709088) 
    <body xmlns="http://jabber.org/protocol/httpbind" secure="true" xmlns:xmpp="urn:xmpp:xbosh" xmlns:stream="http://etherx.jabber.org/streams" ack="209191709088" from="localhost" xmpp:version="1.0">
        <iq xmlns="jabber:client" type="set" to="friend@localhost/1381614803144667995" id="rsttig33">
            <query xmlns="jabber:iq:roster" ver="081a505a63ea20ff30f27c5bf2c1e152">
                <item subscription="none" name="My Name" jid="me@localhost">
                    <group>friends</group>
                </item>
            </query>
        </iq>
        <iq xmlns="jabber:client" type="result" to="friend@localhost/1381614803144667995"/>
    </body>

    //CALL:
    <body rid="209191709089" xmlns="http://jabber.org/protocol/httpbind" sid="624018a4-d61e-44dd-bc0d-58eedc56f9d8">
        <presence from="friend@localhost" to="me@localhost" type="subscribe" />
    </body>

    //RESULT: (209191709089) 
    <body xmlns="http://jabber.org/protocol/httpbind" secure="true" xmlns:xmpp="urn:xmpp:xbosh" xmlns:stream="http://etherx.jabber.org/streams" ack="209191709089" from="localhost" xmpp:version="1.0">
        <iq xmlns="jabber:client" type="set" to="friend@localhost/1381614803144667995" id="rsttig34">
            <query xmlns="jabber:iq:roster" ver="081a505a63ea20ff30f27c5bf2c1e152">
                <item subscription="none" ask="subscribe" name="My Name" jid="me@localhost">
                    <group>friends</group>
                </item>
            </query>
        </iq>
    </body>

    //CALL:
    <body rid="209191709090" xmlns="http://jabber.org/protocol/httpbind" sid="624018a4-d61e-44dd-bc0d-58eedc56f9d8">
        <presence from="friend@localhost" to="me@localhost" type="subscribed"/>
    </body>


    //RESULT: (209191709090) 
    <body xmlns="http://jabber.org/protocol/httpbind" secure="true" xmlns:xmpp="urn:xmpp:xbosh" xmlns:stream="http://etherx.jabber.org/streams" ack="209191709090" from="localhost" xmpp:version="1.0">
        <iq xmlns="jabber:client" type="set" to="friend@localhost/1381614803144667995" id="rsttig35">
            <query xmlns="jabber:iq:roster" ver="081a505a63ea20ff30f27c5bf2c1e152">
                <item subscription="from" ask="subscribe" name="My Name" jid="me@localhost">
                    <group>friends</group>
                </item>
            </query>
        </iq>
    </body>

I have tried moving the Subscribe & subscribed around (subscribe -> subscribed & Subscribed -> Subscribe), I tried it without the roster, and can't seem to get it to subscribe both ways.

Added by Wojciech Kapcia TigaseTeam over 5 years ago

Appologies, I went ahead of myself with suggestion of using pre-approved request, which is not supported yet. I've created a ticket for it #1590

Added by Corey Wilson over 5 years ago

New Roster question for you:

I have a roster with groups

User A:

  • Group 1

  • Group 2

User B:

  • Group 1

  • Group 3

I have a Messenger with a list of available contacts that I want to separate by the Groups they are in. The question is:

How do I query a roster for a single jid so I can determine what groups they are in, and add them to the according list?

I know I can query the entire roster on login, the roster might change after, and I don't want to reload the entire roster each time a user logs in or updates (i.e. A contact becomes part of a new group after login)

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam over 5 years ago

Querying for a single JID is not possible. The spec does not have such a function.

However, this is not necessary. You get a full roster at login time and if the roster changes in the meantime the server pushes change to the online user. So the client always have an up to date information. Tigase also supports roster versioning so you do not have to load the full roster at the login time. You can just check the version to make sure you have roster up to date.

Added by Corey Wilson over 5 years ago

OK I think I can make it work without this. A somewhat related question:

I have communities within my website that will have a group of users.

I.E.

Group A:

  • User 1

  • User 2

  • User 3

Then lets say User A wants to join Group A.

What are your recommendations to sync the Users (Roster,subscribe) in Group A with User A and vice-versa?

Would it be possible to use something like adhoc to synchronize the roster / subscribe when a user joins a community?

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam over 5 years ago

I have an impression that you are trying to use roster and roster's groups for something which it is not designed for. Roster is really a personal contact list, groups within roster are really a personal grouping of contacts. Do not try to build a community functionality based on this as it will be extremely difficult to maintain a group of people across many rosters.

My suggestion is to look at the PubSub protocol, it seems much better suited for a community and social networks like systems.

Added by Corey Wilson over 5 years ago

The idea behind it is I have my friend(s) list, but also have a friend list of people in the communities I am involved in.

So lets say I have a friend - jid: friend@mysite

So in my roster:

<roster>
 <item jid="friend@mysite" name="My Friend">
  <group>Friends</group>
 </item>
</roster>

And then I join a community Group A that has someone in it - jid: community@mysite that also my friend (jid: friend@mysite) is a part of.

Now my roster would look like:

<roster>
  <item jid="friend@mysite" name="My Friend">
    <group>Friends</group>
    <group>Group A</group>
  </item>
  <item jid="community@mysite" name="Member in my Community">
    <group>Group A</group>
  </item>
</roster>

I will still want presence activity of the members in Group A since they, although not directly on my friends list, are an essential part of my social community.

The point of this website is to encourage people to join different communities and become socially active within it. This means your roster could potentially get quite large

I do plan on using the PubSub for a user feed, so users can post messages and they will be pushed to any people subscribed to them, but I would think this is more of a roster setup?

Is there another way I should go about this? Or maybe this is just a bad idea in general?

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam over 5 years ago

To be honest, it all depends on the details, what exactly you want to achieve and how you plan to implement it.

What I am specifically worried about is scenario like this:

  1. Let's say, your installation have 1 million users registered in total

  2. You have a community Group A and you have 100 users in the community

  3. Now, you want to add a new user to the community Group A

  4. In order to add a new user you have to go through the entire database of 1 million users to find 100 users who have Group A in their roster and add the new member of the community

  5. I think you can see that this will be very expensive in terms of computing resources and slow action...

Another scenario which also worries me is:

  1. Again, you have installation with 1 million users registered in total

  2. You have several communities:

    1. Group A with 1,000 members
    2. Group B with 100 members
    3. Group C with 10,000 members
    4. Group D with 5,000 members
    5. Group E with 100,000 members
  3. Now a user wants to be in all of these communities

  4. How do you plan to handle his roster? I mean, even simple loading user's roster over the network will be an expensive and long operation.

  5. Also, think of how much traffic this user will generate on your system when he changes his presence status - 116,100 presence packets sent in one go

  6. And now, think of a case if you have many users who are in many large communities.

  7. Your installation will be killed by the presence traffic

Of course I can think of a workarounds for both above cases which could solve these problems, more or less. I just want to me sure you are aware of implications of your approach.

On the other hand, communities based on PubSub are much more elegant. The first problem automatically goes away, you update the community group in one place only - PubSub node.

The second goes away by definition because PubSub, by default does not send presence notification about node members. Of course you said you want them and it is possible to customize PubSub to do it and I think we even have such an extension to PubSub. But then the presence high load problem can be also solved in PubSub to control the traffic and prioritize to whom presences are sent first and limit traffic somehow.

Also, you want to show to the user a list of his contacts and community members. But this is just a matter to write a client software which loads user normal roster and also loads members from community groups and displays them as a list of people in different groups.

Added by Corey Wilson over 5 years ago

That makes perfect sense. To be honest, I haven't fully dived in to PubSub yet.

One quick thought that comes to mind is a user has to be authorized (in some cases) before they can subscribe to a group. Is there a similar roster request / accept to a pubsub node? I'll probably have to read up on it a bit more.

I'm interested in this extension you mentioned about PubSub providing subscribers presence. Is this documented in XMPP or a custom Tigase feature?

Thank you for all your help :)

Avatar?id=6023&size=32x32

Added by Artur Hefczyc TigaseTeam over 5 years ago

This is our custom extension and a very recent one, hence it is not documented yet. But for now you can assume that such a possibility exists.

As for the PubSub, it does have a broad access permission parameters and you can configure each node separately. I think it should give you enough flexibility.

Avatar?id=6098&size=32x32

Added by Bartosz Malkowski TigaseTeam over 5 years ago

Documentation to extension PubSub Node Presence Extension

    (1-15/15)