67774d86b5209a6447611492196410817b14fc45
[olsrd.git] / lib / nameservice / src / mapwrite.c
1 /*
2  * Copyright (c) 2007, Sven-Ola <sven-ola-aet-gmx.de>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without 
6  * modification, are permitted provided that the following conditions 
7  * are met:
8  *
9  * * Redistributions of source code must retain the above copyright notice, 
10  *   this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above copyright notice, 
12  *   this list of conditions and the following disclaimer in the documentation 
13  *   and/or other materials provided with the distribution.
14  * * Neither the name of the UniK olsr daemon nor the names of its contributors 
15  *   may be used to endorse or promote products derived from this software 
16  *   without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
21  * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
22  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
23  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
25  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
26  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
27  * OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  */
30
31  
32 #include <stdio.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39
40 #include "defs.h"
41 #include "scheduler.h"
42 #include "nameservice.h"
43 #include "mid_set.h"
44 #include "tc_set.h"
45 #include "ipcalc.h"
46 #include "mapwrite.h"
47
48 static char my_latlon_str[48];
49
50 /**
51  * lookup a nodes position
52  */
53 static char* lookup_position_latlon(union olsr_ip_addr *ip)
54 {
55   int hash;
56   struct db_entry *entry;
57   if (ipequal(ip, &olsr_cnf->main_addr))
58   {
59     return my_latlon_str;
60   }
61   for (hash = 0; hash < HASHSIZE; hash++) 
62   {
63     for(entry = latlon_list[hash]; entry != NULL; entry = entry->next)
64     {
65       if (NULL != entry->names && ipequal(&entry->originator, ip))
66       {
67         return entry->names->name;
68       }
69     }
70   }
71   return NULL;
72 }
73
74 /**
75  * write latlon positions to a file
76  */
77 void mapwrite_work(FILE* fmap)
78 {
79   int hash;
80   struct olsr_if *ifs;
81   union olsr_ip_addr ip;
82   struct ipaddr_str strbuf1, strbuf2;
83   struct tc_entry *tc;
84   struct tc_edge_entry *tc_edge;
85
86   if (!my_names || !fmap) return;
87
88   for (ifs = olsr_cnf->interfaces; ifs; ifs = ifs->next)
89   {
90     if (0 != ifs->interf)
91     {
92       if (olsr_cnf->ip_version == AF_INET)
93       {
94         if (!(ip4equal((struct in_addr *)&olsr_cnf->main_addr, &ifs->interf->int_addr.sin_addr)))
95         {
96           if (0 > fprintf(fmap, "Mid('%s','%s');\n",
97             olsr_ip_to_string(&strbuf1, &olsr_cnf->main_addr),
98             olsr_ip_to_string(&strbuf2, (union olsr_ip_addr *)&ifs->interf->int_addr.sin_addr)))
99           {
100             return;
101           }
102         }
103       }
104       else if (!(ip6equal((struct in6_addr *)&olsr_cnf->main_addr, &ifs->interf->int6_addr.sin6_addr)))
105       {
106         if (0 > fprintf(fmap, "Mid('%s','%s');\n",
107           olsr_ip_to_string(&strbuf1, &olsr_cnf->main_addr),
108           olsr_ip_to_string(&strbuf2, (union olsr_ip_addr *)&ifs->interf->int6_addr.sin6_addr)))
109         {
110           return;
111         }
112       }
113     }
114   }
115
116   for (hash = 0; hash < HASHSIZE; hash++) 
117   {
118     struct mid_entry *entry = mid_set[hash].next;
119     while(entry != &mid_set[hash])
120     {
121       struct mid_address *alias = entry->aliases;
122       while(alias)
123       {
124         if (0 > fprintf(fmap, "Mid('%s','%s');\n",
125           olsr_ip_to_string(&strbuf1, &entry->main_addr),
126           olsr_ip_to_string(&strbuf2, &alias->alias)))
127         {
128           return;
129         }
130         alias = alias->next_alias;
131       }
132       entry = entry->next;
133     }
134   }
135   lookup_defhna_latlon(&ip);
136   sprintf(my_latlon_str, "%f,%f,%d", my_lat, my_lon, get_isdefhna_latlon());
137   if (0 > fprintf(fmap, "Self('%s',%s,'%s','%s');\n",
138     olsr_ip_to_string(&strbuf1, &olsr_cnf->main_addr), my_latlon_str, 
139     olsr_ip_to_string(&strbuf2, &ip), my_names->name))
140   {
141     return;
142   }
143   for (hash = 0; hash < HASHSIZE; hash++) 
144   {
145     struct db_entry *entry;
146     for(entry = latlon_list[hash]; entry != NULL; entry = entry->next)
147     {
148       if (NULL != entry->names)
149       {
150         if (0 > fprintf(fmap, "Node('%s',%s,'%s','%s');\n",
151           olsr_ip_to_string(&strbuf1, &entry->originator),
152           entry->names->name, olsr_ip_to_string(&strbuf2, &entry->names->ip),
153           lookup_name_latlon(&entry->originator)))
154         {
155           return;
156         }
157       }
158     }
159   }
160
161   OLSR_FOR_ALL_TC_ENTRIES(tc) {
162   OLSR_FOR_ALL_TC_EDGE_ENTRIES(tc, tc_edge) {
163     char* lla = lookup_position_latlon(&tc->addr);
164     char* llb = lookup_position_latlon(&tc_edge->T_dest_addr);
165     if (NULL != lla && NULL != llb)
166     {
167       /*
168        * To speed up processing, Links with both positions are named PLink()
169        */
170       if (0 > fprintf(fmap, "PLink('%s','%s',%f,%f,%f,%s,%s);\n", 
171             olsr_ip_to_string(&strbuf1, &tc_edge->T_dest_addr),
172             olsr_ip_to_string(&strbuf2, &tc->addr), 
173             tc_edge->link_quality,
174             tc_edge->inverse_link_quality,
175             (tc_edge->link_quality * tc_edge->inverse_link_quality) ?
176               1.0 / (tc_edge->link_quality * tc_edge->inverse_link_quality) : 0.0,
177             lla, llb))
178       {
179         return;
180       }
181     }
182     else
183     {
184       /*
185        * If one link end pos is unkown, only send Link()
186        */
187       if (0 > fprintf(fmap, "Link('%s','%s',%f,%f,%f);\n", 
188             olsr_ip_to_string(&strbuf1, &tc_edge->T_dest_addr),
189             olsr_ip_to_string(&strbuf2, &tc->addr), 
190             tc_edge->link_quality,
191             tc_edge->inverse_link_quality,
192             (tc_edge->link_quality * tc_edge->inverse_link_quality) ?
193               1.0 / (tc_edge->link_quality * tc_edge->inverse_link_quality) : 0.0))
194       {
195         return;
196       }
197     }
198   } OLSR_FOR_ALL_TC_EDGE_ENTRIES_END(tc, tc_edge);
199   } OLSR_FOR_ALL_TC_ENTRIES_END(tc);
200 }
201
202 #ifndef WIN32
203
204 /*
205  * Windows doesn't know fifo's AFAIK. We better write
206  * to a file (done in nameservice.c, see #ifdef WIN32)
207  */
208  
209 static const char* the_fifoname = 0;
210 static int fifopolltime = 0;
211
212 static void mapwrite_poll(void)
213 {
214   fifopolltime++;
215   if (0 == (fifopolltime & 7) && 0 != the_fifoname)
216   {
217     FILE * fout;
218     /* Non-blocking means: fail open if no pipe reader */
219     int fd = open(the_fifoname, O_WRONLY | O_NONBLOCK);
220     if (0 <= fd)
221     {
222       /* 
223        * Change to blocking, otherwhise expect fprintf errors
224        */
225       fcntl(fd, F_SETFL, O_WRONLY);
226       fout = fdopen(fd, "w");
227       if (0 != fout)
228       {
229         mapwrite_work(fout);
230         fclose(fout);
231         /* Give pipe reader cpu slot to detect EOF */
232         usleep(1);
233       }
234       else
235       {
236         close(fd);
237       }
238     }
239   }
240 }
241
242 int mapwrite_init(const char* fifoname)
243 {
244   the_fifoname = fifoname;
245   if (0 != fifoname && 0 != *fifoname)
246   {
247     unlink(fifoname);
248     if (0 > mkfifo(fifoname, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH))
249     {
250       OLSR_PRINTF(1, "mkfifo(%s): %s", fifoname, strerror(errno));
251       return OLSR_FALSE;
252     }
253     else
254     {
255       the_fifoname = fifoname;
256       olsr_register_timeout_function(&mapwrite_poll, OLSR_FALSE);
257     }
258   }
259   return OLSR_TRUE;
260 }
261
262 void mapwrite_exit(void)
263 {
264   if (0 != the_fifoname)
265   {
266     unlink(the_fifoname);
267     /* Ignore any Error */
268     the_fifoname = 0;
269   }
270 }
271 #endif
272
273 /*
274  * Local Variables:
275  * mode: c
276  * c-indent-tabs-mode: t
277  * c-basic-offset: 4
278  * tab-width: 4
279  * End:
280  */