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

Generated by: LCOV version 1.10