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

Generated by: LCOV version 1.10