Link here

Ether/WiFi C Demo

The EtherSmart Wildcard is based on the Lantronix Xport Ethernet device server, and the WiFi Wildcard is based on the Lantronix WiPort wireless device server. This software example coded in C implements an embedded email server, a webserver that delivers static and dynamic web pages to your PC-based browser, and a serial tunneling function that performs serial data exchanges with peripheral devices. These tiny 2" by 2.5" boards are members of the Wildcard™ series that connects to Mosaic's embedded computers to implement web-enabled instrumentation and automation functions.


Ether/WiFi C Demo

// this demonstration code is provided in source form to provide examples of how to use
// the Ethernet/Wifi driver functions.
// Top level functions:
//    Ether_Web_Demo( )    // no input parameters; runs web pages, enables email, tunneling;
//    WiFi_Web_Demo( )    // no input parameters; runs web pages, enables email, tunneling;
//    Ether_Monitor_Demo( int modulenum ) // runs ethernet interactive monitor;see comments
// at the bottom of this file:
//        you can edit main to call the version of the web demo for your Wildcard
 
 
// these can be called interactively (from QEDTerminal)
// after Ether_Web_Demo or WiFi_Web_Demo is invoked:
//    Tunnel_Test( )            // no input parameters, echoes data from Putty connection
//    Email_Test( )            // no input parameters, returns error code.  Sends an email;
                        // Note: YOU MUST EDIT THIS FUNCTION's HARD-CODED IP ADDRESS and
                        // the hostname_str, sender_str, and recipient_str BEFORE CALLING!
 
// Make sure to edit the E_MODULENUM constant to match your hardware jumper settings.
 
// ************** #includes **************
 
 
#include <mosaic\allqed.h> // include all of the qed and C utilities
#ifdef __GNUC__
// For PDQ line platforms, the driver is enabled
// by simply including the header file below.
#include <wwifi.h>
#include "web_resources/image_headers.h"  // Image headers in project subfolder
 
#else    // for QCard/QScreen controllers
// For the QCard architecture, we include the kernel extension manager
// generated library.c.  We assume that it is present in this directory.
#include "library.h"
#include "library.c"
 
#include "Resources\V4_4\image_headers.h"       // for QCard/QScreen controllers
// #include "Resources\V4_09\image_headers.h"   // for QED/QVGA controllers
 
#endif    // __GNUC__
 
 
// for reference, image_headers.h defines the following image and html string parameters:
// FORM_PAGE_HTML_XADDR
// FORM_PAGE_HTML_SIZE
// HOME_BODY_HTML_XADDR
// HOME_BODY_HTML_SIZE
// MOSAIC_LOGO_PNG_XADDR
// MOSAIC_LOGO_PNG_SIZE
// OPERA_CONFIG_HTML_XADDR
// OPERA_CONFIG_HTML_SIZE
 
 
// ************** USEFUL MACRO FOR STRINGS IN V4.xx C COMPILER **************
 
// the TO_XADDR defined in /mosaic/include/types.h
// transforms a separate 16-bit addr, page into a 32-bit xaddress:
// #define TO_XADDR(address,page)     ((xaddr) (((page)<<16)+ (0xFFFF & (address))))
 
// We want to substitute THIS_PAGE (also defined in types.h) for the page,
// as the V4.xx C compiler replicates the strings on each page;
// therefore, in most cases, the calling function's page is the same as the string page:
 
#ifndef STRING_XADDR
    #define STRING_XADDR(str_addr) ((xaddr) TO_XADDR(((xaddr) str_addr), ((xaddr) THIS_PAGE)))
#endif
 
// ************** USEFUL CONSTANTS **************
 
// #define TASK_SIZE 0x400     // 0x400 = decimal 1024 = 1Kbyte = task size
 
#define CR_ASCII    0x0D     // ascii carriage return
#define CRLF_ASCII 0x0D0A     // this is the standard eol sequence for tcp/ip services.
 
#define SMTP_PORT 25         // email Simple Mail Transfer Protocol destination port
 
// *************** IMPORTANT: SET MODULENUM TO MATCH HARDWARE JUMPERS ******************
 
