webradio/httpserv.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001-2007 by egnite Software GmbH. All rights reserved.
00003  * Copyright (C) 2008 by egnite GmbH. All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the copyright holders nor the names of
00015  *    contributors may be used to endorse or promote products derived
00016  *    from this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00019  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00021  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00022  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00023  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00024  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00025  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00026  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00027  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00028  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00029  * SUCH DAMAGE.
00030  *
00031  * For additional information see http://www.ethernut.de/
00032  *
00033  */
00034 
00046 #ifndef MY_FSDEV
00047 #define MY_FSDEV        devUrom
00048 #endif
00049 
00050 #ifdef MY_FSDEV_NAME
00051 #define MY_HTTPROOT     MY_FSDEV_NAME ":/"
00052 #endif
00053 
00054 #include <cfg/os.h>
00055 #include <cfg/memory.h>
00056 
00057 #include "config.h"
00058 
00059 #ifdef USE_HTTPSERVER
00060 
00061 #ifndef HTTPD_THREAD_STACK
00062 #define HTTPD_THREAD_STACK  2048
00063 #endif
00064 
00065 #include <stdlib.h>
00066 #include <string.h>
00067 #include <io.h>
00068 #include <fcntl.h>
00069 #include <time.h>
00070 
00071 #include <dev/board.h>
00072 #include <dev/urom.h>
00073 #include <dev/vscodec.h>
00074 #include <dev/watchdog.h>
00075 
00076 #include <arpa/inet.h>
00077 #include <netinet/tcp.h>
00078 #include <netdb.h>
00079 
00080 #include <sys/confos.h>
00081 #include <sys/confnet.h>
00082 #include <sys/thread.h>
00083 #include <sys/timer.h>
00084 #include <sys/heap.h>
00085 #include <sys/bankmem.h>
00086 #include <sys/socket.h>
00087 #include <sys/version.h>
00088 
00089 #include <pro/ssi.h>
00090 #include <pro/httpd.h>
00091 
00092 #include "logmsg.h"
00093 #include "utils.h"
00094 #include "favlist.h"
00095 #include "httpserv.h"
00096 
00102 #define EMPTY_GAIN  999
00103 
00104 extern void *__heap_start;
00105 //extern void *_etext;
00106 
00107 int h_timevalid;
00108 
00109 
00110 /* Service thread counter. */
00111 static int httpd_tc;
00112 
00113 static int StartServiceThread(void);
00114 
00115 
00119 static int CgiStationFavorites(FILE * stream, REQUEST * req)
00120 {
00121     int i;
00122     int row;
00123     int count = 0;
00124     char *value;
00125     char *id = NULL;
00126     int action = 0;
00127     count = NutHttpGetParameterCount(req);
00128     while (count--) {
00129         value = NutHttpGetParameterValue(req, count);
00130         if (strcmp(value, "edit") == 0) {
00131             action = 1;
00132             id = NutHttpGetParameterName(req, count);
00133         } else if (strcmp(value, "add new Favorite") == 0) {
00134             action = 2;
00135         }
00136     }
00137     if (action == 1 && id) {
00138         int idx = atoi(id);
00139 
00140         fputs("<tr class=\"tr1\"><td>Station Name</td>", stream);
00141         fprintf(stream,
00142                 "<td align=\"left\"><INPUT type=\"hidden\" value=\"saveedit\" name=\"%s\"><INPUT type=\"text\" name=\"sname\" value=\"%s\" class=\"inputl\"></td>",
00143                 id, favlist[idx].rs_name);
00144         fputs("</tr><tr class=\"tr2\"><td>Station URL's</td>", stream);
00145         fprintf(stream, "<td align=\"left\"><TEXTAREA class=\"inputl\" name=\"surl\" style=\"height:100;\">");
00146         for (i = 0; i < favlist[idx].rs_streams; i++) {
00147             fprintf(stream, "%s\n", favlist[idx].rs_uri[i]);
00148         }
00149         fprintf(stream, "</TEXTAREA></td>");
00150         fputs
00151             ("</tr><tr class=\"tr1\"><td>Save Settings</td><td align=\"right\"><INPUT type=\"submit\" value=\"Apply\" class=\"submit\"></td></tr>",
00152              stream);
00153     } else if (action == 2) {
00154         fputs("<tr class=\"tr1\"><td>Station Name</td>", stream);
00155         fputs
00156             ("<td align=\"left\"><INPUT type=\"hidden\" value=\"savenew\" name=\"0\"><INPUT type=\"text\" name=\"sname\" class=\"inputl\"></td>",
00157              stream);
00158         fputs("</tr><tr class=\"tr2\"><td>Station URL's</td>", stream);
00159         fputs("<td align=\"left\"><TEXTAREA class=\"inputl\" name=\"surl\" style=\"height:100;\"></TEXTAREA></td>", stream);
00160         fputs
00161             ("</tr><tr class=\"tr1\"><td>Save Settings</td><td align=\"right\"><INPUT type=\"submit\" name=\"func\" value=\"Apply\" class=\"submit\"></td></tr>",
00162              stream);
00163     } else {
00164         for (i = LAST_FAVORITE + 1, row = 0; i < MAX_FAVORITES; i++) {
00165             if (favlist[i].rs_name == NULL) {
00166                 continue;
00167             }
00168             if (row & 1) {
00169                 fputs("<tr class=\"tr1\">\r\n", stream);
00170             } else {
00171                 fputs("<tr class=\"tr2\">\r\n", stream);
00172             }
00173             row++;
00174 
00175             fprintf(stream, "<td>%s</td>\r\n", favlist[i].rs_name);
00176             fprintf(stream, "<td><INPUT type=\"submit\" name=\"%d\" value=\"edit\" class=\"submit\"></td>\r\n", i);
00177             fprintf(stream,
00178                     "<td><INPUT type=\"submit\" name=\"%d\" value=\"delete\" class=\"submit\" onClick=\"return confirm('Are you sure you want to delete %s ?');\"></td>\r\n",
00179                     i, favlist[i].rs_name);
00180             fprintf(stream, "<td><INPUT type=\"submit\" name=\"%d\" value=\"play now\" class=\"submit\"></td>\r\n", i);
00181             fputs("</tr>\r\n", stream);
00182         }
00183         if (row & 1) {
00184             fputs("<tr class=\"tr1\">\r\n", stream);
00185         } else {
00186             fputs("<tr class=\"tr2\">\r\n", stream);
00187         }
00188         fputs
00189             ("<td colspan=\"4\" align=\"right\"><INPUT type=\"submit\" name=\"0\" value=\"add new Favorite\" class=\"submit\"></td>",
00190              stream);
00191         fputs("</tr>\r\n", stream);
00192     }
00193     fflush(stream);
00194 
00195     return 0;
00196 }
00197 
00198 static int CgiShoutCastGenres(FILE * stream, REQUEST * req)
00199 {
00200     int i;
00201     int count;
00202     char *name;
00203     char *genre;
00204     char *getgenre = NULL;
00205     count = NutHttpGetParameterCount(req);
00206     for (i = 0; i < count; i++) {
00207         name = NutHttpGetParameterName(req, i);
00208         if (strcmp(name, "genre") == 0) {
00209             getgenre = NutHttpGetParameterValue(req, i);
00210             break;
00211         }
00212     }
00213 #if 0
00214     if (getgenre == NULL) {
00215         fprintf(stream, "<OPTION SELECTED id=\"Top500\">Top500</OPTION>\r\n");
00216     } else {
00217         fprintf(stream, "<OPTION id=\"Top500\">Top500</OPTION>\r\n");
00218     }
00219 #else
00220     if (getgenre == NULL) {
00221         fprintf(stream, "<OPTION SELECTED id=\"TopTen\">TopTen</OPTION>\r\n");
00222     } else {
00223         fprintf(stream, "<OPTION id=\"Top500\">TopTen</OPTION>\r\n");
00224     }
00225 #endif
00226     for (i = 0;; i++) {
00227         genre = ShoutCastGetGenre(i);
00228         if (genre == NULL) {
00229             break;
00230         }
00231         if (strcmp(getgenre, genre) == 0) {
00232             fprintf(stream, "<OPTION SELECTED id=\"%s\">%s</OPTION>\r\n", genre, genre);
00233         } else {
00234             fprintf(stream, "<OPTION id=\"%s\">%s</OPTION>\r\n", genre, genre);
00235         }
00236     }
00237     fflush(stream);
00238 
00239     return 0;
00240 }
00241 
00242 static int CgiShoutCastStations(FILE * stream, REQUEST * req)
00243 {
00244     int count;
00245     char *name;
00246     char *genre = NULL;
00247     int i;
00248 
00249     count = NutHttpGetParameterCount(req);
00250     for (i = 0; i < count; i++) {
00251         name = NutHttpGetParameterName(req, i);
00252         if (strcmp(name, "genre") == 0) {
00253             genre = NutHttpGetParameterValue(req, i);
00254             break;
00255         }
00256     }
00257     for (i = 0;; i++) {
00258         if (genre) {
00259             name = ShoutCastGetStationName(genre, i);
00260         } else {
00261             name = ShoutCastGetStationName("Top500", i);
00262         }
00263         if (name == NULL) {
00264             break;
00265         }
00266         if (i & 1) {
00267             fputs("<tr class=\"tr1\">\r\n", stream);
00268         } else {
00269             fputs("<tr class=\"tr2\">\r\n", stream);
00270         }
00271         fprintf(stream, "<td>%s</td>\r\n", name);
00272         fprintf(stream, "<td><INPUT type=\"submit\" name=\"%d\" value=\"play now\" class=\"submit\"></td>\r\n", i);
00273         fprintf(stream, "<td><INPUT type=\"submit\" name=\"%d\" value=\"add to favorites\" class=\"submit\"></td>\r\n", i);
00274         fputs("</tr>\r\n", stream);
00275     }
00276     fflush(stream);
00277 
00278     return 0;
00279 }
00280 
00281 static int CgiShoutCastControl(FILE * stream, REQUEST * req)
00282 {
00283     int count;
00284     char *name;
00285     char *value;
00286     int action = 0;
00287     int idx = 0;
00288 
00289     count = NutHttpGetParameterCount(req);
00290     while (count--) {
00291         value = NutHttpGetParameterValue(req, count);
00292         if (strcmp(value, "add to favorites") == 0) {
00293             action = 1;
00294         }
00295         if (strcmp(value, "play now") == 0) {
00296             action = 2;
00297         }
00298         if (action) {
00299             if ((name = NutHttpGetParameterName(req, count)) == NULL) {
00300                 action = 0;
00301             } else {
00302                 idx = atoi(name);
00303                 break;
00304             }
00305         }
00306     }
00307     if (action == 1) {
00308         ShoutCastAddStation(idx, MAX_FAVORITES);
00309         webradio.wr_favupd = 10;
00310     } else if (action == 2) {
00311         ShoutCastAddStation(idx, TOP_FAVORITE);
00312     }
00313     return 0;
00314 }
00315 
00316 static void AddStationUris(int idx, CONST char *str)
00317 {
00318     char *uri = malloc(256);
00319     CONST char *cp;
00320     char *up;
00321 
00322     if (uri) {
00323         cp = str;
00324         while (*cp) {
00325             while (*cp && *cp < ' ') {
00326                 cp++;
00327             }
00328             up = uri;
00329             while (*cp) {
00330                 if (*cp < ' ') {
00331                     break;
00332                 }
00333                 *up++ = *cp++;
00334             }
00335             *up = 0;
00336             if (strlen(uri)) {
00337                 LogMsg(LOG_HTTPD, "Add '%s'\n", uri);
00338                 FavListSet(idx, NULL, uri);
00339             }
00340         }
00341         free(uri);
00342     }
00343 }
00344 
00345 static int CgiFavoritesControl(FILE * stream, REQUEST * req)
00346 {
00347     int count;
00348     char *name;
00349     char *value;
00350     int action = 0;
00351     int idx = 0;
00352     char *sname = NULL;
00353     char *surl = NULL;
00354 
00355     count = NutHttpGetParameterCount(req);
00356     while (count--) {
00357         name = NutHttpGetParameterName(req, count);
00358         value = NutHttpGetParameterValue(req, count);
00359         if (strcmp(name, "sname") == 0) {
00360             sname = value;
00361         } else if (strcmp(name, "surl") == 0) {
00362             surl = value;
00363         } else if (strcmp(value, "saveedit") == 0) {
00364             action = 1;
00365             idx = atoi(name);
00366         } else if (strcmp(value, "delete") == 0) {
00367             action = 2;
00368             idx = atoi(name);
00369         } else if (strcmp(value, "play now") == 0) {
00370             action = 3;
00371             idx = atoi(name);
00372         } else if (strcmp(value, "savenew") == 0) {
00373             action = 4;
00374         }
00375     }
00376     if (action == 1) {
00377         /* Save existing. */
00378         idx = FavListSet(idx, sname, NULL);
00379         AddStationUris(idx, surl);
00380         webradio.wr_favupd = 2;
00381     } else if (action == 2) {
00382         FavListSet(idx, NULL, NULL);
00383         webradio.wr_favupd = 20;
00384     } else if (action == 3) {
00385         FavListCopy(idx, TOP_FAVORITE);
00386     } else if (action == 4) {
00387         /* Add new. */
00388         idx = FavListSet(MAX_FAVORITES, sname, NULL);
00389         AddStationUris(idx, surl);
00390         webradio.wr_favupd = 2;
00391     }
00392     return 0;
00393 }
00394 
00395 static int CgiSettings(FILE * stream, REQUEST * req)
00396 {
00397     int count;
00398     char *name;
00399     char *value = NULL;
00400     char *hostname = NULL;
00401     char *prox = NULL;
00402     char *dhcp = NULL;
00403     char *ip = NULL;
00404     char *mask = NULL;
00405     char *gateway = NULL;
00406     char *dns0 = NULL;
00407     char *dns1 = NULL;
00408     char *func = NULL;
00409     u_long addr;
00410     int i;
00411     int upd_os = 0;
00412     int upd_net = 0;
00413     int upd_boot = 0;
00414     int upd_radio = 0;
00415 
00416     count = NutHttpGetParameterCount(req);
00417     for (i = 0; i < count; i++) {
00418         name = NutHttpGetParameterName(req, i);
00419         if (strcmp(name, "value") == 0) {
00420             value = NutHttpGetParameterValue(req, i);
00421             break;
00422         } else if (strcmp(name, "hostname") == 0) {
00423             hostname = NutHttpGetParameterValue(req, i);
00424         } else if (strcmp(name, "proxy") == 0) {
00425             prox = NutHttpGetParameterValue(req, i);
00426         } else if (strcmp(name, "dhcp") == 0) {
00427             dhcp = NutHttpGetParameterValue(req, i);
00428         } else if (strcmp(name, "ip") == 0) {
00429             ip = NutHttpGetParameterValue(req, i);
00430         } else if (strcmp(name, "mask") == 0) {
00431             mask = NutHttpGetParameterValue(req, i);
00432         } else if (strcmp(name, "gateway") == 0) {
00433             gateway = NutHttpGetParameterValue(req, i);
00434         } else if (strcmp(name, "dns0") == 0) {
00435             dns0 = NutHttpGetParameterValue(req, i);
00436         } else if (strcmp(name, "dns1") == 0) {
00437             dns1 = NutHttpGetParameterValue(req, i);
00438         } else if (strcmp(name, "func") == 0) {
00439             func = NutHttpGetParameterValue(req, i);
00440         }
00441     }
00442     if (func) {
00443         if (strcmp(func, "Apply") == 0) {
00444             if (hostname) {
00445                 strncpy(confos.hostname, hostname, sizeof(confos.hostname) - 1);
00446                 upd_os = 1;
00447             }
00448             if (prox) {
00449                 char *cp = prox;
00450 
00451                 while (*cp && *cp <= ' ') {
00452                     cp++;
00453                 }
00454                 if (strlen(cp)) {
00455                     strncpy(proxy.proxy_host, cp, sizeof(proxy.proxy_host) - 1);
00456                     if ((cp = strrchr(proxy.proxy_host, ':')) != NULL) {
00457                         *cp++ = 0;
00458                         proxy.proxy_port = atoi(cp);
00459                     }
00460                 }
00461                 else {
00462                     memset(&proxy, 0, sizeof(proxy));
00463                 }
00464                 upd_radio = 1;
00465             }
00466             if (dhcp && strcmp(dhcp, "on") == 0) {
00467                 confnet.cdn_cip_addr = 0;
00468                 upd_net = 1;
00469                 upd_boot = 1;
00470             }
00471             else {
00472                 if (ip) {
00473                     addr = inet_addr(ip);
00474                     if ((long)addr != -1) {
00475                         confnet.cdn_cip_addr = addr;
00476                         upd_net = 1;
00477                         upd_boot = 1;
00478                     }
00479                 }
00480                 if (mask) {
00481                     addr = inet_addr(mask);
00482                     if ((long)addr != -1) {
00483                         confnet.cdn_ip_mask = addr;
00484                         upd_net = 1;
00485                         upd_boot = 1;
00486                     }
00487                 }
00488                 if (gateway) {
00489                     addr = inet_addr(gateway);
00490                     if ((long)addr != -1) {
00491                         confnet.cdn_gateway = addr;
00492                         upd_net = 1;
00493                         upd_boot = 1;
00494                     }
00495                 }
00496                 if (dns0) {
00497                     addr = inet_addr(dns0);
00498                     if ((long)addr != -1) {
00499                         webradio.wr_pridns = addr;
00500                         upd_radio = 1;
00501                         upd_boot = 1;
00502                     }
00503                 }
00504                 if (dns1) {
00505                     addr = inet_addr(dns1);
00506                     if ((long)addr != -1) {
00507                         webradio.wr_secdns = addr;
00508                         upd_radio = 1;
00509                         upd_boot = 1;
00510                     }
00511                 }
00512             }
00513             if (upd_os) {
00514                 LogMsg(LOG_HTTPD, "Saving OS\n");
00515                 NutSaveConfig();
00516             }
00517             if (upd_net) {
00518                 LogMsg(LOG_HTTPD, "Saving Net\n");
00519                 NutNetSaveConfig();
00520             }
00521             if (upd_radio) {
00522                 ConfigSave();
00523             }
00524             if (upd_boot) {
00525                 LogMsg(LOG_HTTPD, "Reboot\n");
00526                 webradio.wr_reboot = 3;
00527             }
00528         } 
00529         else if (strcmp(func, "Erase") == 0) {
00530             u_char mac[6];
00531 
00532             memset(&confos, 0, sizeof(confos));
00533             NutSaveConfig();
00534             memcpy(mac, confnet.cdn_mac, sizeof(mac));
00535             memset(&confnet, 0, sizeof(confnet));
00536             memcpy(confnet.cdn_mac, mac, sizeof(confnet.cdn_mac));
00537             NutNetSaveConfig();
00538             ConfigResetFactory();
00539             FavListResetFactory();
00540             ConfigSave();
00541             FavListSave();
00542             webradio.wr_reboot = 2;
00543         }
00544     }
00545     else if (value) {
00546         if (strcmp(value, "hostname") == 0) {
00547             fprintf(stream, "%s", confos.hostname);
00548         } else if (strcmp(value, "dhcp") == 0) {
00549             if (confnet.cdn_cip_addr == 0) {
00550                 fputs(" checked=\"checked\"", stream);
00551             }
00552         } else if (strcmp(value, "proxy") == 0) {
00553             if (proxy.proxy_port) {
00554                 fputs(proxy.proxy_host, stream);
00555                 if (proxy.proxy_port != 80) {
00556                     fprintf(stream, ":%u", proxy.proxy_port);
00557                 }
00558             }
00559         } else if (strcmp(value, "ip") == 0) {
00560             if (confnet.cdn_cip_addr) {
00561                 fputs(inet_ntoa(confnet.cdn_cip_addr), stream);
00562             } else {
00563                 fputs(inet_ntoa(confnet.cdn_ip_addr), stream);
00564             }
00565         } else if (strcmp(value, "mask") == 0) {
00566             fputs(inet_ntoa(confnet.cdn_ip_mask), stream);
00567         } else if (strcmp(value, "gateway") == 0) {
00568             fputs(inet_ntoa(confnet.cdn_gateway), stream);
00569         } else if (strcmp(value, "dns0") == 0) {
00570             NutDnsGetConfig2(NULL, NULL, &addr, NULL);
00571             fputs(inet_ntoa(addr), stream);
00572         } else if (strcmp(value, "dns1") == 0) {
00573             NutDnsGetConfig2(NULL, NULL, NULL, &addr);
00574             fputs(inet_ntoa(addr), stream);
00575         }
00576     }
00577     return 0;
00578 }
00579 
00580 static int CgiVars(FILE * stream, REQUEST * req)
00581 {
00582     int count;
00583     char *name;
00584     char *cgivar = NULL;
00585     int i;
00586 
00587     count = NutHttpGetParameterCount(req);
00588     for (i = 0; i < count; i++) {
00589         name = NutHttpGetParameterName(req, i);
00590         if (strcmp(name, "var") == 0) {
00591             cgivar = NutHttpGetParameterValue(req, i);
00592             break;
00593         }
00594     }
00595 
00596     if (cgivar == NULL) {
00597         fputs("Error", stream);
00598     } else if (strcmp(cgivar, "MetaTitle") == 0 || strcmp(cgivar, "StreamTitle") == 0) {
00599         if (webradio.wr_rip) {
00600             SHOUTCASTINFO *sci = (SHOUTCASTINFO *) webradio.wr_rip->ri_bcast;
00601             if (sci && sci->sci_metatitle) {
00602                 fputs(sci->sci_metatitle, stream);
00603             }
00604         }
00605     } else if (strcmp(cgivar, "CPUClock") == 0) {
00606         fprintf(stream, "%lu kHz", NutGetCpuClock() / 1000);
00607     } else if (strcmp(cgivar, "MasterClock") == 0) {
00608 #if defined(AT91_PLL_MAINCK)
00609         fprintf(stream, "%lu kHz", At91GetMasterClock() / 1000);
00610 #endif
00611     } else if (strcmp(cgivar, "TotalMemoryUsed") == 0) {
00612         fprintf(stream, "%u kBytes", (u_int) (NUTMEM_SIZE - NutHeapAvailable()) / 1024);
00613     } else if (strcmp(cgivar, "StationName") == 0) {
00614         if (webradio.wr_sip) {
00615             fputs(webradio.wr_sip->si_name, stream);
00616         }
00617     } else if (strcmp(cgivar, "StationGenre") == 0) {
00618         if (webradio.wr_sip && webradio.wr_sip->si_genre) {
00619             fputs(webradio.wr_sip->si_genre, stream);
00620         }
00621     } else if (strcmp(cgivar, "StationBitrate") == 0) {
00622         if (webradio.wr_sip) {
00623             fprintf(stream, "%u kBit", webradio.wr_sip->si_bitrate);
00624         }
00625     } else if (strcmp(cgivar, "BufferContents") == 0) {
00626         fprintf(stream, "%lu Bytes", NutSegBufUsed());
00627     } else if (strcmp(cgivar, "StreamURL") == 0) {
00628         if (webradio.wr_rip) {
00629             SHOUTCASTINFO *sci = (SHOUTCASTINFO *) webradio.wr_rip->ri_bcast;
00630             if (sci->sci_metaurl) {
00631                 fprintf(stream, "%s", sci->sci_metaurl);
00632             }
00633         }
00634     } else if (strcmp(cgivar, "MetadataInterval") == 0) {
00635         if (webradio.wr_rip) {
00636             SHOUTCASTINFO *sci = (SHOUTCASTINFO *) webradio.wr_rip->ri_bcast;
00637             fprintf(stream, "%lu Bytes", sci->sci_metaint);
00638         }
00639     } else if (strcmp(cgivar, "NutVersion") == 0) {
00640         fputs(NutVersionString(), stream);
00641     } else if (strcmp(cgivar, "AppVersion") == 0) {
00642         fputs(VERSION, stream);
00643     } else {
00644         fputs("Unknown", stream);
00645     }
00646     fflush(stream);
00647     return 0;
00648 }
00649 
00662 THREAD(Service, arg)
00663 {
00664     TCPSOCKET *sock;
00665     FILE *stream;
00666 
00667     LogMsg(LOG_HTTPD, "Started HTTP daemon\n");
00668     for (;;) {
00669         /* Create a socket. */
00670         if ((sock = NutTcpCreateSocket()) == 0) {
00671             LogMsg(LOG_WARN, "No sockets\n");
00672             NutSleep(1000);
00673             continue;
00674         }
00675 
00676         /* Set socket options. Silently ignore any error. */
00677 #ifdef HTTPD_MAX_SEGSIZE
00678         {
00679             u_short mss = HTTPD_MAX_SEGSIZE;
00680             NutTcpSetSockOpt(sock, TCP_MAXSEG, &mss, sizeof(mss));
00681         }
00682 #endif
00683 #ifdef HTTPD_TCP_BUFSIZE
00684         {
00685             u_short tcpbufsiz = HTTPD_TCP_BUFSIZE;
00686             NutTcpSetSockOpt(sock, SO_RCVBUF, &tcpbufsiz, sizeof(tcpbufsiz));
00687         }
00688 #endif
00689 #ifdef HTTPD_TCP_TIMEOUT
00690         {
00691             u_long tmo = HTTPD_TCP_TIMEOUT;
00692             NutTcpSetSockOpt(sock, SO_RCVTIMEO, &tmo, sizeof(tmo));
00693         }
00694 #endif
00695 
00696         LogMsg(LOG_HTTPD, "Waiting for HTTP client\n");
00697         stream = TcpStreamAccept(sock, HTTPD_TCP_PORT, "r+b");
00698         if (stream) {
00699             LogMsg(LOG_HTTPD, "Connected HTTP client\n");
00700 #ifdef USE_DYNAMIC_THREADS
00701             /* Start a new thread and let it run. */
00702             StartServiceThread();
00703             NutSleep(1);
00704 #endif
00705             /* Let the Nut/OS library process the client's requests. */
00706             NutHttpProcessRequest(stream);
00707             LogMsg(LOG_HTTPD, "Disconnecting HTTP client\n");
00708             fclose(stream);
00709         }
00710         NutTcpCloseSocket(sock);
00711 
00712 #ifdef USE_DYNAMIC_THREADS
00713         /* If enough threads are running, stop this one. */
00714         if (httpd_tc >= HTTPD_MIN_THREADS) {
00715             httpd_tc--;
00716             LogMsg(LOG_HTTPD, "Stop HTTP daemon\n");
00717             NutThreadExit();
00718         }
00719 #endif
00720     }
00721 }
00722 
00723 /*
00724  * Start a HTTP daemon thread.
00725  */
00726 static int StartServiceThread(void)
00727 {
00728 #ifdef USE_DYNAMIC_THREADS
00729     if (httpd_tc >= HTTPD_MAX_THREADS) {
00730         return 0;
00731     }
00732 #endif
00733 
00734     if (NutThreadCreate("httpd", Service, NULL, HTTPD_SERVICE_STACK) == NULL) {
00735         return -1;
00736     }
00737     httpd_tc++;
00738 
00739     return 0;
00740 }
00741 
00745 int HttpServerStart(void)
00746 {
00747     int i;
00748 
00749     /*
00750      * Register our device for the file system.
00751      */
00752     if (NutRegisterDevice(&MY_FSDEV, 0, 0)) {
00753         LogMsg(LOG_ERROR, "No HTTP mount\n");
00754         return -1;
00755     }
00756 
00757 #ifdef MY_HTTPROOT
00758     /* Register root directory. */
00759     LogMsg(LOG_HTTPD, "Register root dir '" MY_HTTPROOT "'\n");
00760     if (NutRegisterHttpRoot(MY_HTTPROOT)) {
00761         LogMsg(LOG_ERROR, "No HTTP root\n");
00762         return -1;
00763     }
00764 #endif
00765     /*
00766      * Register SSI handler
00767      */
00768     NutRegisterSsi();
00769 
00770     /*
00771      * Register our CGIs.
00772      */
00773     NutRegisterCgi("f_control.cgi", CgiFavoritesControl);
00774     NutRegisterCgi("favorites.cgi", CgiStationFavorites);
00775     NutRegisterCgi("genres.cgi", CgiShoutCastGenres);
00776     NutRegisterCgi("stations.cgi", CgiShoutCastStations);
00777     NutRegisterCgi("sc_control.cgi", CgiShoutCastControl);
00778     NutRegisterCgi("vars.cgi", CgiVars);
00779     NutRegisterCgi("settings.cgi", CgiSettings);
00780 
00781     /*
00782      * Protect the admin directory with user and password.
00783      */
00784     NutRegisterAuth("admin", "admin:admin");
00785 
00786     /*
00787      * Start four server threads.
00788      */
00789     LogMsg(LOG_HTTPD, "Starting %d HTTP daemons\n", HTTPD_MIN_THREADS);
00790     for (i = 0; i < HTTPD_MIN_THREADS; i++) {
00791         if (StartServiceThread()) {
00792             LogMsg(LOG_ERROR, "Thread start failed\n");
00793             return -1;
00794         }
00795     }
00796 
00797     /* Let started threads take over. */
00798     NutSleep(1);
00799 
00800     return 0;
00801 }
00802 
00803 #endif /* USE_HTTPSERVER */

© 2008 by egnite GmbH - visit www.ethernut.de