PageRenderTime 25ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/PacketProcessor/tun2socks-iOS/lwip/src/core/timers.c

https://gitlab.com/longkas/Potatso-iOS
C | 545 lines | 342 code | 40 blank | 163 comment | 53 complexity | 0b9f042bdc45b3fcada7c6f2631606a0 MD5 | raw file
  1. /**
  2. * @file
  3. * Stack-internal timers implementation.
  4. * This file includes timer callbacks for stack-internal timers as well as
  5. * functions to set up or stop timers and check for expired timers.
  6. *
  7. */
  8. /*
  9. * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
  10. * All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or without modification,
  13. * are permitted provided that the following conditions are met:
  14. *
  15. * 1. Redistributions of source code must retain the above copyright notice,
  16. * this list of conditions and the following disclaimer.
  17. * 2. Redistributions in binary form must reproduce the above copyright notice,
  18. * this list of conditions and the following disclaimer in the documentation
  19. * and/or other materials provided with the distribution.
  20. * 3. The name of the author may not be used to endorse or promote products
  21. * derived from this software without specific prior written permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  24. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  25. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  26. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  27. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  28. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  29. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  30. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  31. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  32. * OF SUCH DAMAGE.
  33. *
  34. * This file is part of the lwIP TCP/IP stack.
  35. *
  36. * Author: Adam Dunkels <adam@sics.se>
  37. * Simon Goldschmidt
  38. *
  39. */
  40. #include "lwip/opt.h"
  41. #include "lwip/timers.h"
  42. #include "lwip/tcp_impl.h"
  43. #if LWIP_TIMERS
  44. #include "lwip/def.h"
  45. #include "lwip/memp.h"
  46. #include "lwip/tcpip.h"
  47. #include "lwip/ip_frag.h"
  48. #include "netif/etharp.h"
  49. #include "lwip/dhcp.h"
  50. #include "lwip/autoip.h"
  51. #include "lwip/igmp.h"
  52. #include "lwip/dns.h"
  53. #include "lwip/nd6.h"
  54. #include "lwip/ip6_frag.h"
  55. #include "lwip/mld6.h"
  56. #include "lwip/sys.h"
  57. #include "lwip/pbuf.h"
  58. /** The one and only timeout list */
  59. static struct sys_timeo *next_timeout;
  60. #if NO_SYS
  61. static u32_t timeouts_last_time;
  62. #endif /* NO_SYS */
  63. #if LWIP_TCP
  64. /** global variable that shows if the tcp timer is currently scheduled or not */
  65. static int tcpip_tcp_timer_active;
  66. /**
  67. * Timer callback function that calls tcp_tmr() and reschedules itself.
  68. *
  69. * @param arg unused argument
  70. */
  71. static void
  72. tcpip_tcp_timer(void *arg)
  73. {
  74. LWIP_UNUSED_ARG(arg);
  75. /* call TCP timer handler */
  76. tcp_tmr();
  77. /* timer still needed? */
  78. if (tcp_active_pcbs || tcp_tw_pcbs) {
  79. /* restart timer */
  80. sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
  81. } else {
  82. /* disable timer */
  83. tcpip_tcp_timer_active = 0;
  84. }
  85. }
  86. /**
  87. * Called from TCP_REG when registering a new PCB:
  88. * the reason is to have the TCP timer only running when
  89. * there are active (or time-wait) PCBs.
  90. */
  91. void
  92. tcp_timer_needed(void)
  93. {
  94. /* timer is off but needed again? */
  95. if (!tcpip_tcp_timer_active && (tcp_active_pcbs || tcp_tw_pcbs)) {
  96. /* enable and start timer */
  97. tcpip_tcp_timer_active = 1;
  98. sys_timeout(TCP_TMR_INTERVAL, tcpip_tcp_timer, NULL);
  99. }
  100. }
  101. #endif /* LWIP_TCP */
  102. #if IP_REASSEMBLY
  103. /**
  104. * Timer callback function that calls ip_reass_tmr() and reschedules itself.
  105. *
  106. * @param arg unused argument
  107. */
  108. static void
  109. ip_reass_timer(void *arg)
  110. {
  111. LWIP_UNUSED_ARG(arg);
  112. LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip_reass_tmr()\n"));
  113. ip_reass_tmr();
  114. sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
  115. }
  116. #endif /* IP_REASSEMBLY */
  117. #if LWIP_ARP
  118. /**
  119. * Timer callback function that calls etharp_tmr() and reschedules itself.
  120. *
  121. * @param arg unused argument
  122. */
  123. static void
  124. arp_timer(void *arg)
  125. {
  126. LWIP_UNUSED_ARG(arg);
  127. LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: etharp_tmr()\n"));
  128. etharp_tmr();
  129. sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
  130. }
  131. #endif /* LWIP_ARP */
  132. #if LWIP_DHCP
  133. /**
  134. * Timer callback function that calls dhcp_coarse_tmr() and reschedules itself.
  135. *
  136. * @param arg unused argument
  137. */
  138. static void
  139. dhcp_timer_coarse(void *arg)
  140. {
  141. LWIP_UNUSED_ARG(arg);
  142. LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_coarse_tmr()\n"));
  143. dhcp_coarse_tmr();
  144. sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
  145. }
  146. /**
  147. * Timer callback function that calls dhcp_fine_tmr() and reschedules itself.
  148. *
  149. * @param arg unused argument
  150. */
  151. static void
  152. dhcp_timer_fine(void *arg)
  153. {
  154. LWIP_UNUSED_ARG(arg);
  155. LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dhcp_fine_tmr()\n"));
  156. dhcp_fine_tmr();
  157. sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
  158. }
  159. #endif /* LWIP_DHCP */
  160. #if LWIP_AUTOIP
  161. /**
  162. * Timer callback function that calls autoip_tmr() and reschedules itself.
  163. *
  164. * @param arg unused argument
  165. */
  166. static void
  167. autoip_timer(void *arg)
  168. {
  169. LWIP_UNUSED_ARG(arg);
  170. LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: autoip_tmr()\n"));
  171. autoip_tmr();
  172. sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
  173. }
  174. #endif /* LWIP_AUTOIP */
  175. #if LWIP_IGMP
  176. /**
  177. * Timer callback function that calls igmp_tmr() and reschedules itself.
  178. *
  179. * @param arg unused argument
  180. */
  181. static void
  182. igmp_timer(void *arg)
  183. {
  184. LWIP_UNUSED_ARG(arg);
  185. LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: igmp_tmr()\n"));
  186. igmp_tmr();
  187. sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
  188. }
  189. #endif /* LWIP_IGMP */
  190. #if LWIP_DNS
  191. /**
  192. * Timer callback function that calls dns_tmr() and reschedules itself.
  193. *
  194. * @param arg unused argument
  195. */
  196. static void
  197. dns_timer(void *arg)
  198. {
  199. LWIP_UNUSED_ARG(arg);
  200. LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: dns_tmr()\n"));
  201. dns_tmr();
  202. sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
  203. }
  204. #endif /* LWIP_DNS */
  205. #if LWIP_IPV6
  206. /**
  207. * Timer callback function that calls nd6_tmr() and reschedules itself.
  208. *
  209. * @param arg unused argument
  210. */
  211. static void
  212. nd6_timer(void *arg)
  213. {
  214. LWIP_UNUSED_ARG(arg);
  215. LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: nd6_tmr()\n"));
  216. nd6_tmr();
  217. sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL);
  218. }
  219. #if LWIP_IPV6_REASS
  220. /**
  221. * Timer callback function that calls ip6_reass_tmr() and reschedules itself.
  222. *
  223. * @param arg unused argument
  224. */
  225. static void
  226. ip6_reass_timer(void *arg)
  227. {
  228. LWIP_UNUSED_ARG(arg);
  229. LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: ip6_reass_tmr()\n"));
  230. ip6_reass_tmr();
  231. sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL);
  232. }
  233. #endif /* LWIP_IPV6_REASS */
  234. #if LWIP_IPV6_MLD
  235. /**
  236. * Timer callback function that calls mld6_tmr() and reschedules itself.
  237. *
  238. * @param arg unused argument
  239. */
  240. static void
  241. mld6_timer(void *arg)
  242. {
  243. LWIP_UNUSED_ARG(arg);
  244. LWIP_DEBUGF(TIMERS_DEBUG, ("tcpip: mld6_tmr()\n"));
  245. mld6_tmr();
  246. sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL);
  247. }
  248. #endif /* LWIP_IPV6_MLD */
  249. #endif /* LWIP_IPV6 */
  250. /** Initialize this module */
  251. void sys_timeouts_init(void)
  252. {
  253. #if IP_REASSEMBLY
  254. sys_timeout(IP_TMR_INTERVAL, ip_reass_timer, NULL);
  255. #endif /* IP_REASSEMBLY */
  256. #if LWIP_ARP
  257. sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);
  258. #endif /* LWIP_ARP */
  259. #if LWIP_DHCP
  260. sys_timeout(DHCP_COARSE_TIMER_MSECS, dhcp_timer_coarse, NULL);
  261. sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
  262. #endif /* LWIP_DHCP */
  263. #if LWIP_AUTOIP
  264. sys_timeout(AUTOIP_TMR_INTERVAL, autoip_timer, NULL);
  265. #endif /* LWIP_AUTOIP */
  266. #if LWIP_IGMP
  267. sys_timeout(IGMP_TMR_INTERVAL, igmp_timer, NULL);
  268. #endif /* LWIP_IGMP */
  269. #if LWIP_DNS
  270. sys_timeout(DNS_TMR_INTERVAL, dns_timer, NULL);
  271. #endif /* LWIP_DNS */
  272. #if LWIP_IPV6
  273. sys_timeout(ND6_TMR_INTERVAL, nd6_timer, NULL);
  274. #if LWIP_IPV6_REASS
  275. sys_timeout(IP6_REASS_TMR_INTERVAL, ip6_reass_timer, NULL);
  276. #endif /* LWIP_IPV6_REASS */
  277. #if LWIP_IPV6_MLD
  278. sys_timeout(MLD6_TMR_INTERVAL, mld6_timer, NULL);
  279. #endif /* LWIP_IPV6_MLD */
  280. #endif /* LWIP_IPV6 */
  281. #if NO_SYS
  282. /* Initialise timestamp for sys_check_timeouts */
  283. timeouts_last_time = sys_now();
  284. #endif
  285. }
  286. /**
  287. * Create a one-shot timer (aka timeout). Timeouts are processed in the
  288. * following cases:
  289. * - while waiting for a message using sys_timeouts_mbox_fetch()
  290. * - by calling sys_check_timeouts() (NO_SYS==1 only)
  291. *
  292. * @param msecs time in milliseconds after that the timer should expire
  293. * @param handler callback function to call when msecs have elapsed
  294. * @param arg argument to pass to the callback function
  295. */
  296. #if LWIP_DEBUG_TIMERNAMES
  297. void
  298. sys_timeout_debug(u32_t msecs, sys_timeout_handler handler, void *arg, const char* handler_name)
  299. #else /* LWIP_DEBUG_TIMERNAMES */
  300. void
  301. sys_timeout(u32_t msecs, sys_timeout_handler handler, void *arg)
  302. #endif /* LWIP_DEBUG_TIMERNAMES */
  303. {
  304. struct sys_timeo *timeout, *t;
  305. timeout = (struct sys_timeo *)memp_malloc(MEMP_SYS_TIMEOUT);
  306. if (timeout == NULL) {
  307. LWIP_ASSERT("sys_timeout: timeout != NULL, pool MEMP_SYS_TIMEOUT is empty", timeout != NULL);
  308. return;
  309. }
  310. timeout->next = NULL;
  311. timeout->h = handler;
  312. timeout->arg = arg;
  313. timeout->time = msecs;
  314. #if LWIP_DEBUG_TIMERNAMES
  315. timeout->handler_name = handler_name;
  316. LWIP_DEBUGF(TIMERS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" handler=%s arg=%p\n",
  317. (void *)timeout, msecs, handler_name, (void *)arg));
  318. #endif /* LWIP_DEBUG_TIMERNAMES */
  319. if (next_timeout == NULL) {
  320. next_timeout = timeout;
  321. return;
  322. }
  323. if (next_timeout->time > msecs) {
  324. next_timeout->time -= msecs;
  325. timeout->next = next_timeout;
  326. next_timeout = timeout;
  327. } else {
  328. for(t = next_timeout; t != NULL; t = t->next) {
  329. timeout->time -= t->time;
  330. if (t->next == NULL || t->next->time > timeout->time) {
  331. if (t->next != NULL) {
  332. t->next->time -= timeout->time;
  333. }
  334. timeout->next = t->next;
  335. t->next = timeout;
  336. break;
  337. }
  338. }
  339. }
  340. }
  341. /**
  342. * Go through timeout list (for this task only) and remove the first matching
  343. * entry, even though the timeout has not triggered yet.
  344. *
  345. * @note This function only works as expected if there is only one timeout
  346. * calling 'handler' in the list of timeouts.
  347. *
  348. * @param handler callback function that would be called by the timeout
  349. * @param arg callback argument that would be passed to handler
  350. */
  351. void
  352. sys_untimeout(sys_timeout_handler handler, void *arg)
  353. {
  354. struct sys_timeo *prev_t, *t;
  355. if (next_timeout == NULL) {
  356. return;
  357. }
  358. for (t = next_timeout, prev_t = NULL; t != NULL; prev_t = t, t = t->next) {
  359. if ((t->h == handler) && (t->arg == arg)) {
  360. /* We have a match */
  361. /* Unlink from previous in list */
  362. if (prev_t == NULL) {
  363. next_timeout = t->next;
  364. } else {
  365. prev_t->next = t->next;
  366. }
  367. /* If not the last one, add time of this one back to next */
  368. if (t->next != NULL) {
  369. t->next->time += t->time;
  370. }
  371. memp_free(MEMP_SYS_TIMEOUT, t);
  372. return;
  373. }
  374. }
  375. return;
  376. }
  377. #if NO_SYS
  378. /** Handle timeouts for NO_SYS==1 (i.e. without using
  379. * tcpip_thread/sys_timeouts_mbox_fetch(). Uses sys_now() to call timeout
  380. * handler functions when timeouts expire.
  381. *
  382. * Must be called periodically from your main loop.
  383. */
  384. void
  385. sys_check_timeouts(void)
  386. {
  387. if (next_timeout) {
  388. struct sys_timeo *tmptimeout;
  389. u32_t diff;
  390. sys_timeout_handler handler;
  391. void *arg;
  392. u8_t had_one;
  393. u32_t now;
  394. now = sys_now();
  395. /* this cares for wraparounds */
  396. diff = now - timeouts_last_time;
  397. do
  398. {
  399. #if PBUF_POOL_FREE_OOSEQ
  400. PBUF_CHECK_FREE_OOSEQ();
  401. #endif /* PBUF_POOL_FREE_OOSEQ */
  402. had_one = 0;
  403. tmptimeout = next_timeout;
  404. if (tmptimeout && (tmptimeout->time <= diff)) {
  405. /* timeout has expired */
  406. had_one = 1;
  407. timeouts_last_time = now;
  408. diff -= tmptimeout->time;
  409. next_timeout = tmptimeout->next;
  410. handler = tmptimeout->h;
  411. arg = tmptimeout->arg;
  412. #if LWIP_DEBUG_TIMERNAMES
  413. if (handler != NULL) {
  414. LWIP_DEBUGF(TIMERS_DEBUG, ("sct calling h=%s arg=%p\n",
  415. tmptimeout->handler_name, arg));
  416. }
  417. #endif /* LWIP_DEBUG_TIMERNAMES */
  418. memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
  419. if (handler != NULL) {
  420. handler(arg);
  421. }
  422. }
  423. /* repeat until all expired timers have been called */
  424. }while(had_one);
  425. }
  426. }
  427. /** Set back the timestamp of the last call to sys_check_timeouts()
  428. * This is necessary if sys_check_timeouts() hasn't been called for a long
  429. * time (e.g. while saving energy) to prevent all timer functions of that
  430. * period being called.
  431. */
  432. void
  433. sys_restart_timeouts(void)
  434. {
  435. timeouts_last_time = sys_now();
  436. }
  437. #else /* NO_SYS */
  438. /**
  439. * Wait (forever) for a message to arrive in an mbox.
  440. * While waiting, timeouts are processed.
  441. *
  442. * @param mbox the mbox to fetch the message from
  443. * @param msg the place to store the message
  444. */
  445. void
  446. sys_timeouts_mbox_fetch(sys_mbox_t *mbox, void **msg)
  447. {
  448. u32_t time_needed;
  449. struct sys_timeo *tmptimeout;
  450. sys_timeout_handler handler;
  451. void *arg;
  452. again:
  453. if (!next_timeout) {
  454. time_needed = sys_arch_mbox_fetch(mbox, msg, 0);
  455. } else {
  456. if (next_timeout->time > 0) {
  457. time_needed = sys_arch_mbox_fetch(mbox, msg, next_timeout->time);
  458. } else {
  459. time_needed = SYS_ARCH_TIMEOUT;
  460. }
  461. if (time_needed == SYS_ARCH_TIMEOUT) {
  462. /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
  463. could be fetched. We should now call the timeout handler and
  464. deallocate the memory allocated for the timeout. */
  465. tmptimeout = next_timeout;
  466. next_timeout = tmptimeout->next;
  467. handler = tmptimeout->h;
  468. arg = tmptimeout->arg;
  469. #if LWIP_DEBUG_TIMERNAMES
  470. if (handler != NULL) {
  471. LWIP_DEBUGF(TIMERS_DEBUG, ("stmf calling h=%s arg=%p\n",
  472. tmptimeout->handler_name, arg));
  473. }
  474. #endif /* LWIP_DEBUG_TIMERNAMES */
  475. memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
  476. if (handler != NULL) {
  477. /* For LWIP_TCPIP_CORE_LOCKING, lock the core before calling the
  478. timeout handler function. */
  479. LOCK_TCPIP_CORE();
  480. handler(arg);
  481. UNLOCK_TCPIP_CORE();
  482. }
  483. LWIP_TCPIP_THREAD_ALIVE();
  484. /* We try again to fetch a message from the mbox. */
  485. goto again;
  486. } else {
  487. /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
  488. occured. The time variable is set to the number of
  489. milliseconds we waited for the message. */
  490. if (time_needed < next_timeout->time) {
  491. next_timeout->time -= time_needed;
  492. } else {
  493. next_timeout->time = 0;
  494. }
  495. }
  496. }
  497. }
  498. #endif /* NO_SYS */
  499. #else /* LWIP_TIMERS */
  500. /* Satisfy the TCP code which calls this function */
  501. void
  502. tcp_timer_needed(void)
  503. {
  504. }
  505. #endif /* LWIP_TIMERS */