// NOTE: YOU MUST MAKE SURE THAT THIS CONSTANT CORRESPONDS TO YOUR MODULE SELECT JUMPERS!
// For example, to access the Wildcard at address 4:
//    remove both module select jumper caps and mount the card on Wildcard Module Bus 1
#define E_MODULENUM    4
// Note: if you are using a QScreen or Handheld, accessing a wildcard at module address 0
// is not allowed; this module address is reserved for the GUI on the QScreen and Handheld.
 
 
 
// If EtherSmart is installed on module bus 0, E_MODULENUM = 0, 1, 2, or 3
// If EtherSmart is installed on module bus 1, E_MODULENUM = 4, 5, 6, or 7
// That is, the bus specifies the top bit of a 3-bit modulenum,
// and [J2, J1] specifies the remaining 2 bits of the modulenum.
// Example: On module bus 0, if neither jumper cap is installed: E_MODULENUM = 0
// Example: On module bus 0, if both jumper caps are installed: E_MODULENUM = 3
// Example: On module bus 1, if J2 is installed but J1 is not: E_MODULENUM = 6
 
 
 
// ************** SETUP ETHERNET TASK TO RUN WEB AND TUNNELING SERVICES **************
 
TASK ether_control_task;  // allocate task area
 
_Q void Ether_Task_Setup_Default( void )
// performs full initialization of the Ether_Info struct and mailboxes for the
// modulenum specified by the E_MODULENUM constant, and
// builds and activates an ethernet control task to service the EtherSmart Wildcard
// Note: GCC for V6.xx platforms requires that we explicitly call BUILD_C_TASK as shown here
// This is why we do not use the driver's ETHER_Task_Setup routine here (see glossary for details).
{
 // NEXT_TASK = TASKBASE;    // empties task loop; comment out if other tasks are allowed
    Ether_Setup_Default(E_MODULENUM); // allocate&init ~3Kbyte ram buffers, see glossary entry
    BUILD_C_TASK(0, 0, &ether_control_task );                    // build the service task
    ACTIVATE(Ether_Service_Loop, &ether_control_task );    // activate the service routine
}
 
_Q void WiFi_Task_Setup_Default( void )
// same as Ether_Task_Setup_Default, but marks Wildcard as WiFi
// performs full initialization of the Ether_Info struct and mailboxes for the
// modulenum specified by the E_MODULENUM constant, and
// builds and activates an ethernet control task to service the WiFi Wildcard
// Note: GCC for V6.xx platforms requires that we explicitly call BUILD_C_TASK as shown here
// This is why we do not use the driver's WiFi_Task_Setup routine here (see glossary for details).
{
 // NEXT_TASK = TASKBASE;    // empties task loop; comment out if other tasks are allowed
    WiFi_Setup_Default(E_MODULENUM); // allocate&init ~3Kbyte ram buffers, see glossary entry
    BUILD_C_TASK(0, 0, &ether_control_task );                    // build the service task
    ACTIVATE(Ether_Service_Loop, &ether_control_task );    // activate the service routine
}
 
// ***************** INTERACTIVE CONFIGURATION AND REPORTING ************
 
_Q int Ether_Set_Defaults( void )
// works for xport or wiport (ethernet/wifi)
// call this AFTER calling main() or Ether_Web_Demo or Ether_Task_Setup_Default()
// or WiFi_Web_Demo or WiFi_Task_Setup_Default.
// sets mosaic factory defaults; returns error code
// sets local IP and gateway to 0.0.0.0 = unassigned, so IP address
// gets assigned via DHCP (Dynamic Host Configuration Protocol) by the LAN's gateway.
// see user guide for more information.
{    printf("\rSetting defaults...\r");
    Ether_XPort_Defaults(E_MODULENUM); // works for xport or wiport (ethernet/wifi)
    return((int) Ether_Await_Response(E_MODULENUM)); // error code is in lsword
}
 
_Q int Ether_Set_Local_IP(int my_ip1, int my_ip2, int my_ip3,  int my_ip4)
// call this AFTER calling main() or Ether_Web_Demo or Ether_Task_Setup_Default()
// or WiFi_Web_Demo or WiFi_Task_Setup_Default.
// sets the IP address of the EtherSmart Wildcard specified by E_MODULENUM as:
//   ip1.ip2.ip3.ip4
// For example, to set the IP address to 10.0.1.22, pass to this function the parameters:
//   10 0 1 22
// returns error code
// NOTES: type DECIMAL at the monitor before invoking this function interactively!
//        The input types are declared as int to simplify interactive calling,
//        as the interactive debugger would require char specifiers before each input
//        parameter if the char type were used.
// NOTE: assigning a nonzero IP address disables DHCP!
{    printf("\rSetting local IP address...\r");
    Ether_Local_IP(my_ip1, my_ip2, my_ip3,  my_ip4, E_MODULENUM);
    Ether_XPort_Update(E_MODULENUM);  // works for xport or wiport (ethernet/wifi)
    return((int) Ether_Await_Response(E_MODULENUM)); // error code is in lsword
}
 
