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: 163 172 94.8 %
Date: 2017-01-01 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             : #include "backup_phase2.h"
      16             : 
      17             : #define END_SIGS                0x01
      18             : #define END_BACKUP              0x02
      19             : #define END_REQUESTS            0x04
      20             : #define END_BLK_REQUESTS        0x08
      21             : 
      22          22 : static int add_to_file_requests(struct slist *slist, struct iobuf *rbuf)
      23             : {
      24             :         static uint64_t file_no=1;
      25             :         struct sbuf *sb;
      26             : 
      27          22 :         if(!(sb=sbuf_alloc(PROTO_2))) return -1;
      28             : 
      29          22 :         iobuf_move(&sb->path, rbuf);
      30             :         // Give it a number to simplify tracking.
      31          22 :         sb->protocol2->index=file_no++;
      32          22 :         slist_add_sbuf(slist, sb);
      33             : 
      34          22 :         return 0;
      35             : }
      36             : 
      37           3 : static int add_to_data_requests(struct blist *blist, struct iobuf *rbuf)
      38             : {
      39             :         uint64_t index;
      40             :         struct blk *blk;
      41           3 :         index=base64_to_uint64(rbuf->buf);
      42             : 
      43             : //printf("last_requested: %d\n", blist->last_requested->index);
      44             : 
      45             :         // Find the matching entry.
      46           8 :         for(blk=blist->last_requested; blk; blk=blk->next)
      47           8 :                 if(index==blk->index) break;
      48           3 :         if(!blk)
      49             :         {
      50           0 :                 logp("Could not find requested block %" PRIu64 "\n", index);
      51             :                 return -1;
      52             :         }
      53           3 :         blk->requested=1;
      54           3 :         blist->last_requested=blk;
      55             :         //printf("Found %lu\n", index);
      56             :         return 0;
      57             : }
      58             : 
      59          41 : static int deal_with_read(struct iobuf *rbuf, struct slist *slist,
      60             :         struct cntr *cntr, uint8_t *end_flags)
      61             : {
      62          38 :         int ret=0;
      63          38 :         switch(rbuf->cmd)
      64             :         {
      65             :                 /* Incoming file request. */
      66             :                 case CMD_FILE:
      67             :                 case CMD_METADATA:
      68          22 :                         if(add_to_file_requests(slist, rbuf)) goto error;
      69             :                         return 0;
      70             : 
      71             :                 /* Incoming data block request. */
      72             :                 case CMD_DATA_REQ:
      73           6 :                         if(add_to_data_requests(slist->blist, rbuf)) goto error;
      74             :                         goto end;
      75             : 
      76             :                 /* Incoming control/message stuff. */
      77             :                 case CMD_WRAP_UP:
      78             :                 {
      79             :                         int64_t wrap_up;
      80             :                         struct blk *blk;
      81           1 :                         struct blist *blist=slist->blist;
      82           1 :                         from_base64(&wrap_up, rbuf->buf);
      83           2 :                         for(blk=blist->head; blk; blk=blk->next)
      84             :                         {
      85           2 :                                 if(blk->index==(uint64_t)wrap_up)
      86             :                                 {
      87           1 :                                         blist->last_requested=blk;
      88           1 :                                         blist->last_sent=blk;
      89           1 :                                         break;
      90             :                                 }
      91             :                         }
      92           1 :                         if(!blk)
      93             :                         {
      94           0 :                                 logp("Could not find wrap up index: %016" PRIX64 "\n",
      95             :                                         wrap_up);
      96             : //                              goto error;
      97             :                         }
      98             :                         goto end;
      99             :                 }
     100             :                 case CMD_MESSAGE:
     101             :                 case CMD_WARNING:
     102             :                 {
     103           1 :                         log_recvd(rbuf, cntr, 0);
     104           1 :                         goto end;
     105             :                 }
     106             :                 case CMD_GEN:
     107           9 :                         if(!strcmp(rbuf->buf, "requests_end"))
     108             :                         {
     109           3 :                                 (*end_flags)|=END_REQUESTS;
     110           3 :                                 goto end;
     111             :                         }
     112           6 :                         else if(!strcmp(rbuf->buf, "blk_requests_end"))
     113             :                         {
     114           3 :                                 (*end_flags)|=END_BLK_REQUESTS;
     115           3 :                                 goto end;
     116             :                         }
     117           3 :                         else if(!strcmp(rbuf->buf, "backup_end"))
     118             :                         {
     119           3 :                                 (*end_flags)|=END_BACKUP;
     120           3 :                                 goto end;
     121             :                         }
     122             :                         break;
     123             :                 default:
     124             :                         break;
     125             :         }
     126             : 
     127           2 :         iobuf_log_unexpected(rbuf, __func__);
     128             : error:
     129             :         ret=-1;
     130             : end:
     131          16 :         iobuf_free_content(rbuf);
     132          16 :         return ret;
     133             : }
     134             : 
     135          92 : static int add_to_blks_list(struct asfd *asfd, struct conf **confs,
     136             :         struct slist *slist)
     137             : {
     138          92 :         int just_opened=0;
     139          92 :         struct sbuf *sb=slist->last_requested;
     140          92 :         if(!sb) return 0;
     141             : 
     142          41 :         if(sb->protocol2->bfd.mode==BF_CLOSED)
     143             :         {
     144             :                 char buf[32];
     145          22 :                 struct cntr *cntr=NULL;
     146          22 :                 if(confs) cntr=get_cntr(confs);
     147          22 :                 switch(rabin_open_file(sb, asfd, cntr, confs))
     148             :                 {
     149             :                         case 1: // All OK.
     150             :                                 break;
     151             :                         case 0: // Could not open file. Tell the server.
     152           3 :                                 base64_from_uint64(sb->protocol2->index, buf);
     153           3 :                                 if(asfd->write_str(asfd, CMD_INTERRUPT, buf))
     154           3 :                                         return -1;
     155           3 :                                 if(slist_del_sbuf(slist, sb))
     156             :                                         return -1;
     157           3 :                                 sbuf_free(&sb);
     158           3 :                                 return 0;
     159             :                         default:
     160             :                                 return -1;
     161             :                 }
     162          19 :                 just_opened=1;
     163             :         }
     164             : 
     165          38 :         switch(blks_generate(sb, slist->blist, just_opened))
     166             :         {
     167             :                 case 0: // All OK.
     168             :                         break;
     169             :                 case 1: // File ended.
     170          19 :                         if(rabin_close_file(sb, asfd))
     171             :                         {
     172           0 :                                 logp("Failed to close file %s\n",
     173           0 :                                         sb->path.buf);
     174           0 :                                 return -1;
     175             :                         }
     176          19 :                         slist->last_requested=sb->next;
     177          19 :                         break;
     178             :                 default:
     179             :                         return -1;
     180             :         }
     181             : 
     182             :         return 0;
     183             : }
     184             : 
     185          97 : static void free_stuff(struct slist *slist)
     186             : {
     187             :         struct blk *blk;
     188          97 :         struct blist *blist=slist->blist;
     189          97 :         blk=blist->head;
     190         210 :         while(blk && blk!=blist->last_sent)
     191             :         {
     192          16 :                 if(blk==slist->head->protocol2->bstart)
     193           0 :                         slist->head->protocol2->bstart=NULL;
     194          16 :                 if(blk==slist->head->protocol2->bend)
     195             :                 {
     196             :                         struct sbuf *sb;
     197          16 :                         sb=slist->head;
     198          16 :                         sb->protocol2->bend=NULL;
     199          16 :                         slist->head=slist->head->next;
     200          16 :                         if(!slist->head)
     201           0 :                                 slist->tail=NULL;
     202          16 :                         sbuf_free(&sb);
     203             :                 }
     204          16 :                 blk=blk->next;
     205          16 :                 blk_free(&blist->head);
     206          16 :                 blist->head=blk;
     207             :         }
     208          97 : }
     209             : 
     210          97 : static void get_wbuf_from_data(struct conf **confs,
     211             :         struct iobuf *wbuf, struct slist *slist, uint8_t end_flags)
     212             : {
     213             :         struct blk *blk;
     214          97 :         struct blist *blist=slist->blist;
     215             : 
     216         115 :         for(blk=blist->last_sent; blk; blk=blk->next)
     217             :         {
     218          99 :                 if(blk->requested)
     219             :                 {
     220           3 :                         iobuf_set(wbuf, CMD_DATA, blk->data, blk->length);
     221           3 :                         blk->requested=0;
     222           3 :                         blist->last_sent=blk;
     223           3 :                         cntr_add(get_cntr(confs), CMD_DATA, 1);
     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 :         logfmt("\n");
     309             : 
     310           7 :         if(!(slist=slist_alloc())
     311           7 :           || !(wbuf=iobuf_alloc())
     312           7 :           || 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           7 :                 if(asfd->write_str(asfd, CMD_GEN, "backupphase2")
     320           7 :                   || asfd_read_expect(asfd, CMD_GEN, "ok"))
     321             :                         goto end;
     322             :         }
     323             :         else
     324             :         {
     325             :                 // On resume, the server might update the client with cntr.
     326           0 :                 if(cntr_recv(asfd, confs))
     327             :                         goto end;
     328             :         }
     329             : 
     330          97 :         while(!(end_flags&END_BACKUP))
     331             :         {
     332          97 :                 if(!wbuf->len)
     333             :                 {
     334          97 :                         get_wbuf_from_data(confs, wbuf, slist,
     335             :                                 end_flags);
     336          97 :                         if(!wbuf->len)
     337             :                         {
     338          94 :                                 if(get_wbuf_from_blks(wbuf, slist,
     339             :                                         &end_flags)) goto end;
     340             :                         }
     341             :                 }
     342             : 
     343          97 :                 if(wbuf->len)
     344             :                 {
     345          44 :                         if(asfd->append_all_to_write_buffer(asfd, wbuf)
     346             :                                 ==APPEND_ERROR)
     347             :                                         goto end;
     348             :                 }
     349          97 :                 if(asfd->as->read_write(asfd->as))
     350             :                 {
     351           1 :                         logp("error in %s\n", __func__);
     352           1 :                         goto end;
     353             :                 }
     354             : 
     355          96 :                 if(rbuf->buf && deal_with_read(rbuf, slist, cntr, &end_flags))
     356             :                         goto end;
     357             : 
     358          94 :                 if(slist->head
     359             :                 // Need to limit how many blocks are allocated at once.
     360          92 :                   && (!slist->blist->head
     361         168 :                    || slist->blist->tail->index
     362          84 :                         - slist->blist->head->index<BLKS_MAX_IN_MEM)
     363             :                 )
     364             :                 {
     365          92 :                         if(add_to_blks_list(asfd, confs, slist))
     366             :                                 goto end;
     367             :                 }
     368             : 
     369          94 :                 if(end_flags&END_BLK_REQUESTS)
     370             :                 {
     371             :                         // If got to the end of the file request list
     372             :                         // and the last block of the last file, and
     373             :                         // the write buffer is empty, we got to the end.
     374           6 :                         if(slist->head==slist->tail)
     375             :                         {
     376           3 :                                 if(!slist->tail
     377           6 :                                   || slist->blist->last_sent==
     378           3 :                                         slist->tail->protocol2->bend)
     379             :                                 {
     380           3 :                                         if(!wbuf->len)
     381             :                                                 break;
     382             :                                 }
     383             :                         }
     384             : 
     385             :                 }
     386             :         }
     387             : 
     388           3 :         if(asfd->write_str(asfd, CMD_GEN, "backup_end"))
     389             :                 goto end;
     390             : 
     391           3 :         ret=0;
     392             : end:
     393           8 :         slist_free(&slist);
     394           8 :         blks_generate_free();
     395           8 :         if(wbuf)
     396             :         {
     397             :                 // Write buffer did not allocate 'buf'.
     398           7 :                 wbuf->buf=NULL;
     399           7 :                 iobuf_free(&wbuf);
     400             :         }
     401           8 :         cntr_print_end(cntr);
     402           8 :         cntr_print(cntr, ACTION_BACKUP, asfd);
     403           8 :         if(ret) logp("Error in backup\n");
     404           8 :         logp("End backup\n");
     405             : 
     406           8 :         return ret;
     407             : }

Generated by: LCOV version 1.10