⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 http.c

📁 wince下著名的视频播放器源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  XMMS - Cross-platform multimedia player *  Copyright (C) 1998-2000  Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* modified for FLAC support by Steven Richman (2003) */#include <sys/types.h>#include <sys/socket.h>#include <sys/time.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <glib.h>#include <string.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <xmms/util.h>#include <xmms/plugin.h>#ifdef HAVE_CONFIG_H#include <config.h>#endif#include "configure.h"#include "plugin_common/locale_hack.h"#include "FLAC/format.h"#include "plugin.h"#ifndef HAVE_SOCKLEN_Ttypedef unsigned int socklen_t;#endif#define min(x,y) ((x)<(y)?(x):(y))#define min3(x,y,z) (min(x,y)<(z)?min(x,y):(z))#define min4(x,y,z,w) (min3(x,y,z)<(w)?min3(x,y,z):(w))static gchar *icy_name = NULL;static gint icy_metaint = 0;extern InputPlugin flac_ip;#undef DEBUG_UDP/* Static udp channel functions */static int udp_establish_listener (gint *sock);static int udp_check_for_data(gint sock);static char *flac_http_get_title(char *url);static gboolean prebuffering, going, eof = FALSE;static gint sock, rd_index, wr_index, buffer_length, prebuffer_length;static guint64 buffer_read = 0;static gchar *buffer;static guint64 offset;static pthread_t thread;static GtkWidget *error_dialog = NULL;static FILE *output_file = NULL;#define BASE64_LENGTH(len) (4 * (((len) + 2) / 3))/* Encode the string S of length LENGTH to base64 format and place it   to STORE.  STORE will be 0-terminated, and must point to a writable   buffer of at least 1+BASE64_LENGTH(length) bytes.  */static void base64_encode (const gchar *s, gchar *store, gint length){	/* Conversion table.  */	static gchar tbl[64] = {		'A','B','C','D','E','F','G','H',		'I','J','K','L','M','N','O','P',		'Q','R','S','T','U','V','W','X',		'Y','Z','a','b','c','d','e','f',		'g','h','i','j','k','l','m','n',		'o','p','q','r','s','t','u','v',		'w','x','y','z','0','1','2','3',		'4','5','6','7','8','9','+','/'	};	gint i;	guchar *p = (guchar *)store;	/* Transform the 3x8 bits to 4x6 bits, as required by base64.  */	for (i = 0; i < length; i += 3)	{		*p++ = tbl[s[0] >> 2];		*p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];		*p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];		*p++ = tbl[s[2] & 0x3f];		s += 3;	}	/* Pad the result if necessary...  */	if (i == length + 1)		*(p - 1) = '=';	else if (i == length + 2)		*(p - 1) = *(p - 2) = '=';	/* ...and zero-terminate it.  */	*p = '\0';}/* Create the authentication header contents for the `Basic' scheme.   This is done by encoding the string `USER:PASS' in base64 and   prepending `HEADER: Basic ' to it.  */static gchar *basic_authentication_encode (const gchar *user, const gchar *passwd, const gchar *header){	gchar *t1, *t2, *res;	gint len1 = strlen (user) + 1 + strlen (passwd);	gint len2 = BASE64_LENGTH (len1);	t1 = g_strdup_printf("%s:%s", user, passwd);	t2 = g_malloc0(len2 + 1);	base64_encode (t1, t2, len1);	res = g_strdup_printf("%s: Basic %s\r\n", header, t2);	g_free(t2);	g_free(t1);		return res;}static void parse_url(const gchar * url, gchar ** user, gchar ** pass, gchar ** host, int *port, gchar ** filename){	gchar *h, *p, *pt, *f, *temp, *ptr;	temp = g_strdup(url);	ptr = temp;	if (!strncasecmp("http://", ptr, 7))		ptr += 7;	h = strchr(ptr, '@');	f = strchr(ptr, '/');	if (h != NULL && (!f || h < f))	{		*h = '\0';		p = strchr(ptr, ':');		if (p != NULL && p < h)		{			*p = '\0';			p++;			*pass = g_strdup(p);		}		else			*pass = NULL;		*user = g_strdup(ptr);		h++;		ptr = h;	}	else	{		*user = NULL;		*pass = NULL;		h = ptr;	}	pt = strchr(ptr, ':');	if (pt != NULL && (f == NULL || pt < f))	{		*pt = '\0';		*port = atoi(pt + 1);	}	else	{		if (f)			*f = '\0';		*port = 80;	}	*host = g_strdup(h);		if (f)		*filename = g_strdup(f + 1);	else		*filename = NULL;	g_free(temp);}void flac_http_close(void){	going = FALSE;	pthread_join(thread, NULL);	g_free(icy_name);	icy_name = NULL;}static gint http_used(void){	if (wr_index >= rd_index)		return wr_index - rd_index;	return buffer_length - (rd_index - wr_index);}static gint http_free(void){	if (rd_index > wr_index)		return (rd_index - wr_index) - 1;	return (buffer_length - (wr_index - rd_index)) - 1;}static void http_wait_for_data(gint bytes){	while ((prebuffering || http_used() < bytes) && !eof && going)		xmms_usleep(10000);}static void show_error_message(gchar *error){	if(!error_dialog)	{		GDK_THREADS_ENTER();		error_dialog = xmms_show_message(_("Error"), error, _("Ok"), FALSE,						 NULL, NULL);		gtk_signal_connect(GTK_OBJECT(error_dialog),				   "destroy",				   GTK_SIGNAL_FUNC(gtk_widget_destroyed),				   &error_dialog);		GDK_THREADS_LEAVE();	}}int flac_http_read(gpointer data, gint length){	gint len, cnt, off = 0, meta_len, meta_off = 0, i;	gchar *meta_data, **tags, *temp, *title;	if (length > buffer_length) {		length = buffer_length;	}	http_wait_for_data(length);	if (!going)		return 0;	len = min(http_used(), length);	while (len && http_used())	{		if ((flac_cfg.stream.cast_title_streaming) && (icy_metaint > 0) && (buffer_read % icy_metaint) == 0 && (buffer_read > 0))		{			meta_len = *((guchar *) buffer + rd_index) * 16;			rd_index = (rd_index + 1) % buffer_length;			if (meta_len > 0)			{				http_wait_for_data(meta_len);				meta_data = g_malloc0(meta_len);				if (http_used() >= meta_len)				{					while (meta_len)					{						cnt = min(meta_len, buffer_length - rd_index);						memcpy(meta_data + meta_off, buffer + rd_index, cnt);						rd_index = (rd_index + cnt) % buffer_length;						meta_len -= cnt;						meta_off += cnt;					}					tags = g_strsplit(meta_data, "';", 0);					for (i = 0; tags[i]; i++)					{						if (!strncasecmp(tags[i], "StreamTitle=", 12))						{							temp = g_strdup(tags[i] + 13);							title = g_strdup_printf("%s (%s)", temp, icy_name);							set_track_info(title, -1);							g_free(title);							g_free(temp);						}					}					g_strfreev(tags);				}				g_free(meta_data);			}			if (!http_used())				http_wait_for_data(length - off);			cnt = min3(len, buffer_length - rd_index, http_used());		}		else if ((icy_metaint > 0) && (flac_cfg.stream.cast_title_streaming))			cnt = min4(len, buffer_length - rd_index, http_used(), icy_metaint - (gint) (buffer_read % icy_metaint));		else			cnt = min3(len, buffer_length - rd_index, http_used());		if (output_file)			fwrite(buffer + rd_index, 1, cnt, output_file);		memcpy((gchar *)data + off, buffer + rd_index, cnt);		rd_index = (rd_index + cnt) % buffer_length;		buffer_read += cnt;		len -= cnt;		off += cnt;	}	if (!off) {		fprintf(stderr, "returning zero\n");	}	return off;}static gboolean http_check_for_data(void){	fd_set set;	struct timeval tv;	gint ret;	tv.tv_sec = 0;	tv.tv_usec = 20000;	FD_ZERO(&set);	FD_SET(sock, &set);	ret = select(sock + 1, &set, NULL, NULL, &tv);	if (ret > 0)		return TRUE;	return FALSE;}gint flac_http_read_line(gchar * buf, gint size){	gint i = 0;	while (going && i < size - 1)	{		if (http_check_for_data())		{			if (read(sock, buf + i, 1) <= 0)				return -1;			if (buf[i] == '\n')				break;			if (buf[i] != '\r')				i++;		}	}	if (!going)		return -1;	buf[i] = '\0';	return i;}/* returns the file descriptor of the socket, or -1 on error */static int http_connect (gchar *url_, gboolean head, guint64 offset){	gchar line[1024], *user, *pass, *host, *filename,	     *status, *url, *temp, *file;	gchar *chost;	gint cnt, error, err_len, port, cport;	gboolean redirect;	int udp_sock = 0;	fd_set set;	struct hostent *hp;	struct sockaddr_in address;	struct timeval tv;	url = g_strdup (url_);	do	{		redirect=FALSE;			g_strstrip(url);		parse_url(url, &user, &pass, &host, &port, &filename);		if ((!filename || !*filename) && url[strlen(url) - 1] != '/')			temp = g_strconcat(url, "/", NULL);		else			temp = g_strdup(url);		g_free(url);		url = temp;		chost = flac_cfg.stream.use_proxy ? flac_cfg.stream.proxy_host : host;		cport = flac_cfg.stream.use_proxy ? flac_cfg.stream.proxy_port : port;		sock = socket(AF_INET, SOCK_STREAM, 0);		fcntl(sock, F_SETFL, O_NONBLOCK);		address.sin_family = AF_INET;		status = g_strdup_printf(_("LOOKING UP %s"), chost);		flac_ip.set_info_text(status);		g_free(status);		if (!(hp = gethostbyname(chost)))		{			status = g_strdup_printf(_("Couldn't look up host %s"), chost);			show_error_message(status);			g_free(status);			flac_ip.set_info_text(NULL);			eof = TRUE;		}		if (!eof)		{			memcpy(&address.sin_addr.s_addr, *(hp->h_addr_list), sizeof (address.sin_addr.s_addr));			address.sin_port = (gint) g_htons(cport);			status = g_strdup_printf(_("CONNECTING TO %s:%d"), chost, cport);			flac_ip.set_info_text(status);			g_free(status);			if (connect(sock, (struct sockaddr *) &address, sizeof (struct sockaddr_in)) == -1)			{				if (errno != EINPROGRESS)				{					status = g_strdup_printf(_("Couldn't connect to host %s"), chost);					show_error_message(status);					g_free(status);					flac_ip.set_info_text(NULL);					eof = TRUE;				}			}			while (going)			{				tv.tv_sec = 0;				tv.tv_usec = 10000;				FD_ZERO(&set);				FD_SET(sock, &set);				if (select(sock + 1, NULL, &set, NULL, &tv) > 0)				{					err_len = sizeof (error);					getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &err_len);					if (error)					{						status = g_strdup_printf(_("Couldn't connect to host %s"),									 chost);						show_error_message(status);						g_free(status);						flac_ip.set_info_text(NULL);						eof = TRUE;											}					break;				}			}			if (!eof)			{				gchar *auth = NULL, *proxy_auth = NULL;				gchar udpspace[30];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -