netserver.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. /*************************************************
  2. Copyright (c) 2020
  3. All rights reserved.
  4. File name: netserver.c
  5. Description:
  6. History:
  7. 1. Version:
  8. Date: 2020-11-26
  9. Author: WKJay
  10. Modify:
  11. *************************************************/
  12. #include <rtthread.h>
  13. #include "netserver.h"
  14. #if (RTTHREAD_VERSION >= 40004)
  15. #include <sys/ioctl.h>
  16. #endif
  17. #include <sys/time.h>
  18. #ifdef SAL_USING_POSIX
  19. #include <sys/select.h>
  20. #else
  21. #include <lwip/select.h>
  22. #endif
  23. #if NS_ENABLE_SSL
  24. #include "ns_ssl_if.h"
  25. #endif
  26. /* Flags set by net server*/
  27. #define NS_SESSION_F_LISTENING (1 << 0)
  28. #define NS_SESSION_F_SSL (1 << 1)
  29. #define NS_SESSION_F_CLOSE (1 << 2)
  30. #define NS_IF_LISTEN_BACKLOG 6
  31. #define NS_SELECT_TIMEOUT 2000
  32. #define NS_THREAD_STACK_SIZE 8192
  33. #define NS_THREAD_PRIORITY 10
  34. #define NS_THREAD_TICK 5
  35. #define NS_IS_RESET(s) (s & NS_RESET_FLAG)
  36. #define IS_LISTEN_SESSION(s) (s->flag & NS_SESSION_F_LISTENING)
  37. #define IS_CLOSED_SESSION(s) (s->flag & NS_SESSION_F_CLOSE)
  38. /*------------------------------------------------------------------------------------//
  39. SESSION
  40. //------------------------------------------------------------------------------------*/
  41. static ns_session_t *find_last_connection(netserver_mgr_t *mgr, int *cnt) {
  42. ns_session_t *conn = mgr->conns;
  43. if (mgr->conns == NULL) {
  44. /* There's no connection */
  45. return NULL;
  46. }
  47. (*cnt)++;
  48. while (conn->next) {
  49. conn = conn->next;
  50. (*cnt)++;
  51. }
  52. return conn;
  53. }
  54. /**
  55. * Name: ns_session_create
  56. * Brief: create netserber session
  57. * Input:
  58. * @flag: session flag
  59. * NS_USE_SSL : use tls connection
  60. * Output: netserver manager handler , NULL if create failed
  61. */
  62. static ns_session_t *ns_session_create(netserver_mgr_t *mgr, uint32_t flag) {
  63. ns_session_t *session = NS_CALLOC(1, sizeof(ns_session_t));
  64. if (session == NULL) {
  65. NS_LOG("no memory for ns session");
  66. return NULL;
  67. }
  68. if (flag & NS_SESSION_F_LISTENING) {
  69. if (mgr->listener) {
  70. NS_LOG("already have a listener");
  71. NS_FREE(session);
  72. return NULL;
  73. } else {
  74. mgr->listener = session;
  75. }
  76. } else {
  77. int conn_cnt = 0;
  78. ns_session_t *last_conn = find_last_connection(mgr, &conn_cnt);
  79. if (last_conn) {
  80. if (conn_cnt >= mgr->opts.max_conns) {
  81. NS_LOG("no more connections");
  82. NS_FREE(session);
  83. return NULL;
  84. } else {
  85. last_conn->next = session;
  86. }
  87. } else {
  88. mgr->conns = session;
  89. }
  90. }
  91. session->flag = flag;
  92. if (mgr->flag & NS_USE_SSL) session->flag |= NS_SESSION_F_SSL;
  93. session->socket = -1;
  94. session->tick_timeout =
  95. rt_tick_get() + rt_tick_from_millisecond(mgr->opts.session_timeout);
  96. return session;
  97. }
  98. static int ns_session_close(netserver_mgr_t *mgr, ns_session_t *session) {
  99. ns_session_t *iter;
  100. /* notify user */
  101. if (mgr->opts.callback.session_close_cb) {
  102. mgr->opts.callback.session_close_cb(session);
  103. }
  104. /* Close socket */
  105. if (session->socket >= 0) {
  106. closesocket(session->socket);
  107. }
  108. /* Free ssl data */
  109. #if NS_ENABLE_SSL
  110. if (session->flag & NS_SESSION_F_SSL) {
  111. ns_ssl_if_free(session);
  112. }
  113. #endif
  114. /*Free session data */
  115. if (IS_LISTEN_SESSION(session)) {
  116. NS_FREE(session);
  117. mgr->listener = NULL;
  118. } else {
  119. /* client session free */
  120. if (mgr->conns == session) {
  121. mgr->conns = session->next;
  122. } else {
  123. for (iter = mgr->conns; iter; iter = iter->next) {
  124. if (iter->next == session) {
  125. iter->next = session->next;
  126. break;
  127. }
  128. }
  129. }
  130. NS_FREE(session);
  131. }
  132. return 0;
  133. }
  134. static void _session_handle(netserver_mgr_t *mgr, ns_session_t *conn) {
  135. int ret = 0;
  136. void *data_buff = mgr->data_buff;
  137. uint32_t buff_sz = mgr->opts.data_pkg_max_size;
  138. conn->tick_timeout =
  139. rt_tick_get() + rt_tick_from_millisecond(mgr->opts.session_timeout);
  140. ret = netserver_read(conn, data_buff, buff_sz);
  141. /* close session if error occured */
  142. if (ret <= 0) {
  143. NS_LOG("socket %d read err,close it", conn->socket);
  144. ns_session_close(mgr, conn);
  145. return;
  146. }
  147. /* warn user if data buffer is full */
  148. if (ret == buff_sz) {
  149. NS_LOG("net server data buffer is full. current buffer size is %lu",
  150. buff_sz);
  151. }
  152. /* handle data package */
  153. if (mgr->opts.callback.data_readable_cb) {
  154. ret = mgr->opts.callback.data_readable_cb(conn, data_buff, ret);
  155. } else {
  156. // use default data handle logic
  157. if (ret > 0) {
  158. ret = netserver_write(conn, data_buff, ret);
  159. /* close session if error occured */
  160. if (ret < 0) {
  161. NS_LOG("socket %d send err,close it", conn->socket);
  162. ns_session_close(mgr, conn);
  163. return;
  164. }
  165. }
  166. }
  167. }
  168. /**
  169. * Name: ns_sesion_free_all_connections
  170. * Brief: This function will free all connections
  171. * except listen session
  172. * Input: None
  173. * Output: success:0
  174. */
  175. static int ns_sesion_close_all_connections(netserver_mgr_t *mgr) {
  176. ns_session_t *cur_conn, *next_conn;
  177. for (cur_conn = mgr->conns; cur_conn; cur_conn = next_conn) {
  178. /* obtain next connection in case it be closed */
  179. next_conn = cur_conn->next;
  180. if (ns_session_close(mgr, cur_conn) < 0) {
  181. NS_LOG("close session failed");
  182. return -1;
  183. }
  184. }
  185. return 0;
  186. }
  187. /**
  188. * Name: ns_all_connections_set_fds
  189. * Brief: set all connections fds
  190. * Input: None
  191. * Output: maximal fd number
  192. */
  193. static int ns_all_connections_set_fds(netserver_mgr_t *mgr, fd_set *readset,
  194. fd_set *exceptfds) {
  195. int maxfdp1 = 0;
  196. ns_session_t *session;
  197. for (session = mgr->conns; session; session = session->next) {
  198. if (maxfdp1 < session->socket + 1) maxfdp1 = session->socket + 1;
  199. FD_SET(session->socket, readset);
  200. FD_SET(session->socket, exceptfds);
  201. }
  202. return maxfdp1;
  203. }
  204. static void ns_session_handle(netserver_mgr_t *mgr, fd_set *readset,
  205. fd_set *excptset) {
  206. ns_session_t *cur_conn, *next_conn;
  207. if(mgr->conns == NULL){
  208. rt_thread_mdelay(1);
  209. }
  210. for (cur_conn = mgr->conns; cur_conn; cur_conn = next_conn) {
  211. // obtain next session in case current session be closed
  212. next_conn = cur_conn->next;
  213. if (mgr->opts.callback.session_poll_cb) {
  214. mgr->opts.callback.session_poll_cb(cur_conn);
  215. }
  216. if (FD_ISSET(cur_conn->socket, excptset)) {
  217. NS_LOG("socket %d error,now close", cur_conn->socket);
  218. ns_session_close(mgr, cur_conn);
  219. } else if (FD_ISSET(cur_conn->socket, readset)) {
  220. _session_handle(mgr, cur_conn);
  221. }
  222. }
  223. }
  224. /*------------------------------------------------------------------------------------//
  225. NET SERVER
  226. //------------------------------------------------------------------------------------*/
  227. /**
  228. * Name: netserver_create
  229. * Brief: create netserber manager
  230. * Input:
  231. * @opts: netserver options
  232. * @flag: server flag
  233. * NS_USE_SSL : use tls connection
  234. * Output: netserver manager handler , NULL if create failed
  235. */
  236. netserver_mgr_t *netserver_create(netserver_opt_t *opts, uint32_t flag) {
  237. netserver_mgr_t *mgr = NS_CALLOC(1, sizeof(netserver_mgr_t));
  238. if (mgr == NULL) {
  239. NS_LOG("no memory for netserver manager");
  240. return NULL;
  241. }
  242. mgr->flag = flag;
  243. if (opts->data_pkg_max_size == 0) {
  244. opts->data_pkg_max_size = NS_DATA_PKG_MAX_SIZE_DEFAULT;
  245. }
  246. mgr->data_buff = NS_CALLOC(1, opts->data_pkg_max_size);
  247. if (mgr->data_buff == NULL) {
  248. NS_LOG("no memory for data buffer.");
  249. NS_FREE(mgr);
  250. return NULL;
  251. }
  252. NS_MEMCPY(&mgr->opts, opts, sizeof(netserver_opt_t));
  253. return mgr;
  254. }
  255. static void netserver_close_all(netserver_mgr_t *mgr) {
  256. /* close and free all connections */
  257. if (mgr->conns) {
  258. ns_sesion_close_all_connections(mgr);
  259. mgr->conns = NULL;
  260. }
  261. /* close listen session*/
  262. if (mgr->listener) {
  263. ns_session_close(mgr, mgr->listener);
  264. mgr->listener = NULL;
  265. }
  266. }
  267. static void check_session_close(netserver_mgr_t *mgr) {
  268. ns_session_t *conn = NULL;
  269. for (conn = mgr->conns; conn; conn = conn->next) {
  270. if (conn->flag & NS_SESSION_F_CLOSE) {
  271. NS_LOG("connecion %d received close command,close it.", conn->socket);
  272. ns_session_close(mgr, conn);
  273. }
  274. }
  275. }
  276. static void check_session_timeout(netserver_mgr_t *mgr) {
  277. ns_session_t *conn = NULL;
  278. if (mgr->opts.session_timeout == 0) {
  279. return;
  280. }
  281. for (conn = mgr->conns; conn; conn = conn->next) {
  282. if ((rt_tick_get() - conn->tick_timeout) < (RT_TICK_MAX / 2)) {
  283. NS_LOG("connecion %d timout,close it.", conn->socket);
  284. ns_session_close(mgr, conn);
  285. }
  286. }
  287. }
  288. static void netserver_accept_and_close(netserver_mgr_t *mgr) {
  289. int sock;
  290. struct sockaddr cliaddr;
  291. socklen_t clilen;
  292. clilen = sizeof(struct sockaddr_in);
  293. sock = accept(mgr->listener->socket, &cliaddr, &clilen);
  294. if (sock >= 0) {
  295. closesocket(sock);
  296. }
  297. }
  298. int netserver_read(ns_session_t *ns, void *data, int sz) {
  299. if (IS_CLOSED_SESSION(ns)) return 0;
  300. #if NS_ENABLE_SSL
  301. if (ns->flag & NS_SESSION_F_SSL) {
  302. return ns_ssl_if_read(ns, data, sz);
  303. } else
  304. #endif
  305. {
  306. return recv(ns->socket, data, sz, 0);
  307. }
  308. }
  309. int netserver_write(ns_session_t *ns, void *data, int sz) {
  310. if (IS_CLOSED_SESSION(ns)) return 0;
  311. #if NS_ENABLE_SSL
  312. if (ns->flag & NS_SESSION_F_SSL) {
  313. return ns_ssl_if_write(ns, data, sz);
  314. } else
  315. #endif
  316. {
  317. return send(ns->socket, data, sz, 0);
  318. }
  319. }
  320. int netserver_mgr_free(netserver_mgr_t *mgr) {
  321. if (mgr->conns || mgr->listener) {
  322. NS_LOG("still have connection, can't free mgr.");
  323. return -1;
  324. }
  325. if (mgr->data_buff) {
  326. NS_FREE(mgr->data_buff);
  327. mgr->data_buff = NULL;
  328. }
  329. NS_FREE(mgr);
  330. return 0;
  331. }
  332. void netserver_set_session_timeout(netserver_mgr_t *mgr, uint32_t ms) {
  333. mgr->opts.session_timeout = ms;
  334. }
  335. /**
  336. * Name: netserver_restart
  337. * Brief: this function will close all connections and restart server
  338. * this will reload ssl certificates
  339. * Input: netserver mananger
  340. * Output: None
  341. */
  342. void netserver_restart(netserver_mgr_t *mgr) { mgr->flag |= NS_RESET_FLAG; }
  343. void netserver_session_close(ns_session_t *ns) { ns->flag |= NS_SESSION_F_CLOSE; }
  344. static int listen_socket_create(netserver_mgr_t *mgr) {
  345. int reuse = 1;
  346. struct sockaddr_in servaddr;
  347. mgr->listener = ns_session_create(mgr, NS_SESSION_F_LISTENING);
  348. if (mgr->listener == NULL) {
  349. NS_LOG("cannot create netserver session");
  350. return -1;
  351. }
  352. mgr->listener->socket = socket(AF_INET, SOCK_STREAM, 0);
  353. if (mgr->listener->socket < 0) {
  354. printf("create socket failed.\r\n");
  355. return -1;
  356. }
  357. setsockopt(mgr->listener->socket, SOL_SOCKET, SO_REUSEADDR, &reuse,
  358. sizeof(reuse));
  359. rt_memset(&servaddr, 0, sizeof(servaddr));
  360. servaddr.sin_family = AF_INET;
  361. servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  362. servaddr.sin_port = htons(mgr->opts.listen_port);
  363. if (bind(mgr->listener->socket, (struct sockaddr *)&servaddr,
  364. sizeof(servaddr)) == -1) {
  365. printf("socket %d bind failed.\r\n", mgr->listener->socket);
  366. closesocket(mgr->listener->socket);
  367. return -1;
  368. }
  369. if (listen(mgr->listener->socket, NS_IF_LISTEN_BACKLOG) < 0) {
  370. printf("socket %d listen failed.\r\n", mgr->listener->socket);
  371. closesocket(mgr->listener->socket);
  372. return -1;
  373. }
  374. return 0;
  375. }
  376. static void netserver_handle(void *param) {
  377. netserver_mgr_t *mgr = (netserver_mgr_t *)param;
  378. fd_set readset, exceptfds, tempreadfds, tempexptfds;
  379. int maxfd = 0, sockfd = -1;
  380. unsigned long ul = 1;
  381. struct timeval timeout;
  382. /* Clear reset flag */
  383. mgr->flag &= ~(NS_RESET_FLAG);
  384. /* Create listen socket */
  385. if (listen_socket_create(mgr) < 0) {
  386. NS_LOG("create socket failed.");
  387. goto exit;
  388. }
  389. NS_LOG("net server listening on port:%d.",mgr->opts.listen_port);
  390. #if NS_ENABLE_SSL
  391. /* Create ssl context*/
  392. if (mgr->flag & NS_USE_SSL) {
  393. if (ns_ssl_if_context_create(mgr) < 0) {
  394. NS_LOG("create ssl context failed.");
  395. }
  396. }
  397. #endif
  398. timeout.tv_sec = NS_SELECT_TIMEOUT / 1000;
  399. timeout.tv_usec = (NS_SELECT_TIMEOUT % 1000) * 1000;
  400. /* waiting for new connection or data come in */
  401. for (;;) {
  402. FD_ZERO(&readset);
  403. FD_ZERO(&exceptfds);
  404. FD_SET(mgr->listener->socket, &readset);
  405. FD_SET(mgr->listener->socket, &exceptfds);
  406. maxfd = ns_all_connections_set_fds(mgr, &readset, &exceptfds);
  407. if (maxfd < mgr->listener->socket + 1)
  408. maxfd = mgr->listener->socket + 1;
  409. // prevent select from changing
  410. tempreadfds = readset;
  411. tempexptfds = exceptfds;
  412. sockfd = select(maxfd, &tempreadfds, NULL, &tempexptfds, &timeout);
  413. if (NS_IS_RESET(mgr->flag)) {
  414. NS_LOG("restart netserver");
  415. goto exit;
  416. }
  417. check_session_close(mgr);
  418. check_session_timeout(mgr);
  419. if (sockfd == 0) {
  420. if (mgr->opts.callback.session_poll_cb) {
  421. mgr->opts.callback.session_poll_cb(NULL);
  422. }
  423. // NS_LOG("net server select timeout");
  424. continue;
  425. } else if (sockfd == -1) {
  426. // maybe netdev is down, we close all connections and try to reset
  427. // server.
  428. goto exit;
  429. }
  430. /* if the listen fd is error*/
  431. if(FD_ISSET(mgr->listener->socket,&tempexptfds)){
  432. NS_LOG("listen socket is error, now restart netserver.");
  433. goto exit;
  434. }
  435. /* if the listen fd is ready*/
  436. if (FD_ISSET(mgr->listener->socket, &tempreadfds)) {
  437. socklen_t clilen;
  438. NS_LOG("new connection comes in");
  439. clilen = sizeof(struct sockaddr_in);
  440. ns_session_t *new_conn = ns_session_create(mgr, 0);
  441. if (new_conn) {
  442. /* notify user */
  443. if (mgr->opts.callback.session_create_cb)
  444. mgr->opts.callback.session_create_cb(new_conn);
  445. new_conn->socket =
  446. accept(mgr->listener->socket,
  447. (struct sockaddr *)&new_conn->cliaddr, &clilen);
  448. if (new_conn->socket < 0) {
  449. NS_LOG("new connection accept failed");
  450. ns_session_close(mgr, new_conn);
  451. } else {
  452. int ret = -1;
  453. /* notify user */
  454. if (mgr->opts.callback.session_accept_cb) {
  455. if (mgr->opts.callback.session_accept_cb(new_conn) <
  456. 0) {
  457. /* when user return -1, we close connection */
  458. ns_session_close(mgr, new_conn);
  459. new_conn = NULL;
  460. goto session_handle;
  461. }
  462. }
  463. #if NS_ENABLE_SSL
  464. /* Do handshake */
  465. if (mgr->flag & NS_USE_SSL) {
  466. if (ns_ssl_if_handshake(mgr, new_conn) < 0) {
  467. ns_session_close(mgr, new_conn);
  468. new_conn = NULL;
  469. goto session_handle;
  470. }
  471. }
  472. #endif
  473. if (new_conn) {
  474. ret = ioctlsocket(new_conn->socket, FIONBIO,
  475. (unsigned long *)&ul);
  476. if (ret < 0) {
  477. NS_LOG("set socket non-block failed");
  478. }
  479. }
  480. // FD_SET(new_conn->socket, &readset);
  481. // FD_SET(new_conn->socket, &exceptfds);
  482. }
  483. } else {
  484. /* cannot create new connection,just accept and close it */
  485. NS_LOG("accept connection and close");
  486. netserver_accept_and_close(mgr);
  487. }
  488. }
  489. session_handle:
  490. /* handle sessions */
  491. ns_session_handle(mgr, &tempreadfds, &tempexptfds);
  492. }
  493. exit:
  494. netserver_close_all(mgr);
  495. if (mgr->opts.callback.netserver_reset_cb) {
  496. mgr->opts.callback.netserver_reset_cb(mgr);
  497. }
  498. }
  499. static void netserver(void *param) {
  500. while (1) {
  501. netserver_handle(param);
  502. rt_thread_mdelay(1000);
  503. }
  504. }
  505. int netserver_start(netserver_mgr_t *mgr) {
  506. uint32_t stack_size = 0, tick = 0;
  507. uint8_t priority = 0;
  508. stack_size = mgr->opts.thread_attrs.stack_size
  509. ? mgr->opts.thread_attrs.stack_size
  510. : NS_THREAD_STACK_SIZE_DEFAULT;
  511. tick = mgr->opts.thread_attrs.tick ? mgr->opts.thread_attrs.tick
  512. : NS_THREAD_TICK_DEFAULT;
  513. priority = mgr->opts.thread_attrs.priority ? mgr->opts.thread_attrs.priority
  514. : NS_THREAD_PRIORITY_DEFAULT;
  515. rt_thread_t tid = rt_thread_create("netserver", netserver, mgr, stack_size,
  516. priority, tick);
  517. if (tid) {
  518. if (rt_thread_startup(tid) == RT_EOK) {
  519. return 0;
  520. } else {
  521. return -1;
  522. }
  523. } else {
  524. return -1;
  525. }
  526. }