LCOV - code coverage report
Current view: top level - src/protocol2/rabin - rabin.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 43 76 56.6 %
Date: 2016-02-29 Functions: 5 6 83.3 %

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

Generated by: LCOV version 1.10