Line data Source code
1 : #include "../../burp.h"
2 : #include "../../alloc.h"
3 : #include "../../asfd.h"
4 : #include "../../async.h"
5 : #include "../../bu.h"
6 : #include "../../cstat.h"
7 : #include "../../handy.h"
8 : #include "../../iobuf.h"
9 : #include "../../log.h"
10 : #include "cstat.h"
11 : #include "json_output.h"
12 : #include "status_server.h"
13 :
14 6 : static int parse_cntr_data(const char *buf, struct cstat *clist)
15 : {
16 6 : int bno=0;
17 6 : int ret=-1;
18 6 : char *cname=NULL;
19 6 : struct cstat *c=NULL;
20 6 : char *path=NULL;
21 6 : char *dp=NULL;
22 6 : pid_t pid=-1;
23 :
24 : // Skip the type.
25 6 : if(!(dp=strchr(buf, '\t')))
26 : return 0;
27 5 : dp++;
28 :
29 5 : if(extract_client_pid_bno(dp, &cname, &pid, &bno))
30 : return -1;
31 5 : if(!cname)
32 : return 0;
33 :
34 : // Find the array entry for this client,
35 : // and add the detail from the parent to it.
36 3 : for(c=clist; c; c=c->next)
37 : {
38 3 : struct cntr *cntr=NULL;
39 3 : if(strcmp(c->name, cname))
40 2 : continue;
41 1 : cstat_set_run_status(c, RUN_STATUS_RUNNING);
42 :
43 : // Find the cntr entry for this client/pid.
44 1 : for(cntr=c->cntrs; cntr; cntr=cntr->next)
45 0 : if(cntr->pid==pid)
46 : break;
47 1 : if(!cntr)
48 : {
49 : // Need to allocate a new cntr.
50 1 : if(!(cntr=cntr_alloc())
51 1 : || cntr_init(cntr, cname, pid))
52 : goto end;
53 1 : cstat_add_cntr_to_list(c, cntr);
54 : }
55 1 : if(str_to_cntr(buf, cntr, &path))
56 : goto end;
57 : }
58 :
59 : // FIX THIS: Do something with path.
60 :
61 : ret=0;
62 : end:
63 5 : free_w(&cname);
64 5 : free_w(&path);
65 5 : return ret;
66 : }
67 :
68 4 : static void clean_up_cntrs(struct cstat *clist)
69 : {
70 : struct cstat *c;
71 16 : for(c=clist; c; c=c->next)
72 : {
73 12 : struct cntr *cntr=NULL;
74 24 : for(cntr=c->cntrs; cntr; )
75 : {
76 0 : if(cntr->found)
77 : {
78 0 : cntr=cntr->next;
79 0 : continue;
80 : }
81 0 : cstat_remove_cntr_from_list(c, cntr);
82 0 : cntr_free(&cntr);
83 0 : if(c->cntrs)
84 0 : cntr=c->cntrs;
85 : }
86 : }
87 4 : }
88 :
89 9 : static int parse_clients_list(char *buf, struct cstat *clist)
90 : {
91 9 : char *tok=NULL;
92 : struct cstat *c;
93 :
94 9 : if(!clist)
95 : return 0;
96 :
97 : // Do not need the first token.
98 4 : if(!(tok=strtok(buf, "\t\n")))
99 : return 0;
100 12 : for(c=clist; c; c=c->next)
101 : {
102 : struct cntr *cntr;
103 12 : for(cntr=c->cntrs; cntr; cntr=cntr->next)
104 0 : cntr->found=0;
105 12 : cstat_set_run_status(c, RUN_STATUS_IDLE);
106 : }
107 :
108 7 : while((tok=strtok(NULL, "\t\n")))
109 : {
110 3 : int bno=0;
111 3 : pid_t pid=-1;
112 3 : char *cname=NULL;
113 3 : if(extract_client_pid_bno(tok, &cname, &pid, &bno))
114 0 : return -1;
115 11 : for(c=clist; c; c=c->next)
116 : {
117 : struct cntr *cntr;
118 7 : if(strcmp(c->name, cname))
119 4 : continue;
120 3 : cstat_set_run_status(c, RUN_STATUS_RUNNING);
121 3 : for(cntr=c->cntrs; cntr; cntr=cntr->next)
122 0 : if(cntr->pid==pid)
123 : break;
124 3 : if(cntr)
125 : {
126 0 : cntr->found=1;
127 0 : cntr->bno=bno;
128 : }
129 : break;
130 : }
131 3 : free_w(&cname);
132 : }
133 :
134 4 : clean_up_cntrs(clist);
135 :
136 4 : return 0;
137 : }
138 :
139 : #ifndef UTEST
140 : static
141 : #endif
142 18 : int parse_parent_data(char *buf, struct cstat *clist)
143 : {
144 18 : if(!buf || !*buf)
145 : return 0;
146 :
147 17 : if(!strncmp(buf, "cntr", strlen("cntr")))
148 : {
149 6 : if(parse_cntr_data(buf, clist))
150 : return -1;
151 : }
152 11 : else if(!strncmp(buf, "clients", strlen("clients")))
153 : {
154 9 : if(parse_clients_list(buf, clist))
155 : return -1;
156 : }
157 :
158 : return 0;
159 : }
160 :
161 0 : static char *get_str(const char **buf, const char *pre, int last)
162 : {
163 0 : size_t len=0;
164 0 : char *cp=NULL;
165 0 : char *copy=NULL;
166 0 : char *ret=NULL;
167 0 : if(!buf || !*buf) goto end;
168 0 : len=strlen(pre);
169 0 : if(strncmp(*buf, pre, len)
170 0 : || !(copy=strdup_w((*buf)+len, __func__)))
171 : goto end;
172 0 : if(!last && (cp=strchr(copy, ':'))) *cp='\0';
173 0 : *buf+=len+strlen(copy)+1;
174 0 : ret=strdup_w(copy, __func__);
175 : end:
176 0 : free_w(©);
177 0 : return ret;
178 : }
179 :
180 : /*
181 : void dump_cbno(struct cstat *clist, const char *msg)
182 : {
183 : if(!clist) return;
184 : printf("dump %s: %s\n", msg, clist->name);
185 : struct bu *b;
186 : for(b=clist->bu; b; b=b->prev)
187 : printf(" %d\n", b->bno);
188 : }
189 : */
190 :
191 0 : static int parse_client_data(struct asfd *srfd,
192 : struct cstat *clist, struct conf **confs, long *peer_version)
193 : {
194 0 : int ret=0;
195 0 : char *command=NULL;
196 0 : char *client=NULL;
197 0 : char *backup=NULL;
198 0 : char *logfile=NULL;
199 0 : char *browse=NULL;
200 0 : const char *cp=NULL;
201 0 : struct cstat *cstat=NULL;
202 0 : struct bu *bu=NULL;
203 : //logp("got client data: '%s'\n", srfd->rbuf->buf);
204 :
205 0 : cp=srfd->rbuf->buf;
206 :
207 0 : command=get_str(&cp, "j:", 0);
208 0 : client=get_str(&cp, "c:", 0);
209 0 : backup=get_str(&cp, "b:", 0);
210 0 : logfile=get_str(&cp, "l:", 0);
211 0 : browse=get_str(&cp, "p:", 1);
212 :
213 0 : if(command)
214 : {
215 : size_t l;
216 0 : char peer_version_str[32]="peer_version=";
217 0 : l=strlen(peer_version_str);
218 0 : if(!strcmp(command, "pretty-print-on"))
219 : {
220 0 : json_set_pretty_print(1);
221 0 : if(json_send_warn(srfd, "Pretty print on"))
222 : goto error;
223 : }
224 0 : else if(!strcmp(command, "pretty-print-off"))
225 : {
226 0 : json_set_pretty_print(0);
227 0 : if(json_send_warn(srfd, "Pretty print off"))
228 : goto error;
229 : }
230 0 : else if(!strncmp(command, peer_version_str, l))
231 : {
232 0 : if(!(*peer_version=version_to_long(command+l)))
233 : goto error;
234 : }
235 : else
236 : {
237 0 : if(json_send_warn(srfd, "Unknown command"))
238 : goto error;
239 : }
240 0 : goto end;
241 : }
242 :
243 0 : if(browse)
244 : {
245 0 : free_w(&logfile);
246 0 : if(!(logfile=strdup_w("manifest", __func__)))
247 : goto error;
248 0 : strip_trailing_slashes(&browse);
249 : }
250 :
251 : //dump_cbno(clist, "pcd");
252 :
253 0 : if(client && *client)
254 : {
255 0 : if(!(cstat=cstat_get_by_name(clist, client)))
256 : {
257 0 : char msg[256]="";
258 0 : snprintf(msg, sizeof(msg),
259 : "Could not find client: %s", client);
260 0 : if(json_send_warn(srfd, msg))
261 : goto error;
262 0 : goto end;
263 : }
264 :
265 0 : if(cstat_set_backup_list(cstat))
266 : {
267 0 : if(json_send_warn(srfd, "Could not get backup list"))
268 : goto error;
269 : goto end;
270 :
271 : }
272 : }
273 0 : if(cstat && backup)
274 : {
275 0 : unsigned long bno=0;
276 0 : if(!(bno=strtoul(backup, NULL, 10)))
277 : {
278 0 : if(json_send_warn(srfd, "Could not get backup number"))
279 : goto error;
280 : goto end;
281 : }
282 0 : for(bu=cstat->bu; bu; bu=bu->prev)
283 0 : if(bu->bno==bno) break;
284 :
285 0 : if(!bu)
286 : {
287 0 : if(json_send_warn(srfd, "Backup not found"))
288 : goto error;
289 : goto end;
290 : }
291 : }
292 0 : if(logfile)
293 : {
294 0 : if(strcmp(logfile, "manifest")
295 0 : && strcmp(logfile, "backup")
296 0 : && strcmp(logfile, "restore")
297 0 : && strcmp(logfile, "verify")
298 0 : && strcmp(logfile, "backup_stats")
299 0 : && strcmp(logfile, "restore_stats")
300 0 : && strcmp(logfile, "verify_stats"))
301 : {
302 0 : if(json_send_warn(srfd, "File not supported"))
303 : goto error;
304 : goto end;
305 : }
306 : }
307 : /*
308 : printf("client: %s\n", client?:"");
309 : printf("backup: %s\n", backup?:"");
310 : printf("logfile: %s\n", logfile?:"");
311 : */
312 0 : if(json_send(srfd, clist, cstat, bu, logfile, browse,
313 : get_int(confs[OPT_MONITOR_BROWSE_CACHE]), *peer_version))
314 : goto error;
315 :
316 : goto end;
317 : error:
318 : ret=-1;
319 : end:
320 0 : free_w(&client);
321 0 : free_w(&backup);
322 0 : free_w(&logfile);
323 0 : free_w(&browse);
324 0 : return ret;
325 : }
326 :
327 0 : static int parse_data(struct asfd *asfd, struct cstat *clist,
328 : struct asfd *cfd, struct conf **confs, long *peer_version)
329 : {
330 0 : if(asfd==cfd)
331 0 : return parse_client_data(asfd, clist, confs, peer_version);
332 0 : return parse_parent_data(asfd->rbuf->buf, clist);
333 : }
334 :
335 : static int have_data_for_running_clients(struct cstat *clist)
336 : {
337 : struct cstat *c;
338 0 : for(c=clist; c; c=c->next)
339 : {
340 0 : if(c->run_status==RUN_STATUS_RUNNING)
341 : {
342 0 : if(!c->cntrs
343 0 : || c->cntrs->cntr_status==CNTR_STATUS_UNSET)
344 : return 0;
345 : }
346 : }
347 : return 1;
348 : }
349 :
350 : static int have_run_statuses(struct cstat *clist)
351 : {
352 : struct cstat *c;
353 0 : for(c=clist; c; c=c->next)
354 0 : if(c->permitted && c->run_status==RUN_STATUS_UNSET)
355 : return 0;
356 : return 1;
357 : }
358 :
359 0 : static int get_initial_data(struct async *as,
360 : struct cstat **clist,
361 : struct conf **confs, struct conf **cconfs, long *peer_version)
362 : {
363 0 : int x=10;
364 0 : struct asfd *asfd=NULL;
365 :
366 0 : if(cstat_load_data_from_disk(clist, confs, cconfs))
367 : return -1;
368 :
369 : // Try to get the initial data.
370 0 : while(x)
371 : {
372 : // Do not wait forever for running clients.
373 0 : if(!have_data_for_running_clients(*clist))
374 0 : x--;
375 0 : else if(have_run_statuses(*clist))
376 : return 0;
377 :
378 0 : if(as->read_write(as))
379 : {
380 0 : logp("Exiting main status server loop\n");
381 0 : return -1;
382 : }
383 0 : asfd=as->asfd->next;
384 0 : if(asfd->rbuf->buf)
385 : {
386 0 : if(parse_data(asfd, *clist, NULL, confs, peer_version))
387 : {
388 0 : iobuf_free_content(asfd->rbuf);
389 0 : return -1;
390 : }
391 0 : iobuf_free_content(asfd->rbuf);
392 : }
393 : }
394 : return 0;
395 : }
396 :
397 0 : int status_server(struct async *as, struct conf **confs)
398 : {
399 0 : int ret=-1;
400 0 : int gotdata=0;
401 : struct asfd *asfd;
402 0 : struct cstat *clist=NULL;
403 0 : struct asfd *cfd=as->asfd; // Client.
404 0 : struct conf **cconfs=NULL;
405 0 : long peer_version=version_to_long(get_string(confs[OPT_PEER_VERSION]));
406 :
407 0 : if(!(cconfs=confs_alloc()))
408 : goto end;
409 :
410 0 : if(get_initial_data(as, &clist, confs, cconfs, &peer_version))
411 : goto end;
412 :
413 : while(1)
414 : {
415 : // Take the opportunity to get data from the disk if nothing
416 : // was read from the fds.
417 0 : if(gotdata) gotdata=0;
418 0 : else if(cstat_load_data_from_disk(&clist, confs, cconfs))
419 : goto end;
420 0 : if(as->read_write(as))
421 : {
422 0 : logp("Exiting main status server loop\n");
423 : break;
424 : }
425 0 : for(asfd=as->asfd; asfd; asfd=asfd->next)
426 0 : while(asfd->rbuf->buf)
427 : {
428 0 : gotdata=1;
429 0 : if(parse_data(asfd, clist, cfd, confs, &peer_version)
430 0 : || asfd->parse_readbuf(asfd))
431 : goto end;
432 0 : iobuf_free_content(asfd->rbuf);
433 : }
434 : }
435 0 : ret=0;
436 : end:
437 : // FIX THIS: should free clist;
438 0 : return ret;
439 : }
|