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
Related
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
I am using below code for creating turn Socket but every time it goes in turnSocketDidFail method so whats the wrong in the code , please help me out.
XMPPJID *JID = [XMPPJID jidWithString:#"9107#test.com/110s-Mac-mini"];
[TURNSocket setProxyCandidates:[NSArray arrayWithObjects:JID.domain, nil]];
TURNSocket *socket = [[TURNSocket alloc] initWithStream:[[NDAppDelegate shareAppDelegateInstance] xmppStream] toJID:JID];
[socket startWithDelegate:self delegateQueue:dispatch_get_main_queue()];
- (void)turnSocket:(TURNSocket *)sender didSucceed:(GCDAsyncSocket *)socket {
NSLog(#"TURN Connection succeeded!");
}
- (void)turnSocketDidFail:(TURNSocket *)sender {
NSLog(#"TURN Connection failed!");
}
I am developing an iOS application which uses the Facebook chat feature.
(I am using the XMPPFramework by Robbie Hanson).
https://github.com/robbiehanson/XMPPFramework
In connect method i have given my user name and password
- (BOOL)connect
{
if (![xmppStream isDisconnected]) {
return YES;
}
NSString *myJID = [[NSUserDefaults standardUserDefaults] stringForKey:kXMPPmyJID];
NSString *myPassword = [[NSUserDefaults standardUserDefaults] stringForKey:kXMPPmyPassword];
//
// If you don't want to use the Settings view to set the JID,
// uncomment the section below to hard code a JID and password.
//
myJID = #"example#facebook.com";
myPassword = #"Mypassword";
if (myJID == nil || myPassword == nil) {
return NO;
}
[xmppStream setMyJID:[XMPPJID jidWithString:myJID]];
password = myPassword;
NSError *error = nil;
if (![xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error])
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error connecting"
message:#"See console for error details."
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
DDLogError(#"Error connecting: %#", error);
return NO;
}
in up stream method i have given my host name and port number
- (void)setupStream
{
NSAssert(xmppStream == nil, #"Method setupStream invoked multiple times");
xmppStream = [[XMPPStream alloc] init];
#if !TARGET_IPHONE_SIMULATOR
{
xmppStream.enableBackgroundingOnSocket = YES;
}
#endif
xmppReconnect = [[XMPPReconnect alloc] init];
xmppRosterStorage = [[XMPPRosterCoreDataStorage alloc] init];
xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:xmppRosterStorage];
xmppRoster.autoFetchRoster = YES;
xmppRoster.autoAcceptKnownPresenceSubscriptionRequests = YES;
xmppvCardStorage = [XMPPvCardCoreDataStorage sharedInstance];
xmppvCardTempModule = [[XMPPvCardTempModule alloc] initWithvCardStorage:xmppvCardStorage];
xmppvCardAvatarModule = [[XMPPvCardAvatarModule alloc] initWithvCardTempModule:xmppvCardTempModule];
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()];
[xmppStream setHostName:#"chat.facebook.com"];
[xmppStream setHostPort:5222];
// You may need to alter these settings depending on the server you're connecting to
allowSelfSignedCertificates = NO;
allowSSLHostNameMismatch = NO;
}
Is there any steps that I have missed out? I have no idea how to proceed further. Help me if any one know the solution. Please help me out
Thanks in advance.
Try securing the connection using:
[xmppStream secureConnection:(NSError *)];
in the
- (void)xmppStreamDidConnect:(XMPPStream *)sender;
delegate method.
Hope it helps.
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 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.