* * $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" |
|
Definition at line 46 of file httpserv.c. |
|
Definition at line 75 of file httpserv.c. |
|
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(). |
|
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;
|
|
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: |
|
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 }
|
|
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;
|
|
|
|
|
|
Definition at line 90 of file httpserv.c. |
|
Definition at line 92 of file httpserv.c. Referenced by CgiControl(). |