Example #1
0
EipUint16 HandleConfigData(CipClass *assembly_class,
                           ConnectionObject *connection_object) {
  EipUint16 connection_manager_status = 0;
  CipInstance *config_instance = GetCipInstance(
      assembly_class, connection_object->connection_path.connection_point[2]);

  if (0 != g_config_data_length) {
    if (ConnectionWithSameConfigPointExists(
        connection_object->connection_path.connection_point[2])) { /* there is a connected connection with the same config point
         * we have to have the same data as already present in the config point*/
      CipByteArray *p = (CipByteArray *) GetCipAttribute(config_instance, 3)
          ->data;
      if (p->length != g_config_data_length) {
        connection_manager_status =
            kConnectionManagerStatusCodeErrorOwnershipConflict;
      } else {
        /*FIXME check if this is correct */
        if (memcmp(p->data, g_config_data_buffer, g_config_data_length)) {
          connection_manager_status =
              kConnectionManagerStatusCodeErrorOwnershipConflict;
        }
      }
    } else {
      /* put the data on the configuration assembly object with the current
       design this can be done rather efficiently */
      if (kEipStatusOk
          != NotifyAssemblyConnectedDataReceived(config_instance,
                                                 g_config_data_buffer,
                                                 g_config_data_length)) {
        OPENER_TRACE_WARN("Configuration data was invalid\n");
        connection_manager_status =
            kConnectionManagerStatusCodeInvalidConfigurationApplicationPath;
      }
    }
  }
  return connection_manager_status;
}
Example #2
0
/**** 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;
}
Example #3
0
  ShutdownTcpIpInterface();

  /*no clear all the instances and classes */
  DeleteAllClasses();
}

EipStatus NotifyClass(const CipClass *RESTRICT const cip_class,
                      CipMessageRouterRequest *const message_router_request,
                      CipMessageRouterResponse *const message_router_response,
                      struct sockaddr *originator_address,
                      const int encapsulation_session) {

  /* find the instance: if instNr==0, the class is addressed, else find the instance */
  EipUint16 instance_number =
    message_router_request->request_path.instance_number;                     /* get the instance number */
  CipInstance *instance = GetCipInstance(cip_class, instance_number);       /* look up the instance (note that if inst==0 this will be the class itself) */
  if (instance)       /* if instance is found */
  {
    OPENER_TRACE_INFO("notify: found instance %d%s\n", instance_number,
                      instance_number == 0 ? " (class object)" : "");

    CipServiceStruct *service = instance->cip_class->services;             /* get pointer to array of services */
    if (NULL != service)             /* if services are defined */
    {
      for (size_t i = 0; i < instance->cip_class->number_of_services; i++)                   /* seach the services list */
      {
        if (message_router_request->service == service->service_number)                         /* if match is found */
        {
          /* call the service, and return what it returns */
          OPENER_TRACE_INFO("notify: calling %s service\n",
                            service->name);