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 <sys/heap.h>
00046 #include <sys/thread.h>
00047 #include <sys/timer.h>
00048
00049 #include <netinet/tcp.h>
00050 #include <arpa/inet.h>
00051
00052 #include <stdlib.h>
00053 #include <stdio.h>
00054 #include <string.h>
00055
00056
00057 #include "scanner.h"
00058
00059
00060
00061
00062
00063 static int GetLine(TCPSOCKET * sock, u_char * line, u_short size)
00064 {
00065 int rc = 0;
00066 u_char to_cnt = 0;
00067 int got;
00068 u_char *cp = line;
00069
00070 if (size > 0) {
00071 for (;;) {
00072 if ((got = NutTcpReceive(sock, cp, 1)) <= 0) {
00073 if (got == 0 && to_cnt++ < 10)
00074 continue;
00075 rc = got;
00076 printf("[GL-TO]");
00077 break;
00078 }
00079 if (*cp == '\n') {
00080 *cp = 0;
00081 break;
00082 }
00083 if (*cp != '\r' && rc < (int) size) {
00084 rc++;
00085 cp++;
00086 }
00087 }
00088 }
00089 return rc;
00090 }
00091
00092 static int PutString(TCPSOCKET * sock, u_char * str)
00093 {
00094 u_short len = strlen(str);
00095 u_short n;
00096 int c;
00097
00098 for (n = 0; n < len; n += c)
00099 if ((c = NutTcpSend(sock, str + n, len - n)) < 0)
00100 return -1;
00101 return len;
00102 }
00103
00104
00108 int ScanStreamHeader(TCPSOCKET * sock, RADIOSTATION * rsp)
00109 {
00110 int rc = -1;
00111 u_char *line = malloc(256);
00112 char *cp;
00113
00114
00115
00116
00117 strcpy(line, "GET /");
00118 if (rsp->rs_url)
00119 strcat(line, rsp->rs_url);
00120 strcat(line, " HTTP/1.0\r\n");
00121 PutString(sock, line);
00122
00123 sprintf(line, "Host: %s\r\n", inet_ntoa(rsp->rs_ip));
00124 PutString(sock, line);
00125
00126 PutString(sock, "User-Agent: WinampMPEG/2.7\r\n" "Accept: */*\r\n" "Icy-MetaData: 1\r\n" "Connection: close\r\n\r\n");
00127
00128 if (rsp->rs_name) {
00129 free(rsp->rs_name);
00130 rsp->rs_name = 0;
00131 }
00132 if (rsp->rs_genre) {
00133 free(rsp->rs_genre);
00134 rsp->rs_genre = 0;
00135 }
00136 rsp->rs_metaint = 0;
00137
00138
00139
00140
00141 if (GetLine(sock, line, 256) > 5) {
00142 printf("%s\n", line);
00143 if (strncmp(line, "ICY", 3) == 0) {
00144 if (atoi(line + 4) == 200) {
00145 for (;;) {
00146 if ((rc = GetLine(sock, line, 256)) <= 0) {
00147 break;
00148 }
00149 if (strncmp(line, "icy-name:", 9) == 0) {
00150 cp = line + 9;
00151 while (*cp && *cp == ' ')
00152 cp++;
00153 if (*cp && rsp->rs_name == 0) {
00154 rsp->rs_name = malloc(strlen(cp) + 1);
00155 strcpy(rsp->rs_name, cp);
00156 printf("%s\n", cp);
00157 }
00158 } else if (strncmp(line, "icy-genre:", 10) == 0) {
00159 cp = line + 10;
00160 while (*cp && *cp == ' ')
00161 cp++;
00162 if (*cp && rsp->rs_genre == 0) {
00163 rsp->rs_genre = malloc(strlen(cp) + 1);
00164 strcpy(rsp->rs_genre, cp);
00165 }
00166 } else if (strncmp(line, "icy-metaint:", 12) == 0)
00167 rsp->rs_metaint = atol(line + 12);
00168 else if (strncmp(line, "icy-br:", 7) == 0)
00169 rsp->rs_bitrate = atol(line + 7);
00170 }
00171 } else
00172 puts(line);
00173 }
00174 }
00175
00176 free(line);
00177
00178 printf("\n%s %ukbps %s ", inet_ntoa(rsp->rs_ip), rsp->rs_bitrate, rsp->rs_name);
00179
00180 return rc;
00181 }
00182
00183
00184
00185
00186 static char *ReadMetaTitle(TCPSOCKET * sock, u_long iv)
00187 {
00188 u_char blks = 0;
00189 u_short cnt;
00190 int got;
00191 int rc = 0;
00192 char *title = 0;
00193 u_char *buf;
00194 u_char *mn1;
00195 u_char *mn2;
00196 u_char *md1;
00197 u_char *md2;
00198
00199
00200 if ((buf = malloc(512 + 1)) == 0) {
00201 return 0;
00202 }
00203 for (cnt = 512; iv; iv -= got) {
00204 if (iv < 512)
00205 cnt = iv;
00206 if ((got = NutTcpReceive(sock, buf, cnt)) <= 0)
00207 break;
00208 }
00209
00210 if (iv == 0) {
00211
00212 if ((got = NutTcpReceive(sock, &blks, 1)) == 1) {
00213 if (blks && blks <= 32) {
00214
00215
00216 for (cnt = blks * 16; cnt; cnt -= got) {
00217 if ((got = NutTcpReceive(sock, buf + rc, cnt)) < 0)
00218 break;
00219 rc += got;
00220 buf[rc] = 0;
00221 }
00222 if (cnt == 0) {
00223 mn1 = buf;
00224 while (mn1) {
00225 if ((mn2 = strchr(mn1, ';')) != 0)
00226 *mn2++ = 0;
00227 if ((md1 = strchr(mn1, '=')) != 0) {
00228 *md1++ = 0;
00229 while (*md1 == ' ' || *md1 == '\'')
00230 md1++;
00231 if ((md2 = strrchr(md1, '\'')) != 0)
00232 *md2 = 0;
00233 if (strcasecmp(mn1, "StreamTitle") == 0) {
00234 title = malloc(strlen(md1) + 1);
00235 strcpy(title, md1);
00236 break;
00237 }
00238 }
00239 mn1 = mn2;
00240 }
00241 }
00242 } else
00243 printf("[ML=%u]", blks);
00244 }
00245 } else
00246 puts("[SMFAIL]");
00247 free(buf);
00248 return title;
00249 }
00250
00251
00252
00253
00254
00255
00256 THREAD(Scanner, arg)
00257 {
00258 TCPSOCKET *sock;
00259 RADIOSTATION *rsp;
00260 u_char rs;
00261 u_long rx_to = 10000UL;
00262
00263 NutThreadSetPriority(128);
00264 NutSleep(10000);
00265 for (;;) {
00266 for (rs = 0; rs < MAXNUM_STATIONS; rs++) {
00267 NutSleep(2000);
00268 if (rs == radio.rc_rstation || rs == radio.rc_cstation)
00269 continue;
00270 rsp = &station[rs];
00271 if (rsp->rs_ip == 0 || rsp->rs_port == 0 || radio.rc_off) {
00272 continue;
00273 }
00274
00275
00276 if (rsp->rs_name) {
00277 printf("%u bytes free\n", NutHeapAvailable());
00278 NutSleep(30000);
00279 }
00280
00281
00282 if ((sock = NutTcpCreateSocket()) == 0) {
00283 break;
00284 }
00285 NutTcpSetSockOpt(sock, SO_RCVTIMEO, &rx_to, sizeof(rx_to));
00286
00287
00288 printf("[Scan %s:%u]\n", inet_ntoa(rsp->rs_ip), rsp->rs_port);
00289 if (NutTcpConnect(sock, rsp->rs_ip, rsp->rs_port) == 0) {
00290
00291 if (ScanStreamHeader(sock, rsp) == 0) {
00292 if (rsp->rs_scantitle) {
00293 free(rsp->rs_scantitle);
00294 rsp->rs_scantitle = 0;
00295 }
00296 if (rsp->rs_metaint) {
00297 if ((rsp->rs_scantitle = ReadMetaTitle(sock, rsp->rs_metaint)) != 0) {
00298 printf("%03u: %s\n", rs, rsp->rs_scantitle);
00299 rsp->rs_scandead = 0;
00300 } else
00301 rsp->rs_scandead = 1;
00302 } else
00303 rsp->rs_scandead = 0;
00304 } else
00305 rsp->rs_scandead = 1;
00306 } else {
00307 rsp->rs_scandead = 1;
00308 printf("[SERR=%d]\n", NutTcpError(sock));
00309 }
00310 NutTcpCloseSocket(sock);
00311 }
00312 }
00313 NutSleep(30000);
00314 }
00315
00322 int ScannerInit(void)
00323 {
00324
00325 if (NutThreadCreate("scanner", Scanner, 0, 512) == 0)
00326 return -1;
00327
00328 return 0;
00329 }