📄 http.c
字号:
int udp_port;
if (flac_cfg.stream.use_udp_channel)
{
udp_port = udp_establish_listener (&udp_sock);
if (udp_port > 0)
sprintf (udpspace, "x-audiocast-udpport: %d\r\n", udp_port);
else
udp_sock = 0;
}
if(user && pass)
auth = basic_authentication_encode(user, pass, "Authorization");
if (flac_cfg.stream.use_proxy)
{
file = g_strdup(url);
if(flac_cfg.stream.proxy_use_auth && flac_cfg.stream.proxy_user && flac_cfg.stream.proxy_pass)
{
proxy_auth = basic_authentication_encode(flac_cfg.stream.proxy_user,
flac_cfg.stream.proxy_pass,
"Proxy-Authorization");
}
}
else
file = g_strconcat("/", filename, NULL);
temp = g_strdup_printf("GET %s HTTP/1.0\r\n"
"Host: %s\r\n"
"User-Agent: %s/%s\r\n"
"%s%s%s%s",
file, host, "Reference FLAC Player", FLAC__VERSION_STRING,
proxy_auth ? proxy_auth : "", auth ? auth : "",
flac_cfg.stream.cast_title_streaming ? "Icy-MetaData:1\r\n" : "",
flac_cfg.stream.use_udp_channel ? udpspace : "");
if (offset && !head) {
gchar *temp_dead = temp;
temp = g_strconcat ("%sRange: %ll-\r\n", temp, offset);
fprintf (stderr, "%s", temp);
g_free (temp_dead);
}
g_free(file);
if(proxy_auth)
g_free(proxy_auth);
if(auth)
g_free(auth);
write(sock, temp, strlen(temp));
write(sock, "\r\n", 2);
g_free(temp);
flac_ip.set_info_text(_("CONNECTED: WAITING FOR REPLY"));
while (going && !eof)
{
if (http_check_for_data())
{
if (flac_http_read_line(line, 1024))
{
status = strchr(line, ' ');
if (status)
{
if (status[1] == '2')
break;
else if(status[1] == '3' && status[2] == '0' && status[3] == '2')
{
while(going)
{
if(http_check_for_data())
{
if((cnt = flac_http_read_line(line, 1024)) != -1)
{
if(!cnt)
break;
if(!strncmp(line, "Location:", 9))
{
g_free(url);
url = g_strdup(line+10);
}
}
else
{
eof=TRUE;
flac_ip.set_info_text(NULL);
break;
}
}
}
redirect=TRUE;
break;
}
else
{
status = g_strdup_printf(_("Couldn't connect to host %s\nServer reported: %s"), chost, status);
show_error_message(status);
g_free(status);
break;
}
}
}
else
{
eof = TRUE;
flac_ip.set_info_text(NULL);
}
}
}
while (going && !redirect)
{
if (http_check_for_data())
{
if ((cnt = flac_http_read_line(line, 1024)) != -1)
{
if (!cnt)
break;
if (!strncmp(line, "icy-name:", 9))
icy_name = g_strdup(line + 9);
else if (!strncmp(line, "x-audiocast-name:", 17))
icy_name = g_strdup(line + 17);
if (!strncmp(line, "icy-metaint:", 12))
icy_metaint = atoi(line + 12);
if (!strncmp(line, "x-audiocast-udpport:", 20)) {
#ifdef DEBUG_UDP
fprintf (stderr, "Server wants udp messages on port %d\n", atoi (line + 20));
#endif
/*udp_serverport = atoi (line + 20);*/
}
}
else
{
eof = TRUE;
flac_ip.set_info_text(NULL);
break;
}
}
}
}
}
if(redirect)
{
if (output_file)
{
fclose(output_file);
output_file = NULL;
}
close(sock);
}
g_free(user);
g_free(pass);
g_free(host);
g_free(filename);
} while(redirect);
g_free(url);
return eof ? -1 : sock;
}
static void *http_buffer_loop(void *arg)
{
gchar *status, *url, *temp, *file;
gint cnt, written;
int udp_sock = 0;
url = (gchar *) arg;
sock = http_connect (url, false, offset);
if (sock >= 0 && flac_cfg.stream.save_http_stream) {
gchar *output_name;
file = flac_http_get_title(url);
output_name = file;
if (!strncasecmp(output_name, "http://", 7))
output_name += 7;
temp = strrchr(output_name, '.');
if (temp && (!strcasecmp(temp, ".fla") || !strcasecmp(temp, ".flac")))
*temp = '\0';
while ((temp = strchr(output_name, '/')))
*temp = '_';
output_name = g_strdup_printf("%s/%s.flac", flac_cfg.stream.save_http_path, output_name);
g_free(file);
output_file = fopen(output_name, "wb");
g_free(output_name);
}
while (going)
{
if (!http_used() && !flac_ip.output->buffer_playing())
prebuffering = TRUE;
if (http_free() > 0 && !eof)
{
if (http_check_for_data())
{
cnt = min(http_free(), buffer_length - wr_index);
if (cnt > 1024)
cnt = 1024;
written = read(sock, buffer + wr_index, cnt);
if (written <= 0)
{
eof = TRUE;
if (prebuffering)
{
prebuffering = FALSE;
flac_ip.set_info_text(NULL);
}
}
else
wr_index = (wr_index + written) % buffer_length;
}
if (prebuffering)
{
if (http_used() > prebuffer_length)
{
prebuffering = FALSE;
flac_ip.set_info_text(NULL);
}
else
{
status = g_strdup_printf(_("PRE-BUFFERING: %dKB/%dKB"), http_used() / 1024, prebuffer_length / 1024);
flac_ip.set_info_text(status);
g_free(status);
}
}
}
else
xmms_usleep(10000);
if (flac_cfg.stream.use_udp_channel && udp_sock != 0)
if (udp_check_for_data(udp_sock) < 0)
{
close(udp_sock);
udp_sock = 0;
}
}
if (output_file)
{
fclose(output_file);
output_file = NULL;
}
if (sock >= 0) {
close(sock);
}
if (udp_sock != 0)
close(udp_sock);
g_free(buffer);
g_free(url);
pthread_exit(NULL);
return NULL; /* avoid compiler warning */
}
int flac_http_open(gchar * _url, guint64 _offset)
{
gchar *url;
url = g_strdup(_url);
rd_index = 0;
wr_index = 0;
buffer_length = flac_cfg.stream.http_buffer_size * 1024;
prebuffer_length = (buffer_length * flac_cfg.stream.http_prebuffer) / 100;
buffer_read = 0;
icy_metaint = 0;
prebuffering = TRUE;
going = TRUE;
eof = FALSE;
buffer = g_malloc(buffer_length);
offset = _offset;
pthread_create(&thread, NULL, http_buffer_loop, url);
return 0;
}
char *flac_http_get_title(char *url)
{
if (icy_name)
return g_strdup(icy_name);
if (g_basename(url) && strlen(g_basename(url)) > 0)
return g_strdup(g_basename(url));
return g_strdup(url);
}
/* Start UDP Channel specific stuff */
/* Find a good local udp port and bind udp_sock to it, return the port */
static int udp_establish_listener(int *sock)
{
struct sockaddr_in sin;
socklen_t sinlen = sizeof (struct sockaddr_in);
#ifdef DEBUG_UDP
fprintf (stderr,"Establishing udp listener\n");
#endif
if ((*sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
g_log(NULL, G_LOG_LEVEL_CRITICAL,
"udp_establish_listener(): unable to create socket");
return -1;
}
memset(&sin, 0, sinlen);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = g_htonl(INADDR_ANY);
if (bind(*sock, (struct sockaddr *)&sin, sinlen) < 0)
{
g_log(NULL, G_LOG_LEVEL_CRITICAL,
"udp_establish_listener(): Failed to bind socket to localhost: %s", strerror(errno));
close(*sock);
return -1;
}
if (fcntl(*sock, F_SETFL, O_NONBLOCK) < 0)
{
g_log(NULL, G_LOG_LEVEL_CRITICAL,
"udp_establish_listener(): Failed to set flags: %s", strerror(errno));
close(*sock);
return -1;
}
memset(&sin, 0, sinlen);
if (getsockname(*sock, (struct sockaddr *)&sin, &sinlen) < 0)
{
g_log(NULL, G_LOG_LEVEL_CRITICAL,
"udp_establish_listener(): Failed to retrieve socket info: %s", strerror(errno));
close(*sock);
return -1;
}
#ifdef DEBUG_UDP
fprintf (stderr,"Listening on local %s:%d\n", inet_ntoa(sin.sin_addr), g_ntohs(sin.sin_port));
#endif
return g_ntohs(sin.sin_port);
}
static int udp_check_for_data(int sock)
{
char buf[1025], **lines;
char *valptr;
gchar *title;
gint len, i;
struct sockaddr_in from;
socklen_t fromlen;
fromlen = sizeof(struct sockaddr_in);
if ((len = recvfrom(sock, buf, 1024, 0, (struct sockaddr *)&from, &fromlen)) < 0)
{
if (errno != EAGAIN)
{
g_log(NULL, G_LOG_LEVEL_CRITICAL,
"udp_read_data(): Error reading from socket: %s", strerror(errno));
return -1;
}
return 0;
}
buf[len] = '\0';
#ifdef DEBUG_UDP
fprintf (stderr,"Received: [%s]\n", buf);
#endif
lines = g_strsplit(buf, "\n", 0);
if (!lines)
return 0;
for (i = 0; lines[i]; i++)
{
while ((lines[i][strlen(lines[i]) - 1] == '\n') ||
(lines[i][strlen(lines[i]) - 1] == '\r'))
lines[i][strlen(lines[i]) - 1] = '\0';
valptr = strchr(lines[i], ':');
if (!valptr)
continue;
else
valptr++;
g_strstrip(valptr);
if (!strlen(valptr))
continue;
if (strstr(lines[i], "x-audiocast-streamtitle") != NULL)
{
title = g_strdup_printf ("%s (%s)", valptr, icy_name);
if (going)
set_track_info(title, -1);
g_free (title);
}
#if 0
else if (strstr(lines[i], "x-audiocast-streamlength") != NULL)
{
if (atoi(valptr) != -1)
set_track_info(NULL, atoi(valptr));
}
#endif
else if (strstr(lines[i], "x-audiocast-streammsg") != NULL)
{
/* set_track_info(title, -1); */
/* xmms_show_message(_("Message"), valptr, _("Ok"), */
/* FALSE, NULL, NULL); */
g_message("Stream_message: %s", valptr);
}
#if 0
/* Use this to direct your webbrowser.. yeah right.. */
else if (strstr(lines[i], "x-audiocast-streamurl") != NULL)
{
if (lasturl && g_strcmp (valptr, lasturl))
{
c_message (stderr, "Song URL: %s\n", valptr);
g_free (lasturl);
lasturl = g_strdup (valptr);
}
}
#endif
else if (strstr(lines[i], "x-audiocast-udpseqnr:") != NULL)
{
gchar obuf[60];
sprintf(obuf, "x-audiocast-ack: %ld \r\n", atol(valptr));
if (sendto(sock, obuf, strlen(obuf), 0, (struct sockaddr *) &from, fromlen) < 0)
{
g_log(NULL, G_LOG_LEVEL_WARNING,
"udp_check_for_data(): Unable to send ack to server: %s", strerror(errno));
}
#ifdef DEBUG_UDP
else
fprintf(stderr,"Sent ack: %s", obuf);
fprintf (stderr,"Remote: %s:%d\n", inet_ntoa(from.sin_addr), g_ntohs(from.sin_port));
#endif
}
}
g_strfreev(lines);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -