wifi_comm_lib.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 *
00003 * Software License Agreement (BSD License)
00004 *
00005 *  Copyright (c) 2010, ISR University of Coimbra.
00006 *  All rights reserved.
00007 *
00008 *  Redistribution and use in source and binary forms, with or without
00009 *  modification, are permitted provided that the following conditions
00010 *  are met:
00011 *
00012 *   * Redistributions of source code must retain the above copyright
00013 *     notice, this list of conditions and the following disclaimer.
00014 *   * Redistributions in binary form must reproduce the above
00015 *     copyright notice, this list of conditions and the following
00016 *     disclaimer in the documentation and/or other materials provided
00017 *     with the distribution.
00018 *   * Neither the name of the ISR University of Coimbra nor the names of its
00019 *     contributors may be used to endorse or promote products derived
00020 *     from this software without specific prior written permission.
00021 *
00022 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033 *  POSSIBILITY OF SUCH DAMAGE.
00034 *
00035 * Author: Gonçalo Cabrita and Pedro Sousa
00036 *********************************************************************/
00037 #include "wifi_comm/wifi_comm_lib.h"
00038 
00039 wifi_comm::WiFiComm::WiFiComm(void(*fp)(char * ip)) : n_()
00040 {
00041         ROS_ERROR("Using the constructor wifi_comm::WiFiComm::WiFiComm(void(*)(char*)) is deprecated. Please change to wifi_comm::WiFiComm::WiFiComm(boost::function<void(char*)>)");
00042 
00043         neighbours_sub_ = n_.subscribe("wifi_neighbours_list", 10, &WiFiComm::neighboursListUpdated, this);
00044 
00045     c_callback_ = fp;
00046     using_boost_ = false;
00047 }
00048 
00049 wifi_comm::WiFiComm::WiFiComm(boost::function<void(char * ip)> f) : n_()
00050 {
00051         neighbours_sub_ = n_.subscribe("wifi_neighbours_list", 10, &WiFiComm::neighboursListUpdated, this);
00052 
00053     boost_callback_ = f;
00054     using_boost_ = true;
00055 }
00056 
00057 wifi_comm::WiFiComm::~WiFiComm()
00058 {
00059         ROS_INFO("Killing all active foreign relays before exiting...");
00060         for(int i=0 ; i<foreign_relays_.size() ; i++)
00061         {
00062                 closeForeignRelay((char*)foreign_relays_[i].ip.c_str());
00063         }
00064 }
00065 
00066 char * wifi_comm::WiFiComm::concatTopicAndIp(char * final_topic, char * topic, const char * ip)
00067 {
00068         sprintf(final_topic, "%s_%s", topic, ip);
00069 
00070         for(int i=0 ; i<strlen(final_topic) ; i++)
00071         {
00072                 if(final_topic[i]=='.') final_topic[i]='_'; 
00073         }
00074         return final_topic;
00075 }
00076 
00077 std::string * wifi_comm::WiFiComm::openForeignRelay(char * ip, char * topic, bool public_publish, bool append_my_ip)
00078 {
00079         ROS_ERROR("Using wifi_comm::WiFiComm::openForeignRelay(char * ip, char * topic, bool public_publish, bool append_my_ip) is deprecated. Please change to wifi_comm::WiFiComm::openForeignRelay(char * ip, char * local_topic, char * foreign_topic).");
00080 
00081         ForeignRelay newRelay;
00082 
00083         int pid = fork();
00084         if(pid==0)      // Child
00085         {
00086                 char foreign_topic[STR_SIZE];
00087                 char local_topic[STR_SIZE];
00088                 
00089                 if(public_publish) strcpy(local_topic, topic);
00090                 else concatTopicAndIp(local_topic, topic, ip);
00091 
00092                 char ros_master_uri[STR_SIZE];
00093                 sprintf(ros_master_uri, "http://%s:11311", ip);
00094                 execlp("rosrun", "rosrun", "foreign_relay", "foreign_relay", "adv", ros_master_uri, append_my_ip ? concatTopicAndIp(foreign_topic, topic, (char*)neighbours_list_.self_ip.c_str()) : topic, local_topic, (char*)0);
00095                 
00096                 ROS_WARN("Reached the end of foreign_relay to %s on the topic %s with pid %d", ip, topic, getpid());
00097                 exit(0);
00098         }
00099         else if(pid<0)  // Error
00100         {
00101                 ROS_ERROR("Failed to open foreign_relay to %s on the topic %s", ip, topic);
00102                 return NULL;
00103         }
00104         else            // Parent
00105         {
00106                 newRelay.pid = pid;
00107                 newRelay.ip = ip;
00108                 foreign_relays_.push_back(newRelay);
00109                 ROS_INFO("Successfully opened foreign_relay to %s on the topic %s with pid %d", ip, topic, pid);
00110                 return &newRelay.ip;
00111         }
00112         return NULL;
00113 }
00114 
00115 std::string * wifi_comm::WiFiComm::openForeignRelay(char * ip, char * local_topic, char * foreign_topic)
00116 {
00117         ForeignRelay newRelay;
00118 
00119         int pid = fork();
00120         if(pid==0)      // Child
00121         {
00122                 char ros_master_uri[STR_SIZE];
00123                 sprintf(ros_master_uri, "http://%s:11311", ip);
00124                 execlp("rosrun", "rosrun", "foreign_relay", "foreign_relay", "adv", ros_master_uri, foreign_topic, local_topic, (char*)0);
00125                 
00126                 ROS_WARN("Reached the end of foreign_relay to %s on the topic %s with pid %d", ip, foreign_topic, getpid());
00127                 exit(0);
00128         }
00129         else if(pid<0)  // Error
00130         {
00131                 ROS_ERROR("Failed to open foreign_relay to %s on the topic %s", ip, foreign_topic);
00132                 return NULL;
00133         }
00134         else            // Parent
00135         {
00136                 newRelay.pid = pid;
00137                 newRelay.ip = ip;
00138                 foreign_relays_.push_back(newRelay);
00139                 ROS_INFO("Successfully opened foreign_relay to %s on the topic %s with pid %d", ip, foreign_topic, pid);
00140                 return &newRelay.ip;
00141         }
00142         return NULL;
00143 }
00144 
00145 void wifi_comm::WiFiComm::closeForeignRelay(char * ip)
00146 {
00147         unsigned int i;
00148 
00149         for(i=0 ; i<foreign_relays_.size() ; i++)
00150         {
00151                 if(foreign_relays_[i].ip.compare(ip)==0)
00152                 {
00153                         // Apparently killing one is not enough! Do the child killing:
00154                         char cmd[STR_SIZE];
00155                         sprintf(cmd, "ps -o pid= --ppid %d", foreign_relays_[i].pid);                   
00156 
00157                         char buf[STR_SIZE];
00158                         int child_pid;
00159                         FILE * ptr;
00160                         if((ptr = popen(cmd, "r")) != NULL)
00161                         {
00162                                 fscanf(ptr, "%d", &child_pid);
00163                                 if(kill(child_pid, SIGTERM)!=0) ROS_WARN("Unable to kill foreign_relay child to %s with pid %d", ip, child_pid);
00164                                 if(kill(foreign_relays_[i].pid, SIGTERM)!=0) ROS_WARN("Unable to kill foreign_relay to %s with pid %d", ip, foreign_relays_[i].pid);
00165                         }
00166                         else
00167                         {
00168                                 ROS_WARN("Unable to kill foreign_relay child to %s with ppid %d", ip, foreign_relays_[i].pid);
00169                         }
00170                         pclose(ptr);
00171 
00172                         ROS_INFO("Closed foreign_relay to %s with pid %d", ip, foreign_relays_[i].pid);                 
00173 
00174                         foreign_relays_.erase(foreign_relays_.begin()+i);
00175                 }
00176         }
00177         return;
00178 }
00179 
00180 void wifi_comm::WiFiComm::neighboursListUpdated(const wifi_comm::WiFiNeighboursListConstPtr& msg)
00181 {
00182         unsigned int i, j, ind;
00183         bool found;
00184 
00185         // We store the msg so that we can access the list and size() without having to subscribe again
00186         neighbours_list_.self_ip.assign(msg->self_ip);
00187         neighbours_list_.neighbours.clear();
00188         for(i=0 ; i<msg->neighbours.size() ; i++) neighbours_list_.neighbours.push_back(msg->neighbours[i]);
00189 
00190         // Now open and close foreign_relays!
00191         for(i=0 ; i<msg->neighbours.size() ; i++)
00192         {
00193                 found = false;
00194                 for(j=0 ; j<foreign_relays_.size() ; j++)
00195                 {
00196                         if(msg->neighbours[i].ip.compare(foreign_relays_[j].ip)==0)
00197                         {
00198                                 found = true;
00199                                 break;
00200                         }
00201                 }
00202                 // Trigger callback
00203                 if(!found)
00204                 if(using_boost_) boost_callback_((char*)msg->neighbours[i].ip.c_str());
00205                 else (c_callback_)((char*)msg->neighbours[i].ip.c_str());
00206         }
00207 
00208         for(i=0 ; i<foreign_relays_.size() ; i++)
00209         {
00210                 found = false;
00211                 for(j=0 ; j<msg->neighbours.size() ; j++)
00212                 {
00213                         if(foreign_relays_[i].ip.compare(msg->neighbours[j].ip)==0)
00214                         {
00215                                 found = true;
00216                                 break;
00217                         }
00218                 }
00219                 if(!found) closeForeignRelay((char*)foreign_relays_[i].ip.c_str());
00220         }
00221 }
00222 
00223 // EOF
00224 


wifi_comm
Author(s): Gonçalo Cabrita and Pedro Sousa
autogenerated on Mon Jan 6 2014 11:27:05