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 0 : 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 0 : if(!(sb=sbuf_alloc(PROTO_2))) return -1;
34 :
35 0 : iobuf_move(&sb->path, rbuf);
36 : // Give it a number to simplify tracking.
37 0 : sb->protocol2->index=file_no++;
38 0 : slist_add_sbuf(slist, sb);
39 :
40 0 : 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 0 : static int deal_with_read(struct iobuf *rbuf, struct slist *slist,
66 : struct cntr *cntr, uint8_t *end_flags)
67 : {
68 0 : int ret=0;
69 0 : switch(rbuf->cmd)
70 : {
71 : /* Incoming file request. */
72 : case CMD_FILE:
73 0 : if(add_to_file_requests(slist, rbuf)) goto error;
74 0 : 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 0 : break;
130 : }
131 :
132 0 : iobuf_log_unexpected(rbuf, __func__);
133 : error:
134 0 : ret=-1;
135 : end:
136 0 : iobuf_free_content(rbuf);
137 0 : return ret;
138 : }
139 :
140 0 : static int add_to_blks_list(struct asfd *asfd, struct conf **confs,
141 : struct slist *slist)
142 : {
143 0 : struct sbuf *sb=slist->last_requested;
144 0 : if(!sb) return 0;
145 0 : 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 0 : static void free_stuff(struct slist *slist)
154 : {
155 : struct blk *blk;
156 0 : struct blist *blist=slist->blist;
157 0 : blk=blist->head;
158 0 : 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 0 : }
176 :
177 0 : 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 0 : struct blist *blist=slist->blist;
182 :
183 0 : 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 0 : free_stuff(slist);
211 0 : }
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 0 : static int get_wbuf_from_blks(struct iobuf *wbuf,
221 : struct slist *slist, uint8_t *end_flags)
222 : {
223 0 : struct sbuf *sb=slist->blks_to_send;
224 :
225 0 : if(!sb)
226 : {
227 0 : 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 0 : 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 0 : int backup_phase2_client_protocol2(struct asfd *asfd,
260 : struct conf **confs, int resume)
261 : {
262 0 : int ret=-1;
263 0 : uint8_t end_flags=0;
264 0 : struct slist *slist=NULL;
265 0 : struct iobuf *rbuf=NULL;
266 0 : struct iobuf *wbuf=NULL;
267 0 : struct cntr *cntr=get_cntr(confs);
268 :
269 0 : logp("Phase 2 begin (send backup data)\n");
270 0 : printf("\n");
271 :
272 0 : if(!(slist=slist_alloc())
273 0 : || !(wbuf=iobuf_alloc())
274 0 : || blks_generate_init())
275 0 : goto end;
276 0 : rbuf=asfd->rbuf;
277 :
278 0 : if(!resume)
279 : {
280 : // Only do this bit if the server did not tell us to resume.
281 0 : if(asfd->write_str(asfd, CMD_GEN, "backupphase2")
282 0 : || asfd->read_expect(asfd, CMD_GEN, "ok"))
283 0 : goto end;
284 : }
285 0 : else if(get_int(confs[OPT_SEND_CLIENT_CNTR]))
286 : {
287 : // On resume, the server might update the client with the
288 : // counters.
289 0 : if(cntr_recv(asfd, confs))
290 0 : goto end;
291 : }
292 :
293 0 : while(!(end_flags&END_BACKUP))
294 : {
295 0 : if(!wbuf->len)
296 : {
297 : get_wbuf_from_data(confs, wbuf, slist,
298 0 : end_flags);
299 0 : if(!wbuf->len)
300 : {
301 0 : if(get_wbuf_from_blks(wbuf, slist,
302 0 : &end_flags)) goto end;
303 : }
304 : }
305 :
306 0 : if(wbuf->len)
307 : {
308 0 : if(asfd->append_all_to_write_buffer(asfd, wbuf)
309 0 : ==APPEND_ERROR)
310 0 : goto end;
311 : }
312 0 : if(asfd->as->read_write(asfd->as))
313 : {
314 0 : logp("error in %s\n", __func__);
315 0 : goto end;
316 : }
317 :
318 0 : if(rbuf->buf && deal_with_read(rbuf, slist, cntr, &end_flags))
319 0 : goto end;
320 :
321 0 : if(slist->head
322 : // Need to limit how many blocks are allocated at once.
323 0 : && (!slist->blist->head
324 0 : || slist->blist->tail->index
325 0 : - slist->blist->head->index<BLKS_MAX_IN_MEM)
326 : )
327 : {
328 0 : if(add_to_blks_list(asfd, confs, slist))
329 0 : goto end;
330 : }
331 :
332 0 : if(end_flags&END_BLK_REQUESTS)
333 : {
334 : // If got to the end of the file request list
335 : // and the last block of the last file, and
336 : // the write buffer is empty, we got to the end.
337 0 : if(slist->head==slist->tail)
338 : {
339 0 : if(!slist->tail
340 0 : || slist->blist->last_sent==
341 : slist->tail->protocol2->bend)
342 : {
343 0 : if(!wbuf->len)
344 0 : break;
345 : }
346 : }
347 :
348 : }
349 : }
350 :
351 0 : if(asfd->write_str(asfd, CMD_GEN, "backup_end"))
352 0 : goto end;
353 :
354 0 : ret=0;
355 : end:
356 0 : slist_free(&slist);
357 : // Write buffer did not allocate 'buf'.
358 0 : wbuf->buf=NULL;
359 0 : iobuf_free(&wbuf);
360 :
361 0 : cntr_print_end(cntr);
362 0 : cntr_print(cntr, ACTION_BACKUP);
363 0 : if(ret) logp("Error in backup\n");
364 0 : logp("End backup\n");
365 :
366 0 : return ret;
367 : }
|