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

📄 tracker.c

📁 linux下bt下载C源码
💻 C
字号:
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <errno.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include "parse_metafile.h"
#include "peer.h"
#include "tracker.h"

extern unsigned char  info_hash[20];
extern unsigned char  peer_id[20];
extern Announce_list  *announce_list_head;

extern int                 *sock;
extern struct sockaddr_in  *tracker;
extern int                 *valid;
extern int                  tracker_count;

extern int                 *peer_sock;
extern struct sockaddr_in  *peer_addr;
extern int                 *peer_valid;
extern int                  peer_count;

Peer_addr  *peer_addr_head = NULL;

int http_encode(unsigned char *in,int len1,char *out,int len2)
{
	int  i, j;
	char hex_table[16] = "0123456789abcdef"; 
	
	if( (len1 != 20) || (len2 <= 90) )  return -1;
	for(i = 0, j = 0; i < 20; i++, j++) {
		if( isalpha(in[i]) || isdigit(in[i]) )
			out[j] = in[i];
		else { 
			out[j] = '%';
			j++;
			out[j] = hex_table[in[i] >> 4];
			j++;
			out[j] = hex_table[in[i] & 0xf];
		}
	}
	out[j] = '\0';
	
#ifdef DEBUG
	//printf("http encoded:%s\n",out);
#endif
	
	return 0;
}

int get_tracker_name(Announce_list *node,char *name,int len)
{
	int i = 0, j = 0;

	if( (len < 64) || (node == NULL) )  return -1;
	if( memcmp(node->announce,"http://",7) == 0 ) 
		i = i + 7;
	while( (node->announce[i] != '/') && (node->announce[i] != ':') ) {
		name[j] = node->announce[i];
		i++;
		j++;
		if( i == strlen(node->announce) )  break;
	}
	name[j] = '\0';

#ifdef DEBUG
	printf("%s\n",node->announce);
	printf("tracker name:%s\n",name);
#endif

	return 0;
}

int get_tracker_port(Announce_list *node,unsigned short *port)
{
	int i = 0;

	if( (node == NULL) || (port == NULL) )  return -1;
	if( memcmp(node->announce,"http://",7) == 0 )  i = i + 7;
	*port = 0;
	while( i < strlen(node->announce) ) {
		if( node->announce[i] != ':')   { i++; continue; }

		i++;  // skip ':'
		while( isdigit(node->announce[i]) ) { 
			*port =  *port * 10 + (node->announce[i] - '0');
			i++;
		}
		break;
	}
	if(*port == 0)  *port = 80;

#ifdef DEBUG
	printf("tracker port:%d\n",*port);
#endif

	return 0;
}

int create_request(char *request,int len,Announce_list *node,
				   unsigned short port,long long down,long long up,
				   long long left,int numwant)
{
	char           encoded_info_hash[100];
	char           encoded_peer_id[100];
	int            key;
	char           tracker_name[128];
	unsigned short tracker_port;

	http_encode(info_hash,20,encoded_info_hash,100);
	http_encode(peer_id,20,encoded_peer_id,100);

	srand(time(NULL));
	key = rand() / 10000;

	get_tracker_name(node,tracker_name,128);
	get_tracker_port(node,&tracker_port);

	sprintf(request,
	"GET /announce?info_hash=%s&peer_id=%s&port=%u"
	"&uploaded=%lld&downloaded=%lld&left=%lld"
	"&event=started&key=%d&compact=1&numwant=%d HTTP/1.0\r\n"
	"Host: %s\r\nUser-Agent: Bittorrent\r\nAccept: */*\r\n"
	"Accept-Encoding: gzip\r\nConnection: closed\r\n\r\n",
	encoded_info_hash,encoded_peer_id,port,up,down,left,
	key,numwant,tracker_name);

#ifdef DEBUG
	printf("request:%s\n",request);
#endif

	return 0;
}

int get_response_type(char *buffer,int len,int *total_length)
{
	int i, content_length = 0;

	for(i = 0; i < len-7; i++) {
		if(memcmp(&buffer[i],"5:peers",7) == 0) { 
			i = i+7;
			break; 
		}
	}
	if(i == len-7)        return -1;  // 返回的消息不含"5:peers"关键字
	if(buffer[i] != 'l')  return 0;   // 返回的消息的类型为第一种

	*total_length = 0;
	for(i = 0; i < len-16; i++) {
		if(memcmp(&buffer[i],"Content-Length: ",16) == 0) {
			i = i+16;
			break; 
		}
	}
	if(i != len-16) {
		while(isdigit(buffer[i])) {
			content_length = content_length * 10 + (buffer[i] - '0');
			i++;
		}
		for(i = 0; i < len-4; i++) {
			if(memcmp(&buffer[i],"\r\n\r\n",4) == 0)  { i = i+4; break; }
		}
		if(i != len-4)  *total_length = content_length + i;
	}

	if(*total_length == 0)  return -1;
	else return 1;
}

int prepare_connect_tracker(int *max_sockfd)
{
	int             i, flags, ret, count = 0;
	struct hostent  *ht;
	Announce_list   *p = announce_list_head;

	while(p != NULL)  { count++; p = p->next; }
	tracker_count = count;
	sock = (int *)malloc(count * sizeof(int));
	if(sock == NULL)  goto OUT;
	tracker = (struct sockaddr_in *)malloc(count * sizeof(struct sockaddr_in));
	if(tracker == NULL)  goto OUT;
	valid = (int *)malloc(count * sizeof(int));
	if(valid == NULL)  goto OUT;
	
	p = announce_list_head;
	for(i = 0; i < count; i++) {
		char            tracker_name[128];
		unsigned short  tracker_port = 0;
		
		sock[i] = socket(AF_INET,SOCK_STREAM,0);
		if(sock < 0) {
			printf("%s:%d socket create failed\n",__FILE__,__LINE__);
			valid[i] = 0;
			p = p->next;
			continue;
		}

		get_tracker_name(p,tracker_name,128);
		get_tracker_port(p,&tracker_port);
		
		// 从主机名获取IP地址
		ht = gethostbyname(tracker_name);
		if(ht == NULL) {
			printf("gethostbyname failed:%s\n",hstrerror(h_errno)); 
			valid[i] = 0;
		} else {
			memset(&tracker[i], 0, sizeof(struct sockaddr_in));
			memcpy(&tracker[i].sin_addr.s_addr, ht->h_addr_list[0], 4);
			tracker[i].sin_port = htons(tracker_port);
			tracker[i].sin_family = AF_INET;
			valid[i] = -1;
		}
		
		p = p->next;
	}

	for(i = 0; i < tracker_count; i++) {
		if(valid[i] != 0) {
			if(sock[i] > *max_sockfd) *max_sockfd = sock[i];
			// 设置套接字为非阻塞
			flags = fcntl(sock[i],F_GETFL,0);
			fcntl(sock[i],F_SETFL,flags|O_NONBLOCK);
			// 连接tracker
			ret = connect(sock[i],(struct sockaddr *)&tracker[i],
				          sizeof(struct sockaddr));
			if(ret < 0 && errno != EINPROGRESS)  valid[i] = 0;	
			// 如果返回0,说明连接已经建立
			if(ret == 0)  valid[i] = 1;  
		}
	}

	return 0;

OUT:
	if(sock != NULL)    free(sock);
	if(tracker != NULL) free(tracker);
	if(valid != NULL)   free(valid);
	return -1;
}

int prepare_connect_peer(int *max_sockfd)
{
	int       i, flags, ret, count = 0;
	Peer_addr *p;
	
	p = peer_addr_head;
	while(p != 0)  { count++; p = p->next; }

	peer_count = count;
	peer_sock = (int *)malloc(count*sizeof(int));
	if(peer_sock == NULL)  goto OUT;
	peer_addr = (struct sockaddr_in *)malloc(count*sizeof(struct sockaddr_in));
	if(peer_addr == NULL)  goto OUT;
	peer_valid = (int *)malloc(count*sizeof(int));
	if(peer_valid == NULL) goto OUT;
	
	p = peer_addr_head;  // 此处p重新赋值
	for(i = 0; i < count && p != NULL; i++) {
		peer_sock[i] = socket(AF_INET,SOCK_STREAM,0);
		if(peer_sock[i] < 0) { 
			printf("%s:%d socket create failed\n",__FILE__,__LINE__);
			valid[i] = 0;
			p = p->next;
			continue; 
		}

		memset(&peer_addr[i], 0, sizeof(struct sockaddr_in));
		peer_addr[i].sin_addr.s_addr = inet_addr(p->ip);
		peer_addr[i].sin_port = htons(p->port);
		peer_addr[i].sin_family = AF_INET;
		peer_valid[i] = -1;
		
		p = p->next;
	}
	count = i;
	
	for(i = 0; i < count; i++) {
		if(peer_sock[i] > *max_sockfd) *max_sockfd = peer_sock[i];
		// 设置套接字为非阻塞
		flags = fcntl(peer_sock[i],F_GETFL,0);
		fcntl(peer_sock[i],F_SETFL,flags|O_NONBLOCK);
		// 连接peer
		ret = connect(peer_sock[i],(struct sockaddr *)&peer_addr[i],
			          sizeof(struct sockaddr));
		if(ret < 0 && errno != EINPROGRESS)  peer_valid[i] = 0;
		// 如果返回0,说明连接已经建立
		if(ret == 0)  peer_valid[i] = 1;
	}
	
	free_peer_addr_head();
	return 0;

OUT:
	if(peer_sock  != NULL)  free(peer_sock);
	if(peer_addr  != NULL)  free(peer_addr);
	if(peer_valid != NULL)  free(peer_valid);
	return -1;
}

int parse_tracker_response1(char *buffer,int ret,char *redirection,int len)
{
	int           i, j, count = 0;
	unsigned char c[4];
	Peer_addr     *node, *p;

	for(i = 0; i < ret - 10; i++) {
		if(memcmp(&buffer[i],"Location: ",10) == 0) { 
			i = i + 10;
			j = 0;
			while(buffer[i]!='?' && i<ret && j<len) {
				redirection[j] = buffer[i];
				i++;
				j++;
			}
			redirection[j] = '\0';
			return 1;
		}
	}

	// 获取返回的peer数,关键词"5:peers"之后为各个Peer的IP和端口
	for(i = 0; i < ret - 7; i++) {
		if(memcmp(&buffer[i],"5:peers",7) == 0) { i = i + 7; break; }
	}
	if(i == ret - 7	) { 
		printf("%s:%d can not find keyword 5:peers \n",__FILE__,__LINE__);
		return -1; 
	}
	while( isdigit(buffer[i]) ) {
		count = count * 10 + (buffer[i] - '0');
		i++;
	}
	i++;  // 跳过":"

	count = (ret - i) / 6;
		
	// 将每个peer的IP和端口保存到peer_addr_head指向的链表中
	for(; count != 0; count--) {
		node = (Peer_addr*)malloc(sizeof(Peer_addr));
		c[0] = buffer[i];   c[1] = buffer[i+1]; 
		c[2] = buffer[i+2]; c[3] = buffer[i+3];
		sprintf(node->ip,"%u.%u.%u.%u",c[0],c[1],c[2],c[3]);
		i += 4;
		node->port = ntohs(*(unsigned short*)&buffer[i]);
		i += 2;
		node->next = NULL;
	
		// 判断当前peer是否已经存在于链表中
		p = peer_addr_head;
		while(p != NULL) {
			if( memcmp(node->ip,p->ip,strlen(node->ip)) == 0 ) { 
				free(node); 
				break;
			}
			p = p->next;
		}
			
		// 将当前结点添加到链表中
		if(p == NULL) {
			if(peer_addr_head == NULL)
				peer_addr_head = node;
			else {
				p = peer_addr_head;
				while(p->next != NULL) p = p->next;
				p->next = node;
			}
		}
	}
		
#ifdef DEBUG
		count = 0;
		p = peer_addr_head;
		while(p != NULL) {
			printf("+++ connecting peer %-16s:%-5d +++ \n",p->ip,p->port);
			p = p->next;
			count++;
		}
		printf("peer count is :%d \n",count);
#endif

		return 0;
}

int parse_tracker_response2(char *buffer,int ret)
{
	int        i, ip_len, port;
	Peer_addr  *node = NULL, *p = peer_addr_head;

	if(peer_addr_head != NULL) {
		printf("Must free peer_addr_head\n");
		return -1;
	}
	
	for(i = 0; i < ret; i++) {
		if(memcmp(&buffer[i],"2:ip",4) == 0) {
			i += 4;
			ip_len = 0;
			while(isdigit(buffer[i])) {
				ip_len = ip_len * 10 + (buffer[i] - '0');
				i++;
			}
			i++;  // skip ":"
			node = (Peer_addr*)malloc(sizeof(Peer_addr));
			if(node == NULL) { 
				printf("%s:%d error",__FILE__,__LINE__); 
				continue;
			}
			memcpy(node->ip,&buffer[i],ip_len);
			(node->ip)[ip_len] = '\0';
			node->next = NULL;
		}
		if(memcmp(&buffer[i],"4:port",6) == 0) {
			i += 6;
			i++;  // skip "i"
			port = 0;
			while(isdigit(buffer[i])) {
				port = port * 10 + (buffer[i] - '0');
				i++;
			}
			if(node != NULL)  node->port = port;
			else continue;
			
			printf("+++ add a peer %-16s:%-5d +++ \n",node->ip,node->port);
			
			if(p == peer_addr_head) { peer_addr_head = node; p = node; }
			else p->next = node;
			node = NULL;
		}
	}
	
	return 0;
}

int add_peer_node_to_peerlist(int *sock,struct sockaddr_in saptr)
{
	Peer *node;
	
	node = add_peer_node();
	if(node == NULL)  return -1;
	
	node->socket = *sock;
	node->port   = ntohs(saptr.sin_port);
	node->state  = INITIAL;
	strcpy(node->ip,inet_ntoa(saptr.sin_addr));
	node->start_timestamp = time(NULL);

	return 0;
}

void free_peer_addr_head()
{
	Peer_addr *p = peer_addr_head;
    while(p != NULL) {
		p = p->next;
		free(peer_addr_head);
		peer_addr_head = p;
    }
	peer_addr_head = NULL;
}

⌨️ 快捷键说明

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