Swicth to use standard wireless library
[wifihood] / wifiscand / wifiscand.c
index 57a5fa9..5f94f2f 100644 (file)
@@ -6,6 +6,38 @@
 #else
 #include <glib.h>
 #include <dbus/dbus.h>
+
+#define WIFISCAN_INTROSPECTION "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n\
+         \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n\
+<node name=\"/org/javiplx/wifiscan\">\n\
+  <interface name=\"org.javiplx.wifiscan\">\n\
+    <method name=\"wakeup\">\n\
+      <arg name=\"result\" type=\"s\" direction=\"out\" />\n\
+    </method>\n\
+    <method name=\"start\">\n\
+      <arg name=\"result\" type=\"s\" direction=\"out\" />\n\
+    </method>\n\
+    <method name=\"scan\">\n\
+      <arg name=\"result\" type=\"s\" direction=\"out\" />\n\
+    </method>\n\
+    <method name=\"stop\">\n\
+      <arg name=\"result\" type=\"s\" direction=\"out\" />\n\
+    </method>\n\
+  </interface>\n\
+</node>\n"
+
+#define OSSO_OK 0
+#define OSSO_ERROR 1
+
+#define osso_context_t DBusConnection
+typedef struct osso_rpc_t_values {
+  int i;
+  char *s;
+  } osso_rpc_t_values;
+typedef struct osso_rpc_t {
+  int type;
+  osso_rpc_t_values value;
+  } osso_rpc_t;
 #endif
 
 #define WIFISCAND_VERSION_STRING  "1.1"
