LCOV - code coverage report
Current view: top level - src/server/monitor - status_server.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 58 197 29.4 %
Date: 2017-12-01 Functions: 4 9 44.4 %

          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(&copy);
     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             : }

Generated by: LCOV version 1.10