N-sim
Emulation and simulation of
Wireless Sensor Networks



   Home


   Project Page


   Download


   CVS



   Installation


   Configuration


   Plug-ins




 Hosted by
SourceForge.net Logo

/home/brennan/n-sim/Vaike/linux/system-addons/networking/mesh_neighbor.c

Go to the documentation of this file.
00001 
00014 /*
00015  * Copyright 2007. Los Alamos National Security, LLC. This material
00016  * was produced under U.S. Government contract DE-AC52-06NA25396 for
00017  * Los Alamos National Laboratory (LANL), which is operated by Los
00018  * Alamos National Security, LLC, for the Department of Energy. The
00019  * U.S. Government has rights to use, reproduce, and distribute this
00020  * software. NEITHER THE GOVERNMENT NOR LOS ALAMOS NATIONAL SECURITY,
00021  * LLC, MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL
00022  * LIABILITY FOR THE USE OF THIS SOFTWARE. If software is modified to
00023  * produce derivative works, such modified software should be clearly
00024  * marked, so as not to confuse it with the version available from LANL.
00025  *
00026  * Additionally, this program is free software; you can redistribute
00027  * it and/or modify it under the terms of the GNU General Public
00028  * License as published by the Free Software Foundation; version 2 of
00029  * the License. Accordingly, this program is distributed in the hope
00030  * it will be useful, but WITHOUT ANY WARRANTY; without even the
00031  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00032  * PURPOSE. See the GNU General Public License for more details.
00033  */
00034 
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include <unistd.h>
00039 #include <sys/socket.h>
00040 #include <netinet/in.h>
00041 #include <arpa/inet.h>
00042 #include <net/route.h>
00043 #include <errno.h>
00044 #include <syslog.h>
00045 #include <netdb.h>
00046 #include <math.h>
00047 
00048 #include "mesh_neighbor.h"
00049 #include "sensor_self.h"
00050 
00051 #define MESH_N_DISCOVERY_PORT   652
00052 
00055 #define HELLO_LEN               ((sizeof(double)*3) + 32)
00056 #define HELLO_INTERVAL          180  // 3 minutes
00057 
00058 
00059 unsigned int mac_to_id(char *addr)
00060 {
00061   return addr[4] << 12 | addr[5] << 8 | addr[6] << 4 | addr[7];
00062 }
00063 
00064 
00065 void init_n_entry(self_t *self, neighbor_entry_t *entry)
00066 {
00067   entry->node_id = mac_to_id(self->mac_addr);
00068   entry->lat = self->latitude;
00069   entry->lon = self->longitude;
00070   entry->alt = self->altitude;
00071 }
00072 
00073 
00074 neighbor_entry_t *new_n_entry(self_t *self)
00075 {
00076   neighbor_entry_t *neighbor = malloc(sizeof(neighbor_entry_t));
00077   init_n_entry(self, neighbor);
00078   return neighbor;
00079 }
00080 
00081 
00082 int add_n_entry(self_t *self, unsigned int id, neighbor_entry_t *entry)
00083 {
00084   if (self == NULL || entry == NULL) {
00085     errno = EINVAL;
00086     return -1;
00087   }
00088 
00089   entry->node_id = id;
00090   return avl_insert(entry, id, &self->neighbors);
00091 }
00092 
00093 
00094 int remove_n_entry(self_t *self, unsigned int id, neighbor_entry_t *entry)
00095 {
00096   if (self == NULL) {
00097     errno = EINVAL;
00098     return -1;
00099   }
00100   return avl_delete(entry, id, &self->neighbors);
00101 }
00102 
00103 
00104 neighbor_entry_t *retrieve_n_entry(self_t *self, unsigned int id)
00105 {
00106   return avl_retrieve(id, &self->neighbors);
00107 }
00108 
00109 
00110 neighbor_entry_t *iterate_n_entries(self_t *self)
00111 {
00112   if (self->n_iter == NULL)
00113     self->n_iter = avl_find_min(&self->neighbors);
00114   else
00115     self->n_iter = self->n_iter->next;
00116 
00117   if (self->n_iter == NULL)
00118     return NULL;
00119 
00120    return (neighbor_entry_t*) self->n_iter->element;
00121 }
00122 
00123 
00124 unsigned int num_n_entries(self_t *self)
00125 {
00126   return avl_size(&self->neighbors);
00127 }
00128 
00129 
00130 void empty_n_entries(self_t *self)
00131 {
00132   neighbor_entry_t *cur = NULL;
00133   self->n_iter = NULL;
00134 
00135   while ((cur = iterate_n_entries(self)) != NULL)
00136     free(cur);
00137 
00138   destroy_avltree(self->neighbors.root);
00139   self->neighbors.root = NULL;
00140 }
00141 
00142 
00143 neighbor_entry_t *neighbor_by_position(self_t *self,
00144                                        double bearing, double distance)
00145 {
00146   neighbor_entry_t *cur = NULL;
00147   self->n_iter = NULL;
00148 
00149   while ((cur = iterate_n_entries(self)) != NULL) {
00150     if (fabs(bearing - cur->bearing) < 1 &&
00151         fabs(distance - cur->distance) < 1)
00152       return cur;
00153   }
00154   return NULL;
00155 }
00156 
00157 
00158 neighbor_entry_t *neighbor_by_ip(self_t *self, struct sockaddr_in *ip)
00159 {
00160   neighbor_entry_t *cur = NULL;
00161   self->n_iter = NULL;
00162 
00163   while ((cur = iterate_n_entries(self)) != NULL) {
00164     if (memcmp(&ip->sin_addr, &cur->ip.sin_addr,
00165                sizeof(struct sockaddr_in)) == 0)
00166       return cur;
00167   }
00168   return NULL;
00169 }
00170 
00171 
00172 int neighbor_address(self_t *self, char *addr,
00173                      double bearing, double distance)
00174 {
00175   neighbor_entry_t *cur = neighbor_by_position(self, bearing, distance);
00176 
00177   if (cur == NULL)
00178     return -1;
00179 
00180   memcpy(addr, cur->address, MAC_ADDR_LEN);
00181   return 0;
00182 }
00183 
00184 
00185 int neighbor_position(self_t *self, double *bearing, double *distance,
00186                       char *addr)
00187 {
00188   neighbor_entry_t *entry = retrieve_n_entry(self, mac_to_id(addr));
00189   if (entry == NULL || memcmp(entry->address, addr, MAC_ADDR_LEN) != 0) {
00190     errno = EINVAL;
00191     return -1;
00192   }
00193   *bearing = entry->bearing;
00194   *distance = entry->distance;
00195   return 0;
00196 }
00197 
00198 
00199 
00200 int find_neighbors(self_t *self)
00201 {
00202   int sd;
00203   char hello[HELLO_LEN];
00204   struct sockaddr_in to;
00205   struct hostent *he;
00206 
00207   if ((sd = mesh_socket(self->interface, MESH_N_DISCOVERY_PORT)) < 0)
00208     return sd;
00209 
00210   if ((he = gethostbyname(self->broadcast)) == NULL) {
00211     syslog(LOG_ERR, "gethostbyname(%s): %s",
00212            self->broadcast, hstrerror(h_errno));
00213     return -1;
00214   }
00215   to.sin_family = AF_INET;
00216   to.sin_port = htons(MESH_N_DISCOVERY_PORT);
00217   to.sin_addr = *((struct in_addr*)he->h_addr);
00218   memset(&(to.sin_zero), 0, sizeof(to.sin_zero));
00219 
00220   sprintf(hello, "HELLO::%hhu:%hhu:%hhu:%hhu:%hhu:%hhu:%hhu:%hhu::%lf:%lf:%lf",
00221           self->mac_addr[0], self->mac_addr[1], self->mac_addr[2],
00222           self->mac_addr[3], self->mac_addr[4], self->mac_addr[5],
00223           self->mac_addr[6], self->mac_addr[7], 
00224           self->latitude, self->longitude, self->altitude);
00225 
00226   return mesh_sendmsg(self->interface, self->mac_addr, sd,
00227                       hello, strlen(hello), &to);
00228 }
00229 
00230 
00231 // TODO: make three dimensional
00232 /* using a spherical approximation (haversine) */
00233 static double latlng_to_dist(double lat1, double lng1, double alt1,
00234                              double lat2, double lng2, double alt2)
00235 {
00236   double unit_conversion = 1852.0; /* meters */
00237   double to_radians = M_PI / 180.0;
00238   double to_degrees = 180.0 / M_PI;
00239 
00240   double rad_lat1 = to_radians * lat1;
00241   double rad_lat2 = to_radians * lat2;
00242   double dlng = (to_radians * lng2) - (to_radians * lng1);
00243 
00244   double a = pow(sin(dlng / 2), 2) +
00245     cos(rad_lat1) * cos(rad_lat2) * pow(sin(dlng / 2), 2);
00246   double dist = 2 * atan2(sqrt(a), sqrt(1.0 - a));
00247 
00248   return (dist * to_degrees) * 60.0 * unit_conversion;
00249 }
00250 
00251 // TODO: make three dimensional
00252 static double latlng_to_bearing(double lat1, double lng1, double alt1,
00253                                 double lat2, double lng2, double alt2)
00254 {
00255   double to_radians = M_PI / 180.0;
00256   double to_degrees = 180.0 / M_PI;
00257 
00258   double rad_lat1 = to_radians * lat1;
00259   double rad_lat2 = to_radians * lat2;
00260   double dlng = (to_radians * lng2) - (to_radians * lng1);
00261 
00262   double y = sin(dlng) * cos(rad_lat2);
00263   double x = cos(rad_lat1) * sin(rad_lat2) -
00264     sin(rad_lat1) * cos(rad_lat2) * cos(dlng);
00265 
00266   double theta = atan2(y, x) * to_degrees;
00267   return (theta < 0.0) ? (theta + 360.0) : theta;
00268 }
00269 
00270 
00271 
00272 /* thread */
00273 int neighbor_discovery(self_t *self)
00274 {
00275   int sd;
00276 
00277   if (self == NULL) {
00278     errno = EINVAL;
00279     return -1;
00280   }
00281 
00282   if ((sd = mesh_socket(self->interface, MESH_N_DISCOVERY_PORT)) < 0)
00283     return sd;
00284 
00285   while (1) {
00286     ssize_t bytes = 0;
00287     int error = 0;
00288     char hello[HELLO_LEN+1];
00289     struct sockaddr_in from;
00290     neighbor_entry_t *neighbor;
00291 
00292     if ((bytes = timed_recv(sd, hello, HELLO_LEN,
00293                             &from, HELLO_INTERVAL)) < 0) {
00294       if (bytes == -2)
00295         find_neighbors(self);
00296       else
00297         syslog(LOG_ERR, "timed_recv: %m");
00298       continue;
00299     }
00300     hello[bytes] = '\0';
00301 
00302     neighbor = new_n_entry(self);
00303     if ((error = sscanf(hello,
00304                  "HELLO::%hhu:%hhu:%hhu:%hhu:%hhu:%hhu:%hhu:%hhu::%lf:%lf:%lf",
00305                         &neighbor->address[0], &neighbor->address[1],
00306                         &neighbor->address[2], &neighbor->address[3],
00307                         &neighbor->address[4], &neighbor->address[5],
00308                         &neighbor->address[6], &neighbor->address[7], 
00309                         &neighbor->lat, &neighbor->lon,
00310                         &neighbor->alt)) < 11) {
00311       if (error < 0)
00312         syslog(LOG_ERR, "sscanf: %m");
00313       free(neighbor);
00314     }
00315 
00316     memcpy(&neighbor->ip, &from, sizeof(struct sockaddr_in));
00317     neighbor->ip.sin_port = htons(MESH_N_COMM_PORT);
00318     neighbor->node_id = mac_to_id(neighbor->address);
00319     neighbor->bearing = latlng_to_bearing(self->latitude, self->longitude,
00320                                           self->altitude, neighbor->lat,
00321                                           neighbor->lon, neighbor->alt);
00322     neighbor->distance = latlng_to_dist(self->latitude, self->longitude,
00323                                         self->altitude, neighbor->lat,
00324                                         neighbor->lon, neighbor->alt);
00325     neighbor->next = NULL;
00326 
00327     add_n_entry(self, neighbor->node_id, neighbor);
00328   }
00329   close(sd);
00330   return 0;
00331 }


© 2007, Los Alamos National Security, LLC.