1 /*********************************************************************/ 2 // dar - disk archive - a backup/restoration program 3 // Copyright (C) 2002-2052 Denis Corbin 4 // 5 // This program is free software; you can redistribute it and/or 6 // modify it under the terms of the GNU General Public License 7 // as published by the Free Software Foundation; either version 2 8 // of the License, or (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with this program; if not, write to the Free Software 17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 // 19 // to contact the author : http://dar.linux.free.fr/email.html 20 /*********************************************************************/ 21 22 #include "../my_config.h" 23 24 extern "C" 25 { 26 } // end extern "C" 27 28 #include "messaging.hpp" 29 #include "tools.hpp" 30 31 using namespace std; 32 33 namespace libdar 34 { 35 msg_equivalent(msg_type arg1,msg_type arg2)36 bool msg_equivalent(msg_type arg1, msg_type arg2) 37 { 38 bool ret = false; 39 switch(arg1) 40 { 41 case msg_type::order_read_ahead: 42 case msg_type::order_read_ahead_begin: 43 if(arg2 == msg_type::order_read_ahead 44 || arg2 == msg_type::order_read_ahead_begin) 45 ret = true; 46 break; 47 case msg_type::order_skip: 48 case msg_type::order_skip_begin: 49 if(arg2 == msg_type::order_skip 50 || arg2 == msg_type::order_skip_begin) 51 ret = true; 52 break; 53 case msg_type::order_skippable_fwd: 54 case msg_type::order_skippable_fwd_begin: 55 if(arg2 == msg_type::order_skippable_fwd 56 || arg2 == msg_type::order_skippable_fwd_begin) 57 ret = true; 58 break; 59 case msg_type::order_skippable_bkd: 60 case msg_type::order_skippable_bkd_begin: 61 if(arg2 == msg_type::order_skippable_bkd 62 || arg2 == msg_type::order_skippable_bkd_begin) 63 ret = true; 64 break; 65 case msg_type::answr_position: 66 case msg_type::answr_position_begin: 67 if(arg2 == msg_type::answr_position 68 || arg2 == msg_type::answr_position_begin) 69 ret = true; 70 break; 71 case msg_type::unset: 72 case msg_type::order_read: 73 case msg_type::order_sync_write: 74 case msg_type::answr_sync_write_done: 75 case msg_type::order_skip_to_eof: 76 case msg_type::order_skip_fwd: 77 case msg_type::order_skip_bkd: 78 case msg_type::answr_skip_done: 79 case msg_type::answr_skippable: 80 case msg_type::order_get_position: 81 case msg_type::answr_exception: 82 case msg_type::order_end_of_xmit: 83 case msg_type::order_stop_readahead: 84 case msg_type::answr_readahead_stopped: 85 case msg_type::order_wakeup: 86 ret = (arg1 == arg2); 87 break; 88 case msg_type::data_partial: 89 case msg_type::data_completed: 90 if(arg2 == msg_type::data_partial 91 || arg2 == msg_type::data_completed) 92 ret = true; 93 break; 94 default: 95 throw SRC_BUG; 96 } 97 98 return ret; 99 } 100 msg_continues(msg_type msg)101 bool msg_continues(msg_type msg) 102 { 103 switch(msg) 104 { 105 case msg_type::order_read_ahead_begin: 106 case msg_type::order_skip_begin: 107 case msg_type::order_skippable_fwd_begin: 108 case msg_type::order_skippable_bkd_begin: 109 case msg_type::answr_position_begin: 110 return true; 111 case msg_type::unset: 112 case msg_type::order_read_ahead: 113 case msg_type::order_read: 114 case msg_type::order_sync_write: 115 case msg_type::answr_sync_write_done: 116 case msg_type::order_skip: 117 case msg_type::order_skip_to_eof: 118 case msg_type::order_skip_fwd: 119 case msg_type::order_skip_bkd: 120 case msg_type::answr_skip_done: 121 case msg_type::order_skippable_fwd: 122 case msg_type::order_skippable_bkd: 123 case msg_type::answr_skippable: 124 case msg_type::order_get_position: 125 case msg_type::answr_position: 126 case msg_type::answr_exception: 127 case msg_type::order_end_of_xmit: 128 case msg_type::order_stop_readahead: 129 case msg_type::answr_readahead_stopped: 130 case msg_type::order_wakeup: 131 case msg_type::data_partial: // this is not an error 132 case msg_type::data_completed: 133 return false; 134 default: 135 throw SRC_BUG; 136 } 137 } 138 msg_type2char(msg_type x)139 char msg_type2char(msg_type x) 140 { 141 switch(x) 142 { 143 case msg_type::unset: 144 throw SRC_BUG; 145 case msg_type::order_read_ahead: 146 return 'a'; 147 case msg_type::order_read_ahead_begin: 148 return 'A'; 149 case msg_type::order_read: 150 return 'r'; 151 case msg_type::order_sync_write: 152 return 'y'; 153 case msg_type::answr_sync_write_done: 154 return 'Y'; 155 case msg_type::order_skip: 156 return 's'; 157 case msg_type::order_skip_begin: 158 return 'S'; 159 case msg_type::order_skip_to_eof: 160 return 'z'; 161 case msg_type::order_skip_fwd: 162 return 'g'; 163 case msg_type::order_skip_bkd: 164 return 'c'; 165 case msg_type::answr_skip_done: 166 return 'o'; 167 case msg_type::order_skippable_fwd: 168 return 'f'; 169 case msg_type::order_skippable_fwd_begin: 170 return 'F'; 171 case msg_type::order_skippable_bkd: 172 return 'b'; 173 case msg_type::order_skippable_bkd_begin: 174 return 'B'; 175 case msg_type::answr_skippable: 176 return 'i'; 177 case msg_type::order_get_position: 178 return 'q'; 179 case msg_type::answr_position: 180 return 'p'; 181 case msg_type::answr_position_begin: 182 return 'P'; 183 case msg_type::answr_exception: 184 return 'X'; 185 case msg_type::order_end_of_xmit: 186 return 'Z'; 187 case msg_type::order_stop_readahead: 188 return 'W'; 189 case msg_type::answr_readahead_stopped: 190 return 'w'; 191 case msg_type::order_wakeup: 192 return 'h'; 193 case msg_type::data_partial: 194 return 'd'; 195 case msg_type::data_completed: 196 return 'D'; 197 default: 198 throw SRC_BUG; 199 } 200 } 201 char2msg_type(char x)202 msg_type char2msg_type(char x) 203 { 204 switch(x) 205 { 206 case 'a': 207 return msg_type::order_read_ahead; 208 case 'A': 209 return msg_type::order_read_ahead_begin; 210 case 'r': 211 return msg_type::order_read; 212 case 'y': 213 return msg_type::order_sync_write; 214 case 'Y': 215 return msg_type::answr_sync_write_done; 216 case 's': 217 return msg_type::order_skip; 218 case 'S': 219 return msg_type::order_skip_begin; 220 case 'z': 221 return msg_type::order_skip_to_eof; 222 case 'g': 223 return msg_type::order_skip_fwd; 224 case 'c': 225 return msg_type::order_skip_bkd; 226 case 'o': 227 return msg_type::answr_skip_done; 228 case 'f': 229 return msg_type::order_skippable_fwd; 230 case 'F': 231 return msg_type::order_skippable_fwd_begin; 232 case 'b': 233 return msg_type::order_skippable_bkd; 234 case 'B': 235 return msg_type::order_skippable_bkd_begin; 236 case 'i': 237 return msg_type::answr_skippable; 238 case 'q': 239 return msg_type::order_get_position; 240 case 'p': 241 return msg_type::answr_position; 242 case 'P': 243 return msg_type::answr_position_begin; 244 case 'X': 245 return msg_type::answr_exception; 246 case 'Z': 247 return msg_type::order_end_of_xmit; 248 case 'W': 249 return msg_type::order_stop_readahead; 250 case 'w': 251 return msg_type::answr_readahead_stopped; 252 case 'h': 253 return msg_type::order_wakeup; 254 case 'd': 255 return msg_type::data_partial; 256 case 'D': 257 return msg_type::data_completed; 258 default: 259 throw SRC_BUG; 260 } 261 } 262 msg_continuation_of(msg_type x)263 msg_type msg_continuation_of(msg_type x) 264 { 265 switch(x) 266 { 267 case msg_type::order_read_ahead_begin: 268 throw SRC_BUG; 269 case msg_type::order_skip_begin: 270 throw SRC_BUG; 271 case msg_type::order_skippable_fwd_begin: 272 throw SRC_BUG; 273 case msg_type::order_skippable_bkd_begin: 274 throw SRC_BUG; 275 case msg_type::answr_position_begin: 276 throw SRC_BUG; 277 case msg_type::unset: 278 throw SRC_BUG; 279 case msg_type::order_read_ahead: 280 return msg_type::order_read_ahead_begin; 281 case msg_type::order_read: 282 throw SRC_BUG; 283 case msg_type::order_sync_write: 284 throw SRC_BUG; 285 case msg_type::answr_sync_write_done: 286 throw SRC_BUG; 287 case msg_type::order_skip: 288 return msg_type::order_skip_begin; 289 case msg_type::order_skip_to_eof: 290 throw SRC_BUG; 291 case msg_type::order_skip_fwd: 292 throw SRC_BUG; 293 case msg_type::order_skip_bkd: 294 throw SRC_BUG; 295 case msg_type::answr_skip_done: 296 throw SRC_BUG; 297 case msg_type::order_skippable_fwd: 298 return msg_type::order_skippable_fwd_begin; 299 case msg_type::order_skippable_bkd: 300 return msg_type::order_skippable_bkd_begin; 301 case msg_type::answr_skippable: 302 throw SRC_BUG; 303 case msg_type::order_get_position: 304 throw SRC_BUG; 305 case msg_type::answr_position: 306 return msg_type::answr_position_begin; 307 case msg_type::answr_exception: 308 throw SRC_BUG; 309 case msg_type::order_end_of_xmit: 310 throw SRC_BUG; 311 case msg_type::order_stop_readahead: 312 throw SRC_BUG; 313 case msg_type::answr_readahead_stopped: 314 throw SRC_BUG; 315 case msg_type::order_wakeup: 316 throw SRC_BUG; 317 case msg_type::data_partial: 318 return msg_type::data_partial; 319 case msg_type::data_completed: 320 return msg_type::data_partial; 321 default: 322 throw SRC_BUG; 323 } 324 } 325 326 ////////////////////////////////////////////////////////////////////// 327 clear()328 void messaging_decode::clear() 329 { 330 buffer.reset(); 331 msgt = msg_type::unset; 332 } 333 add_block(const char * x_input,U_I size)334 bool messaging_decode::add_block(const char *x_input, U_I size) 335 { 336 if(size < 1) 337 throw SRC_BUG; 338 else 339 { 340 msg_type tmp = char2msg_type(x_input[0]); 341 if(msgt == msg_type::unset 342 || msg_equivalent(msgt, tmp)) 343 msgt = tmp; 344 } 345 346 if(msgt != msg_type::data_partial && msgt != msg_type::data_completed) 347 { 348 buffer.skip_to_eof(); 349 buffer.write(x_input + 1, size - 1); 350 } 351 352 return !msg_continues(msgt); 353 } 354 get_infinint() const355 infinint messaging_decode::get_infinint() const 356 { 357 infinint ret; 358 359 messaging_decode *me = const_cast<messaging_decode *>(this); 360 if(me == nullptr) 361 throw SRC_BUG; 362 363 me->buffer.skip(0); 364 ret.read(me->buffer); 365 366 return ret; 367 } 368 get_U_I() const369 U_I messaging_decode::get_U_I() const 370 { 371 U_I lu; 372 U_I ret; 373 374 messaging_decode *me = const_cast<messaging_decode *>(this); 375 if(me == nullptr) 376 throw SRC_BUG; 377 378 // no ending conversion, we stay in the same process on the same host 379 380 me->buffer.skip(0); 381 lu = me->buffer.read((char *)(&ret), sizeof(ret)); 382 383 if(lu < sizeof(ret)) 384 throw SRC_BUG; 385 386 return ret; 387 } 388 389 get_string() const390 string messaging_decode::get_string() const 391 { 392 string ret; 393 394 messaging_decode *me = const_cast<messaging_decode *>(this); 395 if(me == nullptr) 396 throw SRC_BUG; 397 398 me->buffer.skip(0); 399 tools_read_string(me->buffer, ret); 400 401 return ret; 402 } 403 get_bool() const404 bool messaging_decode::get_bool() const 405 { 406 char tmp; 407 U_I lu; 408 409 messaging_decode *me = const_cast<messaging_decode *>(this); 410 if(me == nullptr) 411 throw SRC_BUG; 412 413 // no ending conversion, we stay in the same process on the same host 414 415 me->buffer.skip(0); 416 lu = me->buffer.read(&tmp, sizeof(tmp)); 417 if(lu < sizeof(tmp)) 418 throw SRC_BUG; 419 420 return tmp != 0; 421 } 422 423 get_label() const424 label messaging_decode::get_label() const 425 { 426 label ret; 427 428 messaging_decode *me = const_cast<messaging_decode *>(this); 429 if(me == nullptr) 430 throw SRC_BUG; 431 432 me->buffer.skip(0); 433 ret.read(me->buffer); 434 435 return ret; 436 } 437 438 439 ////////////////////////////////////////////////////////////////////// 440 441 clear()442 void messaging_encode::clear() 443 { 444 buffer.reset(); 445 msgt = msg_type::unset; 446 } 447 448 set_infinint(const infinint & val)449 void messaging_encode::set_infinint(const infinint & val) 450 { 451 buffer.skip_to_eof(); 452 val.dump(buffer); 453 } 454 455 set_U_I(U_I val)456 void messaging_encode::set_U_I(U_I val) 457 { 458 // no ending conversion, we stay in the same process on the same host 459 460 buffer.skip_to_eof(); 461 buffer.write((char *)(&val), sizeof(val)); 462 } 463 set_string(const string & val)464 void messaging_encode::set_string(const string & val) 465 { 466 buffer.skip_to_eof(); 467 tools_write_string(buffer, val); 468 } 469 set_bool(bool val)470 void messaging_encode::set_bool(bool val) 471 { 472 char tmp = val ? 1 : 0; 473 474 buffer.skip_to_eof(); 475 buffer.write(&tmp, sizeof(tmp)); 476 } 477 set_label(const label & val)478 void messaging_encode::set_label(const label & val) 479 { 480 buffer.skip_to_eof(); 481 val.dump(buffer); 482 } 483 reset_get_block()484 void messaging_encode::reset_get_block() 485 { 486 buffer.skip(0); 487 } 488 get_block(char * ptr,unsigned int & size)489 bool messaging_encode::get_block(char *ptr, unsigned int & size) 490 { 491 U_I wrote; 492 bool completed = true; 493 494 if(size < 1) 495 throw SRC_BUG; 496 ptr[0] = msg_type2char(msgt); 497 wrote = buffer.read(ptr + 1, size - 1); 498 499 if(wrote == size - 1) // filled the buffer 500 { 501 if(buffer.get_position() < buffer.size()) 502 { 503 // some data remains to be written 504 505 ptr[0] = msg_type2char(msg_continuation_of(msgt)); 506 completed = false; 507 } 508 } 509 510 size = wrote + 1; 511 512 return completed; 513 } 514 515 } // end of generic_thread::namespace 516 517