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