wifi_stumbler.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2013, Seigo ITO
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of Seigo ITO nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #include "wifi_stumbler.h"
00031 
00032 
00033 
00034 WifiStumbler::WifiStumbler()
00035 {
00036 }
00037 
00038 
00039 
00040 WifiStumbler::~WifiStumbler()
00041 {
00042   iw_sockets_close(wlan_sock_);
00043 }
00044 
00045 
00046 
00047 wifi_tools::WifiData WifiStumbler::getData()
00048 {
00049   return wifi_stumble_;
00050 }
00051 
00052 
00053 
00054 void WifiStumbler::setFrame(std::string frame_id)
00055 {
00056   wifi_stumble_.header.frame_id = frame_id;
00057 }
00058 
00059 
00060 
00061 bool WifiStumbler::initialize(std::string wlan_if)
00062 {
00063   wlan_if_ = wlan_if;
00064   wlan_sock_ = iw_sockets_open();
00065   if(wlan_sock_<0)
00066   {
00067    ROS_ERROR("Failed to open wlan socket on %s", wlan_if_.c_str());
00068    return false;
00069   }
00070   return true;
00071 }
00072 
00073 
00074 
00075 bool WifiStumbler::stumble()
00076 {
00077   int pid;
00078   pid = getpid();
00079 
00080   struct iwreq w_request;
00081   w_request.u.data.pointer = (caddr_t)&pid;
00082   w_request.u.data.length = 0;
00083 
00084   if (iw_set_ext(wlan_sock_, wlan_if_.c_str(), SIOCSIWSCAN, &w_request) < 0)
00085   {
00086     ROS_ERROR("Couldn't start stumbler.");
00087     return false;
00088   }
00089 
00090   timeval time;
00091   time.tv_sec = 0;
00092   time.tv_usec = 200000;
00093 
00094   uint8_t *p_buff = NULL;
00095   int buff_size = IW_SCAN_MAX_DATA;
00096 
00097   bool is_end = false;
00098   while(!is_end)
00099   {
00100     fd_set fds;
00101     int ret;
00102     FD_ZERO(&fds);
00103     ret = select(0, &fds, NULL, NULL, &time);
00104     if (ret == 0)
00105     {
00106       uint8_t *p_buff2;
00107       while (!is_end)
00108       {
00109         p_buff2 = (uint8_t *)realloc(p_buff, buff_size);
00110         p_buff = p_buff2;
00111         w_request.u.data.pointer = p_buff;
00112         w_request.u.data.flags = 0;
00113         w_request.u.data.length = buff_size;
00114         if (iw_get_ext(wlan_sock_, wlan_if_.c_str(), SIOCGIWSCAN, &w_request) < 0)
00115         {
00116           if (errno == E2BIG && range_.we_version_compiled > 16)
00117           {
00118             if (w_request.u.data.length > buff_size)
00119               buff_size = w_request.u.data.length;
00120             else
00121               buff_size *= 2;
00122             continue;
00123           }
00124           else if (errno == EAGAIN)
00125           {
00126             time.tv_sec = 0;
00127             time.tv_usec = 200000;
00128             break;
00129           }
00130         }
00131         else
00132           is_end = true;
00133       }
00134     }
00135   }
00136 
00137   // Put wifi data into ROS message
00138   wifi_tools::AccessPoint ap;
00139   iw_event event;
00140   stream_descr stream;
00141 
00142   wifi_stumble_.data.clear();
00143   wifi_stumble_.header.stamp = ros::Time::now();
00144 
00145   iw_init_event_stream(&stream, (char *)p_buff, w_request.u.data.length);
00146   is_end = false;
00147   int value = 0;
00148   while(!is_end)
00149   {
00150     value = iw_extract_event_stream(&stream, &event, range_.we_version_compiled);
00151     if(!(value>0))
00152     {
00153       is_end = true;
00154     }
00155     else
00156     {
00157       if(event.cmd == IWEVQUAL)
00158       {
00159         // quality part of statistics
00160         //ROS_INFO("command=IWEVQUAL");
00161         if (event.u.qual.level != 0 || (event.u.qual.updated & (IW_QUAL_DBM | IW_QUAL_RCPI)))
00162         {
00163           ap.noise = event.u.qual.noise;
00164           ap.ss    = event.u.qual.level;
00165         }
00166       }
00167       else if(event.cmd == SIOCGIWAP)
00168       {
00169         // get access point MAC addresses
00170         //ROS_INFO("command=SIOCGIWAP");
00171         char mac_buff[1024];
00172         iw_ether_ntop((const struct ether_addr *)&event.u.ap_addr.sa_data,mac_buff);
00173         ap.mac_address = std::string(mac_buff);
00174         ROS_INFO("mac_addr=%s",mac_buff);
00175       }
00176       else if(event.cmd == SIOCGIWESSID)
00177       {
00178         // get ESSID
00179         //ROS_INFO("command=SIOCGIWESSID");
00180         wifi_stumble_.data.push_back(ap);
00181       }
00182       else if(event.cmd == SIOCGIWENCODE)
00183       {
00184         // get encoding token & mode
00185         //ROS_INFO("command=SIOCGIWENCODE");
00186       }
00187       else if(event.cmd == SIOCGIWFREQ)
00188       {
00189         // get channel/frequency (Hz)
00190         //ROS_INFO("command=SIOCGIWFREQ");
00191       }
00192       else if(event.cmd == SIOCGIWRATE)
00193       {
00194         // get default bit rate (bps)
00195         //ROS_INFO("command=SIOCGIWRATE");
00196       }
00197       else if(event.cmd == SIOCGIWMODE)
00198       {
00199         // get operation mode
00200         //ROS_INFO("command=SIOCGIWMODE");
00201 
00202       }
00203       else if(event.cmd == IWEVCUSTOM)
00204       {
00205         // Driver specific ascii string
00206         //ROS_INFO("command=IWEVCUSTOM");
00207       }
00208       else if(event.cmd == IWEVGENIE)
00209       {
00210         // Generic IE (WPA, RSN, WMM, ..)
00211         //ROS_INFO("command=IWEVGENIE");
00212       }
00213       else
00214       {
00215         // another command
00216         //ROS_INFO("another command");
00217       }
00218     }
00219   }
00220 
00221   checkDuplication();
00222 
00223   return true;
00224 }
00225 
00226 
00227 
00228 void WifiStumbler::checkDuplication()
00229 {
00230   //check duplication of MAC
00231   std::map<std::string,wifi_tools::AccessPoint> ap_map;
00232   std::map<std::string,wifi_tools::AccessPoint>::iterator it_map;
00233   std::vector<wifi_tools::AccessPoint>::iterator it;
00234   std::string mac;
00235 
00236   it = wifi_stumble_.data.begin();
00237   while( it != wifi_stumble_.data.end() )
00238   {
00239     mac = (std::string)(*it).mac_address;
00240     if( ap_map.find(mac) == ap_map.end())
00241     {
00242       // new access point
00243       ap_map.insert( std::map<std::string,wifi_tools::AccessPoint>::value_type(mac,*it) );
00244     }
00245     else
00246     {
00247       // duplicate access point
00248       //TODO FIFO, or something else?
00249     }
00250     ++it;
00251   }
00252 
00253   wifi_stumble_.data.clear();
00254   it_map = ap_map.begin();
00255   while( it_map != ap_map.end() )
00256   {
00257     wifi_stumble_.data.push_back(it_map->second);
00258     ++it_map;
00259   }
00260 }
00261 
00262 


wifi_tools
Author(s): Seigo ITO
autogenerated on Mon Oct 6 2014 12:23:56