📄 message.c
字号:
srand(time(NULL));
rand_num = rand() % 3;
if( peer->state!=CLOSING && peer->state==DATA ) {
c[0] = buff[5]; c[1] = buff[6];
c[2] = buff[7]; c[3] = buff[8];
if(peer->bitmap.bitfield != NULL)
set_bit_value(&(peer->bitmap),char_to_int(c),1);
if(peer->am_interested == 0) {
peer->am_interested = is_interested(&(peer->bitmap), bitmap);
// 由原来的对peer不感兴趣变为感兴趣时,发interested消息
if(peer->am_interested == 1) create_chock_interested_msg(2,peer);
} else { // 收到三个have则发一个interested消息
if(rand_num == 0) create_chock_interested_msg(2,peer);
}
}
peer->start_timestamp = time(NULL);
return 0;
}
int process_cancel_msg(Peer *peer,unsigned char *buff,int len)
{
unsigned char c[4];
int index, begin, length;
if(peer==NULL || buff==NULL) return -1;
c[0] = buff[5]; c[1] = buff[6];
c[2] = buff[7]; c[3] = buff[8];
index = char_to_int(c);
c[0] = buff[9]; c[1] = buff[10];
c[2] = buff[11]; c[3] = buff[12];
begin = char_to_int(c);
c[0] = buff[13]; c[1] = buff[14];
c[2] = buff[15]; c[3] = buff[16];
length = char_to_int(c);
Request_piece *p, *q;
p = q = peer->Requested_piece_head;
while(p != NULL) {
if( p->index==index && p->begin==begin && p->length==length ) {
if(p == peer->Requested_piece_head)
peer->Requested_piece_head = p->next;
else
q->next = p->next;
free(p);
break;
}
q = p;
p = p->next;
}
peer->start_timestamp = time(NULL);
return 0;
}
int process_bitfield_msg(Peer *peer,unsigned char *buff,int len)
{
unsigned char c[4];
if(peer==NULL || buff==NULL) return -1;
if(peer->state==HANDSHAKED || peer->state==SENDBITFIELD) {
c[0] = buff[0]; c[1] = buff[1];
c[2] = buff[2]; c[3] = buff[3];
if( peer->bitmap.bitfield != NULL ) {
free(peer->bitmap.bitfield);
peer->bitmap.bitfield = NULL;
}
peer->bitmap.valid_length = bitmap->valid_length;
if(bitmap->bitfield_length != char_to_int(c)-1) {
peer->state = CLOSING;
// 丢弃发送缓冲区中的数据
discard_send_buffer(peer);
clear_btcache_before_peer_close(peer);
close(peer->socket);
return -1;
}
peer->bitmap.bitfield_length = char_to_int(c) - 1;
peer->bitmap.bitfield =
(unsigned char *)malloc(peer->bitmap.bitfield_length);
memcpy(peer->bitmap.bitfield,&buff[5],peer->bitmap.bitfield_length);
// 如果原状态为已握手,收到位图后应该向peer发位图
if(peer->state == HANDSHAKED) {
create_bitfield_msg(bitmap->bitfield,bitmap->bitfield_length,peer);
peer->state = DATA;
}
// 如果原状态为已发送位图,收到位图后可以准备交换数据
if(peer->state == SENDBITFIELD) {
peer->state = DATA;
}
// 判断peer是否对我们感兴趣
peer->peer_interested = is_interested(bitmap,&(peer->bitmap));
// 判断对peer是否感兴趣,若是则发送interested消息
peer->am_interested = is_interested(&(peer->bitmap), bitmap);
if(peer->am_interested == 1) create_chock_interested_msg(2,peer);
}
peer->start_timestamp = time(NULL);
return 0;
}
int process_request_msg(Peer *peer,unsigned char *buff,int len)
{
unsigned char c[4];
int index, begin, length;
Request_piece *request_piece, *p;
if(peer==NULL || buff==NULL) return -1;
if(peer->am_choking==0 && peer->peer_interested==1) {
c[0] = buff[5]; c[1] = buff[6];
c[2] = buff[7]; c[3] = buff[8];
index = char_to_int(c);
c[0] = buff[9]; c[1] = buff[10];
c[2] = buff[11]; c[3] = buff[12];
begin = char_to_int(c);
c[0] = buff[13]; c[1] = buff[14];
c[2] = buff[15]; c[3] = buff[16];
length = char_to_int(c);
// 错误的slice请求
if( begin%(16*1024) != 0 ) {
return 0;
}
// 查看该请求是否已存在,若已存在,则不进行处理
p = peer->Requested_piece_head;
while(p != NULL) {
if(p->index==index && p->begin==begin && p->length==length) {
break;
}
p = p->next;
}
if(p != NULL) return 0;
// 将请求加入到请求队列中
request_piece = (Request_piece *)malloc(sizeof(Request_piece));
if(request_piece == NULL) {
printf("%s:%d error",__FILE__,__LINE__);
return 0;
}
request_piece->index = index;
request_piece->begin = begin;
request_piece->length = length;
request_piece->next = NULL;
if( peer->Requested_piece_head == NULL )
peer->Requested_piece_head = request_piece;
else {
p = peer->Requested_piece_head;
while(p->next != NULL) p = p->next;
p->next = request_piece;
}
//printf("*** add a request FROM IP:%s index:%-6d begin:%-6x ***\n",
// peer->ip,index,begin);
}
peer->start_timestamp = time(NULL);
return 0;
}
int process_piece_msg(Peer *peer,unsigned char *buff,int len)
{
unsigned char c[4];
int index, begin, length;
Request_piece *p;
if(peer==NULL || buff==NULL) return -1;
if(peer->peer_choking==0) {
c[0] = buff[0]; c[1] = buff[1];
c[2] = buff[2]; c[3] = buff[3];
length = char_to_int(c) - 9;
c[0] = buff[5]; c[1] = buff[6];
c[2] = buff[7]; c[3] = buff[8];
index = char_to_int(c);
c[0] = buff[9]; c[1] = buff[10];
c[2] = buff[11]; c[3] = buff[12];
begin = char_to_int(c);
p = peer->Request_piece_head;
while(p != NULL) {
if(p->index==index && p->begin==begin && p->length==length)
break;
p = p->next;
}
if(p == NULL) {printf("did not found matched request\n"); return -1;}
if(peer->last_down_timestamp == 0)
peer->last_down_timestamp = time(NULL);
peer->down_count += length;
peer->down_total += length;
write_slice_to_btcache(index,begin,length,buff+13,length,peer);
create_req_slice_msg(peer);
}
peer->start_timestamp = time(NULL);
return 0;
}
int parse_response(Peer *peer)
{
unsigned char btkeyword[20];
unsigned char keep_alive[4] = { 0x0, 0x0, 0x0, 0x0 };
int index;
unsigned char *buff = peer->in_buff;
int len = peer->buff_len;
if(buff==NULL || peer==NULL) return -1;
btkeyword[0] = 19;
memcpy(&btkeyword[1],"BitTorrent protocol",19); // BitTorrent协议关键字
// 分别处理12种消息
for(index = 0; index < len; ) {
if( (len-index >= 68) && (memcmp(&buff[index],btkeyword,20) == 0) ) {
process_handshake_msg(peer,buff+index,68);
index += 68;
}
else if( (len-index >= 4) && (memcmp(&buff[index],keep_alive,4) == 0)){
process_keep_alive_msg(peer,buff+index,4);
index += 4;
}
else if( (len-index >= 5) && (buff[index+4] == CHOKE) ) {
process_choke_msg(peer,buff+index,5);
index += 5;
}
else if( (len-index >= 5) && (buff[index+4] == UNCHOKE) ) {
process_unchoke_msg(peer,buff+index,5);
index += 5;
}
else if( (len-index >= 5) && (buff[index+4] == INTERESTED) ) {
process_interested_msg(peer,buff+index,5);
index += 5;
}
else if( (len-index >= 5) && (buff[index+4] == UNINTERESTED) ) {
process_uninterested_msg(peer,buff+index,5);
index += 5;
}
else if( (len-index >= 9) && (buff[index+4] == HAVE) ) {
process_have_msg(peer,buff+index,9);
index += 9;
}
else if( (len-index >= 5) && (buff[index+4] == BITFIELD) ) {
process_bitfield_msg(peer,buff+index,peer->bitmap.bitfield_length+5);
index += peer->bitmap.bitfield_length + 5;
}
else if( (len-index >= 17) && (buff[index+4] == REQUEST) ) {
process_request_msg(peer,buff+index,17);
index += 17;
}
else if( (len-index >= 13) && (buff[index+4] == PIECE) ) {
unsigned char c[4];
int length;
c[0] = buff[index]; c[1] = buff[index+1];
c[2] = buff[index+2]; c[3] = buff[index+3];
length = char_to_int(c) - 9;
process_piece_msg(peer,buff+index,length+13);
index += length + 13; // length+13为piece消息的长度
}
else if( (len-index >= 17) && (buff[index+4] == CANCEL) ) {
process_cancel_msg(peer,buff+index,17);
index += 17;
}
else if( (len-index >= 7) && (buff[index+4] == PORT) ) {
index += 7;
}
else {
// 如果是未知的消息类型,则跳过不予处理
unsigned char c[4];
int length;
if(index+4 <= len) {
c[0] = buff[index]; c[1] = buff[index+1];
c[2] = buff[index+2]; c[3] = buff[index+3];
length = char_to_int(c);
if(index+4+length <= len) { index += 4+length; continue; }
}
// 如果是一条错误的消息,清空接收缓冲区
peer->buff_len = 0;
return -1;
}
} // end for
// 接收缓冲区中的消息处理完毕后,清空接收缓冲区
peer->buff_len = 0;
return 0;
}
int parse_response_uncomplete_msg(Peer *p,int ok_len)
{
char *tmp_buff;
int tmp_buff_len;
// 分配存储空间,并保存接收缓冲区中不完整的消息
tmp_buff_len = p->buff_len - ok_len;
if(tmp_buff_len <= 0) return -1;
tmp_buff = (char *)malloc(tmp_buff_len);
if(tmp_buff == NULL) {
printf("%s:%d error\n",__FILE__,__LINE__);
return -1;
}
memcpy(tmp_buff,p->in_buff+ok_len,tmp_buff_len);
// 处理接收缓冲区中前面完整的消息
p->buff_len = ok_len;
parse_response(p);
// 将不完整的消息拷贝到接收缓冲区的开始处
memcpy(p->in_buff,tmp_buff,tmp_buff_len);
p->buff_len = tmp_buff_len;
if(tmp_buff != NULL) free(tmp_buff);
return 0;
}
// 当下载完一个piece时,应该向所有的peer发送have消息
int prepare_send_have_msg()
{
Peer *p = peer_head;
int i;
if(peer_head == NULL) return -1;
if(have_piece_index[0] == -1) return -1;
while(p != NULL) {
for(i = 0; i < 64; i++) {
if(have_piece_index[i] != -1) {
create_have_msg(have_piece_index[i],p);
}
else {
break;
}
}
p = p->next;
}
for(i = 0; i < 64; i++) {
if(have_piece_index[i] == -1) {
break;
}
else {
have_piece_index[i] = -1;
}
}
return 0;
}
// 主动创建发送给peer的消息,而不是等收到某个消息再作出响应
int create_response_message(Peer *peer)
{
if(peer==NULL) return -1;
if(peer->state == INITIAL) {
create_handshake_msg(info_hash,peer_id,peer);
peer->state = HALFSHAKED;
return 0;
}
if(peer->state == HANDSHAKED) {
if(bitmap == NULL) return -1;
create_bitfield_msg(bitmap->bitfield,bitmap->bitfield_length,peer);
peer->state = SENDBITFIELD;
return 0;
}
// 发送piece消息,即发送下载文件的内容
if( peer->am_choking==0 && peer->Requested_piece_head!=NULL ) {
Request_piece *req_p = peer->Requested_piece_head;
int ret = read_slice_for_send(req_p->index,req_p->begin,req_p->length,peer);
if(ret < 0 ) { printf("read_slice_for_send ERROR\n");}
else {
if(peer->last_up_timestamp == 0)
peer->last_up_timestamp = time(NULL);
peer->up_count += req_p->length;
peer->up_total += req_p->length;
peer->Requested_piece_head = req_p->next;
//printf("********* sending a slice TO:%s index:%-5d begin:%-5x *********\n",
//peer->ip,req_p->index,req_p->begin);
free(req_p);
return 0;
}
}
// 如果3分钟没有收到任何消息关闭连接
time_t now = time(NULL); // 获取当前时间
long interval1 = now - peer->start_timestamp;
if( interval1 > 180 ) {
peer->state = CLOSING;
discard_send_buffer(peer); // 丢弃发送缓冲区中的数据
clear_btcache_before_peer_close(peer);
close(peer->socket);
}
// 如果45秒没有发送和接收消息,则发送一个keep_alive消息
long interval2 = now - peer->recet_timestamp;
if( interval1>45 && interval2>45 && peer->msg_len==0)
create_keep_alive_msg(peer);
return 0;
}
void discard_send_buffer(Peer *peer)
{
struct linger lin;
int lin_len;
lin.l_onoff = 1;
lin.l_linger = 0;
lin_len = sizeof(lin);
if(peer->socket > 0) {
setsockopt(peer->socket,SOL_SOCKET,SO_LINGER,(char *)&lin,lin_len);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -