FileTransfer problem #215

Open
leestarxin opened this Issue Jun 21, 2013 · 16 comments

Projects

None yet

10 participants

@leestarxin

I post the issue to http://stackoverflow.com/questions/17091398/ios-file-transfer-by-xmppframework
I hope someone can help me,thank you.

@ObjColumnist
Collaborator

The XMPPFramework doesn't support XEP-0096 so I imagine that could be the issue, but I haven't used the turn socket so I'm unsure how that fits in.

@leestarxin

Thank you for your reply,ObjColumnist.
Yes, but I realized xep0096, the final step, the initial sends message to server, the server returns the above error.
In addition, I have returned to TURNsocket success callback, and who knows how to implement

  • (Void) turnSocket: (TURNSocket *) sender didSucceed: (GCDAsyncSocket *) socket

     [socket setDelegate: self delegateQueue: dispatch_get_main_queue ()];
     [socket readDataWithTimeout: -1 tag: 100];

and add delegate

  • (Void) socket: (GCDAsyncSocket *) sock didReadData: (NSData *) data withTag: (long) tag {      NSLog(@"%@",data); }

Is that right? Do not feel right.
Who can help me, I find a lot of information have not been solved, thank you very much.

@robbiehanson @ObjColumnist

@ObjColumnist
Collaborator

This is a question probably best suited for the mailing list http://groups.google.com/group/xmppframework as nobody else is likely to check this issue.

@nqminh

I changed a few code in TURNSocket. Maybe useful to you.

//
// TURNSocket.h
//

@interface TURNSocket : NSObject
{
// ...

NSString *fileName;
NSData   *fileData;

}

//
// TURNSocket.m
//

#define STATE_ASK_TRANSFER 32

// ...

/**

  • SI Transfer
  • This method automatically updates the state.
    **/

    uuid = [xmppStream generateUUID];

    NSString *fileSize = [NSString stringWithFormat:@"%d",[fileData length]];

    NSXMLElement *si = [NSXMLElement elementWithName:@"si" xmlns:@"http://jabber.org/protocol/si"];
    [si addAttributeWithName:@"id" stringValue:uuid];
    [si addAttributeWithName:@"profile" stringValue:@"http://jabber.org/protocol/si/profile/file-transfer"];

    NSXMLElement *file = [NSXMLElement elementWithName:@"file" xmlns:@"http://jabber.org/protocol/si/profile/file-transfer"];
    [file addAttributeWithName:@"name" stringValue:fileName];
    [file addAttributeWithName:@"size" stringValue:fileSize];
    [si addChild:file];

    NSXMLElement *feature = [NSXMLElement elementWithName:@"feature" xmlns:@"http://jabber.org/protocol/feature-neg"];
    NSXMLElement *x = [NSXMLElement elementWithName:@"x" xmlns:@"jabberdata"];
    [x addAttributeWithName:@"type" stringValue:@"form"];

    NSXMLElement *field = [NSXMLElement elementWithName:@"field"];
    [field addAttributeWithName:@"var" stringValue:@"stream-method"];
    [field addAttributeWithName:@"type" stringValue:@"list-single"];

    NSXMLElement *option1 = [NSXMLElement elementWithName:@"option"];
    [option1 addChild:[DDXMLNode elementWithName:@"value" stringValue:@"http://jabber.org/protocol/bytestreams"]];

    NSXMLElement *option2 = [NSXMLElement elementWithName:@"option"];
    [option2 addChild:[DDXMLNode elementWithName:@"value" stringValue:@"http://jabber.org/protocol/ibb"]];

    [field addChild:option1];
    [field addChild:option2];
    [x addChild:field];
    [feature addChild:x];
    [si addChild:feature];

    XMPPIQ *iq = [XMPPIQ iqWithType:@"set" to:jid elementID:uuid child:si];
    [xmppStream sendElement:iq];

    state = STATE_ASK_TRANSFER;
    }

/**

  • Queries the next proxy candidate in the list.
  • If we've queried every candidate, then sends the request to the target, or fails if no proxies were found.
    **/

    • (void)queryNextProxyCandidate { XMPPLogTrace();

    // Update state
    state = STATE_PROXY_DISCO_ITEMS;

    // We start off with multiple proxy candidates (servers that have been known to be proxy servers in the past).
    // We can stop when we've found at least 2 proxies.

    XMPPJID *proxyCandidateJID = nil;

    if ([streamhosts count] < 2)
    {
    while ((proxyCandidateJID == nil) && (++proxyCandidateIndex < [proxyCandidates count]))
    {
    NSString *proxyCandidate = [proxyCandidates objectAtIndex:proxyCandidateIndex];
    proxyCandidateJID = [XMPPJID jidWithString:proxyCandidate];

        if (proxyCandidateJID == nil)
        {
            XMPPLogWarn(@"%@: Invalid proxy candidate '%@', not a valid JID", THIS_FILE, proxyCandidate);
        }
    }
    

    }

    if (proxyCandidateJID)
    {
    [self updateDiscoUUID];

    NSXMLElement *query = [NSXMLElement elementWithName:@"query" xmlns:@"http://jabber.org/protocol/disco#items"];
    
    XMPPIQ *iq = [XMPPIQ iqWithType:@"get" to:proxyCandidateJID elementID:discoUUID child:query];
    
    [xmppStream sendElement:iq];
    
    [self setupDiscoTimerForDiscoItems];
    

    }
    else
    {
    if ([streamhosts count] > 0)
    {
    // We've got a list of potential proxy servers to send to the initiator

        XMPPLogVerbose(@"%@: Streamhosts: \n%@", THIS_FILE, streamhosts);
    
        [self askTransfer];
    }
    else
    {
        // We were unable to find a single proxy server from our list
    
        XMPPLogVerbose(@"%@: No proxies found", THIS_FILE);
    
        [self fail];
    }
    

    }
    }

