netserver.c 17 KB

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