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