Quantum Leaps / Mbed 2 deprecated qp_lwip

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lwipmgr.cpp Source File

lwipmgr.cpp

00001 //////////////////////////////////////////////////////////////////////////////
00002 // Product: lwIP-Manager Active Object
00003 // Last Updated for Version: 4.1.06
00004 // Date of the Last Update:  Feb 21, 2011
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2011 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00027 //////////////////////////////////////////////////////////////////////////////
00028 #include "qp_port.h"                                                // QP-port
00029 #include "dpp.h"                      // application events and active objects
00030 #include "bsp.h"                                      // Board Support Package
00031 
00032 #include "lwip/opt.h"                               // lwIP options come first
00033 #include "lwip/stats.h"
00034 #include "lwip/tcp.h"
00035 #include "lwip/tcp_impl.h"
00036 #include "lwip/udp.h"
00037 #include "lwip/tcpip.h"
00038 #include "lwip/mem.h"
00039 #include "lwip/autoip.h"
00040 #include "lwip/dhcp.h"
00041 
00042 #include "netif/etharp.h"
00043 #include "port/eth_driver.h"
00044                                                    // utilities added by QL...
00045 #include "app/httpd.h"                          // application layer protocols
00046 
00047 #include <string.h>
00048 #include <stdio.h>
00049 
00050 Q_DEFINE_THIS_FILE
00051 
00052                // application signals cannot overlap the device-driver signals
00053 Q_ASSERT_COMPILE(MAX_SIG < DEV_DRIVER_SIG);
00054 
00055 #define LWIP_SLOW_TICK_MS       TCP_TMR_INTERVAL
00056 
00057 // Active object class -------------------------------------------------------
00058 class LwIPMgr : public QActive {
00059 
00060     QTimeEvt m_te_LWIP_SLOW_TICK;
00061     struct netif   *m_netif;
00062     struct udp_pcb *m_upcb;
00063     uint32_t        m_ip_addr;     // IP address in the native host byte order
00064 
00065 #if LWIP_TCP
00066     uint32_t m_tcp_tmr;
00067 #endif
00068 #if LWIP_ARP
00069     uint32_t m_arp_tmr;
00070 #endif
00071 #if LWIP_DHCP
00072     uint32_t m_dhcp_fine_tmr;
00073     uint32_t m_dhcp_coarse_tmr;
00074 #endif
00075 #if LWIP_AUTOIP
00076     uint32_t m_auto_ip_tmr;
00077 #endif
00078 
00079 public:
00080     LwIPMgr();                                                         // ctor
00081 
00082 private:
00083     static QState initial(LwIPMgr *me, QEvent const *e);
00084     static QState running(LwIPMgr *me, QEvent const *e);
00085 };
00086 
00087 
00088 // Local objects -------------------------------------------------------------
00089 static LwIPMgr l_lwIPMgr;                 // the single instance of LwIPMgr AO
00090 
00091 // Global-scope objects ------------------------------------------------------
00092 QActive * const AO_LwIPMgr = (QActive *)&l_lwIPMgr;        // "opaque" pointer
00093 
00094 // Server-Side Include (SSI) demo ............................................
00095 static char const * const ssi_tags[] = {
00096     "s_xmit",
00097     "s_recv",
00098     "s_fw",
00099     "s_drop",
00100     "s_chkerr",
00101     "s_lenerr",
00102     "s_memerr",
00103     "s_rterr",
00104     "s_proerr",
00105     "s_opterr",
00106     "s_err",
00107 };
00108 static int ssi_handler(int iIndex, char *pcInsert, int iInsertLen);
00109 
00110 // Common Gateway Iinterface (CG) demo .......................................
00111 static char const *cgi_display(int index, int numParams,
00112                                char const *param[],
00113                                char const *value[]);
00114 static tCGI const cgi_handlers[] = {
00115     { "/display.cgi", &cgi_display },
00116 };
00117 
00118 // UDP handler ...............................................................
00119 static void udp_rx_handler(void *arg, struct udp_pcb *upcb,
00120                            struct pbuf *p, struct ip_addr *addr, u16_t port);
00121 //............................................................................
00122 LwIPMgr::LwIPMgr()
00123     : QActive((QStateHandler)&LwIPMgr::initial),
00124       m_te_LWIP_SLOW_TICK(LWIP_SLOW_TICK_SIG)
00125 {}
00126 //............................................................................
00127 QState LwIPMgr::initial(LwIPMgr *me, QEvent const * /*e*/) {
00128                                              // initialize the Ethernet Driver
00129     me->m_netif = eth_driver_init((QActive *)me, 0);
00130 
00131     me->m_ip_addr = 0xFFFFFFFF;              // initialize to impossible value
00132 
00133                                         // initialize the lwIP applications...
00134     httpd_init();            // initialize the simple HTTP-Deamon (web server)
00135     http_set_ssi_handler(&ssi_handler, ssi_tags, Q_DIM(ssi_tags));
00136     http_set_cgi_handlers(cgi_handlers, Q_DIM(cgi_handlers));
00137 
00138     me->m_upcb = udp_new();
00139     udp_bind(me->m_upcb, IP_ADDR_ANY, 777);            // use port 777 for UDP
00140     udp_recv(me->m_upcb, &udp_rx_handler, me);
00141 
00142     QS_OBJ_DICTIONARY(&l_lwIPMgr);
00143     QS_OBJ_DICTIONARY(&l_lwIPMgr.m_te_LWIP_SLOW_TICK);
00144     QS_FUN_DICTIONARY(&QHsm::top);
00145     QS_FUN_DICTIONARY(&LwIPMgr::initial);
00146     QS_FUN_DICTIONARY(&LwIPMgr::running);
00147 
00148     QS_SIG_DICTIONARY(SEND_UDP_SIG,        me);
00149     QS_SIG_DICTIONARY(LWIP_SLOW_TICK_SIG,  me);
00150     QS_SIG_DICTIONARY(LWIP_RX_READY_SIG,   me);
00151     QS_SIG_DICTIONARY(LWIP_TX_READY_SIG,   me);
00152     QS_SIG_DICTIONARY(LWIP_RX_OVERRUN_SIG, me);
00153 
00154     return Q_TRAN(&LwIPMgr::running);
00155 }
00156 //............................................................................
00157 QState LwIPMgr::running(LwIPMgr *me, QEvent const *e) {
00158     switch (e->sig) {
00159         case Q_ENTRY_SIG: {
00160             me->m_te_LWIP_SLOW_TICK.postEvery((QActive *)me,
00161                 (LWIP_SLOW_TICK_MS * BSP_TICKS_PER_SEC) / 1000);
00162             return Q_HANDLED();
00163         }
00164         case Q_EXIT_SIG: {
00165             me->m_te_LWIP_SLOW_TICK.disarm();
00166             return Q_HANDLED();
00167         }
00168 
00169         case SEND_UDP_SIG: {
00170             if (me->m_upcb->remote_port != (uint16_t)0) {
00171                 struct pbuf *p = pbuf_new((u8_t *)((TextEvt const *)e)->text,
00172                                       strlen(((TextEvt const *)e)->text) + 1);
00173                 if (p != (struct pbuf *)0) {
00174                     udp_send(me->m_upcb, p);
00175                     pbuf_free(p);                      // don't leak the pbuf!
00176 
00177                     QS_BEGIN(LWIP_SEND_UDP, me)   // app-specific record begin
00178                         QS_STR(((TextEvt const *)e)->text);
00179                     QS_END()
00180                 }
00181             }
00182             return Q_HANDLED();
00183         }
00184 
00185         case LWIP_RX_READY_SIG: {
00186             eth_driver_read();
00187             return Q_HANDLED();
00188         }
00189         case LWIP_TX_READY_SIG: {
00190             eth_driver_write();
00191             return Q_HANDLED();
00192         }
00193         case LWIP_SLOW_TICK_SIG: {
00194             QS_BEGIN(LWIP_SLOW_TICK, me)         // app-specific record begin
00195             QS_END()
00196         
00197             if (me->m_ip_addr != me->m_netif->ip_addr.addr) {
00198                 me->m_ip_addr = me->m_netif->ip_addr.addr; // save the IP addr
00199                 uint32_t ip_net  = ntohl(me->m_ip_addr);// IP in network order
00200                        // publish the text event to display the new IP address
00201                 QS_BEGIN(LWIP_IPADDR, me)         // app-specific record begin
00202                     QS_U8(3, (uint8_t)(ip_net >> 24));
00203                     QS_U8(3, (uint8_t)(ip_net >> 16));
00204                     QS_U8(3, (uint8_t)(ip_net >> 8));
00205                     QS_U8(3, (uint8_t)ip_net);
00206                 QS_END()
00207             }
00208 
00209 #if LWIP_TCP
00210             me->m_tcp_tmr += LWIP_SLOW_TICK_MS;
00211             if (me->m_tcp_tmr >= TCP_TMR_INTERVAL) {
00212                 me->m_tcp_tmr = 0;
00213                 tcp_tmr();
00214             }
00215 #endif
00216 #if LWIP_ARP
00217             me->m_arp_tmr += LWIP_SLOW_TICK_MS;
00218             if (me->m_arp_tmr >= ARP_TMR_INTERVAL) {
00219                 me->m_arp_tmr = 0;
00220                 etharp_tmr();
00221             }
00222 #endif
00223 #if LWIP_DHCP
00224             me->m_dhcp_fine_tmr += LWIP_SLOW_TICK_MS;
00225             if (me->m_dhcp_fine_tmr >= DHCP_FINE_TIMER_MSECS) {
00226                 me->m_dhcp_fine_tmr = 0;
00227                 dhcp_fine_tmr();
00228             }
00229             me->m_dhcp_coarse_tmr += LWIP_SLOW_TICK_MS;
00230             if (me->m_dhcp_coarse_tmr >= DHCP_COARSE_TIMER_MSECS) {
00231                 me->m_dhcp_coarse_tmr = 0;
00232                 dhcp_coarse_tmr();
00233             }
00234 #endif
00235 #if LWIP_AUTOIP
00236             me->auto_ip_tmr += LWIP_SLOW_TICK_MS;
00237             if (me->auto_ip_tmr >= AUTOIP_TMR_INTERVAL) {
00238                 me->auto_ip_tmr = 0;
00239                 autoip_tmr();
00240             }
00241 #endif
00242             return Q_HANDLED();
00243         }
00244         case LWIP_RX_OVERRUN_SIG: {
00245             LINK_STATS_INC(link.err);
00246             return Q_HANDLED();
00247         }
00248     }
00249     return Q_SUPER(&QHsm::top);
00250 }
00251 
00252 // HTTPD customizations ------------------------------------------------------
00253 
00254 // Server-Side Include (SSI) handler .........................................
00255 static int ssi_handler(int iIndex, char *pcInsert, int iInsertLen) {
00256     struct stats_proto *stats = &lwip_stats.link;
00257     STAT_COUNTER value;
00258 
00259     switch (iIndex) {
00260         case 0:                                                    // s_xmit
00261             value = stats->xmit;
00262             break;
00263         case 1:                                                    // s_recv
00264             value = stats->recv;
00265             break;
00266         case 2:                                                    // s_fw
00267             value = stats->fw;
00268             break;
00269         case 3:                                                    // s_drop
00270             value = stats->drop;
00271             break;
00272         case 4:                                                    // s_chkerr
00273             value = stats->chkerr;
00274             break;
00275         case 5:                                                    // s_lenerr
00276             value = stats->lenerr;
00277             break;
00278         case 6:                                                    // s_memerr
00279             value = stats->memerr;
00280             break;
00281         case 7:                                                    // s_rterr
00282             value = stats->rterr;
00283             break;
00284         case 8:                                                    // s_proerr
00285             value = stats->proterr;
00286             break;
00287         case 9:                                                    // s_opterr
00288             value = stats->opterr;
00289             break;
00290         case 10:                                                   // s_err
00291             value = stats->err;
00292             break;
00293     }
00294 
00295     return snprintf(pcInsert, MAX_TAG_INSERT_LEN, "%d", value);
00296 }
00297 
00298 // Common Gateway Iinterface (CG) handler ....................................
00299 static char const *cgi_display(int index, int numParams,
00300                                char const *param[],
00301                                char const *value[])
00302 {
00303     for (int i = 0; i < numParams; ++i) {
00304         if (strstr(param[i], "text") != (char *)0) {      // param text found?
00305         
00306         
00307             TextEvt *te = Q_NEW(TextEvt, DISPLAY_CGI_SIG);
00308             strncpy(te->text, value[i], Q_DIM(te->text));
00309             QF::publish((QEvent *)te);
00310             return "/thank_you.htm";
00311         }
00312     }
00313     return (char *)0; // no URI, HTTPD will send 404 error page to the browser
00314 }
00315 
00316 // UDP receive handler -------------------------------------------------------
00317 static void udp_rx_handler(void *arg, struct udp_pcb *upcb,
00318                            struct pbuf *p, struct ip_addr *addr, u16_t port)
00319 {
00320     TextEvt *te = Q_NEW(TextEvt, DISPLAY_UDP_SIG);
00321     strncpy(te->text, (char *)p->payload, Q_DIM(te->text));
00322     QF::publish(te);
00323 
00324     udp_connect(upcb, addr, port);               // connect to the remote host
00325     pbuf_free(p);                                      // don't leak the pbuf!
00326 }