Reachability via NotificationCenter [edit, working code inside]

Mac OSX specific forum
jamirokwai
Enthusiast
Enthusiast
Posts: 771
Joined: Tue May 20, 2008 2:12 am
Location: Cologne, Germany
Contact:

Reachability via NotificationCenter [edit, working code inside]

Post by jamirokwai »

Hi there,

I am trying to subscribe to NotificationCenter to be notified when network-connection has changed. I found this one link, but can't get my head around it.

https://www.appsloveworld.com/swift/100 ... on-and-net

I am aware of this one, but don't know how to change it.

viewtopic.php?p=503943#p503943

Any help appreciated :-)
Last edited by jamirokwai on Wed Jun 07, 2023 5:48 pm, edited 1 time in total.
Regards,
JamiroKwai
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Reachability via NotificationCenter?

Post by wilbert »

The code you are referring to uses a custom class named Reachability.
https://github.com/tonymillion/Reachabi ... hability.h
https://github.com/tonymillion/Reachabi ... hability.m
The code of the class is based on SCNetworkReachability so I think you should use SCNetworkReachability.

https://developer.apple.com/documentati ... guage=objc
Windows (x64)
Raspberry Pi OS (Arm64)
jamirokwai
Enthusiast
Enthusiast
Posts: 771
Joined: Tue May 20, 2008 2:12 am
Location: Cologne, Germany
Contact:

Re: Reachability via NotificationCenter?

Post by jamirokwai »

Thanks, Wilbert. I will have a look!
Regards,
JamiroKwai
jamirokwai
Enthusiast
Enthusiast
Posts: 771
Joined: Tue May 20, 2008 2:12 am
Location: Cologne, Germany
Contact:

Re: Reachability via NotificationCenter?

Post by jamirokwai »

I found an older code of mine. But it throws the error "clang: error: no such file or directory: '/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration'".

As I currently have no time to investigate further, I pin it down here and come back later.

Code: Select all

    
ImportC "/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration"
  SCNetworkReachabilitySetCallback(target.i,callback.i,context.i)
  SCNetworkReachabilityCreateWithName(nix.i,target.i)
  SCNetworkReachabilityScheduleWithRunLoop(target.i,runLoop.i,runLoopMode.i)
  CFRunLoopGetCurrent()
  CFRelease(target.i)
EndImport

Structure SCNetworkReachabilityContext
  version.i
  info.i
  retain.i
  release.i
  copyDescription.i      
EndStructure

#NetWork_No_Server  = 0
#NetWork_Is_Online  = 2
#NetWork_Is_Offline = 7

context.SCNetworkReachabilityContext

With context
  \version = 0
  \info = @"www.apple.com"
  \retain = #Null
  \release = #Null
  \copyDescription = #Null
EndWith

Global IAmOnline = -1

ProcedureCDLL Check_Connectivity_Callback(target.i,flags.i,info.i) ; OK
  Select Flags
    Case #NetWork_Is_Online  : IAmOnline = 1
    Case #NetWork_Is_Offline,#NetWork_No_Server : IAmOnline = 0
;     Case #NetWork_No_Server  : IAmOnline = -1
  EndSelect
EndProcedure

