gear.cc

Go to the documentation of this file.
00001 //
00002 // gear.cc        : GEAR Filter
00003 // authors        : Yan Yu and Fabio Silva
00004 //
00005 // Copyright (C) 2000-2003 by the University of Southern California
00006 // Copyright (C) 2000-2003 by the University of California
00007 // $Id: gear.cc,v 1.6 2005/09/13 04:53:48 tomh Exp $
00008 //
00009 // This program is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU General Public License,
00011 // version 2, as published by the Free Software Foundation.
00012 //
00013 // This program is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 //
00018 // You should have received a copy of the GNU General Public License along
00019 // with this program; if not, write to the Free Software Foundation, Inc.,
00020 // 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00021 //
00022 // Linking this file statically or dynamically with other modules is making
00023 // a combined work based on this file.  Thus, the terms and conditions of
00024 // the GNU General Public License cover the whole combination.
00025 //
00026 // In addition, as a special exception, the copyright holders of this file
00027 // give you permission to combine this file with free software programs or
00028 // libraries that are released under the GNU LGPL and with code included in
00029 // the standard release of ns-2 under the Apache 2.0 license or under
00030 // otherwise-compatible licenses with advertising requirements (or modified
00031 // versions of such code, with unchanged license).  You may copy and
00032 // distribute such a system following the terms of the GNU GPL for this
00033 // file and the licenses of the other code concerned, provided that you
00034 // include the source code of that other code when and as the GNU GPL
00035 // requires distribution of source code.
00036 //
00037 // Note that people who make modified versions of this file are not
00038 // obligated to grant this special exception for their modified versions;
00039 // it is their choice whether to do so.  The GNU General Public License
00040 // gives permission to release a modified version without this exception;
00041 // this exception also makes it possible to release a modified version
00042 // which carries forward this exception.
00043 
00044 #include "gear.hh"
00045 
00046 #ifdef NS_DIFFUSION
00047 static class GeoRoutingFilterClass : public TclClass {
00048 public:
00049   GeoRoutingFilterClass() : TclClass("Application/DiffApp/GeoRoutingFilter") {}
00050   TclObject * create(int argc, const char*const* argv) {
00051     if (argc == 5)
00052       return (new GeoRoutingFilter(argv[4]));
00053     else 
00054       fprintf(stderr, "Insufficient number of args for creating GeoRoutingFilter");
00055     return (NULL);
00056   }
00057 } class_geo_routing_filter;
00058 
00059 int GeoRoutingFilter::command(int argc, const char*const* argv) {
00060   if (argc == 2) {
00061     if (strcmp(argv[1], "start") == 0) {
00062       run();
00063       return TCL_OK;
00064     }
00065   }
00066   return DiffApp::command(argc, argv);
00067 }
00068 #endif // NS_DIFFUSION
00069 
00070 void GeoFilterReceive::recv(Message *msg, handle h)
00071 {
00072   app_->recv(msg, h);
00073 }
00074 
00075 int GeoMessageSendTimer::expire()
00076 {
00077   // Call timeout function
00078   agent_->messageTimeout(msg_);
00079 
00080   // Do not reschedule this timer
00081   delete this;
00082   return -1;
00083 }
00084 
00085 int GeoNeighborsTimer::expire()
00086 {
00087   // Call timeout function
00088   agent_->neighborTimeout();
00089 
00090   // Reschedule this timer
00091   return 0;
00092 }
00093 
00094 int GeoBeaconRequestTimer::expire()
00095 {
00096   // Call the timeout function
00097   agent_->beaconTimeout();
00098 
00099   // Reschedule this timer
00100   return 0;
00101 }
00102 
00103 void GeoRoutingFilter::beaconTimeout()
00104 {
00105   NRAttrVec attrs;
00106   Message *beacon_msg;
00107   struct timeval tv;
00108 
00109   GetTime(&tv);
00110 
00111   DiffPrintWithTime(DEBUG_IMPORTANT, "Gear - Beacon Timeout !\n");
00112 
00113   // We broadcast the request from time to time, in case a new
00114   // neighbor joins in and never gets a chance to get its informaiton
00115   if ((last_neighbor_request_tv_.tv_sec == 0) ||
00116       ((tv.tv_sec - last_neighbor_request_tv_.tv_sec) >=
00117        GEO_NEIGHBOR_REQUEST_PERIOD)){
00118 
00119     // Update timestamp
00120     GetTime(&last_neighbor_request_tv_);
00121 
00122     // Sends a beacon to all neighbors
00123     attrs.push_back(GeoBeaconTypeAttr.make(NRAttribute::IS, GEO_REQUEST));
00124     attrs.push_back(GeoLatitudeAttr.make(NRAttribute::IS, geo_latitude_));
00125     attrs.push_back(GeoLongitudeAttr.make(NRAttribute::IS, geo_longitude_));
00126     attrs.push_back(GeoRemainingEnergyAttr.make(NRAttribute::IS,
00127                         remainingEnergy()));
00128 
00129     beacon_msg = new Message(DIFFUSION_VERSION, DATA, 0, 0,
00130                  attrs.size(), pkt_count_, rdm_id_,
00131                  BROADCAST_ADDR, LOCALHOST_ADDR);
00132     // Don't forget to increment pkt_count
00133     pkt_count_++;
00134 
00135     beacon_msg->msg_attr_vec_ = CopyAttrs(&attrs);
00136 
00137     DiffPrintWithTime(DEBUG_IMPORTANT, "Gear - Sending Beacon Request...\n");
00138     ((DiffusionRouting *)dr_)->sendMessage(beacon_msg, post_filter_handle_);
00139 
00140     ClearAttrs(&attrs);
00141     delete beacon_msg;
00142   }
00143 }
00144 
00145 void GeoRoutingFilter::neighborTimeout()
00146 {
00147   NeighborList::iterator neighbor_itr;
00148   NeighborEntry *neighbor_entry;
00149   struct timeval tv;
00150 
00151   GetTime(&tv);
00152 
00153   DiffPrintWithTime(DEBUG_IMPORTANT, "Gear - Neighbors Timeout !\n");
00154 
00155   neighbor_itr = neighbors_list_.begin();
00156 
00157   while (neighbor_itr != neighbors_list_.end()){
00158     neighbor_entry = *neighbor_itr;
00159     DiffPrintWithTime(DEBUG_IMPORTANT, "Gear - Check: %d: %d --> %d\n",
00160               neighbor_entry->id_, neighbor_entry->tv_.tv_sec,
00161               tv.tv_sec);
00162 
00163     if ((tv.tv_sec - neighbor_entry->tv_.tv_sec) >= GEO_NEIGHBOR_EXPIRED){
00164       // Delete timed-out neighbor
00165       DiffPrintWithTime(DEBUG_IMPORTANT, "Gear - Deleting neighbor %d\n",
00166             neighbor_entry->id_);
00167       neighbor_itr = neighbors_list_.erase(neighbor_itr);
00168       delete neighbor_entry;
00169     }
00170     else{
00171       DiffPrintWithTime(DEBUG_IMPORTANT, "Gear - Neighbor %d, (%d,%d)\n",
00172             neighbor_entry->id_, neighbor_entry->tv_.tv_sec,
00173             neighbor_entry->tv_.tv_usec);
00174       neighbor_itr++;
00175     }
00176   }
00177 }
00178 
00179 void GeoRoutingFilter::messageTimeout(Message *msg)
00180 {
00181   // Send message
00182   DiffPrintWithTime(DEBUG_IMPORTANT, "Gear - Message Timeout !\n");
00183 
00184   ((DiffusionRouting *)dr_)->sendMessage(msg, post_filter_handle_,
00185                      GEOROUTING_POST_FILTER_PRIORITY);
00186 }
00187 
00188 void GeoRoutingFilter::recv(Message *msg, handle h)
00189 {
00190   if (h == pre_filter_handle_){
00191     preProcessFilter(msg);
00192     return;
00193   }
00194 
00195   if (h == post_filter_handle_){
00196     postProcessFilter(msg);
00197     return;
00198   }
00199 
00200   DiffPrintWithTime(DEBUG_ALWAYS,
00201             "Gear - Received message for an unknown handle %d !\n", h);
00202 }
00203 
00204 void GeoRoutingFilter::preProcessFilter(Message *msg)
00205 {
00206   NRSimpleAttribute<void *> *heuristic_value_attribute = NULL;
00207   NRSimpleAttribute<int> *beacon_type_attribute = NULL;
00208   NRSimpleAttribute<double> *beacon_info_attribute = NULL;
00209   double neighbor_energy = 0.0;
00210   double neighbor_longitude = 0.0;
00211   double neighbor_latitude = 0.0;
00212   double new_heuristic_value = 0.0;
00213   int32_t neighbor_id;
00214   int beacon_type;
00215   struct timeval tv; 
00216   HeuristicValue *heuristic_value = NULL;
00217   GeoLocation dst_location;
00218   TimerCallback *beacon_timer = NULL;
00219   NRAttrVec attrs;
00220   Message *beacon_msg = NULL;
00221   PktHeader *pkt_header = NULL;
00222 
00223   switch (msg->msg_type_){
00224 
00225   case INTEREST:
00226   case EXPLORATORY_DATA:
00227   case PUSH_EXPLORATORY_DATA:
00228 
00229     if (msg->new_message_){
00230       // Don't worry about old messages
00231 
00232       // Pre-process the messages, extracting the geo-header attribute
00233       // if it's present (or trying to create a new geo-header
00234       // otherwise)
00235       pkt_header = preProcessMessage(msg);
00236 
00237       // If we have a packet header, add it to the message list
00238       if (pkt_header){
00239     sendNeighborRequest();
00240         message_list_.push_back(pkt_header);
00241       }
00242     }
00243 
00244     ((DiffusionRouting *)dr_)->sendMessage(msg, pre_filter_handle_);
00245 
00246     break;
00247 
00248   case DATA:
00249 
00250     // Look for a beacon type attribute in the data message
00251     beacon_type_attribute = GeoBeaconTypeAttr.find(msg->msg_attr_vec_);
00252 
00253     // If there is no beacon_type attribute, this is not a beacon data
00254     // message. So, we just forward it to the next filter
00255     if (!beacon_type_attribute){
00256       ((DiffusionRouting *)dr_)->sendMessage(msg, pre_filter_handle_);
00257 
00258       break;
00259     }
00260 
00261     // Get neighbor id
00262     neighbor_id = msg->last_hop_;
00263 
00264     if ((neighbor_id == BROADCAST_ADDR) ||
00265     (neighbor_id == LOCALHOST_ADDR)){
00266       DiffPrintWithTime(DEBUG_ALWAYS, "Gear - Neighbor ID Invalid !\n");
00267       return;
00268     }
00269 
00270     // Look for the rest of the information
00271     beacon_type = beacon_type_attribute->getVal();
00272 
00273     beacon_info_attribute = GeoLongitudeAttr.find(msg->msg_attr_vec_);
00274     if (beacon_info_attribute){
00275       neighbor_longitude = beacon_info_attribute->getVal();
00276     }
00277 
00278     beacon_info_attribute = GeoLatitudeAttr.find(msg->msg_attr_vec_);
00279     if (beacon_info_attribute){
00280       neighbor_latitude = beacon_info_attribute->getVal();
00281     }
00282 
00283     beacon_info_attribute = GeoRemainingEnergyAttr.find(msg->msg_attr_vec_);
00284     if (beacon_info_attribute){
00285       neighbor_energy = beacon_info_attribute->getVal();
00286     }
00287 
00288     // Update our neighbor list with the beacon's information
00289     updateNeighbor(neighbor_id, neighbor_longitude,
00290            neighbor_latitude, neighbor_energy);
00291 
00292     // Get current time
00293     GetTime(&tv);
00294 
00295     DiffPrintWithTime(DEBUG_IMPORTANT,
00296               "Gear - Beacon Information id: %d - location: %f,%f - energy: %f\n",
00297               neighbor_id, neighbor_longitude,
00298               neighbor_latitude, neighbor_energy);
00299 
00300     if (beacon_type == GEO_REQUEST){
00301       DiffPrintWithTime(DEBUG_IMPORTANT,
00302             "Gear - Received a beacon request...\n");
00303       // If we received a neighbor request, we have to generate a
00304       // reply and send it after some random time. But this has to be
00305       // suppresed if we have recently done it already
00306 
00307       if (last_beacon_reply_tv_.tv_sec > 0){
00308     // Send at most one neighbor beacon every
00309     // GEO_BEACON_REPLY_PERIOD seconds
00310     if ((tv.tv_sec - last_beacon_reply_tv_.tv_sec)
00311         < GEO_BEACON_REPLY_PERIOD){
00312       DiffPrintWithTime(DEBUG_IMPORTANT,
00313                 "Gear - Ignoring beacon request until %d.%06d!\n",
00314                 (tv.tv_sec + GEO_BEACON_REPLY_PERIOD), tv.tv_usec);
00315       break;
00316     }
00317       }
00318 
00319       // Create beacon reply message
00320       attrs.push_back(GeoLongitudeAttr.make(NRAttribute::IS, geo_longitude_));
00321       attrs.push_back(GeoLatitudeAttr.make(NRAttribute::IS, geo_latitude_));
00322       attrs.push_back(GeoRemainingEnergyAttr.make(NRAttribute::IS,
00323                           remainingEnergy()));
00324       attrs.push_back(GeoBeaconTypeAttr.make(NRAttribute::IS, GEO_REPLY));
00325 
00326       // Let's try to extract the beacon's heuristic_value
00327       heuristic_value_attribute = GeoHeuristicValueAttr.find(msg->msg_attr_vec_);
00328 
00329       if (heuristic_value_attribute){
00330     // Heuristic Value attribute found ! Include information about
00331     // this destination if we have anything in our table
00332     heuristic_value = (HeuristicValue *) heuristic_value_attribute->getVal();
00333     dst_location.longitude_ = heuristic_value->dst_longitude_;
00334     dst_location.latitude_ = heuristic_value->dst_latitude_;
00335 
00336     // Retrieve heuristic_value
00337     DiffPrintWithTime(DEBUG_IMPORTANT,
00338               "Gear - Requesting h-value in (%lf,%lf)\n",
00339               dst_location.longitude_, dst_location.latitude_); 
00340 
00341     new_heuristic_value = retrieveHeuristicValue(dst_location);
00342 
00343     if (new_heuristic_value != INITIAL_HEURISTIC_VALUE){
00344       // Add the heuristic_value to the message if we have any
00345       // information about this particular destination
00346  
00347       heuristic_value = new HeuristicValue(dst_location.longitude_,
00348                            dst_location.latitude_,
00349                            new_heuristic_value);
00350 
00351       DiffPrintWithTime(DEBUG_IMPORTANT,
00352                 "Gear - Current h-value for (%lf,%lf):%lf\n",
00353                 dst_location.longitude_, dst_location.latitude_,
00354                 new_heuristic_value);
00355 
00356       attrs.push_back(GeoHeuristicValueAttr.make(NRAttribute::IS,
00357                              (void *) heuristic_value,
00358                              sizeof(HeuristicValue)));
00359       delete heuristic_value;
00360     }
00361       }
00362 
00363       beacon_msg = new Message(DIFFUSION_VERSION, DATA, 0, 0, attrs.size(),
00364                    pkt_count_, rdm_id_, BROADCAST_ADDR,
00365                    LOCALHOST_ADDR);
00366 
00367       // Don't forget to update pkt_count
00368       pkt_count_++;
00369       beacon_msg->msg_attr_vec_ = CopyAttrs(&attrs);
00370 
00371       beacon_timer = new GeoMessageSendTimer(this, CopyMessage(beacon_msg));
00372 
00373       ((DiffusionRouting *)dr_)->addTimer(GEO_BEACON_REPLY_DELAY +
00374                       (int) ((GEO_BEACON_REPLY_JITTER *
00375                           (GetRand() * 1.0 / RAND_MAX) -
00376                           (GEO_BEACON_REPLY_JITTER / 2))),
00377                       beacon_timer);
00378 
00379       ClearAttrs(&attrs);
00380       delete beacon_msg;
00381 
00382       DiffPrintWithTime(DEBUG_IMPORTANT,
00383             "Gear - Sending a beacon reply in response to request !\n");
00384       DiffPrintWithTime(DEBUG_IMPORTANT,
00385             "Gear - Local info: location: %f,%f - energy: %f\n",
00386             geo_longitude_, geo_latitude_, remainingEnergy());
00387 
00388       // Update beacon timestamp
00389       GetTime(&last_beacon_reply_tv_);
00390     }
00391     else{
00392       if (beacon_type == GEO_REPLY){
00393     DiffPrintWithTime(DEBUG_IMPORTANT, "Gear - Received beacon reply\n");
00394       }
00395       else{
00396     if (beacon_type == GEO_UPDATE){
00397       DiffPrintWithTime(DEBUG_IMPORTANT,
00398                 "Gear - Received beacon update\n");
00399     }
00400     else{
00401       DiffPrintWithTime(DEBUG_ALWAYS,
00402                 "Gear - Received unknown message !\n");
00403       return;
00404     }
00405       }
00406 
00407       // Extract the heuristic_value from the message
00408       heuristic_value_attribute = GeoHeuristicValueAttr.find(msg->msg_attr_vec_);
00409 
00410       if (heuristic_value_attribute){
00411     heuristic_value = (HeuristicValue *) heuristic_value_attribute->getVal();
00412 
00413     // Update learned cost value table
00414     dst_location.longitude_ = heuristic_value->dst_longitude_;
00415     dst_location.latitude_ = heuristic_value->dst_latitude_;
00416 
00417     DiffPrintWithTime(DEBUG_IMPORTANT,
00418           "Gear - Received h-val update %d: (%lf,%lf):%f\n",
00419           neighbor_id, dst_location.longitude_,
00420           dst_location.latitude_,
00421           heuristic_value->heuristic_value_);
00422 
00423     learned_cost_table_.updateEntry(neighbor_id, dst_location,
00424                     heuristic_value->heuristic_value_);
00425       }
00426     }
00427 
00428     break;
00429 
00430   default:
00431 
00432     // If we do not know about this message, we just pass it to the
00433     // next filter
00434     ((DiffusionRouting *)dr_)->sendMessage(msg, pre_filter_handle_);
00435 
00436     break;
00437 
00438   }
00439 }
00440 
00441 void GeoRoutingFilter::postProcessFilter(Message *msg)
00442 {
00443   PktHeader *pkt_header = NULL;
00444   GeoHeader *geo_header = NULL;
00445   int action;
00446   int32_t next_hop;
00447 
00448   switch (msg->msg_type_){
00449 
00450   case INTEREST:
00451   case EXPLORATORY_DATA:
00452   case PUSH_EXPLORATORY_DATA:
00453 
00454     // Ignore messages with a local application as destination
00455     if (msg->next_hop_ != LOCALHOST_ADDR){
00456 
00457       // Retrieve packet header from previous stage
00458       pkt_header = retrievePacketHeader(msg);
00459 
00460       // If we have record of this packet, we restore the previous
00461       // geo_header information before forwarding it further
00462       if (pkt_header){
00463     geo_header = restoreGeoHeader(pkt_header, msg);
00464 
00465     // Increment path_len
00466     geo_header->path_len_++;
00467 
00468     // Check if we have to broadcast this message. We do not need
00469     // to check if I have seen this broadcast packet before, since
00470     // this is called by PostProcessFilter, so it must be a new
00471     // packet. We only need to check if we are inside the target
00472     // region
00473     action = floodInsideRegion(geo_header);
00474 
00475     // Add GeoHeader attribute to the message
00476     msg->msg_attr_vec_->push_back(GeoHeaderAttr.make(NRAttribute::IS,
00477                              (void *) geo_header,
00478                              sizeof(GeoHeader)));
00479 
00480     switch (action){
00481 
00482     case BROADCAST:
00483 
00484       // We are inside the region and have at least a neighbor
00485       // which is inside the region too, so we just broadcast this
00486       // message
00487       DiffPrintWithTime(DEBUG_IMPORTANT,
00488                 "Gear - Broadcasting message: last_hop: %d!\n",
00489                 msg->last_hop_);
00490       
00491       msg->next_hop_ = BROADCAST_ADDR;
00492       ((DiffusionRouting *)dr_)->sendMessage(msg, post_filter_handle_);
00493 
00494       break;
00495 
00496     case BROADCAST_SUPPRESS:
00497 
00498       // We are either inside the region and have no neighbors
00499       // also inside this region OR packet came from inside the
00500       // region and we are outside the region. In either case, we
00501       // do not forward the packet
00502       DiffPrintWithTime(DEBUG_IMPORTANT,
00503                 "Gear - Suppressing broadcast !\n");
00504 
00505       break;
00506 
00507     case OUTSIDE_REGION:
00508 
00509       // The packet is still outside the region. In order to route
00510       // it to the region, we first try using a 'greedy mode'. If
00511       // that doesn't work, we probably need to navigate around a
00512       // hole
00513       DiffPrintWithTime(DEBUG_IMPORTANT,
00514                 "Gear - Packet outside target region !\n");
00515 
00516       next_hop = findNextHop(geo_header, true);
00517 
00518       // If there are no neighbors, let's try to go around a hole
00519       if (next_hop == BROADCAST_ADDR){
00520 
00521         // Check if we should still be looking for a path
00522         if (geo_header->path_len_ < MAX_PATH_LEN)
00523           next_hop = findNextHop(geo_header, false);
00524       }
00525 
00526       // Still no neighbors, nothing we can do !
00527       if (next_hop == BROADCAST_ADDR){
00528         DiffPrintWithTime(DEBUG_IMPORTANT,
00529                   "Gear - Cannot find next hop !\n");
00530       }
00531       else{
00532         // Forward message to next_hop
00533         msg->next_hop_ = next_hop;
00534         DiffPrintWithTime(DEBUG_IMPORTANT,
00535                   "Gear - Forwarding message !\n");
00536         DiffPrintWithTime(DEBUG_IMPORTANT,
00537                   "Gear - Next Hop: %d\n", next_hop);
00538         DiffPrintWithTime(DEBUG_IMPORTANT,
00539                   "Gear - Last Hop: %d\n", msg->last_hop_);
00540         ((DiffusionRouting *)dr_)->sendMessage(msg, post_filter_handle_);
00541       }
00542     
00543       break;
00544 
00545     default:
00546 
00547       break;
00548     }
00549 
00550     // Let's not forget to delete both geo_header and pkt_header
00551     delete pkt_header;
00552     delete geo_header;
00553       }
00554       else{
00555     // This message has no packet header information, so we just forward it
00556     DiffPrintWithTime(DEBUG_IMPORTANT,
00557               "Gear - Forwarding message without packet header info !\n");
00558     ((DiffusionRouting *)dr_)->sendMessage(msg, post_filter_handle_);
00559       }
00560     }
00561     else{
00562       // This is a message from gradient to a local app
00563       DiffPrintWithTime(DEBUG_LOTS_DETAILS,
00564             "Gear - Forwarding message to a local agent !\n");
00565       ((DiffusionRouting *)dr_)->sendMessage(msg, post_filter_handle_);
00566     }
00567 
00568     break;
00569 
00570   default:
00571 
00572     // All other messages are just forwarded without any changes
00573     ((DiffusionRouting *)dr_)->sendMessage(msg, post_filter_handle_);
00574 
00575     break;
00576   }
00577 }
00578 
00579 handle GeoRoutingFilter::setupPreFilter()
00580 {
00581   NRAttrVec attrs;
00582   handle h;
00583 
00584   // Set up a filter that matches every packet coming in
00585   attrs.push_back(NRClassAttr.make(NRAttribute::IS,
00586                    NRAttribute::INTEREST_CLASS));
00587 
00588   h = ((DiffusionRouting *)dr_)->addFilter(&attrs,
00589                        GEOROUTING_PRE_FILTER_PRIORITY,
00590                        filter_callback_);
00591   ClearAttrs(&attrs);
00592   return h;
00593 }
00594 
00595 handle GeoRoutingFilter::setupPostFilter()
00596 {
00597   NRAttrVec attrs;
00598   handle h;
00599 
00600   // This is a filter that matches all packets after processing by the
00601   // gradient filter
00602   attrs.push_back(NRClassAttr.make(NRAttribute::IS,
00603                    NRAttribute::INTEREST_CLASS));
00604 
00605   h = ((DiffusionRouting *)dr_)->addFilter(&attrs,
00606                        GEOROUTING_POST_FILTER_PRIORITY,
00607                        filter_callback_);
00608 
00609   ClearAttrs(&attrs);
00610   return h;
00611 }
00612 
00613 void GeoRoutingFilter::run()
00614 {
00615 #ifdef NS_DIFFUSION
00616   TimerCallback *neighbor_timer, *beacon_timer;
00617 
00618   // Set up node location
00619   DiffPrintWithTime(DEBUG_ALWAYS, "Initializing GEAR IN NS!\n");
00620   getNodeLocation(&geo_longitude_, &geo_latitude_);
00621 
00622   DiffPrintWithTime(DEBUG_ALWAYS, "Gear - Location %f,%f\n",
00623             geo_longitude_, geo_latitude_);
00624 
00625   // Set up filters
00626   pre_filter_handle_ = setupPreFilter();
00627   post_filter_handle_ = setupPostFilter();
00628 
00629   // Add periodic neighbor checking timer
00630   neighbor_timer = new GeoNeighborsTimer(this);
00631   ((DiffusionRouting *)dr_)->addTimer(GEO_NEIGHBOR_DELAY, neighbor_timer);
00632 
00633   // Add periodic beacon request timer
00634   beacon_timer = new GeoBeaconRequestTimer(this);
00635   ((DiffusionRouting *)dr_)->addTimer(GEO_BEACON_REQUEST_CHECK_PERIOD,
00636                       beacon_timer);
00637 
00638   DiffPrintWithTime(DEBUG_ALWAYS, "Gear - Pre-filter: received handle %d !\n",
00639             pre_filter_handle_);
00640   DiffPrintWithTime(DEBUG_ALWAYS, "Gear - Post-filter: received handle %d !\n",
00641             post_filter_handle_);
00642   DiffPrintWithTime(DEBUG_ALWAYS, "Gear - Initialized !\n");
00643 #endif // NS_DIFFUSION
00644 
00645   // Sends a beacon request upon start-up
00646   beaconTimeout();
00647 
00648 #ifndef NS_DIFFUSION
00649   // We don't do anything
00650   while (1){
00651     sleep(1000);
00652   }
00653 #endif // !NS_DIFFUSION
00654 }
00655 
00656 #ifdef NS_DIFFUSION
00657 GeoRoutingFilter::GeoRoutingFilter(const char *diffrtg)
00658 {
00659   DiffAppAgent *agent;
00660 #else
00661   GeoRoutingFilter::GeoRoutingFilter(int argc, char **argv)
00662 {
00663   // Parse command line options
00664   parseCommandLine(argc, argv);
00665 #endif // NS_DIFFUSION
00666   
00667   struct timeval tv;
00668 
00669   // Initialize a few parameters
00670   initial_energy_ = GEO_INITIAL_ENERGY;
00671   unit_energy_for_send_ = GEO_UNIT_ENERGY_FOR_SEND;
00672   unit_energy_for_recv_ = GEO_UNIT_ENERGY_FOR_RECV;
00673   num_pkt_sent_ = 0;
00674   num_pkt_recv_ = 0;
00675 
00676   // Initialize beacon timestamp
00677   last_beacon_reply_tv_.tv_sec = 0; 
00678   last_beacon_reply_tv_.tv_usec = 0; 
00679   last_neighbor_request_tv_.tv_sec = 0;
00680   last_neighbor_request_tv_.tv_usec = 0;
00681 
00682 #ifdef NS_DIFFUSION
00683   agent = (DiffAppAgent *)TclObject::lookup(diffrtg);
00684   dr_ = agent->dr();
00685 #else
00686   getNodeLocation(&geo_longitude_, &geo_latitude_);
00687 
00688   DiffPrintWithTime(DEBUG_ALWAYS, "Gear - Location %f,%f\n",
00689             geo_longitude_, geo_latitude_);
00690 #endif // NS_DIFFUSION
00691 
00692   GetTime(&tv);
00693   SetSeed(&tv);
00694   pkt_count_ = GetRand();
00695   rdm_id_ = GetRand();
00696 
00697 #ifndef NS_DIFFUSION
00698   // Create Diffusion Routing class
00699   dr_ = NR::createNR(diffusion_port_);
00700 #endif // !NS_DIFFUSION
00701 
00702   filter_callback_ = new GeoFilterReceive(this);
00703 
00704 #ifndef NS_DIFFUSION
00705   // Set up filters
00706   pre_filter_handle_ = setupPreFilter();
00707   post_filter_handle_ = setupPostFilter();
00708 
00709   // Add periodic neighbor checking timer
00710   neighbor_timer = new GeoNeighborsTimer(this);
00711   ((DiffusionRouting *)dr_)->addTimer(GEO_NEIGHBOR_DELAY, neighbor_timer);
00712 
00713   // Add periodic beacon request timer
00714   beacon_timer = new GeoBeaconRequestTimer(this);
00715   ((DiffusionRouting *)dr_)->addTimer(GEO_BEACON_REQUEST_CHECK_PERIOD,
00716                       beacon_timer);
00717 
00718   DiffPrintWithTime(DEBUG_ALWAYS,
00719             "Gear - Pre-filter received handle %d !\n",
00720             pre_filter_handle_);
00721   DiffPrintWithTime(DEBUG_ALWAYS,
00722             "Gear - Post-filter received handle %d !\n",
00723             post_filter_handle_);
00724   DiffPrintWithTime(DEBUG_ALWAYS, "Gear - Initialized !\n");
00725 #endif // !NS_DIFFUSION
00726 }
00727 
00728 void GeoRoutingFilter::getNodeLocation(double *longitude, double *latitude)
00729 {
00730 #ifdef NS_DIFFUSION
00731   double z;
00732 
00733   MobileNode *node = ((DiffusionRouting *)dr_)->getNode();
00734   node->getLoc(longitude, latitude, &z);
00735 #else
00736   char *longitude_env, *latitude_env;
00737   bool got_location = false;
00738 #ifdef USE_EMSIM
00739   char *sim_loc_env;
00740   float my_longitude, my_latitude;
00741 #endif // USE_EMSIM
00742 
00743   longitude_env = getenv("gear_longitude");
00744   latitude_env = getenv("gear_latitude");
00745 
00746   if (longitude_env && latitude_env){
00747     *longitude = atof(longitude_env);
00748     *latitude = atof(latitude_env);
00749     DiffPrintWithTime(DEBUG_ALWAYS,
00750               "Gear - Using location from gear_longitude, gear_latitude\n");
00751     got_location = true;
00752   }
00753 #ifdef USE_EMSIM
00754   else{
00755     // Try to get location from SIM_LOC (emsim environment variable)
00756     sim_loc_env = getenv("SIM_LOC");
00757     if (sim_loc_env){
00758       if (sscanf(sim_loc_env, "%f %f", &my_longitude, &my_latitude) == 2){
00759     DiffPrintWithTime(DEBUG_ALWAYS,
00760               "Gear - Using location from SIM_LOC !\n");
00761     *longitude = (double) my_longitude;
00762     *latitude = (double) my_latitude;
00763     got_location = true;
00764       }
00765     }
00766   }
00767 #endif // USE_EMSIM
00768 
00769   // Check if we were successful getting the node location
00770   if (!got_location){
00771     DiffPrintWithTime(DEBUG_ALWAYS,
00772               "Gear - Could not get the node location !\n");
00773     exit(-1);
00774   }
00775 #endif // NS_DIFFUSION
00776 }
00777 
00778 bool GeoRoutingFilter::checkNeighbors()
00779 {
00780   NeighborList::iterator neighbor_itr;
00781   NeighborEntry *neighbor_entry;
00782   struct timeval tv;
00783 
00784   GetTime(&tv);
00785 
00786   for (neighbor_itr = neighbors_list_.begin();
00787        neighbor_itr != neighbors_list_.end(); ++neighbor_itr){
00788     neighbor_entry = *neighbor_itr;
00789 
00790     if ((tv.tv_sec - neighbor_entry->tv_.tv_sec) >= GEO_NEIGHBOR_UPDATE)
00791       return true;
00792   }
00793   
00794   return false;
00795 }
00796 
00797 void GeoRoutingFilter::sendNeighborRequest()
00798 {
00799   NRAttrVec attrs;
00800   Message *beacon_msg;
00801   TimerCallback *beacon_timer;
00802 
00803   // Check if we need to send a beacon request to update our neighbor
00804   // information
00805   if (!checkNeighbors())
00806     return;
00807 
00808   // Yes ! Create the beacon message
00809   attrs.push_back(GeoBeaconTypeAttr.make(NRAttribute::IS, GEO_REQUEST));
00810   attrs.push_back(GeoLatitudeAttr.make(NRAttribute::IS, geo_latitude_));
00811   attrs.push_back(GeoLongitudeAttr.make(NRAttribute::IS, geo_longitude_));
00812   attrs.push_back(GeoRemainingEnergyAttr.make(NRAttribute::IS,
00813                           remainingEnergy()));
00814 
00815   // Neighbor beacon msg is a DATA message
00816   beacon_msg = new Message(DIFFUSION_VERSION, DATA, 0, 0,
00817                attrs.size(), pkt_count_, rdm_id_,
00818                BROADCAST_ADDR, LOCALHOST_ADDR);
00819   // Don't forget to increment pkt_count
00820   pkt_count_++;
00821 
00822   beacon_msg->msg_attr_vec_ = CopyAttrs(&attrs);
00823 
00824   // Generate a beacon request, add some random jitter before actually
00825   // sending it
00826   DiffPrintWithTime(DEBUG_IMPORTANT,
00827             "Gear - Broadcasting neighbor info request...\n");
00828 
00829   beacon_timer = new GeoMessageSendTimer(this, CopyMessage(beacon_msg));
00830 
00831   ((DiffusionRouting *)dr_)->addTimer(GEO_BEACON_DELAY +
00832                       (int) ((GEO_BEACON_JITTER *
00833                           (GetRand() * 1.0 / RAND_MAX) -
00834                           (GEO_BEACON_JITTER / 2))),
00835                       beacon_timer);
00836 
00837   GetTime(&last_neighbor_request_tv_);
00838 
00839   ClearAttrs(&attrs);
00840   delete beacon_msg;
00841 }
00842 
00843 void GeoRoutingFilter::updateNeighbor(int32_t neighbor_id,
00844                       double neighbor_longitude,
00845                       double neighbor_latitude,
00846                       double neighbor_energy)
00847 {
00848   NeighborEntry *neighbor_entry;
00849 
00850   // Look for this neighbor in our neighbor's list
00851   neighbor_entry = findNeighbor(neighbor_id);
00852 
00853   if (!neighbor_entry){
00854     // Insert a new neighbor into our list
00855     DiffPrintWithTime(DEBUG_IMPORTANT,
00856               "Gear - Inserting new neighbor %d !\n", neighbor_id);
00857 
00858     neighbor_entry = new NeighborEntry(neighbor_id, neighbor_longitude,
00859                        neighbor_latitude, neighbor_energy);
00860 
00861     // Insert new element with key neighbor_id into the hash map
00862     neighbors_list_.push_back(neighbor_entry);
00863   }
00864   else{
00865     // Update an existing neighbor entry
00866     DiffPrintWithTime(DEBUG_IMPORTANT,
00867               "Gear - Updating neighbor %d !\n", neighbor_id);
00868 
00869     neighbor_entry->longitude_ = neighbor_longitude;
00870     neighbor_entry->latitude_ = neighbor_latitude;
00871     neighbor_entry->remaining_energy_ = neighbor_energy;
00872 
00873     GetTime(&(neighbor_entry->tv_));
00874   }
00875 }
00876 
00877 PktHeader * GeoRoutingFilter::retrievePacketHeader(Message *msg)
00878 {
00879   PacketList::iterator packet_itr;
00880   PktHeader *pkt_header = NULL;
00881 
00882   for (packet_itr = message_list_.begin();
00883        packet_itr != message_list_.end(); ++packet_itr){
00884     pkt_header = *packet_itr;
00885     if ((pkt_header->rdm_id_ == msg->rdm_id_) &&
00886     (pkt_header->pkt_num_ == msg->pkt_num_)){
00887       packet_itr = message_list_.erase(packet_itr);
00888       return pkt_header;
00889     }
00890   }
00891 
00892   // Entry not found in our list
00893   return NULL;
00894 }
00895 
00896 PktHeader * GeoRoutingFilter::preProcessMessage(Message *msg)
00897 {
00898   float longitude_min, longitude_max;
00899   float latitude_min, latitude_max;
00900   PktHeader *pkt_header = NULL;
00901 
00902   pkt_header = stripOutHeader(msg);
00903 
00904   if (!pkt_header){
00905     // This is a message either coming from a local application (for
00906     // which a geo_header hasn't been extracted yet) or a message with
00907     // no geographic information (in which case there's nothing we can
00908     // do about). We first try to extract geographic information from
00909     // the message in order to create a new geo_header
00910     if (extractLocation(msg, &longitude_min, &longitude_max,
00911             &latitude_min, &latitude_max)){
00912 
00913       // Create new Packet Header
00914       pkt_header = new PktHeader;
00915 
00916       // Fill in the new packet header
00917       pkt_header->pkt_num_ = msg->pkt_num_;
00918       pkt_header->rdm_id_ = msg->rdm_id_;
00919       pkt_header->prev_hop_ = msg->last_hop_;
00920       pkt_header->pkt_type_ = UNICAST_ORIGINAL;
00921       pkt_header->path_len_ = 0;
00922 
00923       pkt_header->dst_region_.center_.longitude_ = (longitude_min +
00924                             longitude_max) / 2;
00925       pkt_header->dst_region_.center_.latitude_ = (latitude_min +
00926                            latitude_max) / 2;
00927 
00928       pkt_header->dst_region_.radius_ = Distance(longitude_min, latitude_min,
00929                          longitude_max,
00930                          latitude_max) / 2;
00931 
00932       DiffPrintWithTime(DEBUG_IMPORTANT,
00933             "Gear - ExtractLocation %f,%f, %f,%f (%f,%f)\n",
00934             longitude_min, longitude_max,
00935             latitude_min, latitude_max,
00936             pkt_header->dst_region_.center_.longitude_,
00937             pkt_header->dst_region_.center_.latitude_);
00938     }
00939   }
00940 
00941   return pkt_header;
00942 }
00943 
00944 PktHeader * GeoRoutingFilter::stripOutHeader(Message *msg)
00945 {
00946   NRSimpleAttribute<void *> *geo_header_attribute;
00947   GeoHeader *geo_header;
00948   PktHeader *pkt_header = NULL;
00949 
00950   geo_header_attribute = GeoHeaderAttr.find(msg->msg_attr_vec_);
00951 
00952   if (geo_header_attribute){
00953     geo_header = (GeoHeader *)(geo_header_attribute->getVal());
00954 
00955     // Create Packet Header structure
00956     pkt_header = new PktHeader;
00957 
00958     pkt_header->pkt_num_ = msg->pkt_num_;
00959     pkt_header->rdm_id_ = msg->rdm_id_;
00960     pkt_header->prev_hop_ = msg->last_hop_;
00961 
00962     // Copy the msg from Geo_header to PktHeader
00963     pkt_header->pkt_type_ = geo_header->pkt_type_;
00964     pkt_header->dst_region_.center_.longitude_ = geo_header->dst_region_.center_.longitude_;
00965     pkt_header->dst_region_.center_.latitude_ = geo_header->dst_region_.center_.latitude_;
00966     pkt_header->dst_region_.radius_ = geo_header->dst_region_.radius_;
00967     pkt_header->path_len_ = geo_header->path_len_;
00968 
00969     takeOutAttr(msg->msg_attr_vec_, GEO_HEADER_KEY);
00970     delete geo_header_attribute;
00971 
00972     DiffPrintWithTime(DEBUG_IMPORTANT,
00973               "Gear - Got GeoHeader last hop: %d, pkt (%d, %d) !\n",
00974               msg->last_hop_, msg->pkt_num_, msg->rdm_id_);
00975     DiffPrintWithTime(DEBUG_IMPORTANT,
00976               "Gear - Type: %d, Region: (%f,%f):%f, Path: %d !\n",
00977               pkt_header->pkt_type_,
00978               pkt_header->dst_region_.center_.longitude_,
00979               pkt_header->dst_region_.center_.latitude_,
00980               pkt_header->dst_region_.radius_,
00981               pkt_header->path_len_);
00982   }
00983   else{
00984     DiffPrintWithTime(DEBUG_IMPORTANT,
00985               "Gear - GeoHeader Attribute not present !\n");
00986   }
00987   return pkt_header;
00988 }
00989 
00990 void GeoRoutingFilter::takeOutAttr(NRAttrVec *attrs, int32_t key)
00991 {
00992   NRAttrVec::iterator attr_itr;
00993 
00994   for (attr_itr = attrs->begin(); attr_itr != attrs->end(); ++attr_itr){
00995     if ((*attr_itr)->getKey() == key){
00996       break;
00997     }
00998   }
00999 
01000   if (attr_itr != attrs->end())
01001     attrs->erase(attr_itr);
01002 }
01003 
01004 bool GeoRoutingFilter::extractLocation(Message *msg,
01005                        float *longitude_min,
01006                        float *longitude_max,
01007                        float *latitude_min,
01008                        float *latitude_max)
01009 {
01010   NRSimpleAttribute<float> *lat_attr;
01011   NRSimpleAttribute<float> *long_attr;
01012   NRAttrVec::iterator itr;
01013   NRAttrVec *attrs;
01014   bool has_long_min = false;
01015   bool has_long_max = false;
01016   bool has_lat_min = false;
01017   bool has_lat_max = false;
01018 
01019   attrs = msg->msg_attr_vec_;
01020 
01021   // Extracts longitude coordinates for the target point/region from
01022   // this message
01023   itr = attrs->begin();
01024 
01025   for (;;){
01026 
01027     long_attr = LongitudeAttr.find_from(attrs, itr, &itr);
01028 
01029     if (!long_attr){
01030       if (has_long_min && has_long_max)
01031     break;
01032       else
01033     return false;
01034     }
01035 
01036     if ((long_attr->getOp() == NRAttribute::GT) ||
01037     (long_attr->getOp() == NRAttribute::GE)){
01038 
01039       // Check for double set of coordinates
01040       if (has_long_min)
01041     return false;
01042 
01043       has_long_min = true;
01044       *longitude_min = long_attr->getVal();
01045     }
01046 
01047     if ((long_attr->getOp() == NRAttribute::LT) ||
01048     (long_attr->getOp() == NRAttribute::LE)){
01049 
01050       // Check for double set of coordinates
01051       if (has_long_max)
01052     return false;
01053 
01054       has_long_max = true;
01055       *longitude_max = long_attr->getVal();
01056     }
01057 
01058     if (long_attr->getOp() == NRAttribute::EQ){
01059 
01060       // Check for double set of coordinates
01061       if (has_long_min || has_long_max)
01062     return false;
01063 
01064       has_long_min = true;
01065       has_long_max = true;
01066 
01067       *longitude_min = long_attr->getVal();
01068       *longitude_max = *longitude_min;
01069     }
01070 
01071     // Increment itr to avoid an infinite loop
01072     itr++;
01073   }
01074 
01075   // Now we extract latitude coordinates of the target region from the
01076   // message
01077   itr = attrs->begin();
01078 
01079   for (;;){
01080 
01081     lat_attr = LatitudeAttr.find_from(attrs, itr, &itr);
01082 
01083     if (!lat_attr){
01084       if (has_lat_min && has_lat_max)
01085     break;
01086       else
01087     return false;
01088     }
01089 
01090     if ((lat_attr->getOp() == NRAttribute::GT) ||
01091     (lat_attr->getOp() == NRAttribute::GE)){
01092 
01093       // Check for double set of coordinates
01094       if (has_lat_min)
01095     return false;
01096 
01097       has_lat_min = true;
01098       *latitude_min = lat_attr->getVal();
01099     }
01100 
01101     if ((lat_attr->getOp() == NRAttribute::LT) ||
01102     (lat_attr->getOp() == NRAttribute::LE)){
01103 
01104       // Check for double set of coordinates
01105       if (has_lat_max)
01106     return false;
01107 
01108       has_lat_max = true;
01109       *latitude_max = lat_attr->getVal();
01110     }
01111 
01112     if (lat_attr->getOp() == NRAttribute::EQ){
01113 
01114       // Check for double set of coordinates
01115       if (has_lat_min || has_lat_max)
01116     return false;
01117 
01118       has_lat_min = true;
01119       has_lat_max = true;
01120 
01121       *latitude_min = lat_attr->getVal();
01122       *latitude_max = *latitude_min;
01123     }
01124 
01125     // Increment itr to avoid an infinite loop
01126     itr++;
01127   }
01128 
01129   if (has_long_min && has_long_max && has_lat_min && has_lat_min)
01130     return true;
01131 
01132   return false;
01133 }
01134 
01135 GeoHeader * GeoRoutingFilter::restoreGeoHeader(PktHeader *pkt_header, Message *msg)
01136 {
01137   GeoHeader *geo_header;
01138 
01139   geo_header = new GeoHeader;
01140 
01141   msg->last_hop_ = pkt_header->prev_hop_;
01142 
01143   geo_header->pkt_type_ = pkt_header->pkt_type_;
01144   geo_header->dst_region_.center_.longitude_ = pkt_header->dst_region_.center_.longitude_;
01145   geo_header->dst_region_.center_.latitude_ = pkt_header->dst_region_.center_.latitude_;
01146   geo_header->dst_region_.radius_ = pkt_header->dst_region_.radius_;
01147   geo_header->path_len_ = pkt_header->path_len_;
01148 
01149   return geo_header;
01150 }
01151 
01152 int32_t GeoRoutingFilter::findNextHop(GeoHeader *geo_header, bool greedy)
01153 {
01154   NeighborList::iterator neighbor_itr;
01155   NeighborEntry *neighbor_entry;
01156   GeoLocation destination, min_neighbor_location;
01157   double current_learned_cost, min_learned_cost;
01158   double current_distance, min_distance;
01159   double distance, gap;
01160   int32_t min_cost_id, neighbor_id;
01161   int num_neighbors;
01162   double new_heuristic_value;
01163 
01164   // Load the destination coordinate from the packet
01165   destination = geo_header->dst_region_.center_;
01166 
01167   current_distance = Distance(geo_longitude_, geo_latitude_,
01168                   destination.longitude_, destination.latitude_);
01169 
01170   min_distance = MAX_INT;
01171   min_learned_cost = MAX_INT;
01172   num_neighbors = 0;
01173 
01174   // this is really to quiet the compiler.
01175   min_neighbor_location.longitude_ = 0;
01176   min_neighbor_location.latitude_ = 0;
01177   min_cost_id = 0;
01178 
01179   // Now we go through out list of neighbor and compute the cost to
01180   // each one
01181   for (neighbor_itr = neighbors_list_.begin();
01182        neighbor_itr != neighbors_list_.end(); ++neighbor_itr){
01183     neighbor_entry = *neighbor_itr;
01184     num_neighbors++;
01185 
01186     neighbor_id = neighbor_entry->id_;
01187     current_learned_cost = retrieveLearnedCost(neighbor_id, destination);
01188 
01189     // Calculate distance from this neighbor to dst
01190     distance = Distance(neighbor_entry->longitude_, neighbor_entry->latitude_,
01191             destination.longitude_, destination.latitude_);
01192 
01193     // If we are in 'greedy mode', we do not want to move away, so we
01194     // skip neighbors that are farther away than us from the region
01195     if (greedy && (distance > current_distance))
01196       continue;
01197 
01198     DiffPrintWithTime(DEBUG_IMPORTANT,
01199               "Gear - Neighbor: %d: cost = %f, min_cost = %f\n",
01200               neighbor_id, current_learned_cost, min_learned_cost);
01201 
01202     // Found a neighbor with a lower cost
01203     if (current_learned_cost < min_learned_cost){
01204       min_learned_cost = current_learned_cost;
01205       min_cost_id = neighbor_entry->id_;
01206       min_neighbor_location.longitude_ = neighbor_entry->longitude_;
01207       min_neighbor_location.latitude_ = neighbor_entry->latitude_;
01208     }
01209   }
01210 
01211   DiffPrintWithTime(DEBUG_IMPORTANT,
01212             "Gear - # neighbors: %d; cur: %f,%f, dst: %f,%f\n",
01213             num_neighbors, geo_longitude_, geo_latitude_,
01214             destination.longitude_, destination.latitude_);
01215 
01216   // Check if we have neighbors we can use to forward this message
01217   if (min_learned_cost < MAX_INT){
01218 
01219     // Calculate the cost from me to my next hop neighbor
01220     gap = Distance(min_neighbor_location.longitude_,
01221            min_neighbor_location.latitude_,
01222            geo_longitude_, geo_latitude_);
01223 
01224     // Update my heuristic_value
01225     new_heuristic_value = min_learned_cost + gap;
01226 
01227     // Broadcast the new heuristic value if it's changed significantly
01228     if (h_value_table_.updateEntry(destination, new_heuristic_value))
01229       broadcastHeuristicValue(destination, new_heuristic_value);
01230 
01231     // Return neighbor this message should go
01232     return min_cost_id;
01233   }
01234 
01235   // We have no neighbors to whom we can forward this message !
01236   return BROADCAST_ADDR;
01237 }
01238 
01239 void GeoRoutingFilter::broadcastHeuristicValue(GeoLocation dst,
01240                            double new_heuristic_value)
01241 {
01242   NRAttrVec attrs;
01243   HeuristicValue *heuristic_value;
01244   Message *beacon_msg;
01245   TimerCallback *beacon_timer;
01246 
01247   attrs.push_back(GeoLongitudeAttr.make(NRAttribute::IS, geo_longitude_));
01248   attrs.push_back(GeoLatitudeAttr.make(NRAttribute::IS, geo_latitude_));
01249   attrs.push_back(GeoRemainingEnergyAttr.make(NRAttribute::IS,
01250                           remainingEnergy()));
01251   attrs.push_back(GeoBeaconTypeAttr.make(NRAttribute::IS, GEO_UPDATE));
01252 
01253   heuristic_value = new HeuristicValue(dst.longitude_,
01254                        dst.latitude_, new_heuristic_value);
01255 
01256   attrs.push_back(GeoHeuristicValueAttr.make(NRAttribute::IS,
01257                          (void *) heuristic_value,
01258                          sizeof(HeuristicValue)));
01259 
01260   beacon_msg = new Message(DIFFUSION_VERSION, DATA, 0, 0,
01261                attrs.size(), pkt_count_, rdm_id_,
01262                BROADCAST_ADDR, LOCALHOST_ADDR);
01263 
01264   // Don't forget to increase pkt_count
01265   pkt_count_++;
01266 
01267   beacon_msg->msg_attr_vec_ = CopyAttrs(&attrs);
01268 
01269   // Now, we generate a beacon to broadcast triggered h-value update
01270   // but first we add some random jitter before actually sending it
01271   beacon_timer = new GeoMessageSendTimer(this, CopyMessage(beacon_msg));
01272 
01273   ((DiffusionRouting *)dr_)->addTimer(GEO_BEACON_DELAY +
01274                       (int) ((GEO_BEACON_JITTER *
01275                           (GetRand() * 1.0 / RAND_MAX) -
01276                           (GEO_BEACON_JITTER / 2))),
01277                       beacon_timer);
01278 
01279   // Delete everything we created here
01280   ClearAttrs(&attrs);
01281   delete beacon_msg;
01282   delete heuristic_value;
01283 }
01284 
01285 int GeoRoutingFilter::floodInsideRegion(GeoHeader *geo_header)
01286 {
01287   NeighborList::iterator neighbor_itr;
01288   NeighborEntry *neighbor_entry;
01289   GeoLocation destination;
01290   double radius, distance;
01291 
01292   // Load destination coordinates
01293   destination = geo_header->dst_region_.center_;
01294   radius = geo_header->dst_region_.radius_;
01295 
01296   if (Distance(geo_longitude_, geo_latitude_,
01297            destination.longitude_, destination.latitude_) <= radius){
01298 
01299     // We are inside the target region, change mode to BROADCAST
01300     geo_header->pkt_type_ = BROADCAST_TYPE;
01301 
01302     DiffPrintWithTime(DEBUG_IMPORTANT,
01303               "Gear - Packet inside target region !\n");
01304     
01305     // If all my neighbors are outside this region, suppress this
01306     // broadcast message
01307     for (neighbor_itr = neighbors_list_.begin();
01308      neighbor_itr != neighbors_list_.end(); ++neighbor_itr){
01309       neighbor_entry = *neighbor_itr;
01310 
01311       DiffPrintWithTime(DEBUG_IMPORTANT,
01312             "Gear - Neighbor %d, %lf,%lf !\n",
01313             neighbor_entry->id_,
01314             neighbor_entry->longitude_, neighbor_entry->latitude_);
01315 
01316       // Calculate distance between neighbor and dst
01317       distance = Distance(neighbor_entry->longitude_,
01318               neighbor_entry->latitude_,
01319               destination.longitude_, destination.latitude_);
01320 
01321       // As long as we have one neighbor inside the region, broadcast
01322       // the message
01323       if (distance < radius)
01324     return BROADCAST;
01325     }
01326     return BROADCAST_SUPPRESS;
01327   }
01328   else{
01329     if (geo_header->pkt_type_ == BROADCAST_TYPE){
01330       // This is a BROADCAST packet flooded outside the region
01331       return BROADCAST_SUPPRESS;
01332     }
01333     else{
01334       // We are still outside the target region, continue forwading
01335       // the packet towards the region
01336       return OUTSIDE_REGION;
01337     }
01338   }
01339 }
01340 
01341 double GeoRoutingFilter::retrieveLearnedCost(int neighbor_id, GeoLocation dst)
01342 {
01343   int index;
01344 
01345   index = learned_cost_table_.retrieveEntry(neighbor_id, &dst);
01346 
01347   if (index != FAIL)
01348     return learned_cost_table_.table_[index].learned_cost_value_;
01349   else
01350     return estimateCost(neighbor_id, dst);
01351 }
01352 
01353 double GeoRoutingFilter::estimateCost(int neighbor_id, GeoLocation dst)
01354 {
01355   NeighborEntry *neighbor_entry;
01356   double distance;
01357 
01358   // To get this neighbor's location, we first find the entry with neighbor_id
01359   // Since right now it is pure geographical routing, the estimated cost is
01360   // just the distance between neighbor_id to dst.
01361   if (neighbor_id < 0){
01362     DiffPrintWithTime(DEBUG_IMPORTANT,
01363               "Gear - Invalid neighbor id: %d !\n", neighbor_id);
01364     return FAIL;
01365   }
01366 
01367   neighbor_entry = findNeighbor(neighbor_id);
01368 
01369   if (!neighbor_entry)
01370     return FAIL;
01371 
01372   distance = Distance(neighbor_entry->longitude_, neighbor_entry->latitude_,
01373               dst.longitude_, dst.latitude_);
01374 
01375   return distance;
01376 }
01377 
01378 NeighborEntry * GeoRoutingFilter::findNeighbor(int32_t neighbor_id)
01379 {
01380   NeighborList::iterator neighbor_itr;
01381   NeighborEntry *neighbor_entry;
01382 
01383   for (neighbor_itr = neighbors_list_.begin();
01384        neighbor_itr != neighbors_list_.end(); ++neighbor_itr){
01385     neighbor_entry = *neighbor_itr;
01386     if (neighbor_entry->id_ == neighbor_id)
01387       return neighbor_entry;
01388   }
01389   return NULL;
01390 }
01391 
01392 double GeoRoutingFilter::retrieveHeuristicValue(GeoLocation dst)
01393 {
01394   int index;
01395 
01396   index = h_value_table_.retrieveEntry(&dst);
01397 
01398   if (index != FAIL)
01399     return h_value_table_.table_[index].heuristic_value_;
01400 
01401   return INITIAL_HEURISTIC_VALUE;
01402 }
01403 
01404 #ifndef USE_SINGLE_ADDRESS_SPACE
01405 int main(int argc, char **argv)
01406 {
01407   GeoRoutingFilter *geo_filter;
01408 
01409   geo_filter = new GeoRoutingFilter(argc, argv);
01410   geo_filter->run();
01411 
01412   return 0;
01413 }
01414 #endif // !USE_SINGLE_ADDRESS_SPACE

Generated on Tue Mar 6 16:47:45 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6