LCOV - code coverage report
Current view: top level - src/client/monitor - json_input.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 187 229 81.7 %
Date: 2016-03-31 Functions: 13 13 100.0 %

          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 "json_input.h"
      11             : #include "lline.h"
      12             : #include "sel.h"
      13             : #ifdef HAVE_WIN32
      14             : #include <yajl/yajl_parse.h>
      15             : #else
      16             : #include "../../yajl/api/yajl_parse.h"
      17             : #endif
      18             : 
      19             : static int map_depth=0;
      20             : 
      21             : static unsigned long number=0;
      22             : static char *timestamp=NULL;
      23             : static uint16_t flags=0;
      24             : static struct cstat *cnew=NULL;
      25             : static struct cstat *current=NULL;
      26             : static struct cstat **cslist=NULL;
      27             : static struct cntr_ent *cntr_ent=NULL;
      28             : static char lastkey[32]="";
      29             : static int in_backups=0;
      30             : static int in_flags=0;
      31             : static int in_counters=0;
      32             : static int in_logslist=0;
      33             : static int in_log_content=0;
      34             : static struct bu **sselbu=NULL;
      35             : static struct lline *ll_list=NULL;
      36             : static struct lline **sllines=NULL;
      37             : 
      38             : static int is_wrap(const char *val, const char *key, uint16_t bit)
      39             : {
      40         815 :         if(!strcmp(val, key))
      41             :         {
      42         180 :                 flags|=bit;
      43             :                 return 1;
      44             :         }
      45             :         return 0;
      46             : }
      47             : 
      48         370 : static int input_integer(void *ctx, long long val)
      49             : {
      50         370 :         if(in_counters)
      51             :         {
      52          60 :                 if(!strcmp(lastkey, "count"))
      53             :                 {
      54          60 :                         if(!cntr_ent) goto error;
      55          60 :                         cntr_ent->count=(uint64_t)val;
      56             :                 }
      57           0 :                 else if(!strcmp(lastkey, "changed"))
      58             :                 {
      59           0 :                         if(!cntr_ent) goto error;
      60           0 :                         cntr_ent->changed=(uint64_t)val;
      61             :                 }
      62           0 :                 else if(!strcmp(lastkey, "same"))
      63             :                 {
      64           0 :                         if(!cntr_ent) goto error;
      65           0 :                         cntr_ent->same=(uint64_t)val;
      66             :                 }
      67           0 :                 else if(!strcmp(lastkey, "deleted"))
      68             :                 {
      69           0 :                         if(!cntr_ent) goto error;
      70           0 :                         cntr_ent->deleted=(uint64_t)val;
      71             :                 }
      72           0 :                 else if(!strcmp(lastkey, "scanned"))
      73             :                 {
      74           0 :                         if(!cntr_ent) goto error;
      75           0 :                         cntr_ent->phase1=(uint64_t)val;
      76             :                 }
      77             :                 else
      78             :                 {
      79             :                         goto error;
      80             :                 }
      81             :                 return 1;
      82             :         }
      83         310 :         else if(in_backups && !in_flags && !in_counters && !in_logslist)
      84             :         {
      85         230 :                 if(!current) goto error;
      86         230 :                 if(!strcmp(lastkey, "number"))
      87             :                 {
      88         115 :                         number=(unsigned long)val;
      89         115 :                         return 1;
      90             :                 }
      91         115 :                 else if(!strcmp(lastkey, "timestamp"))
      92             :                 {
      93             :                         time_t t;
      94         115 :                         t=(unsigned long)val;
      95         115 :                         free_w(&timestamp);
      96         115 :                         if(!(timestamp=strdup_w(getdatestr(t), __func__)))
      97             :                                 return 0;
      98         115 :                         return 1;
      99             :                 }
     100             :         }
     101             :         else
     102             :         {
     103          80 :                 if(!strcmp(lastkey, "protocol"))
     104             :                 {
     105             :                         return 1;
     106             :                 }
     107             :         }
     108             : error:
     109           0 :         logp("Unexpected integer: %s %llu\n", lastkey, val);
     110           0 :         return 0;
     111             : }
     112             : 
     113         495 : static int input_string(void *ctx, const unsigned char *val, size_t len)
     114             : {
     115             :         char *str;
     116         495 :         if(!(str=(char *)malloc_w(len+2, __func__)))
     117             :                 return 0;
     118         495 :         snprintf(str, len+1, "%s", val);
     119             : 
     120         495 :         if(in_counters)
     121             :         {
     122         120 :                 if(!strcmp(lastkey, "name"))
     123             :                 {
     124             :                         // Ignore 'name' in a counters object. We use 'type'
     125             :                         // instead.
     126             :                 }
     127          60 :                 else if(!strcmp(lastkey, "type"))
     128             :                 {
     129          60 :                         if(!current) goto error;
     130          60 :                         cntr_ent=current->cntr->ent[(uint8_t)*str];
     131             :                 }
     132             :                 else
     133             :                 {
     134             :                         goto error;
     135             :                 }
     136             :                 goto end;
     137             :         }
     138         375 :         else if(!strcmp(lastkey, "name"))
     139             :         {
     140          80 :                 if(cnew) goto error;
     141          80 :                 if(!(current=cstat_get_by_name(*cslist, str)))
     142             :                 {
     143          64 :                         if(!(cnew=cstat_alloc())
     144          32 :                           || cstat_init_with_cntr(cnew, str, NULL))
     145             :                                 goto error;
     146          32 :                         current=cnew;
     147             :                 }
     148             :                 goto end;
     149             :         }
     150         295 :         else if(!strcmp(lastkey, "labels"))
     151             :         {
     152          30 :                 if(!current) goto error;
     153             :                 goto end;
     154             :         }
     155         265 :         else if(!strcmp(lastkey, "run_status"))
     156             :         {
     157          80 :                 if(!current) goto error;
     158          80 :                 current->run_status=run_str_to_status(str);
     159          80 :                 goto end;
     160             :         }
     161         185 :         else if(!strcmp(lastkey, "phase"))
     162             :         {
     163           0 :                 if(!current) goto error;
     164           0 :                 current->cntr->cntr_status=cntr_str_to_status(str);
     165           0 :                 goto end;
     166             :         }
     167         185 :         else if(!strcmp(lastkey, "flags"))
     168             :         {
     169         180 :                 if(!current) goto error;
     170         360 :                 if(is_wrap(str, "hardlinked", BU_HARDLINKED)
     171         350 :                   || is_wrap(str, "deletable", BU_DELETABLE)
     172         300 :                   || is_wrap(str, "working", BU_WORKING)
     173         270 :                   || is_wrap(str, "finishing", BU_FINISHING)
     174         240 :                   || is_wrap(str, "current", BU_CURRENT)
     175         290 :                   || is_wrap(str, "manifest", BU_MANIFEST))
     176             :                         goto end;
     177             :         }
     178           5 :         else if(!strcmp(lastkey, "counters")) // Do we need this?
     179             :         {
     180             :                 goto end;
     181             :         }
     182           5 :         else if(!strcmp(lastkey, "list"))
     183             :         {
     184           0 :                 if(is_wrap(str, "backup", BU_LOG_BACKUP)
     185           0 :                   || is_wrap(str, "restore", BU_LOG_RESTORE)
     186           0 :                   || is_wrap(str, "verify", BU_LOG_VERIFY)
     187           0 :                   || is_wrap(str, "backup_stats", BU_STATS_BACKUP)
     188           0 :                   || is_wrap(str, "restore_stats", BU_STATS_RESTORE)
     189           0 :                   || is_wrap(str, "verify_stats", BU_STATS_VERIFY))
     190             :                         goto end;
     191             :         }
     192           5 :         else if(!strcmp(lastkey, "logs"))
     193             :         {
     194             :                 goto end;
     195             :         }
     196           5 :         else if(!strcmp(lastkey, "logline"))
     197             :         {
     198             :                 goto end;
     199             :         }
     200           5 :         else if(!strcmp(lastkey, "backup")
     201           5 :           || !strcmp(lastkey, "restore")
     202           5 :           || !strcmp(lastkey, "verify")
     203           5 :           || !strcmp(lastkey, "backup_stats")
     204           5 :           || !strcmp(lastkey, "restore_stats")
     205           5 :           || !strcmp(lastkey, "verify_stats"))
     206             :         {
     207             :                 // Log file contents.
     208           0 :                 if(lline_add(&ll_list, str))
     209             :                         goto error;
     210             :                 goto end;
     211             :         }
     212           5 :         else if(!strcmp(lastkey, "warning")) 
     213             :         {
     214             :                 goto end;
     215             :         }
     216             : error:
     217           0 :         logp("Unexpected string: %s %s\n", lastkey, str);
     218           0 :         free_w(&str);
     219           0 :         return 0;
     220             : end:
     221         495 :         free_w(&str);
     222         495 :         return 1;
     223             : }
     224             : 
     225         930 : static int input_map_key(void *ctx, const unsigned char *val, size_t len)
     226             : {
     227         930 :         snprintf(lastkey, len+1, "%s", val);
     228             : //      logp("mapkey: %s\n", lastkey);
     229         930 :         return 1;
     230             : }
     231             : 
     232             : static struct bu *bu_list=NULL;
     233             : 
     234         195 : static int add_to_bu_list(void)
     235             : {
     236             :         struct bu *bu;
     237             :         struct bu *last;
     238         195 :         if(!number) return 0;
     239         115 :         if(!(bu=bu_alloc())) return -1;
     240         115 :         bu->bno=number;
     241         115 :         bu->flags=flags;
     242         115 :         bu->timestamp=timestamp;
     243             : 
     244             :         // FIX THIS: Inefficient to find the end each time.
     245         115 :         for(last=bu_list; last && last->next; last=last->next) { }
     246         115 :         if(last)
     247             :         {
     248          50 :                 last->next=bu;
     249          50 :                 bu->prev=last;
     250             :         }
     251             :         else
     252             :         {
     253          65 :                 bu_list=bu;
     254          65 :                 bu_list->prev=NULL;
     255             :         }
     256             :         
     257         115 :         number=0;
     258         115 :         flags=0;
     259         115 :         timestamp=NULL;
     260         115 :         return 0;
     261             : }
     262             : 
     263         298 : static int input_start_map(void *ctx)
     264             : {
     265         298 :         map_depth++;
     266             :         //logp("startmap: %d\n", map_depth);
     267         298 :         return 1;
     268             : }
     269             : 
     270         297 : static int input_end_map(void *ctx)
     271             : {
     272         297 :         map_depth--;
     273             :         //logp("endmap: %d\n", map_depth);
     274         297 :         if(in_backups && !in_flags && !in_counters && !in_logslist)
     275             :         {
     276         115 :                 if(add_to_bu_list()) return 0;
     277             :         }
     278             :         return 1;
     279             : }
     280             : 
     281         275 : static int input_start_array(void *ctx)
     282             : {
     283             :         //logp("start arr\n");
     284         275 :         if(!strcmp(lastkey, "backups"))
     285             :         {
     286          80 :                 in_backups=1;
     287             :         }
     288         195 :         else if(!strcmp(lastkey, "flags"))
     289             :         {
     290         115 :                 in_flags=1;
     291             :         }
     292          80 :         else if(!strcmp(lastkey, "counters"))
     293             :         {
     294          30 :                 in_counters=1;
     295             :         }
     296          50 :         else if(!strcmp(lastkey, "list"))
     297             :         {
     298           0 :                 in_logslist=1;
     299             :         }
     300          50 :         else if(!strcmp(lastkey, "backup")
     301          50 :           || !strcmp(lastkey, "restore")
     302          50 :           || !strcmp(lastkey, "verify")
     303          50 :           || !strcmp(lastkey, "backup_stats")
     304          50 :           || !strcmp(lastkey, "restore_stats")
     305          50 :           || !strcmp(lastkey, "verify_stats"))
     306             :         {
     307           0 :                 in_log_content=1;
     308             :         }
     309         275 :         return 1;
     310             : }
     311             : 
     312          80 : static void merge_bu_lists(void)
     313             : {
     314             :         struct bu *n;
     315             :         struct bu *o;
     316          80 :         struct bu *lastn=NULL;
     317          80 :         struct bu *lasto=NULL;
     318             : 
     319         229 :         for(o=current->bu; o; )
     320             :         {
     321          69 :                 int found_in_new=0;
     322          69 :                 lastn=NULL;
     323          87 :                 for(n=bu_list; n; n=n->next)
     324             :                 {
     325          87 :                         if(o->bno==n->bno)
     326             :                         {
     327             :                                 // Found o in new list.
     328             :                                 // Copy the fields from new to old.
     329          69 :                                 found_in_new=1;
     330          69 :                                 o->flags=n->flags;
     331          69 :                                 free_w(&o->timestamp);
     332          69 :                                 o->timestamp=n->timestamp;
     333          69 :                                 n->timestamp=NULL;
     334             : 
     335             :                                 // Remove it from new list.
     336          69 :                                 if(lastn)
     337             :                                 {
     338          18 :                                         lastn->next=n->next;
     339          18 :                                         if(n->next) n->next->prev=lastn;
     340             :                                 }
     341             :                                 else
     342             :                                 {
     343          51 :                                         bu_list=n->next;
     344          51 :                                         if(bu_list) bu_list->prev=NULL;
     345             :                                 }
     346          69 :                                 bu_free(&n);
     347          69 :                                 n=lastn;
     348          69 :                                 break;
     349             :                         }
     350          18 :                         lastn=n;
     351             :                 }
     352          69 :                 if(!found_in_new)
     353             :                 {
     354             :                         // Could not find o in new list.
     355             :                         // Remove it from old list.
     356           0 :                         if(lasto)
     357             :                         {
     358           0 :                                 lasto->next=o->next;
     359           0 :                                 if(o->next) o->next->prev=lasto;
     360             :                         }
     361             :                         else
     362             :                         {
     363           0 :                                 current->bu=o->next;
     364           0 :                                 if(current->bu) current->bu->prev=NULL;
     365             :                         }
     366             :                         // Need to reset if the one that was removed was
     367             :                         // selected in ncurses.
     368           0 :                         if(o==*sselbu) *sselbu=NULL;
     369           0 :                         bu_free(&o);
     370           0 :                         o=lasto;
     371             :                 }
     372          69 :                 lasto=o;
     373          69 :                 if(o) o=o->next;
     374             :         }
     375             : 
     376             :         // Now, new list only has entries missing from old list.
     377          80 :         n=bu_list;
     378          80 :         lastn=NULL;
     379         206 :         while(n)
     380             :         {
     381          46 :                 o=current->bu;
     382          46 :                 lasto=NULL;
     383         112 :                 while(o && n->bno < o->bno)
     384             :                 {
     385          20 :                         lasto=o;
     386          20 :                         o=o->next;
     387             :                 }
     388             :                 // Found the place to insert it.
     389          46 :                 if(lasto)
     390             :                 {
     391           8 :                         lasto->next=n;
     392           8 :                         n->prev=lasto;
     393             :                 }
     394             :                 else
     395             :                 {
     396          38 :                         if(current->bu) current->bu->prev=n;
     397          38 :                         current->bu=n;
     398          38 :                         current->bu->prev=NULL;
     399             :                 }
     400          46 :                 lastn=n->next;
     401          46 :                 n->next=o;
     402          46 :                 n=lastn;
     403             :         }
     404          80 : }
     405             : 
     406         275 : static int input_end_array(void *ctx)
     407             : {
     408         275 :         if(in_backups && !in_flags && !in_counters && !in_logslist)
     409             :         {
     410          80 :                 in_backups=0;
     411          80 :                 if(add_to_bu_list()) return 0;
     412             :                 // Now may have two lists. Want to keep the old one is intact
     413             :                 // as possible, so that we can keep a pointer to its entries
     414             :                 // in the ncurses stuff.
     415             :                 // Merge the new list into the old.
     416          80 :                 merge_bu_lists();
     417          80 :                 bu_list=NULL;
     418          80 :                 if(cnew)
     419             :                 {
     420          32 :                         cstat_add_to_list(cslist, cnew);
     421          32 :                         cnew=NULL;
     422             :                 }
     423          80 :                 current=NULL;
     424             :         }
     425         195 :         else if(in_flags)
     426             :         {
     427         115 :                 in_flags=0;
     428             :         }
     429          80 :         else if(in_counters)
     430             :         {
     431          30 :                 in_counters=0;
     432             :         }
     433          50 :         else if(in_logslist)
     434             :         {
     435           0 :                 in_logslist=0;
     436             :         }
     437          50 :         else if(in_log_content)
     438             :         {
     439           0 :                 in_log_content=0;
     440           0 :                 llines_free(sllines);
     441           0 :                 *sllines=ll_list;
     442           0 :                 ll_list=NULL;
     443             :         }
     444             :         return 1;
     445             : }
     446             : 
     447             : static yajl_callbacks callbacks = {
     448             :         NULL,
     449             :         NULL,
     450             :         input_integer,
     451             :         NULL,
     452             :         NULL,
     453             :         input_string,
     454             :         input_start_map,
     455             :         input_map_key,
     456             :         input_end_map,
     457             :         input_start_array,
     458             :         input_end_array
     459             : };
     460             : 
     461           2 : static void do_yajl_error(yajl_handle yajl, struct asfd *asfd)
     462             : {
     463             :         unsigned char *str;
     464             :         str=yajl_get_error(yajl, 1,
     465           2 :                 (const unsigned char *)asfd->rbuf->buf, asfd->rbuf->len);
     466           2 :         logp("yajl error: %s\n", str?(const char *)str:"unknown");
     467           2 :         if(str) yajl_free_error(yajl, str);
     468           2 : }
     469             : 
     470             : static yajl_handle yajl=NULL;
     471             : 
     472          45 : int json_input_init(void)
     473             : {
     474          45 :         if(!(yajl=yajl_alloc(&callbacks, NULL, NULL)))
     475             :                 return -1;
     476          45 :         yajl_config(yajl, yajl_dont_validate_strings, 1);
     477          45 :         return 0;
     478             : }
     479             : 
     480          22 : void json_input_free(void)
     481             : {
     482          88 :         if(!yajl) return;
     483          45 :         yajl_free(yajl);
     484          45 :         yajl=NULL;
     485             : }
     486             : 
     487             : // Client records will be coming through in alphabetical order.
     488             : // FIX THIS: If a client is deleted on the server, it is not deleted from
     489             : // clist.
     490        5283 : int json_input(struct asfd *asfd, struct sel *sel)
     491             : {
     492        5281 :         cslist=&sel->clist;
     493        5281 :         sselbu=&sel->backup;
     494        5281 :         sllines=&sel->llines;
     495             : 
     496        5281 :         if(!yajl && json_input_init()) goto error;
     497             : 
     498        5281 :         if(yajl_parse(yajl, (const unsigned char *)asfd->rbuf->buf,
     499        5281 :                 asfd->rbuf->len)!=yajl_status_ok)
     500             :         {
     501           2 :                 do_yajl_error(yajl, asfd);
     502           1 :                 goto error;
     503             :         }
     504             : 
     505        5280 :         if(!map_depth)
     506             :         {
     507             :                 // Got to the end of the JSON object.
     508          43 :                 if(!sel->gotfirstresponse) sel->gotfirstresponse=1;
     509          43 :                 if(yajl_complete_parse(yajl)!=yajl_status_ok)
     510             :                 {
     511           2 :                         do_yajl_error(yajl, asfd);
     512           1 :                         goto error;
     513             :                 }
     514             :                 json_input_free();
     515             :                 return 1;
     516             :         }
     517             : 
     518             :         return 0;
     519             : error:
     520             :         json_input_free();
     521             :         return -1;
     522             : }

Generated by: LCOV version 1.10