generic_networkhandler.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741
  1. /*******************************************************************************
  2. * Copyright (c) 2009, Rockwell Automation, Inc.
  3. * All rights reserved.
  4. *
  5. ******************************************************************************/
  6. /** @file generic_networkhandler.c
  7. * @author Martin Melik Merkumians
  8. * @brief This file includes all platform-independent functions of the network handler to reduce code duplication
  9. *
  10. * The generic network handler delegates platform-dependent tasks to the platform network handler
  11. */
  12. #include <assert.h>
  13. #include "generic_networkhandler.h"
  14. #include "typedefs.h"
  15. #include "trace.h"
  16. #include "opener_error.h"
  17. #include "encap.h"
  18. #include "ciptcpipinterface.h"
  19. /** @brief handle any connection request coming in the TCP server socket.
  20. *
  21. */
  22. void CheckAndHandleTcpListenerSocket(void);
  23. /** @brief Checks and processes request received via the UDP unicast socket, currently the implementation is port-specific
  24. *
  25. */
  26. void CheckAndHandleUdpUnicastSocket(void);
  27. /** @brief Checks and handles incoming messages via UDP broadcast
  28. *
  29. */
  30. void CheckAndHandleUdpGlobalBroadcastSocket(void);
  31. /** @brief check if on one of the UDP consuming sockets data has been received and if yes handle it correctly
  32. *
  33. */
  34. void CheckAndHandleConsumingUdpSockets(void);
  35. /** @brief Handles data on an established TCP connection, processed connection is given by socket
  36. *
  37. * @param socket The socket to be processed
  38. * @return kEipStatusOk on success, or kEipStatusError on failure
  39. */
  40. EipStatus HandleDataOnTcpSocket(int socket);
  41. /*************************************************
  42. * Function implementations from now on
  43. *************************************************/
  44. EipStatus NetworkHandlerInitialize(void) {
  45. if(kEipStatusOk != NetworkHandlerInitializePlatform()) {
  46. return kEipStatusError;
  47. }
  48. /* clear the master an temp sets */
  49. FD_ZERO(&master_socket);
  50. FD_ZERO(&read_socket);
  51. /* create a new TCP socket */
  52. if ((g_network_status.tcp_listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))
  53. == -1) {
  54. int error_code = GetSocketErrorNumber();
  55. char* error_message = GetErrorMessage(error_code);
  56. OPENER_TRACE_ERR("error allocating socket stream listener, %d - %s\n", error_code, error_message);
  57. FreeErrorMessage(error_message);
  58. return kEipStatusError;
  59. }
  60. int set_socket_option_value = 1; //Represents true for used set socket options
  61. /* Activates address reuse */
  62. if (setsockopt(g_network_status.tcp_listener, SOL_SOCKET, SO_REUSEADDR,
  63. (char *) &set_socket_option_value,
  64. sizeof(set_socket_option_value)) == -1) {
  65. OPENER_TRACE_ERR(
  66. "error setting socket option SO_REUSEADDR on tcp_listener\n");
  67. return kEipStatusError;
  68. }
  69. /* create a new UDP socket */
  70. if ((g_network_status.udp_global_broadcast_listener = socket(AF_INET,
  71. SOCK_DGRAM,
  72. IPPROTO_UDP))
  73. == -1) {
  74. int error_code = GetSocketErrorNumber();
  75. char* error_message = GetErrorMessage(error_code);
  76. OPENER_TRACE_ERR("error allocating UDP global broadcast listener socket, %d - %s\n",
  77. error_code, error_message);
  78. FreeErrorMessage(error_message);
  79. return kEipStatusError;
  80. }
  81. /* create a new UDP socket */
  82. if ((g_network_status.udp_unicast_listener = socket(AF_INET, SOCK_DGRAM,
  83. IPPROTO_UDP)) == -1) {
  84. int error_code = GetSocketErrorNumber();
  85. char* error_message = GetErrorMessage(error_code);
  86. OPENER_TRACE_ERR("error allocating UDP unicast listener socket, %d - %s\n",
  87. error_code, error_message);
  88. FreeErrorMessage(error_message);
  89. return kEipStatusError;
  90. }
  91. /* Activates address reuse */
  92. if (setsockopt(g_network_status.udp_global_broadcast_listener, SOL_SOCKET,
  93. SO_REUSEADDR, (char *) &set_socket_option_value,
  94. sizeof(set_socket_option_value)) == -1) {
  95. OPENER_TRACE_ERR(
  96. "error setting socket option SO_REUSEADDR on udp_broadcast_listener\n");
  97. return kEipStatusError;
  98. }
  99. /* Activates address reuse */
  100. if (setsockopt(g_network_status.udp_unicast_listener, SOL_SOCKET,
  101. SO_REUSEADDR, (char *) &set_socket_option_value,
  102. sizeof(set_socket_option_value)) == -1) {
  103. OPENER_TRACE_ERR(
  104. "error setting socket option SO_REUSEADDR on udp_unicast_listener\n");
  105. return kEipStatusError;
  106. }
  107. struct sockaddr_in my_address = { .sin_family = AF_INET, .sin_port = htons(
  108. kOpenerEthernetPort), .sin_addr.s_addr = interface_configuration_
  109. .ip_address };
  110. /* bind the new socket to port 0xAF12 (CIP) */
  111. if ((bind(g_network_status.tcp_listener, (struct sockaddr *) &my_address,
  112. sizeof(struct sockaddr))) == -1) {
  113. int error_code = GetSocketErrorNumber();
  114. char* error_message = GetErrorMessage(error_code);
  115. OPENER_TRACE_ERR("error with TCP bind: %d - %s\n", error_code, error_message);
  116. FreeErrorMessage(error_message);
  117. return kEipStatusError;
  118. }
  119. if ((bind(g_network_status.udp_unicast_listener,
  120. (struct sockaddr *) &my_address, sizeof(struct sockaddr))) == -1) {
  121. int error_code = GetSocketErrorNumber();
  122. char* error_message = GetErrorMessage(error_code);
  123. OPENER_TRACE_ERR("error with UDP unicast bind: %d - %s\n", error_code, error_message);
  124. FreeErrorMessage(error_message);
  125. return kEipStatusError;
  126. }
  127. struct sockaddr_in global_broadcast_address = { .sin_family = AF_INET,
  128. .sin_port = htons(kOpenerEthernetPort), .sin_addr.s_addr= htonl(INADDR_ANY) };
  129. /* enable the UDP socket to receive broadcast messages */
  130. if (0
  131. > setsockopt(g_network_status.udp_global_broadcast_listener, SOL_SOCKET, SO_BROADCAST,
  132. (char *) &set_socket_option_value, sizeof(int))) {
  133. int error_code = GetSocketErrorNumber();
  134. char* error_message = GetErrorMessage(error_code);
  135. OPENER_TRACE_ERR(
  136. "error with setting broadcast receive for UDP socket: %d - %s\n",
  137. error_code, error_message);
  138. FreeErrorMessage(error_message);
  139. return kEipStatusError;
  140. }
  141. if ((bind(g_network_status.udp_global_broadcast_listener,
  142. (struct sockaddr *) &global_broadcast_address,
  143. sizeof(struct sockaddr))) == -1) {
  144. int error_code = GetSocketErrorNumber();
  145. char* error_message = GetErrorMessage(error_code);
  146. OPENER_TRACE_ERR("error with global broadcast UDP bind: %d - %s\n", error_code, error_message);
  147. FreeErrorMessage(error_message);
  148. return kEipStatusError;
  149. }
  150. /* switch socket in listen mode */
  151. if ((listen(g_network_status.tcp_listener, MAX_NO_OF_TCP_SOCKETS)) == -1) {
  152. int error_code = GetSocketErrorNumber();
  153. char* error_message = GetErrorMessage(error_code);
  154. OPENER_TRACE_ERR("networkhandler: error with listen: %d - %s\n", error_code, error_message);
  155. FreeErrorMessage(error_message);
  156. return kEipStatusError;
  157. }
  158. /* add the listener socket to the master set */
  159. FD_SET(g_network_status.tcp_listener, &master_socket);
  160. FD_SET(g_network_status.udp_unicast_listener, &master_socket);
  161. FD_SET(g_network_status.udp_global_broadcast_listener, &master_socket);
  162. /* keep track of the biggest file descriptor */
  163. highest_socket_handle = GetMaxSocket(
  164. g_network_status.tcp_listener,
  165. g_network_status.udp_global_broadcast_listener,
  166. 0,
  167. g_network_status.udp_unicast_listener);
  168. g_last_time = GetMilliSeconds(); /* initialize time keeping */
  169. g_network_status.elapsed_time = 0;
  170. return kEipStatusOk;
  171. }
  172. void IApp_CloseSocket_udp(int socket_handle) {
  173. CloseSocket(socket_handle);
  174. }
  175. void IApp_CloseSocket_tcp(int socket_handle) {
  176. CloseSocket(socket_handle);
  177. }
  178. EipBool8 CheckSocketSet(int socket) {
  179. EipBool8 return_value = false;
  180. if (FD_ISSET(socket, &read_socket)) {
  181. if (FD_ISSET(socket, &master_socket)) {
  182. return_value = true;
  183. } else {
  184. OPENER_TRACE_INFO("socket: %d closed with pending message\n", socket);
  185. }
  186. FD_CLR(socket, &read_socket);
  187. /* remove it from the read set so that later checks will not find it */
  188. }
  189. return return_value;
  190. }
  191. void CheckAndHandleTcpListenerSocket(void) {
  192. int new_socket;
  193. /* see if this is a connection request to the TCP listener*/
  194. if (true == CheckSocketSet(g_network_status.tcp_listener)) {
  195. OPENER_TRACE_INFO("networkhandler: new TCP connection\n");
  196. new_socket = accept(g_network_status.tcp_listener, NULL, NULL);
  197. if (new_socket == -1) {
  198. int error_code = GetSocketErrorNumber();
  199. char* error_message = GetErrorMessage(error_code);
  200. OPENER_TRACE_ERR("networkhandler: error on accept: %d - %s\n",
  201. error_code, error_message);
  202. FreeErrorMessage(error_message);
  203. return;
  204. }
  205. FD_SET(new_socket, &master_socket);
  206. /* add newfd to master set */
  207. if (new_socket > highest_socket_handle) {
  208. highest_socket_handle = new_socket;
  209. }
  210. OPENER_TRACE_STATE("networkhandler: opened new TCP connection on fd %d\n",
  211. new_socket);
  212. }
  213. }
  214. EipStatus NetworkHandlerProcessOnce(void) {
  215. read_socket = master_socket;
  216. g_time_value.tv_sec = 0;
  217. g_time_value.tv_usec = (
  218. g_network_status.elapsed_time < kOpenerTimerTickInMilliSeconds ?
  219. kOpenerTimerTickInMilliSeconds - g_network_status.elapsed_time : 0)
  220. * 1000; /* 10 ms */
  221. int ready_socket = select(highest_socket_handle + 1, &read_socket, 0, 0,
  222. &g_time_value);
  223. if (ready_socket == kEipInvalidSocket) {
  224. if (EINTR == errno) /* we have somehow been interrupted. The default behavior is to go back into the select loop. */
  225. {
  226. return kEipStatusOk;
  227. } else {
  228. int error_code = GetSocketErrorNumber();
  229. char* error_message = GetErrorMessage(error_code);
  230. OPENER_TRACE_ERR("networkhandler: error with select: %d - %s\n", error_code, error_message);
  231. FreeErrorMessage(error_message);
  232. return kEipStatusError;
  233. }
  234. }
  235. if (ready_socket > 0) {
  236. CheckAndHandleTcpListenerSocket();
  237. CheckAndHandleUdpUnicastSocket();
  238. CheckAndHandleUdpGlobalBroadcastSocket();
  239. CheckAndHandleConsumingUdpSockets();
  240. for (int socket = 0; socket <= highest_socket_handle; socket++) {
  241. if (true == CheckSocketSet(socket)) {
  242. /* if it is still checked it is a TCP receive */
  243. if (kEipStatusError == HandleDataOnTcpSocket(socket)) /* if error */
  244. {
  245. CloseSocket(socket);
  246. CloseSession(socket); /* clean up session and close the socket */
  247. }
  248. }
  249. }
  250. }
  251. g_actual_time = GetMilliSeconds();
  252. g_network_status.elapsed_time += g_actual_time - g_last_time;
  253. g_last_time = g_actual_time;
  254. /* check if we had been not able to update the connection manager for several OPENER_TIMER_TICK.
  255. * This should compensate the jitter of the windows timer
  256. */
  257. if (g_network_status.elapsed_time >= kOpenerTimerTickInMilliSeconds) {
  258. /* call manage_connections() in connection manager every OPENER_TIMER_TICK ms */
  259. ManageConnections(g_network_status.elapsed_time);
  260. g_network_status.elapsed_time = 0;
  261. }
  262. return kEipStatusOk;
  263. }
  264. EipStatus NetworkHandlerFinish(void) {
  265. CloseSocket(g_network_status.tcp_listener);
  266. CloseSocket(g_network_status.udp_unicast_listener);
  267. CloseSocket(g_network_status.udp_global_broadcast_listener);
  268. return kEipStatusOk;
  269. }
  270. void CheckAndHandleUdpGlobalBroadcastSocket(void) {
  271. struct sockaddr_in from_address;
  272. socklen_t from_address_length;
  273. /* see if this is an unsolicited inbound UDP message */
  274. if (true == CheckSocketSet(g_network_status.udp_global_broadcast_listener)) {
  275. from_address_length = sizeof(from_address);
  276. OPENER_TRACE_STATE(
  277. "networkhandler: unsolicited UDP message on EIP global broadcast socket\n");
  278. /* Handle UDP broadcast messages */
  279. int received_size = recvfrom(g_network_status.udp_global_broadcast_listener,
  280. g_ethernet_communication_buffer,
  281. PC_OPENER_ETHERNET_BUFFER_SIZE,
  282. 0, (struct sockaddr *) &from_address,
  283. &from_address_length);
  284. if (received_size <= 0) { /* got error */
  285. int error_code = GetSocketErrorNumber();
  286. char* error_message = GetErrorMessage(error_code);
  287. OPENER_TRACE_ERR(
  288. "networkhandler: error on recvfrom UDP global broadcast port: %d - %s\n", error_code, error_message);
  289. FreeErrorMessage(error_message);
  290. return;
  291. }
  292. OPENER_TRACE_INFO("Data received on global broadcast UDP:\n");
  293. EipUint8 *receive_buffer = &g_ethernet_communication_buffer[0];
  294. int remaining_bytes = 0;
  295. do {
  296. int reply_length = HandleReceivedExplictUdpData(
  297. g_network_status.udp_global_broadcast_listener, &from_address,
  298. receive_buffer, received_size, &remaining_bytes, false);
  299. receive_buffer += received_size - remaining_bytes;
  300. received_size = remaining_bytes;
  301. if (reply_length > 0) {
  302. OPENER_TRACE_INFO("reply sent:\n");
  303. /* if the active socket matches a registered UDP callback, handle a UDP packet */
  304. if (sendto(g_network_status.udp_global_broadcast_listener,
  305. (char *) g_ethernet_communication_buffer, reply_length, 0,
  306. (struct sockaddr *) &from_address, sizeof(from_address))
  307. != reply_length) {
  308. OPENER_TRACE_INFO(
  309. "networkhandler: UDP response was not fully sent\n");
  310. }
  311. }
  312. } while (remaining_bytes > 0);
  313. }
  314. }
  315. void CheckAndHandleUdpUnicastSocket(void) {
  316. struct sockaddr_in from_address;
  317. socklen_t from_address_length;
  318. /* see if this is an unsolicited inbound UDP message */
  319. if (true == CheckSocketSet(g_network_status.udp_unicast_listener)) {
  320. from_address_length = sizeof(from_address);
  321. OPENER_TRACE_STATE(
  322. "networkhandler: unsolicited UDP message on EIP unicast socket\n");
  323. /* Handle UDP broadcast messages */
  324. int received_size = recvfrom(g_network_status.udp_unicast_listener,
  325. g_ethernet_communication_buffer,
  326. PC_OPENER_ETHERNET_BUFFER_SIZE,
  327. 0, (struct sockaddr *) &from_address,
  328. &from_address_length);
  329. if (received_size <= 0) { /* got error */
  330. int error_code = GetSocketErrorNumber();
  331. char* error_message = GetErrorMessage(error_code);
  332. OPENER_TRACE_ERR(
  333. "networkhandler: error on recvfrom UDP unicast port: %d - %s\n", error_code, error_message);
  334. FreeErrorMessage(error_message);
  335. return;
  336. }
  337. OPENER_TRACE_INFO("Data received on UDP unicast:\n");
  338. EipUint8 *receive_buffer = &g_ethernet_communication_buffer[0];
  339. int remaining_bytes = 0;
  340. do {
  341. int reply_length = HandleReceivedExplictUdpData(
  342. g_network_status.udp_unicast_listener, &from_address, receive_buffer,
  343. received_size, &remaining_bytes, true);
  344. receive_buffer += received_size - remaining_bytes;
  345. received_size = remaining_bytes;
  346. if (reply_length > 0) {
  347. OPENER_TRACE_INFO("reply sent:\n");
  348. /* if the active socket matches a registered UDP callback, handle a UDP packet */
  349. if (sendto(g_network_status.udp_unicast_listener,
  350. (char *) g_ethernet_communication_buffer, reply_length, 0,
  351. (struct sockaddr *) &from_address, sizeof(from_address))
  352. != reply_length) {
  353. OPENER_TRACE_INFO(
  354. "networkhandler: UDP unicast response was not fully sent\n");
  355. }
  356. }
  357. } while (remaining_bytes > 0);
  358. }
  359. }
  360. EipStatus SendUdpData(struct sockaddr_in *address, int socket, EipUint8 *data,
  361. EipUint16 data_length) {
  362. int sent_length = sendto(socket, (char *) data, data_length, 0,
  363. (struct sockaddr *) address, sizeof(*address));
  364. if (sent_length < 0) {
  365. int error_code = GetSocketErrorNumber();
  366. char* error_message = GetErrorMessage(error_code);
  367. OPENER_TRACE_ERR("networkhandler: error with sendto in sendUDPData: %d - %s\n", error_code, error_message);
  368. FreeErrorMessage(error_message);
  369. return kEipStatusError;
  370. }
  371. if (sent_length != data_length) {
  372. OPENER_TRACE_WARN(
  373. "data length sent_length mismatch; probably not all data was sent in SendUdpData, sent %d of %d\n",
  374. sent_length, data_length);
  375. return kEipStatusError;
  376. }
  377. return kEipStatusOk;
  378. }
  379. EipStatus HandleDataOnTcpSocket(int socket) {
  380. int remaining_bytes = 0;
  381. long data_sent = PC_OPENER_ETHERNET_BUFFER_SIZE;
  382. /* We will handle just one EIP packet here the rest is done by the select
  383. * method which will inform us if more data is available in the socket
  384. because of the current implementation of the main loop this may not be
  385. the fastest way and a loop here with a non blocking socket would better
  386. fit*/
  387. /*Check how many data is here -- read the first four bytes from the connection */
  388. long number_of_read_bytes = recv(socket, g_ethernet_communication_buffer, 4,
  389. 0); /*TODO we may have to set the socket to a non blocking socket */
  390. if (number_of_read_bytes == 0) {
  391. int error_code = GetSocketErrorNumber();
  392. char* error_message = GetErrorMessage(error_code);
  393. OPENER_TRACE_ERR("networkhandler: connection closed by client: %d - %s\n", error_code, error_message);
  394. FreeErrorMessage(error_message); // free(error_message);
  395. return kEipStatusError;
  396. }
  397. if (number_of_read_bytes < 0) {
  398. int error_code = GetSocketErrorNumber();
  399. char* error_message = GetErrorMessage(error_code);
  400. OPENER_TRACE_ERR("networkhandler: error on recv: %d - %s\n", error_code, error_message);
  401. FreeErrorMessage(error_message); // free(error_message);
  402. return kEipStatusError;
  403. }
  404. const EipUint8 *read_buffer = &g_ethernet_communication_buffer[2]; /* at this place EIP stores the data length */
  405. size_t data_size = GetIntFromMessage(&read_buffer)
  406. + ENCAPSULATION_HEADER_LENGTH - 4; /* -4 is for the 4 bytes we have already read*/
  407. /* (NOTE this advances the buffer pointer) */
  408. if ((PC_OPENER_ETHERNET_BUFFER_SIZE - 4) < data_size) { /*TODO can this be handled in a better way?*/
  409. OPENER_TRACE_ERR(
  410. "too large packet received will be ignored, will drop the data\n");
  411. /* Currently we will drop the whole packet */
  412. do {
  413. number_of_read_bytes = recv(socket, &g_ethernet_communication_buffer[0],
  414. data_sent, 0);
  415. if (number_of_read_bytes == 0) /* got error or connection closed by client */
  416. {
  417. int error_code = GetSocketErrorNumber();
  418. char* error_message = GetErrorMessage(error_code);
  419. OPENER_TRACE_ERR("networkhandler: connection closed by client: %d - %s\n", error_code, error_message);
  420. FreeErrorMessage(error_message);
  421. return kEipStatusError;
  422. }
  423. if (number_of_read_bytes < 0) {
  424. int error_code = GetSocketErrorNumber();
  425. char* error_message = GetErrorMessage(error_code);
  426. OPENER_TRACE_ERR("networkhandler: error on recv: %d - %s\n", error_code, error_message);
  427. FreeErrorMessage(error_message);
  428. return kEipStatusError;
  429. }
  430. data_size -= number_of_read_bytes;
  431. if ((data_size < PC_OPENER_ETHERNET_BUFFER_SIZE) && (data_size != 0)) {
  432. data_sent = data_size;
  433. }
  434. } while (0 < data_size);
  435. assert(0 <= data_size);
  436. return kEipStatusOk;
  437. }
  438. number_of_read_bytes = recv(socket, &g_ethernet_communication_buffer[4],
  439. data_size, 0);
  440. if (number_of_read_bytes == 0) /* got error or connection closed by client */
  441. {
  442. int error_code = GetSocketErrorNumber();
  443. char* error_message = GetErrorMessage(error_code);
  444. OPENER_TRACE_ERR("networkhandler: connection closed by client: %d - %s\n", error_code, error_message);
  445. FreeErrorMessage(error_message);
  446. return kEipStatusError;
  447. }
  448. if (number_of_read_bytes < 0) {
  449. int error_code = GetSocketErrorNumber();
  450. char* error_message = GetErrorMessage(error_code);
  451. OPENER_TRACE_ERR("networkhandler: error on recv: %d - %s\n", error_code, error_message);
  452. FreeErrorMessage(error_message);
  453. return kEipStatusError;
  454. }
  455. if ((unsigned) number_of_read_bytes == data_size) {
  456. /*we got the right amount of data */
  457. data_size += 4;
  458. /*TODO handle partial packets*/
  459. OPENER_TRACE_INFO("Data received on tcp:\n");
  460. g_current_active_tcp_socket = socket;
  461. number_of_read_bytes = HandleReceivedExplictTcpData(
  462. socket, g_ethernet_communication_buffer, data_size, &remaining_bytes);
  463. g_current_active_tcp_socket = -1;
  464. if (remaining_bytes != 0) {
  465. OPENER_TRACE_WARN(
  466. "Warning: received packet was to long: %d Bytes left!\n",
  467. remaining_bytes);
  468. }
  469. if (number_of_read_bytes > 0) {
  470. OPENER_TRACE_INFO("reply sent:\n");
  471. data_sent = send(socket, (char *) &g_ethernet_communication_buffer[0],
  472. number_of_read_bytes, 0);
  473. if (data_sent != number_of_read_bytes) {
  474. OPENER_TRACE_WARN("TCP response was not fully sent\n");
  475. }
  476. }
  477. return kEipStatusOk;
  478. } else {
  479. /* we got a fragmented packet currently we cannot handle this will
  480. * for this we would need a network buffer per TCP socket
  481. *
  482. * However with typical packet sizes of EIP this should't be a big issue.
  483. */
  484. /*TODO handle fragmented packets */
  485. }
  486. return kEipStatusError;
  487. }
  488. /** @brief create a new UDP socket for the connection manager
  489. *
  490. * @param communciation_direction Consuming or producing port
  491. * @param socket_data Data for socket creation
  492. *
  493. * @return the socket handle if successful, else -1 */
  494. int CreateUdpSocket(UdpCommuncationDirection communication_direction,
  495. struct sockaddr_in *socket_data) {
  496. struct sockaddr_in peer_address;
  497. int new_socket;
  498. socklen_t peer_address_length;
  499. peer_address_length = sizeof(struct sockaddr_in);
  500. /* create a new UDP socket */
  501. if ((new_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
  502. int error_code = GetSocketErrorNumber();
  503. char* error_message = GetErrorMessage(error_code);
  504. OPENER_TRACE_ERR("networkhandler: cannot create UDP socket: %d- %s\n", error_code, error_message);
  505. FreeErrorMessage(error_message);
  506. return kEipInvalidSocket;
  507. }
  508. OPENER_TRACE_INFO("networkhandler: UDP socket %d\n", new_socket);
  509. /* check if it is sending or receiving */
  510. if (communication_direction == kUdpCommuncationDirectionConsuming) {
  511. int option_value = 1;
  512. if (setsockopt(new_socket, SOL_SOCKET, SO_REUSEADDR, (char *) &option_value,
  513. sizeof(option_value)) == -1) {
  514. OPENER_TRACE_ERR(
  515. "error setting socket option SO_REUSEADDR on consuming udp socket\n");
  516. return kEipStatusError;
  517. }
  518. /* bind is only for consuming necessary */
  519. if ((bind(new_socket, (struct sockaddr *) socket_data,
  520. sizeof(struct sockaddr))) == -1) {
  521. int error_code = GetSocketErrorNumber();
  522. char* error_message = GetErrorMessage(error_code);
  523. OPENER_TRACE_ERR("error on bind udp: %d - %s\n", error_code, error_message);
  524. FreeErrorMessage(error_message);
  525. return kEipInvalidSocket;
  526. }
  527. OPENER_TRACE_INFO("networkhandler: bind UDP socket %d\n", new_socket);
  528. } else { /* we have a producing udp socket */
  529. if (socket_data->sin_addr.s_addr
  530. == g_multicast_configuration.starting_multicast_address) {
  531. if (1 != g_time_to_live_value) { /* we need to set a TTL value for the socket */
  532. if (setsockopt(new_socket, IPPROTO_IP, IP_MULTICAST_TTL,
  533. &g_time_to_live_value,
  534. sizeof(g_time_to_live_value) < 0)) {
  535. int error_code = GetSocketErrorNumber();
  536. char* error_message = GetErrorMessage(error_code);
  537. OPENER_TRACE_ERR(
  538. "networkhandler: could not set the TTL to: %d, error: %d - %s\n",
  539. g_time_to_live_value, error_code, error_message);
  540. FreeErrorMessage(error_message);
  541. return kEipInvalidSocket;
  542. }
  543. }
  544. }
  545. }
  546. if ((communication_direction == kUdpCommuncationDirectionConsuming)
  547. || (0 == socket_data->sin_addr.s_addr)) {
  548. /* we have a peer to peer producer or a consuming connection*/
  549. if (getpeername(g_current_active_tcp_socket,
  550. (struct sockaddr *) &peer_address, &peer_address_length)
  551. < 0) {
  552. int error_code = GetSocketErrorNumber();
  553. char* error_message = GetErrorMessage(error_code);
  554. OPENER_TRACE_ERR("networkhandler: could not get peername: %d - %s\n", error_code, error_message);
  555. FreeErrorMessage(error_message);
  556. return kEipInvalidSocket;
  557. }
  558. /* store the originators address */
  559. socket_data->sin_addr.s_addr = peer_address.sin_addr.s_addr;
  560. }
  561. /* add new socket to the master list */
  562. FD_SET(new_socket, &master_socket);
  563. if (new_socket > highest_socket_handle) {
  564. highest_socket_handle = new_socket;
  565. }
  566. return new_socket;
  567. }
  568. void CheckAndHandleConsumingUdpSockets(void) {
  569. struct sockaddr_in from_address;
  570. socklen_t from_address_length;
  571. ConnectionObject *connection_object_iterator = g_active_connection_list;
  572. ConnectionObject *current_connection_object = NULL;
  573. /* see a message on one of the registered UDP sockets has been received */
  574. while (NULL != connection_object_iterator) {
  575. current_connection_object = connection_object_iterator;
  576. connection_object_iterator = connection_object_iterator
  577. ->next_connection_object; /* do this at the beginning as the close function may can make the entry invalid */
  578. if ((-1
  579. != current_connection_object->socket[kUdpCommuncationDirectionConsuming])
  580. && (true
  581. == CheckSocketSet(
  582. current_connection_object->socket[kUdpCommuncationDirectionConsuming]))) {
  583. from_address_length = sizeof(from_address);
  584. int received_size = recvfrom(
  585. current_connection_object->socket[kUdpCommuncationDirectionConsuming],
  586. g_ethernet_communication_buffer, PC_OPENER_ETHERNET_BUFFER_SIZE, 0,
  587. (struct sockaddr *) &from_address, &from_address_length);
  588. if (0 == received_size) {
  589. OPENER_TRACE_STATE("connection closed by client\n");
  590. current_connection_object->connection_close_function(
  591. current_connection_object);
  592. continue;
  593. }
  594. if (0 > received_size) {
  595. int error_code = GetSocketErrorNumber();
  596. char* error_message = GetErrorMessage(error_code);
  597. OPENER_TRACE_ERR("networkhandler: error on recv: %d - %s\n", error_code, error_message);
  598. FreeErrorMessage(error_message);
  599. current_connection_object->connection_close_function(
  600. current_connection_object);
  601. continue;
  602. }
  603. HandleReceivedConnectedData(g_ethernet_communication_buffer,
  604. received_size, &from_address);
  605. }
  606. }
  607. }
  608. void CloseSocket(int socket_handle) {
  609. OPENER_TRACE_INFO("networkhandler: closing socket %d\n", socket_handle);
  610. if (kEipInvalidSocket != socket_handle) {
  611. FD_CLR(socket_handle, &master_socket);
  612. CloseSocketPlatform(socket_handle);
  613. }
  614. }
  615. int GetMaxSocket(int socket1, int socket2, int socket3, int socket4) {
  616. if ((socket1 > socket2) && (socket1 > socket3) && (socket1 > socket4))
  617. return socket1;
  618. if ((socket2 > socket1) && (socket2 > socket3) && (socket2 > socket4))
  619. return socket2;
  620. if ((socket3 > socket1) && (socket3 > socket2) && (socket3 > socket4))
  621. return socket3;
  622. return socket4;
  623. }