/*发送请求函数,一次一般发送5个请求*/ void sendRequest(peer_t *peer,ReqState* state) { int i=0; int r; char sendbuf[MAXLINE]; //pthread_mutex_lock(&g_isSeed_lock); //做种后不需要再存分片 //i=g_isSeed; //pthread_mutex_unlock(&g_isSeed_lock); //if(i==2)return; //int size=0; while(i<1) { memset(sendbuf,0,MAXLINE); if(state->index<0) //还未分配给该连接需要发送分片 { state->index=getIndex(peer); //选择分片,该连接负责该分片,直到该分片完成 if(state->index<0) { //printf("没有请求可以发送\n"); break; //没有需要发送请求的分片 } if(state->index==g_num_pieces-1) //最后一片,需要特殊处理 state->len=g_filelen-(g_num_pieces-1)*g_torrentmeta->piece_len; else state->len=g_torrentmeta->piece_len; state->offset=0; printf("请求分片:index:%d len:%d\n",state->index,state->len); } Head* h=(Head*)sendbuf; h->len=reverse_byte_orderi(13); h->id=0x06; Request * req=(Request*)(sendbuf+HEAD_SIZE); req->index=reverse_byte_orderi(state->index); req->offset=reverse_byte_orderi(state->offset); req->len=16384; //16k if(state->offset+req->len>g_piece_state[state->index].len) //最后一片 req->len=g_piece_state[state->index].len-state->offset; printf("send request sock:%d :index: %d offset: %d len:%d\n",peer->sockfd,state->index,state->offset,req->len); state->offset+=req->len; req->len=reverse_byte_orderi(req->len); //printf("%d\n",req->len); r=sendme(peer->sockfd,sendbuf,17); if(r<=0) printf("req send error\n"); if(state->offset>=g_piece_state[state->index].len) //该分片请求已经发完 state->index=-1; i++; } }
/*告诉所有人我有了某个分片*/ void showPiece(int index) { char temp[9]; int len=reverse_byte_orderi(5); char id=0x04; int ind=reverse_byte_orderi(index); memcpy(temp,&len,sizeof(int)); memcpy(temp+sizeof(int),&id,1); memcpy(temp+sizeof(int)+1,&ind,sizeof(int)); pthread_mutex_lock(&all_peer_lock); int i; for(i=0;i<MAXPEER;i++) { if(myPeer[i].sockfd>=0) sendme(myPeer[i].sockfd,temp,9); } pthread_mutex_unlock(&all_peer_lock); }
/*向所有人发送某个分片的cancel*/ void publicCancel(int index){ char temp[17]; int len = reverse_byte_orderi(13); char id = 0x08; int ind = reverse_byte_orderi(index); int begin = reverse_byte_orderi(0); int length = reverse_byte_orderi(0); memcpy(temp,&len,4); memcpy(temp+4,&id,1); memcpy(temp+5,&ind,4); memcpy(temp+9,&begin,4); memcpy(temp+13,&length,4); pthread_mutex_lock(&all_peer_lock); peer_t *p = all_peer; while(p != NULL) { sendme(p->sockfd,temp,17); p = p->next; } pthread_mutex_unlock(&all_peer_lock); }
void sendPiece(int sockfd,int index,int offset,int len) { int i=reverse_byte_orderi(index); int o=reverse_byte_orderi(offset); int l=reverse_byte_orderi(len); int size=l+HEAD_SIZE+2*sizeof(int); char sendline[MAXLINE]; Head *head=(Head*)sendline; head->len=reverse_byte_orderi(size-sizeof(int)); head->id=0x07; Request *req=(Request*)(sendline+HEAD_SIZE); req->index=index; req->offset=offset; pthread_mutex_lock(&g_f_lock); fseek(g_f,i*g_torrentmeta->piece_len+o,SEEK_SET); fread(sendline+HEAD_SIZE+2*sizeof(int),l,1,g_f); pthread_mutex_unlock(&g_f_lock); //memcpy(sendline+HEAD_SIZE+2*sizeof(int),g_filedata+i*g_torrentmeta->piece_len+o,l); printf("send piece:sock:%d index %d offset %d len %d\n",sockfd,i,o,l); int r=sendme(sockfd,sendline,size); g_uploaded+=l; if(r<=0)return; }
void sendshkhdmsg(int sockfd) { printf("\033[34m""I will send shkhdmsg to somebody\n""\033[m"); unsigned char *shkhdmsg1; unsigned char *current; int msglen = 0; shkhdmsg1 = (unsigned char* )malloc(HANDSHAKE_LEN); current = shkhdmsg1; int pstrlen = strlen(BT_PROTOCOL); memcpy(current, (unsigned char*)&pstrlen, sizeof(int)); current += sizeof(int); strncpy(current, BT_PROTOCOL, pstrlen); current += pstrlen; memset(current, 0, 8); current += 8; int i = 0; for(; i < 5; i ++) { int j = 0; int part = reverse_byte_orderi(g_infohash[i]); unsigned char *p = (unsigned char*)∂ for(; j < 4; j ++) { *current++ = p[j]; } } for(i = 0; i < 20; i ++) { *current = g_my_id[i]; current ++; } msglen = current - shkhdmsg1; send(sockfd, shkhdmsg1, msglen, 0); free(shkhdmsg1); shkhdmsg1 = NULL; current = NULL; }
// 制作一个发送给Tracker的HTTP请求. 使用一些全局变量来填充请求中的参数, // 如info_hash, peer_id以及有多少字节已上传和下载, 等等. // // 事件: 0 - started, 1 - stopped, 2 - completed // 这些宏的定义见头文件btdata.h // 这个函数返回HTTP请求消息, 消息的长度写入mlen char* make_tracker_request(int event, int* mlen) { // 分配一个很大的空间给MESG, 并填充它 char *MESG; char* cur; int i; MESG = (char*)malloc(4096*sizeof(char)); cur = MESG; strcpy(cur,"GET /announce?"); cur += strlen("GET /announce?"); // 填入info_hash //char hexdigs[16] = {'0', '1', '2', '3', '4', '5', '6', '7', // '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; strcpy(cur,"info_hash="); cur += strlen("info_hash="); for(i=0; i<5; i++) { int j; int part = reverse_byte_orderi(g_infohash[i]); unsigned char* p = (unsigned char*)∂ for(j=0; j<4; j++) { if((p[j] > 0x2F && p[j] < 0x3A) || (p[j] > 0x41 && p[j] < 0x5B) || (p[j] > 0x60 && p[j] < 0x7B)) { *cur++ = p[j]; } else { *cur++ = '%'; cur += sprintf(cur,"%02X",p[j]); } } } // Peer id strcpy(cur,"&peer_id="); cur += strlen("&peer_id="); for(i=0; i<20; i++) { *cur++ = '%'; cur += sprintf(cur,"%02X",(unsigned char)g_my_id[i]); } // port strcpy(cur,"&port="); cur += strlen("&port="); cur += sprintf(cur,"%d",g_peerport); // ip strcpy(cur,"&ip="); cur += strlen("&ip="); strcpy(cur,g_my_ip); cur += strlen(g_my_ip); // uploaded strcpy(cur,"&uploaded="); cur += strlen("&uploaded="); cur += sprintf(cur,"%d",g_uploaded); // downloaded strcpy(cur,"&downloaded="); cur += strlen("&downloaded="); cur += sprintf(cur,"%d",g_downloaded); // left strcpy(cur,"&left="); cur += strlen("&left="); cur += sprintf(cur,"%d",g_left); switch(event) { case BT_STARTED: strcpy(cur,"&event="); cur += strlen("&event="); strcpy(cur,"started"); cur += strlen("started"); break; case BT_STOPPED: strcpy(cur,"&event="); cur += strlen("&event="); strcpy(cur,"stopped"); cur += strlen("stopped"); break; case BT_COMPLETED: strcpy(cur,"&event="); cur += strlen("&event="); strcpy(cur,"completed"); cur += strlen("completed"); break; // 除了上述情况以外, 不发送event参数 } strcpy(cur," HTTP/1.1\r\n\r\n"); cur += strlen(" HTTP/1.1\r\n\r\n"); *cur = '\0'; *mlen = cur - MESG; return MESG; }
void *PToP(void *arg) { Head* head; peer_t * peer=(peer_t *)arg; peer->bitmap=malloc(mapcount); //记录该peer的bitfield memset(peer->bitmap,0,mapcount); int sockfd=peer->sockfd; int i; char rcvline[MAXLINE]; char sendline[MAXLINE]; char templine[MAXLINE]; char c; memset(rcvline,0,MAXLINE); memset(sendline,0,MAXLINE); //啥话不说,先来一发 Hand* hk=(Hand*)sendline; hk->len=0x13; strcpy(hk->name,"BitTorrent protocol"); memset(hk->reserve,0,8); int hash[5]; for(i=0;i<5;i++) hash[i]=reverse_byte_orderi(g_infohash[i]); memcpy(hk->sha,hash,20); memcpy(hk->id,g_my_id,20); sendme(sockfd,sendline,sizeof(Hand)); if(recvme(sockfd,rcvline,sizeof(Hand))<=0) { printf("握手失败\n"); { shutdown(sockfd,SHUT_RDWR); close(sockfd); peer->sockfd=-1; return NULL; } } hk=(Hand*)rcvline; /*if(memcmp(hash,hk->sha,20)!=0){ printf("hash 不匹配\n"); shutdown(sockfd,SHUT_RDWR); close(sockfd); peer->sockfd=-1; return NULL; }*/ memcpy(peer->name,hk->id,20); //bitfield pthread_mutex_lock(&g_isSeed_lock); i=g_isSeed; pthread_mutex_unlock(&g_isSeed_lock); if(i==2) { memset(sendline,0,MAXLINE); head=(Head*)sendline; head->len=reverse_byte_orderi(mapcount+1); head->id=0x05; pthread_mutex_lock(&g_bitmap_lock); memcpy(&sendline[HEAD_SIZE],g_bitmap,mapcount); pthread_mutex_unlock(&g_bitmap_lock); sendme(sockfd,sendline,HEAD_SIZE+mapcount); } Request* req; int temp; ReqState reqState; reqState.index=-1; reqState.offset=-1; reqState.len=-1; SaveState saveState; saveState.index=-1; saveState.offset=0; int cancel=-1; int errcount=0; while(!g_done) { req=NULL; memset(rcvline,0,MAXLINE); memset(sendline,0,MAXLINE); memset(templine,0,MAXLINE); head=NULL; i=recvme(sockfd,rcvline,sizeof(int)); if(peer->state||i<=0) { errcount++; if(errcount>1) { printf("接受信息错误%d\n",peer->state); shutdown(sockfd,SHUT_RDWR); close(sockfd); peer->sockfd=-1; return NULL; } continue; } errcount=0; head=(Head*)rcvline; if(reverse_byte_orderi(head->len)<=0)continue; //keep alive if(recvme(sockfd,rcvline+sizeof(int),1)<0)continue; int load_len=reverse_byte_orderi(head->len)-1; //printf("状态:%02X\n",head->id); switch(head->id) { case 0x00: //choke printf("被阻塞!\n"); head=(Head*)sendline; head->len=reverse_byte_orderi(1); head->id=0x02; peer->have_interest=1; sendme(sockfd,sendline,HEAD_SIZE); break; case 0x01: //unchoke if(!peer->have_interest)break; peer->choked=0; sendRequest(peer,&reqState); //send request break; case 0x02: //interest if(peer->choking)break; cancel=-1; peer->interested=1; head=(Head*)sendline; head->len=reverse_byte_orderi(1); head->id=0x01; //unchoke sendme(sockfd,sendline,HEAD_SIZE); //等待对方的request break; case 0x03: //not interested cancel=-1; break; case 0x04: //have if(recvme(sockfd,templine,load_len)<=0) continue; memcpy(&temp,templine,sizeof(int)); temp=reverse_byte_orderi(temp); pthread_mutex_lock(&g_bitmap_lock); c=g_bitmap[temp/8]; pthread_mutex_unlock(&g_bitmap_lock); if(isSet(c,8-temp%8))continue; head=(Head*)sendline; head->len=reverse_byte_orderi(1); head->id=0x02; sendme(sockfd,sendline,HEAD_SIZE); break; case 0x05: //bitfield if(recvme(sockfd,templine,load_len)<=0) continue; if(load_len!=mapcount) { shutdown(sockfd,SHUT_RDWR); close(sockfd); peer->sockfd=-1; return NULL; } memcpy(peer->bitmap,templine,mapcount); i=needThis(peer->bitmap); //判断是否有需要该用户,需要记录该用户提供了那些分片 //printf("是否需要该用户%d\n",i); if(i==0) { shutdown(sockfd,SHUT_RDWR); close(sockfd); peer->sockfd=-1; return NULL; } else if(i==1)break; //不感兴趣 //send interest head=(Head*)sendline; head->len=reverse_byte_orderi(1); head->id=0x02; peer->have_interest=1; sendme(sockfd,sendline,HEAD_SIZE); break; case 0x06: //request if(recvme(sockfd,templine,load_len)<=0) continue; req=(Request *)templine; if(reverse_byte_orderi(req->len)>131072) //2^17 { shutdown(sockfd,SHUT_RDWR); close(sockfd); peer->sockfd=-1; return NULL; } if(cancel==reverse_byte_orderi(req->index)){ cancel=-1; continue; } sendPiece(sockfd,req->index,req->offset,req->len); //发送子分片 break; case 0x07: //piece if(recvme(sockfd,templine,load_len)<=0) continue; //printf("load len :%d\n",i); req=(Request *)templine; /*for(i=0;i<8;i++) { for(temp=0;temp<8;temp++) printf("%02X ",templine[i*8+temp]); printf("\n"); }*/ savePiece(reverse_byte_orderi(req->index),reverse_byte_orderi(req->offset),templine+2*sizeof(int),load_len-2*sizeof(int),&saveState); //存储分片:w sendRequest(peer,&reqState); break; case 0x08: //cancel if(recvme(sockfd,templine,load_len)<=0)continue; req=(Request*)templine; cancel=reverse_byte_orderi(req->index); break; default: ;//printf("没有该状态%02X\n",head->id);return NULL; } } shutdown(sockfd,SHUT_RDWR); close(sockfd); peer->sockfd=-1; return NULL; }
void *peer_deal(void *i) { struct param_list *my_param = (struct param_list *)i; int sockfd = my_param->sockfd; int close_bit = 1; printf("Child created for dealing with client request\n"); char *buf = (char *)malloc(HANDSHAKE_LEN); memset(buf,0,HANDSHAKE_LEN); int n; while(n=recv(sockfd,buf,HANDSHAKE_LEN,0) > 0) { struct handshake_packet *my_packet = (struct handshake_packet *)buf; if(my_packet->len != strlen(BT_PROTOCOL)) { printf("len is not match\n"); break; } if(strncmp(my_packet->name,BT_PROTOCOL,strlen(BT_PROTOCOL)) != 0) { printf("BT_PROTOCOL is not match\n"); break; } int i = 0,flag = 1; unsigned char *buf_info = my_packet->info_hash; for(; i<5; i++) { int j = 0; int part = reverse_byte_orderi(g_infohash[i]); unsigned char *p = (unsigned char *)∂ for(; j<4; j++) { if(*buf_info != p[j]) { printf("buf_info is %x and p[j] is %x\n",*buf_info,p[j]); flag = 0; goto END; } buf_info ++; } } END: if(flag != 1) { printf("\033[33m buf_info is not match\n \033[m"); break; } printf("waiting client get info\n"); //sleep(10); //这里是为了等客户端向tracker服务器发送更新请求报文 //这里需要上锁 pthread_mutex_lock(&g_mutex); for(i=0; i<MAXPEERS; i++) { //printf("peers_pool[i].id is %s and my_packet->peer_id is %s\n",peers_pool[i].id,my_packet->peer_id); if(peers_pool[i].used == 1 && strncmp(peers_pool[i].ip,my_param->ip,strlen(my_param->ip)) == 0) { printf("find you\n"); break; } } pthread_mutex_unlock(&g_mutex); if(i == MAXPEERS || peers_pool[i].sockfd > 0) { printf("not you\n"); break; } printf("i is %d\n",i); pthread_mutex_lock(&peers_pool[i].sock_mutex); if(peers_pool[i].status == 1) { pthread_mutex_unlock(&peers_pool[i].sock_mutex); printf("I already some shake hand to peer\n"); break; } peers_pool[i].status = 2; peers_pool[i].sockfd = sockfd; memcpy(peers_pool[i].id,my_packet->peer_id,20); printf("peers_pool 0 status is %d in listen_peers\n",peers_pool[0].status); pthread_mutex_unlock(&peers_pool[i].sock_mutex); //这里开始向对方返回握手信息 printf("send handshake packet return \n"); memcpy(my_packet->peer_id,g_my_id,20); send(sockfd,buf,HANDSHAKE_LEN,0); close_bit = 0; pthread_t thread; int rc = pthread_create(&thread, NULL, recv_from_peer, (void *)i); if(rc) { printf("Error, return code from pthread_create() is %d\n", rc); exit(-1); } printf("shake hands succeed\n"); //sleep(10); //等一会 sendBitField(sockfd); pthread_t thread_1; pthread_create(&thread_1, NULL, check_and_keepalive, (void*)i); break; } if(n<0) { printf("%s\n",strerror(errno)); } if(close_bit) close(sockfd); free(buf); }