OpENer - Open Source EtherNet/IP(TM) I/O Target Stack  2.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
appcontype.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright (c) 2009, Rockwell Automation, Inc.
3  * All rights reserved.
4  *
5  ******************************************************************************/
6 
7 #include <string.h>
8 
9 #include "appcontype.h"
10 
11 #include "cipconnectionmanager.h"
12 #include "cipconnectionobject.h"
13 #include "opener_api.h"
14 #include "assert.h"
15 #include "trace.h"
16 #include "cipepath.h"
17 
19 typedef struct {
20  unsigned int output_assembly;
21  unsigned int input_assembly;
22  unsigned int config_assembly;
25 
27 typedef struct {
28  unsigned int output_assembly;
29  unsigned int input_assembly;
30  unsigned int config_assembly;
31  CipConnectionObject connection_data[
32  OPENER_CIP_NUM_INPUT_ONLY_CONNS_PER_CON_PATH]; /*< the connection data */
34 
36 typedef struct {
37  unsigned int output_assembly;
38  unsigned int input_assembly;
39  unsigned int config_assembly;
40  CipConnectionObject connection_data[
42  ];
44 
60  const CipConnectionObject *const RESTRICT connection_object,
61  EipUint16 *const extended_error);
62 
71  const CipConnectionObject *const RESTRICT connection_object,
72  EipUint16 *const extended_error);
73 
82  const CipConnectionObject *const RESTRICT connection_object,
83  EipUint16 *const extended_error);
84 
86  const unsigned int connection_number,
87  const unsigned int output_assembly,
88  const unsigned int input_assembly,
89  const unsigned int config_assembly) {
90  if (OPENER_CIP_NUM_EXLUSIVE_OWNER_CONNS > connection_number) {
91  g_exlusive_owner_connections[connection_number].output_assembly =
92  output_assembly;
93  g_exlusive_owner_connections[connection_number].input_assembly =
94  input_assembly;
95  g_exlusive_owner_connections[connection_number].config_assembly =
96  config_assembly;
97  }
98 }
99 
100 void ConfigureInputOnlyConnectionPoint(const unsigned int connection_number,
101  const unsigned int output_assembly,
102  const unsigned int input_assembly,
103  const unsigned int config_assembly) {
104  if (OPENER_CIP_NUM_INPUT_ONLY_CONNS > connection_number) {
105  g_input_only_connections[connection_number].output_assembly =
106  output_assembly;
107  g_input_only_connections[connection_number].input_assembly = input_assembly;
108  g_input_only_connections[connection_number].config_assembly =
109  config_assembly;
110  }
111 }
112 
113 void ConfigureListenOnlyConnectionPoint(const unsigned int connection_number,
114  const unsigned int output_assembly,
115  const unsigned int input_assembly,
116  const unsigned int config_assembly) {
117  if (OPENER_CIP_NUM_LISTEN_ONLY_CONNS > connection_number) {
118  g_listen_only_connections[connection_number].output_assembly =
119  output_assembly;
120  g_listen_only_connections[connection_number].input_assembly =
121  input_assembly;
122  g_listen_only_connections[connection_number].config_assembly =
123  config_assembly;
124  }
125 }
126 
128  CipConnectionObject *const RESTRICT connection_object,
129  EipUint16 *const extended_error) {
130 
131  *extended_error = 0;
132 
134  connection_object,
135  extended_error);
136  if (NULL == io_connection) {
137  if (kConnectionManagerExtendedStatusCodeSuccess == *extended_error) {
138  /* we found no connection and don't have an error so try input only next */
139  io_connection = GetInputOnlyConnection(connection_object, extended_error);
140  if (NULL == io_connection) {
141  if (kConnectionManagerExtendedStatusCodeSuccess == *extended_error) {
142  /* we found no connection and don't have an error so try listen only next */
143  io_connection = GetListenOnlyConnection(connection_object,
144  extended_error);
145  if ( (NULL == io_connection) && (kCipErrorSuccess == *extended_error) ) {
146  /* no application connection type was found that suits the given data */
147  *extended_error =
149  } else {
150  ConnectionObjectSetInstanceType(connection_object,
152  OPENER_TRACE_INFO("IO Listen only connection requested\n");
153  //Is listen only connection
154  }
155  }
156  } else {
157  ConnectionObjectSetInstanceType(connection_object,
159  OPENER_TRACE_INFO("IO Input only connection requested\n");
160  //is Input only connection
161  }
162  }
163  } else {
164  ConnectionObjectSetInstanceType(connection_object,
166  OPENER_TRACE_INFO("IO Exclusive Owner connection requested\n");
167  //Is exclusive owner connection
168  }
169 
170  if (NULL != io_connection) {
171  ConnectionObjectDeepCopy(io_connection, connection_object);
172  }
173 
174  return io_connection;
175 }
176 
178  const CipConnectionObject *const RESTRICT connection_object,
179  EipUint16 *const extended_error) {
180 
181  for (size_t i = 0; i < OPENER_CIP_NUM_EXLUSIVE_OWNER_CONNS; ++i) {
182  if ( (g_exlusive_owner_connections[i].output_assembly ==
183  connection_object->consumed_path.instance_id)
184  && (g_exlusive_owner_connections[i].input_assembly ==
185  connection_object->produced_path.instance_id)
186  && (g_exlusive_owner_connections[i].config_assembly ==
187  connection_object->configuration_path.instance_id) ) {
188 
189  /* check if on other connection point with the same output assembly is currently connected */
191  connection_object->produced_path.instance_id);
192  if ( NULL
193  != exclusive_owner ) {
195  ConnectionObjectGetState(exclusive_owner) ) {
196  *extended_error =
198  OPENER_TRACE_INFO("Hit an Ownership conflict in appcontype.c:198\n");
199  break;
200  }
202  ConnectionObjectGetState(exclusive_owner)
203  && ConnectionObjectEqualOriginator(connection_object,
204  exclusive_owner) ) {
205  g_exlusive_owner_connections[i].connection_data.
206  connection_close_function(&(g_exlusive_owner_connections[i].
207  connection_data) );
208  return &(g_exlusive_owner_connections[i].connection_data);
209  } else {
210  *extended_error =
213  "Hit an Ownership conflict with timed out connection");
214  break;
215  }
216  }
217  return &(g_exlusive_owner_connections[i].connection_data);
218  }
219  }
220  return NULL;
221 }
222 
224  const CipConnectionObject *const RESTRICT connection_object,
225  EipUint16 *const extended_error) {
226 
227  for (size_t i = 0; i < OPENER_CIP_NUM_INPUT_ONLY_CONNS; ++i) {
228  if (g_input_only_connections[i].output_assembly
229  == connection_object->consumed_path.instance_id) { /* we have the same output assembly */
230  if (g_input_only_connections[i].input_assembly
231  != connection_object->produced_path.instance_id) {
232  *extended_error =
234  break;
235  }
236  if (g_input_only_connections[i].config_assembly
237  != connection_object->configuration_path.instance_id) {
238  *extended_error =
240  break;
241  }
242 
243  for (size_t j = 0; j < OPENER_CIP_NUM_INPUT_ONLY_CONNS_PER_CON_PATH;
244  ++j) {
246  == ConnectionObjectGetState(&(g_input_only_connections[i].
247  connection_data[j]) )
248  && ConnectionObjectEqualOriginator(connection_object,
249  &(g_input_only_connections[i].
250  connection_data[j]) ) )
251  {
252  g_input_only_connections[i].connection_data[j].
253  connection_close_function(
254  &g_input_only_connections[i].connection_data[j]);
255  return &(g_input_only_connections[i].connection_data[j]);
256  }
257  }
258 
259  for (size_t j = 0; j < OPENER_CIP_NUM_INPUT_ONLY_CONNS_PER_CON_PATH;
260  ++j) {
262  == ConnectionObjectGetState(&(g_input_only_connections[i].
263  connection_data[j]) ) ) {
264  return &(g_input_only_connections[i].connection_data[j]);
265  }
266  }
267  *extended_error =
269  break;
270  }
271  }
272  return NULL;
273 }
274 
276  const CipConnectionObject *const RESTRICT connection_object,
277  EipUint16 *const extended_error) {
278 
279  for (size_t i = 0; i < OPENER_CIP_NUM_LISTEN_ONLY_CONNS; i++) {
280  if (g_listen_only_connections[i].output_assembly
281  == connection_object->consumed_path.instance_id) { /* we have the same output assembly */
282  if (g_listen_only_connections[i].input_assembly
283  != connection_object->produced_path.instance_id) {
284  *extended_error =
286  break;
287  }
288  if (g_listen_only_connections[i].config_assembly
289  != connection_object->configuration_path.instance_id) {
290  *extended_error =
292  break;
293  }
294 
295  if ( NULL
297  connection_object->produced_path.instance_id) ) {
298  *extended_error =
300  break;
301  }
302 
303  for (size_t j = 0; j < OPENER_CIP_NUM_LISTEN_ONLY_CONNS_PER_CON_PATH;
304  ++j) {
306  == ConnectionObjectGetState(&(g_listen_only_connections[i].
307  connection_data[j]) )
308  && ConnectionObjectEqualOriginator(connection_object,
309  &(g_listen_only_connections[i].
310  connection_data[j]) ) )
311  {
312  g_listen_only_connections[i].connection_data[j].
313  connection_close_function(
314  &g_listen_only_connections[i].connection_data[j]);
315  return &(g_listen_only_connections[i].connection_data[j]);
316  }
317  }
318 
319  for (size_t j = 0; j < OPENER_CIP_NUM_LISTEN_ONLY_CONNS_PER_CON_PATH;
320  j++) {
322  == ConnectionObjectGetState(&(g_listen_only_connections[i].
323  connection_data[j]) ) ) {
324  return &(g_listen_only_connections[i].connection_data[j]);
325  }
326  }
327  *extended_error =
329  break;
330  }
331  }
332  return NULL;
333 }
334 
336  const EipUint32 input_point) {
338 
339  while (NULL != node) {
340  CipConnectionObject *producer_multicast_connection = node->data;
341  if ( true ==
342  ConnectionObjectIsTypeIOConnection(producer_multicast_connection) &&
343  (input_point ==
344  producer_multicast_connection->produced_path.instance_id) &&
346  ConnectionObjectGetTToOConnectionType(producer_multicast_connection) )
347  &&
348  (kEipInvalidSocket !=
349  producer_multicast_connection->socket[
351  {
352  /* we have a connection that produces the same input assembly,
353  * is a multicast producer and manages the connection.
354  */
355  return producer_multicast_connection;
356  }
357  node = node->next;
358  }
359  return NULL;
360 }
361 
363  const EipUint32 input_point) {
365 
366  while (NULL != node) {
367  CipConnectionObject *next_non_control_master_connection =
368  node->data;
369  if ( true == ConnectionObjectIsTypeNonLOIOConnection(next_non_control_master_connection)
370  && kConnectionObjectStateEstablished == ConnectionObjectGetState(next_non_control_master_connection)
371  && input_point == next_non_control_master_connection->produced_path.instance_id
373  && (kEipInvalidSocket == next_non_control_master_connection->socket[kUdpCommuncationDirectionProducing]) ) {
374  /* we have a connection that produces the same input assembly,
375  * is a multicast producer and does not manage the connection.
376  */
377  return next_non_control_master_connection;
378  }
379  node = node->next;
380  }
381  return NULL;
382 }
383 
385  const ConnectionObjectInstanceType instance_type)
386 {
387 
388  OPENER_TRACE_INFO("Close all instance type %d only connections\n", instance_type);
390  while (NULL != node) {
391  CipConnectionObject *connection = node->data;
392  node = node->next;
393  if ( (instance_type == ConnectionObjectGetInstanceType(connection))
394  && (input_point == connection->produced_path.instance_id) ) {
395  CipConnectionObject *connection_to_delete = connection;
397  connection_to_delete->consumed_path.instance_id,
398  connection_to_delete->produced_path.instance_id,
400 
401  assert(connection_to_delete->connection_close_function != NULL);
402  connection_to_delete->connection_close_function(connection_to_delete);
403  }
404  }
405 }
406 
409  while (NULL != node) {
410  CipConnectionObject *connection = node->data;
411  assert(connection->connection_close_function != NULL);
412  connection->connection_close_function(connection);
413  node = connection_list.first;
414  }
415 }
416 
419 
420  while (NULL != node) {
421  CipConnectionObject *connection = node->data;
422  OPENER_ASSERT(NULL != connection)
423  if (config_point == connection->configuration_path.instance_id) {
424  return true;
425  }
426  node = node->next;
427  }
428  return false;
429 }
430 
432  memset( g_exlusive_owner_connections, 0,
434  sizeof(ExclusiveOwnerConnection) );
435  memset( g_input_only_connections, 0,
437  memset( g_listen_only_connections, 0,
439 }
bool ConnectionObjectIsTypeNonLOIOConnection(const CipConnectionObject *const connection_object)
unsigned int output_assembly
Definition: appcontype.c:37
unsigned int output_assembly
Definition: appcontype.c:28
bool ConnectionObjectIsTypeIOConnection(const CipConnectionObject *const connection_object)
Tracing infrastructure for OpENer.
#define OPENER_CIP_NUM_LISTEN_ONLY_CONNS
Define the number of supported listen only connections. Each of these connections has to be configure...
DoublyLinkedListNode * first
CipConnectionObject * GetConnectedOutputAssembly(const EipUint32 output_assembly_id)
Listen Only connection data.
Definition: appcontype.c:36
#define OPENER_ASSERT(assertion)
CipConnectionObject connection_data[OPENER_CIP_NUM_INPUT_ONLY_CONNS_PER_CON_PATH]
Definition: appcontype.c:32
ConnectionObjectConnectionType ConnectionObjectGetTToOConnectionType(const CipConnectionObject *const connection_object)
CipConnectionObject * GetNextNonControlMasterConnection(const EipUint32 input_point)
check if there exists an producing multicast exclusive owner or listen only connection that should pr...
Definition: appcontype.c:362
CipDword instance_id
Definition: cipepath.h:165
unsigned int output_assembly
Definition: appcontype.c:20
CipConnectionObject * GetExistingProducerMulticastConnection(const EipUint32 input_point)
Check if there exists already an exclusive owner or listen only connection which produces the input a...
Definition: appcontype.c:335
#define OPENER_CIP_NUM_INPUT_ONLY_CONNS
Define the number of supported input only connections. Each of these connections has to be configured...
void ConnectionObjectSetInstanceType(CipConnectionObject *const connection_object, const ConnectionObjectInstanceType instance_type)
unsigned int input_assembly
Definition: appcontype.c:21
ConnectionCloseFunction connection_close_function
ListenOnlyConnection g_listen_only_connections[OPENER_CIP_NUM_LISTEN_ONLY_CONNS]
Definition: appcontype.c:50
void CheckIoConnectionEvent(unsigned int output_assembly_id, unsigned int input_assembly_id, IoConnectionEvent io_connection_event)
Inform the application on changes occurred for a connection.
void ConnectionObjectDeepCopy(CipConnectionObject *RESTRICT destination, const CipConnectionObject *RESTRICT const source)
Copy the given connection data from source to destination.
void CloseAllConnectionsForInputWithSameType(const EipUint32 input_point, const ConnectionObjectInstanceType instance_type)
Close all connection producing the same input and have the same type (i.e., listen only or input only...
Definition: appcontype.c:384
Exclusive Owner connection data.
Definition: appcontype.c:19
void ConfigureListenOnlyConnectionPoint(const unsigned int connection_number, const unsigned int output_assembly, const unsigned int input_assembly, const unsigned int config_assembly)
Configures the connection point for a listen only connection.
Definition: appcontype.c:113
unsigned int config_assembly
Definition: appcontype.c:22
bool ConnectionWithSameConfigPointExists(const EipUint32 config_point)
Check if there is an established connection that uses the same config point.
Definition: appcontype.c:417
DoublyLinkedListNode * next
bool ConnectionObjectEqualOriginator(const CipConnectionObject *const object1, const CipConnectionObject *const object2)
uint32_t EipUint32
Definition: typedefs.h:34
ConnectionObjectInstanceType
void ConfigureInputOnlyConnectionPoint(const unsigned int connection_number, const unsigned int output_assembly, const unsigned int input_assembly, const unsigned int config_assembly)
Configures the connection point for an input only connection.
Definition: appcontype.c:100
#define OPENER_TRACE_INFO(...)
Definition: trace.h:89
CipConnectionPathEpath produced_path
void ConfigureExclusiveOwnerConnectionPoint(const unsigned int connection_number, const unsigned int output_assembly, const unsigned int input_assembly, const unsigned int config_assembly)
Configures the connection point for an exclusive owner connection.
Definition: appcontype.c:85
#define OPENER_CIP_NUM_EXLUSIVE_OWNER_CONNS
Define the number of supported exclusive owner connections. Each of these connections has to be confi...
ConnectionObjectState ConnectionObjectGetState(const CipConnectionObject *const connection_object)
CipConnectionPathEpath configuration_path
unsigned int input_assembly
Definition: appcontype.c:29
CipConnectionObject connection_data
Definition: appcontype.c:23
InputOnlyConnection g_input_only_connections[OPENER_CIP_NUM_INPUT_ONLY_CONNS]
Definition: appcontype.c:48
void CloseAllConnections(void)
Definition: appcontype.c:407
DoublyLinkedList connection_list
#define OPENER_CIP_NUM_INPUT_ONLY_CONNS_PER_CON_PATH
Define the number of supported input only connections per connection path.
unsigned int input_assembly
Definition: appcontype.c:38
Input Only connection data.
Definition: appcontype.c:27
CipConnectionPathEpath consumed_path
CipConnectionObject * GetIoConnectionForConnectionData(CipConnectionObject *const RESTRICT connection_object, EipUint16 *const extended_error)
check if for the given connection data received in a forward_open request a suitable connection is av...
Definition: appcontype.c:127
CipConnectionObject * GetListenOnlyConnection(const CipConnectionObject *const RESTRICT connection_object, EipUint16 *const extended_error)
Takes an ConnectionObject and searches and returns an Listen Only Connection based on the ConnectionO...
Definition: appcontype.c:275
ExclusiveOwnerConnection g_exlusive_owner_connections[OPENER_CIP_NUM_EXLUSIVE_OWNER_CONNS]
Definition: appcontype.c:46
CipConnectionObject connection_data[OPENER_CIP_NUM_LISTEN_ONLY_CONNS_PER_CON_PATH]
Definition: appcontype.c:42
uint16_t EipUint16
Definition: typedefs.h:33
ConnectionObjectInstanceType ConnectionObjectGetInstanceType(const CipConnectionObject *const connection_object)
unsigned int config_assembly
Definition: appcontype.c:39
void InitializeIoConnectionData(void)
Definition: appcontype.c:431
CipConnectionObject * GetExclusiveOwnerConnection(const CipConnectionObject *const RESTRICT connection_object, EipUint16 *const extended_error)
Takes an ConnectionObject and searches and returns an Exclusive Owner Connection based on the Connect...
Definition: appcontype.c:177
unsigned int config_assembly
Definition: appcontype.c:30
CipConnectionObject * GetInputOnlyConnection(const CipConnectionObject *const RESTRICT connection_object, EipUint16 *const extended_error)
Takes an ConnectionObject and searches and returns an Input Only Connection based on the ConnectionOb...
Definition: appcontype.c:223
#define OPENER_CIP_NUM_LISTEN_ONLY_CONNS_PER_CON_PATH
Define the number of supported Listen only connections per connection path.