Trying to create a very simple proof of concept iOS xmpp app with the robbiehanson xmpp frame work, just need to be able to send and receive messages and roster data. I can authenticate and send messages successfully, but when users attempt to respond to my messages I do not receive them. I have implemented the didReceiveMessage delegate method as follows:
-(void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message {
NSLog(#"incoming message: %#", message);
}
but I never receive this log. If I log in with the existing web app or android app that communicates with this xmpp server I receive these messages, so I'm inclined to believe they are formatted properly. Is there a module I need to add to the XMPPStream for receiving messages? I'm setting up the stream like this (some of the string values have been changed for security and what not):
stream = [[XMPPStream alloc] init];
stream.enableBackgroundingOnSocket = YES;
stream.hostName = #"hostname.com";
stream.hostPort = 5222;
XMPPRosterCoreDataStorage* xmppRosterStorage = [[XMPPRosterCoreDataStorage alloc] initWithInMemoryStore];
XMPPRoster* xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:xmppRosterStorage];
xmppRoster.autoFetchRoster = YES;
xmppRoster.autoAcceptKnownPresenceSubscriptionRequests = YES;
[stream addDelegate:self delegateQueue:dispatch_get_main_queue()];
XMPPJID* jid = [XMPPJID jidWithUser:#"username" domain:#"domain.com" resource:#"iOS"];
[stream setMyJID:jid];
[xmppRoster activate:stream];
[stream connectWithTimeout:XMPPStreamTimeoutNone error:&error]
and then in the xmppStreamDidConnect method I do this to authenticate
NSString *myPassword = #"password";
NSError *error = nil;
[stream authenticateWithPassword:myPassword error:&error]
When I am sending a message out I use this snippet:
MPPJID* recipient = [XMPPJID jidWithString:#"user#domain.com"];
XMPPMessage* message = [[XMPPMessage alloc] initWithType:#"chat" to:recipient];
[message addBody:#"hello world"];
[stream sendElement: message];
I'm thinking there is something simple I am missing that someone who has used this before will be able to point out to me right away. I'm ready to supply other info if necessary for solving this issue.
I simply needed to broadcast my presence, then I was able to receive messages.
I added these lines to the streamDidAuthenticate method
XMPPPresence *presence = [XMPPPresence presence];
[sender sendElement:presence];
Related
I am developing a chat app in iOS using xmpp server. When i tried to connect to the server it returned 0 without any exception. All server credentials are true to the best of my knowledge. I tried many a times but couldn't found any fruitful help. Kindly give me a direction what should I do. Here is a code below.
xmppStream = [[XMPPStream alloc] init];
// [self setupStream];
NSXMLElement *presence = [NSXMLElement elementWithName:#"presence"];
[xmppStream sendElement:presence];
[xmppStream setMyJID:[XMPPJID jidWithString:#"app.com"]];
[xmppStream setHostName:#"appname.com"];
[xmppStream setHostPort:5222];
NSError *error2;
if ([xmppStream connect:&error2])
{
NSLog(#"Connected to XMPP.");
}
else
{
NSLog(#"Error connecting to XMPP: %#",[error2 localizedDescription]);
}
[self xmppStreamDidConnect:xmppStream];
//method is
- (void)setupStream {
NSLog(#"setupStream in delegate");
xmppStream = [[XMPPStream alloc] init];
[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
self.xmppStream.hostName = #"appname.com";
self.xmppStream.hostPort = (port);
[self connect];
}
Follow the connection class given in this link
Connection to server returns “0” only when you specify wrong HostName, HostPort or JID.
And one more thing you need not call xmppStreamDidConnect explicitly it will be called as delegate from XMPPFramework.
In my delegate.m
- (void)setupStream
{
NSAssert(xmppStream == nil, #"Method setupStream invoked multiple times");
customCertEvaluation = YES;
// allowSelfSignedCertificates = YES;
// allowSSLHostNameMismatch = NO; // 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 addDelegate:self delegateQueue:dispatch_get_main_queue()];
#if !TARGET_IPHONE_SIMULATOR
{
// Want xmpp to run in the background?
//
// P.S. - The simulator doesn't support backgrounding yet.
// When you try to set the associated property on the simulator, it simply fails.
// And when you background an app on the simulator,
// it just queues network traffic til the app is foregrounded again.
// We are patiently waiting for a fix from Apple.
// If you do enableBackgroundingOnSocket on the simulator,
// you will simply see an error message from the xmpp stack when it fails to set the property.
xmppStream.enableBackgroundingOnSocket = YES;
}
#endif
// Setup reconnect
//
// The XMPPReconnect module monitors for "accidental disconnections" and
// automatically reconnects the stream for you.
// There's a bunch more information in the XMPPReconnect header file.
xmppReconnect = [[XMPPReconnect alloc] init];
// XMPPAutoPing *xmppAutoPing = [[XMPPAutoPing alloc] initWithDispatchQueue:dispatch_get_main_queue()];
//xmppAutoPing.pingInterval = 25.f; // default is 60
//xmppAutoPing.pingTimeout = 10.f; // default is 10
//[xmppAutoPing addDelegate:self delegateQueue:dispatch_get_main_queue()];
//[xmppAutoPing activate:self.xmppStream];
// Setup roster
//
// The XMPPRoster handles the xmpp protocol stuff related to the roster.
// The storage for the roster is abstracted.
// So you can use any storage mechanism you want.
// You can store it all in memory, or use core data and store it on disk, or use core data with an in-memory store,
// or setup your own using raw SQLite, or create your own storage mechanism.
// You can do it however you like! It's your application.
// But you do need to provide the roster with some storage facility.
xmppRosterStorage = [[XMPPRosterCoreDataStorage alloc] init];
xmppRosterStorage = [[XMPPRosterCoreDataStorage alloc] initWithInMemoryStore];
xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:xmppRosterStorage];
xmppRoster.autoFetchRoster = YES;
xmppRoster.autoAcceptKnownPresenceSubscriptionRequests = YES;
// Setup vCard support
//
// The vCard Avatar module works in conjuction with the standard vCard Temp module to download user avatars.
// The XMPPRoster will automatically integrate with XMPPvCardAvatarModule to cache roster photos in the roster.
xmppvCardStorage = [XMPPvCardCoreDataStorage sharedInstance];
xmppvCardTempModule = [[XMPPvCardTempModule alloc] initWithvCardStorage:xmppvCardStorage];
xmppvCardAvatarModule = [[XMPPvCardAvatarModule alloc] initWithvCardTempModule:xmppvCardTempModule];
// Setup capabilities
//
// The XMPPCapabilities module handles all the complex hashing of the caps protocol (XEP-0115).
// Basically, when other clients broadcast their presence on the network
// they include information about what capabilities their client supports (audio, video, file transfer, etc).
// But as you can imagine, this list starts to get pretty big.
// This is where the hashing stuff comes into play.
// Most people running the same version of the same client are going to have the same list of capabilities.
// So the protocol defines a standardized way to hash the list of capabilities.
// Clients then broadcast the tiny hash instead of the big list.
// The XMPPCapabilities protocol automatically handles figuring out what these hashes mean,
// and also persistently storing the hashes so lookups aren't needed in the future.
//
// Similarly to the roster, the storage of the module is abstracted.
// You are strongly encouraged to persist caps information across sessions.
//
// The XMPPCapabilitiesCoreDataStorage is an ideal solution.
// It can also be shared amongst multiple streams to further reduce hash lookups.
xmppCapabilitiesStorage = [XMPPCapabilitiesCoreDataStorage sharedInstance];
xmppCapabilities = [[XMPPCapabilities alloc] initWithCapabilitiesStorage:xmppCapabilitiesStorage];
xmppCapabilities.autoFetchHashedCapabilities = YES;
xmppCapabilities.autoFetchNonHashedCapabilities = NO;
// Activate xmpp modules
[xmppReconnect activate:xmppStream];
[xmppRoster activate:xmppStream];
[xmppvCardTempModule activate:xmppStream];
[xmppvCardAvatarModule activate:xmppStream];
[xmppCapabilities activate:xmppStream];
// Add ourself as a delegate to anything we may be interested in
[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
// Optional:
//
// Replace me with the proper domain and port.
// The example below is setup for a typical google talk account.
//
// If you don't supply a hostName, then it will be automatically resolved using the JID (below).
// For example, if you supply a JID like 'user#quack.com/rsrc'
// then the xmpp framework will follow the xmpp specification, and do a SRV lookup for quack.com.
//
// If you don't specify a hostPort, then the default (5222) will be used.
[xmppStream setHostName:#"10.10.1.77"];
[xmppStream setHostPort:5222];
// You may need to alter these settings depending on the server you're connecting to
// allowSelfSignedCertificates = YES;
// allowSSLHostNameMismatch = NO;
customCertEvaluation = YES;
}
and also
- (void)xmppStream:(XMPPStream *)sender willSecureWithSettings:(NSMutableDictionary *)settings
{
DDLogVerbose(#"%#: %#", THIS_FILE, THIS_METHOD);
NSString *expectedCertName = [xmppStream.myJID domain];
if (expectedCertName)
{
[settings setObject:expectedCertName forKey:(NSString *)kCFStreamSSLPeerName];
}
if (customCertEvaluation)
[settings setObject:#(YES) forKey:GCDAsyncSocketManuallyEvaluateTrust];
}
- (void)xmppStream:(XMPPStream *)sender didReceiveTrust:(SecTrustRef)trust
completionHandler:(void (^)(BOOL shouldTrustPeer))completionHandler
{
/*DDLogVerbose(#"%#: %#", THIS_FILE, THIS_METHOD);
// The delegate method should likely have code similar to this,
// but will presumably perform some extra security code stuff.
// For example, allowing a specific self-signed certificate that is known to the app.
allowSelfSignedCertificates = YES;
allowSSLHostNameMismatch = NO;
dispatch_queue_t bgQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(bgQueue, ^{
SecTrustResultType result = kSecTrustResultDeny;
OSStatus status = SecTrustEvaluate(trust, &result);
if (status == noErr && (result == kSecTrustResultProceed || result == kSecTrustResultUnspecified)) {
completionHandler(YES);
}
else {
completionHandler(NO);
}
});
*/
completionHandler(YES);
}
I have done everything that was suggested in code but still connecting to server using SSL port gives error
2014-07-18 18:08:14:724 iPhoneXMPP[20593:60b] iPhoneXMPPAppDelegate: xmppStream:socketDidConnect:
2014-07-18 18:08:14:724 iPhoneXMPP[20593:60b] iPhoneXMPPAppDelegate: xmppStream:socketDidConnect:
2014-07-18 18:08:14:925 iPhoneXMPP[20593:60b] iPhoneXMPPAppDelegate: xmppStreamDidDisconnect:withError:
2014-07-18 18:08:14.925 iPhoneXMPP[20593:60b] Unable to connect to server
2014-07-18 18:08:14:926 iPhoneXMPP[20593:60b] Unable to connect to server. Check xmppStream.hostName
How am i supposed to solve to this error; Connection to normal port is fine though.Connection to SSL port is the only problem.
I finally can use SSL in 5223 port. I have to force use startTLS on didConnectToHost on XMPPStream.m. I don't know why isSecure always says NO.
Use the following method to enable the SSL/TLS. However this method is not defined theXMPPStream.h class, you need to define it here and access it from appdelegate or inside setupsteam method.
-(void)setIsSecure:(BOOL)flag
I am developing a chat application in iOS using XMPP. I have so far successfully implemented and tested a single user chat scenario, i.e. sending, receiving, saving and retrieving messages.
The problem now em facing is that now when handling Multi User Chat scenarios em receiving it but not able to save them using XMPP MessageArchiving hence cant retrieve them either.
Anyone who has gone through this process/problem?
Thank you in advance
Messages with groupchat type may be saved within XMPPRoom.xcdatamodel, you need to initialize the XMPPRoomCoreDataStorage in your xmpp setup like:
XMPPRoomCoreDataStorage *xmppRoomStorage = [[XMPPRoomCoreDataStorage alloc] init];
So, this class implements a method to insert all the messages ROOM within the correct data model (in our case, all the outgoing and incoming messages are saved in XMPPRoom.xcdatamodel).
- (void)insertMessage:(XMPPMessage *)message
outgoing:(BOOL)isOutgoing
forRoom:(XMPPRoom *)room
stream:(XMPPStream *)xmppStream
More XEP-0045 info http://xmpp.org/extensions/xep-0045.html
You can use this code for a saving room messages
NSString *xmppRoomJIDString = [NSString stringWithFormat:#"%##conference.your_host", #"your_room_name"];
XMPPJID *roomJID = [XMPPJID jidWithString:xmppRoomJIDString];
XMPPRoomCoreDataStorage *roomCoreDataStorage = [XMPPRoomCoreDataStorage sharedInstance];
XMPPRoom *xmppRoom = [[XMPPRoom alloc]
initWithRoomStorage:roomCoreDataStorage
jid:roomJID
dispatchQueue:dispatch_get_main_queue()];
[xmppRoom activate:xmppStream];
[xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xmppRoom joinRoomUsingNickname:#"your_nicke_name" history:nil];
[xmppRoom fetchConfigurationForm];
I am working on the chat application. I want to block friend. I am using XEP-0016 extensions of xmpp framework.
Here is my code..
- (void)setupXMPPPrivacy
{
NSLog((#"%s [Line %d] "), __PRETTY_FUNCTION__, __LINE__);
//Init XMPPPrivacy List
//xmppPrivacy = [[XMPPPrivacy alloc] init];
xmppPrivacy = [[XMPPPrivacy alloc] initWithDispatchQueue:dispatch_get_main_queue()];
//Activate xmpp modules
[xmppPrivacy activate:xmppStream];
//Delegate XMPPPrivacy
[xmppPrivacy addDelegate:self delegateQueue:dispatch_get_main_queue()];
}
- (void)privacyBlock:(XMPPJID *)jid
{
NSXMLElement *privacyElement = [XMPPPrivacy privacyItemWithType:#"jid" value:jid.bare action:#"deny" order:1];
[XMPPPrivacy blockIQs:privacyElement];
[XMPPPrivacy blockMessages:privacyElement];
[XMPPPrivacy blockPresenceIn:privacyElement];
[XMPPPrivacy blockPresenceOut:privacyElement];
NSLog(#"-------> PRIVACY ELEMENT: %#", privacyElement);
NSArray *arrayPrivacy = [[NSArray alloc] initWithObjects:privacyElement, nil];
[xmppPrivacy setListWithName:#"public" items:arrayPrivacy];
}
But, this is not working. What am I doing wrong?
Help please. Thanks.
I had the same trouble. First problem was UUID generator, it returned nil. But in iOS 5 added NSUUID class. So using [[NSUUID UUID] UUIDString] I solved this problem. Second problem was my big mistake. I initialized xmmpStram and did request to block, but opening stream takes some time.So, I requested before opening a stream.
I have a Problem with the XMPP-Framework for iOS. Every Time I fire registerWithPassword Method i get an Error:
"Error Domain=XMPPStreamErrorDomain Code=1 "Please wait until the
stream is connected." UserInfo=0xad7c300
{NSLocalizedDescription=Please wait until the stream is connected.} "
I do the following steps in my Code:
-(void)createUserWithUsername:(NSString*)name andPW:(NSString*)pw{
[self setupStream];
NSLog(#"name: %# ",name);
NSString *nameFor = name;
[self disconnect];
NSString *jidBenutzer = [NSString stringWithFormat:#"%##my-Server.com",nameFor];
NSError *error = nil;
NSError * err = nil;
NSLog(#"jabberid : %#",jidBenutzer);
XMPPJID *jid = [XMPPJID jidWithString:jidBenutzer];
self.xmppStream.myJID = jid;
[[self xmppStream] registerWithPassword:pw error:&err];
NSLog(#"Connection: %#",error);
NSLog(#"Register: %#",err);
}
I hope you can help me !
From your example code, I do not see any call to:
[xmppStream connect:&error]
From the error message, you are actually not connected.
Make sure you correctly call the connect method and that you are processing the error accordingly.
/**
* This method attempts to register a new user on the server using the given username and password.
* The result of this action will be returned via the delegate methods.
*
* If the XMPPStream is not connected, or the server doesn't support in-band registration, this method does nothing.
**/
This is the below.
- (BOOL)registerWithPassword:(NSString *)password error:(NSError **)errPtr
The method's instructions . You will find that before you use this method , you have to connecting the server.
I can' not find below.
[xmppStream connect:&error]
I use the this.
NSError *error;
NSString *tjid = [[NSString alloc] initWithFormat:#"anonymous#%#", serverName];
isRegister = YES;
[xmppStream setMyJID:[XMPPJID jidWithString:tjid]];
[xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error]
Please make sure your openfire server is turned on from your system preferences.
It is a late answer but still for any new developer like me: You have to login anonymously before registration: For example you are login with yourname#yourserver and your password try to login with unknown#yourserver and for password put nothing. So it will connect the stream but will not authenticate this is required for registration.
The stream should be connected but not be authenticated.