/**

  • Invoked by XMPPClient when an IQ is received.
  • We can determine if the IQ applies to us by checking its element ID.
    **/

    • (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq { // Disco queries (sent to jabber server) use id=discoUUID // P2P queries (sent to other Mojo app) use id=uuid

    if (state <= STATE_PROXY_DISCO_ADDR)
    {
    if (![discoUUID isEqualToString:[iq elementID]])
    {
    // Doesn't apply to us, or is a delayed response that we've decided to ignore
    return NO;
    }
    }
    else
    {
    if (![uuid isEqualToString:[iq elementID]])
    {
    // Doesn't apply to us
    return NO;
    }
    }

    XMPPLogTrace2(@"%@: %@ - state(%i)", THIS_FILE, THIS_METHOD, state);

    if (state == STATE_PROXY_DISCO_ITEMS)
    {
    [self processDiscoItemsResponse:iq];
    }
    else if (state == STATE_PROXY_DISCO_INFO)
    {
    [self processDiscoInfoResponse:iq];
    }
    else if (state == STATE_PROXY_DISCO_ADDR)
    {
    [self processDiscoAddressResponse:iq];
    }
    else if (state == STATE_REQUEST_SENT)
    {
    [self processRequestResponse:iq];
    }
    else if (state == STATE_ACTIVATE_SENT)
    {
    [self processActivateResponse:iq];
    }
    else if (state == STATE_ASK_TRANSFER)
    {
    [self sendRequest];
    }

    return YES;
    }

//
// USING
//

  • (void)test
    {
    XMPPJID *sender = xmppStream.myJID;
    XMPPJID *receiver = your_jid_receiver;

    NSData *fileData = your_data;

    if ([receiver.domain isEqualToString:sender.domain]) {
    [TURNSocket setProxyCandidates:[NSArray arrayWithObjects:sender.domain, nil]];
    } else {
    [TURNSocket setProxyCandidates:[NSArray arrayWithObjects:receiver.domain, sender.domain, nil]];
    }
    TURNSocket *socket = [[TURNSocket alloc] initWithStream:xmppStream toJID:receiver];
    socket.fileName = @"fileSend.abc";
    socket.fileData = fileData;
    [socket startWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    }

#pragma mark - TURNSocket Delegate

  • (void)turnSocket:(TURNSocket *)sender didSucceed:(GCDAsyncSocket *)socket
    {
    NSLog(@"Success to bytestream for file transfer!");
    [socket writeData:sender.fileData withTimeout:10000 tag:0];
    }

  • (void)turnSocketDidFail:(TURNSocket *)sender
    {
    NSLog(@"Couldn't set up bytestream for file transfer!");
    }

@praveengodz

@nqminh with this same method how can we receive the file. If i send file from spark , the request comes to ios is like SI file transfer, for this case how can i accept the request and receive the file?

Request from Spark 2.6.3 is:

http://pastebin.com/5kamqFHt

How to respond for this iq to recive the file ?

@adamk77

I've implemented XEP-0095 and XEP-0096. It was working with an older version of XMPPFramework (a few months ago) and I was able to exchange files with Spark / iMessage. However, I have not had time to test it with the newest version of the code. And I don't have time at the moment to try it again...

I can put it up if anyone's interested.

@zengyuanchen

hi @adamk77 , I am interested in XEP-0095 and XEP-0096 which your had implemented. Could you make public your source code about XEP-0095 and XEP-0096. Thank you very much.

@praveengodz

@adamk77 , Thanks for your reply , please share your implementation for send and receive the files using XEP -0095,0096.
👍

@adamk77

I've forked it and included my changes. It's here: https://github.com/adamk77/XMPPFramework

I had to make some modifications in the TURNSocket class XEP-0065.

New extensions included are XEP-0033 (multicast), XEP-0095 (Stream Initiation) and XEP-0096 (SI File Transfer).

I have some hard coded values in the code. I've marked with the #warning pragma in XMPPSiFileTransfer.m (line number 199). You'll want to change that.

Hope this is useful!

@praveengodz

@adamk77 thanks for sharing.

@zengyuanchen

@adamk77 thanks a lot

@praveengodz

@adamk77 is there any possibilities to share file in MUC.?

@arun-silicon

hii,

i am unable to send and receive files via TURNSocket , can any one help me out for this problem

or is there any process to send files via attachment on xml and send , if so how we can receive this one a receiver side ??

could any one have any solutions for that ?

@jonstaff

Check out my latest pull request, which should fully solve this problem.

A detailed blog post can be found here and a demo app can be found here.

@guptatarun84

hi, Just need an confirmation if XEP-0033 (multicast) is supported in the coming version of framework Jon? Also would like to know its implementation on view controllers. @adamk77 FYI

Many Thanks, Tarun

@adozenlines

@jonstaff I made a few mods to your implementation as the capabilities module was responding to the disco request before the file transfer has the opportunity to do so.

Capabilities support was added to the incoming module.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment