source: trunk/LocationDo/SCNetworkReachabilitymodule.c @ 295

Last change on this file since 295 was 205, checked in by Nicholas Riley, 15 years ago

LocationDo?.py: Add a bunch of TODOs, and some more locations and
actions.

action.py: Add a TODO.

SCNetworkReachabilitymodule.c: Add a TODO.

File size: 2.7 KB
Line 
1#include "Python.h"
2
3#include <SystemConfiguration/SystemConfiguration.h>
4
5#define SCNR_REACHABLE "SCNetworkIsReachable"
6static CFStringRef SCNR_Reachable = CFSTR(SCNR_REACHABLE);
7static SCNetworkReachabilityContext SCNR_Context = {0, NULL, NULL, NULL, NULL};
8
9static void
10SCNR_callback(SCNetworkReachabilityRef target,
11              SCNetworkConnectionFlags flags, void *tagString);
12
13static Boolean
14SCNR_reachable(SCNetworkConnectionFlags flags) {
15  /* not reachable if it requires a non-automatic connection */
16  return ((flags & kSCNetworkFlagsReachable) &&
17          (!(flags & kSCNetworkFlagsConnectionRequired) ||
18           (flags & kSCNetworkFlagsConnectionAutomatic)));
19}
20
21/* XXX should have a way to cancel (e.g. on location detach) */
22
23static void
24SCNR_schedule(CFStringRef tagString,
25              SCNetworkReachabilityRef target) {
26  SCNR_Context.info = (void *)tagString;
27  SCNetworkReachabilitySetCallback(target, SCNR_callback, &SCNR_Context);
28  SCNetworkReachabilityScheduleWithRunLoop(target,
29                                           CFRunLoopGetCurrent(),
30                                           kCFRunLoopDefaultMode);
31}
32
33static void
34SCNR_callback(SCNetworkReachabilityRef target,
35              SCNetworkConnectionFlags flags, void *tagString) {
36  if (SCNR_reachable(flags)) {
37    CFNotificationCenterPostNotification(CFNotificationCenterGetLocalCenter(),
38                                         SCNR_Reachable, tagString, NULL, false);
39    CFRelease((CFStringRef)tagString);
40  } else {
41    SCNR_schedule(tagString, target);
42  }
43}
44
45static PyObject *
46SCNR_notify_when_reachable(PyObject *self, PyObject *args) {
47  const char *hostname;
48  const char *tag;
49  if (!PyArg_ParseTuple(args, "ss", &hostname, &tag))
50    return NULL;
51
52  SCNetworkConnectionFlags flags;
53  if (SCNetworkCheckReachabilityByName(hostname, &flags) &&
54      SCNR_reachable(flags))
55    return PyBool_FromLong(0);
56
57  SCNetworkReachabilityRef target =
58    SCNetworkReachabilityCreateWithName(NULL, hostname);
59  CFStringRef tagString =
60    CFStringCreateWithCString(NULL, tag, kCFStringEncodingUTF8);
61
62  SCNR_schedule(tagString, target);
63
64  return PyBool_FromLong(1);
65}
66
67
68static PyMethodDef SCNetworkReachabilitymodule_methods[] = {
69  {"notify_when_reachable", SCNR_notify_when_reachable, METH_VARARGS,
70   "notify_when_reachable(hostname, tag) -> bool\n\n"
71   "Deliver the SCNetworkIsReachable runloop notification with object tag\n"
72   "when the host becomes reachable, or return false if it's currently\n"
73   "reachable."},
74  {NULL, NULL, 0, NULL}
75};
76
77PyMODINIT_FUNC
78initSCNetworkReachability(void) {
79  PyObject *module = Py_InitModule("SCNetworkReachability",
80                                   SCNetworkReachabilitymodule_methods);
81  PyObject *dict = PyModule_GetDict(module);
82  PyObject *reachable = PyString_FromString(SCNR_REACHABLE);
83  PyDict_SetItemString(dict, SCNR_REACHABLE, reachable);
84  Py_DECREF(reachable);
85}
Note: See TracBrowser for help on using the repository browser.