| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829 |
- /*******************************************************************************
- * Copyright (c) 2009, Rockwell Automation, Inc.
- * All rights reserved.
- *
- ******************************************************************************/
- #include <string.h>
- #include <stdbool.h>
- #include "cipconnectionmanager.h"
- #include "opener_user_conf.h"
- #include "cipcommon.h"
- #include "cipmessagerouter.h"
- #include "ciperror.h"
- #include "endianconv.h"
- #include "opener_api.h"
- #include "encap.h"
- #include "cipidentity.h"
- #include "trace.h"
- #include "cipconnectionobject.h"
- #include "cipclass3connection.h"
- #include "cipioconnection.h"
- #include "cipassembly.h"
- #include "cpf.h"
- #include "appcontype.h"
- #include "generic_networkhandler.h"
- #include "cipepath.h"
- #include "cipelectronickey.h"
- #include "cipqos.h"
- #include "xorshiftrandom.h"
- const size_t g_kForwardOpenHeaderLength = 36; /**< the length in bytes of the forward open command specific data till the start of the connection path (including con path size)*/
- const size_t g_kLargeForwardOpenHeaderLength = 40; /**< the length in bytes of the large forward open command specific data till the start of the connection path (including con path size)*/
- static const unsigned int g_kNumberOfConnectableObjects = 2 +
- OPENER_CIP_NUM_APPLICATION_SPECIFIC_CONNECTABLE_OBJECTS;
- typedef struct {
- EipUint32 class_id;
- OpenConnectionFunction open_connection_function;
- } ConnectionManagementHandling;
- /* global variables private */
- /** List holding information on the object classes and open/close function
- * pointers to which connections may be established.
- */
- ConnectionManagementHandling g_connection_management_list[2 +
- OPENER_CIP_NUM_APPLICATION_SPECIFIC_CONNECTABLE_OBJECTS
- ] = {{0}};
- /** buffer connection object needed for forward open */
- CipConnectionObject g_dummy_connection_object;
- /** @brief Holds the connection ID's "incarnation ID" in the upper 16 bits */
- EipUint32 g_incarnation_id;
- /* private functions */
- EipStatus ForwardOpen(CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response,
- const struct sockaddr *originator_address,
- const CipSessionHandle encapsulation_session);
- EipStatus LargeForwardOpen(CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response,
- const struct sockaddr *originator_address,
- const CipSessionHandle encapsulation_session);
- EipStatus ForwardClose(CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response,
- const struct sockaddr *originator_address,
- const CipSessionHandle encapsulation_session);
- EipStatus GetConnectionOwner(CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response,
- const struct sockaddr *originator_address,
- const CipSessionHandle encapsulation_session);
- EipStatus GetConnectionData(CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response,
- const struct sockaddr *originator_address,
- const CipUdint encapsulation_session);
- EipStatus SearchConnectionData(CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response,
- const struct sockaddr *originator_address,
- const CipUdint encapsulation_session);
- void AssembleConnectionDataResponseMessage(
- CipMessageRouterResponse *message_router_response,
- CipConnectionObject *connection_object);
- EipStatus AssembleForwardOpenResponse(CipConnectionObject *connection_object,
- CipMessageRouterResponse *message_router_response,
- EipUint8 general_status,
- EipUint16 extended_status);
- EipStatus AssembleForwardCloseResponse(EipUint16 connection_serial_number,
- EipUint16 originatior_vendor_id,
- EipUint32 originator_serial_number,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response,
- EipUint16 extended_error_code);
- /** @brief check if the data given in the connection object match with an already established connection
- *
- * The comparison is done according to the definitions in the CIP specification Section 3-5.5.2:
- * The following elements have to be equal: Vendor ID, Connection Serial Number, Originator Serial Number
- * @param connection_object connection object containing the comparison elements from the forward open request
- * @return
- * - NULL if no equal established connection exists
- * - pointer to the equal connection object
- */
- CipConnectionObject *CheckForExistingConnection(
- const CipConnectionObject *const connection_object);
- /** @brief Compare the electronic key received with a forward open request with the device's data.
- *
- * @param key_format format identifier given in the forward open request
- * @param key_data pointer to the electronic key data received in the forward open request
- * @param extended_status the extended error code in case an error happened
- * @return general status on the establishment
- * - EIP_OK ... on success
- * - On an error the general status code to be put into the response
- */
- EipStatus CheckElectronicKeyData(EipUint8 key_format,
- void *key_data,
- EipUint16 *extended_status);
- /** @brief Parse the connection path of a forward open request
- *
- * This function will take the connection object and the received data stream and parse the connection path.
- * @param connection_object pointer to the connection object structure for which the connection should
- * be established
- * @param message_router_request pointer to the received request structure. The position of the data stream pointer has to be at the connection length entry
- * @param extended_error the extended error code in case an error happened
- * @return general status on the establishment
- * - kEipStatusOk ... on success
- * - On an error the general status code to be put into the response
- */
- EipUint8 ParseConnectionPath(CipConnectionObject *connection_object,
- CipMessageRouterRequest *message_router_request,
- EipUint16 *extended_error);
- ConnectionManagementHandling *GetConnectionManagementEntry(
- const EipUint32 class_id);
- void InitializeConnectionManagerData(void);
- void AddNullAddressItem(
- CipCommonPacketFormatData *common_data_packet_format_data);
- /** @brief gets the padded logical path TODO: enhance documentation
- * @param logical_path_segment TheLogical Path Segment
- *
- * @return The padded logical path
- */
- unsigned int GetPaddedLogicalPath(const EipUint8 **logical_path_segment) {
- unsigned int padded_logical_path = *(*logical_path_segment)++;
- if( (padded_logical_path & 3) == 0 ) {
- padded_logical_path = *(*logical_path_segment)++;
- } else if( (padded_logical_path & 3) == 1 ) {
- (*logical_path_segment)++; /* skip pad */
- padded_logical_path = *(*logical_path_segment)++;
- padded_logical_path |= *(*logical_path_segment)++ << 8;
- } else {
- OPENER_TRACE_ERR("illegal logical path segment\n");
- }
- return padded_logical_path;
- }
- /** @brief Generate a new connection Id utilizing the Incarnation Id as
- * described in the EIP specs.
- *
- * A unique connectionID is formed from the boot-time-specified "incarnation ID"
- * and the per-new-connection connection number. The legacy default is to use
- * the lower 16-bit as a connection counter, incrementing for each connection.
- *
- * Some conformance tests may however fail an adapter due to the connection ID
- * not being random enough. To meet such requirements there is an option to
- * enable fully random connection IDs -- although the upper 16-bits are always
- * derived from the incarnation ID -- i.e., each time OpENer is started the
- * upper 16-bits will remain be the same.
- *
- * @return new 32-bit connection id
- */
- CipUdint GetConnectionId(void) {
- #ifndef OPENER_RANDOMIZE_CONNECTION_ID
- static CipUint connection_id = 18;
- connection_id++;
- #else
- CipUint connection_id = NextXorShiftUint32();
- #endif
- return (g_incarnation_id | (connection_id & 0x0000FFFF) );
- }
- void InitializeConnectionManager(CipClass *class) {
- CipClass *meta_class = class->class_instance.cip_class;
- InsertAttribute( (CipInstance *) class, 1, kCipUint, EncodeCipUint, NULL,
- (void *) &class->revision, kGetableSingleAndAll ); /* revision */
- InsertAttribute( (CipInstance *) class, 2, kCipUint, EncodeCipUint, NULL,
- (void *) &class->number_of_instances, kGetableSingleAndAll ); /* largest instance number */
- InsertAttribute( (CipInstance *) class, 3, kCipUint, EncodeCipUint, NULL,
- (void *) &class->number_of_instances, kGetableSingle ); /* number of instances currently existing*/
- InsertAttribute( (CipInstance *) class, 4, kCipUint, EncodeCipUint, NULL,
- (void *) &kCipUintZero, kNotSetOrGetable ); /* optional attribute list - default = 0 */
- InsertAttribute( (CipInstance *) class, 5, kCipUint, EncodeCipUint, NULL,
- (void *) &kCipUintZero, kNotSetOrGetable ); /* optional service list - default = 0 */
- InsertAttribute( (CipInstance *) class, 6, kCipUint, EncodeCipUint, NULL,
- (void *) &meta_class->highest_attribute_number,
- kGetableSingleAndAll ); /* max class attribute number*/
- InsertAttribute( (CipInstance *) class, 7, kCipUint, EncodeCipUint, NULL,
- (void *) &class->highest_attribute_number,
- kGetableSingleAndAll ); /* max instance attribute number*/
- InsertService(meta_class,
- kGetAttributeAll,
- &GetAttributeAll,
- "GetAttributeAll"); /* bind instance services to the metaclass*/
- InsertService(meta_class,
- kGetAttributeSingle,
- &GetAttributeSingle,
- "GetAttributeSingle");
- }
- EipStatus ConnectionManagerInit(EipUint16 unique_connection_id) {
- InitializeConnectionManagerData();
- CipClass *connection_manager = CreateCipClass(kCipConnectionManagerClassCode, /* class code */
- 0, /* # of class attributes */
- 7, /* # highest class attribute number*/
- 2, /* # of class services */
- 0, /* # of instance attributes */
- 14, /* # highest instance attribute number*/
- 8, /* # of instance services */
- 1, /* # of instances */
- "connection manager", /* class name */
- 1, /* revision */
- &InitializeConnectionManager); /* # function pointer for initialization*/
- if(connection_manager == NULL) {
- return kEipStatusError;
- }
- InsertService(connection_manager,
- kGetAttributeSingle,
- &GetAttributeSingle,
- "GetAttributeSingle");
- InsertService(connection_manager,
- kGetAttributeAll,
- &GetAttributeAll,
- "GetAttributeAll");
- InsertService(connection_manager, kForwardOpen, &ForwardOpen, "ForwardOpen");
- InsertService(connection_manager,
- kLargeForwardOpen,
- &LargeForwardOpen,
- "LargeForwardOpen");
- InsertService(connection_manager, kForwardClose, &ForwardClose,
- "ForwardClose");
- InsertService(connection_manager,
- kGetConnectionOwner,
- &GetConnectionOwner,
- "GetConnectionOwner");
- InsertService(connection_manager,
- kGetConnectionData,
- &GetConnectionData,
- "GetConnectionData");
- InsertService(connection_manager,
- kSearchConnectionData,
- &SearchConnectionData,
- "SearchConnectionData");
- g_incarnation_id = ( (EipUint32) unique_connection_id ) << 16;
- AddConnectableObject(kCipMessageRouterClassCode, EstablishClass3Connection);
- AddConnectableObject(kCipAssemblyClassCode, EstablishIoConnection);
- return kEipStatusOk;
- }
- EipStatus HandleReceivedConnectedData(const EipUint8 *const data,
- int data_length,
- struct sockaddr_in *from_address) {
- if( (CreateCommonPacketFormatStructure(data, data_length,
- &g_common_packet_format_data_item) ) ==
- kEipStatusError ) {
- return kEipStatusError;
- } else {
- /* check if connected address item or sequenced address item received, otherwise it is no connected message and should not be here */
- if( (g_common_packet_format_data_item.address_item.type_id ==
- kCipItemIdConnectionAddress)
- || (g_common_packet_format_data_item.address_item.type_id ==
- kCipItemIdSequencedAddressItem) ) { /* found connected address item or found sequenced address item -> for now the sequence number will be ignored */
- if(g_common_packet_format_data_item.data_item.type_id ==
- kCipItemIdConnectedDataItem) { /* connected data item received */
- CipConnectionObject *connection_object = GetConnectedObject(
- g_common_packet_format_data_item.address_item.data.connection_identifier);
- if(connection_object == NULL) {
- return kEipStatusError;
- }
- /* only handle the data if it is coming from the originator */
- if(connection_object->originator_address.sin_addr.s_addr ==
- from_address->sin_addr.s_addr) {
- ConnectionObjectResetLastPackageInactivityTimerValue(connection_object);
- if(SEQ_GT32(g_common_packet_format_data_item.address_item.data.
- sequence_number,
- connection_object->eip_level_sequence_count_consuming) ||
- !connection_object->eip_first_level_sequence_count_received) {
- /* reset the watchdog timer */
- ConnectionObjectResetInactivityWatchdogTimerValue(connection_object);
- /* only inform assembly object if the sequence counter is greater or equal */
- connection_object->eip_level_sequence_count_consuming =
- g_common_packet_format_data_item.address_item.data.sequence_number;
- connection_object->eip_first_level_sequence_count_received = true;
- if(NULL != connection_object->connection_receive_data_function) {
- return connection_object->connection_receive_data_function(
- connection_object,
- g_common_packet_format_data_item.data_item.data,
- g_common_packet_format_data_item.data_item.length);
- }
- }
- } else {
- OPENER_TRACE_WARN(
- "Connected Message Data Received with wrong address information\n");
- }
- }
- }
- }
- return kEipStatusOk;
- }
- /** @brief Function prototype for all Forward Open handle functions
- *
- */
- typedef EipStatus (*HandleForwardOpenRequestFunction)(CipConnectionObject *
- connection_object,
- CipInstance *instance,
- CipMessageRouterRequest *
- message_router_request,
- CipMessageRouterResponse *
- message_router_response);
- /** @brief Handles a Null Non Matching Forward Open Request
- *
- * Null, Non-Matching - Either ping device, or configure a device’s application,
- * or return General Status kCipErrorConnectionFailure and
- * Extended Status kConnectionManagerExtendedStatusCodeNullForwardOpenNotSupported
- */
- EipStatus HandleNullNonMatchingForwardOpenRequest(
- CipConnectionObject *connection_object,
- CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response);
- EipStatus HandleNullNonMatchingForwardOpenRequest(
- CipConnectionObject *connection_object,
- CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response) {
- /* Suppress unused parameter compiler warning. */
- (void) instance;
- (void) message_router_request;
- (void) message_router_response;
- OPENER_TRACE_INFO("Right now we cannot handle Null requests\n");
- return AssembleForwardOpenResponse(connection_object,
- message_router_response,
- kCipErrorConnectionFailure,
- kConnectionManagerExtendedStatusCodeNullForwardOpenNotSupported);
- }
- /** @brief Handles a Null Matching Forward Open request
- *
- * Either reconfigure a target device’s application, or
- * return General Status kCipErrorConnectionFailure and
- * Extended Status kConnectionManagerExtendedStatusCodeNullForwardOpenNotSupported
- */
- EipStatus HandleNullMatchingForwardOpenRequest(
- CipConnectionObject *connection_object,
- CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response);
- EipStatus HandleNullMatchingForwardOpenRequest(
- CipConnectionObject *connection_object,
- CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response) {
- /* Suppress unused parameter compiler warning. */
- (void) instance;
- (void) message_router_request;
- OPENER_TRACE_INFO("Right now we cannot handle Null requests\n");
- return AssembleForwardOpenResponse(connection_object,
- message_router_response,
- kCipErrorConnectionFailure,
- kConnectionManagerExtendedStatusCodeNullForwardOpenNotSupported);
- }
- /** @brief Handles a Non Null Matching Forward Open Request
- *
- * Non-Null, Matching request - Return General Status = kCipErrorConnectionFailure,
- * Extended Status = kConnectionManagerExtendedStatusCodeErrorConnectionInUseOrDuplicateForwardOpen
- */
- EipStatus HandleNonNullMatchingForwardOpenRequest(
- CipConnectionObject *connection_object,
- CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response);
- EipStatus HandleNonNullMatchingForwardOpenRequest(
- CipConnectionObject *connection_object,
- CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response) {
- /* Suppress unused parameter compiler warning. */
- (void) instance;
- (void) message_router_request;
- OPENER_TRACE_INFO("Right now we cannot handle reconfiguration requests\n");
- return AssembleForwardOpenResponse(connection_object,
- message_router_response,
- kCipErrorConnectionFailure,
- kConnectionManagerExtendedStatusCodeErrorConnectionInUseOrDuplicateForwardOpen);
- }
- /** @brief Handles a Non Null Non Matching Forward Open Request
- *
- * Non-Null, Non-Matching request - Establish a new connection
- */
- EipStatus HandleNonNullNonMatchingForwardOpenRequest(
- CipConnectionObject *connection_object,
- CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response);
- EipStatus HandleNonNullNonMatchingForwardOpenRequest(
- CipConnectionObject *connection_object,
- CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response) {
- /* Suppress unused parameter compiler warning. */
- (void) connection_object;
- (void) instance;
- EipUint16 connection_status = kConnectionManagerExtendedStatusCodeSuccess;
- /*check if the trigger type value is invalid or ok */
- if(kConnectionObjectTransportClassTriggerProductionTriggerInvalid ==
- ConnectionObjectGetTransportClassTriggerProductionTrigger(&
- g_dummy_connection_object) )
- {
- return AssembleForwardOpenResponse(&g_dummy_connection_object,
- message_router_response,
- kCipErrorConnectionFailure,
- kConnectionManagerExtendedStatusCodeErrorTransportClassAndTriggerCombinationNotSupported);
- }
- EipUint32 temp = ParseConnectionPath(&g_dummy_connection_object,
- message_router_request,
- &connection_status);
- if(kEipStatusOk != temp) {
- return AssembleForwardOpenResponse(&g_dummy_connection_object,
- message_router_response,
- temp,
- connection_status);
- }
- /*parsing is now finished all data is available and check now establish the connection */
- ConnectionManagementHandling *connection_management_entry =
- GetConnectionManagementEntry( /* Gets correct open connection function for the targeted object */
- g_dummy_connection_object.configuration_path.class_id);
- if(NULL != connection_management_entry) {
- if (NULL != connection_management_entry->open_connection_function) {
- temp = connection_management_entry->open_connection_function(
- &g_dummy_connection_object, &connection_status);
- } else {
- connection_status = kConnectionManagerExtendedStatusCodeMiscellaneous;
- }
- } else {
- temp = kEipStatusError;
- connection_status =
- kConnectionManagerExtendedStatusCodeInconsistentApplicationPathCombo;
- }
- if(kEipStatusOk != temp) {
- OPENER_TRACE_INFO("connection manager: connect failed\n");
- /* in case of error the dummy objects holds all necessary information */
- return AssembleForwardOpenResponse(&g_dummy_connection_object,
- message_router_response,
- temp,
- connection_status);
- } else {
- OPENER_TRACE_INFO("connection manager: connect succeeded\n");
- /* in case of success the new connection is added at the head of the connection list */
- return AssembleForwardOpenResponse(connection_list.first->data,
- message_router_response,
- kCipErrorSuccess,
- 0);
- }
- }
- /** @brief Array of Forward Open handle function pointers
- *
- * File scope variable
- * The first dimension handles if the request was a non-null request (0) or a null request (1),
- * the second dimension handles if the request was a non-matchin (0) or matching request (1)
- */
- static const HandleForwardOpenRequestFunction
- handle_forward_open_request_functions[2][2] =
- { { HandleNonNullNonMatchingForwardOpenRequest,
- HandleNonNullMatchingForwardOpenRequest },
- { HandleNullNonMatchingForwardOpenRequest,
- HandleNullMatchingForwardOpenRequest } };
- EipStatus ForwardOpenRoutine(CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response,
- const struct sockaddr *originator_address,
- const CipSessionHandle encapsulation_session);
- /** @brief Check if resources for new connection available, generate ForwardOpen Reply message.
- *
- * Large Forward Open service calls Forward Open service
- */
- EipStatus LargeForwardOpen(CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response,
- const struct sockaddr *originator_address,
- const CipSessionHandle encapsulation_session) {
- g_dummy_connection_object.is_large_forward_open = true;
- return ForwardOpenRoutine(instance,
- message_router_request,
- message_router_response,
- originator_address,
- encapsulation_session);
- }
- /** @brief Check if resources for new connection available, generate ForwardOpen Reply message.
- *
- * Forward Open four cases
- * Non-Null/Not matching - open a connection
- * Non-Null/Matching - error
- * Null/Not matching - ping a device/configure
- * Null/Matching - reconfigure
- *
- * Null connection - both O->T and T->O connection parameter field are null
- * Non-Null connection - one or both O->T and T->O connection parameter field are not null
- * Matching - Connection Triad matches an existing connection
- * (Connection Serial Number, Originator Vendor ID and Originator Serial Number)
- *
- * @param instance pointer to CIP object instance
- * @param message_router_request pointer to Message Router Request.
- * @param message_router_response pointer to Message Router Response.
- * @param originator_address address struct of the originator as received
- * @param encapsulation_session associated encapsulation session of the explicit message
- * @return >0 .. success, 0 .. no reply to send back
- * -1 .. error
- */
- EipStatus ForwardOpen(CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response,
- const struct sockaddr *originator_address,
- const CipSessionHandle encapsulation_session) {
- g_dummy_connection_object.is_large_forward_open = false;
- return ForwardOpenRoutine(instance,
- message_router_request,
- message_router_response,
- originator_address,
- encapsulation_session);
- }
- EipStatus ForwardOpenRoutine(CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response,
- const struct sockaddr *originator_address,
- const CipSessionHandle encapsulation_session) {
- (void) instance; /*suppress compiler warning */
- bool is_null_request = false; /* 1 = Null Request, 0 = Non-Null Request */
- bool is_matching_request = false; /* 1 = Matching Request, 0 = Non-Matching Request */
- /*first check if we have already a connection with the given params */
- ConnectionObjectInitializeFromMessage(&(message_router_request->data),
- &g_dummy_connection_object);
- g_dummy_connection_object.associated_encapsulation_session =
- encapsulation_session;
- memcpy(&(g_dummy_connection_object.originator_address),
- originator_address,
- sizeof(g_dummy_connection_object.originator_address) );
- ConnectionObjectConnectionType o_to_t_connection_type =
- ConnectionObjectGetOToTConnectionType(&g_dummy_connection_object);
- ConnectionObjectConnectionType t_to_o_connection_type =
- ConnectionObjectGetTToOConnectionType(&g_dummy_connection_object);
- /* Check if both connection types are valid, otherwise send error response */
- if(kConnectionObjectConnectionTypeInvalid == o_to_t_connection_type) {
- return AssembleForwardOpenResponse(&g_dummy_connection_object,
- message_router_response,
- kCipErrorConnectionFailure,
- kConnectionManagerExtendedStatusCodeErrorInvalidOToTConnectionType);
- }
- if(kConnectionObjectConnectionTypeInvalid == t_to_o_connection_type) {
- return AssembleForwardOpenResponse(&g_dummy_connection_object,
- message_router_response,
- kCipErrorConnectionFailure,
- kConnectionManagerExtendedStatusCodeErrorInvalidTToOConnectionType);
- }
- if(kConnectionObjectConnectionTypeMulticast == t_to_o_connection_type) {
- /* for multicast, check if IP is within configured net because we send TTL 1 */
- CipUdint originator_ip =
- ( (struct sockaddr_in *) originator_address )->sin_addr.s_addr;
- CipUdint interface_ip = g_network_status.ip_address;
- CipUdint interface_mask = g_network_status.network_mask;
- if( (originator_ip & interface_mask) != (interface_ip & interface_mask) ) {
- return AssembleForwardOpenResponse(&g_dummy_connection_object,
- message_router_response,
- kCipErrorConnectionFailure,
- kConnectionManagerExtendedStatusCodeNotConfiguredForOffSubnetMulticast);
- }
- }
- /* Check if request is a Null request or a Non-Null request */
- if(kConnectionObjectConnectionTypeNull == o_to_t_connection_type &&
- kConnectionObjectConnectionTypeNull == t_to_o_connection_type) {
- is_null_request = true;
- OPENER_TRACE_INFO("We have a Null request\n");
- } else {
- is_null_request = false;
- OPENER_TRACE_INFO("We have a Non-Null request\n");
- }
- /* Check if we have a matching or non matching request */
- if(NULL != CheckForExistingConnection(&g_dummy_connection_object) ) {
- OPENER_TRACE_INFO("We have a Matching request\n");
- is_matching_request = true;
- } else {
- OPENER_TRACE_INFO("We have a Non-Matching request\n");
- is_matching_request = false;
- }
- HandleForwardOpenRequestFunction choosen_function =
- handle_forward_open_request_functions[is_null_request][is_matching_request];
- return choosen_function(&g_dummy_connection_object,
- instance,
- message_router_request,
- message_router_response);
- }
- EipStatus ForwardClose(CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response,
- const struct sockaddr *originator_address,
- const CipSessionHandle encapsulation_session) {
- /*Suppress compiler warning*/
- (void) instance;
- (void) encapsulation_session;
- /* check connection_serial_number && originator_vendor_id && originator_serial_number if connection is established */
- ConnectionManagerExtendedStatusCode connection_status =
- kConnectionManagerExtendedStatusCodeErrorConnectionTargetConnectionNotFound;
- /* set AddressInfo Items to invalid TypeID to prevent assembleLinearMsg to read them */
- g_common_packet_format_data_item.address_info_item[0].type_id = 0;
- g_common_packet_format_data_item.address_info_item[1].type_id = 0;
- message_router_request->data += 2; /* ignore Priority/Time_tick and Time-out_ticks */
- EipUint16 connection_serial_number = GetUintFromMessage(
- &message_router_request->data);
- EipUint16 originator_vendor_id = GetUintFromMessage(
- &message_router_request->data);
- EipUint32 originator_serial_number = GetUdintFromMessage(
- &message_router_request->data);
- OPENER_TRACE_INFO("ForwardClose: ConnSerNo %d\n", connection_serial_number);
- DoublyLinkedListNode *node = connection_list.first;
- while(NULL != node) {
- /* this check should not be necessary as only established connections should be in the active connection list */
- CipConnectionObject *connection_object = node->data;
- if( (kConnectionObjectStateEstablished ==
- ConnectionObjectGetState(connection_object) )
- || (kConnectionObjectStateTimedOut ==
- ConnectionObjectGetState(connection_object) ) ) {
- if( (connection_object->connection_serial_number ==
- connection_serial_number) &&
- (connection_object->originator_vendor_id == originator_vendor_id)
- && (connection_object->originator_serial_number ==
- originator_serial_number) ) {
- /* found the corresponding connection object -> close it */
- OPENER_ASSERT(NULL != connection_object->connection_close_function);
- if( ( (struct sockaddr_in *) originator_address )->sin_addr.s_addr ==
- connection_object->originator_address.sin_addr.s_addr ) {
- connection_object->connection_close_function(connection_object);
- connection_status = kConnectionManagerExtendedStatusCodeSuccess;
- } else {
- connection_status = kConnectionManagerExtendedStatusWrongCloser;
- }
- break;
- }
- }
- node = node->next;
- }
- if(kConnectionManagerExtendedStatusCodeErrorConnectionTargetConnectionNotFound
- == connection_status) {
- OPENER_TRACE_INFO(
- "Connection not found! Requested connection tried: %u, %u, %i\n",
- connection_serial_number,
- originator_vendor_id,
- originator_serial_number);
- }
- return AssembleForwardCloseResponse(connection_serial_number,
- originator_vendor_id,
- originator_serial_number,
- message_router_request,
- message_router_response,
- connection_status);
- }
- /* TODO: Not implemented */
- EipStatus GetConnectionOwner(CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response,
- const struct sockaddr *originator_address,
- const CipSessionHandle encapsulation_session) {
- /* suppress compiler warnings */
- (void) instance;
- (void) message_router_request;
- (void) message_router_response;
- (void) originator_address;
- (void) encapsulation_session;
- return kEipStatusOk;
- }
- EipStatus GetConnectionData(CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response,
- const struct sockaddr *originator_address,
- const CipUdint encapsulation_session) {
- /* Suppress unused parameter compiler warning. */
- (void)instance;
- (void)originator_address;
- (void)encapsulation_session;
- CIPServiceCode service_code = kGetConnectionData;
- message_router_response->reply_service = (0x80 | service_code);
- //get Connection Number from request
- EipUint16 Connection_number =
- GetUintFromMessage(&message_router_request->data);
- OPENER_TRACE_INFO("GetConnectionData for Connection_number: %d\n",
- Connection_number);
- //search connection
- DoublyLinkedListNode *iterator = connection_list.first;
- CipConnectionObject *search_connection_object = NULL;
- CipConnectionObject *connection_object = NULL;
- while(NULL != iterator) {
- search_connection_object = iterator->data;
- if( (search_connection_object->connection_number == Connection_number) ) {
- connection_object = search_connection_object;
- break;
- }
- iterator = iterator->next;
- }
- if(NULL != connection_object) {
- /* assemble response message */
- AssembleConnectionDataResponseMessage(message_router_response,
- connection_object);
- message_router_response->general_status = kEipStatusOk;
- OPENER_TRACE_INFO("Connection found!\n");
- } else {
- message_router_response->general_status = kCipErrorPathDestinationUnknown;
- OPENER_TRACE_INFO("Connection not found!\n");
- }
- return kEipStatusOk;
- }
- EipStatus SearchConnectionData(CipInstance *instance,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response,
- const struct sockaddr *originator_address,
- const CipUdint encapsulation_session) {
- /* Suppress unused parameter compiler warning. */
- (void)instance;
- (void)originator_address;
- (void)encapsulation_session;
- CIPServiceCode service_code = kSearchConnectionData;
- message_router_response->reply_service = (0x80 | service_code);
- //connection data (connection triad) from request
- EipUint16 Connection_serial_number = GetUintFromMessage(
- &message_router_request->data);
- EipUint16 Originator_vendor_id = GetUintFromMessage(
- &message_router_request->data);
- EipUint32 Originator_serial_number = GetUdintFromMessage(
- &message_router_request->data);
- OPENER_TRACE_INFO(
- "SearchConnectionData for ConnSerNo: %d, OrigVendId: %d, OrigSerNo: %i,\n",
- Connection_serial_number,
- Originator_vendor_id,
- Originator_serial_number);
- //search connection
- DoublyLinkedListNode *iterator = connection_list.first;
- CipConnectionObject *search_connection_object = NULL;
- CipConnectionObject *connection_object = NULL;
- while(NULL != iterator) {
- search_connection_object = iterator->data;
- if( (search_connection_object->connection_serial_number ==
- Connection_serial_number)
- && (search_connection_object->originator_vendor_id ==
- Originator_vendor_id)
- && (search_connection_object->originator_serial_number ==
- Originator_serial_number) ) {
- connection_object = search_connection_object;
- break;
- }
- iterator = iterator->next;
- }
- if(NULL != connection_object) {
- /* assemble response message */
- AssembleConnectionDataResponseMessage(message_router_response,
- connection_object);
- message_router_response->general_status = kEipStatusOk;
- OPENER_TRACE_INFO("Connection found!\n");
- } else {
- message_router_response->general_status = kCipErrorPathDestinationUnknown;
- OPENER_TRACE_INFO("Connection not found!\n");
- }
- return kEipStatusOk;
- }
- void AssembleConnectionDataResponseMessage(
- CipMessageRouterResponse *message_router_response,
- CipConnectionObject *connection_object) {
- // Connection number UINT
- AddIntToMessage(connection_object->connection_number,
- &message_router_response->message);
- // Connection state UINT
- AddIntToMessage(connection_object->state, &message_router_response->message);
- // Originator Port UINT
- AddIntToMessage(connection_object->originator_address.sin_port,
- &message_router_response->message);
- // Target Port UINT
- AddIntToMessage(connection_object->remote_address.sin_port,
- &message_router_response->message);
- // Connection Serial Number UINT
- AddIntToMessage(connection_object->connection_serial_number,
- &message_router_response->message);
- // Originator Vendor ID UINT
- AddIntToMessage(connection_object->originator_vendor_id,
- &message_router_response->message);
- // Originator Serial number UDINT
- AddDintToMessage(connection_object->originator_serial_number,
- &message_router_response->message);
- // Originator O->T CID UDINT
- AddDintToMessage(connection_object->cip_consumed_connection_id,
- &message_router_response->message);
- // Target O->T CID UDINT
- AddDintToMessage(connection_object->cip_consumed_connection_id,
- &message_router_response->message);
- // Connection Timeout Multiplier USINT
- AddSintToMessage(connection_object->connection_timeout_multiplier,
- &message_router_response->message);
- // Reserved USINT
- AddSintToMessage(0, &message_router_response->message);
- // Reserved USINT
- AddSintToMessage(0, &message_router_response->message);
- // Reserved USINT
- AddSintToMessage(0, &message_router_response->message);
- // Originator RPI O->T UDINT
- AddDintToMessage(connection_object->o_to_t_requested_packet_interval,
- &message_router_response->message);
- // Originator API O->T UDINT
- AddDintToMessage(connection_object->transmission_trigger_timer,
- &message_router_response->message);
- // Originator T->O CID UDINT
- AddDintToMessage(connection_object->cip_produced_connection_id,
- &message_router_response->message);
- // Target T->O CID UDINT
- AddDintToMessage(connection_object->cip_produced_connection_id,
- &message_router_response->message);
- // Connection Timeout Multiplier USINT
- AddSintToMessage(connection_object->connection_timeout_multiplier,
- &message_router_response->message);
- // Reserved USINT
- AddSintToMessage(0, &message_router_response->message);
- // Reserved USINT
- AddSintToMessage(0, &message_router_response->message);
- // Reserved USINT
- AddSintToMessage(0, &message_router_response->message);
- // Originator RPI T->O UDINT
- AddDintToMessage(connection_object->t_to_o_requested_packet_interval,
- &message_router_response->message);
- // Originator API T->O UDINT
- AddDintToMessage(connection_object->transmission_trigger_timer,
- &message_router_response->message);
- }
- EipStatus ManageConnections(MilliSeconds elapsed_time) {
- //OPENER_TRACE_INFO("Entering ManageConnections\n");
- /*Inform application that it can execute */
- HandleApplication();
- ManageEncapsulationMessages(elapsed_time);
- DoublyLinkedListNode *node = connection_list.first;
- while(NULL != node) {
- //OPENER_TRACE_INFO("Entering Connection Object loop\n");
- CipConnectionObject *connection_object = node->data;
- if(kConnectionObjectStateEstablished ==
- ConnectionObjectGetState(connection_object) ) {
- if( (NULL != connection_object->consuming_instance) || /* we have a consuming connection check inactivity watchdog timer */
- (kConnectionObjectTransportClassTriggerDirectionServer ==
- ConnectionObjectGetTransportClassTriggerDirection(connection_object) ) ) /* all server connections have to maintain an inactivity watchdog timer */
- {
- if(elapsed_time >= connection_object->inactivity_watchdog_timer) {
- /* we have a timed out connection perform watchdog time out action*/
- OPENER_TRACE_INFO(">>>>>>>>>>Connection ConnNr: %u timed out\n",
- connection_object->connection_serial_number);
- OPENER_ASSERT(NULL != connection_object->connection_timeout_function);
- connection_object->connection_timeout_function(connection_object);
- } else {
- connection_object->inactivity_watchdog_timer -= elapsed_time;
- connection_object->last_package_watchdog_timer -= elapsed_time;
- }
- }
- /* only if the connection has not timed out check if data is to be send */
- if(kConnectionObjectStateEstablished ==
- ConnectionObjectGetState(connection_object) ) {
- /* client connection */
- if( (0 != ConnectionObjectGetExpectedPacketRate(connection_object) )
- && (kEipInvalidSocket !=
- connection_object->socket[kUdpCommuncationDirectionProducing]) ) /* only produce for the master connection */
- {
- if(kConnectionObjectTransportClassTriggerProductionTriggerCyclic !=
- ConnectionObjectGetTransportClassTriggerProductionTrigger(
- connection_object) ) {
- /* non cyclic connections have to decrement production inhibit timer */
- if(elapsed_time <= connection_object->production_inhibit_timer) {
- //The connection is allowed to send again
- } else {
- connection_object->production_inhibit_timer -= elapsed_time;
- }
- }
- if(connection_object->transmission_trigger_timer <= elapsed_time) { /* need to send package */
- OPENER_ASSERT(
- NULL != connection_object->connection_send_data_function);
- EipStatus eip_status =
- connection_object->connection_send_data_function(connection_object);
- if(eip_status == kEipStatusError) {
- OPENER_TRACE_ERR(
- "sending of UDP data in manage Connection failed\n");
- }
- /* add the RPI to the timer value */
- connection_object->transmission_trigger_timer +=
- ConnectionObjectGetRequestedPacketInterval(connection_object);
- /* decrecment the elapsed time from timer value, if less than timer value */
- if (connection_object->transmission_trigger_timer > elapsed_time) {
- connection_object->transmission_trigger_timer -= elapsed_time;
- } else { /* elapsed time was longer than RPI */
- connection_object->transmission_trigger_timer = 0;
- OPENER_TRACE_INFO("elapsed time: %lu ms was longer than RPI: %u ms\n",
- elapsed_time,
- ConnectionObjectGetRequestedPacketInterval(connection_object));
- }
- if(kConnectionObjectTransportClassTriggerProductionTriggerCyclic !=
- ConnectionObjectGetTransportClassTriggerProductionTrigger(
- connection_object) ) {
- /* non cyclic connections have to reload the production inhibit timer */
- ConnectionObjectResetProductionInhibitTimer(connection_object);
- }
- } else {
- connection_object->transmission_trigger_timer -= elapsed_time;
- }
- }
- }
- }
- node = node->next;
- }
- return kEipStatusOk;
- }
- /** @brief Assembles the Forward Open Response
- *
- * @param connection_object pointer to connection Object
- * @param message_router_response pointer to message router response
- * @param general_status the general status of the response
- * @param extended_status extended status in the case of an error otherwise 0
- * @return status
- * kEipStatusOk .. no reply need to be sent back
- * kEipStatusOkSend .. need to send reply
- * kEipStatusError .. error
- */
- EipStatus AssembleForwardOpenResponse(CipConnectionObject *connection_object,
- CipMessageRouterResponse *message_router_response,
- EipUint8 general_status,
- EipUint16 extended_status) {
- /* write reply information in CPF struct dependent of pa_status */
- CipCommonPacketFormatData *cip_common_packet_format_data =
- &g_common_packet_format_data_item;
- cip_common_packet_format_data->item_count = 2;
- cip_common_packet_format_data->data_item.type_id =
- kCipItemIdUnconnectedDataItem;
- AddNullAddressItem(cip_common_packet_format_data);
- CIPServiceCode service_code = kForwardOpen;
- if(connection_object->is_large_forward_open) {
- service_code = kLargeForwardOpen;
- }
- message_router_response->reply_service = (0x80 | service_code);
- message_router_response->general_status = general_status;
- if(kCipErrorSuccess == general_status) {
- OPENER_TRACE_INFO("assembleFWDOpenResponse: sending success response\n");
- /* if there is no application specific data, total length should be 26 */
- message_router_response->size_of_additional_status = 0;
- if(cip_common_packet_format_data->address_info_item[0].type_id != 0) {
- cip_common_packet_format_data->item_count = 3;
- if(cip_common_packet_format_data->address_info_item[1].type_id != 0) {
- cip_common_packet_format_data->item_count = 4; /* there are two sockaddrinfo items to add */
- }
- }
- AddDintToMessage(connection_object->cip_consumed_connection_id,
- &message_router_response->message);
- AddDintToMessage(connection_object->cip_produced_connection_id,
- &message_router_response->message);
- } else {
- /* we have an connection creation error */
- OPENER_TRACE_WARN("AssembleForwardOpenResponse: sending error response, general/extended status=%d/%d\n", general_status, extended_status);
- ConnectionObjectSetState(connection_object,
- kConnectionObjectStateNonExistent);
- /* Expected data length is 10 octets */
- switch(general_status) {
- case kCipErrorNotEnoughData:
- case kCipErrorTooMuchData: {
- message_router_response->size_of_additional_status = 0;
- break;
- }
- default: {
- switch(extended_status) {
- case
- kConnectionManagerExtendedStatusCodeErrorInvalidOToTConnectionSize:
- {
- message_router_response->size_of_additional_status = 2;
- message_router_response->additional_status[0] = extended_status;
- message_router_response->additional_status[1] =
- connection_object->correct_originator_to_target_size;
- break;
- }
- case
- kConnectionManagerExtendedStatusCodeErrorInvalidTToOConnectionSize:
- {
- message_router_response->size_of_additional_status = 2;
- message_router_response->additional_status[0] = extended_status;
- message_router_response->additional_status[1] =
- connection_object->correct_target_to_originator_size;
- break;
- }
- default: {
- message_router_response->size_of_additional_status = 1;
- message_router_response->additional_status[0] = extended_status;
- break;
- }
- }
- break;
- }
- }
- }
- AddIntToMessage(connection_object->connection_serial_number,
- &message_router_response->message);
- AddIntToMessage(connection_object->originator_vendor_id,
- &message_router_response->message);
- AddDintToMessage(connection_object->originator_serial_number,
- &message_router_response->message);
- if(kCipErrorSuccess == general_status) {
- /* set the actual packet rate to requested packet rate */
- AddDintToMessage(connection_object->o_to_t_requested_packet_interval,
- &message_router_response->message);
- AddDintToMessage(connection_object->t_to_o_requested_packet_interval,
- &message_router_response->message);
- }
- AddSintToMessage(0, &message_router_response->message); /* remaining path size - for routing devices relevant */
- AddSintToMessage(0, &message_router_response->message); /* reserved */
- return kEipStatusOkSend; /* send reply */
- }
- /**
- * @brief Adds a Null Address Item to the common data packet format data
- * @param common_data_packet_format_data The CPF data packet where the Null Address Item shall be added
- */
- void AddNullAddressItem(
- CipCommonPacketFormatData *common_data_packet_format_data) {
- /* Precondition: Null Address Item only valid in unconnected messages */
- assert(
- common_data_packet_format_data->data_item.type_id ==
- kCipItemIdUnconnectedDataItem);
- common_data_packet_format_data->address_item.type_id = kCipItemIdNullAddress;
- common_data_packet_format_data->address_item.length = 0;
- }
- /* INT8 assembleFWDCloseResponse(UINT16 pa_ConnectionSerialNr, UINT16 pa_OriginatorVendorID, UINT32 pa_OriginatorSerialNr, S_CIP_MR_Request *pa_MRRequest, S_CIP_MR_Response *pa_MRResponse, S_CIP_CPF_Data *pa_CPF_data, INT8 pa_status, INT8 *pa_msg)
- * create FWDClose response dependent on status.
- * pa_ConnectionSerialNr requested ConnectionSerialNr
- * pa_OriginatorVendorID requested OriginatorVendorID
- * pa_OriginatorSerialNr requested OriginalSerialNr
- * pa_MRRequest pointer to message router request
- * pa_MRResponse pointer to message router response
- * pa_CPF_data pointer to CPF Data Item
- * pa_status status of FWDClose
- * pa_msg pointer to memory where reply has to be stored
- * return status
- * 0 .. no reply need to ne sent back
- * 1 .. need to send reply
- * -1 .. error
- */
- EipStatus AssembleForwardCloseResponse(EipUint16 connection_serial_number,
- EipUint16 originatior_vendor_id,
- EipUint32 originator_serial_number,
- CipMessageRouterRequest *message_router_request,
- CipMessageRouterResponse *message_router_response,
- EipUint16 extended_error_code) {
- /* write reply information in CPF struct dependent of pa_status */
- CipCommonPacketFormatData *common_data_packet_format_data =
- &g_common_packet_format_data_item;
- common_data_packet_format_data->item_count = 2;
- common_data_packet_format_data->data_item.type_id =
- kCipItemIdUnconnectedDataItem;
- AddNullAddressItem(common_data_packet_format_data);
- AddIntToMessage(connection_serial_number, &message_router_response->message);
- AddIntToMessage(originatior_vendor_id, &message_router_response->message);
- AddDintToMessage(originator_serial_number, &message_router_response->message);
- message_router_response->reply_service =
- (0x80 | message_router_request->service);
- /* Excepted length is 10 if there is no application specific data */
- if(kConnectionManagerExtendedStatusCodeSuccess == extended_error_code) {
- AddSintToMessage(0, &message_router_response->message); /* no application data */
- message_router_response->general_status = kCipErrorSuccess;
- message_router_response->size_of_additional_status = 0;
- } else {
- AddSintToMessage(*message_router_request->data,
- &message_router_response->message); /* remaining path size */
- if(kConnectionManagerExtendedStatusWrongCloser == extended_error_code) {
- message_router_response->general_status = kCipErrorPrivilegeViolation;
- } else {
- message_router_response->general_status = kCipErrorConnectionFailure;
- message_router_response->additional_status[0] = extended_error_code;
- message_router_response->size_of_additional_status = 1;
- }
- }
- AddSintToMessage(0, &message_router_response->message); /* reserved */
- return kEipStatusOkSend;
- }
- CipConnectionObject *GetConnectedObject(const EipUint32 connection_id) {
- DoublyLinkedListNode *iterator = connection_list.first;
- while(NULL != iterator) {
- if(kConnectionObjectStateEstablished ==
- ConnectionObjectGetState(iterator->data)
- && connection_id ==
- ConnectionObjectGetCipConsumedConnectionID(iterator->data) ) {
- return iterator->data;
- }
- iterator = iterator->next;
- }
- return NULL;
- }
- CipConnectionObject *GetConnectedOutputAssembly(
- const EipUint32 output_assembly_id) {
- DoublyLinkedListNode *iterator = connection_list.first;
- while(NULL != iterator) {
- if(kConnectionObjectInstanceTypeIOExclusiveOwner ==
- ConnectionObjectGetInstanceType(iterator->data)
- && (kConnectionObjectStateEstablished ==
- ConnectionObjectGetState(iterator->data)
- || kConnectionObjectStateTimedOut ==
- ConnectionObjectGetState(iterator->data) )
- && output_assembly_id ==
- ( (CipConnectionObject *) iterator->data )->produced_path.instance_id) {
- return iterator->data;
- }
- iterator = iterator->next;
- }
- return NULL;
- }
- CipConnectionObject *CheckForExistingConnection(
- const CipConnectionObject *const connection_object) {
- DoublyLinkedListNode *iterator = connection_list.first;
- while(NULL != iterator) {
- if(kConnectionObjectStateEstablished ==
- ConnectionObjectGetState(iterator->data) ) {
- if(EqualConnectionTriad(connection_object, iterator->data) ) {
- return iterator->data;
- }
- }
- iterator = iterator->next;
- }
- return NULL;
- }
- EipStatus CheckElectronicKeyData(EipUint8 key_format,
- void *key_data,
- EipUint16 *extended_status) {
- /* Default return value */
- *extended_status = kConnectionManagerExtendedStatusCodeSuccess;
- /* Check key format */
- if(4 != key_format) {
- *extended_status =
- kConnectionManagerExtendedStatusCodeErrorInvalidSegmentTypeInPath;
- return kEipStatusError;
- }
- bool compatiblity_mode = ElectronicKeyFormat4GetMajorRevisionCompatibility(
- key_data);
- /* Check VendorID and ProductCode, must match, or 0 */
- if( ( (ElectronicKeyFormat4GetVendorId(key_data) != g_identity.vendor_id) &&
- (ElectronicKeyFormat4GetVendorId(key_data) != 0) )
- || ( (ElectronicKeyFormat4GetProductCode(key_data) !=
- g_identity.product_code) &&
- (ElectronicKeyFormat4GetProductCode(key_data) != 0) ) ) {
- *extended_status =
- kConnectionManagerExtendedStatusCodeErrorVendorIdOrProductcodeError;
- return kEipStatusError;
- } else {
- /* VendorID and ProductCode are correct */
- /* Check DeviceType, must match or 0 */
- if( (ElectronicKeyFormat4GetDeviceType(key_data) !=
- g_identity.device_type) &&
- (ElectronicKeyFormat4GetDeviceType(key_data) != 0) ) {
- *extended_status =
- kConnectionManagerExtendedStatusCodeErrorDeviceTypeError;
- return kEipStatusError;
- } else {
- /* VendorID, ProductCode and DeviceType are correct */
- if(false == compatiblity_mode) {
- /* Major = 0 is valid */
- if(0 == ElectronicKeyFormat4GetMajorRevision(key_data) ) {
- return kEipStatusOk;
- }
- /* Check Major / Minor Revision, Major must match, Minor match or 0 */
- if( (ElectronicKeyFormat4GetMajorRevision(key_data) !=
- g_identity.revision.major_revision)
- || ( (ElectronicKeyFormat4GetMinorRevision(key_data) !=
- g_identity.revision.minor_revision) &&
- (ElectronicKeyFormat4GetMinorRevision(key_data) != 0) ) ) {
- *extended_status =
- kConnectionManagerExtendedStatusCodeErrorRevisionMismatch;
- return kEipStatusError;
- }
- } else {
- /* Compatibility mode is set */
- /* Major must match, Minor != 0 and <= MinorRevision */
- if( (ElectronicKeyFormat4GetMajorRevision(key_data) ==
- g_identity.revision.major_revision) &&
- (ElectronicKeyFormat4GetMinorRevision(key_data) > 0)
- && (ElectronicKeyFormat4GetMinorRevision(key_data) <=
- g_identity.revision.minor_revision) ) {
- return kEipStatusOk;
- } else {
- *extended_status =
- kConnectionManagerExtendedStatusCodeErrorRevisionMismatch;
- return kEipStatusError;
- }
- } /* end if CompatiblityMode handling */
- }
- }
- return (*extended_status ==
- kConnectionManagerExtendedStatusCodeSuccess) ? kEipStatusOk :
- kEipStatusError;
- }
- EipUint8 ParseConnectionPath(CipConnectionObject *connection_object,
- CipMessageRouterRequest *message_router_request,
- EipUint16 *extended_error) {
- const EipUint8 *message = message_router_request->data;
- const size_t connection_path_size = GetUsintFromMessage(&message); /* length in words */
- if(0 == connection_path_size) {
- // A (large) forward open request needs to have a connection path size larger than 0
- return kEipStatusError;
- }
- size_t remaining_path = connection_path_size;
- OPENER_TRACE_INFO("Received connection path size: %zu \n",
- connection_path_size);
- CipClass *class = NULL;
- CipDword class_id = 0x0;
- CipInstanceNum instance_id = 0x0;
- /* with 256 we mark that we haven't got a PIT segment */
- ConnectionObjectSetProductionInhibitTime(connection_object, 256);
- size_t header_length = g_kForwardOpenHeaderLength;
- if(connection_object->is_large_forward_open) {
- header_length = g_kLargeForwardOpenHeaderLength;
- }
- if( ( header_length + remaining_path * sizeof(CipWord) ) <
- message_router_request->request_data_size ) {
- /* the received packet is larger than the data in the path */
- *extended_error = 0;
- return kCipErrorTooMuchData;
- }
- if( ( header_length + remaining_path * sizeof(CipWord) ) >
- message_router_request->request_data_size ) {
- /*there is not enough data in received packet */
- *extended_error = 0;
- OPENER_TRACE_INFO("Message not long enough for path\n");
- return kCipErrorNotEnoughData;
- }
- if(remaining_path > 0) {
- /* first look if there is an electronic key */
- if(kSegmentTypeLogicalSegment == GetPathSegmentType(message) ) {
- if(kLogicalSegmentLogicalTypeSpecial ==
- GetPathLogicalSegmentLogicalType(message) ) {
- if(kLogicalSegmentSpecialTypeLogicalFormatElectronicKey ==
- GetPathLogicalSegmentSpecialTypeLogicalType(message) ) {
- if(kElectronicKeySegmentFormatKeyFormat4 ==
- GetPathLogicalSegmentElectronicKeyFormat(message) ) {
- /* Check if there is enough data for holding the electronic key segment */
- if(remaining_path < 5) {
- *extended_error = 0;
- OPENER_TRACE_INFO("Message not long enough for electronic key\n");
- return kCipErrorNotEnoughData;
- }
- /* Electronic key format 4 found */
- connection_object->electronic_key.key_format = 4;
- ElectronicKeyFormat4 *electronic_key = ElectronicKeyFormat4New();
- GetElectronicKeyFormat4FromMessage(&message, electronic_key);
- /* logical electronic key found */
- connection_object->electronic_key.key_data = electronic_key;
- remaining_path -= 5; /*length of the electronic key*/
- OPENER_TRACE_INFO(
- "key: ven ID %d, dev type %d, prod code %d, major %d, minor %d\n",
- ElectronicKeyFormat4GetVendorId(connection_object->electronic_key.
- key_data),
- ElectronicKeyFormat4GetDeviceType(connection_object->
- electronic_key.key_data),
- ElectronicKeyFormat4GetProductCode(connection_object->
- electronic_key.key_data),
- ElectronicKeyFormat4GetMajorRevision(connection_object->
- electronic_key.key_data),
- ElectronicKeyFormat4GetMinorRevision(connection_object->
- electronic_key.key_data) );
- if(kEipStatusOk
- != CheckElectronicKeyData(connection_object->electronic_key.
- key_format,
- connection_object->electronic_key.
- key_data,
- extended_error) ) {
- ElectronicKeyFormat4Delete(&electronic_key);
- return kCipErrorConnectionFailure;
- }
- ElectronicKeyFormat4Delete(&electronic_key);
- }
- } else {
- OPENER_TRACE_INFO("no key\n");
- }
- }
- }
- //TODO: Refactor this afterwards
- if(kConnectionObjectTransportClassTriggerProductionTriggerCyclic !=
- ConnectionObjectGetTransportClassTriggerProductionTrigger(
- connection_object) )
- {
- /*non cyclic connections may have a production inhibit */
- if(kSegmentTypeNetworkSegment == GetPathSegmentType(message) ) {
- NetworkSegmentSubtype network_segment_subtype =
- GetPathNetworkSegmentSubtype(message);
- if(kNetworkSegmentSubtypeProductionInhibitTimeInMilliseconds ==
- network_segment_subtype) {
- OPENER_TRACE_INFO("PIT segment available - value: %u\n",message[1]);
- connection_object->production_inhibit_time = message[1];
- message += 2;
- remaining_path -= 1;
- }
- }
- }
- if(kSegmentTypeLogicalSegment == GetPathSegmentType(message) &&
- kLogicalSegmentLogicalTypeClassId ==
- GetPathLogicalSegmentLogicalType(message) ) {
- class_id = CipEpathGetLogicalValue(&message);
- class = GetCipClass(class_id);
- if(NULL == class) {
- OPENER_TRACE_ERR("classid %" PRIx32 " not found\n",
- class_id);
- if(class_id >= 0xC8) { /*reserved range of class ids */
- *extended_error =
- kConnectionManagerExtendedStatusCodeErrorInvalidSegmentTypeInPath;
- } else {
- *extended_error =
- kConnectionManagerExtendedStatusCodeInconsistentApplicationPathCombo;
- }
- return kCipErrorConnectionFailure;
- }
- OPENER_TRACE_INFO("classid %" PRIx32 " (%s)\n",
- class_id,
- class->class_name);
- } else {
- *extended_error =
- kConnectionManagerExtendedStatusCodeErrorInvalidSegmentTypeInPath;
- return kCipErrorConnectionFailure;
- }
- remaining_path -= 1; /* 1 16Bit word for the class part of the path */
- /* Get instance ID */
- if(kSegmentTypeLogicalSegment == GetPathSegmentType(message) &&
- kLogicalSegmentLogicalTypeInstanceId ==
- GetPathLogicalSegmentLogicalType(message) ) { /* store the configuration ID for later checking in the application connection types */
- const CipDword temp_id = CipEpathGetLogicalValue(&message);
- OPENER_TRACE_INFO("Configuration instance id %" PRId32 "\n",
- temp_id);
- if( (temp_id > kCipInstanceNumMax) ||
- ( NULL == GetCipInstance(class, (CipInstanceNum)temp_id) ) ) {
- /*according to the test tool we should respond with this extended error code */
- *extended_error =
- kConnectionManagerExtendedStatusCodeErrorInvalidSegmentTypeInPath;
- return kCipErrorConnectionFailure;
- }
- instance_id = (CipInstanceNum)temp_id;
- /* 1 or 2 16Bit words for the configuration instance part of the path */
- remaining_path -= (instance_id > 0xFF) ? 2 : 1; //TODO: 32 bit case missing
- } else {
- OPENER_TRACE_INFO("no config data\n");
- }
- if(kConnectionObjectTransportClassTriggerTransportClass3 ==
- ConnectionObjectGetTransportClassTriggerTransportClass(connection_object) )
- {
- /*we have Class 3 connection*/
- if(remaining_path > 0) {
- OPENER_TRACE_WARN(
- "Too much data in connection path for class 3 connection\n");
- *extended_error =
- kConnectionManagerExtendedStatusCodeErrorInvalidSegmentTypeInPath;
- return kCipErrorConnectionFailure;
- }
- /* connection end point has to be the message router instance 1 */
- if( (class_id != kCipMessageRouterClassCode) || (1 != instance_id) ) {
- *extended_error =
- kConnectionManagerExtendedStatusCodeInconsistentApplicationPathCombo;
- return kCipErrorConnectionFailure;
- }
- /* Configuration connection point is producing connection point */
- CipConnectionPathEpath connection_epath =
- { .class_id = class_id, .instance_id = instance_id,
- .attribute_id_or_connection_point = 0 };
- memcpy(&(connection_object->configuration_path),
- &connection_epath,
- sizeof(connection_object->configuration_path) );
- memcpy(&(connection_object->produced_path), &connection_epath,
- sizeof(connection_object->produced_path) );
- /* End class 3 connection handling */
- } else { /* we have an IO connection */
- CipConnectionPathEpath connection_epath =
- { .class_id = class_id, .instance_id = instance_id,
- .attribute_id_or_connection_point = 0 };
- memcpy(&(connection_object->configuration_path),
- &connection_epath,
- sizeof(connection_object->configuration_path) );
- ConnectionObjectConnectionType originator_to_target_connection_type =
- ConnectionObjectGetOToTConnectionType(connection_object);
- ConnectionObjectConnectionType target_to_originator_connection_type =
- ConnectionObjectGetTToOConnectionType(connection_object);
- connection_object->consumed_connection_path_length = 0;
- connection_object->consumed_connection_path = NULL;
- //connection_object->connection_path.connection_point[1] = 0; /* set not available path to Invalid */
- size_t number_of_encoded_paths = 0;
- CipConnectionPathEpath *paths_to_encode[2] = { 0 };
- if(kConnectionObjectConnectionTypeNull ==
- originator_to_target_connection_type) {
- if(kConnectionObjectConnectionTypeNull ==
- target_to_originator_connection_type) { /* configuration only connection */
- number_of_encoded_paths = 0;
- OPENER_TRACE_WARN("assembly: type invalid\n");
- } else { /* 1 path -> path is for production */
- OPENER_TRACE_INFO("assembly: type produce\n");
- number_of_encoded_paths = 1;
- paths_to_encode[0] = &(connection_object->produced_path);
- }
- } else {
- if(kConnectionObjectConnectionTypeNull ==
- target_to_originator_connection_type) { /* 1 path -> path is for consumption */
- OPENER_TRACE_INFO("assembly: type consume\n");
- number_of_encoded_paths = 1;
- paths_to_encode[0] = &(connection_object->consumed_path);
- } else { /* 2 paths -> 1st for production 2nd for consumption */
- OPENER_TRACE_INFO("assembly: type bidirectional\n");
- paths_to_encode[0] = &(connection_object->consumed_path);
- paths_to_encode[1] = &(connection_object->produced_path);
- number_of_encoded_paths = 2;
- }
- }
- for(size_t i = 0; i < number_of_encoded_paths; i++) /* process up to 2 encoded paths */
- {
- if(kSegmentTypeLogicalSegment == GetPathSegmentType(message)
- && (kLogicalSegmentLogicalTypeInstanceId ==
- GetPathLogicalSegmentLogicalType(message)
- || kLogicalSegmentLogicalTypeConnectionPoint ==
- GetPathLogicalSegmentLogicalType(message) ) ) /* Connection Point interpreted as InstanceNr -> only in Assembly Objects */
- { /* Attribute Id or Connection Point */
- /* Validate encoded instance number. */
- const CipDword temp_instance_id = CipEpathGetLogicalValue(&message);
- if (temp_instance_id > kCipInstanceNumMax) {
- *extended_error =
- kConnectionManagerExtendedStatusCodeErrorInvalidSegmentTypeInPath;
- return kCipErrorConnectionFailure;
- }
- instance_id = (CipInstanceNum)temp_instance_id;
- CipConnectionPathEpath path;
- path.class_id = class_id;
- path.instance_id = instance_id;
- path.attribute_id_or_connection_point = 0;
- memcpy(paths_to_encode[i], &path,
- sizeof(connection_object->produced_path) );
- OPENER_TRACE_INFO(
- "connection point %" PRIu32 "\n",
- instance_id);
- if( NULL == GetCipInstance(class, instance_id) ) {
- *extended_error =
- kConnectionManagerExtendedStatusCodeInconsistentApplicationPathCombo;
- return kCipErrorConnectionFailure;
- }
- /* 1 or 2 16Bit word for the connection point part of the path */
- remaining_path -= (instance_id > 0xFF) ? 2 : 1;
- } else {
- *extended_error =
- kConnectionManagerExtendedStatusCodeErrorInvalidSegmentTypeInPath;
- return kCipErrorConnectionFailure;
- }
- }
- g_config_data_length = 0;
- g_config_data_buffer = NULL;
- while(remaining_path > 0) { /* remaining_path_size something left in the path should be configuration data */
- SegmentType segment_type = GetPathSegmentType(message);
- switch(segment_type) {
- case kSegmentTypeDataSegment: {
- DataSegmentSubtype data_segment_type = GetPathDataSegmentSubtype(
- message);
- switch(data_segment_type) {
- case kDataSegmentSubtypeSimpleData:
- g_config_data_length = message[1] * 2; /*data segments store length 16-bit word wise */
- g_config_data_buffer = (EipUint8 *) message + 2;
- remaining_path -= (g_config_data_length + 2) / 2;
- message += (g_config_data_length + 2);
- break;
- default:
- OPENER_TRACE_ERR("Not allowed in connection manager");
- return kCipErrorPathSegmentError;
- }
- }
- break;
- case kSegmentTypeNetworkSegment: {
- NetworkSegmentSubtype subtype =
- GetPathNetworkSegmentSubtype(message);
- switch(subtype) {
- case kNetworkSegmentSubtypeProductionInhibitTimeInMilliseconds:
- if(kConnectionObjectTransportClassTriggerProductionTriggerCyclic
- != ConnectionObjectGetTransportClassTriggerProductionTrigger(
- connection_object) ) {
- /* only non cyclic connections may have a production inhibit */
- connection_object->production_inhibit_time = message[1];
- message += 2;
- remaining_path -= 2;
- } else {
- *extended_error = connection_path_size - remaining_path; /*offset in 16Bit words where within the connection path the error happened*/
- return kCipErrorPathSegmentError; /*status code for invalid segment type*/
- }
- break;
- default:
- OPENER_TRACE_ERR("Not allowed in connection manager");
- return kCipErrorPathSegmentError;
- }
- }
- break;
- default:
- OPENER_TRACE_WARN(
- "No data segment identifier found for the configuration data\n");
- *extended_error = connection_path_size - remaining_path; /*offset in 16Bit words where within the connection path the error happened*/
- return
- kConnectionManagerGeneralStatusPathSegmentErrorInUnconnectedSend;
- }
- }
- }
- }
- OPENER_TRACE_INFO("Resulting PIT value: %u\n",
- connection_object->production_inhibit_time);
- /*save back the current position in the stream allowing followers to parse anything thats still there*/
- message_router_request->data = message;
- return kEipStatusOk;
- }
- void CloseConnection(CipConnectionObject *RESTRICT connection_object) {
- OPENER_TRACE_INFO("cipconnectionmanager: CloseConnection, trigger: %d \n",
- ConnectionObjectGetTransportClassTriggerTransportClass(connection_object));
- if(kConnectionObjectTransportClassTriggerTransportClass3 !=
- ConnectionObjectGetTransportClassTriggerTransportClass(connection_object) )
- {
- /* only close the UDP connection for not class 3 connections */
- CloseUdpSocket(connection_object->socket[kUdpCommuncationDirectionConsuming]);
- connection_object->socket[kUdpCommuncationDirectionConsuming] =
- kEipInvalidSocket;
- CloseUdpSocket(connection_object->socket[kUdpCommuncationDirectionProducing]);
- connection_object->socket[kUdpCommuncationDirectionProducing] =
- kEipInvalidSocket;
- }
- RemoveFromActiveConnections(connection_object);
- ConnectionObjectInitializeEmpty(connection_object);
- }
- void AddNewActiveConnection(CipConnectionObject *const connection_object) {
- DoublyLinkedListInsertAtHead(&connection_list, connection_object);
- ConnectionObjectSetState(connection_object,
- kConnectionObjectStateEstablished);
- }
- void RemoveFromActiveConnections(CipConnectionObject *const connection_object) {
- for(DoublyLinkedListNode *iterator = connection_list.first; iterator != NULL;
- iterator = iterator->next) {
- if(iterator->data == connection_object) {
- DoublyLinkedListRemoveNode(&connection_list, &iterator);
- return;
- }
- } OPENER_TRACE_ERR("Connection not found in active connection list\n");
- }
- EipBool8 IsConnectedOutputAssembly(const CipInstanceNum instance_number) {
- EipBool8 is_connected = false;
- DoublyLinkedListNode *node = connection_list.first;
- while(NULL != node) {
- CipConnectionObject *connection_object = (CipConnectionObject *) node->data;
- CipDword consumed_connection_point =
- connection_object->consumed_path.instance_id;
- if(instance_number == consumed_connection_point &&
- true == ConnectionObjectIsTypeIOConnection(connection_object) ) {
- is_connected = true;
- break;
- }
- node = node->next;
- }
- return is_connected;
- }
- EipStatus AddConnectableObject(const CipUdint class_code,
- OpenConnectionFunction open_connection_function)
- {
- EipStatus status = kEipStatusError;
- /*parsing is now finished all data is available and check now establish the connection */
- for(unsigned int i = 0; i < g_kNumberOfConnectableObjects; ++i) {
- if( (0 == g_connection_management_list[i].class_id) ||
- (class_code == g_connection_management_list[i].class_id) ) {
- g_connection_management_list[i].class_id = class_code;
- g_connection_management_list[i].open_connection_function =
- open_connection_function;
- status = kEipStatusOk;
- break;
- }
- }
- return status;
- }
- ConnectionManagementHandling *
- GetConnectionManagementEntry(const EipUint32 class_id) {
- ConnectionManagementHandling *connection_management_entry = NULL;
- for(unsigned int i = 0; i < g_kNumberOfConnectableObjects; ++i) {
- if(class_id == g_connection_management_list[i].class_id) {
- connection_management_entry = &(g_connection_management_list[i]);
- break;
- }
- }
- return connection_management_entry;
- }
- EipStatus TriggerConnections(unsigned int output_assembly,
- unsigned int input_assembly) {
- EipStatus status = kEipStatusError;
- DoublyLinkedListNode *node = connection_list.first;
- while(NULL != node) {
- CipConnectionObject *connection_object = node->data;
- if( (output_assembly == connection_object->consumed_path.instance_id) &&
- (input_assembly == connection_object->produced_path.instance_id) ) {
- if(
- kConnectionObjectTransportClassTriggerProductionTriggerApplicationObject
- == ConnectionObjectGetTransportClassTriggerProductionTrigger(
- connection_object) ) {
- /* produce at the next allowed occurrence */
- connection_object->transmission_trigger_timer =
- connection_object->production_inhibit_time;
- status = kEipStatusOk;
- }
- break;
- }
- node = node->next;
- }
- return status;
- }
- void CheckForTimedOutConnectionsAndCloseTCPConnections(
- const CipConnectionObject *const connection_object,
- CloseSessionFunction CloseSessions)
- {
- DoublyLinkedListNode *search_node = connection_list.first;
- bool non_timed_out_connection_found = false;
- while(NULL != search_node) {
- CipConnectionObject *search_connection = search_node->data;
- if(ConnectionObjectEqualOriginator(connection_object,
- search_connection) &&
- connection_object != search_connection
- && kConnectionObjectStateTimedOut !=
- ConnectionObjectGetState(search_connection) ) {
- non_timed_out_connection_found = true;
- break;
- }
- search_node = search_node->next;
- }
- if(false == non_timed_out_connection_found) {
- CloseSessions(connection_object);
- }
- }
- void InitializeConnectionManagerData() {
- memset(g_connection_management_list,
- 0,
- g_kNumberOfConnectableObjects * sizeof(ConnectionManagementHandling) );
- InitializeClass3ConnectionData();
- InitializeIoConnectionData();
- }
|