I am doing Chat App. XMPP Framework, automatically fetch contacts from ejabbered server. I am unable to add contacts to ejabbered server through my app. For ex: If I login through iOS Client, Jitsi, there I can give add contact. That too immediately reflect in my app and ejabbered server automatically. I dont know how to add my phone book contacts to ejabbered via my app.
Kindly guide how to add contact through my app.
Coding
- (void)setupStream
{
XMPPJID jid = [XMPPJID jidWithString:[NSString stringWithFormat:#"%##localhost",
`addBuddyTextField.text]];
[appDelegate.xmppRoster addUser:jid withNickname:addBuddyTextField.text];
xmppStream = [[XMPPStream alloc] init];
xmppReconnect = [[XMPPReconnect alloc] init];
xmppRosterStorage = [[XMPPRosterCoreDataStorage alloc] init];
xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:xmppRosterStorage];
xmppRoster.autoFetchRoster = YES;
xmppRoster.autoAcceptKnownPresenceSubscriptionRequests = YES;
}
For adding contacts first you need to send subscribe message to destination user (if destination user is registered to XMPP)
Send subscribe message
- (void) sendSubscribeMessageToUser:(NSString*)userID
{
XMPPJID* jbid= [XMPPJID jidWithString:userID];
XMPPPresence *presence = [XMPPPresence presenceWithType:#"subscribe" to:jbid];
[xmppStream sendElement:presence];
}
when destination user received subscribe message
/**
This fuction is called when other user state is changed
*/
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence
{
DDLogVerbose(#"%#: %# - %#", THIS_FILE, THIS_METHOD, [presence fromStr]);
NSString *presenceType = [presence type]; // online/offline
NSString *myUsername = [[sender myJID] user];
NSString *presenceFromUser = [[presence from] user];
NSString* presenceState= [presence status];
NSLog(#"%# is %# state %#",presenceFromUser,presenceType,presenceState);
if ([presenceType isEqualToString:#"subscribe"])
{
[xmppRoster subscribePresenceToUser:[presence from]];
}
else if ([presenceType isEqualToString:#"subscribed"])
{
[xmppRoster subscribePresenceToUser:[presence from]];
}
}
these functions will add automatically destination user to your contact list
Related
I am using XMPPFramework to implement group chat functionality in my app. The one-to-one chat works fine, but when I join a room by calling [xmppRoom joinRoomUsingNickname], the stream disconnects without giving any error.
I implemented xmppStreamDidDisconnect:withError too, but it's still giving nil error. The user also leaves the room immediately after joining it, since the stream disconnects. I am also using Reconnect module, but when it reconnects, the room is not auto-joined.
I am using pidgin to test it too, but it works fine there. What could be the reason for immediate disconnection?
PS: I am using testing it on iPhone 5 running on iOS 9.1
Update: It's now giving the following error -
Error Domain=GCDAsyncSocketErrorDomain Code=7 "Socket closed by remote
peer" UserInfo={NSLocalizedDescription=Socket closed by remote peer}
Try this modules
MessageManager.h
// Created by Deepak MK on 27/11/15.
//
#import <UIKit/UIKit.h>
#import "XMPP.h"
#import <CoreData/CoreData.h>
#import "XMPPFramework.h"
#import "XMPPMessageDeliveryReceipts.h"
#import "XMPPLastActivity.h"
#import "XMPPRosterMemoryStorage.h"
#import "XMPPRoomMemoryStorage.h"
#import "XMPPvCardCoreDataStorage.h"
#import "XMPPvCardTemp.h"
/**
message manager class manage all message sequence.
*/
#interface MessageManager : NSObject
{
XMPPStream *xmppStream;
NSString *password;
BOOL isOpen;
BOOL isRegistering;
id _delgate;
XMPPRosterCoreDataStorage *xmppRosterStorage;
XMPPRoster *xmppRoster;
XMPPvCardCoreDataStorage* xmppvCardStorage;
XMPPvCardTempModule*xmppvCardTempModule;
}
+ (MessageManager *) sharedMessageHandler;
/**
The stream varible for connecting stream
*/
#property (nonatomic, readonly) XMPPStream *xmppStream;
/**
XMPPRoster varible
*/
#property (nonatomic, strong,readonly) XMPPRoster *xmppRoster;
/**
XMPPRosterCoreDataStorage varible
*/
#property (nonatomic, strong,readonly) XMPPRosterCoreDataStorage *xmppRosterStorage;
/**
XMPPRoom varible
*/
#property (nonatomic, strong, readonly) XMPPRoom *xmppRoom;
/**
Setting of delegate
#param delegate class delegate
*/
- (void) setdelegate:(id)delegate;
/**
Return of delegate
*/
- (id) delegate;
/**
connecting stream of Xmpp server
*/
- (void) setupStream;
/**
Connect user to Xmpp server
#param jabberID login user name
#param myPassword login password
*/
- (BOOL)connectWithUserId:(NSString*)jabberID withPassword:(NSString*)myPassword;
/**
Connect user to Xmpp server
#param userName login user name
#param myPassword login password
*/
- (void) authenticateUserWIthUSerName:(NSString*)userName withPassword:(NSString*)myPassword;
/**
disconnect user from Xmpp server
*/
- (void) disconnect;
/**
changes the presence to online
*/
- (void) goOnline;
/**
changes the presence to offline
*/
- (void) goOffline;
/**
Register new user to xmpp server
#param userName new user name
#param _password new password
#param EmailId new email id
*/
- (void)registerStudentWithUserName:(NSString *)userName withPassword:(NSString *)_password withEmailId:(NSString *)EmailId;
/**
send message to other user with content
#param toAdress destination address
#param content content of message
*/
- (BOOL)sendMessageTo:(NSString*)toAdress withContents:(NSString*)content;
/**
This method is used for sending subscribe invitation to user
#param userID destination address
*/
- (void) sendSubscribeMessageToUser:(NSString*)userID;
/**
This method is used for setting substate of presence
#param subState substate of user
*/
- (void) presenceWithStubState:(NSString*)subState;
/**
This method is used to create new room
#param ChatRoomJID New room name
*/
- (void) setUpRoom:(NSString *)ChatRoomJID;
/**
This method is used to destroyRoom
*/
- (void) destroyCreatedRoom;
/**
This method is used to send message to group
*/
- (BOOL)sendGroupMessageWithBody:(NSString*)_body;
- (void) requestAllMesssage;
#end
/**
Set of methods to be implemented to act as a restaurant patron
*/
#protocol MessageManagerDelegate <NSObject>
/**
Methods to be get state of stream
*/
- (void) didGetStreamState:(BOOL)state;
/**
Methods to be get state of Authentication
*/
- (void) didGetAuthenticationState:(BOOL)state;
/**
Methods to be get state of registration
*/
- (void) didGetRegistrationState:(BOOL)state WithErrorMessage:(NSString*)errorMessage;
/**
Methods to get recieved message
*/
- (void) didReceiveMessageWithBody:(NSString *) body;
/**
Methods to get presence of other user
*/
- (void) didRecievePresence:(NSString*)state withUserName:(NSString*)userName WithSubState:(NSString*)subState;
/**
Methods to get event of user joined room
*/
- (void) didCreatedOrJoinedRoomWithCreatedRoomName:(NSString*)_roomName;
- (void) didGetUserJoinedToRoomORLeaveRoomWithName:(NSString*)_userName WithPresence:(NSString*)presence;
#end
MessageManager.m
#import "MessageManager.h"
#import "DDLog.h"
#import "DDTTYLogger.h"
#import <CFNetwork/CFNetwork.h>
#if DEBUG
static const int ddLogLevel = LOG_LEVEL_VERBOSE;
#else
static const int ddLogLevel = LOG_LEVEL_INFO;
#endif
#define kBaseXMPPURL #"XXXXXXXXXX"
#interface MessageManager()
#end
static MessageManager *sharedMessageHandler = nil;
#implementation MessageManager
#synthesize xmppStream;
#synthesize xmppRoster;
#synthesize xmppRosterStorage;
#synthesize xmppRoom;
#pragma mark - self class Delegate
- (void) setdelegate:(id)delegate
{
_delgate= delegate;
}
- (id) delegate
{
return _delgate;
}
#pragma mark - custom Functions
+ (MessageManager *) sharedMessageHandler
{
if (sharedMessageHandler == nil)
{
sharedMessageHandler = [[super allocWithZone:NULL] init];
}
return sharedMessageHandler;
}
+ (id)allocWithZone:(NSZone *)zone {
return [self sharedMessageHandler];
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
#pragma mark - connection setup Functions
/**
This fuction is used to setup XMPP Stream
*/
- (void)setupStream
{
// Setup xmpp stream
//
// The XMPPStream is the base class for all activity.
// Everything else plugs into the xmppStream, such as modules/extensions and delegates.
xmppStream = [[XMPPStream alloc] init];
[xmppStream setHostName:kBaseXMPPURL];
[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
}
/**
This fuction is used to Connect XMPP With userId and Password
*/
- (BOOL)connectWithUserId:(NSString*)jabberID withPassword:(NSString*)myPassword
{
[self setupStream];
isRegistering=NO;
if (![xmppStream isDisconnected]) {
return YES;
}
if (jabberID == nil || myPassword == nil) {
return NO;
}
[xmppStream setMyJID:[XMPPJID jidWithString:jabberID]];
password = myPassword;
NSError *error = nil;
if (![xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error])
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:[NSString stringWithFormat:#"Can't connect to server %#", [error localizedDescription]]
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
return NO;
}
return YES;
}
- (void) authenticateUserWIthUSerName:(NSString*)userName withPassword:(NSString*)myPassword
{
if ([xmppStream isConnected])
{
NSError*error =nil;
[xmppStream setMyJID:[XMPPJID jidWithString:userName]];
[xmppStream authenticateWithPassword:myPassword error:&error];
}
else
{
[self connectWithUserId:userName withPassword:myPassword];
}
}
#pragma mark ---Delegate of Connect
/**
This fuction is called when stream is connected
*/
- (void)xmppStreamDidConnect:(XMPPStream *)sender {
isOpen = YES;
NSError *error = nil;
NSLog(#"Stream Connected");
if (!isRegistering)
{
if([[self delegate] respondsToSelector:#selector(didGetStreamState:)])
{
[[self delegate]didGetStreamState:YES];
}
[xmppStream authenticateWithPassword:password error:&error];
}
else
{
[xmppStream registerWithPassword:password error:&error];
}
}
/**
This fuction is called when User is Authenticated
*/
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender {
[self goOnline];
NSLog(#"Stream Authenticated");
if([[self delegate] respondsToSelector:#selector(didGetAuthenticationState:)])
{
[[self delegate]didGetAuthenticationState:YES];
}
// if ([xmppStream isAuthenticated]) {
// NSLog(#"authenticated");
// xmppvCardStorage = [[XMPPvCardCoreDataStorage alloc] initWithInMemoryStore];
// xmppvCardTempModule = [[XMPPvCardTempModule alloc] initWithvCardStorage:xmppvCardStorage];
// [xmppvCardTempModule activate:[self xmppStream]];
// [xmppvCardTempModule addDelegate:self delegateQueue:dispatch_get_main_queue()];
// [xmppvCardTempModule fetchvCardTempForJID:[sender myJID] ignoreStorage:YES];
// }
}
- (void)xmppvCardTempModule:(XMPPvCardTempModule *)vCardTempModule didReceivevCardTemp:(XMPPvCardTemp *)vCardTemp forJID:(XMPPJID *)jid{
NSLog(#"Delegate is called");
XMPPvCardTemp *vCard = [xmppvCardStorage vCardTempForJID:jid xmppStream:xmppStream];
NSLog(#"Stored card: %#",vCard);
NSLog(#"%#", vCard.description);
NSLog(#"%#", vCard.name);
NSLog(#"%#", vCard.emailAddresses);
NSLog(#"%#", vCard.formattedName);
NSLog(#"%#", vCard.givenName);
NSLog(#"%#", vCard.middleName);
}
/**
This fuction is called when User is not Authenticated
*/
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(NSXMLElement *)error
{
NSLog(#"Not Authenticated");
if([[self delegate] respondsToSelector:#selector(didGetAuthenticationState:)])
{
[[self delegate]didGetAuthenticationState:NO];
}
}
#pragma mark - Stream disconnection
/**
This fuction is used to disconnet user
*/
- (void)disconnect
{
[self goOffline];
[xmppStream disconnect];
}
#pragma mark ---Delegate of disconnect
/**
This fuction is called when stream is disConnected
*/
- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
{
NSLog(#"Stream Disconnected");
if([[self delegate] respondsToSelector:#selector(didGetStreamState:)])
{
[[self delegate]didGetStreamState:NO];
}
}
#pragma mark - setting presence
/**
This fuction is used change the presence to online
*/
- (void)goOnline
{
XMPPPresence *presence = [XMPPPresence presence];
[xmppStream sendElement:presence];
}
/**
This fuction is used change the presence to Ofline
*/
- (void)goOffline
{
XMPPPresence *presence = [XMPPPresence presenceWithType:#"unavailable"];
[xmppStream sendElement:presence];
}
/**
This fuction is used change the presence substate
*/
- (void) presenceWithStubState:(NSString*)subState
{
XMPPPresence *presence = [XMPPPresence presence];// type="available" is implicit
NSXMLElement *status = [NSXMLElement elementWithName:#"status"];
[status setStringValue:subState];
[presence addChild:status];
[xmppStream sendElement:presence];
}
/**
This fuction is called when other user state is changed
*/
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence
{
DDLogVerbose(#"%#: %# - %#", THIS_FILE, THIS_METHOD, [presence fromStr]);
NSString *presenceType = [presence type]; // online/offline
NSString *myUsername = [[sender myJID] user];
NSString *presenceFromUser = [[presence from] user];
NSString* presenceState= [presence status];
NSLog(#"%# is %# state %#",presenceFromUser,presenceType,presenceState);
if (![presenceFromUser isEqualToString:myUsername])
{
if ([presenceType isEqualToString:#"available"])
{
if([[self delegate] respondsToSelector:#selector(didRecievePresence:withUserName:WithSubState:)])
{
[[self delegate] didRecievePresence:presenceType withUserName:presenceFromUser WithSubState:presenceState];
}
}
else if ([presenceType isEqualToString:#"unavailable"]) {
if([[self delegate] respondsToSelector:#selector(didRecievePresence:withUserName:WithSubState:)])
{
[[self delegate] didRecievePresence:presenceType withUserName:presenceFromUser WithSubState:presenceState];
}
}
else if ([presenceType isEqualToString:#"subscribe"])
{
[xmppRoster subscribePresenceToUser:[presence from]];
[self goOnline];
}
else if ([presenceType isEqualToString:#"subscribed"])
{
[xmppRoster subscribePresenceToUser:[presence from]];
}
}
if (xmppRoom)
{
[xmppRoom fetchMembersList];
}
}
#pragma mark - subscription
- (void) sendSubscribeMessageToUser:(NSString*)userID
{
XMPPJID* jbid= [XMPPJID jidWithString:userID];
XMPPPresence *presence = [XMPPPresence presenceWithType:#"subscribe" to:jbid];
[xmppStream sendElement:presence];
}
#pragma mark - XMPP delegates
/**
This fuction is called when new IQ is received
*/
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq {
return NO;
}
#pragma mark - RegistrationFunction
/**
This fuction is user to retister new user
if stream is connected the it will directly call registeration function
otherwise it will connect stream and then call registeration process
*/
- (void)registerStudentWithUserName:(NSString *)userName withPassword:(NSString *)_password withEmailId:(NSString *)EmailId
{
if (xmppStream==nil)
{
[self setupStream];
}
[xmppStream setMyJID:[XMPPJID jidWithString:userName]];
NSLog(#"Attempting registration for username %#",xmppStream.myJID.bare);
password=_password;
NSError *error = nil;
BOOL success;
if(![ xmppStream isConnected])
{
success = [[self xmppStream] connectWithTimeout:XMPPStreamTimeoutNone error:&error];
isRegistering=YES;
}
else
{
success = [[self xmppStream] registerWithPassword:_password error:&error];
}
if (success)
{
NSLog(#"succeed ");
isRegistering=YES;
}
else
{
if([[self delegate] respondsToSelector:#selector(didGetRegistrationState:WithErrorMessage:)])
{
[[self delegate]didGetRegistrationState:YES WithErrorMessage:#"Stream not connected"];
}
}
}
#pragma mark ---delegates of registrtaion
/**
This fuction is called when new user is registered
*/
- (void)xmppStreamDidRegister:(XMPPStream *)sender{
if([[self delegate] respondsToSelector:#selector(didGetRegistrationState:WithErrorMessage:)])
{
[[self delegate]didGetRegistrationState:YES WithErrorMessage:#"Registration with XMPP Successful!"];
}
}
/**
This fuction is called when registeration process failed
*/
- (void)xmppStream:(XMPPStream *)sender didNotRegister:(NSXMLElement *)error{
// DDXMLElement *errorXML = [error elementForName:#"error"];
// NSString *errorCode = [[errorXML attributeForName:#"code"] stringValue];
// NSString *regError = [NSString stringWithFormat:#"ERROR :- %#",error.description];
//
//
// if([errorCode isEqualToString:#"409"])
// {
// regError=#"Username Already Exists!";
// }
// else
// {
// regError= #"Server not connected";
// }
if([[self delegate] respondsToSelector:#selector(didGetRegistrationState:WithErrorMessage:)])
{
[[self delegate]didGetRegistrationState:NO WithErrorMessage:#"Username Already Exists!"];
}
}
#pragma mark - send and recieve message
/**
This fuction is used to send message to other user with contents of body
*/
//-(void)sendMessageTo:(NSString*)toAdress withContents:(NSString*)messageStr
//{
//
//
// if([messageStr length]> 0)
// {
//
// NSXMLElement *body = [NSXMLElement elementWithName:#"body"];
// [body setStringValue:messageStr];
//
// NSXMLElement *message = [NSXMLElement elementWithName:#"message"];
// [message addAttributeWithName:#"type" stringValue:#"chat"];
// [message addAttributeWithName:#"to" stringValue:toAdress];
// [message addChild:body];
//
// [self.xmppStream sendElement:message];
// }
//}
- (BOOL)sendMessageTo:(NSString*)toAdress withContents:(NSString*)content
{
if([content length]> 0)
{
NSXMLElement *body = [NSXMLElement elementWithName:#"body"];
[body setStringValue:content];
NSXMLElement *message = [NSXMLElement elementWithName:#"message"];
[message addAttributeWithName:#"type" stringValue:#"chat"];
[message addAttributeWithName:#"to" stringValue:toAdress];
[message addChild:body];
[self.xmppStream sendElement:message];
}
return YES;
}
#pragma mark recieve message
/**
This fuction is called when new message arrived
*/
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
DDLogVerbose(#"%#: %#", THIS_FILE, THIS_METHOD);
// A simple example of inbound message handling.
if ([message body])
{
NSString *body = [[message elementForName:#"body"] stringValue];
if([[self delegate] respondsToSelector:#selector(didReceiveMessageWithBody:)])
{
[[self delegate] didReceiveMessageWithBody:body];
}
}
}
#pragma mark - create new room
/**
This fuction is used to setup room with roomId
*/
-(void)setUpRoom:(NSString *)ChatRoomJID
{
if (!ChatRoomJID)
{
return;
}
// Configure xmppRoom
XMPPRoomMemoryStorage *roomMemoryStorage = [[XMPPRoomMemoryStorage alloc] init];
XMPPJID *roomJID = [XMPPJID jidWithString:ChatRoomJID];
xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:roomMemoryStorage jid:roomJID dispatchQueue:dispatch_get_main_queue()];
[xmppRoom activate:xmppStream];
[xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
NSXMLElement *history = [NSXMLElement elementWithName:#"history"];
[history addAttributeWithName:#" maxchars" stringValue:#"0"];
[xmppRoom joinRoomUsingNickname:xmppStream.myJID.user
history:history
password:nil];
[self performSelector:#selector(ConfigureNewRoom:) withObject:nil afterDelay:4];
}
/**
This fuction is used configure new
*/
- (void)ConfigureNewRoom:(id)sender
{
[xmppRoom configureRoomUsingOptions:nil];
[xmppRoom fetchConfigurationForm];
[xmppRoom fetchBanList];
[xmppRoom fetchMembersList];
[xmppRoom fetchModeratorsList];
}
/**
This fuction is called when new room is created
*/
- (void)xmppRoomDidCreate:(XMPPRoom *)sender
{
DDLogInfo(#"%#: %#", THIS_FILE, THIS_METHOD);
// I am inviting friends after room is created
}
/**
This fuction is called when user joined room
*/
- (void)xmppRoomDidJoin:(XMPPRoom *)sender
{
[sender fetchMembersList];
[sender fetchConfigurationForm];
[self requestAllMesssage];
DDLogInfo(#"%#: %#", THIS_FILE, THIS_METHOD);
if([[self delegate] respondsToSelector:#selector(didCreatedOrJoinedRoomWithCreatedRoomName:)])
{
[[self delegate] didCreatedOrJoinedRoomWithCreatedRoomName:sender.myRoomJID.bare];
}
}
- (void)xmppRoom:(XMPPRoom *)sender didFetchMembersList:(NSArray *)items
{
}
- (void)xmppRoom:(XMPPRoom *)sender occupantDidJoin:(XMPPJID *)occupantJID withPresence:(XMPPPresence *)presence
{
if([[self delegate] respondsToSelector:#selector(didGetUserJoinedToRoomORLeaveRoomWithName:WithPresence:)])
{
// id details =occupantJID;
// NSString* string = (NSString*)details;
[[self delegate] didGetUserJoinedToRoomORLeaveRoomWithName:[occupantJID resource] WithPresence:[presence type]];
}
}
- (void)xmppRoom:(XMPPRoom *)sender occupantDidLeave:(XMPPJID *)occupantJID withPresence:(XMPPPresence *)presence
{
if([[self delegate] respondsToSelector:#selector(didGetUserJoinedToRoomORLeaveRoomWithName:WithPresence:)])
{
[[self delegate] didGetUserJoinedToRoomORLeaveRoomWithName:[occupantJID resource] WithPresence:[presence type]];
}
}
- (void)xmppRoom:(XMPPRoom *)sender occupantDidUpdate:(XMPPJID *)occupantJID withPresence:(XMPPPresence *)presence
{
if([[self delegate] respondsToSelector:#selector(didGetUserJoinedToRoomORLeaveRoomWithName:WithPresence:)])
{
[[self delegate] didGetUserJoinedToRoomORLeaveRoomWithName:[occupantJID resource] WithPresence:[presence type]];
}
}
- (void) requestAllMesssage
{
// <presence
// from='hag66#shakespeare.lit/pda'
// id='n13mt3l'
// to='coven#chat.shakespeare.lit/thirdwitch'>
// <x xmlns='http://jabber.org/protocol/muc'>
// <history since='1970-01-01T00:00:00Z'/>
// </x>
// </presence>
//
// NSXMLElement *iQ = [NSXMLElement elementWithName:#"presence"];
// [iQ addAttributeWithName:#"type" stringValue:#"get"];
// [iQ addAttributeWithName:#"id" stringValue:#"n13mt3l"];
//
// NSXMLElement *retrieve = [NSXMLElement elementWithName:#"retrieve"];
// [retrieve addAttributeWithName:#"xmlns" stringValue:#"urn:xmpp:archive"];
// [retrieve addAttributeWithName:#"history since" stringValue:#"1970-01-01T00:00:00Z"];
//
// NSXMLElement *set = [NSXMLElement elementWithName:#"set"];
// [set addAttributeWithName:#"xmlns" stringValue:#"http://jabber.org/protocol/muc"];
//
// [retrieve addChild:set];
// [iQ addChild:retrieve];
//
// [xmppStream sendElement:iQ];
}
- (void)xmppRoom:(XMPPRoom *)sender didFetchConfigurationForm:(NSXMLElement *)configForm
{
DDLogInfo(#"%#: %#", THIS_FILE, THIS_METHOD);
NSXMLElement *newConfig = [configForm copy];
NSArray *fields = [newConfig elementsForName:#"field"];
for (NSXMLElement *field in fields)
{
NSString *var = [field attributeStringValueForName:#"var"];
// Make Room Persistent
if ([var isEqualToString:#"muc#roomconfig_persistentroom"])
{
[field removeChildAtIndex:0];
[field addChild:[NSXMLElement elementWithName:#"value" stringValue:#"1"]];
}
if ([var isEqualToString:#"roomconfig_enablelogging"])
{
[field removeChildAtIndex:0];
[field addChild:[NSXMLElement elementWithName:#"value" stringValue:#"1"]];
}
if ([var isEqualToString:#"muc#roomconfig_maxusers"])
{
[field removeChildAtIndex:0];
[field addChild:[NSXMLElement elementWithName:#"value" stringValue:#"100"]];
}
}
// [sender configureRoomUsingOptions:newConfig];
}
/**
This fuction is used to destroy created room
*/
- (void) destroyCreatedRoom
{
[xmppRoom destroyRoom];
}
- (BOOL)sendGroupMessageWithBody:(NSString*)_body
{
[xmppRoom sendMessageWithBody:_body];
return YES;
}
#end
Generally when the server is closing the connection, you get this error.
There are two reasons when the server closes the connection:
You are not sending regular pings if the client idle.
You are logging in from some different client with the same credentials,
and in the server settings have the setting:
Always kick - If there is a resource conflict, immediately kick the other
resource. in Server>server settings>resource policy.
Please check the server settings.
use this for server setting http://docs.ejabberd.im/admin/guide/installation/
And also check for App Transport Security Setting in your project. if it is not added then add the below code to info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
</plist>
The actual problem was that I was changing subject of the Room, just after creating the room. On removing the code for changing the subject of the room, it started working fine. Here's the code I was using -
-(XMPPRoom *)createRoom:(XMPPJID *)roomJid withSubject:(NSString*)subject{
XMPPRoomMemoryStorage *roomStorage = [[XMPPRoomMemoryStorage alloc]init];
XMPPRoom *xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:roomStorage
jid:roomJid
dispatchQueue:dispatch_get_main_queue()];
[xmppRoom activate:self.xmppStream];
[xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
// if(subject){
// [xmppRoom changeRoomSubject:subject];
// }
return xmppRoom;
}
-(GroupCore *)createRoomAndGroup:(XMPPJID *)roomJid withSubject:(NSString*)subject{
XMPPRoom* xmppRoom = [self createRoom:roomJid withSubject:subject];
GroupCore* group = [appDelegate.coreDataController addGroup:xmppRoom withOptions:CreateOnly];
if(!xmppRoom.roomSubject){
group.name = subject;
}
//[appDelegate saveContext];
// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
// [group joinRoom];
// });
return group;
}
I am new in iOS development and try to connect my iPhone device with the ejabberd server.I follow Xmpp.org document.And also I follow this "http://code.tutsplus.com/tutorials/building-a-jabber-client-for-ios-interface-setup--mobile-7188" document thoroughly.This is a great tutorial.This help me a lot a to setup a ejabberd server in my mac and able to connect to two different application(iMessage and Adium) through ejabberd server but I am facing some problem when I started iPhone application.
First I got XMPP importing error.but I solve it, after that app crash when I use [XMPPStream addDelegate: self delegateQueue:dispatch_get_main_queue() ] method.That time Compiler says "unrecognized selector sent".so I change it to [XMPPStream addDelegate:self ].Error removed.
And at last I got alert message which told me"Can't connect to server",and finally unable to connect to the server.
I want to test client-server connection locally,so I changed server address with my Mac Ip.but still unable to connect.
please help me....If possible please suggest me how to proceed further & any other document on XMPP.
Thanks a lot.
I call this connect function when application start.
- (BOOL)connect {
[self setupStream];
NSString *jabberID = [[NSUserDefaults standardUserDefaults]stringForKey:#"userID"];
NSString *myPassword =[[NSUserDefaults standardUserDefaults] stringForKey:#"userPassword"];
if (![xmppStream isDisconnected]) {
return YES;
}
if (jabberID == nil || myPassword == nil) {
return NO;
}
[xmppStream setMyJID:[XMPPJID jidWithString:jabberID]];
password = myPassword;
NSError *error = nil;
if (![xmppStream connect:&error]){
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error" message:[NSString stringWithFormat:#"Can't connect to server %#", [error localizedDescription]] delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alertView show];
[alertView release];
return NO;
}
return YES;
}
- (void)setupStream {
xmppStream = [[[XMPPStream alloc] init] autorelease];
[xmppStream addDelegate:self];
//[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
}
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence {
NSString *presenceType = [presence type]; // online/offline
NSString *myUsername = [[sender myJID] user];
NSString *presenceFromUser = [[presence from] user];
if (![presenceFromUser isEqualToString:myUsername]) {
if ([presenceType isEqualToString:#"available"]) {
[_chatDelegate newBuddyOnline:[NSString stringWithFormat:#"%##%#", presenceFromUser, #"MYSERVER"]];
} else if ([presenceType isEqualToString:#"unavailable"]) {
[_chatDelegate buddyWentOffline:[NSString stringWithFormat:#"%##%#", presenceFromUser, #"MYSERVER"]];
}
}
}
in the connect method try using these two lines also, if u are using ejabberd as mentioned in the tutorial
xmppStream.hostName = #"localhost";
xmppStream.hostPort=5222;
i was following the same tutorial and it worked for me after adding these lines..put breakpoints in the
- (void)xmppStreamDidConnect:(XMPPStream *)sender
delegate method to check if its connecting
I am trying to make a jabber chat application using the xmppframework.
I have implemented the xmppStream methods in the applicationAppDelegate, but none of these method has been invoked.
Here is the code of the applicationAppDelegate:
- (void)setupStream {
xmppStream = [[XMPPStream alloc] init];
[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
//[self connect];
}
- (void)goOnline {
XMPPPresence *presence = [XMPPPresence presence];
[[self xmppStream] sendElement:presence];
}
- (void)goOffline {
XMPPPresence *presence = [XMPPPresence presenceWithType:#"unavailable"];
[[self xmppStream] sendElement:presence];
}
- (BOOL)connect {
[self setupStream];
NSString *emailUserDefault = [[NSUserDefaults standardUserDefaults] stringForKey:#"email"];
NSString *jabberID = [emailUserDefault stringByAppendingString:#"#server.local"];
NSLog(#"%#",jabberID);
NSString *myPassword = [[NSUserDefaults standardUserDefaults] stringForKey:#"password"];
NSLog(#"%#",myPassword);
if (![xmppStream isDisconnected]) {
NSLog(#"You are connected");
return YES;
}
if (jabberID == nil || myPassword == nil) {
return NO;
}
[xmppStream setMyJID:[XMPPJID jidWithString:jabberID]];
//xmppStream.myJID = [XMPPJID jidWithString:jabberID];
password = myPassword;
NSError *error = nil;
if (![xmppStream connectWithTimeout:20 error:&error])
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:[NSString stringWithFormat:#"Can't connect to server %#", [error localizedDescription]]
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
return NO;
}
return YES;
}
- (void)disconnect {
[self goOffline];
[xmppStream disconnect];
}
- (void)xmppStreamDidConnect:(XMPPStream *)sender {
isOpen = YES;
NSError *error = nil;
[[self xmppStream] authenticateWithPassword:password error:&error];
}
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender {
[self goOnline];
}
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence {
NSString *presenceType = [presence type]; // online/offline
NSString *myUsername = [[sender myJID] user];
NSString *presenceFromUser = [[presence from] user];
if (![presenceFromUser isEqualToString:myUsername]) {
if ([presenceType isEqualToString:#"available"]) {
[__chatDelegate newBuddyOnline:[NSString stringWithFormat:#"%##%#", presenceFromUser, #"server.local"]];
} else if ([presenceType isEqualToString:#"unavailable"]) {
[__chatDelegate buddyWentOffline:[NSString stringWithFormat:#"%##%#", presenceFromUser, #"server.local"]];
}
}
}
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message {
NSString *msg = [[message elementForName:#"body"] stringValue];
NSString *from = [[message attributeForName:#"from"] stringValue];
NSMutableDictionary *m = [[NSMutableDictionary alloc] init];
[m setObject:msg forKey:#"msg"];
[m setObject:from forKey:#"sender"];
[__messageDelegate newMessageReceived:m];
}
Here my code for the chatViewController classe:
- (myApplicationAppDelegate *)appDelegate {
return (myApplicationAppDelegate *)[[UIApplication sharedApplication] delegate];
}
- (XMPPStream *)xmppStream {
return [[self appDelegate] xmppStream];
}
- (void)viewDidLoad
{
[super viewDidLoad];
onlineBuddies = [[NSMutableArray alloc ] init];
myApplicationAppDelegate *del = [self appDelegate];
[self xmppStream];
NSString *login = [[NSUserDefaults standardUserDefaults] objectForKey:#"email"];
del._chatDelegate = self;
if (login) {
if ([[self appDelegate] connect]) {
NSLog(#"show buddy list");
}
} else {
NSLog(#"Login Error");
}
}
I cannot figure out why the xmpp delegate methods are not being invoked. If someone can give me a hand, please don't hesitate.
Thanks in advance.
I think you misunderstood the purpose of AppDelegate. First of all for every iOS app that you are creating in Xcode there is a class created that contains the name AppDelegate but this class should only be used to get information of your application state, such as if the app goes to background, if it's launched with success or if it's coming up from background. Also the app delegate is used to specify the root (or entry point) view controller of your application.
So I think you should first check the basic rules (or a basic tutorial) on how to create a very simple application (a "Hello World Application"), after that you can go forward and create a basic structure of your application and decide what view controller or what model classes will handle your connection handling and response/request parsing.
I strongly suggest that you have a look over view controllers and I'm pretty sure that after you do the above suggested "tasks" you will answer yourself the posted question.
P.S Last point, have a look on "iOS naming & other conventions"enter link description herelife cycle methods
I used the openfire as the xmpp server, and want to transfer file via the Turnsocket.
The openfire (local) config:
xmpp.auth.anonymous true
xmpp.domain local
xmpp.enabled true
xmpp.externalip proxy.local, 192.168.1.101, 127.0.0.1
xmpp.proxy.enabled true
xmpp.proxy.port 7777
xmpp.proxy.transfer.required false
xmpp.server.socket.active true
xmpp.session.conflict.limit 0
xmpp.socket.ssl.active true
I tested the file transfer in the local environment, one user is logged in by Simulator (Sender), the other user is logged in by Device (iPod, receiver).
TURNSocket.m (both changed), change the proxy
+ (void)initialize {
...
proxyCandidates = [[NSMutableArray alloc] initWithObjects:#"local", nil];
...
}
Config both on sender and receiver
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq {
...
if ([TURNSocket isNewStartTURNRequest:iq]) {
NSLog(#"IS NEW TURN request Receive.. TURNSocket..................");
TURNSocket *turnSocket = [[TURNSocket alloc] initWithStream:xmppStream incomingTURNRequest:iq];
[turnSockets addObject:turnSocket];
[turnSocket startWithDelegate:self delegateQueue:dispatch_get_main_queue()];
[turnSocket release];
}
return YES;
}
Setup and call TURNSocket (Sender)
TURNSocket *turnSocket = [[TURNSocket alloc] initWithStream:[self xmppStream] toJID:user.primaryResource.jid];
[turnSockets addObject:turnSocket];
[turnSocket startWithDelegate:self delegateQueue:dispatch_get_main_queue()];
[turnSocket release];
didSucceed called both (sender and receiver)
- (void)turnSocket:(TURNSocket *)sender didSucceed:(GCDAsyncSocket *)socket {
}
Send a file? on sender
- (void)turnSocket:(TURNSocket *)sender didSucceed:(GCDAsyncSocket *)socket {
NSData *dataF = [[NSData alloc] initWithContentsOfFile:
[[NSBundle mainBundle] pathForResource:#"a1" ofType:#"png"]];
[socket writeData:dataF withTimeout:60.0f tag:0];
}
OR: Received data here? (Receiver)
- (void)turnSocket:(TURNSocket *)sender didSucceed:(GCDAsyncSocket *)socket {
NSData *dataF = [[NSData alloc] init];
[socket readDataToData:dataF withTimeout:30.0 tag:0];
NSLog(#"dataF: %d", [dataF length]); // dataF: 0
}
Does anyone know what's the problem?
Thanks very much!
To set an external ip address, you need to use xmpp.proxy.externalip rather than xmpp.externalip
I am trying to build a simple Jabber client.
I have downloaded this sample project, which uses xmpp-framework https://github.com/funkyboy/Building-a-Jabber-client-for-iOS
I am running it in the iOS Simulator. I have installed Openfire locally so that I can interact with a user logged into iChat.
Unfortunately the app only receives messages. It fails in sending messages giving the error "TURN Connection failed!".
This is the code attempting to connect:
- (void)viewDidLoad
{
[super viewDidLoad];
self.tView.delegate = self;
self.tView.dataSource = self;
[self.tView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
messages = [[NSMutableArray alloc ] init];
JabberClientAppDelegate *del = [self appDelegate];
del._messageDelegate = self;
[self.messageField becomeFirstResponder];
XMPPJID *jid = [XMPPJID jidWithString:#"user#server.local"];
NSLog(#"Attempting TURN connection to %#", jid);
TURNSocket *turnSocket = [[TURNSocket alloc] initWithStream:[self xmppStream] toJID:jid];
[turnSockets addObject:turnSocket];
[turnSocket startWithDelegate:self delegateQueue:dispatch_get_main_queue()];
[turnSocket release];
}
And those are the methods called on success/failure:
- (void)turnSocket:(TURNSocket *)sender didSucceed:(GCDAsyncSocket *)socket
{
NSLog(#"TURN Connection succeeded!");
NSLog(#"You now have a socket that you can use to send/receive data to/from the other person.");
[turnSockets removeObject:sender];
}
- (void)turnSocketDidFail:(TURNSocket *)sender
{
NSLog(#"TURN Connection failed!");
[turnSockets removeObject:sender];
}
Can anyone please help?
Thank you.
There is no reason to use TURN for normal messaging. TURN is required for media streaming only. Just use XMPPFramework. There are some good getting-started guides.
Next, use code of this nature to create and send stanzas:
XMPPMessage *msg = [XMPPMessage message];
[msg addAttributeWithName:#"type" stringValue:#"chat"];
[msg addAttributeWithName:#"to" stringValue:#"foo#example.com"];
NSXMLElement *body = [NSXMLElement elementWithName:#"body" stringValue:#"Hello"];
[msg addChild:body];
[[self xmppStream] sendElement:msg];
Note that msg is just a subclass of NSXMLElement, so you can modify the XML at will to craft the protocol you're going to send.