UpnP Nat-pmp - callback not called

Discussion in 'Mac Programming' started by blueillusion, Oct 10, 2011.

  1. blueillusion macrumors member

    Joined:
    Aug 18, 2008
    #1
    I'm trying to implement automatic port forwarding using apples bonjour services.

    The specific function im using is: http://developer.apple.com/library/...ple_ref/c/func/DNSServiceNATPortMappingCreate

    At the moment, all Im trying to do is call the function so that I can get my external ip address.

    I call the function appropriately, it returns success, but my callback is never called. Without the callback, I cant get my external ip.

    The calling code is:

    Code:
    DNSServiceErrorType rError = DNSServiceNATPortMappingCreate(&externalIPServiceRef, 0, 0, 0, 0, 0, 0, portmap_cb, NULL);
        
        if(rError != kDNSServiceErr_NoError)
        {
            switch(rError)
            {
                case kDNSServiceErr_NATPortMappingDisabled:
                    NSLog(@"Portmapping on your router is disabled");
                    break;
                case kDNSServiceErr_NATPortMappingUnsupported:
                    NSLog(@"Portmapping is unsupported on your router");
                    break;
                case kDNSServiceErr_NoRouter:
                    NSLog(@"You don't have a router");
                    break;
                default:
                    NSLog(@"Error Code: %d", rError);
            }
        }
    Where externalIPServiceRef is just an uninitialized DNSServiceRef struct.

    My callback looks like:

    Code:
    void DC_PortmapReply(DNSServiceRef sdRef, 
                             DNSServiceFlags flags, 
                             uint32_t interfaceIndex, 
                             DNSServiceErrorType errorCode, 
                             uint32_t externalAddress, /* four byte IPv4 address in network byte order */
                             DNSServiceProtocol protocol, 
                             uint16_t internalPort, 
                             uint16_t externalPort, /* may be different than the requested port     */
                             uint32_t ttl, /* may be different than the requested ttl      */
                             void *context)
    {    
        if(errorCode != kDNSServiceErr_NoError)
        {
            NSLog(@"Error in callback");
            return;
        }
        
        NSLog(@"In Portmap Reply");
        
        switch(protocol)
        {
            case 0:
            {
                char addrStr[INET_ADDRSTRLEN];
                inet_ntop(AF_INET, &externalAddress, addrStr, INET_ADDRSTRLEN);
                NSString *networkString = [[NSString alloc] initWithUTF8String:addrStr];
                NSNumber *hostNumber = [[NSNumber alloc] initWithUnsignedInteger:externalAddress];
                NSDictionary *d = [[NSDictionary alloc] initWithObjectsAndKeys:networkString, @"networkString", hostNumber, @"hostNumber", nil];
                [[NSNotificationCenter defaultCenter] postNotificationName:DCNetworkAddressNotification object:networkString userInfo:d];
                [networkString release];
                [hostNumber release];
                [d release];
            }
                break;
            case kDNSServiceProtocol_TCP:
                break;
        }
    }
    However, the callback is never called. Does anyone have any experience with using nat-pmp?
     
  2. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #2
    The two highlighted identifiers don't match. Shouldn't they?
     
  3. blueillusion thread starter macrumors member

    Joined:
    Aug 18, 2008
    #3
    Oops, i forgot to post another piece of code.

    In one of my class initializers i do:

    Code:
    portmap_cb = &DC_PortmapReply;
    Which portmap_cb is defined as
    Code:
    DNSServiceNATPortMappingReply portmap_cb
    I've also skipped using the intermediate variable above, and plugged the function name directly into the call DNSServiceNATPortMappingCreate, but nothing happens either.
     
  4. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #4
  5. blueillusion thread starter macrumors member

    Joined:
    Aug 18, 2008
    #5
    I just tried out the Portmapper sample code you provided, and it execute the callbacks as it should.

    After looking carefully at the PortMapper code, It seems that you need to open a socket for a specific DNSService context.

    This makes sense, as you definitely would need to get the requested results from a socket. However this wasn't documented, and I assumed that the dns_sd functions would do that for me.

    However now i know!

    Thanks for pointing me to that code.

    (by the way, this is running on lion)
     
  6. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #6
    All I did was google the function you named, and added a site-specific search qualifier. So the search terms were:
    DNSServiceNATPortMappingCreate site:developer.apple.com

    There were only two results, and one was PortMapper.

    For reference, the PortMapper class is a wrapper around the port-mapping and bonjour functions, because some of them are not documented or are poorly documented (in PortMapper's README file). So if I were doing this task, I would probably just use the PortMapper class as-is.
     

Share This Page