00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00045 #include <cfg/os.h>
00046 #include <cfg/memory.h>
00047
00048 #include "config.h"
00049
00050 #ifdef USE_HTTPSERVER
00051
00052 #include <stdlib.h>
00053 #include <string.h>
00054 #include <io.h>
00055
00056 #include <netinet/tcp.h>
00057
00058 #include <dev/board.h>
00059 #include <dev/vscodec.h>
00060
00061 #include <sys/heap.h>
00062 #include <sys/event.h>
00063 #include <sys/timer.h>
00064
00065 #include <pro/uxml.h>
00066
00067 #include "logmsg.h"
00068 #include "utils.h"
00069 #include "favlist.h"
00070 #include "userif.h"
00071 #include "xmlserv.h"
00072
00073
00074 static int xmld_tc;
00075
00076
00077 static HANDLE xml_infoq;
00078
00079 static int StartReportServiceThread(void);
00080
00081 void XmlRefresh(void)
00082 {
00083 NutEventBroadcast(&xml_infoq);
00084 }
00085
00086
00087
00088
00089 static int XmlProcessCommands(FILE *stream)
00090 {
00091 UXML_NODE *cmd_tree = NULL;
00092 UXML_NODE *node;
00093 UXML_ATTRIB *attr;
00094 char *cmdp;
00095 char *valp;
00096
00097 char *f_tags[] = { "cmd", NULL };
00098 char *f_attribs[] = { "name", "value", NULL };
00099
00100
00101 if ((cmd_tree = UxmlParseStream(stream, f_tags, f_attribs)) == NULL) {
00102 if (ferror(stream)) {
00103
00104 return -1;
00105 }
00106
00107 LogMsg(LOG_XMLCD, "Connection timed out\n");
00108 return 0;
00109 }
00110
00111 for (node = cmd_tree; node; node = node->xmln_next) {
00112 attr = node->xmln_attribs;
00113 cmdp = NULL;
00114 valp = NULL;
00115 while (attr) {
00116 if (strcasecmp(attr->xmla_name, "name") == 0) {
00117 cmdp = attr->xmla_value;
00118 }
00119 else if (strcasecmp(attr->xmla_name, "value") == 0) {
00120 valp = attr->xmla_value;
00121 }
00122 attr = attr->xmla_next;
00123 }
00124 if (cmdp) {
00125 LogMsg(LOG_XMLCD, "XML cmd '%s%s%s'\n", cmdp, valp ? "=" : "", valp ? valp : "");
00126 if (strcasecmp(cmdp, "gain") == 0) {
00127 if (valp) {
00128 webradio.wr_gain = atoi(valp);
00129 webradio.wr_cfgupd = 10;
00130 if (webradio.wr_rip == NULL ||
00131 webradio.wr_rip->ri_decoder == -1 ||
00132 _ioctl(webradio.wr_rip->ri_decoder, AUDIO_SET_PLAYGAIN, &webradio.wr_gain) != 0) {
00133 LogMsg(LOG_ERROR, "No volume control\n");
00134 }
00135 XmlRefresh();
00136 }
00137 }
00138 }
00139 }
00140
00141 UxmlTreeDestroy(cmd_tree);
00142 return 0;
00143 }
00144
00145
00146
00147
00148 static int XmlProcessReports(FILE *stream)
00149 {
00150 char *title = malloc(256);
00151
00152 fprintf(stream, "<radioinfo>");
00153 if (title) {
00154 fprintf(stream, "<title value=\"%s\"></title>", UserIfGetDisplayText(title, 256));
00155 }
00156 fprintf(stream, "<gain value=\"%d\" min=\"%d\" max=\"%d\"></gain>", webradio.wr_gain, AUDIO_DAC_MIN_GAIN, AUDIO_DAC_MAX_GAIN);
00157 fprintf(stream, "</radioinfo>");
00158 fputc(0, stream);
00159 return fflush(stream);
00160 }
00161
00167 THREAD(XmlCmdService, arg)
00168 {
00169 TCPSOCKET *sock;
00170 FILE *stream;
00171
00172
00173
00174
00175 LogMsg(LOG_XMLCD, "Cmd daemon running\n");
00176 for (;;) {
00177
00178 if ((sock = NutTcpCreateSocket()) == 0) {
00179 LogMsg(LOG_ERROR, "No socket\n");
00180 NutSleep(5000);
00181 continue;
00182 }
00183
00184
00185 #ifdef XMLD_MAX_SEGSIZE
00186 {
00187 u_short mss = XMLD_MAX_SEGSIZE;
00188 NutTcpSetSockOpt(sock, TCP_MAXSEG, &mss, sizeof(mss));
00189 }
00190 #endif
00191 #ifdef XMLD_TCP_BUFSIZE
00192 {
00193 u_short tcpbufsiz = XMLD_TCP_BUFSIZE;
00194 NutTcpSetSockOpt(sock, SO_RCVBUF, &tcpbufsiz, sizeof(tcpbufsiz));
00195 }
00196 #endif
00197 #ifdef XMLD_TCP_TIMEOUT
00198 {
00199 u_long tmo = XMLD_TCP_TIMEOUT;
00200 NutTcpSetSockOpt(sock, SO_RCVTIMEO, &tmo, sizeof(tmo));
00201 }
00202 #endif
00203
00204 LogMsg(LOG_XMLCD, "Waiting for cmd client\n");
00205 stream = TcpStreamAccept(sock, XMLD_CMD_TCP_PORT, "r+b");
00206 if (stream) {
00207 LogMsg(LOG_XMLCD, "Connected cmd client\n");
00208 while (XmlProcessCommands(stream) == 0) {
00209 }
00210 LogMsg(LOG_HTTPD, "Disconnecting cmd client\n");
00211 fclose(stream);
00212 }
00213 NutTcpCloseSocket(sock);
00214 }
00215 }
00216
00217
00223 THREAD(XmlRepoService, arg)
00224 {
00225 TCPSOCKET *sock;
00226 FILE *stream;
00227 int refresh;
00228
00229 LogMsg(LOG_XMLRD, "Repo daemon started\n");
00230 for (;;) {
00231
00232 if ((sock = NutTcpCreateSocket()) == 0) {
00233 LogMsg(LOG_WARN, "No sockets\n");
00234 NutSleep(1000);
00235 continue;
00236 }
00237
00238
00239 #ifdef XMLD_MAX_SEGSIZE
00240 {
00241 u_short mss = XMLD_MAX_SEGSIZE;
00242 NutTcpSetSockOpt(sock, TCP_MAXSEG, &mss, sizeof(mss));
00243 }
00244 #endif
00245 #ifdef XMLD_TCP_BUFSIZE
00246 {
00247 u_short tcpbufsiz = XMLD_TCP_BUFSIZE;
00248 NutTcpSetSockOpt(sock, SO_RCVBUF, &tcpbufsiz, sizeof(tcpbufsiz));
00249 }
00250 #endif
00251 #ifdef XMLD_TCP_TIMEOUT
00252 {
00253 u_long tmo = XMLD_TCP_TIMEOUT;
00254 NutTcpSetSockOpt(sock, SO_RCVTIMEO, &tmo, sizeof(tmo));
00255 }
00256 #endif
00257
00258 LogMsg(LOG_XMLRD, "Waiting for repo client\n");
00259 stream = TcpStreamAccept(sock, XMLD_REPO_TCP_PORT, "r+b");
00260 if (stream) {
00261 LogMsg(LOG_XMLRD, "Connected repo client\n");
00262 #ifdef USE_DYNAMIC_THREADS
00263
00264 StartReportServiceThread();
00265 NutSleep(1);
00266 #endif
00267 refresh = 30;
00268 for (;;) {
00269
00270 if (++refresh < 30 && NutEventWait(&xml_infoq, 1000)) {
00271 fputc(0, stream);
00272 if (fflush(stream)) {
00273 break;
00274 }
00275 }
00276 else {
00277 refresh = 0;
00278 if (XmlProcessReports(stream)) {
00279 break;
00280 }
00281 }
00282 }
00283 LogMsg(LOG_XMLRD, "Disconnecting repo client\n");
00284 fclose(stream);
00285 }
00286 NutTcpCloseSocket(sock);
00287
00288 #ifdef USE_DYNAMIC_THREADS
00289
00290 if (xmld_tc >= XMLD_MIN_THREADS) {
00291 xmld_tc--;
00292 LogMsg(LOG_XMLRD, "Stop repo daemon\n");
00293 NutThreadExit();
00294 }
00295 #endif
00296 }
00297 }
00298
00299
00300
00301
00302 static int StartReportServiceThread(void)
00303 {
00304 #ifdef USE_DYNAMIC_THREADS
00305 if (xmld_tc >= XMLD_MAX_THREADS) {
00306 return 0;
00307 }
00308 #endif
00309
00310 if (NutThreadCreate("xmlrepo", XmlRepoService, NULL, XMLD_SERVICE_STACK) == NULL) {
00311 return -1;
00312 }
00313 xmld_tc++;
00314
00315 return 0;
00316 }
00317
00325 int XmlServerStart(void)
00326 {
00327 int i;
00328
00329
00330
00331
00332 LogMsg(LOG_XMLRD, "Starting %d XML repo daemons\n", XMLD_MIN_THREADS);
00333 for (i = 0; i < XMLD_MIN_THREADS; i++) {
00334 if (StartReportServiceThread()) {
00335 LogMsg(LOG_ERROR, "Thread start failed\n");
00336 return -1;
00337 }
00338 }
00339
00340
00341
00342
00343 LogMsg(LOG_XMLCD, "Starting XML cmd daemon\n");
00344 if (NutThreadCreate("xmlcmd", XmlCmdService, NULL, XMLD_SERVICE_STACK) == NULL) {
00345 LogMsg(LOG_ERROR, "Thread start failed\n");
00346 return -1;
00347 }
00348 xmld_tc++;
00349 NutSleep(1);
00350
00351 return 0;
00352 }
00353
00354 #endif