tcp_slave.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <sys/select.h>
  5. #include <sys/socket.h>
  6. #include <arpa/inet.h>
  7. #include <netinet/tcp.h>
  8. #include <fcntl.h>
  9. #include <unistd.h>
  10. #include <errno.h>
  11. #include <pthread.h>
  12. #include "tcp.h"
  13. #include "rtservice.h"
  14. #include "rt_tick.h"
  15. #include "slave.h"
  16. #define DBG_ENABLE
  17. #define DBG_COLOR
  18. #define DBG_SECTION_NAME "tcp_slave"
  19. #define DBG_LEVEL DBG_LOG
  20. #include "dbg_log.h"
  21. struct mbtcp_session {
  22. int fd;
  23. uint32_t tick_timeout;
  24. rt_slist_t slist;
  25. };
  26. #define MBTCP_SESSION_MAX_NUM 5
  27. #define MBTCP_SESSION_TIMEOUT 10
  28. static int _listen_port = 0;
  29. static pthread_mutex_t _mtx;
  30. static rt_slist_t _header = RT_SLIST_OBJECT_INIT(_header);
  31. static int mbtcp_session_get_num(void)
  32. {
  33. int num = 0;
  34. pthread_mutex_lock(&_mtx);
  35. num = rt_slist_len(&_header);
  36. pthread_mutex_unlock(&_mtx);
  37. return num;
  38. }
  39. static void mbtcp_session_delete(struct mbtcp_session *session)
  40. {
  41. pthread_mutex_lock(&_mtx);
  42. rt_slist_remove(&_header, &(session->slist));
  43. pthread_mutex_unlock(&_mtx);
  44. tcp_close(session->fd);
  45. free(session);
  46. }
  47. static void *mbtcp_session_entry(void *param)
  48. {
  49. struct mbtcp_session *session = (struct mbtcp_session *)param;
  50. int option = 1;
  51. int rc = setsockopt(session->fd, IPPROTO_TCP, TCP_NODELAY, (const void *)&option, sizeof(int));
  52. if (rc < 0)
  53. goto _exit;
  54. int flags = fcntl(session->fd, F_GETFL, 0);
  55. flags |= O_NONBLOCK;
  56. fcntl(session->fd, F_SETFL, flags);
  57. flags = fcntl(session->fd, F_GETFD);
  58. flags |= FD_CLOEXEC;
  59. fcntl(session->fd, F_SETFD, flags);
  60. session->tick_timeout = rt_tick_get() + rt_tick_from_millisecond(MBTCP_SESSION_TIMEOUT * 1000);
  61. uint8_t ctx_send_buf[AGILE_MODBUS_MAX_ADU_LENGTH];
  62. uint8_t ctx_read_buf[AGILE_MODBUS_MAX_ADU_LENGTH];
  63. agile_modbus_tcp_t ctx_tcp;
  64. agile_modbus_t *ctx = &ctx_tcp._ctx;
  65. agile_modbus_tcp_init(&ctx_tcp, ctx_send_buf, sizeof(ctx_send_buf), ctx_read_buf, sizeof(ctx_read_buf));
  66. agile_modbus_set_slave(ctx, 1);
  67. while (1) {
  68. rc = tcp_receive(session->fd, ctx->read_buf, ctx->read_bufsz, 1000);
  69. if (rc < 0)
  70. break;
  71. if (rc > 0) {
  72. int send_len = agile_modbus_slave_handle(ctx, rc, 0, agile_modbus_slave_util_callback, &slave_util, NULL);
  73. tcp_flush(session->fd);
  74. if (send_len > 0) {
  75. session->tick_timeout = rt_tick_get() + rt_tick_from_millisecond(MBTCP_SESSION_TIMEOUT * 1000);
  76. if (tcp_send(session->fd, ctx->send_buf, send_len) != send_len)
  77. break;
  78. }
  79. }
  80. if ((rt_tick_get() - session->tick_timeout) < (RT_TICK_MAX / 2))
  81. break;
  82. }
  83. _exit:
  84. LOG_W("socket %d close.", session->fd);
  85. mbtcp_session_delete(session);
  86. }
  87. static int mbtcp_session_create(int fd)
  88. {
  89. if (fd < 0)
  90. return -1;
  91. if (mbtcp_session_get_num() >= MBTCP_SESSION_MAX_NUM)
  92. return -1;
  93. struct mbtcp_session *session = malloc(sizeof(struct mbtcp_session));
  94. if (session == NULL)
  95. return -1;
  96. memset(session, 0, sizeof(struct mbtcp_session));
  97. session->fd = fd;
  98. rt_slist_init(&(session->slist));
  99. pthread_mutex_lock(&_mtx);
  100. rt_slist_append(&_header, &(session->slist));
  101. pthread_mutex_unlock(&_mtx);
  102. pthread_t tid;
  103. pthread_create(&tid, NULL, mbtcp_session_entry, session);
  104. pthread_detach(tid);
  105. return 0;
  106. }
  107. static void *mbtcp_entry(void *param)
  108. {
  109. int server_fd = -1;
  110. // Select use
  111. fd_set readset, exceptset;
  112. // Select timeout
  113. struct timeval select_timeout;
  114. _tcp_start:
  115. LOG_I("mbtcp server running.");
  116. server_fd = tcp_listen(_listen_port, 1);
  117. if (server_fd < 0)
  118. goto _tcp_restart;
  119. while (1) {
  120. FD_ZERO(&readset);
  121. FD_ZERO(&exceptset);
  122. FD_SET(server_fd, &readset);
  123. FD_SET(server_fd, &exceptset);
  124. select_timeout.tv_sec = 1;
  125. select_timeout.tv_usec = 0;
  126. int rc = select(server_fd + 1, &readset, NULL, &exceptset, &select_timeout);
  127. if (rc == -1) {
  128. if (errno == EINTR)
  129. continue;
  130. }
  131. if (rc < 0)
  132. break;
  133. if (rc > 0) {
  134. if (FD_ISSET(server_fd, &exceptset))
  135. break;
  136. if (FD_ISSET(server_fd, &readset)) {
  137. int client_fd = tcp_accept(server_fd);
  138. if (client_fd < 0)
  139. break;
  140. if (mbtcp_session_create(client_fd) < 0)
  141. tcp_close(client_fd);
  142. }
  143. }
  144. }
  145. _tcp_restart:
  146. LOG_W("mbtcp server go wrong, now wait restarting...");
  147. if (server_fd >= 0) {
  148. tcp_close(server_fd);
  149. server_fd = -1;
  150. }
  151. sleep(1);
  152. goto _tcp_start;
  153. }
  154. int tcp_slave_init(int port, pthread_t *tid)
  155. {
  156. if (port <= 0) {
  157. LOG_E("Port must be greater than 0!");
  158. return -1;
  159. }
  160. _listen_port = port;
  161. pthread_mutex_init(&_mtx, NULL);
  162. pthread_create(tid, NULL, mbtcp_entry, NULL);
  163. return 0;
  164. }