00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include <unistd.h>
00041 #include <errno.h>
00042
00043
00044
00045
00046
00047 #include "dtn_api.h"
00048 #include "TcaController.h"
00049
00050
00051 static const int debug = 1;
00052
00053
00054
00055
00056 static const int RECV_TIMEOUT = 30000;
00057
00058
00059
00060
00061
00062
00063
00064
00065 static const u_int32_t REG_EXPIRATION_TIME = 2000000;
00066
00067
00068
00069
00070
00071 bool
00072 make_spec(dtn_bundle_spec_t& spec,
00073 std::string source,
00074 std::string dest,
00075 std::string replyto,
00076 int expiration,
00077 dtn_bundle_priority_t priority = COS_NORMAL,
00078 dtn_bundle_delivery_opts_t dopts = DOPTS_NONE
00079 )
00080 {
00081 memset(&spec, 0, sizeof(spec));
00082
00083 if (dtn_parse_eid_string(&spec.source, source.c_str()))
00084 {
00085 fprintf(stderr, "make_spec: invalid source eid '%s'\n",
00086 source.c_str());
00087 return false;
00088 }
00089
00090 if (dtn_parse_eid_string(&spec.dest, dest.c_str()))
00091 {
00092 fprintf(stderr, "make_spec: invalid dest eid '%s'\n",
00093 dest.c_str());
00094 return false;
00095 }
00096
00097 if (dtn_parse_eid_string(&spec.replyto, replyto.c_str()))
00098 {
00099 fprintf(stderr, "make_spec: invalid replyto eid '%s'\n",
00100 replyto.c_str());
00101 return false;
00102 }
00103
00104 spec.priority = priority;
00105 spec.dopts = dopts;
00106 spec.expiration = expiration;
00107
00108 return true;
00109 }
00110
00111
00112 static bool
00113 check_nargs(const TcaControlBundle& cb, uint n_expected)
00114 {
00115 if (cb.args_.size() != n_expected)
00116 {
00117 printf("TcaController: bundle '%s' contains wrong number of args. "
00118 "%d expected.\n", cb.str().c_str(), n_expected);
00119 return false;
00120 }
00121 return true;
00122 }
00123
00124
00125 TcaController::TcaController(TcaController::Role role,
00126 const std::string& link_id,
00127 const std::string& ask_addr,
00128 const std::string& adv_str,
00129 int registry_ttl, int control_ttl)
00130 : role_(role), link_id_(link_id),
00131 ask_addr_(ask_addr), adv_str_(adv_str),
00132 registry_ttl_(registry_ttl), control_ttl_(control_ttl)
00133
00134 {
00135
00136 }
00137
00138
00139 TcaController::~TcaController()
00140 {
00141 dtn_close(handle_);
00142 }
00143
00144
00145 bool
00146 TcaController::dtn_reg(dtn_endpoint_id_t& eid, dtn_reg_id_t& id)
00147 {
00148
00149
00150
00151 dtn_reg_info_t reginfo;
00152
00153 int ret;
00154
00155 memset(®info, 0, sizeof(reginfo));
00156 dtn_copy_eid(®info.endpoint, &eid);
00157 reginfo.failure_action = DTN_REG_DEFER;
00158 reginfo.regid = DTN_REGID_NONE;
00159 reginfo.expiration = REG_EXPIRATION_TIME;
00160 if ((ret = dtn_register(handle_, ®info, &id)) != 0) {
00161 fprintf(stderr, "error creating registration: %d (%s)\n",
00162 ret, dtn_strerror(dtn_errno(handle_)));
00163 return false;
00164 }
00165
00166
00167 printf("TcaController::dtn_reg: app registered as %s, id=0x%x\n",
00168 eid.uri, id);
00169
00170 return true;
00171 }
00172
00173
00174 bool
00175 TcaController::init(bool tidy)
00176 {
00177
00178 int err = dtn_open(&handle_);
00179 if (err != DTN_SUCCESS) {
00180 fprintf(stderr, "fatal error opening dtn handle: %s\n",
00181 dtn_strerror(err));
00182 return false;
00183 }
00184
00185 printf("TcaController::init: dtn_open succeeded\n");
00186
00187
00188 dtn_reg_id_t app_id;
00189 dtn_build_local_eid(handle_, &local_eid_, "/admin");
00190 if (!dtn_reg(local_eid_, app_id)) return false;
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 if (tidy) eat_bundles();
00202
00203 if (role_ == TCA_GATEWAY)
00204 {
00205
00206 registry_.init_nodes();
00207 if (!registry_.init_addrs())
00208 {
00209
00210
00211
00212 fprintf(stderr,
00213 "TcaController fatal error: no registry nodes available!\n");
00214 return false;
00215 }
00216 }
00217
00218 return true;
00219 }
00220
00221
00222 void
00223 TcaController::run()
00224 {
00225
00226 if (ask_addr_.length() != 0)
00227 {
00228
00229 ask(ask_addr_);
00230 }
00231
00232 dtn_bundle_spec_t spec;
00233 std::string payload;
00234
00235 for (;;)
00236 {
00237 if (recv_bundle(spec, payload, RECV_TIMEOUT))
00238 {
00239 handle_bundle_received(spec, payload);
00240 }
00241 }
00242 }
00243
00244
00245 bool
00246 TcaController::handle_bundle_received(const dtn_bundle_spec_t& spec,
00247 const std::string& payload)
00248 {
00249 TcaControlBundle cb(payload);
00250
00251
00252 switch (cb.type_)
00253 {
00254 case TcaControlBundle::CB_LINK_ANNOUNCE:
00255 handle_link_announce(spec, cb);
00256 break;
00257 case TcaControlBundle::CB_ASK:
00258 handle_ask(spec, cb);
00259 break;
00260 case TcaControlBundle::CB_ASK_RECEIVED:
00261 handle_ask_received(spec, cb);
00262 break;
00263 case TcaControlBundle::CB_ASK_SENT:
00264 handle_ask_sent(spec, cb);
00265 break;
00266 case TcaControlBundle::CB_ADV:
00267 handle_adv(spec, cb);
00268 break;
00269 case TcaControlBundle::CB_ADV_SENT:
00270 handle_adv_sent(spec, cb);
00271 break;
00272 case TcaControlBundle::CB_REG_RECEIVED:
00273 handle_reg_received(spec, cb);
00274 break;
00275 case TcaControlBundle::CB_UNB:
00276 handle_unb(spec, cb);
00277 break;
00278 case TcaControlBundle::CB_COA:
00279
00280
00281 break;
00282 case TcaControlBundle::CB_COA_SENT:
00283 handle_coa_sent(spec, cb);
00284 break;
00285 case TcaControlBundle::CB_ROUTES:
00286 handle_routes(spec, cb);
00287 break;
00288 case TcaControlBundle::CB_LINK_AVAILABLE:
00289 break;
00290 case TcaControlBundle::CB_LINK_UNAVAILABLE:
00291 break;
00292 case TcaControlBundle::CB_CONTACT_UP:
00293 break;
00294 case TcaControlBundle::CB_CONTACT_DOWN:
00295 break;
00296 default:
00297 printf("TcaController: unrecognized bundle code received: '%s'\n",
00298 cb.code_.c_str());
00299 }
00300
00301 return true;
00302 }
00303
00304
00305
00306 bool
00307 TcaController::handle_reg_received(const dtn_bundle_spec_t& spec,
00308 const TcaControlBundle& cb)
00309 {
00310 switch (role_)
00311 {
00312 case TCA_MOBILE:
00313
00314
00315
00316 return route_reg(spec, cb);
00317 break;
00318 case TCA_ROUTER:
00319 return route_reg(spec, cb);
00320 break;
00321 case TCA_GATEWAY:
00322 return gate_reg(spec, cb);
00323 break;
00324 }
00325
00326 return false;
00327 }
00328
00329
00330 bool
00331 TcaController::handle_unb(const dtn_bundle_spec_t& spec,
00332 const TcaControlBundle& cb)
00333 {
00334 (void)spec;
00335
00336 if (role_ != TCA_GATEWAY)
00337 {
00338 printf("TcaController error: non-gateway received unb bundle.\n");
00339 return false;
00340 }
00341
00342 TcaEndpointID dest_eid(cb.args_[0]);
00343 RegRecord rr;
00344
00345 if (!get_registration(dest_eid, rr))
00346 {
00347 printf("TcaController: bind failed: unregistered node [%s]\n",
00348 dest_eid.c_str());
00349
00350
00351
00352
00353 return false;
00354 }
00355
00356
00357
00358
00359
00360 if (!add_route(dest_eid.str(), rr.link_addr_)) return false;
00361
00362 return true;
00363 }
00364
00365
00366 bool
00367 TcaController::handle_coa_sent(const dtn_bundle_spec_t& spec,
00368 const TcaControlBundle& cb)
00369 {
00370 (void)spec;
00371
00372 if (role_ == TCA_MOBILE)
00373 {
00374 printf("TcaController error: mobile received coa_sent bundle.\n");
00375 return false;
00376 }
00377
00378
00379 const std::string& src = cb.args_[0];
00380 const std::string& dest = cb.args_[1];
00381 const std::string& link = cb.args_[2];
00382
00383
00384 TcaEndpointID pattern = dest;
00385 pattern.set_app("*");
00386 del_route(pattern.str());
00387
00388
00389
00390
00391 if (src == local_eid_.uri)
00392 {
00393 TcaEndpointID tca_dest = dest;
00394 if (!do_registration(tca_dest, link_id_)) return false;
00395
00396 tca_dest.set_app("*");
00397 if (!add_route(tca_dest.str(), link)) return false;
00398 }
00399
00400 return true;
00401 }
00402
00403
00404 bool
00405 TcaController::handle_link_announce(const dtn_bundle_spec_t& spec,
00406 const TcaControlBundle& cb)
00407 {
00408 (void)spec;
00409
00410
00411
00412 if (!check_nargs(cb, 1)) return false;
00413 std::string link_spec = cb.args_[0];
00414 link_spec += ":5000";
00415 return ask(link_spec);
00416 }
00417
00418
00419 bool
00420 TcaController::handle_ask(const dtn_bundle_spec_t& spec,
00421 const TcaControlBundle& cb)
00422 {
00423 (void)spec;
00424 (void)cb;
00425 printf("error -- we should never receive an ask bundle!\n");
00426
00427 return true;
00428 }
00429
00430
00431 bool
00432 TcaController::handle_ask_received(const dtn_bundle_spec_t& spec,
00433 const TcaControlBundle& cb)
00434 {
00435 (void)spec;
00436 TcaWrappedBundle wb(cb);
00437
00438
00439
00440 TcaEndpointID src_eid = wb.source();
00441 src_eid.set_app("*");
00442
00443 if (!add_route(src_eid.str(), wb.args_[2])) return false;
00444
00445
00446
00447
00448 std::string response = "adv:";
00449 response += wb.dest();
00450 response += "\t";
00451 response += adv_str_;
00452 send_bundle(wb.source(), response);
00453
00454 return true;
00455 }
00456
00457
00458 bool
00459 TcaController::handle_ask_sent(const dtn_bundle_spec_t& spec,
00460 const TcaControlBundle& cb)
00461 {
00462 (void)spec;
00463 TcaWrappedBundle wb(cb);
00464
00465
00466 TcaEndpointID dest_eid = wb.dest();
00467 dest_eid.set_app("*");
00468
00469 if (!del_route(dest_eid.str())) return false;
00470 return true;
00471 }
00472
00473
00474 bool
00475 TcaController::handle_adv(const dtn_bundle_spec_t& spec,
00476 const TcaControlBundle& cb)
00477 {
00478 (void)spec;
00479 (void)cb;
00480
00481
00482
00483 return true;
00484 }
00485
00486
00487 bool
00488 TcaController::handle_adv_sent(const dtn_bundle_spec_t& spec,
00489 const TcaControlBundle& cb)
00490 {
00491 (void)spec;
00492 TcaWrappedBundle wb(cb);
00493
00494
00495
00496
00497
00498
00499
00500 TcaEndpointID dest_eid = wb.dest();
00501 dest_eid.set_app("*");
00502
00503 if (!del_route(dest_eid.str())) return false;
00504 return true;
00505 }
00506
00507
00508 bool
00509 TcaController::handle_routes(const dtn_bundle_spec_t& spec,
00510 const TcaControlBundle& cb)
00511 {
00512 (void)spec;
00513
00514 printf("routes:\n");
00515 for (unsigned int i=0; i<cb.args_.size(); ++i)
00516 {
00517 printf(" %s \n", cb.args_[i].c_str());
00518 }
00519 return true;
00520 }
00521
00522
00523 bool
00524 TcaController::route_reg(const dtn_bundle_spec_t& spec,
00525 const TcaControlBundle& cb)
00526 {
00527 (void)spec;
00528
00529
00530
00531
00532
00533 if (!check_nargs(cb, 4)) return false;
00534
00535 TcaWrappedBundle wb(cb);
00536
00537 std::string mobile_eid = wb.args_[2];
00538 std::string last_hop = wb.args_[3];
00539
00540 if (last_hop != "NULL")
00541 {
00542
00543
00544
00545 mobile_eid = wb.args_[2];
00546 last_hop = wb.args_[3];
00547
00548 TcaEndpointID pattern(mobile_eid);
00549
00550
00551
00552
00553
00554 pattern.set_app("*");
00555 printf("deleteing routes for %s\n", pattern.str().c_str());
00556 if (!del_route(pattern.str())) return false;
00557
00558
00559 if (!add_route(pattern.str(), last_hop)) return false;
00560 }
00561
00562
00563
00564
00565
00566 if (role_ != TCA_GATEWAY)
00567 {
00568 std::string new_payload = "register:";
00569 new_payload += mobile_eid;
00570 new_payload += "\t";
00571 new_payload += link_id_;
00572
00573 if (!send_bundle("tca://registry", new_payload)) return false;
00574 }
00575
00576 return true;
00577 }
00578
00579
00580 bool
00581 TcaController::gate_reg(const dtn_bundle_spec_t& spec,
00582 const TcaControlBundle& cb)
00583 {
00584 (void)spec;
00585 TcaWrappedBundle wb(cb);
00586
00587 std::string mobile_eid = wb.args_[2];
00588 std::string last_hop = wb.args_[3];
00589
00590 TcaEndpointID src(mobile_eid);
00591
00592
00593
00594
00595 RegRecord old_reg;
00596 bool prev_reg_exists = get_registration(src, old_reg);
00597
00598 if (prev_reg_exists)
00599 {
00600
00601 if (old_reg.link_addr_ == link_id_)
00602 {
00603 printf("TcaController: ignoring re-registration with same"
00604 " gateway\n");
00605
00606
00607
00608
00609
00610
00611
00612
00613 return true;
00614 }
00615 else
00616 {
00617 printf("TcaController: initiating change-of-address\n");
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629 TcaEndpointID pattern = src;
00630 pattern.set_app("admin.coa");
00631
00632 printf("TcaController: adding route %s -> %s\n",
00633 pattern.c_str(), old_reg.link_addr_.c_str());
00634
00635 if (!add_route(pattern.str(), old_reg.link_addr_)) return false;
00636
00637
00638 TcaEndpointID dest_eid = src;
00639 dest_eid.set_app("admin.coa");
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 std::string coa_payload = "coa:";
00654 coa_payload += last_hop;
00655
00656 dtn_bundle_spec_t coa_spec;
00657 if (!make_spec(coa_spec, local_eid_.uri, dest_eid.str(),
00658 local_eid_.uri, control_ttl_, COS_NORMAL, DOPTS_NONE))
00659 return false;
00660
00661
00662
00663
00664
00665 if (!send_bundle(coa_spec, coa_payload)) return false;
00666
00667
00668
00669
00670
00671 }
00672
00673
00674
00675
00676
00677 }
00678
00679 else
00680 {
00681
00682
00683
00684
00685 if (!do_registration(src, link_id_)) return false;
00686
00687
00688 if (!route_reg(spec, cb)) return false;
00689 }
00690
00691 return true;
00692
00693 }
00694
00695
00696 bool
00697 TcaController::ask(const std::string& link)
00698 {
00699
00700
00701
00702
00703
00704 std::string host = "tca://anonymous";
00705
00706 host += link.substr(6, link.length());
00707
00708 std::string pattern = host + "/*";
00709
00710 if (!add_route(pattern, link)) return false;
00711
00712 std::string payload = "ask:";
00713 payload += link_id_;
00714
00715 std::string dest = host + "/admin.ask";
00716
00717 if (!send_bundle(dest, payload))
00718 {
00719 fprintf(stderr,
00720 "TcaController::ask: error: failed to send ask bundle\n");
00721 return false;
00722 }
00723
00724 return true;
00725 }
00726
00727
00728 bool
00729 TcaController::get_routes()
00730 {
00731 if (!send_bundle("tca://localhost/bundlelayer", "get_routes:tca://*"))
00732 {
00733 fprintf(stderr, "error: failed to send get_routes bundle\n");
00734 return false;
00735 }
00736
00737 return true;
00738 }
00739
00740
00741 bool
00742 TcaController::add_route(const std::string& route_pattern,
00743 const std::string& link)
00744 {
00745 std::string body = "add_route:";
00746 body += route_pattern;
00747 body += "\t";
00748 body += link;
00749
00750
00751 if (!send_bundle("tca://localhost/bundlelayer", body))
00752 {
00753 fprintf(stderr, "error: failed to send add_route bundle\n");
00754 return false;
00755 }
00756
00757 return true;
00758 }
00759
00760
00761 bool
00762 TcaController::del_route(const std::string& route_pattern)
00763 {
00764 std::string body = "del_route:";
00765 body += route_pattern;
00766
00767 if (!send_bundle("tca://localhost/bundlelayer", body))
00768 {
00769 fprintf(stderr, "error: failed to send del_route bundle\n");
00770 return false;
00771 }
00772
00773 return true;
00774 }
00775
00776
00777 bool
00778 TcaController::get_registration(const TcaEndpointID& eid, RegRecord& rr)
00779 {
00780 rr.host_ = eid.get_hostid();
00781 if (registry_.read(rr))
00782 {
00783 printf("TcaController: found registry entry %s\n", rr.str().c_str());
00784 return true;
00785 }
00786 else
00787 {
00788 printf("TcaController: no registry entry for host %s\n",
00789 rr.host_.c_str());
00790 return false;
00791 }
00792 }
00793
00794
00795
00796 bool
00797 TcaController::do_registration(const TcaEndpointID& eid,
00798 const std::string& link_addr)
00799 {
00800 RegRecord rr(eid.get_hostid(), link_addr);
00801
00802 if (registry_.write(rr, registry_ttl_))
00803 {
00804 printf("TcaController: wrote registry entry %s\n", rr.str().c_str());
00805 return true;
00806 }
00807 else
00808 {
00809 printf("TcaController: failed to write registry entry %s\n",
00810 rr.str().c_str());
00811 return false;
00812 }
00813
00814 }
00815
00816
00817 bool
00818 TcaController::test_all()
00819 {
00820 get_routes();
00821
00822 add_route("tca://booyah", "tcp://9.8.7.6:54321");
00823 sleep(5);
00824
00825 get_routes();
00826
00827 del_route("tca://booyah");
00828 sleep(5);
00829
00830 get_routes();
00831
00832 return true;
00833 }
00834
00835
00836 void
00837 TcaController::eat_bundles(bool verbose)
00838 {
00839
00840
00841 dtn_bundle_spec_t recv_spec;
00842 std::string payload;
00843
00844 printf("checking for queued bundles...\n");
00845
00846 if (verbose)
00847 {
00848 while (recv_bundle(recv_spec, payload, 0))
00849 printf(" discarding bundle: %s\n", payload.c_str());
00850 }
00851 else
00852 {
00853 dtn_bundle_payload_t recv_payload;
00854 int ret;
00855 do
00856 {
00857 memset(&recv_spec, 0, sizeof(recv_spec));
00858 memset(&recv_payload, 0, sizeof(recv_payload));
00859
00860 ret = dtn_recv(handle_, &recv_spec,
00861 DTN_PAYLOAD_MEM, &recv_payload, 0);
00862
00863 if (ret == 0)
00864 {
00865 fprintf(stderr, "error: unexpected bundle already queued... "
00866 "discarding\n");
00867 }
00868 else if (dtn_errno(handle_) != DTN_ETIMEOUT)
00869 {
00870 fprintf(stderr, "error: "
00871 "unexpected error checking for queued bundles: %s\n",
00872 dtn_strerror(dtn_errno(handle_)));
00873 return;
00874 }
00875 } while (ret == 0);
00876 }
00877 }
00878
00879
00880 bool
00881 TcaController::send_bundle(const dtn_bundle_spec_t& spec,
00882 const std::string& payload)
00883 {
00884 printf("send_bundle: [%s] -> [%s] : '%s'\n",
00885 spec.source.uri, spec.dest.uri, payload.c_str());
00886
00887 dtn_bundle_payload_t send_payload;
00888 memset(&send_payload, 0, sizeof(send_payload));
00889 dtn_set_payload(&send_payload, DTN_PAYLOAD_MEM,
00890 const_cast<char*>(payload.c_str()), payload.length());
00891
00892 dtn_bundle_id_t bundle_id;
00893 memset(&bundle_id, 0, sizeof(bundle_id));
00894
00895 int r = 0;
00896 if ((r = dtn_send(handle_,
00897 const_cast<dtn_bundle_spec_t*>(&spec),
00898 &send_payload, &bundle_id)) != 0)
00899 {
00900 fprintf(stderr, "TcaController::send_bundle error %d (%s)\n",
00901 r, dtn_strerror(dtn_errno(handle_)));
00902 return false;
00903 }
00904
00905 return true;
00906 }
00907
00908
00909 bool
00910 TcaController::recv_bundle(dtn_bundle_spec_t& spec,
00911 std::string& payload,
00912 unsigned int timeout)
00913 {
00914 dtn_bundle_payload_t recv_payload;
00915 memset(&spec, 0, sizeof(spec));
00916 memset(&recv_payload, 0, sizeof(recv_payload));
00917
00918
00919
00920 int r;
00921 if ((r = dtn_recv(handle_, &spec,
00922 DTN_PAYLOAD_MEM, &recv_payload, timeout)) < 0)
00923 {
00924
00925
00926 return false;
00927 }
00928
00929 int n = recv_payload.dtn_bundle_payload_t_u.buf.buf_len;
00930 char s_buf[n+1];
00931 memcpy(s_buf, recv_payload.dtn_bundle_payload_t_u.buf.buf_val, n);
00932 s_buf[n] = '\0';
00933
00934 payload = s_buf;
00935
00936 printf("%d bytes from [%s]: %s\n",
00937
00938 n,
00939 spec.source.uri,
00940 payload.c_str());
00941
00942 return true;
00943 }
00944
00945
00946
00947 bool
00948 TcaController::send_bundle(const std::string& dest,
00949 const std::string& payload)
00950 {
00951
00952
00953
00954 dtn_bundle_spec_t spec;
00955 memset(&spec, 0, sizeof(spec));
00956
00957
00958 dtn_copy_eid(&spec.source, &local_eid_);
00959 dtn_copy_eid(&spec.replyto, &local_eid_);
00960
00961 if (dtn_parse_eid_string(&spec.dest, dest.c_str()))
00962 {
00963 fprintf(stderr, "TcaController::send_bundle: invalid destination"
00964 " eid string, %s\n", dest.c_str());
00965 return false;
00966 }
00967
00968
00969 spec.priority = COS_NORMAL;
00970 spec.dopts = DOPTS_NONE;
00971 spec.expiration = control_ttl_;
00972
00973 return send_bundle(spec, payload);
00974 }
00975
00976
00977