_Q void Ether_IP_Report(void)
// call this AFTER calling main() or Ether_Web_Demo or Ether_Task_Setup_Default()
// or WiFi_Web_Demo or WiFi_Task_Setup_Default.
// takes 7 seconds to execute, so be patient.
// Report is of the form:
// IP 010.000.001.019 GW 010.000.001.022 Mask 255.255.255.000
// which summarizes the IP address, gateway address, and netmask, respectively.
{    Ether_IP_Info_Report(E_MODULENUM);
}
 
_Q void Ether_Ping(int remote_ip1, int remote_ip2, int remote_ip3,  int remote_ip4)
// call this AFTER calling main() or Ether_Web_Demo or Ether_Task_Setup_Default()
// or WiFi_Web_Demo or WiFi_Task_Setup_Default.
// on error, prints " Couldn't enter monitor mode!" or " No response from remote".
// takes thirteen seconds to execute, so be patient.
// Report is of the form (summarizes response time from specified remote host):
// Seq 001 time 10ms
// Seq 002 time 10ms
// Seq 003 time 10ms
// Seq 004 time 10ms
// Seq 005 time 10ms
// Seq 006 time 10ms
// NOTES: type DECIMAL at the monitor before invoking this function interactively!
//        The input types are declared as int to simplify interactive calling,
//        as the interactive debugger would require char specifiers before each input
//        parameter if the char type were used.
{    Ether_Ping_Report(remote_ip1, remote_ip2, remote_ip3, remote_ip4, E_MODULENUM);
}
 
// ***************** REVECTORED SERIAL VIA TCP/IP ************
 
// simplest approach:
// simply store the correct modulenum into the global var named ether_revector_module,
// then call Ether_Serial_Revector
// This will run the default (startup) task through the specified ethersmart wildcard.
// Use Putty "rlogin" to connect to the local port (typically = 80)
// at the specified local IP address, and you're talking to the QED monitor via ethernet.
// To revert to standard serial operation via QED Term, type COLD to revert to standard
// serial, then from QEDTerm type RESTORE to bring back access to all compiled routines,
// then continue communications using QEDTerm.
 
// If you want to maintain serial communications via QEDTerm with the default task
// while running a separate task with I/O revectored via the Ethersmart Wildcard,
// then build and activate a task using Ether_Monitor as the activation routine.
// Use Putty "rlogin" to connect to the local port (typically = 80)
// at the specified local IP address, and you're talking to the task via ethernet.
 
 
TASK ether_montask;  // 1 Kbyte per task area
 
_Q void Ether_Monitor_Demo( int modulenum )
// works for xport or wiport (ethernet/wifi)
// builds and activates a monitor task for the specified module.
// this function expects the modulenum as an input parameter so that
// you can run 2 installed Ethersmart wildcards at once:
// one wildcard can run the standard services (web, email, tunneling)
// while the other one (running Ether_Monitor_Demo) is used to download code
// and control program development and debugging.
// To do this, first call Ether_Web_Demo or WiFi_Web_Demo
// (which runs services on the E_MODULENUM wildcard),
// then call this Ether_Monitor_Demo function with a different modulenum.
{    ether_revector_module = modulenum;    // set variable to specify which module's revectored
    SERIAL_ACCESS = RELEASE_ALWAYS; // allow sharing of serial ports
 // NEXT_TASK = TASKBASE;    // empties task loop; comment out if other tasks are allowed
    BUILD_C_TASK(0, 0, &ether_montask );
    ACTIVATE(Ether_Monitor, &ether_montask );
}
 
 
// ******************* SERIAL TUNNELING TEST **************
 
