8586433d82411a9847f6afbb8d1954c4944d9f83
[cilux] / src / drivers / op / uri2chan.c
1
2 /* -}{----------------------------------------------------------------------- */
3
4 #include <kernelapi.h>
5 #include <notification.h>
6
7 /* -}{----------------------------------------------------------------------- */
8
9 extern int connection_writable(k_channel* chan, int bufpos, int len);
10 extern int connection_readable(k_channel* chan, int bufpos, int len);
11
12 /* -}{----------------------------------------------------------------------- */
13
14 #define TMPBUFSIZE  4096
15 static char         tmpbuf[TMPBUFSIZE];
16 static int          is_np;
17 static char*        nexus_channel;
18 static k_hashtable* chans_for_host;
19
20 /* -}{----------------------------------------------------------------------- */
21
22 static void   nexus_file_read(char*, char*, char*, int, k_stat, void*);
23 static void   write_nexus(char* hostname);
24 static void   nexus_file_written(char*, char*, char*, int, k_stat, void*);
25 static int    root_nexus(void);
26 static void   listen_http(void);
27 static void   listen_nexus(void);
28 static void   connect_to_nexus(void);
29 static void   ping_this(void* arg, char* key, void* val);
30 static char*  generate_new_hostname(k_hashtable* ent_head, k_channel* chan);
31 static void   set_channel_for(char* host, char* chanm);
32 static void   show_np(void);
33 static void   show_list(void* arg, char* key, void* val);
34
35 /* -}{----------------------------------------------------------------------- */
36
37 void init_uri2chan(void)
38 {
39         chans_for_host =k_hashtable_new("Channels for Host", 0);
40
41         k_file_read(".", "nexus.txt", USE_MALL, 0, nexus_file_read, 0);
42
43         is_np=!strcmp(k_ciux, "op");
44         if(is_np)        listen_nexus();
45         if(root_nexus()){
46                 k_log_out("root nexus - but listening on http");
47                 listen_http();
48         }
49         else{
50                 k_log_out("connecting to nexus %s", nexus_channel);
51                 connect_to_nexus();
52         }
53 }
54
55 char* get_host_for(char* uri)
56 {
57         if(0) k_log_out("get_host_for %s", uri);
58         char* host=0;
59         if(0) k_log_out("host for %s=%s", uri, host);
60         return host;
61 }
62
63 char* get_channel_for(char* host)
64 {
65         if(0) k_log_out("get_channel_for %s", host);
66         char* chanm=k_hashtable_get(chans_for_host, host);
67         if(!chanm){
68         }
69         if(0) k_log_out("channel for %s=%s", host, chanm);
70         return chanm;
71 }
72
73 char* use_ping_info(k_hashtable* ent_head, k_channel* chan)
74 {
75         char* from=k_hashtable_get(ent_head, "From:");
76         char* to  =k_hashtable_get(ent_head, "To:");
77
78         if(!from) return 0;
79         if(!strcmp(from, "-")) from=generate_new_hostname(ent_head, chan);
80         if(!from) return 0;
81         if(!ni_hostname() && to) write_nexus(to);
82
83         set_channel_for(from, chan->name);
84
85         if(0) k_log_out("%s PING %s", chan->name, from);
86         if(0) show_np();
87
88         return from;
89 }
90
91 void use_from_info(k_hashtable* ent_head, k_channel* chan)
92 {
93         char* from=k_hashtable_get(ent_head, "From:");
94
95         if(!from) return;
96
97         set_channel_for(from, chan->name);
98
99         if(0) show_np();
100 }
101
102 void ping_tunnels(void)
103 {
104         k_hashtable* channelspinged=k_hashtable_new("channelspinged", 0);
105         k_hashtable_apply(chans_for_host, ping_this, channelspinged);
106         k_hashtable_delete(channelspinged);
107 }
108
109 void send_ping(k_channel* chan, char* firstline, char* to)
110 {
111         char* from=ni_hostname();
112         if(!from) from="-";
113
114         int ln=0;
115         int bufsize=TMPBUFSIZE;
116
117         ln+=snprintf(tmpbuf+ln, bufsize-ln, "%s" CRLF, firstline);
118         if(ln>=bufsize) return;
119         ln+=snprintf(tmpbuf+ln, bufsize-ln, "From: %s" CRLF, from);
120         if(ln>=bufsize) return;
121         if(to){
122         ln+=snprintf(tmpbuf+ln, bufsize-ln, "To: %s" CRLF, to);
123         if(ln>=bufsize) return;
124         }
125         ln+=snprintf(tmpbuf+ln, bufsize-ln, "Server: %s" CRLF, k_version);
126         if(ln>=bufsize) return;
127         ln+=snprintf(tmpbuf+ln, bufsize-ln, "Channels: %s" CRLF, "-");
128         if(ln>=bufsize) return;
129         ln+=snprintf(tmpbuf+ln, bufsize-ln, CRLF);
130         if(ln>=bufsize) return;
131
132         char* head=k_strdup(tmpbuf);
133         k_channel_send(chan, head, ln, FREE_ON_SENT);
134 }
135
136 /* -}{----------------------------------------------------------------------- */
137
138 void nexus_file_read(char*  basedir,
139                      char*  filepath,
140                      char*  data,
141                      int    usedmmap,
142                      k_stat kstat,
143                      void*  context)
144 {
145         int L=0;
146         if(data) data[kstat.size-1]=0;
147         else     data=k_strdup("");
148         k_hashtable* nex=k_hashtable_new("nexus", 1);
149         if(!ni_get_headers(data, nex, 0)){
150                 k_log_err("Corrupt nexus.txt file");
151                 k_hashtable_delete(nex);
152                 k_free(data);
153                 data=k_strdup("");
154                 nex=k_hashtable_new("nexus", 1);
155                 ni_get_headers(data, nex, 0);
156         }
157
158         char* hostname;
159         nexus_channel=k_hashtable_get_dup(nex, "Nexus-Channel:");
160         hostname     =k_hashtable_get(    nex, "Hostname:");
161
162         if(hostname) ni_hostname_set(hostname);
163
164         if(L) if(nexus_channel) k_log_out("Nexus-Channel: %s", nexus_channel);
165         if(L) if(hostname)      k_log_out("Hostname: %s",      hostname);
166
167         k_hashtable_delete(nex);
168         k_free(data);
169 }
170
171 void write_nexus(char* hostname)
172 {
173         ni_hostname_set(hostname);
174
175         snprintf(tmpbuf, TMPBUFSIZE, "Nexus-Channel: %s\r\n"
176                                      "Hostname:      %s\r\n", nexus_channel,
177                                                               hostname);
178
179         k_file_write(".", "nexus.txt", tmpbuf, strlen(tmpbuf),
180                                        nexus_file_written, 0);
181 }
182
183 void nexus_file_written(char*  basedir,
184                         char*  filepath,
185                         char*  data,
186                         int    usedmmap,
187                         k_stat kstat,
188                         void*  context)
189 {
190         if(!data) k_fatal("Failed to write nexus.txt");
191         else      k_log_out("New nexus.txt written:\n%s", data);
192 }
193
194 int root_nexus(void)
195 {
196         char* hostname=ni_hostname();
197         if(!hostname || strchr(hostname, '-')) return 0;
198         return 1;
199 }
200
201 void listen_http(void)
202 {
203         char* chanm="|nip-server|-|8081|-|";
204         k_channel_connect_name(chanm, connection_readable,
205                                       connection_writable);
206 }
207
208 void listen_nexus(void)
209 {
210         char* chanm="|nip-server|-|7747|-|";
211         k_channel_connect_name(chanm, connection_readable,
212                                       connection_writable);
213 }
214
215 void connect_to_nexus(void)
216 {
217         if(nexus_channel){
218                 k_channel_connect_name(nexus_channel, connection_readable,
219                                                       connection_writable);
220         }
221         else k_log_out("discovery of nexus not implemented yet!");
222 }
223
224 void ping_this(void* arg, char* key, void* val)
225 {
226         k_hashtable* channelspinged=arg;
227         char*        chanm=val;
228
229         if(strncmp(chanm, "nip-client", 11)     ) return;
230         if(k_hashtable_get(channelspinged, chanm)) return;
231         k_hashtable_set(channelspinged, chanm, chanm);
232
233         k_channel* chan=k_channel_get_name(chanm);
234         //k_log_out("ping_this: host %s channel %s got=%p", key, chanm, chan);
235
236         if(!chan) k_channel_connect_name(chanm, connection_readable,
237                                                 connection_writable);
238
239         int pingtodeath=0;
240         if(chan && pingtodeath) send_ping(chan, "PING OP/0.5", 0);
241 }
242
243 char* generate_new_hostname(k_hashtable* ent_head, k_channel* chan)
244 {
245         if(!ni_hostname()) return 0;
246         unsigned long a=chan->clientip.s_addr;
247         #define IPQUAD(a) \
248                 ((unsigned char *)&a)[0], \
249                 ((unsigned char *)&a)[1], \
250                 ((unsigned char *)&a)[2], \
251                 ((unsigned char *)&a)[3]
252         snprintf(tmpbuf, TMPBUFSIZE, "%s-%02x%02x%02x%02x.%d",
253                                ni_hostname(), IPQUAD(a), 7747);
254         if(0) k_log_out("generated new hostname: %s\n", tmpbuf);
255         return k_strdup(tmpbuf);
256 }
257
258 /* -}{----------------------------------------------------------------------- */
259
260 void set_channel_for(char* host, char* chanm)
261 {
262         k_hashtable_put_dup(chans_for_host, host, chanm);
263 }
264
265 void show_np(void)
266 {
267         k_log_out("-------- channel for host ---------------");
268         k_hashtable_apply(chans_for_host,  show_list, 0);
269         k_channel_show_all();
270 }
271
272 void show_list(void* arg, char* key, void* val)
273 {
274         char* chanm=val;
275         k_log_out("%s %s", key, chanm);
276 }
277
278 void generate_random(void)
279 {
280         time_t t=time(0);
281         short r;
282         k_random_bytes((char*)&r, sizeof(r));
283         unsigned char r1=(t >>24) & 255;
284         unsigned char r2=(t >>16) & 255;
285         unsigned char r3=(t >> 8) & 255;
286         unsigned char r4=(t     ) & 255;
287         unsigned char r5=(r >> 8) & 255;
288         unsigned char r6=(r     ) & 255;
289         snprintf(tmpbuf, TMPBUFSIZE, "%02x-%02x-%02x-%02x-%02x-%02x",
290                                       r1, r2, r3, r4, r5, r6);
291 }
292
293 /* -}{----------------------------------------------------------------------- */
294