📄 message.c
字号:
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <sys/socket.h>
#include "parse_metafile.h"
#include "bitfield.h"
#include "peer.h"
#include "data.h"
#include "policy.h"
#include "message.h"
#define HANDSHAKE -2
#define KEEP_ALIVE -1
#define CHOKE 0
#define UNCHOKE 1
#define INTERESTED 2
#define UNINTERESTED 3
#define HAVE 4
#define BITFIELD 5
#define REQUEST 6
#define PIECE 7
#define CANCEL 8
#define PORT 9
#define KEEP_ALIVE_TIME 45
extern Bitmap *bitmap;
extern char info_hash[20];
extern char peer_id[20];
extern int have_piece_index[64];
extern Peer *peer_head;
int int_to_char(int i, unsigned char c[4])
{
c[3] = i%256;
c[2] = (i-c[3])/256%256;
c[1] = (i-c[3]-c[2]*256)/256/256%256;
c[0] = (i-c[3]-c[2]*256-c[1]*256*256)/256/256/256%256;
return 0;
}
int char_to_int(unsigned char c[4])
{
int i;
i = c[0]*256*256*256 + c[1]*256*256 + c[2]*256 + c[3];
return i;
}
int create_handshake_msg(char *info_hash,char *peer_id,Peer *peer)
{
int i;
unsigned char keyword[20] = "BitTorrent protocol", c = 0x00;
unsigned char *buffer = peer->out_msg + peer->msg_len;
int len = MSG_SIZE - peer->msg_len;
if(len < 68) return -1; // 68为握手消息的固定长度
buffer[0] = 19;
for(i = 0; i < 19; i++) buffer[i+1] = keyword[i];
for(i = 0; i < 8; i++) buffer[i+20] = c;
for(i = 0; i < 20; i++) buffer[i+28] = info_hash[i];
for(i = 0; i < 20; i++) buffer[i+48] = peer_id[i];
peer->msg_len += 68;
return 0;
}
int create_keep_alive_msg(Peer *peer)
{
unsigned char *buffer = peer->out_msg + peer->msg_len;
int len = MSG_SIZE - peer->msg_len;
if(len < 4) return -1; // 4为keep_alive消息的固定长度
memset(buffer,0,4);
peer->msg_len += 4;
return 0;
}
int create_chock_interested_msg(int type,Peer *peer)
{
unsigned char *buffer = peer->out_msg + peer->msg_len;
int len = MSG_SIZE - peer->msg_len;
// 5为choke、unchoke、interested、uninterested消息的固定长度
if(len < 5) return -1;
memset(buffer,0,5);
buffer[3] = 1;
buffer[4] = type;
peer->msg_len += 5;
return 0;
}
int create_have_msg(int index,Peer *peer)
{
unsigned char *buffer = peer->out_msg + peer->msg_len;
int len = MSG_SIZE - peer->msg_len;
unsigned char c[4];
if(len < 9) return -1; // 9为have消息的固定长度
memset(buffer,0,9);
buffer[3] = 5;
buffer[4] = 4;
int_to_char(index,c);
buffer[5] = c[0];
buffer[6] = c[1];
buffer[7] = c[2];
buffer[8] = c[3];
peer->msg_len += 9;
return 0;
}
int create_bitfield_msg(char *bitfield,int bitfield_len,Peer *peer)
{
int i;
unsigned char c[4];
unsigned char *buffer = peer->out_msg + peer->msg_len;
int len = MSG_SIZE - peer->msg_len;
if( len < bitfield_len+5 ) { // bitfield消息的长度为bitfield_len+5
printf("%s:%d buffer too small\n",__FILE__,__LINE__);
return -1;
}
int_to_char(bitfield_len+1,c);
for(i = 0; i < 4; i++) buffer[i] = c[i];
buffer[4] = 5;
for(i = 0; i < bitfield_len; i++) buffer[i+5] = bitfield[i];
peer->msg_len += bitfield_len+5;
return 0;
}
int create_request_msg(int index,int begin,int length,Peer *peer)
{
int i;
unsigned char c[4];
unsigned char *buffer = peer->out_msg + peer->msg_len;
int len = MSG_SIZE - peer->msg_len;
if(len < 17) return -1; // 17为request消息的固定长度
memset(buffer,0,17);
buffer[3] = 13;
buffer[4] = 6;
int_to_char(index,c);
for(i = 0; i < 4; i++) buffer[i+5] = c[i];
int_to_char(begin,c);
for(i = 0; i < 4; i++) buffer[i+9] = c[i];
int_to_char(length,c);
for(i = 0; i < 4; i++) buffer[i+13] = c[i];
peer->msg_len += 17;
return 0;
}
int create_piece_msg(int index,int begin,char *block,int b_len,Peer *peer)
{
int i;
unsigned char c[4];
unsigned char *buffer = peer->out_msg + peer->msg_len;
int len = MSG_SIZE - peer->msg_len;
if( len < b_len+13 ) { // piece消息的长度为b_len+13
printf("IP:%s len:%d\n",peer->ip,len);
printf("%s:%d buffer too small\n",__FILE__,__LINE__);
return -1;
}
int_to_char(b_len+9,c);
for(i = 0; i < 4; i++) buffer[i] = c[i];
buffer[4] = 7;
int_to_char(index,c);
for(i = 0; i < 4; i++) buffer[i+5] = c[i];
int_to_char(begin,c);
for(i = 0; i < 4; i++) buffer[i+9] = c[i];
for(i = 0; i < b_len; i++) buffer[i+13] = block[i];
peer->msg_len += b_len+13;
return 0;
}
int create_cancel_msg(int index,int begin,int length,Peer *peer)
{
int i;
unsigned char c[4];
unsigned char *buffer = peer->out_msg + peer->msg_len;
int len = MSG_SIZE - peer->msg_len;
if(len < 17) return -1; // 17为cancel消息的固定长度
memset(buffer,0,17);
buffer[3] = 13;
buffer[4] = 8;
int_to_char(index,c);
for(i = 0; i < 4; i++) buffer[i+5] = c[i];
int_to_char(begin,c);
for(i = 0; i < 4; i++) buffer[i+9] = c[i];
int_to_char(length,c);
for(i = 0; i < 4; i++) buffer[i+13] = c[i];
peer->msg_len += 17;
return 0;
}
int create_port_msg(int port,Peer *peer)
{
unsigned char c[4];
unsigned char *buffer = peer->out_msg + peer->msg_len;
int len = MSG_SIZE - peer->msg_len;
if( len < 7) return 0; // 7为port消息的固定长度
memset(buffer,0,7);
buffer[3] = 3;
buffer[4] = 9;
int_to_char(port,c);
buffer[5] = c[2];
buffer[6] = c[3];
peer->msg_len += 7;
return 0;
}
// 以十六进制的形式打印消息的内容,用于调试
int print_msg_buffer(unsigned char *buffer, int len)
{
int i;
for(i = 0; i < len; i++) {
printf("%.2x ",buffer[i]);
if( (i+1) % 16 == 0 ) printf("\n");
}
printf("\n");
return 0;
}
// 判断缓冲区中是否存放了一条完整的消息
int is_complete_message(unsigned char *buff,unsigned int len,int *ok_len)
{
unsigned int i;
char btkeyword[20];
unsigned char keep_alive[4] = { 0x0, 0x0, 0x0, 0x0 };
unsigned char chocke[5] = { 0x0, 0x0, 0x0, 0x1, 0x0};
unsigned char unchocke[5] = { 0x0, 0x0, 0x0, 0x1, 0x1};
unsigned char interested[5] = { 0x0, 0x0, 0x0, 0x1, 0x2};
unsigned char uninterested[5] = { 0x0, 0x0, 0x0, 0x1, 0x3};
unsigned char have[5] = { 0x0, 0x0, 0x0, 0x5, 0x4};
unsigned char request[5] = { 0x0, 0x0, 0x0, 0xd, 0x6};
unsigned char cancel[5] = { 0x0, 0x0, 0x0, 0xd, 0x8};
unsigned char port[5] = { 0x0, 0x0, 0x0, 0x3, 0x9};
if(buff==NULL || len<=0 || ok_len==NULL) return -1;
*ok_len = 0;
btkeyword[0] = 19;
memcpy(&btkeyword[1],"BitTorrent protocol",19); // BitTorrent协议关键字
unsigned char c[4];
unsigned int length;
for(i = 0; i < len; ) {
// 握手、chocke、have等消息的长度是固定的
if( i+68<=len && memcmp(&buff[i],btkeyword,20)==0 ) i += 68;
else if( i+4 <=len && memcmp(&buff[i],keep_alive,4)==0 ) i += 4;
else if( i+5 <=len && memcmp(&buff[i],chocke,5)==0 ) i += 5;
else if( i+5 <=len && memcmp(&buff[i],unchocke,5)==0 ) i += 5;
else if( i+5 <=len && memcmp(&buff[i],interested,5)==0 ) i += 5;
else if( i+5 <=len && memcmp(&buff[i],uninterested,5)==0 ) i += 5;
else if( i+9 <=len && memcmp(&buff[i],have,5)==0 ) i += 9;
else if( i+17<=len && memcmp(&buff[i],request,5)==0 ) i += 17;
else if( i+17<=len && memcmp(&buff[i],cancel,5)==0 ) i += 17;
else if( i+7 <=len && memcmp(&buff[i],port,5)==0 ) i += 7;
// bitfield消息的长度是变化的
else if( i+5 <=len && buff[i+4]==5 ) {
c[0] = buff[i]; c[1] = buff[i+1];
c[2] = buff[i+2]; c[3] = buff[i+3];
length = char_to_int(c);
// 消息长度占4字节,消息本身占length个字节
if( i+4+length <= len ) i += 4+length;
else { *ok_len = i; return -1; }
}
// piece消息的长度也是变化的
else if( i+5 <=len && buff[i+4]==7 ) {
c[0] = buff[i]; c[1] = buff[i+1];
c[2] = buff[i+2]; c[3] = buff[i+3];
length = char_to_int(c);
// 消息长度占4字节,消息本身占length个字节
if( i+4+length <= len ) i += 4+length;
else { *ok_len = i; return -1; }
}
else {
// 处理未知类型的消息
if(i+4 <= len) {
c[0] = buff[i]; c[1] = buff[i+1];
c[2] = buff[i+2]; c[3] = buff[i+3];
length = char_to_int(c);
// 消息长度占4字节,消息本身占length个字节
if(i+4+length <= len) { i += 4+length; continue; }
else { *ok_len = i; return -1; }
}
// 如果也不是未知消息类型,则认为目前接收的数据还不是一个完整的消息
*ok_len = i;
return -1;
}
}
*ok_len = i;
return 1;
}
int process_handshake_msg(Peer *peer,unsigned char *buff,int len)
{
if(peer==NULL || buff==NULL) return -1;
if(memcmp(info_hash,buff+28,20) != 0) {
peer->state = CLOSING;
// 丢弃发送缓冲区中的数据
discard_send_buffer(peer);
clear_btcache_before_peer_close(peer);
close(peer->socket);
return -1;
}
memcpy(peer->id,buff+48,20);
(peer->id)[20] = '\0';
if(peer->state == INITIAL) {
peer->state = HANDSHAKED;
create_handshake_msg(info_hash,peer_id,peer);
}
if(peer->state == HALFSHAKED) peer->state = HANDSHAKED;
peer->start_timestamp = time(NULL);
return 0;
}
int process_keep_alive_msg(Peer *peer,unsigned char *buff,int len)
{
if(peer==NULL || buff==NULL) return -1;
peer->start_timestamp = time(NULL);
return 0;
}
int process_choke_msg(Peer *peer,unsigned char *buff,int len)
{
if(peer==NULL || buff==NULL) return -1;
if( peer->state!=CLOSING && peer->peer_choking==0 ) {
peer->peer_choking = 1;
peer->last_down_timestamp = 0;
peer->down_count = 0;
peer->down_rate = 0;
}
peer->start_timestamp = time(NULL);
return 0;
}
int process_unchoke_msg(Peer *peer,unsigned char *buff,int len)
{
if(peer==NULL || buff==NULL) return -1;
if( peer->state!=CLOSING && peer->peer_choking==1 ) {
peer->peer_choking = 0;
if(peer->am_interested == 1) create_req_slice_msg(peer);
else {
peer->am_interested = is_interested(&(peer->bitmap), bitmap);
if(peer->am_interested == 1) create_req_slice_msg(peer);
else printf("Received unchoke but Not interested to IP:%s \n",peer->ip);
}
peer->last_down_timestamp = 0;
peer->down_count = 0;
peer->down_rate = 0;
}
peer->start_timestamp = time(NULL);
return 0;
}
int process_interested_msg(Peer *peer,unsigned char *buff,int len)
{
if(peer==NULL || buff==NULL) return -1;
if( peer->state!=CLOSING && peer->state==DATA ) {
peer->peer_interested = is_interested(bitmap, &(peer->bitmap));
if(peer->peer_interested == 0) return -1;
if(peer->am_choking == 0) create_chock_interested_msg(1,peer);
}
peer->start_timestamp = time(NULL);
return 0;
}
int process_uninterested_msg(Peer *peer,unsigned char *buff,int len)
{
if(peer==NULL || buff==NULL) return -1;
if( peer->state!=CLOSING && peer->state==DATA ) {
peer->peer_interested = 0;
cancel_requested_list(peer);
}
peer->start_timestamp = time(NULL);
return 0;
}
int process_have_msg(Peer *peer,unsigned char *buff,int len)
{
int rand_num;
unsigned char c[4];
if(peer==NULL || buff==NULL) return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -