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

📄 downloads.c

📁 linux下支持P2P的客户端程序,采用了Gnutella的方法,其中有实现Gnutella的具体源码,是一个基于p2p环境下的音乐共享软件,有助于对P2P的研究
💻 C
字号:
/*-*-linux-c-*-*/#include <stdlib.h>#include <time.h> #include <fcntl.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/socket.h>#include <netinet/in.h>#include <string.h>#include <gtk/gtk.h>#include "newtella.h"#include "connection.h"#include "gui.h"#include "gnutella.h"#include "hosts.h"#include "downloads.h"#include "http.h"#include "file.h"/* General functions for Download connections */int download_write(gpointer gdata, gint s, GdkInputCondition cond){	struct newtella_connection *dcon = (struct newtella_connection *)gdata;	struct gpacket *packet;	gint r;	if (cond == GDK_INPUT_EXCEPTION) {		download_stop(dcon, "Failed at sending HTTP headers"); 		return -1;	}	if (g_list_length(dcon->queue)) {		packet = (struct gpacket *) g_list_last(dcon->queue)->data;		r = send(dcon->s, packet->data, packet->len, 0);		if (r != packet->len) 			download_stop(dcon, "Failed at sending HTTP headers");			dcon->queue = g_list_remove(dcon->queue, packet);		newtella_free(packet->data);		newtella_free(packet);				gdk_input_remove(dcon->write_tag);	}       	return 1;}int download_read(gpointer gdata, gint s, GdkInputCondition cond){	struct newtella_connection *dcon = (struct newtella_connection *)gdata;	struct http_header *http;		gchar *save_file; 	gchar  servent_info[1024];	gint   bytes_to_read, bytes_readed, http_skip, http_size;		if (cond == GDK_INPUT_EXCEPTION) {		download_stop(dcon, "Failed to read!");		return -1;	}				bytes_to_read = bytes_avail(dcon->s);		if (!bytes_to_read) {		if (dcon->total_handled == dcon->fi->size)			dcon->state = GS_COMPLETE;		else {			dcon->state = GS_FAILED;			download_stop(dcon, "Failed to read!");			return -1;		}		gui_update_download(dcon);		return -1;	}	dcon->b = dcon->buffer + dcon->buffer_len;	bytes_readed = con_recv_packet(dcon, bytes_to_read);		if (bytes_readed != bytes_to_read) {		download_stop(dcon, "Failed to read!");		return -1;	}	dcon->buffer_len += bytes_readed;        if (dcon->hs_sent) {		write(dcon->fi->des, dcon->buffer, bytes_readed);		dcon->total_handled += bytes_readed;		con_reset_buffer(dcon);		gui_update_download(dcon);	} else {		/* parse the http headers */		do { 			http_size = http_header_size(dcon->buffer);						if (!http_size)				break;			http = newtella_malloc(http_size);			if (!memcmp("GIV", dcon->buffer, 3)) {			      				con_reset_buffer(dcon);								http->func = HTTP_GET;				http->user_agent = GNEWTELLIUM;				http->connection = "Keep-Alive";				http->file_name = dcon->fi->file_name;				http->file_index = dcon->fi->index;				http->range_start = 0;									dcon->write_tag = 					gdk_input_add(dcon->s, 						      GDK_INPUT_WRITE | GDK_INPUT_EXCEPTION,						      (GdkInputFunction) download_write, 						      (gpointer)dcon);				con_send_packet(dcon, http_header_build(http), 						strlen(http_header_build(http)), 0);				return 1;			}			//g_print("***Got Response: %s\n", dcon->buffer);			http = http_header_parse(dcon->buffer);			/* GUI update */			if (http->user_agent) {				gint row;				g_snprintf(servent_info, sizeof(servent_info), 					   "%s:%d (%s)", ip2str(dcon->fi->ip), 					   dcon->fi->port, http->user_agent);				row = gtk_clist_find_row_from_data(GTK_CLIST(download_list),								   (gpointer) dcon);				gtk_clist_set_text(GTK_CLIST(download_list), row, 4, servent_info);			}			if (http->valid && (http->code == 200 || http->code == 206)) {				save_file = newtella_malloc(strlen(gl_options->download_dir)+							    strlen(dcon->fi->file_name)+1); 				strcpy(save_file, gl_options->download_dir);				strcat(save_file, dcon->fi->file_name);			        				if (!http->range_start)					dcon->fi->des = open(save_file, 							     O_WRONLY | O_CREAT | O_TRUNC,							     0644);				else {					gui_update_download_status(dcon, "Resuming");					dcon->fi->des = open(save_file,							     O_WRONLY,							     0644);					lseek(dcon->fi->des, http->range_start, SEEK_SET);				}				newtella_free(save_file);												/* cut the HTTP header */				http_skip = bytes_readed - http_size;				write(dcon->fi->des, dcon->buffer+http_size, http_skip);				dcon->total_handled = http->range_start - http_skip;				con_reset_buffer(dcon);							dcon->hs_sent = 1;				dcon->state = GS_CONNECTED;			} else {				switch (http->code) {				case 404:					dcon->state = GS_NOTFOUND;					break;				case 503:					dcon->state = GS_BUSY;					break;				default:					dcon->state = GS_FAILED;					break;				}								download_stop(dcon, NULL);				break;			}												} while (!dcon->hs_sent);	}			return 1;}int download_accept(gpointer data, gint source, GdkInputCondition cond){	struct sockaddr_in addr;	size_t len;	struct newtella_connection *dcon =  data;	int rval = accept(dcon->s, (struct sockaddr *) &addr, &len);	if (rval == -1)		printf("Can't accept\n");			dcon->s = rval;	gdk_input_remove(dcon->read_tag);	dcon->read_tag = gdk_input_add(dcon->s, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, 					(GdkInputFunction) download_read, (gpointer)dcon);	return 1;}int download_add(struct file_found *download_file){	struct newtella_connection *dcon = newtella_malloc(sizeof(struct newtella_connection));	gint resume;	/* copy the file info */	dcon->fi = newtella_malloc(sizeof *(dcon->fi));	*(dcon->fi) = *download_file;	dcon->ip = gl_my_host_info->ip;	con_zero_stats(dcon);	con_init_queue(dcon);		dcon->hs_sent = 0;	if (gl_options->dcons == 1)		gl_down_con = g_list_append(NULL, dcon);	else		gl_down_con = g_list_append(gl_down_con, dcon);	gui_add_download(dcon);	resume = file_get_size(dcon->fi->file_name, gl_options->download_dir);	download_start(dcon, resume);		return 1;}void download_resume(struct newtella_connection *dcon){	gint resume;	dcon->state = GS_RESUME;	gui_update_download_status(dcon, "Trying to resume...");	con_reset_buffer(dcon);	con_zero_stats(dcon);	con_init_queue(dcon);		dcon->hs_sent = 0;		resume = file_get_size(dcon->fi->file_name, gl_options->download_dir);	download_start(dcon, resume);}int download_start(struct newtella_connection *dcon, gint resume){	struct sockaddr_in gnode, addr;	size_t option;	struct http_header *http = newtella_malloc(sizeof(struct http_header));	if (!dcon->fi->push) {		/* direct connection */		dcon->state = GS_WAITINGCONNECT;		dcon->s = newtella_force_connect(dcon->fi->ip, dcon->fi->port);			if (dcon->s == -1) {			perror("connect");			dcon->state = GS_FAILED;			return (-1);		}				setsockopt(dcon->s, SOL_SOCKET, SO_KEEPALIVE, (void *) &option, sizeof(option));		setsockopt(dcon->s, SOL_SOCKET, SO_REUSEADDR, (void *) &option, sizeof(option));						dcon->read_tag = gdk_input_add(dcon->s, GDK_INPUT_READ | GDK_INPUT_EXCEPTION, 			      (GdkInputFunction) download_read, (gpointer)dcon);			dcon->write_tag = gdk_input_add(dcon->s, GDK_INPUT_WRITE | GDK_INPUT_EXCEPTION, 			      (GdkInputFunction) download_write, (gpointer)dcon);			      			http->func = HTTP_GET;		http->user_agent = GNEWTELLIUM;		http->connection = "Keep-Alive";		http->file_name = dcon->fi->file_name;		http->file_index = dcon->fi->index;		http->range_start = resume;		http->range_end = dcon->fi->size;		//g_print("***Sending %s\n", http_header_build(http));		con_send_packet(dcon, http_header_build(http), 				strlen(http_header_build(http)), 0);	} else {		/* firewall - send a push */		dcon->state = GS_WAITINGPUSH;		gui_update_download(dcon);		dcon->s = socket(AF_INET, SOCK_STREAM, 0);			if (fcntl(dcon->s, F_SETFL, O_NONBLOCK) == -1) {			perror("fcntl");			exit(EXIT_FAILURE);		}		gnode.sin_family = AF_INET;		gnode.sin_addr.s_addr = htonl(INADDR_ANY);		gnode.sin_port = htons(0);		bind(dcon->s, (struct sockaddr *)&gnode, sizeof(gnode));		if (listen(dcon->s, 1) == -1)			printf("Can't listen\n");				/* get the port number */		option = sizeof(struct sockaddr_in);			if (getsockname(dcon->s, (struct sockaddr *) &addr, &option) == -1)        		printf("Can't getsockname\n");				dcon->port = ntohs(addr.sin_port);			gnutella_send_push(dcon);				dcon->read_tag = gdk_input_add(dcon->s, GDK_INPUT_READ | GDK_INPUT_EXCEPTION,					(GdkInputFunction) download_accept, (gpointer) dcon);	}		/* update time */	dcon->last_time = time((time_t)NULL);		return 1;}int download_stop(struct newtella_connection *dcon, const gchar *reason){	if (dcon->read_tag)		gdk_input_remove(dcon->read_tag);	close(dcon->s);		/* close the downloaded file */	if (dcon->fi->des)		close(dcon->fi->des);	gui_update_download(dcon);		if (reason)		gui_update_download_status(dcon, reason);	dcon->state = GS_STOPPED;	return 1;}int download_kill(struct newtella_connection *dcon){	if (dcon->state != GS_STOPPED)		download_stop(dcon, "Killed");	gl_down_con = g_list_remove(gl_down_con, dcon);       	gui_remove_download(dcon);	newtella_free(dcon->fi);	newtella_free(dcon);	return 1;}

⌨️ 快捷键说明

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