Kal
Kal

Reputation: 211

Callback Id missing in Phonegap plugin using Cocoa async library on delegate method return

I am having trouble getting my plugin to run properly on Phonegap 3.3 that utilizes the Cocoa Async socket library. The problem occurs in the didReadData method in the code below. The response data is correct when I output it to console, however, I can't get the callback to javascript code to work. The best I can tell is that the callbackId used in [self writeJavascript:[pluginResult toErrorCallbackString:callbackId]] is not the same callbackId that was calculated in the sendMessage method. Any help is much appreciated!

/********* TCPSockets.m Cordova Plugin Implementation *******/

#import "TCPSockets.h"
#import "GCDAsyncSocket.h"

@implementation TCPSockets

#define ENABLE_BACKGROUNDING  1

#pragma mark Plugin Start

- (void)sendMessage:(CDVInvokedUrlCommand*)command;
{
NSString* sendMessage = [command.arguments objectAtIndex:0];
NSString* myCallbackId = command.callbackId;

NSLog(@"Callback Id is %@", myCallbackId);

if (sendMessage == nil) {
    pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR
                               messageAsString: @"Error: No parameters for plugin"];
    [self.commandDelegate sendPluginResult:pluginResult callbackId:myCallbackId];
}
else
{
    port = [[command.arguments objectAtIndex:0] retain];
    host = [[command.arguments objectAtIndex:1] retain];
    message = [[command.arguments objectAtIndex:2] retain];
    connectionTimeout = [[command.arguments objectAtIndex:3] retain];
    secureConnection = [[command.arguments objectAtIndex:4] retain];
    response = @"";
    error = nil;

    dispatch_queue_t mainQueue = dispatch_get_main_queue();

    asyncSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:mainQueue];

    if ([secureConnection boolValue])
    {
        NSLog(@"Connecting (SSL) to \"%@\" on port %i...", host, [port intValue]);

        if (![asyncSocket connectToHost:host onPort:[port intValue] withTimeout:    ([connectionTimeout intValue] / 1000) error:&error])
        {
            NSLog(@"Error connecting: %@", error);

            response = error.localizedDescription;
            pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
            [self.commandDelegate sendPluginResult:pluginResult callbackId:myCallbackId];

        }
    }
    else
    {   
        NSLog(@"Connecting to \"%@\" on port %i...", host, [port intValue]);

        if (![asyncSocket connectToHost:host onPort:[port intValue] withTimeout:([connectionTimeout intValue] / 1000) error:&error])
        {
            NSLog(@"Error connecting: %@", error);

            response = error.localizedDescription;
            pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
            [pluginResult setKeepCallback:[NSNumber numberWithBool:YES]];
            [self.commandDelegate sendPluginResult:pluginResult callbackId:myCallbackId];
        }
    }
}
}



- (id)init
{
if ((self = [super init]))
{
    // Setup logging framework
    //[DDLog addLogger:[DDTTYLogger sharedInstance]];
}

return self;
}

#pragma mark Socket Delegate

- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
{
NSLog(@"socket:%p didConnectToHost:%@ port:%hu", sock, self->host, (UInt16)self->port);

if ([secureConnection boolValue])
{
    // SSL connection

    #if ENABLE_BACKGROUNDING && !TARGET_IPHONE_SIMULATOR
    {
        // Backgrounding doesn't seem to be supported on the simulator yet

        [sock performBlock:^{
            if ([sock enableBackgroundingOnSocket])
            {
                NSLog(@"Enabled backgrounding on socket");
            }
            else
            {
                NSLog(@"Enabling backgrounding failed!");
            }
        }];
    }
    #endif

    // Configure SSL/TLS settings (see documentation for the startTLS method in GCDAsyncSocket.h)
    NSMutableDictionary *settings = [NSMutableDictionary dictionaryWithCapacity:3];

    // To connect to a test server, with a self-signed certificate, use settings similar to this:

    // Allow expired certificates
    [settings setObject:[NSNumber numberWithBool:YES]
                 forKey:(NSString *)kCFStreamSSLAllowsExpiredCertificates];

    // Allow self-signed certificates
    [settings setObject:[NSNumber numberWithBool:YES]
                 forKey:(NSString *)kCFStreamSSLAllowsAnyRoot];

    // Don't validate the certificate chain
    [settings setObject:[NSNumber numberWithBool:NO]
                 forKey:(NSString *)kCFStreamSSLValidatesCertificateChain];

    NSLog(@"Starting SSL with settings:\n%@", settings);

    [sock startTLS:settings];
}
else
{

    #if ENABLE_BACKGROUNDING && !TARGET_IPHONE_SIMULATOR
    {
        // Backgrounding doesn't seem to be supported on the simulator yet

        [sock performBlock:^{
            if ([sock enableBackgroundingOnSocket])
            {
                NSLog(@"Enabled backgrounding on socket");
            }
            else
            {
                NSLog(@"Enabling backgrounding failed!");
            }
        }];
    }
    #endif

    NSData *requestData = [[message dataUsingEncoding:NSUTF8StringEncoding] retain];

    NSLog(@"Sending:%@", message);

    [sock writeData:requestData withTimeout:([connectionTimeout intValue] / 1000) tag:0];
    [sock readDataToData:[GCDAsyncSocket LFData] withTimeout:([connectionTimeout intValue] / 1000) tag:0];
}
}

- (void)socketDidSecure:(GCDAsyncSocket *)sock
{
NSLog(@"socketDidSecure:%p", sock);

NSData *requestData = [[message dataUsingEncoding:NSUTF8StringEncoding] retain];

NSLog(@"Sending:%@", message);

[sock writeData:requestData withTimeout:([connectionTimeout intValue] / 1000) tag:0];
[sock readDataToData:[GCDAsyncSocket LFData] withTimeout:([connectionTimeout intValue] / 1000) tag:0];
}

- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
NSLog(@"socket:%p didWriteDataWithTag:%ld", sock, tag);
}

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{

NSLog(@"socket:%p didReadData:WithTag:%ld", sock, tag);

response = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] retain];

response = [[response stringByReplacingOccurrencesOfString:@"\n" withString:@""] retain];

NSLog(@"Resposne data: %@", response);

pluginResult = [[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:response] retain];
[self writeJavascript:[pluginResult toErrorCallbackString:callbackId]];


// Release instance of GCDAsyncSocket
[asyncSocket setDelegate:nil delegateQueue:NULL];
[asyncSocket disconnect];
[asyncSocket release];
}

- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
NSLog(@"socketDidDisconnect:%p withError: %@", sock, err);

if (err != nil) {
    response = [err.localizedDescription retain];
    pluginResult = [[CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:response] retain];

    [self writeJavascript:[pluginResult toErrorCallbackString:callbackId]];
} else {
    response = [[response stringByReplacingOccurrencesOfString:@"\n" withString:@""] retain];
    pluginResult = [[CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:response] retain];

    [self writeJavascript:[pluginResult toSuccessCallbackString:callbackId]];
}
}

@end

Upvotes: 1

Views: 2500

Answers (1)

jcesarmobile
jcesarmobile

Reputation: 53311

on your .h create a property

@property (nonatomic, strong) NSString* myCallbackId;

on the sendData change the

NSString* myCallbackId = command.callbackId;

to

self.myCallbackId = command.callbackId;

on the didReadData change the

[self writeJavascript:[pluginResult toErrorCallbackString:callbackId]];

to

[self writeJavascript:[pluginResult toErrorCallbackString:self.callbackId]];

Upvotes: 1

Related Questions