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 $

Generated on Thu Apr 30 15:53:49 2009 for CERTIDeveloperDocumentation by doxygen 1.5.5