LCOV - code coverage report
Current view: top level - src/client/protocol2 - backup_phase2.c (source / functions) Hit Total Coverage
Test: burp-coverage-clean.info Lines: 81 183 44.3 %
Date: 2015-11-30 Functions: 7 10 70.0 %

          Line data    Source code
       1             : #include "../../burp.h"
       2             : #include "../../action.h"
       3             : #include "../../asfd.h"
       4             : #include "../../async.h"
       5             : #include "../../base64.h"
       6             : #include "../../cmd.h"
       7             : #include "../../cntr.h"
       8             : #include "../../iobuf.h"
       9             : #include "../../log.h"
      10             : #include "../../protocol2/blk.h"
      11             : #include "../../protocol2/blist.h"
      12             : #include "../../protocol2/rabin/rabin.h"
      13             : #include "../../slist.h"
      14             : 
      15             : #define END_SIGS                0x01
      16             : #define END_BACKUP              0x02
      17             : #define END_REQUESTS            0x04
      18             : #define END_BLK_REQUESTS        0x08
      19             : 
      20           0 : static uint64_t decode_req(const char *buf)
      21             : {
      22             :         int64_t val;
      23           0 :         const char *p=buf;
      24           0 :         p+=from_base64(&val, p);
      25           0 :         return (uint64_t)val;
      26             : }
      27             : 
      28           1 : static int add_to_file_requests(struct slist *slist, struct iobuf *rbuf)
      29             : {
      30             :         static uint64_t file_no=1;
      31             :         struct sbuf *sb;
      32             : 
      33           1 :         if(!(sb=sbuf_alloc(PROTO_2))) return -1;
      34             : 
      35           1 :         iobuf_move(&sb->path, rbuf);
      36             :         // Give it a number to simplify tracking.
      37           1 :         sb->protocol2->index=file_no++;
      38           1 :         slist_add_sbuf(slist, sb);
      39             : 
      40           1 :         return 0;
      41             : }
      42             : 
      43           0 : static int add_to_data_requests(struct blist *blist, struct iobuf *rbuf)
      44             : {
      45             :         uint64_t index;
      46             :         struct blk *blk;
      47           0 :         index=decode_req(rbuf->buf);
      48             : 
      49             : //printf("last_requested: %d\n", blist->last_requested->index);
      50             : 
      51             :         // Find the matching entry.
      52           0 :         for(blk=blist->last_requested; blk; blk=blk->next)
      53           0 :                 if(index==blk->index) break;
      54           0 :         if(!blk)
      55             :         {
      56           0 :                 logp("Could not find requested block %lu\n", index);
      57           0 :                 return -1;
      58             :         }
      59           0 :         blk->requested=1;
      60           0 :         blist->last_requested=blk;
      61             :         //printf("Found %lu\n", index);
      62           0 :         return 0;
      63             : }
      64             : 
      65           2 : static int deal_with_read(struct iobuf *rbuf, struct slist *slist,
      66             :         struct cntr *cntr, uint8_t *end_flags)
      67             : {
      68           2 :         int ret=0;
      69           2 :         switch(rbuf->cmd)
      70             :         {
      71             :                 /* Incoming file request. */
      72             :                 case CMD_FILE:
      73           1 :                         if(add_to_file_requests(slist, rbuf)) goto error;
      74           1 :                         return 0;
      75             : 
      76             :                 /* Incoming data block request. */
      77             :                 case CMD_DATA_REQ:
      78           0 :                         if(add_to_data_requests(slist->blist, rbuf)) goto error;
      79           0 :                         goto end;
      80             : 
      81             :                 /* Incoming control/message stuff. */
      82             :                 case CMD_WRAP_UP:
      83             :                 {
      84             :                         int64_t wrap_up;
      85             :                         struct blk *blk;
      86           0 :                         struct blist *blist=slist->blist;
      87           0 :                         from_base64(&wrap_up, rbuf->buf);
      88           0 :                         for(blk=blist->head; blk; blk=blk->next)
      89             :                         {
      90           0 :                                 if(blk->index==(uint64_t)wrap_up)
      91             :                                 {
      92           0 :                                         blist->last_requested=blk;
      93           0 :                                         blist->last_sent=blk;
      94           0 :                                         break;
      95             :                                 }
      96             :                         }
      97           0 :                         if(!blk)
      98             :                         {
      99             :                                 logp("Could not find wrap up index: %016"PRIX64 "\n",
     100           0 :                                         wrap_up);
     101             : //                              goto error;
     102             :                         }
     103           0 :                         goto end;
     104             :                 }
     105             :                 case CMD_MESSAGE:
     106             :                 case CMD_WARNING:
     107             :                 {
     108           0 :                         log_recvd(rbuf, cntr, 0);
     109           0 :                         goto end;
     110             :                 }
     111             :                 case CMD_GEN:
     112           0 :                         if(!strcmp(rbuf->buf, "requests_end"))
     113             :                         {
     114           0 :                                 (*end_flags)|=END_REQUESTS;
     115           0 :                                 goto end;
     116             :                         }
     117           0 :                         else if(!strcmp(rbuf->buf, "blk_requests_end"))
     118             :                         {
     119           0 :                                 (*end_flags)|=END_BLK_REQUESTS;
     120           0 :                                 goto end;
     121             :                         }
     122           0 :                         else if(!strcmp(rbuf->buf, "backup_end"))
     123             :                         {
     124           0 :                                 (*end_flags)|=END_BACKUP;
     125           0 :                                 goto end;
     126             :                         }
     127           0 :                         break;
     128             :                 default:
     129           1 :                         break;
     130             :         }
     131             : 
     132           1 :         iobuf_log_unexpected(rbuf, __func__);
     133             : error:
     134           1 :         ret=-1;
     135             : end:
     136           1 :         iobuf_free_content(rbuf);
     137           1 :         return ret;
     138             : }
     139             : 
     140           1 : static int add_to_blks_list(struct asfd *asfd, struct conf **confs,
     141             :         struct slist *slist)
     142             : {
     143           1 :         struct sbuf *sb=slist->last_requested;
     144           1 :         if(!sb) return 0;
     145           1 :         if(blks_generate(asfd, confs, sb, slist->blist)) return -1;
     146             : 
     147             :         // If it closed the file, move to the next one.
     148           0 :         if(sb->protocol2->bfd.mode==BF_CLOSED) slist->last_requested=sb->next;
     149             : 
     150           0 :         return 0;
     151             : }
     152             : 
     153           3 : static void free_stuff(struct slist *slist)
     154             : {
     155             :         struct blk *blk;
     156           3 :         struct blist *blist=slist->blist;
     157           3 :         blk=blist->head;
     158           6 :         while(blk && blk!=blist->last_sent)
     159             :         {
     160           0 :                 if(blk==slist->head->protocol2->bstart)
     161           0 :                         slist->head->protocol2->bstart=NULL;
     162           0 :                 if(blk==slist->head->protocol2->bend)
     163             :                 {
     164             :                         struct sbuf *sb;
     165           0 :                         sb=slist->head;
     166           0 :                         sb->protocol2->bend=NULL;
     167           0 :                         if(!(slist->head=slist->head->next))
     168           0 :                                 slist->tail=NULL;
     169           0 :                         sbuf_free(&sb);
     170             :                 }
     171           0 :                 blk=blk->next;
     172           0 :                 blk_free(&blist->head);
     173           0 :                 blist->head=blk;
     174             :         }
     175           3 : }
     176             : 
     177           3 : static void get_wbuf_from_data(struct conf **confs,
     178             :         struct iobuf *wbuf, struct slist *slist, uint8_t end_flags)
     179             : {
     180             :         struct blk *blk;
     181           3 :         struct blist *blist=slist->blist;
     182             : 
     183           3 :         for(blk=blist->last_sent; blk; blk=blk->next)
     184             :         {
     185           0 :                 if(blk->requested)
     186             :                 {
     187           0 :                         wbuf->cmd=CMD_DATA;
     188           0 :                         wbuf->buf=blk->data;
     189           0 :                         wbuf->len=blk->length;
     190           0 :                         blk->requested=0;
     191           0 :                         blist->last_sent=blk;
     192           0 :                         cntr_add(get_cntr(confs), CMD_DATA, 1);
     193           0 :                         cntr_add_sentbytes(get_cntr(confs), blk->length);
     194           0 :                         break;
     195             :                 }
     196             :                 else
     197             :                 {
     198           0 :                         cntr_add_same(get_cntr(confs), CMD_DATA);
     199           0 :                         if(end_flags&END_BLK_REQUESTS)
     200             :                         {
     201             :                                 // Force onwards when the server has said that
     202             :                                 // there are no more blocks to request.
     203           0 :                                 blist->last_sent=blk;
     204           0 :                                 continue;
     205             :                         }
     206             :                 }
     207           0 :                 if(blk==blist->last_requested) break;
     208             :         }
     209             :         // Need to free stuff that is no longer needed.
     210           3 :         free_stuff(slist);
     211           3 : }
     212             : 
     213           0 : static int iobuf_from_blk_data(struct iobuf *wbuf, struct blk *blk)
     214             : {
     215           0 :         if(blk_md5_update(blk)) return -1;
     216           0 :         blk_to_iobuf_sig(blk, wbuf);
     217           0 :         return 0;
     218             : }
     219             : 
     220           3 : static int get_wbuf_from_blks(struct iobuf *wbuf,
     221             :         struct slist *slist, uint8_t *end_flags)
     222             : {
     223           3 :         struct sbuf *sb=slist->blks_to_send;
     224             : 
     225           3 :         if(!sb)
     226             :         {
     227           3 :                 if((*end_flags)&END_REQUESTS && !((*end_flags)&END_SIGS))
     228             :                 {
     229           0 :                         iobuf_from_str(wbuf, CMD_GEN, (char *)"sigs_end");
     230           0 :                         (*end_flags)|=END_SIGS;
     231             :                 }
     232           3 :                 return 0;
     233             :         }
     234           0 :         if(!sb->protocol2->bsighead) return 0;
     235             : 
     236           0 :         if(!(sb->flags & SBUF_SENT_STAT))
     237             :         {
     238           0 :                 iobuf_copy(wbuf, &sb->attr);
     239           0 :                 wbuf->cmd=CMD_ATTRIBS_SIGS; // hack
     240           0 :                 sb->flags |= SBUF_SENT_STAT;
     241           0 :                 return 0;
     242             :         }
     243             : 
     244           0 :         if(iobuf_from_blk_data(wbuf, sb->protocol2->bsighead)) return -1;
     245             : 
     246             :         // Move on.
     247           0 :         if(sb->protocol2->bsighead==sb->protocol2->bend)
     248             :         {
     249           0 :                 slist->blks_to_send=sb->next;
     250           0 :                 sb->protocol2->bsighead=sb->protocol2->bstart;
     251             :         }
     252             :         else
     253             :         {
     254           0 :                 sb->protocol2->bsighead=sb->protocol2->bsighead->next;
     255             :         }
     256           0 :         return 0;
     257             : }
     258             : 
     259           4 : int backup_phase2_client_protocol2(struct asfd *asfd,
     260             :         struct conf **confs, int resume)
     261             : {
     262           4 :         int ret=-1;
     263           4 :         uint8_t end_flags=0;
     264           4 :         struct slist *slist=NULL;
     265           4 :         struct iobuf *rbuf=NULL;
     266           4 :         struct iobuf *wbuf=NULL;
     267           4 :         struct cntr *cntr=NULL;
     268             : 
     269           4 :         if(confs) cntr=get_cntr(confs);
     270             : 
     271           4 :         if(!asfd || !asfd->as)
     272             :         {
     273           1 :                 logp("%s() called without async structs!\n", __func__);
     274           1 :                 goto end;
     275             :         }
     276             : 
     277           3 :         logp("Phase 2 begin (send backup data)\n");
     278           3 :         logf("\n");
     279             : 
     280           9 :         if(!(slist=slist_alloc())
     281           3 :           || !(wbuf=iobuf_alloc())
     282           9 :           || blks_generate_init())
     283           0 :                 goto end;
     284           3 :         rbuf=asfd->rbuf;
     285             : 
     286           3 :         if(!resume)
     287             :         {
     288             :                 // Only do this bit if the server did not tell us to resume.
     289           6 :                 if(asfd->write_str(asfd, CMD_GEN, "backupphase2")
     290           3 :                   || asfd->read_expect(asfd, CMD_GEN, "ok"))
     291           0 :                         goto end;
     292             :         }
     293           0 :         else if(get_int(confs[OPT_SEND_CLIENT_CNTR]))
     294             :         {
     295             :                 // On resume, the server might update the client with the
     296             :                 // counters.
     297           0 :                 if(cntr_recv(asfd, confs))
     298           0 :                         goto end;
     299             :         }
     300             : 
     301           6 :         while(!(end_flags&END_BACKUP))
     302             :         {
     303           3 :                 if(!wbuf->len)
     304             :                 {
     305             :                         get_wbuf_from_data(confs, wbuf, slist,
     306           3 :                                 end_flags);
     307           3 :                         if(!wbuf->len)
     308             :                         {
     309           3 :                                 if(get_wbuf_from_blks(wbuf, slist,
     310           3 :                                         &end_flags)) goto end;
     311             :                         }
     312             :                 }
     313             : 
     314           3 :                 if(wbuf->len)
     315             :                 {
     316           0 :                         if(asfd->append_all_to_write_buffer(asfd, wbuf)
     317           0 :                                 ==APPEND_ERROR)
     318           0 :                                         goto end;
     319             :                 }
     320           3 :                 if(asfd->as->read_write(asfd->as))
     321             :                 {
     322           1 :                         logp("error in %s\n", __func__);
     323           1 :                         goto end;
     324             :                 }
     325             : 
     326           2 :                 if(rbuf->buf && deal_with_read(rbuf, slist, cntr, &end_flags))
     327           1 :                         goto end;
     328             : 
     329           1 :                 if(slist->head
     330             :                 // Need to limit how many blocks are allocated at once.
     331           1 :                   && (!slist->blist->head
     332           0 :                    || slist->blist->tail->index
     333           0 :                         - slist->blist->head->index<BLKS_MAX_IN_MEM)
     334             :                 )
     335             :                 {
     336           1 :                         if(add_to_blks_list(asfd, confs, slist))
     337           1 :                                 goto end;
     338             :                 }
     339             : 
     340           0 :                 if(end_flags&END_BLK_REQUESTS)
     341             :                 {
     342             :                         // If got to the end of the file request list
     343             :                         // and the last block of the last file, and
     344             :                         // the write buffer is empty, we got to the end.
     345           0 :                         if(slist->head==slist->tail)
     346             :                         {
     347           0 :                                 if(!slist->tail
     348           0 :                                   || slist->blist->last_sent==
     349             :                                         slist->tail->protocol2->bend)
     350             :                                 {
     351           0 :                                         if(!wbuf->len)
     352           0 :                                                 break;
     353             :                                 }
     354             :                         }
     355             : 
     356             :                 }
     357             :         }
     358             : 
     359           0 :         if(asfd->write_str(asfd, CMD_GEN, "backup_end"))
     360           0 :                 goto end;
     361             : 
     362           0 :         ret=0;
     363             : end:
     364           4 :         slist_free(&slist);
     365           4 :         blks_generate_free();
     366           4 :         if(wbuf)
     367             :         {
     368             :                 // Write buffer did not allocate 'buf'.
     369           3 :                 wbuf->buf=NULL;
     370           3 :                 iobuf_free(&wbuf);
     371             :         }
     372           4 :         cntr_print_end(cntr);
     373           4 :         cntr_print(cntr, ACTION_BACKUP);
     374           4 :         if(ret) logp("Error in backup\n");
     375           4 :         logp("End backup\n");
     376             : 
     377           4 :         return ret;
     378             : }

Generated by: LCOV version 1.10