backend.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. /*******************************************************************************************
  2. * @file backend.c
  3. *
  4. * @brief 会话层(Session Layer). 后端服务器管理,帧接收.
  5. *
  6. * (c) Copyright 2021, Shandong Huali electromechanical Co., Ltd..
  7. * This is protected by international copyright laws. Knowledge of the
  8. * source code may not be used to write a similar product. This file may
  9. * only be used in accordance with a license and should not be redistributed
  10. * in any way. We appreciate your understanding and fairness.
  11. *
  12. *
  13. * @author Simon
  14. * @date Created: 2021.06.16-T16:08:11+0800
  15. *
  16. *******************************************************************************************/
  17. #include "rtthread.h"
  18. #include "stdbool.h"
  19. #include "lwip/opt.h"
  20. #include "lwip/sockets.h"
  21. #include "lwip/sys.h"
  22. #include "lwip/netdb.h"
  23. #include "lwip/netif.h"
  24. #define DBG_TAG "wcs.srv"
  25. #define DBG_LVL DBG_INFO
  26. #include <rtdbg.h>
  27. /* Description */
  28. #ifndef BE_SOCK_PORT
  29. #define BE_SOCK_PORT 2504
  30. #endif
  31. /* 发送缓存最大字节 */
  32. #ifndef BE_TX_MAX_SIZE
  33. #define BE_TX_MAX_SIZE 1024
  34. #endif
  35. #define BE_SOCK_TO 10 /* socket超时时间10ms */
  36. #define BE_BACKLOG 5 /* socket backlog */
  37. /* 帧头 */
  38. #define FRAME_HEAD_TAG1 0X02
  39. #define FRAME_HEAD_TAG2 0XFD
  40. /* 帧尾 */
  41. #define FRAME_TAIL_TAG1 0X03
  42. #define FRAME_TAIL_TAG2 0XFC
  43. /* 帧最短大小 */
  44. #define FRAME_MIN_SIZE 24
  45. /**
  46. * 错误类型
  47. * @brief 错误类型定义
  48. */
  49. enum
  50. {
  51. EOK, /* 无错误 */
  52. ERR, /* 错误 */
  53. ETO, /* 超时 */
  54. };
  55. /**
  56. * backend_session_t
  57. * @brief 后端会话数据
  58. */
  59. typedef struct
  60. {
  61. rt_thread_t server_task; /* 任务句柄 */
  62. rt_thread_t client_task; /* 任务句柄 */
  63. int server_fd; /* 服务端socket */
  64. int client_fd; /* 客户端socket */
  65. uint32_t recv_bufsz; /* 接收缓存大小 */
  66. uint8_t *recv_buffer; /* 接收缓存 */
  67. uint32_t cur_recv_len; /* 现接收长度 */
  68. int (*parser_fun)(void *, int); /* 帧解析函数 */
  69. rt_mq_t tx_buffer; /* 发送缓存 */
  70. rt_mutex_t tx_locker; /* 发送互斥量 */
  71. rt_mutex_t task_locker; /* 线程互斥量 */
  72. }backend_session_t;
  73. static backend_session_t backend = {0};
  74. /**
  75. * @funtion be_is_link_up
  76. * @brief 是否接入网络
  77. * @Author Simon
  78. * @DateTime 2021.06.16-T16:10:20+0800
  79. *
  80. * @return 1-是,0-否
  81. */
  82. static int be_is_link_up(void)
  83. {
  84. struct netif *netif = netif_find("e0");
  85. if(netif)
  86. {
  87. if(netif_is_link_up(netif))
  88. {
  89. if(netif->ip_addr.addr != IPADDR_ANY)
  90. {
  91. return 1;
  92. }
  93. }
  94. }
  95. return 0;
  96. }
  97. /**
  98. * @funtion be_tx_lock
  99. * @brief 发送互斥锁
  100. * @Author Simon
  101. * @DateTime 2021.06.16-T16:10:55+0800
  102. *
  103. */
  104. static void be_tx_lock(void)
  105. {
  106. /* is in thread context */
  107. // if (__get_CONTROL())
  108. {
  109. rt_mutex_take(backend.tx_locker, RT_WAITING_FOREVER);
  110. }
  111. }
  112. /**
  113. * @funtion be_tx_unlock
  114. * @brief 发送互斥锁解锁
  115. * @Author Simon
  116. * @DateTime 2021.06.16-T16:11:20+0800
  117. *
  118. */
  119. static void be_tx_unlock(void)
  120. {
  121. /* is in thread context */
  122. // if (__get_CONTROL())
  123. {
  124. rt_mutex_release(backend.tx_locker);
  125. }
  126. }
  127. /**
  128. * @funtion be_server_close
  129. * @brief 关闭服务器
  130. * @Author Simon
  131. * @DateTime 2021.06.16-T16:11:37+0800
  132. *
  133. * @param be 会话
  134. */
  135. static void be_server_close(backend_session_t *be)
  136. {
  137. closesocket(be->server_fd);
  138. be->server_fd = -1;
  139. }
  140. /**
  141. * @funtion be_server_create
  142. * @brief 创建服务器
  143. * @Author Simon
  144. * @DateTime 2021.06.16-T16:11:52+0800
  145. *
  146. * @param be 会话
  147. * @return EOK-成功, 负数-失败
  148. */
  149. static int be_server_create(backend_session_t *be)
  150. {
  151. struct sockaddr_in addr;
  152. int opt = 1;
  153. /* 申请socket */
  154. if ((be->server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  155. {
  156. LOG_E("create socket failed");
  157. return -ERR;
  158. }
  159. /* 启用SO_REUSEADDR 地址重用 */
  160. setsockopt(be->server_fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&opt, sizeof(opt));
  161. /* bind addr */
  162. addr.sin_family = AF_INET;
  163. addr.sin_port = htons(BE_SOCK_PORT);
  164. addr.sin_addr.s_addr = INADDR_ANY;
  165. memset(&(addr.sin_zero), 0, sizeof(addr.sin_zero));
  166. if (bind(be->server_fd, (struct sockaddr *) &addr, sizeof(struct sockaddr)) == -1)
  167. {
  168. LOG_E("bind socket[%d] failed", be->server_fd);
  169. return -ERR;
  170. }
  171. /* 监听 */
  172. if (listen(be->server_fd, BE_BACKLOG) == -1)
  173. {
  174. LOG_E("listen socket[%d] failed", be->server_fd);
  175. return -ERR;
  176. }
  177. LOG_I("WCS server start successfully");
  178. return EOK;
  179. }
  180. /**
  181. * @funtion be_client_close
  182. * @brief 关闭客服端
  183. * @Author Simon
  184. * @DateTime 2021.06.16-T16:12:57+0800
  185. *
  186. * @param be 会话
  187. */
  188. static void be_client_close(backend_session_t *be)
  189. {
  190. /* close connection */
  191. closesocket(be->client_fd);
  192. be->client_fd = -1;
  193. }
  194. /**
  195. * @funtion be_send_to_client
  196. * @brief 发送数据到客户端
  197. * @Author Simon
  198. * @DateTime 2021.06.16-T16:13:20+0800
  199. *
  200. * @param be 会话
  201. */
  202. static void be_send_to_client(backend_session_t *be)
  203. {
  204. int length;
  205. static uint8_t tx_buffer[BE_TX_MAX_SIZE];
  206. while (1)
  207. {
  208. memset(tx_buffer, 0, sizeof(tx_buffer));
  209. be_tx_lock();
  210. /* get buffer from ringbuffer */
  211. length = rt_mq_recv(be->tx_buffer, tx_buffer, BE_TX_MAX_SIZE, 10);
  212. be_tx_unlock();
  213. /* do a tx procedure */
  214. if (length > 0)
  215. {
  216. send(be->client_fd, tx_buffer, length, 0);
  217. }
  218. else
  219. break;
  220. }
  221. }
  222. /**
  223. * @funtion be_client_getchar
  224. * @brief 从客户端socket获取1字节
  225. * @Author Simon
  226. * @DateTime 2021.06.16-T16:13:51+0800
  227. *
  228. * @param be 会话
  229. * @param ch 字节指针
  230. * @param timeout 超时时间ms
  231. * @return EOK-成功, -ETO-超时, -ERR-错误
  232. */
  233. static int be_client_getchar(backend_session_t *be, char *ch, int timeout)
  234. {
  235. int result = EOK;
  236. int to = 0;
  237. while (1)
  238. {
  239. result = recv(be->client_fd, ch, 1, 0);
  240. if(result > 0)
  241. {
  242. break;
  243. }
  244. else
  245. {
  246. int err = 0;
  247. err = errno;
  248. if(err == EINTR || err == EWOULDBLOCK || err == EAGAIN)
  249. {
  250. to += BE_SOCK_TO;
  251. if(to >= timeout)
  252. {
  253. return -ETO;
  254. }
  255. }
  256. else
  257. {
  258. LOG_D("socket recv error code[%d]", err);
  259. return -ERR;
  260. }
  261. }
  262. }
  263. return EOK;
  264. }
  265. /**
  266. * @funtion be_readline
  267. * @brief 从客户端socket获取1帧数据
  268. * @Author Simon
  269. * @DateTime 2021.06.16-T16:15:19+0800
  270. *
  271. * @param be 会话
  272. * @return 0-未收到数据, 负数-发生错误, 正数-帧长度
  273. */
  274. static int be_readline(backend_session_t *be)
  275. {
  276. int read_len = 0;
  277. char ch = 0, last_ch = 0;
  278. bool is_full = false;
  279. bool is_newline = false;
  280. int rc = 0;
  281. memset(be->recv_buffer, 0x00, be->recv_bufsz);
  282. be->cur_recv_len = 0;
  283. while (be->client_fd >= 0)
  284. {
  285. rc = be_client_getchar(be, &ch, 10);
  286. if(rc != 0)
  287. {
  288. memset(be->recv_buffer, 0x00, be->recv_bufsz);
  289. be->cur_recv_len = 0;
  290. if(rc == -ETO)
  291. {
  292. rc = 0;
  293. }
  294. return rc;
  295. }
  296. /* is newline */
  297. if(ch == FRAME_HEAD_TAG2 && last_ch == FRAME_HEAD_TAG1)
  298. {
  299. be->recv_buffer[read_len++] = last_ch; /* push last ch[first head tag] */
  300. is_newline = true;
  301. }
  302. /* copy body */
  303. if(is_newline)
  304. {
  305. if (read_len < be->recv_bufsz)
  306. {
  307. be->recv_buffer[read_len++] = ch;
  308. be->cur_recv_len = read_len;
  309. }
  310. else
  311. {
  312. is_full = true;
  313. }
  314. }
  315. /* is end */
  316. if (read_len > FRAME_MIN_SIZE
  317. && ch == FRAME_TAIL_TAG2
  318. && last_ch == FRAME_TAIL_TAG1)
  319. {
  320. if (is_full)
  321. {
  322. LOG_E("read line failed. The line data length is out of buffer size(%d)!", be->recv_bufsz);
  323. memset(be->recv_buffer, 0x00, be->recv_bufsz);
  324. be->cur_recv_len = 0;
  325. return 0;
  326. }
  327. break;
  328. }
  329. last_ch = ch;
  330. }
  331. if(read_len)
  332. {
  333. LOG_D("recv frame");
  334. LOG_HEX(DBG_TAG, 16, be->recv_buffer, read_len);
  335. }
  336. return read_len;
  337. }
  338. /**
  339. * @funtion be_set_parser
  340. * @brief 设置数据帧解析函数
  341. * @Author Simon
  342. * @DateTime 2021.06.16-T16:17:00+0800
  343. *
  344. * @param parser_fun 解析函数
  345. */
  346. void be_set_parser(int (*parser_fun)(void *, int))
  347. {
  348. backend.parser_fun = parser_fun;
  349. }
  350. void be_send(void *buf, int sz)
  351. {
  352. LOG_D("send frame");
  353. LOG_HEX(DBG_TAG, 16, buf, sz);
  354. send(backend.client_fd, buf, sz, 0);
  355. }
  356. /**
  357. * @funtion be_task
  358. * @brief 后端任务
  359. * @Author Simon
  360. * @DateTime 2021.06.16-T16:21:10+0800
  361. *
  362. * @param arg 参数
  363. */
  364. static void be_server(void *arg)
  365. {
  366. struct sockaddr_in addr;
  367. socklen_t addr_size;
  368. struct timeval tm;
  369. tm.tv_sec = 1;
  370. tm.tv_usec = 0;
  371. while(be_is_link_up())
  372. {
  373. rt_thread_delay(10);
  374. }
  375. while (1)
  376. {
  377. if(backend.server_fd < 0)
  378. {
  379. while(be_server_create(&backend) < 0)
  380. {
  381. be_server_close(&backend);
  382. rt_thread_delay(1000);
  383. }
  384. }
  385. else
  386. {
  387. int new_clinet_fd = -1;
  388. // LOG_I("waiting for connection");
  389. /* grab new connection */
  390. if ((new_clinet_fd = accept(backend.server_fd, (struct sockaddr *) &addr, &addr_size)) == -1)
  391. {
  392. continue;
  393. }
  394. if(new_clinet_fd >= 0)
  395. {
  396. LOG_I("new wcs client(%s:%d) connection.", inet_ntoa(addr.sin_addr), addr.sin_port);
  397. setsockopt(new_clinet_fd, SOL_SOCKET, SO_RCVTIMEO, &tm, sizeof(tm));
  398. rt_mutex_take(backend.task_locker, RT_WAITING_FOREVER);
  399. if(backend.client_fd >= 0)
  400. {
  401. be_client_close(&backend);
  402. }
  403. backend.client_fd = new_clinet_fd;
  404. rt_mutex_release(backend.task_locker);
  405. }
  406. }
  407. }
  408. }
  409. static void be_client(void *arg)
  410. {
  411. int recv_sz;
  412. while (1)
  413. {
  414. if(backend.client_fd >= 0)
  415. {
  416. rt_mutex_take(backend.task_locker, RT_WAITING_FOREVER);
  417. /* try to send all data in tx ringbuffer */
  418. be_send_to_client(&backend);
  419. /* do a rx procedure */
  420. recv_sz = be_readline(&backend);
  421. if (recv_sz > 0)
  422. {
  423. if(backend.parser_fun)
  424. backend.parser_fun(backend.recv_buffer, recv_sz);
  425. }
  426. else if(recv_sz < 0)
  427. {
  428. /* close connection */
  429. be_client_close(&backend);
  430. }
  431. rt_mutex_release(backend.task_locker);
  432. }
  433. else
  434. {
  435. rt_thread_mdelay(10);
  436. }
  437. }
  438. }
  439. /**
  440. * @funtion be_init
  441. * @brief 后端初始化
  442. * @Author Simon
  443. * @DateTime 2021.06.16-T16:21:29+0800
  444. *
  445. * @return 0-成功
  446. */
  447. static int be_init(void)
  448. {
  449. backend.recv_bufsz = 1024;
  450. backend.recv_buffer = rt_malloc(backend.recv_bufsz);
  451. backend.tx_buffer = rt_mq_create("wcs_tx", BE_TX_MAX_SIZE, 3, RT_IPC_FLAG_FIFO);
  452. backend.tx_locker = rt_mutex_create("wcs_lock", RT_IPC_FLAG_FIFO);
  453. backend.task_locker = rt_mutex_create("wcs_tlock", RT_IPC_FLAG_FIFO);
  454. backend.client_fd = -1;
  455. backend.server_fd = -1;
  456. backend.server_task = rt_thread_create("server", be_server, &backend, 4096, 11, 10);
  457. if (backend.server_task)
  458. {
  459. rt_thread_startup(backend.server_task);
  460. }
  461. backend.client_task = rt_thread_create("client", be_client, &backend, 4096, 12, 10);
  462. if (backend.client_task)
  463. {
  464. rt_thread_startup(backend.client_task);
  465. }
  466. return 0;
  467. }
  468. INIT_APP_EXPORT(be_init);