portgw.c 19 KB

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