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

Generated by: LCOV version 1.10