_Q void Tunnel_Test( void )
// works for xport or wiport (ethernet/wifi)
// call after doing Ether_Task_Setup_Default or WiFi_Task_Setup_Default
// Waits for incoming non-web connection on this module's IP address on port 80
// (the default local port), and examines the linefeed-delimited first line to see
// if it starts with GET; if not, it accepts it as a passive non-web connection.
// So: don't type GET as the first characters of the connection (you'll confuse the system).
// The easiest way to open a connection is via Putty, using the "raw" mode.
// Note: If you use "telnet" mode, you'll see some garbage characters in the first line;
// these are control bytes with the msbit set that are accepted by the connection manager.
{    int num_received=0, inbufcount=0, i=0, numlines=0;
    char c;
    int timeout = 20000;    // 20 second timeout for testing; sets delay til function exit
    xaddr ether_inbuf_base = Ether_Inbuf(E_MODULENUM);
    uint ether_inbuf_size =  Ether_Inbufsize(E_MODULENUM);
    xaddr http_inbuf_base = HTTP_Inbuf(E_MODULENUM);
    char* prompt = "Line was received>";
    int prompt_length = strlen(prompt);
    printf("\rWaiting for connection (type a carriage return from QEDTerm to abort)...\r");
    printf("Suggestion: To connect, use Putty in 'raw' mode, specify IP address, port 80,\r");
    printf("and type a carriage return once the session window opens.\r");
    do
    {    PauseOnKey();        // abort on CR, pause/resume on other keys
        Ether_Check_Response(E_MODULENUM);    // keep mailbox clean, ignore messages
    }
    while( !Ether_Passive_Non_Web_Connection(E_MODULENUM) ); // wait for tunnel connection
    printf("\rAn incoming connection has been accepted;\r");
    printf("each incoming line will be printed to the serial terminal, and a\r");
    printf("response prompt will be sent to the ethernet terminal.\r");
    printf("To exit this routine, wait 20 seconds without typing a line.\r");
        // the first line is in HTTP_Inbuf (because webserver had to check its identity)...
        // count is in 1st 2bytes of buffer
    inbufcount = (FetchInt(http_inbuf_base)); // count is stored in first 2bytes of buffer
    for( i=0; i<inbufcount; i++)
        {    c = FetchChar(http_inbuf_base + 2 + i); // skip 2byte count,get char
            Emit(c);
        }    // type first line including terminating crlf to local serial terminal
    do        // loop and echo additional lines til timeout...
    {    Ether_Get_Line( ether_inbuf_base,ether_inbuf_size,CR_ASCII,1,1,timeout,E_MODULENUM);
                // xlbuf,maxchars,eol,discard.alt.eol?,no.msbitset?,timeout_msec,module
                // get 1 line into counted ether_inbuf (count is stored in first 2 bytes)
        num_received = (int) Ether_Await_Response(E_MODULENUM);    // get lsword of result
 
        inbufcount = (FetchInt(ether_inbuf_base));
        for( i=0; i<inbufcount; i++)
            {    c = FetchChar(ether_inbuf_base + 2 + i); // skip 2byte count,get char
                Emit(c);
            }    // type line including terminating crlf to local serial terminal
        if(num_received)    // send prompt and wait for response if chars were received...
        {    Ether_Send_Buffer( STRING_XADDR(prompt), prompt_length, timeout, E_MODULENUM);
            Ether_Await_Response(E_MODULENUM);    // wait for result, ignore rtn value
            numlines++;                            // bump numlines
        }
    }
    while(num_received);        // until no chars rcvd due to timeout or connection close
    Ether_Disconnect_Flush(E_MODULENUM);    // clean up
    Ether_Await_Response(E_MODULENUM);        // synchronize to result mailbox before exit
    printf("\r\nConnection terminated.\r\n");
}
 
 
// ********************* EMAIL  TEST ***************************
 
// NOTE: Edit these to specify valid host, sender, and recipient:
char* hostname_str = "wildcard.yourdomain.com";     // hostname string
char* sender_str =  "niceguy@yourdomain.com";     // email sender string
char* recipient_str = "notso_niceguy@yourdomain.com";     // email recipient string
 
