Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

geo-routing.cc

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

Generated on Tue Apr 20 12:14:18 2004 for NS2.26SourcesOriginal by doxygen 1.3.3