# Interaction.cc

Go to the documentation of this file.

    00001 // ----------------------------------------------------------------------------
    00002 // CERTI - HLA RunTime Infrastructure
    00003 // Copyright (C) 2002-2005  ONERA
    00004 //
    00005 // This file is part of CERTI-libCERTI
    00006 //
    00007 // CERTI-libCERTI is free software ; you can redistribute it and/or
    00008 // modify it under the terms of the GNU Lesser General Public License
    00009 // as published by the Free Software Foundation ; either version 2 of
    00010 // the License, or (at your option) any later version.
    00011 //
    00012 // CERTI-libCERTI is distributed in the hope that it will be useful, but
    00013 // WITHOUT ANY WARRANTY ; without even the implied warranty of
    00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    00015 // Lesser General Public License for more details.
    00016 //
    00017 // You should have received a copy of the GNU Lesser General Public
    00018 // License along with this program ; if not, write to the Free Software
    00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
    00020 // USA
    00021 //
    00022 // $Id: Interaction.cc,v 3.51 2008/11/09 12:41:40 gotthardp Exp $
    00023 // ----------------------------------------------------------------------------
    00024
    00025
    00026
    00027 #include "Interaction.hh"
    00028 #include "InteractionSet.hh"
    00029 #include "InteractionBroadcastList.hh"
    00030 #include "PrettyDebug.hh"
    00031 #include "NM_Classes.hh"
    00032
    00033 #include <iostream>
    00034 #include <sstream>
    00035 #include <assert.h>
    00036
    00037 using std::cout ;
    00038 using std::endl ;
    00039 using std::list ;
    00040
    00041 namespace certi {
    00042
    00043 static pdCDebug D("INTERACTION", "(Interact) - ");
    00044 static PrettyDebug G("GENDOC",__FILE__) ;
    00045
    00046 Interaction::Interaction(const std::string& theName, InteractionClassHandle theHandle, TransportType theTransport, OrderType theOrder)
    00047 : parent(0), depth(0), transport(theTransport), order(theOrder), handle(theHandle),
    00048 id(PublicLevelID)
    00049 {
    00050     setName(theName);
    00051     /*
    00052      * The set of interaction subclass has no security server
    00053      */
    00054     subClasses = new InteractionSet(NULL);
    00055 } /* end of Interaction constructor */
    00056
    00057 Interaction::~Interaction()
    00058 {
    00059     while (!parameterSet.empty()) {
    00060         delete parameterSet.front();
    00061         parameterSet.pop_front();
    00062     }
    00063
    00064     if (!publishers.empty())
    00065         D.Out(pdError, "Interaction %d: publishers list not empty at termination.", handle);
    00066
    00067     // Deleting subclasses
    00068     if (NULL!=subClasses) {
    00069         delete subClasses;
    00070     }
    00071 } /* end of ~Interaction */
    00072
    00073 void Interaction::addSubClass(Interaction *child) {
    00074     /* build parent-child relationship */
    00075     /* add child as subclass of parent */
    00076     subClasses->addClass(child,NULL);
    00077     /* link child to parent */
    00078     child->superClass = handle;
    00079     /* forward inherited properties to child */
    00080     /* Add Interaction Class Parameter */
    00081     addInheritedClassParameter(child);
    00082     /* security server is the same for child */
    00083     child->server = server;
    00084     /* inherit security Level */
    00085     child->setSecurityLevelId(id);
    00086 } /* end of addChild */
    00087
    00088 // ----------------------------------------------------------------------------
    00090 ParameterHandle
    00091 Interaction::addParameter(Parameter *the_parameter, bool is_inherited)
    00092 {
    00093     // FIXME: the parameter handle has already been set
    00094     // in fed.cc::addParameter() why should it be set again
    00095     // here
    00096     //the_parameter->setHandle(parameterSet.size() + 1);
    00097
    00098     // An inherited parameter keeps its security level, any other get the
    00099     // default security level of the class.
    00100     if (!is_inherited)
    00101         the_parameter->LevelID = id ;
    00102
    00103     parameterSet.push_front(the_parameter);
    00104
    00105     D[pdRegister] << "Interaction " << handle << "[" << name.c_str()
    00106     << "] has a new parameter "
    00107     << the_parameter->getHandle() << "[" << the_parameter->getName().c_str() << "]"
    00108     << std::flush;
    00109
    00110     return the_parameter->getHandle();
    00111 } /* end of addParameter */
    00112
    00113 void
    00114 Interaction::addInheritedClassParameter(Interaction *the_child)
    00115 {
    00116     // The Parameter List is read backward to respect the same attribute order
    00117     // for the child (Parameters are inserted at the beginning of the list)
    00118     Parameter *child = NULL ;
    00119     list<Parameter *>::reverse_iterator it ;
    00120     for (it = parameterSet.rbegin(); it != parameterSet.rend(); it++) {
    00121         assert((*it) != NULL);
    00122
    00123         child = new Parameter(**it);
    00124         assert(child != NULL);
    00125
    00126         D.Out(pdProtocol,
    00127                 "ObjectClass %u adding new parameter %d to child class %u.",
    00128                 handle, (*it)->getHandle(), the_child->handle);
    00129
    00130         the_child->addParameter(child, true);
    00131
    00132         /* FIXME EN: what is the purpose of the check ?? */
    00133         if (child->getHandle() != (*it)->getHandle()) {
    00134             throw RTIinternalError("Error while copying child's attributes.");
    00135         } else {
    00136             ;
    00137         }
    00138     }
    00139 } /* end of addInheritedClassParameter */
    00140
    00141 // ----------------------------------------------------------------------------
    00147 void
    00148 Interaction::broadcastInteractionMessage(InteractionBroadcastList *ibList,
    00149         const RTIRegion *region)
    00150 {
    00151
    00152     G.Out(pdGendoc,"enter Interaction::broadcastInteractionMessage");
    00153
    00154     // 1. Set InteractionHandle to local class Handle.
    00155     ibList->message->interactionClass = handle ;
    00156
    00157     // 2. Update message Parameters list by removing child's Parameters.
    00158     for (int i = 0 ; i < ibList->message->handleArraySize ;) {
    00159         // If the Parameter is not in that class, remove it from the message.
    00160         try {
    00161             getParameterByHandle(ibList->message->handleArray[i]);
    00162             i++ ;
    00163         }
    00164         catch (InteractionParameterNotDefined) {
    00165             ibList->message->removeParameter(i);
    00166         }
    00167     }
    00168
    00169     // 3. Add Interaction subscribers to the list.
    00170     addFederatesIfOverlap(*ibList, region);
    00171
    00172     // 4. Send pending messages.
    00173     D.Out(pdDebug, "Calling SendPendingMessage...");
    00174     ibList->sendPendingMessage(server);
    00175
    00176     G.Out(pdGendoc,"exit Interaction::broadcastInteractionMessage");
    00177
    00178 }
    00179
    00180 // ----------------------------------------------------------------------------
    00182 void
    00183 Interaction::changeTransportationType(TransportType new_type,
    00184         FederateHandle the_handle)
    00185 throw (FederateNotPublishing,
    00186         InvalidTransportationHandle,
    00187         RTIinternalError)
    00188         {
    00189     if (!isPublishing(the_handle))
    00190         throw FederateNotPublishing("Change Interaction Transport Type.");
    00191
    00192     if ((new_type != RELIABLE) && (new_type != BEST_EFFORT))
    00193         throw InvalidTransportationHandle("");
    00194
    00195     transport = new_type ;
    00196
    00197     D.Out(pdInit,
    00198             "Interaction %d: New Transport type is %d.", handle, transport);
    00199         } /* end of changeTransportationType */
    00200
    00201 // ----------------------------------------------------------------------------
    00203 void
    00204 Interaction::changeOrderType(OrderType new_order, FederateHandle the_handle)
    00205 throw (FederateNotPublishing,
    00206         InvalidOrderingHandle,
    00207         RTIinternalError)
    00208         {
    00209     if (!isPublishing(the_handle))
    00210         throw FederateNotPublishing("Change Interaction Order Type.");
    00211
    00212     if ((new_order != RECEIVE) && (new_order != TIMESTAMP))
    00213         throw InvalidOrderingHandle("");
    00214
    00215     D.Out(pdInit, "Interaction %d: New Order type is %d.", handle, order);
    00216         }
    00217
    00218 // ----------------------------------------------------------------------------
    00222 void
    00223 Interaction::checkFederateAccess(FederateHandle the_federate,
    00224         const char *reason) const
    00225         throw (SecurityError)
    00226         {
    00227     // BUG: Should at least but a line in Audit
    00228     if (server == NULL)
    00229         return ;
    00230
    00231     bool result = server->canFederateAccessData(the_federate, id);
    00232
    00233     // BUG: Should use Audit.
    00234     if (!result) {
    00235         cout << "Interaction " << handle << " : SecurityError for federate "
    00236         << the_federate << '(' << reason << ")." << endl ;
    00237         throw SecurityError("Federate should not access Interaction.");
    00238     }
    00239         }
    00240
    00241 // ----------------------------------------------------------------------------
    00243 void
    00244 Interaction::deletePublisher(FederateHandle fed)
    00245 {
    00246     PublishersList::iterator it = publishers.find(fed);
    00247     if (it != publishers.end())
    00248         publishers.erase(it);
    00249 }
    00250
    00251 // ----------------------------------------------------------------------------
    00253 void
    00254 Interaction::display() const
    00255 {
    00256     cout << " Interaction " << handle << " \"" << name << "\" :" << endl ;
    00257
    00258     // Display inheritance
    00259     cout << " Parent Class Handle: " << parent << endl ;
    00260     cout << " Security Level: " << id << endl ;
    00261     cout << " " << subClasses->size() << " Child(s):" << endl ;
    00262
    00263     //    list<InteractionClassHandle>::const_iterator c = children.begin();
    00264     //    for (int i = 1 ; c != children.end(); i++, c++) {
    00265     //        cout << " child " << i << " Handle: " << (*c) << endl ;
    00266     //    }
    00267
    00268     // Display parameters
    00269
    00270     cout << " " << parameterSet.size() << " Parameters:" << endl ;
    00271
    00272     list<Parameter *>::const_iterator p = parameterSet.begin();
    00273     for (; p != parameterSet.end(); p++) {
    00274         (*p)->display();
    00275     }
    00276 }
    00277
    00278 // ----------------------------------------------------------------------------
    00280 Parameter*
    00281 Interaction::getParameterByHandle(ParameterHandle the_handle) const
    00282 throw (InteractionParameterNotDefined, RTIinternalError)
    00283 {
    00284     list<Parameter *>::const_iterator p ;
    00285     for (p = parameterSet.begin(); p != parameterSet.end(); p++) {
    00286         if ((*p)->getHandle() == the_handle)
    00287             return (*p);
    00288     }
    00289
    00290     throw InteractionParameterNotDefined("");
    00291 }
    00292
    00293 // ----------------------------------------------------------------------------
    00295 ParameterHandle
    00296 Interaction::getParameterHandle(const char *the_name) const
    00297 throw (NameNotFound, RTIinternalError)
    00298 {
    00299     list<Parameter *>::const_iterator p ;
    00300     for (p = parameterSet.begin(); p != parameterSet.end(); p++) {
    00301         if ((*p)->getName() == the_name)
    00302             return (*p)->getHandle();
    00303     }
    00304
    00305     throw NameNotFound("");
    00306 }
    00307
    00308 // ----------------------------------------------------------------------------
    00309
    00310 const std::string&
    00311 Interaction::getParameterName(ParameterHandle the_handle) const
    00312 throw (InteractionParameterNotDefined,
    00313         RTIinternalError)
    00314         {
    00315     return getParameterByHandle(the_handle)->getName();
    00316         }
    00317
    00318 // ----------------------------------------------------------------------------
    00320 bool
    00321 Interaction::isPublishing(FederateHandle fed)
    00322 {
    00323     return publishers.find(fed) != publishers.end();
    00324 }
    00325
    00326 // ----------------------------------------------------------------------------
    00330 void
    00331 Interaction::isReady(FederateHandle federate_handle,
    00332         std::vector <ParameterHandle> &parameter_list,
    00333         UShort list_size)
    00334 throw (FederateNotPublishing,
    00335         InteractionParameterNotDefined,
    00336         RTIinternalError)
    00337         {
    00338     // Is Federate Publishing Interaction?
    00339     if (!isPublishing(federate_handle))
    00340         throw FederateNotPublishing("");
    00341
    00342     // Are Parameters Defined?
    00343     for (UShort i = 0 ; i < list_size ; i++)
    00344         getParameterByHandle(parameter_list[i]);
    00345         }
    00346
    00347 // ----------------------------------------------------------------------------
    00349 void
    00350 Interaction::killFederate(FederateHandle the_federate)
    00351 throw ()
    00352 {
    00353     try {
    00354         // Is federate publishing something ? (not important)
    00355         if (isPublishing(the_federate))
    00356             unpublish(the_federate);
    00357
    00358         // Does federate subscribed to something ?
    00359         if (isSubscribed(the_federate))
    00360             unsubscribe(the_federate);
    00361     }
    00362     catch (SecurityError &e) {}
    00363 }
    00364
    00365 // ----------------------------------------------------------------------------
    00367 void
    00368 Interaction::publish(FederateHandle the_handle)
    00369 throw (FederateNotPublishing, RTIinternalError, SecurityError)
    00370 {
    00371     checkFederateAccess(the_handle, (char *) "Publish");
    00372
    00373     if (!isPublishing(the_handle)) {
    00374         D.Out(pdInit, "Interaction %d: Added Federate %d to publishers list.", handle, the_handle);
    00375         publishers.insert(the_handle);
    00376     }
    00377     else
    00378         D.Out(pdError, "Interaction %d: Inconsistent publish request from Federate %d.", handle, the_handle);
    00379 }
    00380
    00381 // ----------------------------------------------------------------------------
    00383 void
    00384 Interaction::unpublish(FederateHandle the_handle)
    00385 throw (FederateNotPublishing, RTIinternalError, SecurityError)
    00386 {
    00387     if (isPublishing(the_handle)) {
    00388         D.Out(pdTerm,
    00389                 "Interaction %d: Removed Federate %d from publishers list.",
    00390                 handle, the_handle);
    00391         deletePublisher(the_handle);
    00392     }
    00393     else {
    00394         throw FederateNotPublishing("");
    00395     }
    00396 }
    00397
    00398 // ----------------------------------------------------------------------------
    00403 InteractionBroadcastList *
    00404 Interaction::sendInteraction(FederateHandle federate_handle,
    00405         std::vector <ParameterHandle> &parameter_list,
    00406         std::vector <ParameterValue_t> &value_list,
    00407         UShort list_size,
    00408         FederationTime time,
    00409         const RTIRegion *region,
    00410         const char *the_tag)
    00411 throw (FederateNotPublishing,
    00412         InteractionClassNotDefined,
    00413         InteractionParameterNotDefined,
    00414         RTIinternalError)
    00415         {
    00416
    00417     G.Out(pdGendoc,"enter Interaction::sendInteraction with time");
    00418
    00419     // Pre-conditions checking
    00420     if (!isPublishing(federate_handle))
    00421         throw FederateNotPublishing("");
    00422
    00423     // Prepare and Broadcast message for this class
    00424     InteractionBroadcastList *ibList = NULL ;
    00425     if (server != NULL) {
    00426         NetworkMessage *answer = NM_Factory::create(NetworkMessage::RECEIVE_INTERACTION) ;
    00427         answer->exception = e_NO_EXCEPTION ;
    00428         answer->federation = server->federation();
    00429         answer->federate = federate_handle ;
    00430         answer->interactionClass = handle ; // Interaction Class Handle
    00431         answer->setDate(time);
    00432
    00433         answer->setLabel(the_tag);
    00434
    00435         answer->handleArraySize = list_size ;
    00436         answer->handleArray.resize(list_size) ;
    00437         answer->sizeValueArray(list_size);
    00438         for (int i = 0 ; i < list_size ; i++) {
    00439             answer->handleArray[i] = parameter_list[i] ;
    00440             answer->valueArray[i] = value_list[i];
    00441         }
    00442
    00443         D.Out(pdProtocol, "Preparing broadcast list.");
    00444         ibList = new InteractionBroadcastList(answer);
    00445
    00446         broadcastInteractionMessage(ibList, region);
    00447     }
    00448     else
    00449         // SendInteraction should not be called on the RTIA.
    00450         throw RTIinternalError("SendInteraction called by RTIA.");
    00451
    00452     G.Out(pdGendoc,"exit Interaction::sendInteraction with time");
    00453
    00454     // Return the BroadcastList in case it had to be passed to the
    00455     // parent class.
    00456     return ibList ;
    00457         }
    00458
    00459 // ----------------------------------------------------------------------------
    00464 InteractionBroadcastList *
    00465 Interaction::sendInteraction(FederateHandle federate_handle,
    00466         std::vector <ParameterHandle> &parameter_list,
    00467         std::vector <ParameterValue_t> &value_list,
    00468         UShort list_size,
    00469         const RTIRegion *region,
    00470         const char *the_tag)
    00471 throw (FederateNotPublishing,
    00472         InteractionClassNotDefined,
    00473         InteractionParameterNotDefined,
    00474         RTIinternalError)
    00475         {
    00476
    00477     G.Out(pdGendoc,"enter Interaction::sendInteraction without time");
    00478
    00479     // Pre-conditions checking
    00480     if (!isPublishing(federate_handle))
    00481         throw FederateNotPublishing("");
    00482
    00483     // Prepare and Broadcast message for this class
    00484     InteractionBroadcastList *ibList = NULL ;
    00485     if (server != NULL) {
    00486         NetworkMessage *answer = NM_Factory::create(NetworkMessage::RECEIVE_INTERACTION) ;
    00487         answer->exception = e_NO_EXCEPTION ;
    00488         answer->federation = server->federation();
    00489         answer->federate = federate_handle ;
    00490         answer->interactionClass = handle ; // Interaction Class Handle
    00491         answer->setLabel(the_tag);
    00492
    00493         answer->handleArraySize = list_size ;
    00494         answer->handleArray.resize(list_size) ;
    00495         answer->sizeValueArray(list_size);
    00496
    00497         for (int i = 0 ; i < list_size ; i++) {
    00498             answer->handleArray[i] = parameter_list[i] ;
    00499             answer->valueArray[i] = value_list[i];
    00500         }
    00501
    00502         D.Out(pdProtocol, "Preparing broadcast list.");
    00503         ibList = new InteractionBroadcastList(answer);
    00504
    00505         broadcastInteractionMessage(ibList, region);
    00506     }
    00507     else
    00508         // SendInteraction should not be called on the RTIA.
    00509         throw RTIinternalError("SendInteraction called by RTIA.");
    00510
    00511     G.Out(pdGendoc,"exit Interaction::sendInteraction without time");
    00512
    00513     // Return the BroadcastList in case it had to be passed to the
    00514     // parent class.
    00515     return ibList ;
    00516         }
    00517
    00518
    00519 // ----------------------------------------------------------------------------
    00521
    00523 void
    00524 Interaction::setSecurityLevelId(SecurityLevelID new_levelID)
    00525 {
    00526     if (!server->dominates(new_levelID, id))
    00527         throw SecurityError("Attempt to lower interaction class level.");
    00528
    00529     id = new_levelID ;
    00530 }
    00531
    00532 // ----------------------------------------------------------------------------
    00533 // setSpace
    00534 void
    00535 Interaction::setSpace(SpaceHandle h)
    00536 {
    00537     space = h ;
    00538 }
    00539
    00540 // ----------------------------------------------------------------------------
    00541 // getSpace
    00542 SpaceHandle
    00543 Interaction::getSpace()
    00544 {
    00545     return space ;
    00546 }
    00547
    00548 } // namespace certi
    00549
    00550 // $Id: Interaction.cc,v 3.51 2008/11/09 12:41:40 gotthardp Exp $