Procedure   Init_CallBack() ; OK
  target = SCNetworkReachabilityCreateWithName(#Null,@"www.apple.com")

  If target
    ; Now set the callback
    If SCNetworkReachabilitySetCallback(target,@Check_Connectivity_Callback(),context)
      ; Find PB's window event loop
      temp.i = CFRunLoopGetCurrent()

      ; Add ourself to the loop
      If SCNetworkReachabilityScheduleWithRunLoop(target,temp,CFStringCreateWithCString_(0, "kCFRunLoopDefaultMode", 0))
        CFRelease(temp)
      Else
        Debug "Scheduling failed!"
      EndIf

      CFRelease(target)
    Else
    Debug "Could not set Callback"
    EndIf
  Else
    Debug "Could not reach www.apple.com" 
  EndIf
EndProcedure
Regards,
JamiroKwai
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Reachability via NotificationCenter?

Post by wilbert »

You can try

Code: Select all

ImportC "-framework SystemConfiguration"
instead of

Code: Select all

ImportC "/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration"
Windows (x64)
Raspberry Pi OS (Arm64)
jamirokwai
Enthusiast
Enthusiast
Posts: 771
Joined: Tue May 20, 2008 2:12 am
Location: Cologne, Germany
Contact:

Re: Reachability via NotificationCenter?

Post by jamirokwai »

wilbert wrote: Mon May 15, 2023 9:28 am You can try

Code: Select all

ImportC "-framework SystemConfiguration"
instead of

Code: Select all

ImportC "/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration"
Hi WIlbert,

thanks. That did the trick!
The code seems to be correct, but the Callback is never called back. I get -1 in the debugger window all the time. Any ideas?

Code: Select all

EnableExplicit

ImportC "-framework SystemConfiguration"
  SCNetworkReachabilitySetCallback(target.i,callback.i,context.i)
  SCNetworkReachabilityCreateWithName(nix.i,target.i)
  SCNetworkReachabilityScheduleWithRunLoop(target.i,runLoop.i,runLoopMode.i)
  CFRunLoopGetCurrent()
  CFRelease(target.i)
EndImport

Structure SCNetworkReachabilityContext
  version.i
  info.i
  retain.i
  release.i
  copyDescription.i 
EndStructure

#NetWork_No_Server  = 0
#NetWork_Is_Online  = 2
#NetWork_Is_Offline = 7

Global context.SCNetworkReachabilityContext

With context
  \version = 0
  \info = @"www.apple.com"
  \retain = #Null
  \release = #Null
  \copyDescription = #Null
EndWith

Global IAmOnline = -1

ProcedureCDLL Check_Connectivity_Callback(target.i,flags.i,info.i) ; OK
  Debug flags
  Select Flags
    Case #NetWork_Is_Online  : IAmOnline = 1
    Case #NetWork_Is_Offline,#NetWork_No_Server : IAmOnline = 0
    Case #NetWork_No_Server  : IAmOnline = -1
  EndSelect
EndProcedure

Procedure   Init_CallBack() ; OK
  Define target = SCNetworkReachabilityCreateWithName(#Null,@"www.apple.com")
  
  If target
    ; Now set the callback
    If SCNetworkReachabilitySetCallback(target,@Check_Connectivity_Callback(),#Null); context)
      ; Find PB's window event loop
      Define temp.i = CFRunLoopGetCurrent()
      
      ; Add ourself to the loop
      If SCNetworkReachabilityScheduleWithRunLoop(target,temp,CFStringCreateWithCString_(0, "kCFRunLoopDefaultMode", 0))
        CFRelease(temp)
      Else
        Debug "Scheduling failed!"
      EndIf
      
      CFRelease(target)
    Else
      Debug "Could not set Callback"
    EndIf
  Else
    Debug "Could not reach www.apple.com" 
  EndIf
EndProcedure

Init_CallBack()
OpenWindow(0,100,100,100,100,"bla")
Repeat
  Define event = WaitWindowEvent(500)
  Debug IAmOnline
ForEver
Regards,
JamiroKwai
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Reachability via NotificationCenter?

Post by wilbert »

I couldn't get it working with SCNetworkReachabilityScheduleWithRunLoop but with SCNetworkReachabilitySetDispatchQueue the callback is called.

Code: Select all

EnableExplicit

ImportC "-framework SystemConfiguration"
  dispatch_queue_create(label.p-utf8, attr.i)
  SCNetworkReachabilityCreateWithName(allocator.i, nodename.p-utf8)
  SCNetworkReachabilitySetCallback(target.i, callout.i, context.i)
  SCNetworkReachabilitySetDispatchQueue(target.i, queue.i)
EndImport

#kSCNetworkReachabilityFlagsReachable = 2

Global IAmOnline = 0
Global reachability = #Null
Global reachabilitySerialQueue = dispatch_queue_create("com.pb_example.reachability", #Null)

ProcedureCDLL Check_Connectivity_Callback(target.i, flags.i, info.i)
  IAmOnline = Bool(flags & #kSCNetworkReachabilityFlagsReachable)
EndProcedure

Procedure Init_CallBack()
  If reachability = #Null
    reachability = SCNetworkReachabilityCreateWithName(#Null, "www.apple.com")
    If reachability
      If SCNetworkReachabilitySetCallback(reachability, @Check_Connectivity_Callback(), #Null)
        If Not SCNetworkReachabilitySetDispatchQueue(reachability, reachabilitySerialQueue)
          SCNetworkReachabilitySetCallback(reachability, #Null, #Null)
          Debug "Scheduling failed!"
        EndIf
      Else
        Debug "Could not set Callback"
      EndIf
    Else
      Debug "Could not reach www.apple.com" 
    EndIf
  EndIf
EndProcedure

Init_CallBack()
OpenWindow(0,100,100,100,100,"bla")
Repeat
  Define event = WaitWindowEvent(500)
  Debug IAmOnline
Until event = #PB_Event_CloseWindow

; Cleanup
If reachability
  SCNetworkReachabilitySetCallback(reachability, #Null, #Null)
  SCNetworkReachabilitySetDispatchQueue(reachability, #Null)
  CFRelease_(reachability)
  reachability = #Null
EndIf
Windows (x64)
Raspberry Pi OS (Arm64)
jamirokwai
Enthusiast
Enthusiast
Posts: 771
Joined: Tue May 20, 2008 2:12 am
Location: Cologne, Germany
Contact:

Re: Reachability via NotificationCenter?

Post by jamirokwai »

Wow. Wilbert, thanks a lot, that works!
wilbert wrote: Wed May 24, 2023 10:59 am I couldn't get it working with SCNetworkReachabilityScheduleWithRunLoop but with SCNetworkReachabilitySetDispatchQueue the callback is called.

Code: Select all

EnableExplicit

ImportC "-framework SystemConfiguration"
  dispatch_queue_create(label.p-utf8, attr.i)
  SCNetworkReachabilityCreateWithName(allocator.i, nodename.p-utf8)
  SCNetworkReachabilitySetCallback(target.i, callout.i, context.i)
  SCNetworkReachabilitySetDispatchQueue(target.i, queue.i)
EndImport

#kSCNetworkReachabilityFlagsReachable = 2

Global IAmOnline = 0
Global reachability = #Null
Global reachabilitySerialQueue = dispatch_queue_create("com.pb_example.reachability", #Null)

ProcedureCDLL Check_Connectivity_Callback(target.i, flags.i, info.i)
  IAmOnline = Bool(flags & #kSCNetworkReachabilityFlagsReachable)
EndProcedure

Procedure Init_CallBack()
  If reachability = #Null
    reachability = SCNetworkReachabilityCreateWithName(#Null, "www.apple.com")
    If reachability
      If SCNetworkReachabilitySetCallback(reachability, @Check_Connectivity_Callback(), #Null)
        If Not SCNetworkReachabilitySetDispatchQueue(reachability, reachabilitySerialQueue)
          SCNetworkReachabilitySetCallback(reachability, #Null, #Null)
          Debug "Scheduling failed!"
        EndIf
      Else
        Debug "Could not set Callback"
      EndIf
    Else
      Debug "Could not reach www.apple.com" 
    EndIf
  EndIf
EndProcedure

Init_CallBack()
OpenWindow(0,100,100,100,100,"bla")
Repeat
  Define event = WaitWindowEvent(500)
  Debug IAmOnline
Until event = #PB_Event_CloseWindow

; Cleanup
If reachability
  SCNetworkReachabilitySetCallback(reachability, #Null, #Null)
  SCNetworkReachabilitySetDispatchQueue(reachability, #Null)
  CFRelease_(reachability)
  reachability = #Null
EndIf
Regards,
JamiroKwai
User avatar
PureBasti
New User
New User
Posts: 8
Joined: Sat Oct 13, 2018 9:02 am

Re: Reachability via NotificationCenter [edit, working code inside]

Post by PureBasti »

Hey everyone :)
First, thanks for the great examples!

I am trying to get it work with the Procedure:
SCNetworkReachabilityCreateWithAddressPair

But I dont get it :(
Does anyone know how this works?

Here the Apple reference https://developer.apple.com/documentati ... guage=objc

Code: Select all

EnableExplicit


Structure sockkaddr 
  sa_family.a
  sa_data.s
EndStructure
  
Structure in_addr
  s_addr.l
EndStructure
  
Structure sockaddr_in
  sin_addr.in_addr
  sin_family.w
  ;sin_len.i
  sin_port.u
  ;sin_zero.a[8]
EndStructure


ImportC "-framework SystemConfiguration"
  dispatch_queue_create(label.p-utf8, attr.i)
  SCNetworkReachabilityCreateWithAddressPair(allocator.i, *localAddress.sockaddr_in, *remoteAddress.sockaddr_in)
  SCNetworkReachabilitySetCallback(target.i, callout.i, context.i)
  SCNetworkReachabilitySetDispatchQueue(target.i, queue.i)
EndImport

#kSCNetworkReachabilityFlagsReachable = 2
#AF_INET = 2 ; Internet IP Protocol


Global reachability = #Null
Global reachabilitySerialQueue = dispatch_queue_create("com.pb_example.reachability", #Null)
Global localAddress.sockaddr_in
Global remoteAddress.sockaddr_in


Procedure Init_CallBack()
  
  localAddress\sin_addr\s_addr = 3232240180
  localAddress\sin_family = #AF_INET
  localAddress\sin_port = 3490
  
  remoteAddress\sin_addr\s_addr = 3232240180
  remoteAddress\sin_family = #AF_INET
  remoteAddress\sin_port = 3490
  
  If reachability = #Null
    reachability = SCNetworkReachabilityCreateWithAddressPair(#Null, @localAddress, @remoteAddress)
    Debug reachability
    If reachability
      Debug "Reachability reference created!"
    Else 
      Debug "error"
    EndIf
  EndIf
EndProcedure


;- main
Init_CallBack()
OpenWindow(0,100,100,100,100,"bla")

;- loop
Repeat
  Define event = WaitWindowEvent(500)
Until event = #PB_Event_CloseWindow

; Cleanup
If reachability
  SCNetworkReachabilitySetCallback(reachability, #Null, #Null)
  SCNetworkReachabilitySetDispatchQueue(reachability, #Null)
  CFRelease_(reachability)
  reachability = #Null
EndIf
Fred
Administrator
Administrator
Posts: 16619
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Reachability via NotificationCenter [edit, working code inside]

Post by Fred »

Always use the Align #PB_Structure_AlignC for C imported structures, or you will have misalignment issues.
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Reachability via NotificationCenter [edit, working code inside]

Post by mk-soft »

Attention!

With macOS the structure 'SOCKADDR_IN' is somewhat different than with Windows or Linux. The length of the structure must be entered before use. (sin_len)

Code: Select all

;-- Contants

#AF_UNSPEC = 0
#AF_INET = 2
CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Windows
    #AF_INET6 = 23
  CompilerCase #PB_OS_Linux
    #AF_INET6 = 10
  CompilerCase #PB_OS_MacOS
    #AF_INET6 = 30
CompilerEndSelect

#PF_UNSPEC = #AF_UNSPEC
#PF_INET = #AF_INET
#PF_INET6 = #AF_INET6

#AI_CANONNAME = 2

#SOCK_STREAM = 1

;-- Structures

CompilerIf Not Defined(in_addr, #PB_Structure)
  Structure in_addr
    StructureUnion
      s_b.a[4]
      s_w.u[2]
      s_addr.l
    EndStructureUnion
  EndStructure
CompilerEndIf

CompilerIf Not Defined(in6_addr, #PB_Structure)
  Structure in6_addr
    s6_addr.a[16]
  EndStructure
CompilerEndIf

CompilerIf Not Defined(SOCKADDR, #PB_Structure)
  Structure SOCKADDR
    sa_family.w
    sa_data.b[14]
  EndStructure
CompilerEndIf

CompilerIf Not Defined(SOCKADDR_IN4, #PB_Structure)
  Structure SOCKADDR_IN4
    CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
      sin_len.a
      sin_family.a
    CompilerElse
      sin_family.w
    CompilerEndIf
    sin_port.w
    sin_addr.in_addr
    sin_zero.b[8]
  EndStructure
CompilerEndIf

CompilerIf Not Defined(SOCKADDR_IN6, #PB_Structure)
  Structure SOCKADDR_IN6
    CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
      sin6_len.a
      sin6_family.a
    CompilerElse
      sin6_family.w
    CompilerEndIf
    sin6_port.w
    sin6_flowinfo.l
    sin6_addr.in6_addr
    sin6_scope_id.l
  EndStructure
CompilerEndIf

CompilerIf #PB_Compiler_OS = #PB_OS_Linux
  
  Structure addrinfo
    ai_flags.l
    ai_family.l
    ai_socktype.l
    ai_protocol.l
    ai_addrlen.l
    PB_align4.l
    StructureUnion
      *ai_addr.SOCKADDR;
      *ai_addr_in.SOCKADDR_IN4;
      *ai_addr_in6.SOCKADDR_IN6;
    EndStructureUnion
    *ai_canonname
    *ai_next.addrinfo;
  EndStructure
  
CompilerElse
  
  Structure addrinfo
    ai_flags.l
    ai_family.l
    ai_socktype.l
    ai_protocol.l
    ai_addrlen.l
    PB_Align4.l
    *ai_canonname
    StructureUnion
      *ai_addr.SOCKADDR;
      *ai_addr_in.SOCKADDR_IN4;
      *ai_addr_in6.SOCKADDR_IN6;
    EndStructureUnion
    *ai_next.addrinfo;
  EndStructure
  
CompilerEndIf  

My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
PureBasti
New User
New User
Posts: 8
Joined: Sat Oct 13, 2018 9:02 am

Re: Reachability via NotificationCenter [edit, working code inside]

Post by PureBasti »

Thank you Fred, thank you mk-soft, I will try it again :)
Post Reply