Can't get message delivery receipt in XMPP - ios

I am new to XMPP. I'm using XMPP and Open fire server for my chat app. The application is working but now I want to get message delivery receipt. I'm using the following code for that,
in setupStream:
xmppMessageDeliveryRecipts = [[XMPPMessageDeliveryReceipts alloc] initWithDispatchQueue:dispatch_get_main_queue()];
xmppMessageDeliveryRecipts.autoSendMessageDeliveryReceipts = YES;
xmppMessageDeliveryRecipts.autoSendMessageDeliveryRequests = YES;
[xmppMessageDeliveryRecipts activate:xmppStream];
And in sendMessage:
NSString *messageID=[xmppStream generateUUID];
NSXMLElement *message = [NSXMLElement elementWithName:#"message"];
[message addAttributeWithName:#"type" stringValue:#"chat"];
[message addAttributeWithName:#"id" stringValue:messageID];
[message addAttributeWithName:#"to" stringValue:myJID];
[message addChild:body];
But i can't get message delivery receipt. How can I get it? Anybody knows?

You are already receiving delivery receipt responses, but XMPPMessageDeliveryReceipts module does not handle it automatically. You need to store all incoming and outgoing messages (check XMPPMessageArchiving module, it can save messages in the XMPPMessageArchiving_CoreDataStorage instance), check if message hasReceiptResponse (defined in XMPPMessage+XEP_0184 category), find the message id in the receipt response and mark corresponding message as "delivered" in the message storage (you may need to add new property e.g. "delivered" to XMPPMessageArchivingCoreDataObject if you will use this module, or make your own storage mechanism)

Related

XMPP remote server connection issue iOS

I am working on a chat application where I set my xmppHostName- 'myserver' and server port -5222. First I created a user on xmpp through my application and it got registered on xmpp but there was an authentication error (although my user id and password were both same). Then I solved this authentication issue by using following method-
NSError *authenticateError = nil;
XMPPPlainAuthentication *plainAuth = [[XMPPPlainAuthentication alloc] initWithStream:self.xmppStream password:password];
if (![_xmppStream authenticate:plainAuth error:&authenticateError]) {
NSLog(#"Authentication errorrrr: %#", authenticateError.localizedDescription);
}
and the authentication error is gone, and my user is online but when I try to send any messages, the server replies with an error through otherserver:
<message xmlns="jabber:client" id="ACC2AAA6-42CE-4590-95A0-C4B28BE9BF04" to="97#otherserver/4ywme5xjh0" from="62#myserver" type="error"><error code="404" type="cancel"><remote-server-not-found xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error></message>
where, 97 is my user id and 62 is front users id. Below is my code for sending xmpp message:
NSXMLElement *body = [NSXMLElement elementWithName:#"body"];
[body setStringValue:messageBody];
NSXMLElement *subject = [NSXMLElement elementWithName:#"subject"];
[subject setStringValue:subjectName];
[message addAttributeWithName:#"to" stringValue:[user stringByAppendingString:myserver]];
[message addChild:body];
[message addChild:subject];
[self.xmppStream sendElement:message];
Here, 'myserver' is my server's hostname and the server replies from another server 'otherserver'. I am sure that I am not setting this 'otherserver' anywhere in my application, then how is this possible that it replies through it?

Xmpp MultiUserChat (MUC) Group Does not remain stable

I created an Xmpp Chat App where I have implemented the one-to-one and group chat.
The Chat itself is working fine.
The issue is in Group chat. I created a group with 2-3 members, again the chat is working fine, but when I kill the application and restart it, I'm not getting the group messsages from any of the groups I have created.
while I am connected to the XMPP Server and re-join any group then I get the messages.
My problem is that I have to join into groups again every time after I kill the app completly.
Please let me know How I can get the messages or join automatically in group when i open the application from killed state.
You need to send presence to XMPP server once your application launched or come out from background. so the XMPP server understand that respective group is ready to handle event.
Edit : you can send presence using following code.
- (void)goOnline {
NSXMLElement *presence = [NSXMLElement elementWithName:#"presence"];
NSXMLElement *show = [NSXMLElement elementWithName:#"show"
stringValue:#"dnd"];
NSXMLElement *status = [NSXMLElement elementWithName:#"status" stringValue:#"available"];
NSXMLElement *priority = [NSXMLElement elementWithName:#"priority" stringValue:#"24"];
[presence addChild:show];
[presence addChild:status];
[presence addChild:priority];
[_xmppStream sendElement:presence];
[self createOrJoinRoom];
}
- (void)createOrJoinRoom {
if ([appDelegate.xmppStream isConnected]) {
NSString *myJID = [[NSUserDefaults standardUserDefaults] stringForKey:#"XMPPUserId"];
NSXMLElement *presence = [NSXMLElement elementWithName:#"presence"];
[presence addAttributeWithName:#"from" stringValue:[[appDelegate.xmppStream myJID]full]];
[presence addAttributeWithName:#"to" stringValue:[NSString stringWithFormat:#"%##%#/%#", #"newone", GroupChatRoomName,myJID]];
NSXMLElement *xelement = [NSXMLElement elementWithName:#"x" xmlns:XMPPMUCNamespace];
[presence addChild:xelement];
[appDelegate.xmppStream sendElement:presence];
}
}
May this help you.
You have to join all your previous join/connected groups. Because in iOS if you kill your app then you left from your created or joined groups.
So every time in this section of the code
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
you have to join your group again.
Below is demo code for it :
XMPPRoomHybridStorage *xmppRoomStorage1 = [XMPPRoomHybridStorage sharedInstance];
xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:xmppRoomStorage1 jid:RoomName];
[xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xmppRoom activate:appDelegate.Obj_xmppManager.xmppStream];
NSXMLElement *history = [NSXMLElement elementWithName:#"history"];
[history addAttributeWithName:#"maxstanzas" stringValue:#"1"];
[xmppRoom joinRoomUsingNickname:self.xmppStream.myJID.user history:nil];
Adding to the Presence answer, I would also check more basic things -
Are the rooms (group chat) you create persistant?
or do you have to create the room again every time you connect?
(notice the difference between 'openning' and 'creating').
On some servers, rooms are temporary by default - you can check this by connecting with 2 seperate clients, send some messages, disconnect only one of them, and reconnect - if you do see the messages that were sent in your reconnected client - this might be your issue, can you show the parameters you pass to the server when you create the room?.
Is the server you are using configured to send history messages by default, and if so how many, again, server implementations may vary, could you share some information on the server you are using (openfire, ejabbered, prosody)? or a snippet from you configuration file?
Is it possible you are getting the messages, but not showing them correctly, maybe not refreshing the screen\view when first entering a room? any log messages?
I am also facing this issue since a week and looking for solution and after a lot of search on google and stack overflow i got a clue which solve this issue.
In my case group created successfully and chat is working good with members and members can send me chat too but when any member of group logout or kill the app and then login again he is unable to send message is this group and group says in response Only occupants are allowed to send messages to the conference.
In my case when user tap on group to go into group and start chat i call this method to join group.
NSString *roomJID = [NSString stringWithFormat:#"%##conference.yourHostName", roomJid];
XMPPJID *jid = [XMPPJID jidWithString:roomJID];
_xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:xmppRoomCoreDataStorage jid:jid dispatchQueue:dispatch_get_main_queue()];
[_xmppRoom activate:stream];
[_xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
[_xmppRoom joinRoomUsingNickname:stream.myJID.bare history:nil];
Hope this will work for you too
By default a MUCRoom will send some history to newly joined user, the number is determined by config, under mod_muc: history_size:.
Or you need to explicitly request for some amount of history while sending the Presence, doc:
<presence
from='hag66#shakespeare.lit/pda'
id='n13mt3l'
to='coven#chat.shakespeare.lit/thirdwitch'>
<x xmlns='http://jabber.org/protocol/muc'>
<history maxstanzas='20'/>
</x>
</presence>

XMPPStreamManagement in iOS unable to send/receive acknowledgement and stanza id

I am able to send messages to users which means i have a working and authenticated xmppStream.
But i am unable to send and receive acknowledgement from server. I want to know which message was received successfully by the server. I googled and found that XEP-0198 should be implemented for this. I am using ejabberd as XMPP server and it supports XEP-0198.
I tried that but i don't know if i am doing it right or not.
First of all i included the header file and added XMPPStreamManagementDelegate.
#import "XMPPStreamManagement.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate,XMPPStreamManagementDelegate>
In the implementation file, here's how i have defined the stream.
XMPPStream *xmppS = [[XMPPStream alloc] init];
[xmppS addDelegate:self delegateQueue:dispatch_get_main_queue()];
XMPPStreamManagement *xsm = [[XMPPStreamManagement alloc] init];
[xsm addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xsm activate:xmppS];
After that i connect with the server. After the connection is successful, i send an enable stanza.
NSXMLElement *enable = [NSXMLElement elementWithName:#"enable" xmlns:#"urn:xmpp:sm:3"];
[xsm.xmppStream sendElement:enable];
Then i send a message
NSXMLElement *a = [NSXMLElement elementWithName:#"request" xmlns:#"urn:xmpp:receipts"];
XMPPElement *e = [[XMPPElement alloc] initWithName:#"message"];
[e addAttributeWithName:#"id" stringValue:#"123456"];
[e addAttributeWithName:#"type" stringValue:#"chat"];
[e addAttributeWithName:#"to" stringValue:#"testuser#myxmppserver.com"];
[e addAttributeWithName:#"from" stringValue:#"testuser2#myxmppserver.com"];
[e addChild:a];
[xsm.xmppStream sendElement:e];
Test User receives the message and Test User 2 gets the received stanza.
<received xmlns="urn:xmpp:receipts" id="123456"/>
My problem is if i send the following stanza, i receive no message.
NSXMLElement *r = [NSXMLElement elementWithName:#"r"];
[xsm.xmppStream sendElement:r];
I have implemented the following function
-(void)xmppStreamManagementDidRequestAck:(XMPPStreamManagement *)sender
{
NSLog(#"ACK");
}
But still nothing gets printed.
Please help. Also, how can i know when the server has received the sent message.
Let me know if anyone wants to know any other part of code from my side.
You can use the functions in xmppStreamManagement for sending the request and get received id:
[xmppStreamManagement requestAck];
and
- (void)xmppStreamManagement:(XMPPStreamManagement *)sender wasEnabled:(NSXMLElement *)enabled
- (void)xmppStreamManagement:(XMPPStreamManagement *)sender didReceiveAckForStanzaIds:(NSArray *)stanzaIds
make sure the stream management is enabled by:
[self.xmppStreamManagement enableStreamManagementWithResumption:YES maxTimeout:0];

Proper way to uniquely identify a message sent via XMPP in delegate method?

I am writing an iOS chat application using XMPPFramework, and I am wondering what's the best way to create a new message so I can map the XMPPMessage that gets returned in one of the delegate methods back to the original message that is sent. I want to do this so I can tell when sending a message is successful or unsuccessful (so I can cache and resend it).
Upon the user hitting the send key on the client, the following code is called to create and send the message:
NSXMLElement *body = [NSXMLElement elementWithName:#"body"];
[body setStringValue:messageText];
NSXMLElement *message = [NSXMLElement elementWithName:#"message"];
[message addAttributeWithName:#"type" stringValue:#"chat"];
[message addAttributeWithName:#"to" stringValue:recipientJID];
[message addChild:body];
[[self xmppStream] sendElement:message];
Then I store the contents, recipient, timestamp, etc. into a custom object (basically everything in message) in an array.
I want to be able to match an object in the array to the XMPPMessage object returned in either of these delegate methods:
- (void)xmppStream:(XMPPStream *)sender didFailToSendMessage:(XMPPMessage *)message error:(NSError *)error
{
}
- (void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message
{
}
Is there an attribute that I can add some kind of unique identifier to in the message variable that I send via XMPPStream that will then show up within the XMPPMessage passed to those delegate methods?
Why don't you send a XMPPMessage instead of a NSXMLElement? That way the object passed in didFailToSendMessage and didSendMessage will match the one you send. Besides, you can set elementId to identify stanzas (Messages, IQs or Presence)
XMPPMessage *message = [XMPPMessage messageWithType:#"chat"
to:someJid
elementID:elementId];
[[self xmppStream] sendElement:message];

Message not sent through XMPP

I am using XMPP in my app. My messages are not being sent whenever I attempt to send a message to any specific ID (for example 'test.codemen#gmail.com' in my code).
My code is given below. Thanks in advance.
- (IBAction)sendMsg:(id)sender
{
NSXMLElement *body = [NSXMLElement elementWithName:#"body"];
[body setStringValue:msgField.text];
NSXMLElement *message = [NSXMLElement elementWithName:#"message"];
[message addAttributeWithName:#"type" stringValue:#"chat"];
[message addAttributeWithName:#"to" stringValue:#"test.codemen#gmail.com"];
[message addChild:body];
iPhoneXMPPAppDelegate *share = [iPhoneXMPPAppDelegate sharedInstance];
[[share xmppStream] sendElement:message];
}
your code looks fine to me.
Google Talk routes messages only to contacts you are subscribed to. Is the user you send the message to on your contact list?
Print the xml , then see what's in the message .Maybe you are sending message to a wrong JID .

Resources