char* email_body_str =    // email_body string
"Subject: EtherSmart/WiFi Email Test\r\n\
This is a test email from the EtherSmart/WiFi Wildcard.\r\n\
Emails can of course have multiple lines...";
 
 
_Q int Email_Test( void )
// works for xport or wiport (ethernet/wifi)
// call after doing Ether_Task_Setup_Default or WiFi_Task_Setup_Default
// smtp email test routine.
// Note: YOU MUST EDIT THIS FUNCTION's HARD-CODED IP ADDRESS
//    AND the hostname_str, sender_str, and recipient_str BEFORE CALLING!
//    Otherwise, it will not work on your system.
// error= 0 on success, or error_no_response = 0x10, or the smtp 3-digit decimal error code
{    xaddr scratchbuf = Ether_Inbuf( E_MODULENUM );        // scratchpad xbuffer
    Ether_Send_Email(
        STRING_XADDR(email_body_str), strlen(email_body_str), // subject plus 2-line email
        STRING_XADDR(hostname_str), strlen(hostname_str),
        STRING_XADDR(sender_str), strlen(sender_str),
        STRING_XADDR(recipient_str), strlen(recipient_str),
        scratchbuf,         // scratchpad xbuffer
        10, 10, 10, 1,         // IMPORTANT: ENTER YOUR GATEWAY'S IP ADDRESS HERE!
        SMTP_PORT,            // port 25 = standard mailserver destination port
        10000,                // use a 10 second timeout (10,000 msec) for testing
        E_MODULENUM);        // specify module number (must match hardware jumpers)
    return((int) Ether_Await_Response(E_MODULENUM)); // error code is in lsword
}
 
 
// *********************** WEBSERVER DEMO (Ethersmart Web Pages) ***************
 
 
// time announcement string for home page:
char* time_announce_str = "seconds since system initialization.</body></html>";
 
// form_response page strings:
 
char* form_response_str = "<html><head><title>Form Response</title></head><body>\r\n\
<H3>Thanks for your response!</H3><p><p>It must be great to be a ";
 
char* person_str = "person";
 
char* name_announce_str = " with a name like ";
 
char* yours_str = "yours";
 
char* good_to_hear_str = ". It's good to hear that ";
 
char* rainbow_str = "rainbow";
 
char* favorite_str = " is your favorite color!</body></html>";
 
// url strings:
char* slash_url_str = "/"; // synonym for home page url
 
char* index_url_str = "/index.html"; // home page url
 
char* opera_url_str = "/opera_configuration.html"; // opera page url
 
char* form_entry_url_str = "/form_entry.html"; // form entry page url
 
char* form_response_url_str = "/form_response.cgi"; // form response page url
 
char* logo_response_url_str = "/logo_response.png"; // logo response page url
 
 
 
// note: in form_page_str, we mark one of the radio buttons as checked; otherwise,
// the browser can skip the field entirely, then we would have to match the fieldnames!
 
 
char seconds_str[16];    // will hold elapsed seconds string
 
