Example program for the lwIP TCP/IP stack (library lwip_1_4_0_rc2) and the QP state machine framework (library qp). This program demonstrates use of lwIP in hard real-time applications, in which the TCP/IP stack is used to monitor and configure the embedded device as well as to provide remote user interface (e.g., by means of a web browser). In particular, the lwIP stack, which is not reentrant, is strictly encapsulated inside a dedicated QP state machine object (active object in QP), so interrupt locking around calls to lwIP is unnecessary. Also, the Ethernet interrupt service routine (ISR) runs very fast without performing any lengthy copy operations. All this means that hard-real-time processing can be done at the task level, especially when you use the preemptive QK kernel built into QP for executing your application. No external RTOS component is needed to achieve fully deterministic real-time response of active object tasks prioritized above the lwiP task. The lwIP-QP integration uses exclusively the event-driven lwIP API. The heavyweight Berkeley-like socket API requiring a blocking RTOS and is not used, which results in much better performance of the lwIP stack and less memory consumption. NOTE: This example compiles cleanly, but does not run just yet because the low-level Ethernet driver in the lwIP library needs to be completed. See comments in the lwip_1_4_0_rc2 library for more information.

Dependencies:   mbed

Committer:
QL
Date:
Sun Mar 27 16:50:21 2011 +0000
Revision:
0:84f3d3d7e5d9
0.9

Who changed what in which revision?

UserRevisionLine numberNew contents of line
QL 0:84f3d3d7e5d9 1 //////////////////////////////////////////////////////////////////////////////
QL 0:84f3d3d7e5d9 2 // Product: lwIP-Manager Active Object
QL 0:84f3d3d7e5d9 3 // Last Updated for Version: 4.1.06
QL 0:84f3d3d7e5d9 4 // Date of the Last Update: Feb 21, 2011
QL 0:84f3d3d7e5d9 5 //
QL 0:84f3d3d7e5d9 6 // Q u a n t u m L e a P s
QL 0:84f3d3d7e5d9 7 // ---------------------------
QL 0:84f3d3d7e5d9 8 // innovating embedded systems
QL 0:84f3d3d7e5d9 9 //
QL 0:84f3d3d7e5d9 10 // Copyright (C) 2002-2011 Quantum Leaps, LLC. All rights reserved.
QL 0:84f3d3d7e5d9 11 //
QL 0:84f3d3d7e5d9 12 // This software may be distributed and modified under the terms of the GNU
QL 0:84f3d3d7e5d9 13 // General Public License version 2 (GPL) as published by the Free Software
QL 0:84f3d3d7e5d9 14 // Foundation and appearing in the file GPL.TXT included in the packaging of
QL 0:84f3d3d7e5d9 15 // this file. Please note that GPL Section 2[b] requires that all works based
QL 0:84f3d3d7e5d9 16 // on this software must also be made publicly available under the terms of
QL 0:84f3d3d7e5d9 17 // the GPL ("Copyleft").
QL 0:84f3d3d7e5d9 18 //
QL 0:84f3d3d7e5d9 19 // Alternatively, this software may be distributed and modified under the
QL 0:84f3d3d7e5d9 20 // terms of Quantum Leaps commercial licenses, which expressly supersede
QL 0:84f3d3d7e5d9 21 // the GPL and are specifically designed for licensees interested in
QL 0:84f3d3d7e5d9 22 // retaining the proprietary status of their code.
QL 0:84f3d3d7e5d9 23 //
QL 0:84f3d3d7e5d9 24 // Contact information:
QL 0:84f3d3d7e5d9 25 // Quantum Leaps Web site: http://www.quantum-leaps.com
QL 0:84f3d3d7e5d9 26 // e-mail: info@quantum-leaps.com
QL 0:84f3d3d7e5d9 27 //////////////////////////////////////////////////////////////////////////////
QL 0:84f3d3d7e5d9 28 #include "qp_port.h" // QP-port
QL 0:84f3d3d7e5d9 29 #include "dpp.h" // application events and active objects
QL 0:84f3d3d7e5d9 30 #include "bsp.h" // Board Support Package
QL 0:84f3d3d7e5d9 31
QL 0:84f3d3d7e5d9 32 #include "lwip/opt.h" // lwIP options come first
QL 0:84f3d3d7e5d9 33 #include "lwip/stats.h"
QL 0:84f3d3d7e5d9 34 #include "lwip/tcp.h"
QL 0:84f3d3d7e5d9 35 #include "lwip/tcp_impl.h"
QL 0:84f3d3d7e5d9 36 #include "lwip/udp.h"
QL 0:84f3d3d7e5d9 37 #include "lwip/tcpip.h"
QL 0:84f3d3d7e5d9 38 #include "lwip/mem.h"
QL 0:84f3d3d7e5d9 39 #include "lwip/autoip.h"
QL 0:84f3d3d7e5d9 40 #include "lwip/dhcp.h"
QL 0:84f3d3d7e5d9 41
QL 0:84f3d3d7e5d9 42 #include "netif/etharp.h"
QL 0:84f3d3d7e5d9 43 #include "port/eth_driver.h"
QL 0:84f3d3d7e5d9 44 // utilities added by QL...
QL 0:84f3d3d7e5d9 45 #include "app/httpd.h" // application layer protocols
QL 0:84f3d3d7e5d9 46
QL 0:84f3d3d7e5d9 47 #include <string.h>
QL 0:84f3d3d7e5d9 48 #include <stdio.h>
QL 0:84f3d3d7e5d9 49
QL 0:84f3d3d7e5d9 50 Q_DEFINE_THIS_FILE
QL 0:84f3d3d7e5d9 51
QL 0:84f3d3d7e5d9 52 // application signals cannot overlap the device-driver signals
QL 0:84f3d3d7e5d9 53 Q_ASSERT_COMPILE(MAX_SIG < DEV_DRIVER_SIG);
QL 0:84f3d3d7e5d9 54
QL 0:84f3d3d7e5d9 55 #define LWIP_SLOW_TICK_MS TCP_TMR_INTERVAL
QL 0:84f3d3d7e5d9 56
QL 0:84f3d3d7e5d9 57 // Active object class -------------------------------------------------------
QL 0:84f3d3d7e5d9 58 class LwIPMgr : public QActive {
QL 0:84f3d3d7e5d9 59
QL 0:84f3d3d7e5d9 60 QTimeEvt m_te_LWIP_SLOW_TICK;
QL 0:84f3d3d7e5d9 61 struct netif *m_netif;
QL 0:84f3d3d7e5d9 62 struct udp_pcb *m_upcb;
QL 0:84f3d3d7e5d9 63 uint32_t m_ip_addr; // IP address in the native host byte order
QL 0:84f3d3d7e5d9 64
QL 0:84f3d3d7e5d9 65 #if LWIP_TCP
QL 0:84f3d3d7e5d9 66 uint32_t m_tcp_tmr;
QL 0:84f3d3d7e5d9 67 #endif
QL 0:84f3d3d7e5d9 68 #if LWIP_ARP
QL 0:84f3d3d7e5d9 69 uint32_t m_arp_tmr;
QL 0:84f3d3d7e5d9 70 #endif
QL 0:84f3d3d7e5d9 71 #if LWIP_DHCP
QL 0:84f3d3d7e5d9 72 uint32_t m_dhcp_fine_tmr;
QL 0:84f3d3d7e5d9 73 uint32_t m_dhcp_coarse_tmr;
QL 0:84f3d3d7e5d9 74 #endif
QL 0:84f3d3d7e5d9 75 #if LWIP_AUTOIP
QL 0:84f3d3d7e5d9 76 uint32_t m_auto_ip_tmr;
QL 0:84f3d3d7e5d9 77 #endif
QL 0:84f3d3d7e5d9 78
QL 0:84f3d3d7e5d9 79 public:
QL 0:84f3d3d7e5d9 80 LwIPMgr(); // ctor
QL 0:84f3d3d7e5d9 81
QL 0:84f3d3d7e5d9 82 private:
QL 0:84f3d3d7e5d9 83 static QState initial(LwIPMgr *me, QEvent const *e);
QL 0:84f3d3d7e5d9 84 static QState running(LwIPMgr *me, QEvent const *e);
QL 0:84f3d3d7e5d9 85 };
QL 0:84f3d3d7e5d9 86
QL 0:84f3d3d7e5d9 87
QL 0:84f3d3d7e5d9 88 // Local objects -------------------------------------------------------------
QL 0:84f3d3d7e5d9 89 static LwIPMgr l_lwIPMgr; // the single instance of LwIPMgr AO
QL 0:84f3d3d7e5d9 90
QL 0:84f3d3d7e5d9 91 // Global-scope objects ------------------------------------------------------
QL 0:84f3d3d7e5d9 92 QActive * const AO_LwIPMgr = (QActive *)&l_lwIPMgr; // "opaque" pointer
QL 0:84f3d3d7e5d9 93
QL 0:84f3d3d7e5d9 94 // Server-Side Include (SSI) demo ............................................
QL 0:84f3d3d7e5d9 95 static char const * const ssi_tags[] = {
QL 0:84f3d3d7e5d9 96 "s_xmit",
QL 0:84f3d3d7e5d9 97 "s_recv",
QL 0:84f3d3d7e5d9 98 "s_fw",
QL 0:84f3d3d7e5d9 99 "s_drop",
QL 0:84f3d3d7e5d9 100 "s_chkerr",
QL 0:84f3d3d7e5d9 101 "s_lenerr",
QL 0:84f3d3d7e5d9 102 "s_memerr",
QL 0:84f3d3d7e5d9 103 "s_rterr",
QL 0:84f3d3d7e5d9 104 "s_proerr",
QL 0:84f3d3d7e5d9 105 "s_opterr",
QL 0:84f3d3d7e5d9 106 "s_err",
QL 0:84f3d3d7e5d9 107 };
QL 0:84f3d3d7e5d9 108 static int ssi_handler(int iIndex, char *pcInsert, int iInsertLen);
QL 0:84f3d3d7e5d9 109
QL 0:84f3d3d7e5d9 110 // Common Gateway Iinterface (CG) demo .......................................
QL 0:84f3d3d7e5d9 111 static char const *cgi_display(int index, int numParams,
QL 0:84f3d3d7e5d9 112 char const *param[],
QL 0:84f3d3d7e5d9 113 char const *value[]);
QL 0:84f3d3d7e5d9 114 static tCGI const cgi_handlers[] = {
QL 0:84f3d3d7e5d9 115 { "/display.cgi", &cgi_display },
QL 0:84f3d3d7e5d9 116 };
QL 0:84f3d3d7e5d9 117
QL 0:84f3d3d7e5d9 118 // UDP handler ...............................................................
QL 0:84f3d3d7e5d9 119 static void udp_rx_handler(void *arg, struct udp_pcb *upcb,
QL 0:84f3d3d7e5d9 120 struct pbuf *p, struct ip_addr *addr, u16_t port);
QL 0:84f3d3d7e5d9 121 //............................................................................
QL 0:84f3d3d7e5d9 122 LwIPMgr::LwIPMgr()
QL 0:84f3d3d7e5d9 123 : QActive((QStateHandler)&LwIPMgr::initial),
QL 0:84f3d3d7e5d9 124 m_te_LWIP_SLOW_TICK(LWIP_SLOW_TICK_SIG)
QL 0:84f3d3d7e5d9 125 {}
QL 0:84f3d3d7e5d9 126 //............................................................................
QL 0:84f3d3d7e5d9 127 QState LwIPMgr::initial(LwIPMgr *me, QEvent const * /*e*/) {
QL 0:84f3d3d7e5d9 128 // initialize the Ethernet Driver
QL 0:84f3d3d7e5d9 129 me->m_netif = eth_driver_init((QActive *)me, 0);
QL 0:84f3d3d7e5d9 130
QL 0:84f3d3d7e5d9 131 me->m_ip_addr = 0xFFFFFFFF; // initialize to impossible value
QL 0:84f3d3d7e5d9 132
QL 0:84f3d3d7e5d9 133 // initialize the lwIP applications...
QL 0:84f3d3d7e5d9 134 httpd_init(); // initialize the simple HTTP-Deamon (web server)
QL 0:84f3d3d7e5d9 135 http_set_ssi_handler(&ssi_handler, ssi_tags, Q_DIM(ssi_tags));
QL 0:84f3d3d7e5d9 136 http_set_cgi_handlers(cgi_handlers, Q_DIM(cgi_handlers));
QL 0:84f3d3d7e5d9 137
QL 0:84f3d3d7e5d9 138 me->m_upcb = udp_new();
QL 0:84f3d3d7e5d9 139 udp_bind(me->m_upcb, IP_ADDR_ANY, 777); // use port 777 for UDP
QL 0:84f3d3d7e5d9 140 udp_recv(me->m_upcb, &udp_rx_handler, me);
QL 0:84f3d3d7e5d9 141
QL 0:84f3d3d7e5d9 142 QS_OBJ_DICTIONARY(&l_lwIPMgr);
QL 0:84f3d3d7e5d9 143 QS_OBJ_DICTIONARY(&l_lwIPMgr.m_te_LWIP_SLOW_TICK);
QL 0:84f3d3d7e5d9 144 QS_FUN_DICTIONARY(&QHsm::top);
QL 0:84f3d3d7e5d9 145 QS_FUN_DICTIONARY(&LwIPMgr::initial);
QL 0:84f3d3d7e5d9 146 QS_FUN_DICTIONARY(&LwIPMgr::running);
QL 0:84f3d3d7e5d9 147
QL 0:84f3d3d7e5d9 148 QS_SIG_DICTIONARY(SEND_UDP_SIG, me);
QL 0:84f3d3d7e5d9 149 QS_SIG_DICTIONARY(LWIP_SLOW_TICK_SIG, me);
QL 0:84f3d3d7e5d9 150 QS_SIG_DICTIONARY(LWIP_RX_READY_SIG, me);
QL 0:84f3d3d7e5d9 151 QS_SIG_DICTIONARY(LWIP_TX_READY_SIG, me);
QL 0:84f3d3d7e5d9 152 QS_SIG_DICTIONARY(LWIP_RX_OVERRUN_SIG, me);
QL 0:84f3d3d7e5d9 153
QL 0:84f3d3d7e5d9 154 return Q_TRAN(&LwIPMgr::running);
QL 0:84f3d3d7e5d9 155 }
QL 0:84f3d3d7e5d9 156 //............................................................................
QL 0:84f3d3d7e5d9 157 QState LwIPMgr::running(LwIPMgr *me, QEvent const *e) {
QL 0:84f3d3d7e5d9 158 switch (e->sig) {
QL 0:84f3d3d7e5d9 159 case Q_ENTRY_SIG: {
QL 0:84f3d3d7e5d9 160 me->m_te_LWIP_SLOW_TICK.postEvery((QActive *)me,
QL 0:84f3d3d7e5d9 161 (LWIP_SLOW_TICK_MS * BSP_TICKS_PER_SEC) / 1000);
QL 0:84f3d3d7e5d9 162 return Q_HANDLED();
QL 0:84f3d3d7e5d9 163 }
QL 0:84f3d3d7e5d9 164 case Q_EXIT_SIG: {
QL 0:84f3d3d7e5d9 165 me->m_te_LWIP_SLOW_TICK.disarm();
QL 0:84f3d3d7e5d9 166 return Q_HANDLED();
QL 0:84f3d3d7e5d9 167 }
QL 0:84f3d3d7e5d9 168
QL 0:84f3d3d7e5d9 169 case SEND_UDP_SIG: {
QL 0:84f3d3d7e5d9 170 if (me->m_upcb->remote_port != (uint16_t)0) {
QL 0:84f3d3d7e5d9 171 struct pbuf *p = pbuf_new((u8_t *)((TextEvt const *)e)->text,
QL 0:84f3d3d7e5d9 172 strlen(((TextEvt const *)e)->text) + 1);
QL 0:84f3d3d7e5d9 173 if (p != (struct pbuf *)0) {
QL 0:84f3d3d7e5d9 174 udp_send(me->m_upcb, p);
QL 0:84f3d3d7e5d9 175 pbuf_free(p); // don't leak the pbuf!
QL 0:84f3d3d7e5d9 176
QL 0:84f3d3d7e5d9 177 QS_BEGIN(LWIP_SEND_UDP, me) // app-specific record begin
QL 0:84f3d3d7e5d9 178 QS_STR(((TextEvt const *)e)->text);
QL 0:84f3d3d7e5d9 179 QS_END()
QL 0:84f3d3d7e5d9 180 }
QL 0:84f3d3d7e5d9 181 }
QL 0:84f3d3d7e5d9 182 return Q_HANDLED();
QL 0:84f3d3d7e5d9 183 }
QL 0:84f3d3d7e5d9 184
QL 0:84f3d3d7e5d9 185 case LWIP_RX_READY_SIG: {
QL 0:84f3d3d7e5d9 186 eth_driver_read();
QL 0:84f3d3d7e5d9 187 return Q_HANDLED();
QL 0:84f3d3d7e5d9 188 }
QL 0:84f3d3d7e5d9 189 case LWIP_TX_READY_SIG: {
QL 0:84f3d3d7e5d9 190 eth_driver_write();
QL 0:84f3d3d7e5d9 191 return Q_HANDLED();
QL 0:84f3d3d7e5d9 192 }
QL 0:84f3d3d7e5d9 193 case LWIP_SLOW_TICK_SIG: {
QL 0:84f3d3d7e5d9 194 QS_BEGIN(LWIP_SLOW_TICK, me) // app-specific record begin
QL 0:84f3d3d7e5d9 195 QS_END()
QL 0:84f3d3d7e5d9 196
QL 0:84f3d3d7e5d9 197 if (me->m_ip_addr != me->m_netif->ip_addr.addr) {
QL 0:84f3d3d7e5d9 198 me->m_ip_addr = me->m_netif->ip_addr.addr; // save the IP addr
QL 0:84f3d3d7e5d9 199 uint32_t ip_net = ntohl(me->m_ip_addr);// IP in network order
QL 0:84f3d3d7e5d9 200 // publish the text event to display the new IP address
QL 0:84f3d3d7e5d9 201 QS_BEGIN(LWIP_IPADDR, me) // app-specific record begin
QL 0:84f3d3d7e5d9 202 QS_U8(3, (uint8_t)(ip_net >> 24));
QL 0:84f3d3d7e5d9 203 QS_U8(3, (uint8_t)(ip_net >> 16));
QL 0:84f3d3d7e5d9 204 QS_U8(3, (uint8_t)(ip_net >> 8));
QL 0:84f3d3d7e5d9 205 QS_U8(3, (uint8_t)ip_net);
QL 0:84f3d3d7e5d9 206 QS_END()
QL 0:84f3d3d7e5d9 207 }
QL 0:84f3d3d7e5d9 208
QL 0:84f3d3d7e5d9 209 #if LWIP_TCP
QL 0:84f3d3d7e5d9 210 me->m_tcp_tmr += LWIP_SLOW_TICK_MS;
QL 0:84f3d3d7e5d9 211 if (me->m_tcp_tmr >= TCP_TMR_INTERVAL) {
QL 0:84f3d3d7e5d9 212 me->m_tcp_tmr = 0;
QL 0:84f3d3d7e5d9 213 tcp_tmr();
QL 0:84f3d3d7e5d9 214 }
QL 0:84f3d3d7e5d9 215 #endif
QL 0:84f3d3d7e5d9 216 #if LWIP_ARP
QL 0:84f3d3d7e5d9 217 me->m_arp_tmr += LWIP_SLOW_TICK_MS;
QL 0:84f3d3d7e5d9 218 if (me->m_arp_tmr >= ARP_TMR_INTERVAL) {
QL 0:84f3d3d7e5d9 219 me->m_arp_tmr = 0;
QL 0:84f3d3d7e5d9 220 etharp_tmr();
QL 0:84f3d3d7e5d9 221 }
QL 0:84f3d3d7e5d9 222 #endif
QL 0:84f3d3d7e5d9 223 #if LWIP_DHCP
QL 0:84f3d3d7e5d9 224 me->m_dhcp_fine_tmr += LWIP_SLOW_TICK_MS;
QL 0:84f3d3d7e5d9 225 if (me->m_dhcp_fine_tmr >= DHCP_FINE_TIMER_MSECS) {
QL 0:84f3d3d7e5d9 226 me->m_dhcp_fine_tmr = 0;
QL 0:84f3d3d7e5d9 227 dhcp_fine_tmr();
QL 0:84f3d3d7e5d9 228 }
QL 0:84f3d3d7e5d9 229 me->m_dhcp_coarse_tmr += LWIP_SLOW_TICK_MS;
QL 0:84f3d3d7e5d9 230 if (me->m_dhcp_coarse_tmr >= DHCP_COARSE_TIMER_MSECS) {
QL 0:84f3d3d7e5d9 231 me->m_dhcp_coarse_tmr = 0;
QL 0:84f3d3d7e5d9 232 dhcp_coarse_tmr();
QL 0:84f3d3d7e5d9 233 }
QL 0:84f3d3d7e5d9 234 #endif
QL 0:84f3d3d7e5d9 235 #if LWIP_AUTOIP
QL 0:84f3d3d7e5d9 236 me->auto_ip_tmr += LWIP_SLOW_TICK_MS;
QL 0:84f3d3d7e5d9 237 if (me->auto_ip_tmr >= AUTOIP_TMR_INTERVAL) {
QL 0:84f3d3d7e5d9 238 me->auto_ip_tmr = 0;
QL 0:84f3d3d7e5d9 239 autoip_tmr();
QL 0:84f3d3d7e5d9 240 }
QL 0:84f3d3d7e5d9 241 #endif
QL 0:84f3d3d7e5d9 242 return Q_HANDLED();
QL 0:84f3d3d7e5d9 243 }
QL 0:84f3d3d7e5d9 244 case LWIP_RX_OVERRUN_SIG: {
QL 0:84f3d3d7e5d9 245 LINK_STATS_INC(link.err);
QL 0:84f3d3d7e5d9 246 return Q_HANDLED();
QL 0:84f3d3d7e5d9 247 }
QL 0:84f3d3d7e5d9 248 }
QL 0:84f3d3d7e5d9 249 return Q_SUPER(&QHsm::top);
QL 0:84f3d3d7e5d9 250 }
QL 0:84f3d3d7e5d9 251
QL 0:84f3d3d7e5d9 252 // HTTPD customizations ------------------------------------------------------
QL 0:84f3d3d7e5d9 253
QL 0:84f3d3d7e5d9 254 // Server-Side Include (SSI) handler .........................................
QL 0:84f3d3d7e5d9 255 static int ssi_handler(int iIndex, char *pcInsert, int iInsertLen) {
QL 0:84f3d3d7e5d9 256 struct stats_proto *stats = &lwip_stats.link;
QL 0:84f3d3d7e5d9 257 STAT_COUNTER value;
QL 0:84f3d3d7e5d9 258
QL 0:84f3d3d7e5d9 259 switch (iIndex) {
QL 0:84f3d3d7e5d9 260 case 0: // s_xmit
QL 0:84f3d3d7e5d9 261 value = stats->xmit;
QL 0:84f3d3d7e5d9 262 break;
QL 0:84f3d3d7e5d9 263 case 1: // s_recv
QL 0:84f3d3d7e5d9 264 value = stats->recv;
QL 0:84f3d3d7e5d9 265 break;
QL 0:84f3d3d7e5d9 266 case 2: // s_fw
QL 0:84f3d3d7e5d9 267 value = stats->fw;
QL 0:84f3d3d7e5d9 268 break;
QL 0:84f3d3d7e5d9 269 case 3: // s_drop
QL 0:84f3d3d7e5d9 270 value = stats->drop;
QL 0:84f3d3d7e5d9 271 break;
QL 0:84f3d3d7e5d9 272 case 4: // s_chkerr
QL 0:84f3d3d7e5d9 273 value = stats->chkerr;
QL 0:84f3d3d7e5d9 274 break;
QL 0:84f3d3d7e5d9 275 case 5: // s_lenerr
QL 0:84f3d3d7e5d9 276 value = stats->lenerr;
QL 0:84f3d3d7e5d9 277 break;
QL 0:84f3d3d7e5d9 278 case 6: // s_memerr
QL 0:84f3d3d7e5d9 279 value = stats->memerr;
QL 0:84f3d3d7e5d9 280 break;
QL 0:84f3d3d7e5d9 281 case 7: // s_rterr
QL 0:84f3d3d7e5d9 282 value = stats->rterr;
QL 0:84f3d3d7e5d9 283 break;
QL 0:84f3d3d7e5d9 284 case 8: // s_proerr
QL 0:84f3d3d7e5d9 285 value = stats->proterr;
QL 0:84f3d3d7e5d9 286 break;
QL 0:84f3d3d7e5d9 287 case 9: // s_opterr
QL 0:84f3d3d7e5d9 288 value = stats->opterr;
QL 0:84f3d3d7e5d9 289 break;
QL 0:84f3d3d7e5d9 290 case 10: // s_err
QL 0:84f3d3d7e5d9 291 value = stats->err;
QL 0:84f3d3d7e5d9 292 break;
QL 0:84f3d3d7e5d9 293 }
QL 0:84f3d3d7e5d9 294
QL 0:84f3d3d7e5d9 295 return snprintf(pcInsert, MAX_TAG_INSERT_LEN, "%d", value);
QL 0:84f3d3d7e5d9 296 }
QL 0:84f3d3d7e5d9 297
QL 0:84f3d3d7e5d9 298 // Common Gateway Iinterface (CG) handler ....................................
QL 0:84f3d3d7e5d9 299 static char const *cgi_display(int index, int numParams,
QL 0:84f3d3d7e5d9 300 char const *param[],
QL 0:84f3d3d7e5d9 301 char const *value[])
QL 0:84f3d3d7e5d9 302 {
QL 0:84f3d3d7e5d9 303 for (int i = 0; i < numParams; ++i) {
QL 0:84f3d3d7e5d9 304 if (strstr(param[i], "text") != (char *)0) { // param text found?
QL 0:84f3d3d7e5d9 305
QL 0:84f3d3d7e5d9 306
QL 0:84f3d3d7e5d9 307 TextEvt *te = Q_NEW(TextEvt, DISPLAY_CGI_SIG);
QL 0:84f3d3d7e5d9 308 strncpy(te->text, value[i], Q_DIM(te->text));
QL 0:84f3d3d7e5d9 309 QF::publish((QEvent *)te);
QL 0:84f3d3d7e5d9 310 return "/thank_you.htm";
QL 0:84f3d3d7e5d9 311 }
QL 0:84f3d3d7e5d9 312 }
QL 0:84f3d3d7e5d9 313 return (char *)0; // no URI, HTTPD will send 404 error page to the browser
QL 0:84f3d3d7e5d9 314 }
QL 0:84f3d3d7e5d9 315
QL 0:84f3d3d7e5d9 316 // UDP receive handler -------------------------------------------------------
QL 0:84f3d3d7e5d9 317 static void udp_rx_handler(void *arg, struct udp_pcb *upcb,
QL 0:84f3d3d7e5d9 318 struct pbuf *p, struct ip_addr *addr, u16_t port)
QL 0:84f3d3d7e5d9 319 {
QL 0:84f3d3d7e5d9 320 TextEvt *te = Q_NEW(TextEvt, DISPLAY_UDP_SIG);
QL 0:84f3d3d7e5d9 321 strncpy(te->text, (char *)p->payload, Q_DIM(te->text));
QL 0:84f3d3d7e5d9 322 QF::publish(te);
QL 0:84f3d3d7e5d9 323
QL 0:84f3d3d7e5d9 324 udp_connect(upcb, addr, port); // connect to the remote host
QL 0:84f3d3d7e5d9 325 pbuf_free(p); // don't leak the pbuf!
QL 0:84f3d3d7e5d9 326 }