Trouble Creating Xmpp Muc Room: Code 503 (Service Unavailable)

MUC How-to with XMPPFramework

Below is how I got my own problem solved. Note that this solution does not involve XMPPRoom at all. First, I created a method that, depending on the situation, either creates or enters a room. (Per XMPP documentation, the XML request for creating is the same is the same as the one you would send to enter a room; that is, if the room has does not exist yet when you enter it, the service will create it for you.)

Here we go. This is the method that creates/enters a room. What this method does is send a presence to the room which you intend to create/enter. If you are the first to enter a room and the room has not been created yet, you automatically become its owner and moderator.

- (void)createOrEnterRoom:(NSString *)roomName
{
//here we enter a room, or if the room does not yet exist, this method creates it
//per XMPP documentation: "If the room does not yet exist, the service SHOULD create the room"
//this method accepts an argument which is what you would baptize the room you wish created
NSXMLElement *presence = [NSXMLElement elementWithName:@"presence"];
NSString *room = [roomName stringByAppendingString:@"@conference.jabber.com/iMac"];
[presence addAttributeWithName:@"to" stringValue:room];
NSXMLElement *x = [NSXMLElement elementWithName:@"x" xmlns:@"http://jabber.org/protocol/muc"];
NSXMLElement *history = [NSXMLElement elementWithName:@"history"];
[history addAttributeWithName:@"maxstanzas" stringValue:@"50"];
[x addChild:history];
[presence addChild:x];
[[self xmppStream] sendElement:presence];
}

Next, in the AppDelegate where XMPPStream methods are declared we filter the XML response we receive in the didReceivePresence method by checking the status code sent by the server. If the status code is 201, bingo! The room creation went just fine. Status codes other than 201 mean different things, but let's focus on 201 for our purpose.

- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence
{
NSXMLElement *x = [presence elementForName:@"x" xmlns:@"http://jabber.org/protocol/muc#user"];
for (NSXMLElement *status in [x elementsForName:@"status"])
{
switch ([status attributeIntValueForName:@"code"])
{
case 201: [self notifyRoomCreationOk:room];
}
}
}

Then, we tell the server that what we are creating a room of the type "instant," which means that we will send an IQ element telling it room defaults. notifyRoomCreationOk is a delegate method called in a different view when the room creation succeeds, after all I have to record the room in a text file to make it persistent so that the next time I open the app the room I created before will be visible. In my notifyRoomCreationOk method, I have sendDefaultRoomConfig which, basically, describes what is stated in the first sentence of this paragraph.

-(void)sendDefaultRoomConfig:(NSString *)room
{
NSXMLElement *x = [NSXMLElement elementWithName:@"x" xmlns:@"jabber:x:data"];
[x addAttributeWithName:@"type" stringValue:@"submit"];
NSXMLElement *query = [NSXMLElement elementWithName:@"query" xmlns:@"http://jabber.org/protocol/muc#owner"];
[query addChild:x];
XMPPIQ *iq = [XMPPIQ iq];
[iq addAttributeWithName:@"id" stringValue:[NSString stringWithFormat:@"inroom-cr%@", room]];
[iq addAttributeWithName:@"to" stringValue:room];
[iq addAttributeWithName:@"type" stringValue:@"set"];
[iq addChild:query];
[[self xmppStream ] sendElement:iq];
}

Make sure that you have XMPPStream enabled on the views that call the above methods, otherwise, these won't work. That's all there is to it. Have fun XMPP-ing!

XMPPFramework - Create an XMPPRoom

Did you add <XMPPRoomDelegate> protocol in the .h file of the view controller in which you want to monitor XMPPRoom's delegates?

It should be something like this: @interface YourViewController : UIViewController <..., XMPPRoomDelegate>.

Of course #import "XMPPRoom.h" should be also in .h file of the mentioned view controller.

ADDITION:

You have to setup XMPPStream object, connect to your 'chat' server (in most cases Jabber server) with XMPPJID, then listen for server response, then authentificate with the password and then to start with XMPPRoom creation if everything mentioned from above goes well.

Example:

- (void)setupStream
{
NSAssert(xmppStream == nil, @"Method setupStream invoked multiple times");
xmppStream = [[XMPPStream alloc] init];

[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
}

Then to connect to server:

[self setupStream];

NSString *myJID = @"...";

[xmppStream setMyJID:[XMPPJID jidWithString:myJID]];

NSError *error2;
if ([xmppStream connect:&error2])
{
NSLog(@"Connected to XMPP.");
}
else
{
NSLog(@"Error connecting to XMPP: %@", [error2 localizedDescription]);
}

Listen for server response (do not forget to add <XMPPStreamDelegate> in .h file):

- (void)xmppStreamDidConnect:(XMPPStream *)sender
{
NSError *error;
if ([[self xmppStream] authenticateWithPassword:password error:&error])
{
NSLog(@"Authentificated to XMPP.");
}
else
{
NSLog(@"Error authentificating to XMPP: %@", [error localizedDescription]);
}
}

Listen for server response for authentification status:

- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
NSLog(@"%s", __FUNCTION__);
XMPPPresence *presence = [XMPPPresence presenceWithType:@"available"];
[sender sendElement:presence];
}

and then try to create XMPPRoom by calling function after authentification success:

- (void)createChatRoom
{
// Configure xmppRoom
XMPPJID *roomJID = [XMPPJID jidWithString:@"TestRoom@conference.testservice.com"];

XMPPRoomMemoryStorage *roomMemoryStorage = [[XMPPRoomMemoryStorage alloc] init];

XMPPRoom *xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:roomMemoryStorage
jid:roomJID
dispatchQueue:dispatch_get_main_queue()];

[xmppRoom activate:self.xmppStream];
[xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xmppRoom joinRoomUsingNickname:user history:nil];
}

Unable to send messages to a MUC room

You have configured this, and this is completely wrong:

hosts:
- chat.example.com
- conference.chat.example.com

modules:
mod_muc:
...

I guess you didn't notice the option HOSTS in the MOD_MUC documentation: https://docs.ejabberd.im/admin/configuration/modules/#mod-muc

Try something like this:

hosts:
- chat.example.com

modules:
mod_muc:
hosts:
- conference.@HOST@
...


Related Topics



Leave a reply



Submit