void Home_Page( int modulenum )
// this is the handler function for the /index.html and the / URLs.
// sends the http header with dynamic (because of changing time stamp) text/html
// content type,  followed by home_body_str text and the elapsed seconds since the
// system was initialized.
{    ulong elapsed_sec;
    xaddr http_outbuf_base = HTTP_Outbuf(modulenum);
    uint http_outbuf_size =  HTTP_Outbufsize(modulenum);
    HTTP_Put_Header(http_outbuf_base, http_outbuf_size);    // http header->outbuf
    HTTP_Put_Content_Type(http_outbuf_base, http_outbuf_size, 1, HTTP_TEXT_HTML_CONTENT);
                        // params: xlbuf,maxbufsize,dynamic?,content_type
                        // dynamic text/html content ->outbuf;header is done
    HTTP_Send_LBuffer(http_outbuf_base, modulenum); // send out header, ignore #bytes_sent
    HTTP_Send_Buffer(HOME_BODY_HTML_XADDR, HOME_BODY_HTML_SIZE, modulenum);
                        // send home_body.html, ignore #bytes_sent
    StoreInt(0, http_outbuf_base);        // reset lcount to start fresh in buffer
    elapsed_sec = ReadElapsedSeconds();  // get elapsed time, used by sprintf...
    sprintf(seconds_str,"%ld",elapsed_sec);
    HTTP_Outbuf_Cat((xaddr) seconds_str,strlen(seconds_str),modulenum);
                    // params: xstring_to_add,cnt_to_add,module
                    // convert seconds to string, add line & crlf to longstring, update lcnt
    HTTP_Outbuf_Cat(STRING_XADDR(time_announce_str), strlen(time_announce_str), modulenum);
    // add to lbuffer: " seconds since system initialization.</body></html>"
    HTTP_Send_LBuffer( http_outbuf_base, modulenum); // send elapsed time, ignore #bytes_sent
}
 
 
void Opera_Config_Page( int modulenum )
// this is the handler function for the /opera_configuration.html URL.
// sends the http header with static text/html content type,
// followed by opera_config.html text
{    xaddr http_outbuf_base = HTTP_Outbuf(modulenum);
    uint http_outbuf_size =  HTTP_Outbufsize(modulenum);
    HTTP_Put_Header(http_outbuf_base, http_outbuf_size);    // http header->outbuf
    HTTP_Put_Content_Type(http_outbuf_base, http_outbuf_size,0, HTTP_TEXT_HTML_CONTENT);
                        // params: xlbuf,maxbufsize,dynamic?,content_type
                        // static text/html content ->outbuf;header is done
    HTTP_Send_LBuffer(http_outbuf_base, modulenum); // send out header, ignore #bytes_sent
    HTTP_Send_Buffer(OPERA_CONFIG_HTML_XADDR, OPERA_CONFIG_HTML_SIZE, modulenum);
}                        // send opera_config.html, ignore #bytes_sent
 
 
void Form_Entry_Page( int modulenum )
// responds to url= /form_entry.html
// places FORM_TEXT into the buffer as a longstring after the http header.
// we send directly from compiled string in flash to avoid copy into ether_out buffer;
// this method is ideal for serving static text.
{    xaddr http_outbuf_base = HTTP_Outbuf(modulenum);
    uint http_outbuf_size =  HTTP_Outbufsize(modulenum);
    HTTP_Put_Header(http_outbuf_base, http_outbuf_size);    // http header->outbuf
    HTTP_Put_Content_Type(http_outbuf_base, http_outbuf_size,0, HTTP_TEXT_HTML_CONTENT);
                        // params: xlbuf,maxbufsize,dynamic?,content_type
                        // static text/html content ->outbuf;header is done
    HTTP_Send_LBuffer(http_outbuf_base, modulenum); // send out header, ignore #bytes_sent
    HTTP_Send_Buffer(FORM_PAGE_HTML_XADDR, FORM_PAGE_HTML_SIZE, modulenum);
}                        // send form_page.html, ignore #bytes_sent
 
 
void Form_Response_Page    ( int modulenum )
// this is the handler function that responds to url= /form_response.cgi
// incoming request from browser looks like this:
// GET /form_response.cgi?classification=<man/woman/child>&name_id=<namestring>
// &color=<red/blue/yellow/green>
// We respond:
// It must be great to be a <man/woman/child/person> with a name like <namestring/yours>.
// It's good to hear that <red/blue/yellow/green/rainbow> is your favorite color.
{    xaddr http_outbuf_base = HTTP_Outbuf(modulenum);
    uint http_outbuf_size =  HTTP_Outbufsize(modulenum);
    xaddr http_value_ptr = HTTP_Value_Ptr(modulenum);    // load value,cnt for first field
    uint http_value_count =  HTTP_Value_Count(modulenum);
    xaddr next_http_value_ptr;    // used for look-ahead field to avoid unescape problems
    uint next_http_value_count;    // used for look-ahead field to avoid unescape problems
    HTTP_Put_Header(http_outbuf_base, http_outbuf_size);    // http header->outbuf
    HTTP_Put_Content_Type(http_outbuf_base, http_outbuf_size,0, HTTP_TEXT_HTML_CONTENT);
                        // params: xlbuf,maxbufsize,dynamic?,content_type
                        // static text/html content ->outbuf;header is done
    HTTP_Send_LBuffer(http_outbuf_base, modulenum); // send out header, ignore #bytes_sent
    HTTP_Send_Buffer(STRING_XADDR(form_response_str), strlen(form_response_str), modulenum);
                        // send form_response_str, ignore #bytes_sent
    StoreInt(0, http_outbuf_base);        // reset lcount to start fresh in buffer
    if(http_value_count)    // if first field was entered, add it to response
        HTTP_Outbuf_Cat(http_value_ptr, http_value_count, modulenum);
    else                    // else add "person" to response
        HTTP_Outbuf_Cat(STRING_XADDR(person_str), strlen(person_str), modulenum);
    HTTP_Outbuf_Cat(STRING_XADDR(name_announce_str), strlen(name_announce_str), modulenum);
                            // add " with a name like " to response
    HTTP_To_Next_Field(modulenum); // go to name_id field, ignore #chars_advanced
    http_value_ptr = HTTP_Value_Ptr(modulenum);    // load value,cnt for name_id field
    http_value_count =  HTTP_Value_Count(modulenum);
    HTTP_To_Next_Field(modulenum); // go to color field, ignore #chars_advanced
    next_http_value_ptr = HTTP_Value_Ptr(modulenum);    // load value,cnt for color field
    next_http_value_count =  HTTP_Value_Count(modulenum);
    if(http_value_count)    // if a name was entered, process it and add it to response
    {    HTTP_Plus_To_Space(http_value_ptr, http_value_count); // get rid of +'s in name text
        http_value_count = HTTP_Unescape(http_value_ptr, http_value_count);
        HTTP_Outbuf_Cat(http_value_ptr, http_value_count, modulenum);
    }
    else                    // else add "yours" to response
        HTTP_Outbuf_Cat(STRING_XADDR(yours_str), strlen(yours_str), modulenum);
    HTTP_Outbuf_Cat(STRING_XADDR(good_to_hear_str), strlen(good_to_hear_str), modulenum);
                            // add ". It's good to hear that " to response
    if(next_http_value_count)    // if color field was entered, add it to response
        HTTP_Outbuf_Cat(next_http_value_ptr, next_http_value_count, modulenum);
    else                    // else add "rainbow" to response
        HTTP_Outbuf_Cat(STRING_XADDR(rainbow_str), strlen(rainbow_str), modulenum);
    HTTP_Outbuf_Cat(STRING_XADDR(favorite_str), strlen(favorite_str), modulenum);
                            // add " is your favorite color!</body></html>" to response
    HTTP_Send_LBuffer( http_outbuf_base, modulenum); // send response, ignore #bytes_sent
}
 
 
void Logo_Response_Page    ( int modulenum )
// this is the handler function that responds to url= /logo_response.png
// assumes that logo.s2 has been loaded into memory. serves it as static image.
{    xaddr http_outbuf_base = HTTP_Outbuf(modulenum);
    uint http_outbuf_size =  HTTP_Outbufsize(modulenum);
    int http_header_size;
    HTTP_Put_Header(http_outbuf_base, http_outbuf_size);    // http header->outbuf
    HTTP_Put_Content_Type(http_outbuf_base, http_outbuf_size,0, HTTP_IMAGE_PNG_CONTENT);
                        // params: xlbuf,maxbufsize,dynamic?,content_type
                        // static png image type->outbuf, cnt in first 2bytes; header's done
    http_header_size = FetchInt(http_outbuf_base);    // get size of http header we created
    HTTP_Send_2Buffers(http_outbuf_base+2, http_header_size,
                        MOSAIC_LOGO_PNG_XADDR, MOSAIC_LOGO_PNG_SIZE, modulenum);
                        // params: xbuf1,cnt1,xbuf2,count2,modulenum
}                        // send header&image, ignore numbytes_sent
 
