Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

httpserv.c File Reference


Detailed Description

HTTP interface.

 *
 * $Log$
 *
 * 

Definition in file httpserv.c.

#include <cfg/os.h>
#include <cfg/memory.h>
#include <stdlib.h>
#include <string.h>
#include <io.h>
#include <fcntl.h>
#include <time.h>
#include <dev/board.h>
#include <dev/urom.h>
#include <sys/thread.h>
#include <sys/timer.h>
#include <sys/heap.h>
#include <sys/socket.h>
#include <pro/httpd.h>
#include "tlv320dac.h"
#include "httpserv.h"

Include dependency graph for httpserv.c:

Go to the source code of this file.

Defines

#define MY_FSDEV   devUrom
#define HTTPD_THREAD_STACK   2048
#define EMPTY_GAIN   999
 Dummy gain.

Functions

static int CgiInfo (FILE *stream, REQUEST *req)
 Radio Info CGI.
int CgiControl (FILE *stream, REQUEST *req)
void Service (void *arg)
 HTTP service thread.
int HttpServerStart (void)
 HTTP Server Start.

Variables

void * __heap_start
void * __etext
int h_timevalid
static char * html_mt = "text/html"


Define Documentation

#define MY_FSDEV   devUrom
 

Definition at line 46 of file httpserv.c.

#define HTTPD_THREAD_STACK   2048
 

Definition at line 75 of file httpserv.c.

#define EMPTY_GAIN   999
 

Dummy gain.

Used to determine volume field that had been left empty. We can't use zero.

Definition at line 85 of file httpserv.c.

Referenced by CgiControl().


Function Documentation

static int CgiInfo FILE *  stream,
REQUEST *  req
[static]
 

Radio Info CGI.

Dynamically creates a page that displays our current status. It will be automatically refreshed every 10 seconds. Thus, let's keep it simple

Definition at line 101 of file httpserv.c.

