Check, if online using CallBack

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

Check, if online using CallBack

Post by jamirokwai »

EDIT: For your interest, I removed the question dealing with this, as I think, we found a solution. See the 4th post below by me.

-----

Hi board,

I'd like to share a sample-function to get information about the online-state.
Not with Callback, as I asked here: http://purebasic.fr/english/viewtopic.php?f=19&t=49841

Hope someone can use it. Comments welcome, especially if usable everywhere :-)
If someone has any hint about using a CallBack, please do so... I am interested!

Code: Select all

ImportC "/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration"
  SCNetworkCheckReachabilityByName(target.i,status.i)
EndImport

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

Procedure   Check_Connectivity(URL.s)
  Protected status.i = 0
  Protected result.i = 0
  
  result = SCNetworkCheckReachabilityByName(@url,@status)
  If result
    ProcedureReturn status
  EndIf
EndProcedure

status = Check_Connectivity("www.apple.com")
Select Status
  Case #NetWork_No_Server  : Debug "Don't know this server!"
  Case #NetWork_Is_Online  : Debug "Online!"
  Case #NetWork_Is_Offline : Debug "Offline!"    
EndSelect
Last edited by jamirokwai on Sun May 13, 2012 12:17 pm, edited 2 times in total.
Regards,
JamiroKwai
Polo
Addict
Addict
Posts: 2422
Joined: Tue May 06, 2003 5:07 pm
Location: UK

Re: Check, if online

Post by Polo »

Why not use PB's GetHTTPHeader?
jamirokwai
Enthusiast
Enthusiast
Posts: 772
Joined: Tue May 20, 2008 2:12 am
Location: Cologne, Germany
Contact:

Re: Check, if online

Post by jamirokwai »

Hi Polo,

using GetHTTPHeader() already, but thanks for the hint.
I need to use the CallBack to avoid having to poll the Network every 2 seconds...
My App should fetch a file from my server every time, the MacBook wakes up, and re-establishes the network connection.

My approach is the following snippet, which works fine until the Thread is going to be inserted into the RunLoop (see the kCFRunLoopDefaultMode).

Code: Select all

ImportC "/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration"
  SCNetworkCheckReachabilityByName(target.i,status.i)
  SCNetworkReachabilitySetCallback(target.i,callback.i,context.i)
  SCNetworkReachabilityCreateWithName(nix.i,target.i)
  SCNetworkReachabilityGetFlags(target.i,flags.i)
  SCNetworkReachabilityScheduleWithRunLoop(target.i,runLoop.i,runLoopMode.i)
  CFRunLoopGetCurrent()
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

Procedure   Check_Connectivity(URL.s)
  Protected status.i = 0
  Protected result.i = 0
  
  result = SCNetworkCheckReachabilityByName(@url,@status)
  If result
    ProcedureReturn status
  EndIf
EndProcedure

ProcedureCDLL Check_Connectivity_Callback(target.i,flags.i,info.i)
  Debug "11"
  Debug target
  Debug flags
EndProcedure

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

target.i = 0
target = SCNetworkReachabilityCreateWithName(#Null,@"www.apple.de")
Debug SCNetworkReachabilitySetCallback(target,@Check_Connectivity_Callback(),context)
temp.i = CFRunLoopGetCurrent()
Debug SCNetworkReachabilityScheduleWithRunLoop(target,temp,0) ; @"kCFRunLoopDefaultMode"  ; how?

OpenWindow(0,0,0,0,0,"")

Repeat
  WaitWindowEvent()  
  Delay(10)
ForEver
Regards,
JamiroKwai
jamirokwai
Enthusiast
Enthusiast
Posts: 772
Joined: Tue May 20, 2008 2:12 am
Location: Cologne, Germany
Contact:

Re: Check, if online

Post by jamirokwai »

With the help of Shardik, I think, I could solve this riddle.

If you run this example on Mac OS X, please swith off WiFi or remove the network-cable.
The debugger should show you the current state.

As it seems, Apple defines being online as NOT BEING OFFLINE. If I got it right :-)

Please have a test. Please credit Shardik and me, if you use the snippet in your Apps.

EDIT: Added CFRelease(target) - otherwise, there would be some memory leak. Thanks again, Shardik!

Code: Select all

ImportC "/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration"
  SCNetworkCheckReachabilityByName(target.i,status.i)
  SCNetworkReachabilitySetCallback(target.i,callback.i,context.i)
  SCNetworkReachabilityCreateWithName(nix.i,target.i)
  SCNetworkReachabilityGetFlags(target.i,flags.i)
  SCNetworkReachabilityScheduleWithRunLoop(target.i,runLoop.i,runLoopMode.i)
  CFRunLoopGetCurrent()
  CFRunLoopStop(loopid.i)
  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