#ifdef      __FABIUS__
// For QED/QCard/QScreen line platforms (running the V4.xx kernel and using Fabius C compiler),
// use this syntax to properly initialize a 4-byte pointer to each handler function:
 
#pragma option init=.doubleword    // declare 32-bit function pointers in code area
#include </mosaic/gui_tk/to_large.h>
 
xaddr (*home_page_ptr)(void)          = Home_Page;
xaddr (*opera_config_page_ptr)(void)  = Opera_Config_Page;
xaddr (*form_entry_page_ptr)(void)    = Form_Entry_Page;
xaddr (*form_response_page_ptr)(void) = Form_Response_Page;
xaddr (*logo_response_page_ptr)(void) = Logo_Response_Page;
 
#include </mosaic/gui_tk/fr_large.h>
#pragma option init=.init       // return the initialized variable area to RAM;
 
void Init_Web_Handler_Pointers( void )
// This is a dummy routine to maintain parallel GCC and Fabius demo code;
// Fabius requires a compile-time initialization of of the pointers to the web handlers
// as performed above.
{
}
 
#endif    // __FABIUS__
 
 
#ifdef __GNUC__
// For PDQ line platforms (running the V6.xx kernel and using GNU C compiler),
// use this syntax to properly initialize a 4-byte pointer to each handler function:
 
