portgw.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. #include "FreeRTOS.h"
  2. #include "task.h"
  3. #include "semphr.h"
  4. #include "queue.h"
  5. #include <errno.h>
  6. #include "common_config.h"
  7. #include "lwip/sockets.h"
  8. #include "lwip/inet.h"
  9. #include "settings_api.h"
  10. #include "portgw.h"
  11. #include "tinystdio.h"
  12. #include "usart.h"
  13. #ifdef PRINTF_STDLIB
  14. #include <stdio.h>
  15. #endif
  16. #ifdef PRINTF_CUSTOM
  17. #include "tinystdio.h"
  18. #endif
  19. #include <string.h>
  20. #ifdef PORTGW_ENABLE
  21. #define PORTGW_PORT_NUM 1001
  22. #define PORTGW_DATA_CHUNK_SIZE 512
  23. /* Set option to drop old connection if the new one is accepted */
  24. #define TCP_DROP_PREV_CONNECTION 1
  25. static int listen_sd;
  26. static struct sockaddr_in sa;
  27. static struct fd_set master_set, read_set, write_set;
  28. static int max_sd;
  29. static uint8_t data_buffer[PORTGW_DATA_CHUNK_SIZE];
  30. #undef DBG
  31. #define DBG if(0)
  32. /* (Re)init serial port */
  33. void serial_reinit()
  34. {
  35. uint16_t parity, stop, wordlen;
  36. /* Parity set */
  37. switch (sSettings.sPortGw.parity) {
  38. case GW_EVEN_PAR:
  39. parity = USART_Parity_Even;
  40. break;
  41. case GW_ODD_PAR:
  42. parity = USART_Parity_Odd;
  43. break;
  44. case GW_NO_PAR:
  45. default:
  46. parity = USART_Parity_No;
  47. break;
  48. }
  49. /* Stop bits set */
  50. switch (sSettings.sPortGw.stopbits) {
  51. case 2:
  52. stop = USART_StopBits_2;
  53. break;
  54. case 1:
  55. default:
  56. stop = USART_StopBits_1;
  57. break;
  58. }
  59. /* Word length set */
  60. switch (sSettings.sPortGw.databits) {
  61. case 8:
  62. if ((sSettings.sPortGw.parity == GW_EVEN_PAR) ||
  63. (sSettings.sPortGw.parity == GW_ODD_PAR)) {
  64. /* 8-bit data + Parity */
  65. wordlen = 9;
  66. } else {
  67. wordlen = 8;
  68. }
  69. break;
  70. case 7:
  71. default:
  72. /* 7-bit data + Parity */
  73. wordlen = 8;
  74. break;
  75. }
  76. uart_config_reinit(RS485_USART, sSettings.sPortGw.baud, wordlen, parity, stop);
  77. }
  78. /* Stop server */
  79. static void stop_server(void) {
  80. /* Clean up all of the sockets that are open */
  81. for (int i = 0; i <= max_sd; ++i)
  82. {
  83. if (FD_ISSET(i, &master_set)) {
  84. DBG printf("Close sock %d\n", i);
  85. closesocket(i);
  86. FD_CLR(i, &master_set);
  87. }
  88. }
  89. DBG printf("Portgw stopped\n");
  90. }
  91. /* Start TCP server */
  92. static bool start_tcp_server(uint16_t port)
  93. {
  94. int res;
  95. listen_sd = socket(PF_INET, SOCK_STREAM, 0);
  96. if (listen_sd < 0) {
  97. DBG printf("Socket create failed\r\n");
  98. return false;
  99. }
  100. res = fcntl(listen_sd, F_SETFL, O_NONBLOCK);
  101. if (res < 0) {
  102. DBG printf("fcntl() failed");
  103. closesocket(listen_sd);
  104. return false;
  105. }
  106. #if 0
  107. /* Not used */
  108. lwip_setsockopt(listen_sd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
  109. if (res < 0) {
  110. printf("setsockopt() failed");
  111. closesocket(listen_sd);
  112. return false;
  113. }
  114. /* Not used (SO_REUSE==1 should be enabled) */
  115. int on = 1;
  116. res = setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
  117. if (res < 0) {
  118. printf("setsockopt() failed");
  119. closesocket(listen_sd);
  120. return false;
  121. }
  122. #endif
  123. memset(&sa, 0, sizeof(struct sockaddr_in));
  124. sa.sin_family = AF_INET;
  125. sa.sin_addr.s_addr = IPADDR_ANY;
  126. sa.sin_port = htons(port);
  127. if (bind(listen_sd, (struct sockaddr *)&sa, sizeof(sa)) == -1)
  128. {
  129. DBG printf("Bind to port %d failed\n", port);
  130. closesocket(listen_sd);
  131. return false;
  132. }
  133. res = listen(listen_sd, 1);
  134. if (res < 0) {
  135. DBG printf("Listen failed failed\r\n");
  136. closesocket(listen_sd);
  137. return false;
  138. }
  139. FD_ZERO(&master_set);
  140. max_sd = listen_sd;
  141. FD_SET(listen_sd, &master_set);
  142. printf("Port %d opened\n", port);
  143. return true;
  144. }
  145. /* Start UDP server */
  146. static bool start_udp_server(uint16_t port)
  147. {
  148. int res;
  149. listen_sd = socket(PF_INET, SOCK_DGRAM, 0);
  150. if (listen_sd < 0) {
  151. printf("Socket create failed\r\n");
  152. return false;
  153. }
  154. else {
  155. printf("Socket create OK\r\n");
  156. }
  157. res = fcntl(listen_sd, F_SETFL, O_NONBLOCK);
  158. if (res < 0) {
  159. DBG printf("fcntl() failed");
  160. closesocket(listen_sd);
  161. return false;
  162. }
  163. #if 0
  164. /* Not used */
  165. lwip_setsockopt(listen_sd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
  166. if (res < 0) {
  167. printf("setsockopt() failed");
  168. closesocket(listen_sd);
  169. return false;
  170. }
  171. /* Not used (SO_REUSE==1 should be enabled) */
  172. int on = 1;
  173. res = setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
  174. if (res < 0) {
  175. printf("setsockopt() failed");
  176. closesocket(listen_sd);
  177. return false;
  178. }
  179. #endif
  180. memset(&sa, 0, sizeof(struct sockaddr_in));
  181. sa.sin_family = AF_INET;
  182. sa.sin_addr.s_addr = IPADDR_ANY;
  183. sa.sin_port = htons(port);
  184. if (bind(listen_sd, (struct sockaddr *)&sa, sizeof(sa)) == -1)
  185. {
  186. DBG printf("Bind to port %d failed\n", port);
  187. closesocket(listen_sd);
  188. return false;
  189. }
  190. FD_ZERO(&master_set);
  191. max_sd = listen_sd;
  192. FD_SET(listen_sd, &master_set);
  193. printf("Port %d opened\n", port);
  194. return true;
  195. }
  196. /* Start server */
  197. static bool start_server(gwtrans_t transtype, uint16_t port)
  198. {
  199. switch (transtype) {
  200. case GW_TCP:
  201. return start_tcp_server(port);
  202. case GW_UDP:
  203. return start_udp_server(port);
  204. default:
  205. return false;
  206. }
  207. }
  208. /* TCP server main loop */
  209. static void tcp_server(void)
  210. {
  211. int recvd, sent;
  212. uint8_t c;
  213. int new_sd;
  214. static int active_sd = -1;
  215. int desc_ready, rc;
  216. struct timeval timeout;
  217. bool close_conn;
  218. timeout.tv_sec = 5;
  219. timeout.tv_usec = 0;
  220. memcpy(&read_set, &master_set, sizeof(master_set));
  221. memcpy(&write_set, &master_set, sizeof(master_set));
  222. DBG printf("Waiting on select()...\n");
  223. rc = select(max_sd + 1, &read_set, &write_set, NULL, &timeout);
  224. DBG printf(" select() returned %d\n", rc);
  225. if (rc < 0) {
  226. DBG printf(" select() failed\n");
  227. }
  228. if (rc == 0) {
  229. DBG printf(" select() timed out.\n");
  230. }
  231. /* One or more descriptors are readable. Need to \
  232. * determine which ones they are. */
  233. desc_ready = rc;
  234. for (int i=0; i <= max_sd && desc_ready > 0; ++i) {
  235. /*******************************************************/
  236. /* Check to see if this descriptor is ready */
  237. /*******************************************************/
  238. if (FD_ISSET(i, &read_set)) {
  239. /* A descriptor was found that was readable - one \
  240. * less has to be looked for. This is being done \
  241. * so that we can stop looking at the working set \
  242. * once we have found all of the descriptors that \
  243. * were ready. */
  244. desc_ready -= 1;
  245. /* Check to see if this is the listening socket */
  246. if (i == listen_sd) {
  247. DBG printf(" Listening socket is readable\n");
  248. /* Accept all incoming connections that are */
  249. /* queued up on the listening socket before we */
  250. /* loop back and call select again. */
  251. do {
  252. /* Accept each incoming connection. If */
  253. /* accept fails with EWOULDBLOCK, then we */
  254. /* have accepted all of them. Any other */
  255. /* failure on accept will cause us to end the */
  256. /* server. */
  257. new_sd = accept(listen_sd, NULL, NULL);
  258. if (new_sd < 0 && errno != 0) {
  259. if (errno != EWOULDBLOCK) {
  260. DBG printf(" accept() failed: %d\n", errno);
  261. }
  262. break;
  263. }
  264. /* Add the new incoming connection to the */
  265. /* master read set */
  266. DBG printf(" New incoming connection - %d\n", new_sd);
  267. FD_SET(new_sd, &master_set);
  268. if (new_sd > max_sd) {
  269. max_sd = new_sd;
  270. }
  271. #if TCP_DROP_PREV_CONNECTION
  272. /* Close previous active connection */
  273. if (active_sd != -1 && active_sd != new_sd) {
  274. DBG printf(" Close prev active connection %d\n", active_sd);
  275. close(active_sd);
  276. FD_CLR(active_sd, &master_set);
  277. if (active_sd == max_sd) {
  278. while (FD_ISSET(max_sd, &master_set) == false) {
  279. max_sd -= 1;
  280. }
  281. }
  282. }
  283. /* Mark new connection as active */
  284. active_sd = new_sd;
  285. DBG printf(" New active connection %d\n", active_sd);
  286. #endif
  287. /* Loop back up and accept another incoming */
  288. /* connection */
  289. } while (new_sd != -1);
  290. }
  291. /* This is not the listening socket, therefore an */
  292. /* existing connection must be readable */
  293. else {
  294. DBG printf(" Descriptor %d is readable\n", i);
  295. close_conn = false;
  296. /* Receive data on this connection until the */
  297. /* recv fails with EWOULDBLOCK. If any other */
  298. /* failure occurs, we will close the */
  299. /* connection. */
  300. if ((recvd = recv(i, data_buffer, sizeof(data_buffer), 0)) > 0) {
  301. DBG {
  302. printf("received %d bytes:", recvd);
  303. for (uint32_t i = 0; i < 3; i++) {
  304. printf(" 0x%X", data_buffer[i]);
  305. }
  306. printf("...\r\n");
  307. }
  308. /* Put RX data to the queue */
  309. for (uint32_t i = 0; i < (uint32_t)recvd; i++) {
  310. if (xQueueSend(rs485TxQ, &data_buffer[i], 1000) != pdTRUE) {
  311. printf("[portgw] Rx data lost\r\n");
  312. }
  313. }
  314. /* Start RS485 transmission */
  315. rs485_enable_tx();
  316. }
  317. if (recvd < 0) {
  318. if (errno != EWOULDBLOCK){
  319. DBG printf(" recv() failed: %d\n", errno);
  320. close_conn = true;
  321. }
  322. }
  323. /* Check to see if the connection has been */
  324. /* closed by the client */
  325. if (recvd == 0) {
  326. DBG printf(" Connection closed\n");
  327. close_conn = true;
  328. }
  329. /* If the close_conn flag was turned on, we need */
  330. /* to clean up this active connection. This */
  331. /* clean up process includes removing the */
  332. /* descriptor from the master set and */
  333. /* determining the new maximum descriptor value */
  334. /* based on the bits that are still turned on in */
  335. /* the master set. */
  336. if (close_conn) {
  337. closesocket(i);
  338. FD_CLR(i, &master_set);
  339. if (i == max_sd) {
  340. while (FD_ISSET(max_sd, &master_set) == false) {
  341. max_sd -= 1;
  342. }
  343. }
  344. }
  345. }
  346. }
  347. /* Socket is ready to write */
  348. else if (FD_ISSET(i, &write_set)){
  349. /* Put RX data to the queue */
  350. uint32_t len = 0;
  351. while (len < sizeof(data_buffer) && xQueueReceive(rs485RxQ, &c, 5) == pdTRUE) {
  352. data_buffer[len++] = c;
  353. }
  354. if (len > 0) {
  355. DBG printf("%d bytes to send\r\n", len);
  356. sent = send(i, data_buffer, len, 0);
  357. if (sent <= 0) {
  358. DBG printf("send failed (%d)\n", sent);
  359. }
  360. }
  361. }
  362. }
  363. }
  364. /* UDP server main loop */
  365. static void udp_server(void)
  366. {
  367. struct timeval timeout;
  368. int recvd, sent;
  369. uint8_t c;
  370. int rc;
  371. bool close_conn;
  372. timeout.tv_sec = 5;
  373. timeout.tv_usec = 0;
  374. memcpy(&read_set, &master_set, sizeof(master_set));
  375. memcpy(&write_set, &master_set, sizeof(master_set));
  376. /* TODO Remove select for UDP */
  377. DBG printf("Waiting on select()...\n");
  378. rc = select(max_sd + 1, &read_set, &write_set, NULL, &timeout);
  379. DBG printf(" select() returned %d\n", rc);
  380. if (rc < 0) {
  381. DBG printf(" select() failed\n");
  382. }
  383. if (rc == 0) {
  384. DBG printf(" select() timed out.\n");
  385. }
  386. else{
  387. /*******************************************************/
  388. /* Check to see if this descriptor is ready */
  389. /*******************************************************/
  390. if (FD_ISSET(listen_sd, &read_set)) {
  391. DBG printf(" Descriptor %d is readable\n", listen_sd);
  392. close_conn = false;
  393. /* Receive data on this connection until the */
  394. /* recv fails with EWOULDBLOCK. If any other */
  395. /* failure occurs, we will close the */
  396. /* connection.
  397. */
  398. socklen_t from_len;
  399. /* Save addr & port where data (requests) come from */
  400. if ((recvd = recvfrom(listen_sd, data_buffer, sizeof(data_buffer), 0,
  401. (struct sockaddr*)&sa, &from_len)) > 0) {
  402. DBG {
  403. printf("From %s:%d received %d bytes:",
  404. inet_ntoa(sa.sin_addr.s_addr), sa.sin_port, recvd);
  405. for (uint32_t i = 0; i < 3; i++) {
  406. printf(" 0x%X", data_buffer[i]);
  407. }
  408. printf("...\r\n");
  409. }
  410. /* Put RX data to the queue */
  411. for (uint32_t i = 0; i < (uint32_t)recvd; i++) {
  412. if (xQueueSend(rs485TxQ, &data_buffer[i], 1000) != pdTRUE) {
  413. printf("[portgw] Rx data lost\r\n");
  414. }
  415. }
  416. /* Start RS485 transmission */
  417. rs485_enable_tx();
  418. }
  419. if (recvd < 0) {
  420. if (errno != EWOULDBLOCK){
  421. DBG printf(" recv() failed\n");
  422. close_conn = true;
  423. }
  424. }
  425. /* Check to see if the connection has been */
  426. /* closed by the client */
  427. if (recvd == 0) {
  428. DBG printf(" Connection closed\n");
  429. close_conn = true;
  430. }
  431. /* If the close_conn flag was turned on, we need */
  432. /* to clean up this active connection. This */
  433. /* clean up process includes removing the */
  434. /* descriptor from the master set and */
  435. /* determining the new maximum descriptor value */
  436. /* based on the bits that are still turned on in */
  437. /* the master set. */
  438. if (close_conn) {
  439. closesocket(listen_sd);
  440. FD_CLR(listen_sd, &master_set);
  441. }
  442. }
  443. /* Socket is ready to write */
  444. else if (FD_ISSET(listen_sd, &write_set)) {
  445. uint32_t len = 0;
  446. while (len < sizeof(data_buffer) && xQueueReceive(rs485RxQ, &c, 5) == pdTRUE) {
  447. data_buffer[len++] = c;
  448. }
  449. if (len > 0) {
  450. DBG printf("%d bytes to send\r\n", len);
  451. /* Send data (responce) to the latest saved addr & port */
  452. sent = sendto(listen_sd, data_buffer, len, 0, (struct sockaddr*)&sa, sizeof(sa));
  453. if (sent <= 0) {
  454. DBG printf("send failed (%d)\n", sent);
  455. }
  456. }
  457. } else {
  458. /* Nothing to do */
  459. taskYIELD();
  460. }
  461. }
  462. }
  463. /* Main task */
  464. void portgw_thread(void *arg)
  465. {
  466. uint16_t port;
  467. gwtrans_t transtype;
  468. gwmode_t mode;
  469. bool enabled;
  470. gwparity_t parity;
  471. uint8_t stopbits;
  472. uint8_t databits;
  473. uint32_t baud;
  474. bool firstrun = true;
  475. (void)arg;
  476. FD_ZERO(&master_set);
  477. enabled = sSettings.sPortGw.enabled;
  478. port = sSettings.sPortGw.port;
  479. transtype = sSettings.sPortGw.transtype;
  480. mode = sSettings.sPortGw.mode;
  481. parity = sSettings.sPortGw.parity;
  482. stopbits = sSettings.sPortGw.stopbits;
  483. databits = sSettings.sPortGw.databits;
  484. baud = sSettings.sPortGw.baud;
  485. (void)mode;
  486. while (1) {
  487. /* Check if network settings was changed */
  488. if ((sSettings.sPortGw.port != port) ||
  489. (sSettings.sPortGw.enabled != enabled) ||
  490. (sSettings.sPortGw.transtype != transtype) ||
  491. (firstrun))
  492. {
  493. port = sSettings.sPortGw.port;
  494. enabled = sSettings.sPortGw.enabled;
  495. transtype = sSettings.sPortGw.transtype;
  496. if (!firstrun) {
  497. /* Stop server */
  498. stop_server();
  499. }
  500. if (enabled) {
  501. /* (Re)start server */
  502. if (!start_server(transtype, port)) {
  503. DBG printf("Server start error\n");
  504. vTaskDelay(5000);
  505. continue;
  506. }
  507. }
  508. else {
  509. /* Clear buffers */
  510. if (uxQueueMessagesWaiting(rs485TxQ) > 0) {
  511. xQueueReset(rs485TxQ);
  512. }
  513. if (uxQueueMessagesWaiting(rs485RxQ) > 0) {
  514. xQueueReset(rs485RxQ);
  515. }
  516. vTaskDelay(5000);
  517. continue;
  518. }
  519. }
  520. /* Check if serial settings was changed */
  521. if ((sSettings.sPortGw.parity != parity) ||
  522. (sSettings.sPortGw.stopbits != stopbits) ||
  523. (sSettings.sPortGw.databits != databits) ||
  524. (sSettings.sPortGw.baud != baud) ||
  525. (firstrun))
  526. {
  527. parity = sSettings.sPortGw.parity;
  528. stopbits = sSettings.sPortGw.stopbits;
  529. databits = sSettings.sPortGw.databits;
  530. baud = sSettings.sPortGw.baud;
  531. serial_reinit();
  532. DBG printf("Serial reinitialized\r\n");
  533. }
  534. if (!enabled) {
  535. vTaskDelay(5000);
  536. continue;
  537. }
  538. switch (transtype) {
  539. case GW_UDP:
  540. udp_server();
  541. break;
  542. case GW_TCP:
  543. tcp_server();
  544. break;
  545. default:
  546. vTaskDelay(5000);
  547. break;
  548. }
  549. firstrun = false;
  550. }
  551. }
  552. /* Main init */
  553. void portgw_init(void)
  554. {
  555. xTaskCreate(portgw_thread, ( char * ) "portgw_thr", configMINIMAL_STACK_SIZE * 2,
  556. NULL, tskIDLE_PRIORITY, NULL);
  557. }
  558. #endif