TclRegistration.cc

Go to the documentation of this file.
00001 /*
00002  * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
00003  * downloading, copying, installing or using the software you agree to
00004  * this license. If you do not agree to this license, do not download,
00005  * install, copy or use the software.
00006  * 
00007  * Intel Open Source License 
00008  * 
00009  * Copyright (c) 2004 Intel Corporation. All rights reserved. 
00010  * 
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions are
00013  * met:
00014  * 
00015  *   Redistributions of source code must retain the above copyright
00016  *   notice, this list of conditions and the following disclaimer.
00017  * 
00018  *   Redistributions in binary form must reproduce the above copyright
00019  *   notice, this list of conditions and the following disclaimer in the
00020  *   documentation and/or other materials provided with the distribution.
00021  * 
00022  *   Neither the name of the Intel Corporation nor the names of its
00023  *   contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *  
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00029  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
00030  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00031  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00032  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00033  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00034  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00035  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00036  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037  */
00038 
00039 #include <oasys/serialize/TclListSerialize.h>
00040 #include <oasys/util/ScratchBuffer.h>
00041 
00042 #include "TclRegistration.h"
00043 #include "bundling/BundleEvent.h"
00044 #include "bundling/BundleDaemon.h"
00045 #include "bundling/BundleList.h"
00046 #include "bundling/BundleStatusReport.h"
00047 #include "bundling/CustodySignal.h"
00048 #include "storage/GlobalStore.h"
00049 
00050 namespace dtn {
00051 
00052 TclRegistration::TclRegistration(const EndpointIDPattern& endpoint,
00053                                  Tcl_Interp* interp)
00054     
00055     : Registration(GlobalStore::instance()->next_regid(),
00056                    endpoint, Registration::DEFER, 0) // XXX/demmer expiration??
00057 {
00058     logpathf("/dtn/registration/tcl/%d", regid_);
00059     set_active(true);
00060 
00061     log_info("new tcl registration on endpoint %s", endpoint.c_str());
00062 
00063     bundle_list_ = new BlockingBundleList(logpath_);
00064     int fd = bundle_list_->notifier()->read_fd();
00065     notifier_channel_ = Tcl_MakeFileChannel((ClientData)fd, TCL_READABLE);
00066 
00067     if (notifier_channel_ == NULL) {
00068         log_err("can't create tcl file channel: %s",
00069                 strerror(Tcl_GetErrno()));
00070     } else {
00071         log_debug("notifier_channel_ is %p", notifier_channel_);
00072         Tcl_RegisterChannel(interp, notifier_channel_);
00073     }
00074 }
00075 
00076 void
00077 TclRegistration::deliver_bundle(Bundle* bundle)
00078 {
00079     bundle_list_->push_back(bundle);
00080 }
00081 
00082 int
00083 TclRegistration::exec(int argc, const char** argv, Tcl_Interp* interp)
00084 {
00085     oasys::TclCommandInterp* cmdinterp = oasys::TclCommandInterp::instance();
00086     if (argc < 1) {
00087         cmdinterp->wrong_num_args(argc, argv, 0, 1, INT_MAX);
00088         return TCL_ERROR;
00089     }
00090     const char* op = argv[0];
00091 
00092     if (strcmp(op, "get_list_channel") == 0)
00093     {
00094         return get_list_channel(interp);
00095     }
00096     else if (strcmp(op, "get_bundle_data") == 0)
00097     {
00098         return get_bundle_data(interp);
00099     }
00100     else
00101     {
00102         cmdinterp->resultf("invalid operation '%s'", op);
00103         return TCL_ERROR;
00104     }
00105 }
00106 
00107 int
00108 TclRegistration::get_list_channel(Tcl_Interp* interp)
00109 {
00110     (void)interp;
00111     oasys::TclCommandInterp* cmdinterp = oasys::TclCommandInterp::instance();
00112     cmdinterp->set_result(Tcl_GetChannelName(notifier_channel_));
00113     return TCL_OK;
00114 }
00115 
00116 
00117 int
00118 TclRegistration::get_bundle_data(Tcl_Interp* interp)
00119 {
00120     oasys::TclCommandInterp* cmdinterp = oasys::TclCommandInterp::instance();
00121     BundleRef b("TclRegistration::get_bundle_data temporary");
00122     b = bundle_list_->pop_front();
00123     if (b == NULL) {
00124         cmdinterp->set_objresult(Tcl_NewListObj(0, 0));
00125         return TCL_OK; // empty list
00126     }
00127 
00128     Tcl_Obj* result;
00129     int ok = parse_bundle_data(interp, b, &result);
00130     cmdinterp->set_objresult(result);
00131 
00132     if (ok != TCL_OK) {
00133         return ok;
00134     }
00135     
00136     BundleDaemon::post(new BundleDeliveredEvent(b.object(), this));
00137     return TCL_OK;
00138     
00139 }
00140 
00183 int
00184 TclRegistration::parse_bundle_data(Tcl_Interp* interp,
00185                                    const BundleRef& b,
00186                                    Tcl_Obj** result)
00187 {
00188     // Using the tcl based serializer, grab all the serialized
00189     // metadata fields into a new list object
00190     Tcl_Obj* objv = Tcl_NewListObj(0, 0);
00191     oasys::TclListSerialize s(interp, objv,
00192                               oasys::Serialize::CONTEXT_LOCAL,
00193                               0);
00194     b->serialize(&s);
00195 
00196     // read in all the payload data (XXX/demmer this will not be nice
00197     // for big bundles)
00198     size_t payload_len = b->payload_.length();
00199     oasys::ScratchBuffer<u_char*> payload_buf;
00200     const u_char* payload_data = (const u_char*)"";
00201     if (payload_len != 0) {
00202         payload_data = b->payload_.read_data(0, payload_len, 
00203                                              payload_buf.buf(payload_len));
00204     }
00205 
00206     char tmp_buf[128];              // used for sprintf strings
00207 
00208 #define addElement(e)                                                      \
00209     if (Tcl_ListObjAppendElement(interp, objv, (e)) != TCL_OK) {           \
00210         *result = Tcl_NewStringObj("Tcl_ListObjAppendElement failed", -1); \
00211         return TCL_ERROR;                                                  \
00212     }
00213     
00214     // stick in the payload
00215     addElement(Tcl_NewStringObj("payload_len", -1));
00216     addElement(Tcl_NewIntObj(payload_len));
00217     
00218     addElement(Tcl_NewStringObj("payload_data", -1));
00219     addElement(Tcl_NewByteArrayObj(const_cast<u_char*>(payload_data), 
00220                                    payload_len));
00221 
00222     // and a pretty formatted creation timestamp
00223     addElement(Tcl_NewStringObj("creation_ts", -1));
00224     sprintf(tmp_buf, "%d.%d", b->creation_ts_.seconds_, b->creation_ts_.seqno_);
00225     addElement(Tcl_NewStringObj(tmp_buf, -1));
00226 
00227     // If we're not an admin bundle, we're done
00228     if (!b->is_admin_) {
00229         goto done;
00230     }
00231 
00232     // Admin Type:
00233     addElement(Tcl_NewStringObj("admin_type", -1));
00234     BundleProtocol::admin_record_type_t admin_type;
00235     if (!BundleProtocol::get_admin_type(b.object(), &admin_type)) {
00236         goto done;
00237     }
00238 
00239     // Now for each type of admin bundle, first append the string to
00240     // define that type, then all the relevant fields of the type
00241     switch (admin_type) {
00242     case BundleProtocol::ADMIN_STATUS_REPORT:
00243     {
00244         addElement(Tcl_NewStringObj("Status Report", -1));
00245 
00246         BundleStatusReport::data_t sr;
00247         if (!BundleStatusReport::parse_status_report(&sr, payload_data,
00248                                                      payload_len)) {
00249             *result =
00250                 Tcl_NewStringObj("Admin Bundle Status Report parsing failed", -1);
00251             return TCL_ERROR;
00252         }
00253 
00254         // Fragment fields
00255         if (sr.admin_flags_ & BundleProtocol::ADMIN_IS_FRAGMENT) {
00256             addElement(Tcl_NewStringObj("orig_frag_offset", -1));
00257             addElement(Tcl_NewLongObj(sr.orig_frag_offset_));
00258             addElement(Tcl_NewStringObj("orig_frag_length", -1));
00259             addElement(Tcl_NewLongObj(sr.orig_frag_length_));
00260         }
00261 
00262         // Status fields with timestamps:
00263 #define APPEND_TIMESTAMP(_flag, _what, _field)                          \
00264         if (sr.status_flags_ & BundleProtocol::_flag) {                 \
00265             addElement(Tcl_NewStringObj(_what, -1));                    \
00266             sprintf(tmp_buf, "%u.%u",                                   \
00267                     sr._field.seconds_, sr._field.seqno_);              \
00268             addElement(Tcl_NewStringObj(tmp_buf, -1));                  \
00269         }
00270 
00271         APPEND_TIMESTAMP(STATUS_RECEIVED,
00272                          "sr_received_time", receipt_tv_);
00273         APPEND_TIMESTAMP(STATUS_CUSTODY_ACCEPTED,
00274                          "sr_custody_time",      custody_tv_);
00275         APPEND_TIMESTAMP(STATUS_FORWARDED,
00276                          "sr_forwarded_time",    forwarding_tv_);
00277         APPEND_TIMESTAMP(STATUS_DELIVERED,
00278                          "sr_delivered_time",    delivery_tv_);
00279         APPEND_TIMESTAMP(STATUS_DELETED,
00280                          "sr_deleted_time",      deletion_tv_);
00281         APPEND_TIMESTAMP(STATUS_ACKED_BY_APP,
00282                          "sr_acked_by_app_time", acknowledgement_tv_);
00283 #undef APPEND_TIMESTAMP
00284         
00285         // Reason Code:
00286         addElement(Tcl_NewStringObj("sr_reason", -1));
00287         switch (sr.reason_code_) {
00288         case BundleProtocol::REASON_NO_ADDTL_INFO:
00289             addElement(Tcl_NewStringObj("No additional information.", -1));
00290             break;
00291             
00292         case BundleProtocol::REASON_LIFETIME_EXPIRED:
00293             addElement(Tcl_NewStringObj("Lifetime expired.", -1));
00294             break;
00295             
00296         case BundleProtocol::REASON_FORWARDED_UNIDIR_LINK:
00297             addElement(Tcl_NewStringObj("Forwarded Over Unidirectional Link.", -1));
00298             break;
00299                         
00300         case BundleProtocol::REASON_TRANSMISSION_CANCELLED:
00301             addElement(Tcl_NewStringObj("Transmission cancelled.", -1));
00302             break;
00303             
00304         case BundleProtocol::REASON_DEPLETED_STORAGE:
00305             addElement(Tcl_NewStringObj("Depleted storage.", -1));
00306             break;
00307             
00308         case BundleProtocol::REASON_ENDPOINT_ID_UNINTELLIGIBLE:
00309             addElement(
00310                 Tcl_NewStringObj("Destination endpoint ID unintelligible.", -1));
00311             break;
00312             
00313         case BundleProtocol::REASON_NO_ROUTE_TO_DEST:
00314             addElement(
00315                 Tcl_NewStringObj("No known route to destination from here.", -1));
00316             break;
00317             
00318         case BundleProtocol::REASON_NO_TIMELY_CONTACT:
00319             addElement(
00320                 Tcl_NewStringObj("No timely contact with next node on route.", -1));
00321             break;
00322             
00323         case BundleProtocol::REASON_BLOCK_UNINTELLIGIBLE:
00324             addElement(
00325                 Tcl_NewStringObj("Block unintelligible.", -1));
00326             break;
00327             
00328         default:
00329             sprintf(tmp_buf, "Error: Unknown Status Report Reason Code 0x%x",
00330                     sr.reason_code_);
00331             addElement(Tcl_NewStringObj(tmp_buf, -1));
00332             break;
00333         }
00334 
00335         // Bundle creation timestamp
00336         addElement(Tcl_NewStringObj("orig_creation_ts", -1));
00337         sprintf(tmp_buf, "%u.%u",
00338                 sr.orig_creation_tv_.seconds_,
00339                 sr.orig_creation_tv_.seqno_);
00340         addElement(Tcl_NewStringObj(tmp_buf, -1));
00341 
00342         // Status Report's Source EID:
00343         addElement(Tcl_NewStringObj("orig_source", -1));
00344         addElement(Tcl_NewStringObj(sr.orig_source_eid_.data(),
00345                                     sr.orig_source_eid_.length()));
00346         break;
00347     }
00348 
00349     //-------------------------------------------
00350 
00351     case BundleProtocol::ADMIN_CUSTODY_SIGNAL:
00352     {
00353         addElement(Tcl_NewStringObj("Custody Signal", -1));
00354 
00355         CustodySignal::data_t cs;
00356         if (!CustodySignal::parse_custody_signal(&cs, payload_data,
00357                                                  payload_len))
00358         {
00359             *result = Tcl_NewStringObj("Admin Custody Signal parsing failed", -1);
00360             return TCL_ERROR;
00361         }
00362 
00363         // Fragment fields
00364         if (cs.admin_flags_ & BundleProtocol::ADMIN_IS_FRAGMENT) {
00365             addElement(Tcl_NewStringObj("orig_frag_offset", -1));
00366             addElement(Tcl_NewLongObj(cs.orig_frag_offset_));
00367             addElement(Tcl_NewStringObj("orig_frag_length", -1));
00368             addElement(Tcl_NewLongObj(cs.orig_frag_length_));
00369         }
00370         
00371         addElement(Tcl_NewStringObj("custody_succeeded", -1));
00372         addElement(Tcl_NewBooleanObj(cs.succeeded_));
00373 
00374         addElement(Tcl_NewStringObj("custody_reason", -1));
00375         switch(cs.reason_) {
00376         case BundleProtocol::CUSTODY_NO_ADDTL_INFO:
00377             addElement(Tcl_NewStringObj("No additional information.", -1));
00378             break;
00379             
00380         case BundleProtocol::CUSTODY_REDUNDANT_RECEPTION:
00381             addElement(Tcl_NewStringObj("Redundant bundle reception.", -1));
00382             break;
00383             
00384         case BundleProtocol::CUSTODY_DEPLETED_STORAGE:
00385             addElement(Tcl_NewStringObj("Depleted Storage.", -1));
00386             break;
00387             
00388         case BundleProtocol::CUSTODY_ENDPOINT_ID_UNINTELLIGIBLE:
00389             addElement(Tcl_NewStringObj("Destination endpoint ID unintelligible.", -1));
00390             break;
00391             
00392         case BundleProtocol::CUSTODY_NO_ROUTE_TO_DEST:
00393             addElement(Tcl_NewStringObj("No known route to destination from here", -1));
00394             break;
00395             
00396         case BundleProtocol::CUSTODY_NO_TIMELY_CONTACT:
00397             addElement(Tcl_NewStringObj("No timely contact with next node en route.", -1));
00398             break;
00399             
00400         case BundleProtocol::CUSTODY_BLOCK_UNINTELLIGIBLE:
00401             addElement(Tcl_NewStringObj("Block unintelligible.", -1));
00402             break;
00403             
00404         default:
00405             sprintf(tmp_buf, "Error: Unknown Custody Signal Reason Code 0x%x",
00406                     cs.reason_);
00407             addElement(Tcl_NewStringObj(tmp_buf, -1));
00408             break;
00409         }
00410 
00411         // Custody signal timestamp
00412         addElement(Tcl_NewStringObj("custody_signal_time", -1));
00413         sprintf(tmp_buf, "%u.%u",
00414                 cs.custody_signal_tv_.seconds_,
00415                 cs.custody_signal_tv_.seqno_);
00416         addElement(Tcl_NewStringObj(tmp_buf, -1));
00417         
00418         // Bundle creation timestamp
00419         addElement(Tcl_NewStringObj("orig_creation_ts", -1));
00420         sprintf(tmp_buf, "%u.%u",
00421                 cs.orig_creation_tv_.seconds_,
00422                 cs.orig_creation_tv_.seqno_);
00423         addElement(Tcl_NewStringObj(tmp_buf, -1));
00424 
00425         // Original source eid
00426         addElement(Tcl_NewStringObj("orig_source", -1));
00427         addElement(Tcl_NewStringObj(cs.orig_source_eid_.data(),
00428                                     cs.orig_source_eid_.length()));
00429         break;
00430     }
00431 
00432     //-------------------------------------------
00433 
00434     case BundleProtocol::ADMIN_ECHO:
00435     {
00436         addElement(Tcl_NewStringObj("Admin Echo Signal", -1));
00437         break;
00438     }
00439     
00440     //-------------------------------------------
00441 
00442     case BundleProtocol::ADMIN_NULL:
00443     {
00444         addElement(Tcl_NewStringObj("Admin Null Signal", -1));
00445         break;
00446     }
00447     
00448     default:
00449         sprintf(tmp_buf,
00450                 "Error: Unknown Status Report Type 0x%x", admin_type);
00451         addElement(Tcl_NewStringObj(tmp_buf, -1));
00452         break;
00453     }
00454 
00455     // all done
00456  done:
00457     *result = objv;
00458     return TCL_OK;
00459 }
00460 
00461 } // namespace dtn

Generated on Fri Dec 22 14:48:01 2006 for DTN Reference Implementation by  doxygen 1.5.1