xaddr home_page_ptr          ;
xaddr opera_config_page_ptr  ;
xaddr form_entry_page_ptr    ;
xaddr form_response_page_ptr ;
xaddr logo_response_page_ptr ;
 
void Init_Web_Handler_Pointers( void )
// call this at the start of the Web_Handler_Installation() function
// to perform GCC's required runtime initialization of the pointers to the web handlers.
{    home_page_ptr          = (xaddr) Home_Page;
    opera_config_page_ptr  = (xaddr) Opera_Config_Page;
    form_entry_page_ptr    = (xaddr) Form_Entry_Page;
    form_response_page_ptr = (xaddr) Form_Response_Page;
    logo_response_page_ptr = (xaddr) Logo_Response_Page;
}
 
#endif    // __GNUC__
 
 
int Web_Handler_Installation( int modulenum )
// call this after Ether_Task_Setup_Default
// point browser to raw ip or to ip/index.html to see the home web page.
// urls are case sensitive. any other url's serve out: page not found.
// returns nonzero error if too many handlers were added
// (limited by AUTOSERVE_DEFAULT_ROWS passed to ether_init)
{    int error = 0;    // we'll OR error results together and return final result
    Init_Web_Handler_Pointers();    // GNUC/V6.xx platforms require runtime pointer initialization
 
    error |= HTTP_Add_Handler(STRING_XADDR(slash_url_str), strlen(slash_url_str),
                (xaddr) home_page_ptr, modulenum);
    error |= HTTP_Add_Handler(STRING_XADDR(index_url_str), strlen(index_url_str),
                (xaddr) home_page_ptr, modulenum);
    error |= HTTP_Add_Handler(STRING_XADDR(opera_url_str), strlen(opera_url_str),
                (xaddr) opera_config_page_ptr, modulenum);
    error |= HTTP_Add_Handler(STRING_XADDR(form_entry_url_str), strlen(form_entry_url_str),
                (xaddr) form_entry_page_ptr, modulenum);
    error |= HTTP_Add_Handler(STRING_XADDR(form_response_url_str),
                strlen(form_response_url_str), (xaddr) form_response_page_ptr, modulenum);
    error |= HTTP_Add_Handler(STRING_XADDR(logo_response_url_str),
                strlen(logo_response_url_str), (xaddr) logo_response_page_ptr, modulenum);
    InitElapsedTime();        // start at zero so home page reports correct elapsed time
    return(error);
}
 
 
_Q void Ether_Web_Demo( void )
// for EtherSmart Wildcard: point browser to raw ip or to
//  ip/index.html to see the home web page.  urls are case sensitive.
// any other url's serve out: page not found.
// returns nonzero error if too many handlers were added
// (limited by AUTOSERVE_DEFAULT_ROWS passed to ether_init)
{    Ether_Task_Setup_Default();
    Web_Handler_Installation(E_MODULENUM);    // ignore too_many_handlers? flag
}
 
_Q void WiFi_Web_Demo( void )
// for WiFi Wildcard: point browser to raw ip or to
//  ip/index.html to see the home web page.  urls are case sensitive.
// any other url's serve out: page not found.
// returns nonzero error if too many handlers were added
// (limited by AUTOSERVE_DEFAULT_ROWS passed to ether_init)
{    WiFi_Task_Setup_Default();
    Web_Handler_Installation(E_MODULENUM);    // ignore too_many_handlers? flag
}
 
int main( void )
{                        // comment in the correct version for your wildcard:
    Ether_Web_Demo();
//    WiFi_Web_Demo();
  return 0;
}



See also → Ether/Wifi Forth Demo

 
This page is about: C Language Example Code Controls Lantronix XPort Ethernet Device Server for Embedded Email Client, Embedded Dynamic Web Server, Serial Tunneling – This C language software example controls the Lantronix XPort Ethernet device to implement an embedded email server, a webserver that delivers static and dynamic web pages to your PC-based browser, and a serial tunneling function that performs serial data exchanges with peripheral devices.
 
 
Navigation