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

Generated by: LCOV version 1.10