コード例 #1
0
/** @brief Get the registered MessageRouter object corresponding to ClassID.
 *  given a class ID, return a pointer to the registration node for that object
 *
 *  @param class_id Class code to be searched for.
 *  @return Pointer to registered message router object
 *      NULL .. Class not registered
 */
CipMessageRouterObject *GetRegisteredObject(EipUint32 class_id) {
  CipMessageRouterObject *object = g_first_object; /* get pointer to head of class registration list */

  while (NULL != object) /* for each entry in list*/
  {
    OPENER_ASSERT(object->cip_class != NULL);
    if (object->cip_class->class_id == class_id) {
      return object; /* return registration node if it matches class ID*/
    }
    object = object->next;
  }
  return NULL;
}
コード例 #2
0
ファイル: cipioconnection.c プロジェクト: 8bitgeek/OpENer
void HandleIoConnectionTimeOut(ConnectionObject *connection_object) {
  ConnectionObject *next_non_control_master_connection;
  CheckIoConnectionEvent(connection_object->connection_path.connection_point[0],
                    connection_object->connection_path.connection_point[1],
                    kIoConnectionEventTimedOut);

  if (kRoutingTypeMulticastConnection
      == (connection_object->t_to_o_network_connection_parameter
          & kRoutingTypeMulticastConnection)) {
    switch (connection_object->instance_type) {
      case kConnectionTypeIoExclusiveOwner:
        CloseAllConnectionsForInputWithSameType(
            connection_object->connection_path.connection_point[1],
            kConnectionTypeIoInputOnly);
        CloseAllConnectionsForInputWithSameType(
            connection_object->connection_path.connection_point[1],
            kConnectionTypeIoListenOnly);
        break;
      case kConnectionTypeIoInputOnly:
        if (kEipInvalidSocket
            != connection_object->socket[kUdpCommuncationDirectionProducing]) { /* we are the controlling input only connection find a new controller*/
          next_non_control_master_connection =
              GetNextNonControlMasterConnection(
                  connection_object->connection_path.connection_point[1]);
          if (NULL != next_non_control_master_connection) {
            next_non_control_master_connection->socket[kUdpCommuncationDirectionProducing] =
                connection_object->socket[kUdpCommuncationDirectionProducing];
            connection_object->socket[kUdpCommuncationDirectionProducing] =
                kEipInvalidSocket;
            next_non_control_master_connection->transmission_trigger_timer =
                connection_object->transmission_trigger_timer;
          } else { /* this was the last master connection close all listen only connections listening on the port */
            CloseAllConnectionsForInputWithSameType(
                connection_object->connection_path.connection_point[1],
                kConnectionTypeIoListenOnly);
          }
        }
        break;
      default:
        break;
    }
  }

  OPENER_ASSERT(NULL != connection_object->connection_close_function);
  connection_object->connection_close_function(connection_object);
}
コード例 #3
0
ファイル: cipcommon.c プロジェクト: EIPStackGroup/OpENer
void CipStackInit(const EipUint16 unique_connection_id) {
  EncapsulationInit();
  /* The message router is the first CIP object be initialized!!! */
  EipStatus eip_status = CipMessageRouterInit();
  OPENER_ASSERT(kEipStatusOk == eip_status)
  eip_status = CipIdentityInit();
  OPENER_ASSERT(kEipStatusOk == eip_status)
  eip_status = CipTcpIpInterfaceInit();
  OPENER_ASSERT(kEipStatusOk == eip_status)
  eip_status = CipEthernetLinkInit();
  OPENER_ASSERT(kEipStatusOk == eip_status)
  eip_status = ConnectionManagerInit(unique_connection_id);
  OPENER_ASSERT(kEipStatusOk == eip_status)
  eip_status = CipAssemblyInitialize();
  OPENER_ASSERT(kEipStatusOk == eip_status)
  eip_status = CipQoSInit();
  OPENER_ASSERT(kEipStatusOk == eip_status)
  /* the application has to be initialized at last */
  eip_status = ApplicationInitialization();
  OPENER_ASSERT(kEipStatusOk == eip_status)

  /* Shut up compiler warning with traces disabled */
    (void) eip_status;
}
コード例 #4
0
ファイル: cipioconnection.c プロジェクト: 8bitgeek/OpENer
/**** Implementation ****/
int EstablishIoConnction(ConnectionObject *connection_object,
                         EipUint16 *extended_error) {
  int originator_to_target_connection_type,
      target_to_originator_connection_type;
  int eip_status = kEipStatusOk;
  CipAttributeStruct *attribute;
  /* currently we allow I/O connections only to assembly objects */
  CipClass *assembly_class = GetCipClass(kCipAssemblyClassCode); /* we don't need to check for zero as this is handled in the connection path parsing */
  CipInstance *instance = NULL;

  ConnectionObject *io_connection_object = GetIoConnectionForConnectionData(
      connection_object, extended_error);

  if (NULL == io_connection_object) {
    return kCipErrorConnectionFailure;
  }

  /* TODO add check for transport type trigger */

  if (kConnectionTriggerTypeCyclicConnection
      != (io_connection_object->transport_type_class_trigger
          & kConnectionTriggerTypeProductionTriggerMask)) {
    if (256 == io_connection_object->production_inhibit_time) {
      /* there was no PIT segment in the connection path set PIT to one fourth of RPI */
      io_connection_object->production_inhibit_time =
          ((EipUint16) (io_connection_object->t_to_o_requested_packet_interval)
              / 4000);
    } else {
      /* if production inhibit time has been provided it needs to be smaller than the RPI */
      if (io_connection_object->production_inhibit_time
          > ((EipUint16) ((io_connection_object
              ->t_to_o_requested_packet_interval) / 1000))) {
        /* see section C-1.4.3.3 */
        *extended_error = 0x111; /**< RPI not supported. Extended Error code deprecated */
        return kCipErrorConnectionFailure;
      }
    }
  }
  /* set the connection call backs */
  io_connection_object->connection_close_function = CloseIoConnection;
  io_connection_object->connection_timeout_function = HandleIoConnectionTimeOut;
  io_connection_object->connection_send_data_function = SendConnectedData;
  io_connection_object->connection_receive_data_function =
      HandleReceivedIoConnectionData;

  GeneralConnectionConfiguration(io_connection_object);

  originator_to_target_connection_type = (io_connection_object
      ->o_to_t_network_connection_parameter & 0x6000) >> 13;
  target_to_originator_connection_type = (io_connection_object
      ->t_to_o_network_connection_parameter & 0x6000) >> 13;

  if ((originator_to_target_connection_type == 0)
      && (target_to_originator_connection_type == 0)) { /* this indicates an re-configuration of the connection currently not supported and we should not come here as this is handled in the forwardopen function*/

  } else {
    int producing_index = 0;
    int data_size;
    int diff_size;
    int is_heartbeat;

    if ((originator_to_target_connection_type != 0)
        && (target_to_originator_connection_type != 0)) { /* we have a producing and consuming connection*/
      producing_index = 1;
    }

    io_connection_object->consuming_instance = 0;
    io_connection_object->consumed_connection_path_length = 0;
    io_connection_object->producing_instance = 0;
    io_connection_object->produced_connection_path_length = 0;

    if (originator_to_target_connection_type != 0) { /*setup consumer side*/
      if (0
          != (instance = GetCipInstance(
              assembly_class,
              io_connection_object->connection_path.connection_point[0]))) { /* consuming Connection Point is present */
        io_connection_object->consuming_instance = instance;

        io_connection_object->consumed_connection_path_length = 6;
        io_connection_object->consumed_connection_path.path_size = 6;
        io_connection_object->consumed_connection_path.class_id =
            io_connection_object->connection_path.class_id;
        io_connection_object->consumed_connection_path.instance_number =
            io_connection_object->connection_path.connection_point[0];
        io_connection_object->consumed_connection_path.attribute_number = 3;

        attribute = GetCipAttribute(instance, 3);
        OPENER_ASSERT(attribute != NULL);
        /* an assembly object should always have an attribute 3 */
        data_size = io_connection_object->consumed_connection_size;
        diff_size = 0;
        is_heartbeat = (((CipByteArray *) attribute->data)->length == 0);

        if ((io_connection_object->transport_type_class_trigger & 0x0F) == 1) {
          /* class 1 connection */
          data_size -= 2; /* remove 16-bit sequence count length */
          diff_size += 2;
        }
        if ((kOpenerConsumedDataHasRunIdleHeader) &&(data_size > 0)
            && (!is_heartbeat)) { /* we only have an run idle header if it is not an heartbeat connection */
          data_size -= 4; /* remove the 4 bytes needed for run/idle header */
          diff_size += 4;
        }
        if (((CipByteArray *) attribute->data)->length != data_size) {
          /*wrong connection size */
          connection_object->correct_originator_to_target_size =
              ((CipByteArray *) attribute->data)->length + diff_size;
          *extended_error =
              kConnectionManagerStatusCodeErrorInvalidOToTConnectionSize;
          return kCipErrorConnectionFailure;
        }
      } else {
        *extended_error =
            kConnectionManagerStatusCodeInvalidConsumingApllicationPath;
        return kCipErrorConnectionFailure;
      }
    }

    if (target_to_originator_connection_type != 0) { /*setup producer side*/
      if (0
          != (instance =
              GetCipInstance(
                  assembly_class,
                  io_connection_object->connection_path.connection_point[producing_index]))) {
        io_connection_object->producing_instance = instance;

        io_connection_object->produced_connection_path_length = 6;
        io_connection_object->produced_connection_path.path_size = 6;
        io_connection_object->produced_connection_path.class_id =
            io_connection_object->connection_path.class_id;
        io_connection_object->produced_connection_path.instance_number =
            io_connection_object->connection_path.connection_point[producing_index];
        io_connection_object->produced_connection_path.attribute_number = 3;

        attribute = GetCipAttribute(instance, 3);
        OPENER_ASSERT(attribute != NULL);
        /* an assembly object should always have an attribute 3 */
        data_size = io_connection_object->produced_connection_size;
        diff_size = 0;
        is_heartbeat = (((CipByteArray *) attribute->data)->length == 0);

        if ((io_connection_object->transport_type_class_trigger & 0x0F) == 1) {
          /* class 1 connection */
          data_size -= 2; /* remove 16-bit sequence count length */
          diff_size += 2;
        }
        if ((kOpenerProducedDataHasRunIdleHeader) &&(data_size > 0)
            && (!is_heartbeat)) { /* we only have an run idle header if it is not an heartbeat connection */
          data_size -= 4; /* remove the 4 bytes needed for run/idle header */
          diff_size += 4;
        }
        if (((CipByteArray *) attribute->data)->length != data_size) {
          /*wrong connection size*/
          connection_object->correct_target_to_originator_size =
              ((CipByteArray *) attribute->data)->length + diff_size;
          *extended_error =
              kConnectionManagerStatusCodeErrorInvalidTToOConnectionSize;
          return kCipErrorConnectionFailure;
        }

      } else {
        *extended_error =
            kConnectionManagerStatusCodeInvalidProducingApplicationPath;
        return kCipErrorConnectionFailure;
      }
    }

    if (NULL != g_config_data_buffer) { /* config data has been sent with this forward open request */
      *extended_error = HandleConfigData(assembly_class, io_connection_object);
      if (0 != *extended_error) {
        return kCipErrorConnectionFailure;
      }
    }

    eip_status = OpenCommunicationChannels(io_connection_object);
    if (kEipStatusOk != eip_status) {
      *extended_error = 0; /*TODO find out the correct extended error code*/
      return eip_status;
    }
  }

  AddNewActiveConnection(io_connection_object);
  CheckIoConnectionEvent(io_connection_object->connection_path.connection_point[0],
                    io_connection_object->connection_path.connection_point[1],
                    kIoConnectionEventOpened);
  return eip_status;
}