00001
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
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
00232
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;
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
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
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 }