00103 {
00104     /* These useful API calls create a HTTP response for us. */
00105     NutHttpSendHeaderTop(stream, req, 200, "Ok");
00106     NutHttpSendHeaderBot(stream, html_mt, -1);
00107 
00108     /* Send HTML header. */
00109     fputs("<HTML><HEAD><TITLE>Internet Radio Information</TITLE>" /* */
00110           "<meta http-equiv=\"refresh\" content=\"10; URL=info.cgi\">" /* */
00111           "</HEAD><BODY>\r\n" /* */
00112           "<h1>Internet Radio Status</h1>" /* */
00113           , stream);
00114 
00115     /* If we received date and time from a time server, display it. */
00116     if (h_timevalid) {
00117         time_t now = time(0);
00118         struct _tm *lot = localtime(&now);
00119         fprintf(stream, "Date = %02u.%02u.%u<br>\r\n", lot->tm_mday, lot->tm_mon + 1, 1900 + lot->tm_year);
00120         fprintf(stream, "Time = %02u:%02u:%02u<br>\r\n", lot->tm_hour, lot->tm_min, lot->tm_sec);
00121     }
00122     /* Display our clock settings. */
00123     fprintf(stream, "<br>CPU Clock = %lu kHz<br>\r\n", NutGetCpuClock() / 1000);
00124     fprintf(stream, "Master Clock = %lu kHz<br>\r\n", At91GetMasterClock() / 1000);
00125     /* Display our memory usage. */
00126     fprintf(stream, "<br>Code size incl. Web Content = %u kBytes<br>\r\n", ((u_int)(&__etext) - NUTMEM_START) / 1024);
00127     fprintf(stream, "Static data size = %u kBytes<br>\r\n", (u_int)(&__heap_start - &__etext) / 1024);
00128     fprintf(stream, "Total memory used = %u kBytes<br>\r\n", (u_int)(NUTMEM_SIZE - NutHeapAvailable()) / 1024);
00129     fflush(stream);
00130 
00131     if (radio.rc_sip == NULL) {
00132         fputs("<br><br><b>No station connected<br>\r\n", stream);
00133     }
00134     else {
00135         fprintf(stream, "<h2>Radio Station</h2>\r\n");
00136         fprintf(stream, "Name = %s<br>\r\n", radio.rc_sip->si_name);
00137         fprintf(stream, "Genre = %s<br>\r\n", radio.rc_sip->si_genre);
00138         fprintf(stream, "Bitrate = %u kBit<br>\r\n", radio.rc_sip->si_bitrate);
00139         fflush(stream);
00140         if (radio.rc_rip) {
00141             SHOUTCASTINFO *sci = (SHOUTCASTINFO *) radio.rc_rip->ri_bcast;
00142             fprintf(stream, "<h2>SHOUTcast Stream</h2>\r\n");
00143             fprintf(stream, "Buffer contents = %u Bytes<br>\r\n", radio.rc_rip->ri_avail);
00144             if (sci) {
00145                 fprintf(stream, "Title = %s<br>\r\n", sci->sci_metatitle);
00146                 fprintf(stream, "URL = %s<br>\r\n", sci->sci_metaurl);
00147             }
00148             fprintf(stream, "Metadata interval = %lu Bytes<br>\r\n", sci->sci_metaint);
00149             fflush(stream);
00150             if (radio.rc_pip) {
00151                 MP3PLAYERINFO *mpi = (MP3PLAYERINFO *) radio.rc_pip->pi_bcast;
00152                 if (mpi) {
00153                     fprintf(stream, "<h2>MP3 Decoder</h2>\r\n");
00154                     fprintf(stream, "Layer = %d<br>\r\n", mpi->mpi_frameinfo.layer);
00155                     fprintf(stream, "Version = %d<br>\r\n", mpi->mpi_frameinfo.version);
00156                     fprintf(stream, "Bitrate = %d<br>\r\n", mpi->mpi_frameinfo.bitrate);
00157                     fprintf(stream, "Channels = %d<br>\r\n", mpi->mpi_frameinfo.nChans);
00158                     fprintf(stream, "Sample rate = %d<br>\r\n", mpi->mpi_frameinfo.samprate);
00159                     fprintf(stream, "Bits per sample = %d<br>\r\n", mpi->mpi_frameinfo.bitsPerSample);
00160                     fflush(stream);
00161                 }
00162             }
00163         }
00164     }
00165 
00166     fputs("<BR><BR><a href=\"/index.html\">BACK</a>", stream);
00167 
00168     /* Send HTML footer and flush output buffer. */
00169     fputs("</BODY></HTML>", stream);
00170     fflush(stream);
00171 
00172     return 0;

int CgiControl FILE *  stream,
REQUEST *  req
 

Definition at line 177 of file httpserv.c.

References EMPTY_GAIN, html_mt, PlayerStop(), radio, RADIOCONTROL::rc_pip, RADIOCONTROL::rc_rip, ReceiverStop(), and Tlv320DacSetVolume().

00179 {
00180     int lvol = EMPTY_GAIN;
00181     int rvol = EMPTY_GAIN;
00182     int stop = 0;
00183 
00184     NutHttpSendHeaderTop(stream, req, 200, "Ok");
00185     NutHttpSendHeaderBot(stream, html_mt, -1);
00186 
00187     /* Send HTML header. */
00188     fputs("<HTML><BODY><BR><H1>Control Result</H1><BR><BR>", stream);
00189     fflush(stream);
00190 
00191     if (req->req_query) {
00192         char *name;
00193         char *value;
00194         int i;
00195         int count;
00196 
00197         count = NutHttpGetParameterCount(req);
00198         /* Extract count parameters. */
00199         for (i = 0; i < count; i++) {
00200             name = NutHttpGetParameterName(req, i);
00201             value = NutHttpGetParameterValue(req, i);
00202 
00203             /* Send the parameters back to the client. */
00204             //fprintf(stream, "%s = '%s'<BR>\r\n", name, value);
00205             if (strcmp(name, "lvol") == 0 && value[0]) {
00206                 lvol = atoi(value);
00207             }
00208             else if (strcmp(name, "rvol") == 0 && value[0]) {
00209                 rvol = atoi(value);
00210             }
00211             else if (strcmp(name, "stream") == 0 && value[0]) {
00212                 stop = 1;
00213             }
00214         }
00215 
00216         /* Handle volume changes. User needs to fill one channel only 
00217            in order to set both. */
00218         if (rvol == EMPTY_GAIN) {
00219             rvol = lvol;
00220         }
00221         else if (lvol == EMPTY_GAIN) {
00222             lvol = rvol;
00223         }
00224         if (lvol != EMPTY_GAIN) {
00225             Tlv320DacSetVolume(lvol, rvol);
00226             fprintf(stream, "Volume set to %d/%d dB<BR>.\r\n", lvol, rvol);
00227         }
00228 
00229         /* Handle station re-connect. */
00230         if (stop) {
00231             if (radio.rc_rip) {
00232                 ReceiverStop(radio.rc_rip);
00233                 fprintf(stream, "Stream stopped.<BR>\r\n");
00234             }
00235             if (radio.rc_pip) {
00236                 PlayerStop(radio.rc_pip);
00237                 fprintf(stream, "Player stopped.<BR>\r\n");
00238             }
00239         }
00240     }
00241 
00242     fputs("<BR><BR><p><a href=\"/index.html\">BACK</a></BODY></HTML></p>", stream);
00243     fflush(stream);
00244 
00245     return 0;

Here is the call graph for this function:

Service void *  arg  ) 
 

HTTP service thread.

The endless loop in this thread waits for a client connect, processes the HTTP request and disconnects. Nut/Net doesn't support a server backlog. If one client has established a connection, further connect attempts will be rejected. Typically browsers open more than one connection in order to load images concurrently. So we run this routine by several threads.

Definition at line 259 of file httpserv.c.

00261 {
00262     TCPSOCKET *sock;
00263     FILE *stream;
00264     u_char id = (u_char) ((uptr_t) arg);
00265 
00266     /*
00267      * Now loop endless for connections.
00268      */
00269     for (;;) {
00270 
00271         /*
00272          * Create a socket.
00273          */
00274         if ((sock = NutTcpCreateSocket()) == 0) {
00275             printf("[%u] Creating socket failed\n", id);
00276             NutSleep(5000);
00277             continue;
00278         }
00279 
00280         /*
00281          * Listen on port 80. This call will block until we get a connection
00282          * from a client.
00283          */
00284         NutTcpAccept(sock, 80);
00285 
00286         /*
00287          * Wait until at least 8 kByte of free RAM is available. This will
00288          * keep the client connected in low memory situations.
00289          */
00290         while (NutHeapAvailable() < 8192) {
00291             printf("[%u] Low mem\n", id);
00292             NutSleep(1000);
00293         }
00294 
00295         /*
00296          * Associate a stream with the socket so we can use standard I/O calls.
00297          */
00298         if ((stream = _fdopen((int) ((uptr_t) sock), "r+b")) == 0) {
00299             printf("[%u] Creating stream device failed\n", id);
00300         } else {
00301             /*
00302              * This API call saves us a lot of work. It will parse the
00303              * client's HTTP request, send any requested file from the
00304              * registered file system or handle CGI requests by calling
00305              * our registered CGI routine.
00306              */
00307             NutHttpProcessRequest(stream);
00308 
00309             /*
00310              * Destroy the virtual stream device.
00311              */
00312             fclose(stream);
00313         }
00314 
00315         /*
00316          * Close our socket.
00317          */
00318         NutTcpCloseSocket(sock);
00319     }

int HttpServerStart void   ) 
 

HTTP Server Start.

Definition at line 324 of file httpserv.c.

00326 {
00327     int i;
00328 
00329     /*
00330      * Register our device for the file system.
00331      */
00332     NutRegisterDevice(&MY_FSDEV, 0, 0);
00333 
00334 #ifdef MY_HTTPROOT
00335     /* Register root path. */
00336     printf("Registering HTTP root '" MY_HTTPROOT "'...");
00337     if (NutRegisterHttpRoot(MY_HTTPROOT)) {
00338         puts("failed");
00339         for (;;);
00340     }
00341     puts("OK");
00342 #endif
00343 
00344     /*
00345      * Register our CGIs.
00346      */
00347     NutRegisterCgi("info.cgi", CgiInfo);
00348     NutRegisterCgi("control.cgi", CgiControl);
00349 
00350     /*
00351      * Protect the admin directory with user and password.
00352      */
00353     NutRegisterAuth("admin", "admin:lemta");
00354 
00355     /*
00356      * Start four server threads.
00357      */
00358     for (i = 1; i <= 4; i++) {
00359         char *thname = "httpd0";
00360 
00361         thname[5] = '0' + i;
00362         NutThreadCreate(thname, Service, (void *) (uptr_t) i, HTTPD_THREAD_STACK);
00363     }
00364     return 0;


Variable Documentation

void* __heap_start
 

void* __etext
 

int h_timevalid
 

Definition at line 90 of file httpserv.c.

char* html_mt = "text/html" [static]
 

Definition at line 92 of file httpserv.c.

Referenced by CgiControl().


Generated on Fri Feb 23 17:28:52 2007 for SAM Internet Radio by  doxygen 1.4.4