Example program with HTTPServer and sensor data streaming over TCPSockets, using Donatien Garnier's Net APIs and services code on top of LWIP. Files StreamServer.h and .cpp encapsulate streaming over TCPSockets. Broadcast is done by sendToAll(), and all incoming data is echoed back to the client. Echo code can be replaced with some remote control of the streaming interface. See main() that shows how to periodically send some data to all subscribed clients. To subscribe, a client should open a socket at <mbed_ip> port 123. I used few lines in TCL code to set up a quick sink for the data. HTTP files are served on port 80 concurrently to the streaming.

Dependencies:   mbed

Committer:
iva2k
Date:
Sat Jun 12 06:01:50 2010 +0000
Revision:
0:e614f7875b60

        

Who changed what in which revision?

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