Open madhukiranraju opened 9 years ago
What device (I assume iOS or OS X) are you sending from and what are you sending to? It looks like you're using Smack; does this mean an Android device is receiving?
The error you're receiving is caused by a timeout (Outgoing file transfer failed because: Timeout waiting for recipient
disco#inforesponse.
), indicating that the recipient doesn't properly handle an incoming request for disco#info
.
yes,It works fine ,just set
xmppIncomingFileTransfer.disableIBB = NO;
xmppIncomingFileTransfer.disableSOCKS5 = YES;
Sorry I can not understand. I managed successfully from iphone client to spark. Unfortunately I can not send files from iphone to iphone. here is the error:
Error Domain = XMPPOutgoingFileTransferErrorDomain Code = -1 "Unable to send SI offer; the recipient does not have the required features." UserInfo = {0x8388b8e0 NSLocalizedDescription = Unable to send SI offer; the recipient does not have the required features.}
This and my Delegate class. As you can see I have included the code for file transfer. I think I have taken all the steps correctly. Unfortunately, the file transfer will not work. What am I doing wrong? thank you.
#import "AppDelegate.h"
#import "RootViewController.h"
#import "SettingsViewController.h"
#import "GCDAsyncSocket.h"
#import "XMPP.h"
#import "XMPPLogging.h"
#import "XMPPReconnect.h"
#import "XMPPCapabilitiesCoreDataStorage.h"
#import "XMPPRosterCoreDataStorage.h"
#import "XMPPvCardAvatarModule.h"
#import "XMPPvCardCoreDataStorage.h"
#import "DDLog.h"
#import "DDTTYLogger.h"
#import <CFNetwork/CFNetwork.h>
#import "SingletonDati.h"
// Log levels: off, error, warn, info, verbose
#if DEBUG
static const int ddLogLevel = LOG_LEVEL_VERBOSE;
#else
static const int ddLogLevel = LOG_LEVEL_INFO;
#endif
@interface AppDelegate(){
XMPPIncomingFileTransfer *_xmppIncomingFileTransfer;
}
- (void)setupStream;
- (void)teardownStream;
- (void)goOnline;
- (void)goOffline;
@end
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@implementation AppDelegate
@synthesize xmppStream;
@synthesize xmppReconnect;
@synthesize xmppRoster;
@synthesize xmppRosterStorage;
@synthesize xmppvCardTempModule;
@synthesize xmppvCardAvatarModule;
@synthesize xmppCapabilities;
@synthesize xmppCapabilitiesStorage;
@synthesize window;
@synthesize navigationController;
@synthesize settingsViewController;
@synthesize loginButton;
@synthesize password;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Configure logging framework
[DDLog addLogger:[DDTTYLogger sharedInstance]
withLogLevel:XMPP_LOG_LEVEL_VERBOSE | XMPP_LOG_FLAG_TRACE | XMPP_LOG_FLAG_SEND_RECV];
/// [DDLog addLogger:[DDTTYLogger sharedInstance] withLogLevel:XMPP_LOG_FLAG_SEND_RECV];
// Setup the XMPP stream
[self setupStream];
// Setup the view controllers
/// [window setRootViewController:navigationController];
[window makeKeyAndVisible];
if (![self connect])
{
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.0 * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[navigationController presentViewController:settingsViewController animated:YES completion:NULL];
});
}
return YES;
}
- (void)dealloc
{
[self teardownStream];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Core Data
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (NSManagedObjectContext *)managedObjectContext_roster
{
return [xmppRosterStorage mainThreadManagedObjectContext];
}
- (NSManagedObjectContext *)managedObjectContext_capabilities
{
return [xmppCapabilitiesStorage mainThreadManagedObjectContext];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Private
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)setupStream
{
NSAssert(xmppStream == nil, @"Method setupStream invoked multiple times");
// 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];
#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];
// 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 = NO;
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()];
_xmppIncomingFileTransfer = [XMPPIncomingFileTransfer new];
[_xmppIncomingFileTransfer activate:xmppStream];
// Add ourselves as delegate to necessary methods
[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
[_xmppIncomingFileTransfer 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:@""];
[xmppStream setHostPort:5222];
// You may need to alter these settings depending on the server you're connecting to
customCertEvaluation = YES;
}
- (void)teardownStream
{
[xmppStream removeDelegate:self];
[xmppRoster removeDelegate:self];
[xmppReconnect deactivate];
[xmppRoster deactivate];
[xmppvCardTempModule deactivate];
[xmppvCardAvatarModule deactivate];
[xmppCapabilities deactivate];
[xmppStream disconnect];
xmppStream = nil;
xmppReconnect = nil;
xmppRoster = nil;
xmppRosterStorage = nil;
xmppvCardStorage = nil;
xmppvCardTempModule = nil;
xmppvCardAvatarModule = nil;
xmppCapabilities = nil;
xmppCapabilitiesStorage = nil;
}
// It's easy to create XML elments to send and to read received XML elements.
// You have the entire NSXMLElement and NSXMLNode API's.
//
// In addition to this, the NSXMLElement+XMPP category provides some very handy methods for working with XMPP.
//
// On the iPhone, Apple chose not to include the full NSXML suite.
// No problem - we use the KissXML library as a drop in replacement.
//
// For more information on working with XML elements, see the Wiki article:
// https://github.com/robbiehanson/XMPPFramework/wiki/WorkingWithElements
- (void)goOnline
{
XMPPPresence *presence = [XMPPPresence presence]; // type="available" is implicit
NSString *domain = [xmppStream.myJID domain];
//Google set their presence priority to 24, so we do the same to be compatible.
if([domain isEqualToString:@"gmail.com"]
|| [domain isEqualToString:@"gtalk.com"]
|| [domain isEqualToString:@"talk.google.com"])
{
NSXMLElement *priority = [NSXMLElement elementWithName:@"priority" stringValue:@"24"];
[presence addChild:priority];
}
[[self xmppStream] sendElement:presence];
}
- (void)goOffline
{
XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];
[[self xmppStream] sendElement:presence];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Connect/disconnect
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (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 = @"user@gmail.com/xmppframework";
// 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;
}
return YES;
}
- (void)disconnect
{
[self goOffline];
[xmppStream disconnect];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark UIApplicationDelegate
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store
// enough application state information to restore your application to its current state in case
// it is terminated later.
//
// If your application supports background execution,
// called instead of applicationWillTerminate: when the user quits.
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
#if TARGET_IPHONE_SIMULATOR
DDLogError(@"The iPhone simulator does not process background network traffic. "
@"Inbound traffic is queued until the keepAliveTimeout:handler: fires.");
#endif
if ([application respondsToSelector:@selector(setKeepAliveTimeout:handler:)])
{
[application setKeepAliveTimeout:600 handler:^{
DDLogVerbose(@"KeepAliveHandler");
// Do other keep alive stuff here.
}];
}
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
}
- (void)applicationWillTerminate:(UIApplication *)application
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
[self teardownStream];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark XMPPStream Delegate
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)xmppStream:(XMPPStream *)sender socketDidConnect:(GCDAsyncSocket *)socket
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
NSLog(@"*** connessione SOCKET RIUSCITA");
}
- (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];
}
}
/**
* Allows a delegate to hook into the TLS handshake and manually validate the peer it's connecting to.
*
* This is only called if the stream is secured with settings that include:
* - GCDAsyncSocketManuallyEvaluateTrust == YES
* That is, if a delegate implements xmppStream:willSecureWithSettings:, and plugs in that key/value pair.
*
* Thus this delegate method is forwarding the TLS evaluation callback from the underlying GCDAsyncSocket.
*
* Typically the delegate will use SecTrustEvaluate (and related functions) to properly validate the peer.
*
* Note from Apple's documentation:
* Because [SecTrustEvaluate] might look on the network for certificates in the certificate chain,
* [it] might block while attempting network access. You should never call it from your main thread;
* call it only from within a function running on a dispatch queue or on a separate thread.
*
* This is why this method uses a completionHandler block rather than a normal return value.
* The idea is that you should be performing SecTrustEvaluate on a background thread.
* The completionHandler block is thread-safe, and may be invoked from a background queue/thread.
* It is safe to invoke the completionHandler block even if the socket has been closed.
*
* Keep in mind that you can do all kinds of cool stuff here.
* For example:
*
* If your development server is using a self-signed certificate,
* then you could embed info about the self-signed cert within your app, and use this callback to ensure that
* you're actually connecting to the expected dev server.
*
* Also, you could present certificates that don't pass SecTrustEvaluate to the client.
* That is, if SecTrustEvaluate comes back with problems, you could invoke the completionHandler with NO,
* and then ask the client if the cert can be trusted. This is similar to how most browsers act.
*
* Generally, only one delegate should implement this method.
* However, if multiple delegates implement this method, then the first to invoke the completionHandler "wins".
* And subsequent invocations of the completionHandler are ignored.
**/
- (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.
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);
}
});
}
- (void)xmppStreamDidSecure:(XMPPStream *)sender
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
}
- (void)xmppStreamDidConnect:(XMPPStream *)sender
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
isXmppConnected = YES;
NSError *error = nil;
if (![[self xmppStream] authenticateWithPassword:password error:&error])
{
DDLogError(@"Error authenticating: %@", error);
}
}
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
[self goOnline];
}
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(NSXMLElement *)error
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
}
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
return NO;
}
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
// A simple example of inbound message handling.
if ([message isChatMessageWithBody])
{
XMPPUserCoreDataStorageObject *user = [xmppRosterStorage userForJID:[message from]
xmppStream:xmppStream
managedObjectContext:[self managedObjectContext_roster]];
NSString *body = [[message elementForName:@"body"] stringValue];
NSString *displayName = [user displayName];
if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive)
{
/* UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:displayName
message:body
delegate:nil
cancelButtonTitle:@"Ok"
otherButtonTitles:nil];
[alertView show];
*/
NSMutableDictionary *dati=[[NSMutableDictionary alloc]init];
[dati setObject:(body) forKey:@"messaggioRicevuto"];
[dati setObject:displayName forKey:@"remoteUser"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"RiceviMessaggio" object:self userInfo:dati];
}
else
{
// We are not active, so use a local notification instead
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.alertAction = @"Ok";
localNotification.alertBody = [NSString stringWithFormat:@"From: %@\n\n%@",displayName,body];
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
}
}
}
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence
{
DDLogVerbose(@"%@: %@ - %@", THIS_FILE, THIS_METHOD, [presence fromStr]);
}
- (void)xmppStream:(XMPPStream *)sender didReceiveError:(id)error
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
}
- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
if (!isXmppConnected)
{
DDLogError(@"Unable to connect to server. Check xmppStream.hostName");
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark XMPPRosterDelegate
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)xmppRoster:(XMPPRoster *)sender didReceiveBuddyRequest:(XMPPPresence *)presence
{
DDLogVerbose(@"%@: %@", THIS_FILE, THIS_METHOD);
XMPPUserCoreDataStorageObject *user = [xmppRosterStorage userForJID:[presence from]
xmppStream:xmppStream
managedObjectContext:[self managedObjectContext_roster]];
NSString *displayName = [user displayName];
NSString *jidStrBare = [presence fromStr];
NSString *body = nil;
if (![displayName isEqualToString:jidStrBare])
{
body = [NSString stringWithFormat:@"Buddy request from %@ <%@>", displayName, jidStrBare];
}
else
{
body = [NSString stringWithFormat:@"Buddy request from %@", displayName];
}
if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:displayName
message:body
delegate:nil
cancelButtonTitle:@"Not implemented"
otherButtonTitles:nil];
[alertView show];
}
else
{
// We are not active, so use a local notification instead
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.alertAction = @"Not implemented";
localNotification.alertBody = body;
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
}
}
//IN ARRIVO
#pragma mark - XMPPIncomingFileTransferDelegate Methods
- (void)xmppIncomingFileTransfer:(XMPPIncomingFileTransfer *)sender
didFailWithError:(NSError *)error
{
DDLogVerbose(@"%@: Incoming file transfer failed with error: %@", THIS_FILE, error);
}
- (void)xmppIncomingFileTransfer:(XMPPIncomingFileTransfer *)sender
didReceiveSIOffer:(XMPPIQ *)offer
{
DDLogVerbose(@"%@: Incoming file transfer did receive SI offer. Accepting...", THIS_FILE);
[sender acceptSIOffer:offer];
}
- (void)xmppIncomingFileTransfer:(XMPPIncomingFileTransfer *)sender
didSucceedWithData:(NSData *)data
named:(NSString *)name
{
DDLogVerbose(@"%@: Incoming file transfer did succeed.", THIS_FILE);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
NSString *fullPath = [[paths lastObject] stringByAppendingPathComponent:name];
[data writeToFile:fullPath options:0 error:nil];
DDLogVerbose(@"%@: Data was written to the path: %@", THIS_FILE, fullPath);
}
////test--------------
///INVIO
- (void)xmppOutgoingFileTransfer:(XMPPOutgoingFileTransfer *)sender
didFailWithError:(NSError *)error
{
DDLogInfo(@"Outgoing file transfer failed with error: %@", error);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
message:@"There was an error sending your file. See the logs."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
}
- (void)xmppOutgoingFileTransferDidSucceed:(XMPPOutgoingFileTransfer *)sender
{
DDLogVerbose(@"File transfer successful.");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Success!"
message:@"Your file was sent successfully."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
}
#pragma mark - Public Methods
- (void)prepareStreamAndLogInWithJID:(XMPPJID *)jid password:(NSString *)password
{
DDLogVerbose(@"Preparing the stream and logging in as %@", jid.full);
xmppStream = [XMPPStream new];
xmppStream.myJID = jid;
xmppRosterStorage = [XMPPRosterCoreDataStorage new];
xmppRoster = [[XMPPRoster alloc] initWithRosterStorage:xmppRosterStorage];
xmppRoster.autoFetchRoster = YES;
_xmppIncomingFileTransfer = [XMPPIncomingFileTransfer new];
// Activate all modules
[xmppRoster activate:xmppStream];
[_xmppIncomingFileTransfer activate:xmppStream];
// Add ourselves as delegate to necessary methods
[xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
[_xmppIncomingFileTransfer addDelegate:self delegateQueue:dispatch_get_main_queue()];
NSError *err;
if (![xmppStream connectWithTimeout:30 error:&err]) {
DDLogInfo(@"%@: Error connecting: %@", THIS_FILE, err);
} else {
password = password;
}
}
#pragma mark - Private Methods
- (void)tearDownStream
{
[xmppStream removeDelegate:self];
[_xmppIncomingFileTransfer removeDelegate:self];
[xmppRoster deactivate];
[_xmppIncomingFileTransfer deactivate];
[xmppStream disconnect];
xmppStream = nil;
xmppRoster = nil;
xmppRosterStorage = nil;
_xmppIncomingFileTransfer = nil;
}
#pragma mark - XMPPStreamDelegate Methods
@end
I do got same error info:
Outgoing file transfer failed with error: Error Domain=XMPPOutgoingFileTransferErrorDomain Code=-1 "Unable to send SI offer; the recipient doesn't have the required features." UserInfo=0x7fc960ce3a80 {NSLocalizedDescription=Unable to send SI offer; the recipient doesn't have the required features.}
Hope... one of us will update with 'Solution' ASAP.
:( Are five days that I'm going crazy to fix this error with no results. I really hope that some user can give a solution. Thank You.
What are the JIDs for each device you're sending to and receiving from?
Hello Jonstaff,
Sender JID : Sender-username@domain/resource Receiver JID : Receiver-username@domain/resource
Resource : taken from full JID in presence delegate
e.g: test123@192.165.4.78/237956891081628672871
Thanks in advance
I need the actual JIDs you're using in the failed transfer, not a description of how they work.
Sender JID: 2000530038@192.168.XX.XX/4184529043698432067
Receiver JID: 918790013636@192.168.XX.XX/23749801272032817639
Where , 192.168.XX.XX is local host
these are my logs:
2015-02-09 19:40:48.391 SecretChat[23833:3009098] ******test@185.58.111.111/test
2015-02-09 19:40:50:499 SecretChat[23833:9e0b] SEND: <iq type="get" to="test@185.58.111.111/test" id="511EF964-A679-456E-A4FD-70F51D104F1A"><query xmlns="http://jabber.org/protocol/disco#info"/></iq>
2015-02-09 19:40:50:605 SecretChat[23833:9e0b] RECV: <iq xmlns="jabber:client" type="result" to="admin@185.58.111.111/test" id="511EF964-A679-456E-A4FD-70F51D104F1A" from="test@185.58.111.111/test"><query xmlns="http://jabber.org/protocol/disco#info"><feature var="http://jabber.org/protocol/disco#info"/><feature var="http://jabber.org/protocol/caps"/></query></iq>
2015-02-09 19:40:50:609 SecretChat[23833:1903] SEND: <iq type="result" to="test@185.58.111.111/test" id="511EF964-A679-456E-A4FD-70F51D104F1A" from="admin@185.58.111.111/test"><query xmlns="http://jabber.org/protocol/disco#info"><identity category="client" type="ios-osx"/><feature var="http://jabber.org/protocol/si"/><feature var="http://jabber.org/protocol/si/profile/file-transfer"/><feature var="http://jabber.org/protocol/bytestreams"/><feature var="http://jabber.org/protocol/ibb"/></query></iq>
2015-02-09 19:40:50:650 SecretChat[23833:807] AppDelegate: xmppStream:didReceiveIQ:
2015-02-09 19:40:50:650 SecretChat[23833:807] AppDelegate: xmppStream:didReceiveIQ:
2015-02-09 19:40:51:702 SecretChat[23833:9e0b] RECV: <iq xmlns="jabber:client" type="result" to="admin@185.58.111.111/test" id="511EF964-A679-456E-A4FD-70F51D104F1A" from="test@185.58.111.111/test"><query xmlns="http://jabber.org/protocol/disco#info"><identity category="client" type="ios-osx"/><feature var="http://jabber.org/protocol/si"/><feature var="http://jabber.org/protocol/si/profile/file-transfer"/><feature var="http://jabber.org/protocol/bytestreams"/><feature var="http://jabber.org/protocol/ibb"/></query></iq>
2015-02-09 19:40:52:852 SecretChat[23833:807] Outgoing file transfer failed with error: Error Domain=XMPPOutgoingFileTransferErrorDomain Code=-1 "Unable to send SI offer; the recipient doesn't have the required features." UserInfo=0x18b3b110 {NSLocalizedDescription=Unable to send SI offer; the recipient doesn't have the required features.}
2015-02-09 19:40:52:853 SecretChat[23833:807] Error performing fetch: Error Domain=XMPPOutgoingFileTransferErrorDomain Code=-1 "Unable to send SI offer; the recipient doesn't have the required features." UserInfo=0x18b3b110 {NSLocalizedDescription=Unable to send SI offer; the recipient doesn't have the required features.}
2015-02-09 19:40:52:866 SecretChat[23833:9e0b] XMPPCapabilities: Hash mismatch! hash(VyOFcFX6+YNmKssVXSBKGFP0BS4=) != calculatedHash(ITcwJgVrZLkXrP0EGRyR1B+pHIY=)
2015-02-09 19:40:52:868 SecretChat[23833:9e0b] XMPPCapabilities: maybeQueryNextJidWithHashKey:dueToHashMismatch: - Key doesn't exist in discoRequestHashDict
2015-02-09 19:40:53:110 SecretChat[23833:807] AppDelegate: xmppStream:didReceiveIQ:
2015-02-09 19:40:53:110 SecretChat[23833:807] AppDelegate: xmppStream:didReceiveIQ
2015-02-09 19:47:55:541 SecretChat[3238:7207] RECV: <iq xmlns="jabber:client" type="get" to="test@185.58.111.111/test" id="05F88A04-4157-4A9C-8633-C8E68137E4EC" from="admin@185.58.111.111/test"><query xmlns="http://jabber.org/protocol/disco#info"/></iq>
2015-02-09 19:47:55:541 SecretChat[3238:607] AppDelegate: xmppStream:didReceiveIQ:
2015-02-09 19:47:55:541 SecretChat[3238:607] AppDelegate: xmppStream:didReceiveIQ:
2015-02-09 19:47:55:541 SecretChat[3238:2c0b] SEND: <iq type="result" to="admin@185.58.111.111/test" id="05F88A04-4157-4A9C-8633-C8E68137E4EC"><query xmlns="http://jabber.org/protocol/disco#info"><feature var="http://jabber.org/protocol/disco#info"/><feature var="http://jabber.org/protocol/caps"/></query></iq>
2015-02-09 19:47:55:542 SecretChat[3238:2c0b] SEND: <iq type="result" to="admin@185.58.111.111/test" id="05F88A04-4157-4A9C-8633-C8E68137E4EC" from="test@185.58.111.111/test"><query xmlns="http://jabber.org/protocol/disco#info"><identity category="client" type="ios-osx"/><feature var="http://jabber.org/protocol/si"/><feature var="http://jabber.org/protocol/si/profile/file-transfer"/><feature var="http://jabber.org/protocol/bytestreams"/><feature var="http://jabber.org/protocol/ibb"/></query></iq>
2015-02-09 19:47:55:746 SecretChat[3238:2c0b] RECV: <iq xmlns="jabber:client" type="result" to="test@185.58.111.111/test" id="05F88A04-4157-4A9C-8633-C8E68137E4EC" from="admin@185.58.111.111/test"><query xmlns="http://jabber.org/protocol/disco#info"><identity category="client" type="ios-osx"/><feature var="http://jabber.org/protocol/si"/><feature var="http://jabber.org/protocol/si/profile/file-transfer"/><feature var="http://jabber.org/protocol/bytestreams"/><feature var="http://jabber.org/protocol/ibb"/></query></iq>
2015-02-09 19:47:55:746 SecretChat[3238:607] AppDelegate: xmppStream:didReceiveIQ:
2015-02-09 19:47:55:747 SecretChat[3238:607] AppDelegate: xmppStream:didReceiveIQ:
2015-02-09 19:47:55:748 SecretChat[3238:7207] XMPPCapabilities: Hash mismatch! hash(VyOFcFX6+YNmKssVXSBKGFP0BS4=) != calculatedHash(ITcwJgVrZLkXrP0EGRyR1B+pHIY=)
2015-02-09 19:47:55:748 SecretChat[3238:7207] XMPPCapabilities: maybeQueryNextJidWithHashKey:dueToHashMismatch: - Key doesn't exist in discoRequestHashDict
2015-02-09 19:48:03:047 SecretChat[3238:7207] RECV: <iq xmlns="jabber:client" type="get" to="test@185.58.111.111/test" id="9D9951FB-F319-4698-BEA2-32AED6CDFC04" from="admin@185.58.111.111/test"><query xmlns="http://jabber.org/protocol/disco#info"/></iq>
2015-02-09 19:48:03:047 SecretChat[3238:607] AppDelegate: xmppStream:didReceiveIQ:
2015-02-09 19:48:03:047 SecretChat[3238:607] AppDelegate: xmppStream:didReceiveIQ:
2015-02-09 19:48:03:048 SecretChat[3238:7207] SEND: <iq type="result" to="admin@185.58.111.111/test" id="9D9951FB-F319-4698-BEA2-32AED6CDFC04"><query xmlns="http://jabber.org/protocol/disco#info"><feature var="http://jabber.org/protocol/disco#info"/><feature var="http://jabber.org/protocol/caps"/></query></iq>
I wanted to inform you guys that I have succeeded. After 10 days of work I have reached this conclusion. I deleted my class AppDelegate taken from the sample project framework xmmpframework. Right now I'm working with the class AppDelegate Project File-Transfer-Demo and everything works. I really hope that in the next release of the framework XMPPFRAMEWORK in the sample project for IOS will also include File-Transfer-Demo. Thanks for the support.
That's great :)
你好jonstaff,我在传输文件中一直返回失败 ,麻烦你帮我看下是什么情况,多谢。 这是我的代码:
XMPPJID *jid = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@%@/Smack",recipient,ServerName]];
if (!_fileTransfer) {
_fileTransfer = [[XMPPOutgoingFileTransfer alloc]
initWithDispatchQueue:dispatch_get_main_queue()];
_fileTransfer.disableSOCKS5 = YES;
[_fileTransfer activate:_xmppStream];
[_fileTransfer addDelegate:self delegateQueue:dispatch_get_main_queue()];
}
NSError *err;
if (![_fileTransfer sendData:fileData
named:fileName
toRecipient:jid
description:description
error:&err]) {
//不能传输
NSLog(@"不能传输");
}
返回的错误信息是: Error Domain = XMPPOutgoingFileTransferErrorDomain Code = -1 "Unable to send SI offer
你好。我的中文不好,所以请原谅我。在哪里说 Error Domain = XMPPOutgoingFileTransferErrorDomain Code = -1 "Unable to send SI offer
? 还有什么说?这个错误不是完整。
你好jonstaff,很高兴收到你的回复,我的完整错误信息是:Error Domain=XMPPOutgoingFileTransferErrorDomain Code=-1 "Unable to send SI offer; the recipient doesn't have the required features." UserInfo=0x15e59910 {NSLocalizedDescription=Unable to send SI offer; the recipient doesn't have the required features.} 其中,我要传输到的Jid信息是13430420870@win-qlsnkq93bfg/Smack。再次感谢你的回复,希望能和你有更多的交流,我来自中国深圳。
Hello Everybody, since two weeks i'm facing this problem when i trying to send files. Domain=XMPPOutgoingFileTransferErrorDomain Code=-1 "Unable to send SI offer; the recipient doesn't have the required features." UserInfo=0x15e59910 {NSLocalizedDescription=Unable to send SI offer; the recipient doesn't have the required features.} Does anyone find how to fix this error ? I need some help please...
copied by venkateswarlunp. it work for me. Sender JID : Sender-username@domain/resource Receiver JID : Receiver-username@domain/resource
Resource : taken from full JID in presence delegate
I got it working this way-
xmppIncomingFileTransfer = [[XMPPIncomingFileTransfer alloc] init];
xmppIncomingFileTransfer.disableIBB = NO;
xmppIncomingFileTransfer.disableSOCKS5 = NO;
[xmppIncomingFileTransfer activate:xmppStream];
[xmppIncomingFileTransfer addDelegate:self delegateQueue:dispatch_get_main_queue()];
- (void)xmppIncomingFileTransfer:(XMPPIncomingFileTransfer *)sender
didFailWithError:(NSError *)error
{
DDLogVerbose(@"%@: Incoming file transfer failed with error: %@", THIS_FILE, error);
}
- (void)xmppIncomingFileTransfer:(XMPPIncomingFileTransfer *)sender
didReceiveSIOffer:(XMPPIQ *)offer
{
DDLogVerbose(@"%@: Incoming file transfer did receive SI offer. Accepting...", THIS_FILE);
[sender acceptSIOffer:offer];
}
- (void)xmppIncomingFileTransfer:(XMPPIncomingFileTransfer *)sender
didSucceedWithData:(NSData *)data
named:(NSString *)name
{
DDLogVerbose(@"%@: Incoming file transfer did succeed.", THIS_FILE);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
NSString *fullPath = [[paths lastObject] stringByAppendingPathComponent:name];
[data writeToFile:fullPath options:0 error:nil];
DDLogVerbose(@"%@: Data was written to the path: %@", THIS_FILE, fullPath);
}
Incoming files will be written to the documents directory, you can update UI when it is done.
if (!_fileTransfer) {
_fileTransfer = [[XMPPOutgoingFileTransfer alloc] initWithDispatchQueue:dispatch_get_main_queue()];
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[_fileTransfer activate:appDelegate.xmppStream];
_fileTransfer.disableIBB = NO;
_fileTransfer.disableSOCKS5 = NO;
[_fileTransfer addDelegate:self delegateQueue:dispatch_get_main_queue()];
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
NSString *fullPath = [[paths lastObject] stringByAppendingPathComponent:filename];
NSData *data = [NSData dataWithContentsOfFile:fullPath];
NSError *err;
if (![_fileTransfer sendData:data
named:filename
toRecipient:[XMPPJID jidWithString:self.contact.primaryResource.jidStr]
description:@"Baal's Soulstone, obviously."
error:&err]) {
DDLogInfo(@"You messed something up: %@", err);
}
- (void)xmppOutgoingFileTransfer:(XMPPOutgoingFileTransfer *)sender
didFailWithError:(NSError *)error
{
DDLogInfo(@"Outgoing file transfer failed with error: %@", error);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error"
message:@"There was an error sending your file. See the logs."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
}
- (void)xmppOutgoingFileTransferDidSucceed:(XMPPOutgoingFileTransfer *)sender
{
DDLogVerbose(@"File transfer successful.");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Success!"
message:@"Your file was sent successfully."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
}
Note that the disableIBB and disableSOCKS5 should match at both ends. If the problem still exists, go to XMPPOutgoingFileTransfer.m and then to the method-
Then put a NSLOG/Breakpoint at this line -
hasSOCKS5 = hasSI && hasFT && hasSOCKS5;
hasIBB = hasSI && hasFT && hasIBB;
Both values should become TRUE when sending a file. Check which one is FALSE (causing the error), you will get an idea why the incoming end is sending FALSE instantly. Try to fix that.
the sender in the wifi , the receive in 4G send file failed. it's the outcoming’s log and the receive's log below.
2015-12-22 19:22:32.468 pirate[789:225573] XMPPOutgoingFileTransfer:startFileTransfer 2015-12-22 19:22:32:471 pirate[789:e6b] 4-SEND: Baal's Soulstone, obviously.http://jabber.org/protocol/bytestreamshttp://jabber.org/protocol/ibb 2015-12-22 19:22:32:765 pirate[789:e6b] 3-RECV: http://jabber.org/protocol/bytestreams 2015-12-22 19:22:32:772 pirate[789:4f3f] 4-SEND: 2015-12-22 19:22:32:777 pirate[789:4f3f] 3-RECV: 2015-12-22 19:22:32:782 pirate[789:5a43] 4-SEND: 2015-12-22 19:23:32.784 pirate[789:225573] XMPPOutgoingFileTransfer:failWithReason 2015-12-22 19:23:32:786 pirate[789:b07] Outgoing file transfer failed with error: Error Domain=GCDAsyncSocketErrorDomain Code=2 "Invalid host parameter (nil or ""). Should be a domain name or IP address string." UserInfo={NSLocalizedDescription=Invalid host parameter (nil or ""). Should be a domain name or IP address string.}
the incoming’s log:
2015-12-22 19:26:22:377 pirate[789:5a67] 3-RECV: 2015-12-22 19:26:22:381 pirate[789:4937] 4-SEND: 2015-12-22 19:26:22:606 pirate[789:4937] 3-RECV: Baal's Soulstone, obviously.http://jabber.org/protocol/bytestreamshttp://jabber.org/protocol/ibb 2015-12-22 19:26:22:613 pirate[789:e73] 4-SEND: http://jabber.org/protocol/bytestreams 2015-12-22 19:26:23:629 pirate[789:5a67] 3-RECV:
my server: mod_proxy65: host: “proxy.auto.hooca.com.cn" name: ”file transfer proxy” ip: “192.168.0.25” hostname: “140.206.XX.XX” port: 7777 shaper: proxy_shaper
Hi Please have a look i am getting this error
i am completely new in xmpp and openfire both so please tell me why i am getting this error jid i am supplying are correct i read all comments above unable to get solution
i am using file transfer demo. The lines below i just copied from above i want to know how to make this congfiguration on openfire where do if can find these variables.
my server: mod_proxy65: host: “proxy.auto.hooca.com.cn" name: ”file transfer proxy” ip: “192.168.0.25” hostname: “140.206.XX.XX” port: 7777 shaper: proxy_shaper
Thanks a lot
Is it possible to transfer offline file with above code.
above code is working for sending file when users are online.
I need to transfer when recipient is offline and once recipient is online, file should be fetch.
thanks in advance.
Hi Jonathon Staff,
i have been trying to send file by disabling SockS5.
below is the code for button action
and below is the console logs
Please help me .