LCOV - code coverage report
Current view: top level - src/protocol2/rabin - rabin.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 70 89 78.7 %
Date: 2020-08-31 23:02:24 Functions: 7 7 100.0 %

          Line data    Source code
       1             : #include "../../burp.h"
       2             : #include "rabin.h"
       3             : #include "rconf.h"
       4             : #include "win.h"
       5             : #include "../../alloc.h"
       6             : #include "../blk.h"
       7             : #include "../blist.h"
       8             : #include "../../sbuf.h"
       9             : #include "../../client/protocol2/rabin_read.h"
      10             : 
      11             : static struct blk *blk=NULL;
      12             : static char *gcp=NULL;
      13             : static char *gbuf=NULL;
      14             : static char *gbuf_end=NULL;
      15             : static struct rconf rconf;
      16             : static struct win *win=NULL; // Rabin sliding window.
      17             : static int first=0;
      18             : 
      19          34 : int blks_generate_init(void)
      20             : {
      21          34 :         rconf_init(&rconf);
      22          34 :         if(!(win=win_alloc(&rconf))
      23          34 :           || !(gbuf=(char *)malloc_w(rconf.blk_max, __func__)))
      24             :                 return -1;
      25          34 :         gbuf_end=gbuf;
      26          34 :         gcp=gbuf;
      27          34 :         return 0;
      28             : }
      29             : 
      30          41 : void blks_generate_free(void)
      31             : {
      32          41 :         free_w(&gbuf);
      33          41 :         blk_free(&blk);
      34          41 :         win_free(&win);
      35          41 : }
      36             : 
      37             : // This is where the magic happens.
      38             : // Return 1 for got a block, 0 for no block got.
      39          28 : static int blk_read(void)
      40             : {
      41             :         unsigned char c;
      42             : 
      43          56 :         for(; gcp<gbuf_end; gcp++)
      44             :         {
      45          28 :                 c=(unsigned char)*gcp;
      46             : 
      47          28 :                 blk->fingerprint = (blk->fingerprint * rconf.prime) + c;
      48          56 :                 win->checksum    = (win->checksum    * rconf.prime) + c
      49          28 :                                    - (win->data[win->pos] * rconf.multiplier);
      50          28 :                 win->data[win->pos] = c;
      51             : 
      52          28 :                 win->pos++;
      53          28 :                 if(blk->data)
      54          19 :                         blk->data[blk->length] = c;
      55          28 :                 blk->length++;
      56             : 
      57          28 :                 if(win->pos == rconf.win_size)
      58           0 :                         win->pos=0;
      59          28 :                 if( blk->length >= rconf.blk_min
      60           0 :                  && (blk->length == rconf.blk_max
      61           0 :                   || (
      62             :                         (win->checksum & 1)
      63             :                         && (win->checksum & 2)
      64           0 :                         && !(win->checksum & 4)
      65           0 :                         && (win->checksum % rconf.blk_avg) == rconf.prime))
      66             :                 ) {
      67           0 :                         gcp++;
      68           0 :                         return 1;
      69             :                 }
      70             :         }
      71             :         return 0;
      72             : }
      73             : 
      74          29 : static void win_reset(void)
      75             : {
      76          29 :         win->checksum=0;
      77          29 :         win->pos=0;
      78          29 :         memset(win->data, 0, rconf.win_size);
      79          29 : }
      80             : 
      81          19 : static int blk_read_to_list(struct sbuf *sb, struct blist *blist)
      82             : {
      83          19 :         if(!blk_read()) return 0;
      84             : 
      85           0 :         win_reset();
      86             : 
      87             :         // Got something.
      88           0 :         if(first)
      89             :         {
      90           0 :                 sb->protocol2->bstart=blk;
      91           0 :                 first=0;
      92             :         }
      93           0 :         if(!sb->protocol2->bsighead)
      94             :         {
      95           0 :                 sb->protocol2->bsighead=blk;
      96             :         }
      97           0 :         blist_add_blk(blist, blk);
      98           0 :         blk=NULL;
      99             :         return 1;
     100             : }
     101             : 
     102             : // The client uses this.
     103             : // Return 0 for OK. 1 for OK, and file ended, -1 for error.
     104          39 : int blks_generate(struct sbuf *sb, struct blist *blist, int just_opened)
     105             : {
     106             :         static ssize_t bytes;
     107          39 :         first=just_opened;
     108             : 
     109          39 :         if(!blk && !(blk=blk_alloc_with_data(rconf.blk_max)))
     110             :                 return -1;
     111             : 
     112          39 :         if(first)
     113          20 :                 win_reset();
     114             : 
     115          39 :         if(gcp<gbuf_end)
     116             :         {
     117             :                 // Could have got a fill before buf ran out -
     118             :                 // need to resume from the same place in that case.
     119           0 :                 if(blk_read_to_list(sb, blist))
     120             :                         return 0; // Got a block.
     121             :                 // Did not get a block. Carry on and read more.
     122             :         }
     123          39 :         while((bytes=rabin_read(sb, gbuf, rconf.blk_max)))
     124             :         {
     125          19 :                 gcp=gbuf;
     126          19 :                 gbuf_end=gbuf+bytes;
     127          19 :                 sb->protocol2->bytes_read+=bytes;
     128          19 :                 if(blk_read_to_list(sb, blist))
     129             :                         return 0; // Got a block
     130             :                 // Did not get a block. Maybe should try again?
     131             :                 // If there are async timeouts, look at this!
     132             :                 return 0;
     133             :         }
     134             : 
     135             :         // Getting here means there is no more to read from the file.
     136             :         // Make sure to deal with anything left over.
     137             : 
     138          20 :         if(!sb->protocol2->bytes_read)
     139             :         {
     140             :                 // Empty file, set up an empty block so that the server
     141             :                 // can skip over it.
     142           1 :                 free_w(&blk->data);
     143           1 :                 sb->protocol2->bstart=blk;
     144           1 :                 sb->protocol2->bsighead=blk;
     145           1 :                 blist_add_blk(blist, blk);
     146           1 :                 blk=NULL;
     147             :         }
     148          19 :         else if(blk)
     149             :         {
     150          19 :                 if(blk->length)
     151             :                 {
     152          19 :                         if(first)
     153             :                         {
     154           0 :                                 sb->protocol2->bstart=blk;
     155           0 :                                 first=0;
     156             :                         }
     157          19 :                         if(!sb->protocol2->bsighead)
     158             :                         {
     159          19 :                                 sb->protocol2->bsighead=blk;
     160             :                         }
     161          19 :                         blist_add_blk(blist, blk);
     162             :                 }
     163           0 :                 else blk_free(&blk);
     164          19 :                 blk=NULL;
     165             :         }
     166          20 :         if(blist->tail) sb->protocol2->bend=blist->tail;
     167             :         return 1;
     168             : }
     169             : 
     170           9 : int blk_verify_fingerprint(uint64_t fingerprint, char *data, size_t length)
     171             : {
     172           9 :         win_reset();
     173             : 
     174           9 :         memcpy(gbuf, data, length);
     175           9 :         gbuf_end=gbuf+length;
     176           9 :         gcp=gbuf;
     177           9 :         blk_free(&blk);
     178           9 :         if(!blk && !(blk=blk_alloc())) return -1;
     179           9 :         blk->length=0;
     180           9 :         blk->fingerprint=0;
     181             : 
     182             :         // FIX THIS: blk_read should return 1 when it has a block.
     183             :         // But, if the block is too small (because the end of the file
     184             :         // happened), it returns 0, and blks_generate treats it as having found
     185             :         // a final block.
     186             :         // So, here the return of blk_read is ignored and we look at the
     187             :         // position of gcp instead.
     188           9 :         blk_read();
     189             : //printf("%d %d\n", blk->length, length);
     190             : //printf("%016"PRIX64" %016"PRIX64" ",
     191             : //      blk->fingerprint, fingerprint);
     192             : //printf("%s\n", blk->fingerprint==fingerprint?"yes":"no");
     193           9 :         if(gcp==gbuf_end
     194           9 :           && blk->fingerprint==fingerprint)
     195             :                 return 1;
     196           3 :         return 0;
     197             : }

Generated by: LCOV version 1.13