@@ -32,133 +64,41 @@ typedef struct {
 
 /* ------------------------------------------------------------------ WirelessInterface_ScanItem */
 
-static int WirelessInterface_ScanItem(struct iw_event* event, ScanInfo **scaninfo) {
-
-       switch(event->cmd) {
-                                 
-               case SIOCGIWAP: {
+void WirelessInterface_ScanItem(struct wireless_scan* ap, ScanInfo **scaninfo) {
 
                        *scaninfo = (ScanInfo*) malloc( sizeof(ScanInfo) );
                        memset(*scaninfo, 0, sizeof(ScanInfo) );
 
-                       iw_ether_ntop( (const struct ether_addr*)(event->u.ap_addr.sa_data), (*scaninfo)->mac);
-                       return 1;
-               }
+                       iw_sawap_ntop( &ap->ap_addr, (*scaninfo)->mac);
 
-               case IWEVQUAL: {
-                       (*scaninfo)->rssi = event->u.qual.level - 0x100;
-                       return 0;
-               }
+                       (*scaninfo)->rssi = ap->stats.qual.level - 0x100;
+                       (*scaninfo)->noise = ap->stats.qual.level - 0x100;
 
-               default: {
-                        return 0;
-                }
-       }
 }
 
 /* ---------------------------------------------------------------------- */
 
-void* makeScan(WirelessInterface* coso, gchar *message) {
-       struct iwreq          wrq;
-       unsigned char* buffer     = NULL;
-       int            buflen     = IW_SCAN_MAX_DATA;
+void* makeScan(WirelessInterface* wlan, gchar *message) {
+       wireless_scan_head context;
        iwrange        range;
-       int            has_range;
-       struct timeval        tv;
-       int            timeout    = 10000000;
+       int delay = 1;
 
        ScanInfo        **scan = NULL;
 
-       has_range = (iw_get_range_info(coso->sock, coso->ifname, &range) >= 0);
-
-       tv.tv_sec          = 0;
-       tv.tv_usec         = 250000;
-       wrq.u.data.pointer = NULL;
-       wrq.u.data.flags   = 0;
-       wrq.u.data.length  = 0;
-
-       if(iw_set_ext(coso->sock, coso->ifname, SIOCSIWSCAN, &wrq) < 0) {
-               if(errno != EPERM) {
-                       message = "Interface doesn't support scanning";
-                       return NULL;
-               }
-               tv.tv_usec = 0;
-       }
-       timeout -= tv.tv_usec;
-
-       while(1) {
-               fd_set rfds;
-               int    last_fd;
-               int    ret;
-
-               FD_ZERO(&rfds);
-               last_fd = -1;
-
-               ret = select(last_fd + 1, &rfds, NULL, NULL, &tv);
-
-               if(ret < 0) {
-                       if(errno == EAGAIN || errno == EINTR) continue;
-                       
-                       else {
-                               message = "Unknown scanning error";
-                               return NULL;
-                       }
-               }
+       iw_get_range_info(wlan->sock, wlan->ifname, &range);
 
-               if(!ret) {
-                       unsigned char* newbuf;
+       /* We don't call iw_scan to allow fine control of delays and timeouts */
+       context.result = NULL;
+       context.retry = 0;
 
-                       realloc:
-                       newbuf = (unsigned char*) realloc(buffer, buflen);
-                       
-                       if(!newbuf) {
-                               if(buffer) free(buffer);
-                               message = "Memory allocation failure in scan";
-                               return NULL;
-                       }
-                       
-                       buffer = newbuf;
-
-                       wrq.u.data.pointer = buffer;
-                       wrq.u.data.flags   = 0;
-                       wrq.u.data.length  = buflen;
-                       
-                       if(iw_get_ext(coso->sock, coso->ifname, SIOCGIWSCAN, &wrq) < 0) {
-                               if((errno == E2BIG)) {
-                                       if(wrq.u.data.length > buflen) buflen = wrq.u.data.length;
-                                       else buflen *= 2;
-
-                                       goto realloc;
-                               }
-
-                               if(errno == EAGAIN) {
-                                       tv.tv_sec   = 0;
-                                       tv.tv_usec  = 100000;
-                                       timeout    -= tv.tv_usec;
-                                       
-                                       if(timeout > 0) continue;
-                               }
-
-                               free(buffer);
-                               
-                               message = "Unable to read scan data";
-
-                               return NULL;
-                       }
-                       
-                       else break;
+       while(delay>0) {
+               delay = iw_process_scan(wlan->sock, wlan->ifname, range.we_version_compiled, &context);
+               if(delay < 0) break;
+               usleep(delay * 1000);
                }
-       }
 
+       if ( delay == 0 ) {
 
-       if(wrq.u.data.length)   {
-               struct iw_event      iwe;
-               stream_descr stream;
-               int          ret;
-               void*    scan_dict = NULL;
-               
-               iw_init_event_stream(&stream, (char*)(buffer), wrq.u.data.length);
-               
                scan = (ScanInfo**) malloc( 25 * sizeof(ScanInfo *) );
                memset(scan, 0, 25 * sizeof(ScanInfo *) );
                *scan = NULL;
@@ -167,27 +107,20 @@ void* makeScan(WirelessInterface* coso, gchar *message) {
 
                i = 0;
                ScanInfo *sc = NULL;
-               do {
-                       ret = iw_extract_event_stream(&stream, &iwe, range.we_version_compiled);
-               
-                       if(ret > 0) {
-                               int sr = WirelessInterface_ScanItem(&iwe, &sc);
-                               if(sr && i<25) {
+
+               /* Extract values */
+               struct wireless_scan *ap = context.result;
+               while ( ap != NULL && i < 25 ) {
+                               WirelessInterface_ScanItem(ap, &sc);
                                        *(scan+i) = sc;
+                                       ap = ap->next;
                                        i++;
-                               }
                        }
-               }
-               
-               while(ret > 0);
 
        } else {
                message = "Unknown error";
-               free(buffer);
-               return NULL;
        }
 
-       free(buffer);
        return scan;
 }
 
@@ -233,6 +166,14 @@ gint dbus_req_handler(const gchar * interface, const gchar * method,
     retval->value.s = (gchar*) malloc( sizeof(gchar *) );
     retval->value.s[0] = '\0';
 
+#ifndef HAVE_LIBOSSO
+    if ( strcmp(method,"Introspect")==0 ) {
+        retval->value.s = (gchar *) realloc(retval->value.s,630*sizeof(gchar *));
+        snprintf(retval->value.s,strlen(WIFISCAN_INTROSPECTION),WIFISCAN_INTROSPECTION);
+        return OSSO_OK;
+    }
+#endif
+
     if ( strcmp(method,"wakeup")==0 ) {
         retval->value.s = (gchar *) realloc(retval->value.s,16*sizeof(gchar *));
         snprintf(retval->value.s,16,"WifiScand ready");
@@ -282,14 +223,14 @@ gint dbus_req_handler(const gchar * interface, const gchar * method,
        appdata->iface.sock = 0;
 #ifdef HAVE_LIBOSSO
         osso_deinitialize(appdata->osso_context);
-#else
-       dbus_deinitialize(appdata->osso_context);
-#endif
         /* Instead of exiting, signaling finish to main loop could be better
         retval->value.s = (gchar *) realloc(retval->value.s,34*sizeof(gchar *));
         snprintf(retval->value.s,34,"Interface moved to original state");
         */
         exit(0);
+#else
+        return OSSO_OK;
+#endif
     }
 
     if ( strcmp(method,"scan")==0 ) {
@@ -323,18 +264,7 @@ gint dbus_req_handler(const gchar * interface, const gchar * method,
 
 #ifndef HAVE_LIBOSSO
 
-#define OSSO_OK 0
-#define OSSO_ERROR 1
-
-#define osso_context_t DBusConnection
-typedef struct osso_rpc_t_values {
-  int i;
-  char *s;
-  } osso_rpc_t_values;
-typedef struct osso_rpc_t {
-  int type;
-  osso_rpc_t_values value;
-  } osso_rpc_t;
+dbus_bool_t stopped_service = FALSE;
 
 static DBusObjectPathVTable *vtable = NULL;
 
@@ -383,6 +313,9 @@ static DBusHandlerResult handler_wrapper (DBusConnection  *connection,
                                dbus_message_get_member(message),
                                NULL, data, retval);
 
+               if ( strcmp(dbus_message_get_member(message),"stop")==0 )
+                       stopped_service = TRUE;
+
                if ( retval->value.s != NULL ) {
                        DBusMessage *reply = dbus_message_new_method_return (message);
                        if (reply == NULL)
@@ -413,7 +346,7 @@ int main( void ) {
        osso_context = osso_initialize(OSSO_NAME, WIFISCAND_VERSION_STRING, TRUE, NULL);
 #else
        dbus_error_init(&error);
-       osso_context = dbus_bus_get(DBUS_BUS_STARTER, &error);
+       osso_context = dbus_bus_get(DBUS_BUS_SESSION, &error);
 #endif
 
        /* Check that initialization was ok */
@@ -454,7 +387,7 @@ int main( void ) {
        event_loop = g_main_loop_new(NULL, FALSE);
        g_main_loop_run(event_loop);
 #else
-       while (dbus_connection_read_write_dispatch (osso_context, -1)) {}
+       while (dbus_connection_read_write_dispatch(osso_context, -1) && stopped_service==FALSE) {}
 #endif
 
        /* Deinitialize OSSO */