Procedure   Check_Connectivity(URL.s)
  Protected status.i = 0
  Protected result.i = 0
  
  result = SCNetworkCheckReachabilityByName(@url,@status)
  If result
    ProcedureReturn status
  EndIf
EndProcedure

ProcedureCDLL Check_Connectivity_Callback(target.i,flags.i,info.i)
  ; you probably will compare the target here with the Target-ID you got earlier
  ; This way, you can determine, if a certain server is online
  If Flags = #NetWork_No_Server
    Debug "No Network-Connection at all."
  ElseIf Flags = #NetWork_Is_Online
    Debug "We are online."
  ElseIf Flags = #Network_Is_Offline
    Debug "We are offline"
  EndIf
EndProcedure

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

; First get the Target-ID
target.i = 0
target = SCNetworkReachabilityCreateWithName(#Null,@"www.apple.com")
If target = 0
  Debug "Could not reach www.apple.com"  
EndIf

; Now se the callback
If SCNetworkReachabilitySetCallback(target,@Check_Connectivity_Callback(),context) = 0
  Debug "Could not set Callback"
EndIf

; Find the Loop from Mac OS X
temp.i = CFRunLoopGetCurrent()

; Add outself to the Loop
If SCNetworkReachabilityScheduleWithRunLoop(target,temp,CFStringCreateWithCString_(0, "kCFRunLoopDefaultMode", 0)) = 0
  Debug "Scheduling failed!"
EndIf

OpenWindow(0,200,200,200,200,"Test")

Repeat
  Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
 
temp = CFRunLoopGetCurrent()
CFRunLoopStop(temp)
CFRelease(target)
Regards,
JamiroKwai
Polo
Addict
Addict
Posts: 2422
Joined: Tue May 06, 2003 5:07 pm
Location: UK

Re: Check, if online

Post by Polo »

Seem to be working fine! :)
jamirokwai
Enthusiast
Enthusiast
Posts: 772
Joined: Tue May 20, 2008 2:12 am
Location: Cologne, Germany
Contact:

Re: Check, if online

Post by jamirokwai »

Polo wrote:Seem to be working fine! :)
Good to hear... More to come about networking :-)
Regards,
JamiroKwai
jamirokwai
Enthusiast
Enthusiast
Posts: 772
Joined: Tue May 20, 2008 2:12 am
Location: Cologne, Germany
Contact:

Re: Check, if online

Post by jamirokwai »

Shardik added some if .. then .. else to make our Callback even better. Thanks for that!
Most probably, you can just copy this to your Mac-App to use it...

Do not make extensive calls or calculations inside the ProcedureCDLL Check_Connectivity_Callback().
For this reason, the CallBack will copy the Flags to Global AmIOnline.i. If - this whenever you need information about being on- or offline.

Code: Select all

ImportC "/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration"
  SCNetworkCheckReachabilityByName(target.i,status.i)
  SCNetworkReachabilitySetCallback(target.i,callback.i,context.i)
  SCNetworkReachabilityCreateWithName(nix.i,target.i)
  SCNetworkReachabilityGetFlags(target.i,flags.i)
  SCNetworkReachabilityScheduleWithRunLoop(target.i,runLoop.i,runLoopMode.i)
  CFRunLoopGetCurrent()
  CFRunLoopStop(loopid.i)
  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 AmIOnline.i = 0 ; you may poll this for changes set by the CallBack

Procedure Check_Connectivity(URL.s)
  Protected status.i = 0
  Protected result.i = 0
  
  result = SCNetworkCheckReachabilityByName(@url,@status)
  If result
    ProcedureReturn status
  EndIf
EndProcedure

ProcedureCDLL Check_Connectivity_Callback(target.i,flags.i,info.i)
  ; you probably will compare the target here with the Target-ID you got earlier
  ; This way, you can determine, if a certain server is online
  If Flags = #NetWork_No_Server
    Debug "No Network-Connection at all."
  ElseIf Flags = #NetWork_Is_Online
    Debug "We are online."
  ElseIf Flags = #Network_Is_Offline
    Debug "We are offline"
  EndIf
  AmIOnline.i = Flags
EndProcedure

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

CallbackIsScheduled = #False

; First get the Target-ID
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)
      CallbackIsScheduled = #True
    Else
      Debug "Scheduling failed!"
    EndIf

    CFRelease(target)
  Else
    Debug "Could not set Callback"
  EndIf
Else
  Debug "Could not reach www.apple.com" 
EndIf

If CallbackIsScheduled
  OpenWindow(0,200,200,200,200,"Check online status")

  Repeat
    Event = WaitWindowEvent()
  Until Event = #PB_Event_CloseWindow
EndIf
Regards,
JamiroKwai
Post Reply