Cocoa-NetworkChange

 view release on metacpan or  search on metacpan

src/NetworkChange.xs  view on Meta::CPAN

#define PERL_NO_GET_CONTEXT /* we want efficiency */
#include <EXTERN.h>
#include <perl.h>
#include <XSUB.h>

#define NEED_newSVpvn_flags
#include "ppport.h"

#undef Move

#import <Foundation/Foundation.h>
#import <CoreWLAN/CoreWLAN.h>

#import "Reachability.h"

static inline SV*
nsstring_to_sv(NSString* str) {
    SV* sv = sv_2mortal(newSV(0));
    sv_setpv(sv, [str UTF8String]);
    return sv;
}

static void
set_current_interface(CWInterface* interface, HV* hv_interface) {
    (void)hv_store(hv_interface, "ssid", 4,
        SvREFCNT_inc(nsstring_to_sv([interface ssid])), 0);
    (void)hv_store(hv_interface, "interface", 9,
        SvREFCNT_inc(nsstring_to_sv([interface interfaceName])), 0);
    (void)hv_store(hv_interface, "mac_address", 11,
        SvREFCNT_inc(nsstring_to_sv([interface hardwareAddress])), 0);
    (void)hv_store(hv_interface, "bssid", 5,
        SvREFCNT_inc(nsstring_to_sv([interface bssid])), 0);
}

MODULE = Cocoa::NetworkChange    PACKAGE = Cocoa::NetworkChange

PROTOTYPES: DISABLE

void
on_network_change(SV* sv_connect_cb, ...)
PPCODE:
{
    SV* connect_cb = get_sv("Cocoa::NetworkChange::__connect_cb", GV_ADD);
    sv_setsv(connect_cb, sv_connect_cb);

    if (items > 1) {
        SV* disconnect_cb = get_sv("Cocoa::NetworkChange::__disconnect_cb", GV_ADD);
        sv_setsv(disconnect_cb, ST(1));
    }

    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

    Reachability* reach = [Reachability reachabilityForInternetConnection];
    reach.reachableBlock = ^(Reachability* reach){
        dispatch_sync(dispatch_get_main_queue(), ^{
            CWInterface* currentInterface = [CWInterface interfaceWithName:nil];
            HV* hv_interface = (HV*)sv_2mortal((SV*)newHV());
            set_current_interface(currentInterface, hv_interface);

            SV* connect_cb = get_sv("Cocoa::NetworkChange::__connect_cb", 0);
            if (connect_cb) {
                dSP;
                ENTER;
                SAVETMPS;

                PUSHMARK(SP);
                XPUSHs(sv_2mortal(newRV_inc((SV*)hv_interface)));
                PUTBACK;

                call_sv(connect_cb, G_SCALAR);

                SPAGAIN;

                PUTBACK;
                FREETMPS;
                LEAVE;
            }
        });
    };
    reach.unreachableBlock = ^(Reachability* reach){
        dispatch_sync(dispatch_get_main_queue(), ^{
            SV* disconnect_cb = get_sv("Cocoa::NetworkChange::__disconnect_cb", 0);
            if (disconnect_cb) {
                dSP;
                ENTER;
                SAVETMPS;

                PUSHMARK(SP);
                PUTBACK;

                call_sv(disconnect_cb, G_SCALAR);

                SPAGAIN;

                PUTBACK;
                FREETMPS;
                LEAVE;
            }
        });
    };



( run in 0.652 second using v1.01-cache-2.11-cpan-71847e10f99 )